{ ******************************************************* Include file of standard domain constants and types ******************************************************* } const dns_socket=53; { socket for domain server } test_version=false; { If true, use dns_socket + 100, test files, etc } dbvern=17; { internal version number be sure to change version whenever you make *any* changes to structure of database } abort=true; { 1st arg to jsys_err } noabort=false; jsys_test=true; { should the jsys test be used ? } no_jsys_test=false; cr=13; { carriage return / line delimiter } lf=10; { line feed } tab=9; { tab character } ip_hdr_sz=20; { octets in the IP header } udp_hdr_sz=8; { octets in the UDP header } dmn_hdr_sz=12; { octets in the domain style header } max_dgm_octets=548; { max datagram octets } max_msg_octet=64000; { max size uncompressed message } max_atom_chars=15; { max characters in a syntactic atom, e.g. in master file } max_big_atom_chars=80; { max chars in a big atom } max_binary_octets=40; { max binary octets in a chunk } max_chunk=10; { max chunks per RDATA } max_dname_chars=256; { max octets in a dname } max_dname_labels=128; { max labels in a dname } max_exp_rrs=15; { max number of exp RRs in a section } max_fn_chars=63; { max characters in a filename } max_int_rrs=50; { max number of int RRs in a section } max_rrs=200; { max RRs in a section } max_lab_chars=63; { max octets in a label } max_lab_levels=20; { max levels in a label } max_rdata_items=8; { max fields in an rdata_entry } max_search_servers=4; { max servers per request } max_server_addresses=3; { max addresses per server } max_zlhosts=3; { maximum number of hosts which can be used to refresh a particular network loaded zone } tslots=200; { max time slots in tgraph } hslots=200; { max host slots in graph } qslots=256; { max qtype slots in qgraph } cslots=256; { max qclass slots in cgraph } dimax=143; { time of day interval max (10 min interval) } sgmax=10; { maximum section count in size graph } prfmax=12; { maximum array index of address preference } maxcs=512; { maximum compression savings to graph } label_hashmod=1009; { modulo for label hashing } label_hashmax=1008; { label_hashmod-1 } { message opcodes } std_query=0; { standard query } inv_query=1; { inverse query } cm_query=2; { completion query--multiple answers } cu_query=3; { completion query--unique answer } { response codes } no_error=0; { no error } format_error=1; { NS couldn't interpret query } server_failure=2; { problem with NS } name_error=3; { domain name doesn't exist } not_implemented=4; { no support for this query type } refused=5; { NS refused for policy reasons } { qtype special values } axfr=252; { transfer entire zone } mailb=253; { mailbox related RRs: mb, mg, mr } maila=254; { mail agent RRs: md, mf } star=255; { qtype and qclass wildcard } type atom=packed array[1..max_atom_chars] of char; big_atom=packed array[1..max_big_atom_chars] of char; filename=packed array[1..max_fn_chars] of char; itime=integer; { internal times are seconds, either positive delta or negative absolute } lock= record lockwd:integer; { master lock } share:integer; { share count } exclusive:integer { exclusive count } end; dname_string=packed array[1..max_dname_chars] of octet; dname_string_table=record count:0..max_dname_labels; bp:array[1..max_dname_labels] of g1bpt end; dtype=( dtype_l_bound, { lower bound is not valid } a, { host address } ns, { authoritative name server } md, { mail destination } mf, { mail forwarder } cname, { canonical name } soa, { start of zone of authority } mb, { mailbox domain name } mg, { mail group member } mr, { mail rename } null, { null RR } wks, { well known service description } ptr, { domain name pointer } hinfo, { host information } minfo, { mailbox or mail list information } mx, { mail agent replacement for MD + MF } dtype_h_bound );{upper bound is not valid } qtype=0..177777b; { qtypes include dtype plus those defined above } dclass=( dclass_l_bound, { lower bound is not valid } internet, { ARPA Internet } csnet, { CSNET } dclass_h_bound );{ upper bounnd is not valid } qclass=0..177777b; { qclass includes dclass plus star } sectcode=(question,answer,authority,additional); { ***** Storage allocation types ***** } satype=(sd_slt, { storage allocation types } sd_zone, sd_ulabel, sd_dname, sd_node, sd_lht, sd_rr, sd_rdchunk, sd_litstring); sakind=(sa_units { record number of allocations } ,sa_aus { record number of AUs allocated } ); sapool=(sa_search { allocations for search related items } ,sa_data { allocations for data } ); stgmap=array[satype,sakind] of integer; pagemap=packed array[db_first_page..db_last_page] of boolean; free_block=record next:free_block_pointer;{ next free block } size:integer { number of free AUs in block } end; { ***** RDATA format types ***** These types are used with the IRDATA routine to describe the structure of the RDATA fields for a given type and class } rdata_field=( dname_field, { domain name } cstring_field, { string, e.g. CPU in HINFO } time_field, { 32 bit time value } int16_field, { 16 bit integer } int32_field, { 32 bit integer } inet_a_field, { 32 bit IP address } inet_p_field, { 8 bit IP protocol number } inet_s_field, { variable length IP socket WKS } vbinary_field, { variable length binary field } no_more_field ); { end marker for table } rdata_entry=packed record rdata_item:packed array[1..max_rdata_items] of rdata_field; rdata_asp:packed array[1..max_rdata_items] of qtype end; rdata_table=packed array[dtype] of rdata_entry; { ***** label definitions ***** Labels are managed separately for each zone. Each zone has a label table that points to the unique definitions for each distinct label, where distinct is case-insensitive, i.e. there is a single unique label (ULABEL) for all occurances of "A" or "a" in a particular zone. The purpose of this is to allow us to find all occurances of the use of a label in nodenames, and to make label references fixed in size. ULABELs are in UPPER CASE. An instance of a label in the database is represented using a ULABEL pointer and an array of modifier bits in a mod_bits. Modifier bits are associated one-to-one with octets in a ULABEL, and signify characters that should be mapped to lower case when the data is exported. This can be done by adding octal 40 to an octet. Nodes that have the same label are chained together. } { in label_string, octet zero is length } label_string=packed array[0..max_lab_chars] of octet; ulabel= record nodeptr:node_pointer; { node with this label } next:ulabel_pointer; { ptr to next label } text:label_string end; mod_bits=packed array[1..max_lab_chars] of boolean; lab_use=record labptr:ulabel_pointer; case_mod:mod_bits end; { these data structures used to locate ULABELS } secondary_label_table=record direct:ulabel_pointer; lchain:array[octet] of ulabel_pointer end; primary_label_table=record direct:ulabel_pointer; stable:array[octet] of secondary_label_table_pointer end; { these data structures used for nodes and dnames } label_hashrange=0..label_hashmax; label_hashtable=record case boolean of true: (node_hash:array[label_hashrange] of node_pointer); false: (dname_hash:array[label_hashrange] of dname_pointer) end; { ***** domain name definitions ***** Like labels, there is a single representation for a particular domain name in a particular zone. Unlike labels, domain names are not case insensitive. That is, while all occurances of ISI.ARPA will use the same data via multiple pointers, isi.ARPA will be a different representation from ISI.ARPA. Thus to test to see if two domain names in a zone are the same, it is necessary to see if they are the same length and if all their corresponding ULABEL pointers are EQ. Note that the purpose here is to reduce storage requirements, rather than achieve any sort of accessing. A domain name, say X1.X2 is represented as a linked list with three DNAME blocks: +----------+ +----------+ +----------+ | |--------->| |--------->| nil | +----------+ +----------+ +----------+ | | | | | | +-----|----+ +-----|----+ +-----|----+ | | | V V V ULABEL of X1 ULABEL of X2 ULABEL of ""(root) All domain names of length Y are chained off of the hash table pointed to by the Yth entry in dname_table. Domain names of length N+1 will point to a domain name of length N, which is chained from the Nth entry in dname_table. } dname=record dlabel:lab_use; more:dname_pointer; { following labels in name } dname_chain:dname_pointer { next name of this size } end; dname_table=array[1..255] of label_hashtable_pointer; { ***** node definitions ***** The structure of a domain tree in a zone is composed of chained NODE blocks. Each node block has a pointer (UP_PTR) to its direct ancestor, a pointer (SIDE_PTR) to its next sibling, and a pointer (DOWN_PTR) to its first sibling. All nodes with a particular direct ancestor are chained together in alphabetical order of node name via SIDE_PTRs. No two siblings can have labels that are identical except for case; the first casing into the database stays. That is, while we may have nodes X.ARPA and x.CSNET, we can't have x.ARPA and X.ARPA. All nodes which refer to the same ULABEL are chained together via node_lchain. Nodes with a high branching factor for children may have a non NIL entry in DOWN_TBL. The Nth entry in the DOWN_TBL points to the first child which starts with the specified octet. The variant record part of the node record is always rr_ptr except for the search zone. } node=record node_label:lab_use; node_lchain:node_pointer; { next node with same label } up_ptr:node_pointer; side_ptr:node_pointer; down_ptr:node_pointer; down_tbl:label_hashtable_pointer; case boolean of true: (rr_ptr:rr_pointer); false: (zone_ptr:zone_entry_pointer) end; { ***** RR definitions ***** Each RR is represented as a RR block with a chain of rdchunks that make up the RDATA field. All RRs of a particular type and class are chained together via RDCHAIN. These chains are anchored in the zone's RR_TABLE array. These chains are used in inverse queries. The RDATA field of an RR is represented as a linked list of RDCHUNKs. RDCHUNKS contain either a doamin name or literal data. } rr=packed record next:rr_pointer; { pointer to next RR this node } ttl:integer; { expiration time } rrtype:dtype; { resource record type } rrclass:dclass; { resource record class } rdata:rdchunk_pointer; { pointer to first RR chunk } end; rr_table=array[dtype,dclass] of rr_pointer; chunktypes=( lit_chunk, name_chunk ); litstring=packed record case boolean of true: (lcount:field16); false: (ldata:packed array[-1..max_binary_octets] of octet) end; rdchunk=record more:rdchunk_pointer; {ptr to more of this RDATA} rdchain:rdchunk_pointer; {ptr to next chunk at this level} case ckind:chunktypes of lit_chunk: ( litdata:litstring_pointer ); name_chunk: ( rrname:dname_pointer ) end; rd_table=array[1..max_chunk,0..255] of rdchunk_pointer; { ******************************************************* Expanded domain types ******************************************************* } exp_label=packed record labinfo:label_string; case_mod:mod_bits end; exp_dname=packed record count:0..max_lab_levels; { number of labels } dlabels:array[1..max_lab_levels] of exp_label end; exp_chunk=packed record case ckind:chunktypes of lit_chunk:(lit_data_count:0..max_binary_octets; lit_data:packed array[1..max_binary_octets] of octet); name_chunk:(rrname:exp_dname) end; exp_rr=record ttl:integer; rrtype:dtype; rrclass:dclass; chunk_count:integer; chunks:array[1..max_chunk] of exp_chunk end; { zone definitions } zone_ltype=(zloadf, { zone loaded from file } zloadfd, { zone from file with file date as serial } cloadf, { cache load from file } zloadn { zone loaded over network } ); zone_cdata=record { refresh configuration for zone } zone_to_load:exp_dname; zone_uses_filedates:boolean; zone_serial:integer; zone_refresh:integer; zone_retry:integer; zone_expire:integer; zone_minimum:integer; loadclass:dclass; default_rinterval:integer; case loadtype:zone_ltype of zloadf, zloadfd: (refresh_file:filename); zloadn: (hostcount:0..max_zlhosts; hosts:array[1..max_zlhosts] of exp_dname) end; file_type = ( fatl, err, log ); file_blk = record flock:lock; fident:file of char; end; zone_entry=record zone_chain:zone_entry_pointer; { next authoritative } zone_node:node_pointer; {ptr to zone's root node} zone_class:dclass; loaded:boolean; zsoa:node_pointer; {ptr to node with SOA} zsoa_rr:rr_pointer; { SOA record for zone } zone_is_cache:boolean; zone_lock:lock; zone_config:zone_cdata; dtable:dname_table; ltable:primary_label_table; { rrtable:rr_table; } rdtable:rd_table; sadata:stgmap; { storage allocation statistics } zone_pools:array[sapool] of free_block_pointer; zone_pages:pagemap end; search_block=record slock:integer; { AOSE lockword for this block } sbnext:search_block_pointer; rcomp:integer_pointer; {pointer to resolver command} ldores:integer; {non-zero if reserved for ldo} erttl:integer; {recursion counter to kill infinite loops} tstart:integer; {MSclock when query was started} tquery:integer; {absolute time query was started} fcode:integer; psave:integer; { jsys save area for stack pointer } sname:dname_string; stable:dname_string_table; stype:qtype; sclass:qclass; lock1:lock_pointer; { pointers to locked zones } lock2:lock_pointer; locked:integer; azone:zone_entry_pointer; alabel:integer; lmatch:integer; derc:integer; outcnt:integer; outins:integer; outbp:integer; cnptr:integer; anret:integer; adpref:integer; adeln:node_pointer; {node pointer for authoritative delegation} adell:integer; {label value from jsys} cdeln:node_pointer; {node pointer for cache delegation} cdell:integer; {label value from jsys} dnbp:integer; dncp:integer; dnlc:integer; rtimeo:integer; {time of next activity} resttl:integer; {watchdog inside resolver} rflags:integer; {flags register from JSYS code} rsolvn:node_pointer {node where resolver placed answers} end; hgraph_index=1..hslots; hgraph_type=record host:integer; { host address } touts:integer; { times started } tbacks:integer; { times completed } ttotal:integer { total delay for responses } end; hgraph=array[hgraph_index] of hgraph_type; tgraph=record { timing graph } touts:integer; { times started } tbacks:integer; { times completed } ttotal:integer; { total delay for responses } tquanta:integer; { slot spacing} tdelay:array[0..tslots] of integer; { histogram by tquanta } end; qgraph_index=1..qslots; qgraph=array[qgraph_index] of integer; { graph usage by qtype, last slot is other } cgraph_index=1..cslots; cgraph=array[cgraph_index] of integer; { graph usage by qclass, last slot is other } sgraph=record strun:integer; { truncations in this section } ssize:array[0..sgmax] of integer end; search_address_type=record tries:integer; { transmissions made } limit:integer; { transmissions remaining } ipaddress:integer; stat_ptr:integer; { index in hgraph for RT } eta:integer; { estimated RTT in milliseconds } rank:integer; { comparitive worth of server } end; server_type=record server_name:dname_string; (* name of server *) addresses_ready:boolean; (* address setup done? *) address_count:integer; (* number of addresses *) server_addresses:array[1..max_server_addresses] of search_address_type; end; servers_dv=record server_count:integer; { count of server references } server_quality:integer; { how good is this delegation } server_at:dname_string; { name of delegated zone } server_at_len:integer; { length of server_at } servers:array[1..max_search_servers] of server_type; end; fruse=record { fork resource usage } elpgt:integer; { elapsed page traps } elpgf:integer; { elapsed page faults } elpgrt:integer; { elapsed time in paging code (ms)} elrun:integer; { elapsed runtime (ms) } elwall:integer; { elapsed wallclock time (ms) } elwb:integer; { elapsed base (process start time ) } end; msure_type=record mname:dname_string; { Name of measured host } mcomment:packed array[1..100] of char; { measurement comment } mclear:integer; { GTAD time of statistics reset } mdate:integer; { GTAD time of measurement } tzero:integer; { GTAD time of database creation } prifn:filename; { Filename of primary database } secfn:filename; dupver:integer; { version number duplicate } infttl:integer; { limit for JSYS looping } plttl:integer; { primitive lock disms time in MS } lckttl:integer; { MS wait for exclusive to clear } rwaiti:integer; { initial MS wait for resolver } rwait:integer; { subsequent MS wait for resolver } ripoll:integer; { resolver idle poll interval } rbpoll:integer; { resolver busy poll interval } qtoi:integer; { query initial timeout } qtor:integer; { query retransmission timeout } qtoq:integer; { query timeout for quiet interval } dynsw:integer; { non-zero for RTT timeouts } dynnum:integer; { numerator of ETA to timeout ratio } dynden:integer; { denominator } prefm:array[0..prfmax] of integer; { preference masks } prefv:array[0..prfmax] of integer; { preference values } prefe:array[0..prfmax] of integer; { preference ETA } rmttl:integer; { resolver max TTL } maxit:integer; { max individual address tries } maxst:integer; { max tries per server } dcalls:integer; { calls to GTDOM% } dbyfn:array [0..gtdfmx] of integer; {GTDOM% calls by function} dbyqt:qgraph; { GTDOM% calls by QTYPE} dscall:integer; { calls to DSETUP } dsbbsy:integer; { busy SBLOCKS found in DSETUP } dsbbl:integer; { all SBLOCKS busy } dedoa:integer; { finite effort requests killed } daztry:integer; { authoritative zone to search } dazne:integer; { name error in authoritative } dazdel:integer; { authoritative delegation } dazstr:integer; { authoritative * node } dazfnd:integer; { authoritative node used } dcache:integer; { attempts to use cache } dcnmba:integer; { cache uses allowed by MBA } dcans:integer; { cache found answers } dresol:integer; { attempts to use resolver } drnldo:integer; { resolve uses allowed by LDO } drrip:integer; { resolves left going in background } drdism:integer; { DISMS in rsolve } dcncal:integer; { CNAMEL calls } dcngo:integer; { times CNAMEL infchk OK } dicdie:integer; { infinite loop check failures } dpwait:integer; { times waited on primitive lock } dewait:integer; { times waited for excusive to leave } dferr:integer; { DFINIS with error } dfok:integer; { DFINIS without error } dfgra:tgraph; { DFINIS time graph } uierrs:integer; { UDP input errors } uoerrs:integer; { UDP output errors } udpgra:tgraph; { UDP delay tabulation } udphst:hgraph; { UDP host response graph } newudp:hgraph; { recent data used for strategy } udphl:integer; { NEWUDP halflife in ms } udpdcy:integer; { time for next halflife decay } rusage:fruse; { resolver resource usage } resolve_loops:integer; { times resolver loop executed } nsugra:tgraph; { Name server response time graph } nsuhst:hgraph; { Name server host graph } nsucod:array[field4] of integer; { NS requests by response } nsbyqt:qgraph; { NS requests by QTYPE } nsbyqc:cgraph; { NS requests by QCLASS } bogon:integer; { NS incomming BOGONS } pfail:integer; { arriving parse failures } nsbyds:array[0..dimax] of integer; { time of day graph } nusage:fruse; { name server resource usage } nsaa:integer; { authoritative answer count } nudptc:integer; { UDP caused truncation } nssgra:array[sectcode] of sgraph; { section statistics} nsusiz:array[0..512] of integer; {response size graph} nsucs:array[0..maxcs] of integer { compression savings } end; { ***** master block ***** } master_block=record dirty:integer; { MUST BE FIRST- see cpymaster } update_lock:lock; { lock for all updating } dflush:integer; { non-zero to flush JSYSi } zupdate:integer; { GTAD of zone update } cupdate:integer; { GTAD of cache update } jsys_init:integer; { zero if not used by JSYS } dbvers:integer; { internal software version number} prijfn:integer; { JFN for primary database } secjfn:integer; { JFN for secondary database } master_base:master_block_pointer; alloc_lock:lock; { lock for allocation } used_pages:pagemap; search_zone:zone_entry; cache_lock:lock; { lock for discarding cache } cache_pointer:zone_entry_pointer; msg_files:array[file_type] of file_blk; sbloop:search_block_pointer; rcom:array[1..max_sb] of integer; iaorg:dname_string; starbp:g1bpt; { g1bpt to '*' } stard:packed array[1..4] of octet; { * } sb_array:array[1..max_sb] of search_block; resolve_handle:integer; { resolver UDP handle } resolve_port:integer; { resolver port } resolve_job:integer; { resolver job, -1 if none } logrn:integer; { non-zero for normal resolver logging } logri:integer; { non-zero to dump incoming resolver packets } logrp:integer; { non-zero for all resolver peculiar } logns:integer; { non-zero for nameserver summary log } logue:integer; { non-zero to log UDP errors } logua:integer; { non-zero to log all UDP packets } resolve_addrs:server_type; { addresses to resolve from } resolve_dserve:servers_dv; { default servers } measure:msure_type { measurement data } end; qsection=packed record qnames:array[1..max_exp_rrs] of exp_dname; qtypes:packed array[1..max_exp_rrs] of qtype; qclasses:packed array[1..max_exp_rrs] of qclass { qanswer:array [1..max_int_rrs] of rr_pointer deleted 9/13/88 since it seemed stupid PVM } end; exp_ref=packed record aproc:boolean; rr_data:exp_rr; owner:exp_dname; end; int_ref=packed record aproc:boolean; rr_ptr:rr_pointer; owner_used:boolean; { true if owner has name } owner:exp_dname { rather than tree location } end; section=packed record exp_count:integer; { count of exps } exp:array[1..max_exp_rrs] of exp_ref; int_count:integer; { count of ints } int:array[1..max_int_rrs] of int_ref; end; {* Header fields as defined by the RFC. This form is used throughout the program in representing the header. *} header_template=packed record id:field16; { identifier for query } response:boolean; { query (0) / response (1) } opcode:field4; { kind of query } aa:boolean; { responding NS is authority } tc:boolean; { message was truncated } rd:boolean; { recursion desired } ra:boolean; { recursion available } unused:field3; { fill to 16 } rcode:field4; { response code } qdcount:field16; { question section count } ancount:field16; { answer section count} nscount:field16; { authority section count } arcount:field16 { additional section count } end; {* Data send/receive format *} pkt_type=packed record header:header_template; data_recs:packed array[1..536] of octet end; xmit_type=(dgm, tcp); {* Format for queries used by dgm/tcp routines } message_template=packed record xmit_using:xmit_type; octet_cnt:integer; { in data_recs } to_address:integer; to_port:integer; from_address:integer; from_port:integer; raw_pkt:pkt_type end; {* Internal representation of query/response *} query_template=record rawmsg:message_template; header:header_template; q_section:qsection; {question} sdata:array[sectcode] of section end; { query_template } { ***** New style message definitions ***** } chunke_type=record bp:g1bpt; (* pointer to data *) length:integer; (* length in bytes *) kind:chunktypes (* type of chunk *) end; rdchunk_table=record count:0..max_chunk; chunke:array[1..max_chunk] of chunke_type; end; dheader_type=packed record domain_id:field16; { identifier for query } response:boolean; { query (0) / response (1) } opcode:field4; { kind of query } aa:boolean; { responding NS is authority } tc:boolean; { message was truncated } rd:boolean; { recursion desired } ra:boolean; { recursion available } unused:field3; { fill to 16 } rcode:field4; { response code } qdcount:field16; { question section count } ancount:field16; { answer section count} nscount:field16; { authority section count } arcount:field16 { additional section count } end; rawmsg= packed record rec_count:field18; {received word count} count:field18; {word count} case boolean of true: (unspec:packed array[1..max_msg_octet] of octet); false: (version:field4; {ip header} ihl:field4; tos:field8; iplength:field16; unused1:field4; ident:field16; flagrsvd:field1; flagdf:field1; flagmf:field1; fragment:field13; unused2:field4; ttl:field8; protocol:field8; ipchecksum:field16; unused3:field4; sorc_adr:field32; unused4:field4; dest_adr:field32; unused5:field4; {end ip header} sorc_port:field16; {udp header} dest_port:field16; unused6:field4; udplength:field16; udpchecksum:field16; {end udp} dhead:dheader_type) end; transport=packed record { transport information } xmit_using:xmit_type; foreign_address:integer; foreign_port:integer; local_address:integer; local_port:integer end; rrdv= record namebp:g1bpt; { pointer to name } databp:g1bpt { pointer to data } end; section_dv=record truncated:boolean; count:integer; rdv:array[1..max_rrs] of rrdv end; domsg= packed record { domain format message } free_ptr:g1bpt; { pointer to unused octet } free_cnt:integer; { count of free octets } parse:array[sectcode] of section_dv; case boolean of true: (dhead:dheader_type); { domain header } false: (data:packed array[1..max_msg_octet] of octet); end.