diff options
260 files changed, 80335 insertions, 4614 deletions
diff --git a/contrib/bind/CHANGES b/contrib/bind/CHANGES index 8206c7e..a09b7d4 100644 --- a/contrib/bind/CHANGES +++ b/contrib/bind/CHANGES @@ -1,2941 +1,1265 @@ -$Id: CHANGES,v 8.56 1998/04/07 04:59:42 vixie Exp $ - --- 4.9.7-T1A released --- + --- 8.1.2-T3B released --- -808. [security] A number of routines did insufficient bounds checking which - could cause crashes by reading from an invalid memory - location. (From BIND-8). + 366. [bug] Z_AUTH was set on the cache zone do_reload(). -807. [bug] The server sometimes leaked the flushset (ns_resp.c). - (From BIND-8). + 365. [security] Missing bounds checking in inverse query handling + allowed an attacker to overwrite the server's stack. -806. [bug] add_related_additional() leaked memory if the name - was already in the related array. (From BIND-8). + 364. [port] Added support for HP MPE. - --- 4.9.6 released --- + 363. [bug] named-xfer automatically restarts the transfer if the + SOA changes during the transfer. There was no limit + on the number of restarts, resulting in a lot of + wasted effort if the SOA was constantly changing. + The number of restarts is now limited. -805. [security] The server now caches only those response records - that are within the current query domain. (From BIND-8) + 362. [security] Requesting a zone transfer for a domain name which + had a resource record of a certain format would + cause the server to abort(). -804. [security] another buffer overrun plugged, this time in res_search(). + 361. [bug] named-xfer tries to close files named might have + had open. On Solaris, sysconf(_SC_OPEN_MAX) can + return RLIM_INFINITY, and if it did named-xfer + would try to close all those files. named-xfer + now applies an upper limit of FD_SETSIZE. -803. [bug] core leak fixed in ns_resp.c (twice). + 360. [port] Solaris 2.5 systems needed <sys/resource.h> to + be included in port_after.h to get rlim_t. -802. [proto] RTT sorting was defeating round robin for nameserver A RRs. + --- 8.1.2-T3A released --- -801. [bug] res_send() now considers FD_SETSIZE usefully. + 359. [func] IRS group support is now controlled by the + WANT_IRS_GR define in port_before.h. -800. [bug] formatting errors corrected in precsize_aton(). + 358. [port] Updated IRIX port. -799. [bug] now that inet_pton() is safe, we call it a little more often. + 357. [port] Added support for QNX. -798. [bug] file descriptor leak plugged on systems without SO_LINGER. + 356. [func] Added -u (set user id), -g (set group id), and + -t (chroot) command line options to 'named'. -797. [bug] named-xfer signal, exit, and stub bugs fixed. + 355. [func] If getnetconf() fails because it can't create the + socket used to get the interface list, the server + will log an error if it is doing a periodic interface + scan, and panic otherwise. Previous versions of the + server always panicked. -798. [bug] tokens with merely _leading_ digits won't be taken as TTL's. + 354. [security] Bounds checking in named-xfer, dig, host, and nslookup + had problems similar to those in item 293. Added a + few more bounds checks to the server. -797. [port] Motorola 88K port integrated. + 353. [port] Paths are no longer overridden in port_after.h, and + are now generated from the various DEST paths in + Makefile.set. -796. [doc] some spelling errors, omissions, and misdirections removed. + 352. [bug] Because of problems with setting an infinite rlim_max + for RLIMIT_NOFILE on some systems, previous versions + of the server implemented "limit files unlimited" by + setting the limit to the value returned by + sysconf(_SC_OPEN_MAX). The server will now use + RLIM_INFINITY on systems which allow it. -795. [security] "dig @0 version.bind chaos" no longer shows user names. + 351. [port] Updated HP/UX 10.x port. -794. [bug] make d_rcnt larger; reorder databuf for packing efficiency. + 350. [bug] errno could be changed by certain signal handlers. + These signal handlers now save errno on entry + and restore it on exit. This changes eliminates the + need for the SPURIOUS_ECHILD #define. -793. [bug] we forgot to reset a pointer after a realloc (named_xfer.c). + 349. [bug] hesiod.h wasn't installed. -792. [bug] RRset TTL was not being maintained coherently. + 348. [port] Added support for LynxOS. -791. [doc] BOG was off by one in its ndots description. + 347. [bug] res_update() leaked the zone section it allocated. + This leak no longer occurs on normal returns, but + still occurs when there is an abnormal return. This + will be addressed in a future fix. -790. [whining] preserve forwarded RRset order for one last release. + 346. [bug] Fix 303 fixed one thing and broke another, resulting + in a nonfunctional grscan(). -789. [bug] TCP timeouts were leaking file descriptors. + 345. [bug] Fix 328 was bad, causing the root zone to be purged + every time a toplevel domain was reloaded. -788. [bug] AXFR needs 64K to fit in, not PACKETSZ. + 344. [bug] The priming fix in change 330 erroneously called + unsched() twice, causing a core dump if priming + failed. The priming fix could also erroneously + query [0.0.0.0].0. -787. [bug] dangling CNAMEs caused erroneous forwarded responses. + 343. [bug] The REQUIRE() in free_rrecp() was wrong, and was + triggered by an unapproved update. -786. [protocol] better checking of incoming additional data. + 342. [port] Added support for SCO UNIX 3.2v5.0.4. -785. [bug] forced reload of parents after zone expiry had problems. + --- 8.1.2-T2A released --- -784. [bug] SRV RR's were not decoded properly. + 341. [port] The LOG_CONS option to openlog() does not work as + documented on some systems. The server will now use + LOG_CONS only if USE_LOG_CONS is defined by the + port. Currently the bsdos, decunix, freebsd, linux, + and netbsd ports define USE_LOG_CONS. -783. [bug] BUFSIZ is less than PACKETSZ on some systems (overruns). + 340. [bug] The pid file was updated before the configuration + file had been read. -782. [bug] named could spin on invalid TCP input formats (ns_main.c). + 339. [port] #define HAVE_GETRUSAGE for Solaris >= 2.5. -781. [bug] short names of all hex digits were being handled incorrectly. + 338. [func] 'host' can now print AAAA records. -780. [bug] doupdate was handling BOGUSNS and syslog messages incorrectly. + 337. [bug] rm_datum() erroneously set dp->d_next to NULL + when savedpp wasn't NULL. Given a dynamic update + operation that deleted more than one RR, this bug + would cause all but one of the RRs to be leaked, and + would prevent correct rollback if the update failed. -779. [bug] named-xfer can now handle RFC1035-compliant zone transfers. + 336. [bug] Make sure 's' isn't negative in res_send(). This + shouldn't happen, but there have been some reports + suggesting it can happen. -778. [security] wire protocol names now limited to MAXCDNAME octets. + 335. [lint] Cleaned up more gcc warnings. -777. [port] res_send name redefinition now covered by BIND_RES_POSIX3. + 334. [port] Added support for HP-UX 9.x. - --- 4.9.5-p1 released --- + 333. [bug] db_glue.c didn't compile if DEBUG wasn't defined. -776. [doc] doc/misc/FAQ.* updated by its author. + 332. [bug] named-bootconf.pl didn't convert secondary lines + that didn't contain a filename correctly. -775. [bug] KEY RRs were not allowed to default fields per [DNSSEC]. + 331. [bug] If the server was configured with forwarders (but + not in forward-only mode), and a query ran out of + forwarders and had no nameservers, then the server + would erroneously forward the request to [0.0.0.0].0. -774. [bug] nslookup was overflowing yet another internal data structure. + 330. [bug] If priming of the root servers failed, recovery could + take a long time. If using forwarders to prime + and the query expired, the first forwarder would + always be skipped on subsequent attempts. The server + complained about priming problems in forward-only mode, + even though it doesn't matter. -773. [bug] syslog was being given an unprotected string to format from. + 329. [port] Some versions of Linux apparently need SPURIOUS_ECHILD. -772. [debug] a debugging syslog() was made clearer. + 328. [bug] purge_zone() didn't recurse if given the root zone, + causing old data and new data for the root zone to be + merged. -771. [contrib] contrib/host updated by its author. + 327. [func] Add log_check() and log_check_channel(). -770. [bug] nslookup was overflowing an internal data structure. + 326. [func] Add r_prev field to ns_updrec in <arpa/nameser.h>. -769. [port] ultrix linkage hackery removed from res/res_comp.c. + 325. [bug] Rollback of a failed dynamic update was done in FIFO + order instead of LIFO order. -768. [lint] named-xfer u_char* vs. char*. + 324. [bug] evTryAccept() closed the wrong fd if getsockname() + failed. -767. [port] shres/sunos updates from the author. + 323. [bug] eventlib didn't clear bits that had been serviced + or deselected out of ctx->{rd,wr,ex}Last. -766. [bug] nslookup was not limiting the number of addresses it handled. + 322. [bug] evDestroy() destroyed the files list before destroying + the streams list. If there were any active streams, + this would cause a double destroy of the streams' + file objects, very likely triggering an 'insist'. -765. [port] LOG_NOWAIT turned on if available. + 321. [bug] The correct error code for a failed asynchronous + connect was not reported. It now is, at least on + systems that have the SO_ERROR socket option. -764. [lint] nslookup NULL vs ERROR. + 320. [func] Allow multiple pending accepts. evTryAccept() now + reports the errno if an error was queued. -763. [bug] p_rr() was erroneously reporting short packets. + 319. [bug] The toplevel Makefile passed MARGS before $settings, + which prevented overriding a port's Makefile.set + from the command line. -762. [bug] minor memory leak fixed (during bad-name syslogging). + 318. [bug] The Solaris port_after.h checked for SUNOS_2_5_1 + instead of SUNOS_5_5_1. -761. [port] NeXTstep portability improved for modern systems. + 317. [unused] [This change number was allocated but not used.] -760. [bug] NAPTR RR support was incomplete/broken in named-xfer. + 316. [bug] evTryAccept() didn't append to the done list correctly + if connLast wasn't NULL. -759. [port] The resolver's POSIX.3 conformance is now optional since - it was causing trouble for vendor shared library editing. + 315. [bug] The dynamic update code was incorrectly converted to + clean up ns_updrec structures using the new clustered + memory allocator, and this would cause an 'insist' to + be triggered some time after a dynamic update had + been processed. Instead of freeing the ns_updrec + fields directly in ns_update.c, res_freeupdrec() was + added to the resolver. - --- 4.9.5-rel released --- + 314. [bug] Adding and then deleting an RR in a single dynamic + update request would crash the server. -758. [doc] more Linux libc discussions included. + 313. [bug] The nameserver would only try zone transfers from + the master that answered its SOA query. If a master + for some reason can answer the SOA but not the AXFR, + the other masters (if any) should be tried. -757. [doc] RFCs 1876, 1995, 1996, 2010, and 2052 now included. + 312. [security] Bounds checking in the resolver and dynamic update + code had problems similar to those in item 293. + Added more checks to ns_resp.c. -756. [contrib] new version of contrib/host received from author. + 311. [bug] The s_wbuf in the qstream structure was leaked in + certain zone transfer failures. -755. [bug] nslookup had a latent buffer overrun in initialization. + 310. [bug] If the server ran out of memory in ns_xfr(), the + subsequent connection cleanup could modify the + z_numxfrs field of zone 0 instead of the zone being + transferred, causing an 'insist' to be triggered later. -754. [port] NCR's flavour of SVr4 is now supported. + 309. [bug] NAMELEN() could return a negative length. -753. [bug] fp_nquery() could read past end of buffer. (fix from BIND 8.1) + 308. [func] Don't log ECONNRESET in stream_getlen(). -752. [conf] SENSIBLE_DOTS is now the default. SGI can use WANT_PIDFILE. + 307. [bug] include/isc/assertions.h and include/isc/list.h + weren't installed. -751. [doc] the the BOG had an extra "the" in two places. + 306. [bug] Timewarping into the future would cause repeating + timers to generate an event for every interval between + the previous time and the new time. Repeating timers + are now rescheduled based on the last event time, not + their due time. Idle timers now use the last event + time to compute the idle interval instead of the due + time. -750. [bug] erroneous zones weren't resetting z_ftime. + 305. [bug] The BOUNDS_CHECK() for the 5 32-bit integers in the + SOA RR was wrong. -749. [bug] named-xfer's handling of unknown type codes was not robust. - (it's still wrong but now it's wrong more gracefully.) + 304. [bug] lib/isc/assertions.c and lib/isc/memcluster.c did not + follow the port_{before/after}.h convention. + memcluster.c #included eventlib.h but did not need it. -748. [lint] u_char vs. char changes in db_load.c. + --- 8.1.2-T1A released --- -747. [bug] a previous patch had leftovers. + 303. [bug] 'bp' in grscan() in lib/irs/lcl_gr.c was incorrectly + validated, potentially causing corrupt data to be read. -746. [bug] dangling CNAMEs were not handled properly. + 302. [port] #define HAVE_GETRUSAGE for Solaris >= 2.5.1. -745. [doc] shres/sunos/INSTALL, ./INSTALL and man/gethostbyname.3 - modernized. + 301. [port] Added support for Solaris 2.6. -744. [bug] NAPTR replacement domains were being verified as hostnames. + 300. [bug] The space for the pathname of named-xfer in the + options block leaked. -743. [port] hpux10.10 makefile cleanup. + 299. [bug] <irs.h> wasn't in the include directory, and wasn't + included before "port_after.h". -742. [bug] inet_net_pton() was doing bad things to subnets and b'casts. + 298. [func] Added "deallocate-on-exit" and "memstatistics-file" + options. If deallocate-on-exit is "yes", the server + will painstakingly deallocate every object it + allocated. This is slower than letting the OS clean + things up, but is helpful in detecting memory leaks. -741. [func] source and owner are now logged with name errors. + 297. [port] GNU libc 2.0 doesn't have <nlist.h> so in the + Linux port we now provide a stub nlist.h that + includes the real nlist.h if GNU libc < 2.0 and + does nothing if >= 2.0. - --- 4.9.5-t6b released --- + 296. [bug] "make stdlinks" didn't "mkdir /var/obj" if /var/obj + didn't exist. -740. [bug] dangling cname checking had a few memory leaks. + 295. [bug] Specifying a query-source with and address and port + that the server was listening to didn't work. -739. [func] SRV support made more complete; NAPTR support added. + 294. [security] The server was willing to answer queries on its + forwarding sockets. -738. [protocol] dangling CNAMEs are no longer considered format errors. + 293. [security] rrextract() did insufficient bounds checking which + could cause it to crash the server by reading from + an invalid memory location. -737. [bug] owner domain names like "*." were not considered valid. + 292. [bug] The server sometimes leaked the flushset (ns_resp.c). -736. [contrib] new version of contrib/host included. + 291. [bug] The server did not detect oversized UDP packets, + causing useless retries. -735. [doc] added some text to shres/solaris/INSTALL. + 290. [bug] free_listen_info_list() leaked the IP matching lists; + the leak occurred when the config file was reloaded. -734. [bug] loading a zone with a single line SOA RR killed following line. + 289. [bug] [This bug number was allocated for something that + turned out not to be a bug.] -733. [bug] priming could deadlock in odd cases. + 288. [func] Add new list and assertion code to the ISC library. -732. [bug] SIGHUP now caught before initial zone load. + 287. [bug] "dig +sort" doesn't do anything, but was mentioned + in dig's usage message, as well as in the man page. -731. [bug] IP/TCP session logging now controlled by #ifdef DEBUG. + 286. [bug] Some systems have a default FD_SETSIZE much smaller + than the number of files that can be opened. This + could cause problems in the resolver and eventlib. + FD_SETSIZE may now be set in + port/*/include/fd_setsize.h. -730. [port] untested HPUX 10 support added to top level Makefile. + 285. [bug] If OS probing failed to match any of the supported + ports, the build would try to continue with BSD 4.4 + settings, with poor results in most situations. An + error message is now printed if probing fails. -729. [port] ultrix vs. _res_close(); ultrix wins. + 284. [func] The interface list is now doubly-linked. -728. [bug] several d_rcode references weren't #ifdef'd NCACHE. + 283. [bug] The server would panic if binding to an interface that + it had discovered failed. Simply not listening to + the interface is a better solution. -727. [bug] SOA timer warnings now consistently logged at LOG_WARNING. + 282. [bug] The nslookup Makefile didn't prefix DESTHELP with + DESTDIR when setting DEFS. -726. [protocol] added T_NAPTR as RR type 35, hoping the IANA concurs. + 281. [bug] A socket() called in ns_main.c used PF_INET instead + of AF_INET. - --- 4.9.5-t5b released --- + 280. [bug] The sample named.conf used "clean-interval" instead of + "cleaning-interval". -725. [port] shared libraries should work on Linux now. + 279. [bug] Some panic() messages in the IP matching code in + ns_config.c were wrong. -724. [bug] "dig @0 VERSION.BIND TXT CHAOS" had never been tested. + 278. [bug] Setting an interval to zero (e.g. interface-interval) + eventually caused random timer destruction. -723. [port] Solaris 2.6 has AF_LINK but not sa_len. + 277. [bug] ns_panic() used "args" twice, but only called + va_start() and va_end() once. -722. [protocol] verify RdLength of A and AAAA RRs. + 276. [bug] nslookup's "ls" command always listed all records + instead of behaving the way its man page describes. -721. [port] missing include directories will be made during "install". + 275. [bug] add_related_additional() leaked memory if the name + was already in the related array. -720. [port] solaris and sunos should use native assemblers with gcc. + 274. [bug] If a timer was cleared while in executing its callback, + and a new non-repeating timer was created afterwards + (but still in the callback), the new timer was + erroneously destroyed when the callback completed. -719. [port] cleaned up some A/UX linkages. + 273. [func] Added transfer-source and host-statistics options. -718. [func] some SOA sanity checks were changed from errors to warnings. + 272. [func] The zone number is now unsigned, allowing up to + 65536 zones instead of the previous limit of 32768. -717. [port] BSD/named/Makefile needed to have dmalloc.c reference removed. + 271. [func] Added evDefer(). -716. [protocol] cnames and referrals were generating spurious log messages. + 270. [bug] The meaning of the count returned by select() varies + somewhat by operating system. Under certain + circumstances, this confused eventlib's accounting and + caused the server to spin. -715. [port] ultrix PCC didn't like a =&, said it was ambigious somehow. + 269. [func] Added evLastEventTime(). - --- 4.9.5-t4b released --- + 268. [bug] Connections weren't cleaned up when the eventlib + context was destroyed. -714. [port] contrib/os2-emx now contains files nec'y for OS/2 (EMX). + 267. [func] Added evTimeRW() and evUntimeRW() to control idle timer + usage in the eventlib streams module. + + 266. [func] Added file descriptor table to ev_files.c to improve + performance of evSelect() and evDeselect(). -713. [func] gethostbyname2(x, AF_INET6) now accepts address literals. + 265. [func] Added evHold(), evUnhold(), and evTryAccept(). -712. [bug] gethostbyname() wasn't seeing RES_USE_INET6 early enough. + 264. [func] Double-link many eventlib lists to allow faster + removal of list elements. -711. [bug] nslookup was printing IPv6 addresses improperly. + 263. [bug] Remember the previous non-blocking status of + sockets given to evListen(). -710. [port] an alignment bug was found and fixed by Cray. + 262. [func] Added idle timers to eventlib. -709. [bug] named-xfer was dumping core on incoming LOC RRs. + 261. [func] Added clustered memory allocator to eventlib; eventlib + and named now use this allocator. -708. [protocol] primary zones are edited to make rrset ttl's coherent during - loading. + 260. [func] The value of FD_SETSIZE that eventlib uses can be + set by changing include/fd_setsize.h. -707. [protocol] rrsets with coherent ttl's won't be overridden by new rrsets - with incoherent ttl's. + 259. [bug] Notification of hosts on the also-notify list stopped + after the first successful notification. -706. [port] Ultrix portability restored. + --- 8.1.1 released --- -705. [func] added "limit files XXX" to boot file. + 258. [bug] Setting SO_SNDLOWAT to 0 in ns_xfr() wasn't doing + what it was intended to do, and could trigger a + kernel bug on various systems derived from BSD 4.4. -704. [bug] trace generation code was getting unaligned accesses. + 257. [bug] In lib/irs/dns_ho.c, variable needsort was used in + addrsort() before it was initialized. -703. [contrib] added contrib/getkeyby, from gnu@toad.com. + 256. [func] Ignore ECHILD from select() if SPURIOUS_ECHILD is + defined. -702. [func] MAXDNAME is now 4*256+1 to allow for \000 and the NUL. + 255. [bug] The contents of libport.a needed to be in libbind.a. + libport.a has been removed. -701. [bug] samedomain() wasn't paying attention to escapes. + 254. [install] Install library and .h files under /usr/local/bind + instead of /usr/local. When the include files were + in /usr/local/include, some compilers would + automatically use them. The clients would typically + not link with -lbind, causing unresolved symbols at + link time. -700. [func] allow long text strings in T_X25 RRs. + 253. [port] Removed change 216. -699. [port] added base64.c to shres/*/Makefile. + 252. [port] Added port for UnixWare 2.0.x. -698. [port] picked some lint out of tools/nslookup/getinfo.c. + 251. [doc] Added a documentation on installing to non-default + locations. -697. [bug] we were calling isupper() without calling isascii() first. + 250. [bug] The Makefiles for the binaries didn't create the + installation target directories if they didn't exist. -696. [protocol] a new kind of bad referral is now caught and ignored. + 249. [bug] Change HAS_SA_LEN to HAVE_SA_LEN in the AIX 4 port. - --- 4.9.5-t3b released --- + 248. [security] The server now caches only those response records + that are within the current query domain. -695. [func] Use delete_stale() in preference to delete_all() more often. + 247. [bug] Forwarding of dynamic update requests sent to a + slave for the zone is broken. This will be fixed + in a future release, but in the meantime the server + will simply refuse the request. Cleaned up the + way some update code indicated that the request should + be refused. -694. [func] DATUMREFCNT is no longer an option. + --- 8.1.1-T2B released --- -693. [port] fixed up the CPPFLAGS usage in the top level Makefile. + 246. [bug] process_prereq() could core dump if the name being + processed wasn't known. -692. [port] fixed up the __ defines (for POSIX.3) in include/resolv.h. + 245. [bug] It was possible to evSelectFD the same event bits + on the same fd more than once. -691. [port] removed all uses of "ssize_t", the world is not ready for it. - (fixed two latent signed/unsigned code bugs in the process.) + 244. [bug] eventlib didn't decrement fdCount correctly if the + eventmask matched in multiple descriptor sets. - --- 4.9.5-t3a released --- + 243. [lint] Improved comment in stale(). -690. [bug] the stale() and delete_all() calls in finddata() weren't - respectful toward T_ANY and C_ANY queries. + 242. [port] Added port for OpenBSD. -689. [lint] miscellaneous compiler warnings were disappeared. + 241. [bug] evConnect() didn't evDeselect() the fd if connect() + failed, which would cause us to call select() with + a mask that included a closed file. select() would + then return EBADF and trigger an 'insist'. -688. [func] handles insane/unreachable root servers a little better now. + 240. [bug] evCancelConn() closed the fd. -687. [bug] T1A's core dumps from bad databufs should be all fixed now. + 239. [port] SunOS doesn't supply RAND_MAX. -686. [func] overlong TXT strings should work again. + 238. [bug] fakeaddr() called inet_aton() which wasn't strict + enough. inet_pton() is now used. -685. [port] updated compat/include/sys/cdefs.h to BSD 4.4-Lite (8.7) vers. + 237. [port] Added UnixWare 2.1.2 port. -684. [doc] doc/i-d/* added. + 236. [bug] The buffer in res_querydomain could overflow. -683. [contrib] "nslint" added to contrib/. + 235. [bug] Fixed memory allocation problems in lib/irs/nis_gr.c. -682. [protocol] irrelevant authority information is now correctly ignored. + 234. [bug] evDeselectFD didn't restore the fd's previous + nonblocking status correctly. -681. [func] DO_RELOAD Is no longer optional. + 233. [func] Define SPURIOUS_ECHILD in Solaris port. Don't + complain about getting ECHILD from recvfrom() if + SPURIOUS_ECHILD is defined. -680. [cleanup] ALLOW_UPDATES is gone. + 232. [func] named-bootconf.pl now supplies a commented out + query-source directive and instructions to use it + if there's a firewall involved. -679. [port] some systems need _res to be in text rather than bss. + 231. [bug] Changed a few strdup() calls in rrextract() into + savestr() calls. This prevents "related" checking + from being turned off if the server runs out of + memory. -678. [port] -Dssize_t=int is gone; see portability.h. + 230. [bug] If the query control structure was reset in ns_resp.c, + we leaked the memory used for the previous + qp->q_domain. -677. [contrib] outdates #671; update to contrib/host version 960808. + 229. [func] Added the "dump-file" and "statistics-file" options. -676. [doc] formatting fix to man/named.man8. + 228. [bug] named.conf called "statistics-interval" + "stats-interval". - --- 4.9.5-t2a released --- + 227. [func] demoted "zones changed" and "zones shrunk" messages + in tryxfer() to debug level 3. -675. [lint] various. + --- 8.1.1-T1A released --- -674. [feature] support added for SRV RR (untested). + 226. [bug] evCancelConn trashed the connections list if the + first element was removed. This could cause a + seg fault or trigger an 'insist'. -673. [protocol] added definitions for EID, NIMLOC, SRV, ATMA, and IXFR. + 225. [bug] In the "cannot redefine listen-on for port ..." + error message, the port was not converted to host + byte order before being printed. -672. [bug] fixed decoding problem wrt AAAA in tools/nslookup/debug.c. + 224. [port] Added port for AIX 4. -671. [bug] fixed formatting problem wrt TXT in contrib/host/host.c. + 223. [bug] The dynamic update routine findzone() didn't match + class, so if you had two zones with the same name + but different classes (e.g. IN and HS), then + the wrong allow-update ACL could be used, and the + wrong zone could be updated. - --- 4.9.5-t1a released --- + 222. [bug] If a dynamic master zone was updated and then was made + non-dynamic by removing the allow-update ACL or + changing it to "none" before the zone had been dumped, + then the master file would not reflect the update. -670. [feature] added SIG and KEY RR support (without signature or - verification). + 221. [func] added 'also-notify'. -669. [internal] name/number translations are now mostly table driven. + 220. [func] revised HAVE_GETRUSAGE ifdefs in ns_config.c. The + "cannot set resource limits on this system" message + on systems without HAVE_GETRUSAGE will now be logged + once per options block, and the message severity is + now "info" instead of "warning". -668. [feature] nslookup now has better[/different] error messages. + 219. [bug] If the root name was encoded in a message using a + compression pointer, dn_expand() would erroneously + return "." as the name instead of "". -667. [feature] inet_neta(), inet_net_ntop(), inet_net_pton() added. + 218. [bug] when gethostans() in dns_ho.c encountered a CNAME + while processing a PTR query, it erroneously required + that the CNAME target pass the res_hnok() test (i.e. + that it be an RFC 952 hostname). -666. [bug] parent zone will be reloaded when a child zone changes. + 217. [bug] dnsquery didn't work because it tried to use the + obsolete and broken p_query() call instead of + fp_nquery(). -665. [protocol] RETURNSOA logic has been refined, and now ships "enabled." + 216. [port] set SH=bash in port/freebsd/Makefile.set. -664. [protocol] cached RRsets are now completely flushed when new data arrives. + 215. [port] #define ts_sec and ts_nsec to tv_sec and tv_nsec + respectively in port/freebsd/include/port_before.h. -663. [port] IRIX shared libraries are now supported. + 214. [bug] the clarification TTL changes (see change 145 below) + set the SOA minimum field to zero if the MSB was set. + The server now leaves the SOA RR alone, but sets + z_minimum to zero if the MSB is set. -662. [port] SCO OSE5 support has been upgraded slightly. + 213. [bug] if the SOA refresh or retry fields of a slave zone + were 0, an 'insist' would be triggered when zone + maintenance was performed. The server still leaves + the SOA RR alone, but now imposes a minimum value for + z_refresh and z_retry. -661. [bug] insane root servers will now be handled correctly. + 212. [func] added the clean-interval, interface-interval, and + statistics-interval options. -660. [bug] TXT RRs are now parsed and displayed in full RFC1035 form. + 211. [func] scan for new or deleted interfaces periodically. -659. [port] UXP/DS is now supported in the top level Makefile. + 210. [func] the _PATH_DUMPFILE default is now "named_dump.db". -658. [feature] BIND now checks that UDP checksums are enabled in the kernel. + 209. [bug] <isc/eventlib.h> and <isc/logging.h> were #included + after port_after.h. They are now #included before + it, since they #include system header files. + ns_lexer.h was #including <stdio.h> and ns_parseutil.h. + Now it #includes neither one. These changes required + that the definition of struct timespec be moved from + port_after.h to port_before.h in the ULTRIX, SunOS, + and A/UX ports. - --- 4.9.4-p1 released --- + 208. [port] removed HAVE_GETRUSAGE from the Solaris port, since + Solaris only has it if a Berkeley compatibility + package is installed. -657. [bug] some configurations were mistakenly disabling cache purges. + 207. [bug] abortxfer() always used SIGKILL, which didn't give + named-xfer a chance to clean up after itself. Now + abortxfer() does a SIGTERM first. If the SIGTERM isn't + successful, it will use SIGKILL. -656. [doc] "\ " was causing a line break in zone file parsing. + 206. [bug] If two zones with the same name but different classes + (e.g. IN and HS) were defined, then a zone transfer + of whichever zone loaded first would work normally, + but a zone transfer of the second would give only the + NS and SOA RRs. -655. [doc] named(8) wasn't describing the "response" literal. + 205. [bug] certain operating systems (notably Solaris) return + error codes the server didn't expect, and thus + treated as fatal to the interface. More error codes + are now recognized. The server will now log + unrecognized errors, but will not delete the + interface. Certain error results from recvfrom() and + accept() now panic the server. -654. [doc] formatting errors fixed in include/arpa/nameser.h. + 204. [bug] stub zone transfers would fail if there were no + NS records in the SOA response. The stub logic + now works as intended and has more error checking. -653. [doc] doc/misc/DynamicUpdate now has a deprecating comment. + 203. [bug] we logged a failure of bind() in opensocket_d() + twice. -652. [bug] BSD/nslookup/Makefile was making the wrong links. + 202. [port] Linux defines AF_INET6 as 10, so we use that value + in port/linux/include/port_after.h. -651. [bug] a hashing function should be as simple as possible, - but not simpler. + 201. [bug] library Makefiles want to press on if linking of + an individual module fails. The 'ld' rule was + set up to do this, but the subsequent 'mv' rule + was not, causing the make to stop if the 'ld' failed. + Now the 'mv' is done only if the 'ld' succeeds. -650. [bug] dn_mailok() could walk off the end of the name buffer. + 200. [bug] the value of timeout.tv_sec was printed in SendRequest + (bin/nslookup/send.c). select() on some systems + (such as Linux) modifies the value of the timeout, so + printing it is useless since it will always be 0. -649. [bug] bad names were not exiting through the right code path. + 199. [func] if s is too big for FD_SETSIZE in res_send, complain + and try another nameserver. -648. [bug] we were referencing dynamic memory after free()'ing it. + 198. [bug] sysnotify() was too strict in requiring an NS RR + for the server named in the SOA MNAME field. RFCs + 1996 and 2136 say the NS RR is optional. -647. [bug] savename() was bzero()'ing the wrong number of bytes. + 197. [bug] The parser erroneously freed zone_name if a zone + redefinition was attempted. This would cause the + server to dump core if a zone appeared more than + once in a configuration file. -646. [bug] ctypes.h needed to be included in res/res_debug.c. + 196. [bug] Makefiles below port/*/include had "fi \" followed + by "done" on the next line. This made bash 2.0 + unhappy. The "fi" is now followed by a ";". -645. [port] sys/types.h needed to be included in a lot of places. + 195. [port] ULTRIX's sh doesn't like an empty "for x in ..." list, + and that was causing "make install" to fail in + the src/port/ultrix/include/rpc directory. - --- 4.9.4-rel released --- + 194. [port] add SH variable to toplevel Makefile, document the + need to use SH=bash on systems where /bin/sh is + derived from "ash". -644. [bug] gethnamadr.c:getanswer() wasn't decrementing buflen. + 193. [bug] named-bootconf.pl could repeat end-of-line comments -643. [contrib] new contrib/misc/gencidrzone. + 192. [bug] ndc was being installed in DESTBIN instead of + DESTSBIN. - --- 4.9.4-t5b released --- + 191. [bug] block delivery of all other signals when in SIGTERM + handler in named-xfer. -642. [bug] SOA serial checking was not trying backup servers. + 190. [bug] named-bootconf.pl didn't handle non-masked xfrnets + correctly if the network was class B or class C. -641. [doc] added doc/rfc/rfc1713. + --- 8.1-REL released --- -640. [bug] don't try to purge the cache on nonrecursive servers. + 189. [port] update to the port/sco50 directory rcvd from author. -639. [bug] sysquery() was not recovering from lack of root servers. + 188. [func] to avoid potentially confusing log messages, don't + set Z_DYNAMIC if "allow-update { none; };" is + specified in the config file. -638. [bug] dnsquery.c wasn't calling res_init(). + 187. [bug] a panic() in new_ip_match_mask() erroneously + referred to the function as "new_ip_match_pattern". -637. [bug] ns_resp() was erroneously detecting name errors. + 186. [bug] transfers-in couldn't be set higher than the default. + It may now be set as high as 20. -636. [bug] nslookup() was returning failure even when fwdrs were avail. + 185. [doc] add a stub example to named.conf. -635. [bug] inet_pton() was returning EINVAL rather than EAFNOSUPPORT. + 184. [bug] the usage message was out-of-date. - --- 4.9.4-t4b released --- + 183. [port] some systems don't define AF_INET6, so we + define it if necessary in all port_after.h + + --- 8.1-T5B released --- -634. [bug] named-xfer was writing AAAA RRs to the wrong file pointer. + 182. [bug] fix the way bindname is allocated in hesiod_to_bind(). -633. [port] ULTRIX and RISCOS both need NEED_STRDUP in conf/portability.h. + 181. [bug] MAXHOSTNAMELEN wasn't defined on Solaris. -632. [bug] BSD/named/Makefile was installing its man page in section 1. + 180. [bug] a check for zptr != NULL in res_update was wrong. It + should have been zptr == NULL. - --- 4.9.4-t4a released --- + 179. [bug] sq_remove() and sq_done() were calling ns_freexfr() + when any stream was removed, resulting in a panic + when the server was reloaded. ns_freexfr() is now + only called when a zone transfer stream is removed. -631. [bug] nslookup was dumping core on bad 'server' commands. + --- 8.1-T4B released --- -630. [bug] dig was not able to print SRV RRs. + 178. [bug] if the server was reloaded and then a zone was + deleted and the server reloaded again, all within + a short period of time, then pending NOTIFY messages + would cause the server to panic when they ran. -629. [bug] dig was seeing artificial protocol errors printing AAAA RRs. + 177. [lint] replaced BUFSIZ with a more appropriate size in + several places. - --- 4.9.4-t3b released --- + 176. [func] change MAXDATA to 2*MAXDNAME + 5*INT32SZ. -628. [bug] "stub ." changes were being updated in the wrong place. + 175. [security] libirs now limits hostnames to MAXHOSTNAMELEN + characters. -627. [bug] forgot to remove fourth arg from inet_pton() in tools/addr.c. + 174. [bug] we called ns_refreshtime() instead of ns_retrytime() + in the Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL case in + zone_maint(). -626. [port] was missing -DSPRINTF_CHAR in one spot in the top Makefile. + 173. [bug] the server didn't clear the Z_NEED_RELOAD flag in + zoneinit(). - --- 4.9.4-t3a released --- + 172. [bug] if a server was a slave for a zone, and an outbound + transfer ever hung or terminated unusually, regular + zone maintenance would cease for the zone. -625. [api] inet_pton()'s signature changed due to ipng@sunroof discussion. + 171. [port] work around a bug in the Digital UNIX 4.0B SIOCGIFCONF + ioctl. -624. [port] shres/* should work again (was broken by inet_ntop, inet_pton) + 170. [func] the message logged when a zone is loaded now + indicates the class of the zone. -623. [bug] sprintf() doesn't return "int" on DomainOS, either. + 169. [func] the message logged when a zone is removed now + indicates both the type and class of the zone. - --- 4.9.4-t2a released --- + 168. [bug] if a zone's type changed from master to slave on a + server reload, the server erroneously deleted the + new zone data as part of cleaning up the old zone + data. -622. [bug] sprintf() doesn't return "int" on SunOS or ULTRIX. + 167. [func] when converting from wire format to printable format, + represent special characters ".;\@$ by escaping them + with \ instead of converting them to \DDD. - --- 4.9.4-t1a released --- + 166. [bug] when a slave zone expired, it was not scheduled for + immedidate maintenance. -622. [bug] more print errors in the name validation logic fixed. + 165. [port] added port for SCO OSE 5.0.2, renamed port for + SCO UNIX 3.2v4.2. -621. [feature] added support for IPv6 addresses to the resolver and daemon. - see doc/misc/IPv6 for details. + 164. [func] created the "response-checks" logging category. -620. [perf] XSTATS off by default. client stats now in XSTATS. + 163. [port] don't define AF_INET6 in nameser_compat.h. -619. [conf] LOC_RR is on by default (it's an RFC now). + 162. [bug] the server panicked if a dynamic update request + was sent for a dynamic zone which had not loaded + because of syntax errors in the master file. The + server now returns NOTAUTH. -618. [perf] pulled in memory saving NAME,NAMELEN,NAMESIZE logic from - development source pool. + 161. [bug] debugging messages in process_prereq() referred to + process_updates() instead of process_prereq(). -617. [bug] we were logging at INFO priority even when not loading a - zone due to certain kinds of database format errors. + 160. [bug] hp was not reset after a realloc() in named-xfer.c -616. [bug] truncated responses were not being forwarded. + 159. [bug] named-bootconf.pl didn't translate stub zones. -615. [contrib] added contrib/misc/gencidrzone.pl, updated contrib/host. + 158. [lint] cast a number of "no effect" statements to void so + that gcc doesn't complain when invoked with + -Wall -W -Wno-unused -614. [bug] minor and latent bug in dcalloc() fixed. + 157. [lint] a number of uses of the %lu printf() format were + converted to %u; the corresponding casts to u_long + were removed. -613. [bug] the RFC952 + "_" code wasn't strict enough. + 156. [lint] converted z_deferupdcnt and z_updatecnt from int to + u_int32_t. -612. [bug] the PTR name check was using ipv6.int rather than ip6.int. + 155. [func] maint_interval is now gone; SOA sanity checking + related to it is gone too. -611. [conf] changed "check-names forwarded" to "check-names response". + 154. [bug] in named-xfer, unsigned 32-bit integers were + sometimes stored in signed 32-bit variables and then + printed using a cast to u_long and printf() format + %lu. This would cause problems on 64-bit systems if + the MSB of the 32-bit integer was set. The variable + declarations have been changed to u_int32_t, and the + printf format is now %u. -610. [doc] man page said check-name, should have said check-names. + 153. [bug] log_open_stream() had two syslogs that said the + failing function was log_vwrite() instead of + log_open_stream(). -609. [bug] in res_send(), query ID mismatches weren't handled in VC's. + 152. [lint] made class, type, and dlen in rrextract() and + named-xfer.c/print_output() u_int16_t. -608. [bug] res_send() would overrun its buffer when parsing truncated - replies for its diagnostic output. + 151. [bug] the server was incrementing nssSentFErr in the + formerr: code in ns_resp.c even though it wasn't + sending FORMERR to anyone. -607. [bug] EINTR wasn't causing a select() restart in res_send. + 150. [func] in "check-names response fail" mode, instead of + just dropping a failing response, we now send + REFUSED to the client and drop the query. -606. [bug] fixed a race condition related to SO_LINGER. + 149. [bug] if there wasn't a space between the SOA minimum value + and a following ')' in a master file, the server + would generate an error when it tried to parse the + minimum value, causing the zone load to fail. -605. [bug] some "lame delegation" messages were printing wrong information + 148. [func] the list of supported syslog facilities has been + increased; the following facilities may now be used, + provided they're available on the system 'named' is + being built on: kern, user, mail, daemon, auth, + syslog, lpr, news, uucp, cron, authpriv, ftp, + local[0-7]. -604. [bug] uncached out of zone CNAMEs were returning SERVFAIL rather - than timing out; this prevented the client from retrying. + 147. [bug] the maybe_syslog_facility, logging_opt, + channel_severity, address_name, key_ref, key_stmt, + acl_stmt, zone_stmt, optional_class, and size_spec + rules in the parser either leaked memory or could + leak memory. -603. [bug] lame delegations will now try other servers rather than just - SERVFAIL'ing. the old behaviour was too draconian. + 146. [func] if an RR set in a reply differed from an RR set in + the cache only in the TTL, we would not update the + TTL of the RR set in the cache. We now update this + TTL to that of the reply RR set if the reply RR set's + TTL is greater. -602. [security] we were cycling back through the volatile cache when searching - for glue to match the bootstrap cache. + 145. [func] follow the direction of the clarification draft and + treat TTLs as unsigned 32-bit integers, with a + maximum value of 2^31 - 1. TTLs greater than the + maximum will be converted to 0. A warning will + be issued if this conversion occurs while loading + a master zone or during inbound zone transfer. -601. [bug] we were not recognizing upward zone cuts in some circumstances + 144. [func] "dig version.bind. txt chaos" now returns only + the version number (e.g. "8.1-T4B"). -600. [API bug] getnetbyaddr() was taking a long, rather than a u_long. + 143. [lint] fixed various mismatches between printf() format + string components and their corresponding + arguments. -599. [bug] PX RRs were not properly handled by named-xfer.c. + 142. [lint] SendRequest_close() in nslookup/send.c had a return + type of int instead of void. -598. [bug] WKS RRs were written incorrectly in db_dump.c. + 141. [port] converted bcopy() to memcpy() or memmove() as + appropriate. -597. [bug] named would not create a brand new pid file. + 140. [bug] certain buffer size checking comparisons in + rdata_expand() weren't working because they were + checking to see if an unsigned value was < 0. -596. [bug] memory leak in ns_resp.c plugged. + 139. [func] convert a few address comparisons from == to using + ina_equal(). -595. [bug] another wildcarding bug (in ns_maint.c) stomped. + 138. [bug] an address comparison used in marking a server as + bad was done incorrectly in ns_resp.c because the + comparison used = instead of ==. -594. [contrib] added contrib/misc/settransfer-gaine.shar. + 137. [lint] cleaned up warnings caused by assignment used as + truth-value in various source files. -593. [security] db_load() will allow invalid SOA ANAMEs, for now. + 136. [func] changed eventlib-related INSIST statements into + INSIST_ERR, so that we can print out strerror(errno). -592. [bug] dig and nslookup needed code from 4.9.4-T1A for AXFR (#589). + 135. [lint] replaced _getshort() with ns_get16() and _getlong() + with ns_get32() in various source files. -591. [bug] dig and nslookup both dumped core if dn_expand() failed. + 134. [lint] findzone() and rdata_expand() were used before + they were declared in ns_update.c, and were not + declared static. -590. [port] changed __RES to 19960229 due to dn_isvalid() API addition. + 133. [lint] merge_logs() was not declared in ns_func.h. -589. [bug] named-xfer was unable to handle some compliant AXFR streams. + 132. [lint] Linux port_after.h didn't declare daemon(). We now + do so, but only if GNU libc < 2.0. -588. [security] call dn_isvalid() from db_load() to catch zone naming errors. + 131. [lint] set_boolean_option() was not declared in ns_func.h. -587. [security] added function dn_isvalid(), called from dn_expand(), per CERT. + 130. [lint] yyparse() was not declared in ns_parser.y. -586. [bug] dangling NS RR's (no A RR's in cache) weren't recoverable. + 129. [lint] ns_lexer.h didn't declare lexer_end_file(). -585. [bug] named was ignoring the cache for "." even after priming. + 128. [lint] db_dump.c, db_lookup.c, db_update.c, db_glue.c, + db_save.c, ns_ncache.c, ns_req.c, ns_stats.c, and + ns_xfr.c didn't #include <string.h> -584. [bug] ns_resp() could dump core during some kinds of query restarts. + 127. [lint] logging.c, ev_connects.c, ns_maint.c, ns_glue.c, + ns_update.c, dig/dig.c, nslookup/list.c, + nslookup/send.c, host/host.c, and + dnsquery/dnsquery.c didn't #include <unistd.h>. -583. [bug] default logging priority for lame delegations now LOG_DEBUG. + 126. [lint] res_update.c, heap.c, db_load.c, db_save.c, db_glue.c, + ns_lexer.c, ns_forw.c, ns_maint.c, ns_req.c, + ns_stats.c, ns_xfr.c, ns_glue.c, ns_config.c, + ns_update.c, host/host.c, nslookup/list.c, and + nslookup/getinfo.c didn't #include <stdlib.h>. -582. [doc] added RFC 1912 which expands upon RFC 1537. + 125. [lint] res_mkupdate.c, ns_update.c, nsupdate.c, ns_print.c, + didn't #include <ctype.h>. -581. [port] BSD really does not have SIGIOT any more, stop using it. + 124. [port] replaced bcmp() with memcmp(). -580. [bug] getnetent() could mangle /etc/networks input lines. + 123. [func] while not required, it's nice to preserve the order + of RRs as received when ROUND_ROBIN isn't on, so + we now do so. -579. [bug] db_dump was printing -1 for TTL wherever default TTL was used. + 122. [bug] under certain improbable conditions, the server + could erroneously set a maintenance timer for a + master zone. When the timer went off, it would + trigger the INSIST() in zone_maint(). -578. [port] many scanf/printf patterns misused %lu, DEC AXP didn't like it. + 121. [port] replaced bzero() with memset(). -577. [bug] named-xfer and res_debug were mishandling "\\" in TXT/HINFO. + 120. [func] added multiple-cnames option. -576. [bug] "limit" directive was setting current but not max system limit. + 119. [bug] the timeout: code in ns_resp.c didn't clean up TCP + connections. - --- 4.9.3-p1 released --- + 118. [port] added port for IRIX 5.3, 6.2, 6.4 -575. [port] Ultrix/Hesiod named responses are oversized, we were - incorrectly accepting them and then overwriting the stack. + 117. [bug] removed declaration of getnum_error from db_load.c, + since it is now declared in ns_glob.h. -574. [port] BSD/OS 2.1 required some ./BSD/Makefile changes. + 116. [bug] GNU libc 2.0 doesn't have a <net/route.h>, so in the + Linux port we now provide a stub net/route.h that + includes the real <net/route.h> if GNU libc < 2.0 and + does nothing if >= 2.0. - --- 4.9.3-rel released --- + 115. [func] on Linux systems, avoid an often unnecessary 'ranlib' + and the subsequent relinking of all binaries by using + the 's' flag of 'ar'. -573. [contrib] put in "951231" version of contrib/host. + 114. [bug] 'make install' didn't work on HP/UX because the + path to the install script was wrong in many cases. -572. [doc] new file doc/info/SCO-2 concerning <sys/param.h> porting. + 113. [bug] named-xfer didn't clean up properly when sent SIGTERM. -571. [bug] zones whose master files contained only $INCLUDEs were - incorrectly considered to not have any RR's (old bug.) + 112. [bug] named-xfer didn't clean up properly if an error + occured in print_output(). -570. [doc] trivial man/named.8 tweak. + 111. [func] added "max-transfer-time-in" option. The server + used to allow a maximum of 2 hours for an inbound + zone transfer to complete. This time can now be + set globally or on a per-zone basis. The parameter + is the number of minutes a transfer can take. -569. [doc] minor documentation tweak to shres/solaris/ISSUES. + 110. [func] moved declaration of d_ns in struct databuf to improve + structure alignment. - --- 4.9.3-beta34 released --- + 109. [bug] addname() in ns_print.c didn't write an "@" for RRs + that contained a domain name which was the same as + the zone origin (it wrote nothing). -568. [bug] very minor initialization bug fixed in tools/dig.c. + 108. [bug] the server didn't check for EINTR in readable() and + writable() in ev_streams.c. -567. [bug] disabled VALIDATE; all this code is trash and will be removed - along with ALLOW_UPDATES very early in the next alpha cycle. - we are now back to the B26 level of stability, with several - minor bug fixes from intervening betas. + 107. [bug] check for both EWOULDBLOCK and EAGAIN after certain + system calls instead of using PORT_WOULDBLK. This + fixes partial zone transfer problems reported on + Sun systems. -566. [bug] fixed memory leak introduced in #565. + 106. [bug] db_load() couldn't read SOAs with ( ) that were only + one line. - --- 4.9.3-beta33 released --- + 105. [bug] fixed typo in Linux Makefile.set MANROFF definition. -565. [proto] we were generating truncated RRsets due to VALIDATE bugs. + 104. [func] move various rrset debugging messages, rm_datum, and + nsfree messages to debug level 3. Moved a few rrset + debugging messages to debug level 2. -564. [proto] we weren't stopping early enough on some kinds of truncation. + 103. [bug] d_rcnt could overflow; to prevent this it has been + increased to 32 bits. d_mark was made unsigned and + decreased to 12 bits. -563. [doc] added doc/info/Solaris, concerning Sun Patch-ID# 102165-02. + 102. [func] added macro DRCNTDEC to go along with DRCNTINC. -562. [bug] named/ns_resp.c had an overzealous #ifdef. + 101. [bug] clean_cache() didn't count deleted RRs, so it + always reported "Cleaned cache of 0 RRs". -561. [port] tools/nslookup/getinfo.c had an ANSI C nit. + 100. [bug] heap_for_each() didn't return a status, and didn't + check for a NULL context or a NULL action. + heap_element() didn't set errno to EINVAL when + given invalid arguments. -560. [port] shres/netbsd and Makefile's netbsd stuff was wrong. + 99. [bug] the category rule in the parser leaked memory. -559. [doc] shres/* documentation had more pathname problems. + 98. [bug] "notify" was not recognized as a valid category + name. -558. [port] SCO OSE5 portability problem (minor). + 97. [security] zone access control wasn't applied correctly to + names that didn't exist, allowing an attacker to + determine whether or not a given name exists in a + zone. -557. [doc] added doc/misc/style.txt out of my archives. + 96. [bug] we didn't recognize certain non-fatal errno values + when recvfrom() failed; this would result in us + dropping an interface unnecessarily. -556. [contrib] updated contrib/arlib, contrib/dnsparse (really!). + --- 8.1-T3B released --- -555. [bug] quoted newlines were still broken even after #509. + 95. [bug] named-bootconf.pl didn't process xfrnets correctly + (if no netmask was specifed, it assumed a mask of + 255.255.255.255 instead of the natural netmask for + the class of the address). -554. [bug] dangling CNAME cache chains could make named dump core. + 94. [bug] named-bootconf.pl didn't handle lines ending in a + comment. -553. [bug] forwarders didn't work well with VALIDATE. + 93. [bug] if rename() failed in merge_logs(), we would return + garbage instead of -1. - --- 4.9.3-beta32 released --- + 92. [bug] writemsg() in named-xfer.c was returning a random + value instead of the number of bytes written. -552. [doc] ./Makefile had some out of date comments. + 91. [bug] schedretry() could set retry times in the past + because it was relying on 'tt' which hadn't been + updated. It now calls gettime(&tt). -551. [bug] shres/sunos/* needed some fine tuning. + 90. [bug] 'tt' might not have been current when clean_cache() + was called. -550. [contrib] contrib/dnsparse replaced with a later version. + 89. [bug] ns_lexer.h didn't #include <ctype.h> - --- 4.9.3-beta31 released --- + 88. [cleanup] removed some relics of the early days of BIND 8's + new logging system from the parser and ns_config.c. -549. [bug] "make links" hadn't been tested in a while; shres/* req'd chg. + 87. [bug] when writing to a TCP socket, the server didn't + handle errors from the write() correctly. Under the + right circumstances, this will cause the server to + spin. The most common trigger would be a large + outbound zone transfer where the far end died. -548. [bug] shres/sunos/* needed some fixups due to a late Sun patch. + 86. [cleanup] fixed comment in dig.c that messed up font-lock mode + in emacs. -547. [doc] Makefile comments for Linux were out of date. + 85. [bug] inet_lnaof, inet_makeaddr, inet_netof, and + inet_network were missing from lib/inet. -546. [doc] OPTIONS had an incorrect path name and some factual errors. + 84. [func] improved log_channel creation and use by making the + type more opaque. The logging API provides a more + complete set of services. Added the LOG_CHANNEL_OFF + flag. -545. [bug] shres/sunos/Makefile had some incorrect path names. + 83. [func] removed statistics_channel; it wasn't being used. - --- 4.9.3-beta30 released --- + 82. [lint] a few handler functions were declared as + void (*)() instead of void (*)(void). All now have + the latter declaration. -544. [port] some systems with broken CPP's wouldn't compile ns_req.c. + 81. [port] added port for A/UX 3.1.1. -543. [bug] query restart bug in ns_resp.c. + 80. [port] added port for SCO UNIX 3.2v4.2. - --- 4.9.3-beta29 released --- + 79. [bug] when processsing slave zones during a config file + reload, in the "backup file changed" (or missing) + case we were calling purge_zone() and do_reload() + even if we had never successfully transferred and + loaded the zone. -542. [port] rearranged signal() calls to make POSIX + SYSV possible. + 78. [cleanup] moved writemsg() to named-xfer.c. -541. [port] padded _res to 512 bytes; moved initialized data to res_data.c. + 77. [cleanup] removed doupdate() from ns_resp.c. -540. [port] added experimental shres/netbsd/ directory. + 76. [bug] writev() in lib/bsd would keep going if there was + a partial write; this could cause incorrect output. -539. [bug] we weren't able to load 0 ttl's in zone files. + 75. [func] added readv() to lib/bsd. -538. [doc] BOG corrections. + 74. [bug] if evConnect() failed in tcp_send() we were aborting + the server instead of just returning an error. - --- 4.9.3-beta28 never released --- + 73. [port] automatically fix getgrgid() declaration in ULTRIX + 4.5 grp.h. -537. [contrib] new contrib/lamers/ directory. + 72. [func] make port/*/Makefile invoke SUBDIR make in + include. Add/modify include and include/sys + Makefiles. -536. [bug] there was a possible deadlock condition over missing glue. + 71. [port] added utimes() to lib/bsd. -535. [bug] previous patch to db_load() was misapplied. + 70. [doc] README broken up into INSTALL, TODO, port/README. + Added more info about many topics. -534. [bug] several ancient cache corruption bugs fixed in ns_resp(). + 69. [bug] NOTIFY didn't handle an unknown NS target. E.g. + if we had "test.domain NS unknown.name" and + "unknown.name" was not known, NOTIFY wasn't doing an + "A" query for "unknown.name". -533. [root] root servers required a new ``no-fetch-glue'' option. + 68. [lint] tweaks to ERR() and OK() in eventlib_p.h. -532. [bug] all kinds of stuff was broken under shres/ due to new subdir. + 67. [bug] 'ch' in main() was a char instead of an int. - --- 4.9.3-beta27 released --- + 66. [bug] in bin/named/Makefile, pathnames wasn't getting + linked with ${LIBBIND}, ${LIBPORT}, and ${SYSLIBS}. -531. [bug] limited support for labels containing \. (literal dot.) + 65. [port] automatically fix timespec in BSD/OS 2.1 includes. -530. [bug] new root.cache file imported from internic. + 64. [func] lib/isc/heap.c now includes port_before.h and + port_after.h. Fix 58 (below) has been undone; + with port_after.h we'll now use __ansi_realloc() + from Fix 59. -529. [bug] another set of bug fixes to the zone transfer scheduler. + 63. [bug] STRIP and PS were missing from MARGS in bin/Makefile. -528. [bug] VALIDATE reenabled but without packet editing. + 62. [func] RRs in the additional data section must relate to + RRs in the answer and authority sections. Only + certain RR types are allowed in the authority and + additional data sections. -527. [bug] glue passing through CNAMEs will now be cached properly. + 61. [bug] Dynamic update didn't understand SRV records. -526. [bug] deleted zones should no longer cause core dumps. + 60. [bug] SRV records weren't decoded properly. -525. [func] several messages changed to be more informative. + --- 8.1-T3A released --- -524. [bug] loc_ntoa() was returning a pointer to a stack variable. + 59. [bug] The IRS library also wanted an ANSI C realloc(). + port/sunos now provides __ansi_realloc(). -523. [bug] wildcard RR's were being deleted by purge_zone(). + 58. [bug] SunOS didn't like heap.c doing realloc() on a NULL + pointer (in ANSI C that is equivalent to malloc()), + so we malloc() instead. -522. [bug] "ndc start" didn't work if no pid file existed. + 57. [bug] interface discovery complained about bogus + interfaces on ULTRIX, SunOS, and HP/UX because + SIOCGIFCONF_ADDR wasn't defined in their port_after.h. -521. [port] Sun SVR4 fixes, including shared library support. + 56. [API] created lib/nameser/ns_name.c and moved a lot of the + functionality from lib/resolv/res_comp.c into it. + functions older than 8.1 were stubbed out, but new + functions from 8.1 were just renamed/removed. -520. [bug] we weren't using "forwarders" if "options forward_only" - wasn't set (in some cases.) + 55. [bug] findzone in ns_update wasn't ignoring z_nil zones. -519. [bug] named-xfer wasn't called res_init(). + 54. [bug] if the named-xfer exec() failed, a misleading message + was printed. -518. [bug] lots of byte order nits. + 53. [bug] interface discovery didn't work on NetBSD because + HAVE_SA_LEN wasn't defined in port_after.h. -517. [bug] "tools/host -a" now prints in RR format again. + 52. [func] log the host we got a NOTIFY message from -516. [proto] minimum TTL changes from five minutes to zero seconds. + 51. [bug] we weren't sending out NOTIFY messages if the SOA + was changed as the result of a dynamic update. -515. [bug] SOA TTL of zero is no longer considered an error. + 50. [bug] req_notify() wasn't calling sched_zone_maint() after + it called qserial_query(). -514. [bug] division by zero error corrected in ns_refreshtime(). + 49. [bug] initial_{data,stack,core}_size and initial_num_files + weren't in an #ifdef HAVE_GETRUSAGE block. -513. [bug] we had the #ifdefs nexted backwards in <netdb.h>. + 48. [func] use sysconf(_SC_OPEN_MAX) instead of getdtablesize() + in all cases when USE_POSIX is defined. -512. [bug] we were able to dump core while tracing due to a NULL pointer. + 47. [bug] printupdatelog() was printing the post-update serial + number in the zone section instead of the pre-update + serial number. -511. [bug] DiG wasn't able to suppress all of res_debug.c's comments. + 46. [bug] zp->z_serial wasn't being updated if a dynamic update + changed the zone serial number. + + 45. [bug] the SEQ_GT test in db_update was backwards. -510. [doc] BOG typos. new doc/misc/FAQ. new site in MIRRORS. + 44. [func] merge_logs() didn't work because a 'break' wasn't + removed when class and type lookups were converted + to sym_ston. -509. [bug] another side effect of the inet_aton() change was fixed, - this time it was breaking escaped newlines in named.boot. + 43. [func] evResetTimer() added to eventlib. -508. [contrib] new contrib/host, contrib/misc/settransfer, contrib/msql. - contrib/umich/lame_delegation was withdrawn by the author. + 42. [bug] incr_serial() doesn't need to call schedule_dump(). -507. [bug] DiG didn't do ndots and was trigger happy about options. + 41. [bug] reset_retrytimer() could clear a timer that had + already been cleared. -506. [port] NextStep, Interactive, SCO, Digital UNIX, ULTRIX improvements. + 40. [bug] some zone data structures weren't freed if the zone + was removed. -505. [bug] we were overly restrictive about nonauthoritative NXDOMAINs. + 39. [func] The eventlib timers module now uses a heap to + implement the timer queue. -504. [bug] named was generating corrupt responses in au truncation. + 38. [bug] dynamic zones weren't dumped if they were removed + from the configuration file. -503. [port] shres/* now supports SunOS 4.1.4. + 37. [func] created the "load" logging category. -502. [bug] nslookup wasn't behaving properly in the presence of "ndots". + 36. [func] find_zone now uses a hash table instead of a linear + search. -501. [bug] we now delay 5 seconds after an "ndc restart" or "ndc start". + 35. [bug] we weren't scheduling a retry for dumps or soa serial + increments that failed. -500. [bug] change #494 was incomplete. + 34. [func] instead of doing all NOTIFY messages five seconds after + loading completes, we now spread them out over up + to fifteen minutes (the maximum delay depends on how + many zones there are). - --- 4.9.3-beta26 released --- + 33. [func] if there are too many qserials running, we'll try + again in five to thirty seconds. -499. [bug] we needed a SERVFAIL in an error case. + 32. [bug] z_dumptime wasn't getting set to zero after a + zone dump. -498. [bug] some recently added byte order bugs were stomped; - data_inaddr() was made slightly more conservative. + 31. [func] Each zone now has a maintenance timer. sched_maint() + is gone. The new programming rule: if you change + zp->z_time, it's your reponsibility to ensure + sched_zone_maint(zp) gets called. -497. [port] local_hostname_length() moved to its own source file. + 30. [func] short circuit PrintTimers evPrintfs if not debugging + at a level where PrintTimers would print something. -496. [bug] Beta25's change to compat/Makefile was wrong. + 29. [bug] if a log message with a non-default category was + logged to a default category channel which had + print-category on, "default" was printed instead + of the category name. -495. [bug] tools/host.c wasn't processing cnames properly. + 28. [func] the performance of the main loop has been improved. - --- 4.9.3-beta25 released --- + 27. [bug] NOTIFY messages weren't being delayed after a + zone load. -494. [func] "include" directive in boot file is no longer fatal if the - specified file doesn't exist or is not readable. + 26. [bug] the eventlib category wasn't working if the channel + wasn't the default debugging channel. -493. [bug] new interfaces' UDP sockets weren't affecting select()'s mask. + 25. [func] added the "maintenance" logging category. -492. [doc] another round of changes and cleanups to the BOG. + 24. [func] periodic statistics dumps are now done using an + eventlib timer instead of in ns_maint(). -491. [bug] various cleanups to lame server detection. + 23. [bug] names which have multiple CNAME records are illegal, + but the server was allowing them. -490. [port] completely new shres/* from CKD. + 22. [func] convert to POSIX signals from eventlib signal handling; + the eventlib API no longer provides signal support. -489. [doc] added a ***NOTE*** to ./INSTALL about operating system files. + 21. [func] converted assert() to INSIST() so that the logging + system (category "insist") will be used if a + consistency check fails. -488. [port] GNU C Library changes for include/netdb.h. + 20. [bug] the server could exit when it shouldn't, and without + leaving a message or a core file, because it wasn't + handling SIGPIPE. -487. [func] named will try a little bit longer to bind() its stream socket. + 19. [port] Solaris has trouble if the size of the buffer used for + IP_OPTIONS processing isn't 40 bytes. -486. [contrib] new packages: contrib/inaddrtool and contrib/trnamed. + 18. [bug] library Makefiles we were using 'ld' instead + of ${LD}. Added LD_LIBFLAGS. -485. [func] ns_forw will no longer forward to 0.0.0.0, 255.255.255.255, - or 127.0.0.1. + 17. [bug] on at least one OS, ctime() can return NULL and + this can cause problems. We now call checked_ctime() + in ns_glue.c, which returns "<unknown time>\n" if + ctime() fails. -484. [port] more POSIX_SIGNALS conversions. + 16. [bug] some signal handlers were calling library routines + which POSIX does not designate as safe for use by + signal handlers. -483. [bug] compat/Makefile wasn't passing on all definitions to submakes. + 15. [func] finished conversion to new options scheme of + name checking and inbound zone transfer parameters. -482. [port] bad bug in NeXT C Library worked around. + 14. [func] added os_change_directory(). -481. [doc] RFC 1794 is now included in doc/rfc. + 13. [bug] write_open() in ns_config.c wasn't checking if the + file was regular before unlinking. -480. [bug] a debugging printf() was accessing freed memory. + 12. [func] added "os" logging category. -479. [port] doc/info/NCR has been replaced. + 11. [bug] named-bootconf.pl used the deprecated channel name + "default" instead of "default_syslog". -478. [port] doc/info/interactive has been replaced by its author. + 10. [bug] named-bootconf.pl didn't understand continuation lines. -477. [port] UNIXWARE 2.X changes. + 9. [bug] remove -p from mkdep command in Makefiles for + bin/named and bin/nslookup. -476. [bug] ns_init.c was creating files in "//tmp" rather than "/tmp". + 8. [bug] add CDEBUG to Makefiles that link using ${CC}. -475. [bug] inet_aton() reverts to mostly previous behaviour. + 7. [bug] timestamp and level were printed twice for file + channels in lib/isc/logging.c. -474. [bug] PTR->CNAME support added; name test fixed. + 6. [bug] off by one with on level_text subscript in + lib/isc/logging.c. -473. [func] added gethostbyname2(), improved its man page. + 5. [bug] broken channels sometimes weren't marked as broken + in lib/isc/logging.c. -472. [port] Linux connect() can reconnect, res/res_send.c now knows this. + 4. [bug] didn't set foundname=0 after try_again: in ns_resp.c. -471. [build] several "clean" targets were not removing ".depend" files. + 3. [bug] update_pid_file() didn't put a newline after the pid. -470. [bug] dqflush() was using memory after free()ing it and never closing - any file descriptors and not clearing select()'s mask bits. + 2. [func] minor log message tweaks in ns_config.c. - --- 4.9.3-beta24 released --- - -469. [bug] We no longer share static return buffers across functions in - res_debug.c. - -468. [logging] An extraneous haveComplained() was removed from ns_resp.c. - -467. [portdoc] Linux build doc changes. - - --- 4.9.3-beta23 released --- - -466. [doc] big reorg to BOG. - -465. [doc] minor corrections to man pages. - -464. [port] NEC Makefile changes. - -463. [contrib] random updates. - -462. [bug] res_send() wasn't always clearing errno, which led to - false-negative return conditions. - -461. [port] minor u_char-vs-char lint removed. - -460. [port] backed out a recent Linux portability change. - - --- 4.9.3-beta22 released --- - -459. [port] made a major lint pass. - -458. [func] paved over a bad security hole in named-xfer. - -457. [bug] negative caching vs (secure_zone | cname checking) bugs. - -456. [port] moved all:: target to be first in top level Makefile. - -455. [bug] res/res_send.c had a bad macro definition. - -454. [doc] RUNSON moved to doc/info. MIRRORS file added. - -453. [quality] learntFrom() was reformatted. - -452. [doc] minor changes for shlib/ISSUES, tools/nslookup/nslookup.help. - -451. [port] linux, NCR, Solaris, NExT portability changes. - -450. [func] added RES_NOALIASES flag, needed for security. - -449. [bug] we were defining a nonstandard DNS header flag as PR. no more. - - --- 4.9.3-beta21 released --- - -448. [port] systems with hundreds of network interfaces need big ioctl()'s. - -447. [func] zones without NS RR's or with mismatching SOA RR's are caught. - -446. [bug] miscellaneous fixes to res/gethnamaddr.c. - -445. [bug] the secure_zone logic was incomplete. - -444. [bug] bootfile "options" parsing was broken. - -443. [bug] named-xfer was munging incoming WKS RR's. - -442. [contrib] various cleanups. - - --- 4.9.3-beta20 released --- - -441. [contrib] put in DOC 2.1.1. - -440. [func] change/addition to the "lame delegation" syslog message. - -439. [bug] emulation macros WIFSIGNALED and WIFEXITED were bogus. - -438. [bug] missing "#ifndef INVQ" added. - -437. [doc] man pages and BOG updated to include new B18/B19 features. - -436. [port] PIDDIR definition removed from Solaris 2.X. - -435. [port] shres/Makefile fixed for new location of inet_addr.c. - -434. [port] getnetnamaddr.c had a spurious "#if defined(sun)" - -433. [bugs] random typos and glitches from the beta19 afternoon rush. - - --- 4.9.3-beta19 released --- - -432. [func] we should be much more resistant to root cache corruption now. - -431. [bug] tcp socket send buffer will now be set at 16K to avoid blocks. - -430. [bug] ns_req.c had two cases where it could overflow a buffer. - -429. [bug] the "." zone will now respect the setting of NO_GLUE. - -428. [func] 0.0.0.0 A RR's are allowed in the DB but we won't use them. - -427. [func] "options fake-iquery" added, users of Sun nslookup take note. - -426. [port] include/netdb.h now has some #ifdef sun defs in it. - -425. [bug] negative caching bugs in findns() and in ns_forw.c. - -424. [func] "limit transfers-per-ns" directive added. - -423. [bug] infinite loop fixed in named-xfer.c's version number printing. - -422. [bug] gethostbyname() of a dotted quad in an auto variable will - no longer cause the caller to consume random stack trash. - -421. [port] inet_aton() has moved from lib44bsd.a back to libresolv.a. - -420. [func] any punctuation character can now terminate an inet_aton(). - -419. [port] use sigemptyset(), sigaddset() - in preference to sigmask(). - - --- 4.9.3-beta18 released --- - -418. [bug] ``close(11): interrupted system call'' now fixed. - -417. [bug] big name servers would never refresh all their zones since - tryxfer() wasn't a "fair" scheduler. it is now. - -416. [func] SOA syntax errors will now lead to dead zones, not dead srvrs. - -415. [func] expiration values lower than refresh values cause a warning. - -414. [func] added "options" and "limit" directives to named.boot. - -413. [port] new file: doc/info/solaris.too. - -412. [bug] possible div-by-zero in ns_init.c. - -411. [port] NeXTstep, UNIXWARE, ISC, AUX changes/additions to top Makefile. - -410. [port] POSIX_SIGNALS covers a bit more code now. - -409. [bug] CNAME->PTR responses were triggering syslog() unnecessarily. - -408. [port] res_send.c's socket() calls were using the wrong arguments. - this was benign but with IPv6 looming, we need to clean it up. - -407. [bug] the delayed free() logic (DATUMREFCNT) didn't account for - the possibility of some NULL pointers, in ns_resp.c. - -406. [bug] we were walking through purged list items in ns_forw.c. - this caused bad things to happen when glue expired. - -405. [bug] "attempted update to auth zone" is no longer a warning. - -404. [bug] fp_nquery() is now used everywhere, fp_query() is deprecated. - -403. [port] hstrerror()'s result is now declared as const. - -402. [bug] a flakey initialization in the resolver has been fixed. - -401. [port] removed some junk around getnetbyname(), needs testing on suns. - -400. [func] BIND's version number now appears as a comment in zone files - written by named-xfer. - -399. [func] older, bogus HINFO RR's will now be fixed up with warnings. - -398. [bug] "SOA class not same as zone's" is now a zone load error. - -397. [func] all of the syslog() priorities have been lowered. - -396. [doc] added doc/misc/{FAQ.1of2,FAQ.2of2,vixie-security.ps}. - -368. [port] top level Makefile updates: .depend files aren't shipped; - solaris, linux, dec osf/1, dynix build more cleanly. - -367. [port] LOC RR logic has had some lint removed. also named-xfer.c. - -366. [contrib] dnswalk 1.8.3 is now included. - -365. [security] initial query ID is no longer a fixed constant. - - --- 4.9.3-beta17 released --- - -364. named/ndc.sh didn't always exit with nonzero on errors. - -363. include/arpa/Makefile was installing into //. - -362. convex cleanups. osf/1 cleanups. - -361. minor nit in sprintf() format string in tools/host.c. - - --- 4.9.3-beta16 released --- - -360. CRED is long gone. - -359. convex systems have getrusage(). - -358. CPPFLAGS wasn't quite right. - - --- 4.9.3-beta15 released --- - -357. netdb.h now externs h_errno. - -356. fixed odd corner case bug in res_query(). - -355. no BIND beta is complete without a patch to shres/PROBLEMS. - -354. minor addition to the "ndc" command line syntax. - -353. "." domain syslog() raised from LOG_DEBUG to LOG_WARNING. - -352. minor nit in named-xfer.c. - -351. the BSD/* Makefiles were mode 440, are now 444. - -350. new (undocumented) make target: "make mkdirs". - -349. output format change in tools/host.c. - -348. contrib/* updates. - -347. CPPFLAGS variable added to the Makefile tree, should quieten some makes. - nextstep, solaris, and svr4 systems have some new build parameters. - -346. BOG cleanups and addition of PX RR documentation. - -345. more items for RUNSON. - -344. several combinations and permutations of compilation options didn't work. - - --- 4.9.3-beta14 released --- - -343. Type cast fix for #340. - -343. Small change to RUNSON. - -342. Removed fsync() call, it really wasn't nec'y and was causing trouble. - - --- 4.9.3-beta13 released --- - -341. Small fix for #331. - -340. Inverse queries, if enabled, will be logged if QRYLOG is enabled and on. - -339. Nonrecursive servers (-r) will once again sysquery() for missing glue. - -338. named/ndc now preserves the user's $PATH. - -337. SUNSECURITY is now only on for shres/*. - -336. New version of contrib/host has been included. - -335. tools/nsquery.c and tools/nstest.c were moved to contrib/old/. - -334. Portability changes for HP-UX, Solaris, Linux, SCO UNIX. - -333. INVQ (inverse query support) now defaults to "off". - -332. Some of the internal hashing logic for syslog() rate limiting was not - accurate (more things were logged than should have been). - - --- 4.9.3-beta12-patch2 released --- - -331. Default domain in $INCLUDE files is now intuitive (rather than "."). - -330. Lame delegations are now only logged for class "IN". - -329. Format change to XSTATS output to make it more readable. - -328. Bad responses could cause core dumps in DiG, nslookup, etc. - -327. The now-requisite change to shres/* was discovered and put in. - -326. Portability changes for Linux, SCO, ULTRIX3, NeXT. - -325. Bit the bullet and reset all the RCS revision numbers to 8.1==4.9.3.b12. - - --- 4.9.3-beta12-patch1 released --- - -324. Added some missing pieces to the NSAP and NSAP_PTR handling. - -323. Tightened some of the GEN_AXFR code, fixed potential C_HS problem. - -322. Fixed minor niggle in the way "dig" parses its arguments. - -321. Final(?) tuning of the SunOS shres stuff. - -320. Reorganized the SunOS build params in the top level Makefile. - - --- 4.9.3-beta12 released --- - -319. Fixed DiG so that ". IN NS" was the default if no args are given. (Vixie) - -318. Merged the resolver with 4.4BSD's; made a BSD/ subdirectory off the main - tree for easy integration into BSD/OS, FreeBSD, NetBSD, et al; moved the - "master" subdirectory to "conf/master" to cut down on top level clutter. - -317. Lots of last minute fiddling to make Beta12 "right". (cast of thousands) - -316. Minor byte order bug in BIND_NOTIFY. (Grange) - -315. Added code to db_load() to detect "no RR's found" case. (Vixie; Heiney) - -314. "Zone declared more than once" test added. (Grange; Vixie) - -313. XSTATS interval was changed from "no more than once a minute, and usually - every fifteen minutes" to "no more than once an hour, and usually every - hour". (Gianopoulos; Vixie) - -312. Minor stuff in BIND_NOTIFY and the Ultrix and OSF/1 builds. (Heiney) - -311. Continuing hacks to LOC RR (experimental) and shres/*. (Davis) - - --- 4.9.3-beta11-patch5 released --- - -310. Minor BOG patches. (Shapiro) - -309. Minor LOC RR lint. (Heiney; Truck) - -308. Minor STUBS changes in ns_req.c. (Andrews) - -307. Ultrix and OSF/1 now install "man" (not "cat") pages. AIX now installs - *.[0-9] rather than *.0 pages. (Vixie, et al) - -306. conf/Info.* moved to new directory doc/info/*. (Vixie) - -305. NOTIFY could cause multiple simultaneous axfr's. (Andrews; Vixie) - - --- 4.9.3-beta11-patch4 released --- - -304. Minor fixes to PURGE_ZONE, CLEANCACHE, RETURNSOA, and dig. (Mark Andrews) - -303. LOC RR support is now in. (Chris Davis; Vixie) - -302. General portability stuff (with ISC leanings). (Mark Galbraith) - -301. Minor DiG portability fix. (Dima Volodin) - -300. Yet more HINFO fixes. (Gianopoulos) - -299. Really minor patch to tools/nstest.c, plus AIX fixes. (David Bolen) - -298. More shres/* fixes. (Davis; Woods) - -297. Minor SCO fixups. (Eduard Vopicka) - -296. Fixed #include <signal.h> problem in db_glue.c. (cast of thousands) - -295. Minor goofs in the sources. (Grange; Gianopoulos) - -294. Minor patch to the BOG (font problem). (Shapiro; Vixie) - - --- 4.9.3-beta11-patch3 released --- - -293. Minor #ifdef screwup corrected. (Mohamed Ellozy) - -292. Small HP-UX portability change. (Truck) - -291. Minor BOG correction. (Harlan Stenn) - -290. PX RR support. (Pierluigi Bonetti) - -289. Made random refresh interval a little more robust. (Miller; Vixie) - -288. Minor portability changes for DEC OSF/1. (Bob Heiney) - -287. We now do a setvbuf() on outbound AXFR streams since the system's - default size causes more write()'s (and therefore TCP segments) - than we really want. (Paul Mockapetris' idea; Paul Vixie's code.) - -286. Recast all uses of abort() to call private function panic(). This was - nec'y since we use the ABRT (IOT) signal to force a statistics dump, and - having it dump statistics inside of abort() was a bad thing. - (Mark Andrews noticed the problem; Paul Vixie fixed it.) - -285. Minor change to top-level Makefile for OSF/1 man pages. (Shapiro) - -284. Minor change to HINFO stuff. (Gianopoulos) - -283. Minor changes to XSTATS #ifdef's. (Benoit Grange) - -282. Minor change to top-level Makefile for ULTRIX/VAX. (William Gianopoulos) - - --- 4.9.3-beta11-patch2 released --- - -281. Another batch of (minor) HINFO changes. (William Gianopoulos) - -280. Minor formatting changes to keep ctags happy. (Craig Leres) - -279. Minor changes to OPTIONS. (Mark Seiden) - -278. New option XSTATS (default "on" for now). (Benoit Grange) - -277. res_mkquery() wasn't calling res_init(). (Philip Gladstone) - -276. Minor cleanup to shres/INSTALL. (Chris Davis) - -275. We now set a SO_LINGER on outbound zone transfers. (Peter Wemm; Vixie) - -274. Minor portability fix for VAX Ultrix. (Stan Barber) - -273. Fixed two time warp problems. (Bob Heiney; Paul Vixie) - -272. Named-xfer will now log and error and abort if it encounters an RR type - it doesn't recognize. (Mark Andrews; Paul Vixie) - -271. Minor cleanups to the HINFO comparison code in db_update. (Bryan Beecher) - -270. Made CLEANCACHE less of a CPU hog. (Benoit Grange; Mark Andrews) - -269. Add even more branches to the cred/clev decision tree, to make it more - robust about borderline data at zone cuts. (Jack McCann; Mark Andrews) - -268. New option (default: "on" for now): PURGE_ZONE. (Mark Andrews) - -267. Added contrib/misc/{soa-easy,dnsfind}.shar. I will not be including - this in the b11p2 diffs, though it will be in the next full kit. - (Tim Cook) - -266. I finally broke down and made a recommendation in the BOG with respect to - "nameserver 127.0.0.1". (Greg Woods supplied the patch) - -265. Minor portability stuff for SunOS. (Greg Woods) - - --- 4.9.3-beta11-patch1 released --- - -264. 900-second check removed; TTL==0 should work now. (Mark Andrews) - -263. Minor db_save() patch for initializing memory. (Bryan Beecher) - -262. Minor ESIX (SVR4.0.4/gcc) changes. (John Polstra) - -261. Minor dig-related patch to res_send.c. (Mark Andrews) - -260. Minor line number fix for ns_init(). (Havard Eidnes) - -259. NetBSD shared library stuff is now in contrib/misc/netbsd-shlib.shar. - (Matt Ragan) - -258. NeXT portability changes. (Allan Nathanson) - -257. Minor HP-UX portability stuff. (Lewis; Corrigan) - -256. Two medium sized bugs in BIND_NOTIFY. (Don "Truck" Lewis) - -255. Minor lint in ns_req.c. (Mark Andrews) - -254. Minor ndc.sh build problem. (Michael Corrigan) - -253. Minor coding inconsistency in res/res_comp.c. (Jeff Schreiber; Vixie) - -252. Minor BOG addition (SIGIOT). (Bryan Knowles) - - --- 4.9.3-beta11 released --- - -251. If a master zone's serial number goes backwards, named now logs a - warning. (Mark Andrews) - -250. Minor portability nit in ns_forw(). (Simon Leinen) - -249. Another portability problem fixed in ndc.sh. (Corrigan) - -248. Declaration problem with findZonePri() fixed. (Corrigan) - -247. References to CNAMES from MX/NS/MB will now be explicitly logged. (Vixie) - -246. Made the BIND_NOTIFY logic more robust; it still does not match the - current I-D (no delays yet). (Vixie) - -245. Fixed a writable-string problem. Added a lot of ANSI "const"'s. (Vixie) - - --- 4.9.3-beta10-patch1 released --- - -244. Added shres/PROBLEMS file. (Chris Davis) - -243. Corrected the BOG on the meaning of ".". (Doug Luce, Paul Vixie) - -242. SOA's can now be stored in $INCLUDE files. (John Lind) - -241. Rejection of 0.0.0.0 had a potential seg fault. (Mark Andrews) - -240. NoRecurse wasn't preventing queries for missing glue. (Mark Andrews) - -239. WKS nonaggregation test had bad length. (Ed Clarke, Chris Britton) - -238. NeXT library problem worked around. (Greg Wohletz) - -237. Core dump fixed in the dprintf() macro. (Eric Murray) - -236. MBZ fields in new queries were actually stack trash. (Olson, Vixie) - -235. Adds and changes to contrib/: - Added contrib/misc/dnstools.shar, from alt.sources. (Eric Murray) - Added contrib/misc/settransfer.shar (nonrecommended). (Tom Brisco) - Updated contrib/host/* with latest public version. (Eric Wassenaar) - Updated contrib/host/makezones with latest pub. version. (Philip Hazel) - -234. Made the "ps" command needed by ndc.sh a configurable parameter. - - --- 4.9.3-beta10 released --- - -233. Added and reordered a lot of code in ns_resp() to cause it to be - slighly harder to spoof with bad packets. More work needs to be done, - so that named will be as spoof-proof as the resolver has become. (Vixie.) - -232. Added new RR types to include/arpa/nameser.h, per RFC 1700. (Vixie) - -231. New "ndc" command. (Vixie) - -230. The VALIDATE option is now formally deprecated. It has bugs its detection - of invalid responses, and is known to mutilate perfectly valid CNAME - responses, to the detriment of clients. This code will likely be deleted - in the next BIND release, to be replaced by an ``always restart query'' - strategy. (Vixie) - -229. Moved a syslog() so that primary as well as secondary loads are logged. - -228. Resolver functions now reliably set h_errno. (Vixie, Wassenaar) - -227. Expired zones now lose their cached serial number information, giving - an opportunity to refresh a zone after a serial number goes backward. - (Andrews) - -226. Sun386i support crept in on little cat feet. (Brownlee) - -225. UDP packets could be overstuffed by 12 bytes. (Reilly, Vixie) - -224. failing connect()'s in named-xfer will no longer be logged. (Andrews) - -223. merged IETF stream (Vixie): - a. made ALLOW_UPDATES even more optional (it will disappear soon); - b. added NOTIFY option (experimental); - c. cleaned up some comments; - d. removed T_SA (was experimental, replaced by ROUND_ROBIN); - e. made named/Makefile's default CFLAGS -g (it usually inherits -O); - f. random code cleanup; - g. some internal errors are now fatal instead of warnings. - these changes were brought in once it became clear that there would be - another Beta of 4.9.3. - -222. tools/Makefile was using "make" instead of "${MAKE}". (Day) - -221. yet another bug was found and fixed in the SUNSECURITY code. (Brown) - -220. a variable reuse problem in the SUNSECURITY syslog()'s in gethnamaddr.c - was fixed. (Wohletz, Wemm, Vixie) - -219. "stub" root zones now affect the hint cache (STUBS is experimental). - in this situation it is reasonable to not have a "cache" directive, - and some code was reordered to make this possible. (Andrews) - -218. contrib/umich/lame-delegation/LISA-VI-paper.ps is now a proper - PostScript(tm) file. (Davis) - -217. syslog() cleanups in named-xfer.c. (Vixie, Barrett) - -216. shres/Makefile now forces -O. (Braniss, Ray) - -215. New contrib/misc/ctldns.sh. (Bush) - -214. New contrib/misc/dns-peers.info. (Wolfhugel) - -213. BOG and named(8) fixes. (Paffrath, Vixie, Hawkinson) - -212. database input errors will no longer cause the following line to - be ignored. (Gianopoulos) - -211. the TXT RR fixes done so far in 4.9.3 have been backed out; we're - back to the 4.9.2 behaviour. (Gianopoulos) - -210. the authority section will no longer duplicate the answer section - if both would contain the same NS RR set. (Vixie) - - --- 4.9.3-beta9-patch1 released --- - -209. installed marka's patch to CRED that fixes BETA9's flaw. - -208. added comment to README about -l44bsd and inet_aton(). - -207. new directory: contrib/multizdb. highly nonrecommended. - -206. small NextStep change in Makefile. - - --- 4.9.3-beta9 released --- - -205. minor Makefile fix after beta9 was previewed on bind-workers; also, a - new file conf/Info.Linux-more has been included. - -204. BOG fixes. - -203. netlists elements are now - { addr [ "&" mask ] } - which for the EBNF-impaired, means that "&" introduces an explicit mask. - implicit masks are either by-class or 0xffffffff, depending on ALLOW_HOSTS - in the call to get_netlist(). - -202. name compression is now case-insensitive. - -201. duplicate RRDATA won't trigger the new "auth warning" in db_update(). - - --- 4.9.3-beta8-patch2 released --- - -200. added a haveComplained() to limit auth warnings. - -199. fixed idiotic code reordering from patch1. - - --- 4.9.3-beta8-patch1 released --- - -198. a bad-string-termination bug was fixed in getnetanswer(). - -197. an uninitialized-variable bug was fixed in db_update(). - - --- 4.9.3-beta8 released --- - -196. Several minor corrections were made to the BOG. - -195. "clev" now distinguishes between root and TLD (wasn't worth a darn before) - -194. empty nodes in authority zones are now protected from non-auth updates. - (most of db_update() was rewritten to fix/support this.) - -193. negative cache items weren't updated before, now they are. - -192. zone updates from answers were prevented for new types but not if some - rr already existed with that type. fixed. also syslogged. - -191. the cache now distinguishes between authoritative answers and zone rr's. - -190. negative cache items are now marked appropriately authoritative. - -189. CRED is no longer optional. - -188. Another enhancement has been made to HINFO parsing. Named-xfer now - accepts RFC-bogus input formats generated by previous versions of BIND. - -187. SUNSECURITY now forces RES_DEFNAMES on so that relative "localhost" works. - -186. Minor portability fixes for DEC OSF/1, HP-UX. - - --- 4.9.3-beta7-patch2 released --- - -186. i forgot to comment out template Linux lines in top Makefile. fixed. - -185. "bogusns" directive significantly strengthened, for IN-ADDR.ARPA problem. - also fixed a bug in hardcoded root server lame detection. - - --- 4.9.3-beta7-patch1 released --- - -184. Yet another ULTRIX incompatibility has been worked around. - -183. Bogus HINFO RR's will no longer cause corrupt secondary zone files. - -182. NeXT support is now complete. Builds right out of the box. - -181. Updated TODO file. - -180. Added new INSTALL file. - -179. Minor doc fix in OPTIONS file. - -178. Security-related bug fix to new sunos shres/* stuff. - -177. Limited Linux portability was added. - -176. Trailing dots on zone names in named.boot are now ignored. - -175. Random lint was removed. - -174. DiG changes: increment version number (2.1), allow default domain (.). - - --- 4.9.3-beta7 released --- - -173. named-xfer would act strangely if trailing dot domains given as arguments. - -172. setenv() now provided on systems that need it (NeXTStep, e.g.). - -171. doc changes for shres/*. - -170. fixed debugging output problem in ns_req.c. - -169. fixed portability "bugs" on ultrix systems (some tools wouldn't link). - -168. minor functionality change in named/ns_validate.c. - -167. minor lint in res/res_comp.c. - -166. minor change to contrib/doc-2.0/*. - - --- 4.9.3-beta6 released --- - -165. another small adjustment to the Apollo section of the Makefile. - -164. a completely new shres/* was submitted; contrib/sunlibc is deprecated. - -163. INVQ is back on again by default. See README. - -162. another set of patches for obscure corner cases in the HINFO parser. - -161. added new SUNOS4 macro to Makefile and conf/portability.h; this should - fix the trouble folks were having with strerror() on SunOS 4.X systems. - -160. minor Makefile changes. - -159. processes which send outbound zone transfers now close all inherited - descriptors, since they can be longer-lived than the main named. - - --- 4.9.3-beta5 released --- - -158. various lint involving options which are rarely defined. - -157. sunos needed -DBSD=43 rather than -DBSD. - -156. minor memory leak fixed in ns_req.c. - -155. some install directories for DGUX were wrong. - - --- 4.9.3-beta4 released --- - -154. a new man/* hierarchy was installed which should be more portable. - -153. a new contrib/host has been included. - -152. a parsing problem in HINFO was fixed. - -151. a few minor changes to contrib/sunlibc/Makefile. - -150. typo in res_send.c fixed. - -149. fine tuning the credibility-level heuristics. - -148. dn_expand() will fail on names which have bad characters in them. - -147. disappearing zones could cause a core dump in syslog() - fixed. - -146. text of warnings in named-xfer corrected. - -145. limited DGUX, RISCOS support added. - -144. contrib/sunlibc/Makefile MFLAGS/MARGS problem fixed. - -143. another SunOS recv() bug has been worked around. - -142. various BOG fixes. - -141. updated master/root.cache file from latest InterNIC version. - -140. Added ``max-fetch'' to named(8). - -139. NOT_BIND problem in named/tree.c fixed. - -138. minor lint, memory leaks, and portability problems were fixed. - - --- 4.9.3-beta3 released --- - -137. some serious (and recently) dynamic memory bugs were killed. - -136. a reference to uninitialized data was fixed in res_query(). - -135. a RES_STAYOPEN-related bug was fixed in res_send(). - -134. isascii() and isxdigit() now simulated on systems which lack them. - -133. named's local setproctitle() has been renamed to avoid system conflicts. - -132. minor bugfix to negative caching code. - -131. minor bugfix in validation code. - -130. the typestats[] multiple definition problem was fixed. - -129. some Sequent portability changes were folded in. - -128. a new contrib/sunlibc was donated, but hasn't been tested. - -127. minor changes to contrib/sunlibc/Info.*. is anybody using shres/*, tho? - -126. STDIN_FILENO and STDOUT_FILENO are now defined by conf/portability.h. - -125. there is now a ``max-fetch'' directive in the boot file (see the BOG). - -124. there is now a RENICE option in conf/options.h. - -123. the toplevel Makefile has been made slightly more readable. - -122. <<DELETED>> - -121. minor fixups in the lame delegation code. - - --- 4.9.3-beta2 released --- - -120. I upgraded my "-me" macros so that the included doc/bog/file.psf is OK. - -119. NXDOMAIN responses from the negative cache will now always be - authoritative. this is the least of all evils, trust me. - -118. strcasecmp() in compat/lib is now ANSI compliant. - -117. PTR RR's are no longer subject to ROUND_ROBIN processing. - -116. writev() emulation for SCO had a bug. - -115. the resolver no longer calls sscanf() or qsort(). - -114. minor debugging nit cleaned up in res_querydomain(). - -113. IP options on incoming connections are now logged and ignored. This - should probably be done for datagrams as well but not today. - -112. tree.c made portable to non-POSIX/ANSI systems. - -111. NSAP RR's are now supported. NSAP_PTR RR's are deprecated and so left out. - -110. outbound zone transfers are now logged. - -109. various lint cleaned up wrt 16-bit integer handling. - -108. named-xfer was exiting bogusly on some systems due to flakey kernel - interfaces. i've rewritten some of the code to avoid the problem, - and fixed plenty of lint in the process. - - --- 4.9.3-beta1 released --- - -107. Apollo systems were dumping core because of a missing #include <resolv.h>. - -106. NSAP and NSAP_PTR RR's now recognized by res_debug() (but nothing else). - -105. NeXTstep 2.1/3.0 and Pyramid dcosx now nominally supported. - -104. res_querydomain() was doing Bad things if given an empty name. - - --- 4.9.3.a5.p4 published --- - -103. named-xfer's exit cause is now syslog()'d more often/clearly (Paul Vixie). - -102. I left out a ";" in the new compat/lib/ftruncate.c file (Craig Leres). - -101. X25, ISDN, and RT RR support have been added (Michael A. Meiszl). - - --- 4.9.3.a5.p3 published --- - -100. Another glitch (very minor this time) was found and fixed in the - QSERIAL logic. This was a performance problem only -- reliability - wasn't affected (Bob Heiney). - -99. SCO UNIX is now supported, thanks in part to Michael A. Meiszl. - -98. I witlessly used a GCC-only feature (automatic aggregate initialization) - in a5p2. Kazuhisa Shimizu was the first to report it. - - --- 4.9.3.a5.p2 published --- - -97. NEC EWS4800 EWS-UX/V Rel4.0/Rel4.2 support (from Kazuhisa Shimizu). - -96. Some of the security checking logic in the new res/gethnamaddr.c's - getanswer() was happening in the wrong order (thanks, Bob Heiney). - -95. Minor typo in the man/host.1 man page (caught by Robert Elz). - -94. DiG was groping core if given more than 10 tokens in a lookup string - (Michael J. Corrigan provided the fix). - -93. Queries to INADDR_ANY ("0.0.0.0") come back from the system's primary - interface, and res_send() was discarding them. A proper fix would add - a lot of code to the resolver, so for now we'll just work around it - (Michael J. Corrigan reported this). - -92. The "data outside zone" syslog message was misleading (Bob Heiney). - - --- 4.9.3.a5.p1 published --- - -91. res/gethnamaddr.c wouldn't compile on non-BSD systems since it depended - on LOG_AUTH which is a post-4.3 feature (Bob Heiney reported this). - - ****** 4.9.3-alpha5 released ****** - -90. redid most of my previous round of prototyping now that i truly - understand which variables and parameters should be u_char and which - ones should be char. (Vixie) - -89. added (optional) prototypes for _getshort() and _getlong(); this means - the calls all need casts of their argument since it usually isn't a - u_char*. Also prototyped res_query(), res_search, and the nominally - private but for some reason not static res_querydomain(). (Vixie) - -88. security related: responses from servers we didn't query are now ignored - by the resolver; answers with QDCOUNT!=1 are treated as errors; name - mismatches in the question or any part of the answer field are syslog()'d - and ignored. (Vixie) - -87. fixed a bug in the SUNSECURITY stuff. (Vixie) - -86. a long standing bug in the name hashing code that caused it to ``hash in'' - the case of the name's characters, was found and fixed. (twice.) (Vixie) - -85. Bob Heiney did some performance analysis and concluded that samedomain() - was soaking down cycles at a rate disproportionate to its usefulness; he - reimplemented it in a way that violated the (good,fast,cheap) rule. - -84. the RFC1101 implementation of getnetby*() was using case-sensitive - string compares. - -83. fp_query() will no longer try to format packets larger than PACKETSZ, - and for perversity, dig and named are now prepared to handle replies - (via TCP) larger than PACKETSZ. new function: __fp_nquery(). (Vixie) - -82. multiline initial syslog() is fixed (Bill G). - -81. Don Lewis sent in a big update for the lame delegation logic. Vixie fixed - one bug. Bryan Beecher had a big hand in this. - -80. TCP replies can now be up to 8K in size (don walsh). - -79. validation bug fixed (don lewis). - -78. BOG patches from mike minnich and others. - -77. more lint fixes for Cray (norb brotz). - -76. a new hostname(7) man page was contributed by Art Harkin. - -75. DESTINC is now a settable Makefile parameter (Marion Hakanson). - -74. the zones-not-transferring bug is finally gone. - -73. now using LOG_PERROR in openlog(); many parallel dprintf()'s are gone. - -72. inability to retrieve serial number via UDP now forces TCP transfer. - -71. removing secondary zone files and SIGHUP'ing will now force a transfer. - -70. "cache" directives can now specify "/class" as documented in the BOG. - -69. Mark Andrews' fix for the ns_forw core dump is in. - -68. Keith Bostic fixed some typo's in the man pages. - -67. Compiling without NCACHE is possible now (John Hanley). - -66. Bill Gianopoulos and Alan Barrett finally agreed on what glue was and - Bill's alpha4 patch is mostly gone now, and one new idea was added. - -65. BOG improvements (Vixie, Brooks). - -64. Mark Andrews' CLEANCACHE (recommended) and RETURNSOA (__NOT__ recommended!) - are in. RETURNSOA should not be enabled at this time; there's nothing - wrong with the code but it will cause cache corruption in older servers - and may not be necessary. The jury is still out. - -63. outbound zone transfers are now logged (requested by Ron Johnson). - -62. serial number queries sent out for zone transfer purposes will now be - limited to a maximum of four (4) simultaneous outstanding; this keeps - BIND from overflowing its UDP socket buffer when hundreds of zones must - be checked (still trying to fix Paul Pomes' problem). - -61. short A RR's in responses will no longer lead to purify errors due to short - malloc()'s in savedata() (thanks to Nicholas Briggs for reporting this). - - ****** 4.9.3-alpha4 released ****** - -60. manifest constants used instead of "sizeof({u_,}int{16,32}_t)", for - systems which lack 16- and 32-bit integers (paul vixie for norm brotz). - -59. zone transfer anti-glue logic made RFC1034-compliant (bill gianopoulos). - -58. seg fault in sysquery() (from LAME_DELEGATION) fixed (mark andrews). - - ****** 4.9.3-alpha3 released ****** - -57. a big, hefty patch was made to the negative caching logic (mark andrews). - -56. named-xfer will no longer scramble the default origin (alan barrett). - -55. random bits of lint found and removed (mario guerra). - -54. convexos-10 is now supported (jukka ukkonen). - -53. seg fault in database dumps (from VALIDATE) fixed (don lewis). - -52. problem with extra bogus 0.0.0.0 A RR's from VALIDATE fixed (mark andrews). - -51. the LAME_DELEGATION logic once written into 4.8.3 by don lewis has - been substantially reworked and put into 4.9.3-alpha3 (bryan beecher). - -50. all instances of "sizeof(HEADER)" were changed to "HFIXEDSZ" to make - life easier for the cray. also, "struct HEADER" in include/arpa/nameser.h - uses just bit fields now, for portability to 64-bit systems without - 16-bit integer types. (norb brotz suggested it; paul vixie did it). - -49. build changes for NeXT and AIX systems (artur romao; c. wolfhugel). - -48. random sunshlib changes (piete brooks). - -47. minor fixes for solaris build (carson gaspar; paul pomes). - -48. a few bugs were wrung out of the BOG (per hedeland; vixie). - - ****** 4.9.3-alpha2 released ****** - -47. several obscure Makefile problems were fixed (vixie). - -46. there is now a per-primary-NS quota for simultaneous zone transfers; this - will cut down on the retry thrashing seen on servers that are secondary for - thousands of zones (vixie). - -45. a bug introduced by change #23 has been fixed (marten terpstra; apb). - -44. the "data outside zone" messages are now consistent (piete brooks; vixie). - -43. several #include's were reordered in res/*.c and a few #ifdef's were - changed; BIND should now run OK on DGUX (henry miller). - -42. several changes to the conf/options.h and Makefile (vixie): - -> SVR4 has been added as a top-level Makefile CDEFS option - -> SYSV has moved from conf/options.h to the top level Makefile - -> INVQ is now an "#ifdef" rather than a "#if" - -41. resolver no longer uses initialized static data, which should make shared - libraries easier to generate (vixie did it, at the urging of many others). - -40. now compiles on Apollo DomainOS (don lewis). - - ****** 4.9.3-alpha1 released ****** - -39. lots of lint found and fixed (craig leres). - -38. illegal enum compare fixed in named/ns_stats.c (vixie). - -37. missing ')' added in SUNSECURITY section of res/gethnamaddr.c (h miller). - - ****** 4.9.3-prealpha released ****** - -36. ***REMOVED*** - -35. various bugs were fixed in the negative caching (vixie; mark andrews). - -34. several debugging and dump output problems were fixed (mark andrews). - -33. TXT RR's can now be read from zone files even if they lack quotes; - the RFC doesn't say quotes are needed (jim martin). - -32. limited support for AIX-3 is now included (christoph wolfhugel). - -31. SUNSECURITY is now an obvious default in ./Makefile (p killey; b beecher). - -30. VC queries that time out are now GC'd and SERVFAIL'd (mark andrews). - -29. HP-UX 9.0's top-level makefile variables have been changed (don lewis). - -28. various fixes for tools/host.c (jim martin; mark andrews). - -27. syslog messages logged by SUNSECURITY will now include the address of - the host that's having problems (david morrison). - -26. systems whose connect() calls fail if a socket is already connect()'d - will now have their sockets closed and recreated in res_send() (piete - brooks; mark andrews; vixie). - -25. res_send() will now corrected reset its "connected" variable when the - connectedness of a socket changes (mark andrews). - -24. SERVFAIL responses will no longer terminate the res_search() inner loop, - thus catastrophic problems with early search elements will no longer - prevent res_search() from trying later search elements (bryan beecher;vix). - -23. non-NS RR's for delegated subzones will no longer be accepted in a zone - transfer (alan p barrett). - -22. the setting for _PATH_PIDFILE is now overridden by the Makefile (l hume). - -21. named.restart.sh now has a smaller path with %DESTSBIN% first therein; - this should prevent the vendor version of named from being exec'd by - accident (leigh hume). - -20. big change: statistics are now kept "per name server" rather than as - a single global array. the /var/tmp/named.stats file format has changed - quite a bit, so older awk/perl scripts are likely to stop working. - -19. big change: every RR now keeps a pointer to a "nameser" struct; this - currently permits SIGINT-initiated dumps to include the address of all - non-zone data, which will help with tracking down corrupt data. - -18. db_load.c was missing two #ifdef/#endif's for CRED (mike minnich). - -17. don't aggregate SOA or WKS RR's in the cache (vixie). - -16. minor cosmetic changes (vixie). - -15. fixed typo in compat/Makefile ("LIBDIR" -> "DESTDIR") (rob davies). - -14. fixed spurious "accept: interrupted system calls" (vixie). - -13. named will now start as many named-xfer's as it should; previously it - lost track of the need for transfers at the beginning of each maint - cycle. also, we don't bother asking for an SOA if we know that our - zone is out of date. i've changed the transfer metrics so that more - transfers can happen concurrently, and maint cycles come more often. - (andrew partan; vixie). - -12. a number of LOG_ERR and LOG_CRIT syslogs were downgraded to LOG_NOTICE - (rob davies; vixie). - -11. sequence number checking now treats "zero" as a special case. - (craig leres; andrew partan; vixie). - -10. MFLAGS no longer used explicitly, since it is often used implicitly - (mark andrews; vixie). - -9. ADDAUTH is no longer considered experimental (tony stoneley; vixie). - -8. several obscure type bugs fixed (don lewis). - -7. signal handlers all now preserve errno (don lewis). - -6. TTL deprecation made more portable (don lewis). - -5. now compiles on Apollo DomainOS and is generally more POSIX-ish (don lewis). - -4. bryan beecher's "query" tool has been promoted to tools/ and renamed to - dnsquery. minor changes were required in several Makefiles (vixie). - -3. "make links" at the top level will now make a higher resolution link tree, - which makes porting easier on some systems (ian dickinson). - -2. Convex feof() bug now has a workaround (jukka ukkonen). - -1. gethostby*() will no longer overwrite its fixed-size array if a host with - too many addresses is handled (reported by piete brooks, fixed by vixie). - --------------------------------------- 4.9.3 above, 4.9.2 below - -4.9.2 ------------------ FINAL ----------------- Paul Vixie - -57. updated TODO, README files. - -56. fix to contrib/sunlibc/Makefile. - -55. several new items in contrib/. - -54. Corrected bad command line parsing bug in tools/dig.c; also added the - old query timing code back in (thanks to Havard Eidnes). - -53. Ported contrib/decwrl/host.c to the modern interfaces. - -4.9.2 ------------------ BETA5 ----------------- Paul Vixie - -52. A number of optimizations that fell out of negative caching and/or the - validation code have been turned off in order to avoid confusing older - nameservers and their unfortunate assumptions about co-invariants. - Mark Andrews and Robert Elz were the principle debuggers and contributors - to this part of the effort. - -51. We're now much more portable to systems without Posix or BSD signals, - thanks to Bill Wisner. - -50. tools/host.c now has more reasonable error messages and can deal with - negative caching servers. - -49. Lots of Makefile gaffes are now fixed. - -48. New "host" in contrib/host/, complements of Eric Wassenaar. - -47. AFSDB support is now complete, thanks to Chris Everhart. - -46. The bug whereby named would sporadically return NXDOMAIN when it should - have sent back a referral has been fixed. - -4.9.2 ------------------ BETA3, BETA4 ----------------- Paul Vixie - -45. Robert Elz has provided updated LOCALDOMAIN environment variable - processing, making it more like resolv.conf's "search" than "domain". - In the spirit of this I have added a RES_OPTIONS environment variable - and a corresponding "options" keyword to resolv.conf. All of this is - documented in the man pages and in the BOG. Robert has also contributed - several bug fixes to the validation and negative caching code. - -4.9.2 ------------------ ALPHA ----------------- Paul Vixie - -44. BETA1, BETA2, and three patches to BETA2 have all come and gone without - itemized descriptions in this file. I'll provide the RCS history on the - code to anyone who asks, but basically what's been happening is that some - core dumps were fixed, others added, then those were fixed too. Meanwhile - RFC 1535 has been published, codifying CERT's concerns and our answer to - them. BIND is now RFC 1535 compatible. RFC's 1535, 1536, and 1537 are - now included in the doc/ directory. Note that Mark Andrews supplied many - of the fixes to the core dumps, some of which were introduced by me and - some by ISI's negative caching and/or validation code. - -43. patch05 to ALPHA2 (930908) released: this includes new DNSRCH logic to - correct a serious problem that CERT called me with today. the change is - subtle and will have the effect that names which could match either as - fully qualified names or partially qualified names using the local search - list will be found as fully qualified. previous releases would have found - them first through the local search list. local search lists are a bad - idea in my opinion; see new SEARCH_DEFAULT option in OPTIONS file for more - information. also in this release: limited Solaris support, in the form - of POSIX-style signal handling used on systems which support (or require) - it. as of this patch, 4.9.2 has a good chance of compiling out of the box - on Solaris, modulo makefile edits. dig and host should be more portable - now, too. - -42. patch04 to ALPHA2 (930908) released: this corrects several borderline - syntax errors in various Makefiles (Sun and Ultrix makes complained); - it corrects a coredump on Ultrix systems (which aren't really as POSIX - as i thought they were); it lets dig and nslookup compile again on SunOS; - and it cleans up some dirty junk in named-xfer.c. this stuff is really - really minor but i would like to see it tested on a Sun system before the - beta. - -41. patch03 to ALPHA2 (930908) released: this uses compat/include by default - which is helpful on BSD/386 systems and shouldn't hurt any others except - perhaps real 4.4BSD systems (and maybe not even those); it removes Bryan - Beecher's SHUFFLE_ADDRS option since he and I agree that Marshall Rose's - ROUND_ROBIN stuff is more general and cleaner; it includes various patches - to the documentation sent in by several folks (please print the BOG and - let me know if you find problems in it); it fixes "make depend" problem - in "man/" subdirectory; it fixes several outright bugs in Gregory Shapiro's - SECURE_ZONES code; it removes an obscure syslog() that should have been a - dprintf() ("validate_count -> 0"); it fixes a bug in NCACHE whereby a T_ANY - query for a name which was negatively cached but had children would return - _answers_ with the T_ANY type for subsequent queries; several newer syslog - messages were reworded to make them clearer; a portability bug in the - SUNSECURITY logic was fixed; another in the RFC1101 logic was fixed; - support for the PAGER environment variable was added to nslookup (sorry, - i know we're in functional freeze but this will enable development in the - next cycle and it was pretty simple) and only affects the "view" and "help" - commands. - -40. patch02 to ALPHA2 (930908) released; this includes more fixed from Mark - Andrews, this time to Anant's NCACHE stuff (memory leak and functional - bug). Also included is a patch from Gregory Neil Shapiro to his SECURE_ - ZONES code, which I hadn't noticed since I don't run it here. - -39. patch01 to ALPHA2 (930908) released; this includes some fixes from Mark - Andrews to his "clev" and ADDAUTH stuff. The "clev" patch fixes a problem - on all servers; the ADDAUTH stuff is still experimental so most users will - not be affected by it. Dave Morrison also sent a patch for the USE_UTIME - logic, which is important for ULTRIX systems. - -38. 4.9.2-ALPHA2 released on 930908. - -37. Mark Andrews sent an initial attempt at implementing ADDAUTH, which will - eventually allow named to include authority and glue RR's with all - authoritative answers. I am not sure that the design goal is right, and - the implementation currently sends back glue RR's but no authority RR's, - so I'm recommending against using this for now. But since it changes some - internal interfaces in a harmless enough way, I'm including the changes. - -36. Marshall Rose's ROUND_ROBIN code snuck in at the last hour. This is the - best answer I've seen to the problems purported to be solved by SA RR's, - and my wording in the OPTIONS file shows this. - -35. These items from TODO is now done: - - [vixie@pa.dec.com 25apr93]: clean up debugging - replace all "#ifdef DEBUG...fprintf(...)...#endif" with dprintf(...) - which would be a macro that only expands to an fprintf() if DEBUG is - set. dprintf(x, (args)) with x as the log level. perhaps change log - levels to be symbolic, and perhaps make them a mask instead of a limit. - - [vixie@pa.dec.com 25apr93]: clean up #ifdef's and portability - add and use function prototypes. make everything static that can be. - externs should only be in .h files (add more .h files, per module if - needed, to cover these). add "export" keyword (null define) to make - it clear which names are exported and which are static. all top-blevel - names in a module must be "export" or "static". - - [gshapiro@wpi.edu and vixie@pa.dec.com 26apr93]: access control - "xfrnets" is ok but what we really need is full access control per - zone rather than a global list of acceptable client nets. this is - especially important if you send /etc/passwd via zone transfer. - - [postel@isi.edu anant@isi.edu jaffe@noc.rutgers.edu - 28apr93]: negative caching - Paul: - We'ed like to have included in 4.9.1 - our implemention for negative caching. - --jon & Anant. - - [vixie@pa.dec.com 16may93]: inet_addr needs to die - to be replaced by calls to inet_aton, which doesn't confuse the - broadcast address with bad addresses. - - [Paul: I know you said that you'd like to wait for the IETF DNS WG to - "bless" an official load balancing scheme, but I'll be adding my - shuffle A records to BIND 4.9 for use here at U-M anyhow. The code - mods to existing source files are minimal since the bulk of the work - is done in a separate .c I added. If you don't want SA records to - move into 4.9.1 unless they become official, please just toss this - first entry. --bryan@umich.edu] - - [bryan@umich.edu 25apr93]: add "shuffle A" records - There are several schemes for adding some kind of load balancing - capability to the DNS. Our "Shuffle Address" (SA) records are one - stab at this, and since they're in use at U-M, I need to add them - so we can use BIND 4.9 here. - - [bryan@umich.edu 25apr93]: add AFSDB records - AFSDB records were proposed in RFC xxxx. We use them here at the - University of Michigan, so I need to add them for our copy of - BIND 4.9. - - [bryan@umich.edu 25apr93]: small fix to resolver's p_cdname() - The current copy of p_cdname() in the resolver does not work - for query responses larger than 512 bytes (which can happen when - using TCP). A very small modification changes the "sanity check" - argument (the second one) to dn_expand() from "msg + 512" to - "cp + MAXCDNAME". (This showed up very recently.) - -34. While waiting for some last minute changes from volunteers, I looked - at my work queue and saw that asp@uunet.uu.net had asked a while ago - that named not fork/exec a named-xfer unless it had already determined - that the serial number was out of date. This is important to sites like - UUNET and DECWRL, which have thousands of "secondary" lines in their - named.boot and can take hours to check all the serial numbers at boot - time if named forks/execs named-xfer and lets named-xfer compare the - serial numbers, rather than comparing them in named and only fork/exec'ing - a named-xfer if it's actually neccessary to do a transfer. In spite of - C's lack of threads, this only took a few hours to do. So it's in. - -33. Gregory Shapiro's "secure_zone" changes are in. See the BOG. - -32. Internals changes: STATS is no longer optional; ns_req() has been split - into three functions for readability. Convex systems are now supported. - You can now define LOG_FAC in conf/options.h if you want to syslog as - LOG_LOCAL1 or some other non-LOG_DAEMON value. The mkstemp() problem on - ULTRIX has been fixed. More dead code has been eliminated. - -31. Large TCP queries are now printable in debug mode (which is used by - "dig" and "nslookup"), thanks to a patch and a lot of patient explain- - ations from Bryan Beecher. - -30. Data from subdomains ("deeper zones") is now considered more credible - than data from parent zones, if both are authoritative. This permits - a subdomain's data to differ from its parents delegation information - and have the most-local information supercede the least-local. Mark - Andrews <marka@syd.dms.csiro.au> sent this in, and it is nonoptional. - -29. rossc@ucc.su.oz.au's SUNSECURITY patch is now included, along with - marka@syd.dms.csiro.au's performance improvement to it. Note that - I am violating my own policies by including this, since it came - without a corresponding patch to OPTIONS, conf/options.h, and the BOG. - -28. Interfaces with multiple addresses were not being handled properly. - This is an issue for 4.3-Reno and later BSD systems, including BNR2 - ("Net-2") and 4.4BSD. Multiple addresses are not properly handled - as if they were all aliases for the localhost. - -27. Jukka Ukkonen <ukkonen@csc.fi> sent me some patches for the Convex, - which I've put it but cannot test. - -26. sob@tmc.edu (Stan Barber) sent me new versions of contrib/host/host.c - and contrib/host/send.c, which I have installed but not tested. I am - still waiting for someone to update the version in tools/host.c, which - is going to be a lot more work. Contact me via e-mail if you want to - help. - -25. My credibility stuff from the original 4.9 (and before that, KJB) - was operating under a ``scorched earth'' policy due to a brain fault - on my part when I wrote the code originally. Tim.Goodwin@pipex.net - discovered this and sent in a patch. Note that throwing out glue is - generally OK since glue is generally NOT OK, but disposing of it after - ~20 references is a lot better than disposing of it after 1 reference. - -24. NS RR sorting on forwarded and system queries was not happening - unless more than 1024 milliseconds of RTT variance existed among - the servers. This was a good value for development and testing - but not for production use. The value is now 128 milliseconds. - No, this should not be a configurable in the boot file. - -23. I am including a file doc/FAQ which was posted to usenet as: - From: craig@ecel.uwa.edu.au (Craig Richmond - division) - Newsgroups: comp.protocols.tcp-ip.domains - Subject: FAQ: Setting up a basic DNS server for a domain - Date: 3 Aug 1993 10:53:51 GMT - Organization: The University of Western Australia - Lines: 1088 - Message-ID: <23lg3v$1go@uniwa.uwa.edu.au> - Summary: Step by Step implementation of a DNS server - Keywords: FAQ DNS setup - -22. named-xfer now syslogs if the remote server's serial number is _lower_ - than ours, which does seem like a bad thing. per@erix.ericsson.se - (Per Hedeland) sent this in. - -21. man/resolver.3 had a typo on the exp_dn argument to dn_expand. fixed. - (Steve Alexander <stevea@lachman.com> sent this in.) - -20. include/sys/cdefs.h moved to compat/include/sys/cdefs.h since some - systems have their own which must be used. the top-level makefile - must be edited if you are on one of these systems, since the default - CFLAGS includes this new directory as a -I directive. sys/bitypes.h - has also moved. - -19. A neccessary bug fix for ISI's VALIDATE/NCACHE code has been incorporated. - If you had to rebuild without these turned on in options.h to get your - CNAME lookups to work again in an earlier 4.9.2 ALPHA, you can turn them - on again now. - -18. The q_system field of the query structure has been removed in favor of - a q_type field containing bit definitions. The old PRIMING_CACHE magic - cookie is no longer used. Go to the end of the universe, do not pass go. - -17. Converted to ANSI C. All functions are static unless they are actually - needed outside the current module ("file" in C terminology); static - functions are declared with prototypes if they are forward-referenced. - Externally visible functions are declared in separate header files, with - prototypes. ns.h and db.h have been split into four new header files: - db.h -> db_defs.h db_glob.h db_func.h - ns.h -> ns_defs.h ns_glob.h ns_func.h - - The *_defs files contain only structure and type definitions, and macro - definitions. Nothing that generates text or data space in the executable - is declared here. - - The *_glob files contain only global variable declarations, which used to - be defined in the various *.c files in a more or less random fashion. The - declarations are "extern" if included from non-main()-containing files, but - are defined globally and given initial values in main()-ish files. This - reuse of the same declarations insures that the type and size declarations - match between definitions and external references to them. - - The *_func files contains function prototypes for global ("extern") - functions. The prototypes are all optional so will not break non-ANSI - systems. Note that I don't have such a system any more so I may be wrong. - -16. Removed all remaining references to "short" or "long" that did not - depend on the vague semantics of those types. Most uses were actually - depending on a size of 16 bits for short and 32 bits for long, and there - are processors/compilers where each of these types is different. This - work was begun in 4.9 and is now complete. Note that some structs that - are used in large data structures use "char" for 8-bit integers. It helps. - -05Jul93 - ALPHA Released - -This is the cleanup release after 4.9. I'm going to try the TCSH style of -logging the changes; let me know if you think it's a bad way of doing it. - -15. the resolver now includes an implementation of RFC 1101, which allows - network names to be encoded in the DNS tree rather than in /etc/networks. - this implementation is by rps@matuc2.mat.uc.pt (Rui Pedro Mendes Salgueiro) - i put the test program and original documentation in contrib/rfc1101/. i - would like to see their main.c ("nettest") turned into a tools/nettest, - but i'm not willing to do the work myself. it needs a man page, etc. - -14. as expected the initial HS zone transfer stuff didn't work that well. - thanks to <per@ericsson.se>, retries after failed SOA queries will use - C_IN rather than falling through to C_HS inappropriately. - -13. ns_init.c was fcntl(SETFL)'ing in a destructive way. it now does a - fcntl(GETFL) to get the old option mask and then |'s in the new flag. - this patch came from Eduard Vopicka <Eduard.Vopicka@vse.cz>. - -12. there are two new conf/Info.* files; check 'em out. - -11. ultrix (some versions, especially the vax ones) libc.a had some bad - naming conventions for some resolver routines. getshort/putshort just - have to be real functions, not just macros, or you can't link anything - with this resolver. patch was sent by <aas@brain.physics.swin.oz.au>. - -10. sethostent(x) for host files was sticky for nonzero 'x' (avalon@anu.edu.au) - -9. hp9000s700 is now supported in include/arpa/nameser.h (avalon@anu.edu.au) - -8. statistics dumps now print the time in decimal-seconds-since-1970 in - addition to the old "ctime" format, for ease of debugging. (Peter Koch). - -7. systems with 14-character filename limitations have apparently been - having trouble in named-xfer since its temporary file names are bigger - than they can handle. ash@hp sent in some patches a while ago, enabled - with SHORT_FNAMES in conf/options.h, to deal with this appropriately. - We should probably just generate short names always. - -6. Some security stuff from ISI. According to Anant Kumar <anant@isi.edu>: - - The validation procedure is the major change here. Currently, we - accept anything from a server, as long as we had asked it a question. - This implies that a malicious server can really send us any data and - we not only pass it on, we also cache it for as long as the TTL - holds. This can be really bad for our health and for that of those - who use the DNS. - - We add this procedure to verify for each RR returned by a server - that it is indeed authoritative for either that zone, or for a - parent zone. We end up trusting the root servers for everything! - Also, the more rich our cache is the more choosy we become about the - data we add on to it. This stuff is all ifdef'd with "#ifdef VALIDATE" - - The negative caching stuff adds on a d_rcode field to the databufs. - Any positive entry now shows a NOERROR there while negative entries - have either a NXDOMAIN or NOERROR_NODATA. NOERROR_NODATA rcode is - never returned. It is used only to differentiate, within the - internal database, between negative and positive entries. We use the - regular hash table (hashtab) to store negative entries, too. Only - authoritative answers are negative cached, for NTTL (parameterized, - currently 10 minutes) seconds. Non-authoritative NXDOMAINs or - NOERROR with zero RR count, now generated, are now accepted but - never cached. This is ifdef'd with "#ifdef NCACHE". - -5. "make install" now has a prayer of working for the man pages. an observation - was made that net2++ systems _require_ formatted "cat" pages and that older - systems are _able_ to use them, so that's all we install. - -4. i wrote man pages for named.reload, named.restart, and named-xfer. these - were actually in 4.9.1 for 4.4BSD. - -3. unneeded functions in compat/lib will now generate placeholder symbols, to - make sure that the linker doesn't generate ugly-but-harmless warnings. - -2. my ignorance of the true meaning of _POSIX_SOURCE has been corrected, - along with the ugly-but-working code in conf/portability.h and elsewhere. - -1. non-resolver routines moved from res/ to compat/lib/. this will shorten - libresolv.a and make it easier to integrate new BIND releases into Net-2 - descendents such as 4.4BSD and BSD/386. - -4.9.1 ------------------ - -This is the integration of the changes that were made for 4.4BSD. This -release will not be published. Changes include: - -doc/BOG/*: many changes to improve appearance of the output, including - orphan-avoidance and better tab stops. Sent to me by someone on - the net who deserves thanks but I've lost the original mail. Oops. - -include/*: the CSRG people weren't entirely pleased with the interface - changes i made to the res_*() and inet_*() functions. in particular, - the changes from "long" to "u_int32_t" were too sweeping in their - opinion since Posix is already working on standardizing them and - might look unkindly on an apparently-still-evolving interface. also, - the possibility that all the vendors will change their implementations - to match the new interface is apparently rather dim. therefore most - externally-visible occurances of the int32_t type have been changed - back to "long" in the resolver interface. we believe that this should - still be portable to Cray and AXP machines, but i'll wait to hear from - someone who can actually try it out and let me know. - -tools/*: the "net2" version of "lex" requires some additional flags and libs, - and this had implications for the Makefiles and the dig.c source file. - nslookup's man page is now in man/ rather than tools/nslookup, for - consistency. - -named/*: last-minute 4.9-FINAL changes to named-xfer.c and db_load.c resulted - in corruption of TXT records on zone transfers, and a high number of - useless syslog(SYS_ERR) messages about zones already being up to date. - these last-minute changes have been massaged into better shape and are - now a lot readier for prime time than they were. a lesson was learned. - - the inet_aton() function is now used where appropriate, rather than the - old inet_addr(). this is just an evolutionary move that should have no - practical implications. bad addresses in the "tcplist", "bogusns", and - "sortlist" directives (from named.boot) are now syslogged. - - some open files are still inherited by named-xfer from named, but they - are properly closed now. - - the SIGXFSZ signal is now accepted as an alias for SIGHUP, in support - of the wierd DEC Hesiod implementation. no practical significance. - -res/*: one important bug fix in the gethostent() stuff, and a whole bunch of - evolutionary include file changes. - -include/*: include/sys was moved to compat/include/sys, since systems that - do not need it really really really need to get their own instead. - at some point i'm going to move the res/*.c files that are needed for - compatibility but not really part of the resolver, into compat/lib. - -general: there are more settable parameters in the top-level Makefile, and - they are propagated downward into the subdirectories' Makefiles. you - should not have to edit any Makefile except the top-level one. Note - that "make links" still creates local Makefiles in the build directory - because "mkdep" still edits the Makefiles on most systems. - -4.9-FINAL ------------------- - -Kevin Dunlap sent in some changes for the BOG. So did a lot of other folks. - -Someone asked about AXP-OSF, so I did a trivial 64-bit port. Porting to -other 64-bit systems should be simple now. Someone also sent in some MIPS -RISCOS portability changes, which were simple and therefore were put in. -Note that some type names have been added to BSD 4.4 as a result of this -work; they are going to be in <sys/types.h> in BSD 4.4 but they are in a -local include file called <sys/bitypes.h> in this distribution, with -appropriate #ifdef's in the include files that depend on them. Those of you -who are porting to 64-bit platforms where "long" isn't 32 bits should be -using these new names for your types; there was no standard before this, -but the names we've added for BIND 4.9 and BSD 4.4 are going to be proposed -to Posix at some point. Sometimes it's just not OK for "int" to be the -"natural integer size of the machine" and you just _have_ to tell the compiler -how many bits you want. - -The NIC added a new root server, thus pushing the size of a nonauthoritative -root server response (which includes the root server list in the answer as -well as the authority sections) over the 512-byte limit. This showed up a -long-term BIND bug wherein it failed to set the TC ("truncation occurred") -bit if truncation occurred anywhere but the answer section. Since truncation -was occuring at the end of the packet, in the additional data section, this -meant that BIND was generating truncated responses without setting TC in the -response header. Upon further investigation, I found that BIND ignored TC -on responses it received from other name servers. RFC 1035 states that RR's -from truncated responses should not be cached; with creative interpretation -of the exact 1035 wording, I found a way to reach this goal while still -caching the answer section (as long as the truncation occurred in some other -section, which 1035 gives no definitive way to determine but I'm happy with -my guess). - -While researching the above, I finally broke down and added credibility -output to the zone dump files. They are in the comments so should cause -no trouble. There's more work to be done on the dump output; in particular, -Phil Almquist proposed and even prototyped a "tagging" of all RR's with the -A RR of the nameserver that sent them to us; this feature should be added -and the dump output should include it. This would add a lot to our ability -to track down corrupt data. - -Don Lewis and I had more discussions about TC and ended up agreeing that the -right thing to do is to set TC on responses that overflow in the answer or -authority section, truncating at an RR boundary, but do not set TC on responses -that overflow in the additional-data section (truncating at a {name,type} -boundary). This actually solves the root server problem pretty well, since -BIND 4.9 will, when it tries to use an NS whose A isn't in the cache, generate -a sysquery() for the missing A. (Heck, additional data TTL's are depreciated -at the rate of 5% per use, so this would end up happening pretty quickly even -if we did cache a partial {name,type} -- but now we won't have to.) - -While trying to fix all of this stuff I ended up moving some functions around -to avoid duplicating them in different source files, and I reformatted some -source lines that went over 80 characters. I also made a few things "static" -that used to be unneccessarily global. More of that will happen in 4.9.1. - -DEC's product version of MIT Hesiod uses SIGXFSZ for what we do with SIGHUP; -since the default for SIGXFSZ is to exit, it seemed prudent to wire it up to -do what SIGHUP does instead, so that this BIND can run on DEC Hesiod servers. - -At the request of several people, I integrated the USC "dig" and Rutgers -"host" tools into the distribution. This required some changes to the -resolver library's debugging output formats, which will be visible in -nslookup, nsquery, and any other tool that sets the RES_DEBUG option. -Note that there is no support for "DEFNAMES" in this version of dig, due -to design changes between 4.8 (from which "dig" is derived) and 4.9. there -is no reason in principle why it can't be made to work, but it doesn't work -now. therefore only fully-qualified names can be looked up with this "dig". - -I had to change the name of the resolver "state" structure to be "__res_state" -for standards conformance (really, it is not reasonable to expect that because -a program includes <resolv.h> it will never define its own structure called -"state". This change highlights the imperative that any application which is -relinked against this resolver must first be recompiled against these include -files (notably <resolv.h>). This is true for almost all versions of libresolv. - -I asked for items for the "TODO" list and got quite a few. Check them out -before you hack; someone else may already have started doing what you want to -do. I also asked for tools for the "contrib" subdirectory and got 650KB worth. -They make the BIND 4.9 distribution a lot larger than 4.8.3 was, but the extra -bytes are well worth their weight. - -Kenneth Almquist (no relation to Phil, as far as I know) posted a patch for -res_send() that lets it keep track of servers that are responding "SERVFAIL" -or some other fatal condition; these servers are NOT used for retries of the -current query. This information is not persistent between calls to res_send() -since future calls will probably be for different {name,type} queries, which -will not neccessarily fail in the same way. This change is trivial and makes -a measurable difference in the amount of DNS traffic on my local net. - -4.9-BETA ------------------- April 17, 1993 -- Paul Vixie -- DECWRL - -"Peter Koch" <pk@TechFak.Uni-Bielefeld.DE>'s previous patch caused core -dumps on some systems. I fixed part of it and Peter sent me a fix for -the rest of it. All is now well. - -The Bind Operations Guide in doc/BOG has been updated to 4.9. Also, the -man page in man/named.8 has had some patches applied. The copyrights are -all fixed now. Let's get this thing OUT of here! - -4.9-ALPHA ------------------- March 15, 1993 -- Paul Vixie -- DECWRL - -There was a really bad bug affecting wildcards. I received a patch -from "Peter Koch" <pk@TechFak.Uni-Bielefeld.DE> which fixes some of -it, but I can't quite motivate myself to fix the rest of it since I -know that what's _really_ wrong is going to require chainsaws and -dynamite to fix and that'll add another year to the release. I think -that this patch will hold us for a while. - -There are a LOT of portability changes that I'm holding onto, especially -including 64-bit fixes. Do not submit any more portability changes -until 4.9.1 opens. Go ahead and make them, but be prepared to remake -them later. Let me know what you are doing but don't send me any diffs -for portability until I ask for them. 4.9 has been stuck in the barrel -for way too long already -- patches that don't fix RFC-noncompliance or -core dumps will just go into my "todo" folder (which is presently a -black hole of great mass). - -4.9-ALPHA ---------------- Febrtuary 2, 1992 -- Paul Vixie -- DECWRL - -Mostly portability fixes. The nslookup "lex" problem is BSDI-specific -and I'm not going to hold up release because of it. This will be the -last alpha release before the public beta. It is, as usual, running -the DEC.COM primary name service and has done so for more than a week -without any problems. - -4.9-ALPHA ---------------- January 10, 1993 -- Paul Vixie -- DECWRL - -Once I get the known bug in nslookup (see below) fixed, this version is going -to go into public beta. I would appreciate it if everyone would try it out. - -KNOWN BUG IN THIS RELEASE: something wild is going on inside of the yylex() -routing on BSD/386 systems. It only affects nslookup. I'm still trying to -figure out how I'm going to debug this; lex experts, please see what's going -on. None of the changes since the 930105 release should have been capable -of producing this change, but something is sure doing it. - -I finally fixed the {GET,PUT}{SHORT,LONG} macros to stop issuing warnings -on HP-UX systems. They are also warning-free on Ultrix(SPIM,VAX), BSDI(386), -and SunOS(SPARC) systems. I took the plunge and changed the internal functions -in res/res_comp.c to depend on these macros instead of duplicating the code, -and everything still works. - -Tom Limoncelli found three ancient memory leaks. I fixed two of them -but the last one looks too much like a "cannot happen" for me to be -willing to experiment with it. Besides which, it's "very" minor. - -Uses setsid() on POSIX systems. PID file is now optional. (arc@sgi) - -Comments (";" or "#") are now allowed in resolv.conf (arc@sgi). - -Documentation and copyright changes in README. - -Known to compile on NeXT machines. - -Some portability changes for AIX, whose CC is very picky. - -I forgot to mention in the 921227 release that T_RP is supported (arc@sgi). - -I included a number of changes that Alan Barrett has been trying to get -in since the 921221 version. Most are portability-related, and the few -things that are functional are changes to my own previous additions :-), -so I'm fairly sure that they are doing the right thing. Alan's changes -include: - - include/arpa/nameser.h - improved error diagnosis in the BYTE_ORDER configuration. - - changed hp9000 test to hp9000s300. As far as I know, there is - no hp9000 preprocessor symbol. Should probably add other - hp9000s<whatever> tests, but have not done so. - - named/ns.h - Moved the XFER-related stuff from the end of the file to near - the top, where it is grouped with similar stuff. - - Makefiles: - Add SYSLIBS variable, so folk can compile with -lBSD easily. - - Changed install targets to make them easier to customise. - - make links wasn't handling named.{reload,restart}* - - Add ${CDEBUG} flag to link step. Some debuggers don't work - right if the program isn't linked with the -g flag. - - struct timeval members are declared as unsigned long on some systems. - Add casts to (long) in several if statements that appear to assume - that tv_sec is signed. - - PID_FIX in ns_main.c controlled more than just whether or not the - pid file gets fixed. - Changed it to control only that one feature. - - For debugging, it is useful for a nameserver to listen to non-standard - port, but to forward requests to a standard port. - Add "-p remote/local" option to named/ns_main.c. - Also needed some other changes elsewhere. - - Don't forward back to the host that asked us a question, unless they - asked from some port other than their nameserver port. This allows a - dig or nslookup user on a host to ask us questions with - recursion-desired, where we are willing to recursively ask the - nameserver on their host. However, if a nameserver asks us something - we will not recurse back to them. - nslookup() in named/ns_forw.c checks for this and returns -1. - ns_forw() and sysquery() notice this and return SERVFAIL. - - Moved the nsContainsUs functionality from a separate routine - into nslookup(). No need to do the same tree walk several times. - - While trying to track down various problems, added detection - and logging of errors in several syscalls in ns_main.c. - - Avoid integer overflow in roundtrip time calc in ns_resp. - This needs a definition for INT_MAX. - - Fixed root zone transfer bug. Also corrected some slightly misleading - comments in the doaxfr() code, and added some more comments. - -4.9-ALPHA ---------------- January 5, 1993 -- Paul Vixie -- DECWRL - -This one was built and tested on Ultrix 4.2 (SPIM, MIPS CC and GCC), -BSD/386 (Gamma.4), Sun SPARC (4.0.3, sorry, that's the latest I have), -4.3BSD Reno (VAX, PCC), and Ultrix 3.0 (VAX PCC). - -Moved res/defs.h to conf/portability.h; named/options.h to conf/options.h. - -Portability changes for O_NDELAY. SUNOS is really strange about this. - -Removed some unneccessary goto's added to ns_main.c on 1jan. Oops. - -Art Harkin of HP sent in a number of small (read: obviously correct) -improvements, some related to portability, some to functionality. - -4.9-ALPHA ---------------- January 1, 1993 -- Paul Vixie -- DECWRL - -Changed all O_NONBLOCK to O_NDELAY. Changed all {r}index to str{r}chr. - -Added some SysV support in the form of bcopy->memcpy, bzero->memset. - -Added C_HS support to named-xfer (greg@duke.cs.unlv.edu). - -Fixed a line-number problem in asp's "include" logic (asp@uunet.uu.net). - -streamq's were being used after free(). bug report from fuat@ans.net -and jpe@ee.egr.duke.edu. bug fix by vixie. - -In the resolver, we now default to address 127.0.0.1 rather than 0.0.0.0. -There's a comment in the code that explains why. - -In the resolver, arc@xingping.esg.sgi.com changed it to use inet_aton() -and included that function for those not running 4.4bsd. - -arc@xingping.esg.sgi.com also provided lots of portability fixes and -general cleanups, in particular to nslookup which he maintains for CSRG. - -4.9-ALPHA ---------------- December 27, 1992 -- Paul Vixie -- DECWRL - -Added strtoul() to libresolv.a since it's yet another neccessary function -that older systems don't have. If we can stomach strcasecmp() we can sure -handle this. - -Moved res/named/gethostnamadr.c to res/gethnamaddr.c (note basename change) -and res/named/sethostent.c to res/sethostent.c. Since the host table stuff -isn't in separate files any more I saw no reason to retain the subdirectory. - -Updated all the copyrights and applied the small lint changes that bring -the baseline of this version from "4.8.3 as seen on ucbarpa" up to "4.8.3 -as released with net-2". Thanks to the alpha testers for pointing this out -to me and for sending in the diffs. - -With much howling and screaming, I ported this to UMIPS (MIPS System V). -There are a lot of really bad things going on in their libc.a, and now -they're going on in BIND as well. - -I added a "res/defs.h" file and then proceeded to include it from all kinds -of files that aren't in res/. I'm thinking of moving it but I'm also trying -to figure out where -- include/ is the wrong place. res/defs.h has in it all -the ugly ifdef's needed to figure out whether this is a late-model BSD system, -a POSIX system, or just old. - -All the "#endif" and "#else" cpp directives now have comments around their -annotations. It turns out that System V CPP complains about "#endif DEBUG" -but has no problem with "#endif /*DEBUG*/". In many cases where the #ifdef -was obviously visible and unambiguous, I simply removed the annotation. - -The "l" is now a ";". Thanks to all who replied :-). - -There was a very bad bug in the named-xfer interface. 'nuff said. - -AIX needs a 32-bit field for PID's. I can't imagine. But it's fixed. - -The "domain" directive in named.boot is now an option, defaulting to off. - -There was a benign bug in sqrm(). - -doaxfr() is now shorter and clearer. - -There is an "include" directive in the named.boot file now. Its syntax is -simple: "include somefile". No quotes, no "#", no <brackets>. This feature -was in 4.9-ALPHA as well, courtesy of Andrew Partan. I forgot to document it. - -4.9-ALPHA ---------------- December 21, 1992 -- Paul Vixie -- DECWRL - -This release incorporates fixes from a lot of people, including many from -DECWRL. Some fixes are just lint; some are to avoid dumping core on non-VAX -computers; many are to fix promiscuity, corruption, and rudeness. - -Various internal DEC programmers have ported the old 4.8.3 code to various -not-entirely-BSD-like platforms and turned up some interesting lint. All -of this has been fixed. Also, we fixed a bad bug in the handling of timeouts -and SERVFAIL's when forwarders and slave are both used. - -I have made major changes to the code inside the ALLOW_UPDATES ifdef's, but -I don't use it and have never compiled with that option turned on so I don't -know if it still works. Given that SNMP has come and there is an IETF WG for -SNMP management of the DNS, I am thinking very seriously of purging all of the -ALLOW_UPDATES code in 4.9.1. I suspect that Mike Schwartz will let me know if -this is ok.. - -(interrim "KJB" notes) ------------------- March, 1992 -- Paul Vixie -- DECWRL - -If we are about to forward a query for some zone for which we are one of the -servers, we send back a SERVFAIL instead. If we don't have it, chances are -good that the other name servers won't have it either. This is the major -cause of "network meltdown" when the root servers declare you as a name server -for some zone you don't know about and havn't configured yourself for. - -Fixed a memory leak such that if db_update() fails to update the database -from a response packet, a databuf will no longer be orphaned. Also fixed -what looks like a similar leak in the ALLOW_UPDATES code but I don't use it -that hasn't been tested. - -Fixed a memory sponge such that if we forward a query to someone who is not -ever going to answer it, we will eventually expire it from our query queue. -Previously it would expire after N retries to N' different servers, which -could be a very long time. Particularly in the case of lame delegations and -other forwarding loops, we feel that 90 seconds (two max-retry intervals) is -enough time for a query to be answered. While we were into this code we made -several fields in the query structure into "short"'s since they were only -being used to store smallish integers. The query list gets Very Long during -a forwarding loop -- even 90 seconds worth of queries is a lot of queries. - -This version includes my hacks that assign a "credibility index" to each -<name,type> such that when more credible data arrives for a given -<name,type>, all old data is purged. When equally-credible data arrives it -is aggregated in the way we all know and love; when less credible data -arrives it is completely ignored. Credibility, from best to worst, is: - 1. zone files (primary or secondary) - 2. authoritative answers - 3. non-authoritative answers and authority records - 4. additional data - 5. zone files ("cache" or "bootstrap" information) -You need this version of bind if you still show any A RR's in network -32.0.0.0 when you look up uucp-gw-1.pa.dec.com's A or adobe.com's NS. - -I have also added some extra code to prevent pollution of the internal -"hint cache." In all versions of BIND that I was able to test, any IN_A -response to any sysquery() would cause the IN_A RR to be added to the -fcachetab ("hint cache"). This resulted in lots of extra cruft in the hint -cache, that wasn't timed out properly, which in turn resulted in lots of -strange answers ('nuff said, take my word for it.) - -Though changes have been made to make the Ultrix and GNU (2.1) C compilers -stop complaining about the source, it should still compile and run just -about anywhere. In fact, after I cleaned up lots of old lint, this version -of BIND is known to compile and run on: - - Ultrix 4.2 (MIPS or VAX) - SunOS 4.0.3 - BSD/386 (BSDi beta) - -This was being released as King James Bind because, like KJ Sendmail, it is -a merge of every major variant of Bind that we know about. It was -assembled and tested by Paul Vixie of DEC NSL/WRL, with generous donations -of code and advice from Win Treese of DEC CRL. Changes from Don Lewis of -Harris, Andrew Partan of UUNET, and Piet Beertema of EUNet are also included. -See the OPTIONS file for a description of the changes you can control with -#ifdef's. - -This server has been run on UUCP-GW-{1,2}.PA.DEC.COM, which are in the UUCP -Zone. Our named.boot file has ~1900 lines in it. Before we instituted the -changes in this release, our name server usually ran at about 16MB virtual, -15MB physical, growing slowly but constantly until we restarted it. -Whenever a new zone was added to the NIC's root zone listing us as a name -server, our servers would kill themselves and eachother (and NS.UU.NET, one -of the other UUCP Zone name servers) with forwarding loops. After these -changes, we run at a fairly constant 8MB virtual and physical size, and our -apparent CPU utilization is always 0.0% since we never finish a quantum and -the scheduler always sees us as waiting for I-O. In other words, life is good. - -Notes from UCB version 4.8.3 follow: - -------------------- - -This is version 4.8.3 of bind. It is a test release that updates -versions 4.8 and 4.8.1 with fixes, and is essentially the same as -the version of named on the 4.3BSD Reno release. Although it is -currently described as a test release, it is believed to be reasonably -stable and more usable than the previously-released versions. -Here are some of the more important changes: - - o A list of domains may be specified for searching in resolv.conf instead - of just the local domain name. - - o gethostbyname() will accept a dotted quad. - - o Support has been added for the the T_TXT data type and for the class - C_HS. These are both used by Hesiod from Project Athena at MIT. - - o All of the pathnames have been put into one header file. This - makes it easier to change the location based upon your local - configuration. - - o Responses are only accepted from an address to which we might of sent - the request. This might cause problems if some server is multihomed - and is still running BIND 4.3, but it prevents attacks induced by - sending responses from another address. - - o Numerous bugs have been fixed: Adding a new authoritative zone now - works when the server has a cached SOA record. Comparisons in the - db now look at type and class as well instead of dropping records - with identical data. Scheduling of maintenance interrupts has been - moved to one routine avoid spurious ones. Named goes into the background - after more of the initialization is done. Stream connection queue - handling was cleaned up including a bug that caused data corruption - and core dumps. Sys5 no longer can have multiple transfers of the - same zone occuring at the same time. Handle CNAME -> CNAME loops - more gracefully. Avoid making one server never get queried. Border - conditions in resolver are checked more accurately. - - o Nslookup has been updated. - -There are several bug reports that have yet to be integrated into this -version. Hopefully they will be dealt with in the next release. Please -send feedback on this release. - -Notes from versions 4.8.1 and 4.8 follow: - ------------------- - -This is version 4.8.1 of bind. It is a test release that includes -version 4.8 with fixes, asynchronous zone transfer and better reload -capabilities. Although it is currently described as a test release, -it is believed to be reasonably stable and more usable than the currently- -released version, 4.8. The changes of note are: - - o The asynchronous zone transfer code previously posted to the bind - mailing list has been integrated, completed and tested. There are - a number of changes from the version posted, including fixes to - allow top-level domains to work and a simplification of the timer - code. - - o The code for reloading the server has been changed so that only - primary zones master files that have changed are reloaded. The - cache and secondary zones are not flushed, and the sortlist, domain, - etc. are reset to correspond to the boot file contents. - - o Several bugs have been fixed: the name "*" is not interpreted as - a wildcard in cached zones, only in primary zones. Secondary servers - no longer decrement the time-to-live of records by the time since - they verified the zone with the master; as a result, they never - hand out nameserver referrals with too short a TTL to be usable. - A bug was fixed that caused secondary servers with out-of-date - zones to return empty answers between the actual expiration time - and the next timeout. - -There are several other bugs that have been reported but have not yet -been fixed. In addition, the next regular release of named will -support negative caching, but this has not been integrated. - -I would appreciate receiving feedback on this release; in particular, -problems (or lack of problems) when installing on various systems. -I attempted to update the SysV code when integrating the zone-transfer, -but haven't tested it. - -The notes from version 4.8 follow. - ----------- -Welcome to version 4.8 of bind. - -There have been several changes to the named boot file (/etc/named.boot) -of which you should be aware. The "domain" line for each zone is no longer -needed, but one such line may still be used to specify a default domain -to be used for queries containing names with only a single component. -The term "suffixes", which was added in version 4.7alpha, has been removed. - -The manual page on named (named.8) has been updated to reflect all -these changes. Please read this and look at the example files -before installation. You should also note the changes in the -resolver code to support non-fully-qualified addresses and per-user -host aliases. See hostname(7) for an overview. Two new routines -have been added to the resolver library since the last test release: -res_query formulates a query, sends it, waits for a response and does -preliminary error checking; res_search implements the search rules -of gethostbyname using res_query. - -The MX lookup routine in sendmail has been modified to use res_search. -Also, dn_skip takes an additional parameter and has been renamed -to dn_skipname. While old sendmail binaries will work with the new -version of bind, because of these changes, it is desirable to install -new sendmail sources and recompile sendmail. Do not rebuild sendmail -from old sources. The new sendmail is on ucbarpa.Berkeley.EDU for -anonymous FTP from pub/4.3/sendmail.MX.tar and pub/4.3/sendmail.MX.tar.Z. - -There have been numerous changes to named, fixing most of the known -bugs that can be fixed without major structural changes in the server. -Several server configurations that failed before should now work. -Certain robustness problems have been fixed, in particular bounds- -checking when processing incoming packets. Two changes have been made -in preparation for negative caching: SOA records are sent in the authority -section in negative responses with NXDOMAIN set, and a bug was fixed that -caused confusion and repeated requests if a response had no error, no answer -and an SOA in the authority section. As such responses are already sent -by other servers, and will be sent by the next release of BIND, it is -important that all sites upgrade to this version as quickly as possible. - -The root "hint" cache and cache file remain the largest problem area, -along with named's naivete in accepting bogus server's data. -These will be addressed in the next release, along with asynchronous -zone transfers, intelligent reloading of zone files, faster startup, -and caching of negative responses. - -This version (4.8) will replace the last officially released version (4.5). -Version 4.5 has a serious bug that causes the generation of a continuous -stream of bogons to the root domain servers (bogus queries with the query -response bit set and possibly garbage for nsid and rcode). It is imperative -that these versions of named be replaced as fast as possible. We urge you to -field 4.8 quickly, for the sake of the root domain servers. - - Mike Karels - Jean Wood - bind@ucbarpa.Berkeley.EDU - -## ++Copyright++ -## - -## Copyright (c) -## 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. -## - -## --Copyright-- + 1. [bug] zone names needed to be canonicalized in the parser. + + --- 8.1-T2B released --- diff --git a/contrib/bind/INSTALL b/contrib/bind/INSTALL index 2ac19c0..0b6a0eb 100644 --- a/contrib/bind/INSTALL +++ b/contrib/bind/INSTALL @@ -1,99 +1,271 @@ -$Id: INSTALL,v 8.9 1997/06/24 06:43:50 vixie Exp $ - -THE FILES: ----------- -INSTALL -- This file -README -- Release announcements, tips and traps (some out of date) -OPTIONS -- The options that can be turned on and off -RUNSON -- What machines/compilers is BIND known to build on -TODO -- Have spare time? Consider contributing to the project! -BSD/* -- How to integrate BIND into a 4.4BSD or 4.4BSD-Lite -contrib/* -- Useful BIND-related contributions -doc/info/* -- Platform-dependent build hints -doc/* -- other RFCs, drafts, papers and - -INTRODUCTION: -------------- -BIND used to be extremely difficult to build. That changed around -version 4.9.3. These are the instructions on how to compile the -software. For information on how to create your configuration files -(resolv.conf, named.boot, and zone files) see the doc/bog directory for -the complete "BIND Operations Guide". You might also consider getting -"DNS and BIND" by C. Liu and P. Albitz from O'Reilly & Associates, -Sebastopol, CA, ISBN 0-937175-82-X 1992 - -Note: If you maintain a BSD or are otherwise running a 4.4BSD-based system - and want to integrate BIND into it, check out BSD/README. - -BUILDING & INSTALLING: ----------------------- -1. (optional) If you are going to compile for multiple platforms, you -can make a symbolic link tree for each platform to save disk space. To -create a directory called "sun4.dir", do: - make DST=sun4.dir links -Now "cd sun4.dir" and you can do everything as if you had a complete -copy of the source. Just be careful if you are modifying a file, make -sure you turn any links into files: - mv file file.tmp ; cp file.tmp file ; rm file.tmp - -2. (optional) If you have a typical site, you should find yourself only -editing Makefile and conf/options.h. Make backups of them now: - - mv conf/options.h conf/options.h.dist - cp conf/options.h.dist conf/options.h - chmod u+w conf/options.h - - mv Makefile Makefile.dist - cp Makefile.dist Makefile - chmod u+w Makefile - -3. Edit "conf/options.h" and turn on any options that you want. The -defaults are pretty reasonable for most installations. - -4. Edit "Makefile". The default build parameters are given for 4.4 BSD. -They should be overridden (not edited!). Do this by going to the -section that describes your operating system and uncoment the -appropriate lines. Add any other variables (for example, some people -add "DISTHELP=/usr/local/lib".) If in doubt, use the default! Read -the comments carefully! - -5. "make" should build everything. Consider putting "./bin" in your -path if "make depend" fails and you think bin/mkdep will help you out. - - *** NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE *** - - The next step (#6) will burn down files which were supplied with - your operating system. You should run the suggested "-n" first - and make sure you have saved any files you want to save. - - *** NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE *** - -6. "make install" will install everything. You might first do -"make -n install" to see what commands would be executed by "make install" -to make sure you understand where everything is about to be installed. - -7. (optional, SunOS 4, SunOS 5, NetBSD-1.x, IRIX, Linix only): You can -integrate the new resolver (client-side) code into the shared libraries -of your operating system so that all dynamicly linked programs take -advantage of the new resolver. Read shres/<osname>/INSTALL to find out -how to do it. - - - -HOW TO GET HELP: ----------------- -The "bind-users@vix.com" mailing list was created especially for people to -talk about and ask questions about installation, maintenance, etc. It is -highly recommended that you first help yourself by reading the BOG (doc/bog) -or a book on DNS and BIND. - -To be added to this mailing list, send mail to <bind-users-request@vix.com> - -Note that the bind-users mailing list is also available on Usenet as - comp.protocols.dns.bind -and that we would all prefer that you read it that way if you possibly can. - -This INSTALL was... - originally written on 15Jul94 by Tom Limoncelli <tal@bell-labs.com> - changed in minor ways 23Dec95 by Christopher Davis <ckd@kei.com> - and then changed by Tom Limoncelli again 16Oct96. +Supported Systems + + AIX 4.x + A/UX 3.1.1 + BSD/OS 2.1, 3.x + Digital ULTRIX 4.5 + Digital UNIX 3.2C, 4.0 + FreeBSD 2.x, 3.0 + HP MPE + HP-UX 9.x, 10.20 + IRIX 5.3, 6.2, 6.4 + LynxOS + NetBSD 1.2, 1.3 + OpenBSD 2.1 + QNX + Red Hat Linux 4.x, 5.0 + SCO UNIX 3.2v4.2, SCO OSE 5.0.4, UnixWare 2.0.x, 2.1.2 + SunOS 4.1.4 + SunOS 5.5 (Solaris 2.5), 5.6 (Solaris 2.6) + + See port/README for information on porting BIND 8 to other systems. + + +Building + + If you do not have an ANSI/ISO C compiler, give up or get GCC. The + one exception is the ULTRIX compiler, which isn't full ANSI C but it + has function prototypes and BIND works around the rest. BIND 8 also + wants a C library that's ANSI/ISO standard, although it can work + around some common failings. + + If you do not have yacc, get byacc or GNU bison. If you do not have + lex, get GNU flex. For information on where to get GNU software, see + http://www.fsf.org/order/ftp.html. + + If you want to build outside the source pool, then + + make DST=/your/destination/here SRC=`pwd` links + cd /your/destination/here + + If you want to use DST=/var/obj/bind, you can simply type + + make stdlinks + + Next, make sure you have no stale trash laying about + + make clean + + Then, update the Makefile dependencies: + + make depend + + Finally, + + make + + +Installation + + To install, type + + make install + + This will copy binaries to the appropriate locations for your system, + and install the BIND 8 library and header files under /usr/local/bind. + + The following variables can be used to change where things get + installed: + + DESTDIR prefix used in front of all other + DEST variables. The default is the + empty prefix. + DESTLIB libraries + DESTINC include files + DESTBIN ordinary binaries (e.g. dig, nslookup) + DESTSBIN system binaries (e.g. named) + DESTEXEC helper binaries (e.g. named-xfer) + DESTHELP place to put nslookup's help file + DESTETC configuration file + DESTRUN PID file location + + These variables may be specified on the command line of the 'make' + or in the Makefile.set for your port (e.g. if you use Solaris, in + src/port/solaris/Makefile.set). + + Before doing 'make install' using either method, you must + + rm .settings + + in the top level source directory because the build system caches + these variables. + + +Using BIND 8 Library Routines + + Until a method to update the system's libraries is available, + applications wishing to use BIND 8 library routines must include + BIND 8 .h files, and must link with libbind.a. E.g. + + cc -I/usr/local/bind/include -c sample.c + cc -o sample -L/usr/local/bind/lib sample.o -lbind + + The default locations for libbind.a and .h files in BIND 8.1.1 + and BIND 8.1.2 are different from those used in BIND 8.1-REL. If + you did a 'make install' for BIND 8.1-REL, then you should delete + the files it installed. They are: + + /usr/local/lib/libbind.a + /usr/local/include/arpa/inet.h + /usr/local/include/arpa/nameser.h + /usr/local/include/arpa/nameser_compat.h + /usr/local/include/netdb.h + /usr/local/include/resolv.h + /usr/local/include/sys/bitypes.h (if it exists) + /usr/local/include/sys/cdefs.h (if it exists) + + +Operating System Notes + + SunOS 4.1.4 + + An ANSI/ISO C compiler is required; we used gcc 2.7.2.1. + + Solaris + + We've tested with Sun's compilers, yacc, and lex, and also + with gcc, byacc, and flex. By default, the build will try + to use gcc. If you want to use the Sun compilers, simply + copy "port/solaris/Makefile.set.sun" to + "port/solaris/Makefile.set". To go back to using gcc, copy + "port/solaris/Makefile.set.gcc" to "port/solaris/Makefile.set". + + If you're using a Solaris release earlier than 2.5 and you have + a large number of interfaces on your system, you many need + use a script to "limit descriptors N" (where 'N' is a + suitably large number) before execing "named". On Solaris + 2.5 and later, the server will do this itself. + + Certain older versions of FreeBSD, NetBSD and BSD/OS + + These systems have a /bin/sh based on "ash", which doesn't + handle POSIX-style quoting correctly. Using "bash" will fix + the problem. Either run make with "SH=bash" on the command + line, or edit src/Makefile and change "SH=sh" to "SH=bash". + + QNX + + Read src/port/qnx/README before trying to build. + + +FD_SETSIZE + + The highest numbered file descriptor that the server and the resolver + can utilize is determined by the FD_SETSIZE value of the system. Some + systems set FD_SETSIZE much smaller than the actual number of files + that can be opened. On such systems, create an "fd_setsize.h" file + that sets FD_SETSIZE appropriately in the port's include directory. + + +User and Group ID + + Specifying "-u" followed by a username or numeric user id on the + "named" command line will cause the server to give up all + privileges and become that user after the initial load of the + configuation file is complete. "-g" may be used similarly to set + the group id. If "-u" is specified but "-g" is not, the group + used will be the given user's primary group. + + Here are some hints: + + Because the server will have no privileges after changing + its user id, you must restart the server if you change the + interfaces and ports that the server is listening on, or if + you add an interface. + + If you log to files, you should create all of the log files + in advance (e.g. with "touch"), and make sure they are owned + by the user and group "named" will be running as. + + You'll have to edit "ndc" to get it to start the server + with the appropriate flags. + + Note: this feature is still experimental. + + +Chroot + + "-t" followed by a directory path on the "named" command line will + cause the server to chroot() to that directory before it starts + loading the configuration file. + + Setting up a chrooted area varies somewhat by operating system. Some + experimentation may be necessary. Here are some hints: + + Don't forget to install named-xfer. + + Either don't use shared libraries when you build, or do + whatever is required on your OS to allow shared libraries + to be used after a chroot(). + + syslog() is often troublesome after chrooting. Use the + "logging" statement and log to a file instead. + + /dev/null should be in the chroot directory hierarchy. You + can usually find out the mknod parameters for a null device by + looking in /dev/MAKEDEV. + + You'll have to edit "ndc" to get it to start the server + with the appropriate flags, and to use the right pid file. + + Note: this feature is still experimental. + + +Using the Server + + Note that /etc/named.boot is long gone. You need to make yourself an + /etc/named.conf (note, that ends in "conf" rather than "boot") file. + This file looks a lot like a C program or a modern gated.conf file; + there are lots of {curly braces} and it takes some getting used to. + You may get a lot more help from the example file (which is + bin/named/named.conf) than from the documentation (see ../doc/html). + You can convert your named.boot file to a named.conf file if you have + Perl; see bin/named/named-bootconf.pl. + + All the files that used to be created in /var/tmp, e.g. named.run, + will now be created in the directory specified in the options + statement. If debugging is turned on using the "-d" flag on server + startup, then named.run will be created in the current directory. + + +Known Dynamic DNS Bugs + + If the server is master for a zone and authoritative for a child of + that zone, then a dynamic update to the parent will destroy the + delegation to the child when the parent zone is written to disk. + This problem will be fixed in a future release. The only workaround + is to not be authoritative for child zones of a dynamic zone. + + Slave servers do not forward update requests to the primary master + correctly. This will be fixed in a future release. In the meantime, + slaves will refuse dynamic updates. + + +Shared Libraries + + Absolutely no support exists for editing the system's shared + libraries to update the resolver. If you want to do that you + probably want to look at BIND Version 4 (see http://www.isc.org/isc/) + or wait a while or help out a lot. This means you probably do not + want to install the library or include files into /usr/lib or + /usr/include, and this kit helpfully puts everything into + /usr/local/lib and /usr/local/include for that reason among others. + + +Notes about contrib and doc + + The BIND 8 "doc" package includes HTML documentation as well as all + the RFC's, Internet Drafts, and "man" pages we can think of. You may + need to install the doc/tmac files in your nroff/troff support + directory since we use the newer BSD "mandoc" system for our "man" + pages. + + The BIND 8 "contrib" package is full of junk that you may want to + take a look at. Feel free to send us more junk for future releases. + + +Bugs + + Please report bugs to + + bind-bugs@isc.org diff --git a/contrib/bind/Makefile b/contrib/bind/Makefile index 8ca4d0c..2a95287 100644 --- a/contrib/bind/Makefile +++ b/contrib/bind/Makefile @@ -1,1001 +1,66 @@ -# Makefile for BIND>=4.9 top level -# vixie@decwrl December, 1992 [original] -# -# $Id: Makefile,v 8.52 1998/04/07 04:59:42 vixie Exp $ - -## Copyright (c) 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. +## Copyright (c) 1996 by Internet Software Consortium. ## -## 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 +## 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. -VER = 4.9.7-T1B -SHELL = /bin/sh -MAKE = make -DESTDIR = - -INCL = include -RES = res/libresolv.a -COMPLIB = compat/lib/lib44bsd.a - -# The default build parameters are given for 4.4 BSD. They should -# be overridden for other operating systems as indicated below. - -#(BSD4.4, BSD/OS, FreeBSD, NetBSD, other net2-alikes) -# -# DO NOT COMMENT THESE OUT. OVERRIDE THEM BELOW. -# -CC = cc $(CPPFLAGS) -LDFLAGS = -CDEBUG = -O -g -CPPFLAGS= -INDOT = -XFER_INDOT = -LEX = lex -I -LIBS = -ll -lutil -PIDDIR = /var/run -DESTBIN = /usr/bin -DESTSBIN = /usr/sbin -DESTEXEC = /usr/libexec -DESTMAN = /usr/share/man -DESTHELP = /usr/share/misc -DESTLIB = /usr/lib -DESTINC = /usr/include -COMPINCL = compat/include -LDS = -CATEXT = 0 -INSTALL_COMPAT = install -INSTALL = install -RANLIB = ranlib -AR = ar cru -MANROFF = ( tbl | nroff -man ) -MANDIR = cat -PS = ps -IOT = ABRT -SHCC = -SHLD = -PIC = - -# (NetBSD - for details on shared library building, see shres/netbsd/INSTALL) -#uncomment next three lines to build a shared library version of libresolv -#SHRES = shres/netbsd -#SHCC = cc $(CPPFLAGS) -#PIC = -fpic - -#(Linux - on modern systems, all you need to do is rename or remove -# compat/include/sys/cdefs.h. See doc/info/Linux for more information.) -#CC = gcc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSYSV -#LEX=flex -8 -I -#INSTALL_COMPAT = install-compat -#LIBS = -lfl -#DESTEXEC = /usr/sbin -#DESTMAN = /usr/man -#MANDIR = man -#MANROFF = cat -#DESTHELP = /usr/lib -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT -#uncomment next line to build a shared library version of libresolv -#SHRES = shres/linux -#uncomment next line to build tools and named with shared libresolv -#RES = $(SHRES)/libresolv.so -# ... and then (for shared) uncomment these lines too: -#SHCC = gcc $(CPPFLAGS) -fomit-frame-pointer -pipe -#PIC= -fpic -#SHMAJVER=4 -#SHVER=$(SHMAJVER).9.5.0.4 -#SHLD= gcc -shared -Wl,-rpath,$(DESTDIR)$(DESTLIB),-soname,libresolv.so.$(SHMAJVER) -lfl - -#(CRAY) -#CDEBUG = -g -#LEX=lex -#IOT = IOT - -#(DEC AXP OSF/1 Version 2.1 and earlier) -#CC = cc $(CPPFLAGS) -#CDEBUG = -g3 -O2 -Olimit 2000 -#CPPFLAGS = -#LEX = lex -#LIBS = -ll -lutil -#DESTEXEC = /usr/sbin -#COMPINCL = compat/include -#INSTALL_COMPAT = install-compat -#INSTALL = installbsd -#MANDIR = man -#MANROFF = cat -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT - -#(DEC AXP OSF/1 Version 3.0 and after) -#CC = cc $(CPPFLAGS) -std -#CDEBUG = -g3 -O2 -Olimit 2000 -#CPPFLAGS = -DCHECK_UDP_SUM -#LEX = lex -#LIBS = -ll -lutil -lmld -#DESTEXEC = /usr/sbin -#COMPINCL = compat/include -#INSTALL_COMPAT = install-compat -#INSTALL = installbsd -#MANDIR = man -#MANROFF = cat -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT -#KSYMS = /vmunix -#KMEM = /dev/kmem -#UDPSUM = udpcksum - -#(irix4) -#CC = cc $(CPPFLAGS) -xansi -signed -#CDEBUG = -g -#CPPFLAGS = -D__STDC__ -D_BSD_SIGNALS -DSIG_FN=int -DCHECK_UDP_SUM -DKMAP -#LEX = lex -#LIBS = -ll -lmld -#DESTSBIN = /usr/etc -#DESTEXEC = /usr/etc -#DESTMAN = /usr/catman/local -#DESTHELP = /usr/lib -#INSTALL = bsdinstall.sh -#RANLIB = : -#PS = ps -p -#(bsdinstall.sh is in conf/) -#IOT = IOT -#KSYMS = /unix -#KMEM = /dev/kmem -#UDPSUM = udpcksum - -#(irix5 and irix6.2) -#CC = cc $(CPPFLAGS) -xansi -signed -#CDEBUG = -g -#CPPFLAGS = -D__STDC__ -D_BSD_SIGNALS -DSIG_FN=void -D__BIT_TYPES_DEFINED__ \ -# -DCHECK_UDP_SUM -DKMAP -#LEX = lex -#LIBS = -ll -lelf -#DESTSBIN = /usr/etc -#DESTEXEC = /usr/etc -#DESTMAN = /usr/share/catman/local -#DESTHELP = /usr/lib -#INSTALL = bsdinstall.sh -#RANLIB = : -#PS = ps -p -#(bsdinstall.sh is in conf/) -#IOT = IOT -#KSYMS = /unix -#KMEM = /dev/kmem -#UDPSUM = udpcksum -# shared libresolv.o options below. -# they could work under irix6, if the cmplr didn't change alot -#SHRES = shres/irix -#SHCC = $(CC) $(CPPFLAGS) -#SHLD = ld -shared -#RES = $(SHRES)/libresolv.so - -#(sunos4.x) -#CC = /usr/bin/cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSUNOS4 -DSPRINTF_CHAR -DCHECK_UDP_SUM -Dconst= -#INDOT = in. -#XFER_INDOT = in. -#LEX = lex -#LIBS = -ll -#(add "-ldl" to LIBS if your links fail with "dlopen" problems. this indicates -# that your libc.so file is screwed up, but it's easier to fix this than that.) -#PIDDIR = /etc -#DESTSBIN = /usr/etc -#DESTEXEC = /usr/etc -#DESTHELP = /usr/lib -#COMPINCL = compat/include -#MANDIR = man -#CATEXT = $$$$N -#MANROFF = cat -#INSTALL_COMPAT = install-compat -#INSTALL = install -#IOT = IOT -#KSYMS = /vmunix -#KMEM = /dev/kmem -#UDPSUM = _udp_cksum -# (for details on shared library building, see shres/sunos/INSTALL; -# note that shres/solaris/INSTALL has some good testing notes for sunos) -#uncomment next line to build a shared library version of libresolv -#SHRES = shres/sunos -# uncomment only one of the pairs of lines below -# -- if you use gcc (recommended) -# (if -fpic doesn't work, see shres/sunos/PROBLEMS) -#SHCC = gcc -DSUNSECURITY $(CPPFLAGS) -#PIC= -B/usr/bin/ -fpic -D_res=_res_shlib -# -- if you use Sun's cc -#SHCC = /usr/bin/cc -DSUNSECURITY $(CPPFLAGS) -#PIC = -pic -D_res=_res_shlib - -#(ULTRIX/RISC - also see below) -#CC = cc $(CPPFLAGS) -Olimit 2000 -YPOSIX - -#(ULTRIX, other 4.[23]bsd-alikes) -#CDEBUG = -g -#CPPFLAGS = -DCHECK_UDP_SUM -#LEX = lex -#LIBS = -ll -#PIDDIR = /etc -#DESTSBIN = /usr/etc -#DESTEXEC = /usr/etc -#DESTHELP = /usr/lib -#COMPINCL = compat/include -#CATEXT = $$$$N -#INSTALL_COMPAT = install-compat -#INSTALL = install -#DESTMAN = /usr/man -#MANDIR = man -#MANROFF = cat -#IOT = IOT -#KSYMS = /vmunix -#KMEM = /dev/kmem -#UDPSUM = udpcksum - -#(solaris2.x/sunos5.x) -#be careful with installation - note in particular that the system ships -#with /usr/sbin/in.named (with in.) and /usr/sbin/named-xfer (without in.) -#to emulate this naming, INDOT should be set to 'in.' while XFER_INDOT -#should be empty. also, under solaris2.x, use 'make install' at your own risk. -#don't include sys/stream.h via netinet/in.h by defining _SYS_STREAM_H. -#->and note that sun moved their nslookup to /usr/sbin for some odd reason; -# when you install this one in /usr/bin you should delete sun's or else you -# will get confusing results since you never know which nslookup you're using. -#PIDDIR = /etc -#LEX = lex -#uncomment next line for Sun C compiler -#CC = /opt/SUNWspro/bin/cc $(CPPFLAGS) -R$(DESTLIB) -#uncomment next two lines for GNU C compiler -#CC = gcc $(CPPFLAGS) -#LDFLAGS=-Xlinker -R$(DESTLIB) -#otherwise uncomment the next line and hope for the best -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPPFLAGS = -DSVR4 -D_SYS_STREAM_H -DMAXHOSTNAMELEN=256 -#CPPFLAGS = $(CPPPFLAGS) $(SOLCOMPAT) -#INDOT = in. -#XFER_INDOT = -#LIBS = -ll -lnsl -lsocket -#DESTEXEC = /usr/sbin -#DESTHELP = /usr/lib -#INSTALL_COMPAT = install-compat -#LDS = : -#INSTALL = /usr/ucb/install -#RANLIB = : -#ARPREF = `lorder -#ARSUFF = | tsort` -#MANDIR = man -#MANROFF = cat -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT -#uncomment next line for link-compatibility with Solaris resolver library -#SOLCOMPAT = -Dgethostbyname=res_gethostbyname \ -# -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ -# -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \ -# -Dendhostent=res_endhostent -Dgethostent=res_gethostent \ -# -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \ -# -Dgetnetent=res_getnetent -# for details on shared library building, see shres/solaris/INSTALL -#uncomment next line to build a shared library version of libresolv -#SHRES = shres/solaris -#uncomment next line to build tools and named with shared libresolv -#if you do so, you *must* define SOLCOMPAT as well (and it must be in CPPFLAGS) -#RES = $(SHRES)/libresolv.so -# uncomment only one of the triplets of lines below -# -- if you use gcc (recommended) -# (if -fpic doesn't work, see shres/solaris/ISSUES) -#SHCC = gcc -B/usr/ccs/bin/ $(CPPPFLAGS) -#PIC= -fpic -#SHLD = /usr/ccs/bin/ld -G -# -- if you use Sun's cc -#SHCC = /opt/SUNWspro/bin/cc $(CPPPFLAGS) -#PIC = -Kpic -#SHLD = /opt/SUNWspro/bin/cc -G - -#(hpux7.0,hpux8.0,hpux9.0,) -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DCHECK_UDP_SUM -#LEX = lex -#LIBS = -ll -lBSD -#PIDDIR = /etc -#DESTSBIN = /etc -#DESTEXEC = /etc -#DESTMAN = /usr/man -#DESTHELP = /usr/lib -#INSTALL = bsdinstall.sh -#RANLIB = : -#MANROFF = cat -#PS = ps -p -#KSYMS = /hp-ux -#KMEM = /dev/kmem -#UDPSUM = udpcksum -#(bsdinstall.sh is in conf/) - -#(hpux10.10) -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -Dconst= -#LEX = lex -#LIBS = -ll -#PIDDIR = /etc -#DESTSBIN = /usr/sbin -#DESTEXEC = /usr/sbin -#DESTMAN = /usr/man -#DESTHELP = /usr/lib -#LDS = : -#INSTALL = bsdinstall.sh -#RANLIB = : -#MANROFF = cat -#PS = ps -p -#INSTALL_COMPAT = install-install -#(bsdinstall.sh is in conf/) - -#(apollo domainos) -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -U_APOLLO_SOURCE -D_BSD_SOURCE -DSPRINTF_CHAR -D_CLASSIC_BSD_SPRINTF -#LIBS = -ll -#DESTSBIN = /etc -#DESTEXEC = /etc -#DESTHELP = /usr/lib -#DESTMAN = /usr/man -#PIDDIR = /etc -#LEX = lex -#PS = /bsd4.3/bin/ps -#IOT = IOT - -#(AIX3) -#CC = bsdcc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DBSD=43 -#LIBS = -ll -#DESTEXEC = /usr/sbin -#INSTALL = /usr/ucb/install -#CATEXT = $$$$N -#LEX = lex -#PS = ps -p -#IOT = IOT - -#(AIX4) -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -D_BSD=44 -#LIBS = -ll -lbsd -#DESTEXEC = /usr/sbin -#INSTALL = /usr/ucb/install -#CATEXT = $$$$N -#LEX = lex -#PS = ps -p -#IOT = IOT - -# (ConvexOS-10.x) -#CC = gcc $(CPPFLAGS) -g -O2 -fpcc-struct-return -fno-builtin -funsigned-char -#CDEBUG = -g -#CPPFLAGS = -#INDOT = -#LEX = flex -8 -I -#LIBS = -lfl -#PIDDIR = /usr/local/etc -#DESTBIN = /usr/local/bin -#DESTSBIN = /usr/local/bin -#DESTEXEC = /usr/local/etc -#DESTMAN = /usr/local/man -#DESTHELP = /usr/local/etc -#DESTLIB = /usr/local/lib -#DESTINC = /usr/local/include -#COMPINCL = compat/include -#LDS = -#INSTALL_COMPAT = install -#INSTALL = install -#RANLIB = ranlib -#IOT = IOT - -#(NEC EWS4800 EWS-UX/V Rel4.0/Rel4.2,UX/4800) -#be careful with installation - note in particular that the system ships -#with /usr/sbin/in.named (with in.) and /usr/sbin/named-xfer (without in.) -#to emulate this naming, INDOT should be set to in. and XFER_INDOT should be -#set to empty. also, under EWS4800, use 'make install' at your own risk. -#CC = /usr/necccs/bin/cc $(CPPFLAGS) -#CC = /usr/abiccs/bin/cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSVR4 -DUSE_POSIX -#INDOT = in. -#XFER_INDOT = -#LEX = lex -#LIBS = -ll -lnsl -lsocket -#DESTBIN = /usr/local/bin -#DESTSBIN = /etc -#DESTEXEC = /etc -#DESTHELP = /usr/local/lib -#DESTLIB = /usr/local/lib -#DESTINC = /usr/local/include -#DESTMAN = /usr/local/man -#PIDDIR = /etc -#LDS = : -#RANLIB = : -#COMPINCL = compat/include -#CATEXT = $$$$N -#INSTALL_COMPAT = install-compat -#INSTALL = /usr/ucb/install -#PS = ps -p -#IOT = IOT - -# SCO OSE5, SCO ODT 3.0, SCO Unix 3.2v4.2 -# uncomment only one set of the CC/CDEBUG lines below -# -- OSE5 using SCO's cc -#CC = cc $(CPPFLAGS) -#CDEBUG=-O3 -# -- ODT 3.0 / 3.2v4.2 using SCO's cc ( lots of warnings during compilation ) -#CC = cc $(CPPFLAGS) -#CDEBUG=-O -# -- if you use gcc ( gcc highly recommended on 3.2v4.2 / ODT 3.0 ) -#CC = gcc $(CPPFLAGS) -#CDEBUG=-O6 -# For the time being, the rest is common for all supported SCO flavors -#CPPFLAGS = -DSYSV -DSYSV3 -#LDFLAGS=-s -#INDOT= -#LEX=lex -#LIBS=-ll -lnsl_s -lsocket -lc_s -#DESTBIN=/usr/bin -#DESTSBIN = /etc -#DESTEXEC=/etc -#DESTHELP=/usr/lib -#DESTMAN=/usr/local/man -#PIDDIR = /etc -#LDS=: -#RANLIB=: -#COMPINCL=compat/include -#CATEXT = $$$$N -#INSTALL_COMPAT = install-compat -#INSTALL = scoinst -#MANROFF= (tbl | groff -man -Tascii) -#PS = ps -p -#IOT = IOT - -#(UNIXWARE) -#CC = cc $(CPPFLAGS) -#CPPFLAGS = -DSVR4 -DBSD_COMP -DUSE_POSIX -D_SYS_STREAM_H -#CDEBUG = -O -#LEX = lex -#INDOT = in. -#XFER_INDOT = -#INSTALL = /usr/ucb/install -# (1.X) -#LIBS = -ll -lsocket -lnsl -# (2.X) -#LIBS = -ll -lsocket -lnsl -lgen -#DESTSBIN = /usr/sbin -#DESTEXEC = /usr/sbin -#ARPREF = `lorder -#ARSUFF = | tsort` -#CATEXT = $$$$N -#PS = ps -p -#PIDDIR = /etc/inet -#INSTALL_COMPAT = install-compat -#RANLIB = : -#LDS = : -#DESTHELP=/usr/lib -#IOT = IOT - -#(NeXTstep 2.0ff, single architecture make) -#CC = cc $(CPPFLAGS) #you can use -O2 for 3.2ff -#CPPFLAGS = -Dpid_t=int -#CDEBUG = -g -#LIBS = -ll -#LEX = lex -#DESTEXEC = /usr/etc -#DESTHELP = /usr/lib -#DESTMAN = /usr/man -#DESTSBIN = /usr/etc -#PIDDIR = /etc -#MANDIR = man -#CATEXT = $$$$N -#MANROFF = cat -#INSTALL_COMPAT = install-compat -#IOT = IOT - -#(NeXTstep 3.3 Multi Architecture Binaries) -#CC = cc $(CPPFLAGS) -arch i386 -arch m68k -arch hppa -arch sparc -#CDEBUG = -O2 -#CPPFLAGS = -Dpid_t=int -#LDS = : -#AR = libtool -o -#RANLIB = : -#LIBS = -ll -#LEX = lex -#DESTEXEC = /usr/etc -#DESTHELP = /usr/lib -#DESTMAN = /usr/man -#DESTSBIN = /usr/etc -#PIDDIR = /etc -#MANDIR = man -#CATEXT = $$$$N -#MANROFF = cat -#INSTALL_COMPAT = install-compat -#IOT = IOT - -#(Pyramid dcosx) -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSVR4 -DPOSIX_SIGNALS -#LEX = lex -#LIBS = -ll -lnsl -lsocket -#RANLIB = : -#PS = ps -p -#IOT = IOT - -#(Sequent Dynix/PTX) -#CC = cc $(CPPFLAGS) -Wc,-pw -#CDEBUG = -g -#CPPFLAGS = -Du_int=\"unsigned int\" -DSYSV -#RANLIB = : -#LIBS = -ll -lsocket -linet -lnsl -lseq -#PIDDIR = /etc -#DESTSBIN = /usr/local/etc -#DESTEXEC = /usr/local/etc -#DESTHELP = /usr/local/lib -#LEX = lex -#PS = ps -p -#IOT = IOT - -#(dgux) -#LEX = lex -#RANLIB = -#CC = gcc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -D__STDC__ -DDGUX -#LIBS = -ll -#DESTBIN = /usr/bin -#DESTSBIN = /usr/bin -#DESTEXEC = /usr/bin -#DESTMAN = /usr/local/man -#DESTHELP = /usr/lib -#DESTLIB = /usr/lib -#DESTINC = /usr/include -#PIDDIR = /etc -#PS = ps -p -#IOT = IOT - -#(epix) Has to be compiled and loaded with -systype bsd43 -# Epix 2.x.x requires /bsd43/bin in front of the PATH variable -#CC = cc $(CPPFLAGS) -signed -systype bsd43 -#CDEBUG = -g -#CPPFLAGS = -DSTDIN_FILENO=0 -#LEX = lex -#LIBS = -ll -#DESTSBIN = /etc/local -#DESTEXEC = /etc/local -#DESTMAN = /usr/local/man -#DESTHELP = /usr/lib -#INSTALL = install.sh -#RANLIB = : -#PS = ps -p -#IOT = IOT - -#Mips RISC/os 4.52 -#CC = cc $(CPPFLAGS) -systype bsd43 -#CPPFLAGS = -Dpid_t=int -#CDEBUG = -O -g3 -Olimit 1000 -#LEX = lex -#LIBS = -ll -#PIDDIR = /etc -#DESTBIN = /usr/local/bin -#DESTSBIN = /usr/etc -#DESTEXEC = /usr/etc -#DESTMAN = /usr/local/man -#DESTHELP = /usr/local/lib -#DESTLIB = /usr/local/lib -#DESTINC = /usr/local/include -#PS = ps -p -#IOT = IOT - -#Esix SVR4.0.4 with gcc -# also works for Dell 2.2 and other i386 SVR4.0. Probably Unixware 1.1 as well. -#Be careful with installation - note in particular that the system ships -#with /usr/sbin/in.named (with in.) and /usr/sbin/named-xfer (without in.) -#to emulate this naming, INDOT should be set to in. and XFER_INDOT should be -#set to empty. also, use 'make install' at your own risk. -#don't include sys/stream.h via netinet/in.h by defining _SYS_STREAM_H. -#CC = gcc $(CPPFLAGS) -#CPPFLAGS = -DSVR4 -DBSD_COMP -DUSE_POSIX -D_SYS_STREAM_H -#CDEBUG = -O -#LEX = lex -#INDOT = in. -#XFER_INDOT = -#PIDDIR = /etc -#INSTALL = /usr/ucb/install -#LIBS = -ll -lsocket -lnsl -#DESTSBIN = /usr/sbin -#DESTEXEC = /usr/sbin -#LDS = @: -#RANLIB = @: -#ARPREF = `lorder -#ARSUFF = | tsort` -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT - -#(ISC4.0 using GCC) -#CC = gcc $(CPPFLAGS) -posix -#CPPFLAGS = -DISC -#CDEBUG = -g -#LEX = flex -I -#LIBS = -lbsd -#PIDDIR = /etc -#DESTBIN = /usr/bin -#DESTSBIN = /etc -#DESTEXEC = /etc -#DESTHELP = /etc -#DESTMAN = /usr/catman/l_man -#CATEXT = $$$$N -#RANLIB = @: -#LDS = @: -#PS = ps -p -#ARPREF = `lorder -#ARSUFF = | tsort` -#IOT = IOT - -# AUX 3.x (I used 3.1.1) -#CC = gcc $(CPPFLAGS) -#CDEBUG = -O2 -#CPPFLAGS = -D_POSIX_SOURCE -DSYSV -#LEX = lex -#LIBS = -ll -lposix -lmalloc -s -#PIDDIR = /etc -#DESTBIN = /etc -#DESTSBIN = /etc -#DESTEXEC = /etc -#DESTMAN = /usr/local/man -#DESTHELP = /etc -#COMPINCL = compat/include -#CATEXT = $$$$N -#INSTALL_COMPAT = install-compat -#INSTALL = install -#RANLIB = @: -#PS = ps -p -#IOT = IOT - -#NCR System V/MLS -#use same definitions as for sunos4.x except for the following -#be careful with installation - note in particular that the system ships -#with /usr/sbin/in.named (with in.) and /usr/sbin/named-xfer (without in.) -#to emulate this naming, INDOT should be set to 'in.' while XFER_INDOT -#should be empty. also, under solaris2.x, use 'make install' at your own risk. -#don't include sys/stream.h via netinet/in.h by defining _SYS_STREAM_H. -#PIDDIR = /usr/local/lib -#LEX = lex -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSVR4 -D_SYS_STREAM_H -Hnocopyr -DPOSIX_SIGNALS -DNCR -w -#INDOT = in. -#XFER_INDOT = -#LIBS = -ll -lnsl -lsocket -#DESTEXEC = /usr/local/bin -#LDS = : -#RANLIB = : -#ARPREF = `lorder -#ARSUFF = | tsort` -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT - -#NCR System Vr4.3 3.x -#also, use 'make install' at your own risk. -#PIDDIR = /etc/inet -#LEX = lex -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSVR4 -Hnocopyr -DPOSIX_SIGNALS -DNO_SA_LEN -DNCR -w -#INDOT = in. -#XFER_INDOT = in. -#LIBS = -ll -lnsl -lsocket -#DESTEXEC = /usr/sbin -#LDS = : -#RANLIB = : -#ARPREF = `lorder -#ARSUFF = | tsort` -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT - -#NCR System Vr4.3-3.0 -#also, use 'make install' at your own risk. -#PIDDIR = /etc/inet -#LEX = lex -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSVR4 -Hnocopyr -DPOSIX_SIGNALS -DNO_SA_LEN -DNCR -w -#INDOT = in. -#XFER_INDOT = in. -#LIBS = -ll -lnsl -lsocket -#DESTEXEC = /usr/sbin -#LDS = : -#RANLIB = : -#ARPREF = `lorder -#ARSUFF = | tsort` -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT -#SHCC = cc $(CPPPFLAGS) -#PIC = -Kpic -#SHLD = cc -G -#SHRES = shres/ncr - -#NCR System Vr4.3-2.03 -#also, use 'make install' at your own risk. -#PIDDIR = /etc -#LEX = lex -#CC = cc $(CPPFLAGS) -#CDEBUG = -g -#CPPFLAGS = -DSVR4 -Hnocopyr -DPOSIX_SIGNALS -DNO_SA_LEN -DNCR -w -#INDOT = -#XFER_INDOT = -#LIBS = -ll -lnsl -lsocket -#DESTSBIN = /usr/etc -#DESTEXEC = /usr/etc -#LDS = : -#RANLIB = : -#ARPREF = `lorder -#ARSUFF = | tsort` -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT -#SHCC = cc $(CPPPFLAGS) -#PIC = -Kpic -#SHLD = cc -G -#SHRES = shres/ncr - -#(UXP/DS) -#PIDDIR = /etc -#LEX = lex -#CC = cc $(CPPFLAGS) -#CDEBUG = -O -#CPPFLAGS = -DSVR4 -D_SYS_STREAM_H -DUSE_POSIX -#INDOT = in. -#XFER_INDOT = -#LIBS = -ll -lnsl -lsocket -#LDS = : -#COMPINCL = compat/include -#AR = ar -cru -## for V10L20 -#INSTALL = /usr/ucb/install -g sys -## for V20L10 -#INSTALL = /usr/ucb/install -#RANLIB = : -#ARPREF = `lorder -#ARSUFF = | tsort` -#CATEXT = $$$$N -#PS = ps -p -#IOT = IOT -#PIC = -Kpic -#MANROFF = ( tbl | nroff -man ) -#MANDIR = man - -#(MOTOROLA Rel FH40.4x ,m88k) -#Support for Motorola m88k machines. The compiler supports -#three compile flags for processor type -# -F88000 the generic 88k -# -F88100 for the 88100 chip -# -F88110 for the 88110 chip -# -# Set to which version of CPU is being used. This was -# compiled on a 197DP with the -F88110 flag -# Earlier boards (187 and V/88) need 88100 and 88000 -# -# See /usr/ccs/lib/.compilerc -# -#CC = /usr/ccs/bin/cc $(CPPFLAGS) -#CDEBUG = -g -O -#CPPFLAGS = -F88110 -D_SYS_STREAM_H -DSVR4 -#INDOT -in. -#XFER_INDOT = -#LEX = lex -#LIBS = -lsocket -lnsl -ll -#DESTBIN = /usr/bin -#DESTSBIN = /usr/sbin -#DESTEXEC = /etc -#DESTHELP = /usr/lib -#DESTLIB = /usr/lib -#DESTINC = /usr/include -#DESTMAN = /usr/share/man -#PIDDIR = /etc -#LDS = @: -#LDFLAGS=-s -#RANLIB = touch -#COMPINCL = compat/include -#CATEXT = $$$$N -#INSTALL_COMPAT = install-compat -#INSTALL = /usr/ucb/install -#PS =ps -p -#IOT = IOT - -#################################################################### -############ no user servicable parts beyond this point ############ -#################################################################### - -MANARGS = \ - "SHELL=${SHELL}" "INDOT=${INDOT}" "XFER_INDOT=${XFER_INDOT}" \ - "DESTDIR=${DESTDIR}" "DESTMAN=${DESTMAN}" "INSTALL=${INSTALL}" \ - CATEXT='${CATEXT}' MANDIR='${MANDIR}' MANROFF='${MANROFF}' - -MARGS = "VER=${VER}" "CC=${CC}" "CDEBUG=${CDEBUG}" "LIBS=${LIBS}" \ - "INCL=../${INCL}" "RES=../${RES}" "LEX=${LEX}" "LDFLAGS=${LDFLAGS}" \ - "PIDDIR=${PIDDIR}" "DESTBIN=${DESTBIN}" "DESTSBIN=${DESTSBIN}" \ - "DESTEXEC=${DESTEXEC}" "COMPINCL=../${COMPINCL}" \ - "COMPLIB=../${COMPLIB}" "DESTLIB=${DESTLIB}" "DESTINC=${DESTINC}" \ - "DESTHELP=${DESTHELP}" "PIC=${PIC}" "SHCC=${SHCC}" "SHLD=${SHLD}" \ - "AR=${AR}" "RANLIB=${RANLIB}" "LDS=${LDS}" 'ARPREF=${ARPREF}' \ - 'ARSUFF=${ARSUFF}' $(MANARGS) PS="${PS}" "IOT=${IOT}" \ - "CPPFLAGS=${CPPFLAGS}" "KSYMS=${KSYMS}" "KMEM=${KMEM}" \ - "UDPSUM=${UDPSUM}" "SHVER=${SHVER}" "SHMAJVER=${SHMAJVER}" - -MACHINE = native -DST = $(MACHINE).b -SRC = .. - -SUBDIRS = res $(SHRES) include compat named tools man - -all:: FRC - -all clean depend:: FRC - @for x in $(SUBDIRS); do \ - (cd $$x; pwd; $(MAKE) $(MARGS) $@); \ - done - -$(SUBDIRS):: FRC - @for x in $@; do \ - (cd $$x; pwd; $(MAKE) $(MARGS) all); \ +# $Id: Makefile,v 8.46 1998/01/28 23:42:06 halley Exp $ + +TOP= +SUBDIRS= include port lib bin + +SH=sh + +all clean depend install distclean:: FRC + @set -e; \ + version=`cat ${TOP}Version`; \ + systype=`${SH} ${TOP}port/systype ${TOP}.systype`; \ + if [ $$systype = "unknown" ]; then \ + echo "There is no BIND port for this system in this kit."; \ + else \ + settings=`${SH} ${TOP}port/settings ${TOP}.settings \ + < ${TOP}port/$$systype/Makefile.set`; \ + PATH=`pwd`/port/$$systype/bin:$$PATH; export PATH; \ + for x in ${SUBDIRS}; do \ + ( cd $$x; pwd; \ + eval "${MAKE} $$settings ${MARGS} SYSTYPE=$$systype \ + VER=$$version \ + $@"; \ + ); \ + done \ + fi + +clean distclean:: + rm -f .systype .settings + +links: FRC + @set -e; mkdir ${DST}; cd ${DST}; pwd; ln -s ${SRC} SRC; \ + ln -s SRC/Version .; cp SRC/Makefile .; chmod +w Makefile; \ + systype=`${SH} SRC/port/systype`; \ + for x in ${SUBDIRS}; do \ + ( mkdir $$x; cd $$x; pwd; ln -s ../SRC/$$x SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + ${MAKE} ${MARGS} SYSTYPE=$$systype links; \ + ); \ done -clean:: FRC - -test -d doc/bog && (cd doc/bog; pwd; $(MAKE) $(MARGS) $@) - (cd conf; rm -f *~ *.CKP *.BAK *.orig) - rm -f *~ *.CKP *.BAK *.orig - -depend:: FRC - -mkdirs: FRC - -set +e; for x in $(DESTDIR)$(DESTBIN) $(DESTDIR)$(DESTSBIN) \ - $(DESTDIR)$(DESTEXEC) $(DESTDIR)$(DESTMAN) \ - $(DESTDIR)$(DESTHELP) $(DESTDIR)$(DESTLIB) \ - $(DESTDIR)$(DESTINC); do \ - test -d $$x || mkdir -p $$x; \ - done - -install: FRC - @for x in $(SUBDIRS); do \ - y=`if [ "X$$x" = "Xcompat" ]; \ - then echo ${INSTALL_COMPAT}; \ - else echo install; \ - fi`; \ - (cd $$x; pwd; $(MAKE) $(MARGS) $$y); \ - done - -D = OPTIONS master bin doc named CHANGES README compat include res \ - Makefile TODO conf man tools - -copyright: FRC - bin/copyright <conf/copyright `find ${D} -type f ! -name '*,v' -print` - -tar: FRC - ( cd doc/bog; make file.psf file.lst ) - find * '(' -name RCS -o -name obj -o -name .depend ')' \ - -print >/tmp/bindXf - gnutar -c -z -f ../bind-${VER}.tar.gz -X /tmp/bindXf . - rm -f /tmp/bindXf - -links: $(DST) - -$(DST): FRC - @set -ex; mkdir $(DST); cd $(DST); \ - ln -s $(SRC) SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ( mkdir include; cd include; ln -s ../SRC/include SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/*.h SRC/arpa .; \ - ); \ - ( mkdir conf; cd conf; ln -s ../SRC/conf SRC; \ - ln -s SRC/*.h .; \ - ); \ - ( mkdir tools; cd tools; ln -s ../SRC/tools SRC; \ - ln -s SRC/*.[ch] .; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ( mkdir nslookup; cd nslookup; ln -s ../SRC/nslookup SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/[a-z]* .; \ - ); \ - ); \ - ( mkdir res; cd res; ln -s ../SRC/res SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/*.[ch] .; \ - ); \ - ( mkdir compat; cd compat; ln -s ../SRC/compat SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/include .; \ - ( mkdir lib; cd lib; ln -s ../SRC/lib SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/*.c .; \ - ); \ - ); \ - ( mkdir named; cd named; ln -s ../SRC/named SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/*.[ch] SRC/*.sh .; \ - ); \ - ( mkdir shres; cd shres; ln -s ../SRC/shres SRC; \ - ( mkdir sunos; cd sunos; ln -s ../../SRC/shres/sunos SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/makeshlib SRC/*.patch* .; \ - ); \ - ( mkdir netbsd; cd netbsd; ln -s ../../SRC/shres/netbsd SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/makeshlib SRC/lorder-sparc.sed SRC/shlibname.awk .; \ - ); \ - ( mkdir solaris; cd solaris; ln -s ../../SRC/shres/solaris SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ); \ - ( mkdir irix; cd irix; ln -s ../../SRC/shres/irix SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ); \ - ( mkdir linux; cd linux; ln -s ../../SRC/shres/linux SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ); \ - ); \ - ( mkdir man; cd man; ln -s ../SRC/man SRC; \ - cp SRC/Makefile .; chmod +w Makefile; \ - ln -s SRC/*.[0-9] .; \ - ) +stdlinks: FRC + if [ ! -d /var/obj ]; then \ + mkdir /var/obj; \ + fi + ${MAKE} ${MARGS} SRC=`pwd` DST=/var/obj/bind links -gcc2-lint: FRC - @-make CC="gcc2 -Wall -Wno-comment -Wno-parentheses -Dlint" all \ - 2>&1 | grep '\.[ch]:[0-9]' +uplinks: FRC + @set -e; systype=`${SH} ${TOP}port/systype`; pwd=`pwd`; \ + ${MAKE} ${MARGS} SRC=$$pwd "DST=`dirname $$pwd`/$$systype" links FRC: diff --git a/contrib/bind/README b/contrib/bind/README index cfa72ec..45b984f 100644 --- a/contrib/bind/README +++ b/contrib/bind/README @@ -1,279 +1,145 @@ -Internet Software Consortium -BIND Release 4.9.7 README -$Date: 1998/04/07 04:24:01 $ - -The official version of ISC BIND is now 8.1.1. This is ISC BIND 4.9.7, -hoped to be the last of 4.*, which we are releasing since it has an important -security bug (plus some memory leaks) fixed. - -The official place to get BIND is <URL:ftp://ftp.isc.org/isc/bind/src>. - -The official mailing lists are: <bind-users@vix.com> - users/admins - (use *-request@* for admin mail) <bind-workers@vix.com> - developers - -The official Usenet newsgroups are: <URL:news:comp.protocols.dns.bind> - <URL:news:comp.protocols.dns.ops> - <URL:news:comp.protocols.dns.std> - -BIND is maintained by: The Internet Software Consortium - (see <URL:http://www.isc.org/>) - -Bug reports should be sent to: <bind-bugs@vix.com> - -Read the top of CHANGES for interesting stuff. - -To build this: QUICK - - (on SUNOS, use the BSD build environment or you will - get the wrong definition for O_NDELAY) - - look at conf/options.h and edit to your tastes. - The OPTIONS file here in this directory will help you - figure out what to do. - - You should also look at the Makefile to select the proper set - of definitions depending on whether you are using Ultrix, - SunOS, and other 4.[23] BSD-alikes or using BSD 4.4, BSD/386, - and other net2-alikes. - - "make links" will build a shadow source tree full - of symbolic links. the default name of this tree - is "./native.b", but you can override it by setting - the DST variable on the "make" command line, as in: - make DST=vax.b SRC=.. - if your DST is not a subdir of "here", you will need to - override the SRC variable's default (which is ".."), - as in: - make DST=/tmp/vax.b SRC=`pwd` - note that the DST directory must be nonexistent at - the time that you run "make links". - - after "make links", you can cd to the new build - directory, check the settings in the Makefile, and - run "make depend". if you aren't using "make links" - (shame on you), just use "make depend" from "here". - "make depend" may fail on your system; if so, look in - the bin/ directory and find a mkdep that does in fact - work for you. - - if you skip the "make depend" phase, or after you run it, - you can do "make all" (from the build directory if you - used "make links" or from "here" if you're just hacking - around). you will get the following new things out of it: - res/libresolv.a - compat/lib/lib44bsd.a (optional) - include/{netdb,resolv}.h - include/arpa/{inet,nameser}.h - compat/include/sys/{cdefs,bitypes}.h - tools/{nstest,nsquery,dig,host} - tools/nslookup/nslookup - named/named - named/named-xfer - if you have trouble with "make all", check conf/portability.h - for things that your system needs, or doesn't need, or whatever. - it is preferable to add #ifdef's to conf/portability.h than to - add them anywhere else. +This is the source portion of BIND version 8.1.2-T3B. Its companions are +"doc" and "contrib" so you are probably not missing anything. + +See the CHANGES file for a detailed listing of all changes. See the INSTALL +file for information on building and installing BIND 8.1.2. + + +BIND 8.1.2 Highlights + + Security fixes for a number of problems including: + + An attacker could overwrite the stack if inverse query support + was enabled. + + A number of denial of service attacks where malformed packets + could cause the server to crash. + + The server was willing to answer queries on its forwarding + sockets. + + Several memory leaks have been plugged. + + The server no longer panics if a periodic interface scan fails due + to no file descriptors being available. + + Updates to a number of ports. New ports for QNX, LynxOS, HP-UX 9.x, + and HP MPE. + + "limit files unlimited" now works as expected on systems where setting + an infinite rlim_max for RLIMIT_NOFILE works. + + Adding and deleting the same record in the same dynamic update no + longer crashes the server. + + If a dynamic update fails, rollback is now done in LIFO order instead + of FIFO order. + + Better behavior when priming of the root servers fails. + + purge_zone() didn't work correctly for the root zone, allowing + old data to persist after loading the zone. + + Improved handling of oversized UDP packets. + + All hosts on the also-notify list are now notified. + + The meaning of the count returned by select() varies somewhat by + operating system, and this could cause previous releases of the + server to spin. + + Per-host statistics may be disabled by specifying 'host-statistics no' + in named.conf. + + The maximum number of zones has been increased from 32768 to 65536. + + query-source may specify an address and port that the server is + already listening on. BIND 8.1.1 required that either the address + or port be wild. E.g., you can now say: + + listen-on port 53 { 10.0.0.1; }; + query-source address 10.0.0.1 port 53; + + The value of FD_SETSIZE to use may be specified. + + Experimental -u (set user id), -g (set group id), and -t (chroot) + command line options. See the INSTALL file for details. + + +BIND 8 Features + + -> DNS Dynamic Updates (RFC 2136) + + -> DNS Change Notification (RFC 1996) + + -> Completely new configuration syntax + + -> Flexible, categorized logging system + + -> IP-address-based access control for queries, zone transfers, and + updates that may be specified on a zone-by-zone basis + + -> More efficient zone transfers + + -> Improved performance for servers with thousands of zones + + -> The server no longer forks for outbound zone transfers + + -> Many bug fixes + + +File and Directory Overview + + CHANGES history of added features and + fixed bugs + + INSTALL how to build and install + + README this file + + TODO features planned but not yet written + + Version the version number of this release + + bin/* source for executables, including + the nameserver + + include/* public .h files + + lib/* the resolver and various BIND + support libraries + + port/* ports to various operating systems - from the build directory (or "here" if you didn't - use "make links"), you can try "make -n install" - which will tell you what will be installed. it might - actually be right; however, what you will probably have to - do is copy the above files into the places you want - run them from. the other files you will need are: - tools/nslookup/nslookup.help - named/named.restart - named/named.reload - - resolver library notes: to install it, either put the .a - file into /usr/local/lib or /usr/lib (if you use -lresolv - on all the links of your networking software), or use "ar" - to put all res/*.o directly into your /lib/libc.a file. - either way you will want to copy the include files - (including those from compat/include/sys) over to - /usr/include (or /usr/local/include if you're willing to - use -I/usr/local/include on all your network-software - compiles). something like this: - cp res/libresolv.a /usr/lib; ranlib /usr/lib/libresolv.a - tar chf - include | (cd /usr/include; tar xvpf -) - cp compat/include/sys/*.h /usr/include/sys - - installing the man pages is left as an exercise for the - reader. there are just too many different versions of - "man" floating around for me to be able to help you figure - out what to do for the one you happen to be using. - - WARNING: If you were running a BIND 4.8.3 or earlier based - named you should remove all cache files prior to starting - named. It would generally be a good idea to remove all cache - files regardless when installing a new version. The creadability - code depends upon the cache files having been made with the - latest named-xfer for correct operation. - -(special compilation-related warning about SunOS systems:) - - From: Tom Limoncelli - To: vixie (Paul A Vixie) - Date: Mon, 11 Jan 93 11:30:39 EST - - Sun compiler v2.0.1 hates bind4.9 code. - - Sun has 3 compilers: - - /usr/ucb/cc -- the default for SunOS 4.1.[123], - dropped in Solaris 2.0. - /usr/lang/cc -- the "unbundled" cc v1.0 - (pretty good, but expensive), only - generates code for SunOS 4.1.x. - /usr/lang/cc.2.0.1 -- the latest "unbundled" cc, - for when they stop shipping the - bundled version altogether. This - generates code for SunOS 4.1.x and Solaris 2.x. - - Sun's 2.0.1 C compiler (the one with the floating licenses) for SunOS - 4.1.x outputs a HUGE number of warnings. They can be ignored. - ---------------------- (4.8.3 README -- mostly obsolete now) - -This directory contains all the info and sources -for the Berkeley Internet Name Domain server. -You should read and understand these directions before starting -to install the libraries and nameserver. Some of these steps -replace existing source and binary files; you should make backups -of all existing files before you begin this installation. -Two installation procedures are described. The first is for 4.3BSD -and other similar systems that are already configured to use earlier -versions of the nameserver, and which have the new version of <netdb.h> -(containing a h_addr_list field in the hostent structure). The second -procedure is for 4.2BSD and derived systems. This procedure requires -more decisions to be made, and may have to be varied due to system -or operation constraints. - -The subdirectories and their contents are: - -bin - shell scripts used by current Berkeley makefiles -man - manual pages & documentation -doc - copy of Bind Operations Guide, and other documents -include - include files to go in /usr/include -named - name server sources -res - source for C library resolver routines (and other libc additions) - (may be used as separate library, resolv.a) -conf/master - Sample data files -tools - some test programs - - -Here is how to install the name server on 4.3BSD: - -0) cp bin/mkdep.append /usr/ucb/mkdep - cp bin/manroff /usr/man/manroff -1) cp include/arpa/nameser.h /usr/include/arpa -2) cp include/*.h /usr/include -3) cp man/*.1 /usr/man/manl - cp man/*.3 /usr/man/man3 - cp man/*.5 /usr/man/man5 - cp man/*.7 /usr/man/man7 - cp man/*.8 /usr/man/man8 -4) NOTE: Don't install the Makefiles on 4.3 Tahoe Release - cp res/{res*.c,herror.c} /usr/src/lib/libc/net - cp res/Makefile.libc.net /usr/src/lib/libc/net/Makefile - cp res/strcasecmp.c /usr/src/lib/libc/gen - cp res/strpbrk.c /usr/src/lib/libc/compat-sys5 - cp res/named/{*.c,Makefile} /usr/src/lib/libc/net/named -5) add strcasecmp.[co] to the Makefile in /usr/src/lib/libc/gen -6) add strpbrk.[co] to the Makefile in /usr/src/lib/libc/compat-sys5 -7) rebuild and install /lib/libc.a. -8) edit named/pathnames.h to correpond with your system's configuration -9) cd named; make depend; make all; make install -10) cd tools/nslookup; make nslookup; make install -11) create the master files (samples in conf/master/*) -12) edit /etc/rc.local to include: - -if [ -f /etc/named ]; then - /etc/named; echo -n ' named' >/dev/console -fi - -13) recompile network client and server programs that use gethostbyname, etc. - - -Here is how to install the name server on 4.2BSD or similar systems. -First, a few notes on the choices that must be made. - -Rather than building libresolv.a, you may wish to integrate the resolver -routines into /lib/libc.a. This is recommended to make it easy to recompile -network programs once named is running. This procedure may require hand- -tayloring on some systems. - -You will have to choose a version of mkdep from the bin directory -that will work on your system: -If you've modified make(1) to use .depend files as described -in the current sendmail distribution, use mkdep; otherwise, -if you have the 4.3BSD cc -M option, use mkdep.append; on ultrix, -use mkdep.ultrix (uses cc -Em); otherwise, use mkdep.old.compiler. -The mkdep script is used by "make depend" to regenerate Makefile dependency -lists. - -You will need to chose a version of netdb.h. First, check /usr/include/netdb.h -on your system. If the hostent structure has a h_addr_list entry, you can -probably use your existing netdb.h or the one in include/netdb.h. -If the existing netdb.h in /usr/include does not have a h_addr_list field, -you will have to decide whether to update to the 4.3BSD format of the hostent -structure. This is the best approach, but cannot be used unless you plan -to upgrade entirely: if you use the new structure in /usr/include/resolv.h, -you must recompile everything that uses the hostent structure, including -the rest of the C library and all networking programs, without using -any pre-existing object files. If this isn't possible or desirable, -and /usr/include/netdb.h doesn't have an h_addr_list line, use -include/netdb.h.4.2 instead of netdb.h. The other version of netdb.h -(include/netdb.h.4.2.compat) may be used instead of include/netdb.h.4.2. -This version along with a change in res/named/gethostnamadr.c.compat -provide for using the new format of the hostent structure while having -binary compatibility with existing libraries. - -On systems with Sun RPC, you will have to merge include/netdb.h or -include/netdb.h.4.2 with /usr/include/netdb.h; copy the rpc-related lines -into the appropriate copy of netdb.h. Alternatively, use an alternate -include path when compiling the resolver library and programs that use it. - -0) cp bin/{whatever} /usr/ucb/mkdep (see above) - cp bin/manroff /usr/man/manroff -1) cp include/arpa/nameser.h /usr/include/arpa - Also, on ultrix 2.x, if you haven't fixed - the inet_addr definition in inet.h, do - cp include/arpa/inet.h /usr/include/arpa -2) cp include/resolv.h /usr/include -3) cp include/netdb.h /usr/include/netdb.h -OR - cp include/netdb.h.4.2 /usr/include/netdb.h -OR - edit /usr/include/netdb.h -4) cp man/*.1 /usr/man/manl - cp man/*.3 /usr/man/man3 - cp man/*.5 /usr/man/man5 - cp man/*.7 /usr/man/man7 - cp man/*.8 /usr/man/man8 -5) cd res; make depend; - make libresolv.a; - make install -OR - update the libc sources as in the 4.3BSD instructions above - and use res/Makefile as a guide for integration - and omit the RES=-lresolv in the next two steps -OR - compile the .o files in res according to Makefile, - then use place those object files in /lib/libc.a (keeping a backup!) - and omit the RES=-lresolv in the next two steps -6) edit named/pathnames.h to correpond with your system's configuration -7) cd named; make depend; make RES=-lresolv all; make install - (if your system defines signal-catching routines to return int - instead of void, use "make DEFINES=-DSIG_FN=int RES=-lresolv all") -8) edit tools/nslookup/pathnames.h to correpond with your system's - configuration -9) cd tools/nslookup; make RES=-lresolv nslookup install -10) create the master files (samples in conf/master/*) -11) edit /etc/rc.local to include: - -if [ -f /etc/named ]; then - /etc/named; echo -n ' named' >/dev/console -fi - -12) eventually, recompile network client and server programs that use -gethostbyname, etc. + +Kits, Questions, Comments, and Bug Reports + + <URL:ftp://ftp.isc.org/isc/bind/src/cur> current non-test release + <URL:ftp://ftp.isc.org/isc/bind/src/testing> latest public test kit + + <URL:usenet:comp.protocols.dns.bind> using BIND + <URL:usenet:comp.protocols.dns.ops> DNS operations in general + <URL:usenet:comp.protocols.dns.std> DNS standards in general + + <URL:mailto:bind-users-request@vix.com> gw'd to u:c.p.d.bind + <URL:mailto:namedroppers-request@internic.net> gw'd to u:c.p.d.std + <URL:mailto:bind-workers-request@vix.com> code warriors only please + + <URL:http://www.isc.org/bind.html> the BIND home page + <URL:mailto:bind-bugs@isc.org> bug reports + + +To Support the Effort + + Note that BIND is supported by the Internet Software Consortium, and + although it is free for use and redistribution and incorporation into + vendor products and export and anything else you can think of, it + costs money to produce. That money comes from ISPs, hardware and + software vendors, companies who make extensive use of the software, + and generally kind hearted folk such as yourself. + + The Internet Software Consortium has also commissioned a DHCP server + implementation, has taken over official support/release of the INN + system, and supports the Kerberos Version 5 effort at MIT. You can + learn more about the ISC's goals and accomplishments from the web page + at <URL:http://www.isc.org/>. diff --git a/contrib/bind/TODO b/contrib/bind/TODO index 5f6a453..634d03a 100644 --- a/contrib/bind/TODO +++ b/contrib/bind/TODO @@ -1,187 +1,27 @@ -$Id: TODO,v 8.3 1995/06/19 08:34:22 vixie Exp $ +These are not in priority order. -Things to do. Each entry should contain the proposer, date proposed, and an -explaination of what's being proposed. New ones are added at the bottom. -Note that the author/coordinator of BIND does not neccessarily endorse all -of the proposals listed herein; if you did not get explicit "buy-in" then -your changes may not be accepted even if they appear in proposal form here -in this file. +-> "make" should work in any subdirectory as it does in the top level. -[Mark.Andrews@dms.CSIRO.AU 14dec94]: rfc952/rfc1123 host name compliance: - -> Test domain names to ensure that the name conforms to the form - specified by RFC952 as modified by RFC1123. - -> WARN if the domain name does not meet the conditions set by - rfc952/rfc1123 for the following resource records. - class == C_IN && type == T_A - class == C_IN && type == T_MX - -> REJECT this records on the primary server. - -> CNAME which doesn't match pointing to the above is also - illegal but harder to check. +-> "make distclean" should remove .depend files, "make clean" shouldn't. -[paul@vix.com 30nov94]: cause NOTIFY to track the IETF process for it; - reorder ns_resp() again so that "Notify notimp" causes qdelete() - but the host source address checking and so on is still done. +-> NT port -[paul@vix.com 25apr93]: clean up #ifdef's and portability - feature #ifdef's should be limited to whole functions, which will be - called no matter what and would only be non-empty if the feature is - enabled. allow feature ifdef's in .h files, though. +-> DNS Security (RFC 2065) - portability #ifdef's should be limited to whole functions, too. add - a new portability.c module that implements anything which varies from - system to system. +-> IXFR - add a second portability.h-like file that is included _before_ all the - system includes. portability.h as it stands is included _after_ all - system includes, which is convenient for most things but not all. +-> Enhanced forwarding -[sater@cs.vu.nl 26apr93]: sortlist improvement - Improve the code around the sortlist area to better cope with parallel - networks of different speeds. The -i hack I sent to you could function - as inspiration only. +-> Command protocol -[kre@munnari.oz.au 26apr93]: add an INN style control interface - to replace sending signals. With that expand debugging to - permit monitoring of actions taken on a single query - (query through control port, full traced as it occurs) - or all queries that reference some particular name or - zone, or which are forwarded, or asked, of some - particluar server. Allow reloads & dumps of a single - zone, rather than the whole universe. Allow selective - cache pruning (to edit away bad data that's been obtained - from somewhere) +-> IPv6 transport -[kre@munnari.oz.au 26apr93]: add a syntax to zone files (non rfc - standard, but I don't care) to permit RR's to age away - at some particular time, and others to become active at - some particular time (probably with a syntax something - like "<[date]" or "@[date]" preceding, or in the - former case, replacing, the TTL field of the record). - Approaching "date" in the "<[date]" case, the TTL's on - the record would be decreased, so no data cached anywhere - will remain valid after "date", after "date", this RR - would simply be inoperative (essentially identical to - a comment). In the "@[date]" case (or perhaps ">[date]" - for symmetry) the RR would be ignored until "date" at - which time the "@[date]" field would simply be ignored. - Both annotations could be used together (with - appropriate interpretations depending on which date is - earlier than the other). Annotations on RR's in a zone - would cause the SOA parameters to be automatically - adjusted in zone transfers (and SOA requests) so that - secondary servers would also hand out the same values - (dropping the TTL down low as a "<[date]" approaches, - and forcing a new zone transfer at "date"). +-> named-xfer elimination -[steve@uunet.uu.net 26apr93]: TXT RR improvements - - fix TXT records so that they can deal properly with multiple - strings (e.g., ``foo IN TXT "aaa" "bbb"''). This - results in a fair number of smallish changes throughout the - code and also throughout various tools (e.g., nslookup). +-> asynchronous resolver -[kyle@uunet.uu.net 16may93]: need an option to die if primary zone file missing - as of 4.9, a server will not forward a query if it is itself on the - NS list for the relevant domain. this means that if a primary server - cannot load its zone file, it will not be able to answer queries in - that zone -- it won't even forward them. this is arguably correct, - since it prevents bad forwarding loops when two or more servers are - all unable to load the zone (primary or secondary, with secondary - failures being the more common). what is needed is real loop detection - such that reasonable non-looping queries can be forwarded. what we're - likely to actually get is an option that causes named to just syslog - and die if it can't load a primary zone file. note that at present, - named is running somewhat bare-assed since an expired zone in a - secondary (or missing zone file in a primary) will cause that named - to return SERVFAIL for all queries to that zone. if your screwed up - primary/secondary server is also the forwarding server for a collection - of hosts, those hosts will get SERVFAIL's back from queries to the - affected domains, and depending on the age of their resolvers, they - might not try other servers after they get the first SERVFAIL. - [ this entry was written by Paul Vixie after getting a problem report - from Kyle after uu.net disappeared in a brief but ugly way. --vix ] +-> new database -- DB 2.0? -[paul@vix.com 05jun94]: things i'm expecting to fix someday: - -> finish STATS (b+tree?), remove older A_RR-based tagging - -> (more?) svr4 changes from wisner@well, marc@cam, istewart@datlog - -> switch completely to posix-style signals - -> xfrnets directives should aggregate - -> syntactic sugar to use "mtime" of file as soa serial number - -> better support for "firewalls" (zohar@ibm, minnich@dupont) - -> attributes in TXT RR (cpw@lanl) - -> fix database consistency problems during zone reloads (Bob Heiney) - -> preliminary support for variable width subnet masks - -> failover isn't working very well for hesiod queries (gshapiro) - -> dig needs to be able to turn on RES_INSECURE{1,2} options - -> clean out old RR's that lay within a newly loaded zone file (heiney) - -> automatically refresh root.cache from the root servers periodically - -> Makefiles should use/pass CFLAGS rather than modifying CC - -> use Berkeley DB rather than malloc() for all database ops - -> include files should be generated from templates - -> use nvi-style port/* hierarchy, fewer portability #ifdef's - -> make __res static, add procedural interface to replace "extern"'ing - -> add hesiod/yp capable versions of get{pw,serv,???}by*() - -> add hesiod/yp to get{net,host}by*() - -> do something like solaris' /etc/nsswitch.conf (but in resolv.conf) - -> we should only need one copy of binary->text, text->binary, and - packet marshalling/unmarshalling. add general routines to -lresolv, - and rearrange the code to use them. - -> apps that want to do DNS queries should not have to learn res_query; - a higher level interface should be provided, that has its own cache - and/or shares with the server's DB-based one. - -> implement or integrate the next round of RFC's (coming soon). +-> move man pages from doc/man/* into src/. -[paul@vix.com 05jun95]: more things i'm expecting to fix someday: - -> add "ndc checkconf" (i.e., "named -v") - -## ++Copyright++ 1993 -## - -## Copyright (c) 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. -## - -## --Copyright-- +-> fix dynamic DNS delegation loss problem diff --git a/contrib/bind/Version b/contrib/bind/Version new file mode 100644 index 0000000..e6ea01a --- /dev/null +++ b/contrib/bind/Version @@ -0,0 +1 @@ +8.1.2-T3B diff --git a/contrib/bind/bin/Makefile b/contrib/bind/bin/Makefile new file mode 100644 index 0000000..b330286 --- /dev/null +++ b/contrib/bind/bin/Makefile @@ -0,0 +1,90 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.17 1998/03/20 00:40:13 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = .. +O=o +A=a +INCL = ${TOP}/include +LIBBIND = ${TOP}/lib/libbind.${A} +LIBPORT = ${TOP}/port/libport.${A} +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LEX = lex -I +YACC = yacc +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cruv + +LDFLAGS= + +MARGS = "SYSTYPE=${SYSTYPE}" "SHELL=${SHELL}" "A=${A}" "O=${O}" \ + "CC=${CC}" "LEX=${LEX}" "YACC=${YACC}" "CDEBUG=${CDEBUG}" \ + "SYSLIBS=${SYSLIBS}" "LDFLAGS=${LDFLAGS}" \ + "DESTDIR=${DESTDIR}" "PIDDIR=${PIDDIR}" "DESTMAN=${DESTMAN}" \ + "DESTBIN=${DESTBIN}" "DESTSBIN=${DESTSBIN}" "DESTEXEC=${DESTEXEC}" \ + "DESTLIB=${DESTLIB}" "DESTINC=${DESTINC}" "DESTETC=${DESTETC}" \ + "DESTRUN=${DESTRUN}" "DESTHELP=${DESTHELP}" \ + "RANLIB=${RANLIB}" "AR=${AR}" "ARPREF=${ARPREF}" "ARSUFF=${ARSUFF}" \ + "INCL=../${INCL}" "PORTINCL=../${PORTINCL}" \ + "LIBBIND=../${LIBBIND}" "LIBPORT=../${LIBPORT}" \ + "INSTALL=${INSTALL}" "CPPFLAGS=${CPPFLAGS}" "TOP=../${TOP}" \ + "VER=${VER}" "STRIP=${STRIP}" "PS=${PS}" + +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +SUBDIRS = addr nslookup dig dnsquery host named named-xfer ndc nsupdate + +all: ${SUBDIRS} + +${SUBDIRS}: FRC + @(cd $@; pwd; ${MAKE} ${MARGS}) + +install depend tags clean distclean:: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ + done + +distclean:: clean + +clean:: + rm -f *.BAK *.CKP *~ *.orig + +links: FRC + @set -e; \ + for x in $(SUBDIRS); do \ + ( mkdir $$x; cd $$x; pwd; ln -s ../SRC/$$x SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + $(MAKE) $(MARGS) links; \ + ); \ + done + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/addr/Makefile b/contrib/bind/bin/addr/Makefile new file mode 100644 index 0000000..0e8b2ec --- /dev/null +++ b/contrib/bind/bin/addr/Makefile @@ -0,0 +1,79 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.19 1997/06/19 03:22:06 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s + +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +PROG= addr +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep -p ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/addr/addr.c b/contrib/bind/bin/addr/addr.c new file mode 100644 index 0000000..535033a --- /dev/null +++ b/contrib/bind/bin/addr/addr.c @@ -0,0 +1,172 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: addr.c,v 8.5 1997/04/25 00:00:29 vixie Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "port_before.h" +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> +#include <ctype.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "port_after.h" + +static const char *prog = "addr"; + +#define BIGGEST_ADDRESS IN6ADDRSZ + +static void +usage() { + fprintf(stderr, + "usage: %s [-4] [-6] [-n hexstring] [-p address]\n", + prog); + exit(1); +} + +/* Warning: this scribbles on `dst' even if it's going to return `0'. */ +static int +hexstring(src, dst, len) + const char *src; + u_char *dst; + int len; +{ + static const char xdigits[] = "0123456789abcdef"; + u_char *ptr = dst, *end = dst + len; + u_int val; + int ch, digits; + + val = 0; + digits = 0; + memset(dst, 0, len); + while ((ch = *src++) != '\0') { + if (ch == '0' && (*src == 'x' || *src == 'X')) { + src++; + continue; + } + if (isascii(ch) && (isspace(ch) || ispunct(ch))) { + if (digits > 0) { + if (ptr == end) + return (0); + *ptr++ = (u_char) (val & 0xff); + val = 0; + digits = 0; + } + digits = 0; + continue; + } + if (!isascii(ch) || !isxdigit(ch)) + return (0); + if (isupper(ch)) + ch = tolower(ch); + /* Clock it in using little endian arithmetic. */ + val <<= 4; + val |= (strchr(xdigits, ch) - xdigits); + if (++digits == 2) { + if (ptr == end) + return (0); + *ptr++ = (u_char) (val & 0xff); + digits = 0; + val = 0; + } + } + if (digits > 0) { + if (ptr == end) + return (0); + *ptr++ = (u_char) (val & 0xff); + } + return ((ptr - dst) == len); +} + +static void +display(input, af, addr, len) + const char *input; + int af; + const u_char *addr; + int len; +{ + static int before = 0; + char p[sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255"]; + int i; + + if (before) + putchar('\n'); + else + before++; + + printf("Input: \"%s\"\n", input); + printf("Network: [af%d len%d]", af, len); + for (i = 0; i < len; i++) + printf(" %02x", addr[i]); + putchar('\n'); + printf("Presentation: \"%s\"\n", inet_ntop(af, addr, p, sizeof p)); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + u_char addr[BIGGEST_ADDRESS]; + int optchr, af, len; + + prog = argv[0]; + af = AF_INET; + len = INADDRSZ; + while ((optchr = getopt(argc, argv, "46n:p:")) != -1) { + switch (optchr) { + case '4': + af = AF_INET; + len = INADDRSZ; + break; + case '6': + af = AF_INET6; + len = IN6ADDRSZ; + break; + case 'n': + if (!hexstring(optarg, addr, len)) { + fprintf(stderr, "bad hex string: \"%s\"\n", + optarg); + usage(); + /* NOTREACHED */ + } + display(optarg, af, addr, len); + break; + case 'p': + if (inet_pton(af, optarg, addr) <= 0) { + fprintf(stderr, "bad address: \"%s\"\n", + optarg); + usage(); + /* NOTREACHED */ + } + display(optarg, af, addr, len); + break; + default: + usage(); + /* NOTREACHED */ + } + } + exit(0); + /* NOTREACHED */ +} diff --git a/contrib/bind/bin/dig/Makefile b/contrib/bind/bin/dig/Makefile new file mode 100644 index 0000000..dbbc00f --- /dev/null +++ b/contrib/bind/bin/dig/Makefile @@ -0,0 +1,83 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.19 1997/06/19 03:22:07 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s + +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +NSLOOKUP_OBJS= \ + ../nslookup/subr.${O} ../nslookup/send.${O} \ + ../nslookup/list.${O} ../nslookup/debug.${O} + +PROG= dig +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${NSLOOKUP_OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} ${NSLOOKUP_OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep -p ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/dig/dig.c b/contrib/bind/bin/dig/dig.c new file mode 100644 index 0000000..7db8ba0 --- /dev/null +++ b/contrib/bind/bin/dig/dig.c @@ -0,0 +1,1243 @@ +#ifndef lint +static char rcsid[] = "$Id: dig.c,v 8.19 1998/03/19 19:30:18 halley Exp $"; +#endif + +/* + * Copyright (c) 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. + */ + +/* + * 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 (c) 1996 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/*********************** Notes for the BIND 4.9 release (Paul Vixie, DEC) + * dig 2.0 was written by copying sections of libresolv.a and nslookup + * and modifying them to be more useful for a general lookup utility. + * as of BIND 4.9, the changes needed to support dig have mostly been + * incorporated into libresolv.a and nslookup; dig now links against + * some of nslookup's .o files rather than #including them or maintaining + * local copies of them. + * + * while merging dig back into the BIND release, i made a number of + * structural changes. for one thing, i put all of dig's private + * library routines into this file rather than maintaining them in + * separate, #included, files. i don't like to #include ".c" files. + * i removed all calls to "bcopy", replacing them with structure + * assignments. i removed all "extern"'s of standard functions, + * replacing them with #include's of standard header files. this + * version of dig is probably as portable as the rest of BIND. + * + * i had to remove the query-time and packet-count statistics since + * the current libresolv.a is a lot harder to modify to maintain these + * than the 4.8 one (used in the original dig) was. for consolation, + * i added a "usage" message with extensive help text. + * + * to save my (limited, albeit) sanity, i ran "indent" over the source. + * i also added the standard berkeley/DEC copyrights, since this file now + * contains a fair amount of non-USC code. note that the berkeley and + * DEC copyrights do not prohibit redistribution, with or without fee; + * we add them only to protect ourselves (you have to claim copyright + * in order to disclaim liability and warranty). + * + * Paul Vixie, Palo Alto, CA, April 1993 + **************************************************************************** + + ****************************************************************** + * DiG -- Domain Information Groper * + * * + * dig.c - Version 2.1 (7/12/94) ("BIND takeover") * + * * + * Developed by: Steve Hotz & Paul Mockapetris * + * USC Information Sciences Institute (USC-ISI) * + * Marina del Rey, California * + * 1989 * + * * + * dig.c - * + * Version 2.0 (9/1/90) * + * o renamed difftime() difftv() to avoid * + * clash with ANSI C * + * o fixed incorrect # args to strcmp,gettimeofday * + * o incorrect length specified to strncmp * + * o fixed broken -sticky -envsa -envset functions * + * o print options/flags redefined & modified * + * * + * Version 2.0.beta (5/9/90) * + * o output format - helpful to `doc` * + * o minor cleanup * + * o release to beta testers * + * * + * Version 1.1.beta (10/26/89) * + * o hanging zone transer (when REFUSED) fixed * + * o trailing dot added to domain names in RDATA * + * o ISI internal * + * * + * Version 1.0.tmp (8/27/89) * + * o Error in prnttime() fixed * + * o no longer dumps core on large pkts * + * o zone transfer (axfr) added * + * o -x added for inverse queries * + * (i.e. "dig -x 128.9.0.32") * + * o give address of default server * + * o accept broadcast to server @255.255.255.255 * + * * + * Version 1.0 (3/27/89) * + * o original release * + * * + * DiG is Public Domain, and may be used for any purpose as * + * long as this notice is not removed. * + ******************************************************************/ + +/* Import. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <resolv.h> +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +#include "../nslookup/res.h" + +extern char *_res_resultcodes[]; /* res_debug.c */ + +/* Global. */ + +#define VERSION 81 +#define VSTRING "8.1" + +#define PRF_DEF 0x2ff9 +#define PRF_MIN 0xA930 +#define PRF_ZONE 0x24f9 + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +int eecode = 0; + +FILE *qfp; +int sockFD; + +#define SAVEENV "DiG.env" +#define DIG_MAXARGS 30 + +static char *defsrv, *srvmsg; +static char defbuf[40] = "default -- "; +static char srvbuf[60]; +static char myhostname[MAXHOSTNAMELEN]; + +/* stuff for nslookup modules */ +FILE *filePtr; +jmp_buf env; +HostInfo *defaultPtr = NULL; +HostInfo curHostInfo, defaultRec; +int curHostValid = FALSE; +int queryType, queryClass; +extern int StringToClass(), StringToType(); /* subr.c */ +#if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) +FILE *yyin = NULL; +void yyrestart(FILE *f) { } +#endif +char *pager = NULL; +/* end of nslookup stuff */ + +/* Forward. */ + +static void Usage(void); +static int SetOption(const char *); +static void res_re_init(void); +static int xstrtonum(char *); +static int printZone(const char *, const struct sockaddr_in *); +static int print_axfr(FILE *output, const u_char *msg, + size_t msglen); +static struct timeval difftv(struct timeval, struct timeval); +static void prnttime(struct timeval); +static void stackarg(char *, char **); + +/* Public. */ + +int +main(int argc, char **argv) { + struct hostent *hp; + short port = htons(NAMESERVER_PORT); + /* Wierd stuff for SPARC alignment, hurts nothing else. */ + union { + HEADER header_; + u_char packet_[PACKETSZ]; + } packet_; +#define packet (packet_.packet_) + u_char answer[8*1024]; + int n; + char doping[90]; + char pingstr[50]; + char *afile; + char *addrc, *addrend, *addrbegin; + + struct timeval exectime, tv1, tv2, start_time, end_time, query_time; + + char *srv; + int anyflag = 0; + int sticky = 0; + int tmp; + int qtypeSet; + int addrflag = 0; + int zone = 0; + int bytes_out, bytes_in; + + char cmd[256]; + char domain[MAXDNAME]; + char msg[120], *msgptr; + char **vtmp; + char *args[DIG_MAXARGS]; + char **ax; + int once = 1, dofile = 0; /* batch -vs- interactive control */ + char fileq[100]; + int fp; + int wait=0, delay; + int envset=0, envsave=0; + struct __res_state res_x, res_t; + char *pp; + + res_init(); + _res.pfcode = PRF_DEF; + qtypeSet = 0; + memset(domain, 0, sizeof domain); + gethostname(myhostname, (sizeof myhostname)); + defsrv = strcat(defbuf, inet_ntoa(_res.nsaddr.sin_addr)); + res_x = _res; + +/* + * If LOCALDEF in environment, should point to file + * containing local favourite defaults. Also look for file + * DiG.env (i.e. SAVEENV) in local directory. + */ + + if ((((afile = (char *) getenv("LOCALDEF")) != (char *) NULL) && + ((fp = open(afile, O_RDONLY)) > 0)) || + ((fp = open(SAVEENV, O_RDONLY)) > 0)) { + read(fp, (char *)&res_x, (sizeof res_x)); + close(fp); + _res = res_x; + } +/* + * Check for batch-mode DiG; also pre-scan for 'help'. + */ + vtmp = argv; + ax = args; + while (*vtmp != NULL) { + if (strcmp(*vtmp, "-h") == 0 || + strcmp(*vtmp, "-help") == 0 || + strcmp(*vtmp, "-usage") == 0 || + strcmp(*vtmp, "help") == 0) { + Usage(); + exit(0); + } + + if (strcmp(*vtmp, "-f") == 0) { + dofile++; once=0; + if ((qfp = fopen(*++vtmp, "r")) == NULL) { + fflush(stdout); + perror("file open"); + fflush(stderr); + exit(10); + } + } else { + if (ax - args == DIG_MAXARGS) { + fprintf(stderr, "dig: too many arguments\n"); + exit(10); + } + *ax++ = *vtmp; + } + vtmp++; + } + + _res.id = 1; + gettimeofday(&tv1, NULL); + +/* + * Main section: once if cmd-line query + * while !EOF if batch mode + */ + *fileq = '\0'; + while ((dofile && fgets(fileq, sizeof fileq, qfp) != NULL) || + (!dofile && once--)) + { + if (*fileq == '\n' || *fileq == '#' || *fileq==';') + continue; /* ignore blank lines & comments */ + +/* + * "Sticky" requests that before current parsing args + * return to current "working" environment (X******). + */ + if (sticky) { + printf(";; (using sticky settings)\n"); + _res = res_x; + } + +/* + * Concat cmd-line and file args. + */ + stackarg(fileq, ax); + + /* defaults */ + queryType = ns_t_ns; + queryClass = ns_c_in; + zone = 0; + *pingstr = 0; + srv = NULL; + + sprintf(cmd, "\n; <<>> DiG %s <<>> ", VSTRING); + argv = args; + argc = ax - args; +/* + * More cmd-line options than anyone should ever have to + * deal with .... + */ + while (*(++argv) != NULL && **argv != '\0') { + strcat(cmd, *argv); + strcat(cmd, " "); + if (**argv == '@') { + srv = (*argv+1); + continue; + } + if (**argv == '%') + continue; + if (**argv == '+') { + SetOption(*argv+1); + continue; + } + + if (strncmp(*argv, "-nost", 5) == 0) { + sticky = 0; + continue; + } else if (strncmp(*argv, "-st", 3) == 0) { + sticky++; + continue; + } else if (strncmp(*argv, "-envsa", 6) == 0) { + envsave++; + continue; + } else if (strncmp(*argv, "-envse", 6) == 0) { + envset++; + continue; + } + + if (**argv == '-') { + switch (argv[0][1]) { + case 'T': + wait = atoi(*++argv); + break; + case 'c': + if ((tmp = atoi(*++argv)) + || *argv[0]=='0') { + queryClass = tmp; + } else if ((tmp = StringToClass(*argv, + 0, NULL) + ) != 0) { + queryClass = tmp; + } else { + printf( + "; invalid class specified\n" + ); + } + break; + case 't': + if ((tmp = atoi(*++argv)) + || *argv[0]=='0') { + queryType = tmp; + qtypeSet++; + } else if ((tmp = StringToType(*argv, + 0, NULL) + ) != 0) { + queryType = tmp; + qtypeSet++; + } else { + printf( + "; invalid type specified\n" + ); + } + break; + case 'x': + if (!qtypeSet) { + queryType = T_ANY; + qtypeSet++; + } + if (!(addrc = *++argv)) { + printf( + "; no arg for -x?\n" + ); + break; + } + addrend = addrc + strlen(addrc); + if (*addrend == '.') + *addrend = '\0'; + *domain = '\0'; + while ((addrbegin = strrchr(addrc,'.'))) { + strcat(domain, addrbegin+1); + strcat(domain, "."); + *addrbegin = '\0'; + } + strcat(domain, addrc); + strcat(domain, ".in-addr.arpa."); + break; + case 'p': port = htons(atoi(*++argv)); break; + case 'P': + if (argv[0][2] != '\0') + strcpy(pingstr,&argv[0][2]); + else + strcpy(pingstr,"ping -s"); + break; + case 'n': + _res.ndots = atoi(&argv[0][2]); + break; + } /* switch - */ + continue; + } /* if '-' */ + + if ((tmp = StringToType(*argv, -1, NULL)) != -1) { + if ((T_ANY == tmp) && anyflag++) { + queryClass = C_ANY; + continue; + } + if (T_AXFR == tmp) { + _res.pfcode = PRF_ZONE; + zone++; + } else { + queryType = tmp; + qtypeSet++; + } + } else if ((tmp = StringToClass(*argv, -1, NULL)) + != -1) { + queryClass = tmp; + } else { + memset(domain, 0, sizeof domain); + sprintf(domain,"%s",*argv); + } + } /* while argv remains */ + + if (_res.pfcode & 0x80000) + printf("; pfcode: %08lx, options: %08lx\n", + _res.pfcode, _res.options); + +/* + * Current env. (after this parse) is to become the + * new "working" environmnet. Used in conj. with sticky. + */ + if (envset) { + res_x = _res; + envset = 0; + } + +/* + * Current env. (after this parse) is to become the + * new default saved environmnet. Save in user specified + * file if exists else is SAVEENV (== "DiG.env"). + */ + if (envsave) { + afile = (char *) getenv("LOCALDEF"); + if ((afile && + ((fp = open(afile, + O_WRONLY|O_CREAT|O_TRUNC, + S_IREAD|S_IWRITE)) > 0)) + || + ((fp = open(SAVEENV, + O_WRONLY|O_CREAT|O_TRUNC, + S_IREAD|S_IWRITE)) > 0)) { + write(fp, (char *)&_res, (sizeof _res)); + close(fp); + } + envsave = 0; + } + + if (_res.pfcode & RES_PRF_CMD) + printf("%s\n", cmd); + + addrflag = anyflag = 0; + +/* + * Find address of server to query. If not dot-notation, then + * try to resolve domain-name (if so, save and turn off print + * options, this domain-query is not the one we want. Restore + * user options when done. + * Things get a bit wierd since we need to use resolver to be + * able to "put the resolver to work". + */ + + srvbuf[0] = 0; + srvmsg = defsrv; + if (srv != NULL) { + struct in_addr addr; + + if (inet_aton(srv, &addr)) { + _res.nscount = 1; + _res.nsaddr.sin_addr = addr; + srvmsg = strcat(srvbuf, srv); + } else { + res_t = _res; + _res.pfcode = 0; + _res.options = RES_DEFAULT; + res_init(); + hp = gethostbyname(srv); + _res = res_t; + if (hp == NULL + || hp->h_addr_list == NULL + || *hp->h_addr_list == NULL) { + fflush(stdout); + fprintf(stderr, + "; Bad server: %s -- using default server and timer opts\n", + srv); + fflush(stderr); + srvmsg = defsrv; + srv = NULL; + } else { + u_int32_t **addr; + + _res.nscount = 0; + for (addr = (u_int32_t**)hp->h_addr_list; + *addr && (_res.nscount < MAXNS); + addr++) { + _res.nsaddr_list[ + _res.nscount++ + ].sin_addr.s_addr = **addr; + } + + srvmsg = strcat(srvbuf,srv); + strcat(srvbuf, " "); + strcat(srvmsg, + inet_ntoa(_res.nsaddr.sin_addr) + ); + } + } + printf("; (%d server%s found)\n", + _res.nscount, (_res.nscount==1)?"":"s"); + _res.id += _res.retry; + } + + { + int i; + + for (i = 0; i < _res.nscount; i++) { + _res.nsaddr_list[i].sin_family = AF_INET; + _res.nsaddr_list[i].sin_port = port; + } + _res.id += _res.retry; + } + + if (zone) { + int i; + + for (i = 0; i < _res.nscount; i++) { + int x = printZone(domain, + &_res.nsaddr_list[i]); + if (_res.pfcode & RES_PRF_STATS) { + struct timeval exectime; + time_t t; + + printf(";; FROM: %s to SERVER: %s\n", + myhostname, + inet_ntoa(_res.nsaddr_list[i] + .sin_addr)); + gettimeofday(&exectime, NULL); + t = (time_t)exectime.tv_sec; + printf(";; WHEN: %s", ctime(&t)); + } + if (!x) + break; /* success */ + } + fflush(stdout); + continue; + } + + if (*domain && !qtypeSet) { + queryType = T_A; + qtypeSet++; + } + + bytes_out = n = res_mkquery(QUERY, domain, + queryClass, queryType, + NULL, 0, NULL, + packet, sizeof packet); + if (n < 0) { + fflush(stderr); + printf(";; res_mkquery: buffer too small\n\n"); + continue; + } + eecode = 0; + if (_res.pfcode & RES_PRF_HEAD1) + __fp_resstat(NULL, stdout); + (void) gettimeofday(&start_time, NULL); + if ((bytes_in = n = res_send(packet, n, + answer, sizeof answer)) < 0) { + fflush(stdout); + n = 0 - n; + msg[0]=0; + strcat(msg,";; res_send to server "); + strcat(msg,srvmsg); + perror(msg); + fflush(stderr); + + if (!dofile) { + if (eecode) + exit(eecode); + else + exit(9); + } + } + (void) gettimeofday(&end_time, NULL); + + if (_res.pfcode & RES_PRF_STATS) { + time_t t; + + query_time = difftv(start_time, end_time); + printf(";; Total query time: "); + prnttime(query_time); + putchar('\n'); + printf(";; FROM: %s to SERVER: %s\n", + myhostname, srvmsg); + gettimeofday(&exectime,NULL); + t = (time_t)exectime.tv_sec; + printf(";; WHEN: %s", ctime(&t)); + printf(";; MSG SIZE sent: %d rcvd: %d\n", + bytes_out, bytes_in); + } + + fflush(stdout); +/* + * Argh ... not particularly elegant. Should put in *real* ping code. + * Would necessitate root priviledges for icmp port though! + */ + if (*pingstr) { + sprintf(doping,"%s %s 56 3 | tail -3",pingstr, + (srv==NULL)?(defsrv+10):srv); + system(doping); + } + putchar('\n'); + +/* + * Fairly crude method and low overhead method of keeping two + * batches started at different sites somewhat synchronized. + */ + gettimeofday(&tv2, NULL); + delay = (int)(tv2.tv_sec - tv1.tv_sec); + if (delay < wait) { + sleep(wait - delay); + } + } + return (eecode); +} + +/* Private. */ + +static void +Usage() { + fputs("\ +usage: dig [@server] [domain] [q-type] [q-class] {q-opt} {d-opt} [%comment]\n\ +where: server,\n\ + domain are names in the Domain Name System\n\ + q-class is one of (in,any,...) [default: in]\n\ + q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default: a]\n\ +", stderr); + fputs("\ + q-opt is one of:\n\ + -x dot-notation-address (shortcut to in-addr.arpa lookups)\n\ + -f file (batch mode input file name)\n\ + -T time (batch mode time delay, per query)\n\ + -p port (nameserver is on this port) [53]\n\ + -Pping-string (see man page)\n\ + -t query-type (synonym for q-type)\n\ + -c query-class (synonym for q-class)\n\ + -envsav,-envset (see man page)\n\ + -[no]stick (see man page)\n\ +", stderr); + fputs("\ + d-opt is of the form ``+keyword=value'' where keyword is one of:\n\ + [no]debug [no]d2 [no]recurse retry=# time=# [no]ko [no]vc\n\ + [no]defname [no]search domain=NAME [no]ignore [no]primary\n\ + [no]aaonly [no]cmd [no]stats [no]Header [no]header\n\ + [no]ttlid [no]cl [no]qr [no]reply [no]ques [no]answer\n\ + [no]author [no]addit pfdef pfmin pfset=# pfand=# pfor=#\n\ +", stderr); + fputs("\ +notes: defname and search don't work; use fully-qualified names.\n\ +", stderr); +} + +static int +SetOption(const char *string) { + char option[NAME_LEN], type[NAME_LEN], *ptr; + int i; + + i = sscanf(string, " %s", option); + if (i != 1) { + fprintf(stderr, ";*** Invalid option: %s\n", option); + return (ERROR); + } + + if (strncmp(option, "aa", 2) == 0) { /* aaonly */ + _res.options |= RES_AAONLY; + } else if (strncmp(option, "noaa", 4) == 0) { + _res.options &= ~RES_AAONLY; + } else if (strncmp(option, "deb", 3) == 0) { /* debug */ + _res.options |= RES_DEBUG; + } else if (strncmp(option, "nodeb", 5) == 0) { + _res.options &= ~(RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "ko", 2) == 0) { /* keepopen */ + _res.options |= (RES_STAYOPEN | RES_USEVC); + } else if (strncmp(option, "noko", 4) == 0) { + _res.options &= ~RES_STAYOPEN; + } else if (strncmp(option, "d2", 2) == 0) { /* d2 (more debug) */ + _res.options |= (RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "nod2", 4) == 0) { + _res.options &= ~RES_DEBUG2; + } else if (strncmp(option, "def", 3) == 0) { /* defname */ + _res.options |= RES_DEFNAMES; + } else if (strncmp(option, "nodef", 5) == 0) { + _res.options &= ~RES_DEFNAMES; + } else if (strncmp(option, "sea", 3) == 0) { /* search list */ + _res.options |= RES_DNSRCH; + } else if (strncmp(option, "nosea", 5) == 0) { + _res.options &= ~RES_DNSRCH; + } else if (strncmp(option, "do", 2) == 0) { /* domain */ + ptr = strchr(option, '='); + if (ptr != NULL) + sscanf(++ptr, "%s", _res.defdname); + } else if (strncmp(option, "ti", 2) == 0) { /* timeout */ + ptr = strchr(option, '='); + if (ptr != NULL) + sscanf(++ptr, "%d", &_res.retrans); + } else if (strncmp(option, "ret", 3) == 0) { /* retry */ + ptr = strchr(option, '='); + if (ptr != NULL) + sscanf(++ptr, "%d", &_res.retry); + } else if (strncmp(option, "i", 1) == 0) { /* ignore */ + _res.options |= RES_IGNTC; + } else if (strncmp(option, "noi", 3) == 0) { + _res.options &= ~RES_IGNTC; + } else if (strncmp(option, "pr", 2) == 0) { /* primary */ + _res.options |= RES_PRIMARY; + } else if (strncmp(option, "nop", 3) == 0) { + _res.options &= ~RES_PRIMARY; + } else if (strncmp(option, "rec", 3) == 0) { /* recurse */ + _res.options |= RES_RECURSE; + } else if (strncmp(option, "norec", 5) == 0) { + _res.options &= ~RES_RECURSE; + } else if (strncmp(option, "v", 1) == 0) { /* vc */ + _res.options |= RES_USEVC; + } else if (strncmp(option, "nov", 3) == 0) { + _res.options &= ~RES_USEVC; + } else if (strncmp(option, "pfset", 5) == 0) { + ptr = strchr(option, '='); + if (ptr != NULL) + _res.pfcode = xstrtonum(++ptr); + } else if (strncmp(option, "pfand", 5) == 0) { + ptr = strchr(option, '='); + if (ptr != NULL) + _res.pfcode = _res.pfcode & xstrtonum(++ptr); + } else if (strncmp(option, "pfor", 4) == 0) { + ptr = strchr(option, '='); + if (ptr != NULL) + _res.pfcode |= xstrtonum(++ptr); + } else if (strncmp(option, "pfmin", 5) == 0) { + _res.pfcode = PRF_MIN; + } else if (strncmp(option, "pfdef", 5) == 0) { + _res.pfcode = PRF_DEF; + } else if (strncmp(option, "an", 2) == 0) { /* answer section */ + _res.pfcode |= RES_PRF_ANS; + } else if (strncmp(option, "noan", 4) == 0) { + _res.pfcode &= ~RES_PRF_ANS; + } else if (strncmp(option, "qu", 2) == 0) { /* question section */ + _res.pfcode |= RES_PRF_QUES; + } else if (strncmp(option, "noqu", 4) == 0) { + _res.pfcode &= ~RES_PRF_QUES; + } else if (strncmp(option, "au", 2) == 0) { /* authority section */ + _res.pfcode |= RES_PRF_AUTH; + } else if (strncmp(option, "noau", 4) == 0) { + _res.pfcode &= ~RES_PRF_AUTH; + } else if (strncmp(option, "ad", 2) == 0) { /* addition section */ + _res.pfcode |= RES_PRF_ADD; + } else if (strncmp(option, "noad", 4) == 0) { + _res.pfcode &= ~RES_PRF_ADD; + } else if (strncmp(option, "tt", 2) == 0) { /* TTL & ID */ + _res.pfcode |= RES_PRF_TTLID; + } else if (strncmp(option, "nott", 4) == 0) { + _res.pfcode &= ~RES_PRF_TTLID; + } else if (strncmp(option, "he", 2) == 0) { /* head flags stats */ + _res.pfcode |= RES_PRF_HEAD2; + } else if (strncmp(option, "nohe", 4) == 0) { + _res.pfcode &= ~RES_PRF_HEAD2; + } else if (strncmp(option, "H", 1) == 0) { /* header all */ + _res.pfcode |= RES_PRF_HEADX; + } else if (strncmp(option, "noH", 3) == 0) { + _res.pfcode &= ~(RES_PRF_HEADX); + } else if (strncmp(option, "qr", 2) == 0) { /* query */ + _res.pfcode |= RES_PRF_QUERY; + } else if (strncmp(option, "noqr", 4) == 0) { + _res.pfcode &= ~RES_PRF_QUERY; + } else if (strncmp(option, "rep", 3) == 0) { /* reply */ + _res.pfcode |= RES_PRF_REPLY; + } else if (strncmp(option, "norep", 5) == 0) { + _res.pfcode &= ~RES_PRF_REPLY; + } else if (strncmp(option, "cm", 2) == 0) { /* command line */ + _res.pfcode |= RES_PRF_CMD; + } else if (strncmp(option, "nocm", 4) == 0) { + _res.pfcode &= ~RES_PRF_CMD; + } else if (strncmp(option, "cl", 2) == 0) { /* class mnemonic */ + _res.pfcode |= RES_PRF_CLASS; + } else if (strncmp(option, "nocl", 4) == 0) { + _res.pfcode &= ~RES_PRF_CLASS; + } else if (strncmp(option, "st", 2) == 0) { /* stats*/ + _res.pfcode |= RES_PRF_STATS; + } else if (strncmp(option, "nost", 4) == 0) { + _res.pfcode &= ~RES_PRF_STATS; + } else { + fprintf(stderr, "; *** Invalid option: %s\n", option); + return (ERROR); + } + res_re_init(); + return (SUCCESS); +} + +/* + * Force a reinitialization when the domain is changed. + */ +static void +res_re_init() +{ + static char localdomain[] = "LOCALDOMAIN"; + long pfcode = _res.pfcode; + long ndots = _res.ndots; + char *buf; + + /* + * This is ugly but putenv() is more portable than setenv(). + */ + buf = malloc((sizeof localdomain) + strlen(_res.defdname) +10/*fuzz*/); + sprintf(buf, "%s=%s", localdomain, _res.defdname); + putenv(buf); /* keeps the argument, so we won't free it */ + res_init(); + _res.pfcode = pfcode; + _res.ndots = ndots; +} + +/* + * convert char string (decimal, octal, or hex) to integer + */ +static int +xstrtonum(char *p) { + int v = 0; + int i; + int b = 10; + int flag = 0; + while (*p != 0) { + if (!flag++) + if (*p == '0') { + b = 8; p++; + continue; + } + if (isupper(*p)) + *p = tolower(*p); + if (*p == 'x') { + b = 16; p++; + continue; + } + if (isdigit(*p)) { + i = *p - '0'; + } else if (isxdigit(*p)) { + i = *p - 'a' + 10; + } else { + fprintf(stderr, + "; *** Bad char in numeric string..ignored\n"); + i = -1; + } + if (i >= b) { + fprintf(stderr, + "; *** Bad char in numeric string..ignored\n"); + i = -1; + } + if (i >= 0) + v = v * b + i; + p++; + } + return (v); +} + +typedef union { + HEADER qb1; + u_char qb2[PACKETSZ]; +} querybuf; + +static int +printZone(const char *zone, const struct sockaddr_in *sin) { + static u_char *answer = NULL; + static int answerLen = 0; + + querybuf buf; + HEADER *headerPtr; + int msglen, amtToRead, numRead, result = 0, sockFD, len; + int count, type, class, rlen, done, n; + int numAnswers = 0, numRecords = 0, soacnt = 0; + u_char *cp, tmp[NS_INT16SZ]; + char dname[2][NS_MAXDNAME], file[NAME_LEN]; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error = NO_ERRORS; + + /* + * Create a query packet for the requested zone name. + */ + msglen = res_mkquery(ns_o_query, zone, queryClass, ns_t_axfr, NULL, + 0, 0, buf.qb2, sizeof buf); + if (msglen < 0) { + if (_res.options & RES_DEBUG) + fprintf(stderr, ";; res_mkquery failed\n"); + return (ERROR); + } + + /* + * Set up a virtual circuit to the server. + */ + if ((sockFD = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { + int e = errno; + + perror(";; socket"); + return (e); + } + if (connect(sockFD, (struct sockaddr *)sin, sizeof *sin) < 0) { + int e = errno; + + perror(";; connect"); + (void) close(sockFD); + sockFD = -1; + return e; + } + + /* + * Send length & message for zone transfer + */ + + ns_put16(msglen, tmp); + if (write(sockFD, (char *)tmp, NS_INT16SZ) != NS_INT16SZ || + write(sockFD, (char *)&buf, msglen) != msglen) { + int e = errno; + perror(";; write"); + (void) close(sockFD); + sockFD = -1; + return (e); + } + + dname[0][0] = '\0'; + for (done = 0; !done; (void)NULL) { + /* + * Read the length of the response. + */ + + cp = tmp; + amtToRead = INT16SZ; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_LEN; + break; + } + + len = ns_get16(tmp); + if (len == 0) + break; /* nothing left to read */ + + /* + * The server sent too much data to fit the existing buffer -- + * allocate a new one. + */ + if (len > answerLen) { + if (answerLen != 0) + free(answer); + answerLen = len; + answer = (u_char *)Malloc(answerLen); + } + + /* + * Read the response. + */ + + amtToRead = len; + cp = answer; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_MSG; + break; + } + + result = print_axfr(stdout, answer, cp - answer); + if (result != 0) { + error = ERR_PRINTING; + break; + } + numRecords += htons(((HEADER *)answer)->ancount); + numAnswers++; + + /* Header. */ + cp = answer + HFIXEDSZ; + /* Question. */ + for (count = ntohs(((HEADER *)answer)->qdcount); + count > 0; + count--) { + n = dn_skipname(cp, answer + len); + if (n < 0) { + error = ERR_PRINTING; + done++; + break; + } + cp += n + QFIXEDSZ; + if (cp > answer + len) { + error = ERR_PRINTING; + done++; + break; + } + } + /* Answer. */ + for (count = ntohs(((HEADER *)answer)->ancount); + count > 0 && !done; + count--) { + n = dn_expand(answer, answer + len, cp, + dname[soacnt], sizeof dname[0]); + if (n < 0) { + error = ERR_PRINTING; + done++; + break; + } + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > answer + len) { + error = ERR_PRINTING; + done++; + break; + } + GETSHORT(type, cp); + GETSHORT(class, cp); + cp += INT32SZ; /* ttl */ + GETSHORT(rlen, cp); + cp += rlen; + if (cp > answer + len) { + error = ERR_PRINTING; + done++; + break; + } + if (type == T_SOA && soacnt++ && + !strcasecmp(dname[0], dname[1])) { + done++; + break; + } + } + } + + printf(";; Received %d answer%s (%d record%s).\n", + numAnswers, (numAnswers != 1) ? "s" : "", + numRecords, (numRecords != 1) ? "s" : ""); + + (void) close(sockFD); + sockFD = -1; + + switch (error) { + case NO_ERRORS: + return (0); + + case ERR_READING_LEN: + return (EMSGSIZE); + + case ERR_PRINTING: + return (result); + + case ERR_READING_MSG: + return (EMSGSIZE); + + default: + return (EFAULT); + } +} + +static int +print_axfr(FILE *file, const u_char *msg, size_t msglen) { + ns_msg handle; + + if (ns_initparse(msg, msglen, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return (ns_r_formerr); + } + if (ns_msg_getflag(handle, ns_f_rcode) != ns_r_noerror) + return (ns_msg_getflag(handle, ns_f_rcode)); + + /* + * We are looking for info from answer resource records. + * If there aren't any, return with an error. We assume + * there aren't any question records. + */ + if (ns_msg_count(handle, ns_s_an) == 0) + return (NO_INFO); + +#ifdef PROTOCOLDEBUG + printf(";;; (message of %d octets has %d answers)\n", + msglen, ns_msg_count(handle, ns_s_an)); +#endif + for (;;) { + static char origin[NS_MAXDNAME], name_ctx[NS_MAXDNAME]; + const char *name; + char buf[2048]; /* XXX need to malloc/realloc. */ + ns_rr rr; + + if (ns_parserr(&handle, ns_s_an, -1, &rr)) { + if (errno != ENODEV) { + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + return (FORMERR); + } + break; + } + name = ns_rr_name(rr); + if (origin[0] == '\0' && name[0] != '\0') { + fprintf(file, "$ORIGIN %s.\n", name); + strcpy(origin, name); + } + if (ns_sprintrr(&handle, &rr, name_ctx, origin, + buf, sizeof buf) < 0) { + fprintf(file, ";; ns_sprintrr: %s\n", strerror(errno)); + return (FORMERR); + } + strcpy(name_ctx, name); + fputs(buf, file); + fputc('\n', file); + } + return (SUCCESS); +} + +static struct timeval +difftv(struct timeval a, struct timeval b) { + static struct timeval diff; + + diff.tv_sec = b.tv_sec - a.tv_sec; + if ((diff.tv_usec = b.tv_usec - a.tv_usec) < 0) { + diff.tv_sec--; + diff.tv_usec += 1000000; + } + return (diff); +} + +static void +prnttime(struct timeval t) { + printf("%lu msec", (u_long)(t.tv_sec * 1000 + (t.tv_usec / 1000))); +} + +/* + * Take arguments appearing in simple string (from file or command line) + * place in char**. + */ +static void +stackarg(char *l, char **y) { + int done = 0; + + while (!done) { + switch (*l) { + case '\t': + case ' ': + l++; + break; + case '\0': + case '\n': + done++; + *y = NULL; + break; + default: + *y++ = l; + while (!isspace(*l)) + l++; + if (*l == '\n') + done++; + *l++ = '\0'; + *y = NULL; + } + } +} diff --git a/contrib/bind/bin/dnsquery/Makefile b/contrib/bind/bin/dnsquery/Makefile new file mode 100644 index 0000000..95d557d --- /dev/null +++ b/contrib/bind/bin/dnsquery/Makefile @@ -0,0 +1,79 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.18 1997/06/19 03:22:08 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s + +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +PROG= dnsquery +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep -p ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/dnsquery/dnsquery.c b/contrib/bind/bin/dnsquery/dnsquery.c new file mode 100644 index 0000000..790e0cc --- /dev/null +++ b/contrib/bind/bin/dnsquery/dnsquery.c @@ -0,0 +1,206 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: dnsquery.c,v 8.7 1997/05/21 19:51:22 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "port_after.h" + +extern int errno; +extern int h_errno; +extern char *h_errlist[]; + +int +main(int argc, char *argv[]) { + char name[MAXDNAME]; + u_char answer[8*1024]; + int c, n, i = 0; + u_int32_t ul; + int nameservers = 0, class, type, len; + struct in_addr q_nsaddr[MAXNS]; + struct hostent *q_nsname; + extern int optind, opterr; + extern char *optarg; + HEADER *hp; + int stream = 0, debug = 0; + + /* set defaults */ + len = MAXDNAME; + gethostname(name, len); + class = C_IN; + type = T_ANY; + + /* if no args, exit */ + if (argc == 1) { + fprintf(stderr, "Usage: %s [-h] host [-n ns] [-t type] [-c class] [-r retry] [-p period] [-s] [-v] [-d] [-a]\n", argv[0]); + exit(-1); + } + + /* handle args */ + while ((c = getopt(argc, argv, "c:dh:n:p:r:st:u:v")) != EOF) { + switch (c) { + + case 'r' : _res.retry = atoi(optarg); + break; + + case 'p' : _res.retrans = atoi(optarg); + break; + + case 'h' : strcpy(name, optarg); + break; + + case 'c' : { + int success, proto_class; + + proto_class = sym_ston(__p_class_syms, + optarg, &success); + if (success) + class = proto_class; + else { + fprintf(stderr, "Bad class (%s)\n", optarg); + exit(-1); + } + } + break; + + case 't' : { + int success, proto_type; + + proto_type = sym_ston(__p_type_syms, + optarg, &success); + if (success) + type = proto_type; + else { + fprintf(stderr, "Bad type (%s)\n", optarg); + exit(-1); + } + } + break; + + case 'd' : debug++; + break; + + case 's' : + case 'v' : stream++; + break; + + case 'n' : + /* + * If we set some nameservers here without + * using gethostbyname() first, then they will + * get overwritten when we do the first query. + * So, we must init the resolver before any + * of this. + */ + if (!(_res.options & RES_INIT)) + if (res_init() == -1) { + fprintf(stderr, + "res_init() failed\n"); + exit(-1); + } + if (nameservers >= MAXNS) break; + (void) inet_aton(optarg, + &q_nsaddr[nameservers]); + if (!inet_aton(optarg, (struct in_addr *)&ul)){ + q_nsname = gethostbyname(optarg); + if (q_nsname == 0) { + fprintf(stderr, + "Bad nameserver (%s)\n", + optarg); + exit(-1); + } + memcpy(&q_nsaddr[nameservers], + q_nsname->h_addr, INADDRSZ); + } + else + q_nsaddr[nameservers].s_addr = ul; + nameservers++; + break; + + default : fprintf(stderr, + "\tUsage: %s [-n ns] [-h host] [-t type] [-c class] [-r retry] [-p period] [-s] [-v] [-d] [-a]\n", argv[0]); + exit(-1); + } + } + if (optind < argc) + strcpy(name, argv[optind]); + + len = sizeof(answer); + + /* + * set these here so they aren't set for a possible call to + * gethostbyname above + */ + if (debug || stream) { + if (!(_res.options & RES_INIT)) + if (res_init() == -1) { + fprintf(stderr, "res_init() failed\n"); + exit(-1); + } + if (debug) + _res.options |= RES_DEBUG; + if (stream) + _res.options |= RES_USEVC; + } + + /* if the -n flag was used, add them to the resolver's list */ + if (nameservers != 0) { + _res.nscount = nameservers; + for (i = nameservers - 1; i >= 0; i--) { + _res.nsaddr_list[i].sin_addr.s_addr = q_nsaddr[i].s_addr; + _res.nsaddr_list[i].sin_family = AF_INET; + _res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); + } + } + + /* + * if the -h arg is fully-qualified, use res_query() since + * using res_search() will lead to use of res_querydomain() + * which will strip the trailing dot + */ + if (name[strlen(name) - 1] == '.') { + n = res_query(name, class, type, answer, len); + if (n < 0) { + fprintf(stderr, "Query failed (h_errno = %d) : %s\n", + h_errno, h_errlist[h_errno]); + exit(-1); + } + } else if ((n = res_search(name, class, type, answer, len)) < 0) { + fprintf(stderr, "Query failed (h_errno = %d) : %s\n", + h_errno, h_errlist[h_errno]); + exit(-1); + } + fp_nquery(answer, n, stdout); + exit(0); +} diff --git a/contrib/bind/bin/host/Makefile b/contrib/bind/bin/host/Makefile new file mode 100644 index 0000000..c1090d4 --- /dev/null +++ b/contrib/bind/bin/host/Makefile @@ -0,0 +1,79 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.18 1997/06/19 03:22:08 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s + +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +PROG= host +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep -p ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/host/host.c b/contrib/bind/bin/host/host.c new file mode 100644 index 0000000..78eb48b --- /dev/null +++ b/contrib/bind/bin/host/host.c @@ -0,0 +1,1411 @@ +#ifndef lint +static char rcsid[] = "$Id: host.c,v 8.21 1998/03/19 19:31:25 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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) 1996 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1986 Regents of the University of California.\n\ + Portions Copyright (c) 1993 Digital Equipment Corporation.\n\ + Portions Copyright (c) 1996 Internet Software Consortium.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +/* + * Actually, this program is from Rutgers University, however it is + * based on nslookup and other pieces of named tools, so it needs + * the above copyright notices. + */ + +/* Import. */ + +#include "port_before.h" + +#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 <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +extern int h_errno; +extern char *_res_resultcodes[]; + +/* Global. */ + +#define NUMNS 8 +#define NUMNSADDR 16 +#define NUMMX 50 + +#define SUCCESS 0 +#define TIME_OUT -1 +#define NO_INFO -2 +#define ERROR -3 +#define NONAUTH -4 + +typedef union { + HEADER qb1; + u_char qb2[NS_PACKETSZ]; +} querybuf; + +static char cnamebuf[NS_MAXDNAME]; +static u_char hostbuf[NS_MAXDNAME]; + +static int sockFD; +static FILE *filePtr; + +static struct __res_state orig; +static char *cname = NULL; +static int getclass = ns_c_in, verbose = 0, list = 0; +static int server_specified = 0; +static int gettype; + +/* Forward. */ + +static int parsetype(const char *s); +static int parseclass(const char *s); +static void printanswer(const struct hostent *hp); +static void hperror(int errnum); +static int getaddrinfo(struct in_addr addr); +static int gethostinfo(char *name); +static int getdomaininfo(const char *name, const char *domain); +static int getinfo(const char *name, const char *domain, + int type); +static int printinfo(const querybuf *answer, const u_char *eom, + int filter, int isls); +static const u_char * pr_rr(const u_char *cp, const u_char *msg, FILE *file, + int filter); +static const char * pr_type(int type); +static const char * pr_class(int class); +static const u_char * pr_cdname(const u_char *cp, const u_char *msg, + char *name, int namelen); +static int ListHosts(char *namePtr, int queryType); +static const char * DecodeError(int result); + +/* Public. */ + +int +main(int c, char **v) { + struct in_addr addr; + struct hostent *hp; + char *s, *oldcname; + int inverse = 0, waitmode = 0; + int ncnames; + + res_init(); + _res.retrans = 5; + + if (c < 2) { + fprintf(stderr, "Usage: host [-w] [-v] [-r] [-d] [-t querytype] [-c class] [-a] host [server]\n -w to wait forever until reply\n -v for verbose output\n -r to disable recursive processing\n -d to turn on debugging output\n -t querytype to look for a specific type of information\n -c class to look for non-Internet data\n -a is equivalent to '-v -t *'\n"); + exit(1); + } + while (c > 2 && v[1][0] == '-') { + if (strcmp (v[1], "-w") == 0) { + _res.retry = 1; + _res.retrans = 15; + waitmode = 1; + v++; + c--; + } + else if (strcmp (v[1], "-r") == 0) { + _res.options &= ~RES_RECURSE; + v++; + c--; + } + else if (strcmp (v[1], "-d") == 0) { + _res.options |= RES_DEBUG; + v++; + c--; + } + else if (strcmp (v[1], "-v") == 0) { + verbose = 1; + v++; + c--; + } + else if (strcmp (v[1], "-l") == 0) { + list = 1; + v++; + c--; + } + else if (strncmp (v[1], "-t", 2) == 0) { + v++; + c--; + gettype = parsetype(v[1]); + v++; + c--; + } + else if (strncmp (v[1], "-c", 2) == 0) { + v++; + c--; + getclass = parseclass(v[1]); + v++; + c--; + } + else if (strcmp (v[1], "-a") == 0) { + verbose = 1; + gettype = ns_t_any; + v++; + c--; + } + } + if (c > 2) { + s = v[2]; + server_specified++; + + if (!inet_aton(s, &addr)) { + hp = gethostbyname(s); + if (hp == NULL) { + fprintf(stderr, + "Error in looking up server name:\n"); + hperror(h_errno); + exit(1); + } + memcpy(&_res.nsaddr.sin_addr, hp->h_addr, NS_INADDRSZ); + printf("Using domain server:\n"); + printanswer(hp); + } else { + _res.nsaddr.sin_family = AF_INET; + _res.nsaddr.sin_addr = addr; + _res.nsaddr.sin_port = htons(NAMESERVER_PORT); + printf("Using domain server %s:\n", + inet_ntoa(_res.nsaddr.sin_addr)); + } + _res.nscount = 1; + _res.retry = 2; + } + if (strcmp(v[1], ".") == 0 || !inet_aton(v[1], &addr)) + addr.s_addr = INADDR_NONE; + hp = NULL; + h_errno = TRY_AGAIN; +/* + * We handle default domains ourselves, thank you. + */ + _res.options &= ~RES_DEFNAMES; + + if (list) + exit(ListHosts(v[1], gettype ? gettype : ns_t_a)); + oldcname = NULL; + ncnames = 5; + while (hp == NULL && h_errno == TRY_AGAIN) { + if (addr.s_addr == INADDR_NONE) { + cname = NULL; + if (oldcname == NULL) + hp = (struct hostent *)gethostinfo(v[1]); + else + hp = (struct hostent *)gethostinfo(oldcname); + if (cname) { + if (ncnames-- == 0) { + printf("Too many cnames. Loop?\n"); + exit(1); + } + strcat(cname, "."); + oldcname = cname; + hp = NULL; + h_errno = TRY_AGAIN; + continue; + } + } else { + if (getaddrinfo(addr) == 0) + hp = NULL; + else + hp = (struct hostent *)1; /* XXX */ + } + if (!waitmode) + break; + } + + if (hp == NULL) { + hperror(h_errno); + exit(1); + } + + exit(0); +} + +/* Private. */ + +static int +parsetype(const char *s) { + int type, success; + + type = sym_ston(__p_type_syms, s, &success); + if (success) + return (type); + if (strcmp(s, "*") == 0) + return (ns_t_any); + if (atoi(s)) + return (atoi(s)); + fprintf(stderr, "Invalid query type: %s\n", s); + exit(2); +} + +static int +parseclass(const char *s) { + int class, success; + + class = sym_ston(__p_class_syms, s, &success); + if (success) + return (class); + if (atoi(s)) + return (atoi(s)); + fprintf(stderr, "Invalid query class: %s\n", s); + exit(2); +} + +static void +printanswer(const struct hostent *hp) { + struct in_addr **hptr; + char **cp; + + printf("Name: %s\n", hp->h_name); + printf("Address:"); + for (hptr = (struct in_addr **)hp->h_addr_list; *hptr; hptr++) + printf(" %s", inet_ntoa(**hptr)); + printf("\nAliases:"); + for (cp = hp->h_aliases; cp && *cp && **cp; cp++) + printf(" %s", *cp); + printf("\n\n"); +} + +static void +hperror(int errnum) { + switch(errnum) { + case HOST_NOT_FOUND: + fprintf(stderr, "Host not found.\n"); + break; + case TRY_AGAIN: + fprintf(stderr, "Host not found, try again.\n"); + break; + case NO_RECOVERY: + fprintf(stderr, "No recovery, Host not found.\n"); + break; + case NO_ADDRESS: + fprintf(stderr, + "There is an entry for this host, but it doesn't have " + ); + switch (gettype) { + case ns_t_a: + fprintf(stderr, "an Internet address.\n"); + break; + case ns_t_ns: + fprintf(stderr, "a Name Server.\n"); + break; + case ns_t_md: + fprintf(stderr, "a Mail Destination.\n"); + break; + case ns_t_mf: + fprintf(stderr, "a Mail Forwarder.\n"); + break; + case ns_t_cname: + fprintf(stderr, "a Canonical Name.\n"); + break; + case ns_t_soa: + fprintf(stderr, "a Start of Authority record.\n"); + break; + case ns_t_mb: + fprintf(stderr, "a Mailbox Domain Name.\n"); + break; + case ns_t_mg: + fprintf(stderr, "a Mail Group Member.\n"); + break; + case ns_t_mr: + fprintf(stderr, "a Mail Rename Name.\n"); + break; + case ns_t_null: + fprintf(stderr, "a Null Resource record.\n"); + break; + case ns_t_wks: + fprintf(stderr, "any Well Known Service information.\n"); + break; + case ns_t_ptr: + fprintf(stderr, "a Pointer record.\n"); + break; + case ns_t_hinfo: + fprintf(stderr, "any Host Information.\n"); + break; + case ns_t_minfo: + fprintf(stderr, "any Mailbox Information.\n"); + break; + case ns_t_mx: + fprintf(stderr, "a Mail Exchanger record.\n"); + break; + case ns_t_txt: + fprintf(stderr, "a Text record.\n"); + break; + case ns_t_rp: + fprintf(stderr, "a Responsible Person.\n"); + break; + case ns_t_srv: + fprintf(stderr, "a Server Selector.\n"); + break; + case ns_t_naptr: + fprintf(stderr, "a URN Naming Authority.\n"); + break; + default: + fprintf(stderr, "the information you requested.\n"); + break; + } + break; + } +} + +static int +getaddrinfo(struct in_addr addr) { + u_int32_t ha = ntohl(addr.s_addr); + char name[NS_MAXDNAME]; + + sprintf(name, "%u.%u.%u.%u.IN-ADDR.ARPA.", + (ha) & 0xff, + (ha >> 8) & 0xff, + (ha >> 16) & 0xff, + (ha >> 24) & 0xff); + return (getinfo(name, NULL, ns_t_ptr)); +} + +static int +gethostinfo(char *name) { + char *cp, **domain; + const char *tp; + int hp, nDomain; + int asis = 0; + u_int n; + + if (strcmp(name, ".") == 0) + return (getdomaininfo(name, NULL)); + for (cp = name, n = 0; *cp; cp++) + if (*cp == '.') + n++; + if (n && cp[-1] == '.') { + if (cp[-1] == '.') + cp[-1] = 0; + hp = getdomaininfo(name, (char *)NULL); + if (cp[-1] == 0) + cp[-1] = '.'; + return (hp); + } + if (n == 0 && (tp = hostalias(name))) { + if (verbose) + printf("Aliased to \"%s\"\n", tp); + _res.options |= RES_DEFNAMES; + return (getdomaininfo(tp, (char *)NULL)); + } + if (n >= _res.ndots) { + asis = 1; + if (verbose) + printf("Trying null domain\n"); + hp = getdomaininfo(name, (char*)NULL); + if (hp) + return (hp); + } + for (domain = _res.dnsrch; *domain; domain++) { + if (verbose) + printf("Trying domain \"%s\"\n", *domain); + hp = getdomaininfo(name, *domain); + if (hp) + return (hp); + } + if (h_errno != HOST_NOT_FOUND || (_res.options & RES_DNSRCH) == 0) + return (0); + if (!asis) + return (0); + if (verbose) + printf("Trying null domain\n"); + return (getdomaininfo(name, (char *)NULL)); +} + +static int +getdomaininfo(const char *name, const char *domain) { + int val1, val2; + + if (gettype) + return (getinfo(name, domain, gettype)); + else { + val1 = getinfo(name, domain, ns_t_a); + if (cname || verbose) + return (val1); + val2 = getinfo(name, domain, ns_t_mx); + return (val1 || val2); + } +} + +static int +getinfo(const char *name, const char *domain, int type) { + HEADER *hp; + u_char *eom, *bp, *cp; + querybuf buf, answer; + int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen; + u_short pref, class; + char host[NS_MAXDNAME]; + + if (domain == NULL) + sprintf(host, "%.*s", NS_MAXDNAME, name); + else + sprintf(host, "%.*s.%.*s", + NS_MAXDNAME, name, NS_MAXDNAME, domain); + + n = res_mkquery(QUERY, host, getclass, type, NULL, 0, NULL, + buf.qb2, sizeof buf); + if (n < 0) { + if (_res.options & RES_DEBUG) + printf("res_mkquery failed\n"); + h_errno = NO_RECOVERY; + return (0); + } + n = res_send(buf.qb2, n, answer.qb2, sizeof answer); + if (n < 0) { + if (_res.options & RES_DEBUG) + printf("res_send failed\n"); + h_errno = TRY_AGAIN; + return (0); + } + eom = answer.qb2 + n; + return (printinfo(&answer, eom, ns_t_any, 0)); +} + +static int +printinfo(const querybuf *answer, const u_char *eom, int filter, int isls) { + int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen; + u_short pref, class; + const u_char *bp, *cp; + const HEADER *hp; + + /* + * Find first satisfactory answer. + */ + hp = (HEADER *) answer; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + nscount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + if (_res.options & RES_DEBUG || (verbose && isls == 0)) + printf("rcode = %d (%s), ancount=%d\n", + hp->rcode, DecodeError(hp->rcode), ancount); + if (hp->rcode != NOERROR || (ancount+nscount+arcount) == 0) { + switch (hp->rcode) { + case NXDOMAIN: + h_errno = HOST_NOT_FOUND; + return (0); + case SERVFAIL: + h_errno = TRY_AGAIN; + return (0); + case NOERROR: + h_errno = NO_DATA; + return (0); + case FORMERR: + case NOTIMP: + case REFUSED: + h_errno = NO_RECOVERY; + return (0); + } + return (0); + } + bp = hostbuf; + nmx = 0; + buflen = sizeof(hostbuf); + cp = answer->qb2 + HFIXEDSZ; + if (qdcount > 0) { + while (qdcount-- > 0) { + n = dn_skipname(cp, eom); + if (n < 0) { + printf("Form error.\n"); + return (0); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + printf("Form error.\n"); + return (0); + } + } + } + if (ancount) { + if (!hp->aa) + if (verbose && isls == 0) + printf( + "The following answer is not authoritative:\n" + ); + while (--ancount >= 0 && cp && cp < eom) { + cp = pr_rr(cp, answer->qb2, stdout, filter); + /* + * When we ask for address and there is a CNAME, it + * seems to return both the CNAME and the address. + * Since we trace down the CNAME chain ourselves, we + * don't really want to print the address at this + * point. + */ + if (cname && ! verbose) + return (1); + } + } + if (!verbose) + return (1); + if (nscount) { + printf("For authoritative answers, see:\n"); + while (--nscount >= 0 && cp && cp < eom) + cp = (u_char *)pr_rr(cp, answer->qb2, stdout, filter); + } + if (arcount) { + printf("Additional information:\n"); + while (--arcount >= 0 && cp && cp < eom) + cp = (u_char *)pr_rr(cp, answer->qb2, stdout, filter); + } + return (1); +} + +/* + * Print resource record fields in human readable form. + */ +static const u_char * +pr_rr(const u_char *cp, const u_char *msg, FILE *file, int filter) { + int type, class, dlen, n, c, proto, ttl; + struct in_addr inaddr; + u_char in6addr[NS_IN6ADDRSZ]; + const u_char *cp1; + struct protoent *protop; + struct servent *servp; + char punc = ' '; + int doprint; + char name[NS_MAXDNAME]; + char tmpbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + + if ((cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name))) == NULL) + return (NULL); /* compression error */ + + type = ns_get16(cp); + cp += INT16SZ; + + class = ns_get16(cp); + cp += INT16SZ; + + ttl = ns_get32(cp); + cp += INT32SZ; + + if (filter == type || filter == ns_t_any || + (filter == ns_t_a && (type == ns_t_ptr || type == ns_t_ns))) + doprint = 1; + else + doprint = 0; + + if (doprint) { + if (verbose) + fprintf(file, "%s\t%d%s\t%s", + name, ttl, pr_class(class), pr_type(type)); + else + fprintf(file, "%s%s %s", + name, pr_class(class), pr_type(type)); + if (verbose) + punc = '\t'; + else + punc = ' '; + } + dlen = ns_get16(cp); + cp += INT16SZ; + cp1 = cp; + + /* + * Print type specific data, if appropriate. + */ + switch (type) { + case ns_t_a: + memcpy(&inaddr, cp, NS_INADDRSZ); + if (doprint) + fprintf(file,"%c%s", punc, inet_ntoa(inaddr)); + cp += dlen; + break; + case ns_t_aaaa: + memcpy(in6addr, cp, NS_IN6ADDRSZ); + if (doprint) { + if (inet_ntop(AF_INET6, in6addr, tmpbuf, + sizeof tmpbuf) != NULL) + fprintf(file,"%c%s", punc, tmpbuf); + else + fprintf(file,"%c???", punc); + } + cp += dlen; + break; + case ns_t_cname: + if (dn_expand(msg, msg + 512, cp, cnamebuf, + sizeof(cnamebuf)) >= 0) + cname = cnamebuf; + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file,"%c%s",punc, name); + break; + + case ns_t_hinfo: + case ns_t_isdn: + { + const u_char *cp2 = cp + dlen; + n = *cp++; + if (n != 0) { + if (doprint) + fprintf(file,"%c%.*s", punc, n, cp); + cp += n; + } + if ((cp < cp2) && (n = *cp++)) { + if (doprint) + fprintf(file,"%c%.*s", punc, n, cp); + cp += n; + } else if (type == ns_t_hinfo) + if (doprint) + fprintf(file, + "\n; *** Warning *** OS-type missing" + ); + } + break; + + case ns_t_soa: + cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, "\t%s", name); + cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, " %s", name); + if (doprint) + fprintf(file, "(\n\t\t\t%ld\t;serial (version)", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%ld\t;refresh period", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, + "\n\t\t\t%ld\t;retry refresh this often", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%ld\t;expiration period", + ns_get32(cp)); + cp += INT32SZ; + if (doprint) + fprintf(file, "\n\t\t\t%ld\t;minimum TTL\n\t\t\t)", + ns_get32(cp)); + cp += INT32SZ; + break; + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + if (doprint) { + if (type == ns_t_mx && !verbose) + fprintf(file," (pri=%d) by ", ns_get16(cp)); + else if (verbose) + fprintf(file,"\t%d ", ns_get16(cp)); + else + fprintf(file," "); + } + cp += sizeof(u_short); + cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, "%s", name); + break; + + case ns_t_srv: + if (doprint) + fprintf(file," %d", ns_get16(cp)); + cp += sizeof(u_short); + if (doprint) + fprintf(file," %d", ns_get16(cp)); + cp += sizeof(u_short); + if (doprint) + fprintf(file," %d", ns_get16(cp)); + cp += sizeof(u_short); + cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file,"%s",name); + break; + + case ns_t_naptr: + /* order */ + if (doprint) + fprintf(file, " %d", ns_get16(cp)); + cp += sizeof(u_short); + /* preference */ + if (doprint) + fprintf(file, " %d", ns_get16(cp)); + cp += NS_INT16SZ; + /* Flags */ + n = *cp++; + if (doprint) { + if (n) + fprintf(file, "%c%.*s", punc, n, cp); + else + fprintf(file, "%c\"\"",punc); + } + cp += n; + /* Service */ + n = *cp++; + if (doprint) { + if (n) + fprintf(file, "%c%.*s", punc, n, cp); + else + fprintf(file,"%c\"\"",punc); + } + cp += n; + /* Regexp */ + n = *cp++; + if (doprint) { + if (n) + fprintf(file, "%c%.*s", punc, n, cp); + else + fprintf(file, "%c\"\"",punc); + } + cp += n; + /* replacement */ + cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, "%s", name); + break; + + case ns_t_minfo: + case ns_t_rp: + cp = (u_char *)pr_cdname(cp, msg, name, sizeof name); + if (doprint) { + if (type == ns_t_rp) { + char *p; + + p = strchr(name, '.'); + if (p != NULL) + *p = '@'; + } + fprintf(file, "%c%s", punc, name); + } + cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name)); + if (doprint) + fprintf(file, " %s", name); + break; + + case ns_t_x25: + n = *cp++; + if (n != 0) { + if (doprint) + fprintf(file, "%c%.*s", punc, n, cp); + cp += n; + } + break; + + case ns_t_txt: + { + int n, j; + const u_char *end = cp + dlen; + + while (cp < end) { + if (doprint) + (void) fputs(" \"", file); + n = *cp++; + if (n != 0) + for (j = n; j > 0 && cp < end ; j --) { + if (doprint) { + if (*cp == '\n' || + *cp == '"' || + *cp == '\\') + putc('\\', + file); + putc(*cp, file); + } + cp++; + } + if (doprint) + putc('"', file); + } + } + break; + + case ns_t_wks: + if (dlen < INT32SZ + 1) + break; + memcpy(&inaddr, cp, INADDRSZ); + cp += INT32SZ; + proto = *cp++; + protop = getprotobynumber(proto); + if (doprint) { + if (protop) + fprintf(file, "%c%s %s", punc, + inet_ntoa(inaddr), protop->p_name); + else + fprintf(file, "%c%s %d", punc, + inet_ntoa(inaddr), proto); + } + n = 0; + while (cp < cp1 + dlen) { + c = *cp++; + do { + if (c & 0200) { + servp = NULL; + if (protop) + servp = getservbyport(htons(n), + protop-> + p_name); + if (doprint) { + if (servp) + fprintf(file, " %s", + servp->s_name); + else + fprintf(file, " %d", + n); + } + } + c <<= 1; + } while (++n & 07); + } + break; + + default: + if (doprint) + fprintf(file, "%c???", punc); + cp += dlen; + break; + } + if (cp != cp1 + dlen) + fprintf(file, "packet size error (%p != %p)\n", + cp, cp1 + dlen); + if (doprint) + fprintf(file, "\n"); + return (cp); +} + +/* + * Return a string for the type. A few get special treatment when + * not in verbose mode, to make the program more chatty and easier to + * understand. + */ +static const char * +pr_type(int type) { + if (!verbose) switch (type) { + case ns_t_a: + return ("has address"); + case ns_t_cname: + return ("is a nickname for"); + case ns_t_mx: + return ("mail is handled"); + case ns_t_txt: + return ("descriptive text"); + case ns_t_afsdb: + return ("DCE or AFS service from"); + } + if (verbose) + return (sym_ntos(__p_type_syms, type, NULL)); + else + return (sym_ntop(__p_type_syms, type, NULL)); +} + +/* + * Return a mnemonic for class + */ +static const char * +pr_class(int class) { + static char spacestr[20]; + + if (!verbose) switch (class) { + case ns_c_in: /* internet class */ + return (""); + case ns_c_hs: /* hesiod class */ + return (""); + } + + spacestr[0] = ' '; + strcpy(&spacestr[1], p_class(class)); + return (spacestr); +} + +static const u_char * +pr_cdname(const u_char *cp, const u_char *msg, char *name, int namelen) { + int n = dn_expand(msg, msg + 512, cp, name, namelen - 2); + + if (n < 0) + return (NULL); + if (name[0] == '\0') { + name[0] = '.'; + name[1] = '\0'; + } + return (cp + n); +} + +static int +ListHosts(char *namePtr, int queryType) { + querybuf buf, answer; + struct sockaddr_in sin; + const HEADER *headerPtr; + const struct hostent *hp; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error = NO_ERRORS; + + int msglen, amtToRead, numRead, i, len, dlen, type, nscount, n; + int numAnswers = 0, soacnt = 0, result = 0; + u_char tmp[NS_INT16SZ]; + char name[NS_MAXDNAME], dname[2][NS_MAXDNAME], domain[NS_MAXDNAME]; + u_char *cp, *nmp, *eom; + + /* Names and addresses of name servers to try. */ + char nsname[NUMNS][NS_MAXDNAME]; + int nshaveaddr[NUMNS]; + struct in_addr nsipaddr[NUMNSADDR]; + int numns, numnsaddr, thisns; + + /* + * Normalize to not have trailing dot. We do string compares below + * of info from name server, and it won't have trailing dots. + */ + i = strlen(namePtr); + if (namePtr[i-1] == '.') + namePtr[i-1] = 0; + + if (server_specified) { + memcpy(&nsipaddr[0], &_res.nsaddr.sin_addr, NS_INADDRSZ); + numnsaddr = 1; + } else { + /* + * First we have to find out where to look. This needs a NS + * query, possibly followed by looking up addresses for some + * of the names. + */ + msglen = res_mkquery(ns_o_query, namePtr, ns_c_in, ns_t_ns, + NULL, 0, NULL, buf.qb2, sizeof buf); + if (msglen < 0) { + printf("res_mkquery failed\n"); + return (ERROR); + } + + msglen = res_send(buf.qb2, msglen, answer.qb2, sizeof answer); + if (msglen < 0) { + printf("Cannot find nameserver -- try again later\n"); + return (ERROR); + } + if (_res.options & RES_DEBUG || verbose) + printf("rcode = %d (%s), ancount=%d\n", + answer.qb1.rcode, DecodeError(answer.qb1.rcode), + ntohs(answer.qb1.ancount)); + + /* + * Analyze response to our NS lookup. + */ + + nscount = ntohs(answer.qb1.ancount) + + ntohs(answer.qb1.nscount) + + ntohs(answer.qb1.arcount); + + if (answer.qb1.rcode != NOERROR || nscount == 0) { + switch (answer.qb1.rcode) { + case NXDOMAIN: + /* Check if it's an authoritive answer */ + if (answer.qb1.aa) + printf("No such domain\n"); + else + printf("Unable to get information about domain -- try again later.\n"); + break; + case SERVFAIL: + printf("Unable to get information about that domain -- try again later.\n"); + break; + case NOERROR: + printf("That domain exists, but seems to be a leaf node.\n"); + break; + case FORMERR: + case NOTIMP: + case REFUSED: + printf("Unrecoverable error looking up domain name.\n"); + break; + } + return (0); + } + + cp = answer.qb2 + HFIXEDSZ; + eom = answer.qb2 + msglen; + if (ntohs(answer.qb1.qdcount) > 0) { + n = dn_skipname(cp, eom); + if (n < 0) { + printf("Form error.\n"); + return (ERROR); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + printf("Form error.\n"); + return (ERROR); + } + } + + numns = 0; + numnsaddr = 0; + + /* + * Look at response from NS lookup for NS and A records. + */ + + for ((void)NULL; nscount; nscount--) { + cp += dn_expand(answer.qb2, answer.qb2 + msglen, cp, + domain, sizeof(domain)); + if (cp + 3 * INT16SZ + INT32SZ > eom) { + printf("Form error.\n"); + return (ERROR); + } + type = ns_get16(cp); + cp += INT16SZ + INT16SZ + INT32SZ; + dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + dlen > eom) { + printf("Form error.\n"); + return (ERROR); + } + if (type == ns_t_ns) { + if (dn_expand(answer.qb2, eom, + cp, name, sizeof(name)) >= 0) { + if (numns < NUMNS && + strcasecmp((char *)domain, + namePtr) == 0) { + for (i = 0; i < numns; i++) + if (strcasecmp( + nsname[i], + (char *)name + ) == 0) + /* duplicate */ + break; + if (i >= numns) { + strncpy(nsname[numns], + (char *)name, + sizeof(name)); + nshaveaddr[numns] = 0; + numns++; + } + } + } + } else if (type == ns_t_a) { + if (numnsaddr < NUMNSADDR) + for (i = 0; i < numns; i++) { + if (strcasecmp(nsname[i], + (char *)domain) + == 0) { + nshaveaddr[i]++; + memcpy( + &nsipaddr[numnsaddr], + cp, NS_INADDRSZ); + numnsaddr++; + break; + } + } + } + cp += dlen; + } + + /* + * Usually we'll get addresses for all the servers in the + * additional info section. But in case we don't, look up + * their addresses. + */ + + for (i = 0; i < numns; i++) { + if (nshaveaddr[i] == 0) { + struct in_addr **hptr; + int numaddrs = 0; + + hp = gethostbyname(nsname[i]); + if (hp) { + for (hptr = (struct in_addr **) + hp->h_addr_list; + *hptr != NULL; + hptr++) + if (numnsaddr < NUMNSADDR) { + memcpy( + &nsipaddr[numnsaddr], + *hptr, NS_INADDRSZ); + numnsaddr++; + numaddrs++; + } + } + if (_res.options & RES_DEBUG || verbose) + printf( + "Found %d addresses for %s by extra query\n", + numaddrs, nsname[i]); + } else if (_res.options & RES_DEBUG || verbose) + printf("Found %d addresses for %s\n", + nshaveaddr[i], nsname[i]); + } + } + /* + * Now nsipaddr has numnsaddr addresses for name servers that + * serve the requested domain. Now try to find one that will + * accept a zone transfer. + */ + thisns = 0; + + again: + numAnswers = 0; + soacnt = 0; + + /* + * Create a query packet for the requested domain name. + */ + msglen = res_mkquery(QUERY, namePtr, getclass, ns_t_axfr, NULL, + 0, NULL, buf.qb2, sizeof buf); + if (msglen < 0) { + if (_res.options & RES_DEBUG) + fprintf(stderr, "ListHosts: Res_mkquery failed\n"); + return (ERROR); + } + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(NAMESERVER_PORT); + + /* + * Set up a virtual circuit to the server. + */ + + for ((void)NULL; thisns < numnsaddr; thisns++) { + if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("ListHosts"); + return (ERROR); + } + memcpy(&sin.sin_addr, &nsipaddr[thisns], NS_INADDRSZ); + if (_res.options & RES_DEBUG || verbose) + printf("Trying %s\n", inet_ntoa(sin.sin_addr)); + if (connect(sockFD, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + break; + if (verbose) + perror("Connection failed, trying next server"); + close(sockFD); + sockFD = -1; + } + if (thisns >= numnsaddr) { + printf("No server for that domain responded\n"); + if (!verbose) + perror("Error from the last server was"); + return (ERROR); + } + + /* + * Send length & message for zone transfer + */ + + ns_put16(msglen, tmp); + if (write(sockFD, (char *)tmp, INT16SZ) != INT16SZ || + write(sockFD, (char *)buf.qb2, msglen) != msglen) { + perror("ListHosts"); + (void) close(sockFD); + sockFD = -1; + return (ERROR); + } + + filePtr = stdout; + + for (;;) { + /* + * Read the length of the response. + */ + cp = buf.qb2; + amtToRead = INT16SZ; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_LEN; + break; + } + + if ((len = ns_get16(buf.qb2)) == 0) + break; /* Protocol violation. */ + + /* + * Read the response. + */ + + amtToRead = len; + cp = buf.qb2; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_MSG; + break; + } + + i = buf.qb1.rcode; + if (i != NOERROR || ntohs(buf.qb1.ancount) == 0) { + if (thisns + 1 < numnsaddr && + (i == SERVFAIL || i == NOTIMP || i == REFUSED)) { + if (_res.options & RES_DEBUG || verbose) + printf( + "Server failed, trying next server: %s\n", + i != NOERROR + ? DecodeError(i) + : "Premature end of data"); + (void) close(sockFD); + sockFD = -1; + thisns++; + goto again; + } + printf("Server failed: %s\n", i != NOERROR + ? DecodeError(i) : "Premature end of data"); + break; + } + + result = printinfo(&buf, cp, queryType, 1); + if (! result) { + error = ERR_PRINTING; + break; + } + numAnswers++; + cp = buf.qb2 + HFIXEDSZ; + if (ntohs(buf.qb1.qdcount) > 0) { + n = dn_skipname(cp, buf.qb2 + len); + if (n < 0) { + error = ERR_PRINTING; + break; + } + cp += n + QFIXEDSZ; + } + nmp = cp; + n = dn_skipname(cp, buf.qb2 + len); + if (n < 0) { + error = ERR_PRINTING; + break; + } + cp += n; + if (cp + INT16SZ > buf.qb2 + len) { + error = ERR_PRINTING; + break; + } + if ((ns_get16(cp) == ns_t_soa)) { + (void) dn_expand(buf.qb2, buf.qb2 + len, nmp, + dname[soacnt], sizeof dname[0]); + if (soacnt) { + if (strcmp(dname[0], dname[1]) == 0) + break; + } else + soacnt++; + } + } + + (void) close(sockFD); + sockFD = -1; + + switch (error) { + case NO_ERRORS: + return (SUCCESS); + + case ERR_READING_LEN: + return (ERROR); + + case ERR_PRINTING: + fprintf(stderr,"*** Error during listing of %s: %s\n", + namePtr, DecodeError(result)); + return (result); + + case ERR_READING_MSG: + headerPtr = (HEADER *) &buf; + fprintf(stderr,"ListHosts: error receiving zone transfer:\n"); + fprintf(stderr, + " result: %s, answers = %d, authority = %d, additional = %d\n", + _res_resultcodes[headerPtr->rcode], + ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), + ntohs(headerPtr->arcount)); + return (ERROR); + default: + return (ERROR); + } +} + +static const char * +DecodeError(int result) { + switch(result) { + case NOERROR: return ("Success"); break; + case FORMERR: return ("Format error"); break; + case SERVFAIL: return ("Server failed"); break; + case NXDOMAIN: return ("Non-existent domain"); break; + case NOTIMP: return ("Not implemented"); break; + case REFUSED: return ("Query refused"); break; + case NO_INFO: return ("No information"); break; + case ERROR: return ("Unspecified error"); break; + case TIME_OUT: return ("Timed out"); break; + case NONAUTH: return ("Non-authoritative answer"); break; + default: return ("BAD ERROR VALUE"); + } + /* NOTREACHED */ +} diff --git a/contrib/bind/bin/named-xfer/Makefile b/contrib/bind/bin/named-xfer/Makefile new file mode 100644 index 0000000..9243c0f --- /dev/null +++ b/contrib/bind/bin/named-xfer/Makefile @@ -0,0 +1,88 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.20 1997/06/19 03:22:09 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cruv +INSTALL= install +STRIP=-s + +PS=ps +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +NAMED_OBJS= \ + ../named/db_glue.${O} ../named/ns_glue.${O} ../named/tmp_version.${O} + +PROG= named-xfer +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${NAMED_OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} ${NAMED_OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + +clean: FRC + rm -f ${PROG} core .depend + rm -f *.BAK *.CKP *~ *.${O} *.orig + +depend: ${SRCS} + mkdep -p ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTEXEC}: + mkdir -p ${DESTDIR}${DESTEXEC} + +install: ${DESTDIR}${DESTSBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTEXEC}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags ${SRCS} *.h + +commands.c: commands.l + ${LEX} -t $< > $@ || rm $@ + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/named-xfer/named-xfer.c b/contrib/bind/bin/named-xfer/named-xfer.c new file mode 100644 index 0000000..292714e --- /dev/null +++ b/contrib/bind/bin/named-xfer/named-xfer.c @@ -0,0 +1,2177 @@ +/* + * The original version of xfer by Kevin Dunlap. + * Completed and integrated with named by David Waitzman + * (dwaitzman@bbn.com) 3/14/88. + * Modified by M. Karels and O. Kure 10-88. + * Modified extensively since then by just about everybody. + */ + +/* + * Copyright (c) 1988, 1990 + * 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, 1997 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. + */ + +#if !defined(lint) && !defined(SABER) +char copyright[] = +"@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\ + portions Copyright (c) 1993 Digital Equipment Corporation\n\ + portions Copyright (c) 1995, 1996 Internet Software Consorium\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91"; +static char rcsid[] = "$Id: named-xfer.c,v 8.38 1998/03/27 00:19:28 halley Exp $"; +#endif /* not lint */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <limits.h> +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <resolv.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include <stdarg.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#define MAIN_PROGRAM +#include "../named/named.h" +#undef MAIN_PROGRAM + +#define MAX_XFER_RESTARTS 2 + +# ifdef SHORT_FNAMES +extern long pathconf __P((const char *path, int name)); /* XXX */ +# endif + +static struct zoneinfo zone; /* zone information */ + +static char ddtfilename[] = _PATH_TMPXFER, + *ddtfile = ddtfilename, + *tmpname, + *domain; /* domain being xfered */ + +static int quiet = 0, + read_interrupted = 0, + curclass, + domain_len; /* strlen(domain) */ + +static FILE *fp = NULL, + *dbfp = NULL; + +static char *ProgName; + +static void usage(const char *); +static int getzone(struct zoneinfo *, u_int32_t, int), + print_output(struct zoneinfo *, u_int32_t, + u_char *, int, u_char *), + netread(int, char *, int, int), + writemsg(int, const u_char *, int); +static SIG_FN read_alarm(void); +static SIG_FN term_handler(void); +static const char *soa_zinfo(struct zoneinfo *, u_char *, u_char*); + +struct zoneinfo zp_start, zp_finish; + +static int restarts = 0; + +FILE *ddt = NULL; + +/* + * Debugging printf. + */ +#ifdef DEBUG +void +dprintf(int level, const char *format, ...) { + va_list ap; + + va_start(ap, format); + if (ddt != NULL && debug >= level) + (void) vfprintf(ddt, format, ap); + va_end(ap); +} +#endif /*DEBUG*/ + +static +int init_xfer_logging() { + log_channel chan; + + if (log_new_context(ns_log_max_category, NULL, &log_ctx) < 0) { + perror("log_new_context"); + return (0); + } + log_option(log_ctx, LOG_OPTION_DEBUG, debug); + log_option(log_ctx, LOG_OPTION_LEVEL, debug); + + log_ctx_valid = 1; + + chan = log_new_syslog_channel(0, 0, LOG_DAEMON); + if (chan == NULL) + return (0); + if (log_add_channel(log_ctx, ns_log_default, chan) < 0) { + perror("log_add_channel syslog"); + return (0); + } + + if (debug) { + unsigned int flags = LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; + + chan = log_new_file_channel(flags, 0, NULL, ddt, 0, ULONG_MAX); + if (chan == NULL) + return (0); + if (log_add_channel(log_ctx, ns_log_default, chan) < 0) { + perror("log_add_channel debug"); + return (0); + } + } + + return (1); +} + +void cleanup_for_exit(void) { +#ifdef DEBUG + if (!debug) +#endif + (void) unlink(tmpname); +} + + +int +main(int argc, char *argv[]) { + struct zoneinfo *zp; + struct hostent *hp; + struct in_addr axfr_src; + char *dbfile = NULL, *tracefile = NULL, *tm = NULL; + int dbfd, ddtd, result, c, fd, closed = 0; + u_int32_t serial_no = 0; + u_int port = htons(NAMESERVER_PORT); + struct stat statbuf; +#ifdef STUBS + int stub_only = 0; +#endif + int class = C_IN; + int n; + long num_files; + + ProgName = strrchr(argv[0], '/'); + if (ProgName != NULL) + ProgName++; + else + ProgName = argv[0]; + + (void) umask(022); + + /* this is a hack; closing everything in the parent is hard. */ + num_files = MIN(sysconf(_SC_OPEN_MAX), FD_SETSIZE); + for (fd = num_files - 1; fd > STDERR_FILENO; fd--) + closed += (close(fd) == 0); + +#ifdef RENICE + nice(-40); /* this is the recommended procedure to */ + nice(20); /* reset the priority of the current process */ + nice(0); /* to "normal" (== 0) - see nice(3) */ +#endif + +#ifdef LOG_PERROR + n = LOG_PERROR; +#else + n = 0; +#endif +#ifdef SYSLOG_42BSD + openlog(ProgName, LOG_PID); +#else + openlog(ProgName, LOG_PID|LOG_CONS|n, LOG_DAEMON); +#endif + axfr_src.s_addr = 0; +#ifdef STUBS + while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qx:S")) != EOF) +#else + while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qx:")) != EOF) +#endif + switch (c) { + case 'C': + class = get_class(optarg); + break; + case 'd': +#ifdef DEBUG + debug = atoi(optarg); +#endif + break; + case 'l': + ddtfile = (char *)malloc(strlen(optarg) + + sizeof(".XXXXXX") + 1); + if (!ddtfile) + panic("malloc(ddtfile)", NULL); +#ifdef SHORT_FNAMES + filenamecpy(ddtfile, optarg); +#else + (void) strcpy(ddtfile, optarg); +#endif /* SHORT_FNAMES */ + (void) strcat(ddtfile, ".XXXXXX"); + break; + case 's': + serial_no = strtoul(optarg, (char **)NULL, 10); + break; + case 't': + tracefile = optarg; + break; + case 'z': /* zone == domain */ + domain = optarg; + domain_len = strlen(domain); + while ((domain_len > 0) && + (domain[domain_len-1] == '.')) + domain[--domain_len] = '\0'; + break; + case 'f': + dbfile = optarg; + tmpname = (char *)malloc((unsigned)strlen(optarg) + + sizeof(".XXXXXX") + 1); + if (!tmpname) + panic("malloc(tmpname)", NULL); +#ifdef SHORT_FNAMES + filenamecpy(tmpname, optarg); +#else + (void) strcpy(tmpname, optarg); +#endif /* SHORT_FNAMES */ + break; + case 'p': + port = htons((u_int16_t)atoi(optarg)); + break; + case 'P': + port = (u_int16_t)atoi(optarg); + break; +#ifdef STUBS + case 'S': + stub_only = 1; + break; +#endif + case 'q': + quiet++; + break; + case 'x': + if (!inet_aton(optarg, &axfr_src)) + panic("bad -x addr: %s", optarg); + break; + case '?': + default: + usage("unrecognized argument"); + /* NOTREACHED */ + } + + if (!domain || !dbfile || optind >= argc) { + if (!domain) + usage("no domain"); + if (!dbfile) + usage("no dbfile"); + if (optind >= argc) + usage("not enough arguments"); + /* NOTREACHED */ + } + if (stat(dbfile, &statbuf) != -1 && + !S_ISREG(statbuf.st_mode) && + !S_ISFIFO(statbuf.st_mode)) + usage("dbfile must be a regular file or FIFO"); + if (tracefile && (fp = fopen(tracefile, "w")) == NULL) + perror(tracefile); + (void) strcat(tmpname, ".XXXXXX"); + /* tmpname is now something like "/etc/named/named.bu.db.XXXXXX" */ + if ((dbfd = mkstemp(tmpname)) == -1) { + perror(tmpname); + if (!quiet) + syslog(LOG_ERR, "can't make tmpfile (%s): %m\n", + tmpname); + exit(XFER_FAIL); + } +#ifdef HAVE_FCHMOD /* XXX */ + if (fchmod(dbfd, 0644) == -1) +#else + if (chmod(tmpname, 0644) == -1) +#endif + { + perror(tmpname); + if (!quiet) + syslog(LOG_ERR, "can't [f]chmod tmpfile (%s): %m\n", + tmpname); + exit(XFER_FAIL); + } + if ((dbfp = fdopen(dbfd, "r+")) == NULL) { + perror(tmpname); + if (!quiet) + syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname); + exit(XFER_FAIL); + } +#ifdef DEBUG + if (debug) { + /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */ + if ((ddtd = mkstemp(ddtfile)) == -1) { + perror(ddtfile); + debug = 0; + } +#ifdef HAVE_FCHMOD + else if (fchmod(ddtd, 0644) == -1) +#else + else if (chmod(ddtfile, 0644) == -1) +#endif + { + perror(ddtfile); + debug = 0; + } else if ((ddt = fdopen(ddtd, "w")) == NULL) { + perror(ddtfile); + debug = 0; + } else + setvbuf(ddt, NULL, _IOLBF, 0); + } +#endif + + if (!init_xfer_logging()) { + perror("init_xfer_logging"); + } + + /* + * Ignore many types of signals that named (assumed to be our parent) + * considers important- if not, the user controlling named with + * signals usually kills us. + */ + (void) signal(SIGHUP, SIG_IGN); +#ifdef SIGSYS + (void) signal(SIGSYS, SIG_IGN); +#endif +#ifdef DEBUG + if (debug == 0) +#endif + { + (void) signal(SIGINT, SIG_IGN); + (void) signal(SIGQUIT, SIG_IGN); + } + (void) signal(SIGILL, SIG_IGN); + +#if defined(SIGUSR1) && defined(SIGUSR2) + (void) signal(SIGUSR1, SIG_IGN); + (void) signal(SIGUSR2, SIG_IGN); +#else /* SIGUSR1&&SIGUSR2 */ + (void) signal(SIGEMT, SIG_IGN); + (void) signal(SIGFPE, SIG_IGN); +#endif /* SIGUSR1&&SIGUSR2 */ + + dprintf(1, "domain `%s'; file `%s'; serial %u; closed %d\n", + domain, dbfile, serial_no, closed); + + buildservicelist(); + buildprotolist(); + + /* init zone data */ + + zp = &zone; +#ifdef STUBS + if (stub_only) + zp->z_type = Z_STUB; + else +#endif + zp->z_type = Z_SECONDARY; + zp->z_class = class; + zp->z_origin = domain; + zp->z_source = dbfile; + zp->z_axfr_src = axfr_src; + zp->z_addrcnt = 0; + dprintf(1, "zone found (%d): \"%s\", source = %s\n", + zp->z_type, + (zp->z_origin[0] == '\0') ? "." : zp->z_origin, + zp->z_source); + + for (; optind != argc; optind++) { + tm = argv[optind]; + if (!inet_aton(tm, &zp->z_addr[zp->z_addrcnt])) { + hp = gethostbyname(tm); + if (hp == NULL) { + syslog(LOG_NOTICE, + "uninterpretable server (%s) for %s\n", + tm, zp->z_origin); + continue; + } + memcpy(&zp->z_addr[zp->z_addrcnt], + hp->h_addr, + INADDRSZ); + dprintf(1, "Arg: \"%s\"\n", tm); + } + if (++zp->z_addrcnt >= NSMAX) { + zp->z_addrcnt = NSMAX; + dprintf(1, "NSMAX reached\n"); + break; + } + } + dprintf(1, "addrcnt = %d\n", zp->z_addrcnt); + + res_init(); + _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); + result = getzone(zp, serial_no, port); + (void) my_fclose(dbfp); + switch (result) { + + case XFER_SUCCESS: /* ok exit */ + if (rename(tmpname, dbfile) == -1) { + perror("rename"); + if (!quiet) + syslog(LOG_ERR, "rename %s to %s: %m", + tmpname, dbfile); + exit(XFER_FAIL); + } + exit(XFER_SUCCESS); + + case XFER_UPTODATE: /* the zone was already uptodate */ + (void) unlink(tmpname); + exit(XFER_UPTODATE); + + default: + result = XFER_FAIL; + /* fall through */ + case XFER_TIMEOUT: + case XFER_FAIL: + cleanup_for_exit(); + exit(result); /* error or timeout */ + } + /*NOTREACHED*/ + return (0); /* Make gcc happy. */ +} + +static char *UsageText[] = { + "\t-z zone_to_transfer\n", + "\t-f db_file\n", + "\t-s serial_no\n", + "\t[-d debug_level]\n", + "\t[-l debug_log_file]\n", + "\t[-t trace_file]\n", + "\t[-p port]\n", +#ifdef STUBS + "\t[-S]\n", +#endif + "\t[-C class]\n", + "\t[-x axfr-src]\n", + "\tservers...\n", + NULL +}; + +static void +usage(const char *msg) { + char * const *line; + + fprintf(stderr, "Usage error: %s\n", msg); + fprintf(stderr, "Usage: %s\n", ProgName); + for (line = UsageText; *line; line++) + fputs(*line, stderr); + exit(XFER_FAIL); +} + +#define DEF_DNAME '\001' /* '\0' means the root domain */ +/* XXX: The following variables should probably all be "static" */ +u_int32_t minimum_ttl = 0; +int soa_cnt = 0; +#ifdef STUBS +int ns_cnt = 0; +#endif +int query_type = 0; +int prev_comment = 0; /* was previous record a comment? */ +char zone_top[MAXDNAME]; /* the top of the zone */ +char prev_origin[MAXDNAME]; /* from most recent $ORIGIN line */ +char prev_dname[MAXDNAME] = { DEF_DNAME }; /* from previous record */ +char prev_ns_dname[MAXDNAME] = { DEF_DNAME }; /* from most recent NS record */ + +static int +getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { + HEADER *hp; + u_int len; + u_int32_t serial; + int s, n, l, error = 0; + u_int cnt; + u_char *cp, *nmp, *eom, *tmp ; + u_char *buf = NULL; + u_int bufsize = 0; + char name[MAXDNAME], name2[MAXDNAME]; + struct sockaddr_in sin; +#ifdef POSIX_SIGNALS + struct sigaction sv, osv; +#else + struct sigvec sv, osv; +#endif + int qdcount, ancount, aucount, class, type; + const char *badsoa_msg = "Nil"; + +#ifdef DEBUG + if (debug) { + (void)fprintf(ddt,"getzone() %s ", zp->z_origin); + switch (zp->z_type) { + case Z_STUB: + fprintf(ddt,"stub\n"); + break; + case Z_SECONDARY: + fprintf(ddt,"secondary\n"); + break; + default: + fprintf(ddt,"unknown type\n"); + } + } +#endif +#ifdef POSIX_SIGNALS + memset(&sv, 0, sizeof sv); + sv.sa_handler = (SIG_FN (*)()) read_alarm; + /* SA_ONSTACK isn't recommended for strict POSIX code */ + /* is it absolutely necessary? */ + /* sv.sa_flags = SA_ONSTACK; */ + sigfillset(&sv.sa_mask); + (void) sigaction(SIGALRM, &sv, &osv); + memset(&sv, 0, sizeof sv); + sv.sa_handler = (SIG_FN (*)()) term_handler; + sigfillset(&sv.sa_mask); + (void) sigaction(SIGTERM, &sv, &osv); +#else + memset(&sv, 0, sizeof sv); + sv.sv_handler = read_alarm; + sv.sv_mask = ~0; + (void) sigvec(SIGALRM, &sv, &osv); + memset(&sv, 0, sizeof sv); + sv.sv_handler = term_handler; + sv.sv_mask = ~0; + (void) sigvec(SIGTERM, &sv, &osv); +#endif + + strcpy(zone_top, zp->z_origin); + if ((l = strlen(zone_top)) != 0 && zone_top[l - 1] == '.') + zone_top[l - 1] = '\0'; + strcpy(prev_origin, zone_top); + + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { + curclass = zp->z_class; + error = 0; + if (buf == NULL) { + if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) { + syslog(LOG_INFO, "malloc(%u) failed", + 2 * PACKETSZ); + error++; + break; + } + bufsize = 2 * PACKETSZ; + } + if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { + syslog(LOG_INFO, "socket: %m"); + error++; + break; + } + if (zp->z_axfr_src.s_addr != 0) { + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = 0; /* "ANY" */ + sin.sin_addr = zp->z_axfr_src; + dprintf(2, "binding to address [%s]\n", + inet_ntoa(sin.sin_addr)); + if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) + syslog(LOG_INFO, "warning: bind(%s) failed", + inet_ntoa(zp->z_axfr_src)); + } + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = port; + sin.sin_addr = zp->z_addr[cnt]; + dprintf(2, "connecting to server #%d [%s].%d\n", + cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + if (!quiet) + syslog(LOG_INFO, + "connect(%s) for zone %s failed: %m", + inet_ntoa(sin.sin_addr), zp->z_origin); + error++; + (void) my_close(s); + continue; + } + n = res_mkquery(QUERY, zp->z_origin, curclass, + T_SOA, NULL, 0, NULL, buf, bufsize); + if (n < 0) { + if (!quiet) + syslog(LOG_INFO, + "zone %s: res_mkquery T_SOA failed", + zp->z_origin); + (void) my_close(s); +#ifdef POSIX_SIGNALS + (void) sigaction(SIGALRM, &osv, (struct sigaction *)0); +#else + (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); +#endif + return (XFER_FAIL); + } + /* + * Send length & message for SOA query + */ + if (writemsg(s, buf, n) < 0) { + syslog(LOG_INFO, "writemsg: %m"); + error++; + (void) my_close(s); + continue; + } + /* + * Get out your butterfly net and catch the SOA + */ + if (netread(s, (char *)buf, INT16SZ, XFER_TIMER) < 0) { + error++; + (void) my_close(s); + continue; + } + if ((len = ns_get16(buf)) == 0) { + (void) my_close(s); + continue; + } + if (len > bufsize) { + if ((buf = (u_char *)realloc(buf, len)) == NULL) { + syslog(LOG_INFO, + "malloc(%u) failed for SOA from server [%s], zone %s\n", + len, + inet_ntoa(sin.sin_addr), + zp->z_origin); + (void) my_close(s); + continue; + } + bufsize = len; + } + if (netread(s, (char *)buf, len, XFER_TIMER) < 0) { + error++; + (void) my_close(s); + continue; + } +#ifdef DEBUG + if (debug >= 3) { + (void)fprintf(ddt,"len = %d\n", len); + fp_nquery(buf, len, ddt); + } +#endif + hp = (HEADER *) buf; + qdcount = ntohs(hp->qdcount); + ancount = ntohs(hp->ancount); + aucount = ntohs(hp->nscount); + + /* + * close socket if any of these apply: + * 1) rcode != NOERROR + * 2) not an authority response + * 3) not an answer to our question + * 4) both the number of answers and authority count < 1) + */ + if (hp->rcode != NOERROR || !hp->aa || qdcount != 1 || + (ancount < 1 && aucount < 1)) { +#ifndef ultrix /*XXX*/ + syslog(LOG_NOTICE, + "[%s] %s for %s, SOA query got rcode %d, aa %d, ancount %d, aucount %d", + inet_ntoa(sin.sin_addr), + (hp->aa + ? (qdcount==1 ?"no SOA found" :"bad response") + : "not authoritative"), + zp->z_origin[0] != '\0' ? zp->z_origin : ".", + hp->rcode, hp->aa, ancount, aucount); +#endif + error++; + (void) my_close(s); + continue; + } + zp_start = *zp; + if ((int)len < HFIXEDSZ + QFIXEDSZ) { + badsoa_msg = "too short"; + badsoa: + syslog(LOG_INFO, + "malformed SOA from [%s], zone %s: %s", + inet_ntoa(sin.sin_addr), zp->z_origin, + badsoa_msg); + error++; + (void) my_close(s); + continue; + } + /* + * Step through response. + */ + tmp = buf + HFIXEDSZ; + eom = buf + len; + /* Query Section. */ + n = dn_expand(buf, eom, tmp, name2, sizeof name2); + if (n < 0) { + badsoa_msg = "qname error"; + goto badsoa; + } + tmp += n; + if (tmp + 2 * INT16SZ > eom) { + badsoa_msg = "query error"; + goto badsoa; + } + NS_GET16(type, tmp); + NS_GET16(class, tmp); + if (class != curclass || type != T_SOA || + strcasecmp(zp->z_origin, name2) != 0) { + syslog(LOG_INFO, + "wrong query in resp from [%s], zone %s: [%s %s %s]\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + name2, p_class(class), p_type(type)); + error++; + (void) my_close(s); + continue; + } + /* ... Answer Section. + * We may have to loop a little, to bypass SIG SOA's in + * the response. + */ + do { + u_char *cp4; + u_short type, class, dlen; + u_int32_t ttl; + + n = dn_expand(buf, eom, tmp, name2, sizeof name2); + if (n < 0) { + badsoa_msg = "aname error"; + goto badsoa; + } + tmp += n; + + /* Are type, class, and ttl OK? */ + cp4 = tmp; /* Leave tmp pointing to type field */ + if (eom - cp4 < 3 * INT16SZ + INT32SZ) { + badsoa_msg = "zinfo too short"; + goto badsoa; + } + NS_GET16(type, cp4); + NS_GET16(class, cp4); + NS_GET32(ttl, cp4); + NS_GET16(dlen, cp4); + if (cp4 + dlen > eom) { + badsoa_msg = "zinfo dlen too big"; + goto badsoa; + } + if (type == T_SOA) + break; + /* Skip to next record, if any. */ + dprintf(1, "skipping %s %s RR in response\n", + name2, p_type(type)); + tmp = cp4 + dlen; + } while (1); + + if (strcasecmp(zp->z_origin, name2) != 0) { + syslog(LOG_INFO, + "wrong answer in resp from [%s], zone %s: [%s %s %s]\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + name2, p_class(class), p_type(type)); + error++; + (void) my_close(s); + continue; + } + badsoa_msg = soa_zinfo(&zp_start, tmp, eom); + if (badsoa_msg) + goto badsoa; + if (SEQ_GT(zp_start.z_serial, serial_no) || !serial_no) { + const char *l, *nl; + dprintf(1, "need update, serial %u\n", + zp_start.z_serial); + hp = (HEADER *) buf; + soa_cnt = 0; +#ifdef STUBS + ns_cnt = 0; +#endif + gettime(&tt); + for (l = Version; l; l = nl) { + size_t len; + if ((nl = strchr(l, '\n')) != NULL) { + len = nl - l; + nl = nl + 1; + } else { + len = strlen(l); + nl = NULL; + } + while (isspace((unsigned char) *l)) + l++; + if (*l) + fprintf(dbfp, "; BIND version %.*s\n", + (int)len, l); + } + fprintf(dbfp, "; zone '%s' last serial %u\n", + domain, serial_no); + fprintf(dbfp, "; from %s at %s", + inet_ntoa(sin.sin_addr), + ctimel(tt.tv_sec)); + for (;;) { + if ((soa_cnt == 0) || (zp->z_type == Z_STUB)) { +#ifdef STUBS + if (zp->z_type == Z_STUB) { + if (soa_cnt == 1 && + ns_cnt == 0) + query_type = T_NS; + else + query_type = T_SOA; + } else +#endif + query_type = T_AXFR; + n = res_mkquery(QUERY, zp->z_origin, + curclass, query_type, + NULL, 0, + NULL, buf, bufsize); + if (n < 0) { + if (!quiet) { +#ifdef STUBS + if (zp->z_type == Z_STUB) + syslog(LOG_INFO, + (query_type == T_SOA) + ? "zone %s: res_mkquery T_SOA failed" + : "zone %s: res_mkquery T_NS failed", + zp->z_origin); + else +#endif + syslog(LOG_INFO, + "zone %s: res_mkquery T_AXFR failed", + zp->z_origin); + } + (void) my_close(s); +#ifdef POSIX_SIGNALS + sigaction(SIGALRM, &osv, + (struct sigaction *)0); +#else + sigvec(SIGALRM, &osv, + (struct sigvec *)0); +#endif + return (XFER_FAIL); + } + /* + * Send length & msg for zone transfer + */ + if (writemsg(s, buf, n) < 0) { + syslog(LOG_INFO, + "writemsg: %m"); + error++; + (void) my_close(s); + break; + } + } + /* + * Receive length & response + */ + if (netread(s, (char *)buf, INT16SZ, + (soa_cnt == 0) ?300 :XFER_TIMER) + < 0) { + error++; + break; + } + if ((len = ns_get16(buf)) == 0) + break; + if (len > bufsize) { + buf = (u_char *)realloc(buf, len); + if (buf == NULL) { + syslog(LOG_INFO, + "malloc(%u) failed for packet from server [%s], zone %s\n", + len, + inet_ntoa(sin.sin_addr), + zp->z_origin); + error++; + break; + } + bufsize = len; + } + hp = (HEADER *)buf; + eom = buf + len; + if (netread(s, (char *)buf, len, XFER_TIMER) + < 0) { + error++; + break; + } +#ifdef DEBUG + if (debug >= 3) { + (void)fprintf(ddt,"len = %d\n", len); + fp_nquery(buf, len, ddt); + } + if (fp) + fp_nquery(buf, len, fp); +#endif + if (len < HFIXEDSZ) { + struct sockaddr_in my_addr; + char my_addr_text[30]; + int alen; + + badrec: + error++; + alen = sizeof my_addr; + if (getsockname(s, (struct sockaddr *) + &my_addr, &alen) < 0) + sprintf(my_addr_text, + "[errno %d]", errno); + else + sprintf(my_addr_text, + "[%s].%u", + inet_ntoa(my_addr. + sin_addr), + ntohs(my_addr.sin_port) + ); + syslog(LOG_INFO, + "[%s] record too short from [%s], zone %s\n", + my_addr_text, + inet_ntoa(sin.sin_addr), + zp->z_origin); + break; + } + cp = buf + HFIXEDSZ; + if (hp->qdcount) { + if ((n = dn_skipname(cp, eom)) == -1 + || n + QFIXEDSZ >= eom - cp) + goto badrec; + cp += n + QFIXEDSZ; + } + nmp = cp; + if ((n = dn_skipname(cp, eom)) == -1) + goto badrec; + tmp = cp + n; +#ifdef STUBS + if (zp->z_type == Z_STUB) { + ancount = ntohs(hp->ancount); + n = 0; + for (cnt = 0; cnt < (u_int)ancount; cnt++) { + n = print_output(zp, serial_no, buf, + len, cp); + if (n < 0) + break; + cp += n; + } + /* + * If we've processed the answer section and + * didn't get any useful answers, bail out. + */ + if (query_type == T_SOA && soa_cnt == 0) { + syslog(LOG_ERR, + "stubs: no SOA in answer"); + error++; + break; + } + if (query_type == T_NS && ns_cnt == 0) { + syslog(LOG_ERR, + "stubs: no NS in answer"); + error++; + break; + } + if (n >= 0 && hp->nscount) { + ancount = ntohs(hp->nscount); + for (cnt = 0; + cnt < (u_int)ancount; + cnt++) { + n = print_output(zp, serial_no, + buf, len, + cp); + if (n < 0) + break; + cp += n; + } + } + ancount = ntohs(hp->arcount); + for (cnt = 0; + n > 0 && cnt < (u_int)ancount; + cnt++) { + n = print_output(zp, serial_no, buf, + len, cp); + cp += n; + } + if (n < 0) { + syslog(LOG_INFO, + "print_output: unparseable answer (%d), zone %s", + hp->rcode, zp->z_origin); + error++; + break; + } + if (cp != eom) { + syslog(LOG_INFO, + "print_output: short answer (%d, %d), zone %s", + cp - buf, eom - buf, + zp->z_origin); + error++; + break; + } + } else { +#endif /*STUBS*/ + ancount = ntohs(hp->ancount); + for (n = cnt = 0; + cnt < (u_int)ancount; + cnt++) { + n = print_output(zp, serial_no, buf, + len, cp); + if (n < 0) + break; + cp += n; + } + if (n < 0) { + syslog(LOG_INFO, + "print_output: unparseable answer (%d), zone %s", + hp->rcode, zp->z_origin); + error++; + break; + } + if (cp != eom) { + syslog(LOG_INFO, + "print_output: short answer (%d, %d), zone %s", + cp - buf, eom - buf, + zp->z_origin); + error++; + break; + } +#ifdef STUBS + } +#endif + + if (soa_cnt >= 2) + break; + + } + (void) my_close(s); + if (error == 0) { +#ifdef POSIX_SIGNALS + (void) sigaction(SIGALRM, &osv, + (struct sigaction *)0); +#else + (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); +#endif + return (XFER_SUCCESS); + } + dprintf(2, "error receiving zone transfer\n"); + } else if (zp_start.z_serial == serial_no) { + (void) my_close(s); + dprintf(1, "zone up-to-date, serial %u\n", zp_start.z_serial); + return (XFER_UPTODATE); + } else { + (void) my_close(s); + if (!quiet) + syslog(LOG_NOTICE, + "serial from [%s], zone %s: %u lower than current: %u\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + zp_start.z_serial, serial_no); + return (XFER_FAIL); + } + } +#ifdef POSIX_SIGNALS + (void) sigaction(SIGALRM, &osv, (struct sigaction *)0); +#else + (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); +#endif + if (!error) + return (XFER_TIMEOUT); + return (XFER_FAIL); +} + +static SIG_FN +term_handler() { + cleanup_for_exit(); + _exit(XFER_FAIL); /* not safe to call exit() from a signal handler */ +} + +/* + * Set flag saying to read was interrupted + * used for a read timer + */ +static SIG_FN +read_alarm() { + read_interrupted = 1; +} + +static int +netread(int fd, char *buf, int len, int timeout) { + static const char setitimerStr[] = "setitimer: %m"; + struct itimerval ival, zeroival; + struct sockaddr_in sa; + int n, salen; +#if defined(NETREAD_BROKEN) + int retries = 0; +#endif + + memset(&zeroival, 0, sizeof zeroival); + ival = zeroival; + ival.it_value.tv_sec = timeout; + while (len > 0) { + if (setitimer(ITIMER_REAL, &ival, NULL) < 0) { + syslog(LOG_INFO, setitimerStr); + return (-1); + } + errno = 0; + salen = sizeof sa; + n = recvfrom(fd, buf, len, 0, (struct sockaddr *)&sa, &salen); + if (n == 0 && errno == 0) { +#if defined(NETREAD_BROKEN) + if (++retries < 42) /* doug adams */ + continue; +#endif + syslog(LOG_INFO, "premature EOF, fetching \"%s\"", + domain); + return (-1); + } + if (n < 0) { + if (errno == 0) { +#if defined(NETREAD_BROKEN) + if (++retries < 42) /* doug adams */ + continue; +#endif + syslog(LOG_INFO, + "recv(len=%d): n=%d && !errno", + len, n); + return (-1); + } + if (errno == EINTR) { + if (!read_interrupted) { + /* It wasn't a timeout; ignore it. */ + continue; + } + errno = ETIMEDOUT; + } + syslog(LOG_INFO, "recv(len=%d): %m", len); + return (-1); + } + buf += n; + len -= n; + } + if (setitimer(ITIMER_REAL, &zeroival, NULL) < 0) { + syslog(LOG_INFO, setitimerStr); + return (-1); + } + return (0); +} + +/* + * Write a counted buffer to a file descriptor preceded by a length word. + */ +static int +writemsg(int rfd, const u_char *msg, int msglen) { + struct iovec iov[2]; + u_char len[INT16SZ]; + int ret; + + __putshort(msglen, len); + iov[0].iov_base = (char *)len; + iov[0].iov_len = INT16SZ; + iov[1].iov_base = (char *)msg; + iov[1].iov_len = msglen; + ret = writev(rfd, iov, 2); + if (ret != INT16SZ + msglen) { + syslog(LOG_DEBUG, "writemsg(%d,%#x,%d) failed: %s", + rfd, msg, msglen, strerror(errno)); + return (-1); + } + return (ret); +} + +static const char * +soa_zinfo(struct zoneinfo *zp, u_char *cp, u_char *eom) { + int n, type, class; + u_int32_t ttl; + u_int16_t dlen; + u_char *rdatap; + + /* Are type, class, and ttl OK? */ + if (eom - cp < 3 * INT16SZ + INT32SZ) + return ("zinfo too short"); + NS_GET16(type, cp); + NS_GET16(class, cp); + NS_GET32(ttl, cp); + NS_GET16(dlen, cp); + rdatap = cp; + if (type != T_SOA || class != curclass) + return ("zinfo wrong typ/cla/ttl"); + /* Skip master name and contact name, we can't validate them. */ + if ((n = dn_skipname(cp, eom)) == -1) + return ("zinfo mname"); + cp += n; + if ((n = dn_skipname(cp, eom)) == -1) + return ("zinfo hname"); + cp += n; + /* Grab the data fields. */ + if (eom - cp < 5 * INT32SZ) + return ("zinfo dlen"); + NS_GET32(zp->z_serial, cp); + NS_GET32(zp->z_refresh, cp); + NS_GET32(zp->z_retry, cp); + NS_GET32(zp->z_expire, cp); + NS_GET32(zp->z_minimum, cp); + if (cp != rdatap + dlen) + return ("bad soa dlen"); + return (NULL); +} + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + hp->rcode = FORMERR; \ + return (-1); \ + } \ + } while (0) + +/* + * Parse the message, determine if it should be printed, and if so, print it + * in .db file form. Does minimal error checking on the message content. + * + * XXX why aren't we using ns_sprintrr() ? + */ +static int +print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, + int msglen, u_char *rrp) { + u_char *cp; + HEADER *hp = (HEADER *) msg; + u_int32_t addr, ttl, tmpnum; + int i, j, tab, result, n1, n; + u_int class, type, dlen; + char data[MAXDATA]; + u_char *cp1, *cp2, *temp_ptr, *eom, *rr_type_ptr; + u_char *cdata, *rdatap; + char *origin, dname[MAXDNAME]; + const char *proto; + const char *ignore = ""; + const char *badsoa_msg; + int escaped = 0; + + eom = msg + msglen; + cp = rrp; + n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + rr_type_ptr = cp; + NS_GET16(type, cp); + NS_GET16(class, cp); + NS_GET32(ttl, cp); + /* + * Following the Clarification draft's direction, we treat TTLs with + * the MSB set as if they were 0. + */ + if (ttl > MAXIMUM_TTL) { + syslog(LOG_INFO, "%s: TTL > %u, converted to 0", dname, + MAXIMUM_TTL); + ttl = 0; + } + NS_GET16(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; + + origin = dname; + while (*origin) { + if (!escaped && *origin == '.') { + origin++; /* skip over '.' */ + break; + } + escaped = (*origin++ == '\\') && !escaped; + } + dprintf(3, "print_output: dname %s type %d class %d ttl %u\n", + dname, type, class, ttl); + /* + * Convert the resource record data into the internal database format. + * CP points to the raw resource record. + * After this switch: + * CP has been updated to point past the RR. + * CP1 points to the internal database version. + * N is the length of the internal database version. + */ + switch (type) { + case T_A: + case T_WKS: + case T_HINFO: + case T_TXT: + case T_X25: + case T_ISDN: + case T_LOC: + case T_NSAP: + case T_AAAA: + case T_KEY: + cp1 = cp; + n = dlen; + cp += n; + break; + + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + n = dn_expand(msg, msg + msglen, cp, data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 = (u_char *)data; + n = strlen(data) + 1; + break; + + case T_MINFO: + case T_SOA: + case T_RP: + n = dn_expand(msg, msg + msglen, cp, data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + n = strlen(data) + 1; + cp1 = (u_char *)data + n; + n1 = sizeof data - n; + if (type == T_SOA) + n1 -= 5 * INT32SZ; + n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char *) cp1) + 1; + if (type == T_SOA) { + BOUNDS_CHECK(cp, 5 * INT32SZ); + temp_ptr = cp + 4 * INT32SZ; + NS_GET32(minimum_ttl, temp_ptr); + /* + * Following the Clarification draft's direction, + * we treat TTLs with the MSB set as if they were 0. + */ + if (minimum_ttl > MAXIMUM_TTL) { + syslog(LOG_INFO, + "%s: SOA minimum TTL > %u, converted to 0", + dname, MAXIMUM_TTL); + minimum_ttl = 0; + } + n = 5 * INT32SZ; + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + } + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_NAPTR: + /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(data, cp, INT16SZ*2); + cp1 = (u_char *)data + INT16SZ*2; + cp += INT16SZ*2; + + /* Flags */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Service */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Regexp */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Replacement */ + n = dn_expand(msg, msg + msglen, cp, (char *)cp1, + sizeof data - ((char *)cp1 - data)); + if (n < 0) + return (-1); + cp += n; + + /* compute end of data */ + cp1 += strlen((char *)cp1) + 1; + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = (u_char *)data + INT16SZ; + cp += INT16SZ; + + if (type == T_SRV) { + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(cp1, cp, INT16SZ*2); + cp1 += INT16SZ*2; + cp += INT16SZ*2; + } + + /* get name */ + n = dn_expand(msg, msg + msglen, cp, + (char *)cp1, + sizeof data - (cp1 - (u_char *)data)); + if (n < 0) + return (-1); + cp += n; + + /* compute end of data */ + cp1 += strlen((char *) cp1) + 1; + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_PX: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = (u_char *)data + INT16SZ; + cp += INT16SZ; + + /* get MAP822 name */ + n = dn_expand(msg, msg + msglen, cp, + (char *)cp1, sizeof data - INT16SZ); + if (n < 0) + return (-1); + cp += n; + cp1 += (n = (strlen((char *) cp1) + 1)); + n1 = sizeof data - n; + + /* get MAPX400 name */ + n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); + if (n < 0) + return (-1); + cp += n; + cp1 += strlen((char *) cp1) + 1; + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_SIG: + /* CP is the raw resource record as it arrived. + * CP1, after this switch, points to the internal database version. */ + cp1 = (u_char *)data; + + /* first just copy over the type_covered, algorithm, */ + /* labels, orig ttl, two timestamps, and the footprint */ + BOUNDS_CHECK(cp, NS_SIG_SIGNER); + memcpy(cp1, cp, NS_SIG_SIGNER); + cp += NS_SIG_SIGNER; + cp1 += NS_SIG_SIGNER; + + /* then the signer's name */ + n = dn_expand(msg, msg + msglen, cp, + (char *)cp1, (sizeof data) - 18); + if (n < 0) + return (-1); + cp += n; + cp1 += strlen((char*)cp1)+1; + + /* finally, we copy over the variable-length signature. + Its size is the total data length, minus what we copied. */ + n = dlen - (NS_SIG_SIGNER + n); + if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) { + hp->rcode = FORMERR; + return (-1); /* out of room! */ + } + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + case T_NXT: + n = dn_expand(msg, msg + msglen, cp, + (char *)data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 = (u_char *)data + strlen(data) + 1; + n = dlen - n; + if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) { + hp->rcode = FORMERR; + return (-1); /* out of room! */ + } + if (n > 0) { /* Actually, n should never be less than 4 */ + memcpy(cp1, cp, n); + cp += n; + } else { + hp->rcode = FORMERR; + return (-1); + } + n += cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + + default: + syslog(LOG_INFO, "\"%s %s %s\" - unknown type (%d)", + dname, p_class(class), p_type(type), type); + hp->rcode = NOTIMP; + return (-1); + } + + if (n > MAXDATA) { + dprintf(1, "update type %d: %d bytes is too much data\n", + type, n); + hp->rcode = FORMERR; + return (-1); + } + if (cp != rdatap + dlen) { + dprintf(1, + "encoded rdata length is %u, but actual length was %u\n", + dlen, (u_int)(cp - rdatap)); + hp->rcode = FORMERR; + return (-1); + } + + cdata = cp1; + result = cp - rrp; + + /* + * Special handling for SOA records. + */ + + if (type == T_SOA) { + if (strcasecmp(dname, zp->z_origin) != 0) { + syslog(LOG_INFO, + "wrong zone name in AXFR (wanted \"%s\", got \"%s\")", + zp->z_origin, dname); + hp->rcode = FORMERR; + return (-1); + } + if (!soa_cnt) { + badsoa_msg = soa_zinfo(&zp_start, rr_type_ptr, eom); + if (badsoa_msg) { + syslog(LOG_INFO, + "malformed SOA for zone %s: %s", + zp->z_origin, badsoa_msg); + hp->rcode = FORMERR; + return (-1); + } + if (SEQ_GT(zp_start.z_serial, serial_no) || + !serial_no) + soa_cnt++; + else { + syslog(LOG_INFO, + "serial went backwards after transfer started"); + return (-1); + } + } else { + badsoa_msg = soa_zinfo(&zp_finish, rr_type_ptr, eom); + if (badsoa_msg) { + syslog(LOG_INFO, + "malformed SOA for zone %s: %s", + zp->z_origin, badsoa_msg); + hp->rcode = FORMERR; + return (-1); + } + dprintf(2, "SOA, serial %u\n", zp_finish.z_serial); + if (zp_start.z_serial != zp_finish.z_serial) { + dprintf(1, "serial changed, restart\n"); + restarts++; + if (restarts > MAX_XFER_RESTARTS) { + syslog(LOG_INFO, + "too many transfer restarts for zone %s", + zp->z_origin); + hp->rcode = FORMERR; + return (-1); + } + soa_cnt = 0; +#ifdef STUBS + ns_cnt = 0; +#endif + minimum_ttl = 0; + strcpy(prev_origin, zp->z_origin); + prev_dname[0] = DEF_DNAME; + /* + * Flush buffer, truncate file + * and seek to beginning to restart. + */ + fflush(dbfp); + if (ftruncate(fileno(dbfp), 0) != 0) { + if (!quiet) + syslog(LOG_INFO, + "ftruncate %s: %m\n", + tmpname); + return (-1); + } + fseek(dbfp, 0L, 0); + return (result); + } + soa_cnt++; + return (result); + } + } + +#ifdef STUBS + if (zp->z_type == Z_STUB) { + if (query_type == T_NS && type == T_NS) + ns_cnt++; + /* + * If we're processing a response to an SOA query, we don't + * want to print anything from the response except for the SOA. + * We do want to check everything in the packet, which is + * why we do this check now instead of earlier. + */ + if (query_type == T_SOA && type != T_SOA) + return (result); + } +#endif + + if (!soa_cnt || soa_cnt >= 2) { + char *gripe; + + if (!soa_cnt) + gripe = "got RR before first SOA"; + else + gripe = "got RR after second SOA"; + syslog(LOG_INFO, "%s in zone %s", gripe, zp->z_origin); + hp->rcode = FORMERR; + return (-1); + } + + /* + * If they are trying to tell us info about something that is + * not in the zone that we are transfering, then ignore it! + * They don't have the authority to tell us this info. + * + * We have to do a bit of checking here - the name that we are + * checking is is fully qualified & may be in a subdomain of the + * zone in question. We also need to ignore any final dots. + * + * If a domain has both NS records and non-NS records, (for + * example, NS and MX records), then we should ignore the non-NS + * records (except that we should not ignore glue A records). + * XXX: It is difficult to do this properly, so we just compare + * the current dname with that in the most recent NS record. + * This defends against the most common error case, + * where the remote server sends MX records soon after the + * NS records for a particular domain. If sent earlier, we lose. XXX + */ + if (!samedomain(dname, domain)) { + (void) fprintf(dbfp, "; Ignoring info about %s, not in zone %s.\n", + dname, domain); + ignore = "; "; + } else if (type != T_NS && type != T_A && + strcasecmp(zone_top, dname) != 0 && + strcasecmp(prev_ns_dname, dname) == 0) + { + (void) fprintf(dbfp, "; Ignoring extra info about %s, invalid after NS delegation.\n", + dname); + ignore = "; "; + } + + /* + * If the current record is not being ignored, but the + * previous record was ignored, then we invalidate information + * that might have been altered by ignored records. + * (This means that we sometimes output unnecessary $ORIGIN + * lines, but that is harmless.) + * + * Also update prev_comment now. + */ + if (prev_comment && ignore[0] == '\0') { + prev_dname[0] = DEF_DNAME; + prev_origin[0] = DEF_DNAME; + } + prev_comment = (ignore[0] != '\0'); + + /* + * set prev_ns_dname if necessary + */ + if (type == T_NS) { + (void) strcpy(prev_ns_dname, dname); + } + + /* + * If the origin has changed, print the new origin + */ + if (strcasecmp(prev_origin, origin)) { + (void) strcpy(prev_origin, origin); + (void) fprintf(dbfp, "%s$ORIGIN %s.\n", ignore, origin); + } + tab = 0; + + if (strcasecmp(prev_dname, dname)) { + /* + * set the prev_dname to be the current dname, then cut off all + * characters of dname after (and including) the first '.' + */ + char *cutp; + + (void) strcpy(prev_dname, dname); + escaped = 0; + cutp = dname; + while (*cutp) { + if (!escaped && *cutp == '.') + break; + escaped = (*cutp++ == '\\') && !escaped; + } + *cutp = '\0'; + + if (dname[0] == 0) { + if (origin[0] == 0) + (void) fprintf(dbfp, "%s.\t", ignore); + else + (void) fprintf(dbfp, "%s.%s.\t", + ignore, origin); /* ??? */ + } else { + char *backslash; + backslash = (*dname == '@' || *dname == '$') ? + "\\" : ""; + (void) fprintf(dbfp, "%s%s%s\t", ignore, + backslash, dname); + } + if (strlen(dname) < (size_t)8) + tab = 1; + } else { + (void) fprintf(dbfp, "%s\t", ignore); + tab = 1; + } + + if (ttl != minimum_ttl) + (void) fprintf(dbfp, "%d\t", (int) ttl); + else if (tab) + (void) putc('\t', dbfp); + + (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type)); + cp = cdata; + + /* + * Print type specific data + */ + switch (type) { + + case T_A: + switch (class) { + case C_IN: + case C_HS: + fputs(inet_ntoa(ina_get(cp)), dbfp); + break; + } + (void) fprintf(dbfp, "\n"); + break; + + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + if (cp[0] == '\0') + (void) fprintf(dbfp, ".\n"); + else + (void) fprintf(dbfp, "%s.\n", cp); + break; + + case T_NS: + cp = cdata; + if (cp[0] == '\0') + (void) fprintf(dbfp, ".\t"); + else + (void) fprintf(dbfp, "%s.", cp); + (void) fprintf(dbfp, "\n"); + break; + + case T_HINFO: + case T_ISDN: + cp2 = cp + n; + for (i = 0; i < 2; i++) { + if (i != 0) + (void) putc(' ', dbfp); + n = *cp++; + cp1 = cp + n; + if (cp1 > cp2) + cp1 = cp2; + (void) putc('"', dbfp); + j = 0; + while (cp < cp1) { + if (*cp == '\0') { + cp = cp1; + break; + } + if (strchr("\n\"\\", *cp)) + (void) putc('\\', dbfp); + (void) putc(*cp++, dbfp); + j++; + } + if (j == 0 && (type != T_ISDN || i == 0)) + (void) putc('?', dbfp); + (void) putc('"', dbfp); + } + (void) putc('\n', dbfp); + break; + + case T_SOA: + (void) fprintf(dbfp, "%s.", cp); + cp += strlen((char *) cp) + 1; + (void) fprintf(dbfp, " %s. (\n", cp); + cp += strlen((char *) cp) + 1; + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, "%s\t\t%u", ignore, tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u", tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u", tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u", tmpnum); + NS_GET32(tmpnum, cp); + (void) fprintf(dbfp, " %u )\n", tmpnum); + break; + + case T_MX: + case T_AFSDB: + case T_RT: + NS_GET16(tmpnum, cp); + (void) fprintf(dbfp, "%u", tmpnum); + (void) fprintf(dbfp, " %s.\n", cp); + break; + + case T_PX: + NS_GET16(tmpnum, cp); + (void) fprintf(dbfp, "%u", tmpnum); + (void) fprintf(dbfp, " %s.", cp); + cp += strlen((char *) cp) + 1; + (void) fprintf(dbfp, " %s.\n", cp); + break; + + case T_TXT: + case T_X25: + cp1 = cp + n; + while (cp < cp1) { + (void) putc('"', dbfp); + if ((i = *cp++) != 0) { + for (j = i; j > 0 && cp < cp1; j--) { + if (strchr("\n\"\\", *cp)) + (void) putc('\\', dbfp); + (void) putc(*cp++, dbfp); + } + } + (void) putc('"', dbfp); + if (cp < cp1) + (void) putc(' ', dbfp); + } + (void) putc('\n', dbfp); + break; + + case T_NSAP: + fprintf(dbfp, "%s\n", inet_nsap_ntoa(n, cp, NULL)); + break; + + case T_AAAA: { + char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + + fprintf(dbfp, "%s\n", inet_ntop(AF_INET6, cp, t, sizeof t)); + break; + } + + case T_LOC: { + char t[255]; + + (void) fprintf(dbfp, "%s\n", loc_ntoa(cp, t)); + break; + } + + case T_NAPTR: { + u_int32_t order, preference; + + /* Order */ + NS_GET16(order, cp); + fprintf(dbfp, "%u", order); + + /* Preference */ + NS_GET16(preference, cp); + fprintf(dbfp, " %u", preference); + + /* Flags */ + if ((n = *cp++) != 0) { + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + } + + /* Service */ + if ((n = *cp++) != 0) { + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + } + + /* Regexp */ + if ((n = *cp++) != 0) { + fprintf(dbfp, " \"%.*s\"", (int)n, cp); + cp += n; + } + + /* Replacement */ + fprintf(dbfp, " %s.\n", cp); + + break; + } + case T_SRV: { + u_int priority, weight, port; + + NS_GET16(priority, cp); + NS_GET16(weight, cp); + NS_GET16(port, cp); + fprintf(dbfp, "\t%u %u %u %s.\n", + priority, weight, port, cp); + break; + } + + case T_WKS: + fputs(inet_ntoa(ina_get(cp)), dbfp); + cp += INADDRSZ; + fputc(' ', dbfp); + proto = protocolname(*cp); + cp += sizeof(char); + (void) fprintf(dbfp, "%s ", proto); + i = 0; + while (cp < cdata + n) { + j = *cp++; + do { + if (j & 0200) + (void) fprintf(dbfp, " %s", + servicename(i, proto)); + j <<= 1; + } while (++i & 07); + } + (void) fprintf(dbfp, "\n"); + break; + + case T_MINFO: + case T_RP: + (void) fprintf(dbfp, "%s.", cp); + cp += strlen((char *) cp) + 1; + (void) fprintf(dbfp, " %s.\n", cp); + break; + + case T_KEY: { + char databuf[16+NS_MD5RSA_MAX_BASE64]; /* 16 for slop */ + u_int keyflags; + + /* get & format key flags */ + keyflags = ns_get16(cp); + (void) fprintf(dbfp, "0x%04x ", keyflags); + cp += INT16SZ; + + /* protocol id */ + (void) fprintf(dbfp, " %u", *cp++); + + /* algorithm id */ + (void) fprintf(dbfp, " %u ", *cp++); + + /* key itself (which may have zero length) */ + n = b64_ntop(cp, (cp1 + n) - cp, databuf, sizeof databuf); + if (n < 0) + fprintf(dbfp, "; BAD BASE64\n"); + else + fprintf(dbfp, "%s\n", databuf); + break; + } + + case T_SIG: { + char databuf[16+NS_MD5RSA_MAX_BASE64]; /* 16 for slop */ + + /* get & format rr type which signature covers */ + (void) fprintf(dbfp,"%s", p_type(ns_get16((u_char*)cp))); + cp += INT16SZ; + + /* algorithm id */ + (void) fprintf(dbfp," %d",*cp++); + + /* labels (# of labels in name) - skip in textual record */ + cp++; + + /* orig time to live (TTL)) */ + (void) fprintf(dbfp," %u", (u_int32_t)ns_get32((u_char*)cp)); + cp += INT32SZ; + + /* expiration time */ + (void) fprintf(dbfp," %s", p_secstodate(ns_get32((u_char*)cp))); + cp += INT32SZ; + + /* time signed */ + (void) fprintf(dbfp," %s", p_secstodate(ns_get32((u_char*)cp))); + cp += INT32SZ; + + /* Key footprint */ + (void) fprintf(dbfp," %d", ns_get16((u_char*)cp)); + cp += INT16SZ; + + /* signer's name */ + (void) fprintf(dbfp, " %s. ", cp); + cp += strlen((char *) cp) + 1; + + /* signature itself */ + n = b64_ntop(cp, (cdata + n) - cp, databuf, sizeof databuf); + if (n < 0) + fprintf (dbfp, "; BAD BASE64\n"); + else + fprintf (dbfp, "%s\n", databuf); + break; + } + + case T_NXT: + fprintf(dbfp, "%s.", (char *)cp); + i = strlen((char *)cp)+1; + cp += i; + n -= i; + for (i=0; i < n*NS_NXT_BITS; i++) + if (NS_NXT_BIT_ISSET (i, cp)) + fprintf(dbfp, " %s", p_type(i)); + fprintf(dbfp,"\n"); + break; + + default: + cp1 = cp + n; + while (cp < cp1) + fprintf(dbfp, "0x%02.2X ", *cp++ & 0xFF); + (void) fprintf(dbfp, "???\n"); + } + if (ferror(dbfp)) { + syslog(LOG_ERR, "%s: %m", tmpname); + cleanup_for_exit(); + exit(XFER_FAIL); + } + return (result); +} + +#ifdef SHORT_FNAMES +/* +** This routine handles creating temporary files with mkstemp +** in the presence of a 14 char filename system. Pathconf() +** does not work over NFS. +*/ +filenamecpy(char *ddtfile, char *optarg) { + int namelen, extra, len; + char *dirname, *filename; + + /* determine the length of filename allowed */ + if((dirname = strrchr(optarg, '/')) == NULL){ + filename = optarg; + } else { + *dirname++ = '\0'; + filename = dirname; + } + namelen = pathconf(dirname == NULL? "." : optarg, _PC_NAME_MAX); + if(namelen <= 0) + namelen = 255; /* length could not be determined */ + if(dirname != NULL) + *--dirname = '/'; + + /* copy a shorter name if it will be longer than allowed */ + extra = (strlen(filename)+strlen(".XXXXXX")) - namelen; + if(extra > 0){ + len = strlen(optarg) - extra; + (void) strncpy(ddtfile, optarg, len); + ddtfile[len] = '\0'; + } else + (void) strcpy(ddtfile, optarg); +} +#endif /* SHORT_FNAMES */ diff --git a/contrib/bind/bin/named/Makefile b/contrib/bind/bin/named/Makefile new file mode 100644 index 0000000..7e30cd0 --- /dev/null +++ b/contrib/bind/bin/named/Makefile @@ -0,0 +1,126 @@ +## Copyright (c) 1996, 1997 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. + +# $Id: Makefile,v 8.31 1998/03/20 00:49:46 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +YACC = yacc -d +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cruv +INSTALL= install +STRIP=-s + +PS=ps +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} ${DEFS} + +VER= LOCAL-`date +%y%m%d.%H%M%S` +HOSTNAMECMD= hostname || uname -n + +PROG= named +HDRS= db_defs.h db_glob.h ns_defs.h ns_glob.h named.h pathnames.h +SRCS= db_dump.c db_load.c db_lookup.c db_save.c db_update.c \ + db_glue.c \ + ns_parser.c ns_lexer.c ns_parseutil.c \ + ns_forw.c ns_init.c ns_main.c ns_maint.c ns_req.c \ + ns_resp.c ns_stats.c ns_ncache.c ns_xfr.c ns_glue.c \ + ns_udp.c ns_config.c ns_update.c +OBJS= db_dump.${O} db_load.${O} db_lookup.${O} db_save.${O} db_update.${O} \ + db_glue.${O} \ + ns_parser.${O} ns_lexer.${O} ns_parseutil.${O} \ + ns_forw.${O} ns_init.${O} ns_main.${O} ns_maint.${O} ns_req.${O} \ + ns_resp.${O} ns_stats.${O} ns_ncache.${O} ns_xfr.${O} ns_glue.${O} \ + ns_udp.${O} ns_config.${O} ns_update.${O} + +all: ${PROG} pathnames + +${PROG}: pathnames.h ${OBJS} ${LIBBIND} Makefile tmp_version.${O} + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} tmp_version.${O} \ + ${LIBBIND} ${SYSLIBS} + +ns_parser.c ns_parser.h: ns_parser.y + ${YACC} ns_parser.y + mv y.tab.c ns_parser.c + mv y.tab.h ns_parser.h + +tmp_version.${O}: tmp_version.c + +tmp_version.c: version.c Makefile ../Makefile ${SRCS} ${HDRS} + (u=$${USER-root} d=`pwd` h=`${HOSTNAMECMD}` t=`date`; \ + sed -e "s|%WHEN%|$${t}|" -e "s|%VERSION%|"${VER}"|" \ + -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \ + < version.c > tmp_version.c) + +pathnames.h: ${TOP}/.settings Makefile + rm -f pathnames.h + sed -e "s|%DESTSBIN%|${DESTSBIN}|" \ + -e "s|%DESTEXEC%|${DESTEXEC}|" \ + -e "s|%DESTETC%|${DESTETC}|" \ + -e "s|%DESTRUN%|${DESTRUN}|" \ + < pathtemplate.h > pathnames.h + +pathnames: pathnames.${O} pathnames.h ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o $@ pathnames.${O} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + rm -f ns_parser.c ns_parser.h + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + rm -f tmp_version.c tmp_version.${O} + rm -f pathnames pathnames.${O} tmp_pathnames.h pathnames.h + rm -f y.tab.h y.tab.c + +depend: ${SRCS} pathnames.h + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${DEFS} ${SRCS} + +${DESTDIR}${DESTSBIN}: + mkdir -p ${DESTDIR}${DESTSBIN} + +install: ${DESTDIR}${DESTSBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTSBIN}/${PROG} + +links: FRC + @ln -s SRC/*.[chy] SRC/test .; rm -f ns_parser.[ch] + +tags: FRC + ctags ${SRCS} *.h + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/named/db_defs.h b/contrib/bind/bin/named/db_defs.h new file mode 100644 index 0000000..ab93480 --- /dev/null +++ b/contrib/bind/bin/named/db_defs.h @@ -0,0 +1,233 @@ +/* + * from db.h 4.16 (Berkeley) 6/1/90 + * $Id: db_defs.h,v 8.17 1998/02/17 17:17:43 vixie Exp $ + */ + +/* Copyright (c) 1985, 1990 + * 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) 1996, 1997 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. + */ + +/* + * Global definitions for data base routines. + */ + +#define INVBLKSZ 7 /* # of namebuf pointers per block */ +#define INVHASHSZ 919 /* size of inverse hash table */ + + /* max length of data in RR data field */ +#define MAXDATA (2*MAXDNAME + 5*INT32SZ) + +#define DB_ROOT_TIMBUF 3600 +#define TIMBUF 300 + +#define DICT_INDEXBITS 24 +#define DICT_MAXLENGTH 127 +#define DICT_INSERT_P 0x0001 + +/* + * Hash table structures. + */ +struct databuf { + struct databuf *d_next; /* linked list */ + struct nameser *d_ns; /* NS from whence this came */ + u_int32_t d_ttl; /* time to live */ + /* if d_zone == DB_Z_CACHE, then + * d_ttl is actually the time when + * the record will expire. + * otherwise (for authoritative + * primary and secondary zones), + * d_ttl is the time to live. + */ + unsigned d_flags :7; /* see below */ + unsigned d_cred :3; /* DB_C_{??????} */ + unsigned d_clev :6; + u_int16_t d_zone; /* zone number or 0 for the cache */ + int16_t d_class; /* class number */ + int16_t d_type; /* type number */ + int16_t d_size; /* size of data area */ + u_int32_t d_rcnt; + unsigned d_rcode :4; /* rcode for negative caching */ + unsigned d_mark :12; /* place to mark data */ + u_int16_t d_nstime; /* NS response time, milliseconds */ + u_char d_data[sizeof(void*)]; /* dynamic (padded) */ +}; +#define DATASIZE(n) (sizeof(struct databuf) - sizeof(void*) + n) + +#ifdef BIND_UPDATE +/* + * d_mark definitions + */ +#define D_MARK_DELETED 0x01 +#define D_MARK_ADDED 0x02 +#define D_MARK_FOUND 0x04 +#endif + +/* + * d_flags definitions + */ +#define DB_F_HINT 0x01 /* databuf belongs to fcachetab */ +#define DB_F_ACTIVE 0x02 /* databuf is linked into a cache */ +#define DB_F_FREE 0x04 /* databuf has been freed */ + +/* + * d_cred definitions + */ +#define DB_C_ZONE 4 /* authoritative zone - best */ +#define DB_C_AUTH 3 /* authoritative answer */ +#define DB_C_ANSWER 2 /* non-authoritative answer */ +#define DB_C_ADDITIONAL 1 /* additional data */ +#define DB_C_CACHE 0 /* cache - worst */ + +struct namebuf { + u_int n_hashval; /* hash value of _n_name */ + struct namebuf *n_next; /* linked list */ + struct databuf *n_data; /* data records */ + struct namebuf *n_parent; /* parent domain */ + struct hashbuf *n_hash; /* hash table for children */ + char _n_name[sizeof(void*)]; /* Counted str (dynamic). */ +}; +#define NAMESIZE(n) (sizeof(struct namebuf) - sizeof(void*) + 1 + n + 1) +#define NAMELEN(nb) (((u_char *)((nb)._n_name))[0]) +#define NAME(nb) ((nb)._n_name + 1) + +struct hashbuf { + int h_size; /* size of hash table */ + int h_cnt; /* number of entries */ + struct namebuf *h_tab[1]; /* allocated as needed */ +}; +#define HASHSIZE(s) (sizeof(struct hashbuf) + (s-1) * sizeof(struct namebuf *)) + +#define HASHSHIFT 3 +#define HASHMASK 0x1f + +/* + * Flags to updatedb + */ +#define DB_NODATA 0x01 /* data should not exist */ +#define DB_MEXIST 0x02 /* data must exist */ +#define DB_DELETE 0x04 /* delete data if it exists */ +#define DB_NOTAUTH 0x08 /* must not update authoritative data */ +#define DB_NOHINTS 0x10 /* don't reflect update in fcachetab */ +#define DB_PRIMING 0x20 /* is this update the result of priming? */ + +#define DB_Z_CACHE 0 /* cache-zone-only db_dump() */ +#define DB_Z_ALL 65535 /* normal db_dump() */ +#define DB_Z_SPECIAL(z) ((z) == DB_Z_CACHE || (z) == DB_Z_ALL) + +/* + * Error return codes + */ +#define OK 0 +#define NONAME (-1) +#define NOCLASS (-2) +#define NOTYPE (-3) +#define NODATA (-4) +#define DATAEXISTS (-5) +#define NODBFILE (-6) +#define TOOMANYZONES (-7) +#define GOODDB (-8) +#define NEWDB (-9) +#define AUTH (-10) +#ifdef BIND_UPDATE +#define SERIAL (-11) +#endif + +/* + * getnum() options + */ +#define GETNUM_NONE 0x00 /* placeholder */ +#define GETNUM_SERIAL 0x01 /* treat as serial number */ +#define GETNUM_SCALED 0x02 /* permit "k", "m" suffixes, scale result */ + +/* + * Database access abstractions. + */ +#define foreach_rr(dp, np, ty, cl, zn) \ + for ((dp) = (np)->n_data; (dp) != NULL; (dp) = (dp)->d_next) \ + if ((cl) != C_ANY && (cl) != (dp)->d_class) \ + continue; \ + else if ((ty) != T_ANY && (ty) != (dp)->d_type) \ + continue; \ + else if (((zn) == DB_Z_CACHE) \ + ? stale(dp) \ + : (zn) != (dp)->d_zone) \ + continue; \ + else if ((dp)->d_rcode) \ + continue; \ + else \ + /* Caller code follows in sequence. */ + +#define DRCNTINC(x) \ + do { \ + if (++((x)->d_rcnt) == 0) \ + ns_panic(ns_log_db, 1, "++d_rcnt == 0"); \ + } while (0) + +#define DRCNTDEC(x) \ + do { \ + if (((x)->d_rcnt)-- == 0) \ + ns_panic(ns_log_db, 1, "d_rcnt-- == 0"); \ + } while (0) diff --git a/contrib/bind/bin/named/db_dict.c b/contrib/bind/bin/named/db_dict.c new file mode 100644 index 0000000..a0b8921 --- /dev/null +++ b/contrib/bind/bin/named/db_dict.c @@ -0,0 +1,111 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: db_dict.c,v 8.1 1997/09/26 17:55:40 halley Exp $"; +#endif /* not lint */ + +/* + * Portions Copyright (c) 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +#define DICT_BLOCKBITS 8 +#define DICT_BLOCKSHIFT 16 +#define DICT_BLOCKMAX (1 << DICT_BLOCKBITS) +#define DICT_OFFSETBITS 16 +#define DICT_OFFSETSHIFT 0 +#define DICT_OFFSETMAX (1 << DICT_OFFSETBITS) + +#define DICT_CONSUMED(Length) ((Length) + 1) +#define DICT_INDEX(Block,Offset) (((Block) << DICT_BLOCKSHIFT) | \ + ((Offset) << DICT_OFFSETSHIFT)) + +static int dict_new(const char *, int); + +static char * blocks[DICT_BLOCKMAX]; +static int offsets[DICT_BLOCKMAX]; +static int cur_block = 0; +static int cur_offset = -1; + +int +dict_lookup(const char *text, int length, int flags) { + int block, offset, ret; + + /* XXX this is a proof of concept, some kind of hash is needed. */ + for (block = 0; block <= cur_block; block++) { + const char *cur = &blocks[block][0]; + const char *end = &blocks[block][offsets[block]]; + + while (cur < end) { + int xlength = *cur; + + if (xlength == length && + memcmp(cur+1, text, length) == 0) + return (DICT_INDEX(block, offset)); + cur += DICT_CONSUMED(length); + } + } + if ((flags & DICT_INSERT_P) != 0) + return (dict_new(text, length)); + return (-ENOENT); +} + +static int +dict_new(const char *text, int length) { + int ret; + + if (length < 0 || length > DICT_MAXLENGTH) + return (-E2BIG); + if (cur_offset + DICT_CONSUMED(length) >= DICT_OFFSETMAX) { + if (cur_block + 1 == DICT_BLOCKMAX) + return (-ENOSPC); + cur_block++; + blocks[cur_block] = memget(DICT_OFFSETMAX); + if (blocks[cur_block] == NULL) + return (-ENOMEM); + cur_offset = 0; + } + assert(cur_offset >= 0); + assert(cur_offset + DICT_CONSUMED(length) < DICT_OFFSETMAX); + ret = DICT_INDEX(cur_block, cur_offset); + blocks[cur_block][cur_offset] = length; + memcpy(&blocks[cur_block][cur_offset+1], text, length); + cur_offset += DICT_CONSUMED(length); + offsets[cur_block] = cur_offset; + return (ret); +} diff --git a/contrib/bind/bin/named/db_dump.c b/contrib/bind/bin/named/db_dump.c new file mode 100644 index 0000000..9c15af3 --- /dev/null +++ b/contrib/bind/bin/named/db_dump.c @@ -0,0 +1,635 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)db_dump.c 4.33 (Berkeley) 3/3/91"; +static char rcsid[] = "$Id: db_dump.c,v 8.24 1998/02/13 19:49:09 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988, 1990 + * 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, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" + +static const char *MkCredStr(int); + +/* + * Dump current data base in a format similar to RFC 883. + */ + +void +doadump() +{ + FILE *fp; + + ns_notice(ns_log_db, "dumping nameserver data"); + + if ((fp = write_open(server_options->dump_filename)) == NULL) + return; + gettime(&tt); + fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec)); + if (zones && nzones) + zt_dump(fp); + fputs( +"; Note: Cr=(auth,answer,addtnl,cache) tag only shown for non-auth RR's\n", + fp); + fputs( +"; Note: NT=milliseconds for any A RR which we've used as a nameserver\n", + fp); + fprintf(fp, "; --- Cache & Data ---\n"); + if (hashtab != NULL) + (void) db_dump(hashtab, fp, DB_Z_ALL, ""); + fprintf(fp, "; --- Hints ---\n"); + if (fcachetab != NULL) + (void) db_dump(fcachetab, fp, DB_Z_ALL, ""); + (void) my_fclose(fp); + ns_notice(ns_log_db, "finished dumping nameserver data"); +} + +int +zt_dump(FILE *fp) { + struct zoneinfo *zp; + + fprintf(fp, ";; ++zone table++\n"); + for (zp = &zones[1]; zp < &zones[nzones]; zp++) { + char *pre, buf[64]; + u_int cnt; + + if (!zp->z_origin) + continue; + + fprintf(fp, "; %s (type %d, class %d, source %s)\n", + zp->z_origin + ? (*zp->z_origin ? zp->z_origin : ".") + : "Nil", + zp->z_type, zp->z_class, + zp->z_source ? zp->z_source : "Nil"); + fprintf(fp, ";\ttime=%lu, lastupdate=%lu, serial=%u,\n", + (u_long)zp->z_time, (u_long)zp->z_lastupdate, + zp->z_serial); + fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n", + zp->z_refresh, zp->z_retry, + zp->z_expire, zp->z_minimum); + fprintf(fp, ";\tftime=%lu, xaddr=[%s], state=%04x, pid=%d\n", + (u_long)zp->z_ftime, inet_ntoa(zp->z_xaddr), + zp->z_flags, (int)zp->z_xferpid); + sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt); + pre = buf; + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { + fprintf(fp, "%s[%s]", pre, inet_ntoa(zp->z_addr[cnt])); + pre = ", "; + } + if (zp->z_addrcnt) + fputc('\n', fp); + if (zp->z_axfr_src.s_addr != 0) + fprintf(fp, "; update source [%s]\n", + inet_ntoa(zp->z_axfr_src)); + } + fprintf(fp, ";; --zone table--\n"); + return (0); +} + +int +db_dump(struct hashbuf *htp, FILE *fp, int zone, char *origin) { + struct databuf *dp = NULL; + struct namebuf *np; + struct namebuf **npp, **nppend; + char dname[MAXDNAME]; + u_int32_t n; + u_int32_t addr; + int j, i, found_data, tab, printed_origin; + u_char *cp, *end; + const char *proto, *sep; + int16_t type; + u_int16_t keyflags; + u_char *sigdata; + u_char *savecp; + char temp_base64[NS_MD5RSA_MAX_BASE64]; + + found_data = 0; + printed_origin = 0; + npp = htp->h_tab; + nppend = npp + htp->h_size; + while (npp < nppend) { + for (np = *npp++; np != NULL; np = np->n_next) { + if (np->n_data == NULL) + continue; + /* Blecch - can't tell if there is data here for the + * right zone, so can't print name yet + */ + found_data = 0; + /* we want a snapshot in time... */ + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + /* Is the data for this zone? */ + if (zone != DB_Z_ALL && dp->d_zone != zone) + continue; + /* XXX why are we not calling stale() here? */ + if (dp->d_zone == DB_Z_CACHE && + dp->d_ttl <= (u_int32_t)tt.tv_sec && + (dp->d_flags & DB_F_HINT) == 0) + continue; + if (!printed_origin) { + fprintf(fp, "$ORIGIN %s.\n", origin); + printed_origin++; + } + tab = 0; + if (dp->d_rcode == NXDOMAIN || + dp->d_rcode == NOERROR_NODATA) { + fputc(';', fp); + } else if (found_data == 0 || found_data == 1) { + found_data = 2; + } + if (found_data == 0 || found_data == 2) { + if (NAME(*np)[0] == '\0') { + if (origin[0] == '\0') + fprintf(fp, ".\t"); + else + fprintf(fp, ".%s.\t", origin); /* ??? */ + } else + fprintf(fp, "%s\t", NAME(*np)); + if (NAMELEN(*np) < (unsigned)8) + tab = 1; + found_data++; + } else { + (void) putc('\t', fp); + tab = 1; + } + if (dp->d_zone == DB_Z_CACHE) { + if (dp->d_flags & DB_F_HINT && + (int32_t)(dp->d_ttl - tt.tv_sec) + < DB_ROOT_TIMBUF) + fprintf(fp, "%d\t", DB_ROOT_TIMBUF); + else + fprintf(fp, "%d\t", + (int)(dp->d_ttl - tt.tv_sec)); + } else if (dp->d_ttl != USE_MINIMUM && + dp->d_ttl != zones[dp->d_zone].z_minimum) + fprintf(fp, "%d\t", (int)dp->d_ttl); + else if (tab) + (void) putc('\t', fp); + fprintf(fp, "%s\t%s\t", + p_class(dp->d_class), + p_type(dp->d_type)); + cp = (u_char *)dp->d_data; + sep = "\t;"; + type = dp->d_type; + if (dp->d_rcode == NXDOMAIN || + dp->d_rcode == NOERROR_NODATA) { +#ifdef RETURNSOA + if (dp->d_size == 0) { +#endif + + fprintf(fp, "%s%s-$", + (dp->d_rcode == NXDOMAIN) + ?"NXDOMAIN" :"NODATA", + sep); + goto eoln; +#ifdef RETURNSOA + } else { + type = T_SOA; + } +#endif + } + /* + * Print type specific data + */ + /* XXX why are we not using ns_sprintrr() here? */ + switch (type) { + case T_A: + switch (dp->d_class) { + case C_IN: + case C_HS: + fputs(inet_ntoa(ina_get(cp)), fp); + break; + } + if (dp->d_nstime) { + fprintf(fp, "%sNT=%d", + sep, dp->d_nstime); + sep = " "; + } + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + fprintf(fp, "%s.", cp); + break; + + case T_NS: + cp = (u_char *)dp->d_data; + if (cp[0] == '\0') + fprintf(fp, ".\t"); + else + fprintf(fp, "%s.", cp); + break; + + case T_HINFO: + case T_ISDN: { + char buf[256]; + + if ((n = *cp++) != '\0') { + memcpy(buf, cp, n); buf[n] = '\0'; + fprintf(fp, "\"%.*s\"", (int)n, buf); + cp += n; + } else + fprintf(fp, "\"\""); + if ((n = *cp++) != '\0') { + memcpy(buf, cp, n); buf[n] = '\0'; + fprintf(fp, " \"%.*s\"", (int)n, buf); + } else + fprintf(fp, " \"\""); + break; + } + + case T_SOA: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s. (\n", cp); +#if defined(RETURNSOA) + if (dp->d_rcode) + fputs(";", fp); +#endif + cp += strlen((char *)cp) + 1; + NS_GET32(n, cp); + fprintf(fp, "\t\t%u", n); + NS_GET32(n, cp); + fprintf(fp, " %u", n); + NS_GET32(n, cp); + fprintf(fp, " %u", n); + NS_GET32(n, cp); + fprintf(fp, " %u", n); + NS_GET32(n, cp); + fprintf(fp, " %u )", n); +#if defined(RETURNSOA) + if (dp->d_rcode) { + fprintf(fp,";%s.;%s%s-$",cp, + (dp->d_rcode == NXDOMAIN) ? + "NXDOMAIN" : "NODATA", + sep); + } +#endif + break; + + case T_MX: + case T_AFSDB: + case T_RT: + NS_GET16(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + break; + + case T_PX: + NS_GET16(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + + case T_X25: + if ((n = *cp++) != '\0') + fprintf(fp, " \"%.*s\"", (int)n, cp); + else + fprintf(fp, " \"\""); + break; + + case T_TXT: + end = (u_char *)dp->d_data + dp->d_size; + while (cp < end) { + (void) putc('"', fp); + if ((n = *cp++) != '\0') { + for (j = n ; j > 0 && cp < end ; j--) { + if (*cp == '\n' || *cp == '"' || *cp == '\\') + (void) putc('\\', fp); + (void) putc(*cp++, fp); + } + } + (void) putc('"', fp); + if (cp < end) + (void) putc(' ', fp); + } + break; + + case T_NSAP: + (void) fputs(inet_nsap_ntoa(dp->d_size, + dp->d_data, NULL), + fp); + break; + + case T_AAAA: { + char t[sizeof + "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" + ]; + + (void) fputs(inet_ntop(AF_INET6, dp->d_data, + t, sizeof t), + fp); + break; + } + + case T_LOC: { + char t[256]; + + (void) fputs(loc_ntoa(dp->d_data, t), fp); + break; + } + + case T_NAPTR: { + u_int32_t order, preference; + + NS_GET16(order, cp); + fprintf(fp, "%u", order); + + NS_GET16(preference, cp); + fprintf(fp, "%u", preference); + + if ((n = *cp++) != 0) { + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + } + if ((n = *cp++) != 0) { + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + } + if ((n = *cp++) != 0) { + fprintf(fp, " \"%.*s\"", (int)n, cp); + cp += n; + } + fprintf(fp, " %s.", cp); + + break; + } + + case T_SRV: { + u_int priority, weight, port; + + NS_GET16(priority, cp); + NS_GET16(weight, cp); + NS_GET16(port, cp); + fprintf(fp, "\t%u %u %u %s.", + priority, weight, port, cp); + break; + } + + case T_WKS: + fputs(inet_ntoa(ina_get(cp)), fp); + cp += INADDRSZ; + proto = protocolname(*cp); + cp += sizeof(char); + fprintf(fp, " %s ", proto); + i = 0; + while(cp < (u_char *)dp->d_data + dp->d_size) { + j = *cp++; + do { + if (j & 0200) + fprintf(fp, " %s", + servicename(i, proto)); + j <<= 1; + } while (++i & 07); + } + break; + + case T_MINFO: + case T_RP: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + + case T_KEY: + savecp = cp; /* save the beginning */ + /*>>> Flags (unsigned_16) */ + NS_GET16(keyflags,cp); + fprintf(fp, "0x%04x ", keyflags); + /*>>> Protocol (8-bit decimal) */ + fprintf(fp, "%3u ", *cp++); + /*>>> Algorithm id (8-bit decimal) */ + fprintf(fp, "%3u ", *cp++); + + /*>>> Public-Key Data (multidigit BASE64) */ + /* containing ExponentLen, Exponent, and Modulus */ + i = b64_ntop(cp, dp->d_size - (cp - savecp), + temp_base64, + sizeof temp_base64); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + + case T_SIG: + sigdata = cp; + /* RRtype (char *) */ + NS_GET16(n,cp); + fprintf(fp, "%s ", p_type(n)); + /* Algorithm id (8-bit decimal) */ + fprintf(fp, "%d ", *cp++); + /* Labels (8-bit decimal) (not saved in file) */ + /* FIXME -- check value and print err if bad */ + cp++; + /* OTTL (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%u ", n); + /* Texp (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%s ", p_secstodate (n)); + /* Tsig (u_long) */ + NS_GET32(n, cp); + fprintf(fp, "%s ", p_secstodate (n)); + /* Kfootprint (unsigned_16) */ + NS_GET16(n, cp); + fprintf(fp, "%u ", n); + /* Signer's Name (char *) */ + fprintf(fp, "%s ", cp); + cp += strlen((char *)cp) + 1; + /* Signature (base64 of any length) */ + i = b64_ntop(cp, dp->d_size - (cp - sigdata), + temp_base64, + sizeof temp_base64); + if (i < 0) + fprintf(fp, "; BAD BASE64"); + else + fprintf(fp, "%s", temp_base64); + break; + + case T_NXT: + fprintf(fp, "%s.", cp); + n = strlen ((char *)cp) + 1; + cp += n; + i = 8 * (dp->d_size - n); /* How many bits? */ + for (n = 0; n < (u_int32_t)i; n++) { + if (NS_NXT_BIT_ISSET(n, cp)) + fprintf(fp," %s",__p_type(n)); + } + break; + + default: + fprintf(fp, "%s?d_type=%d?", + sep, dp->d_type); + sep = " "; + } + if (dp->d_cred < DB_C_ZONE) { + fprintf(fp, "%sCr=%s", + sep, MkCredStr(dp->d_cred)); + sep = " "; + } else { + fprintf(fp, "%sCl=%d", + sep, dp->d_clev); + sep = " "; + } + eoln: + if (dp->d_ns != NULL){ + fprintf(fp, "%s[%s]", + sep, inet_ntoa(dp->d_ns->addr)); + sep = " "; + } + putc('\n', fp); + } + } + } + if (ferror(fp)) + return (NODBFILE); + + npp = htp->h_tab; + nppend = npp + htp->h_size; + while (npp < nppend) { + for (np = *npp++; np != NULL; np = np->n_next) { + if (np->n_hash == NULL) + continue; + getname(np, dname, sizeof(dname)); + if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE) + return (NODBFILE); + } + } + return (OK); +} + +static const char * +MkCredStr(int cred) { + static char badness[20]; + + switch (cred) { + case DB_C_ZONE: return "zone"; + case DB_C_AUTH: return "auth"; + case DB_C_ANSWER: return "answer"; + case DB_C_ADDITIONAL: return "addtnl"; + case DB_C_CACHE: return "cache"; + default: break; + } + sprintf(badness, "?%d?", cred); + return (badness); +} diff --git a/contrib/bind/bin/named/db_func.h b/contrib/bind/bin/named/db_func.h new file mode 100644 index 0000000..2d4c05b --- /dev/null +++ b/contrib/bind/bin/named/db_func.h @@ -0,0 +1,151 @@ +/* Copyright (c) 1985, 1990 + * 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) 1996, 1997 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. + */ + +/* db_proc.h - prototypes for functions in db_*.c + * + * $Id: db_func.h,v 8.22 1997/12/04 06:47:00 halley Exp $ + */ + +/* ++from db_update.c++ */ +extern int db_update(const char *name, + struct databuf *odp, + struct databuf *newdp, + struct databuf **savedpp, + int flags, + struct hashbuf *htp, + struct sockaddr_in from), + db_cmp(const struct databuf *, const struct databuf *), + findMyZone(struct namebuf *np, int class); +void fixttl(struct databuf *dp); +/* --from db_update.c-- */ + +/* ++from db_save.c++ */ +extern struct namebuf *savename(const char *, int); +extern struct databuf *savedata(int, int, u_int32_t, u_char *, int); +extern struct hashbuf *savehash(struct hashbuf *); +/* --from db_save.c-- */ + +/* ++from db_dump.c++ */ +extern int db_dump(struct hashbuf *, FILE *, int, char *), + zt_dump(FILE *); +extern void doadump(void); +/* --from db_dump.c-- */ + +/* ++from db_load.c++ */ +extern void endline(FILE *); +extern int getword(char *, size_t, FILE *, int), + getnum(FILE *, const char *, int), + db_load(const char *, const char *, + struct zoneinfo *, const char *); +extern int getnonblank(FILE *, const char *), + getservices(int, char *, FILE *, const char *); +extern char getprotocol(FILE *, const char *); +extern int makename(char *, const char *, int); +#ifdef BIND_NOTIFY +extern void notify_after_load(evContext, void *, const void *), + db_cancel_pending_notifies(void); +#endif +/* --from db_load.c-- */ + +/* ++from db_glue.c++ */ +extern void buildservicelist(void), + destroyservicelist(void), + buildprotolist(void), + destroyprotolist(void), + getname(struct namebuf *, char *, int); +extern int servicenumber(const char *), + protocolnumber(const char *), + get_class(const char *), + samedomain(const char *, const char *); +extern u_int dhash(const u_char *, int), + nhash(const char *); +extern const char *protocolname(int), + *servicename(u_int16_t, const char *); +#ifndef BSD +extern int getdtablesize(void); +#endif +extern struct databuf *rm_datum(struct databuf *, + struct namebuf *, + struct databuf *, + struct databuf **); +extern struct namebuf *rm_name(struct namebuf *, + struct namebuf **, + struct namebuf *); +extern void rm_hash(struct hashbuf *); +extern void db_freedata(struct databuf *); +/* --from db_glue.c-- */ + +/* ++from db_lookup.c++ */ +extern struct namebuf *nlookup(const char *, struct hashbuf **, + const char **, int); +extern struct namebuf *np_parent __P((struct namebuf *)); +extern int match(struct databuf *, int, int); +/* --from db_lookup.c-- */ + +/* ++from db_dict.c++ */ +int dict_lookup(const char *, int, int); +/* --from db_dict.c-- */ diff --git a/contrib/bind/bin/named/db_glob.h b/contrib/bind/bin/named/db_glob.h new file mode 100644 index 0000000..79d915d --- /dev/null +++ b/contrib/bind/bin/named/db_glob.h @@ -0,0 +1,94 @@ +/* + * from db.h 4.16 (Berkeley) 6/1/90 + * $Id: db_glob.h,v 8.8 1997/06/09 17:46:51 halley Exp $ + */ + +/* Copyright (c) 1985, 1990 + * 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) 1996, 1997 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. + */ + +/* + * Global variables for data base routines. + */ + + /* ONE_WEEK maximum ttl */ +DECL u_int max_cache_ttl INIT(7*24*60*60); + + /* no minimum ttl */ +DECL u_int min_cache_ttl INIT(0); + + /* current line number */ +DECL int lineno; + + /* root hash table */ +DECL struct hashbuf *hashtab INIT(NULL); + + /* hash table of cache read from file */ +DECL struct hashbuf *fcachetab INIT(NULL); + +#ifdef FORCED_RELOAD +DECL int reloading INIT(0); +#endif /* FORCED_RELOAD */ diff --git a/contrib/bind/bin/named/db_glue.c b/contrib/bind/bin/named/db_glue.c new file mode 100644 index 0000000..bc6aed4 --- /dev/null +++ b/contrib/bind/bin/named/db_glue.c @@ -0,0 +1,616 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)db_glue.c 4.4 (Berkeley) 6/1/90"; +static char rcsid[] = "$Id: db_glue.c,v 8.27 1998/02/14 00:41:39 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988 + * 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) 1996, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +struct valuelist { + struct valuelist * next; + struct valuelist * prev; + char * name; + char * proto; + int port; +}; +static struct valuelist *servicelist, *protolist; + +void +buildservicelist() { + struct servent *sp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setservent(0); +#else + setservent(1); +#endif + while ((sp = getservent()) != NULL) { + slp = (struct valuelist *)memget(sizeof(struct valuelist)); + if (!slp) + panic("memget(servent)", NULL); + slp->name = savestr(sp->s_name, 1); + slp->proto = savestr(sp->s_proto, 1); + slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */ + slp->next = servicelist; + slp->prev = NULL; + if (servicelist) + servicelist->prev = slp; + servicelist = slp; + } + endservent(); +} + +void +destroyservicelist() { + struct valuelist *slp, *slp_next; + + for (slp = servicelist; slp != NULL; slp = slp_next) { + slp_next = slp->next; + freestr(slp->name); + freestr(slp->proto); + memput(slp, sizeof *slp); + } +} + +void +buildprotolist() { + struct protoent *pp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setprotoent(0); +#else + setprotoent(1); +#endif + while ((pp = getprotoent()) != NULL) { + slp = (struct valuelist *)memget(sizeof(struct valuelist)); + if (!slp) + panic("memget(protoent)", NULL); + slp->name = savestr(pp->p_name, 1); + slp->port = pp->p_proto; /* host byte order */ + slp->next = protolist; + slp->prev = NULL; + if (protolist) + protolist->prev = slp; + protolist = slp; + } + endprotoent(); +} + +void +destroyprotolist() { + struct valuelist *plp, *plp_next; + + for (plp = protolist; plp != NULL; plp = plp_next) { + plp_next = plp->next; + freestr(plp->name); + memput(plp, sizeof *plp); + } +} + +static int +findservice(const char *s, struct valuelist **list) { + struct valuelist *lp = *list; + int n; + + for (; lp != NULL; lp = lp->next) + if (strcasecmp(lp->name, s) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + return (lp->port); /* host byte order */ + } + if (sscanf(s, "%d", &n) != 1 || n <= 0) + n = -1; + return (n); +} + +/* + * Convert service name or (ascii) number to int. + */ +int +servicenumber(const char *p) { + return (findservice(p, &servicelist)); +} + +/* + * Convert protocol name or (ascii) number to int. + */ +int +protocolnumber(const char *p) { + return (findservice(p, &protolist)); +} + +static struct servent * +cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */ + struct valuelist **list = &servicelist; + struct valuelist *lp = *list; + static struct servent serv; + + port = ntohs(port); + for (; lp != NULL; lp = lp->next) { + if (port != (u_int16_t)lp->port) /* Host byte order. */ + continue; + if (strcasecmp(lp->proto, proto) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + serv.s_name = lp->name; + serv.s_port = htons((u_int16_t)lp->port); + serv.s_proto = lp->proto; + return (&serv); + } + } + return (0); +} + +static struct protoent * +cgetprotobynumber(int proto) { /* Host byte order. */ + struct valuelist **list = &protolist; + struct valuelist *lp = *list; + static struct protoent prot; + + for (; lp != NULL; lp = lp->next) + if (lp->port == proto) { /* Host byte order. */ + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + prot.p_name = lp->name; + prot.p_proto = lp->port; /* Host byte order. */ + return (&prot); + } + return (0); +} + +const char * +protocolname(int num) { + static char number[8]; + struct protoent *pp; + + pp = cgetprotobynumber(num); + if (pp == 0) { + (void) sprintf(number, "%d", num); + return (number); + } + return (pp->p_name); +} + +const char * +servicename(u_int16_t port, const char *proto) { /* Host byte order. */ + static char number[8]; + struct servent *ss; + + ss = cgetservbyport(htons(port), proto); + if (ss == 0) { + (void) sprintf(number, "%d", port); + return (number); + } + return (ss->s_name); +} + +static struct map map_class[] = { + { "in", C_IN }, + { "chaos", C_CHAOS }, + { "hs", C_HS }, + { NULL, 0 } +}; + +int +get_class(const char *class) { + const struct map *mp; + + if (isdigit(*class)) + return (atoi(class)); + for (mp = map_class; mp->token != NULL; mp++) + if (strcasecmp(class, mp->token) == 0) + return (mp->val); + return (C_IN); +} + +/* rm_datum(dp, np, pdp, savedpp) + * remove datum 'dp' from name 'np'. pdp is previous data pointer. + * if savedpp is not NULL, and compiled with BIND_UPDATE, save + * datum dp there rather than freeing the memory (caller will take + * care of freeing it) + * return value: + * "next" field from removed datum, suitable for relinking + */ +struct databuf * +rm_datum(struct databuf *dp, struct namebuf *np, struct databuf *pdp, + struct databuf **savedpp) { + struct databuf *ndp = dp->d_next; + + ns_debug(ns_log_db, 3, "rm_datum(%lx, %lx, %lx, %lx) -> %lx", + (u_long)dp, (u_long)np->n_data, (u_long)pdp, + (u_long)savedpp, (u_long)ndp); + if ((dp->d_flags & DB_F_ACTIVE) == 0) + panic("rm_datum: DB_F_ACTIVE not set", NULL); + if (pdp == NULL) + np->n_data = ndp; + else + pdp->d_next = ndp; +#ifdef BIND_UPDATE + if (savedpp != NULL) { + /* mark deleted or pending deletion */ + dp->d_mark |= D_MARK_DELETED; + dp->d_next = *savedpp; + *savedpp = dp; + } else + dp->d_next = NULL; +#else + dp->d_next = NULL; +#endif + dp->d_flags &= ~DB_F_ACTIVE; + DRCNTDEC(dp); + if (dp->d_rcnt) { +#ifdef DEBUG + int32_t ii; +#endif + + switch(dp->d_type) { + case T_NS: + ns_debug(ns_log_db, 3, "rm_datum: %s rcnt = %d", + dp->d_data, dp->d_rcnt); + break; +#ifdef DEBUG + case T_A: + memcpy(&ii, dp->d_data, sizeof ii); + ns_debug(ns_log_db, 3, + "rm_datum: %08.8X rcnt = %d", + ii, dp->d_rcnt); + break; +#endif + default: + ns_debug(ns_log_db, 3, + "rm_datum: rcnt = %d", dp->d_rcnt); + } + } else +#ifdef BIND_UPDATE + if (savedpp == NULL) +#endif + db_freedata(dp); + return (ndp); +} + +/* rm_name(np, he, pnp) + * remove name 'np' from parent 'pp'. pnp is previous name pointer. + * return value: + * "next" field from removed name, suitable for relinking. + */ +struct namebuf * +rm_name(struct namebuf *np, struct namebuf **pp, struct namebuf *pnp) { + struct namebuf *nnp = np->n_next; + const char *msg; + + /* verify */ + if ( (np->n_data && (msg = "data")) + || (np->n_hash && (msg = "hash")) + ) { + ns_panic(ns_log_db, 1, "rm_name(%#x(%s)): non-nil %s pointer", + np, NAME(*np), msg); + } + + /* unlink */ + if (pnp) + pnp->n_next = nnp; + else + *pp = nnp; + + /* deallocate */ + memput(np, NAMESIZE(NAMELEN(*np))); + + /* done */ + return (nnp); +} + +void +rm_hash(struct hashbuf *htp) { + REQUIRE(htp != NULL); + REQUIRE(htp->h_cnt == 0); + + memput(htp, HASHSIZE(htp->h_size)); +} + +/* + * Get the domain name of 'np' and put in 'buf'. Bounds checking is done. + */ +void +getname(struct namebuf *np, char *buf, int buflen) { + char *cp; + int i; + + cp = buf; + while (np != NULL) { + i = (int) NAMELEN(*np); + if (i + 1 >= buflen) { + *cp = '\0'; + ns_info(ns_log_db, + "domain name too long: %s...", buf); + strcpy(buf, "Name_Too_Long"); + return; + } + if (cp != buf) + *cp++ = '.'; + memcpy(cp, NAME(*np), i); + cp += i; + buflen -= i + 1; + np = np->n_parent; + } + *cp = '\0'; +} + +/* + * Compute hash value from data. + */ +u_int +dhash(const u_char *dp, int dlen) { + u_char *cp; + u_int hval; + int n; + + n = dlen; + if (n > 8) + n = 8; + hval = 0; + while (--n >= 0) { + hval <<= 1; + hval += *dp++; + } + return (hval % INVHASHSZ); +} + +/* u_int + * nhash(name) + * compute hash for this name and return it; ignore case differences + */ +u_int +nhash(const char *name) { + u_char ch; + u_int hval; + + hval = 0; + while ((ch = (u_char)*name++) != (u_char)'\0') { + if (isascii(ch) && isupper(ch)) + ch = tolower(ch); + hval <<= 1; + hval += ch; + } + return (hval % INVHASHSZ); +} + +/* +** SAMEDOMAIN -- Check whether a name belongs to a domain +** ------------------------------------------------------ +** +** Returns: +** TRUE if the given name lies in the domain. +** FALSE otherwise. +** +** Trailing dots are first removed from name and domain. +** Always compare complete subdomains, not only whether the +** domain name is the trailing string of the given name. +** +** "host.foobar.top" lies in "foobar.top" and in "top" and in "" +** but NOT in "bar.top" +*/ + +int +samedomain(const char *a, const char *b) { + size_t la, lb; + int diff, i, escaped; + const char *cp; + + la = strlen(a); + lb = strlen(b); + + /* ignore a trailing label separator (i.e. an unescaped dot) in 'a' */ + if (la && a[la-1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if la==1 */ + for (i = la - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else { + break; + } + if (!escaped) + la--; + } + /* ignore a trailing label separator (i.e. an unescaped dot) in 'b' */ + if (lb && b[lb-1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if lb==1 */ + for (i = lb - 2; i >= 0; i--) + if (b[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else { + break; + } + if (!escaped) + lb--; + } + + /* lb==0 means 'b' is the root domain, so 'a' must be in 'b'. */ + if (lb == 0) + return (1); + + /* 'b' longer than 'a' means 'a' can't be in 'b'. */ + if (lb > la) + return (0); + + /* We use strncasecmp because we might be trying to + * ignore a trailing dot. */ + if (lb == la) + return (strncasecmp(a, b, lb) == 0); + + /* Ok, we know la > lb. */ + + diff = la - lb; + + /* If 'a' is only 1 character longer than 'b', then it can't be + a subdomain of 'b' (because of the need for the '.' label + separator). */ + if (diff < 2) + return (0); + + /* If the character before the last 'lb' characters of 'b' + isn't '.', then it can't be a match (this lets us avoid + having "foobar.com" match "bar.com"). */ + if (a[diff-1] != '.') + return (0); + + /* We're not sure about that '.', however. It could be escaped + and thus not a really a label separator. */ + escaped=0; + for (i = diff-2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } + else + break; + if (escaped) + return (0); + + /* We use strncasecmp because we might be trying to + * ignore trailing dots. */ + cp = a + diff; + return (strncasecmp(cp, b, lb) == 0); +} + +void +db_freedata(struct databuf *dp) { + int bytes = (dp->d_type == T_NS) ? + DATASIZE(dp->d_size)+INT32SZ : DATASIZE(dp->d_size); + + if (dp->d_rcnt != 0) + panic("db_freedata: d_rcnt != 0", NULL); + if ((dp->d_flags & (DB_F_ACTIVE|DB_F_FREE)) != 0) + panic("db_freedata: %s set", + (dp->d_flags & DB_F_FREE) != 0 ? "DB_F_FREE" : + "DB_F_ACTIVE"); + if (dp->d_next != NULL) + panic("db_free: d_next != NULL", NULL); + dp->d_flags |= DB_F_FREE; + memput(dp, bytes); +} diff --git a/contrib/bind/bin/named/db_load.c b/contrib/bind/bin/named/db_load.c new file mode 100644 index 0000000..d05a969 --- /dev/null +++ b/contrib/bind/bin/named/db_load.c @@ -0,0 +1,2218 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91"; +static char rcsid[] = "$Id: db_load.c,v 8.41 1998/02/13 20:02:28 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988, 1990 + * 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, 1997 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. + */ + +/* + * Load zone from ASCII file on local host. Format similar to RFC 883. + */ + +/* Import. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +/* Forward. */ + +static int gettoken(FILE *, const char *); +static int getttl(FILE *, const char *, int, u_int32_t *, int *); +static int getcharstring(char *, char *, int, int, int, FILE *, + const char *); +static int makename_ok(char *name, const char *origin, int class, + struct zoneinfo *zp, + enum transport transport, + enum context context, + const char *owner, const char *filename, + int lineno, int size); +static int getmlword(char *, size_t, FILE *, int); +static int getallwords(char *, size_t, FILE *, int); +static u_int32_t wordtouint32(char *); +static int datepart(const char *, int, int, int, int *); +static u_int32_t datetosecs(const char *, int *); +static int get_nxt_types(u_char *, FILE *, const char *); +static void fixup_soa(const char *fn, struct zoneinfo *zp); +#ifdef BIND_NOTIFY +static void notify_after_delay(evContext ctx, void *uap, + struct timespec due, + struct timespec inter); +#endif +static int wordtouint32_error = 0; +static int empty_token = 0; +static int getmlword_nesting = 0; + +/* Global. */ + +static int clev; /* a zone deeper in a hierarchy has more credibility */ + +#ifdef BIND_NOTIFY +static notify_info_list pending_notifies; +#endif + +/* + * Parser token values + */ +#define CURRENT 1 +#define DOT 2 +#define AT 3 +#define DNAME 4 +#define INCLUDE 5 +#define ORIGIN 6 +#define ERROR 7 + +#define MAKENAME_OK(N) \ + do { \ + if (!makename_ok(N, origin, class, zp, \ + transport, context, \ + domain, filename, lineno, \ + sizeof(data) - ((u_char*)N - data))) { \ + errs++; \ + sprintf(buf, "bad name \"%s\"", N); \ + goto err; \ + } \ + } while (0) + +/* Public. */ + +/* int + * db_load(filename, in_origin, zp, def_domain) + * load a database from `filename' into zone `zp'. append `in_origin' + * to all nonterminal domain names in the file. `def_domain' is the + * default domain for include files or NULL for zone base files. + * returns: + * -1 = can't open file + * 0 = success + * >0 = number of errors encountered + */ +int +db_load(const char *filename, const char *in_origin, + struct zoneinfo *zp, const char *def_domain) +{ + static int read_soa, read_ns, rrcount; + + const char *errtype = "Database"; + char *cp; + char domain[MAXDNAME], origin[MAXDNAME], tmporigin[MAXDNAME]; + char buf[MAXDATA]; + u_char data[MAXDATA]; + const char *op; + int c, someclass, class, type, dbflags, dataflags, multiline; + int slineno, i, errs, didinclude, escape, success, dateerror; + u_int32_t ttl, n, serial; + u_long tmplong; + struct databuf *dp; + FILE *fp; + struct stat sb; + struct in_addr ina; + enum transport transport; + enum context context; + u_int32_t sig_type; + u_int32_t keyflags; + struct sockaddr_in empty_from; + + empty_from.sin_family = AF_INET; + empty_from.sin_addr.s_addr = htonl(INADDR_ANY); + empty_from.sin_port = htons(0); + +/* + * We use an 'if' inside of the 'do' below because otherwise the Solaris + * compiler detects that the 'while' is never executed because of the 'goto' + * and complains. + */ +#define ERRTO(msg) do { if (1) { errtype = msg; goto err; } } while (0) + + switch (zp->z_type) { + case Z_PRIMARY: + case Z_CACHE: + transport = primary_trans; + break; + case Z_SECONDARY: + case Z_STUB: + transport = secondary_trans; + break; + default: + transport = response_trans; /*guessing*/ + break; + } + errs = 0; + didinclude = 0; + if (!def_domain) { + /* This is not the result of a $INCLUDE. */ + rrcount = 0; + read_soa = 0; + read_ns = 0; + clev = nlabels(in_origin); + } + + ns_debug(ns_log_load, 1, "db_load(%s, %s, %d, %s)", + filename, in_origin, zp - zones, + def_domain ? def_domain : "Nil"); + + strcpy(origin, in_origin); + if ((fp = fopen(filename, "r")) == NULL) { + ns_warning(ns_log_load, "%s: %s", filename, strerror(errno)); + return (-1); + } + if (zp->z_type == Z_CACHE) { + dbflags = DB_NODATA | DB_NOHINTS; + dataflags = DB_F_HINT; +#ifdef STUBS + } else if (zp->z_type == Z_STUB && clev == 0) { + dbflags = DB_NODATA | DB_NOHINTS; + dataflags = DB_F_HINT; +#endif + } else { + dbflags = DB_NODATA; + dataflags = 0; + } + gettime(&tt); + if (fstat(fileno(fp), &sb) < 0) { + ns_warning(ns_log_load, "%s: %s", filename, strerror(errno)); + sb.st_mtime = (int)tt.tv_sec; + } + slineno = lineno; + lineno = 1; + if (def_domain) + strcpy(domain, def_domain); + else + domain[0] = '\0'; + class = zp->z_class; + zp->z_flags &= ~(Z_INCLUDE|Z_DB_BAD); + while ((c = gettoken(fp, filename)) != EOF) { + switch (c) { + case INCLUDE: + if (!getword(buf, sizeof buf, fp, 0)) + /* file name*/ + break; + if (!getword(tmporigin, sizeof(tmporigin), fp, 1)) + strcpy(tmporigin, origin); + else { + if (makename(tmporigin, origin, + sizeof(tmporigin)) == -1) + ERRTO("$INCLUDE makename failed"); + endline(fp); + } + didinclude = 1; + errs += db_load(buf, tmporigin, zp, domain); + continue; + + case ORIGIN: + (void) strcpy(buf, origin); + if (!getword(origin, sizeof(origin), fp, 1)) + break; + ns_debug(ns_log_load, 3, "db_load: origin %s, buf %s", + origin, buf); + if (makename(origin, buf, sizeof(origin)) == -1) + ERRTO("$ORIGIN makename failed"); + ns_debug(ns_log_load, 3, "db_load: origin now %s", + origin); + continue; + + case DNAME: + if (!getword(domain, sizeof(domain), fp, 1)) + break; + if (makename(domain, origin, sizeof(domain)) == -1) + ERRTO("ownername makename failed"); + goto gotdomain; + + case AT: + (void) strcpy(domain, origin); + goto gotdomain; + + case DOT: + domain[0] = '\0'; + /* FALLTHROUGH */ + case CURRENT: + gotdomain: + if (!getword(buf, sizeof buf, fp, 0)) { + if (c == CURRENT) + continue; + break; + } + if (ns_parse_ttl(buf, &tmplong) < 0) + ttl = USE_MINIMUM; + else { + ttl = (u_int32_t)tmplong; + if (ttl > MAXIMUM_TTL) { + ns_info(ns_log_load, + "%s: Line %d: TTL > %u; converted to 0", + filename, lineno, MAXIMUM_TTL); + ttl = 0; + } + if (zp->z_type == Z_CACHE) { + /* + * This allows the cache entry to age + * while sitting on disk (powered off). + */ + if (ttl > max_cache_ttl) + ttl = max_cache_ttl; + ttl += sb.st_mtime; + } + if (!getword(buf, sizeof buf, fp, 0)) + break; + } + + /* Parse class (IN, etc) */ + someclass = sym_ston(__p_class_syms, buf, &success); + if (success && someclass != C_ANY) { + class = someclass; + (void) getword(buf, sizeof buf, fp, 0); + } + + /* Parse RR type (A, MX, etc) */ + type = sym_ston(__p_type_syms, buf, &success); + if (success == 0 || type == ns_t_any) { + ns_info(ns_log_load, + "%s: Line %d: Unknown type: %s.", + filename, lineno, buf); + errs++; + break; + } + + context = ns_ownercontext(type, transport); + if (!ns_nameok(domain, class, zp, transport, context, + domain, inaddr_any)) { + errs++; + ns_notice(ns_log_load, + "%s:%d: owner name error", + filename, lineno); + break; + } + context = domain_ctx; + switch (type) { + case ns_t_key: + case ns_t_sig: + case ns_t_nxt: + /* + * Don't do anything here for these types -- + * they read their own input separately later. + */ + goto dont_get_word; + + case ns_t_soa: + case ns_t_minfo: + case ns_t_rp: + case ns_t_ns: + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ptr: + escape = 1; + break; + default: + escape = 0; + } + if (!getword(buf, sizeof buf, fp, escape)) + break; + ns_debug(ns_log_load, 3, + "d='%s', c=%d, t=%d, ttl=%u, data='%s'", + domain, class, type, ttl, buf); + /* + * Convert the ascii data 'buf' to the proper format + * based on the type and pack into 'data'. + */ + dont_get_word: + switch (type) { + case ns_t_a: + if (!inet_aton(buf, &ina)) + ERRTO("IP Address"); + (void) ina_put(ina, data); + n = NS_INT32SZ; + break; + + case ns_t_soa: + context = hostname_ctx; + goto soa_rp_minfo; + case ns_t_rp: + case ns_t_minfo: + context = mailname_ctx; + /* FALLTHROUGH */ + soa_rp_minfo: + (void) strcpy((char *)data, buf); + + MAKENAME_OK((char *)data); + cp = (char *)(data + strlen((char *)data) + 1); + if (!getword(cp, + (sizeof data) - + (cp - (char*)data), + fp, 1)) + ERRTO("Domain Name"); + if (type == ns_t_rp) + context = domain_ctx; + else + context = mailname_ctx; + MAKENAME_OK(cp); + cp += strlen((char *)cp) + 1; + if (type != ns_t_soa) { + n = cp - (char *)data; + break; + } + if (class != zp->z_class) { + errs++; + ns_info(ns_log_load, "%s:%d: %s", + filename, lineno, + "SOA class not same as zone's"); + } + if (strcasecmp(zp->z_origin, domain) != 0) { + errs++; + ns_error(ns_log_load, + "%s:%d: SOA for \"%s\" not at zone top \"%s\"", + filename, lineno, domain, + zp->z_origin); + } + c = getnonblank(fp, filename); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + serial = zp->z_serial; + zp->z_serial = getnum(fp, filename, + GETNUM_SERIAL); + if (getnum_error) + errs++; + n = (u_int32_t) zp->z_serial; + PUTLONG(n, cp); + if (serial != 0 && + SEQ_GT(serial, zp->z_serial)) { + ns_notice(ns_log_load, + "%s:%d: WARNING: new serial number < old (%lu < %lu)", + filename , lineno, + zp->z_serial, serial); + } + if (getttl(fp, filename, lineno, &n, + &multiline) <= 0) { + errs++; + n = INIT_REFRESH; + } + PUTLONG(n, cp); + zp->z_refresh = MAX(n, MIN_REFRESH); + if (zp->z_type == Z_SECONDARY +#if defined(STUBS) + || zp->z_type == Z_STUB +#endif + ) { + ns_refreshtime(zp, MIN(sb.st_mtime, + tt.tv_sec)); + sched_zone_maint(zp); + } +#ifdef BIND_UPDATE + if ((zp->z_type == Z_PRIMARY) && + (zp->z_flags & Z_DYNAMIC)) + if ((u_int32_t)zp->z_soaincrintvl > + zp->z_refresh/3) { + ns_info(ns_log_load, + "zone soa update time truncated to 1/3rd of refresh time"); + zp->z_soaincrintvl = + zp->z_refresh / 3; + } +#endif + + if (getttl(fp, filename, lineno, &n, + &multiline) <= 0) { + errs++; + n = INIT_REFRESH; + } + PUTLONG(n, cp); + zp->z_retry = MAX(n, MIN_RETRY); + if (getttl(fp, filename, lineno, + &zp->z_expire, &multiline) <= 0) { + errs++; + zp->z_expire = INIT_REFRESH; + } + n = zp->z_expire; + PUTLONG(n, cp); + if (getttl(fp, filename, lineno, &n, + &multiline) <= 0) { + errs++; + n = 120; + } + PUTLONG(n, cp); + if (n > MAXIMUM_TTL) { + ns_info(ns_log_load, + "%s: Line %d: SOA minimum TTL > %u; converted to 0", + filename, lineno, MAXIMUM_TTL); + zp->z_minimum = 0; + } else + zp->z_minimum = n; + n = cp - (char *)data; + if (multiline) { + buf[0] = getnonblank(fp, filename); + buf[1] = '\0'; + if (buf[0] != ')') + ERRTO("SOA \")\""); + endline(fp); + } + read_soa++; + if (zp->z_type == Z_PRIMARY) + fixup_soa(filename, zp); + break; + + case ns_t_wks: + /* Address */ + if (!inet_aton(buf, &ina)) + ERRTO("WKS IP Address"); + (void) ina_put(ina, data); + /* Protocol */ + data[INADDRSZ] = getprotocol(fp, filename); + /* Services */ + n = getservices(NS_INT32SZ + sizeof(char), + (char *)data, fp, filename); + break; + + case ns_t_ns: + if (strcasecmp(zp->z_origin, domain) == 0) + read_ns++; + context = hostname_ctx; + goto cname_etc; + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + context = domain_ctx; + goto cname_etc; + case ns_t_ptr: + context = ns_ptrcontext(domain); + cname_etc: + (void) strcpy((char *)data, buf); + MAKENAME_OK((char *)data); + n = strlen((char *)data) + 1; + break; + + case ns_t_naptr: + /* Order Preference Flags Service Replacement Regexp */ + n = 0; + cp = buf; + /* Order */ + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + if (cp == buf || n > 65535) + ERRTO("NAPTR Order"); + cp = (char *)data; + PUTSHORT((u_int16_t)n, cp); + + /* Preference */ + n = getnum(fp, filename, GETNUM_NONE); + if (getnum_error || n > 65536) + ERRTO("NAPTR Preference"); + PUTSHORT((u_int16_t)n, cp); + + /* Flags */ + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("NAPTR Flags"); + n = strlen(buf); + *cp++ = n; + memcpy(cp, buf, (int)n); + cp += n; + + /* Service Classes */ + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("NAPTR Service Classes"); + n = strlen(buf); + *cp++ = n; + memcpy(cp, buf, (int)n); + cp += n; + + /* Pattern */ + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("NAPTR Pattern"); + n = strlen(buf); + *cp++ = n; + memcpy(cp, buf, (int)n); + cp += n; + + /* Replacement */ + if (!getword(buf, sizeof buf, fp, 1)) + ERRTO("NAPTR Replacement"); + (void) strcpy((char *)cp, buf); + context = domain_ctx; + MAKENAME_OK(cp); + /* advance pointer to end of data */ + cp += strlen((char *)cp) +1; + + /* now save length */ + n = (cp - (char *)data); + break; + + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + case ns_t_srv: + n = 0; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + if ((cp == buf) || (n > 65535)) + ERRTO("Priority"); + cp = (char *)data; + PUTSHORT((u_int16_t)n, cp); + + if (type == ns_t_srv) { + n = getnum(fp, filename, GETNUM_NONE); + if (getnum_error || n > 65536) + ERRTO("SRV RR"); + PUTSHORT((u_int16_t)n, cp); + + n = getnum(fp, filename, GETNUM_NONE); + if (getnum_error || n > 65536) + ERRTO("SRV RR"); + PUTSHORT((u_int16_t)n, cp); + } + + if (!getword(buf, sizeof buf, fp, 1)) + ERRTO("Domain Name"); + (void) strcpy((char *)cp, buf); + context = hostname_ctx; + MAKENAME_OK(cp); + /* advance pointer to end of data */ + cp += strlen((char *)cp) +1; + + /* now save length */ + n = (cp - (char *)data); + break; + + case ns_t_px: + context = domain_ctx; + n = 0; + data[0] = '\0'; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + if ((cp == buf) || (n > 65535)) + ERRTO("PX Priority"); + cp = (char *)data; + PUTSHORT((u_int16_t)n, cp); + + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("PX Domain1"); + (void) strcpy((char *)cp, buf); + MAKENAME_OK(cp); + /* advance pointer to next field */ + cp += strlen((char *)cp) + 1; + if (!getword(buf, sizeof buf, fp, 0)) + ERRTO("PX Domain2"); + (void) strcpy((char *)cp, buf); + MAKENAME_OK(cp); + /* advance pointer to end of data */ + cp += strlen((char *)cp) + 1; + + /* now save length */ + n = (cp - (char *)data); + break; + + case ns_t_hinfo: + n = getcharstring(buf, (char *)data, type, + 2, 2, fp, filename); + if (n == 0) + ERRTO("HINFO RR"); + break; + + case ns_t_isdn: + n = getcharstring(buf, (char *)data, type, + 1, 2, fp, filename); + if (n == 0) + ERRTO("ISDN RR"); + break; + + case ns_t_txt: + n = getcharstring(buf, (char *)data, type, + 1, 0, fp, filename); + if (n == 0) + ERRTO("TXT RR"); + break; + + + case ns_t_x25: + n = getcharstring(buf, (char *)data, type, + 1, 1, fp, filename); + if (n == 0) + ERRTO("X25 RR"); + break; + + case ns_t_nsap: + n = inet_nsap_addr(buf, (u_char *)data, + sizeof data); + if (n == 0) + ERRTO("NSAP RR"); + endline(fp); + break; + + case ns_t_aaaa: + if (inet_pton(AF_INET6, buf, data) <= 0) + ERRTO("IPv4 Address"); + n = NS_IN6ADDRSZ; + endline(fp); + break; + + case ns_t_key: { + /* The KEY record looks like this in the db file: + * Name Cl KEY Flags Proto Algid PublicKeyData + * where: + * Name,Cl per usual + * KEY RR type + * Flags 4 digit hex value (unsigned_16) + * Proto 8 bit u_int + * Algid 8 bit u_int + * PublicKeyData + * a string of base64 digits, + * skipping any embedded whitespace. + */ + u_int32_t al, pr; + int nk, klen; + char *expstart; + u_int expbytes, modbytes; + + i = 0; + data[i] = '\0'; + cp = (char *)data; + getmlword_nesting = 0; /* KLUDGE err recov. */ + /*>>> Flags (unsigned_16) */ + if (!getmlword((char*)buf, sizeof buf, fp, 0)) + ERRTO("KEY Flags Field"); + keyflags = wordtouint32(buf); + if (wordtouint32_error || 0xFFFF < keyflags) + goto err; + if (keyflags & NS_KEY_RESERVED_BITMASK) + ERRTO("KEY Reserved Flag Bit"); + PUTSHORT(keyflags, cp); + + /*>>> Protocol (8-bit decimal) */ + if (!getmlword((char*)buf, sizeof buf, fp, 0)) + ERRTO("KEY Protocol Field"); + pr = wordtouint32(buf); + if (wordtouint32_error || 255 < pr) + ERRTO("KEY Protocol Field"); + *cp++ = (u_char) pr; + + /*>>> Algorithm id (8-bit decimal) */ + if (!getmlword((char*)buf, sizeof buf, fp, 0)) + ERRTO("KEY Algorithm ID"); + al = wordtouint32(buf); + if (wordtouint32_error || + 0 == al || 255 == al || 255 < al) + ERRTO("KEY Algorithm ID"); + *cp++ = (u_char) al; + + /*>>> Public Key data is in BASE64. + * We don't care what algorithm it uses or what + * the internal structure of the BASE64 data is. + */ + if (!getallwords(buf, MAXDATA, fp, 0)) + klen = 0; + else { + /* Convert from BASE64 to binary. */ + klen = b64_pton(buf, (u_char*)cp, + sizeof data - + (cp - (char *)data)); + if (klen < 0) + ERRTO("KEY Public Key"); + } + + /* set total length */ + n = cp + klen - (char *)data; + + /* + * Now check for valid key flags & algs & etc, + * from the RFC. + */ + + if (keyflags & (NS_KEY_ZONEKEY | NS_KEY_IPSEC + | NS_KEY_EMAIL)) + pr |= 1; /* A nonzero proto. */ + if (NS_KEY_TYPE_NO_KEY == + (keyflags & NS_KEY_TYPEMASK)) + nk = 1; /* No-key */ + else + nk = 0; /* have a key */ + + if ((keyflags & NS_KEY_ZONEKEY) && + (NS_KEY_TYPE_CONF_ONLY == + (keyflags & NS_KEY_TYPEMASK))) + /* Zone key must have Auth bit set. */ + ERRTO("KEY Zone Key Auth. bit"); + + if (al == 0 && nk == 0) + ERRTO("KEY Algorithm"); + if (al != 0 && pr == 0) + ERRTO("KEY Protocols"); + + if (nk == 1 && klen != 0) + ERRTO("KEY No-Key Flags Set"); + + if (nk == 0 && klen == 0) + ERRTO("KEY Type Spec'd"); + + /* Check algorithm-ID and key structure, for + the algorithm-ID's that we know about. */ + switch (al) { + case NS_ALG_MD5RSA: + if (klen == 0) + break; + expstart = cp; + expbytes = *expstart++; + if (expbytes == 0) + GETSHORT(expbytes, expstart); + + if (expbytes < 1) + ERRTO("Exponent too short"); + if (expbytes > + (NS_MD5RSA_MAX_BITS + 7) / 8 + ) + ERRTO("Exponent too long"); + if (*expstart == 0) + ERRTO("Exponent w/ 0"); + + modbytes = klen - + (expbytes + (expstart - cp)); + if (modbytes < + (NS_MD5RSA_MIN_BITS + 7) / 8 + ) + ERRTO("Modulus too short"); + if (modbytes > + (NS_MD5RSA_MAX_BITS + 7) / 8 + ) + ERRTO("Modulus too long"); + if (*(expstart+expbytes) == 0) + ERRTO("Modulus starts w/ 0"); + break; + + case NS_ALG_EXPIRE_ONLY: + if (klen != 0) + ERRTO( + "Key provided for expire-only algorithm" + ); + break; + case NS_ALG_PRIVATE_OID: + if (klen == 0) + ERRTO("No ObjectID in key"); + break; + } + + endline(fp); /* flush the rest of the line */ + break; + } /*T_KEY*/ + + case ns_t_sig: + { + /* The SIG record looks like this in the db file: + Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig + + where: Name and Cl are as usual + SIG is a keyword + RRtype is a char string + ALGid is 8 bit u_int + OTTL is 32 bit u_int (optionally present) + Texp is YYYYMMDDHHMMSS + Tsig is YYYYMMDDHHMMSS + Kfoot is 16-bit unsigned decimal integer + Signer is a char string + Sig is 64 to 319 base-64 digits + A missing OTTL is detected by the magnitude of the Texp value + that follows it, which is larger than any u_int. + The Labels field in the binary RR does not appear in the + text RR. + + It's too crazy to run these pages of SIG code at the right + margin. I'm exdenting them for readability. + */ + int siglen; + u_int32_t al; + u_int32_t signtime, exptime, timetilexp; + u_int32_t origTTL; + time_t now; + + /* The TTL gets checked against the Original TTL, + and bounded by the signature expiration time, which + are both under the signature. We can't let TTL drift + based on the SOA record. If defaulted, fix it now. + (It's not clear to me why USE_MINIMUM isn't eliminated + before putting ALL RR's into the database. -gnu@toad.com) */ + if (ttl == USE_MINIMUM) + ttl = zp->z_minimum; + + i = 0; + data[i] = '\0'; + getmlword_nesting = 0; /* KLUDGE err recovery */ + + /* RRtype (char *) */ + if (!getmlword((char*)buf, sizeof buf, fp, 0)) + ERRTO("SIG record doesn't specify type"); + sig_type = sym_ston(__p_type_syms, buf, &success); + if (!success || sig_type == ns_t_any) { + /* + * We'll also accept a numeric RR type, + * for signing RR types that this version + * of named doesn't yet understand. + * In the ns_t_any case, we rely on wordtouint32 + * to fail when scanning the string "ANY". + */ + sig_type = wordtouint32 (buf); + if (wordtouint32_error || sig_type > 0xFFFF) + ERRTO("Unknown RR type in SIG record"); + } + cp = (char *)&data[i]; + PUTSHORT((u_int16_t)sig_type, cp); + i += 2; + + /* Algorithm id (8-bit decimal) */ + if (!getmlword(buf, sizeof buf, fp, 0)) + ERRTO("Missing algorithm ID"); + al = wordtouint32(buf); + if (0 == al || wordtouint32_error || 255 <= al) + goto err; + data[i] = (u_char) al; + i++; + + /* + * Labels (8-bit decimal) + * Not given in the file. Must compute. + */ + n = dn_count_labels(domain); + if (0 >= n || 255 < n) + ERRTO("SIG label count invalid"); + data[i] = (u_char) n; + i++; + + /* + * OTTL (optional u_int32_t) and + * Texp (u_int32_t date) + */ + if (!getmlword(buf, sizeof buf, fp, 0)) + ERRTO("OTTL and expiration time missing"); + /* + * See if OTTL is missing and this is a date. + * This relies on good, silent error checking + * in datetosecs. + */ + exptime = datetosecs(buf, &dateerror); + if (!dateerror) { + /* Output TTL as OTTL */ + origTTL = ttl; + cp = (char *)&data[i]; + PUTLONG (origTTL, cp); + i += 4; + } else { + /* Parse and output OTTL; scan TEXP */ + origTTL = wordtouint32(buf); + if (0 >= origTTL || wordtouint32_error || + (origTTL > 0x7fffffff)) + goto err; + cp = (char *)&data[i]; + PUTLONG(origTTL, cp); + i += 4; + if (!getmlword(buf, sizeof buf, fp, 0)) + ERRTO("Expiration time missing"); + exptime = datetosecs(buf, &dateerror); + } + if (dateerror || exptime > 0x7fffffff || exptime <= 0) + ERRTO("Invalid expiration time"); + cp = (char *)&data[i]; + PUTLONG(exptime, cp); + i += 4; + + /* Tsig (u_int32_t) */ + if (!getmlword(buf, sizeof buf, fp, 0)) + ERRTO("Missing signature time"); + signtime = datetosecs(buf, &dateerror); + if (0 == signtime || dateerror) + ERRTO("Invalid signature time"); + cp = (char *)&data[i]; + PUTLONG(signtime, cp); + i += 4; + + /* Kfootprint (unsigned_16) */ + if (!getmlword(buf, sizeof buf, fp, 0)) + ERRTO("Missing key footprint"); + n = wordtouint32(buf); + if (wordtouint32_error || n >= 0x0ffff) + ERRTO("Invalid key footprint"); + cp = (char *)&data[i]; + PUTSHORT((u_int16_t)n, cp); + i += 2; + + /* Signer's Name */ + if (!getmlword((char*)buf, sizeof buf, fp, 0)) + ERRTO("Missing signer's name"); + cp = (char *)&data[i]; + strcpy(cp,buf); + context = domain_ctx; + MAKENAME_OK(cp); + i += strlen(cp) + 1; + + /* + * Signature (base64 of any length) + * We don't care what algorithm it uses or what + * the internal structure of the BASE64 data is. + */ + if (!getallwords(buf, sizeof buf, fp, 0)) { + siglen = 0; + } else { + cp = (char *)&data[i]; + siglen = b64_pton(buf, (u_char*)cp, sizeof data - i); + if (siglen < 0) + goto err; + } + + /* set total length and we're done! */ + n = i + siglen; + + /* + * Check signature time, expiration, and adjust TTL. Note + * that all time values are in GMT (UTC), *not* local time. + */ + + now = time (0); + + /* Don't let bogus name servers increase the signed TTL */ + if (ttl > origTTL) + ERRTO("TTL is greater than signed original TTL"); + + /* Don't let bogus signers "sign" in the future. */ + if (signtime > (u_int32_t)now) + ERRTO("signature time is in the future"); + + /* Ignore received SIG RR's that are already expired. */ + if (exptime <= (u_int32_t)now) + ERRTO("expiration time is in the past"); + + /* Lop off the TTL at the expiration time. */ + timetilexp = exptime - now; + if (timetilexp < ttl) { + ns_debug(ns_log_load, 1, + "shrinking expiring %s SIG TTL from %d to %d", + p_secstodate(exptime), ttl, timetilexp); + ttl = timetilexp; + } + + /* + * Check algorithm-ID and key structure, for + * the algorithm-ID's that we know about. + */ + switch (al) { + case NS_ALG_MD5RSA: + if (siglen == 0) + ERRTO("No key for RSA algorithm"); + if (siglen < 1) + ERRTO("Signature too short"); + if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8) + ERRTO("Signature too long"); + /* We rely on cp from parse */ + if (*cp == 0) + ERRTO("Signature starts with zeroes"); + break; + + case NS_ALG_EXPIRE_ONLY: + if (siglen != 0) + ERRTO( + "Signature supplied to expire-only algorithm"); + break; + case NS_ALG_PRIVATE_OID: + if (siglen == 0) + ERRTO("No ObjectID in key"); + break; + } + + /* Should we complain about algorithm-ID's that we + don't understand? It may help debug some obscure + cases, but in general we should accept any RR whether + we could cryptographically process it or not; it + may be being published for some newer DNS clients + to validate themselves. */ + + endline(fp); /* flush the rest of the line */ + + break; /* Accept this RR. */ + } + + case ns_t_nxt: + /* The NXT record looks like: + Name Cl NXT nextname RRT1 RRT2 MX A SOA ... + + where: Name and Cl are as usual + NXT is a keyword + nextname is the next valid name in + the zone after "Name". All + names between the two are + known to be nonexistent. + RRT's... are a series of RR type + names, which indicate that + RR's of these types are + published for "Name", and + that no RR's of any other + types are published for + "Name". + + When a NXT record is cryptographically + signed, it proves the nonexistence of an + RR (actually a whole set of RR's). */ + + getmlword_nesting = 0; /* KLUDGE err recov. */ + if (!getmlword(buf, sizeof buf, fp, 1)) + goto err; + (void) strcpy((char *)data, buf); + MAKENAME_OK((char *)data); + n = strlen((char *)data) + 1; + cp = n + (char *)data; + n += get_nxt_types((u_char *)cp, fp, filename); + break; + + case ns_t_loc: + cp = buf + (n = strlen(buf)); + *cp = ' '; + cp++; + while ((i = getc(fp), *cp = i, i != EOF) + && *cp != '\n' + && (n < MAXDATA)) { + cp++; n++; + } + if (*cp == '\n') /* leave \n for getword */ + ungetc(*cp, fp); + *cp = '\0'; + /* now process the whole line */ + n = loc_aton(buf, (u_char *)data); + if (n == 0) + goto err; + endline(fp); + break; + + default: + goto err; + } + /* + * Ignore data outside the zone. + */ + if (zp->z_type != Z_CACHE && + !samedomain(domain, zp->z_origin)) + { + ns_info(ns_log_load, + "%s:%d: data \"%s\" outside zone \"%s\" (ignored)", + filename, lineno, domain, + zp->z_origin); + continue; + } + dp = savedata(class, type, (u_int32_t)ttl, + (u_char *)data, (int)n); + dp->d_zone = zp - zones; + dp->d_flags = dataflags; + dp->d_cred = DB_C_ZONE; + dp->d_clev = clev; + if ((c = db_update(domain, dp, dp, NULL, dbflags, + (dataflags & DB_F_HINT) + ? fcachetab + : hashtab, empty_from)) + != OK) { + if (c != DATAEXISTS) + ns_debug(ns_log_load, 1, + "update failed %s %d", + domain, type); + db_freedata(dp); + } else { + rrcount++; + } + continue; + + case ERROR: + break; + } + err: + errs++; + ns_notice(ns_log_load, "%s:%d: %s error (%s)", + filename, empty_token ? (lineno - 1) : lineno, + errtype, buf); + if (!empty_token) + endline(fp); + } + (void) my_fclose(fp); + lineno = slineno; + if (!def_domain) { + if (didinclude) { + zp->z_flags |= Z_INCLUDE; + zp->z_ftime = 0; + } else + zp->z_ftime = sb.st_mtime; + zp->z_lastupdate = sb.st_mtime; + if (zp->z_type != Z_CACHE) { + const char *msg = NULL; + + if (read_soa == 0) + msg = "no SOA RR found"; + else if (read_soa != 1) + msg = "multiple SOA RRs found"; + else if (read_ns == 0) + msg = "no NS RRs found at zone top"; + else if (!rrcount) + msg = "no relevant RRs found"; + if (msg != NULL) { + errs++; + ns_warning(ns_log_load, + "Zone \"%s\" (file %s): %s", + zp->z_origin, filename, msg); + } + } + } + if (!def_domain) { + if (errs) + ns_warning(ns_log_load, + "%s zone \"%s\" (%s) rejected due to errors (serial %u)", + zoneTypeString(zp), zp->z_origin, + p_class(zp->z_class), zp->z_serial); + else + ns_info(ns_log_load, + "%s zone \"%s\" (%s) loaded (serial %u)", + zoneTypeString(zp), zp->z_origin, + p_class(zp->z_class), zp->z_serial); + } + if (errs) { + zp->z_flags |= Z_DB_BAD; + zp->z_ftime = 0; + } +#ifdef BIND_NOTIFY + if (!errs && !def_domain && + (zp->z_type == z_master || zp->z_type == z_slave)) { + static const char no_room[] = + "%s failed, cannot notify for zone %s"; + notify_info ni; + + ni = memget(sizeof *ni); + if (ni == NULL) + ns_info(ns_log_load, no_room, "memget", zp->z_origin); + else { + ni->name = savestr(zp->z_origin, 0); + if (ni->name == NULL) { + memput(ni, sizeof *ni); + ns_info(ns_log_load, no_room, + "memget", zp->z_origin); + } else { + ni->class = zp->z_class; + ni->state = notify_info_waitfor; + if (evWaitFor(ev, + (const void *)notify_after_load, + notify_after_load, ni, + &ni->wait_id) < 0) { + ns_error(ns_log_load, + "evWaitFor() failed: %s", + strerror(errno)); + freestr(ni->name); + memput(ni, sizeof *ni); + } else { + APPEND(pending_notifies, ni, link); + ns_need(MAIN_NEED_NOTIFY); + } + } + } + } +#endif + return (errs); +} + +static int +gettoken(FILE *fp, const char *src) { + int c; + char op[32]; + + for (;;) { + c = getc(fp); + top: + switch (c) { + case EOF: + return (EOF); + + case '$': + if (getword(op, sizeof op, fp, 0)) { + if (!strcasecmp("include", op)) + return (INCLUDE); + if (!strcasecmp("origin", op)) + return (ORIGIN); + } + ns_notice(ns_log_db, + "%s:%d: Unknown $ option: $%s", + src, lineno, op); + return (ERROR); + + case ';': + while ((c = getc(fp)) != EOF && c != '\n') + ; + goto top; + + case ' ': + case '\t': + return (CURRENT); + + case '.': + return (DOT); + + case '@': + return (AT); + + case '\n': + lineno++; + continue; + + default: + (void) ungetc(c, fp); + return (DNAME); + } + } +} + +/* int + * getword(buf, size, fp, preserve) + * get next word, skipping blanks & comments. + * '\' '\n' outside of "quotes" is considered a blank. + * parameters: + * buf - destination + * size - of destination + * fp - file to read from + * preserve - should we preserve \ before \\ and \.? + * return value: + * 0 = no word; perhaps EOL or EOF; lineno was incremented. + * 1 = word was read + */ +int +getword(char *buf, size_t size, FILE *fp, int preserve) { + char *cp = buf; + int c, spaceok; + + empty_token = 0; /* XXX global side effect. */ + while ((c = getc(fp)) != EOF) { + if (c == ';') { + /* Comment. Skip to end of line. */ + while ((c = getc(fp)) != EOF && c != '\n') + (void)NULL; + c = '\n'; + } + if (c == '\n') { + /* + * Unescaped newline. It's a terminator unless we're + * already midway into a token. + */ + if (cp != buf) + ungetc(c, fp); + else + lineno++; + break; + } + if (c == '"') { + /* "Quoted string." Gather the whole string here. */ + while ((c = getc(fp)) != EOF && c!='"' && c!='\n') { + if (c == '\\') { + if ((c = getc(fp)) == EOF) + c = '\\'; + if (preserve) + switch (c) { + case '\\': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (cp >= buf+size-1) + break; + *cp++ = '\\'; + } + if (c == '\n') + lineno++; + } + if (cp >= buf+size-1) + break; + *cp++ = c; + } + /* + * Newline string terminators are + * not token terminators. + */ + if (c == '\n') { + lineno++; + break; + } + /* Sample following character, check for terminator. */ + if ((c = getc(fp)) != EOF) + ungetc(c, fp); + if (c == EOF || isspace(c)) { + *cp = '\0'; + return (1); + } + continue; + } + spaceok = 0; + if (c == '\\') { + /* Do escape processing. */ + if ((c = getc(fp)) == EOF) + c = '\\'; + if (preserve) + switch (c) { + case '\\': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (cp >= buf+size-1) + break; + *cp++ = '\\'; + } + if (c == ' ' || c == '\t') + spaceok++; + } + if (isspace(c) && !spaceok) { + /* Blank of some kind. Skip run. */ + while (isspace(c = getc(fp)) && c != '\n') + (void)NULL; + ungetc(c, fp); + /* Blank means terminator if the token is nonempty. */ + if (cp != buf) /* Trailing whitespace */ + break; + continue; /* Leading whitespace */ + } + if (cp >= buf + size - 1) + break; + *cp++ = (char)c; + } + *cp = '\0'; + if (cp == buf) + empty_token = 1; + return (cp != buf); +} + +/* + * int + * getttl(fp, fn, ln, ttl, multiline) + * read a word from the file and parse it as a TTL. + * return: + * 1 ttl found + * 0 word not read (EOF or EOL?) + * -1 word read but it wasn't a ttl + * side effects: + * *ttl is written if the return value is to be 1. + */ +static int +getttl(FILE *fp, const char *fn, int lineno, u_int32_t *ttl, int *multiline) { + char buf[MAXDATA]; + u_long tmp; + int ch; + int len; + + while (!feof(fp) && !getword(buf, sizeof buf, fp, 0) && *multiline) + (void)NULL; + len = strlen(buf); + if (*multiline && len && buf[len-1] == ')') { + buf[len-1] = '\0'; + *multiline = 0; + } + if (ns_parse_ttl(buf, &tmp) < 0) { + ns_notice(ns_log_db, "%s:%d: expected a TTL, got \"%s\"", + fn, lineno, buf); + return (-1); + } + if (*multiline) { + ch = getnonblank(fp, fn); + if (ch == EOF) + return (-1); + if (ch == ';') + endline(fp); + else + ungetc(ch, fp); + } + *ttl = (u_int32_t)tmp; + return (1); +} + +/* Get multiline words. Same parameters as getword. Handles any + number of leading ('s or )'s in the words it sees. + FIXME: We kludge recognition of ( and ) for multiline input. + Each paren must appear at the start of a (blank-separated) word, + which is particularly counter-intuitive for ). Good enough for now, + until Paul rewrites the parser. (gnu@toad.com, oct96) +*/ +static int +getmlword(char *buf, size_t size, FILE *fp, int preserve) { + char *p; + + do { + while (!getword (buf, size, fp, preserve)) { + /* No more words on this line. See if doing the + multiline thing. */ + if (!getmlword_nesting) { /* Nope... */ + ungetc('\n', fp); /* Push back newline */ + lineno--; /* Unbump the lineno */ + empty_token = 0; /* Undo this botch */ + return 0; + } + if (feof(fp) || ferror(fp)) + return 0; /* Error, no terminating ')' */ + /* Continue reading til we get a word... */ + } + while ('(' == *buf) { + /* Word starts with paren. Multiline mode. + Move the rest of the word down over the paren. */ + getmlword_nesting++; + p = buf; + while (0 != (p[0]=p[1])) p++; + } + while (')' == *buf) { + getmlword_nesting--; + p = buf; + while (0 != (p[0]=p[1])) p++; + } + } while (buf[0] == 0); /* loop til we get a non-( non-) word */ + + return 1; /* Got a word... */ +} + +/* Get all the remaining words on a line, concatenated into one big + long (not too long!) string, with the whitespace squeezed out. + This routine, like getword(), does not swallow the newline if words seen. + This routine, unlike getword(), never swallows the newline if no words. + Parameters are the same as getword(). Result is: + 0 got no words at all + 1 got one or more words + -1 got too many words, they don't all fit; or missing close paren +*/ +static int +getallwords(char *buf, size_t size, FILE *fp, int preserve) { + char *runningbuf = buf; + int runningsize = size; + int len; + + while (runningsize > 0) { + if (!getmlword (runningbuf, runningsize, fp, preserve)) { + return runningbuf!=buf; /* 1 or 0 */ + } + len = strlen(runningbuf); + runningbuf += len; + runningsize -= len; + } + return -1; /* Error, String too long */ +} + +int +getnum(FILE *fp, const char *src, int opt) { + int c, n; + int seendigit = 0; + int seendecimal = 0; + int m = 0; + int allow_dots = 0; + + getnum_error = 0; +#ifdef DOTTED_SERIAL + if (opt & GETNUM_SERIAL) + allow_dots++; +#endif + for (n = 0; (c = getc(fp)) != EOF; ) { + if (isspace(c)) { + if (c == '\n') + lineno++; + if (seendigit) + break; + continue; + } + if (c == ';') { + while ((c = getc(fp)) != EOF && c != '\n') + ; + if (c == '\n') + lineno++; + if (seendigit) + break; + continue; + } + if (getnum_error) + continue; + if (!isdigit(c)) { + if (c == ')' && seendigit) { + (void) ungetc(c, fp); + break; + } + if (seendigit && (opt & GETNUM_SCALED) && + strchr("KkMmGg", c) != NULL) { + switch (c) { + case 'K': case 'k': + n *= 1024; + break; + case 'M': case 'm': + n *= (1024 * 1024); + break; + case 'G': case 'g': + n *= (1024 * 1024 * 1024); + break; + } + break; + } + if (seendecimal || c != '.' || !allow_dots) { + ns_notice(ns_log_db, + "%s:%d: expected a number", + src, lineno); + getnum_error = 1; + } else { + if (!seendigit) + n = 1; +#ifdef SENSIBLE_DOTS + n *= 10000; +#else + n *= 1000; +#endif + seendigit = 1; + seendecimal = 1; + } + continue; + } +#ifdef SENSIBLE_DOTS + if (seendecimal) + m = m * 10 + (c - '0'); + else + n = n * 10 + (c - '0'); +#else + n = n * 10 + (c - '0'); +#endif + seendigit = 1; + } + if (getnum_error) + return (0); + if (m > 9999) { + ns_info(ns_log_db, + "%s:%d: number after the decimal point exceeds 9999", + src, lineno); + getnum_error = 1; + return (0); + } + if (seendecimal) { + ns_info(ns_log_db, + "%s:%d: decimal serial number interpreted as %d", + src, lineno, n+m); + } + return (n + m); +} + +#ifndef BIND_UPDATE +static +#endif +int +getnonblank(FILE *fp, const char *src) { + int c; + + while ((c = getc(fp)) != EOF) { + if (isspace(c)) { + if (c == '\n') + lineno++; + continue; + } + if (c == ';') { + while ((c = getc(fp)) != EOF && c != '\n') + ; + if (c == '\n') + lineno++; + continue; + } + return (c); + } + ns_info(ns_log_db, "%s:%d: unexpected EOF", src, lineno); + return (EOF); +} + +/* + * Take name and fix it according to following rules: + * "." means root. + * "@" means current origin. + * "name." means no changes. + * "name" means append origin. + */ +int +makename(char *name, const char *origin, int size) { + int n; + u_char domain[MAXCDNAME]; + + switch (ns_name_pton(name, domain, sizeof(domain))) { + case -1: + return (-1); + case 1: /* FULLY QUALIFIED */ + break; + case 0: /* UNQUALIFIED */ + if (strcmp(name, "@") == 0) /* must test raw name */ + domain[0] = 0; + if ((n = dn_skipname(domain, domain+sizeof(domain))) == -1) + return (-1); + /* step back over root, append origin */ + switch (ns_name_pton(origin, domain+n-1, sizeof(domain)-n+1)) { + case -1: + return (-1); + case 0: + case 1: + break; + } + break; + } + if (ns_name_ntop(domain, name, size) == -1) + return (-1); + if (name[0] == '.') /* root */ + name[0] = '\0'; + return (0); +} + +static int +makename_ok(char *name, const char *origin, int class, struct zoneinfo *zp, + enum transport transport, enum context context, + const char *owner, const char *filename, int lineno, int size) +{ + int ret = 1; + + if (makename(name, origin, size) == -1) { + ns_info(ns_log_db, "%s:%d: makename failed", + filename, lineno); + return (0); + } + if (!ns_nameok(name, class, zp, transport, context, owner, + inaddr_any)) { + ns_info(ns_log_db, "%s:%d: database naming error", + filename, lineno); + ret = 0; + } + return (ret); +} + +void +endline(FILE *fp) { + int c; + + while ((c = getc(fp)) != '\0') { + if (c == '\n') { + (void) ungetc(c,fp); + break; + } else if (c == EOF) { + break; + } + } +} + +#define MAXPORT 1024 +#define MAXLEN 24 + +#ifndef BIND_UPDATE +static +#endif +char +getprotocol(FILE *fp, const char *src) { + int k; + char b[MAXLEN]; + + (void) getword(b, sizeof(b), fp, 0); + + k = protocolnumber(b); + if (k == -1) + ns_info(ns_log_db, "%s:%d: unknown protocol: %s.", + src, lineno, b); + return ((char) k); +} + +#ifndef BIND_UPDATE +static +#endif +int +getservices(int offset, char *data, FILE *fp, const char *src) { + int j, ch, k, maxl, bracket; + char bm[MAXPORT/8]; + char b[MAXLEN]; + + for (j = 0; j < MAXPORT/8; j++) + bm[j] = 0; + maxl = 0; + bracket = 0; + while (getword(b, sizeof(b), fp, 0) || bracket) { + if (feof(fp) || ferror(fp)) + break; + if (strlen(b) == 0) + continue; + if (b[0] == '(') { + bracket++; + continue; + } + if (b[0] == ')') { + bracket = 0; + while ((ch = getc(fp)) != EOF && ch != '\n') + (void)NULL; + if (ch == '\n') + lineno++; + break; + } + k = servicenumber(b); + if (k == -1) { + ns_info(ns_log_db, + "%s:%d: Unknown service '%s'", + src, lineno, b); + continue; + } + if ((k < MAXPORT) && (k)) { + bm[k/8] |= (0x80>>(k%8)); + if (k > maxl) + maxl = k; + } else { + ns_info(ns_log_db, + "%s:%d: port no. (%d) too big", + src, lineno, k); + } + } + if (bracket) + ns_info(ns_log_db, "%s:%d: missing close paren", + src, lineno); + maxl = maxl/8+1; + memcpy(data+offset, bm, maxl); + return (maxl+offset); +} + +/* + * Converts a word to a u_int32_t. Error if any non-numeric + * characters in the word, except leading or trailing white space. + */ +static u_int32_t +wordtouint32(buf) + char *buf; +{ + u_long result; + u_int32_t res2; + char *bufend; + + wordtouint32_error = 0; + result = strtoul(buf, &bufend, 0); + if (bufend == buf) + wordtouint32_error = 1; + else + while ('\0' != *bufend) { + if (isspace(*bufend)) + bufend++; + else { + wordtouint32_error = 1; + break; + } + } + /* Check for truncation between u_long and u_int32_t */ + res2 = result; + if (res2 != result) + wordtouint32_error = 1; + return (res2); +} + + +/* + * Parse part of a date. Set error flag if any error. + * Don't reset the flag if there is no error. + */ +static int +datepart(const char *buf, int size, int min, int max, int *errp) { + int result = 0; + int i; + + for (i = 0; i < size; i++) { + if (!isdigit(buf[i])) + *errp = 1; + result = (result * 10) + buf[i] - '0'; + } + if (result < min) + *errp = 1; + if (result > max) + *errp = 1; + return (result); +} + + +/* Convert a date in ASCII into the number of seconds since + 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all + digits required, no spaces allowed. */ + +static u_int32_t +datetosecs(const char *cp, int *errp) { + struct tm time; + u_int32_t result; + int mdays, i; + static const int days_per_month[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (strlen(cp) != 14) { + *errp = 1; + return 0; + } + *errp = 0; + + memset(&time, 0, sizeof time); + time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; + time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; + time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); + time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); + time.tm_min = datepart(cp + 10, 2, 00, 59, errp); + time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); + if (*errp) /* Any parse errors? */ + return (0); + + /* + * OK, now because timegm() is not available in all environments, + * we will do it by hand. Roll up sleeves, curse the gods, begin! + */ + +#define SECS_PER_DAY ((u_int32_t)24*60*60) +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + + result = time.tm_sec; /* Seconds */ + result += time.tm_min * 60; /* Minutes */ + result += time.tm_hour * (60*60); /* Hours */ + result += (time.tm_mday - 1) * SECS_PER_DAY; /* Days */ + + /* Months are trickier. Look without leaping, then leap */ + mdays = 0; + for (i = 0; i < time.tm_mon; i++) + mdays += days_per_month[i]; + result += mdays * SECS_PER_DAY; /* Months */ + if (time.tm_mon > 1 && isleap (1900+time.tm_year)) + result += SECS_PER_DAY; /* Add leapday for this year */ + + /* First figure years without leapdays, then add them in. */ + /* The loop is slow, FIXME, but simple and accurate. */ + result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */ + for (i = 70; i < time.tm_year; i++) + if (isleap (1900+i)) + result += SECS_PER_DAY; /* Add leapday for prev year */ + + return (result); +} + + +#define MAXCHARSTRING 255 + +static int +getcharstring(char *buf, char *data, int type, + int minfields, int maxfields, + FILE *fp, const char *src) +{ + int nfield = 0, done = 0, n = 0, i; + char *b = buf; + + do { + nfield++; + i = strlen(buf); +#ifdef ALLOW_LONG_TXT_RDATA + b = buf; + if (type == ns_t_txt || type == ns_t_x25) { + while (i > MAXCHARSTRING + && n + MAXCHARSTRING + 1 < MAXDATA) { + data[n] = MAXCHARSTRING; + memmove(data + n + 1, b, MAXCHARSTRING); + n += MAXCHARSTRING + 1; + b += MAXCHARSTRING; + i -= MAXCHARSTRING; + } + } +#endif /* ALLOW_LONG_TXT_RDATA */ + if (i > MAXCHARSTRING) { + ns_info(ns_log_db, + "%s:%d: RDATA field %d too long", + src, lineno, nfield); + return (0); + } + if (n + i + 1 > MAXDATA) { + ns_info(ns_log_db, + "%s:%d: total RDATA too long", + src, lineno); + return (0); + } + data[n] = i; + memmove(data + n + 1, b, (int)i); + n += i + 1; + done = (maxfields && nfield >= maxfields); + } while (!done && getword(buf, MAXDATA, fp, 0)); + + if (nfield < minfields) { + ns_info(ns_log_db, + "%s:%d: expected %d RDATA fields, only saw %d", + src, lineno, minfields, nfield); + return (0); + } + + if (done) + endline(fp); + + return (n); +} + + +/* + * get_nxt_types(): Read the list of types in the NXT record. + * + * Data is the array where the bit flags are stored; it must + * contain at least ns_t_any/NS_NXT_BITS bytes. + * FP is the input FILE *. + * Filename is the sourcefile + * + * The result is how many bytes are significant in the result. + * ogud@tis.com 1995 + */ +static int +get_nxt_types(u_char *data, FILE *fp, const char *filename) { + char b[MAXLABEL]; /* Not quite the right size, but good enough */ + int maxtype=0; + int success; + int type; + int errs = 0; + + memset(data, 0, ns_t_any/NS_NXT_BITS+1); + + while (getmlword(b, sizeof(b), fp, 0)) { + if (feof(fp) || ferror(fp)) + break; + if (strlen(b) == 0 || b[0] == '\n') + continue; + + /* Parse RR type (A, MX, etc) */ + type = sym_ston(__p_type_syms, (char *)b, &success); + if ((!success) || type == ns_t_any) { + errs++; + ns_info(ns_log_db, + "%s: Line %d: Unknown type: %s in NXT record.", + filename, lineno, b); + continue; + } + NS_NXT_BIT_SET(type, data); + if (type > maxtype) + maxtype = type; + } + if (errs) + return (0); + else + return (maxtype/NS_NXT_BITS+1); +} + +/* sanity checks PRIMARY ONLY */ +static void +fixup_soa(const char *fn, struct zoneinfo *zp) { + /* Sanity: give enough time for the zone to transfer (retry). */ + if (zp->z_expire < (zp->z_refresh + zp->z_retry)) + ns_notice(ns_log_db, + "%s: WARNING SOA expire value is less than SOA refresh+retry (%u < %u+%u)", + fn, zp->z_expire, zp->z_refresh, zp->z_retry); + + /* Sanity. */ + if (zp->z_expire < (zp->z_refresh + 10 * zp->z_retry)) + ns_warning(ns_log_db, +"%s: WARNING SOA expire value is less than refresh + 10 * retry \ +(%u < (%u + 10 * %u))", + fn, zp->z_expire, zp->z_refresh, zp->z_retry); + + /* + * Sanity: most hardware/telco faults are detected and fixed within + * a week, secondaries should continue to operate for this time. + * (minimum of 4 days for long weekends) + */ + if (zp->z_expire < (7 * 24 * 3600)) + ns_warning(ns_log_db, + "%s: WARNING SOA expire value is less than 7 days (%u)", + fn, zp->z_expire); + + /* + * Sanity: maximum down time if we havn't talked for six months + * war must have broken out. + */ + if (zp->z_expire > ( 183 * 24 * 3600)) + ns_warning(ns_log_db, + "%s: WARNING SOA expire value is greater than 6 months (%u)", + fn, zp->z_expire); + + /* Sanity. */ + if (zp->z_refresh < (zp->z_retry * 2)) + ns_warning(ns_log_db, + "%s: WARNING SOA refresh value is less than 2 * retry (%u < %u * 2)", + fn, zp->z_refresh, zp->z_retry); +} + +#ifdef BIND_NOTIFY +static void +free_notify_info(notify_info ni) { + if (ni->state == notify_info_waitfor) + evUnwait(ev, ni->wait_id); + else if (ni->state == notify_info_delay) + evClearTimer(ev, ni->timer_id); + freestr(ni->name); + memput(ni, sizeof *ni); +} + +void +notify_after_load(evContext ctx, void *uap, const void *tag) { + int delay, max_delay; + notify_info ni = uap; + + INSIST(tag == (const void *)notify_after_load); + + /* delay notification for from five seconds up to fifteen minutes */ + max_delay = MIN(nzones/5, 895); + max_delay = MAX(max_delay, 25); + delay = 5 + (rand() % max_delay); + ns_debug(ns_log_notify, 3, "notify_after_load: uap %p tag %p delay %d", + uap, tag, delay); + if (evSetTimer(ctx, notify_after_delay, ni, + evAddTime(evNowTime(), evConsTime(delay, 0)), + evConsTime(0, 0), &ni->timer_id) < 0) { + ns_error(ns_log_notify, "evSetTimer() failed: %s", + strerror(errno)); + UNLINK(pending_notifies, ni, link); + ni->state = notify_info_error; + free_notify_info(ni); + } + ni->state = notify_info_delay; +} + +static void +notify_after_delay(evContext ctx, void *uap, + struct timespec due, + struct timespec inter) +{ + notify_info ni = uap; + + UNLINK(pending_notifies, ni, link); + ni->state = notify_info_done; + sysnotify(ni->name, ni->class, ns_t_soa); + free_notify_info(ni); +} + +void +db_cancel_pending_notifies(void) { + notify_info ni, ni_next; + for (ni = HEAD(pending_notifies); ni != NULL; ni = ni_next) { + ni_next = NEXT(ni, link); + free_notify_info(ni); + } + INIT_LIST(pending_notifies); +} +#endif diff --git a/contrib/bind/bin/named/db_lookup.c b/contrib/bind/bin/named/db_lookup.c new file mode 100644 index 0000000..ddf17ad --- /dev/null +++ b/contrib/bind/bin/named/db_lookup.c @@ -0,0 +1,269 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)db_lookup.c 4.18 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: db_lookup.c,v 8.13 1998/02/13 19:52:54 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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) 1996, 1997 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. + */ + +/* + * Table lookup routines. + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" + +/* + * Lookup 'name' and return a pointer to the namebuf; + * NULL otherwise. If 'insert', insert name into tables. + * Wildcard lookups are handled. + */ +struct namebuf * +nlookup(const char *name, struct hashbuf **htpp, + const char **fname, int insert) +{ + struct namebuf *np; + const char *cp; + int c; + u_int hval; + struct hashbuf *htp; + struct namebuf *parent = NULL; + int escaped = 0; + + htp = *htpp; + hval = 0; + *fname = "???"; + for (cp = name; (c = *cp++) != 0; (void)NULL) { + if (!escaped && (c == '.')) { + parent = np = nlookup(cp, htpp, fname, insert); + if (np == NULL) + return (NULL); + if (*fname != cp) + return (np); + if ((htp = np->n_hash) == NULL) { + if (!insert) { + if (ns_wildcard(NAME(*np))) + *fname = name; + return (np); + } + htp = savehash((struct hashbuf *)NULL); + np->n_hash = htp; + } + *htpp = htp; + break; + } + + /* rotate left HASHSHIFT */ + hval = (hval << HASHSHIFT) | + (hval>>((sizeof(hval)*8)-HASHSHIFT)); + hval += ((isascii(c) && isupper(c)) ? tolower(c) : c) + & HASHMASK; + if (escaped) + escaped = 0; + else if (c == '\\') + escaped = 1; + } + cp--; + /* + * Lookup this label in current hash table. + */ + for (np = htp->h_tab[hval % htp->h_size]; + np != NULL; + np = np->n_next) { + if (np->n_hashval == hval && + ((size_t)NAMELEN(*np) == (size_t)(cp - name)) && + (strncasecmp(name, NAME(*np), cp - name) == 0)) { + *fname = name; + return (np); + } + } + if (!insert) { + /* + * Look for wildcard in this hash table. + * Don't use a cached "*" name as a wildcard, + * only authoritative. + */ + hval = ('*' & HASHMASK) % htp->h_size; + for (np = htp->h_tab[hval]; np != NULL; np = np->n_next) { + if (ns_wildcard(NAME(*np)) && + np->n_data && np->n_data->d_zone != 0) { + *fname = name; + return (np); + } + } + return (parent); + } + np = savename(name, cp - name); + np->n_parent = parent; + np->n_hashval = hval; + hval %= htp->h_size; + np->n_next = htp->h_tab[hval]; + htp->h_tab[hval] = np; + /* Increase hash table size. */ + if (++htp->h_cnt > htp->h_size * 2) { + *htpp = savehash(htp); + if (parent == NULL) { + if (htp == hashtab) { + hashtab = *htpp; + } else { + fcachetab = *htpp; + } + } + else + parent->n_hash = *htpp; + htp = *htpp; + } + *fname = name; + return (np); +} + +/* struct namebuf * + * np_parent(struct namebuf *np) + * Find the "parent" namebuf of np. + * This is tricky since the parent of "com" is "" and both are stored + * in the same hashbuf. + * See also: + * the AXFR wart description in ns_req.c + */ +struct namebuf * +np_parent(np) + struct namebuf *np; +{ + struct hashbuf *htp; + struct namebuf *np2; + + if (np->n_parent != NULL || NAME(*np)[0] == '\0') + return (np->n_parent); + + /* Try to figure out if np is pointing into the cache or hints. */ + /* Try the cache first. */ + htp = hashtab; + try_again: + /* Search the hash chain that np should be part of. */ + for (np2 = htp->h_tab[np->n_hashval % htp->h_size]; + np2 != NULL; + np2 = np2->n_next) { + + if (np == np2) { /* found it! */ + /* "" hashes into the first bucket */ + for (np = htp->h_tab[0]; np ; np=np->n_next) { + if (NAME(*np)[0] == '\0') + /* found the root namebuf */ + return (np); + } + ns_debug(ns_log_db, 1, + "np_parent(0x%lx) couldn't find root entry", + (u_long) np); + return (NULL); /* XXX shouldn't happen */ + } + } + /* Try the hints. */ + if (htp == hashtab) { + htp = fcachetab; + goto try_again; + } + ns_debug(ns_log_db, 1, "np_parent(0x%lx) couldn't namebuf", + (u_long)np); + return (NULL); /* XXX shouldn't happen */ +} + +/* int + * match(dp, class, type) + * Does data record `dp' match the class and type? + * return value: + * boolean + */ +int +match(struct databuf *dp, int class, int type) { + if (dp->d_class != class && class != C_ANY) + return (0); + if (dp->d_type != type && type != T_ANY) + return (0); + return (1); +} diff --git a/contrib/bind/bin/named/db_save.c b/contrib/bind/bin/named/db_save.c new file mode 100644 index 0000000..a05c40f --- /dev/null +++ b/contrib/bind/bin/named/db_save.c @@ -0,0 +1,221 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)db_save.c 4.16 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: db_save.c,v 8.15 1998/01/26 22:40:08 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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) 1996, 1997 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. + */ + +/* + * Buffer allocation and deallocation routines. + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +/* + * Allocate a name buffer & save name. + */ +struct namebuf * +savename(const char *name, int len) { + struct namebuf *np; + + /* + * Note that MAXLABEL * 4 < 256, so a single length byte is enough. + * Also, we use MAXLABEL * 4 because each label character can + * expand into up to four characters when rendered in canonical + * form. + */ + INSIST(len >= 0 && len <= (MAXLABEL * 4)); + np = (struct namebuf *) memget(NAMESIZE(len)); + if (np == NULL) + panic("savename: memget", NULL); + memset(np, 0, NAMESIZE(len)); + NAMELEN(*np) = (unsigned)len; + memcpy(NAME(*np), name, len); + NAME(*np)[len] = '\0'; + return (np); +} + +/* + * Allocate a data buffer & save data. + */ +struct databuf * +savedata(class, type, ttl, data, size) + int class, type; + u_int32_t ttl; + u_char *data; + int size; +{ + struct databuf *dp; + int bytes = (type == T_NS) ? DATASIZE(size)+INT32SZ : DATASIZE(size); + + dp = (struct databuf *)memget(bytes); + if (dp == NULL) + panic("savedata: memget", NULL); + memset(dp, 0, bytes); + dp->d_next = NULL; + dp->d_type = type; + dp->d_class = class; + dp->d_ttl = ttl; + dp->d_size = size; + dp->d_mark = 0; + dp->d_flags = 0; + dp->d_cred = 0; + dp->d_clev = 0; + dp->d_rcode = NOERROR; + dp->d_ns = NULL; + dp->d_nstime = 0; + memcpy(dp->d_data, data, dp->d_size); + return (dp); +} + +int hashsizes[] = { /* hashtable sizes */ + 2, + 11, + 113, + 337, + 977, + 2053, + 4073, + 8011, + 16001, + 99887, + 0 +}; + +/* + * Allocate a data buffer & save data. + */ +struct hashbuf * +savehash(oldhtp) + struct hashbuf *oldhtp; +{ + struct hashbuf *htp; + struct namebuf *np, *nnp, **hp; + int n, newsize; + + if (oldhtp == NULL) + newsize = hashsizes[0]; + else { + for (n = 0; (newsize = hashsizes[n++]) != 0; (void)NULL) + if (oldhtp->h_size == newsize) { + newsize = hashsizes[n]; + break; + } + if (newsize == 0) + newsize = oldhtp->h_size * 2 + 1; + } + ns_debug(ns_log_db, 4, "savehash GROWING to %d", newsize); + htp = (struct hashbuf *) memget(HASHSIZE(newsize)); + if (htp == NULL) + ns_panic(ns_log_db, 0, "savehash: %s", strerror(errno)); + htp->h_size = newsize; + memset(htp->h_tab, 0, newsize * sizeof(struct namebuf *)); + if (oldhtp == NULL) { + htp->h_cnt = 0; + return (htp); + } + ns_debug(ns_log_db, 4, "savehash(%#lx) cnt=%d, sz=%d, newsz=%d", + (u_long)oldhtp, oldhtp->h_cnt, oldhtp->h_size, newsize); + htp->h_cnt = oldhtp->h_cnt; + for (n = 0; n < oldhtp->h_size; n++) { + for (np = oldhtp->h_tab[n]; np != NULL; np = nnp) { + nnp = np->n_next; + hp = &htp->h_tab[np->n_hashval % htp->h_size]; + np->n_next = *hp; + *hp = np; + } + } + oldhtp->h_cnt = 0; /* Keep rm_hash() happy. */ + rm_hash(oldhtp); + return (htp); +} diff --git a/contrib/bind/bin/named/db_update.c b/contrib/bind/bin/named/db_update.c new file mode 100644 index 0000000..ab70663 --- /dev/null +++ b/contrib/bind/bin/named/db_update.c @@ -0,0 +1,932 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)db_update.c 4.28 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: db_update.c,v 8.23 1998/02/13 20:01:38 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1990 + * 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) 1996, 1997 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 "port_before.h" + +#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 <resolv.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" + +/* int + * isRefByNS(name, htp) + * recurse through all of `htp' looking for NS RR's that refer to `name'. + * returns: + * nonzero if at least one such NS RR exists + * cautions: + * this is very expensive; probably you only want to use on fcachetab. + */ +static int +isRefByNS(const char *name, struct hashbuf *htp) { + struct namebuf *np; + struct databuf *dp; + + for (np = htp->h_tab[0]; np != NULL; np = np->n_next) { + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if ((dp->d_class == C_ANY || + dp->d_class == C_IN || + dp->d_class == C_HS) && + dp->d_type == T_NS && + !dp->d_rcode && + !strcasecmp(name, (char *)dp->d_data)) { + return (1); + } + } + if (np->n_hash && isRefByNS(name, np->n_hash)) + return (1); + } + return (0); +} + + +/* int + * findMyZone(struct namebuf *np, int class) + * surf the zone cuts and find this zone the hard way + * return value: + * zone number or DB_Z_CACHE if it's outside a zone + * interesting cases: + * DEC.COM SOA (primary) + * CRL.DEC.COM NS (in primary) + * if you start at CRL.. here, you find the DEC.COM zone + * if you start at NS.CRL.. here, you're in the cache + * DEC.COM SOA (primary) + * CRL.DEC.COM NS (in primary) + * CRL.DEC.COM SOA (secondary) + * CRL.DEC.COM NS (in secondary) + * if you start at CRL.. here, you find the CRL.DEC.COM zone + * if you start at NS.CRL.. here, you're in the CRL.. zone + */ +int +findMyZone(struct namebuf *np, int class) { + for ((void)NULL; np; np = np_parent(np)) { + struct databuf *dp; + + /* if we encounter an SOA, we're in its zone (which can be + * the cache or an authoritative zone, depending). + */ + for (dp = np->n_data; dp; dp = dp->d_next) + if (match(dp, class, T_SOA)) + return (dp->d_zone); + + /* if we find an NS at some node without having seen an SOA + * (above), then we're out in the cache somewhere. + */ + for (dp = np->n_data; dp; dp = dp->d_next) + if (match(dp, class, T_NS)) + return (DB_Z_CACHE); + } + + /* getting all the way to the root without finding an NS or SOA + * probably means that we are in deep dip, but we'll treat it as + * being in the cache. (XXX?) + */ + return (DB_Z_CACHE); +} + + +#define ISVALIDGLUE(xdp) ((xdp)->d_type == T_NS || (xdp)->d_type == T_A \ + || (xdp)->d_type == T_AAAA) + +/* int + * db_update(name, odp, newdp, savedpp, flags, htp, from) + * update data base node at `name'. `flags' controls the action. + * side effects: + * inverse query tables modified, if we're using them. + * return value: + * OK - success + * NONAME - name doesn't exist + * AUTH - you can't do that + * DATAEXISTS - there's something there and DB_NODATA was specified + * NODATA - there's no data, and (DB_DELETE or DB_MEXIST) was spec'd + * + * Policy: How to add data if one more RR is -ve data + * + * NEND NOERROR_NODATA + * NXD NXDOMAIN + * + * match + * old + * Data NEND NXD + * Data Merge Data Data + * new NEND NEND NEND NEND + * NXD NXD NXD NXD + * + * no match + * old + * Data NEND NXD + * Data Merge Merge Data + * new NEND Merge Merge NEND + * NXD NXD NXD NXD + * + */ +/* XXX: this code calls nlookup, which can create namebuf's. if this code + * has to exit with a fatal error, it should scan from the new np upward + * and for each node which has no children and no data it should remove + * the namebuf. design notes: (1) there's no harm in doing this even if + * success occurred; (2) stopping on the first nonremovable np is optimal; + * the code for removal should be taken out of clean_cache() and made + * general enough for this use, and for clean_cache()'s continued use. + * vix, 21jul94 + */ +int +db_update(const char *name, + struct databuf *odp, struct databuf *newdp, + struct databuf **savedpp, + int flags, struct hashbuf *htp, struct sockaddr_in from) +{ + struct databuf *dp, *pdp; + struct namebuf *np; + int zn, isHintNS; + int check_ttl = 0; + const char *fname; +#ifdef BIND_UPDATE + int i, found_other_ns = 0; + struct databuf *tmpdp; + u_char *cp1, *cp2; + u_int32_t dp_serial, newdp_serial; +#endif + + ns_debug(ns_log_db, 3, "db_update(%s, %#x, %#x, %#x, 0%o, %#x)%s", + name, odp, newdp, savedpp, flags, htp, + (odp && (odp->d_flags&DB_F_HINT)) ? " hint" : ""); + np = nlookup(name, &htp, &fname, newdp != NULL); + if (np == NULL || fname != name) + return (NONAME); + + if (newdp && zones[newdp->d_zone].z_type == Z_PRIMARY) + check_ttl = 1; + + /* don't let nonauthoritative updates write in authority zones */ + if (newdp && ((zn = findMyZone(np, newdp->d_class)) != DB_Z_CACHE) && +#ifdef STUBS + (zones[zn].z_type != Z_STUB) && +#endif + (flags & DB_NOTAUTH)) { + int foundRR = 0; + + /* + * Don't generate the warning if the update + * would have been harmless (identical data). + */ + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!db_cmp(dp, newdp)) { + foundRR++; + break; + } + } + if (!foundRR) + ns_debug(ns_log_db, 5, + "[%s].%d update? to auth zone \"%s\" (%s)", + inet_ntoa(from.sin_addr), + ntohs(from.sin_port), + zones[zn].z_origin, + name); + return (AUTH); + } + + if (newdp && zn && !(flags & DB_NOTAUTH)) { + if (nlabels(zones[zn].z_origin) > newdp->d_clev) { + ns_debug(ns_log_db, 5, + "attempted update child zone %s, %s", + zones[zn].z_origin, name); + return (AUTH); + } + } + + /* some special checks for root NS' A RR's */ + isHintNS = isRefByNS(name, fcachetab); +#ifdef DEPRECATED + if (newdp && isHintNS && newdp->d_type == T_A) { + /* upgrade credibility of additional data for rootsrv addrs */ + if (newdp->d_cred == DB_C_ADDITIONAL) { + ns_debug(ns_log_db, 3, + "upgrading credibility for A RR (%s)", + name); + /* XXX: should copy NS RR's, but we really just want + * to prevent deprecation later so this will do. + */ + newdp->d_cred = DB_C_ANSWER; + newdp->d_clev = 0; + } + } +#endif + + /* Reflect certain updates in hint cache also... */ + /* Don't stick data we are authoritative for in hints. */ + if (!(flags & DB_NOHINTS) && + (flags & DB_PRIMING) && + (odp != NULL) && + (htp != fcachetab) && + (DB_Z_SPECIAL(odp->d_zone)) && + !(odp->d_flags & DB_F_HINT) && + (!newdp || !newdp->d_rcode) && + ((name[0] == '\0' && odp->d_type == T_NS) || + (odp->d_type == T_A && isHintNS) + ) + ) + { + ns_debug(ns_log_db, 3, "db_update: hint '%s' %u", + name, odp->d_ttl); + dp = savedata(odp->d_class, odp->d_type, odp->d_ttl, + odp->d_data, odp->d_size); + dp->d_zone = DB_Z_CACHE; + dp->d_flags = DB_F_HINT; + dp->d_cred = DB_C_CACHE; + dp->d_clev = 0; + if (db_update(name, + dp, dp, NULL, + (flags|DB_NOHINTS), + fcachetab, from) + != OK) { + ns_debug(ns_log_db, 3, + "db_update: hint %#x freed", dp); + db_freedata(dp); + } + } + + if (odp != NULL) { + int foundRR = 0; + + pdp = NULL; + for (dp = np->n_data; dp != NULL; ) { + if (!match(dp, odp->d_class, odp->d_type)) { + /* {class,type} doesn't match. these are + * the aggregation cases. + */ + /* Check that CNAMEs are only accompanied by + * Secure DNS RR's (KEY, SIG, and NXT). + */ + if (((dp->d_type == T_CNAME && + odp->d_type != T_KEY && + odp->d_type != T_SIG && + odp->d_type != T_NXT) || + (odp->d_type == T_CNAME && + dp->d_type != T_KEY && + dp->d_type != T_SIG && + dp->d_type != T_NXT)) && + odp->d_class == dp->d_class && + /* XXXRTH d_mark removed in 4.9.5, + but still here for dynamic + update */ + odp->d_mark == dp->d_mark && + !dp->d_rcode && + !odp->d_rcode && +#ifdef BIND_UPDATE + /* updating a CNAME with another CNAME is permitted */ + (dp->d_type != T_CNAME || + odp->d_type != T_CNAME) && +#endif + zones[odp->d_zone].z_type != Z_CACHE) { + ns_info(ns_log_db, + "%s has CNAME and other data (invalid)", + name); + goto skip; + } + if (!newdp || newdp->d_class != dp->d_class) + goto skip; + + /* if the new data is authorative + * remove any data for this domain with + * the same class that isn't as credable + */ + if (newdp->d_cred == DB_C_ZONE && + newdp->d_cred > dp->d_cred) + /* better credibility and the old datum + * was not from a zone file. remove + * the old datum. + */ + goto delete; + +#if 0 /* caught by findMyZone() now. */ + /* if we have authoritative data for a + * node, don't add in other data. + */ + if (dp->d_cred == DB_C_ZONE && + newdp->d_cred < dp->d_cred) + return (AUTH); +#endif + + /* if the new data is authoritative but + * but isn't as credible, reject it. + */ + if (newdp->d_cred == DB_C_ZONE && + dp->d_cred == DB_C_ZONE) { + /* Both records are from a zone file. + * If their credibility levels differ, + * we're dealing with a zone cut. The + * record with lower clev is from the + * upper zone's file and is therefore + * glue. + */ + if (newdp->d_clev < dp->d_clev) { + if (!ISVALIDGLUE(newdp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, ignored", + name, p_type(newdp->d_type), + zones[newdp->d_zone].z_origin, + zones[dp->d_zone].z_origin); + } + return (AUTH); + } + if (newdp->d_clev > dp->d_clev) { + if (!ISVALIDGLUE(dp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, deleted", + name, p_type(dp->d_type), + zones[dp->d_zone].z_origin, + zones[newdp->d_zone].z_origin); + } + goto delete; + } + } + + /* process NXDOMAIN */ + /* policy */ + if (newdp->d_rcode == NXDOMAIN) { + if (dp->d_cred < DB_C_AUTH) + goto delete; + else + return (DATAEXISTS); + } + + if (dp->d_rcode == NXDOMAIN) + goto delete; + + /* process NOERROR_NODATA */ + /* NO PROCESSING REQUIRED */ + + goto skip; + } /*if {class,type} did not match*/ + + /* + * {type,class} did match. This is the replace case. + */ + ns_debug(ns_log_db, 5, + "db_update: flags = %#x, sizes = %d, %d (cmp %d)", + flags, odp->d_size, dp->d_size, + db_cmp(dp, odp)); + if (newdp) { + ns_debug(ns_log_db, 4, + "credibility for %s is %d(%d) from [%s].%d, is %d(%d) in cache", + *name ? name : ".", + newdp->d_cred, + newdp->d_clev, + inet_ntoa(from.sin_addr), + ntohs(from.sin_port), + dp->d_cred, + dp->d_clev); + if (newdp->d_cred > dp->d_cred) { + /* better credibility. + * remove the old datum. + */ + goto delete; + } + if (newdp->d_cred < dp->d_cred) { + /* credibility is worse. ignore it. */ + return (AUTH); + } + if (newdp->d_cred == DB_C_ZONE && + dp->d_cred == DB_C_ZONE ) { + /* Both records are from a zone file. + * If their credibility levels differ, + * we're dealing with a zone cut. The + * record with lower clev is from the + * upper zone's file and is therefore + * glue. + */ + + /* XXX - Tricky situation here is you + * have 2 zones a.b.c and sub.a.b.c + * being served by the same server. + * named will send NS records for + * sub.a.b.c during zone transfer of + * a.b.c zone. If we're secondary for + * both zones, and we reload zone + * a.b.c, we'll get the NS records + * (and possibly A records to go with + * them?) for sub.a.b.c as part of the + * a.b.c zone transfer. But we've + * already got a more credible record + * from the sub.a.b.c zone. So we want + * to ignore the new record, but we + * shouldn't syslog because there's + * nothing the user can do to prevent + * the situation. Perhaps we should + * only complain when we are primary? + */ + + if (newdp->d_clev < dp->d_clev) { + if (!ISVALIDGLUE(newdp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, ignored", + name, p_type(newdp->d_type), + zones[newdp->d_zone].z_origin, + zones[dp->d_zone].z_origin); + } + return (AUTH); + } + if (newdp->d_clev > dp->d_clev) { + if (!ISVALIDGLUE(dp)) { + ns_info(ns_log_db, + "domain %s %s record in zone %s should be in zone %s, deleted", + name, p_type(dp->d_type), + zones[dp->d_zone].z_origin, + zones[newdp->d_zone].z_origin); + } + goto delete; + } + } + + /* credibility is the same. + * let it aggregate in the normal way. + */ + + /* + * if the new or old RR is -ve, delete old. + */ + if (dp->d_rcode || newdp->d_rcode) { + /* XXX: how can a zone rr be neg? */ + if (dp->d_cred != DB_C_ZONE) + goto delete; + else + return (DATAEXISTS); + } + + /* + * Some RR types should not be aggregated. + */ + if (dp->d_type == T_SOA) { +#ifdef BIND_UPDATE + u_int32_t dp_ser, ndp_ser; + u_char *dp_cp, *ndp_cp; + + dp_cp = findsoaserial(dp->d_data); + ndp_cp = findsoaserial(newdp->d_data); + GETLONG(dp_ser, dp_cp); + GETLONG(ndp_ser, ndp_cp); + + if (SEQ_GT(ndp_ser, dp_ser)) + goto delete; + else + return (SERIAL); +#else + goto delete; +#endif /*BIND_UPDATE*/ + } + if (dp->d_type == T_WKS && + !memcmp(dp->d_data, newdp->d_data, + INT32SZ + sizeof(u_char))) + goto delete; + if (dp->d_type == T_CNAME && + !NS_OPTION_P(OPTION_MULTIPLE_CNAMES)) + goto delete; +#ifdef BIND_UPDATE + if (dp->d_type == T_SIG) + /* + * Type covered has already been + * checked. + */ + goto delete; +#endif + if (check_ttl) { + if (newdp->d_ttl != dp->d_ttl) + ns_warning(ns_log_db, + "%s %s %s differing ttls: corrected", + name[0]?name:".", + p_class(dp->d_class), + p_type(dp->d_type)); + if (newdp->d_ttl > dp->d_ttl) { + newdp->d_ttl = dp->d_ttl; + } else { + dp->d_ttl = newdp->d_ttl; + } + } + } + if ((flags & DB_NODATA) && !db_cmp(dp, odp)) { + /* Refresh ttl if cache entry. */ + if (dp->d_zone == DB_Z_CACHE) { + if (odp->d_zone != DB_Z_CACHE) { + /* Changing cache->auth. */ + dp->d_zone = odp->d_zone; + dp->d_ttl = odp->d_ttl; + ns_debug(ns_log_db, 4, + "db_update: cache entry now in auth zone"); + return (DATAEXISTS); + } + fixttl(odp); + if (odp->d_ttl > dp->d_ttl) + dp->d_ttl = odp->d_ttl; + ns_debug(ns_log_db, 3, + "db_update: new ttl %u +%lu", + dp->d_ttl, + (u_long)(dp->d_ttl - tt.tv_sec) + ); + } + return (DATAEXISTS); + } + /* + * If the old databuf has some data, check that the + * data matches that in the new databuf. + */ + if (odp->d_size > 0) + if (db_cmp(dp, odp)) + goto skip; + if (odp->d_clev < dp->d_clev) + goto skip; + if (odp->d_cred < dp->d_cred) + goto skip; +#ifdef BIND_UPDATE + if (!strcasecmp(name, zones[dp->d_zone].z_origin) && + !newdp) { + /* do not delete SOA or NS records as a set */ + /* XXXRTH isn't testing d_size unnecessary? */ + if ((odp->d_size == 0) && + (odp->d_class == C_ANY) && + (odp->d_type == T_ANY || + odp->d_type == T_SOA || + odp->d_type == T_NS) && + (dp->d_type == T_SOA || + dp->d_type == T_NS)) + goto skip; + /* XXXRTH I added this to prevent SOA deletion + I'm using the same style of comparison as + the other code in this section. Do we + really need to look at dp->d_type here? + We're in the "match" section... */ + if ((odp->d_type == T_SOA) && + (dp->d_type == T_SOA)) + goto skip; + /* do not delete the last NS record + for the zone */ + if ((odp->d_type == T_NS) && + (dp->d_type == T_NS)) { + found_other_ns = 0; + for (tmpdp = np->n_data; + tmpdp && !found_other_ns; + tmpdp = tmpdp->d_next) + if ((tmpdp->d_type == T_NS) && + (tmpdp != dp)) + found_other_ns = 1; + if (!found_other_ns) { + ns_debug(ns_log_db, 3, + "cannot delete last remaining NS record for zone %s", + name); + goto skip; + } + } + } +#endif + + foundRR = 1; + if (flags & DB_DELETE) { + delete: +#ifdef BIND_UPDATE + /* + * XXX assume here that savedpp!=NULL iff. db_update + * has been called by the dyanmic update code. + * Maybe a new flag is more appropriate? + */ + if (savedpp != NULL) + foundRR = 1; +#endif + dp = rm_datum(dp, np, pdp, savedpp); + } else { + skip: pdp = dp; + dp = dp->d_next; + } + } + if (!foundRR) { + if (flags & DB_DELETE) + return (NODATA); + if (flags & DB_MEXIST) + return (NODATA); + } + } + /* XXX: delete a terminal namebuf also if all databuf's + * underneath of it have been deleted) */ + if (newdp == NULL) + return (OK); + /* XXX: empty nodes bypass credibility checks above; should check + * response source address here if flags&NOTAUTH. + */ + fixttl(newdp); + ns_debug(ns_log_db, 3, "db_update: adding%s %#x", + (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp); + + if (NS_OPTION_P(OPTION_HOSTSTATS) && + newdp->d_zone == DB_Z_CACHE && + (newdp->d_flags & DB_F_HINT) == 0) + newdp->d_ns = nameserFind(from.sin_addr, NS_F_INSERT); + + /* Add to end of list, generally preserving order */ + newdp->d_next = NULL; + if ((dp = np->n_data) == NULL) { + DRCNTINC(newdp); + if (newdp->d_flags & DB_F_ACTIVE) + panic("db_update: DB_F_ACTIVE set", NULL); + newdp->d_flags |= DB_F_ACTIVE; + np->n_data = newdp; + return (OK); + } + while (dp->d_next != NULL) { + if ((flags & DB_NODATA) && !db_cmp(dp, newdp)) + return (DATAEXISTS); + dp = dp->d_next; + } + if ((flags & DB_NODATA) && !db_cmp(dp, newdp)) + return (DATAEXISTS); + DRCNTINC(newdp); + if (newdp->d_flags & DB_F_ACTIVE) + panic("db_update: DB_F_ACTIVE set", NULL); + newdp->d_flags |= DB_F_ACTIVE; + dp->d_next = newdp; + return (OK); +} + +void +fixttl(struct databuf *dp) { + if (dp->d_zone == DB_Z_CACHE && (dp->d_flags & DB_F_HINT) == 0) { + if (dp->d_ttl <= (u_int32_t)tt.tv_sec) + return; + else if (dp->d_ttl < (u_int32_t)tt.tv_sec+min_cache_ttl) + dp->d_ttl = (u_int32_t)tt.tv_sec+min_cache_ttl; + else if (dp->d_ttl > (u_int32_t)tt.tv_sec+max_cache_ttl) + dp->d_ttl = (u_int32_t)tt.tv_sec+max_cache_ttl; + } +} + +/* + * Compare type, class and data from databufs for equivalence. + * All domain names in RR's must be compared case-insensitively. + * Return 0 if equivalent, nonzero otherwise. + */ +int +db_cmp(const struct databuf *dp1, const struct databuf *dp2) { + const u_char *cp1, *cp2; + int len, len2; + + /* XXXDYNUP- should be changed to + if (!match(dp1, dp2->d_type, dp2->d_class) */ + if (dp1->d_type != dp2->d_type || dp1->d_class != dp2->d_class) + return (1); + /* XXXDYNUP - should be changed to (dp1->d_size != dp2->d_size && + dp1->d_size != 0 && dp2->d_size != 0) */ + if (dp1->d_size != dp2->d_size) + return (1); + /* d_mark is only used for dynamic updates currently */ +#ifndef BIND_UPDATE + if (dp1->d_mark != dp2->d_mark) + return (1); /* old and new RR's are distinct */ +#endif + if (dp1->d_rcode && dp2->d_rcode) + return ((dp1->d_rcode == dp1->d_rcode)?0:1); + if (dp1->d_rcode || dp2->d_rcode) + return (1); + + switch (dp1->d_type) { + + case T_A: + case T_WKS: + case T_NULL: + case T_NSAP: + case T_AAAA: + case T_LOC: + case T_KEY: + /* Only binary data */ + return (memcmp(dp1->d_data, dp2->d_data, dp1->d_size)); + + case T_NS: + case T_CNAME: + case T_PTR: + case T_MB: + case T_MG: + case T_MR: + /* Only a domain name */ + return (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data)); + + case T_SIG: + /* Binary data, a domain name, more binary data */ + if (dp1->d_size < NS_SIG_SIGNER) + return (1); + if (memcmp(dp1->d_data, dp2->d_data, NS_SIG_SIGNER)) + return (1); + len = NS_SIG_SIGNER + + strlen((char *)dp1->d_data + NS_SIG_SIGNER); + if (strcasecmp((char *)dp1->d_data + NS_SIG_SIGNER, + (char *)dp2->d_data + NS_SIG_SIGNER)) + return (1); + return (memcmp(dp1->d_data + len, + dp2->d_data + len, + dp1->d_size - len)); + + case T_NXT: + /* First a domain name, then binary data */ + if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data)) + return (1); + len = strlen((char *)dp1->d_data)+1; + return (memcmp(dp1->d_data + len, + dp2->d_data + len, + dp1->d_size - len)); + + case T_HINFO: + case T_ISDN: + cp1 = dp1->d_data; + cp2 = dp2->d_data; + len = *cp1; + len2 = *cp2; + if (len != len2) + return (1); + if (strncasecmp((char *)++cp1, (char *)++cp2, len)) + return (1); + cp1 += len; + cp2 += len; + len = *cp1; + len2 = *cp2; + if (len != len2) + return (1); + return (strncasecmp((char *)++cp1, (char *)++cp2, len)); + + case T_SOA: + case T_MINFO: + case T_RP: + if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data)) + return (1); + cp1 = dp1->d_data + strlen((char *)dp1->d_data) + 1; + cp2 = dp2->d_data + strlen((char *)dp2->d_data) + 1; + if (dp1->d_type != T_SOA) + return (strcasecmp((char *)cp1, (char *)cp2)); + if (strcasecmp((char *)cp1, (char *)cp2)) + return (1); + cp1 += strlen((char *)cp1) + 1; + cp2 += strlen((char *)cp2) + 1; + return (memcmp(cp1, cp2, INT32SZ * 5)); + + case T_NAPTR: { + int t1,t2; + + if (dp1->d_size != dp2->d_size) + return (1); + cp1 = dp1->d_data; + cp2 = dp2->d_data; + + /* Order */ + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) + return (1); + + /* Preference */ + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) + return (1); + + /* Flags */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Services */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Regexp */ + t1 = *cp1++; t2 = *cp2++; + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1; cp2 += t2; + + /* Replacement */ + t1 = strlen((char *)cp1); t2 = strlen((char *)cp2); + if (t1 != t2 || memcmp(cp1, cp2, t1)) + return (1); + cp1 += t1 + 1; cp2 += t2 + 1; + + /* they all checked out! */ + return (0); + } + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + cp1 = dp1->d_data; + cp2 = dp2->d_data; + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */ + return (1); + if (dp1->d_type == T_SRV) { + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* weight */ + return (1); + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* port */ + return (1); + } + return (strcasecmp((char *)cp1, (char *)cp2)); + + case T_PX: + cp1 = dp1->d_data; + cp2 = dp2->d_data; + if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */ + return (1); + if (strcasecmp((char *)cp1, (char *)cp2)) + return (1); + cp1 += strlen((char *)cp1) + 1; + cp2 += strlen((char *)cp2) + 1; + return (strcasecmp((char *)cp1, (char *)cp2)); + + case T_TXT: + case T_X25: + if (dp1->d_size != dp2->d_size) + return (1); + return (memcmp(dp1->d_data, dp2->d_data, dp1->d_size)); + + default: + return (1); + } +} diff --git a/contrib/bind/bin/named/named-bootconf.pl b/contrib/bind/bin/named/named-bootconf.pl new file mode 100755 index 0000000..ce474c4 --- /dev/null +++ b/contrib/bind/bin/named/named-bootconf.pl @@ -0,0 +1,324 @@ +#!/usr/bin/perl + +## Copyright (c) 1996, 1997 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. + +## $Id: named-bootconf.pl,v 8.16 1998/02/13 19:48:25 halley Exp $ + +# This is a filter. Input is a named.boot. Output is a named.conf. + +$new_config = ""; + +$have_options = 0; +%options = (); +%options_comments = (); +@topology = (); +@topology_comments = (); +@bogus = (); +@bogus_comments = (); +@transfer_acl = (); +@transfer_comments = (); +$logging = ""; + +while(<>) { + next if /^$/; + + # skip comment-only lines + if (/^\s*;+\s*(.*)$/) { + $new_config .= "// $1\n"; + next; + } + + # handle continued lines + while (/\\$/) { + s/\\$/ /; + $_ .= <>; + } + + chop; + + # deal with lines ending in a coment + if (s/\s*;+\s*(.*)$//) { + $comment = "// $1"; + } else { + $comment = ""; + } + + ($directive, @rest) = split; + + $class = ""; + if ($directive =~ /^(.*)\/(.*)$/) { + $directive = $1; + $class = $2; + } + + if ($directive eq "primary") { + $zname = shift(@rest); + &maybe_print_comment("","\n"); + $new_config .= "zone \"$zname\" "; + if ($class ne "") { + $new_config .= "$class "; + } + $new_config .= "{\n"; + $new_config .= "\ttype master;\n"; + $filename = shift(@rest); + $new_config .= "\tfile \"$filename\";\n"; + $new_config .= "};\n\n"; + } elsif ($directive eq "secondary" || $directive eq "stub") { + if ($directive eq "secondary") { + $type = "slave"; + } else { + $type = "stub"; + } + $zname = shift(@rest); + &maybe_print_comment("","\n"); + $new_config .= "zone \"$zname\" "; + if ($class ne "") { + $new_config .= "$class "; + } + $new_config .= "{\n"; + $new_config .= "\ttype $type;\n"; + $filename = pop(@rest); + if ($filename =~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { + push(@rest, $filename); + $filename = ""; + } else { + $new_config .= "\tfile \"$filename\";\n"; + } + $new_config .= "\tmasters {\n"; + foreach $master (@rest) { + $new_config .= "\t\t$master;\n"; + } + $new_config .= "\t};\n"; + $new_config .= "};\n\n"; + } elsif ($directive eq "cache") { + $zname = shift(@rest); + &maybe_print_comment("","\n"); + $new_config .= "zone \"$zname\" {\n"; + $new_config .= "\ttype hint;\n"; + $filename = shift(@rest); + $new_config .= "\tfile \"$filename\";\n"; + $new_config .= "};\n\n"; + } elsif ($directive eq "directory") { + $options{"directory"} = "\"$rest[0]\""; + $options_comments{"directory"} = $comment; + $have_options = 1; + } elsif ($directive eq "check-names") { + $type = shift(@rest); + if ($type eq "primary") { + $type = "master"; + } elsif ($type eq "secondary") { + $type = "slave"; + } + $action = shift(@rest); + $options{"check-names $type"} = $action; + $options_comments{"check-names $type"} = $comment; + $have_options = 1; + } elsif ($directive eq "forwarders") { + $options{"forwarders"}="{\n"; + foreach $forwarder (@rest) { + $options{"forwarders"} .= "\t\t$forwarder;\n"; + } + $options{"forwarders"} .= "\t}"; + $options_comments{"forwarders"} = $comment; + $have_options = 1; + } elsif ($directive eq "slave") { + &handle_options("forward-only"); + } elsif ($directive eq "options") { + &handle_options(@rest); + } elsif ($directive eq "limit") { + &handle_limit(@rest); + } elsif ($directive eq "include") { + $new_config .= + "// make sure your include is still in the right place\n"; + $comment = "\t" . $comment; + $new_config .= "include \"$rest[0]\";$comment\n\n"; + } elsif ($directive eq "xfrnets" || $directive eq "tcplist") { + if ($comment ne "") { + $comment = "\t$comment"; + } + foreach $elt (@rest) { + push(@transfer_acl, $elt); + push(@transfer_comments, $comment); + } + $have_options = 1; + } elsif ($directive eq "sortlist") { + if ($comment ne "") { + $comment = "\t$comment"; + } + foreach $elt (@rest) { + push(@topology, $elt); + push(@topology_comments, $comment); + } + } elsif ($directive eq "bogusns") { + if ($comment ne "") { + $comment = "\t$comment"; + } + foreach $elt (@rest) { + push(@bogus, $elt); + push(@bogus_comments, $comment); + } + } elsif ($directive eq "max-fetch") { + $options{"transfers-in"}=$rest[0]; + $options_comments{"transfers-in"}=$comment; + $have_options = 1; + } else { + $new_config .= "// NOTE: unconverted directive '$directive @rest'\n\n"; + } +} + +print "// generated by named-bootconf.pl\n\n"; +if ($have_options) { + print "options {\n"; + foreach $option (sort(keys(%options))) { + print "\t$option $options{$option};"; + if ($options_comments{$option} ne "") { + print "\t$options_comments{$option}"; + } + print "\n"; + } + if (@transfer_acl > 0) { + print "\tallow-transfer {\n"; + for ($i = 0; $i <= $#transfer_acl; $i++) { + &print_maybe_masked("\t\t", $transfer_acl[$i], + $transfer_comments[$i]); + } + print "\t};\n"; + } + print "\t/* +\t * If there is a firewall between you and nameservers you want +\t * to talk to, you might need to uncomment the query-source +\t * directive below. Previous versions of BIND always asked +\t * questions using port 53, but BIND 8.1 uses an unprivileged +\t * port by default. +\t */ +\t// query-source address * port 53; +"; + + print "};\n\n"; +} +if ($logging ne "") { + print "logging {\n$logging};\n\n"; +} +if (@topology > 0) { + print "// Note: the following will be supported in a future release.\n"; + print "/*\n"; + print "host { any; } {\n\ttopology {\n"; + for ($i = 0; $i <= $#topology; $i++) { + &print_maybe_masked("\t\t", $topology[$i], + $topology_comments[$i]); + } + print "\t};\n};\n"; + print "*/\n"; + print "\n"; +} +if (@bogus > 0) { + for ($i = 0; $i <= $#bogus; $i++) { + print "server $bogus[$i] { bogus yes; };$bogus_comments[$i]\n"; + } + print "\n"; +} +print $new_config; + +exit 0; + +sub maybe_print_comment { + $prefix = shift; + $suffix = shift; + if ($comment ne "") { + $new_config .= sprintf("%s%s%s", $prefix, $comment, $suffix); + } +} + +sub handle_options { + foreach $option (@_) { + if ($option eq "forward-only") { + $options{"forward"}="only"; + $options_comments{"forward"}=$comment; + $have_options = 1; + } elsif ($option eq "no-recursion") { + $options{"recursion"}="no"; + $options_comments{"recursion"}=$comment; + $have_options = 1; + } elsif ($option eq "no-fetch-glue") { + $options{"fetch-glue"}="no"; + $options_comments{"fetch-glue"}=$comment; + $have_options = 1; + } elsif ($option eq "fake-iquery") { + $options{"fake-iquery"}="yes"; + $options_comments{"fake-iquery"}=$comment; + $have_options = 1; + } elsif ($option eq "query-log") { + if ($comment ne "") { + $logging .= "\t$comment\n"; + } + $logging .= "\tcategory queries { default_syslog; };\n"; + } else { + $options{"// NOTE: unconverted option '$option'"}=""; + $options_comments{"// NOTE: unconverted option '$option'"}= + $comment; + $have_options = 1; + } + } +} + +sub handle_limit { + $limit = shift; + if ($limit eq "datasize" || $limit eq "transfers-in" + || $limit eq "transfers-per-ns" || $limit eq "files") { + $options{$limit}=$_[0]; + $options_comments{$limit}=$comment; + $have_options = 1; + } else { + $options{"// NOTE: unconverted limit '$limit @_'"}=""; + $options_comments{"// NOTE: unconverted limit '$limit @_'"}=$comment; + $have_options = 1; + } +} + +sub print_maybe_masked { + # this assumes a contiguous netmask starting at the MSB + $prefix = shift; + $elt = shift; + $elt_comment = shift; + if ($elt =~ /^(.*)&(.*)$/) { + $address = $1; + $mask = $2; + ($m1,$m2,$m3,$m4) = split(/\./, $mask); + $mask_val = ($m1 << 24) + ($m2 << 16) +($m3 << 8) + $m4; + $zero_bits = 0; + while (($mask_val % 2) == 0) { + $mask_val /= 2; + $zero_bits++; + } + $mask_bits = 32 - $zero_bits; + } else { + $address = $elt; + ($a1,$a2,$a3,$a4) = split(/\./, $address); + if ($a1 < 128) { + $mask_bits = 8; + } elsif ($a1 < 192) { + $mask_bits = 16; + } else { + $mask_bits = 24; + } + } + + print "$prefix$address"; + if ($mask_bits != 32) { + print "/$mask_bits"; + } + print ";$elt_comment\n"; +} diff --git a/contrib/bind/bin/named/named.conf b/contrib/bind/bin/named/named.conf new file mode 100644 index 0000000..8df9bc1 --- /dev/null +++ b/contrib/bind/bin/named/named.conf @@ -0,0 +1,426 @@ +/* + * 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 { + directory "."; // use current directory + 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 + check-names master fail; + check-names slave warn; + check-names response ignore; + host-statistics yes; + deallocate-on-exit no; // Painstakingly deallocate all + // objects when exiting instead of + // letting the OS clean up for us. + // Useful a memory leak is suspected. + // Final statistics are written to the + // memstatistics-file. + datasize default; + stacksize default; + coresize default; + files unlimited; + recursion yes; + fetch-glue yes; + fake-iquery no; + notify yes; // send NOTIFY messages. You can set + // notify on a zone-by-zone + // basis in the "zone" statement + // see (below) + 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. + 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. + allow-query { any; }; + allow-transfer { any; }; + transfers-in 10; // DEFAULT_XFERS_RUNNING, cannot be + // set > than MAX_XFERS_RUNNING (20) + transfers-per-ns 2; // DEFAULT_XFERS_PER_NS + transfers-out 0; // not implemented + max-transfer-time-in 120; // MAX_XFER_TIME; the default number + // of minutes an inbound zone transfer + // may run. May be set on a per-zone + // basis. + /* + * The "transfer-format" option specifies the way outbound zone + * transfers (i.e. from us to them) are formatted. Two values are + * allowed: + * + * one-answer Each RR gets its own DNS message. + * This format is not very efficient, + * but is widely understood. All + * versions of BIND prior to 8.1 generate + * this format for outbound zone + * and require it on inbound transfers. + * + * many-answers As many RRs as will fit are put into + * each DNS message. This format is + * the most efficient, but is only known + * to work with BIND 8. Patches to + * BIND 4.9.5 named-xfer that enable it + * to understand 'many-answers' will be + * available. + * + * If you are going to be doing zone transfers to older servers, you + * shouldn't use 'many-answers'. 'transfer-format' may also be set + * on a host-by-host basis using the 'server' statement (see below). + */ + transfer-format one-answer; + query-source address * port *; + /* + * 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 { }; // default is no forwarders + /* + * Here's a forwarders example that isn't trivial + */ + /* + forwarders { + 1.2.3.4; + 5.6.7.8; + }; + */ + topology { localhost; localnets; }; // prefer local nameservers + /* + * Here's a more complicated topology example; it's commented out + * because only one topology block is allowed. + * + topology { + 10/8; // prefer network 10.0.0.0 + // netmask 255.0.0.0 most + !1.2.3/24; // don't like 1.2.3.0 netmask + // 255.255.255.0 at all + { 1.2/16; 3/8; }; // like 1.2.0.0 netmask 255.255.0.0 + // and 3.0.0.0 netmask 255.0.0.0 + // equally well, but less than 10/8 + }; + */ + + listen-on port 53 { any; }; // listen for queries on port 53 on + // any interface on the system + // (i.e. all interfaces). The + // "port 53" is optional; if you + // don't specify a port, port 53 + // is assumed. + /* + * Multiple listen-on statements are allowed. Here's a more + * complicated example: + */ + /* + listen-on { 5.6.7.8; }; // listen on port 53 on interface + // 5.6.7.8 + listen-on port 1234 { // listen on port 1234 on any + !1.2.3.4; // interface on network 1.2.3 + 1.2.3/24; // netmask 255.255.255.0, except for + }; // interface 1.2.3.4. + */ + + /* + * Interval Timers + */ + cleaning-interval 60; // clean the cache of expired RRs + // every 'cleaning-interval' minutes + interface-interval 60; // scan for new or deleted interfaces + // every 'interface-interval' minutes + statistics-interval 60; // log statistics every + // 'statistics-interval' minutes +}; + +zone "master.demo.zone" { + type master; // what used to be called "primary" + file "master.demo.zone"; + check-names fail; + allow-update { none; }; + allow-transfer { any; }; + allow-query { any; }; + // notify yes; // send NOTIFY messages for this + // zone? The global option is used + // if "notify" is not specified + // here. + also-notify { }; // don't notify any nameservers other + // than those on the NS list for this + // zone +}; + +zone "slave.demo.zone" { + type slave; // what used to be called "secondary" + file "slave.demo.zone"; + masters { + 1.2.3.4; // where to zone transfer from + 5.6.7.8; + }; + transfer-source 10.0.0.53; // fixes multihoming problems + check-names warn; + allow-update { none; }; + allow-transfer { any; }; + allow-query { any; }; + max-transfer-time-in 120; // if not set, global option is used. + also-notify { }; // don't notify any nameservers other + // than those on the NS list for this + // zone +}; + +zone "stub.demo.zone" { + type stub; // stub zones are like slave zones, + // except that only the NS records + // are transferred. + file "stub.demo.zone"; + masters { + 1.2.3.4; // where to zone transfer from + 5.6.7.8; + }; + check-names warn; + allow-update { none; }; + allow-transfer { any; }; + allow-query { any; }; + max-transfer-time-in 120; // if not set, global option is used. +}; + +zone "." { + type hint; // used to be specified w/ "cache" + file "cache.db"; +}; + +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 "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; + }; +}; + +key sample_key { // for TSIG; supported by parser + algorithm hmac-md5; // but not yet implemented in the + secret "your secret here"; // rest of the server +}; + +key key2 { + algorithm hmac-md5; + secret "ereh terces rouy"; +}; + +server 1.2.3.4 { + 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; key2; }; // for TSIG; supported by the parser + // but not yet implemented in the + // rest of the server +}; + +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; + }; + + /* + * 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"; + * 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 { + severity debug 3; // level 3 debugging to file + file "foo"; // foo + 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). + */ + }; + + /* + * 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/contrib/bind/bin/named/named.h b/contrib/bind/bin/named/named.h new file mode 100644 index 0000000..57e787b --- /dev/null +++ b/contrib/bind/bin/named/named.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1996, 1997 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. + */ + +/* + * $Id: named.h,v 8.12 1997/12/04 06:52:27 halley Exp $ + */ + +/* Options. Leave these on. */ +#define DEBUG +#define ADDAUTH +#define STUBS +#define RETURNSOA +#define BOGUSNS +#define TRACEROOT +#define XFRNETS +#define QRYLOG +#define YPKLUDGE +#define RENICE +#define FORCED_RELOAD +#define SLAVE_FORWARD +#define BIND_UPDATE +#define BIND_NOTIFY +#define WANT_PIDFILE +#define FWD_LOOP +#define DOTTED_SERIAL +#define SENSIBLE_DOTS +#define ROUND_ROBIN +#define SORT_RESPONSE +#define DNS_SECURITY +#undef RSAREF +#undef BSAFE +#define ALLOW_LONG_TXT_RDATA + +#if 0 +#define strdup PLEASE_USE_SAVESTR +#define malloc PLEASE_USE_DB_MEMGET +#define calloc PLEASE_USE_DB_MEMGET +#define realloc PLEASE_USE_DB_MEMGET +#define free PLEASE_USE_DB_MEMPUT +#endif + +#include <isc/assertions.h> +#include <isc/list.h> + +#include "pathnames.h" + +#include "ns_defs.h" +#include "db_defs.h" + +#include "ns_glob.h" +#include "db_glob.h" + +#include "ns_func.h" +#include "db_func.h" diff --git a/contrib/bind/bin/named/ns_config.c b/contrib/bind/bin/named/ns_config.c new file mode 100644 index 0000000..ff26156 --- /dev/null +++ b/contrib/bind/bin/named/ns_config.c @@ -0,0 +1,2366 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_config.c,v 8.34 1998/03/27 00:19:47 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> +#include <fcntl.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#ifdef HAVE_GETRUSAGE /* XXX */ +#include <sys/resource.h> +#endif + +#include "named.h" +#include "ns_parseutil.h" + +static int tmpnum = 0; +static int config_initialized = 0; + +static int need_logging_free = 0; +static int default_logging_installed; + +static int options_installed = 0; +static int logging_installed = 0; +static int default_options_installed; +static int initial_configuration = 1; + +static char **logging_categories; +static char *current_pid_filename = NULL; + +#define ZONE_SYM_TABLE_SIZE 4973 +static symbol_table zone_symbol_table; + +/* Zones */ + +void +free_zone_timerinfo(struct zoneinfo *zp) { + if (zp->z_timerinfo != NULL) { + freestr(zp->z_timerinfo->name); + memput(zp->z_timerinfo, sizeof *zp->z_timerinfo); + zp->z_timerinfo = NULL; + } else + ns_error(ns_log_config, "timer for zone '%s' had no timerinfo", + zp->z_origin); +} + +void +free_zone_contents(struct zoneinfo *zp, int undefine_sym) { + INSIST(zp != NULL); + + if (undefine_sym) + undefine_symbol(zone_symbol_table, zp->z_origin, + (zp->z_type << 16) | zp->z_class); + if (zp->z_flags & Z_TIMER_SET) { + free_zone_timerinfo(zp); + if (evClearTimer(ev, zp->z_timer) < 0) + ns_error(ns_log_config, + "evClearTimer for zone '%s' failed in ns_init: %s", + zp->z_origin, + strerror(errno)); + } + if (zp->z_origin != NULL) + freestr(zp->z_origin); + if (zp->z_source != NULL) + freestr(zp->z_source); + if (zp->z_update_acl != NULL) + free_ip_match_list(zp->z_update_acl); + if (zp->z_query_acl != NULL) + free_ip_match_list(zp->z_query_acl); + if (zp->z_transfer_acl != NULL) + free_ip_match_list(zp->z_transfer_acl); +#ifdef BIND_UPDATE + if (zp->z_updatelog != NULL) + freestr(zp->z_updatelog); +#endif /* BIND_UPDATE */ +} + +static void +free_zone(struct zoneinfo *zp) { + INSIST(zp != NULL); + + free_zone_contents(zp, 0); + memput(zp, sizeof *zp); +} + +struct zoneinfo * +find_zone(const char *name, int type, int class) { + struct zoneinfo *zp; + symbol_value value; + + ns_debug(ns_log_config, 3, "find_zone(%s,%d,%d)", name, type, class); + if (lookup_symbol(zone_symbol_table, name, + (type<<16) | class, &value)) { + INSIST(value.integer >= 0 && value.integer < nzones); + ns_debug(ns_log_config, 3, + "find_zone: existing zone %d", value.integer); + zp = &zones[value.integer]; + return (zp); + } + ns_debug(ns_log_config, 3, "find_zone: unknown zone"); + return (NULL); +} + +static struct zoneinfo * +new_zone(int class, int type) { + struct zoneinfo *zp; + + if (zones != NULL) { + if (type == z_hint) { + zp = &zones[0]; + return (zp); + } + + for (zp = &zones[1]; zp < &zones[nzones]; zp++) + if (zp->z_type == z_nil) + return (zp); + } + + /* + * This code assumes that nzones never decreases. + */ + if (nzones % 64 == 0) { + ns_debug(ns_log_config, 1, "Reallocating zones structure"); + zp = (struct zoneinfo *) + memget((64 + nzones) * sizeof(struct zoneinfo)); + if (zp == NULL) + panic("no memory for more zones", NULL); + memcpy(zp, zones, nzones * sizeof(struct zoneinfo)); + memset(&zp[nzones], 0, 64 * sizeof(struct zoneinfo)); + memput(zones, nzones * sizeof(struct zoneinfo)); + zones = zp; + } + zp = &zones[nzones++]; + + return (zp); +} + +/* + * Check out a zoneinfo structure and return non-zero if it's OK. + */ +static int +validate_zone(struct zoneinfo *zp) { + int warnings = 0; + char filename[MAXPATHLEN+1]; + + /* Check name */ + if (!res_dnok(zp->z_origin)) { + ns_error(ns_log_config, "invalid zone name '%s'", + zp->z_origin); + return (0); + } + + /* Check class */ + if (zp->z_class == C_ANY || zp->z_class == C_NONE) { + ns_error(ns_log_config, "invalid class %d for zone '%s'", + zp->z_class, zp->z_origin); + return (0); + } + + /* Check type. */ + if (zp->z_type == 0) { + ns_error(ns_log_config, "no type specified for zone '%s'", + zp->z_origin); + return (0); + } + if (zp->z_type == z_hint && strcasecmp(zp->z_origin, "") != 0) { + ns_error(ns_log_config, + "only the root zone may be a hint zone (zone '%s')", + zp->z_origin); + return (0); + } + + /* Check filename. */ + if (zp->z_type == z_master && zp->z_source == NULL) { + ns_error(ns_log_config, + "'file' statement missing for master zone %s", + zp->z_origin); + return (0); + } + /* + * XXX We should run filename through an OS-specific + * validator here. + */ + if (zp->z_source != NULL && + strlen(zp->z_source) > MAXPATHLEN) { + ns_error(ns_log_config, "filename too long for zone '%s'", + zp->z_origin); + return (0); + } + + /* Check masters */ + if (zp->z_addrcnt != 0) { + if (zp->z_type != z_slave && zp->z_type != z_stub) { + ns_error(ns_log_config, + "'masters' statement present for %s zone '%s'", + (zp->z_type == z_master) ? "master" : "hint", + zp->z_origin); + return (0); + } + } else { + if (zp->z_type == z_slave || zp->z_type == z_stub) { + ns_error(ns_log_config, + "no 'masters' statement for non-master zone '%s'", + zp->z_origin); + return (0); + } + } + + /* Check also-notify */ + if (zp->z_notify_count != 0) { + if (zp->z_type != z_master && zp->z_type != z_slave) { + ns_error(ns_log_config, + "'also-notify' given for non-master, non-slave zone '%s'", + zp->z_origin); + return (0); + } + } + +#ifdef BIND_UPDATE + /* XXX need more checking here */ + if (zp->z_type == z_master) { + if (!zp->z_soaincrintvl) + zp->z_soaincrintvl = SOAINCRINTVL; + if (!zp->z_dumpintvl) + zp->z_dumpintvl = DUMPINTVL; + if (!zp->z_deferupdcnt) + zp->z_deferupdcnt = DEFERUPDCNT; + if (!zp->z_updatelog) { + /* XXX OS-specific filename validation here */ + if ((strlen(zp->z_source) + (sizeof ".log" - 1)) > + MAXPATHLEN) { + ns_error(ns_log_config, + "filename too long for dynamic zone '%s'", + zp->z_origin); + return (0); + } + /* this sprintf() is now safe */ + sprintf(filename, "%s.log", zp->z_source); + zp->z_updatelog = savestr(filename, 1); + } + } +#endif /* BIND_UPDATE */ + + return (1); +} + +/* + * Start building a new zoneinfo structure. Returns an opaque + * zone_config suitable for use by the parser. + */ +zone_config +begin_zone(char *name, int class) { + zone_config zh; + struct zoneinfo *zp; + + /* + * require: name is canonical, class is a valid class + */ + + ns_debug(ns_log_config, 3, "begin_zone('%s', %d)", + (*name == '\0') ? "." : name, class); + + zp = (struct zoneinfo *)memget(sizeof (struct zoneinfo)); + if (zp == NULL) + panic("memget failed in begin_zone", NULL); + memset(zp, 0, sizeof (struct zoneinfo)); + zp->z_origin = name; + zp->z_class = class; + zp->z_checknames = not_set; + zh.opaque = zp; + return (zh); +} + +/* + * Merge new configuration information into an existing zone. The + * new zoneinfo must be valid. + */ +static void +update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) { + struct stat f_time; + char buf[MAXPATHLEN+1]; + int i; + + INSIST(zp != NULL); + INSIST(new_zp != NULL); + + ns_debug(ns_log_config, 1, "update_zone_info('%s', %d)", + (*new_zp->z_origin == '\0') ? "." : new_zp->z_origin, + new_zp->z_type); + +#ifdef BIND_UPDATE + /* + * A dynamic master zone that's becoming non-dynamic may need to be + * dumped before we start the update. + */ + if ((zp->z_flags & Z_DYNAMIC) && !(new_zp->z_flags & Z_DYNAMIC) && + ((zp->z_flags & Z_NEED_SOAUPDATE) || + (zp->z_flags & Z_NEED_DUMP))) + (void)zonedump(zp); +#endif + + /* + * First do the simple stuff, making sure to free + * any data that was dynamically allocated. + */ + if (zp->z_origin != NULL) + freestr(zp->z_origin); + zp->z_origin = new_zp->z_origin; + new_zp->z_origin = NULL; + zp->z_class = new_zp->z_class; + zp->z_type = new_zp->z_type; + zp->z_checknames = new_zp->z_checknames; + for (i = 0; i < new_zp->z_addrcnt; i++) + zp->z_addr[i] = new_zp->z_addr[i]; + zp->z_addrcnt = new_zp->z_addrcnt; + if (zp->z_update_acl) + free_ip_match_list(zp->z_update_acl); + zp->z_update_acl = new_zp->z_update_acl; + new_zp->z_update_acl = NULL; + if (zp->z_query_acl) + free_ip_match_list(zp->z_query_acl); + zp->z_query_acl = new_zp->z_query_acl; + new_zp->z_query_acl = NULL; + zp->z_axfr_src = new_zp->z_axfr_src; + if (zp->z_transfer_acl) + free_ip_match_list(zp->z_transfer_acl); + zp->z_transfer_acl = new_zp->z_transfer_acl; + new_zp->z_transfer_acl = NULL; + zp->z_max_transfer_time_in = new_zp->z_max_transfer_time_in; + + zp->z_notify = new_zp->z_notify; + for (i = 0; i < new_zp->z_notify_count; i++) + zp->z_also_notify[i] = new_zp->z_also_notify[i]; + zp->z_notify_count = new_zp->z_notify_count; + +#ifdef BIND_UPDATE + if (new_zp->z_flags & Z_DYNAMIC) + zp->z_flags |= Z_DYNAMIC; + else + zp->z_flags &= ~Z_DYNAMIC; + zp->z_soaincrintvl = new_zp->z_soaincrintvl; + zp->z_dumpintvl = new_zp->z_dumpintvl; + zp->z_deferupdcnt = new_zp->z_deferupdcnt; + if (zp->z_updatelog) + freestr(zp->z_updatelog); + zp->z_updatelog = new_zp->z_updatelog; + new_zp->z_updatelog = NULL; +#endif /* BIND_UPDATE */ + + /* + * now deal with files + */ + switch (zp->z_type) { + case z_hint: + ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source); + zp->z_refresh = 0; /* No dumping. */ + /* + * If we've loaded this file, and the file has + * not been modified and contains no $include, + * then there's no need to reload. + */ + if (zp->z_source && + !strcmp(new_zp->z_source, zp->z_source) && + !(zp->z_flags & Z_INCLUDE) && + stat(zp->z_source, &f_time) != -1 && + zp->z_ftime == f_time.st_mtime) { + ns_debug(ns_log_config, 1, "cache is up to date"); + break; + } + + /* File has changed, or hasn't been loaded yet. */ + if (zp->z_source) { + freestr(zp->z_source); + clean_cache(fcachetab, 1); + } + zp->z_source = new_zp->z_source; + new_zp->z_source = NULL; + ns_debug(ns_log_config, 1, "reloading zone"); + (void) db_load(zp->z_source, zp->z_origin, zp, NULL); + break; + + case z_master: + ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source); + /* + * If we've loaded this file, and the file has + * not been modified and contains no $include, + * then there's no need to reload. + */ + if (zp->z_source && + !strcmp(new_zp->z_source, zp->z_source) && + !(zp->z_flags & Z_INCLUDE) && + stat(zp->z_source, &f_time) != -1 && + zp->z_ftime == f_time.st_mtime) { + ns_debug(ns_log_config, 1, "zone is up to date"); + break; /* zone is already up to date */ + } +#ifdef BIND_UPDATE + if (zp->z_source && (zp->z_flags & Z_DYNAMIC)) + ns_warning(ns_log_config, + "source file of dynamic zone '%s' has changed", + zp->z_origin); + + primary_reload: +#endif /* BIND_UPDATE */ + if (zp->z_source != NULL) + freestr(zp->z_source); + zp->z_source = new_zp->z_source; + new_zp->z_source = NULL; + zp->z_flags &= ~Z_AUTH; + ns_stopxfrs(zp); + purge_zone(zp->z_origin, hashtab, zp->z_class); + ns_debug(ns_log_config, 1, "reloading zone"); +#ifdef BIND_UPDATE + if (zp->z_flags & Z_DYNAMIC) { + struct stat sb; + + if (stat(zp->z_source, &sb) < 0) + ns_error(ns_log_config, "stat(%s) failed: %s", + zp->z_source, strerror(errno)); + else { + if (sb.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) + ns_warning(ns_log_config, + "dynamic zone file '%s' is writable", + zp->z_source); + } + } +#endif + if (!db_load(zp->z_source, zp->z_origin, zp, NULL)) + zp->z_flags |= Z_AUTH; + zp->z_refresh = 0; /* no maintenance needed */ + zp->z_time = 0; +#ifdef BIND_UPDATE + zp->z_lastupdate = 0; + if (zp->z_flags & Z_DYNAMIC) + /* + * Note that going to primary_reload + * unconditionally reloads the zone. + */ + if (merge_logs(zp) == 1) { + new_zp->z_source = savestr(zp->z_source, 1); + goto primary_reload; + } +#endif + break; + + case z_slave: +#ifdef STUBS + case z_stub: +#endif + ns_debug(ns_log_config, 1, "addrcnt = %d", zp->z_addrcnt); + if (!new_zp->z_source) { + /* + * We will always transfer this zone again + * after a reload. + */ + sprintf(buf, "NsTmp%ld.%d", (long)getpid(), tmpnum++); + new_zp->z_source = savestr(buf, 1); + zp->z_flags |= Z_TMP_FILE; + } else + zp->z_flags &= ~Z_TMP_FILE; + /* + * If we had a backup file name, and it was changed, + * free old zone and start over. If we don't have + * current zone contents, try again now in case + * we have a new server on the list. + */ + if (zp->z_source && + (strcmp(new_zp->z_source, zp->z_source) || + (stat(zp->z_source, &f_time) == -1 || + (zp->z_ftime != f_time.st_mtime)))) { + ns_debug(ns_log_config, 1, + "backup file changed or missing"); + freestr(zp->z_source); + zp->z_source = NULL; + zp->z_serial = 0; /* force xfer */ + ns_stopxfrs(zp); + /* + * We only need to do_reload if we have + * successfully transferred the zone. + */ + if (zp->z_flags & Z_AUTH) { + zp->z_flags &= ~Z_AUTH; + /* + * Purge old data and reload parent so that + * NS records are present during the zone + * transfer. + */ + do_reload(zp->z_origin, zp->z_type, + zp->z_class); + } + } + if (zp->z_source == NULL) { + zp->z_source = new_zp->z_source; + new_zp->z_source = NULL; + } + if (!(zp->z_flags & Z_AUTH)) + zoneinit(zp); +#ifdef FORCED_RELOAD + else { + /* + ** Force secondary to try transfer soon + ** after SIGHUP. + */ + if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) + && reloading) { + qserial_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + } + } +#endif /* FORCED_RELOAD */ + break; + } + if ((zp->z_flags & Z_FOUND) && /* already found? */ + (zp - zones) != DB_Z_CACHE) /* cache never sets Z_FOUND */ + ns_error(ns_log_config, "Zone \"%s\" declared more than once", + zp->z_origin); + zp->z_flags |= Z_FOUND; + ns_debug(ns_log_config, 1, + "zone[%d] type %d: '%s' z_time %lu, z_refresh %u", + zp-zones, zp->z_type, + *(zp->z_origin) == '\0' ? "." : zp->z_origin, + (u_long)zp->z_time, zp->z_refresh); +} + +/* + * Finish constructing a new zone. If valid, the constructed zone is + * merged into the zone database. The zone_config used is invalid after + * end_zone() completes. + */ +void +end_zone(zone_config zh, int should_install) { + struct zoneinfo *zp, *new_zp; + char *zname; + symbol_value value; + + new_zp = zh.opaque; + INSIST(new_zp != NULL); + + zname = (new_zp->z_origin[0] == '\0') ? "." : new_zp->z_origin; + ns_debug(ns_log_config, 3, "end_zone('%s', %d)", zname, + should_install); + + if (!should_install) { + free_zone(new_zp); + return; + } + if (!validate_zone(new_zp)) { + ns_error(ns_log_config, + "zone '%s' did not validate, skipping", zname); + free_zone(new_zp); + return; + } + zp = find_zone(new_zp->z_origin, new_zp->z_type, new_zp->z_class); + if (zp == NULL) { + zp = new_zone(new_zp->z_class, new_zp->z_type); + INSIST(zp != NULL); + value.integer = (zp - zones); + define_symbol(zone_symbol_table, savestr(new_zp->z_origin, 1), + (new_zp->z_type << 16) | new_zp->z_class, + value, SYMBOL_FREE_KEY); + } + ns_debug(ns_log_config, 5, "zone '%s', type = %d, class = %d", zname, + new_zp->z_type, new_zp->z_class); + if (new_zp->z_source != NULL) + ns_debug(ns_log_config, 5, " file = %s", new_zp->z_source); + ns_debug(ns_log_config, 5, " checknames = %d", new_zp->z_checknames); + if (new_zp->z_addrcnt) { + int i; + + ns_debug(ns_log_config, 5, " masters:"); + for (i=0; i<new_zp->z_addrcnt; i++) + ns_debug(ns_log_config, 5, " %s", + inet_ntoa(new_zp->z_addr[i])); + } + + update_zone_info(zp, new_zp); + free_zone(new_zp); + zh.opaque = NULL; +} + +int +set_zone_type(zone_config zh, int type) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if type already set for this zone */ + if (zp->z_type != 0) + return (0); + zp->z_type = type; + return (1); +} + +int +set_zone_filename(zone_config zh, char *filename) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if filename already set for this zone */ + if (zp->z_source != NULL) + return (0); + zp->z_source = filename; + return (1); +} + +int +set_zone_checknames(zone_config zh, enum severity s) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if checknames already set for this zone */ + if (zp->z_checknames != not_set) + return (0); + zp->z_checknames = s; + return (1); +} + +int +set_zone_notify(zone_config zh, int value) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + if (value) + zp->z_notify = znotify_yes; + else + zp->z_notify = znotify_no; + + return (1); +} + +int +set_zone_update_acl(zone_config zh, ip_match_list iml) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if checknames already set for this zone */ + if (zp->z_update_acl != NULL) + return (0); + zp->z_update_acl = iml; +#ifdef BIND_UPDATE + if (!ip_match_is_none(iml)) + zp->z_flags |= Z_DYNAMIC; + else + ns_debug(ns_log_config, 3, "update acl is none for '%s'", + zp->z_origin); +#endif + return (1); +} + +int +set_zone_query_acl(zone_config zh, ip_match_list iml) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if checknames already set for this zone */ + if (zp->z_query_acl != NULL) + return (0); + zp->z_query_acl = iml; + return (1); +} + +int +set_zone_transfer_source(zone_config zh, struct in_addr ina) { + struct zoneinfo *zp = zh.opaque; + + zp->z_axfr_src = ina; + return (1); +} + +int +set_zone_transfer_acl(zone_config zh, ip_match_list iml) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if checknames already set for this zone */ + if (zp->z_transfer_acl != NULL) + return (0); + zp->z_transfer_acl = iml; + return (1); +} + +int +set_zone_transfer_time_in(zone_config zh, long max_time) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + /* Fail if checknames already set for this zone */ + if (zp->z_max_transfer_time_in) + return (0); + zp->z_max_transfer_time_in = max_time; + return (1); +} + +int +add_zone_master(zone_config zh, struct in_addr address) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + zp->z_addr[zp->z_addrcnt] = address; + zp->z_addrcnt++; + if (zp->z_addrcnt >= NSMAX) { + ns_warning(ns_log_config, "NSMAX reached for zone '%s'", + zp->z_origin); + zp->z_addrcnt = NSMAX - 1; + } + return (1); +} + +int +add_zone_notify(zone_config zh, struct in_addr address) { + struct zoneinfo *zp; + + zp = zh.opaque; + INSIST(zp != NULL); + + zp->z_also_notify[zp->z_notify_count] = address; + zp->z_notify_count++; + if (zp->z_notify_count >= NSMAX) { + ns_warning(ns_log_config, "also-notify set full for zone '%s'", + zp->z_origin); + zp->z_notify_count = NSMAX - 1; + } + return (1); +} + +/* Options */ + +options +new_options() { + options op; + ip_match_list iml; + ip_match_element ime; + + op = (options)memget(sizeof (struct options)); + if (op == NULL) + panic("memget failed in new_options()", NULL); + + op->directory = savestr(".", 1); + op->pid_filename = savestr(_PATH_PIDFILE, 1); + op->named_xfer = savestr(_PATH_XFER, 1); + op->dump_filename = savestr(_PATH_DUMPFILE, 1); + op->stats_filename = savestr(_PATH_STATS, 1); + op->memstats_filename = savestr(_PATH_MEMSTATS, 1); + op->flags = DEFAULT_OPTION_FLAGS; + op->transfers_in = DEFAULT_XFERS_RUNNING; + op->transfers_per_ns = DEFAULT_XFERS_PER_NS; + op->transfers_out = 0; + op->transfer_format = axfr_one_answer; + op->max_transfer_time_in = MAX_XFER_TIME; + memset(&op->query_source, 0, sizeof op->query_source); + op->query_source.sin_family = AF_INET; + op->query_source.sin_addr.s_addr = htonl(INADDR_ANY); + op->query_source.sin_port = htons(0); /* INPORT_ANY */ + op->query_acl = NULL; + op->transfer_acl = NULL; + /* default topology is { localhost; localnets; } */ + iml = new_ip_match_list(); + ime = new_ip_match_localhost(); + add_to_ip_match_list(iml, ime); + ime = new_ip_match_localnets(); + add_to_ip_match_list(iml, ime); + op->topology = iml; + op->data_size = 0UL; /* use system default */ + op->stack_size = 0UL; /* use system default */ + op->core_size = 0UL; /* use system default */ + op->files = ULONG_MAX; /* unlimited */ + op->check_names[primary_trans] = fail; + op->check_names[secondary_trans] = warn; + op->check_names[response_trans] = ignore; + op->listen_list = NULL; + op->fwdtab = NULL; + /* XXX init forwarding */ + op->clean_interval = 3600; + op->interface_interval = 3600; + op->stats_interval = 3600; + return (op); +} + +void +free_options(options op) { + INSIST(op != NULL); + + if (op->directory) + freestr(op->directory); + if (op->pid_filename) + freestr(op->pid_filename); + if (op->named_xfer) + freestr(op->named_xfer); + if (op->dump_filename) + freestr(op->dump_filename); + if (op->stats_filename) + freestr(op->stats_filename); + if (op->memstats_filename) + freestr(op->memstats_filename); + if (op->query_acl) + free_ip_match_list(op->query_acl); + if (op->transfer_acl) + free_ip_match_list(op->transfer_acl); + if (op->topology) + free_ip_match_list(op->topology); + if (op->listen_list) + free_listen_info_list(op->listen_list); + if (op->fwdtab) + free_forwarders(op->fwdtab); + memput(op, sizeof *op); +} + +void +set_boolean_option(options op, int bool_opt, int value) { + INSIST(op != NULL); + + switch (bool_opt) { + case OPTION_NORECURSE: + case OPTION_NOFETCHGLUE: + case OPTION_FORWARD_ONLY: + case OPTION_FAKE_IQUERY: + case OPTION_NONOTIFY: + case OPTION_NONAUTH_NXDOMAIN: + case OPTION_MULTIPLE_CNAMES: + case OPTION_HOSTSTATS: + case OPTION_DEALLOC_ON_EXIT: + if (value) + op->flags |= bool_opt; + else + op->flags &= ~bool_opt; + break; + default: + panic("unexpected option in set_boolean_option", NULL); + } +} + +#ifdef HAVE_GETRUSAGE +enum limit { Datasize, Stacksize, Coresize, Files }; + +static struct rlimit initial_data_size; +static struct rlimit initial_stack_size; +static struct rlimit initial_core_size; +static struct rlimit initial_num_files; + +static void +get_initial_limits() { +# ifdef RLIMIT_DATA + if (getrlimit(RLIMIT_DATA, &initial_data_size) < 0) + ns_warning(ns_log_config, "getrlimit(DATA): %s", + strerror(errno)); +# endif +# ifdef RLIMIT_STACK + if (getrlimit(RLIMIT_STACK, &initial_stack_size) < 0) + ns_warning(ns_log_config, "getrlimit(STACK): %s", + strerror(errno)); +# endif +# ifdef RLIMIT_CORE + if (getrlimit(RLIMIT_CORE, &initial_core_size) < 0) + ns_warning(ns_log_config, "getrlimit(CORE): %s", + strerror(errno)); +# endif +# ifdef RLIMIT_NOFILE + if (getrlimit(RLIMIT_NOFILE, &initial_num_files) < 0) + ns_warning(ns_log_config, "getrlimit(NOFILE): %s", + strerror(errno)); +# endif +} + +static void +ns_rlimit(enum limit limit, u_long limit_value) { + struct rlimit limits, old_limits; + int rlimit = -1; + char *name; + rlimit_type value; + + if (limit_value == ULONG_MAX) { +#ifndef RLIMIT_FILE_INFINITY + if (limit == Files) + value = MAX((rlimit_type)sysconf(_SC_OPEN_MAX), + initial_num_files.rlim_max); + else +#endif + value = (rlimit_type)RLIM_INFINITY; + } else + value = (rlimit_type)limit_value; + + limits.rlim_cur = limits.rlim_max = value; + switch (limit) { + case Datasize: +#ifdef RLIMIT_DATA + rlimit = RLIMIT_DATA; +#endif + name = "max data size"; + if (value == 0) + limits = initial_data_size; + break; + case Stacksize: +#ifdef RLIMIT_STACK + rlimit = RLIMIT_STACK; +#endif + name = "max stack size"; + if (value == 0) + limits = initial_stack_size; + break; + case Coresize: +#ifdef RLIMIT_CORE + rlimit = RLIMIT_CORE; +#endif + name = "max core size"; + if (value == 0) + limits = initial_core_size; + break; + case Files: +#ifdef RLIMIT_NOFILE + rlimit = RLIMIT_NOFILE; +#endif + name = "max number of open files"; + if (value == 0) + limits = initial_num_files; + /* XXX check < FD_SETSIZE? */ + break; + default: + name = NULL; /* Make gcc happy. */ + panic("impossible condition in ns_rlimit()", NULL); + } + if (rlimit == -1) { + ns_warning(ns_log_config, + "limit \"%s\" not supported on this system - ignored", + name); + return; + } + if (getrlimit(rlimit, &old_limits) < 0) { + ns_warning(ns_log_config, "getrlimit(%s): %s", name, + strerror(errno)); + } + if (user_id != 0 && limits.rlim_max == RLIM_INFINITY) + limits.rlim_cur = limits.rlim_max = old_limits.rlim_max; + if (setrlimit(rlimit, &limits) < 0) { + ns_warning(ns_log_config, "setrlimit(%s): %s", name, + strerror(errno)); + return; + } else { + if (value == 0) + ns_debug(ns_log_config, 3, "%s is default", + name); + else if (value == RLIM_INFINITY) + ns_debug(ns_log_config, 3, "%s is unlimited", name); + else +#ifdef RLIMIT_LONGLONG + ns_debug(ns_log_config, 3, "%s is %llu", name, + (unsigned long long)value); +#else + ns_debug(ns_log_config, 3, "%s is %lu", name, value); +#endif + } +} +#endif /* HAVE_GETRUSAGE */ + +listen_info_list +new_listen_info_list() { + listen_info_list ll; + + ll = (listen_info_list)memget(sizeof (struct listen_info_list)); + if (ll == NULL) + panic("memget failed in new_listen_info_list()", NULL); + ll->first = NULL; + ll->last = NULL; + return (ll); +} + +void +free_listen_info_list(listen_info_list ll) { + listen_info li, next_li; + + INSIST(ll != NULL); + for (li = ll->first; li != NULL; li = next_li) { + next_li = li->next; + free_ip_match_list(li->list); + memput(li, sizeof *li); + } + memput(ll, sizeof *ll); +} + +void +add_listen_on(options op, u_short port, ip_match_list iml) { + listen_info_list ll; + listen_info ni; + + INSIST(op != NULL); + + if (op->listen_list == NULL) + op->listen_list = new_listen_info_list(); + ll = op->listen_list; + ni = (listen_info)memget(sizeof (struct listen_info)); + if (ni == NULL) + panic("memget failed in add_listen_on", NULL); + ni->port = port; + ni->list = iml; + ni->next = NULL; + if (ll->last != NULL) + ll->last->next = ni; + ll->last = ni; + if (ll->first == NULL) + ll->first = ni; +} + +FILE * +write_open(char *filename) { + FILE *stream; + int fd; + struct stat sb; + int regular; + + if (stat(filename, &sb) < 0) { + if (errno != ENOENT) { + ns_error(ns_log_os, + "write_open: stat of %s failed: %s", + filename, strerror(errno)); + return (NULL); + } + regular = 1; + } else + regular = (sb.st_mode & S_IFREG); + + if (!regular) { + ns_error(ns_log_os, "write_open: %s isn't a regular file", + filename); + return (NULL); + } + + (void)unlink(filename); + fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fd < 0) + return (NULL); + stream = fdopen(fd, "w"); + if (stream == NULL) + (void)close(fd); + return (stream); +} + +void +update_pid_file() { + FILE *fp; + + REQUIRE(server_options != NULL); + REQUIRE(server_options->pid_filename != NULL); + + /* XXX */ ns_debug(ns_log_default, 1, "update_pid_file()"); + if (current_pid_filename != NULL) { + (void)unlink(current_pid_filename); + freestr(current_pid_filename); + current_pid_filename = NULL; + } + current_pid_filename = savestr(server_options->pid_filename, 0); + if (current_pid_filename == NULL) { + ns_error(ns_log_config, + "savestr() failed in update_pid_file()"); + return; + } + fp = write_open(current_pid_filename); + if (fp != NULL) { + (void) fprintf(fp, "%ld\n", (long)getpid()); + (void) fclose(fp); + } else + ns_error(ns_log_config, "couldn't create pid file '%s'", + server_options->pid_filename); +} + +/* + * XXX This function will eventually be public and will be relocated to + * the UNIX OS support library. + */ + +static int +os_change_directory(const char *name) { + struct stat sb; + + if (name == NULL || + *name == '\0') { + errno = EINVAL; + return (0); + } + + if (chdir(name) < 0) + return (0); + + if (stat(name, &sb) < 0) { + ns_error(ns_log_os, "stat(%s) failed: %s", name, + strerror(errno)); + return (1); + } + if (sb.st_mode & S_IWOTH) + ns_warning(ns_log_os, "directory %s is world-writable", name); + + return (1); +} + +static void +periodic_getnetconf(evContext ctx, void *uap, struct timespec due, + struct timespec inter) +{ + getnetconf(1); +} + +static void +set_interval_timer(int which_timer, int interval) { + evTimerID *tid = NULL; + evTimerFunc func = NULL; + + switch (which_timer) { + case CLEAN_TIMER: + tid = &clean_timer; + func = ns_cleancache; + break; + case INTERFACE_TIMER: + tid = &interface_timer; + func = periodic_getnetconf; + break; + case STATS_TIMER: + tid = &stats_timer; + func = ns_logstats; + break; + default: + ns_panic(ns_log_config, 1, + "set_interval_timer: unknown timer %d", which_timer); + } + if ((active_timers & which_timer) != 0) { + if (interval > 0) { + if (evResetTimer(ev, *tid, func, NULL, + evAddTime(evNowTime(), + evConsTime(interval, 0)), + evConsTime(interval, 0)) < 0) + ns_error(ns_log_config, + "evResetTimer %d interval %d failed: %s", + which_timer, interval, + strerror(errno)); + } else { + if (evClearTimer(ev, *tid) < 0) + ns_error(ns_log_config, + "evClearTimer %d failed: %s", + which_timer, strerror(errno)); + else + active_timers &= ~which_timer; + } + } else if (interval > 0) { + if (evSetTimer(ev, func, NULL, + evAddTime(evNowTime(), + evConsTime(interval, 0)), + evConsTime(interval, 0), tid) < 0) + ns_error(ns_log_config, + "evSetTimer %d interval %d failed: %s", + which_timer, interval, strerror(errno)); + else + active_timers |= which_timer; + } +} + +/* + * Set all named global options based on the global options structure + * generated by the parser. + */ +void +set_options(options op, int is_default) { + listen_info li; + INSIST(op != NULL); + + if (op->listen_list == NULL) { + ip_match_list iml; + ip_match_element ime; + struct in_addr address; + + op->listen_list = new_listen_info_list(); + + address.s_addr = htonl(INADDR_ANY); + iml = new_ip_match_list(); + ime = new_ip_match_pattern(address, 0); + add_to_ip_match_list(iml, ime); + add_listen_on(op, htons(NS_DEFAULTPORT), iml); + } + if (server_options != NULL) + free_options(server_options); + server_options = op; + + /* XXX should validate pid filename */ + INSIST(op->pid_filename != NULL); + + if (op->directory && !os_change_directory(op->directory)) + ns_panic(ns_log_config, 0, "can't change directory to %s: %s", + op->directory, strerror(errno)); + + /* XXX currently a value of 0 means "use default"; it would be + better if the options block had a "attributes updated" vector + (like the way X deals with GC updates) */ + + if (!op->transfers_in) + op->transfers_in = DEFAULT_XFERS_RUNNING; + else if (op->transfers_in > MAX_XFERS_RUNNING) { + ns_warning(ns_log_config, + "the maximum number of concurrent inbound transfers is %d", + MAX_XFERS_RUNNING); + op->transfers_in = MAX_XFERS_RUNNING; + } + + if (!op->transfers_per_ns) + op->transfers_per_ns = DEFAULT_XFERS_PER_NS; + + if (!op->max_transfer_time_in) + op->max_transfer_time_in = MAX_XFER_TIME; + + /* XXX currently transfers_out is not used */ + + /* + * Limits + */ + +#ifdef HAVE_GETRUSAGE + ns_rlimit(Datasize, op->data_size); + ns_rlimit(Stacksize, op->stack_size); + ns_rlimit(Coresize, op->core_size); + ns_rlimit(Files, op->files); +#else + ns_info(ns_log_config, "cannot set resource limits on this system"); +#endif + + + /* + * Timers + */ + set_interval_timer(CLEAN_TIMER, server_options->clean_interval); + set_interval_timer(INTERFACE_TIMER, + server_options->interface_interval); + set_interval_timer(STATS_TIMER, server_options->stats_interval); + + options_installed = 1; + default_options_installed = is_default; +} + +void +use_default_options() { + set_options(new_options(), 1); +} + +/* + * IP Matching Lists + */ + +ip_match_list +new_ip_match_list() { + ip_match_list iml; + + iml = (ip_match_list)memget(sizeof (struct ip_match_list)); + if (iml == NULL) + panic("memget failed in new_ip_match_list", NULL); + iml->first = NULL; + iml->last = NULL; + return (iml); +} + +void +free_ip_match_list(ip_match_list iml) { + ip_match_element ime, next_element; + + for (ime = iml->first; ime != NULL; ime = next_element) { + next_element = ime->next; + memput(ime, sizeof *ime); + } + memput(iml, sizeof *iml); +} + +ip_match_element +new_ip_match_pattern(struct in_addr address, u_int mask_bits) { + ip_match_element ime; + u_int32_t mask; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_pattern", NULL); + ime->type = ip_match_pattern; + ime->flags = 0; + ime->u.direct.address = address; + if (mask_bits == 0) + /* can't shift >= the size of a type in bits, so + we deal with an empty mask here */ + mask = 0; + else { + /* set the 'mask_bits' most significant bits */ + mask = 0xffffffffU; + mask >>= (32 - mask_bits); + mask <<= (32 - mask_bits); + } + mask = ntohl(mask); + ime->u.direct.mask.s_addr = mask; + ime->next = NULL; + if (!ina_onnet(ime->u.direct.address, ime->u.direct.address, + ime->u.direct.mask)) { + memput(ime, sizeof *ime); + ime = NULL; + } + return (ime); +} + +ip_match_element +new_ip_match_mask(struct in_addr address, struct in_addr mask) { + ip_match_element ime; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_pattern", NULL); + ime->type = ip_match_pattern; + ime->flags = 0; + ime->u.direct.address = address; + ime->u.direct.mask = mask; + ime->next = NULL; + if (!ina_onnet(ime->u.direct.address, ime->u.direct.address, + ime->u.direct.mask)) { + memput(ime, sizeof *ime); + ime = NULL; + } + return (ime); +} + +ip_match_element +new_ip_match_indirect(ip_match_list iml) { + ip_match_element ime; + + INSIST(iml != NULL); + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_indirect", NULL); + ime->type = ip_match_indirect; + ime->flags = 0; + ime->u.indirect.list = iml; + ime->next = NULL; + return (ime); +} + +ip_match_element +new_ip_match_localhost() { + ip_match_element ime; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_localhost", NULL); + ime->type = ip_match_localhost; + ime->flags = 0; + ime->u.indirect.list = NULL; + ime->next = NULL; + return (ime); +} + +ip_match_element +new_ip_match_localnets() { + ip_match_element ime; + + ime = (ip_match_element)memget(sizeof (struct ip_match_element)); + if (ime == NULL) + panic("memget failed in new_ip_match_localnets", NULL); + ime->type = ip_match_localnets; + ime->flags = 0; + ime->u.indirect.list = NULL; + ime->next = NULL; + return (ime); +} + +void +ip_match_negate(ip_match_element ime) { + if (ime->flags & IP_MATCH_NEGATE) + ime->flags &= ~IP_MATCH_NEGATE; + else + ime->flags |= IP_MATCH_NEGATE; +} + +void +add_to_ip_match_list(ip_match_list iml, ip_match_element ime) { + INSIST(iml != NULL); + INSIST(ime != NULL); + + if (iml->last != NULL) + iml->last->next = ime; + ime->next = NULL; + iml->last = ime; + if (iml->first == NULL) + iml->first = ime; +} + +void +dprint_ip_match_list(int category, ip_match_list iml, int indent, + char *allow, char *deny) { + ip_match_element ime; + char spaces[40+1]; + char addr_text[sizeof "255.255.255.255"]; + char mask_text[sizeof "255.255.255.255"]; + char *tmp; + + INSIST(iml != NULL); + + if (indent > 40) + indent = 40; + if (indent) + memset(spaces, ' ', indent); + spaces[indent] = '\0'; + + for (ime = iml->first; ime != NULL; ime = ime->next) { + switch (ime->type) { + case ip_match_pattern: + memset(addr_text, 0, sizeof addr_text); + strncpy(addr_text, inet_ntoa(ime->u.direct.address), + ((sizeof addr_text) - 1)); + memset(mask_text, 0, sizeof mask_text); + strncpy(mask_text, inet_ntoa(ime->u.direct.mask), + ((sizeof mask_text) - 1)); + ns_debug(category, 7, "%s%saddr: %s, mask: %s", + spaces, + (ime->flags & IP_MATCH_NEGATE) ? deny : allow, + addr_text, mask_text); + break; + case ip_match_localhost: + ns_debug(category, 7, "%s%slocalhost", spaces, + (ime->flags & IP_MATCH_NEGATE) ? + deny : allow); + break; + case ip_match_localnets: + ns_debug(category, 7, "%s%slocalnets", spaces, + (ime->flags & IP_MATCH_NEGATE) ? + deny : allow); + break; + case ip_match_indirect: + ns_debug(category, 7, "%s%sindirect list %p", spaces, + (ime->flags & IP_MATCH_NEGATE) ? deny : allow, + ime->u.indirect.list); + if (ime->u.indirect.list != NULL) + dprint_ip_match_list(category, + ime->u.indirect.list, + indent+2, allow, deny); + break; + default: + panic("unexpected ime type in dprint_ip_match_list()", + NULL); + } + } +} + +int +ip_match_address(ip_match_list iml, struct in_addr address) { + ip_match_element ime; + int ret; + int indirect; + + INSIST(iml != NULL); + for (ime = iml->first; ime != NULL; ime = ime->next) { + switch (ime->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + ime->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + ime->u.indirect.list = local_networks; + indirect = 1; + break; + default: + indirect = 0; /* Make gcc happy. */ + panic("unexpected ime type in ip_match_address()", + NULL); + } + if (indirect) { + ret = ip_match_address(ime->u.indirect.list, address); + if (ret >= 0) { + if (ime->flags & IP_MATCH_NEGATE) + ret = (ret) ? 0 : 1; + return (ret); + } + } else { + if (ina_onnet(address, ime->u.direct.address, + ime->u.direct.mask)) { + if (ime->flags & IP_MATCH_NEGATE) + return (0); + else + return (1); + } + } + } + return (-1); +} + +int +ip_address_allowed(ip_match_list iml, struct in_addr address) { + int ret; + + if (iml == NULL) + return (0); + ret = ip_match_address(iml, address); + if (ret < 0) + ret = 0; + return (ret); +} + +int +ip_match_network(ip_match_list iml, struct in_addr address, + struct in_addr mask) { + ip_match_element ime; + int ret; + int indirect; + + INSIST(iml != NULL); + for (ime = iml->first; ime != NULL; ime = ime->next) { + switch (ime->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + ime->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + ime->u.indirect.list = local_networks; + indirect = 1; + break; + default: + indirect = 0; /* Make gcc happy. */ + panic("unexpected ime type in ip_match_network()", + NULL); + } + if (indirect) { + ret = ip_match_network(ime->u.indirect.list, + address, mask); + if (ret >= 0) { + if (ime->flags & IP_MATCH_NEGATE) + ret = (ret) ? 0 : 1; + return (ret); + } + } else { + if (address.s_addr == ime->u.direct.address.s_addr && + mask.s_addr == ime->u.direct.mask.s_addr) { + if (ime->flags & IP_MATCH_NEGATE) + return (0); + else + return (1); + } + } + } + return (-1); +} + +int +distance_of_address(ip_match_list iml, struct in_addr address) { + ip_match_element ime; + int ret; + int indirect; + int distance; + + INSIST(iml != NULL); + for (distance = 1, ime = iml->first; + ime != NULL; ime = ime->next, distance++) { + switch (ime->type) { + case ip_match_pattern: + indirect = 0; + break; + case ip_match_indirect: + indirect = 1; + break; + case ip_match_localhost: + ime->u.indirect.list = local_addresses; + indirect = 1; + break; + case ip_match_localnets: + ime->u.indirect.list = local_networks; + indirect = 1; + break; + default: + indirect = 0; /* Make gcc happy. */ + panic("unexpected ime type in distance_of_address()", + NULL); + } + if (indirect) { + ret = ip_match_address(ime->u.indirect.list, address); + if (ret >= 0) { + if (ime->flags & IP_MATCH_NEGATE) + ret = (ret) ? 0 : 1; + if (distance > MAX_TOPOLOGY_DISTANCE) + distance = MAX_TOPOLOGY_DISTANCE; + if (ret) + return (distance); + else + return (MAX_TOPOLOGY_DISTANCE); + } + } else { + if (ina_onnet(address, ime->u.direct.address, + ime->u.direct.mask)) { + if (distance > MAX_TOPOLOGY_DISTANCE) + distance = MAX_TOPOLOGY_DISTANCE; + if (ime->flags & IP_MATCH_NEGATE) + return (MAX_TOPOLOGY_DISTANCE); + else + return (distance); + } + } + } + return (UNKNOWN_TOPOLOGY_DISTANCE); +} + +int +ip_match_is_none(ip_match_list iml) { + ip_match_element ime; + + if (iml == NULL) + return (1); + ime = iml->first; + if (ime->type == ip_match_indirect) { + if (ime->flags & IP_MATCH_NEGATE) + return (0); + iml = ime->u.indirect.list; + if (iml == NULL) + return (0); + ime = iml->first; + } + if (ime->type == ip_match_pattern) { + if ((ime->flags & IP_MATCH_NEGATE) && + ime->u.direct.address.s_addr == 0 && + ime->u.direct.mask.s_addr == 0) + return (1); + } + return (0); +} + + +/* + * Forwarder glue + * + * XXX This will go away when the rest of bind understands + * forward zones. + */ + +void +add_forwarder(options op, struct in_addr address) { + struct fwdinfo *fip = NULL, *ftp = NULL; + +#ifdef SLAVE_FORWARD + int forward_count = 0; +#endif + + INSIST(op != NULL); + + /* On multiple forwarder lines, move to end of the list. */ +#ifdef SLAVE_FORWARD + if (op->fwdtab != NULL) { + forward_count++; + for (fip = op->fwdtab; fip->next != NULL; fip = fip->next) + forward_count++; + } +#else + if (op->fwdtab != NULL) { + for (fip = op->fwdtab; fip->next != NULL; fip = fip->next) { + ; + } + } +#endif /* SLAVE_FORWARD */ + + ftp = (struct fwdinfo *)memget(sizeof(struct fwdinfo)); + if (!ftp) + panic("memget failed in add_forwarder", NULL); + ftp->fwdaddr.sin_family = AF_INET; + ftp->fwdaddr.sin_addr = address; + ftp->fwdaddr.sin_port = ns_port; +#ifdef FWD_LOOP + if (aIsUs(ftp->fwdaddr.sin_addr)) { + ns_error(ns_log_config, "forwarder '%s' ignored, my address", + inet_ntoa(address)); + memput(ftp, sizeof *ftp); + return; + } +#endif /* FWD_LOOP */ + ns_debug(ns_log_config, 2, "added forwarder %s", inet_ntoa(address)); + ftp->next = NULL; + if (op->fwdtab == NULL) + op->fwdtab = ftp; /* First time only */ + else + fip->next = ftp; +#ifdef SLAVE_FORWARD + forward_count++; + + /* + ** Set the slave retry time to 60 seconds total divided + ** between each forwarder + */ + if (forward_count != 0) { + slave_retry = (int) (60 / forward_count); + if(slave_retry <= 0) + slave_retry = 1; + } +#endif +} + +void +free_forwarders(struct fwdinfo *fwdtab) { + struct fwdinfo *ftp, *fnext; + + for (ftp = fwdtab; ftp != NULL; ftp = fnext) { + fnext = ftp->next; + memput(ftp, sizeof *ftp); + } +} + +/* + * Servers + */ + + +static server_info +new_server(struct in_addr address) { + server_info si; + + si = (server_info)memget(sizeof (struct server_info)); + if (si == NULL) + panic("memget failed in new_server()", NULL); + si->address = address; + si->flags = 0U; + si->transfers = 0; + si->transfer_format = axfr_use_default; + si->key_list = NULL; + si->next = NULL; + return si; +} + +static void +free_server(server_info si) { + /* Don't free key; it'll be done when the auth table is freed. */ + memput(si, sizeof *si); +} + +server_info +find_server(struct in_addr address) { + server_info si; + + for (si = nameserver_info; si != NULL; si = si->next) + if (si->address.s_addr == address.s_addr) + break; + return (si); +} + +static void +add_server(server_info si) { + ip_match_element ime; + + si->next = nameserver_info; + nameserver_info = si; + + /* + * To ease transition, we'll add bogus nameservers to an + * ip matching list. This will probably be redone when the + * merging of nameserver data structures occurs. + */ + if (si->flags & SERVER_INFO_BOGUS) { + ime = new_ip_match_pattern(si->address, 32); + INSIST(ime != NULL); + add_to_ip_match_list(bogus_nameservers, ime); + } + ns_debug(ns_log_config, 3, "server %s: flags %08x transfers %d", + inet_ntoa(si->address), si->flags, si->transfers); + if (si->key_list != NULL) + dprint_key_info_list(si->key_list); +} + +static void +free_nameserver_info() { + server_info si_next, si; + + for (si = nameserver_info; si != NULL; si = si_next) { + si_next = si->next; + free_server(si); + } + nameserver_info = NULL; + if (bogus_nameservers != NULL) { + free_ip_match_list(bogus_nameservers); + bogus_nameservers = NULL; + } +} + +server_config +begin_server(struct in_addr address) { + server_config sc; + + sc.opaque = new_server(address); + return (sc); +} + +void +end_server(server_config sc, int should_install) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + if (should_install) + add_server(si); + else + free_server(si); + sc.opaque = NULL; +} + +void +set_server_option(server_config sc, int bool_opt, int value) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + switch (bool_opt) { + case SERVER_INFO_BOGUS: + if (value) + si->flags |= bool_opt; + else + si->flags &= ~bool_opt; + break; + default: + panic("unexpected option in set_server_option", NULL); + } +} + +void +set_server_transfers(server_config sc, int transfers) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + if (transfers < 0) + transfers = 0; + si->transfers = transfers; +} + +void +set_server_transfer_format(server_config sc, + enum axfr_format transfer_format) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + si->transfer_format = transfer_format; +} + +void +add_server_key_info(server_config sc, key_info ki) { + server_info si; + + si = sc.opaque; + + INSIST(si != NULL); + + if (si->key_list == NULL) + si->key_list = new_key_info_list(); + add_to_key_info_list(si->key_list, ki); +} + +/* + * Keys + */ + +key_info +new_key_info(char *name, char *algorithm, char *secret) { + key_info ki; + + INSIST(name != NULL); + INSIST(algorithm != NULL); + INSIST(secret != NULL); + ki = (key_info)memget(sizeof (struct key_info)); + if (ki == NULL) + panic("memget failed in new_key_info", NULL); + ki->name = name; + ki->algorithm = algorithm; + ki->secret = secret; + return (ki); +} + +void +free_key_info(key_info ki) { + INSIST(ki != NULL); + freestr(ki->name); + freestr(ki->algorithm); + freestr(ki->secret); + memput(ki, sizeof *ki); +} + +void +dprint_key_info(key_info ki) { + INSIST(ki != NULL); + ns_debug(ns_log_config, 7, "key %s", ki->name); + ns_debug(ns_log_config, 7, " algorithm %s", ki->algorithm); + ns_debug(ns_log_config, 7, " secret %s", ki->secret); +} + +key_info_list +new_key_info_list() { + key_info_list kil; + + kil = (key_info_list)memget(sizeof (struct key_info_list)); + if (kil == NULL) + panic("memget failed in new_key_info_list()", NULL); + kil->first = NULL; + kil->last = NULL; + return (kil); +} + +void +free_key_info_list(key_info_list kil) { + key_list_element kle, kle_next; + + INSIST(kil != NULL); + for (kle = kil->first; kle != NULL; kle = kle_next) { + kle_next = kle->next; + /* note we do NOT free kle->info */ + memput(kle, sizeof *kle); + } + memput(kil, sizeof *kil); +} + +void +add_to_key_info_list(key_info_list kil, key_info ki) { + key_list_element kle; + + INSIST(kil != NULL); + INSIST(ki != NULL); + + kle = (key_list_element)memget(sizeof (struct key_list_element)); + if (kle == NULL) + panic("memget failed in add_to_key_info_list()", NULL); + kle->info = ki; + if (kil->last != NULL) + kil->last->next = kle; + kle->next = NULL; + kil->last = kle; + if (kil->first == NULL) + kil->first = kle; +} + +void +dprint_key_info_list(key_info_list kil) { + key_list_element kle; + + INSIST(kil != NULL); + + for (kle = kil->first; kle != NULL; kle = kle->next) + dprint_key_info(kle->info); +} + +/* + * Logging. + */ + +log_config +begin_logging() { + log_config log_cfg; + log_context lc; + + log_cfg = (log_config)memget(sizeof (struct log_config)); + if (log_cfg == NULL) + ns_panic(ns_log_config, 0, + "memget failed creating log_config"); + if (log_new_context(ns_log_max_category, logging_categories, &lc) < 0) + ns_panic(ns_log_config, 0, + "log_new_context() failed: %s", strerror(errno)); + log_cfg->log_ctx = lc; + log_cfg->eventlib_channel = NULL; + log_cfg->packet_channel = NULL; + log_cfg->default_debug_active = 0; + return (log_cfg); +} + +void +add_log_channel(log_config log_cfg, int category, log_channel chan) { + log_channel_type type; + + INSIST(log_cfg != NULL); + + type = log_get_channel_type(chan); + if (category == ns_log_eventlib) { + if (type != log_file && type != log_null) { + ns_error(ns_log_config, + "must specify a file or null channel for the eventlib category"); + return; + } + if (log_cfg->eventlib_channel != NULL) { + ns_error(ns_log_config, + "only one channel allowed for the eventlib category"); + return; + } + log_cfg->eventlib_channel = chan; + } + if (category == ns_log_packet) { + if (type != log_file && type != log_null) { + ns_error(ns_log_config, + "must specify a file or null channel for the packet category"); + return; + } + if (log_cfg->packet_channel != NULL) { + ns_error(ns_log_config, + "only one channel allowed for the packet category"); + return; + } + log_cfg->packet_channel = chan; + } + + if (log_add_channel(log_cfg->log_ctx, category, chan) < 0) { + ns_error(ns_log_config, "log_add_channel() failed"); + return; + } + + if (chan == debug_channel) + log_cfg->default_debug_active = 1; +} + +void +open_special_channels() { + int using_null = 0; + + if (log_open_stream(eventlib_channel) == NULL) { + eventlib_channel = null_channel; + using_null = 1; + } + if (log_open_stream(packet_channel) == NULL) { + packet_channel = null_channel; + using_null = 1; + } + + if (using_null && + log_open_stream(null_channel) == NULL) + ns_panic(ns_log_config, 1, "couldn't open null channel"); +} + +void +set_logging(log_config log_cfg, int is_default) { + log_context lc; + int skip_debug = 0; + + INSIST(log_cfg != NULL); + lc = log_cfg->log_ctx; + + /* + * Add the default category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_default)) { + add_log_channel(log_cfg, ns_log_default, debug_channel); + add_log_channel(log_cfg, ns_log_default, syslog_channel); + } + + /* + * Add the panic category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_panic)) { + add_log_channel(log_cfg, ns_log_panic, stderr_channel); + add_log_channel(log_cfg, ns_log_panic, syslog_channel); + } + + /* + * Add the eventlib category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_eventlib)) + add_log_channel(log_cfg, ns_log_eventlib, debug_channel); + + /* + * Add the packet category if it's not in the context already. + */ + if (!log_category_is_active(lc, ns_log_packet)) + add_log_channel(log_cfg, ns_log_packet, debug_channel); + +#ifdef DEBUG + /* + * Preserve debugging state. + */ + log_option(lc, LOG_OPTION_DEBUG, debug); + log_option(lc, LOG_OPTION_LEVEL, debug); +#endif + + /* + * Special case for query-log, so we can co-exist with the command + * line option and SIGWINCH. + */ + if (log_category_is_active(lc, ns_log_queries)) + qrylog = 1; + + /* + * Cleanup the old context. + */ + if (need_logging_free) + log_free_context(log_ctx); + + /* + * The default file channels will never have their reference counts + * drop to zero, and so they will not be closed by the logging system + * when log_free_context() is called. We don't want to keep files + * open unnecessarily, and we want them to behave like user-created + * channels, so we close them here. + */ + if (log_get_stream(debug_channel) != stderr) + (void)log_close_stream(debug_channel); + (void)log_close_stream(null_channel); + + /* + * Install the new context. + */ + log_ctx = lc; + eventlib_channel = log_cfg->eventlib_channel; + packet_channel = log_cfg->packet_channel; + +#ifdef DEBUG + if (debug) { + open_special_channels(); + evSetDebug(ev, debug, log_get_stream(eventlib_channel)); + } +#endif + + log_ctx_valid = 1; + need_logging_free = 1; + logging_installed = 1; + default_logging_installed = is_default; +} + +void +end_logging(log_config log_cfg, int should_install) { + if (should_install) + set_logging(log_cfg, 0); + else + log_free_context(log_cfg->log_ctx); + memput(log_cfg, sizeof (struct log_config)); +} + +void +use_default_logging() { + log_config log_cfg; + + log_cfg = begin_logging(); + set_logging(log_cfg, 1); + memput(log_cfg, sizeof (struct log_config)); +} + +static void +init_default_log_channels() { + FILE *null_stream; + u_int flags; + char *name; + FILE *stream; + + syslog_channel = log_new_syslog_channel(0, log_info, LOG_DAEMON); + if (syslog_channel == NULL || log_inc_references(syslog_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create syslog_channel"); + + flags = LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; + if (foreground) { + name = NULL; + stream = stderr; + } else { + name = _PATH_DEBUG; + stream = NULL; + } + debug_channel = log_new_file_channel(flags, log_info, name, stream, + 0, ULONG_MAX); + if (debug_channel == NULL || log_inc_references(debug_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create debug_channel"); + + stderr_channel = log_new_file_channel(0, log_info, NULL, stderr, + 0, ULONG_MAX); + if (stderr_channel == NULL || log_inc_references(stderr_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create stderr_channel"); + + null_channel = log_new_file_channel(LOG_CHANNEL_OFF, log_info, + _PATH_DEVNULL, NULL, 0, ULONG_MAX); + if (null_channel == NULL || log_inc_references(null_channel) < 0) + ns_panic(ns_log_config, 0, "couldn't create null_channel"); +} + +static void +shutdown_default_log_channels() { + log_free_channel(syslog_channel); + log_free_channel(debug_channel); + log_free_channel(stderr_channel); + log_free_channel(null_channel); +} + +void +init_logging() { + int i; + int size; + const struct ns_sym *s; + char category_name[256]; + + size = ns_log_max_category * (sizeof (char *)); + + logging_categories = (char **)memget(size); + if (logging_categories == NULL) + ns_panic(ns_log_config, 0, "memget failed in init_logging"); + memset(logging_categories, 0, size); + for (s = category_constants; s != NULL && s->name != NULL; s++) { + sprintf(category_name, "%s: ", s->name); + logging_categories[s->number] = savestr(category_name, 1); + } + + init_default_log_channels(); + use_default_logging(); +} + +void +shutdown_logging() { + int size; + const struct ns_sym *s; + + evSetDebug(ev, 0, NULL); + shutdown_default_log_channels(); + log_free_context(log_ctx); + + for (s = category_constants; s != NULL && s->name != NULL; s++) + freestr(logging_categories[s->number]); + size = ns_log_max_category * (sizeof (char *)); + memput(logging_categories, size); +} + +/* + * Main Loader + */ + +void +init_configuration() { + /* + * Remember initial limits for use if "default" is specified in + * a config file. + */ +#ifdef HAVE_GETRUSAGE + get_initial_limits(); +#endif + zone_symbol_table = new_symbol_table(ZONE_SYM_TABLE_SIZE, NULL); + use_default_options(); + parser_initialize(); + config_initialized = 1; +} + +void +shutdown_configuration() { + REQUIRE(config_initialized); + + if (server_options != NULL) { + free_options(server_options); + server_options = NULL; + } + if (current_pid_filename != NULL) + freestr(current_pid_filename); + free_nameserver_info(); + free_symbol_table(zone_symbol_table); + parser_shutdown(); + config_initialized = 0; +} + +void +load_configuration(const char *filename) { + REQUIRE(config_initialized); + + ns_debug(ns_log_config, 3, "load configuration %s", filename); + + /* + * Clean up any previous configuration and initialize + * global data structures we'll be updating. + */ + free_nameserver_info(); + bogus_nameservers = new_ip_match_list(); + + options_installed = 0; + logging_installed = 0; + + parse_configuration(filename); + + /* + * If the user didn't specify logging or options, but they previously + * had specified one or both of them, then we need to + * re-establish the default environment. We have to be careful + * about when we install default options because the parser + * must respect limits (e.g. data-size, number of open files) + * specified in the options file. In the ordinary case where the + * options section isn't changing on a zone reload, it would be bad + * to lower these limits temporarily, because we might not survive + * to the point where they get raised back again. The logging case + * has similar motivation -- we don't want to override the existing + * logging scheme (perhaps causing log messages to go somewhere + * unexpected) when the user hasn't expressed a desire for a new + * scheme. + */ + if (!logging_installed) + use_default_logging(); + if (!options_installed && !default_options_installed) { + use_default_options(); + ns_warning(ns_log_config, "re-establishing default options"); + } + + update_pid_file(); + + /* Init or reinit the interface/port list and associated sockets. */ + getnetconf(0); + opensocket_f(); + + initial_configuration = 0; +} diff --git a/contrib/bind/bin/named/ns_defs.h b/contrib/bind/bin/named/ns_defs.h new file mode 100644 index 0000000..f81a383 --- /dev/null +++ b/contrib/bind/bin/named/ns_defs.h @@ -0,0 +1,756 @@ +/* + * from ns.h 4.33 (Berkeley) 8/23/90 + * $Id: ns_defs.h,v 8.38 1998/03/17 03:22:27 halley Exp $ + */ + +/* + * Copyright (c) 1986 + * 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) 1996, 1997 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. + */ + +/* + * Global definitions for the name server. + */ + +/* + * Effort has been expended here to make all structure members 32 bits or + * larger land on 32-bit boundaries; smaller structure members have been + * deliberately shuffled and smaller integer sizes chosen where possible + * to make sure this happens. This is all meant to avoid structure member + * padding which can cost a _lot_ of memory when you have hundreds of + * thousands of entries in your cache. + */ + +/* + * Timeout time should be around 1 minute or so. Using the + * the current simplistic backoff strategy, the sequence + * retrys after 4, 8, and 16 seconds. With 3 servers, this + * dies out in a little more than a minute. + * (sequence RETRYBASE, 2*RETRYBASE, 4*RETRYBASE... for MAXRETRY) + */ +#define MINROOTS 2 /* min number of root hints */ +#define NSMAX 16 /* max number of NS addrs to try ([0..255]) */ +#define RETRYBASE 4 /* base time between retries */ +#define MAXCLASS 255 /* XXX - may belong elsewhere */ +#define MAXRETRY 3 /* max number of retries per addr */ +#define MAXCNAMES 8 /* max # of CNAMES tried per addr */ +#define MAXQUERIES 20 /* max # of queries to be made */ +#define MAXQSERIAL 4 /* max # of outstanding QSERIAL's */ + /* (prevent "recursive" loops) */ +#define INIT_REFRESH 600 /* retry time for initial secondary */ + /* contact (10 minutes) */ +#define MIN_REFRESH 2 /* never refresh more frequently than once */ + /* every MIN_REFRESH seconds */ +#define MIN_RETRY 1 /* never retry more frequently than once */ + /* every MIN_RETRY seconds */ +#define NADDRECS 20 /* max addt'l rr's per resp */ + +#define XFER_TIMER 120 /* named-xfer's connect timeout */ +#define MAX_XFER_TIME 60*60*2 /* default max seconds for an xfer */ +#define XFER_TIME_FUDGE 10 /* MAX_XFER_TIME fudge */ +#define MAX_XFERS_RUNNING 20 /* max value of transfers_in */ +#define DEFAULT_XFERS_RUNNING 10 /* default value of transfers_in */ +#define DEFAULT_XFERS_PER_NS 2 /* default # of xfers per peer nameserver */ +#define XFER_BUFSIZE (16*1024) /* arbitrary but bigger than most MTU's */ + +#define ALPHA 0.7 /* How much to preserve of old response time */ +#define BETA 1.2 /* How much to penalize response time on failure */ +#define GAMMA 0.98 /* How much to decay unused response times */ + + /* What maintainance operations need to be performed sometime soon? */ +#define MAIN_NEED_RELOAD 0x0001 /* db_reload() needed. */ +#define MAIN_NEED_MAINT 0x0002 /* ns_maint() needed. */ +#define MAIN_NEED_ENDXFER 0x0004 /* endxfer() needed. */ +#define MAIN_NEED_ZONELOAD 0x0008 /* loadxfer() needed. */ +#define MAIN_NEED_DUMP 0x0010 /* doadump() needed. */ +#define MAIN_NEED_STATSDUMP 0x0020 /* ns_stats() needed. */ +#define MAIN_NEED_EXIT 0x0040 /* exit() needed. */ +#define MAIN_NEED_QRYLOG 0x0080 /* toggle_qrylog() needed. */ +#define MAIN_NEED_DEBUG 0x0100 /* use_desired_debug() needed. */ +#define MAIN_NEED_NOTIFY 0x0200 /* do_notify_after_load() needed */ + + /* What global options are set? */ +#define OPTION_NORECURSE 0x0001 /* Don't recurse even if asked. */ +#define OPTION_NOFETCHGLUE 0x0002 /* Don't fetch missing glue. */ +#define OPTION_FORWARD_ONLY 0x0004 /* Don't use NS RR's, just forward. */ +#define OPTION_FAKE_IQUERY 0x0008 /* Fake up bogus response to IQUERY. */ +#define OPTION_NONOTIFY 0x0010 /* Turn off notify */ +#define OPTION_NONAUTH_NXDOMAIN 0x0020 /* Generate non-auth NXDOMAINs? */ +#define OPTION_MULTIPLE_CNAMES 0x0040 /* Allow a name to have multiple + * CNAME RRs */ +#define OPTION_HOSTSTATS 0x0080 /* Maintain per-host statistics? */ +#define OPTION_DEALLOC_ON_EXIT 0x0100 /* Deallocate everything on exit? */ + +#define DEFAULT_OPTION_FLAGS (OPTION_HOSTSTATS) + +#ifdef BIND_UPDATE +#define SOAINCRINTVL 300 /* default value for the time after which + * the zone serial number must be incremented + * after a successful update has occurred */ +#define DUMPINTVL 3600 /* default interval at which to dump changed zones + * randomized, not exact */ +#define DEFERUPDCNT 100 /* default number of updates that can happen + * before the zone serial number will be + * incremented */ +#define UPDATE_TIMER XFER_TIMER +#endif /* BIND_UPDATE */ + +#define USE_MINIMUM 0xffffffff +#define MAXIMUM_TTL 0x7fffffff + +#define CLEAN_TIMER 0x01 +#define INTERFACE_TIMER 0x02 +#define STATS_TIMER 0x04 + + /* IP address accessor, network byte order. */ +#define ina_ulong(ina) (ina.s_addr) + + /* IP address accessor, host byte order, read only. */ +#define ina_hlong(ina) ntohl(ina.s_addr) + + /* IP address equality. */ + /* XXX: assumes that network byte order won't affect equality. */ +#define ina_equal(a, b) (ina_ulong(a) == ina_ulong(b)) + + /* IP address equality with a mask. */ +#define ina_onnet(h, n, m) ((ina_ulong(h) & ina_ulong(m)) == ina_ulong(n)) + + /* Sequence space arithmetic. */ +#define SEQ_GT(a,b) ((int32_t)((a)-(b)) > 0) + +#define NS_OPTION_P(option) ((server_options == NULL) ? \ + (panic(panic_msg_no_options, NULL), 0) : \ + ((server_options->flags & option) != 0)) + +#define NS_INCRSTAT(addr, which) \ + do { \ + if ((int)which >= (int)nssLast) \ + ns_panic(ns_log_insist, 1, panic_msg_bad_which, \ + __FILE__, __LINE__, #which); \ + else { \ + if (NS_OPTION_P(OPTION_HOSTSTATS)) { \ + struct nameser *ns = \ + nameserFind(addr, NS_F_INSERT); \ + if (ns != NULL) \ + ns->stats[(int)which]++; \ + } \ + globalStats[(int)which]++; \ + } \ + } while (0) + +enum severity { ignore, warn, fail, not_set }; + +enum znotify { znotify_use_default=0, znotify_yes, znotify_no }; + +enum axfr_format { axfr_use_default=0, axfr_one_answer, axfr_many_answers }; + +struct ip_match_direct { + struct in_addr address; + struct in_addr mask; +}; + +struct ip_match_indirect { + struct ip_match_list *list; +}; + +typedef enum { ip_match_pattern, ip_match_indirect, ip_match_localhost, + ip_match_localnets } ip_match_type; + +typedef struct ip_match_element { + ip_match_type type; + u_int flags; + union { + struct ip_match_direct direct; + struct ip_match_indirect indirect; + } u; + struct ip_match_element *next; +} *ip_match_element; + +/* Flags for ip_match_element */ +#define IP_MATCH_NEGATE 0x01 /* match means deny access */ + +typedef struct ip_match_list { + ip_match_element first; + ip_match_element last; +} *ip_match_list; + +typedef struct ztimer_info { + char *name; + int class; + int type; +} *ztimer_info; + +/* these fields are ordered to maintain word-alignment; + * be careful about changing them. + */ +struct zoneinfo { + char *z_origin; /* root domain name of zone */ + time_t z_time; /* time for next refresh */ + time_t z_lastupdate; /* time of last soa serial increment */ + u_int32_t z_refresh; /* refresh interval */ + u_int32_t z_retry; /* refresh retry interval */ + u_int32_t z_expire; /* expiration time for cached info */ + u_int32_t z_minimum; /* minimum TTL value */ + u_int32_t z_serial; /* changes if zone modified */ + char *z_source; /* source location of data */ + time_t z_ftime; /* modification time of source file */ + struct in_addr z_axfr_src; /* bind() the axfr socket to this */ + struct in_addr z_xaddr; /* override server for next xfer */ + struct in_addr z_addr[NSMAX]; /* list of master servers for zone */ + u_char z_addrcnt; /* number of entries in z_addr[] */ + u_char z_type; /* type of zone; see below */ + u_int16_t z_flags; /* state bits; see below */ + pid_t z_xferpid; /* xfer child pid */ + int z_class; /* class of zone */ + int z_numxfrs; /* Ref count of concurrent xfrs. */ + enum severity z_checknames; /* How to handle non-RFC-compliant names */ +#ifdef BIND_UPDATE + time_t z_dumptime; /* randomized time for next zone dump + * if Z_NEED_DUMP is set */ + u_int32_t z_dumpintvl; /* time interval between zone dumps */ + time_t z_soaincrintvl; /* interval for updating soa serial */ + time_t z_soaincrtime; /* time for soa increment */ + u_int32_t z_deferupdcnt; /* max number of updates before SOA + * serial number incremented */ + u_int32_t z_updatecnt; /* number of update requests processed + * since the last SOA serial update */ + char *z_updatelog; /* log file for updates */ +#endif + ip_match_list z_update_acl; /* list of who can issue dynamic + updates */ + ip_match_list z_query_acl; /* sites we'll answer questions for */ + ip_match_list z_transfer_acl; /* sites that may get a zone transfer + from us */ + long z_max_transfer_time_in; /* max num seconds for AXFR */ + enum znotify z_notify; /* Notify mode */ + struct in_addr z_also_notify[NSMAX]; /* More nameservers to notify */ + int z_notify_count; + evTimerID z_timer; /* maintenance timer */ + ztimer_info z_timerinfo; /* UAP associated with timer */ + time_t z_nextmaint; /* time of next maintenance */ +}; + + /* zone types (z_type) */ +enum zonetype { z_nil, z_master, z_slave, z_hint, z_stub, z_any }; +#define Z_NIL z_nil /* XXX */ +#define Z_MASTER z_master /* XXX */ +#define Z_PRIMARY z_master /* XXX */ +#define Z_SLAVE z_slave /* XXX */ +#define Z_SECONDARY z_slave /* XXX */ +#define Z_HINT z_hint /* XXX */ +#define Z_CACHE z_hint /* XXX */ +#define Z_STUB z_stub /* XXX */ +#define Z_ANY z_any /* XXX*2 */ + + /* zone state bits (16 bits) */ +#define Z_AUTH 0x0001 /* zone is authoritative */ +#define Z_NEED_XFER 0x0002 /* waiting to do xfer */ +#define Z_XFER_RUNNING 0x0004 /* asynch. xfer is running */ +#define Z_NEED_RELOAD 0x0008 /* waiting to do reload */ +#define Z_SYSLOGGED 0x0010 /* have logged timeout */ +#define Z_QSERIAL 0x0020 /* sysquery()'ing for serial number */ +#define Z_FOUND 0x0040 /* found in boot file when reloading */ +#define Z_INCLUDE 0x0080 /* set if include used in file */ +#define Z_DB_BAD 0x0100 /* errors when loading file */ +#define Z_TMP_FILE 0x0200 /* backup file for xfer is temporary */ +#ifdef BIND_UPDATE +#define Z_DYNAMIC 0x0400 /* allow dynamic updates */ +#define Z_NEED_DUMP 0x0800 /* zone has changed, needs a dump */ +#define Z_NEED_SOAUPDATE 0x1000 /* soa serial number needs increment */ +#endif /* BIND_UPDATE */ +#define Z_XFER_ABORTED 0x2000 /* zone transfer has been aborted */ +#define Z_XFER_GONE 0x4000 /* zone transfer process is gone */ +#define Z_TIMER_SET 0x8000 /* z_timer contains a valid id */ + + /* named_xfer exit codes */ +#define XFER_UPTODATE 0 /* zone is up-to-date */ +#define XFER_SUCCESS 1 /* performed transfer successfully */ +#define XFER_TIMEOUT 2 /* no server reachable/xfer timeout */ +#define XFER_FAIL 3 /* other failure, has been logged */ + +/* XXX - "struct qserv" is deprecated in favor of "struct nameser" */ +struct qserv { + struct sockaddr_in + ns_addr; /* address of NS */ + struct databuf *ns; /* databuf for NS record */ + struct databuf *nsdata; /* databuf for server address */ + struct timeval stime; /* time first query started */ + int nretry; /* # of times addr retried */ +}; + +/* + * Structure for recording info on forwarded or generated queries. + */ +struct qinfo { + u_int16_t q_id; /* id of query */ + u_int16_t q_nsid; /* id of forwarded query */ + struct sockaddr_in + q_from; /* requestor's address */ + u_char *q_msg, /* the message */ + *q_cmsg; /* the cname message */ + int16_t q_msglen, /* len of message */ + q_msgsize, /* allocated size of message */ + q_cmsglen, /* len of cname message */ + q_cmsgsize; /* allocated size of cname message */ + int16_t q_dfd; /* UDP file descriptor */ + struct fwdinfo *q_fwd; /* last forwarder used */ + time_t q_time; /* time to retry */ + time_t q_expire; /* time to expire */ + struct qinfo *q_next; /* rexmit list (sorted by time) */ + struct qinfo *q_link; /* storage list (random order) */ + struct databuf *q_usedns[NSMAX]; /* databuf for NS that we've tried */ + struct qserv q_addr[NSMAX]; /* addresses of NS's */ +#ifdef notyet + struct nameser *q_ns[NSMAX]; /* name servers */ +#endif + u_char q_naddr; /* number of addr's in q_addr */ + u_char q_curaddr; /* last addr sent to */ + u_char q_nusedns; /* number of elements in q_usedns[] */ + u_int8_t q_flags; /* see below */ + int16_t q_cname; /* # of cnames found */ + int16_t q_nqueries; /* # of queries required */ + struct qstream *q_stream; /* TCP stream, null if UDP */ + struct zoneinfo *q_zquery; /* Zone query is about (Q_ZSERIAL) */ + char *q_domain; /* domain of most enclosing zone cut */ + char *q_name; /* domain of query */ + u_int16_t q_class; /* class of query */ + u_int16_t q_type; /* type of query */ +#ifdef BIND_NOTIFY + int q_notifyzone; /* zone which needs a sysnotify() + * when the reply to this comes in. + */ +#endif +}; + + /* q_flags bits (8 bits) */ +#define Q_SYSTEM 0x01 /* is a system query */ +#define Q_PRIMING 0x02 /* generated during priming phase */ +#define Q_ZSERIAL 0x04 /* getting zone serial for xfer test */ +#define Q_USEVC 0x08 /* forward using tcp not udp */ + +#define Q_NEXTADDR(qp,n) \ + (((qp)->q_fwd == (struct fwdinfo *)0) ? \ + &(qp)->q_addr[n].ns_addr : &(qp)->q_fwd->fwdaddr) + +#define RETRY_TIMEOUT 45 + +/* + * Return codes from ns_forw: + */ +#define FW_OK 0 +#define FW_DUP 1 +#define FW_NOSERVER 2 +#define FW_SERVFAIL 3 + +typedef void (*sq_closure)(struct qstream *qs); + +#ifdef BIND_UPDATE +struct fdlist { + int fd; + struct fdlist *next; +}; +#endif + +typedef struct _interface { + int dfd, /* Datagram file descriptor */ + sfd; /* Stream file descriptor. */ + time_t gen; /* Generation number. */ + struct in_addr addr; /* Interface address. */ + u_int16_t port; /* Interface port. */ + u_int16_t flags; /* Valid bits for evXXXXID. */ + evFileID evID_d; /* Datagram read-event. */ + evConnID evID_s; /* Stream listen-event. */ + LINK(struct _interface) link; +} interface; + +#define INTERFACE_FILE_VALID 0x01 +#define INTERFACE_CONN_VALID 0x02 +#define INTERFACE_FORWARDING 0x04 + +struct qstream { + int s_rfd; /* stream file descriptor */ + int s_size; /* expected amount of data to rcv */ + int s_bufsize; /* amount of data received in s_buf */ + u_char *s_buf; /* buffer of received data */ + u_char *s_wbuf; /* send buffer */ + u_char *s_wbuf_send; /* next sendable byte of send buffer */ + u_char *s_wbuf_free; /* next free byte of send buffer */ + u_char *s_wbuf_end; /* byte after end of send buffer */ + sq_closure s_wbuf_closure; /* callback for writable descriptor */ + struct qstream *s_next; /* next stream */ + struct sockaddr_in + s_from; /* address query came from */ + interface *s_ifp; /* interface query came from */ + time_t s_time; /* time stamp of last transaction */ + int s_refcnt; /* number of outstanding queries */ + u_char s_temp[HFIXEDSZ]; +#ifdef BIND_UPDATE + int s_opcode; /* type of request */ + int s_linkcnt; /* number of client connections using + * this connection to forward updates + * to the primary */ + struct fdlist *s_fds; /* linked list of connections to the + * primaries that have been used by + * the server to forward this client's + * update requests */ +#endif + evStreamID evID_r; /* read event. */ + evFileID evID_w; /* writable event handle. */ + evConnID evID_c; /* connect event handle */ + u_int flags; /* see below */ + struct qstream_xfr { + enum { s_x_base, s_x_firstsoa, s_x_zone, + s_x_lastsoa, s_x_done } + state; /* state of transfer. */ + u_char *msg, /* current assembly message. */ + *cp, /* where are we in msg? */ + *eom, /* end of msg. */ + *ptrs[128]; /* ptrs for dn_comp(). */ + int class, /* class of an XFR. */ + id, /* id of an XFR. */ + opcode; /* opcode of an XFR. */ + u_int zone; /* zone being XFR'd. */ + struct namebuf *top; /* top np of an XFR. */ + struct qs_x_lev { /* decompose the recursion. */ + enum {sxl_ns, sxl_all, sxl_sub} + state; /* what's this level doing? */ + int flags; /* see below (SXL_*). */ + char dname[MAXDNAME]; + struct namebuf *np, /* this node. */ + *nnp, /* next node to process. */ + **npp, /* subs. */ + **npe; /* end of subs. */ + struct databuf *dp; /* current rr. */ + struct qs_x_lev *next; /* link. */ + } *lev; /* LIFO. */ + enum axfr_format transfer_format; + } xfr; +}; +#define SXL_GLUING 0x01 +#define SXL_ZONECUT 0x02 + + /* flags */ +#define STREAM_MALLOC 0x01 +#define STREAM_WRITE_EV 0x02 +#define STREAM_READ_EV 0x04 +#define STREAM_CONNECT_EV 0x08 +#define STREAM_DONE_CLOSE 0x10 +#define STREAM_AXFR 0x20 + +#define ALLOW_NETS 0x0001 +#define ALLOW_HOSTS 0x0002 +#define ALLOW_ALL (ALLOW_NETS | ALLOW_HOSTS) + +struct fwdinfo { + struct fwdinfo *next; + struct sockaddr_in + fwdaddr; +}; + +enum nameserStats { nssRcvdR, /* sent us an answer */ + nssRcvdNXD, /* sent us a negative response */ + nssRcvdFwdR, /* sent us a response we had to fwd */ + nssRcvdDupR, /* sent us an extra answer */ + nssRcvdFail, /* sent us a SERVFAIL */ + nssRcvdFErr, /* sent us a FORMERR */ + nssRcvdErr, /* sent us some other error */ + nssRcvdAXFR, /* sent us an AXFR */ + nssRcvdLDel, /* sent us a lame delegation */ + nssRcvdOpts, /* sent us some IP options */ + nssSentSysQ, /* sent them a sysquery */ + nssSentAns, /* sent them an answer */ + nssSentFwdQ, /* fwdd a query to them */ + nssSentDupQ, /* sent them a retry */ + nssSendtoErr, /* error in sendto */ + nssRcvdQ, /* sent us a query */ + nssRcvdIQ, /* sent us an inverse query */ + nssRcvdFwdQ, /* sent us a query we had to fwd */ + nssRcvdDupQ, /* sent us a retry */ + nssRcvdTCP, /* sent us a query using TCP */ + nssSentFwdR, /* fwdd a response to them */ + nssSentFail, /* sent them a SERVFAIL */ + nssSentFErr, /* sent them a FORMERR */ + nssSentNaAns, /* sent them a non autoritative answer */ + nssSentNXD, /* sent them a negative response */ + nssLast }; + +struct nameser { + struct in_addr addr; /* key */ + u_long stats[nssLast]; /* statistics */ +#ifdef notyet + u_int32_t rtt; /* round trip time */ + /* XXX - need to add more stuff from "struct qserv", and use our rtt */ + u_int16_t flags; /* see below */ +#endif + u_int8_t xfers; /* #/xfers running right now */ +}; + +enum transport { primary_trans, secondary_trans, response_trans, num_trans }; + +/* types used by the parser or config routines */ + +typedef struct zone_config { + void *opaque; +} zone_config; + +typedef struct listen_info { + u_short port; + ip_match_list list; + struct listen_info *next; +} *listen_info; + +typedef struct listen_info_list { + listen_info first; + listen_info last; +} *listen_info_list; + +#ifndef RLIMIT_TYPE +#define RLIMIT_TYPE u_long +#endif +typedef RLIMIT_TYPE rlimit_type; + +typedef struct options { + u_int flags; + char *directory; + char *dump_filename; + char *pid_filename; + char *stats_filename; + char *memstats_filename; + char *named_xfer; + int transfers_in; + int transfers_per_ns; + int transfers_out; + enum axfr_format transfer_format; + long max_transfer_time_in; + struct sockaddr_in query_source; + ip_match_list query_acl; + ip_match_list transfer_acl; + ip_match_list topology; + enum severity check_names[num_trans]; + u_long data_size; + u_long stack_size; + u_long core_size; + u_long files; + listen_info_list listen_list; + struct fwdinfo *fwdtab; + /* XXX need to add forward option */ + int clean_interval; + int interface_interval; + int stats_interval; +} *options; + +typedef struct key_info { + char *name; + char *algorithm; + char *secret; /* XXX should be u_char? */ +} *key_info; + +typedef struct key_list_element { + key_info info; + struct key_list_element *next; +} *key_list_element; + +typedef struct key_info_list { + key_list_element first; + key_list_element last; +} *key_info_list; + +typedef struct topology_config { + void *opaque; +} topology_config; + +#define UNKNOWN_TOPOLOGY_DISTANCE 9998 +#define MAX_TOPOLOGY_DISTANCE 9999 + +typedef struct topology_distance { + ip_match_list patterns; + struct topology_distance *next; +} *topology_distance; + +typedef struct topology_context { + topology_distance first; + topology_distance last; +} *topology_context; + +typedef struct acl_table_entry { + char *name; + ip_match_list list; + struct acl_table_entry *next; +} *acl_table_entry; + +typedef struct server_config { + void *opaque; +} server_config; + +#define SERVER_INFO_BOGUS 0x01 + +typedef struct server_info { + struct in_addr address; + u_int flags; + int transfers; + enum axfr_format transfer_format; + key_info_list key_list; + /* could move statistics to here, too */ + struct server_info *next; +} *server_info; + +/* + * enum <--> name translation + */ + +struct ns_sym { + int number; /* Identifying number, like ns_log_default */ + char * name; /* Its symbolic name, like "default" */ +}; + +/* + * Logging options + */ + +typedef enum ns_logging_categories { + ns_log_default = 0, + ns_log_config, + ns_log_parser, + ns_log_queries, + ns_log_lame_servers, + ns_log_statistics, + ns_log_panic, + ns_log_update, + ns_log_ncache, + ns_log_xfer_in, + ns_log_xfer_out, + ns_log_db, + ns_log_eventlib, + ns_log_packet, + ns_log_notify, + ns_log_cname, + ns_log_security, + ns_log_os, + ns_log_insist, + ns_log_maint, + ns_log_load, + ns_log_resp_checks, + ns_log_max_category +} ns_logging_categories; + +typedef struct log_config { + log_context log_ctx; + log_channel eventlib_channel; + log_channel packet_channel; + int default_debug_active; +} *log_config; + +struct map { + char * token; + int val; +}; + +#define NOERROR_NODATA 6 /* only used internally by the server, used for + * -ve $ing non-existence of records. 6 is not + * a code used as yet anyway. anant@isi.edu + */ + +#define NTTL 600 /* ttl for negative data: 10 minutes? */ + +#define VQEXPIRY 900 /* a VQ entry expires in 15*60 = 900 seconds */ + +#ifdef BIND_UPDATE +enum req_action { Finish, Refuse, Return }; +#endif + +#ifdef BIND_NOTIFY +typedef enum { + notify_info_waitfor, notify_info_delay, notify_info_error, + notify_info_done +} notify_info_state; + +typedef struct notify_info { + char *name; + int class; + notify_info_state state; + evWaitID wait_id; + evTimerID timer_id; + LINK(struct notify_info) link; +} *notify_info; + +typedef LIST(struct notify_info) notify_info_list; +#endif /* BIND_NOTIFY */ + +#ifdef INIT + error "INIT already defined, check system include files" +#endif +#ifdef DECL + error "DECL already defined, check system include files" +#endif + +#ifdef MAIN_PROGRAM +#define INIT(x) = x +#define DECL +#else +#define INIT(x) +#define DECL extern +#endif diff --git a/contrib/bind/bin/named/ns_forw.c b/contrib/bind/bin/named/ns_forw.c new file mode 100644 index 0000000..9c72825 --- /dev/null +++ b/contrib/bind/bin/named/ns_forw.c @@ -0,0 +1,1132 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)ns_forw.c 4.32 (Berkeley) 3/3/91"; +static char rcsid[] = "$Id: ns_forw.c,v 8.34 1998/02/24 01:02:40 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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) 1996, 1997 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 "port_before.h" + +#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 <errno.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +struct complaint { + u_long tag1, tag2; + time_t expire; + struct complaint *next; +}; + +static struct complaint *complaints = NULL; +static int retry_timer_set = 0; + +/* + * Forward the query to get the answer since its not in the database. + * Returns FW_OK if a request struct is allocated and the query sent. + * Returns FW_DUP if this is a duplicate of a pending request. + * Returns FW_NOSERVER if there were no addresses for the nameservers. + * Returns FW_SERVFAIL on memory allocation error or if asked to do something + * dangerous, such as fwd to ourselves or fwd to the host that asked us. + * + * (no action is taken on errors and qpp is not filled in.) + */ +int +ns_forw(struct databuf *nsp[], u_char *msg, int msglen, + struct sockaddr_in from, struct qstream *qsp, int dfd, + struct qinfo **qpp, const char *dname, int class, int type, + struct namebuf *np, int use_tcp) +{ + struct qinfo *qp; + char tmpdomain[MAXDNAME]; + struct sockaddr_in *nsa; + HEADER *hp; + u_int16_t id; + int n; + + ns_debug(ns_log_default, 3, "ns_forw()"); + + hp = (HEADER *) msg; + id = hp->id; + /* Look at them all */ + for (qp = nsqhead; qp != NULL; qp = qp->q_link) { + if (qp->q_id == id && + memcmp(&qp->q_from, &from, sizeof qp->q_from) == 0 && + ((qp->q_cmsglen == 0 && qp->q_msglen == msglen && + memcmp(qp->q_msg + 2, msg + 2, msglen - 2) == 0) || + (qp->q_cmsglen == msglen && + memcmp(qp->q_cmsg + 2, msg + 2, msglen - 2) == 0) + )) { + ns_debug(ns_log_default, 3, "forw: dropped DUP id=%d", + ntohs(id)); + nameserIncr(from.sin_addr, nssRcvdDupQ); + return (FW_DUP); + } + } + + qp = qnew(dname, class, type); + getname(np, tmpdomain, sizeof tmpdomain); + qp->q_domain = savestr(tmpdomain, 1); + qp->q_from = from; /* nslookup wants to know this */ + n = nslookup(nsp, qp, dname, "ns_forw"); + if (n < 0) { + ns_debug(ns_log_default, 2, "forw: nslookup reports danger"); + ns_freeqry(qp); + return (FW_SERVFAIL); + } + if (n == 0 && !server_options->fwdtab) { + ns_debug(ns_log_default, 2, "forw: no nameservers found"); + ns_freeqry(qp); + return (FW_NOSERVER); + } + qp->q_stream = qsp; + qp->q_curaddr = 0; + qp->q_fwd = server_options->fwdtab; + qp->q_dfd = dfd; + qp->q_id = id; + qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; + if (use_tcp) + qp->q_flags |= Q_USEVC; + hp->id = qp->q_nsid = htons(nsid_next()); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + if ((qp->q_msg = (u_char *)memget((unsigned)msglen)) == NULL) { + ns_notice(ns_log_default, "forw: memget: %s", + strerror(errno)); + ns_freeqry(qp); + return (FW_SERVFAIL); + } + qp->q_msgsize = msglen; + memcpy(qp->q_msg, msg, qp->q_msglen = msglen); + if (!qp->q_fwd) { + hp->rd = 0; + qp->q_addr[0].stime = tt; + } + +#ifdef SLAVE_FORWARD + if (NS_OPTION_P(OPTION_FORWARD_ONLY)) + schedretry(qp, (time_t)slave_retry); + else +#endif /* SLAVE_FORWARD */ + schedretry(qp, qp->q_fwd ?(2*RETRYBASE) :retrytime(qp)); + + nsa = Q_NEXTADDR(qp, 0); + ns_debug(ns_log_default, 1, + "forw: forw -> [%s].%d ds=%d nsid=%d id=%d %dms retry %dsec", + inet_ntoa(nsa->sin_addr), + ntohs(nsa->sin_port), ds, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (qp->q_addr[0].nsdata != NULL) + ? qp->q_addr[0].nsdata->d_nstime + : -1, + (int)(qp->q_time - tt.tv_sec)); +#ifdef DEBUG + if (debug >= 10) + fp_nquery(msg, msglen, log_get_stream(packet_channel)); +#endif + if (qp->q_flags & Q_USEVC) { + if (tcp_send(qp) != NOERROR) { + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)tcpsendStr)) + ns_info(ns_log_default, + "ns_forw: tcp_send(%s) failed: %s", + sin_ntoa(*nsa), strerror(errno)); + } + } else if (sendto(ds, (char *)msg, msglen, 0, (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) { + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, "ns_forw: sendto(%s): %s", + sin_ntoa(*nsa), strerror(errno)); + nameserIncr(nsa->sin_addr, nssSendtoErr); + } + if (NS_OPTION_P(OPTION_HOSTSTATS)) + nameserIncr(from.sin_addr, nssRcvdFwdQ); + nameserIncr(nsa->sin_addr, nssSentFwdQ); + if (qpp) + *qpp = qp; + hp->rd = 1; + return (0); +} + +/* haveComplained(tag1, tag2) + * check to see if we have complained about (tag1,tag2) recently + * returns: + * boolean: have we complained recently? + * side-effects: + * outdated complaint records removed from our static list + * author: + * Paul Vixie (DECWRL) April 1991 + */ +int +haveComplained(u_long tag1, u_long tag2) { + struct complaint *cur, *next, *prev; + int r = 0; + + for (cur = complaints, prev = NULL; + cur != NULL; + prev = cur, cur = next) { + next = cur->next; + if (tt.tv_sec > cur->expire) { + if (prev) + prev->next = next; + else + complaints = next; + memput(cur, sizeof *cur); + cur = prev; + } else if (tag1 == cur->tag1 && tag2 == cur->tag2) + r++; + } + if (!r) { + cur = (struct complaint *)memget(sizeof(struct complaint)); + if (cur) { + cur->tag1 = tag1; + cur->tag2 = tag2; + cur->expire = tt.tv_sec + INIT_REFRESH; /* "10:00" */ + cur->next = NULL; + if (prev) + prev->next = cur; + else + complaints = cur; + } + } + return (r); +} + +void +freeComplaints(void) { + struct complaint *cur, *next; + + for (cur = complaints; cur != NULL; cur = next) { + next = cur->next; + memput(cur, sizeof *cur); + } + complaints = NULL; +} + +/* void + * nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr) + * Issue a complaint about a dangerous situation found by nslookup(). + * params: + * sysloginfo is a string identifying the complainant. + * queryname is the domain name associated with the problem. + * complaint is a string describing what is wrong. + * dname and a_rr are the problematic other name server. + */ +static void +nslookupComplain(const char *sysloginfo, const char *queryname, + const char *complaint, const char *dname, + const struct databuf *a_rr, const struct databuf *nsdp) +{ + char *a, *ns; + const char *a_type; + int print_a; + + ns_debug(ns_log_default, 2, "NS '%s' %s", dname, complaint); + if (sysloginfo && queryname && !haveComplained((u_long)queryname, + (u_long)complaint)) { + char buf[999]; + + a = ns = (char *)NULL; + print_a = (a_rr->d_type == T_A); + a_type = p_type(a_rr->d_type); + if (a_rr->d_rcode) { + print_a = 0; + switch(a_rr->d_rcode) { + case NXDOMAIN: + a_type = "NXDOMAIN"; + break; + case NOERROR_NODATA: + a_type = "NODATA"; + break; + } + } + if (NS_OPTION_P(OPTION_HOSTSTATS)) { + char nsbuf[20], abuf[20]; + + if (nsdp != NULL) { + if (nsdp->d_ns != NULL) { + strcpy(nsbuf, + inet_ntoa(nsdp->d_ns->addr)); + ns = nsbuf; + } else { + ns = zones[nsdp->d_zone].z_origin; + } + } + if (a_rr->d_ns != NULL) { + strcpy(abuf, inet_ntoa(a_rr->d_ns->addr)); + a = abuf; + } else { + a = zones[a_rr->d_zone].z_origin; + } + } + if (a != NULL || ns != NULL) + ns_info(ns_log_default, + "%s: query(%s) %s (%s:%s) learnt (%s=%s:NS=%s)", + sysloginfo, queryname, + complaint, dname, + print_a ? + inet_ntoa(ina_get(a_rr->d_data)) : "", + a_type, + a ? a : "<Not Available>", + ns ? ns : "<Not Available>" ); + else + ns_info(ns_log_default, "%s: query(%s) %s (%s:%s)", + sysloginfo, queryname, + complaint, dname, + print_a ? + inet_ntoa(ina_get(a_rr->d_data)) : ""); + } +} + +/* + * nslookup(nsp, qp, syslogdname, sysloginfo) + * Lookup the address for each nameserver in `nsp' and add it to + * the list saved in the qinfo structure pointed to by `qp'. + * Omits information about nameservers that we shouldn't ask. + * Detects the following dangerous operations: + * One of the A records for one of the nameservers in nsp + * refers to the address of one of our own interfaces; + * One of the A records refers to the nameserver port on + * the host that asked us this question. + * returns: the number of addresses added, or -1 if a dangerous operation + * is detected. + * side effects: + * logs if a dangerous situation is detected and + * (syslogdname && sysloginfo) + */ +int +nslookup(struct databuf *nsp[], struct qinfo *qp, + const char *syslogdname, const char *sysloginfo) +{ + struct namebuf *np; + struct databuf *dp, *nsdp; + struct qserv *qs; + int n; + u_int i; + struct hashbuf *tmphtp; + char *dname; + const char *fname; + int oldn, naddr, class, found_arr, potential_ns; + time_t curtime; + + ns_debug(ns_log_default, 3, "nslookup(nsp=%#x, qp=%#x, \"%s\")", + nsp, qp, syslogdname); + + potential_ns = 0; + naddr = n = qp->q_naddr; + curtime = (u_long) tt.tv_sec; + while ((nsdp = *nsp++) != NULL) { + class = nsdp->d_class; + dname = (char *)nsdp->d_data; + ns_debug(ns_log_default, 3, + "nslookup: NS \"%s\" c=%d t=%d (flags 0x%lu)", + dname, class, nsdp->d_type, (u_long)nsdp->d_flags); + + /* don't put in servers we have tried */ + for (i = 0; i < qp->q_nusedns; i++) { + if (qp->q_usedns[i] == nsdp) { + ns_debug(ns_log_default, 2, + "skipping used NS w/name %s", + nsdp->d_data); + goto skipserver; + } + } + + tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab); + np = nlookup(dname, &tmphtp, &fname, 1); + if (np == NULL) { + ns_debug(ns_log_default, 3, "%s: not found %s %#x", + dname, fname, np); + found_arr = 0; + goto need_sysquery; + } + if (fname != dname) { + if (findMyZone(np, class) == DB_Z_CACHE) { + /* + * lifted from findMyZone() + * We really need to know if the NS + * is the bottom of one of our zones + * to see if we've got missing glue + */ + for (; np; np = np_parent(np)) + for (dp = np->n_data; dp; dp = dp->d_next) + if (match(dp, class, T_NS)) { + if (dp->d_rcode) + break; + if (dp->d_zone) { + static char *complaint = + "Glue A RR missing"; + nslookupComplain(sysloginfo, + syslogdname, + complaint, + dname, dp, + nsdp); + goto skipserver; + } else { + found_arr = 0; + goto need_sysquery; + } + } + /* shouldn't happen, but ... */ + found_arr = 0; + goto need_sysquery; + } else { + /* Authoritative A RR missing. */ + continue; + } + } + found_arr = 0; + oldn = n; + + /* look for name server addresses */ + delete_stale(np); + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + struct in_addr nsa; + + if (dp->d_type == T_CNAME && dp->d_class == class) { + static const char *complaint = + "NS points to CNAME"; + if (dp->d_rcode) + continue; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + goto skipserver; + } + if (dp->d_type != T_A || dp->d_class != class) + continue; + if (dp->d_rcode) { + static const char *complaint = + "A RR negative cache entry"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + goto skipserver; + } + if (ina_hlong(ina_get(dp->d_data)) == INADDR_ANY) { + static const char *complaint = + "Bogus (0.0.0.0) A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#ifdef INADDR_LOOPBACK + if (ina_hlong(ina_get(dp->d_data))==INADDR_LOOPBACK) { + static const char *complaint = + "Bogus LOOPBACK A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#endif +#ifdef INADDR_BROADCAST + if (ina_hlong(ina_get(dp->d_data))==INADDR_BROADCAST){ + static const char *complaint = + "Bogus BROADCAST A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#endif +#ifdef IN_MULTICAST + if (IN_MULTICAST(ina_hlong(ina_get(dp->d_data)))) { + static const char *complaint = + "Bogus MULTICAST A RR"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#endif + /* + * Don't use records that may become invalid to + * reference later when we do the rtt computation. + * Never delete our safety-belt information! + */ + if ((dp->d_zone == DB_Z_CACHE) && + (dp->d_ttl < (u_int32_t)curtime) && + !(dp->d_flags & DB_F_HINT) ) + { + ns_debug(ns_log_default, 1, + "nslookup: stale '%s'", + NAME(*np)); + n = oldn; + found_arr = 0; + goto need_sysquery; + } + + found_arr++; + nsa = ina_get(dp->d_data); + /* don't put in duplicates */ + qs = qp->q_addr; + for (i = 0; i < (u_int)n; i++, qs++) + if (ina_equal(qs->ns_addr.sin_addr, nsa)) + goto skipaddr; + qs->ns_addr.sin_family = AF_INET; + qs->ns_addr.sin_port = ns_port; + qs->ns_addr.sin_addr = nsa; + qs->ns = nsdp; + qs->nsdata = dp; + qs->nretry = 0; + /* + * If this A RR has no RTT, initialize its RTT to a + * small random value. + */ + if (dp->d_nstime == 0) + dp->d_nstime = 1 + + (int)(25.0*rand()/(RAND_MAX + 1.0)); + /* + * if we are being asked to fwd a query whose + * nameserver list includes our own name/address(es), + * then we have detected a lame delegation and rather + * than melt down the network and hose down the other + * servers (who will hose us in return), we'll return + * -1 here which will cause SERVFAIL to be sent to + * the client's resolver which will hopefully then + * shut up. + * + * (originally done in nsContainsUs by vix@dec mar92; + * moved into nslookup by apb@und jan1993) + * + * try to limp along instead of denying service + * gdonl mar96 + */ + if (aIsUs(nsa)) { + static char *complaint = "contains our address"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } + /* + * If we want to forward to a host that asked us + * this question then either we or they are sick + * (unless they asked from some port other than + * their nameserver port). (apb@und jan1993) + * + * try to limp along instead of denying service + * gdonl mar96 + */ + if (memcmp(&qp->q_from, &qs->ns_addr, + sizeof(qp->q_from)) == 0) + { + static char *complaint = "forwarding loop"; + nslookupComplain(sysloginfo, syslogdname, + complaint, dname, dp, nsdp); + continue; + } +#ifdef BOGUSNS + /* + * Don't forward queries to bogus servers. Note + * that this is unlike the previous tests, which + * are fatal to the query. Here we just skip the + * server, which is only fatal if it's the last + * server. Note also that we antialias here -- all + * A RR's of a server are considered the same server, + * and if any of them is bogus we skip the whole + * server. Those of you using multiple A RR's to + * load-balance your servers will (rightfully) lose + * here. But (unfortunately) only if they are bogus. + */ + if (ip_match_address(bogus_nameservers, nsa) > 0) + goto skipserver; +#endif + + n++; + if (n >= NSMAX) + goto out; + skipaddr: + (void)NULL; + } + ns_debug(ns_log_default, 8, "nslookup: %d ns addrs", n); + need_sysquery: + if (found_arr == 0) { + potential_ns++; + if (!(qp->q_flags & Q_SYSTEM)) + (void) sysquery(dname, class, T_A, NULL, 0, + QUERY); + } + skipserver: + (void)NULL; + } + out: + ns_debug(ns_log_default, 3, "nslookup: %d ns addrs total", n); + qp->q_naddr = n; + if (n == 0 && potential_ns == 0 && !server_options->fwdtab) { + static char *complaint = "No possible A RRs"; + if (sysloginfo && syslogdname && + !haveComplained((u_long)syslogdname, (u_long)complaint)) + { + ns_info(ns_log_default, "%s: query(%s) %s", + sysloginfo, syslogdname, complaint); + } + return(-1); + } + /* Update the refcounts before the sort. */ + for (i = naddr; i < (u_int)n; i++) { + DRCNTINC(qp->q_addr[i].nsdata); + DRCNTINC(qp->q_addr[i].ns); + } + if (n > 1) { + qsort((char *)qp->q_addr, n, sizeof(struct qserv), + (int (*)(const void *, const void *))qcomp); + } + return (n - naddr); +} + +/* + * qcomp - compare two NS addresses, and return a negative, zero, or + * positive value depending on whether the first NS address is + * "better than", "equally good as", or "inferior to" the second + * NS address. + * + * How "goodness" is defined (for the purposes of this routine): + * - If the estimated round trip times differ by an amount deemed significant + * then the one with the smaller estimate is preferred; else + * - If we can determine which one is topologically closer then the + * closer one is preferred; else + * - The one with the smaller estimated round trip time is preferred + * (zero is returned if the two estimates are identical). + * + * How "topological closeness" is defined (for the purposes of this routine): + * Ideally, named could consult some magic map of the Internet and + * determine the length of the path to an arbitrary destination. Sadly, + * no such magic map exists. However, named does have a little bit of + * topological information in the form of the sortlist (which includes + * the directly connected subnet(s), the directly connected net(s), and + * any additional nets that the administrator has added using the "sortlist" + * directive in the bootfile. Thus, if only one of the addresses matches + * something in the sortlist then it is considered to be topologically + * closer. If both match, but match different entries in the sortlist, + * then the one that matches the entry closer to the beginning of the + * sorlist is considered to be topologically closer. In all other cases, + * topological closeness is ignored because it's either indeterminate or + * equal. + * + * How times are compared: + * Both times are rounded to the closest multiple of the NOISE constant + * defined below and then compared. If the rounded values are equal + * then the difference in the times is deemed insignificant. Rounding + * is used instead of merely taking the absolute value of the difference + * because doing the latter would make the ordering defined by this + * routine be incomplete in the mathematical sense (e.g. A > B and + * B > C would not imply A > C). The mathematics are important in + * practice to avoid core dumps in qsort(). + * + * XXX: this doesn't solve the European root nameserver problem very well. + * XXX: we should detect and mark as inferior nameservers that give bogus + * answers + * + * (this was originally vixie's stuff but almquist fixed fatal bugs in it + * and wrote the above documentation) + */ + +/* + * RTT delta deemed to be significant, in milliseconds. With the current + * definition of RTTROUND it must be a power of 2. + */ +#define NOISE 128 /* milliseconds; 0.128 seconds */ + +#define sign(x) (((x) < 0) ? -1 : ((x) > 0) ? 1 : 0) +#define RTTROUND(rtt) (((rtt) + (NOISE >> 1)) & ~(NOISE - 1)) + +int +qcomp(struct qserv *qs1, struct qserv *qs2) { + int pos1, pos2, pdiff; + u_long rtt1, rtt2; + long tdiff; + + if ((!qs1->nsdata) || (!qs2->nsdata)) + return 0; + rtt1 = qs1->nsdata->d_nstime; + rtt2 = qs2->nsdata->d_nstime; + +#ifdef DEBUG + if (debug >= 10) { + char a1[sizeof "255.255.255.255"], + a2[sizeof "255.255.255.255"]; + + strcpy(a1, inet_ntoa(qs1->ns_addr.sin_addr)); + strcpy(a2, inet_ntoa(qs2->ns_addr.sin_addr)); + ns_debug(ns_log_default, 10, + "qcomp(%s, %s) %lu (%lu) - %lu (%lu) = %lu", + a1, a2, + rtt1, RTTROUND(rtt1), + rtt2, RTTROUND(rtt2), + rtt1 - rtt2); + } +#endif + if (RTTROUND(rtt1) == RTTROUND(rtt2)) { + pos1 = distance_of_address(server_options->topology, + qs1->ns_addr.sin_addr); + pos2 = distance_of_address(server_options->topology, + qs2->ns_addr.sin_addr); + pdiff = pos1 - pos2; + ns_debug(ns_log_default, 10, "\tpos1=%d, pos2=%d", pos1, pos2); + if (pdiff) + return (pdiff); + } + tdiff = rtt1 - rtt2; + return (sign(tdiff)); +} +#undef sign +#undef RTTROUND + +/* + * Arrange that forwarded query (qp) is retried after t seconds. + * Query list will be sorted after z_time is updated. + */ +void +schedretry(struct qinfo *qp, time_t t) { + struct qinfo *qp1, *qp2; + + ns_debug(ns_log_default, 4, "schedretry(%#x, %ld sec)", qp, (long)t); + if (qp->q_time) + ns_debug(ns_log_default, 4, + "WARNING: schedretry(%#lx, %ld) q_time already %ld", + (u_long)qp, (long)t, (long)qp->q_time); + gettime(&tt); + t += (u_long) tt.tv_sec; + qp->q_time = t; + + if ((qp1 = retryqp) == NULL) { + retryqp = qp; + qp->q_next = NULL; + goto done; + } + if (t < qp1->q_time) { + qp->q_next = qp1; + retryqp = qp; + goto done; + } + while ((qp2 = qp1->q_next) != NULL && qp2->q_time < t) + qp1 = qp2; + qp1->q_next = qp; + qp->q_next = qp2; + done: + reset_retrytimer(); +} + +/* + * Unsched is called to remove a forwarded query entry. + */ +void +unsched(struct qinfo *qp) { + struct qinfo *np; + + ns_debug(ns_log_default, 3, "unsched(%#lx, %d)", + (u_long)qp, ntohs(qp->q_id)); + if (retryqp == qp) { + retryqp = qp->q_next; + } else { + for (np = retryqp; np->q_next != NULL; np = np->q_next) { + if (np->q_next != qp) + continue; + np->q_next = qp->q_next; /* dequeue */ + break; + } + } + qp->q_next = NULL; /* sanity check */ + qp->q_time = 0; + reset_retrytimer(); +} + +void +reset_retrytimer() { + static evTimerID id; + + if (retry_timer_set) { + (void) evClearTimer(ev, id); + retry_timer_set = 0; + } + + if (retryqp) { + evSetTimer(ev, retrytimer, NULL, + evConsTime(retryqp->q_time, 0), + evConsTime(0, 0), &id); + retry_timer_set = 1; + } else + memset(&id, 0, sizeof id); +} + +void +retrytimer(evContext ctx, void *uap, struct timespec due, + struct timespec ival) { + retry_timer_set = 0; + retry(retryqp); +} + +/* + * Retry is called to retransmit query 'qp'. + */ +void +retry(struct qinfo *qp) { + int n; + HEADER *hp; + struct sockaddr_in *nsa; + + ns_debug(ns_log_default, 3, "retry(%#lx) id=%d", (u_long)qp, + ntohs(qp->q_id)); + + if (qp->q_msg == NULL) { /* XXX - why? */ + qremove(qp); + return; + } + + if (qp->q_expire < tt.tv_sec) { + ns_debug(ns_log_default, 1, + "retry(%#lx): expired @ %lu (%d secs before now (%lu))", + (u_long)qp, (u_long)qp->q_expire, + (int)(tt.tv_sec - qp->q_expire), + (u_long)tt.tv_sec); + if (qp->q_stream || (qp->q_flags & Q_PRIMING)) + goto fail; + qremove(qp); + return; + } + + /* try next address */ + n = qp->q_curaddr; + if (qp->q_fwd != NULL) { + qp->q_fwd = qp->q_fwd->next; + if (qp->q_fwd != NULL) + goto found; + /* Out of forwarders, try direct queries. */ + } + if (qp->q_naddr > 0) { + ++qp->q_addr[n].nretry; + if (!NS_OPTION_P(OPTION_FORWARD_ONLY)) { + do { + if (++n >= (int)qp->q_naddr) + n = 0; + if (qp->q_addr[n].nretry < MAXRETRY) + goto found; + } while (n != qp->q_curaddr); + } + } + fail: + /* + * Give up. Can't reach destination. + */ + hp = (HEADER *)(qp->q_cmsg ? qp->q_cmsg : qp->q_msg); + if (qp->q_flags & Q_PRIMING) { + /* Can't give up priming */ + if (qp->q_expire < tt.tv_sec) { + /* + * The query has expired. Reset it and retry from + * the beginning. + */ + hp->rcode = NOERROR; + hp->qr = hp->aa = 0; + qp->q_fwd = server_options->fwdtab; + for (n = 0; n < (int)qp->q_naddr; n++) + qp->q_addr[n].nretry = 0; + n = 0; + qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; + goto found; + } + /* + * The query hasn't expired yet; it probably ran out + * of servers or forwarders. Wait up to 60 seconds + * past the expire time. + */ + unsched(qp); + schedretry(qp, (time_t)(qp->q_expire - tt.tv_sec + 60)); + return; + } + ns_debug(ns_log_default, 5, "give up"); + n = ((HEADER *)qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen); + hp->id = qp->q_id; + hp->qr = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + hp->rd = 1; + hp->rcode = SERVFAIL; +#ifdef DEBUG + if (debug >= 10) + fp_nquery(qp->q_msg, n, log_get_stream(packet_channel)); +#endif + if (send_msg((u_char *)hp, n, qp)) { + ns_debug(ns_log_default, 1, + "gave up retry(%#lx) nsid=%d id=%d", + (u_long)qp, ntohs(qp->q_nsid), ntohs(qp->q_id)); + } + if (NS_OPTION_P(OPTION_HOSTSTATS)) + nameserIncr(qp->q_from.sin_addr, nssSentFail); + qremove(qp); + return; + + found: + if (qp->q_fwd == 0 && qp->q_addr[n].nretry == 0) + qp->q_addr[n].stime = tt; + qp->q_curaddr = n; + hp = (HEADER *)qp->q_msg; + hp->rd = (qp->q_fwd ? 1 : 0); + nsa = Q_NEXTADDR(qp, n); + ns_debug(ns_log_default, 1, + "%s(addr=%d n=%d) -> [%s].%d ds=%d nsid=%d id=%d %dms", + (qp->q_fwd ? "reforw" : "resend"), + n, qp->q_addr[n].nretry, + inet_ntoa(nsa->sin_addr), + ntohs(nsa->sin_port), ds, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (qp->q_addr[n].nsdata != 0) + ? qp->q_addr[n].nsdata->d_nstime + : (-1)); +#ifdef DEBUG + if (debug >= 10) + fp_nquery(qp->q_msg, qp->q_msglen, + log_get_stream(packet_channel)); +#endif + if (qp->q_flags & Q_USEVC) { + if (tcp_send(qp) != NOERROR) + ns_debug(ns_log_default, 3, + "error resending tcp msg: %s", + strerror(errno)); + } else if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0, + (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) + { + ns_debug(ns_log_default, 3, "error resending msg: %s", + strerror(errno)); + } + hp->rd = 1; /* leave set to 1 for dup detection */ + nameserIncr(nsa->sin_addr, nssSentDupQ); + unsched(qp); +#ifdef SLAVE_FORWARD + if (NS_OPTION_P(OPTION_FORWARD_ONLY)) + schedretry(qp, (time_t)slave_retry); + else +#endif /* SLAVE_FORWARD */ + schedretry(qp, qp->q_fwd ? (2*RETRYBASE) : retrytime(qp)); +} + +/* + * Compute retry time for the next server for a query. + * Use a minimum time of RETRYBASE (4 sec.) or twice the estimated + * service time; * back off exponentially on retries, but place a 45-sec. + * ceiling on retry times for now. (This is because we don't hold a reference + * on servers or their addresses, and we have to finish before they time out.) + */ +time_t +retrytime(struct qinfo *qp) { + time_t t, u, v; + struct qserv *ns = &qp->q_addr[qp->q_curaddr]; + + if (ns->nsdata != NULL) + t = (time_t) MAX(RETRYBASE, 2 * ns->nsdata->d_nstime / 1000); + else + t = (time_t) RETRYBASE; + u = t << ns->nretry; + v = MIN(u, RETRY_TIMEOUT); /* max. retry timeout for now */ + ns_debug(ns_log_default, 3, + "retrytime: nstime%ldms t%ld nretry%ld u%ld : v%ld", + ns->nsdata ? (long)(ns->nsdata->d_nstime / 1000) : (long)-1, + (long)t, (long)ns->nretry, (long)u, (long)v); + return (v); +} + +void +qflush() { + while (nsqhead) + qremove(nsqhead); + nsqhead = NULL; + priming = 0; +} + +void +qremove(struct qinfo *qp) { + struct sockaddr_in empty_from; + + empty_from.sin_family = AF_INET; + empty_from.sin_addr.s_addr = htonl(INADDR_ANY); + empty_from.sin_port = htons(0); + + ns_debug(ns_log_default, 3, "qremove(%#lx)", (u_long)qp); + + if (qp->q_flags & Q_ZSERIAL) + qserial_answer(qp, 0, empty_from); + unsched(qp); + ns_freeqry(qp); +} + +struct qinfo * +qfindid(u_int16_t id) { + struct qinfo *qp; + + for (qp = nsqhead; qp != NULL; qp = qp->q_link) + if (qp->q_nsid == id) + break; + ns_debug(ns_log_default, 3, "qfindid(%d) -> %#lx", ntohs(id), + (u_long)qp); + return (qp); +} + +struct qinfo * +qnew(const char *name, int class, int type) { + struct qinfo *qp; + + qp = (struct qinfo *)memget(sizeof *qp); + if (qp == NULL) + panic("qnew: memget failed", NULL); + memset(qp, 0, sizeof *qp); + ns_debug(ns_log_default, 5, "qnew(%#lx)", (u_long)qp); +#ifdef BIND_NOTIFY + qp->q_notifyzone = DB_Z_CACHE; +#endif + qp->q_link = nsqhead; + nsqhead = qp; + qp->q_name = savestr(name, 1); + qp->q_class = (u_int16_t)class; + qp->q_type = (u_int16_t)type; + qp->q_flags = 0; + return (qp); +} + +void +ns_freeqns(struct qinfo *qp, char *where) { + static const char freed[] = "freed", busy[] = "busy"; + const char *result; + struct databuf *dp; + int i; + + for (i = 0 ; i < (int)qp->q_naddr ; i++) { + dp = qp->q_addr[i].ns; + if (dp) { + DRCNTDEC(dp); + result = (dp->d_rcnt) ? busy : freed; + ns_debug(ns_log_default, 3, "%s: ns %s rcnt %d (%s)", + where, dp->d_data, dp->d_rcnt, result); + if (result == freed) + db_freedata(dp); + } + dp = qp->q_addr[i].nsdata; + if (dp) { + DRCNTDEC(dp); + result = (dp->d_rcnt) ? busy : freed; + ns_debug(ns_log_default, 3, + "%s: nsdata %s rcnt %d (%s)", + where, inet_ntoa(ina_get(dp->d_data)), + dp->d_rcnt, result); + if (result == freed) + db_freedata(dp); + } + } +} + +void +ns_freeqry(struct qinfo *qp) { + struct qinfo *np; + struct databuf *dp; + + ns_debug(ns_log_default, 3, "ns_freeqry(%#lx)", (u_long)qp); + if (qp->q_next) + ns_debug(ns_log_default, 1, + "WARNING: ns_freeqry of linked ptr %#lx", (u_long)qp); + if (qp->q_msg != NULL) + memput(qp->q_msg, qp->q_msgsize); + if (qp->q_cmsg != NULL) + memput(qp->q_cmsg, qp->q_cmsgsize); + if (qp->q_domain != NULL) + freestr(qp->q_domain); + if (qp->q_name != NULL) + freestr(qp->q_name); + ns_freeqns(qp, "ns_freeqry"); + if (nsqhead == qp) + nsqhead = qp->q_link; + else { + for(np = nsqhead; + np->q_link != NULL; + np = np->q_link) { + if (np->q_link != qp) + continue; + np->q_link = qp->q_link; /* dequeue */ + break; + } + } + memput(qp, sizeof *qp); +} diff --git a/contrib/bind/bin/named/ns_func.h b/contrib/bind/bin/named/ns_func.h new file mode 100644 index 0000000..bf58528 --- /dev/null +++ b/contrib/bind/bin/named/ns_func.h @@ -0,0 +1,380 @@ +/* Copyright (c) 1985, 1990 + * 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) 1996, 1997 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. + */ + +/* ns_func.h - declarations for ns_*.c's externally visible functions + * + * $Id: ns_func.h,v 8.43 1998/03/20 00:53:44 halley Exp $ + */ + +/* ++from ns_glue.c++ */ +extern struct in_addr ina_get(const u_char *data); +extern const char *sin_ntoa(struct sockaddr_in); +extern void ns_debug(int, int, const char *, ...), + ns_info(int, const char *, ...), + ns_notice(int, const char *, ...), + ns_warning(int, const char *, ...), + ns_error(int, const char *, ...), + ns_panic(int, int, const char *, ...), + ns_assertion_failed(char *file, int line, + assertion_type type, char *cond, + int print_errno); +extern void panic(const char *, const void *), + gettime(struct timeval *); +extern int nlabels(const char *), + my_close(int), + my_fclose(FILE *); +extern void __freestr(char *); +extern char *__newstr(size_t, int), + *__savestr(const char *, int), + *checked_ctime(const time_t *t), + *ctimel(long); +extern u_char *ina_put(struct in_addr ina, u_char *data), + *savebuf(const u_char *, size_t, int); +extern void dprintf(int level, const char *format, ...); +#ifdef DEBUG_STRINGS +extern char *debug_newstr(size_t, int, const char *, int), + *debug_savestr(const char *, int, const char *, int); +extern void debug_freestr(char *, const char *, int); +#define newstr(l, n) debug_newstr((l), (n), __FILE__, __LINE__) +#define savestr(s, n) debug_savestr((s), (n), __FILE__, __LINE__) +#define freestr(s) debug_freestr((s), __FILE__, __LINE__) +#else +#define newstr(l, n) __newstr((l), (n)) +#define savestr(s, n) __savestr((s), (n)) +#define freestr(s) __freestr((s)) +#endif /* DEBUG_STRINGS */ +/* --from ns_glue.c-- */ + +/* ++from ns_resp.c++ */ +extern void ns_resp(u_char *, int, struct sockaddr_in, + struct qstream *), + prime_cache(void), + delete_all(struct namebuf *, int, int), + delete_stale(struct namebuf *); +extern struct qinfo *sysquery(const char *, int, int, + struct in_addr *, int, int); +extern void sysnotify(const char *, int, int); +extern int doupdate(u_char *, u_char *, struct databuf **, + int, int, int, u_int, struct sockaddr_in), + send_msg(u_char *, int, struct qinfo *), + findns(struct namebuf **, int, + struct databuf **, int *, int), + finddata(struct namebuf *, int, int, HEADER *, + char **, int *, int *), + wanted(const struct databuf *, int, int), + add_data(struct namebuf *, + struct databuf **, + u_char *, int, int *), + trunc_adjust(u_char *, int, int); +/* --from ns_resp.c-- */ + +/* ++from ns_req.c++ */ +extern void ns_req(u_char *, int, int, + struct qstream *, + struct sockaddr_in, + int), + free_addinfo(void), + free_nsp(struct databuf **); +extern int stale(struct databuf *), + make_rr(const char *, struct databuf *, + u_char *, int, int, + u_char **, u_char **), + doaddinfo(HEADER *, u_char *, int), + doaddauth(HEADER *, u_char *, int, + struct namebuf *, + struct databuf *); +#ifdef BIND_NOTIFY +extern int findZonePri(const struct zoneinfo *, + const struct sockaddr_in); +#endif +/* --from ns_req.c-- */ + +/* ++from ns_xfr.c++ */ +extern void ns_xfr(struct qstream *qsp, struct namebuf *znp, + int zone, int class, int type, + int id, int opcode), + ns_stopxfrs(struct zoneinfo *), + ns_freexfr(struct qstream *); +/* --from ns_xfr.c-- */ + +/* ++from ns_forw.c++ */ +extern time_t retrytime(struct qinfo *); +extern int ns_forw(struct databuf *nsp[], + u_char *msg, + int msglen, + struct sockaddr_in from, + struct qstream *qsp, + int dfd, + struct qinfo **qpp, + const char *dname, + int class, + int type, + struct namebuf *np, + int use_tcp), + haveComplained(u_long, u_long), + nslookup(struct databuf *nsp[], + struct qinfo *qp, + const char *syslogdname, + const char *sysloginfo), + qcomp(struct qserv *, struct qserv *); +extern void schedretry(struct qinfo *, time_t), + unsched(struct qinfo *), + reset_retrytimer(void), + retrytimer(evContext ctx, void *uap, + struct timespec due, struct timespec ival), + retry(struct qinfo *), + qflush(void), + qremove(struct qinfo *), + ns_freeqns(struct qinfo *, char *), + ns_freeqry(struct qinfo *), + freeComplaints(void); +extern struct qinfo *qfindid(u_int16_t), + *qnew(const char *, int, int); +/* --from ns_forw.c-- */ + +/* ++from ns_main.c++ */ +extern struct in_addr net_mask(struct in_addr); +extern void sq_remove(struct qstream *), + sq_flushw(struct qstream *), + sq_flush(struct qstream *allbut), + dq_remove_gen(time_t gen), + dq_remove_all(), + sq_done(struct qstream *), + ns_setproctitle(char *, int), + getnetconf(int), + nsid_init(void), + ns_setoption(int option), + writestream(struct qstream *, const u_char *, int), + ns_need(int need), + opensocket_f(void); +extern u_int16_t nsid_next(void); +extern int sq_openw(struct qstream *, int), + sq_writeh(struct qstream *, sq_closure), + sq_write(struct qstream *, const u_char *, int), + ns_need_p(int option), + tcp_send(struct qinfo *), + aIsUs(struct in_addr); +/* --from ns_main.c-- */ + +/* ++from ns_maint.c++ */ +extern void ns_maint(void), + zone_maint(struct zoneinfo *), + sched_zone_maint(struct zoneinfo *), + ns_cleancache(evContext ctx, void *uap, + struct timespec due, + struct timespec inter), + purge_zone(const char *, struct hashbuf *, int), + loadxfer(void), + qserial_retrytime(struct zoneinfo *, time_t), + qserial_query(struct zoneinfo *), + qserial_answer(struct qinfo *, u_int32_t, + struct sockaddr_in), +#ifdef DEBUG + printzoneinfo(int, int, int), +#endif + endxfer(void), + ns_reload(void); +extern int clean_cache(struct hashbuf *, int); +extern void reapchild(evContext, void *, int); +extern const char * zoneTypeString(const struct zoneinfo *); +/* --from ns_maint.c-- */ + +/* ++from ns_init.c++ */ +extern void ns_refreshtime(struct zoneinfo *, time_t), + ns_retrytime(struct zoneinfo *, time_t), + ns_init(const char *); +extern enum context ns_ptrcontext(const char *owner); +extern enum context ns_ownercontext(int type, enum transport); +extern int ns_nameok(const char *name, int class, + struct zoneinfo *zp, + enum transport, enum context, + const char *owner, + struct in_addr source); +extern int ns_wildcard(const char *name); +extern void zoneinit(struct zoneinfo *), + do_reload(const char *, int, int), + ns_shutdown(void); +/* --from ns_init.c-- */ + +/* ++from ns_ncache.c++ */ +extern void cache_n_resp(u_char *, int, struct sockaddr_in); +/* --from ns_ncache.c-- */ + +/* ++from ns_udp.c++ */ +extern void ns_udp(void); +/* --from ns_udp.c-- */ + +/* ++from ns_stats.c++ */ +extern void ns_stats(void), + ns_freestats(void); +extern void ns_logstats(evContext ctx, void *uap, + struct timespec, struct timespec); +extern void qtypeIncr(int qtype); +extern struct nameser *nameserFind(struct in_addr addr, int flags); +#define NS_F_INSERT 0x0001 +#define nameserIncr(a,w) NS_INCRSTAT(a,w) /* XXX should change name. */ +/* --from ns_stats.c-- */ + +/* ++from ns_update.c++ */ +u_char *findsoaserial(u_char *data); +u_int32_t get_serial_unchecked(struct zoneinfo *zp); +u_int32_t get_serial(struct zoneinfo *zp); +void set_serial(struct zoneinfo *zp, u_int32_t serial); +int schedule_soa_update(struct zoneinfo *, int); +int schedule_dump(struct zoneinfo *); +int incr_serial(struct zoneinfo *zp); +int merge_logs(struct zoneinfo *zp); +int zonedump(struct zoneinfo *zp); +void dynamic_about_to_exit(void); +enum req_action req_update(HEADER *hp, u_char *cp, u_char *eom, + u_char *msg, struct qstream *qsp, + int dfd, struct sockaddr_in from); +void rdata_dump(struct databuf *dp, FILE *fp); +/* --from ns_update.c-- */ + +/* ++from ns_config.c++ */ +void free_zone_timerinfo(struct zoneinfo *); +void free_zone_contents(struct zoneinfo *, int); +struct zoneinfo *find_zone(const char *, int, int); +zone_config begin_zone(char *, int); +void end_zone(zone_config, int); +int set_zone_type(zone_config, int); +int set_zone_filename(zone_config, char *); +int set_zone_checknames(zone_config, enum severity); +int set_zone_notify(zone_config, int value); +int set_zone_update_acl(zone_config, ip_match_list); +int set_zone_query_acl(zone_config, ip_match_list); +int set_zone_transfer_acl(zone_config, ip_match_list); +int set_zone_transfer_source(zone_config, struct in_addr); +int set_zone_transfer_time_in(zone_config, long); +int add_zone_master(zone_config, struct in_addr); +int add_zone_notify(zone_config, struct in_addr); +options new_options(void); +void free_options(options); +void set_boolean_option(options, int, int); +listen_info_list new_listen_info_list(void); +void free_listen_info_list(listen_info_list); +void add_listen_on(options, u_int16_t, ip_match_list); +FILE * write_open(char *filename); +void update_pid_file(void); +void set_options(options, int); +void use_default_options(void); +ip_match_list new_ip_match_list(void); +void free_ip_match_list(ip_match_list); +ip_match_element new_ip_match_pattern(struct in_addr, u_int); +ip_match_element new_ip_match_mask(struct in_addr, struct in_addr); +ip_match_element new_ip_match_indirect(ip_match_list); +ip_match_element new_ip_match_localhost(void); +ip_match_element new_ip_match_localnets(void); +void ip_match_negate(ip_match_element); +void add_to_ip_match_list(ip_match_list, ip_match_element); +void dprint_ip_match_list(int, ip_match_list, int, char *, + char *); +int ip_match_address(ip_match_list, struct in_addr); +int ip_address_allowed(ip_match_list, struct in_addr); +int ip_match_network(ip_match_list, struct in_addr, + struct in_addr); +int distance_of_address(ip_match_list, struct in_addr); +int ip_match_is_none(ip_match_list); +void add_forwarder(options, struct in_addr); +void free_forwarders(struct fwdinfo *); +server_info find_server(struct in_addr); +server_config begin_server(struct in_addr); +void end_server(server_config, int); +void set_server_option(server_config, int, int); +void set_server_transfers(server_config, int); +void set_server_transfer_format(server_config, + enum axfr_format); +void add_server_key_info(server_config, key_info); +key_info new_key_info(char *, char *, char *); +void free_key_info(key_info); +void dprint_key_info(key_info); +key_info_list new_key_info_list(void); +void free_key_info_list(key_info_list); +void add_to_key_info_list(key_info_list, key_info); +void dprint_key_info_list(key_info_list); +log_config begin_logging(void); +void add_log_channel(log_config, int, log_channel); +void open_special_channels(void); +void set_logging(log_config, int); +void end_logging(log_config, int); +void use_default_logging(void); +void init_logging(void); +void shutdown_logging(void); +void init_configuration(void); +void shutdown_configuration(void); +void load_configuration(const char *); +/* --from ns_config.c-- */ +/* ++from parser.y++ */ +ip_match_list lookup_acl(char *); +void define_acl(char *, ip_match_list); +key_info lookup_key(char *); +void define_key(char *, key_info); +void parse_configuration(const char *); +void parser_initialize(void); +void parser_shutdown(void); +/* --from parser.y-- */ diff --git a/contrib/bind/bin/named/ns_glob.h b/contrib/bind/bin/named/ns_glob.h new file mode 100644 index 0000000..35f3041 --- /dev/null +++ b/contrib/bind/bin/named/ns_glob.h @@ -0,0 +1,317 @@ +/* + * from ns.h 4.33 (Berkeley) 8/23/90 + * $Id: ns_glob.h,v 8.34 1998/03/20 01:18:07 halley Exp $ + */ + +/* Copyright (c) 1986 + * 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) 1996, 1997 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. + */ + +/* + * Global variables for the name server. + */ + +#ifdef DEBUG +DECL int debug INIT(0); +DECL int desired_debug INIT(0); +#endif + + /* global event context */ +DECL evContext ev; + + /* list of open streams */ +DECL struct qstream *streamq; + + /* often set to the current time */ +DECL struct timeval tt; + + /* head of allocated queries */ +DECL struct qinfo *nsqhead; + + /* datagram socket for sysquery() and ns_forw(). */ +DECL int ds INIT(-1); + + /* event ID for reads of "ds". */ +DECL evFileID ds_evID; + +#ifdef QRYLOG + /* is query logging turned on? */ +DECL int qrylog; +#endif /*QRYLOG*/ + + /* port to which we send queries */ +DECL u_int16_t ns_port; + + /* Source addr of our internal resolver. */ +DECL struct sockaddr_in source_addr; /* INITs to <INADDR_ANY, 0>. */ + + /* Used by ns_stats */ +DECL time_t boottime; + +DECL time_t resettime; + + /* next query to retry */ +DECL struct qinfo *retryqp; + + /* default configuration file */ +DECL char *conffile INIT(NULL); + + /* default debug output file */ +DECL const char *debugfile INIT(_PATH_DEBUG); + + /* zone information */ +DECL struct zoneinfo *zones; + + /* number of zones in use */ +DECL int nzones; + + /* set if we need a priming */ +DECL int needs_prime_cache; + + /* is cache being primed */ +DECL int priming; + + /* ptrs to dnames in msg for dn_comp */ +DECL u_char *dnptrs[40]; + + /* end pointer for dnptrs */ +DECL u_char **dnptrs_end + INIT(dnptrs + sizeof dnptrs / sizeof(u_char*)); + + /* number of names in addinfo */ +DECL int addcount; + + /* name of cache file */ +DECL const char *cache_file; + +#ifdef SLAVE_FORWARD + /* retry time when a slave */ +DECL int slave_retry INIT(4); +#endif + +#ifdef BIND_UPDATE +DECL const char * LogSignature INIT(";BIND LOG V8\n"); +DECL const char * DumpSignature INIT(";BIND DUMP V8\n"); +DECL const char * DumpSuffix INIT(".dumptmp"); +#endif + +DECL const char sendtoStr[] INIT("sendto"); +DECL const char tcpsendStr[] INIT("tcp_send"); + + /* defined in version.c, can't use DECL/INIT */ +extern char Version[]; +extern char ShortVersion[]; + + /* If getnum() has an error, here will be the result. */ +DECL int getnum_error INIT(0); + +enum context { domain_ctx, owner_ctx, mailname_ctx, hostname_ctx }; +DECL const char *context_strings[] +#ifdef MAIN_PROGRAM + = { "domain", "owner", "mail", "host", NULL } +#endif +; + +DECL const char *transport_strings[] +#ifdef MAIN_PROGRAM + = { "primary", "secondary", "response", NULL } +#endif +; + +DECL const char *severity_strings[] +#ifdef MAIN_PROGRAM + = { "ignore", "warn", "fail", "not_set", NULL } +#endif +; + +DECL struct in_addr inaddr_any; /* Inits to 0.0.0.0 */ + +DECL options server_options INIT(NULL); + +DECL server_info nameserver_info INIT(NULL); + + /* These will disappear some day in favour of "struct nameser". */ +DECL ip_match_list bogus_nameservers INIT(NULL); + +DECL log_context log_ctx; +DECL int log_ctx_valid INIT(0); + +DECL log_channel syslog_channel INIT(NULL); +DECL log_channel debug_channel INIT(NULL); +DECL log_channel stderr_channel INIT(NULL); +DECL log_channel eventlib_channel INIT(NULL); +DECL log_channel packet_channel INIT(NULL); +DECL log_channel null_channel INIT(NULL); + +DECL ip_match_list local_addresses INIT(NULL); +DECL ip_match_list local_networks INIT(NULL); + + /* are we running in no-fork mode? */ + +DECL int foreground INIT(0); + +DECL const struct ns_sym logging_constants[] +#ifdef MAIN_PROGRAM += { + { log_info, "info" }, + { log_notice, "notice" }, + { log_warning, "warning" }, + { log_error, "error" }, + { log_critical, "critical" }, + { 0, NULL } +} +#endif +; + +DECL const struct ns_sym syslog_constants[] +#ifdef MAIN_PROGRAM += { + { 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 } +} +#endif +; + +DECL const struct ns_sym category_constants[] +#ifdef MAIN_PROGRAM += { + { ns_log_default, "default" }, + { ns_log_config, "config" }, + { ns_log_parser, "parser" }, + { ns_log_queries, "queries" }, + { ns_log_lame_servers, "lame-servers" }, + { ns_log_statistics, "statistics" }, + { ns_log_panic, "panic" }, + { ns_log_update, "update" }, + { ns_log_ncache, "ncache" }, + { ns_log_xfer_in, "xfer-in" }, + { ns_log_xfer_out, "xfer-out" }, + { ns_log_db, "db" }, + { ns_log_eventlib, "eventlib" }, + { ns_log_packet, "packet" }, + { ns_log_notify, "notify" }, + { ns_log_cname, "cname" }, + { ns_log_security, "security" }, + { ns_log_os, "os" }, + { ns_log_insist, "insist" }, + { ns_log_maint, "maintenance" }, + { ns_log_load, "load" }, + { ns_log_resp_checks, "response-checks" }, + { 0, NULL } +} +#endif +; + +DECL const char panic_msg_no_options[] + INIT("no server_options in NS_OPTION_P"); + +DECL const char panic_msg_insist_failed[] + INIT("%s:%d: insist '%s' failed: %s"); + +DECL const char panic_msg_bad_which[] + INIT("%s:%d: INCRSTATS(%s): bad \"which\""); + +DECL u_long globalStats[nssLast]; + +DECL evTimerID clean_timer; +DECL evTimerID interface_timer; +DECL evTimerID stats_timer; +DECL int active_timers INIT(0); + +DECL uid_t user_id; +DECL char * user_name INIT(NULL); +DECL gid_t group_id; +DECL char * group_name INIT(NULL); +DECL char * chroot_dir INIT(NULL); diff --git a/contrib/bind/bin/named/ns_glue.c b/contrib/bind/bin/named/ns_glue.c new file mode 100644 index 0000000..460b64d --- /dev/null +++ b/contrib/bind/bin/named/ns_glue.c @@ -0,0 +1,416 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_glue.c,v 8.7 1998/02/13 19:51:45 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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 "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <resolv.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <stdarg.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +/* + * IP address from unaligned octets. + */ +struct in_addr +ina_get(const u_char *data) { + struct in_addr ret; + u_int32_t i; + + GETLONG(i, data); + ina_ulong(ret) = htonl(i); + return (ret); +} + +/* + * IP address to unaligned octets. + */ +u_char * +ina_put(struct in_addr ina, u_char *data) { + PUTLONG(ntohl(ina_ulong(ina)), data); + return (data); +} + +/* + * XXX: sin_ntoa() should probably be in libc. + */ +const char * +sin_ntoa(struct sockaddr_in sin) { + static char ret[sizeof "[111.222.333.444].55555"]; + + sprintf(ret, "[%s].%u", + inet_ntoa(sin.sin_addr), + ntohs(sin.sin_port)); + return (ret); +} + +/* + * Logging Support + */ + +void +ns_debug(int category, int level, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_debug(level), format, args); + va_end(args); +} + +void +ns_info(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_info, format, args); + va_end(args); +} + +void +ns_notice(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_notice, format, args); + va_end(args); +} + +void +ns_warning(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_warning, format, args); + va_end(args); +} + +void +ns_error(int category, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_error, format, args); + va_end(args); +} + +void +ns_panic(int category, int dump_core, const char *format, ...) { + va_list args; + + if (!log_ctx_valid) + return; + va_start(args, format); + log_vwrite(log_ctx, category, log_critical, format, args); + va_end(args); + va_start(args, format); + log_vwrite(log_ctx, ns_log_panic, log_critical, format, args); + va_end(args); + if (dump_core) + abort(); + else + exit(1); +} + +void +ns_assertion_failed(char *file, int line, assertion_type type, char *cond, + int print_errno) +{ + ns_panic(ns_log_insist, 1, "%s:%d: %s(%s)%s%s failed.", + file, line, assertion_type_to_text(type), cond, + (print_errno) ? ": " : "", + (print_errno) ? strerror(errno) : ""); +} + +/* + * XXX This is for compatibility and will eventually be removed. + */ +void +panic(const char *msg, const void *arg) { + ns_panic(ns_log_default, 1, msg, arg); +} + +/* + * How many labels in this name? + * Note: the root label is not included in the count. + */ +int +nlabels (const char *dname) { + int count, i, found, escaped; + const char *tmpdname, *end_tmpdname; + int tmpdnamelen, c; + + INSIST(dname != NULL); + + count = 0; + tmpdname = dname; + tmpdnamelen = strlen(tmpdname); + /* + * Ignore a trailing label separator (i.e. an unescaped dot) + * in 'tmpdname'. + */ + if (tmpdnamelen && tmpdname[tmpdnamelen-1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if tmpdnamelen==1 */ + for (i = tmpdnamelen - 2; i >= 0; i--) + if (tmpdname[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else { + break; + } + if (!escaped) + tmpdnamelen--; + } + + end_tmpdname = tmpdname + tmpdnamelen; + + while(tmpdname != end_tmpdname) { + count++; + /* + * Strip off the first label if we're not already at + * the root label. + */ + for (escaped = found = 0; + (tmpdname != end_tmpdname) && !found; + tmpdname++) { + c = *tmpdname; + if (!escaped && (c == '.')) + found = 1; + + if (escaped) + escaped = 0; + else if (c == '\\') + escaped = 1; + } + } + + ns_debug(ns_log_default, 12, "nlabels of \"%s\" -> %d", dname, + count); + return (count); +} + +/* + * Get current system time and put it in a global. + */ +void +gettime(struct timeval *ttp) { + if (gettimeofday(ttp, NULL) < 0) + ns_error(ns_log_default, "gettimeofday: %s", strerror(errno)); +} + +/* + * This is useful for tracking down lost file descriptors. + */ +int +my_close(int fd) { + int s; + + do { + errno = 0; + s = close(fd); + } while (s < 0 && errno == EINTR); + + if (s < 0 && errno != EBADF) + ns_info(ns_log_default, "close(%d) failed: %s", fd, + strerror(errno)); + else + ns_debug(ns_log_default, 3, "close(%d) succeeded", fd); + return (s); +} + +/* + * This is useful for tracking down lost file descriptors. + */ +int +my_fclose(FILE *fp) { + int fd = fileno(fp), + s = fclose(fp); + + if (s < 0) + ns_info(ns_log_default, "fclose(%d) failed: %m", fd, + strerror(errno)); + else + ns_debug(ns_log_default, 3, "fclose(%d) succeeded", fd); + return (s); +} + +/* + * Save a counted buffer and return a pointer to it. + */ +u_char * +savebuf(const u_char *buf, size_t len, int needpanic) { + u_char *bp = (u_char *)memget(len); + + if (bp == NULL) { + if (needpanic) + panic("savebuf: memget failed (%s)", strerror(errno)); + else + return (NULL); + } + memcpy(bp, buf, len); + return (bp); +} + +#ifdef DEBUG_STRINGS +char * +debug_newstr(size_t len, int needpanic, const char *file, int line) { + size_t size; + + size = len + 3; /* 2 length bytes + NUL. */ + printf("%s:%d: newstr %d\n", file, line, size); + return (__newstr(len, needpanic)); +} + +char * +debug_savestr(const char *str, int needpanic, const char *file, int line) { + size_t len; + + len = strlen(str); + len += 3; /* 2 length bytes + NUL. */ + printf("%s:%d: savestr %d %s\n", file, line, len, str); + return (__savestr(str, needpanic)); +} + +void +debug_freestr(char *str, const char *file, int line) { + u_char *buf, *bp; + size_t len; + + buf = (u_char *)str - 2/*Len*/; + bp = buf; + NS_GET16(len, bp); + len += 3; /* 2 length bytes + NUL. */ + printf("%s:%d: freestr %d %s\n", file, line, len, str); + __freestr(str); + return; +} +#endif /* DEBUG_STRINGS */ + +/* + * Return a counted string buffer big enough for a string of length 'len'. + */ +char * +__newstr(size_t len, int needpanic) { + u_char *buf, *bp; + + REQUIRE(len <= 65536); + + buf = (u_char *)memget(2/*Len*/ + len + 1/*Nul*/); + if (buf == NULL) { + if (needpanic) + panic("savestr: memget failed (%s)", strerror(errno)); + else + return (NULL); + } + bp = buf; + NS_PUT16(len, bp); + return ((char *)bp); +} + +/* + * Save a NUL terminated string and return a pointer to it. + */ +char * +__savestr(const char *str, int needpanic) { + char *buf; + size_t len; + + len = strlen(str); + if (len > 65536) { + if (needpanic) + ns_panic(ns_log_default, 1, + "savestr: string too long"); + else + return (NULL); + } + buf = __newstr(len, needpanic); + memcpy(buf, str, len + 1); + return (buf); +} + +void +__freestr(char *str) { + u_char *buf, *bp; + size_t len; + + buf = (u_char *)str - 2/*Len*/; + bp = buf; + NS_GET16(len, bp); + memput(buf, 2/*Len*/ + len + 1/*Nul*/); +} + +char * +checked_ctime(const time_t *t) { + char *ctime_result; + + ctime_result = ctime(t); + if (ctime_result == NULL) { + ns_error(ns_log_default, "ctime() returned NULL!"); + ctime_result = "<unknown time>\n"; + } + + return (ctime_result); +} + +/* + * Since the fields in a "struct timeval" are longs, and the argument to ctime + * is a pointer to a time_t (which might not be a long), here's a bridge. + */ +char * +ctimel(long l) { + time_t t = (time_t)l; + + return (checked_ctime(&t)); +} diff --git a/contrib/bind/bin/named/ns_init.c b/contrib/bind/bin/named/ns_init.c new file mode 100644 index 0000000..920bfeb --- /dev/null +++ b/contrib/bind/bin/named/ns_init.c @@ -0,0 +1,512 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)ns_init.c 4.38 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: ns_init.c,v 8.40 1998/04/07 18:11:58 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1990 + * 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) 1996, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +#ifdef DEBUG +static void content_zone(int, int); +#endif + +/* + * Set new refresh time for zone. Use a random number in the last half of + * the refresh limit; we want it to be substantially correct while still + * preventing slave synchronization. + */ +void +ns_refreshtime(struct zoneinfo *zp, time_t timebase) { + u_long refresh = (zp->z_refresh > 0) ? zp->z_refresh : INIT_REFRESH; + time_t half = (refresh + 1) / 2; + + zp->z_time = timebase + half + (rand() % half); +} + +/* + * Set new retry time for zone. + */ +void +ns_retrytime(struct zoneinfo *zp, time_t timebase) { + zp->z_time = timebase + zp->z_retry; +} + +/* + * Read configuration file and save it as internal state. + */ +void +ns_init(const char *conffile) { + struct zoneinfo *zp; + static int loads = 0; /* number of times loaded */ + + ns_debug(ns_log_config, 1, "ns_init(%s)", conffile); + gettime(&tt); + + if (loads == 0) { + zones = (struct zoneinfo *)memget(64 * sizeof *zones); + if (zones == NULL) + ns_panic(ns_log_config, 0, + "Not enough memory to allocate initial zones array"); + memset(zones, 0, 64 * sizeof *zones); + nzones = 1; /* zone zero is cache data */ + /* allocate cache hash table, formerly the root hash table. */ + hashtab = savehash((struct hashbuf *)NULL); + + /* allocate root-hints/file-cache hash table */ + fcachetab = savehash((struct hashbuf *)NULL); + /* init zone data */ + zones[0].z_type = Z_CACHE; + zones[0].z_origin = savestr("", 1); + init_configuration(); + } else { + /* Mark previous zones as not yet found in boot file. */ + for (zp = &zones[1]; zp < &zones[nzones]; zp++) + zp->z_flags &= ~Z_FOUND; + } + +#ifdef DEBUG + if (debug >= 3) { + ns_debug(ns_log_config, 3, "content of zones before loading"); + content_zone(nzones - 1, 3); + } +#endif + + load_configuration(conffile); + + /* Erase all old zones that were not found. */ + for (zp = &zones[1]; zp < &zones[nzones]; zp++) { + if (zp->z_type && (zp->z_flags & Z_FOUND) == 0) { +#ifdef BIND_UPDATE + /* + * A dynamic zone might have changed, so we + * need to dump it before removing it. + */ + if ((zp->z_flags & Z_DYNAMIC) && + ((zp->z_flags & Z_NEED_SOAUPDATE) || + (zp->z_flags & Z_NEED_DUMP))) + (void)zonedump(zp); +#endif + ns_stopxfrs(zp); + do_reload(zp->z_origin, zp->z_type, zp->z_class); + ns_notice(ns_log_config, + "%s zone \"%s\" (%s) removed", + zoneTypeString(zp), zp->z_origin, + p_class(zp->z_class)); + free_zone_contents(zp, 1); + memset(zp, 0, sizeof(*zp)); + } + } + +#ifdef DEBUG + if (debug >= 2) { + ns_debug(ns_log_config, 2, "content of zones after loading"); + content_zone(nzones-1, 2); + } +#endif + + ns_debug(ns_log_config, 1, "exit ns_init()"); + loads++; +} + +void +zoneinit(struct zoneinfo *zp) { + struct stat sb; + int result; + + /* + * Try to load zone from backup file, + * if one was specified and it exists. + * If not, or if the data are out of date, + * we will refresh the zone from a primary + * immediately. + */ + if (!zp->z_source) + return; + result = stat(zp->z_source, &sb); + if (result != -1) { + ns_stopxfrs(zp); + purge_zone(zp->z_origin, hashtab, zp->z_class); + } + if (result == -1 || db_load(zp->z_source, zp->z_origin, zp, NULL)) { + /* + * Set zone to be refreshed immediately. + */ + zp->z_refresh = INIT_REFRESH; + zp->z_retry = INIT_REFRESH; + if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))) { + zp->z_time = tt.tv_sec; + sched_zone_maint(zp); + } + } else { + zp->z_flags |= Z_AUTH; + zp->z_flags &= ~Z_NEED_RELOAD; + ns_refreshtime(zp, tt.tv_sec); + sched_zone_maint(zp); + } +} + +void +do_reload(const char *domain, int type, int class) { + struct zoneinfo *zp; + + ns_debug(ns_log_config, 1, "do_reload: %s %d %d", + *domain ? domain : ".", type, class); + + /* + * Check if the zone has changed type. If so, we might not need to + * do any purging or parent reloading. + * + * If the new zone is a master zone, then it will have purged the + * old data and loaded, so we don't need to do anything. + * + * If the new zone is a slave or stub zone and has successfully loaded, + * then we don't need to do anything either. + * + * NOTE: we take care not to match ourselves. + */ + if ((type != z_master && + find_zone(domain, z_master, class) != NULL) || + (type != z_slave && + (zp = find_zone(domain, z_slave, class)) != NULL && + zp->z_serial != 0) || + (type != z_stub && + (zp = find_zone(domain, z_stub, class)) != NULL && + zp->z_serial != 0) + ) + return; + + /* + * Clean up any leftover data. + */ + purge_zone(domain, hashtab, class); + + /* + * Reload + */ + while (*domain) { + const char *s; + int escaped; + + /* + * XXX this is presentation level hair and belongs elsewhere. + */ + escaped = 0; + for (s = domain; *s != '\0'; s++) { + if (!escaped) { + if (*s == '.') + break; + else if (*s == '\\') + escaped = 1; + } else + escaped = 0; + } + + if (*s != '\0') + domain = s + 1; /* skip label and its separator */ + else + domain = ""; /* root zone */ + + if ((zp = find_zone(domain, Z_STUB, class)) || + (zp = find_zone(domain, Z_CACHE, class)) || + (zp = find_zone(domain, Z_PRIMARY, class)) || + (zp = find_zone(domain, Z_SECONDARY, class))) { + + ns_debug(ns_log_config, 1, "do_reload: matched %s", + *domain ? domain : "."); + + if (zp->z_type == Z_CACHE) + purge_zone(zp->z_origin, fcachetab, + zp->z_class); + else + purge_zone(zp->z_origin, hashtab, zp->z_class); + + zp->z_flags &= ~Z_AUTH; + + switch (zp->z_type) { + case Z_SECONDARY: + case Z_STUB: + zoneinit(zp); + break; + case Z_PRIMARY: + if (db_load(zp->z_source, zp->z_origin, zp, 0) + == 0) + zp->z_flags |= Z_AUTH; + break; + case Z_CACHE: + (void)db_load(zp->z_source, zp->z_origin, zp, + 0); + break; + } + break; + } + } +} + +#ifdef DEBUG +/* prints out the content of zones */ +static void +content_zone(int end, int level) { + int i; + + for (i = 1; i <= end; i++) { + printzoneinfo(i, ns_log_config, level); + } +} +#endif + +enum context +ns_ptrcontext(owner) + const char *owner; +{ + if (samedomain(owner, "in-addr.arpa") || samedomain(owner, "ip6.int")) + return (hostname_ctx); + return (domain_ctx); +} + +enum context +ns_ownercontext(type, transport) + int type; + enum transport transport; +{ + enum context context = domain_ctx; + + switch (type) { + case T_A: + case T_WKS: + case T_MX: + switch (transport) { + case primary_trans: + case secondary_trans: + context = owner_ctx; + break; + case response_trans: + context = hostname_ctx; + break; + default: + panic("impossible condition in ns_ownercontext()", + NULL); + } + break; + case T_MB: + case T_MG: + context = mailname_ctx; + break; + default: + /* Nothing to do. */ + break; + } + return (context); +} + +int +ns_nameok(const char *name, int class, struct zoneinfo *zp, + enum transport transport, + enum context context, + const char *owner, + struct in_addr source) +{ + enum severity severity = not_set; + int ok = 1; + + if (zp != NULL) + severity = zp->z_checknames; + if (severity == not_set) + severity = server_options->check_names[transport]; + + if (severity == ignore) + return (1); + switch (context) { + case domain_ctx: + ok = (class != C_IN) || res_dnok(name); + break; + case owner_ctx: + ok = (class != C_IN) || res_ownok(name); + break; + case mailname_ctx: + ok = res_mailok(name); + break; + case hostname_ctx: + ok = res_hnok(name); + break; + default: + ns_panic(ns_log_default, 1, + "unexpected context %d in ns_nameok", (int)context); + } + if (!ok) { + char *s, *o; + + if (source.s_addr == INADDR_ANY) + s = savestr(transport_strings[transport], 0); + else { + s = newstr(strlen(transport_strings[transport]) + + sizeof " from [000.000.000.000]", 0); + if (s) + sprintf(s, "%s from [%s]", + transport_strings[transport], + inet_ntoa(source)); + } + if (strcasecmp(owner, name) == 0) + o = savestr("", 0); + else { + const char *t = (*owner == '\0') ? "." : owner; + + o = newstr(strlen(t) + sizeof " (owner \"\")", 0); + if (o) + sprintf(o, " (owner \"%s\")", t); + } + /* + * We use log_write directly here to avoid duplicating + * the message formatting and arguments. + */ + log_write(log_ctx, ns_log_default, + (transport == response_trans) ? + log_info : log_notice, + "%s name \"%s\"%s %s (%s) is invalid - %s", + context_strings[context], + name, o != NULL ? o : "[memget failed]", + p_class(class), + s != NULL ? s : "[memget failed]", + (severity == fail) ? + "rejecting" : "proceeding anyway"); + if (severity == warn) + ok = 1; + if (s != NULL) + freestr(s); + if (o != NULL) + freestr(o); + } + return (ok); +} + +int +ns_wildcard(const char *name) { + if (*name != '*') + return (0); + return (*++name == '\0'); +} + +void +ns_shutdown() { + struct zoneinfo *zp; + + /* Erase zones. */ + for (zp = &zones[0]; zp < &zones[nzones]; zp++) { + if (zp->z_type) { + if (zp->z_type != z_hint) { + ns_stopxfrs(zp); + purge_zone(zp->z_origin, hashtab, zp->z_class); + } + free_zone_contents(zp, 1); + } + } + memput(zones, ((nzones / 64) + 1) * 64 * sizeof *zones); + + /* Erase the cache. */ + clean_cache(hashtab, 1); + hashtab->h_cnt = 0; /* ??? */ + rm_hash(hashtab); + clean_cache(fcachetab, 1); + fcachetab->h_cnt = 0; /* ??? */ + rm_hash(fcachetab); + +#ifdef BIND_NOTIFY + db_cancel_pending_notifies(); +#endif + freeComplaints(); + shutdown_configuration(); +} diff --git a/contrib/bind/bin/named/ns_lexer.c b/contrib/bind/bin/named/ns_lexer.c new file mode 100644 index 0000000..fe319fa --- /dev/null +++ b/contrib/bind/bin/named/ns_lexer.c @@ -0,0 +1,750 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_lexer.c,v 8.12 1997/12/04 08:11:52 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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 "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <stdarg.h> +#include <syslog.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" +#include "ns_parser.h" +#include "ns_parseutil.h" +#include "ns_lexer.h" + +typedef enum lexer_state { + scan, number, identifier, ipv4, quoted_string +} LexerState; + +#define LEX_EOF 0x01 + +typedef struct lexer_file_context { + const char * name; + FILE * stream; + int line_number; + LexerState state; + u_int flags; + int warnings; + int errors; + struct lexer_file_context * + next; +} *LexerFileContext; + +LexerFileContext current_file = NULL; + +#define LEX_LAST_WAS_DOT 0x01 +#define LEX_CONSECUTIVE_DOTS 0x02 + +typedef struct lexer_identifier { + char buffer[LEX_MAX_IDENT_SIZE+1]; + int index; + int num_dots; + unsigned int flags; +} *LexerIdentifier; + +static LexerIdentifier id; + +static char special_chars[256]; + +#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') +#define domain_char(c) (isalnum((c)) || (c) == '.' || (c) == '-') +#define special_char(c) (special_chars[(c)] == 1) +#define identifier_char(c) (!whitespace(c) && !special_char(c)) + +static int last_token; +static YYSTYPE last_yylval; + +static int lexer_initialized = 0; + +/* + * Problem Reporting + */ + +static char * +token_to_text(int token, YYSTYPE lval) { + static char buffer[LEX_MAX_IDENT_SIZE+50]; + + if (token < 128) { + if (token == 0) + strcpy(buffer, "<end of file>"); + else + sprintf(buffer, "'%c'", token); + } else { + switch (token) { + case L_EOS: + strcpy(buffer, ";"); + break; + case L_STRING: + sprintf(buffer, "'%s'", lval.cp); + break; + case L_QSTRING: + sprintf(buffer, "\"%s\"", lval.cp); + break; + case L_IPADDR: + sprintf(buffer, "%s", inet_ntoa(lval.ip_addr)); + break; + case L_NUMBER: + sprintf(buffer, "%ld", lval.num); + break; + case L_END_INCLUDE: + sprintf(buffer, "<end of include>"); + break; + default: + sprintf(buffer, "%s", lval.cp); + } + } + + return (buffer); +} + +static char where[MAXPATHLEN + 100]; +static char message[20480]; + +static void +parser_complain(int is_warning, int print_last_token, const char *format, + va_list args) +{ + LexerFileContext lf; + int severity; + + if (is_warning) { + severity = log_warning; + } else { + severity = log_error; + } + + INSIST(current_file != NULL); + if (current_file->next != NULL) { + for (lf = current_file; lf != NULL; lf = lf->next) { + log_write(log_ctx, ns_log_parser, severity, + "%s '%s' line %d", + (lf == current_file) ? + "In" : "included from", + lf->name, lf->line_number); + } + } + sprintf(where, "%s:%d: ", current_file->name, + current_file->line_number); + vsprintf(message, format, args); + if (print_last_token) + log_write(log_ctx, ns_log_parser, severity, "%s%s near %s", + where, message, + token_to_text(last_token, last_yylval)); + else + log_write(log_ctx, ns_log_parser, severity, + "%s%s", where, message); +} + +int +parser_warning(int print_last_token, const char *format, ...) { + va_list args; + + va_start(args, format); + parser_complain(1, print_last_token, format, args); + va_end(args); + current_file->warnings++; + return (1); +} + +int +parser_error(int print_last_token, const char *format, ...) { + va_list args; + + va_start(args, format); + parser_complain(0, print_last_token, format, args); + va_end(args); + current_file->errors++; + return (1); +} + +void +yyerror(const char *message) { + parser_error(1, message); +} + +/* + * Keywords + */ + +struct keyword { + char *name; + int token; +}; + +/* + * "keywords" is an array of the keywords which are the fixed syntactic + * elements of the configuration file. Each keyword has a string version + * of the keyword and a token id, which should be an identifier which + * matches that in a %token statement inside the parser.y file. + */ +static struct keyword keywords[] = { + {"acl", T_ACL}, + {"address", T_ADDRESS}, + {"algorithm", T_ALGID}, + {"allow-query", T_ALLOW_QUERY}, + {"allow-transfer", T_ALLOW_TRANSFER}, + {"allow-update", T_ALLOW_UPDATE}, + {"also-notify", T_ALSO_NOTIFY}, + {"auth-nxdomain", T_AUTH_NXDOMAIN}, + {"bogus", T_BOGUS}, + {"category", T_CATEGORY}, + {"channel", T_CHANNEL}, + {"check-names", T_CHECK_NAMES}, + {"cleaning-interval", T_CLEAN_INTERVAL}, + {"coresize", T_CORESIZE}, + {"datasize", T_DATASIZE}, + {"deallocate-on-exit", T_DEALLOC_ON_EXIT}, + {"debug", T_DEBUG}, + {"default", T_DEFAULT}, + {"directory", T_DIRECTORY}, + {"dump-file", T_DUMP_FILE}, + {"dynamic", T_DYNAMIC}, + {"fail", T_FAIL}, + {"fake-iquery", T_FAKE_IQUERY}, + {"false", T_FALSE}, + {"fetch-glue", T_FETCH_GLUE}, + {"file", T_FILE}, + {"files", T_FILES}, + {"first", T_FIRST}, + {"forward", T_FORWARD}, + {"forwarders", T_FORWARDERS}, + {"hint", T_HINT}, + {"host-statistics", T_HOSTSTATS}, + {"if-no-answer", T_IF_NO_ANSWER}, + {"if-no-domain", T_IF_NO_DOMAIN}, + {"ignore", T_IGNORE}, + {"include", T_INCLUDE}, + {"interface-interval", T_INTERFACE_INTERVAL}, + {"key", T_SEC_KEY}, + {"keys", T_KEYS}, + {"listen-on", T_LISTEN_ON}, + {"logging", T_LOGGING}, + {"many-answers", T_MANY_ANSWERS}, + {"master", T_MASTER}, + {"masters", T_MASTERS}, + {"max-transfer-time-in", T_MAX_TRANSFER_TIME_IN}, + {"memstatistics-file", T_MEMSTATS_FILE}, + {"multiple-cnames", T_MULTIPLE_CNAMES}, + {"named-xfer", T_NAMED_XFER}, + {"no", T_NO}, + {"notify", T_NOTIFY}, + {"null", T_NULL_OUTPUT}, + {"one-answer", T_ONE_ANSWER}, + {"only", T_ONLY}, + {"options", T_OPTIONS}, + {"pid-file", T_PIDFILE}, + {"port", T_PORT}, + {"print-category", T_PRINT_CATEGORY}, + {"print-severity", T_PRINT_SEVERITY}, + {"print-time", T_PRINT_TIME}, + {"query-source", T_QUERY_SOURCE}, + {"recursion", T_RECURSION}, + {"response", T_RESPONSE}, + {"secret", T_SECRET}, + {"server", T_SERVER}, + {"severity", T_SEVERITY}, + {"size", T_SIZE}, + {"slave", T_SLAVE}, + {"stacksize", T_STACKSIZE}, + {"statistics-file", T_STATS_FILE}, + {"statistics-interval", T_STATS_INTERVAL}, + {"stub", T_STUB}, + {"syslog", T_SYSLOG}, + {"topology", T_TOPOLOGY}, + {"transfer-format", T_TRANSFER_FORMAT}, + {"transfer-source", T_TRANSFER_SOURCE}, + {"transfers", T_TRANSFERS}, + {"transfers-in", T_TRANSFERS_IN}, + {"transfers-out", T_TRANSFERS_OUT}, + {"transfers-per-ns", T_TRANSFERS_PER_NS}, + {"true", T_TRUE}, + {"type", T_TYPE}, + {"unlimited", T_UNLIMITED}, + {"versions", T_VERSIONS}, + {"warn", T_WARN}, + {"yes", T_YES}, + {"zone", T_ZONE}, + {(char *) NULL, 0}, +}; + +/* + * The table size should be a prime chosen to minimize collisions. + */ +#define KEYWORD_TABLE_SIZE 461 + +static symbol_table keyword_table = NULL; + +static void +init_keywords() { + struct keyword *k; + symbol_value value; + + if (keyword_table != NULL) + free_symbol_table(keyword_table); + keyword_table = new_symbol_table(KEYWORD_TABLE_SIZE, NULL); + for (k = keywords; k->name != NULL; k++) { + value.integer = k->token; + define_symbol(keyword_table, k->name, 0, value, 0); + } + dprint_symbol_table(99, keyword_table); +} + +/* + * File Contexts + */ + +void +lexer_begin_file(const char *filename, FILE *stream) { + LexerFileContext lf; + + if (stream == NULL) { + stream = fopen(filename, "r"); + if (stream == NULL) { + parser_error(0, "couldn't open include file '%s'", + filename); + return; + } + } + lf = (LexerFileContext)memget(sizeof (struct lexer_file_context)); + if (lf == NULL) + panic("memget failed in lexer_begin_file", NULL); + INSIST(stream != NULL); + lf->stream = stream; + lf->name = filename; /* note copy by reference */ + lf->line_number = 1; + lf->state = scan; + lf->flags = 0; + lf->warnings = 0; + lf->errors = 0; + lf->next = current_file; + current_file = lf; +} + +void +lexer_end_file(void) { + LexerFileContext lf; + + INSIST(current_file != NULL); + lf = current_file; + current_file = lf->next; + fclose(lf->stream); + memput(lf, sizeof *lf); +} + +/* + * Character Input + */ + +static void +scan_to_comment_end(int c_plus_plus_style) { + int c, nc; + int done = 0; + int prev_was_star = 0; + + while (!done) { + c = getc(current_file->stream); + switch (c) { + case EOF: + if (!c_plus_plus_style) + parser_error(0, "EOF in comment"); + current_file->flags |= LEX_EOF; + done = 1; + break; + case '*': + prev_was_star = 1; + break; + case '/': + if (prev_was_star && !c_plus_plus_style) + done = 1; + prev_was_star = 0; + break; + case '\n': + if (c_plus_plus_style) { + /* don't consume the newline because + we want it to be a delimiter for + anything before the comment + started */ + ungetc(c, current_file->stream); + done = 1; + } else { + current_file->line_number++; + } + prev_was_star = 0; + break; + default: + prev_was_star = 0; + } + } +} + +int +get_next_char(int comment_ok) { + int c, nc; + + if (current_file->flags & LEX_EOF) + return (EOF); + + c = getc(current_file->stream); + + if (comment_ok) { + while (c == '/' || c == '#') { + if (c == '#') { + scan_to_comment_end(1); + if (current_file->flags & LEX_EOF) + return (EOF); + c = getc(current_file->stream); + } else { + nc = getc(current_file->stream); + switch (nc) { + case EOF: + current_file->flags |= LEX_EOF; + return ('/'); + case '*': + case '/': + scan_to_comment_end((nc == '/')); + if (current_file->flags & LEX_EOF) + return (EOF); + c = getc(current_file->stream); + break; + default: + ungetc((nc), current_file->stream); + return ('/'); + } + } + } + } + + if (c == EOF) + current_file->flags |= LEX_EOF; + else if (c == '\n') + current_file->line_number++; + return (c); +} + +void +put_back_char(int c) { + if (c == EOF) + current_file->flags |= LEX_EOF; + else { + ungetc((c), current_file->stream); + if (c == '\n') + current_file->line_number--; + } +} + + +/* + * Identifiers + */ + +static void +clear_identifier(LexerIdentifier id) { + INSIST(id != NULL); + id->index = 0; + id->num_dots = 0; + id->flags = 0; +} + +static char * +dup_identifier(LexerIdentifier id) { + char *duplicate; + + INSIST(id != NULL); + duplicate = savestr(id->buffer, 1); + return (duplicate); +} + +static void +finish_identifier(LexerIdentifier id) { + INSIST(id != NULL && id->index < LEX_MAX_IDENT_SIZE); + id->buffer[id->index] = '\0'; +} + +static void +add_to_identifier(LexerIdentifier id, int c) { + INSIST(id != NULL); + id->buffer[id->index] = c; + id->index++; + if (id->index >= LEX_MAX_IDENT_SIZE) { + parser_error(0, "identifier too long"); + current_file->state = scan; + /* discard chars until we hit a non-identifier char */ + while (identifier_char(c)) { + c = get_next_char(1); + } + put_back_char(c); + clear_identifier(id); + } else { + if (c == '.') { + if (id->flags & LEX_LAST_WAS_DOT) + id->flags |= LEX_CONSECUTIVE_DOTS; + id->flags |= LEX_LAST_WAS_DOT; + id->num_dots++; + } else { + id->flags &= ~LEX_LAST_WAS_DOT; + } + } +} + +/* + * yylex() -- return the next token from the current input stream + */ +int +yylex() { + int c, i; + int comment_ok = 1; + int token = -1; + symbol_value value; + + while (token < 0) { + c = get_next_char(comment_ok); + switch(current_file->state) { + case scan: + if (c == EOF) { + if (current_file->next == NULL) + /* + * We don't want to call + * lexer_end_file() here because we + * want to keep the toplevel file + * context to log errors against. + */ + token = 0; + else { + lexer_end_file(); + token = L_END_INCLUDE; + } + break; + } + if (whitespace(c)) + break; + if (identifier_char(c)) { + if (isdigit(c)) + current_file->state = number; + else + current_file->state = identifier; + clear_identifier(id); + add_to_identifier(id, c); + } else + if (special_char(c)) { + if (c == ';') { + token = L_EOS; + break; + } + if (c == '"') { + clear_identifier(id); + current_file->state = + quoted_string; + comment_ok = 0; + break; + } + token = c; + } else { + parser_error(0, + "invalid character '%c'", + c); + } + break; + + case number: + if (identifier_char(c)) { + if (!isdigit(c)) + current_file->state = + (c == '.') ? ipv4 : identifier; + add_to_identifier(id, c); + } else { + put_back_char(c); + current_file->state = scan; + finish_identifier(id); + yylval.num = atoi(id->buffer); + token = L_NUMBER; + } + break; + + case identifier: + if (identifier_char(c)) { + add_to_identifier(id, c); + } else { + put_back_char(c); + current_file->state = scan; + finish_identifier(id); + /* is it a keyword? */ + if (lookup_symbol(keyword_table, id->buffer, + 0, &value)) { + yylval.cp = id->buffer; + token = value.integer; + } else { + yylval.cp = dup_identifier(id); + token = L_STRING; + } + } + break; + + case ipv4: + if (identifier_char(c)) { + if (!isdigit(c)) { + if (c != '.' || + (id->flags & LEX_CONSECUTIVE_DOTS)) + current_file->state = + identifier; + } + add_to_identifier(id, c); + } else { + put_back_char(c); + if (id->num_dots > 3 || + (id->flags & LEX_LAST_WAS_DOT)) + current_file->state = identifier; + else { + if (id->num_dots == 1) { + add_to_identifier(id, '.'); + add_to_identifier(id, '0'); + add_to_identifier(id, '.'); + add_to_identifier(id, '0'); + } else if (id->num_dots == 2) { + add_to_identifier(id, '.'); + add_to_identifier(id, '0'); + } + current_file->state = scan; + finish_identifier(id); + token = L_IPADDR; + if (inet_aton(id->buffer, + &(yylval.ip_addr))==0) { + yylval.cp = dup_identifier(id); + token = L_STRING; + } + } + } + break; + + case quoted_string: + if (c == EOF) { + parser_error(0, "EOF in quoted string"); + return 0; + } else { + if (c == '"') { + comment_ok = 1; + current_file->state = scan; + finish_identifier(id); + yylval.cp = dup_identifier(id); + token = L_QSTRING; + } else { + /* XXX add backslash escapes here */ + add_to_identifier(id, c); + } + } + break; + + default: + panic("unhandled state in yylex", NULL); + } + } + + last_token = token; + last_yylval = yylval; + return (token); +} + +/* + * Initialization + */ + +symbol_table constants; + +static void +import_constants(const struct ns_sym *s, int type) { + symbol_value value; + for ((void)NULL; s != NULL && s->name != NULL; s++) { + value.integer = s->number; + define_symbol(constants, s->name, type, value, 0); + } +} + +static void +import_res_constants(const struct res_sym *r, int type) { + symbol_value value; + for ((void)NULL; r != NULL && r->name != NULL; r++) { + value.integer = r->number; + define_symbol(constants, r->name, type, value, 0); + } +} + +#define CONSTANTS_TABLE_SIZE 397 /* should be prime */ + +static void +import_all_constants() { + constants = new_symbol_table(CONSTANTS_TABLE_SIZE, NULL); + import_res_constants(__p_class_syms, SYM_CLASS); + import_constants(category_constants, SYM_CATEGORY); + import_constants(logging_constants, SYM_LOGGING); + import_constants(syslog_constants, SYM_SYSLOG); +} + +void +lexer_initialize() { + memset(special_chars, 0, sizeof special_chars); + special_chars[';'] = 1; + special_chars['{'] = 1; + special_chars['}'] = 1; + special_chars['!'] = 1; + special_chars['/'] = 1; + special_chars['"'] = 1; + special_chars['*'] = 1; + id = (LexerIdentifier)memget(sizeof (struct lexer_identifier)); + if (id == NULL) + panic("memget failed in init_once", NULL); + init_keywords(); + import_all_constants(); + lexer_initialized = 1; +} + +void +lexer_setup(void) { + REQUIRE(lexer_initialized); + + current_file = NULL; /* XXX should we INSIST(current_file==NULL)? */ + INSIST(id != NULL); +} + +void +lexer_shutdown(void) { + REQUIRE(lexer_initialized); + + free_symbol_table(keyword_table); + free_symbol_table(constants); + memput(id, sizeof (struct lexer_identifier)); + lexer_initialized = 0; +} diff --git a/contrib/bind/bin/named/ns_lexer.h b/contrib/bind/bin/named/ns_lexer.h new file mode 100644 index 0000000..3491df3 --- /dev/null +++ b/contrib/bind/bin/named/ns_lexer.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1996, 1997 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. + */ + +#ifndef NS_LEXER_H +#define NS_LEXER_H + +/* + * Note: <stdio.h> and "ns_parseutil.h" must be included + * before this file is included. + */ + +#define LEX_MAX_IDENT_SIZE 1024 + +#define SYM_CLASS 0x01 +#define SYM_CATEGORY 0x02 +#define SYM_LOGGING 0x04 +#define SYM_SYSLOG 0x08 + +int parser_warning(int, const char *, ...); +int parser_error(int, const char *, ...); +void yyerror(const char *); +void lexer_begin_file(const char *, FILE *); +void lexer_end_file(void); +int yylex(void); +void lexer_initialize(void); +void lexer_setup(void); +void lexer_shutdown(void); + +extern symbol_table constants; + +#endif /* NS_LEXER_H */ diff --git a/contrib/bind/bin/named/ns_main.c b/contrib/bind/bin/named/ns_main.c new file mode 100644 index 0000000..a4b4360 --- /dev/null +++ b/contrib/bind/bin/named/ns_main.c @@ -0,0 +1,2200 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)ns_main.c 4.55 (Berkeley) 7/1/91"; +static char rcsid[] = "$Id: ns_main.c,v 8.65 1998/04/06 23:45:32 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1989, 1990 + * 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) 1996, 1997 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. + */ + +#if !defined(lint) && !defined(SABER) +char copyright[] = +"@(#) Copyright (c) 1986, 1989, 1990 The Regents of the University of California.\n\ + portions Copyright (c) 1993 Digital Equipment Corporation\n\ + portions Copyright (c) 1995, 1996, 1997 Internet Software Consortium\n\ + All rights reserved.\n"; +#endif /* not lint */ + +/* + * Internet Name server (see RCF1035 & others). + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#ifdef SVR4 /* XXX */ +# include <sys/sockio.h> +#else +# include <sys/mbuf.h> +#endif + +#include <netinet/in.h> +#include <net/route.h> +#include <net/if.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <netdb.h> +#include <pwd.h> +#include <resolv.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> +#include <isc/list.h> + +#include "port_after.h" + +#ifdef HAVE_GETRUSAGE /* XXX */ +#include <sys/resource.h> +#endif + +#define MAIN_PROGRAM +#include "named.h" +#undef MAIN_PROGRAM + + /* list of interfaces */ +static LIST(struct _interface) iflist; +static int iflist_initialized = 0; + + /* UDP receive, TCP send buffer size */ +static const int rbufsize = 8 * 1024, + /* TCP send window size */ + sbufsize = 16 * 1024; + +static u_int16_t nsid_state; +static int needs; + +static struct qstream *sq_add(void); +static int opensocket_d(interface *), + opensocket_s(interface *); +static void sq_query(struct qstream *), + dq_remove(interface *), + ns_handle_needs(void); +static int sq_dowrite(struct qstream *); +static void use_desired_debug(void); +static void stream_write(evContext, void *, int, int); + +static interface * if_find(struct in_addr, u_int16_t port); + +static int sq_here(struct qstream *); + +static void stream_accept(evContext, void *, int, + const void *, int, + const void *, int), + stream_getlen(evContext, void *, int, int), + stream_getmsg(evContext, void *, int, int), + datagram_read(evContext, void *, int, int), + dispatch_message(u_char *, int, int, + struct qstream *, + struct sockaddr_in, int, + interface *); +static void stream_send(evContext, void *, int, + const void *, int, + const void *, int); +static void init_signals(void); +static void set_signal_handler(int, SIG_FN (*)()); +static int only_digits(const char *); + +static void +usage() { + fprintf(stderr, +"Usage: named [-d #] [-q] [-r] [-f] [-p port] [[-b|-c] configfile]\n"); +#ifdef CAN_CHANGE_ID + fprintf(stderr, +" [-u (username|uid)] [-g (groupname|gid)]\n"); +#endif +#ifdef HAVE_CHROOT + fprintf(stderr, +" [-t directory]\n"); +#endif + exit(1); +} + +static char bad_p_option[] = +"-p remote/local obsolete; use 'listen-on' in config file to specify local"; + +static char bad_directory[] = "chdir failed for directory '%s': %s"; + +/*ARGSUSED*/ +int +main(int argc, char *argv[], char *envp[]) { + int n, udpcnt; + char *arg; + struct qstream *sp; + interface *ifp; + const int on = 1; + int rfd, size, len, debug_option; + char **argp, *p; + int ch; + FILE *fp; /* file descriptor for pid file */ + struct passwd *pw; + struct group *gr; +#ifdef HAVE_GETRUSAGE + struct rlimit rl; +#endif + + user_id = getuid(); + group_id = getgid(); + + ns_port = htons(NAMESERVER_PORT); + desired_debug = debug; + + /* BSD has a better random number generator but it's not clear + * that we need it here. + */ + gettime(&tt); + srand(((unsigned)getpid()) + (unsigned)tt.tv_usec); + + (void) umask(022); + + while ((ch = getopt(argc, argv, "b:c:d:g:p:t:u:w:qrf")) != EOF) { + switch (ch) { + case 'b': + case 'c': + if (conffile != NULL) + freestr(conffile); + conffile = savestr(optarg, 1); + break; + + case 'd': + desired_debug = atoi(optarg); + if (desired_debug <= 0) + desired_debug = 1; + break; + + case 'p': + /* use nonstandard port number. + * usage: -p remote/local + * remote is the port number to which + * we send queries. local is the port + * on which we listen for queries. + * local defaults to same as remote. + */ + ns_port = htons((u_int16_t) atoi(optarg)); + p = strchr(optarg, '/'); + if (p) { + syslog(LOG_WARNING, bad_p_option); + fprintf(stderr, bad_p_option); + fputc('\n', stderr); + } + break; + + case 'w': + if (chdir(optarg) < 0) { + syslog(LOG_CRIT, bad_directory, optarg, + strerror(errno)); + fprintf(stderr, bad_directory, optarg, + strerror(errno)); + fputc('\n', stderr); + exit(1); + } + break; +#ifdef QRYLOG + case 'q': + qrylog = 1; + break; +#endif + + case 'r': + ns_setoption(OPTION_NORECURSE); + break; + + case 'f': + foreground = 1; + break; + + case 't': + chroot_dir = savestr(optarg, 1); + break; + +#ifdef CAN_CHANGE_ID + case 'u': + user_name = savestr(optarg, 1); + if (only_digits(user_name)) + user_id = atoi(user_name); + else { + pw = getpwnam(user_name); + if (pw == NULL) { + fprintf(stderr, + "user \"%s\" unknown\n", + user_name); + exit(1); + } + user_id = pw->pw_uid; + if (group_name == NULL) { + char name[256]; + + sprintf(name, "%lu", + (u_long)pw->pw_gid); + group_name = savestr(name, 1); + group_id = pw->pw_gid; + } + } + break; + + case 'g': + if (group_name != NULL) + freestr(group_name); + group_name = savestr(optarg, 1); + if (only_digits(group_name)) + group_id = atoi(group_name); + else { + gr = getgrnam(group_name); + if (gr == NULL) { + fprintf(stderr, + "group \"%s\" unknown\n", + group_name); + exit(1); + } + group_id = gr->gr_gid; + } + break; +#endif /* CAN_CHANGE_ID */ + + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc) { + if (conffile != NULL) + freestr(conffile); + conffile = savestr(*argv, 1); + argc--, argv++; + } + if (argc) + usage(); + + if (conffile == NULL) + conffile = savestr(_PATH_CONF, 1); + + /* + * Make sure we don't inherit any open descriptors + * other than those that daemon() can deal with. + */ + for (n = sysconf(_SC_OPEN_MAX) - 1; n >= 0; n--) + if (n != STDIN_FILENO && + n != STDOUT_FILENO && + n != STDERR_FILENO) + (void) close(n); + + /* + * Chroot if desired. + */ + if (chroot_dir != NULL) { +#ifdef HAVE_CHROOT + if (chroot(chroot_dir) < 0) { + fprintf(stderr, "chroot %s failed: %s\n", chroot_dir, + strerror(errno)); + exit(1); + } + if (chdir("/") < 0) { + fprintf(stderr, "chdir(\"/\") failed: %s\n", + strerror(errno)); + exit(1); + } +#else + fprintf(stderr, "warning: chroot() not available\n"); + freestr(chroot_dir); + chroot_dir = NULL; +#endif + } + + /* Establish global event context. */ + evCreate(&ev); + + /* + * Set up logging. + */ + n = LOG_PID; +#ifdef LOG_NOWAIT + n |= LOG_NOWAIT; +#endif +#ifdef LOG_NDELAY + n |= LOG_NDELAY; +#endif +#if defined(LOG_CONS) && defined(USE_LOG_CONS) + n |= LOG_CONS; +#endif +#ifdef SYSLOG_42BSD + openlog("named", n); +#else + openlog("named", n, LOG_DAEMON); +#endif + + init_logging(); + set_assertion_failure_callback(ns_assertion_failed); + +#ifdef DEBUG + use_desired_debug(); +#endif + + init_signals(); + + ns_notice(ns_log_default, "starting. %s", Version); + + _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); + + nsid_init(); + + /* + * Initialize and load database. + */ + gettime(&tt); + buildservicelist(); + buildprotolist(); + ns_init(conffile); + time(&boottime); + resettime = boottime; + + /* + * Fork and go into background now that + * we've done any slow initialization + * and are ready to answer queries. + */ + + if (foreground == 0) { + if (daemon(1, 0)) + ns_panic(ns_log_default, 1, "daemon: %s", + strerror(errno)); + update_pid_file(); + } + + /* Check that udp checksums are on. */ + ns_udp(); + + /* + * We waited until now to log this because we wanted logging to + * be set up the way the user prefers. + */ + if (chroot_dir != NULL) + ns_info(ns_log_security, "chrooted to %s", chroot_dir); + +#ifdef CAN_CHANGE_ID + /* + * Set user and group if desired. + */ + if (group_name != NULL) { + if (setgid(group_id) < 0) + ns_panic(ns_log_security, 1, "setgid(%s): %s", + group_name, strerror(errno)); + ns_info(ns_log_security, "group = %s", group_name); + } + if (user_name != NULL) { + if (getuid() == 0 && initgroups(user_name, group_id) < 0) + ns_panic(ns_log_security, 1, "initgroups(%s, %d): %s", + user_name, (int)group_id, strerror(errno)); + endgrent(); + endpwent(); + if (setuid(user_id) < 0) + ns_panic(ns_log_security, 1, "setuid(%s): %s", + user_name, strerror(errno)); + ns_info(ns_log_security, "user = %s", user_name); + } +#endif /* CAN_CHANGE_ID */ + + ns_notice(ns_log_default, "Ready to answer queries."); + gettime(&tt); + prime_cache(); + for (;;) { + evEvent event; + + if (needs) + ns_handle_needs(); + INSIST_ERR(evGetNext(ev, &event, EV_WAIT) != -1); + INSIST_ERR(evDispatch(ev, event) != -1); + } + /* NOTREACHED */ + return (0); +} + +#ifndef IP_OPT_BUF_SIZE +/* arbitrary size */ +#define IP_OPT_BUF_SIZE 50 +#endif + +static void +stream_accept(evContext lev, void *uap, int rfd, + const void *lav, int lalen, + const void *rav, int ralen) +{ + interface *ifp = uap; + struct qstream *sp; + struct iovec iov; + int n, len; + const int on = 1; +#ifdef IP_OPTIONS /* XXX */ + u_char ip_opts[IP_OPT_BUF_SIZE]; +#endif + const struct sockaddr_in *la, *ra; + + la = (const struct sockaddr_in *)lav; + ra = (const struct sockaddr_in *)rav; + + INSIST(ifp != NULL); + + if (rfd < 0) { + switch (errno) { + case EINTR: + case EAGAIN: +#if (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif + case ECONNABORTED: +#ifdef EPROTO + case EPROTO: +#endif + case EHOSTUNREACH: + case EHOSTDOWN: + case ENETUNREACH: + case ENETDOWN: + case ECONNREFUSED: +#ifdef ENONET + case ENONET: +#endif + /* + * These errors are expected and harmless, so + * we ignore them. + */ + return; + case EBADF: + case ENOTSOCK: + case EFAULT: + /* + * If one these happens, we're broken. + */ + ns_panic(ns_log_default, 1, "accept: %s", + strerror(errno)); + case EMFILE: + /* + * If we're out of file descriptors, find the least + * busy fd and close it. Then we'll return to the + * eventlib which will call us right back. + */ + if (streamq) { + struct qstream *nextsp; + struct qstream *candidate = NULL; + time_t lasttime, maxctime = 0; + + for (sp = streamq; sp; sp = nextsp) { + nextsp = sp->s_next; + if (sp->s_refcnt) + continue; + gettime(&tt); + lasttime = tt.tv_sec - sp->s_time; + if (lasttime >= VQEXPIRY) + sq_remove(sp); + else if (lasttime > maxctime) { + candidate = sp; + maxctime = lasttime; + } + } + if (candidate) + sq_remove(candidate); + return; + } + /* fall through */ + default: + /* + * Either we got an error we didn't expect, or we + * got EMFILE and didn't have anything left to close. + * Log it and press on. + */ + ns_info(ns_log_default, "accept: %s", strerror(errno)); + return; + } + } + + /* Condition the socket. */ + +/* XXX clean up */ +#if 0 + if ((n = fcntl(rfd, F_GETFL, 0)) == -1) { + ns_info(ns_log_default, "fcntl(rfd, F_GETFL): %s", + strerror(errno)); + (void) close(rfd); + return; + } + if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) == -1) { + ns_info(ns_log_default, "fcntl(rfd, NONBLOCK): %s", + strerror(errno)); + (void) close(rfd); + return; + } +#endif +#ifndef CANNOT_SET_SNDBUF + if (setsockopt(rfd, SOL_SOCKET, SO_SNDBUF, + (char*)&sbufsize, sizeof sbufsize) < 0) { + ns_info(ns_log_default, "setsockopt(rfd, SO_SNDBUF, %d): %s", + sbufsize, strerror(errno)); + (void) close(rfd); + return; + } +#endif + if (setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE, + (char *)&on, sizeof on) < 0) { + ns_info(ns_log_default, "setsockopt(rfd, KEEPALIVE): %s", + strerror(errno)); + (void) close(rfd); + return; + } + + /* + * We don't like IP options. Turn them off if the connection came in + * with any. log this event since it usually indicates a security + * problem. + */ +#if defined(IP_OPTIONS) /* XXX */ + len = sizeof ip_opts; + if (getsockopt(rfd, IPPROTO_IP, IP_OPTIONS, + (char *)ip_opts, &len) < 0) { + ns_info(ns_log_default, "getsockopt(rfd, IP_OPTIONS): %s", + strerror(errno)); + (void) close(rfd); + return; + } + if (len != 0) { + nameserIncr(ra->sin_addr, nssRcvdOpts); + if (!haveComplained(ina_ulong(ra->sin_addr), + (u_long)"rcvd ip options")) { + ns_info(ns_log_default, + "rcvd IP_OPTIONS from %s (ignored)", + sin_ntoa(*ra)); + } + if (setsockopt(rfd, IPPROTO_IP, IP_OPTIONS, NULL, 0) < 0) { + ns_info(ns_log_default, "setsockopt(!IP_OPTIONS): %s", + strerror(errno)); + (void) close(rfd); + } + } +#endif + + /* Create and populate a qsp for this socket. */ + if ((sp = sq_add()) == NULL) { + (void) close(rfd); + return; + } + sp->s_rfd = rfd; /* stream file descriptor */ + gettime(&tt); + sp->s_time = tt.tv_sec; /* last transaction time */ + sp->s_from = *ra; /* address to respond to */ + sp->s_ifp = ifp; + INSIST(sizeof sp->s_temp >= INT16SZ); + iov = evConsIovec(sp->s_temp, INT16SZ); + INSIST_ERR(evRead(lev, rfd, &iov, 1, stream_getlen, sp, &sp->evID_r) + != -1); + sp->flags |= STREAM_READ_EV; +#ifdef DEBUG + if (debug) + ns_info(ns_log_default, "IP/TCP connection from %s (fd %d)", + sin_ntoa(sp->s_from), rfd); +#endif +} + +int +tcp_send(struct qinfo *qp) { + struct qstream *sp; + int on = 1; + + ns_debug(ns_log_default, 1, "tcp_send"); + if ((sp = sq_add()) == NULL) { + return(SERVFAIL); + } + if ((sp->s_rfd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1) { + sq_remove(sp); + return(SERVFAIL); + } + + if (sq_openw(sp, qp->q_msglen + INT16SZ) == -1) { + sq_remove(sp); + return(SERVFAIL); + } + if (sq_write(sp, qp->q_msg, qp->q_msglen) == -1) { + sq_remove(sp); + return(SERVFAIL); + } + + if (setsockopt(sp->s_rfd, SOL_SOCKET, SO_KEEPALIVE, + (char*)&on, sizeof(on)) < 0) + ns_info(ns_log_default, + "tcp_send: setsockopt(rfd, SO_KEEPALIVE): %s", + strerror(errno)); + gettime(&tt); + sp->s_size = -1; + sp->s_time = tt.tv_sec; /* last transaction time */ + sp->s_refcnt = 1; + sp->flags |= STREAM_DONE_CLOSE; + if (qp->q_fwd) + sp->s_from = qp->q_fwd->fwdaddr; + else + sp->s_from = qp->q_addr[qp->q_curaddr].ns_addr; + if (evConnect(ev, sp->s_rfd, &sp->s_from, sizeof(sp->s_from), + stream_send, sp, &sp->evID_c) == -1) { + sq_remove(sp); + return (SERVFAIL); + } + sp->flags |= STREAM_CONNECT_EV; + return(NOERROR); +} + +static void +stream_send(evContext lev, void *uap, int fd, const void *la, int lalen, + const void *ra, int ralen) { + struct qstream *sp = uap; + + ns_debug(ns_log_default, 1, "stream_send"); + + sp->flags &= ~STREAM_CONNECT_EV; + + if (fd == -1) { + /* connect failed */ + sq_remove(sp); + return; + } + if (evSelectFD(ev, sp->s_rfd, EV_WRITE, + stream_write, sp, &sp->evID_w) < 0) { + sq_remove(sp); + return; + } + sp->flags |= STREAM_WRITE_EV; +} + +static void +stream_write(evContext ctx, void *uap, int fd, int evmask) { + struct qstream *sp = uap; + struct iovec iov; + + ns_debug(ns_log_default, 1, "stream_write"); + INSIST(evmask & EV_WRITE); + INSIST(fd == sp->s_rfd); + if (sq_dowrite(sp) < 0) { + sq_remove(sp); + return; + } + if (sp->s_wbuf_free != sp->s_wbuf_send) + return; + + if (sp->s_wbuf) { + memput(sp->s_wbuf, sp->s_wbuf_end - sp->s_wbuf); + sp->s_wbuf = NULL; + } + (void) evDeselectFD(ev, sp->evID_w); + sp->flags &= ~STREAM_WRITE_EV; + sp->s_refcnt = 0; + iov = evConsIovec(sp->s_temp, INT16SZ); + INSIST_ERR(evRead(ctx, fd, &iov, 1, stream_getlen, sp, &sp->evID_r) != + -1); + sp->flags |= STREAM_READ_EV; +} + +static void +stream_getlen(evContext lev, void *uap, int fd, int bytes) { + struct qstream *sp = uap; + struct iovec iov; + + sp->flags &= ~STREAM_READ_EV; + if (bytes != INT16SZ) { + /* + * bytes == 0 is normal EOF; see if something unusual + * happened. + */ + if (bytes < 0) { + /* + * ECONNRESET happens frequently and is not worth + * logging. + */ + if (errno != ECONNRESET) + ns_info(ns_log_default, + "stream_getlen(%s): %s", + sin_ntoa(sp->s_from), strerror(errno)); + } else if (bytes != 0) + ns_error(ns_log_default, + "stream_getlen(%s): unexpected byte count %d", + sin_ntoa(sp->s_from), bytes); + sq_remove(sp); + return; + } + + /* + * Unpack the size, allocate memory for the query. This is + * tricky since in a low memory situation with possibly very + * large (64KB) queries, we want to make sure we can read at + * least the header since we need it to send back a SERVFAIL + * (owing to the out-of-memory condition). + */ + sp->s_size = ns_get16(sp->s_temp); + ns_debug(ns_log_default, 5, "stream message: %d bytes", sp->s_size); + + if (!(sp->flags & STREAM_MALLOC)) { + sp->s_bufsize = 64*1024-1; /* maximum tcp message size */ + sp->s_buf = (u_char *)memget(sp->s_bufsize); + if (sp->s_buf != NULL) + sp->flags |= STREAM_MALLOC; + else { + sp->s_buf = sp->s_temp; + sp->s_bufsize = HFIXEDSZ; + } + } + + iov = evConsIovec(sp->s_buf, sp->s_size); + if (evRead(lev, sp->s_rfd, &iov, 1, stream_getmsg, sp, &sp->evID_r) + == -1) + ns_panic(ns_log_default, 1, "evRead(fd %d): %s", + (void *)sp->s_rfd, strerror(errno)); + sp->flags |= STREAM_READ_EV; +} + +static void +stream_getmsg(evContext lev, void *uap, int fd, int bytes) { + struct qstream *sp = uap; + int buflen, n; + + sp->flags &= ~STREAM_READ_EV; + if (bytes == -1) { + ns_info(ns_log_default, "stream_getmsg(%s): %s", + sin_ntoa(sp->s_from), strerror(errno)); + sq_remove(sp); + return; + } + + gettime(&tt); + sp->s_time = tt.tv_sec; + + ns_debug(ns_log_default, 5, "sp %#x rfd %d size %d time %d next %#x", + sp, sp->s_rfd, sp->s_size, sp->s_time, sp->s_next); + ns_debug(ns_log_default, 5, "\tbufsize %d bytes %d", sp->s_bufsize, + bytes); + + /* + * Do we have enough memory for the query? If not, and if we have a + * query id, then we will send a SERVFAIL error back to the client. + */ + if (bytes != sp->s_size) { + HEADER *hp = (HEADER *)sp->s_buf; + + hp->qr = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + hp->ancount = htons(0); + hp->qdcount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = SERVFAIL; + writestream(sp, sp->s_buf, HFIXEDSZ); + sp->flags |= STREAM_DONE_CLOSE; + return; + } + + nameserIncr(sp->s_from.sin_addr, nssRcvdTCP); + sq_query(sp); + dispatch_message(sp->s_buf, bytes, sp->s_bufsize, sp, sp->s_from, -1, + sp->s_ifp); +} + +static void +datagram_read(evContext lev, void *uap, int fd, int evmask) { + interface *ifp = uap; + struct sockaddr_in from; + int from_len = sizeof from; + int n; + union { + HEADER h; /* Force alignment of 'buf'. */ + u_char buf[PACKETSZ+1]; + } u; + + n = recvfrom(fd, (char *)u.buf, sizeof u.buf, 0, + (struct sockaddr *)&from, &from_len); + + if (n < 0) { + switch (errno) { + case EINTR: + case EAGAIN: +#if (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif + case EHOSTUNREACH: + case EHOSTDOWN: + case ENETUNREACH: + case ENETDOWN: + case ECONNREFUSED: +#ifdef ENONET + case ENONET: +#endif + /* + * These errors are expected and harmless, so we + * ignore them. + */ + return; + case EBADF: + case ENOTCONN: + case ENOTSOCK: + case EFAULT: + /* + * If one these happens, we're broken. + */ + ns_panic(ns_log_default, 1, "recvfrom: %s", + strerror(errno)); + default: + /* + * An error we don't expect. Log it and press + * on. + */ + ns_info(ns_log_default, "recvfrom: %s", + strerror(errno)); + return; + } + } + +#ifndef BSD + /* Handle bogosity on systems that need it. */ + if (n == 0) + return; +#endif + + ns_debug(ns_log_default, 1, "datagram from %s, fd %d, len %d", + sin_ntoa(from), fd, n); + + if (n > PACKETSZ) { + /* + * The message is too big. It's probably a response to + * one of our questions, so we truncate it and press on. + */ + n = trunc_adjust(u.buf, PACKETSZ, PACKETSZ); + ns_debug(ns_log_default, 1, "truncated oversize UDP packet"); + } + + gettime(&tt); /* Keep 'tt' current. */ + dispatch_message(u.buf, n, PACKETSZ, NULL, from, fd, ifp); +} + +static void +dispatch_message(u_char *msg, int msglen, int buflen, struct qstream *qsp, + struct sockaddr_in from, int dfd, interface *ifp) +{ + HEADER *hp = (HEADER *)msg; + + if (msglen < HFIXEDSZ) { + ns_debug(ns_log_default, 1, "dropping undersize message"); + return; + } + if (hp->qr) { + ns_resp(msg, msglen, from, qsp); + if (qsp) + sq_done(qsp); + /* Now is a safe time for housekeeping. */ + if (needs_prime_cache) + prime_cache(); + } else if (ifp != NULL) + ns_req(msg, msglen, buflen, qsp, from, dfd); + else { + ns_notice(ns_log_security, + "refused query on non-query socket from %s", + sin_ntoa(from)); + /* XXX Send refusal here. */ + } +} + +void +getnetconf(int periodic_scan) { + struct ifconf ifc; + struct ifreq ifreq; + struct in_addr ina; + interface *ifp; + char buf[32768], *cp, *cplim; + u_int32_t nm; + time_t my_generation = time(NULL); + int s, cpsize; + int found; + listen_info li; + u_int16_t port; + ip_match_element ime; + u_char *mask_ptr; + struct in_addr mask; + + ns_debug(ns_log_default, 1, "getnetconf(generation %lu)", + (u_long)my_generation); + + /* Get interface list from system. */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + if (!periodic_scan) + ns_panic(ns_log_default, 1, "socket(SOCK_RAW): %s", + strerror(errno)); + ns_error(ns_log_default, "socket(SOCK_RAW): %s", + strerror(errno)); + return; + } + + if (!iflist_initialized) { + INIT_LIST(iflist); + iflist_initialized = 1; + } + + if (local_addresses != NULL) + free_ip_match_list(local_addresses); + local_addresses = new_ip_match_list(); + if (local_networks != NULL) + free_ip_match_list(local_networks); + local_networks = new_ip_match_list(); + + ifc.ifc_len = sizeof buf; + ifc.ifc_buf = buf; + if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) + ns_panic(ns_log_default, 1, "get interface configuration: %s", + strerror(errno)); + + ns_debug(ns_log_default, 2, "getnetconf: SIOCGIFCONF: ifc_len = %d", + ifc.ifc_len); + + /* Parse system's interface list and open some sockets. */ + cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */ + for (cp = buf; cp < cplim; cp += cpsize) { + memcpy(&ifreq, cp, sizeof ifreq); +#if defined HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (ifreq.ifr_addr.sa_len == 0) + ifreq.ifr_addr.sa_len = 16; +#endif + cpsize = sizeof ifreq.ifr_name + ifreq.ifr_addr.sa_len; +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof ifreq; +#else + cpsize = sizeof ifreq.ifr_name; + if (ioctl(s, SIOCGIFADDR, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, + "get interface addr (%s): %s", + ifreq.ifr_name, strerror(errno)); + continue; + } +#endif + ina = ina_get((u_char *)&((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr); + if (ifreq.ifr_addr.sa_family != AF_INET) { + ns_debug(ns_log_default, 2, + "getnetconf: af %d != INET", + ifreq.ifr_addr.sa_family); + continue; + } + ns_debug(ns_log_default, 1, + "getnetconf: considering %s [%s]", + ifreq.ifr_name, inet_ntoa(ina)); + /* + * Don't test IFF_UP, packets may still be received at this + * address if any other interface is up. + */ + if (ina_hlong(ina) == INADDR_ANY) { + ns_debug(ns_log_default, 2, + "getnetconf: INADDR_ANY, ignoring."); + continue; + } + + INSIST(server_options != NULL); + INSIST(server_options->listen_list != NULL); + + found=0; + for (li = server_options->listen_list->first; + li != NULL; + li = li->next) { + if (ip_match_address(li->list, ina) > 0) { + found++; + /* + * Look for an already existing source + * interface address/port pair. + * This happens mostly when reinitializing. + * Also, if the machine has multiple point to + * point interfaces, then the local address + * may appear more than once. + */ + ifp = if_find(ina, li->port); + if (ifp != NULL) { + ns_debug(ns_log_default, 1, + "dup interface addr [%s].%u (%s)", + inet_ntoa(ina), + ntohs(li->port), + ifreq.ifr_name); + ifp->gen = my_generation; + continue; + } + + ifp = (interface *)memget(sizeof *ifp); + if (!ifp) + ns_panic(ns_log_default, 1, + "memget(interface)", NULL); + memset(ifp, 0, sizeof *ifp); + APPEND(iflist, ifp, link); + ifp->addr = ina; + ifp->port = li->port; + ifp->gen = my_generation; + ifp->flags = 0; + ifp->dfd = -1; + ifp->sfd = -1; + if (opensocket_d(ifp) < 0 || + opensocket_s(ifp) < 0) { + dq_remove(ifp); + found = 0; + break; + } + ns_info(ns_log_default, + "listening on [%s].%u (%s)", + inet_ntoa(ina), ntohs(li->port), + ifreq.ifr_name); + } + } + if (!found) + ns_debug(ns_log_default, 1, + "not listening on addr [%s] (%s)", + inet_ntoa(ina), ifreq.ifr_name); + + /* + * Add this interface's address to the list of local + * addresses if we haven't added it already. + */ + if (ip_match_address(local_addresses, ina) < 0) { + ime = new_ip_match_pattern(ina, 32); + add_to_ip_match_list(local_addresses, ime); + } + + /* + * Get interface flags. + */ + if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, "get interface flags: %s", + strerror(errno)); + continue; + } + + if ((ifreq.ifr_flags & IFF_POINTOPOINT)) { + /* + * The local network for a PPP link is just the + * two ends of the link, so for each endpoint we + * add a pattern that will only match the endpoint. + */ + if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, "get dst addr: %s", + strerror(errno)); + continue; + } + + mask.s_addr = htonl(INADDR_BROADCAST); + + /* + * Our end. + * + * Only add it if we haven't seen it before. + */ + if (ip_match_network(local_networks, ina, mask) < 0) { + ime = new_ip_match_pattern(ina, 32); + add_to_ip_match_list(local_networks, ime); + } + + /* + * The other end. + */ + ina = ((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr; + /* + * Only add it if we haven't seen it before. + */ + if (ip_match_network(local_networks, ina, mask) < 0) { + ime = new_ip_match_pattern(ina, 32); + add_to_ip_match_list(local_networks, ime); + } + } else { + /* + * Add this interface's network and netmask to the + * list of local networks. + */ + +#ifdef SIOCGIFNETMASK /* XXX */ + if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) { + ns_notice(ns_log_default, "get netmask: %s", + strerror(errno)); + continue; + } + /* + * Use ina_get because the ifreq structure might not + * be aligned. + */ + mask_ptr = (u_char *) + &((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; + mask = ina_get(mask_ptr); +#else + mask = net_mask(ina); +#endif + + ina.s_addr &= mask.s_addr; /* make network address */ + + /* + * Only add it if we haven't seen it before. + */ + if (ip_match_network(local_networks, ina, mask) < 0) { + ime = new_ip_match_mask(ina, mask); + add_to_ip_match_list(local_networks, ime); + } + } + } + close(s); + + ns_debug(ns_log_default, 7, "local addresses:"); + dprint_ip_match_list(ns_log_default, local_addresses, 2, "", ""); + ns_debug(ns_log_default, 7, "local networks:"); + dprint_ip_match_list(ns_log_default, local_networks, 2, "", ""); + + /* + * now go through the iflist and delete anything that + * does not have the current generation number. this is + * how we catch interfaces that go away or change their + * addresses. note that 0.0.0.0 is the wildcard element + * and should never be deleted by this code. + */ + dq_remove_gen(my_generation); + + if (EMPTY(iflist)) + ns_warning(ns_log_default, "not listening on any interfaces"); +} + +/* opensocket_d(ifp) + * Open datagram socket bound to interface address. + * Returns: + * 0 on success. + * -1 on failure. + */ +static int +opensocket_d(interface *ifp) { + struct sockaddr_in nsa; + const int on = 1; + int m, n; + int fd; + + memset(&nsa, 0, sizeof nsa); + nsa.sin_family = AF_INET; + nsa.sin_addr = ifp->addr; + nsa.sin_port = ifp->port; + + if ((ifp->dfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + ns_error(ns_log_default, "socket(SOCK_DGRAM): %s", + strerror(errno)); + return (-1); + } +#ifdef F_DUPFD /* XXX */ + /* + * Leave a space for stdio to work in. + */ + if ((fd = fcntl(ifp->dfd, F_DUPFD, 20)) != -1) { + close(ifp->dfd); + ifp->dfd = fd; + } else + ns_notice(ns_log_default, "fcntl(dfd, F_DUPFD, 20): %s", + strerror(errno)); +#endif + ns_debug(ns_log_default, 1, "ifp->addr %s d_dfd %d", + sin_ntoa(nsa), ifp->dfd); + if (setsockopt(ifp->dfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof(on)) != 0) { + ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s", + strerror(errno)); + /* XXX press on regardless, this is not too serious. */ + } +#ifdef SO_RCVBUF /* XXX */ + m = sizeof n; + if ((getsockopt(ifp->dfd, SOL_SOCKET, SO_RCVBUF, (char*)&n, &m) >= 0) + && (m == sizeof n) + && (n < rbufsize)) { + (void) setsockopt(ifp->dfd, SOL_SOCKET, SO_RCVBUF, + (char *)&rbufsize, sizeof(rbufsize)); + } +#endif /* SO_RCVBUF */ + if (bind(ifp->dfd, (struct sockaddr *)&nsa, sizeof nsa)) { + ns_error(ns_log_default, "bind(dfd=%d, %s): %s", + ifp->dfd, sin_ntoa(nsa), strerror(errno)); + return (-1); + } + if (evSelectFD(ev, ifp->dfd, EV_READ, datagram_read, ifp, + &ifp->evID_d) == -1) { + ns_error(ns_log_default, "evSelectFD(dfd=%d): %s", + ifp->dfd, strerror(errno)); + return (-1); + } + ifp->flags |= INTERFACE_FILE_VALID; + return (0); +} + +/* opensocket_s(ifp) + * Open stream (listener) socket bound to interface address. + * Returns: + * 0 on success. + * -1 on failure. + */ +static int +opensocket_s(interface *ifp) { + struct sockaddr_in nsa; + const int on = 1; + int n; + int fd; + + memset(&nsa, 0, sizeof nsa); + nsa.sin_family = AF_INET; + nsa.sin_addr = ifp->addr; + nsa.sin_port = ifp->port; + + /* + * Open stream (listener) port. + */ + n = 0; + again: + if ((ifp->sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ns_error(ns_log_default, "socket(SOCK_STREAM): %s", + strerror(errno)); + return (-1); + } +#ifdef F_DUPFD /* XXX */ + /* + * Leave a space for stdio to work in. + */ + if ((fd = fcntl(ifp->sfd, F_DUPFD, 20)) != -1) { + close(ifp->sfd); + ifp->sfd = fd; + } else + ns_notice(ns_log_default, "fcntl(sfd, F_DUPFD, 20): %s", + strerror(errno)); +#endif + if (setsockopt(ifp->sfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof on) != 0) { + ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s", + strerror(errno)); + /* Consider that your first warning of trouble to come. */ + } + if (bind(ifp->sfd, (struct sockaddr *)&nsa, sizeof nsa) < 0) { + if (errno != EADDRINUSE || ++n > 4) { + if (errno == EADDRINUSE) + ns_error(ns_log_default, + "There may be a name server already running on %s", + sin_ntoa(nsa)); + else + ns_error(ns_log_default, + "bind(sfd=%d, %s): %s", ifp->sfd, + sin_ntoa(nsa), strerror(errno)); + return (-1); + } + + /* Retry opening the socket a few times */ + close(ifp->sfd); + ifp->sfd = -1; + sleep(30); + goto again; + } + if (evListen(ev, ifp->sfd, 5/*XXX*/, stream_accept, ifp, &ifp->evID_s) + == -1) { + ns_error(ns_log_default, "evListen(sfd=%d): %s", + ifp->sfd, strerror(errno)); + return (-1); + } + ifp->flags |= INTERFACE_CONN_VALID; + return (0); +} + +/* opensocket_f() + * Open datagram socket bound to no particular interface; use for ns_forw + * and sysquery. + */ +void +opensocket_f() { + static struct sockaddr_in prev_qsrc; + static int been_here; + static interface *prev_ifp; + struct sockaddr_in nsa; + const int on = 1; + int n, need_close; + interface *ifp; + + need_close = 0; + if (been_here) { + if (prev_ifp != NULL) + prev_ifp->flags &= ~INTERFACE_FORWARDING; + else if (server_options->query_source.sin_port == htons(0) || + prev_qsrc.sin_addr.s_addr != + server_options->query_source.sin_addr.s_addr || + prev_qsrc.sin_port != + server_options->query_source.sin_port) + need_close = 1; + } else + ds = -1; + + been_here = 1; + INSIST(server_options != NULL); + + if (need_close) { + evDeselectFD(ev, ds_evID); + close(ds); + ds = -1; + } + + /* + * If we're already listening on the query_source address and port, + * we don't need to open another socket. We mark the interface, so + * we'll notice we're in trouble if it goes away. + */ + ifp = if_find(server_options->query_source.sin_addr, + server_options->query_source.sin_port); + if (ifp != NULL) { + ifp->flags |= INTERFACE_FORWARDING; + prev_ifp = ifp; + ds = ifp->dfd; + ns_info(ns_log_default, "forwarding source address is %s", + sin_ntoa(server_options->query_source)); + return; + } + + /* + * If we're already using the correct query source, we're done. + */ + if (ds >= 0) + return; + + prev_qsrc = server_options->query_source; + prev_ifp = NULL; + + if ((ds = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + ns_panic(ns_log_default, 1, "socket(SOCK_DGRAM): %s", + strerror(errno)); + if (setsockopt(ds, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof on) != 0) { + ns_notice(ns_log_default, "setsockopt(REUSEADDR): %s", + strerror(errno)); + /* XXX press on regardless, this is not too serious. */ + } + if (bind(ds, (struct sockaddr *)&server_options->query_source, + sizeof server_options->query_source) < 0) + ns_panic(ns_log_default, 1, "opensocket_f: bind(%s): %s", + sin_ntoa(server_options->query_source), + strerror(errno)); + + n = sizeof nsa; + if (getsockname(ds, (struct sockaddr *)&nsa, &n) < 0) + ns_panic(ns_log_default, 1, "opensocket_f: getsockaddr: %s", + strerror(errno)); + + ns_debug(ns_log_default, 1, "fwd ds %d addr %s", ds, sin_ntoa(nsa)); + ns_info(ns_log_default, "Forwarding source address is %s", + sin_ntoa(nsa)); + + if (evSelectFD(ev, ds, EV_READ, datagram_read, NULL, &ds_evID) == -1) + ns_panic(ns_log_default, 1, "evSelectFD(fd %d): %s", + (void *)ds, strerror(errno)); + /* XXX: should probably use a different FileFunc that only accepts + * responses, since requests on this socket make no sense. + */ +} + +static void +setdebug(int new_debug) { +#ifdef DEBUG + int old_debug; + + if (!new_debug) + ns_debug(ns_log_default, 1, "Debug off"); + old_debug = debug; + debug = new_debug; + log_option(log_ctx, LOG_OPTION_DEBUG, debug); + log_option(log_ctx, LOG_OPTION_LEVEL, debug); + evSetDebug(ev, debug, log_get_stream(eventlib_channel)); + if (debug) { + if (!old_debug) + open_special_channels(); + ns_debug(ns_log_default, 1, "Debug level %d", debug); + if (!old_debug) { + ns_debug(ns_log_default, 1, "Version = %s", Version); + ns_debug(ns_log_default, 1, "conffile = %s", conffile); + } + } +#endif +} + +static SIG_FN +onhup(int sig) { + ns_need(MAIN_NEED_RELOAD); +} + +static SIG_FN +onintr(int sig) { + ns_need(MAIN_NEED_EXIT); +} + +static SIG_FN +setdumpflg(int sig) { + ns_need(MAIN_NEED_DUMP); +} + +#ifdef DEBUG +static SIG_FN +setIncrDbgFlg(int sig) { + desired_debug++; + ns_need(MAIN_NEED_DEBUG); +} + +static SIG_FN +setNoDbgFlg(int sig) { + desired_debug = 0; + ns_need(MAIN_NEED_DEBUG); +} +#endif /*DEBUG*/ + +#if defined(QRYLOG) && defined(SIGWINCH) +static SIG_FN +setQrylogFlg(int sig) { + ns_need(MAIN_NEED_QRYLOG); +} +#endif /*QRYLOG && SIGWINCH*/ + +static SIG_FN +setstatsflg(int sig) { + ns_need(MAIN_NEED_STATSDUMP); +} + +static SIG_FN +discard_pipe(int sig) { +#ifdef SIGPIPE_ONE_SHOT + int saved_errno = errno; + set_signal_handler(SIGPIPE, discard_pipe); + errno = saved_errno; +#endif +} + +/* +** Routines for managing stream queue +*/ + +static struct qstream * +sq_add() { + struct qstream *sqp; + + if (!(sqp = (struct qstream *)memget(sizeof *sqp))) { + ns_error(ns_log_default, "sq_add: memget: %s", + strerror(errno)); + return (NULL); + } + memset(sqp, 0, sizeof *sqp); + ns_debug(ns_log_default, 3, "sq_add(%#lx)", (u_long)sqp); + + sqp->flags = 0; + /* XXX should init other fields too? */ + sqp->s_next = streamq; + streamq = sqp; + return (sqp); +} + +/* sq_remove(qp) + * remove stream queue structure `qp'. + * no current queries may refer to this stream when it is removed. + * side effects: + * memory is deallocated. sockets are closed. lists are relinked. + */ +void +sq_remove(struct qstream *qp) { + struct qstream *qsp; + + ns_debug(ns_log_default, 2, "sq_remove(%#lx, %d) rfcnt=%d", + (u_long)qp, qp->s_rfd, qp->s_refcnt); + + if (qp->s_wbuf != NULL) { + memput(qp->s_wbuf, qp->s_wbuf_end - qp->s_wbuf); + qp->s_wbuf = NULL; + } + if (qp->flags & STREAM_MALLOC) + memput(qp->s_buf, qp->s_bufsize); + if (qp->flags & STREAM_READ_EV) + INSIST_ERR(evCancelRW(ev, qp->evID_r) != -1); + if (qp->flags & STREAM_WRITE_EV) + INSIST_ERR(evDeselectFD(ev, qp->evID_w) != -1); + if (qp->flags & STREAM_CONNECT_EV) + INSIST_ERR(evCancelConn(ev, qp->evID_c) != -1); + if (qp->flags & STREAM_AXFR) + ns_freexfr(qp); + (void) close(qp->s_rfd); + if (qp == streamq) + streamq = qp->s_next; + else { + for (qsp = streamq; + qsp && (qsp->s_next != qp); + qsp = qsp->s_next) + (void)NULL; + if (qsp) + qsp->s_next = qp->s_next; + } + memput(qp, sizeof *qp); +} + +/* void + * sq_flush(allbut) + * call sq_remove() on all open streams except `allbut' + * side effects: + * global list `streamq' modified + * idiocy: + * is N^2 due to the scan inside of sq_remove() + */ +void +sq_flush(struct qstream *allbut) { + struct qstream *sp, *spnext; + + for (sp = streamq; sp != NULL; sp = spnext) { + spnext = sp->s_next; + if (sp != allbut) + sq_remove(sp); + } +} + +/* int + * sq_openw(qs, buflen) + * add a write buffer to a stream + * return: + * 0 = success + * -1 = failure (check errno) + */ +int +sq_openw(struct qstream *qs, int buflen) { +#ifdef SO_LINGER /* XXX */ + static const struct linger ll = { 1, 120 }; +#endif + + INSIST(qs->s_wbuf == NULL); + qs->s_wbuf = (u_char *)memget(buflen); + if (qs->s_wbuf == NULL) + return (-1); + qs->s_wbuf_send = qs->s_wbuf; + qs->s_wbuf_free = qs->s_wbuf; + qs->s_wbuf_end = qs->s_wbuf + buflen; +#ifdef SO_LINGER /* XXX */ + /* kernels that map pages for IO end up failing if the pipe is full + * at exit and we take away the final buffer. this is really a kernel + * bug but it's harmless on systems that are not broken, so... + */ + setsockopt(qs->s_rfd, SOL_SOCKET, SO_LINGER, (char *)&ll, sizeof ll); +#endif + return (0); +} + +/* static void + * sq_dowrite(qs) + * try to submit data to the system, remove it from our queue. + */ +static int +sq_dowrite(struct qstream *qs) { + if (qs->s_wbuf_free > qs->s_wbuf_send) { + int n = write(qs->s_rfd, qs->s_wbuf_send, + qs->s_wbuf_free - qs->s_wbuf_send); + if (n < 0) { + if (errno != EINTR && errno != EAGAIN +#if (EWOULDBLOCK != EAGAIN) + && errno != EWOULDBLOCK +#endif + ) + return (-1); + return (0); + } + qs->s_wbuf_send += n; + if (qs->s_wbuf_free > qs->s_wbuf_send) { + /* XXX: need some kind of delay here during which the + * socket will be deselected so we don't spin. + */ + n = qs->s_wbuf_free - qs->s_wbuf_send; + memmove(qs->s_wbuf, qs->s_wbuf_send, n); + qs->s_wbuf_send = qs->s_wbuf; + qs->s_wbuf_free = qs->s_wbuf + n; + } + } + if (qs->s_wbuf_free == qs->s_wbuf_send) + qs->s_wbuf_free = qs->s_wbuf_send = qs->s_wbuf; + return (0); +} + +/* void + * sq_flushw(qs) + * called when the socket becomes writable and we want to flush our + * buffers and the system's socket buffers. use as a closure with + * sq_writeh(). + */ +void +sq_flushw(struct qstream *qs) { + if (qs->s_wbuf_free == qs->s_wbuf_send) { + sq_writeh(qs, NULL); + sq_done(qs); + } +} + +/* static void + * sq_writable(ctx, uap, fd, evmask) + * glue between eventlib closures and qstream closures + */ +static void +sq_writable(evContext ctx, void *uap, int fd, int evmask) { + struct qstream *qs = uap; + + INSIST(evmask & EV_WRITE); + INSIST(fd == qs->s_rfd); + if (sq_dowrite(qs) < 0) { + sq_remove(qs); + return; + } + if (qs->s_wbuf_closure + && qs->s_wbuf_end - qs->s_wbuf_free >= HFIXEDSZ+2) /* XXX guess */ + (*qs->s_wbuf_closure)(qs); + if (sq_dowrite(qs) < 0) { + sq_remove(qs); + return; + } +} + +/* int + * sq_writeh(qs, closure) + * register a closure to be called when a stream becomes writable + * return: + * 0 = success + * -1 = failure (check errno) + */ +int +sq_writeh(struct qstream *qs, sq_closure c) { + if (c) { + if (!qs->s_wbuf_closure) { + if (evSelectFD(ev, qs->s_rfd, EV_WRITE, + sq_writable, qs, &qs->evID_w) < 0) { + return (-1); + } + qs->flags |= STREAM_WRITE_EV; + } + } else { + (void) evDeselectFD(ev, qs->evID_w); + qs->flags &= ~STREAM_WRITE_EV; + } + qs->s_wbuf_closure = c; + return (0); +} + +/* int + * sq_write(qs, buf, len) + * queue a message onto the stream, prepended by a two byte length field + * return: + * 0 = success + * -1 = failure (check errno; E2BIG means we can't handle this right now) + */ +int +sq_write(struct qstream *qs, const u_char *buf, int len) { + INSIST(qs->s_wbuf != NULL); + if (NS_INT16SZ + len > qs->s_wbuf_end - qs->s_wbuf_free) { + if (sq_dowrite(qs) < 0) + return (-1); + if (NS_INT16SZ + len > qs->s_wbuf_end - qs->s_wbuf_free) { + errno = E2BIG; + return (-1); + } + } + __putshort(len, qs->s_wbuf_free); + qs->s_wbuf_free += NS_INT16SZ; + memcpy(qs->s_wbuf_free, buf, len); + qs->s_wbuf_free += len; + return (0); +} + +/* int + * sq_here(sp) + * determine whether stream 'sp' is still on the streamq + * return: + * boolean: is it here? + */ +static int +sq_here(struct qstream *sp) { + struct qstream *t; + + for (t = streamq; t != NULL; t = t->s_next) + if (t == sp) + return (1); + return (0); +} + +/* + * Initiate query on stream; + * mark as referenced and stop selecting for input. + */ +static void +sq_query(struct qstream *sp) { + sp->s_refcnt++; +} + +/* + * Note that the current request on a stream has completed, + * and that we should continue looking for requests on the stream. + */ +void +sq_done(struct qstream *sp) { + struct iovec iov; + + if (sp->s_wbuf != NULL) { + memput(sp->s_wbuf, sp->s_wbuf_end - sp->s_wbuf); + sp->s_wbuf = NULL; + } + if (sp->flags & STREAM_AXFR) + ns_freexfr(sp); + sp->s_refcnt = 0; + sp->s_time = tt.tv_sec; + if (sp->flags & STREAM_DONE_CLOSE) { + /* XXX */ + sq_remove(sp); + return; + } + iov = evConsIovec(sp->s_temp, INT16SZ); + if (evRead(ev, sp->s_rfd, &iov, 1, stream_getlen, sp, &sp->evID_r) == + -1) + ns_panic(ns_log_default, 1, "evRead(fd %d): %s", + (void *)sp->s_rfd, strerror(errno)); + sp->flags |= STREAM_READ_EV; +} + +/* void + * dq_remove_gen(gen) + * close/deallocate all the udp sockets (except 0.0.0.0) which are + * not from the current generation. + * side effects: + * global list `iflist' is modified. + */ +void +dq_remove_gen(time_t gen) { + interface *this, *next; + + for (this = HEAD(iflist); this != NULL; this = next) { + next = NEXT(this, link); + if (this->gen != gen && ina_hlong(this->addr) != INADDR_ANY) + dq_remove(this); + } +} + +/* void + * dq_remove_all() + * close/deallocate all interfaces. + * side effects: + * global list `iflist' is modified. + */ +void +dq_remove_all() { + interface *this, *next; + + for (this = HEAD(iflist); this != NULL; this = next) { + next = NEXT(this, link); + /* + * Clear the forwarding flag so we don't panic the server. + */ + this->flags &= ~INTERFACE_FORWARDING; + dq_remove(this); + } +} + +/* void + * dq_remove(interface *this) + * close/deallocate an interface's sockets. called on errors + * or if the interface disappears. + * side effects: + * global list `iflist' is modified. + */ +static void +dq_remove(interface *this) { + ns_notice(ns_log_default, "deleting interface [%s].%u", + inet_ntoa(this->addr), ntohs(this->port)); + + if ((this->flags & INTERFACE_FORWARDING) != 0) + ns_panic(ns_log_default, 0, + "forwarding interface [%s].%u gone", + inet_ntoa(this->addr), + ntohs(this->port)); + + /* Deallocate fields. */ + if ((this->flags & INTERFACE_FILE_VALID) != 0) + (void) evDeselectFD(ev, this->evID_d); + if (this->dfd >= 0) + (void) close(this->dfd); + if ((this->flags & INTERFACE_CONN_VALID) != 0) + (void) evCancelConn(ev, this->evID_s); + if (this->sfd >= 0) + (void) close(this->sfd); + + UNLINK(iflist, this, link); + memput(this, sizeof *this); +} + +/* struct in_addr + * net_mask(ina) + * makes a classful assumption in a classless world, and returns it. + */ +struct in_addr +net_mask(struct in_addr ina) { + u_long hl = ina_hlong(ina); + struct in_addr ret; + + if (IN_CLASSA(hl)) + hl = IN_CLASSA_NET; + else if (IN_CLASSB(hl)) + hl = IN_CLASSB_NET; + else if (IN_CLASSC(hl)) + hl = IN_CLASSC_NET; + else + hl = INADDR_BROADCAST; + ina_ulong(ret) = htonl(hl); + return (ret); +} + +/* aIsUs(addr) + * scan our list of interface addresses for "addr". + * returns: + * 0: address isn't one of our interfaces + * >0: address is one of our interfaces, or INADDR_ANY + */ +int +aIsUs(struct in_addr addr) { + interface *ifp; + + if (ina_hlong(addr) == INADDR_ANY || if_find(addr, 0) != NULL) + return (1); + return (0); +} + +/* interface * + * if_find(addr, port) + * scan our list of interface addresses for "addr" and port. + * port == 0 means match any port + * returns: + * pointer to interface with this address/port, or NULL if there isn't + * one. + */ +static interface * +if_find(struct in_addr addr, u_int16_t port) { + interface *ifp; + + for (ifp = HEAD(iflist); ifp != NULL; ifp = NEXT(ifp, link)) + if (ina_equal(addr, ifp->addr)) + if (port == 0 || ifp->port == port) + break; + return (ifp); +} + +/* + * These are here in case we ever want to get more clever, like perhaps + * using a bitmap to keep track of outstanding queries and a random + * allocation scheme to make it a little harder to predict them. Note + * that the resolver will need the same protection so the cleverness + * should be put there rather than here; this is just an interface layer. + */ + +void +nsid_init() { + nsid_state = res_randomid(); +} + +u_int16_t +nsid_next() { + if (nsid_state == 65535) + nsid_state = 0; + else + nsid_state++; + return (nsid_state); +} + +static void +deallocate_everything(void) { + FILE *f; + + f = write_open(server_options->memstats_filename); + + ns_freestats(); + qflush(); + sq_flush(NULL); + free_addinfo(); + ns_shutdown(); + dq_remove_all(); + if (local_addresses != NULL) + free_ip_match_list(local_addresses); + if (local_networks != NULL) + free_ip_match_list(local_networks); + destroyservicelist(); + destroyprotolist(); + shutdown_logging(); + evDestroy(ev); + if (conffile != NULL) + freestr(conffile); + if (user_name != NULL) + freestr(user_name); + if (group_name != NULL) + freestr(group_name); + if (chroot_dir != NULL) + freestr(chroot_dir); + if (f != NULL) { + memstats(f); + (void)fclose(f); + } +} + +static void +ns_exit(void) { + ns_info(ns_log_default, "named shutting down"); +#ifdef BIND_UPDATE + dynamic_about_to_exit(); +#endif + if (server_options && server_options->pid_filename) + (void)unlink(server_options->pid_filename); + ns_logstats(ev, NULL, evNowTime(), evConsTime(0, 0)); + if (NS_OPTION_P(OPTION_DEALLOC_ON_EXIT)) + deallocate_everything(); + exit(0); +} + +static void +use_desired_debug(void) { +#ifdef DEBUG + sigset_t set; + int bad; + + /* protect against race conditions by blocking debugging signals */ + + if (sigemptyset(&set) < 0) { + ns_error(ns_log_os, + "sigemptyset failed in use_desired_debug: %s", + strerror(errno)); + return; + } + if (sigaddset(&set, SIGUSR1) < 0) { + ns_error(ns_log_os, + "sigaddset SIGUSR1 failed in use_desired_debug: %s", + strerror(errno)); + return; + } + if (sigaddset(&set, SIGUSR2) < 0) { + ns_error(ns_log_os, + "sigaddset SIGUSR2 failed in use_desired_debug: %s", + strerror(errno)); + return; + } + if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) { + ns_error(ns_log_os, + "sigprocmask to block USR1 and USR2 failed: %s", + strerror(errno)); + return; + } + setdebug(desired_debug); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) < 0) + ns_error(ns_log_os, + "sigprocmask to unblock USR1 and USR2 failed: %s", + strerror(errno)); +#endif +} + +static void +toggle_qrylog(void) { + qrylog = !qrylog; + ns_notice(ns_log_default, "query log %s\n", qrylog ?"on" :"off"); +} + +#ifdef BIND_NOTIFY +static void +do_notify_after_load(void) { + evDo(ev, (const void *)notify_after_load); +} +#endif + +/* + * This is a functional interface to the global needs and options. + */ + +static const struct need_handler { + int need; + void (*handler)(void); + } need_handlers[] = { + { MAIN_NEED_RELOAD, ns_reload }, + { MAIN_NEED_MAINT, ns_maint }, + { MAIN_NEED_ENDXFER, endxfer }, + { MAIN_NEED_ZONELOAD, loadxfer }, + { MAIN_NEED_DUMP, doadump }, + { MAIN_NEED_STATSDUMP, ns_stats }, + { MAIN_NEED_EXIT, ns_exit }, + { MAIN_NEED_QRYLOG, toggle_qrylog }, + { MAIN_NEED_DEBUG, use_desired_debug }, +#ifdef BIND_NOTIFY + { MAIN_NEED_NOTIFY, do_notify_after_load }, +#endif + { 0, NULL } + }; + +void +ns_setoption(int option) { + ns_warning(ns_log_default, "used obsolete ns_setoption(%d)", option); +} + +void +ns_need(int need) { + needs |= need; +} + +int +ns_need_p(int need) { + return ((needs & need) != 0); +} + +static void +ns_handle_needs() { + const struct need_handler *nhp; + + for (nhp = need_handlers; nhp->need && nhp->handler; nhp++) { + if ((needs & nhp->need) != 0) { + /* + * Turn off flag first, handler might turn it back on. + */ + needs &= ~nhp->need; + (*nhp->handler)(); + } + } +} + + +void +writestream(struct qstream *sp, const u_char *msg, int msglen) { + if (sq_openw(sp, msglen + INT16SZ) == -1) { + sq_remove(sp); + return; + } + if (sq_write(sp, msg, msglen) == -1) { + sq_remove(sp); + return; + } + sq_writeh(sp, sq_flushw); +} + +static void +set_signal_handler(int sig, SIG_FN (*handler)()) { + struct sigaction sa; + + memset(&sa, 0, sizeof sa); + sa.sa_handler = handler; + if (sigemptyset(&sa.sa_mask) < 0) { + ns_error(ns_log_os, + "sigemptyset failed in set_signal_handler(%d): %s", + sig, strerror(errno)); + return; + } + if (sigaction(sig, &sa, NULL) < 0) + ns_error(ns_log_os, + "sigaction failed in set_signal_handler(%d): %s", + sig, strerror(errno)); +} + +static void +init_signals() { + set_signal_handler(SIGINT, setdumpflg); + set_signal_handler(SIGILL, setstatsflg); +#ifdef DEBUG + set_signal_handler(SIGUSR1, setIncrDbgFlg); + set_signal_handler(SIGUSR2, setNoDbgFlg); +#endif + set_signal_handler(SIGHUP, onhup); +#if defined(SIGWINCH) && defined(QRYLOG) /* XXX */ + set_signal_handler(SIGWINCH, setQrylogFlg); +#endif + set_signal_handler(SIGCHLD, reapchild); + set_signal_handler(SIGPIPE, discard_pipe); + set_signal_handler(SIGTERM, onintr); +#if defined(SIGXFSZ) /* XXX */ + /* Wierd DEC Hesiodism, harmless. */ + set_signal_handler(SIGXFSZ, onhup); +#endif +} + +static int +only_digits(const char *s) { + if (*s == '\0') + return (0); + while (*s != '\0') { + if (!isdigit(*s)) + return (0); + s++; + } + return (1); +} diff --git a/contrib/bind/bin/named/ns_maint.c b/contrib/bind/bin/named/ns_maint.c new file mode 100644 index 0000000..ad6e7f8 --- /dev/null +++ b/contrib/bind/bin/named/ns_maint.c @@ -0,0 +1,1210 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)ns_maint.c 4.39 (Berkeley) 3/2/91"; +static char rcsid[] = "$Id: ns_maint.c,v 8.38 1998/03/16 19:40:25 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988 + * 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) 1996, 1997 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 "port_before.h" + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <signal.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +static int xfers_running, /* # of xfers running */ + xfers_deferred, /* # of needed xfers not run yet */ + qserials_running, + nxfers(struct zoneinfo *, int), + bottom_of_zone(struct databuf *, int); + +static void startxfer(struct zoneinfo *), + abortxfer(struct zoneinfo *), + addxfer(struct zoneinfo *), + tryxfer(void), + purge_z_2(struct hashbuf *, int); + +#define qserial_qfull() (qserials_running == MAXQSERIAL) + +static time_t stats_time; + + /* State of all running zone transfers */ +static struct { + pid_t xfer_pid; + int xfer_state; /* see below */ + WAIT_T xfer_status; +} xferstatus[MAX_XFERS_RUNNING]; + +#define XFER_IDLE 0 +#define XFER_RUNNING 1 +#define XFER_DONE 2 + + +/* + * Perform maintenance on all zones that need it. + */ +void +ns_maint() { + struct zoneinfo *zp; + int zonenum, deleted; + + gettime(&tt); + + ns_debug(ns_log_maint, 1, "ns_maint()"); + + for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++) + zone_maint(zp); + ns_debug(ns_log_maint, 1, "exit ns_maint()"); +} + +/* + * Perform routine zone maintenance. + */ +void +zone_maint(struct zoneinfo *zp) { + gettime(&tt); + + ns_debug(ns_log_maint, 1, "zone_maint('%s'); now %lu", + zp->z_origin[0] == '\0' ? "." : zp->z_origin, + (u_long)tt.tv_sec); + +#ifdef DEBUG + if (debug >= 2) + printzoneinfo((zp - zones), ns_log_maint, 2); +#endif + + switch (zp->z_type) { + + case Z_SECONDARY: + /*FALLTHROUGH*/ +#ifdef STUBS + case Z_STUB: +#endif + if (zp->z_serial != 0 && + ((zp->z_lastupdate+zp->z_expire) < (u_int32_t)tt.tv_sec)) { + zp->z_serial = 0; + } + if (zp->z_flags & (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL)) { + ns_retrytime(zp, tt.tv_sec); + break; + } + if (zp->z_flags & Z_XFER_RUNNING) { + abortxfer(zp); + /* + * Check again in 30 seconds in case the first + * abort doesn't work. + */ + if (zp->z_time != 0 && zp->z_time <= tt.tv_sec) + zp->z_time = tt.tv_sec + 30; + break; + } + qserial_query(zp); + break; + +#ifdef BIND_UPDATE + case Z_PRIMARY: + if (! (zp->z_flags & Z_DYNAMIC)) + break; + if (tt.tv_sec >= zp->z_soaincrtime && + zp->z_soaincrintvl > 0 && + zp->z_flags & Z_NEED_SOAUPDATE) { + if (incr_serial(zp) < 0) { + /* Try again later. */ + ns_error(ns_log_maint, + "error updating serial number for %s from %d", + zp->z_origin, + zp->z_serial); + zp->z_soaincrtime = 0; + (void)schedule_soa_update(zp, 0); + } + + } + if (tt.tv_sec >= zp->z_dumptime && + zp->z_dumpintvl > 0 && + zp->z_flags & Z_NEED_DUMP) { + if (zonedump(zp) < 0) { + /* Try again later. */ + ns_error(ns_log_maint, + "zone dump for '%s' failed, rescheduling", + zp->z_origin); + zp->z_dumptime = 0; + (void)schedule_dump(zp); + } + } + break; +#endif /* BIND_UPDATE */ + + default: + break; + } + + /* + * It is essential that we never try to set a timer in the past + * or for now because doing so could cause an infinite loop. + */ + INSIST(zp->z_time == 0 || zp->z_time > tt.tv_sec); + + sched_zone_maint(zp); +} + +static void +do_zone_maint(evContext ctx, void *uap, struct timespec due, + struct timespec inter) { + ztimer_info zti = uap; + struct zoneinfo *zp; + + INSIST(zti != NULL); + + ns_debug(ns_log_maint, 1, "do_zone_maint for zone %s (class %s)", + zti->name, p_class(zti->class)); + zp = find_zone(zti->name, zti->type, zti->class); + if (zp == NULL) { + ns_error(ns_log_maint, + "do_zone_maint: %s zone '%s' (class %s) is not authoritative", + zoneTypeString(zp), zti->name, + p_class(zti->class)); + return; + } + + free_zone_timerinfo(zp); + + zp->z_flags &= ~Z_TIMER_SET; + zone_maint(zp); +} + +/* + * Figure out the next maintenance time for the zone and set a timer. + */ +void +sched_zone_maint(struct zoneinfo *zp) { + time_t next_maint = (time_t)0; + char *zone_name; + ztimer_info zti; + + if (zp->z_time != 0) + next_maint = zp->z_time; +#ifdef BIND_UPDATE + if (zp->z_type == z_master && (zp->z_flags & Z_DYNAMIC)) { + if (zp->z_soaincrintvl > 0 && + (next_maint == 0 || next_maint > zp->z_soaincrtime)) + next_maint = zp->z_soaincrtime; + if (zp->z_dumpintvl > 0 && + (next_maint == 0 || next_maint > zp->z_dumptime)) + next_maint = zp->z_dumptime; + } +#endif + + if (next_maint != 0) { + if (next_maint < tt.tv_sec) + next_maint = tt.tv_sec; + + if (zp->z_flags & Z_TIMER_SET) { + if (next_maint == zp->z_nextmaint) { + ns_debug(ns_log_maint, 1, + "no schedule change for zone '%s'", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin); + return; + } + + if (evResetTimer(ev, zp->z_timer, + do_zone_maint, zp->z_timerinfo, + evConsTime(next_maint, 0), + evConsTime(0, 0)) < 0) { + ns_error(ns_log_maint, + "evChangeTimer failed in sched_zone_maint for zone '%s': %s", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin, + strerror(errno)); + return; + } + } else { + zti = (ztimer_info)memget(sizeof *zti); + if (zti == NULL) + ns_panic(ns_log_maint, 1, + "memget failed in sched_zone_maint"); + zti->name = savestr(zp->z_origin, 1); + zti->class = zp->z_class; + zti->type = zp->z_type; + if (evSetTimer(ev, do_zone_maint, zti, + evConsTime(next_maint, 0), + evConsTime(0, 0), &zp->z_timer) < 0) { + ns_error(ns_log_maint, + "evSetTimer failed in sched_zone_maint for zone '%s': %s", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin, + strerror(errno)); + return; + } + zp->z_flags |= Z_TIMER_SET; + zp->z_timerinfo = zti; + } + ns_debug(ns_log_maint, 1, + "next maintenance for zone '%s' in %lu sec", + zp->z_origin[0] == '\0' ? "." : zp->z_origin, + (u_long)(next_maint - tt.tv_sec)); + } else { + if (zp->z_flags & Z_TIMER_SET) { + free_zone_timerinfo(zp); + if (evClearTimer(ev, zp->z_timer) < 0) + ns_error(ns_log_maint, + "evClearTimer failed in sched_zone_maint for zone '%s': %s", + zp->z_origin[0] == '\0' ? "." : + zp->z_origin, + strerror(errno)); + zp->z_flags &= ~Z_TIMER_SET; + } + ns_debug(ns_log_maint, 1, + "no scheduled maintenance for zone '%s'", + zp->z_origin[0] == '\0' ? "." : zp->z_origin); + } + zp->z_nextmaint = next_maint; +} + +void +ns_cleancache(evContext ctx, void *uap, + struct timespec due, + struct timespec inter) +{ + int deleted; + + gettime(&tt); + INSIST(uap == NULL); + deleted = clean_cache(hashtab, 0); + ns_info(ns_log_maint, "Cleaned cache of %d RR%s", + deleted, (deleted==1) ? "" : "s"); +} + +/* + * Mark a zone "up to date" after named-xfer tells us this or we + * discover it through the qserial_*() logic. + * The caller is responsible for calling sched_zone_maint(zp). + */ +static void +markUpToDate(struct zoneinfo *zp) { + struct stat f_time; + + zp->z_flags &= ~Z_SYSLOGGED; + zp->z_lastupdate = tt.tv_sec; + ns_refreshtime(zp, tt.tv_sec); + /* + * Restore Z_AUTH in case expired, + * but only if there were no errors + * in the zone file. + */ + if ((zp->z_flags & Z_DB_BAD) == 0) + zp->z_flags |= Z_AUTH; + if (zp->z_source) { + struct timeval t[2]; + + t[0] = tt; + t[1] = tt; + (void) utimes(zp->z_source, t); + } + /* we use "stat" to set zp->z_ftime instead of just + setting it to tt.tv_sec in order to avoid any + possible rounding problems in utimes(). */ + if (stat(zp->z_source, &f_time) != -1) + zp->z_ftime = f_time.st_mtime; + /* XXX log if stat fails? */ +} + +void +qserial_retrytime(struct zoneinfo *zp, time_t timebase) { + zp->z_time = timebase + 5 + (rand() % 25); +} + +/* + * Query for the serial number of a zone, so that we can check to see if + * we need to transfer it. If there are too many outstanding serial + * number queries, we'll try again later. + * The caller is responsible for calling sched_zone_maint(zp). + */ +void +qserial_query(struct zoneinfo *zp) { + struct qinfo *qp; + + ns_debug(ns_log_default, 1, "qserial_query(%s)", zp->z_origin); + + if (qserial_qfull()) { + qserial_retrytime(zp, tt.tv_sec); + return; + } + + qp = sysquery(zp->z_origin, zp->z_class, T_SOA, + zp->z_addr, zp->z_addrcnt, QUERY); + if (!qp) { + ns_info(ns_log_default, "qserial_query(%s): sysquery FAILED", + zp->z_origin); + /* XXX - this is bad, we should do something */ + qserial_retrytime(zp, tt.tv_sec); + return; + } + qp->q_flags |= Q_ZSERIAL; + qp->q_zquery = zp; + zp->z_flags |= Z_QSERIAL; + zp->z_xaddr = inaddr_any; + ns_refreshtime(zp, tt.tv_sec); + qserials_running++; + ns_debug(ns_log_default, 1, "qserial_query(%s) QUEUED", zp->z_origin); +} + +void +qserial_answer(struct qinfo *qp, u_int32_t serial, struct sockaddr_in from) { + struct zoneinfo *zp = qp->q_zquery; + + ns_debug(ns_log_default, 1, "qserial_answer(%s, %u)", zp->z_origin, + serial); + zp->z_flags &= ~Z_QSERIAL; + qp->q_flags &= ~Q_ZSERIAL; /* keeps us from being called twice */ + qserials_running--; + if (serial == 0) { + /* An error occurred, or the query timed out. */ + ns_info(ns_log_default, "Err/TO getting serial# for \"%s\"", + zp->z_origin); + addxfer(zp); + } else if (SEQ_GT(serial, zp->z_serial) || !zp->z_serial) { + ns_debug(ns_log_default, 1, + "qserial_answer: zone is out of date"); + zp->z_xaddr = from.sin_addr; /* don't use qp->q_from */ + addxfer(zp); + } else if (SEQ_GT(zp->z_serial, serial)) { + if (!haveComplained((u_long)zp, (u_long)"went backward")) { + ns_notice(ns_log_default, + "Zone \"%s\" (class %d) SOA serial# (%u) rcvd from [%s] is < ours (%u)", + zp->z_origin, zp->z_class, serial, + inet_ntoa(from.sin_addr), zp->z_serial); + } + } else { + ns_debug(ns_log_default, 1, + "qserial_answer: zone serial is still OK"); + markUpToDate(zp); + sched_zone_maint(zp); + } +} + +/* + * Start an asynchronous zone transfer for a zone. + * Depends on current time being in tt. + * Caller must do sched_zone_maint(zp) after startxfer returns. + */ +static void +startxfer(struct zoneinfo *zp) { + char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME]; + int argc = 0, argc_ns = 0, pid, i; + u_int cnt; + char debug_str[10]; + char serial_str[10]; + char port_str[10]; + char class_str[10]; + char src_str[20]; + + ns_debug(ns_log_default, 1, "startxfer() %s", zp->z_origin); + + argv[argc++] = server_options->named_xfer; + argv[argc++] = "-z"; + argv[argc++] = zp->z_origin; + argv[argc++] = "-f"; + argv[argc++] = zp->z_source; + argv[argc++] = "-s"; + sprintf(serial_str, "%u", zp->z_serial); + argv[argc++] = serial_str; + if (zp->z_axfr_src.s_addr != 0) { + argv[argc++] = "-x"; + argv[argc++] = strcpy(src_str, inet_ntoa(zp->z_axfr_src)); + } + argv[argc++] = "-C"; + sprintf(class_str, "%d", zp->z_class); + argv[argc++] = class_str; + if (zp->z_flags & Z_SYSLOGGED) + argv[argc++] = "-q"; + argv[argc++] = "-P"; + sprintf(port_str, "%d", ns_port); + argv[argc++] = port_str; +#ifdef STUBS + if (zp->z_type == Z_STUB) + argv[argc++] = "-S"; +#endif +#ifdef DEBUG + if (debug) { + argv[argc++] = "-d"; + sprintf(debug_str, "%d", debug); + argv[argc++] = debug_str; + argv[argc++] = "-l"; + argv[argc++] = _PATH_XFERDDT; + if (debug > 5) { + argv[argc++] = "-t"; + argv[argc++] = _PATH_XFERTRACE; + } + } +#endif + + if (ina_hlong(zp->z_xaddr) != INADDR_ANY) { + /* + * Address was specified by the qserial logic, use it + * first. + */ + if (aIsUs(zp->z_xaddr) && + !haveComplained((u_long)zp, (u_long)startxfer)) { + ns_notice(ns_log_default, + "attempted to fetch zone %s from self (%s)", + zp->z_origin, inet_ntoa(zp->z_xaddr)); + } else + argv[argc++] = strcpy(argv_ns[argc_ns++], + inet_ntoa(zp->z_xaddr)); + } + /* + * Copy the server ip addresses into argv, after converting + * to ascii and saving the static inet_ntoa result. Skip zp->z_xaddr + * if seen. + */ + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { + struct in_addr a; + + a = zp->z_addr[cnt]; + if (ina_equal(a, zp->z_xaddr)) + continue; + if (aIsUs(a) && + !haveComplained((u_long)zp, (u_long)startxfer)) { + ns_notice(ns_log_default, + "attempted to fetch zone %s from self (%s)", + zp->z_origin, inet_ntoa(a)); + continue; + } + argv[argc++] = strcpy(argv_ns[argc_ns++], inet_ntoa(a)); + } + + argv[argc] = NULL; + +#ifdef DEBUG + if (debug >= 1) { + char buffer[1024]; + char *curr, *last; + int len; + + curr = buffer; + last = &buffer[sizeof buffer - 1]; /* leave room for \0 */ + for (i = 0; i < argc; i++) { + len = strlen(argv[i]); + if (curr + len + 1 >= last) { + ns_debug(ns_log_xfer_in, 1, + "xfer args debug printout truncated"); + break; + } + strncpy(curr, argv[i], len); + curr += len; + *curr = ' '; + curr++; + } + *curr = '\0'; + ns_debug(ns_log_xfer_in, 1, buffer); + } +#endif /* DEBUG */ + + gettime(&tt); + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == 0) { + xferstatus[i].xfer_state = XFER_RUNNING; + break; + } + } + if ((pid = vfork()) == -1) { + ns_error(ns_log_default, "xfer vfork: %s", strerror(errno)); + zp->z_time = tt.tv_sec + 10; + return; + } + + if (pid == 0) { + /* Child. */ + execv(server_options->named_xfer, argv); + ns_error(ns_log_default, "can't exec %s: %s", + server_options->named_xfer, strerror(errno)); + _exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */ + } + /* Parent. */ + xferstatus[i].xfer_pid = pid; /* XXX - small race condition here if we + * can't hold signals */ + ns_debug(ns_log_default, 1, "started xfer child %d", pid); + zp->z_flags &= ~Z_NEED_XFER; + zp->z_flags |= Z_XFER_RUNNING; + zp->z_xferpid = pid; + xfers_running++; + if (zp->z_max_transfer_time_in) + zp->z_time = tt.tv_sec + zp->z_max_transfer_time_in; + else + zp->z_time = tt.tv_sec + server_options->max_transfer_time_in; +} + +const char * +zoneTypeString(const struct zoneinfo *zp) { + static char ret[sizeof "(4294967296?)"]; /* 2^32 */ + + switch (zp->z_type) { + case Z_MASTER: return ("master"); + case Z_SLAVE: return ("slave"); +#ifdef STUBS + case Z_STUB: return ("stub"); +#endif + case Z_CACHE: return ("cache"); + default: + sprintf(ret, "(%u?)", (u_int32_t)zp->z_type); + return (ret); + } +} + +#ifdef DEBUG +void +printzoneinfo(int zonenum, int category, int level) { + struct timeval tt; + struct zoneinfo *zp = &zones[zonenum]; + + if (debug == 0) + return; + + if (!zp->z_origin) + return; + + gettime(&tt); + + ns_debug(category, level, "zone %d: %s, class %s, type %s", zonenum, + zp->z_origin[0] ? zp->z_origin : ".", + p_class(zp->z_class), zoneTypeString(zp)); + if (zp->z_source) + ns_debug(category, level, "\tsource %s", zp->z_source); + ns_debug(category, level, "\tflags %lx, serial %u, minimum %u", + (u_long)zp->z_flags, zp->z_serial, zp->z_minimum); + ns_debug(category, level, "\trefresh %u, retry %u, expire %u", + zp->z_refresh, zp->z_retry, zp->z_expire); + if (zp->z_time) + ns_debug(category, level, "\tz_time %lu (now %lu, left: %lu)", + zp->z_time, (u_long)tt.tv_sec, + (u_long)(zp->z_time - tt.tv_sec)); + else + ns_debug(category, level, "\tz_time %lu", zp->z_time); +#ifdef BIND_UPDATE + if (zp->z_type == z_master && zp->z_flags & Z_DYNAMIC) { + ns_debug(category, level, + "\tdumpintvl %lu, soaincrintvl %lu deferupdcnt %lu", + zp->z_dumpintvl, zp->z_soaincrintvl, + zp->z_deferupdcnt); + if (zp->z_soaincrtime) + ns_debug(category, level, + "\tz_soaincrtime %lu (now %lu, left: %lu)", + zp->z_soaincrtime, (u_long)tt.tv_sec, + (u_long)(zp->z_soaincrtime - tt.tv_sec)); + else + ns_debug(category, level, "\tz_soaincrtime %lu", + zp->z_soaincrtime); + if (zp->z_dumptime) + ns_debug(category, level, + "\tz_dumptime %lu (now %lu, left: %lu)", + zp->z_dumptime, (u_long)tt.tv_sec, + (u_long)(zp->z_dumptime - tt.tv_sec)); + else + ns_debug(category, level, "\tz_dumptime %lu", + zp->z_dumptime); + } +#endif +} +#endif /* DEBUG */ + +/* clean_cache(htp, all) + * Scan the entire cache looking for expired TTL's on nonauthoritative + * data, and remove it. if `all' is true, ignore TTL and rm everything. + * notes: + * this should be lazy and eventlib driven. + * return: + * number of deleted RRs. + */ +int +clean_cache(struct hashbuf *htp, int all) { + struct databuf *dp, *pdp; + struct namebuf *np, *pnp, *npn; + struct namebuf **npp, **nppend; + int deleted = 0; + + nppend = htp->h_tab + htp->h_size; + for (npp = htp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, np = *npp; np != NULL; np = npn) { + for (pdp = NULL, dp = np->n_data; dp != NULL; + (void)NULL) { + if (dp->d_zone == DB_Z_CACHE && + (stale(dp) || all)) { + dp = rm_datum(dp, np, pdp, NULL); + deleted++; + } else { + pdp = dp; + dp = dp->d_next; + } + } /*for(pdp)*/ + + if (np->n_hash) { + /* Call recursively to remove subdomains. */ + deleted += clean_cache(np->n_hash, all); + + /* If now empty, free it */ + if (np->n_hash->h_cnt == 0) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + + if (np->n_hash == NULL && np->n_data == NULL) { + npn = rm_name(np, npp, pnp); + htp->h_cnt--; + } else { + npn = np->n_next; + pnp = np; + } + } /*for(pnp)*/ + } /*for(npp)*/ + return (deleted); +} + +void +purge_zone(const char *dname, struct hashbuf *htp, int class) { + const char *fname; + struct databuf *dp, *pdp; + struct namebuf *np; + struct hashbuf *phtp = htp; + int root_zone = 0; + + ns_debug(ns_log_default, 1, "purge_zone(%s,%d)", dname, class); + if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname && + !ns_wildcard(NAME(*np))) { + for (pdp = NULL, dp = np->n_data; dp != NULL; (void)NULL) { + if (dp->d_class == class) + dp = rm_datum(dp, np, pdp, NULL); + else { + pdp = dp; + dp = dp->d_next; + } + } + + if (*dname == '\0') + root_zone = 1; + + if (np->n_hash != NULL || root_zone) { + struct hashbuf *h; + + if (root_zone) + h = htp; + else + h = np->n_hash; + + purge_z_2(h, class); + if (h->h_cnt == 0 && !root_zone) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + + /* remove entry from cache, if required */ + if (np->n_hash == NULL && np->n_data == NULL) { + struct namebuf **npp, **nppend; + struct namebuf *npn, *pnp, *nnp; + + ns_debug(ns_log_default, 3, + "purge_zone: cleaning cache"); + + /* Walk parent hashtable looking for ourself. */ + if (np->n_parent) + phtp = np->n_parent->n_hash; + else + phtp = htp; /* top / root zone */ + + if (phtp) { + nppend = phtp->h_tab + phtp->h_size; + for (npp = phtp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, nnp = *npp; + nnp != NULL; + nnp = npn) { + if (nnp == np) { + ns_debug(ns_log_default, 3, + "purge_zone: found our selves"); + npn = rm_name(nnp,npp,pnp); + phtp->h_cnt--; + } else { + npn = nnp->n_next; + pnp = nnp; + } + } + } + } + } + } +} + +static void +purge_z_2(htp, class) + struct hashbuf *htp; + int class; +{ + struct databuf *dp, *pdp; + struct namebuf *np, *pnp, *npn; + struct namebuf **npp, **nppend; + + nppend = htp->h_tab + htp->h_size; + for (npp = htp->h_tab; npp < nppend; npp++) { + for (pnp = NULL, np = *npp; np != NULL; np = npn) { + if (!bottom_of_zone(np->n_data, class)) { + for (pdp = NULL, dp = np->n_data; + dp != NULL; + (void)NULL) { + if (dp->d_class == class) + dp = rm_datum(dp, np, pdp, + NULL); + else { + pdp = dp; + dp = dp->d_next; + } + } + if (np->n_hash) { + /* call recursively to rm subdomains */ + purge_z_2(np->n_hash, class); + + /* if now empty, free it */ + if (np->n_hash->h_cnt == 0) { + rm_hash(np->n_hash); + np->n_hash = NULL; + } + } + } + + if (np->n_hash == NULL && np->n_data == NULL) { + npn = rm_name(np, npp, pnp); + htp->h_cnt--; + } else { + npn = np->n_next; + pnp = np; + } + } + } +} + +static int +bottom_of_zone(struct databuf *dp, int class) { + int ret = 0; + + for ((void)NULL; dp; dp = dp->d_next) { + if (dp->d_class != class) + continue; + if (dp->d_zone == DB_Z_CACHE) + continue; + if (dp->d_rcode) /* This should not occur. */ + continue; + if (dp->d_type != T_SOA) + continue; + ret = 1; + break; + } + ns_debug(ns_log_default, 3, "bottom_of_zone() == %d", ret); + return (ret); +} + +/* + * Handle XFER limit for a nameserver. + */ +static int +nxfers(struct zoneinfo *zp, int delta) { + struct in_addr nsa; + struct nameser *nsp; + int ret; + + if (ina_hlong(zp->z_xaddr) != INADDR_ANY) + nsa = zp->z_xaddr; /* qserial overrode address */ + else if (!zp->z_addrcnt) + return (-1); + else + nsa = zp->z_addr[0]; /* first ns holds zone's xfer limit */ + + if (!(nsp = nameserFind(nsa, NS_F_INSERT))) + return (-1); /* probably ENOMEM */ + + ret = nsp->xfers; + if (delta < 0 && -delta > ret) + return (-1); /* taking more than we have */ + + nsp->xfers += delta; + return (ret); +} + +/* + * Abort an xfer that has taken too long. + */ +static void +abortxfer(struct zoneinfo *zp) { + if (zp->z_flags & (Z_XFER_GONE|Z_XFER_ABORTED)) { + int i; + + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == zp->z_xferpid) { + xferstatus[i].xfer_pid = 0; + xferstatus[i].xfer_state = XFER_IDLE; + break; + } + } + + if (zp->z_flags & Z_XFER_GONE) + ns_warning(ns_log_default, + "zone transfer timeout for \"%s\"; pid %lu missing", + zp->z_origin, (u_long)zp->z_xferpid); + else if (kill(zp->z_xferpid, SIGKILL) == -1) + ns_warning(ns_log_default, + "zone transfer timeout for \"%s\"; kill pid %lu: %s", + zp->z_origin, (u_long)zp->z_xferpid, + strerror(errno)); + else + ns_warning(ns_log_default, +"zone transfer timeout for \"%s\"; second kill \ +pid %lu - forgetting, processes may accumulate", + zp->z_origin, (u_long)zp->z_xferpid); + + zp->z_xferpid = 0; + xfers_running--; + (void)nxfers(zp, -1); + zp->z_flags &= ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); + } else if (kill(zp->z_xferpid, SIGTERM) == -1) { + if (errno == ESRCH) + /* No warning on first time, it may have just exited */ + zp->z_flags |= Z_XFER_GONE; + else { + ns_warning(ns_log_default, + "zone transfer timeout for \"%s\"; pid %lu kill failed %s", + zp->z_origin, (u_long)zp->z_xferpid, + strerror(errno)); + zp->z_flags |= Z_XFER_ABORTED; + } + } else { + ns_notice(ns_log_default, + "zone transfer timeout for \"%s\"; pid %lu killed", + zp->z_origin, (u_long)zp->z_xferpid); + zp->z_flags |= Z_XFER_ABORTED; + } +} + +/* + * SIGCHLD signal handler: process exit of xfer's. + */ +void +reapchild(evContext ctx, void *uap, int sig) { + int pid, i; + WAIT_T status; + int saved_errno = errno; + + gettime(&tt); + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_pid == pid) { + xferstatus[i].xfer_status = status; + xferstatus[i].xfer_state = XFER_DONE; + ns_need(MAIN_NEED_ENDXFER); + break; + } + } + } + + errno = saved_errno; +} + +/* + * Finish processing of of finished xfers + */ +void +endxfer() { + struct zoneinfo *zp; + int exitstatus, pid, i; + WAIT_T status; + + gettime(&tt); + + for (i = 0; i < MAX_XFERS_RUNNING; i++) { + if (xferstatus[i].xfer_state != XFER_DONE) + continue; + pid = xferstatus[i].xfer_pid; + status = xferstatus[i].xfer_status; + exitstatus = WIFEXITED(status) ? WEXITSTATUS(status) : 0; + + for (zp = zones; zp < &zones[nzones]; zp++) { + if (zp->z_xferpid != pid) + continue; + xfers_running--; + (void) nxfers(zp, -1); + zp->z_xferpid = 0; + zp->z_flags &= + ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE); + ns_debug(ns_log_default, 1, + "\nendxfer: child %d zone %s returned status=%d termsig=%d", + pid, zp->z_origin, exitstatus, + WIFSIGNALED(status) ? WTERMSIG(status) : -1); + if (WIFSIGNALED(status)) { + if (WTERMSIG(status) != SIGKILL) { + ns_notice(ns_log_default, + "named-xfer \"%s\" exited with signal %d", + zp->z_origin[0]?zp->z_origin:".", + WTERMSIG(status)); + } + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + } else { + switch (exitstatus) { + case XFER_UPTODATE: + markUpToDate(zp); + sched_zone_maint(zp); + break; + + case XFER_SUCCESS: + /* XXX should incorporate loadxfer() */ + zp->z_flags |= Z_NEED_RELOAD; + zp->z_flags &= ~Z_SYSLOGGED; + ns_need(MAIN_NEED_ZONELOAD); + break; + + case XFER_TIMEOUT: + if (!(zp->z_flags & Z_SYSLOGGED)) { + zp->z_flags |= Z_SYSLOGGED; + ns_notice(ns_log_default, + "zoneref: Masters for secondary zone \"%s\" unreachable", + zp->z_origin); + } + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + break; + + default: + if (!(zp->z_flags & Z_SYSLOGGED)) { + zp->z_flags |= Z_SYSLOGGED; + ns_notice(ns_log_default, + "named-xfer for \"%s\" exited %d", + zp->z_origin, + exitstatus); + } + /* FALLTHROUGH */ + case XFER_FAIL: + zp->z_flags |= Z_SYSLOGGED; + ns_retrytime(zp, tt.tv_sec); + sched_zone_maint(zp); + break; + } + break; + } + } + xferstatus[i].xfer_state = XFER_IDLE; + xferstatus[i].xfer_pid = 0; + } + tryxfer(); +} + +/* + * Try to start some xfers - new "fair scheduler" by Bob Halley @DEC (1995) + */ +static void +tryxfer() { + static struct zoneinfo *zp = NULL; + static struct zoneinfo *lastzones = NULL; + static int lastnzones = 0; + struct zoneinfo *startzp, *stopzp; + + /* initialize, and watch out for changes in zones! */ + if (lastzones != zones) { + if (lastzones != NULL) + ns_debug(ns_log_default, 3, "zones changed: %p != %p", + lastzones, zones); + lastzones = zones; + zp = zones; + } + + /* did zones shrink? */ + if (lastnzones > nzones) { + ns_debug(ns_log_default, 3, "zones shrunk"); + zp = zones; + } + lastnzones = nzones; + + if (zp == zones) + stopzp = &zones[nzones-1]; + else + stopzp = zp - 1; + + ns_debug(ns_log_default, 3, + "tryxfer start zp=%p stopzp=%p def=%d running=%d", + zp, stopzp, xfers_deferred, xfers_running); + + startzp = zp; + for (;;) { + int xfers; + + if (!xfers_deferred || + xfers_running >= server_options->transfers_in) + break; + + if ((xfers = nxfers(zp, 0)) != -1 && + xfers < server_options->transfers_per_ns && + (zp->z_flags & Z_NEED_XFER)) { + nxfers(zp, 1); + xfers_deferred--; + startxfer(zp); + sched_zone_maint(zp); + } + + if (zp == stopzp) { + ns_debug(ns_log_default, 3, "tryxfer stop mark"); + zp = startzp; + break; + } + + zp++; + /* wrap around? */ + if (zp == &zones[nzones]) + zp = zones; + } + ns_debug(ns_log_default, 3, "tryxfer stop zp=%p", zp); +} + +/* + * Reload zones whose transfers have completed. + */ +void +loadxfer() { + struct zoneinfo *zp; + + gettime(&tt); + for (zp = zones; zp < &zones[nzones]; zp++) { + if (zp->z_flags & Z_NEED_RELOAD) { + ns_debug(ns_log_default, 1, "loadxfer() \"%s\"", + zp->z_origin[0] ? zp->z_origin : "."); + zp->z_flags &= ~(Z_NEED_RELOAD|Z_AUTH); +/* XXX this is bad, should be done in ns_reload() for primary changes. */ + ns_stopxfrs(zp); + purge_zone(zp->z_origin, hashtab, zp->z_class); + if (!db_load(zp->z_source, zp->z_origin, zp, NULL)) + zp->z_flags |= Z_AUTH; + if (zp->z_flags & Z_TMP_FILE) + (void) unlink(zp->z_source); + sched_zone_maint(zp); + } + } +} + +/* + * Add this zone to the set of those needing transfers. + */ +static void +addxfer(struct zoneinfo *zp) { + if (!(zp->z_flags & Z_NEED_XFER)) { + zp->z_flags |= Z_NEED_XFER; + xfers_deferred++; + tryxfer(); + } +} + +/* + * Flush and reload data base. + */ +void +ns_reload() { + ns_notice(ns_log_default, "reloading nameserver"); + + qflush(); + sq_flush(NULL); +#ifdef FORCED_RELOAD + reloading = 1; /* to force transfer if secondary and backing up */ +#endif + ns_init(conffile); + time(&resettime); +#ifdef FORCED_RELOAD + reloading = 0; +#endif /* FORCED_RELOAD */ + ns_notice(ns_log_default, "Ready to answer queries."); +} diff --git a/contrib/bind/bin/named/ns_ncache.c b/contrib/bind/bin/named/ns_ncache.c new file mode 100644 index 0000000..413ccc6 --- /dev/null +++ b/contrib/bind/bin/named/ns_ncache.c @@ -0,0 +1,226 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_ncache.c,v 8.17 1998/03/20 01:12:01 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/file.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + return; \ + } \ + } while (0) + +void +cache_n_resp(u_char *msg, int msglen, struct sockaddr_in from) { + struct databuf *dp; + HEADER *hp; + u_char *cp, *eom, *rdatap; + char dname[MAXDNAME]; + int n; + int type, class; + int Vcode; + int flags; + u_int16_t ancount; + u_int dlen; + + nameserIncr(from.sin_addr, nssRcvdNXD); + + hp = (HEADER *)msg; + cp = msg+HFIXEDSZ; + eom = msg + msglen; + + n = dn_expand(msg, eom, cp, dname, sizeof dname); + if (n < 0) { + ns_debug(ns_log_ncache, 1, + "Query expand name failed: cache_n_resp"); + hp->rcode = FORMERR; + return; + } + cp += n; + BOUNDS_CHECK(cp, 2 * INT16SZ); + GETSHORT(type, cp); + GETSHORT(class, cp); + ns_debug(ns_log_ncache, 1, "ncache: dname %s, type %d, class %d", + dname, type, class); + + ancount = ntohs(hp->ancount); + + while (ancount--) { + u_int32_t ttl; + u_int16_t atype; + u_int16_t aclass; + n = dn_skipname(cp, eom); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + cp += n; + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + GETSHORT(atype, cp); + GETSHORT(aclass, cp); + if (atype != T_CNAME || aclass != class) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + GETLONG(ttl, cp); + GETSHORT(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; + n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + cp += n; + if (cp != rdatap + dlen) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + } + +#ifdef RETURNSOA + if (hp->nscount) { + u_int32_t ttl; + u_int16_t atype; + u_char *tp = cp; + u_char *cp1; + u_char data[MAXDATA]; + size_t len = sizeof data; + + /* we store NXDOMAIN as T_SOA regardless of the query type */ + if (hp->rcode == NXDOMAIN) + type = T_SOA; + + /* store ther SOA record */ + n = dn_skipname(tp, msg + msglen); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + tp += n; + + BOUNDS_CHECK(tp, 3 * INT16SZ + INT32SZ); + GETSHORT(atype, tp); /* type */ + if (atype != T_SOA) { + ns_debug(ns_log_ncache, 3, + "ncache: type (%d) != T_SOA", atype); + goto no_soa; + } + tp += INT16SZ; /* class */ + GETLONG(ttl, tp); /* ttl */ + GETSHORT(dlen, tp); /* dlen */ + BOUNDS_CHECK(tp, dlen); + rdatap = tp; + + /* origin */ + n = dn_expand(msg, msg + msglen, tp, (char*)data, len); + if (n < 0) { + ns_debug(ns_log_ncache, 3, + "ncache: origin form error"); + return; + } + tp += n; + n = strlen((char*)data) + 1; + cp1 = data + n; + len -= n; + /* mail */ + n = dn_expand(msg, msg + msglen, tp, (char*)cp1, len); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: mail form error"); + return; + } + tp += n; + n = strlen((char*)cp1) + 1; + cp1 += n; + len -= n; + n = 5 * INT32SZ; + BOUNDS_CHECK(tp, n); + memcpy(cp1, tp, n); + /* serial, refresh, retry, expire, min */ + cp1 += n; + len -= n; + tp += n; + if (tp != rdatap + dlen) { + ns_debug(ns_log_ncache, 3, "ncache: form error"); + return; + } + /* store the zone of the soa record */ + n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len); + if (n < 0) { + ns_debug(ns_log_ncache, 3, "ncache: form error 2"); + return; + } + n = strlen((char*)cp1) + 1; + cp1 += n; + + dp = savedata(class, type, MIN(ttl, NTTL) + tt.tv_sec, data, + cp1 - data); + } else { + no_soa: +#endif + dp = savedata(class, type, NTTL + tt.tv_sec, NULL, 0); +#ifdef RETURNSOA + } +#endif + dp->d_zone = DB_Z_CACHE; + dp->d_cred = hp->aa ? DB_C_AUTH : DB_C_ANSWER; + dp->d_clev = 0; + if(hp->rcode == NXDOMAIN) { + dp->d_rcode = NXDOMAIN; + flags = DB_NODATA|DB_NOTAUTH|DB_NOHINTS; + } else { + dp->d_rcode = NOERROR_NODATA; + flags = DB_NOTAUTH|DB_NOHINTS; + } + + if ((n = db_update(dname, dp, dp, NULL, flags, hashtab, from)) != OK) { + ns_debug(ns_log_ncache, 1, + "db_update failed (%d), cache_n_resp()", n); + db_freedata(dp); + return; + } + ns_debug(ns_log_ncache, 4, + "ncache succeeded: [%s %s %s] rcode:%d ttl:%ld", + dname, p_type(type), p_class(class), + dp->d_rcode, (long)(dp->d_ttl - tt.tv_sec)); +} diff --git a/contrib/bind/bin/named/ns_parser.c b/contrib/bind/bin/named/ns_parser.c new file mode 100644 index 0000000..47944ea --- /dev/null +++ b/contrib/bind/bin/named/ns_parser.c @@ -0,0 +1,2376 @@ +#ifndef lint +static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93 (BSDI)"; +#endif +#include <stdlib.h> +#define YYBYACC 1 +#define YYMAJOR 1 +#define YYMINOR 9 +#define YYEMPTY (-1) +#define YYLEX yylex() +#define yyclearin (yychar=YYEMPTY) +#define yyerrok (yyerrflag=0) +#define YYRECOVERING (yyerrflag!=0) +#define YYPREFIX "yy" +#line 2 "ns_parser.y" +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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. + */ + +/* Global C stuff goes here. */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" +#include "ns_parseutil.h" +#include "ns_lexer.h" + +#define SYM_ZONE 0x010000 +#define SYM_SERVER 0x020000 +#define SYM_KEY 0x030000 +#define SYM_ACL 0x040000 +#define SYM_CHANNEL 0x050000 +#define SYM_PORT 0x060000 + +#define SYMBOL_TABLE_SIZE 29989 /* should always be prime */ +static symbol_table symtab; + +#define AUTH_TABLE_SIZE 397 /* should always be prime */ +static symbol_table authtab = NULL; + +static zone_config current_zone; +static int seen_zone; + +static options current_options; +static int seen_options; + +static topology_config current_topology; +static int seen_topology; + +static server_config current_server; +static int seen_server; + +static char *current_algorithm; +static char *current_secret; + +static log_config current_logging; +static int current_category; +static int chan_type; +static int chan_level; +static u_int chan_flags; +static int chan_facility; +static char *chan_name; +static int chan_versions; +static u_long chan_max_size; + +static log_channel lookup_channel(char *); +static void define_channel(char *, log_channel); +static char *canonical_name(char *); + +int yyparse(); + +#line 96 "ns_parser.y" +typedef union { + char * cp; + int s_int; + long num; + u_long ul_int; + u_int16_t us_int; + struct in_addr ip_addr; + ip_match_element ime; + ip_match_list iml; + key_info keyi; + enum axfr_format axfr_fmt; +} YYSTYPE; +#line 121 "y.tab.c" +#define L_EOS 257 +#define L_IPADDR 258 +#define L_NUMBER 259 +#define L_STRING 260 +#define L_QSTRING 261 +#define L_END_INCLUDE 262 +#define T_INCLUDE 263 +#define T_OPTIONS 264 +#define T_DIRECTORY 265 +#define T_PIDFILE 266 +#define T_NAMED_XFER 267 +#define T_DUMP_FILE 268 +#define T_STATS_FILE 269 +#define T_MEMSTATS_FILE 270 +#define T_FAKE_IQUERY 271 +#define T_RECURSION 272 +#define T_FETCH_GLUE 273 +#define T_QUERY_SOURCE 274 +#define T_LISTEN_ON 275 +#define T_PORT 276 +#define T_ADDRESS 277 +#define T_DATASIZE 278 +#define T_STACKSIZE 279 +#define T_CORESIZE 280 +#define T_DEFAULT 281 +#define T_UNLIMITED 282 +#define T_FILES 283 +#define T_HOSTSTATS 284 +#define T_DEALLOC_ON_EXIT 285 +#define T_TRANSFERS_IN 286 +#define T_TRANSFERS_OUT 287 +#define T_TRANSFERS_PER_NS 288 +#define T_TRANSFER_FORMAT 289 +#define T_MAX_TRANSFER_TIME_IN 290 +#define T_ONE_ANSWER 291 +#define T_MANY_ANSWERS 292 +#define T_NOTIFY 293 +#define T_AUTH_NXDOMAIN 294 +#define T_MULTIPLE_CNAMES 295 +#define T_CLEAN_INTERVAL 296 +#define T_INTERFACE_INTERVAL 297 +#define T_STATS_INTERVAL 298 +#define T_LOGGING 299 +#define T_CATEGORY 300 +#define T_CHANNEL 301 +#define T_SEVERITY 302 +#define T_DYNAMIC 303 +#define T_FILE 304 +#define T_VERSIONS 305 +#define T_SIZE 306 +#define T_SYSLOG 307 +#define T_DEBUG 308 +#define T_NULL_OUTPUT 309 +#define T_PRINT_TIME 310 +#define T_PRINT_CATEGORY 311 +#define T_PRINT_SEVERITY 312 +#define T_TOPOLOGY 313 +#define T_SERVER 314 +#define T_LONG_AXFR 315 +#define T_BOGUS 316 +#define T_TRANSFERS 317 +#define T_KEYS 318 +#define T_ZONE 319 +#define T_IN 320 +#define T_CHAOS 321 +#define T_HESIOD 322 +#define T_TYPE 323 +#define T_MASTER 324 +#define T_SLAVE 325 +#define T_STUB 326 +#define T_RESPONSE 327 +#define T_HINT 328 +#define T_MASTERS 329 +#define T_TRANSFER_SOURCE 330 +#define T_ALSO_NOTIFY 331 +#define T_ACL 332 +#define T_ALLOW_UPDATE 333 +#define T_ALLOW_QUERY 334 +#define T_ALLOW_TRANSFER 335 +#define T_SEC_KEY 336 +#define T_ALGID 337 +#define T_SECRET 338 +#define T_CHECK_NAMES 339 +#define T_WARN 340 +#define T_FAIL 341 +#define T_IGNORE 342 +#define T_FORWARD 343 +#define T_FORWARDERS 344 +#define T_ONLY 345 +#define T_FIRST 346 +#define T_IF_NO_ANSWER 347 +#define T_IF_NO_DOMAIN 348 +#define T_YES 349 +#define T_TRUE 350 +#define T_NO 351 +#define T_FALSE 352 +#define YYERRCODE 256 +short yylhs[] = { -1, + 0, 25, 25, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 27, 34, 28, 35, 35, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 38, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 5, 5, 4, 4, 3, 3, 43, 44, 40, 40, + 40, 40, 2, 2, 23, 23, 23, 23, 23, 21, + 21, 21, 22, 22, 22, 37, 37, 37, 37, 41, + 41, 41, 41, 20, 20, 20, 20, 42, 42, 42, + 39, 39, 45, 45, 46, 47, 29, 48, 48, 48, + 50, 49, 52, 49, 54, 54, 54, 54, 55, 55, + 56, 57, 57, 57, 57, 57, 58, 9, 9, 10, + 10, 59, 60, 60, 60, 60, 60, 60, 60, 53, + 53, 53, 8, 8, 61, 51, 51, 51, 7, 7, + 7, 6, 62, 30, 63, 63, 64, 64, 64, 64, + 64, 14, 14, 12, 12, 11, 11, 11, 11, 11, + 13, 17, 66, 65, 65, 65, 67, 33, 68, 68, + 68, 18, 19, 32, 70, 31, 69, 69, 15, 15, + 16, 16, 16, 16, 71, 71, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, + 75, 74, 74, 76, 76, 77, 1, 24, 24, +}; +short yylen[] = { 2, + 1, 1, 2, 1, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 3, 0, 5, 2, 3, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 5, 2, 0, 5, 2, 4, + 4, 4, 1, 1, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, + 2, 2, 0, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, + 0, 1, 2, 3, 1, 0, 5, 2, 3, 1, + 0, 6, 0, 6, 1, 1, 2, 1, 2, 2, + 2, 0, 1, 1, 2, 2, 3, 1, 1, 0, + 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, + 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, + 1, 1, 0, 6, 2, 3, 2, 2, 2, 4, + 1, 2, 3, 1, 2, 1, 3, 3, 1, 3, + 1, 1, 1, 2, 3, 1, 0, 6, 2, 2, + 1, 3, 3, 5, 0, 5, 0, 3, 0, 1, + 1, 1, 1, 1, 2, 3, 2, 2, 4, 2, + 2, 4, 4, 4, 2, 2, 4, 1, 2, 3, + 1, 0, 1, 2, 3, 1, 1, 1, 1, +}; +short yydefred[] = { 0, + 0, 11, 0, 15, 96, 0, 0, 0, 167, 0, + 0, 2, 4, 0, 0, 0, 0, 0, 0, 12, + 13, 0, 0, 0, 143, 0, 208, 209, 0, 0, + 3, 5, 6, 7, 8, 9, 10, 14, 0, 0, + 0, 175, 180, 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, 0, 37, + 0, 0, 43, 44, 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 154, 0, 159, 0, 161, + 0, 20, 22, 21, 25, 23, 24, 69, 65, 66, + 67, 68, 26, 27, 28, 0, 0, 39, 0, 0, + 0, 0, 85, 86, 87, 80, 84, 81, 82, 83, + 30, 31, 88, 89, 90, 51, 52, 45, 46, 29, + 32, 33, 47, 48, 49, 0, 0, 0, 70, 71, + 72, 0, 76, 77, 78, 79, 36, 0, 16, 0, + 17, 140, 141, 101, 142, 139, 134, 103, 133, 97, + 0, 98, 151, 0, 0, 0, 0, 0, 0, 0, + 176, 0, 0, 0, 155, 152, 174, 0, 171, 0, + 0, 0, 0, 0, 207, 56, 55, 58, 53, 54, + 57, 61, 62, 64, 0, 0, 0, 0, 73, 74, + 75, 34, 0, 18, 0, 0, 99, 149, 147, 148, + 0, 144, 0, 145, 198, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 157, 158, + 160, 153, 0, 0, 169, 170, 168, 0, 42, 40, + 41, 95, 0, 0, 0, 0, 0, 166, 163, 162, + 0, 0, 146, 195, 196, 188, 181, 182, 184, 183, + 187, 0, 190, 0, 0, 0, 0, 191, 178, 0, + 185, 172, 173, 35, 38, 0, 93, 138, 135, 0, + 0, 132, 0, 0, 0, 125, 0, 0, 0, 0, + 123, 124, 0, 150, 0, 164, 201, 0, 0, 206, + 0, 0, 0, 0, 0, 0, 186, 94, 102, 0, + 136, 108, 0, 105, 126, 0, 119, 121, 122, 118, + 127, 128, 129, 104, 0, 130, 165, 189, 0, 199, + 197, 0, 204, 192, 193, 194, 137, 107, 0, 0, + 0, 0, 117, 131, 200, 205, 109, 110, 111, 115, + 116, +}; +short yydgoto[] = { 10, + 197, 122, 198, 201, 138, 164, 165, 289, 328, 329, + 96, 97, 98, 99, 42, 271, 259, 192, 193, 126, + 152, 212, 113, 100, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 23, 81, 82, 157, 158, 253, 118, + 83, 84, 119, 120, 254, 255, 24, 88, 89, 215, + 290, 216, 300, 325, 351, 352, 353, 301, 302, 303, + 291, 41, 178, 179, 261, 262, 30, 194, 181, 91, + 237, 238, 308, 311, 309, 312, 313, +}; +short yysindex[] = { 122, + -200, 0, -238, 0, 0, -227, -228, -188, 0, 0, + 122, 0, 0, -220, -176, -164, -158, -155, -149, 0, + 0, -147, -88, -4, 0, -188, 0, 0, 4, -188, + 0, 0, 0, 0, 0, 0, 0, 0, 79, -240, + 11, 0, 0, 16, 20, 0, -218, -60, -40, -34, + -24, -14, -53, -53, -53, -193, -95, -190, -190, -190, + -190, -53, -53, -98, -56, -41, -162, -31, -53, -53, + -53, 6, 19, 22, 102, 161, 163, -204, -57, 0, + -120, 36, 0, 0, 0, -73, -205, -115, 38, -241, + 177, 257, 258, 16, -69, 0, 49, 0, -29, 0, + -226, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -33, -36, 0, 31, 32, + 51, 185, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 16, 16, 16, 0, 0, + 0, -277, 0, 0, 0, 0, 0, 188, 0, 55, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 57, 0, 0, -162, -53, 56, 193, -118, 60, 104, + 0, 59, 63, -25, 0, 0, 0, 69, 0, -188, + -188, -11, -7, 203, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 16, -20, -16, -9, 0, 0, + 0, 0, 73, 0, 209, 210, 0, 0, 0, 0, + -143, 0, 77, 0, 0, 78, -53, 75, -184, 215, + -36, 216, 217, 218, 232, -277, -10, 99, 0, 0, + 0, 0, 113, 114, 0, 0, 0, -1, 0, 0, + 0, 0, 236, 73, 123, -214, -222, 0, 0, 0, + -81, 124, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 121, 0, 125, 16, 16, 16, 0, 0, 130, + 0, 0, 0, 0, 0, 131, 0, 0, 0, -104, + 132, 0, -202, 129, -221, 0, -53, -53, -53, -100, + 0, 0, 134, 0, 136, 0, 0, -96, 138, 0, + 271, 125, 141, 3, 8, 12, 0, 0, 0, 142, + 0, 0, 143, 0, 0, -89, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 0, 0, 0, 146, 0, + 0, 147, 0, 0, 0, 0, 0, 0, -185, -190, + 76, 100, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; +short yyrindex[] = { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -85, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 149, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 284, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 155, 158, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 159, 160, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 294, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 295, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 299, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 301, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 171, 0, 0, 172, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 173, 174, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; +short yygindex[] = { 0, + 311, 0, 0, 211, 266, 0, 0, 357, 0, 0, + 350, 95, 0, -80, 0, 0, 0, 253, 255, -58, + 0, 212, -43, -8, 0, 438, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 369, 0, 0, 0, 0, + 0, 0, 331, 333, 0, 199, 0, 0, 367, 0, + 0, 0, 0, 0, 105, 108, 0, 0, 0, 156, + 170, 0, 0, 283, 0, 201, 0, 0, 0, 0, + 0, 226, 0, 0, 157, 0, 152, +}; +#define YYTABLESIZE 465 +short yytable[] = { 29, + 128, 129, 130, 95, 159, 200, 222, 95, 196, 170, + 114, 115, 95, 184, 173, 85, 95, 43, 131, 132, + 319, 45, 22, 95, 334, 140, 141, 142, 338, 189, + 25, 95, 26, 292, 39, 95, 32, 179, 27, 28, + 95, 288, 102, 304, 95, 27, 28, 174, 95, 127, + 127, 127, 127, 94, 27, 28, 20, 27, 28, 86, + 87, 21, 209, 210, 211, 206, 207, 208, 123, 27, + 28, 27, 28, 357, 175, 176, 177, 166, 169, 293, + 33, 294, 116, 117, 295, 327, 296, 297, 298, 299, + 124, 125, 34, 94, 167, 187, 358, 94, 35, 241, + 322, 36, 94, 167, 249, 323, 94, 37, 250, 38, + 190, 191, 258, 94, 279, 251, 27, 28, 40, 149, + 150, 94, 151, 284, 248, 94, 44, 344, 136, 137, + 94, 219, 345, 90, 94, 46, 346, 173, 94, 267, + 268, 269, 101, 270, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 27, 28, 58, 59, 60, + 133, 307, 61, 62, 63, 64, 65, 66, 67, 68, + 174, 179, 69, 70, 71, 72, 73, 74, 27, 28, + 121, 243, 244, 265, 86, 87, 27, 28, 92, 93, + 27, 28, 75, 188, 314, 315, 316, 175, 176, 177, + 103, 293, 134, 294, 167, 108, 295, 162, 296, 297, + 298, 299, 260, 76, 77, 349, 350, 135, 78, 163, + 104, 199, 79, 80, 146, 195, 105, 139, 92, 93, + 27, 28, 92, 93, 27, 28, 106, 92, 93, 27, + 28, 92, 93, 27, 28, 225, 107, 169, 92, 93, + 27, 28, 260, 331, 332, 333, 92, 93, 27, 28, + 92, 93, 27, 28, 143, 92, 93, 27, 28, 92, + 93, 27, 28, 92, 93, 27, 28, 144, 188, 226, + 145, 169, 227, 147, 324, 148, 330, 153, 154, 155, + 156, 359, 161, 228, 172, 109, 110, 111, 112, 180, + 188, 188, 188, 182, 183, 186, 116, 205, 117, 195, + 213, 214, 229, 217, 220, 221, 224, 239, 230, 231, + 232, 240, 233, 234, 235, 242, 191, 247, 236, 190, + 252, 256, 257, 263, 46, 266, 264, 272, 274, 275, + 276, 127, 188, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 277, 281, 58, 59, 60, 225, + 285, 61, 62, 63, 64, 65, 66, 67, 68, 282, + 283, 69, 70, 71, 72, 73, 74, 1, 307, 287, + 306, 350, 310, 2, 3, 4, 317, 318, 321, 326, + 336, 75, 337, 226, 340, 341, 227, 343, 347, 1, + 354, 348, 355, 356, 349, 19, 63, 228, 188, 188, + 188, 177, 76, 77, 156, 59, 60, 78, 91, 92, + 5, 79, 80, 202, 120, 203, 229, 106, 112, 113, + 114, 204, 230, 231, 232, 6, 233, 234, 235, 218, + 7, 273, 236, 168, 185, 246, 245, 278, 31, 160, + 203, 202, 286, 8, 171, 335, 361, 9, 360, 320, + 223, 305, 280, 342, 339, +}; +short yycheck[] = { 8, + 59, 60, 61, 33, 125, 42, 125, 33, 42, 125, + 54, 55, 33, 94, 256, 256, 33, 26, 62, 63, + 125, 30, 261, 33, 125, 69, 70, 71, 125, 256, + 258, 33, 261, 256, 123, 33, 257, 123, 260, 261, + 33, 256, 261, 125, 33, 260, 261, 289, 33, 58, + 59, 60, 61, 123, 260, 261, 257, 260, 261, 300, + 301, 262, 340, 341, 342, 146, 147, 148, 259, 260, + 261, 260, 261, 259, 316, 317, 318, 86, 87, 302, + 257, 304, 276, 277, 307, 307, 309, 310, 311, 312, + 281, 282, 257, 123, 309, 125, 282, 123, 257, 125, + 303, 257, 123, 309, 125, 308, 123, 257, 125, 257, + 337, 338, 256, 123, 125, 125, 260, 261, 123, 324, + 325, 123, 327, 125, 205, 123, 123, 125, 291, 292, + 123, 175, 125, 123, 123, 256, 125, 256, 123, 324, + 325, 326, 123, 328, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 260, 261, 278, 279, 280, + 259, 258, 283, 284, 285, 286, 287, 288, 289, 290, + 289, 257, 293, 294, 295, 296, 297, 298, 260, 261, + 276, 190, 191, 227, 300, 301, 260, 261, 258, 259, + 260, 261, 313, 99, 275, 276, 277, 316, 317, 318, + 261, 302, 259, 304, 309, 259, 307, 281, 309, 310, + 311, 312, 221, 334, 335, 305, 306, 259, 339, 293, + 261, 258, 343, 344, 123, 259, 261, 259, 258, 259, + 260, 261, 258, 259, 260, 261, 261, 258, 259, 260, + 261, 258, 259, 260, 261, 256, 261, 256, 258, 259, + 260, 261, 261, 297, 298, 299, 258, 259, 260, 261, + 258, 259, 260, 261, 259, 258, 259, 260, 261, 258, + 259, 260, 261, 258, 259, 260, 261, 259, 184, 290, + 259, 290, 293, 123, 293, 123, 295, 345, 346, 347, + 348, 350, 257, 304, 257, 349, 350, 351, 352, 123, + 206, 207, 208, 47, 47, 257, 276, 123, 277, 259, + 123, 257, 323, 257, 259, 123, 257, 259, 329, 330, + 331, 259, 333, 334, 335, 257, 338, 125, 339, 337, + 258, 123, 123, 257, 256, 261, 259, 123, 123, 123, + 123, 350, 248, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 123, 257, 278, 279, 280, 256, + 125, 283, 284, 285, 286, 287, 288, 289, 290, 257, + 257, 293, 294, 295, 296, 297, 298, 256, 258, 257, + 257, 306, 258, 262, 263, 264, 257, 257, 257, 261, + 257, 313, 257, 290, 257, 125, 293, 257, 257, 0, + 257, 259, 257, 257, 305, 257, 123, 304, 314, 315, + 316, 257, 334, 335, 257, 257, 257, 339, 125, 125, + 299, 343, 344, 125, 257, 125, 323, 257, 257, 257, + 257, 121, 329, 330, 331, 314, 333, 334, 335, 174, + 319, 231, 339, 87, 95, 193, 192, 236, 11, 81, + 120, 119, 254, 332, 88, 300, 352, 336, 351, 290, + 178, 261, 237, 312, 308, +}; +#define YYFINAL 10 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 352 +#if YYDEBUG +char *yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +"'!'",0,0,0,0,0,0,0,0,"'*'",0,0,0,0,"'/'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"L_EOS", +"L_IPADDR","L_NUMBER","L_STRING","L_QSTRING","L_END_INCLUDE","T_INCLUDE", +"T_OPTIONS","T_DIRECTORY","T_PIDFILE","T_NAMED_XFER","T_DUMP_FILE", +"T_STATS_FILE","T_MEMSTATS_FILE","T_FAKE_IQUERY","T_RECURSION","T_FETCH_GLUE", +"T_QUERY_SOURCE","T_LISTEN_ON","T_PORT","T_ADDRESS","T_DATASIZE","T_STACKSIZE", +"T_CORESIZE","T_DEFAULT","T_UNLIMITED","T_FILES","T_HOSTSTATS", +"T_DEALLOC_ON_EXIT","T_TRANSFERS_IN","T_TRANSFERS_OUT","T_TRANSFERS_PER_NS", +"T_TRANSFER_FORMAT","T_MAX_TRANSFER_TIME_IN","T_ONE_ANSWER","T_MANY_ANSWERS", +"T_NOTIFY","T_AUTH_NXDOMAIN","T_MULTIPLE_CNAMES","T_CLEAN_INTERVAL", +"T_INTERFACE_INTERVAL","T_STATS_INTERVAL","T_LOGGING","T_CATEGORY","T_CHANNEL", +"T_SEVERITY","T_DYNAMIC","T_FILE","T_VERSIONS","T_SIZE","T_SYSLOG","T_DEBUG", +"T_NULL_OUTPUT","T_PRINT_TIME","T_PRINT_CATEGORY","T_PRINT_SEVERITY", +"T_TOPOLOGY","T_SERVER","T_LONG_AXFR","T_BOGUS","T_TRANSFERS","T_KEYS","T_ZONE", +"T_IN","T_CHAOS","T_HESIOD","T_TYPE","T_MASTER","T_SLAVE","T_STUB","T_RESPONSE", +"T_HINT","T_MASTERS","T_TRANSFER_SOURCE","T_ALSO_NOTIFY","T_ACL", +"T_ALLOW_UPDATE","T_ALLOW_QUERY","T_ALLOW_TRANSFER","T_SEC_KEY","T_ALGID", +"T_SECRET","T_CHECK_NAMES","T_WARN","T_FAIL","T_IGNORE","T_FORWARD", +"T_FORWARDERS","T_ONLY","T_FIRST","T_IF_NO_ANSWER","T_IF_NO_DOMAIN","T_YES", +"T_TRUE","T_NO","T_FALSE", +}; +char *yyrule[] = { +"$accept : config_file", +"config_file : statement_list", +"statement_list : statement", +"statement_list : statement_list statement", +"statement : include_stmt", +"statement : options_stmt L_EOS", +"statement : logging_stmt L_EOS", +"statement : server_stmt L_EOS", +"statement : zone_stmt L_EOS", +"statement : acl_stmt L_EOS", +"statement : key_stmt L_EOS", +"statement : L_END_INCLUDE", +"statement : error L_EOS", +"statement : error L_END_INCLUDE", +"include_stmt : T_INCLUDE L_QSTRING L_EOS", +"$$1 :", +"options_stmt : T_OPTIONS $$1 '{' options '}'", +"options : option L_EOS", +"options : options option L_EOS", +"option :", +"option : T_DIRECTORY L_QSTRING", +"option : T_NAMED_XFER L_QSTRING", +"option : T_PIDFILE L_QSTRING", +"option : T_STATS_FILE L_QSTRING", +"option : T_MEMSTATS_FILE L_QSTRING", +"option : T_DUMP_FILE L_QSTRING", +"option : T_FAKE_IQUERY yea_or_nay", +"option : T_RECURSION yea_or_nay", +"option : T_FETCH_GLUE yea_or_nay", +"option : T_NOTIFY yea_or_nay", +"option : T_HOSTSTATS yea_or_nay", +"option : T_DEALLOC_ON_EXIT yea_or_nay", +"option : T_AUTH_NXDOMAIN yea_or_nay", +"option : T_MULTIPLE_CNAMES yea_or_nay", +"option : T_CHECK_NAMES check_names_type check_names_opt", +"option : T_LISTEN_ON maybe_port '{' address_match_list '}'", +"option : T_FORWARD forward_opt", +"$$2 :", +"option : T_FORWARDERS $$2 '{' opt_forwarders_list '}'", +"option : T_QUERY_SOURCE query_source", +"option : T_ALLOW_QUERY '{' address_match_list '}'", +"option : T_ALLOW_TRANSFER '{' address_match_list '}'", +"option : T_TOPOLOGY '{' address_match_list '}'", +"option : size_clause", +"option : transfer_clause", +"option : T_TRANSFER_FORMAT transfer_format", +"option : T_MAX_TRANSFER_TIME_IN L_NUMBER", +"option : T_CLEAN_INTERVAL L_NUMBER", +"option : T_INTERFACE_INTERVAL L_NUMBER", +"option : T_STATS_INTERVAL L_NUMBER", +"option : error", +"transfer_format : T_ONE_ANSWER", +"transfer_format : T_MANY_ANSWERS", +"maybe_wild_addr : L_IPADDR", +"maybe_wild_addr : '*'", +"maybe_wild_port : in_port", +"maybe_wild_port : '*'", +"query_source_address : T_ADDRESS maybe_wild_addr", +"query_source_port : T_PORT maybe_wild_port", +"query_source : query_source_address", +"query_source : query_source_port", +"query_source : query_source_address query_source_port", +"query_source : query_source_port query_source_address", +"maybe_port :", +"maybe_port : T_PORT in_port", +"yea_or_nay : T_YES", +"yea_or_nay : T_TRUE", +"yea_or_nay : T_NO", +"yea_or_nay : T_FALSE", +"yea_or_nay : L_NUMBER", +"check_names_type : T_MASTER", +"check_names_type : T_SLAVE", +"check_names_type : T_RESPONSE", +"check_names_opt : T_WARN", +"check_names_opt : T_FAIL", +"check_names_opt : T_IGNORE", +"forward_opt : T_ONLY", +"forward_opt : T_FIRST", +"forward_opt : T_IF_NO_ANSWER", +"forward_opt : T_IF_NO_DOMAIN", +"size_clause : T_DATASIZE size_spec", +"size_clause : T_STACKSIZE size_spec", +"size_clause : T_CORESIZE size_spec", +"size_clause : T_FILES size_spec", +"size_spec : any_string", +"size_spec : L_NUMBER", +"size_spec : T_DEFAULT", +"size_spec : T_UNLIMITED", +"transfer_clause : T_TRANSFERS_IN L_NUMBER", +"transfer_clause : T_TRANSFERS_OUT L_NUMBER", +"transfer_clause : T_TRANSFERS_PER_NS L_NUMBER", +"opt_forwarders_list :", +"opt_forwarders_list : forwarders_in_addr_list", +"forwarders_in_addr_list : forwarders_in_addr L_EOS", +"forwarders_in_addr_list : forwarders_in_addr_list forwarders_in_addr L_EOS", +"forwarders_in_addr : L_IPADDR", +"$$3 :", +"logging_stmt : T_LOGGING $$3 '{' logging_opts_list '}'", +"logging_opts_list : logging_opt L_EOS", +"logging_opts_list : logging_opts_list logging_opt L_EOS", +"logging_opts_list : error", +"$$4 :", +"logging_opt : T_CATEGORY category $$4 '{' channel_list '}'", +"$$5 :", +"logging_opt : T_CHANNEL channel_name $$5 '{' channel_opt_list '}'", +"channel_severity : any_string", +"channel_severity : T_DEBUG", +"channel_severity : T_DEBUG L_NUMBER", +"channel_severity : T_DYNAMIC", +"version_modifier : T_VERSIONS L_NUMBER", +"version_modifier : T_VERSIONS T_UNLIMITED", +"size_modifier : T_SIZE size_spec", +"maybe_file_modifiers :", +"maybe_file_modifiers : version_modifier", +"maybe_file_modifiers : size_modifier", +"maybe_file_modifiers : version_modifier size_modifier", +"maybe_file_modifiers : size_modifier version_modifier", +"channel_file : T_FILE L_QSTRING maybe_file_modifiers", +"facility_name : any_string", +"facility_name : T_SYSLOG", +"maybe_syslog_facility :", +"maybe_syslog_facility : facility_name", +"channel_syslog : T_SYSLOG maybe_syslog_facility", +"channel_opt : channel_file", +"channel_opt : channel_syslog", +"channel_opt : T_NULL_OUTPUT", +"channel_opt : T_SEVERITY channel_severity", +"channel_opt : T_PRINT_TIME yea_or_nay", +"channel_opt : T_PRINT_CATEGORY yea_or_nay", +"channel_opt : T_PRINT_SEVERITY yea_or_nay", +"channel_opt_list : channel_opt L_EOS", +"channel_opt_list : channel_opt_list channel_opt L_EOS", +"channel_opt_list : error", +"channel_name : any_string", +"channel_name : T_NULL_OUTPUT", +"channel : channel_name", +"channel_list : channel L_EOS", +"channel_list : channel_list channel L_EOS", +"channel_list : error", +"category_name : any_string", +"category_name : T_DEFAULT", +"category_name : T_NOTIFY", +"category : category_name", +"$$6 :", +"server_stmt : T_SERVER L_IPADDR $$6 '{' server_info_list '}'", +"server_info_list : server_info L_EOS", +"server_info_list : server_info_list server_info L_EOS", +"server_info : T_BOGUS yea_or_nay", +"server_info : T_TRANSFERS L_NUMBER", +"server_info : T_TRANSFER_FORMAT transfer_format", +"server_info : T_KEYS '{' key_list '}'", +"server_info : error", +"address_match_list : address_match_element L_EOS", +"address_match_list : address_match_list address_match_element L_EOS", +"address_match_element : address_match_simple", +"address_match_element : '!' address_match_simple", +"address_match_simple : L_IPADDR", +"address_match_simple : L_IPADDR '/' L_NUMBER", +"address_match_simple : L_NUMBER '/' L_NUMBER", +"address_match_simple : address_name", +"address_match_simple : '{' address_match_list '}'", +"address_name : any_string", +"key_ref : any_string", +"key_list_element : key_ref", +"key_list : key_list_element L_EOS", +"key_list : key_list key_list_element L_EOS", +"key_list : error", +"$$7 :", +"key_stmt : T_SEC_KEY $$7 any_string '{' key_definition '}'", +"key_definition : algorithm_id secret", +"key_definition : secret algorithm_id", +"key_definition : error", +"algorithm_id : T_ALGID any_string L_EOS", +"secret : T_SECRET any_string L_EOS", +"acl_stmt : T_ACL any_string '{' address_match_list '}'", +"$$8 :", +"zone_stmt : T_ZONE L_QSTRING optional_class $$8 optional_zone_options_list", +"optional_zone_options_list :", +"optional_zone_options_list : '{' zone_option_list '}'", +"optional_class :", +"optional_class : any_string", +"zone_type : T_MASTER", +"zone_type : T_SLAVE", +"zone_type : T_HINT", +"zone_type : T_STUB", +"zone_option_list : zone_option L_EOS", +"zone_option_list : zone_option_list zone_option L_EOS", +"zone_option : T_TYPE zone_type", +"zone_option : T_FILE L_QSTRING", +"zone_option : T_MASTERS '{' master_in_addr_list '}'", +"zone_option : T_TRANSFER_SOURCE maybe_wild_addr", +"zone_option : T_CHECK_NAMES check_names_opt", +"zone_option : T_ALLOW_UPDATE '{' address_match_list '}'", +"zone_option : T_ALLOW_QUERY '{' address_match_list '}'", +"zone_option : T_ALLOW_TRANSFER '{' address_match_list '}'", +"zone_option : T_MAX_TRANSFER_TIME_IN L_NUMBER", +"zone_option : T_NOTIFY yea_or_nay", +"zone_option : T_ALSO_NOTIFY '{' opt_notify_in_addr_list '}'", +"zone_option : error", +"master_in_addr_list : master_in_addr L_EOS", +"master_in_addr_list : master_in_addr_list master_in_addr L_EOS", +"master_in_addr : L_IPADDR", +"opt_notify_in_addr_list :", +"opt_notify_in_addr_list : notify_in_addr_list", +"notify_in_addr_list : notify_in_addr L_EOS", +"notify_in_addr_list : notify_in_addr_list notify_in_addr L_EOS", +"notify_in_addr : L_IPADDR", +"in_port : L_NUMBER", +"any_string : L_STRING", +"any_string : L_QSTRING", +}; +#endif +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 10000 +#define YYMAXDEPTH 10000 +#endif +#endif +#define YYINITSTACKSIZE 200 +int yydebug; +int yynerrs; +struct yystack { + short *ssp; + YYSTYPE *vsp; + short *ss; + YYSTYPE *vs; + int stacksize; + short *sslim; +}; +int yychar; /* some people use this, so we copy it in & out */ +int yyerrflag; /* must be global for yyerrok & YYRECOVERING */ +YYSTYPE yylval; +#line 1282 "ns_parser.y" + +static char * +canonical_name(char *name) { + char canonical[MAXDNAME]; + + if (strlen(name) >= MAXDNAME) + return (NULL); + strcpy(canonical, name); + if (makename(canonical, ".", sizeof canonical) < 0) + return (NULL); + return (savestr(canonical, 0)); +} + +static void +init_acls() { + ip_match_element ime; + ip_match_list iml; + struct in_addr address; + + /* Create the predefined ACLs */ + + address.s_addr = 0U; + + /* ACL "any" */ + ime = new_ip_match_pattern(address, 0); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("any", 1), iml); + + /* ACL "none" */ + ime = new_ip_match_pattern(address, 0); + ip_match_negate(ime); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("none", 1), iml); + + /* ACL "localhost" */ + ime = new_ip_match_localhost(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("localhost", 1), iml); + + /* ACL "localnets" */ + ime = new_ip_match_localnets(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("localnets", 1), iml); +} + +static void +free_sym_value(int type, void *value) { + ns_debug(ns_log_parser, 99, "free_sym_value: type %06x value %p", + type, value); + type &= ~0xffff; + switch (type) { + case SYM_ACL: + free_ip_match_list(value); + break; + case SYM_KEY: + free_key_info(value); + break; + default: + ns_panic(ns_log_parser, 1, + "unhandled case in free_sym_value()"); + /* NOTREACHED */ + break; + } +} + +static log_channel +lookup_channel(char *name) { + symbol_value value; + + if (lookup_symbol(symtab, name, SYM_CHANNEL, &value)) + return ((log_channel)(value.pointer)); + return (NULL); +} + +static void +define_channel(char *name, log_channel channel) { + symbol_value value; + + value.pointer = channel; + define_symbol(symtab, name, SYM_CHANNEL, value, SYMBOL_FREE_KEY); +} + +static void +define_builtin_channels() { + define_channel(savestr("default_syslog", 1), syslog_channel); + define_channel(savestr("default_debug", 1), debug_channel); + define_channel(savestr("default_stderr", 1), stderr_channel); + define_channel(savestr("null", 1), null_channel); +} + +static void +parser_setup() { + seen_options = 0; + seen_topology = 0; + symtab = new_symbol_table(SYMBOL_TABLE_SIZE, NULL); + if (authtab != NULL) + free_symbol_table(authtab); + authtab = new_symbol_table(AUTH_TABLE_SIZE, free_sym_value); + init_acls(); + define_builtin_channels(); +} + +static void +parser_cleanup() { + if (symtab != NULL) + free_symbol_table(symtab); + symtab = NULL; + /* + * We don't clean up authtab here because the ip_match_lists are in + * use. + */ +} + +/* + * Public Interface + */ + +ip_match_list +lookup_acl(char *name) { + symbol_value value; + + if (lookup_symbol(authtab, name, SYM_ACL, &value)) + return ((ip_match_list)(value.pointer)); + return (NULL); +} + +void +define_acl(char *name, ip_match_list iml) { + symbol_value value; + + INSIST(name != NULL); + INSIST(iml != NULL); + + value.pointer = iml; + define_symbol(authtab, name, SYM_ACL, value, + SYMBOL_FREE_KEY|SYMBOL_FREE_VALUE); + ns_debug(ns_log_parser, 7, "acl %s", name); + dprint_ip_match_list(ns_log_parser, iml, 2, "allow ", "deny "); +} + +key_info +lookup_key(char *name) { + symbol_value value; + + if (lookup_symbol(authtab, name, SYM_KEY, &value)) + return ((key_info)(value.pointer)); + return (NULL); +} + +void +define_key(char *name, key_info ki) { + symbol_value value; + + INSIST(name != NULL); + INSIST(ki != NULL); + + value.pointer = ki; + define_symbol(authtab, name, SYM_KEY, value, SYMBOL_FREE_VALUE); + dprint_key_info(ki); +} + +void +parse_configuration(const char *filename) { + FILE *config_stream; + + config_stream = fopen(filename, "r"); + if (config_stream == NULL) + ns_panic(ns_log_parser, 0, "can't open '%s'", filename); + + lexer_setup(); + parser_setup(); + lexer_begin_file(filename, config_stream); + (void)yyparse(); + lexer_end_file(); + parser_cleanup(); +} + +void +parser_initialize(void) { + lexer_initialize(); +} + +void +parser_shutdown(void) { + if (authtab != NULL) + free_symbol_table(authtab); + lexer_shutdown(); +} +#line 965 "y.tab.c" +/* allocate initial stack */ +#if defined(__STDC__) || defined(__cplusplus) +static int yyinitstack(struct yystack *sp) +#else +static int yyinitstack(sp) + struct yystack *sp; +#endif +{ + int newsize; + short *newss; + YYSTYPE *newvs; + + newsize = YYINITSTACKSIZE; + newss = (short *)malloc(newsize * sizeof *newss); + newvs = (YYSTYPE *)malloc(newsize * sizeof *newvs); + sp->ss = sp->ssp = newss; + sp->vs = sp->vsp = newvs; + if (newss == NULL || newvs == NULL) return -1; + sp->stacksize = newsize; + sp->sslim = newss + newsize - 1; + return 0; +} + +/* double stack size, up to YYMAXDEPTH */ +#if defined(__STDC__) || defined(__cplusplus) +static int yygrowstack(struct yystack *sp) +#else +static int yygrowstack(sp) + struct yystack *sp; +#endif +{ + int newsize, i; + short *newss; + YYSTYPE *newvs; + + if ((newsize = sp->stacksize) >= YYMAXDEPTH) return -1; + if ((newsize *= 2) > YYMAXDEPTH) newsize = YYMAXDEPTH; + i = sp->ssp - sp->ss; + if ((newss = (short *)realloc(sp->ss, newsize * sizeof *newss)) == NULL) + return -1; + sp->ss = newss; + sp->ssp = newss + i; + if ((newvs = (YYSTYPE *)realloc(sp->vs, newsize * sizeof *newvs)) == NULL) + return -1; + sp->vs = newvs; + sp->vsp = newvs + i; + sp->stacksize = newsize; + sp->sslim = newss + newsize - 1; + return 0; +} + +#define YYFREESTACK(sp) { free((sp)->ss); free((sp)->vs); } + +#define YYABORT goto yyabort +#define YYREJECT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab +int +yyparse() +{ + register int yym, yyn, yystate, yych; + register YYSTYPE *yyvsp; + YYSTYPE yyval; + struct yystack yystk; +#if YYDEBUG + register char *yys; + extern char *getenv(); + + if (yys = getenv("YYDEBUG")) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = yych = YYEMPTY; + + if (yyinitstack(&yystk)) goto yyoverflow; + *yystk.ssp = yystate = 0; + +yyloop: + if (yyn = yydefred[yystate]) goto yyreduce; + if (yych < 0) + { + if ((yych = YYLEX) < 0) yych = 0; + yychar = yych; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yych <= YYMAXTOKEN) yys = yyname[yych]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, yystate, yych, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yych) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yych) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, shifting to state %d\n", + YYPREFIX, yystate, yytable[yyn]); +#endif + if (yystk.ssp >= yystk.sslim && yygrowstack(&yystk)) + goto yyoverflow; + *++yystk.ssp = yystate = yytable[yyn]; + *++yystk.vsp = yylval; + yychar = yych = YYEMPTY; + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yych) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yych) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#ifdef lint + goto yynewerror; +#endif +yynewerror: + yyerror("syntax error"); +#ifdef lint + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yystk.ssp]) && + (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, error recovery shifting\ + to state %d\n", YYPREFIX, *yystk.ssp, yytable[yyn]); +#endif + if (yystk.ssp >= yystk.sslim && yygrowstack(&yystk)) + goto yyoverflow; + *++yystk.ssp = yystate = yytable[yyn]; + *++yystk.vsp = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: error recovery discarding state %d\n", + YYPREFIX, *yystk.ssp); +#endif + if (yystk.ssp <= yystk.ss) goto yyabort; + --yystk.ssp; + --yystk.vsp; + } + } + } + else + { + if (yych == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yych <= YYMAXTOKEN) yys = yyname[yych]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, error recovery discards token %d (%s)\n", + YYPREFIX, yystate, yych, yys); + } +#endif + yychar = yych = YYEMPTY; + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, reducing by rule %d (%s)\n", + YYPREFIX, yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyvsp = yystk.vsp; /* for speed in code under switch() */ + yyval = yyvsp[1-yym]; + switch (yyn) + { +case 1: +#line 206 "ns_parser.y" +{ + /* nothing */ + } +break; +case 14: +#line 227 "ns_parser.y" +{ lexer_begin_file(yyvsp[-1].cp, NULL); } +break; +case 15: +#line 235 "ns_parser.y" +{ + if (seen_options) + parser_error(0, "cannot redefine options"); + current_options = new_options(); + } +break; +case 16: +#line 241 "ns_parser.y" +{ + if (!seen_options) + set_options(current_options, 0); + else + free_options(current_options); + current_options = NULL; + seen_options = 1; + } +break; +case 20: +#line 257 "ns_parser.y" +{ + if (current_options->directory != NULL) + freestr(current_options->directory); + current_options->directory = yyvsp[0].cp; + } +break; +case 21: +#line 263 "ns_parser.y" +{ + if (current_options->named_xfer != NULL) + freestr(current_options->named_xfer); + current_options->named_xfer = yyvsp[0].cp; + } +break; +case 22: +#line 269 "ns_parser.y" +{ + if (current_options->pid_filename != NULL) + freestr(current_options->pid_filename); + current_options->pid_filename = yyvsp[0].cp; + } +break; +case 23: +#line 275 "ns_parser.y" +{ + if (current_options->stats_filename != NULL) + freestr(current_options->stats_filename); + current_options->stats_filename = yyvsp[0].cp; + } +break; +case 24: +#line 281 "ns_parser.y" +{ + if (current_options->memstats_filename != NULL) + freestr(current_options->memstats_filename); + current_options->memstats_filename = yyvsp[0].cp; + } +break; +case 25: +#line 287 "ns_parser.y" +{ + if (current_options->dump_filename != NULL) + freestr(current_options->dump_filename); + current_options->dump_filename = yyvsp[0].cp; + } +break; +case 26: +#line 293 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_FAKE_IQUERY, yyvsp[0].num); + } +break; +case 27: +#line 297 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_NORECURSE, !yyvsp[0].num); + } +break; +case 28: +#line 301 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_NOFETCHGLUE, !yyvsp[0].num); + } +break; +case 29: +#line 305 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_NONOTIFY, !yyvsp[0].num); + } +break; +case 30: +#line 309 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_HOSTSTATS, yyvsp[0].num); + } +break; +case 31: +#line 313 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_DEALLOC_ON_EXIT, + yyvsp[0].num); + } +break; +case 32: +#line 318 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN, + !yyvsp[0].num); + } +break; +case 33: +#line 323 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_MULTIPLE_CNAMES, + yyvsp[0].num); + } +break; +case 34: +#line 328 "ns_parser.y" +{ + current_options->check_names[yyvsp[-1].s_int] = yyvsp[0].s_int; + } +break; +case 35: +#line 332 "ns_parser.y" +{ + char port_string[10]; + symbol_value value; + + (void)sprintf(port_string, "%u", yyvsp[-3].us_int); + if (lookup_symbol(symtab, port_string, SYM_PORT, NULL)) + parser_error(0, + "cannot redefine listen-on for port %u", + ntohs(yyvsp[-3].us_int)); + else { + add_listen_on(current_options, yyvsp[-3].us_int, yyvsp[-1].iml); + value.pointer = NULL; + define_symbol(symtab, savestr(port_string, 1), + SYM_PORT, value, SYMBOL_FREE_KEY); + } + + } +break; +case 37: +#line 351 "ns_parser.y" +{ + if (current_options->fwdtab) { + free_forwarders(current_options->fwdtab); + current_options->fwdtab = NULL; + } + } +break; +case 40: +#line 360 "ns_parser.y" +{ + if (current_options->query_acl) + free_ip_match_list(current_options->query_acl); + current_options->query_acl = yyvsp[-1].iml; + } +break; +case 41: +#line 366 "ns_parser.y" +{ + if (current_options->transfer_acl) + free_ip_match_list(current_options->transfer_acl); + current_options->transfer_acl = yyvsp[-1].iml; + } +break; +case 42: +#line 372 "ns_parser.y" +{ + if (current_options->topology) + free_ip_match_list(current_options->topology); + current_options->topology = yyvsp[-1].iml; + } +break; +case 43: +#line 378 "ns_parser.y" +{ + /* To get around the $$ = $1 default rule. */ + } +break; +case 45: +#line 383 "ns_parser.y" +{ + current_options->transfer_format = yyvsp[0].axfr_fmt; + } +break; +case 46: +#line 387 "ns_parser.y" +{ + current_options->max_transfer_time_in = yyvsp[0].num * 60; + } +break; +case 47: +#line 391 "ns_parser.y" +{ + current_options->clean_interval = yyvsp[0].num * 60; + } +break; +case 48: +#line 395 "ns_parser.y" +{ + current_options->interface_interval = yyvsp[0].num * 60; + } +break; +case 49: +#line 399 "ns_parser.y" +{ + current_options->stats_interval = yyvsp[0].num * 60; + } +break; +case 51: +#line 406 "ns_parser.y" +{ + yyval.axfr_fmt = axfr_one_answer; + } +break; +case 52: +#line 410 "ns_parser.y" +{ + yyval.axfr_fmt = axfr_many_answers; + } +break; +case 53: +#line 415 "ns_parser.y" +{ yyval.ip_addr = yyvsp[0].ip_addr; } +break; +case 54: +#line 416 "ns_parser.y" +{ yyval.ip_addr.s_addr = htonl(INADDR_ANY); } +break; +case 55: +#line 419 "ns_parser.y" +{ yyval.us_int = yyvsp[0].us_int; } +break; +case 56: +#line 420 "ns_parser.y" +{ yyval.us_int = htons(0); } +break; +case 57: +#line 424 "ns_parser.y" +{ + current_options->query_source.sin_addr = yyvsp[0].ip_addr; + } +break; +case 58: +#line 430 "ns_parser.y" +{ + current_options->query_source.sin_port = yyvsp[0].us_int; + } +break; +case 63: +#line 441 "ns_parser.y" +{ yyval.us_int = htons(NS_DEFAULTPORT); } +break; +case 64: +#line 442 "ns_parser.y" +{ yyval.us_int = yyvsp[0].us_int; } +break; +case 65: +#line 446 "ns_parser.y" +{ + yyval.num = 1; + } +break; +case 66: +#line 450 "ns_parser.y" +{ + yyval.num = 1; + } +break; +case 67: +#line 454 "ns_parser.y" +{ + yyval.num = 0; + } +break; +case 68: +#line 458 "ns_parser.y" +{ + yyval.num = 0; + } +break; +case 69: +#line 462 "ns_parser.y" +{ + if (yyvsp[0].num == 1 || yyvsp[0].num == 0) { + yyval.num = yyvsp[0].num; + } else { + parser_warning(0, + "number should be 0 or 1; assuming 1"); + yyval.num = 1; + } + } +break; +case 70: +#line 474 "ns_parser.y" +{ + yyval.s_int = primary_trans; + } +break; +case 71: +#line 478 "ns_parser.y" +{ + yyval.s_int = secondary_trans; + } +break; +case 72: +#line 482 "ns_parser.y" +{ + yyval.s_int = response_trans; + } +break; +case 73: +#line 488 "ns_parser.y" +{ + yyval.s_int = warn; + } +break; +case 74: +#line 492 "ns_parser.y" +{ + yyval.s_int = fail; + } +break; +case 75: +#line 496 "ns_parser.y" +{ + yyval.s_int = ignore; + } +break; +case 76: +#line 502 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_FORWARD_ONLY, 1); + } +break; +case 77: +#line 506 "ns_parser.y" +{ + set_boolean_option(current_options, OPTION_FORWARD_ONLY, 0); + } +break; +case 78: +#line 510 "ns_parser.y" +{ + parser_warning(0, "forward if-no-answer is unimplemented"); + } +break; +case 79: +#line 514 "ns_parser.y" +{ + parser_warning(0, "forward if-no-domain is unimplemented"); + } +break; +case 80: +#line 520 "ns_parser.y" +{ + current_options->data_size = yyvsp[0].ul_int; + } +break; +case 81: +#line 524 "ns_parser.y" +{ + current_options->stack_size = yyvsp[0].ul_int; + } +break; +case 82: +#line 528 "ns_parser.y" +{ + current_options->core_size = yyvsp[0].ul_int; + } +break; +case 83: +#line 532 "ns_parser.y" +{ + current_options->files = yyvsp[0].ul_int; + } +break; +case 84: +#line 538 "ns_parser.y" +{ + u_long result; + + if (unit_to_ulong(yyvsp[0].cp, &result)) + yyval.ul_int = result; + else { + parser_error(0, "invalid unit string '%s'", yyvsp[0].cp); + /* 0 means "use default" */ + yyval.ul_int = 0; + } + freestr(yyvsp[0].cp); + } +break; +case 85: +#line 551 "ns_parser.y" +{ + yyval.ul_int = (u_long)yyvsp[0].num; + } +break; +case 86: +#line 555 "ns_parser.y" +{ + yyval.ul_int = 0; + } +break; +case 87: +#line 559 "ns_parser.y" +{ + yyval.ul_int = ULONG_MAX; + } +break; +case 88: +#line 565 "ns_parser.y" +{ + current_options->transfers_in = (u_long) yyvsp[0].num; + } +break; +case 89: +#line 569 "ns_parser.y" +{ + current_options->transfers_out = (u_long) yyvsp[0].num; + } +break; +case 90: +#line 573 "ns_parser.y" +{ + current_options->transfers_per_ns = (u_long) yyvsp[0].num; + } +break; +case 93: +#line 583 "ns_parser.y" +{ + /* nothing */ + } +break; +case 94: +#line 587 "ns_parser.y" +{ + /* nothing */ + } +break; +case 95: +#line 593 "ns_parser.y" +{ + add_forwarder(current_options, yyvsp[0].ip_addr); + } +break; +case 96: +#line 603 "ns_parser.y" +{ + current_logging = begin_logging(); + } +break; +case 97: +#line 607 "ns_parser.y" +{ + end_logging(current_logging, 1); + current_logging = NULL; + } +break; +case 101: +#line 619 "ns_parser.y" +{ + current_category = yyvsp[0].s_int; + } +break; +case 103: +#line 624 "ns_parser.y" +{ + chan_type = log_null; + chan_flags = 0; + chan_level = log_info; + } +break; +case 104: +#line 630 "ns_parser.y" +{ + log_channel current_channel = NULL; + + if (lookup_channel(yyvsp[-4].cp) != NULL) { + parser_error(0, "can't redefine channel '%s'", yyvsp[-4].cp); + freestr(yyvsp[-4].cp); + } else { + switch (chan_type) { + case log_file: + current_channel = + log_new_file_channel(chan_flags, + chan_level, + chan_name, NULL, + chan_versions, + chan_max_size); + freestr(chan_name); + chan_name = NULL; + break; + case log_syslog: + current_channel = + log_new_syslog_channel(chan_flags, + chan_level, + chan_facility); + break; + case log_null: + current_channel = log_new_null_channel(); + break; + default: + ns_panic(ns_log_parser, 1, + "unknown channel type: %d", + chan_type); + } + if (current_channel == NULL) + ns_panic(ns_log_parser, 0, + "couldn't create channel"); + define_channel(yyvsp[-4].cp, current_channel); + } + } +break; +case 105: +#line 671 "ns_parser.y" +{ + symbol_value value; + + if (lookup_symbol(constants, yyvsp[0].cp, SYM_LOGGING, &value)) { + chan_level = value.integer; + } else { + parser_error(0, "unknown severity '%s'", yyvsp[0].cp); + chan_level = log_debug(99); + } + freestr(yyvsp[0].cp); + } +break; +case 106: +#line 683 "ns_parser.y" +{ + chan_level = log_debug(1); + } +break; +case 107: +#line 687 "ns_parser.y" +{ + chan_level = yyvsp[0].num; + } +break; +case 108: +#line 691 "ns_parser.y" +{ + chan_level = 0; + chan_flags |= LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; + } +break; +case 109: +#line 698 "ns_parser.y" +{ + chan_versions = yyvsp[0].num; + chan_flags |= LOG_TRUNCATE; + } +break; +case 110: +#line 703 "ns_parser.y" +{ + chan_versions = LOG_MAX_VERSIONS; + chan_flags |= LOG_TRUNCATE; + } +break; +case 111: +#line 710 "ns_parser.y" +{ + chan_max_size = yyvsp[0].ul_int; + } +break; +case 112: +#line 716 "ns_parser.y" +{ + chan_versions = 0; + chan_max_size = ULONG_MAX; + } +break; +case 113: +#line 721 "ns_parser.y" +{ + chan_max_size = ULONG_MAX; + } +break; +case 114: +#line 725 "ns_parser.y" +{ + chan_versions = 0; + } +break; +case 117: +#line 733 "ns_parser.y" +{ + chan_flags |= LOG_CLOSE_STREAM; + chan_type = log_file; + chan_name = yyvsp[-1].cp; + } +break; +case 118: +#line 741 "ns_parser.y" +{ yyval.cp = yyvsp[0].cp; } +break; +case 119: +#line 742 "ns_parser.y" +{ yyval.cp = savestr("syslog", 1); } +break; +case 120: +#line 745 "ns_parser.y" +{ yyval.s_int = LOG_DAEMON; } +break; +case 121: +#line 747 "ns_parser.y" +{ + symbol_value value; + + if (lookup_symbol(constants, yyvsp[0].cp, SYM_SYSLOG, &value)) { + yyval.s_int = value.integer; + } else { + parser_error(0, "unknown facility '%s'", yyvsp[0].cp); + yyval.s_int = LOG_DAEMON; + } + freestr(yyvsp[0].cp); + } +break; +case 122: +#line 761 "ns_parser.y" +{ + chan_type = log_syslog; + chan_facility = yyvsp[0].s_int; + } +break; +case 123: +#line 767 "ns_parser.y" +{ /* nothing to do */ } +break; +case 124: +#line 768 "ns_parser.y" +{ /* nothing to do */ } +break; +case 125: +#line 770 "ns_parser.y" +{ + chan_type = log_null; + } +break; +case 126: +#line 773 "ns_parser.y" +{ /* nothing to do */ } +break; +case 127: +#line 775 "ns_parser.y" +{ + if (yyvsp[0].num) + chan_flags |= LOG_TIMESTAMP; + else + chan_flags &= ~LOG_TIMESTAMP; + } +break; +case 128: +#line 782 "ns_parser.y" +{ + if (yyvsp[0].num) + chan_flags |= LOG_PRINT_CATEGORY; + else + chan_flags &= ~LOG_PRINT_CATEGORY; + } +break; +case 129: +#line 789 "ns_parser.y" +{ + if (yyvsp[0].num) + chan_flags |= LOG_PRINT_LEVEL; + else + chan_flags &= ~LOG_PRINT_LEVEL; + } +break; +case 134: +#line 803 "ns_parser.y" +{ yyval.cp = savestr("null", 1); } +break; +case 135: +#line 807 "ns_parser.y" +{ + log_channel channel; + symbol_value value; + + if (current_category >= 0) { + channel = lookup_channel(yyvsp[0].cp); + if (channel != NULL) { + add_log_channel(current_logging, + current_category, channel); + } else + parser_error(0, "unknown channel '%s'", yyvsp[0].cp); + } + freestr(yyvsp[0].cp); + } +break; +case 140: +#line 829 "ns_parser.y" +{ yyval.cp = savestr("default", 1); } +break; +case 141: +#line 830 "ns_parser.y" +{ yyval.cp = savestr("notify", 1); } +break; +case 142: +#line 834 "ns_parser.y" +{ + symbol_value value; + + if (lookup_symbol(constants, yyvsp[0].cp, SYM_CATEGORY, &value)) + yyval.s_int = value.integer; + else { + parser_error(0, "invalid logging category '%s'", + yyvsp[0].cp); + yyval.s_int = -1; + } + freestr(yyvsp[0].cp); + } +break; +case 143: +#line 853 "ns_parser.y" +{ + char *ip_printable; + symbol_value value; + + ip_printable = inet_ntoa(yyvsp[0].ip_addr); + value.pointer = NULL; + if (lookup_symbol(symtab, ip_printable, SYM_SERVER, NULL)) + seen_server = 1; + else + seen_server = 0; + if (seen_server) + parser_error(0, "cannot redefine server '%s'", + ip_printable); + else + define_symbol(symtab, savestr(ip_printable, 1), + SYM_SERVER, value, + SYMBOL_FREE_KEY); + current_server = begin_server(yyvsp[0].ip_addr); + } +break; +case 144: +#line 873 "ns_parser.y" +{ + end_server(current_server, !seen_server); + } +break; +case 147: +#line 883 "ns_parser.y" +{ + set_server_option(current_server, SERVER_INFO_BOGUS, yyvsp[0].num); + } +break; +case 148: +#line 887 "ns_parser.y" +{ + set_server_transfers(current_server, (int)yyvsp[0].num); + } +break; +case 149: +#line 891 "ns_parser.y" +{ + set_server_transfer_format(current_server, yyvsp[0].axfr_fmt); + } +break; +case 152: +#line 903 "ns_parser.y" +{ + ip_match_list iml; + + iml = new_ip_match_list(); + if (yyvsp[-1].ime != NULL) + add_to_ip_match_list(iml, yyvsp[-1].ime); + yyval.iml = iml; + } +break; +case 153: +#line 912 "ns_parser.y" +{ + if (yyvsp[-1].ime != NULL) + add_to_ip_match_list(yyvsp[-2].iml, yyvsp[-1].ime); + yyval.iml = yyvsp[-2].iml; + } +break; +case 155: +#line 921 "ns_parser.y" +{ + if (yyvsp[0].ime != NULL) + ip_match_negate(yyvsp[0].ime); + yyval.ime = yyvsp[0].ime; + } +break; +case 156: +#line 929 "ns_parser.y" +{ + yyval.ime = new_ip_match_pattern(yyvsp[0].ip_addr, 32); + } +break; +case 157: +#line 933 "ns_parser.y" +{ + if (yyvsp[0].num < 0 || yyvsp[0].num > 32) { + parser_error(0, "mask bits out of range; skipping"); + yyval.ime = NULL; + } else { + yyval.ime = new_ip_match_pattern(yyvsp[-2].ip_addr, yyvsp[0].num); + if (yyval.ime == NULL) + parser_error(0, + "address/mask mismatch; skipping"); + } + } +break; +case 158: +#line 945 "ns_parser.y" +{ + struct in_addr ia; + + if (yyvsp[-2].num > 255) { + parser_error(0, "address out of range; skipping"); + yyval.ime = NULL; + } else { + if (yyvsp[0].num < 0 || yyvsp[0].num > 32) { + parser_error(0, + "mask bits out of range; skipping"); + yyval.ime = NULL; + } else { + ia.s_addr = htonl((yyvsp[-2].num & 0xff) << 24); + yyval.ime = new_ip_match_pattern(ia, yyvsp[0].num); + if (yyval.ime == NULL) + parser_error(0, + "address/mask mismatch; skipping"); + } + } + } +break; +case 160: +#line 967 "ns_parser.y" +{ + char name[256]; + + /* + * We want to be able to clean up this iml later so + * we give it a name and treat it like any other acl. + */ + sprintf(name, "__internal_%p", yyvsp[-1].iml); + define_acl(savestr(name, 1), yyvsp[-1].iml); + yyval.ime = new_ip_match_indirect(yyvsp[-1].iml); + } +break; +case 161: +#line 981 "ns_parser.y" +{ + ip_match_list iml; + + iml = lookup_acl(yyvsp[0].cp); + if (iml == NULL) { + parser_error(0, "unknown ACL '%s'", yyvsp[0].cp); + yyval.ime = NULL; + } else + yyval.ime = new_ip_match_indirect(iml); + freestr(yyvsp[0].cp); + } +break; +case 162: +#line 999 "ns_parser.y" +{ + key_info ki; + + ki = lookup_key(yyvsp[0].cp); + if (ki == NULL) { + parser_error(0, "unknown key '%s'", yyvsp[0].cp); + yyval.keyi = NULL; + } else + yyval.keyi = ki; + freestr(yyvsp[0].cp); + } +break; +case 163: +#line 1013 "ns_parser.y" +{ + if (yyvsp[0].keyi == NULL) + parser_error(0, "empty key not added to server list "); + else + add_server_key_info(current_server, yyvsp[0].keyi); + } +break; +case 167: +#line 1027 "ns_parser.y" +{ + current_algorithm = NULL; + current_secret = NULL; + } +break; +case 168: +#line 1032 "ns_parser.y" +{ + key_info ki; + + if (lookup_key(yyvsp[-3].cp) != NULL) { + parser_error(0, "can't redefine key '%s'", yyvsp[-3].cp); + freestr(yyvsp[-3].cp); + } else { + if (current_algorithm == NULL || + current_secret == NULL) + parser_error(0, "skipping bad key '%s'", yyvsp[-3].cp); + else { + ki = new_key_info(yyvsp[-3].cp, current_algorithm, + current_secret); + define_key(yyvsp[-3].cp, ki); + } + } + } +break; +case 169: +#line 1052 "ns_parser.y" +{ + current_algorithm = yyvsp[-1].cp; + current_secret = yyvsp[0].cp; + } +break; +case 170: +#line 1057 "ns_parser.y" +{ + current_algorithm = yyvsp[0].cp; + current_secret = yyvsp[-1].cp; + } +break; +case 171: +#line 1062 "ns_parser.y" +{ + current_algorithm = NULL; + current_secret = NULL; + } +break; +case 172: +#line 1068 "ns_parser.y" +{ yyval.cp = yyvsp[-1].cp; } +break; +case 173: +#line 1071 "ns_parser.y" +{ yyval.cp = yyvsp[-1].cp; } +break; +case 174: +#line 1079 "ns_parser.y" +{ + if (lookup_acl(yyvsp[-3].cp) != NULL) { + parser_error(0, "can't redefine ACL '%s'", yyvsp[-3].cp); + freestr(yyvsp[-3].cp); + } else + define_acl(yyvsp[-3].cp, yyvsp[-1].iml); + } +break; +case 175: +#line 1093 "ns_parser.y" +{ + int sym_type; + symbol_value value; + char *zone_name; + + if (!seen_options) + parser_error(0, + "no options statement before first zone; using previous/default"); + sym_type = SYM_ZONE | (yyvsp[0].num & 0xffff); + value.pointer = NULL; + zone_name = canonical_name(yyvsp[-1].cp); + if (zone_name == NULL) { + parser_error(0, "can't make zone name '%s' canonical", + yyvsp[-1].cp); + seen_zone = 1; + zone_name = savestr("__bad_zone__", 1); + } else { + seen_zone = lookup_symbol(symtab, zone_name, sym_type, + NULL); + if (seen_zone) { + parser_error(0, + "cannot redefine zone '%s' class %d", + zone_name, yyvsp[0].num); + } else + define_symbol(symtab, zone_name, sym_type, + value, 0); + } + freestr(yyvsp[-1].cp); + current_zone = begin_zone(zone_name, yyvsp[0].num); + } +break; +case 176: +#line 1124 "ns_parser.y" +{ end_zone(current_zone, !seen_zone); } +break; +case 179: +#line 1132 "ns_parser.y" +{ + yyval.num = C_IN; + } +break; +case 180: +#line 1136 "ns_parser.y" +{ + symbol_value value; + + if (lookup_symbol(constants, yyvsp[0].cp, SYM_CLASS, &value)) + yyval.num = value.integer; + else { + /* the zone validator will give the error */ + yyval.num = C_NONE; + } + freestr(yyvsp[0].cp); + } +break; +case 181: +#line 1150 "ns_parser.y" +{ + yyval.s_int = Z_MASTER; + } +break; +case 182: +#line 1154 "ns_parser.y" +{ + yyval.s_int = Z_SLAVE; + } +break; +case 183: +#line 1158 "ns_parser.y" +{ + yyval.s_int = Z_HINT; + } +break; +case 184: +#line 1162 "ns_parser.y" +{ + yyval.s_int = Z_STUB; + } +break; +case 187: +#line 1172 "ns_parser.y" +{ + if (!set_zone_type(current_zone, yyvsp[0].s_int)) + parser_warning(0, "zone type already set; skipping"); + } +break; +case 188: +#line 1177 "ns_parser.y" +{ + if (!set_zone_filename(current_zone, yyvsp[0].cp)) + parser_warning(0, + "zone filename already set; skipping"); + } +break; +case 190: +#line 1184 "ns_parser.y" +{ + set_zone_transfer_source(current_zone, yyvsp[0].ip_addr); + } +break; +case 191: +#line 1188 "ns_parser.y" +{ + if (!set_zone_checknames(current_zone, yyvsp[0].s_int)) + parser_warning(0, + "zone checknames already set; skipping"); + } +break; +case 192: +#line 1194 "ns_parser.y" +{ + if (!set_zone_update_acl(current_zone, yyvsp[-1].iml)) + parser_warning(0, + "zone update acl already set; skipping"); + } +break; +case 193: +#line 1200 "ns_parser.y" +{ + if (!set_zone_query_acl(current_zone, yyvsp[-1].iml)) + parser_warning(0, + "zone query acl already set; skipping"); + } +break; +case 194: +#line 1206 "ns_parser.y" +{ + if (!set_zone_transfer_acl(current_zone, yyvsp[-1].iml)) + parser_warning(0, + "zone transfer acl already set; skipping"); + } +break; +case 195: +#line 1212 "ns_parser.y" +{ + if (!set_zone_transfer_time_in(current_zone, yyvsp[0].num*60)) + parser_warning(0, + "zone max transfer time (in) already set; skipping"); + } +break; +case 196: +#line 1218 "ns_parser.y" +{ + set_zone_notify(current_zone, yyvsp[0].num); + } +break; +case 199: +#line 1226 "ns_parser.y" +{ + /* nothing */ + } +break; +case 200: +#line 1230 "ns_parser.y" +{ + /* nothing */ + } +break; +case 201: +#line 1236 "ns_parser.y" +{ + add_zone_master(current_zone, yyvsp[0].ip_addr); + } +break; +case 204: +#line 1246 "ns_parser.y" +{ + /* nothing */ + } +break; +case 205: +#line 1250 "ns_parser.y" +{ + /* nothing */ + } +break; +case 206: +#line 1256 "ns_parser.y" +{ + add_zone_notify(current_zone, yyvsp[0].ip_addr); + } +break; +case 207: +#line 1266 "ns_parser.y" +{ + if (yyvsp[0].num < 0 || yyvsp[0].num > 65535) { + parser_warning(0, + "invalid IP port number '%d'; setting port to 0", + yyvsp[0].num); + yyvsp[0].num = 0; + } else + yyval.us_int = htons(yyvsp[0].num); + } +break; +#line 2319 "y.tab.c" + } + yystk.ssp -= yym; + yystate = *yystk.ssp; + yystk.vsp -= yym; + yym = yylhs[yyn]; + yych = yychar; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state 0 to\ + state %d\n", YYPREFIX, YYFINAL); +#endif + yystate = YYFINAL; + *++yystk.ssp = YYFINAL; + *++yystk.vsp = yyval; + if (yych < 0) + { + if ((yych = YYLEX) < 0) yych = 0; + yychar = yych; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yych <= YYMAXTOKEN) yys = yyname[yych]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, YYFINAL, yych, yys); + } +#endif + } + if (yych == 0) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state %d \ +to state %d\n", YYPREFIX, *yystk.ssp, yystate); +#endif + if (yystk.ssp >= yystk.sslim && yygrowstack(&yystk)) + goto yyoverflow; + *++yystk.ssp = yystate; + *++yystk.vsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + YYFREESTACK(&yystk); + return (1); +yyaccept: + YYFREESTACK(&yystk); + return (0); +} diff --git a/contrib/bind/bin/named/ns_parser.h b/contrib/bind/bin/named/ns_parser.h new file mode 100644 index 0000000..1d23613 --- /dev/null +++ b/contrib/bind/bin/named/ns_parser.h @@ -0,0 +1,110 @@ +#define YYEMPTY (-1) +#define L_EOS 257 +#define L_IPADDR 258 +#define L_NUMBER 259 +#define L_STRING 260 +#define L_QSTRING 261 +#define L_END_INCLUDE 262 +#define T_INCLUDE 263 +#define T_OPTIONS 264 +#define T_DIRECTORY 265 +#define T_PIDFILE 266 +#define T_NAMED_XFER 267 +#define T_DUMP_FILE 268 +#define T_STATS_FILE 269 +#define T_MEMSTATS_FILE 270 +#define T_FAKE_IQUERY 271 +#define T_RECURSION 272 +#define T_FETCH_GLUE 273 +#define T_QUERY_SOURCE 274 +#define T_LISTEN_ON 275 +#define T_PORT 276 +#define T_ADDRESS 277 +#define T_DATASIZE 278 +#define T_STACKSIZE 279 +#define T_CORESIZE 280 +#define T_DEFAULT 281 +#define T_UNLIMITED 282 +#define T_FILES 283 +#define T_HOSTSTATS 284 +#define T_DEALLOC_ON_EXIT 285 +#define T_TRANSFERS_IN 286 +#define T_TRANSFERS_OUT 287 +#define T_TRANSFERS_PER_NS 288 +#define T_TRANSFER_FORMAT 289 +#define T_MAX_TRANSFER_TIME_IN 290 +#define T_ONE_ANSWER 291 +#define T_MANY_ANSWERS 292 +#define T_NOTIFY 293 +#define T_AUTH_NXDOMAIN 294 +#define T_MULTIPLE_CNAMES 295 +#define T_CLEAN_INTERVAL 296 +#define T_INTERFACE_INTERVAL 297 +#define T_STATS_INTERVAL 298 +#define T_LOGGING 299 +#define T_CATEGORY 300 +#define T_CHANNEL 301 +#define T_SEVERITY 302 +#define T_DYNAMIC 303 +#define T_FILE 304 +#define T_VERSIONS 305 +#define T_SIZE 306 +#define T_SYSLOG 307 +#define T_DEBUG 308 +#define T_NULL_OUTPUT 309 +#define T_PRINT_TIME 310 +#define T_PRINT_CATEGORY 311 +#define T_PRINT_SEVERITY 312 +#define T_TOPOLOGY 313 +#define T_SERVER 314 +#define T_LONG_AXFR 315 +#define T_BOGUS 316 +#define T_TRANSFERS 317 +#define T_KEYS 318 +#define T_ZONE 319 +#define T_IN 320 +#define T_CHAOS 321 +#define T_HESIOD 322 +#define T_TYPE 323 +#define T_MASTER 324 +#define T_SLAVE 325 +#define T_STUB 326 +#define T_RESPONSE 327 +#define T_HINT 328 +#define T_MASTERS 329 +#define T_TRANSFER_SOURCE 330 +#define T_ALSO_NOTIFY 331 +#define T_ACL 332 +#define T_ALLOW_UPDATE 333 +#define T_ALLOW_QUERY 334 +#define T_ALLOW_TRANSFER 335 +#define T_SEC_KEY 336 +#define T_ALGID 337 +#define T_SECRET 338 +#define T_CHECK_NAMES 339 +#define T_WARN 340 +#define T_FAIL 341 +#define T_IGNORE 342 +#define T_FORWARD 343 +#define T_FORWARDERS 344 +#define T_ONLY 345 +#define T_FIRST 346 +#define T_IF_NO_ANSWER 347 +#define T_IF_NO_DOMAIN 348 +#define T_YES 349 +#define T_TRUE 350 +#define T_NO 351 +#define T_FALSE 352 +typedef union { + char * cp; + int s_int; + long num; + u_long ul_int; + u_int16_t us_int; + struct in_addr ip_addr; + ip_match_element ime; + ip_match_list iml; + key_info keyi; + enum axfr_format axfr_fmt; +} YYSTYPE; +extern YYSTYPE yylval; diff --git a/contrib/bind/bin/named/ns_parser.y b/contrib/bind/bin/named/ns_parser.y new file mode 100644 index 0000000..77dee0b --- /dev/null +++ b/contrib/bind/bin/named/ns_parser.y @@ -0,0 +1,1473 @@ +%{ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_parser.y,v 8.11 1997/12/04 07:03:05 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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. + */ + +/* Global C stuff goes here. */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" +#include "ns_parseutil.h" +#include "ns_lexer.h" + +#define SYM_ZONE 0x010000 +#define SYM_SERVER 0x020000 +#define SYM_KEY 0x030000 +#define SYM_ACL 0x040000 +#define SYM_CHANNEL 0x050000 +#define SYM_PORT 0x060000 + +#define SYMBOL_TABLE_SIZE 29989 /* should always be prime */ +static symbol_table symtab; + +#define AUTH_TABLE_SIZE 397 /* should always be prime */ +static symbol_table authtab = NULL; + +static zone_config current_zone; +static int seen_zone; + +static options current_options; +static int seen_options; + +static topology_config current_topology; +static int seen_topology; + +static server_config current_server; +static int seen_server; + +static char *current_algorithm; +static char *current_secret; + +static log_config current_logging; +static int current_category; +static int chan_type; +static int chan_level; +static u_int chan_flags; +static int chan_facility; +static char *chan_name; +static int chan_versions; +static u_long chan_max_size; + +static log_channel lookup_channel(char *); +static void define_channel(char *, log_channel); +static char *canonical_name(char *); + +int yyparse(); + +%} + +%union { + char * cp; + int s_int; + long num; + u_long ul_int; + u_int16_t us_int; + struct in_addr ip_addr; + ip_match_element ime; + ip_match_list iml; + key_info keyi; + enum axfr_format axfr_fmt; +} + +/* Lexical analyzer return values. */ +%token L_EOS +%token <ip_addr> L_IPADDR +%token <num> L_NUMBER +%token <cp> L_STRING +%token <cp> L_QSTRING +%token L_END_INCLUDE + +/* Include support */ +%token T_INCLUDE + +/* Items related to the "options" statement: */ +%token T_OPTIONS +%token T_DIRECTORY T_PIDFILE T_NAMED_XFER +%token T_DUMP_FILE T_STATS_FILE T_MEMSTATS_FILE +%token T_FAKE_IQUERY T_RECURSION T_FETCH_GLUE +%token T_QUERY_SOURCE T_LISTEN_ON T_PORT T_ADDRESS +%type <us_int> in_port +%type <us_int> maybe_port +%type <us_int> maybe_wild_port +%type <ip_addr> maybe_wild_addr +%token T_DATASIZE T_STACKSIZE T_CORESIZE +%token T_DEFAULT T_UNLIMITED +%token T_FILES +%token T_HOSTSTATS T_DEALLOC_ON_EXIT +%token T_TRANSFERS_IN T_TRANSFERS_OUT T_TRANSFERS_PER_NS +%token T_TRANSFER_FORMAT T_MAX_TRANSFER_TIME_IN +%token T_ONE_ANSWER T_MANY_ANSWERS +%type <axfr_fmt> transfer_format +%token T_NOTIFY T_AUTH_NXDOMAIN T_MULTIPLE_CNAMES +%token T_CLEAN_INTERVAL T_INTERFACE_INTERVAL T_STATS_INTERVAL + +/* Items used for the "logging" statement: */ +%token T_LOGGING T_CATEGORY T_CHANNEL T_SEVERITY T_DYNAMIC +%token T_FILE T_VERSIONS T_SIZE +%token T_SYSLOG T_DEBUG T_NULL_OUTPUT +%token T_PRINT_TIME T_PRINT_CATEGORY T_PRINT_SEVERITY +%type <s_int> category +%type <cp> category_name channel_name facility_name +%type <s_int> maybe_syslog_facility + +/* Items used for the "topology" statement: */ +%token T_TOPOLOGY + +/* ip_match_list */ +%type <ime> address_match_simple address_match_element address_name +%type <iml> address_match_list + +/* Items used for "server" statements: */ +%token T_SERVER +%token T_LONG_AXFR +%token T_BOGUS +%token T_TRANSFERS +%token T_KEYS + +/* Items used for "zone" statements: */ +%token T_ZONE +%type <num> optional_class +%type <s_int> zone_type +%token T_IN T_CHAOS T_HESIOD +%token T_TYPE +%token T_MASTER T_SLAVE T_STUB T_RESPONSE +%token T_HINT +%token T_MASTERS T_TRANSFER_SOURCE +%token T_ALSO_NOTIFY + +/* Items used for access control lists and "allow" clauses: */ +%token T_ACL +%token T_ALLOW_UPDATE T_ALLOW_QUERY T_ALLOW_TRANSFER + +/* Items related to the "key" statement: */ +%token T_SEC_KEY T_ALGID T_SECRET +%type <keyi> key_ref +%type <cp> algorithm_id secret + +/* Items used for "size_spec" clauses: */ +%type <ul_int> size_spec + +/* Items used for a "check-names" clause: */ +%token T_CHECK_NAMES +%type <s_int> check_names_type +%type <s_int> check_names_opt +%token T_WARN T_FAIL T_IGNORE + +/* Items used for "forward" clauses: */ +%token T_FORWARD T_FORWARDERS +%token T_ONLY T_FIRST T_IF_NO_ANSWER T_IF_NO_DOMAIN + +/* Items used for yes/no responses: */ +%type <num> yea_or_nay +%token T_YES T_TRUE T_NO T_FALSE + +/* Miscellaneous items (used in several places): */ +%type <cp> any_string + +%% +config_file: statement_list + { + /* nothing */ + } + ; + +statement_list: statement + | statement_list statement + ; + +statement: include_stmt + | options_stmt L_EOS + | logging_stmt L_EOS + | server_stmt L_EOS + | zone_stmt L_EOS + | acl_stmt L_EOS + | key_stmt L_EOS + | L_END_INCLUDE + | error L_EOS + | error L_END_INCLUDE + ; + +include_stmt: T_INCLUDE L_QSTRING L_EOS { lexer_begin_file($2, NULL); } + ; + +/* + * Options + */ + +options_stmt: T_OPTIONS + { + if (seen_options) + parser_error(0, "cannot redefine options"); + current_options = new_options(); + } + '{' options '}' + { + if (!seen_options) + set_options(current_options, 0); + else + free_options(current_options); + current_options = NULL; + seen_options = 1; + } + ; + +options: option L_EOS + | options option L_EOS + ; + +option: /* Empty */ + | T_DIRECTORY L_QSTRING + { + if (current_options->directory != NULL) + freestr(current_options->directory); + current_options->directory = $2; + } + | T_NAMED_XFER L_QSTRING + { + if (current_options->named_xfer != NULL) + freestr(current_options->named_xfer); + current_options->named_xfer = $2; + } + | T_PIDFILE L_QSTRING + { + if (current_options->pid_filename != NULL) + freestr(current_options->pid_filename); + current_options->pid_filename = $2; + } + | T_STATS_FILE L_QSTRING + { + if (current_options->stats_filename != NULL) + freestr(current_options->stats_filename); + current_options->stats_filename = $2; + } + | T_MEMSTATS_FILE L_QSTRING + { + if (current_options->memstats_filename != NULL) + freestr(current_options->memstats_filename); + current_options->memstats_filename = $2; + } + | T_DUMP_FILE L_QSTRING + { + if (current_options->dump_filename != NULL) + freestr(current_options->dump_filename); + current_options->dump_filename = $2; + } + | T_FAKE_IQUERY yea_or_nay + { + set_boolean_option(current_options, OPTION_FAKE_IQUERY, $2); + } + | T_RECURSION yea_or_nay + { + set_boolean_option(current_options, OPTION_NORECURSE, !$2); + } + | T_FETCH_GLUE yea_or_nay + { + set_boolean_option(current_options, OPTION_NOFETCHGLUE, !$2); + } + | T_NOTIFY yea_or_nay + { + set_boolean_option(current_options, OPTION_NONOTIFY, !$2); + } + | T_HOSTSTATS yea_or_nay + { + set_boolean_option(current_options, OPTION_HOSTSTATS, $2); + } + | T_DEALLOC_ON_EXIT yea_or_nay + { + set_boolean_option(current_options, OPTION_DEALLOC_ON_EXIT, + $2); + } + | T_AUTH_NXDOMAIN yea_or_nay + { + set_boolean_option(current_options, OPTION_NONAUTH_NXDOMAIN, + !$2); + } + | T_MULTIPLE_CNAMES yea_or_nay + { + set_boolean_option(current_options, OPTION_MULTIPLE_CNAMES, + $2); + } + | T_CHECK_NAMES check_names_type check_names_opt + { + current_options->check_names[$2] = $3; + } + | T_LISTEN_ON maybe_port '{' address_match_list '}' + { + char port_string[10]; + symbol_value value; + + (void)sprintf(port_string, "%u", $2); + if (lookup_symbol(symtab, port_string, SYM_PORT, NULL)) + parser_error(0, + "cannot redefine listen-on for port %u", + ntohs($2)); + else { + add_listen_on(current_options, $2, $4); + value.pointer = NULL; + define_symbol(symtab, savestr(port_string, 1), + SYM_PORT, value, SYMBOL_FREE_KEY); + } + + } + | T_FORWARD forward_opt + | T_FORWARDERS + { + if (current_options->fwdtab) { + free_forwarders(current_options->fwdtab); + current_options->fwdtab = NULL; + } + } + '{' opt_forwarders_list '}' + | T_QUERY_SOURCE query_source + | T_ALLOW_QUERY '{' address_match_list '}' + { + if (current_options->query_acl) + free_ip_match_list(current_options->query_acl); + current_options->query_acl = $3; + } + | T_ALLOW_TRANSFER '{' address_match_list '}' + { + if (current_options->transfer_acl) + free_ip_match_list(current_options->transfer_acl); + current_options->transfer_acl = $3; + } + | T_TOPOLOGY '{' address_match_list '}' + { + if (current_options->topology) + free_ip_match_list(current_options->topology); + current_options->topology = $3; + } + | size_clause + { + /* To get around the $$ = $1 default rule. */ + } + | transfer_clause + | T_TRANSFER_FORMAT transfer_format + { + current_options->transfer_format = $2; + } + | T_MAX_TRANSFER_TIME_IN L_NUMBER + { + current_options->max_transfer_time_in = $2 * 60; + } + | T_CLEAN_INTERVAL L_NUMBER + { + current_options->clean_interval = $2 * 60; + } + | T_INTERFACE_INTERVAL L_NUMBER + { + current_options->interface_interval = $2 * 60; + } + | T_STATS_INTERVAL L_NUMBER + { + current_options->stats_interval = $2 * 60; + } + | error + ; + +transfer_format: T_ONE_ANSWER + { + $$ = axfr_one_answer; + } + | T_MANY_ANSWERS + { + $$ = axfr_many_answers; + } + ; + +maybe_wild_addr: L_IPADDR { $$ = $1; } + | '*' { $$.s_addr = htonl(INADDR_ANY); } + ; + +maybe_wild_port: in_port { $$ = $1; } + | '*' { $$ = htons(0); } + ; + +query_source_address: T_ADDRESS maybe_wild_addr + { + current_options->query_source.sin_addr = $2; + } + ; + +query_source_port: T_PORT maybe_wild_port + { + current_options->query_source.sin_port = $2; + } + ; + +query_source: query_source_address + | query_source_port + | query_source_address query_source_port + | query_source_port query_source_address + ; + +maybe_port: /* nothing */ { $$ = htons(NS_DEFAULTPORT); } + | T_PORT in_port { $$ = $2; } + ; + +yea_or_nay: T_YES + { + $$ = 1; + } + | T_TRUE + { + $$ = 1; + } + | T_NO + { + $$ = 0; + } + | T_FALSE + { + $$ = 0; + } + | L_NUMBER + { + if ($1 == 1 || $1 == 0) { + $$ = $1; + } else { + parser_warning(0, + "number should be 0 or 1; assuming 1"); + $$ = 1; + } + } + ; + +check_names_type: T_MASTER + { + $$ = primary_trans; + } + | T_SLAVE + { + $$ = secondary_trans; + } + | T_RESPONSE + { + $$ = response_trans; + } + ; + +check_names_opt: T_WARN + { + $$ = warn; + } + | T_FAIL + { + $$ = fail; + } + | T_IGNORE + { + $$ = ignore; + } + ; + +forward_opt: T_ONLY + { + set_boolean_option(current_options, OPTION_FORWARD_ONLY, 1); + } + | T_FIRST + { + set_boolean_option(current_options, OPTION_FORWARD_ONLY, 0); + } + | T_IF_NO_ANSWER + { + parser_warning(0, "forward if-no-answer is unimplemented"); + } + | T_IF_NO_DOMAIN + { + parser_warning(0, "forward if-no-domain is unimplemented"); + } + ; + +size_clause: T_DATASIZE size_spec + { + current_options->data_size = $2; + } + | T_STACKSIZE size_spec + { + current_options->stack_size = $2; + } + | T_CORESIZE size_spec + { + current_options->core_size = $2; + } + | T_FILES size_spec + { + current_options->files = $2; + } + ; + +size_spec: any_string + { + u_long result; + + if (unit_to_ulong($1, &result)) + $$ = result; + else { + parser_error(0, "invalid unit string '%s'", $1); + /* 0 means "use default" */ + $$ = 0; + } + freestr($1); + } + | L_NUMBER + { + $$ = (u_long)$1; + } + | T_DEFAULT + { + $$ = 0; + } + | T_UNLIMITED + { + $$ = ULONG_MAX; + } + ; + +transfer_clause: T_TRANSFERS_IN L_NUMBER + { + current_options->transfers_in = (u_long) $2; + } + | T_TRANSFERS_OUT L_NUMBER + { + current_options->transfers_out = (u_long) $2; + } + | T_TRANSFERS_PER_NS L_NUMBER + { + current_options->transfers_per_ns = (u_long) $2; + } + ; + +opt_forwarders_list: /* nothing */ + | forwarders_in_addr_list + ; + +forwarders_in_addr_list: forwarders_in_addr L_EOS + { + /* nothing */ + } + | forwarders_in_addr_list forwarders_in_addr L_EOS + { + /* nothing */ + } + ; + +forwarders_in_addr: L_IPADDR + { + add_forwarder(current_options, $1); + } + ; + +/* + * Logging + */ + +logging_stmt: T_LOGGING + { + current_logging = begin_logging(); + } + '{' logging_opts_list '}' + { + end_logging(current_logging, 1); + current_logging = NULL; + } + ; + +logging_opts_list: logging_opt L_EOS + | logging_opts_list logging_opt L_EOS + | error + ; + +logging_opt: T_CATEGORY category + { + current_category = $2; + } + '{' channel_list '}' + | T_CHANNEL channel_name + { + chan_type = log_null; + chan_flags = 0; + chan_level = log_info; + } + '{' channel_opt_list '}' + { + log_channel current_channel = NULL; + + if (lookup_channel($2) != NULL) { + parser_error(0, "can't redefine channel '%s'", $2); + freestr($2); + } else { + switch (chan_type) { + case log_file: + current_channel = + log_new_file_channel(chan_flags, + chan_level, + chan_name, NULL, + chan_versions, + chan_max_size); + freestr(chan_name); + chan_name = NULL; + break; + case log_syslog: + current_channel = + log_new_syslog_channel(chan_flags, + chan_level, + chan_facility); + break; + case log_null: + current_channel = log_new_null_channel(); + break; + default: + ns_panic(ns_log_parser, 1, + "unknown channel type: %d", + chan_type); + } + if (current_channel == NULL) + ns_panic(ns_log_parser, 0, + "couldn't create channel"); + define_channel($2, current_channel); + } + } + ; + +channel_severity: any_string + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_LOGGING, &value)) { + chan_level = value.integer; + } else { + parser_error(0, "unknown severity '%s'", $1); + chan_level = log_debug(99); + } + freestr($1); + } + | T_DEBUG + { + chan_level = log_debug(1); + } + | T_DEBUG L_NUMBER + { + chan_level = $2; + } + | T_DYNAMIC + { + chan_level = 0; + chan_flags |= LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; + } + ; + +version_modifier: T_VERSIONS L_NUMBER + { + chan_versions = $2; + chan_flags |= LOG_TRUNCATE; + } + | T_VERSIONS T_UNLIMITED + { + chan_versions = LOG_MAX_VERSIONS; + chan_flags |= LOG_TRUNCATE; + } + ; + +size_modifier: T_SIZE size_spec + { + chan_max_size = $2; + } + ; + +maybe_file_modifiers: /* nothing */ + { + chan_versions = 0; + chan_max_size = ULONG_MAX; + } + | version_modifier + { + chan_max_size = ULONG_MAX; + } + | size_modifier + { + chan_versions = 0; + } + | version_modifier size_modifier + | size_modifier version_modifier + ; + +channel_file: T_FILE L_QSTRING maybe_file_modifiers + { + chan_flags |= LOG_CLOSE_STREAM; + chan_type = log_file; + chan_name = $2; + } + ; + + +facility_name: any_string { $$ = $1; } + | T_SYSLOG { $$ = savestr("syslog", 1); } + ; + +maybe_syslog_facility: /* nothing */ { $$ = LOG_DAEMON; } + | facility_name + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_SYSLOG, &value)) { + $$ = value.integer; + } else { + parser_error(0, "unknown facility '%s'", $1); + $$ = LOG_DAEMON; + } + freestr($1); + } + ; + +channel_syslog: T_SYSLOG maybe_syslog_facility + { + chan_type = log_syslog; + chan_facility = $2; + } + ; + +channel_opt: channel_file { /* nothing to do */ } + | channel_syslog { /* nothing to do */ } + | T_NULL_OUTPUT + { + chan_type = log_null; + } + | T_SEVERITY channel_severity { /* nothing to do */ } + | T_PRINT_TIME yea_or_nay + { + if ($2) + chan_flags |= LOG_TIMESTAMP; + else + chan_flags &= ~LOG_TIMESTAMP; + } + | T_PRINT_CATEGORY yea_or_nay + { + if ($2) + chan_flags |= LOG_PRINT_CATEGORY; + else + chan_flags &= ~LOG_PRINT_CATEGORY; + } + | T_PRINT_SEVERITY yea_or_nay + { + if ($2) + chan_flags |= LOG_PRINT_LEVEL; + else + chan_flags &= ~LOG_PRINT_LEVEL; + } + ; + +channel_opt_list: channel_opt L_EOS + | channel_opt_list channel_opt L_EOS + | error + ; + +channel_name: any_string + | T_NULL_OUTPUT { $$ = savestr("null", 1); } + ; + +channel: channel_name + { + log_channel channel; + symbol_value value; + + if (current_category >= 0) { + channel = lookup_channel($1); + if (channel != NULL) { + add_log_channel(current_logging, + current_category, channel); + } else + parser_error(0, "unknown channel '%s'", $1); + } + freestr($1); + } + ; + +channel_list: channel L_EOS + | channel_list channel L_EOS + | error + ; + +category_name: any_string + | T_DEFAULT { $$ = savestr("default", 1); } + | T_NOTIFY { $$ = savestr("notify", 1); } + ; + +category: category_name + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_CATEGORY, &value)) + $$ = value.integer; + else { + parser_error(0, "invalid logging category '%s'", + $1); + $$ = -1; + } + freestr($1); + } + ; + +/* + * Server Information + */ + +server_stmt: T_SERVER L_IPADDR + { + char *ip_printable; + symbol_value value; + + ip_printable = inet_ntoa($2); + value.pointer = NULL; + if (lookup_symbol(symtab, ip_printable, SYM_SERVER, NULL)) + seen_server = 1; + else + seen_server = 0; + if (seen_server) + parser_error(0, "cannot redefine server '%s'", + ip_printable); + else + define_symbol(symtab, savestr(ip_printable, 1), + SYM_SERVER, value, + SYMBOL_FREE_KEY); + current_server = begin_server($2); + } + '{' server_info_list '}' + { + end_server(current_server, !seen_server); + } + ; + +server_info_list: server_info L_EOS + | server_info_list server_info L_EOS + ; + +server_info: T_BOGUS yea_or_nay + { + set_server_option(current_server, SERVER_INFO_BOGUS, $2); + } + | T_TRANSFERS L_NUMBER + { + set_server_transfers(current_server, (int)$2); + } + | T_TRANSFER_FORMAT transfer_format + { + set_server_transfer_format(current_server, $2); + } + | T_KEYS '{' key_list '}' + | error + ; + +/* + * Address Matching + */ + +address_match_list: address_match_element L_EOS + { + ip_match_list iml; + + iml = new_ip_match_list(); + if ($1 != NULL) + add_to_ip_match_list(iml, $1); + $$ = iml; + } + | address_match_list address_match_element L_EOS + { + if ($2 != NULL) + add_to_ip_match_list($1, $2); + $$ = $1; + } + ; + +address_match_element: address_match_simple + | '!' address_match_simple + { + if ($2 != NULL) + ip_match_negate($2); + $$ = $2; + } + ; + +address_match_simple: L_IPADDR + { + $$ = new_ip_match_pattern($1, 32); + } + | L_IPADDR '/' L_NUMBER + { + if ($3 < 0 || $3 > 32) { + parser_error(0, "mask bits out of range; skipping"); + $$ = NULL; + } else { + $$ = new_ip_match_pattern($1, $3); + if ($$ == NULL) + parser_error(0, + "address/mask mismatch; skipping"); + } + } + | L_NUMBER '/' L_NUMBER + { + struct in_addr ia; + + if ($1 > 255) { + parser_error(0, "address out of range; skipping"); + $$ = NULL; + } else { + if ($3 < 0 || $3 > 32) { + parser_error(0, + "mask bits out of range; skipping"); + $$ = NULL; + } else { + ia.s_addr = htonl(($1 & 0xff) << 24); + $$ = new_ip_match_pattern(ia, $3); + if ($$ == NULL) + parser_error(0, + "address/mask mismatch; skipping"); + } + } + } + | address_name + | '{' address_match_list '}' + { + char name[256]; + + /* + * We want to be able to clean up this iml later so + * we give it a name and treat it like any other acl. + */ + sprintf(name, "__internal_%p", $2); + define_acl(savestr(name, 1), $2); + $$ = new_ip_match_indirect($2); + } + ; + +address_name: any_string + { + ip_match_list iml; + + iml = lookup_acl($1); + if (iml == NULL) { + parser_error(0, "unknown ACL '%s'", $1); + $$ = NULL; + } else + $$ = new_ip_match_indirect(iml); + freestr($1); + } + ; + +/* + * Keys + */ + +key_ref: any_string + { + key_info ki; + + ki = lookup_key($1); + if (ki == NULL) { + parser_error(0, "unknown key '%s'", $1); + $$ = NULL; + } else + $$ = ki; + freestr($1); + } + ; + +key_list_element: key_ref + { + if ($1 == NULL) + parser_error(0, "empty key not added to server list "); + else + add_server_key_info(current_server, $1); + } + ; + +key_list: key_list_element L_EOS + | key_list key_list_element L_EOS + | error + ; + +key_stmt: T_SEC_KEY + { + current_algorithm = NULL; + current_secret = NULL; + } + any_string '{' key_definition '}' + { + key_info ki; + + if (lookup_key($3) != NULL) { + parser_error(0, "can't redefine key '%s'", $3); + freestr($3); + } else { + if (current_algorithm == NULL || + current_secret == NULL) + parser_error(0, "skipping bad key '%s'", $3); + else { + ki = new_key_info($3, current_algorithm, + current_secret); + define_key($3, ki); + } + } + } + ; + +key_definition: algorithm_id secret + { + current_algorithm = $1; + current_secret = $2; + } + | secret algorithm_id + { + current_algorithm = $2; + current_secret = $1; + } + | error + { + current_algorithm = NULL; + current_secret = NULL; + } + ; + +algorithm_id: T_ALGID any_string L_EOS { $$ = $2; } + ; + +secret: T_SECRET any_string L_EOS { $$ = $2; } + ; + +/* + * ACLs + */ + +acl_stmt: T_ACL any_string '{' address_match_list '}' + { + if (lookup_acl($2) != NULL) { + parser_error(0, "can't redefine ACL '%s'", $2); + freestr($2); + } else + define_acl($2, $4); + } + ; + +/* + * Zones + */ + +zone_stmt: T_ZONE L_QSTRING optional_class + { + int sym_type; + symbol_value value; + char *zone_name; + + if (!seen_options) + parser_error(0, + "no options statement before first zone; using previous/default"); + sym_type = SYM_ZONE | ($3 & 0xffff); + value.pointer = NULL; + zone_name = canonical_name($2); + if (zone_name == NULL) { + parser_error(0, "can't make zone name '%s' canonical", + $2); + seen_zone = 1; + zone_name = savestr("__bad_zone__", 1); + } else { + seen_zone = lookup_symbol(symtab, zone_name, sym_type, + NULL); + if (seen_zone) { + parser_error(0, + "cannot redefine zone '%s' class %d", + zone_name, $3); + } else + define_symbol(symtab, zone_name, sym_type, + value, 0); + } + freestr($2); + current_zone = begin_zone(zone_name, $3); + } + optional_zone_options_list + { end_zone(current_zone, !seen_zone); } + ; + +optional_zone_options_list: /* Empty */ + | '{' zone_option_list '}' + ; + +optional_class: /* Empty */ + { + $$ = C_IN; + } + | any_string + { + symbol_value value; + + if (lookup_symbol(constants, $1, SYM_CLASS, &value)) + $$ = value.integer; + else { + /* the zone validator will give the error */ + $$ = C_NONE; + } + freestr($1); + } + ; + +zone_type: T_MASTER + { + $$ = Z_MASTER; + } + | T_SLAVE + { + $$ = Z_SLAVE; + } + | T_HINT + { + $$ = Z_HINT; + } + | T_STUB + { + $$ = Z_STUB; + } + ; + +zone_option_list: zone_option L_EOS + | zone_option_list zone_option L_EOS + ; + +zone_option: T_TYPE zone_type + { + if (!set_zone_type(current_zone, $2)) + parser_warning(0, "zone type already set; skipping"); + } + | T_FILE L_QSTRING + { + if (!set_zone_filename(current_zone, $2)) + parser_warning(0, + "zone filename already set; skipping"); + } + | T_MASTERS '{' master_in_addr_list '}' + | T_TRANSFER_SOURCE maybe_wild_addr + { + set_zone_transfer_source(current_zone, $2); + } + | T_CHECK_NAMES check_names_opt + { + if (!set_zone_checknames(current_zone, $2)) + parser_warning(0, + "zone checknames already set; skipping"); + } + | T_ALLOW_UPDATE '{' address_match_list '}' + { + if (!set_zone_update_acl(current_zone, $3)) + parser_warning(0, + "zone update acl already set; skipping"); + } + | T_ALLOW_QUERY '{' address_match_list '}' + { + if (!set_zone_query_acl(current_zone, $3)) + parser_warning(0, + "zone query acl already set; skipping"); + } + | T_ALLOW_TRANSFER '{' address_match_list '}' + { + if (!set_zone_transfer_acl(current_zone, $3)) + parser_warning(0, + "zone transfer acl already set; skipping"); + } + | T_MAX_TRANSFER_TIME_IN L_NUMBER + { + if (!set_zone_transfer_time_in(current_zone, $2*60)) + parser_warning(0, + "zone max transfer time (in) already set; skipping"); + } + | T_NOTIFY yea_or_nay + { + set_zone_notify(current_zone, $2); + } + | T_ALSO_NOTIFY '{' opt_notify_in_addr_list '}' + | error + ; + +master_in_addr_list: master_in_addr L_EOS + { + /* nothing */ + } + | master_in_addr_list master_in_addr L_EOS + { + /* nothing */ + } + ; + +master_in_addr: L_IPADDR + { + add_zone_master(current_zone, $1); + } + ; + +opt_notify_in_addr_list: /* nothing */ + | notify_in_addr_list + ; + +notify_in_addr_list: notify_in_addr L_EOS + { + /* nothing */ + } + | notify_in_addr_list notify_in_addr L_EOS + { + /* nothing */ + } + ; + +notify_in_addr: L_IPADDR + { + add_zone_notify(current_zone, $1); + } + ; + +/* + * Misc. + */ + +in_port: L_NUMBER + { + if ($1 < 0 || $1 > 65535) { + parser_warning(0, + "invalid IP port number '%d'; setting port to 0", + $1); + $1 = 0; + } else + $$ = htons($1); + } + ; + +any_string: L_STRING + | L_QSTRING + ; + +%% + +static char * +canonical_name(char *name) { + char canonical[MAXDNAME]; + + if (strlen(name) >= MAXDNAME) + return (NULL); + strcpy(canonical, name); + if (makename(canonical, ".", sizeof canonical) < 0) + return (NULL); + return (savestr(canonical, 0)); +} + +static void +init_acls() { + ip_match_element ime; + ip_match_list iml; + struct in_addr address; + + /* Create the predefined ACLs */ + + address.s_addr = 0U; + + /* ACL "any" */ + ime = new_ip_match_pattern(address, 0); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("any", 1), iml); + + /* ACL "none" */ + ime = new_ip_match_pattern(address, 0); + ip_match_negate(ime); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("none", 1), iml); + + /* ACL "localhost" */ + ime = new_ip_match_localhost(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("localhost", 1), iml); + + /* ACL "localnets" */ + ime = new_ip_match_localnets(); + iml = new_ip_match_list(); + add_to_ip_match_list(iml, ime); + define_acl(savestr("localnets", 1), iml); +} + +static void +free_sym_value(int type, void *value) { + ns_debug(ns_log_parser, 99, "free_sym_value: type %06x value %p", + type, value); + type &= ~0xffff; + switch (type) { + case SYM_ACL: + free_ip_match_list(value); + break; + case SYM_KEY: + free_key_info(value); + break; + default: + ns_panic(ns_log_parser, 1, + "unhandled case in free_sym_value()"); + /* NOTREACHED */ + break; + } +} + +static log_channel +lookup_channel(char *name) { + symbol_value value; + + if (lookup_symbol(symtab, name, SYM_CHANNEL, &value)) + return ((log_channel)(value.pointer)); + return (NULL); +} + +static void +define_channel(char *name, log_channel channel) { + symbol_value value; + + value.pointer = channel; + define_symbol(symtab, name, SYM_CHANNEL, value, SYMBOL_FREE_KEY); +} + +static void +define_builtin_channels() { + define_channel(savestr("default_syslog", 1), syslog_channel); + define_channel(savestr("default_debug", 1), debug_channel); + define_channel(savestr("default_stderr", 1), stderr_channel); + define_channel(savestr("null", 1), null_channel); +} + +static void +parser_setup() { + seen_options = 0; + seen_topology = 0; + symtab = new_symbol_table(SYMBOL_TABLE_SIZE, NULL); + if (authtab != NULL) + free_symbol_table(authtab); + authtab = new_symbol_table(AUTH_TABLE_SIZE, free_sym_value); + init_acls(); + define_builtin_channels(); +} + +static void +parser_cleanup() { + if (symtab != NULL) + free_symbol_table(symtab); + symtab = NULL; + /* + * We don't clean up authtab here because the ip_match_lists are in + * use. + */ +} + +/* + * Public Interface + */ + +ip_match_list +lookup_acl(char *name) { + symbol_value value; + + if (lookup_symbol(authtab, name, SYM_ACL, &value)) + return ((ip_match_list)(value.pointer)); + return (NULL); +} + +void +define_acl(char *name, ip_match_list iml) { + symbol_value value; + + INSIST(name != NULL); + INSIST(iml != NULL); + + value.pointer = iml; + define_symbol(authtab, name, SYM_ACL, value, + SYMBOL_FREE_KEY|SYMBOL_FREE_VALUE); + ns_debug(ns_log_parser, 7, "acl %s", name); + dprint_ip_match_list(ns_log_parser, iml, 2, "allow ", "deny "); +} + +key_info +lookup_key(char *name) { + symbol_value value; + + if (lookup_symbol(authtab, name, SYM_KEY, &value)) + return ((key_info)(value.pointer)); + return (NULL); +} + +void +define_key(char *name, key_info ki) { + symbol_value value; + + INSIST(name != NULL); + INSIST(ki != NULL); + + value.pointer = ki; + define_symbol(authtab, name, SYM_KEY, value, SYMBOL_FREE_VALUE); + dprint_key_info(ki); +} + +void +parse_configuration(const char *filename) { + FILE *config_stream; + + config_stream = fopen(filename, "r"); + if (config_stream == NULL) + ns_panic(ns_log_parser, 0, "can't open '%s'", filename); + + lexer_setup(); + parser_setup(); + lexer_begin_file(filename, config_stream); + (void)yyparse(); + lexer_end_file(); + parser_cleanup(); +} + +void +parser_initialize(void) { + lexer_initialize(); +} + +void +parser_shutdown(void) { + if (authtab != NULL) + free_symbol_table(authtab); + lexer_shutdown(); +} diff --git a/contrib/bind/bin/named/ns_parseutil.c b/contrib/bind/bin/named/ns_parseutil.c new file mode 100644 index 0000000..aed15af --- /dev/null +++ b/contrib/bind/bin/named/ns_parseutil.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 1996, 1997 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. + */ + +/* Global C stuff goes here. */ + + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" +#include "ns_parseutil.h" + + +/* + * Symbol Table + */ + +symbol_table +new_symbol_table(int size_guess, free_function free_value) { + symbol_table st; + + st = (symbol_table)memget(sizeof (struct symbol_table)); + if (st == NULL) + panic("memget failed in new_symbol_table()", NULL); + st->table = (symbol_entry *)memget(size_guess * sizeof *st->table); + if (st->table == NULL) + panic("memget failed in new_symbol_table()", NULL); + memset(st->table, 0, size_guess * sizeof (symbol_entry)); + st->size = size_guess; /* size_guess should be prime */ + st->free_value = free_value; + return (st); +} + +void +free_symbol(symbol_table st, symbol_entry ste) { + if (ste->flags & SYMBOL_FREE_KEY) + freestr(ste->key); + if (ste->flags & SYMBOL_FREE_VALUE) + (st->free_value)(ste->type, ste->value.pointer); +} + +void +free_symbol_table(symbol_table st) { + int i; + symbol_entry ste, ste_next; + + for (i = 0; i < st->size; i++) { + for (ste = st->table[i]; ste != NULL; ste = ste_next) { + ste_next = ste->next; + free_symbol(st, ste); + memput(ste, sizeof *ste); + } + } + memput(st->table, st->size * sizeof (symbol_entry)); + memput(st, sizeof *st); +} + +void +dprint_symbol_table(int level, symbol_table st) { + int i; + symbol_entry ste; + + for (i = 0; i < st->size; i++) { + for (ste = st->table[i]; ste != NULL; ste = ste->next) + ns_debug(ns_log_parser, level, + "%7d: (%s: %d %p/%d %04x) ", + i, ste->key, ste->type, ste->value.pointer, + ste->value.integer, ste->flags); + } +} + +/* + * 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. + */ +static int +symbol_hash(const char *key, int prime) { + const char *s; + unsigned int h = 0; + unsigned int g; + int c; + + for (s = key; *s != '\0'; s++) { + c = *s; + if (isascii(c) && isupper(c)) + c = tolower(c); + h = ( h << 4 ) + c; + if ((g = ( h & 0xf0000000 )) != 0) { + h = h ^ (g >> 24); + h = h ^ g; + } + } + return (h % prime); +} + +int +lookup_symbol(symbol_table st, const char *key, int type, + symbol_value *value) { + int hash; + symbol_entry ste; + + hash = symbol_hash(key, st->size); + for (ste = st->table[hash]; ste != NULL; ste = ste->next) + if ((type == 0 || ste->type == type) && + strcasecmp(ste->key, key) == 0) + break; + if (ste != NULL) { + if (value != NULL) + *value = ste->value; + return (1); + } + return (0); +} + +void +define_symbol(symbol_table st, char *key, int type, symbol_value value, + unsigned int flags) { + int hash; + symbol_entry ste; + + hash = symbol_hash(key, st->size); + for (ste = st->table[hash]; ste != NULL; ste = ste->next) + if ((type == 0 || ste->type == type) && + strcasecmp(ste->key, key) == 0) + break; + if (ste == NULL) { + ste = (symbol_entry)memget(sizeof *ste); + if (ste == NULL) + panic("memget failed in define_symbol()", NULL); + ste->key = key; + ste->type = type; + ste->value = value; + ste->flags = flags; + ste->next = st->table[hash]; + st->table[hash] = ste; + } else { + ns_debug(ns_log_parser, 7, "redefined symbol %s type %d", + key, type); + free_symbol(st, ste); + ste->key = key; + ste->value = value; + ste->flags = flags; + } +} + +void +undefine_symbol(symbol_table st, char *key, int type) { + int hash; + symbol_entry prev_ste, ste, next_ste; + + hash = symbol_hash(key, st->size); + for (prev_ste = NULL, ste = st->table[hash]; + ste != NULL; + prev_ste = ste, ste = ste->next) + if ((type == 0 || ste->type == type) && + strcasecmp(ste->key, key) == 0) + break; + if (ste != NULL) { + free_symbol(st, ste); + if (prev_ste != NULL) + prev_ste->next = ste->next; + else + st->table[hash] = ste->next; + memput(ste, sizeof *ste); + } +} + +/* + * Conversion Routines + */ + +int +unit_to_ulong(char *in, u_long *out) { + int c, units_done = 0; + u_long result = 0L; + + INSIST(in != NULL); + + for (; (c = *in) != '\0'; in++) { + if (units_done) + return (0); + if (isdigit(c)) { + result *= 10; + result += (c - '0'); + } else { + switch (c) { + case 'k': + case 'K': + result *= 1024; + units_done = 1; + break; + case 'm': + case 'M': + result *= (1024*1024); + units_done = 1; + break; + case 'g': + case 'G': + result *= (1024*1024*1024); + units_done = 1; + break; + default: + return (0); + } + } + } + + *out = result; + return (1); +} diff --git a/contrib/bind/bin/named/ns_parseutil.h b/contrib/bind/bin/named/ns_parseutil.h new file mode 100644 index 0000000..d241bea --- /dev/null +++ b/contrib/bind/bin/named/ns_parseutil.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1996, 1997 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. + */ + +#ifndef NS_PARSEUTIL_H +#define NS_PARSEUTIL_H + +/* + * Symbol Table + */ + +#define SYMBOL_FREE_KEY 0x01 +#define SYMBOL_FREE_VALUE 0x02 + +typedef union symbol_value { + void *pointer; + int integer; +} symbol_value; + +typedef void (*free_function)(int, void *); + +typedef struct symbol_entry { + char *key; + int type; + symbol_value value; + unsigned int flags; + struct symbol_entry *next; +} *symbol_entry; + +typedef struct symbol_table { + int size; + symbol_entry *table; + free_function free_value; +} *symbol_table; + +symbol_table new_symbol_table(int, free_function); +void free_symbol(symbol_table, symbol_entry); +void free_symbol_table(symbol_table); +void dprint_symbol_table(int, symbol_table); +int lookup_symbol(symbol_table, const char *, int, + symbol_value *); +void define_symbol(symbol_table, char *, int, symbol_value, + unsigned int); +void undefine_symbol(symbol_table, char *, int type); + +/* + * Conversion Routines + */ + +int unit_to_ulong(char *, u_long *); + +#endif /* !NS_PARSEUTIL_H */ diff --git a/contrib/bind/bin/named/ns_req.c b/contrib/bind/bin/named/ns_req.c new file mode 100644 index 0000000..ee60ce4 --- /dev/null +++ b/contrib/bind/bin/named/ns_req.c @@ -0,0 +1,1669 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)ns_req.c 4.47 (Berkeley) 7/1/91"; +static char rcsid[] = "$Id: ns_req.c,v 8.46 1998/03/27 00:21:03 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988, 1990 + * 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, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/uio.h> +#include <sys/file.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <fcntl.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +struct addinfo { + char *a_dname; /* domain name */ + char *a_rname; /* referred by */ + u_int16_t a_rtype; /* referred by */ + u_int16_t a_class; /* class for address */ +}; + +#ifndef BIND_UPDATE +enum req_action { Finish, Refuse, Return }; +#endif + +static struct addinfo addinfo[NADDRECS]; +static void addname(const char *, const char *, + u_int16_t, u_int16_t); +static void copyCharString(u_char **, const char *); + +static enum req_action req_query(HEADER *hp, u_char **cpp, u_char *eom, + struct qstream *qsp, + int *buflenp, int *msglenp, + u_char *msg, int dfd, + struct sockaddr_in from); + +static enum req_action req_iquery(HEADER *hp, u_char **cpp, u_char *eom, + int *buflenp, u_char *msg, + struct sockaddr_in from); + +#ifdef BIND_NOTIFY +static enum req_action req_notify(HEADER *hp, u_char **cpp, u_char *eom, + u_char *msg,struct sockaddr_in from); +#endif + +/* + * Process request using database; assemble and send response. + */ +void +ns_req(u_char *msg, int msglen, int buflen, struct qstream *qsp, + struct sockaddr_in from, int dfd) +{ + HEADER *hp = (HEADER *) msg; + u_char *cp, *eom; + enum req_action action; + int n; + +#ifdef DEBUG + if (debug > 3) { + ns_debug(ns_log_packet, 3, "ns_req(from %s)", sin_ntoa(from)); + fp_nquery(msg, msglen, log_get_stream(packet_channel)); + } +#endif + + /* + * It's not a response so these bits have no business + * being set. will later simplify work if we can + * safely assume these are always 0 when a query + * comes in. + */ + hp->aa = hp->ra = 0; + + hp->rcode = NOERROR; + cp = msg + HFIXEDSZ; + eom = msg + msglen; + buflen -= HFIXEDSZ; + + free_addinfo(); /* sets addcount to zero */ + dnptrs[0] = NULL; + + switch (hp->opcode) { + case ns_o_query: + action = req_query(hp, &cp, eom, qsp, + &buflen, &msglen, + msg, dfd, from); + break; + + case ns_o_iquery: + action = req_iquery(hp, &cp, eom, &buflen, msg, from); + break; + +#ifdef BIND_NOTIFY + case ns_o_notify: + action = req_notify(hp, &cp, eom, msg, from); + break; +#endif + +#ifdef BIND_UPDATE + case ns_o_update: + action = req_update(hp, cp, eom, msg, qsp, dfd, from); + break; +#endif /* BIND_UPDATE */ + + default: + ns_debug(ns_log_default, 1, + "ns_req: Opcode %d not implemented", hp->opcode); + /* XXX - should syslog, limited by haveComplained */ + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = NOTIMP; + action = Finish; + } + + /* + * vector via internal opcode. (yes, it was even uglier before.) + */ + switch (action) { + case Return: + return; + case Refuse: + hp->rcode = REFUSED; + cp = eom; + /*FALLTHROUGH*/ + case Finish: + /* rest of the function handles this case */ + break; + default: + panic("ns_req: bad action variable", NULL); + /*NOTREACHED*/ + } + + /* + * apply final polish + */ + hp->qr = 1; /* set Response flag */ + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + + n = doaddinfo(hp, cp, buflen); + cp += n; + buflen -= n; + +#ifdef DEBUG + ns_debug(ns_log_default, 1, + "ns_req: answer -> %s fd=%d id=%d size=%d", + sin_ntoa(from), (qsp == NULL) ? dfd : qsp->s_rfd, + ntohs(hp->id), cp - msg); + if (debug >= 10) + fp_nquery(msg, cp - msg, log_get_stream(packet_channel)); +#endif /*DEBUG*/ + if (qsp == NULL) { + if (sendto(dfd, (char*)msg, cp - msg, 0, + (struct sockaddr *)&from, + sizeof(from)) < 0) { + if (!haveComplained(ina_ulong(from.sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, + "ns_req: sendto(%s): %s", + sin_ntoa(from), strerror(errno)); + nameserIncr(from.sin_addr, nssSendtoErr); + } + nameserIncr(from.sin_addr, nssSentAns); + if (hp->rcode == NXDOMAIN) + nameserIncr(from.sin_addr, nssSentNXD); + if (!hp->aa) + nameserIncr(from.sin_addr, nssSentNaAns); + } else + writestream(qsp, msg, cp - msg); + + /* Is now a safe time? */ + if (needs_prime_cache) + prime_cache(); +} + +#ifdef BIND_NOTIFY +int +findZonePri(const struct zoneinfo *zp, const struct sockaddr_in from) { + struct in_addr ina; + int i; + + ina = from.sin_addr; + for (i = 0; (u_int)i < zp->z_addrcnt; i++) + if (ina_equal(zp->z_addr[i], ina)) + return (i); + return (-1); +} + +static enum req_action +req_notify(HEADER *hp, u_char **cpp, u_char *eom, u_char *msg, + struct sockaddr_in from) +{ + int n, type, class, zn; + char dnbuf[MAXDNAME]; + struct namebuf *np; + const char *fname; + struct hashbuf *htp = hashtab; /* lookup relative to root */ + + /* valid notify's have one question and zero answers */ + if ((ntohs(hp->qdcount) != 1) + || ntohs(hp->ancount) != 0 + || ntohs(hp->nscount) != 0 + || ntohs(hp->arcount) != 0) { + ns_debug(ns_log_notify, 1, + "FORMERR Notify header counts wrong"); + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = FORMERR; + return (Finish); + } + + n = dn_expand(msg, eom, *cpp, dnbuf, sizeof dnbuf); + if (n < 0) { + ns_debug(ns_log_notify, 1, + "FORMERR Query expand name failed"); + hp->rcode = FORMERR; + return (Finish); + } + *cpp += n; + if (*cpp + 2 * INT16SZ > eom) { + ns_debug(ns_log_notify, 1, + "FORMERR notify too short"); + hp->rcode = FORMERR; + return (Finish); + } + GETSHORT(type, *cpp); + GETSHORT(class, *cpp); + ns_info(ns_log_notify, "rcvd NOTIFY(%s, %s, %s) from %s", + dnbuf, p_class(class), p_type(type), sin_ntoa(from)); + /* XXX - when answers are allowed, we'll need to do compression + * correctly here, and we will need to check for packet underflow. + */ + np = nlookup(dnbuf, &htp, &fname, 0); + if (!np) { + ns_info(ns_log_notify, + "rcvd NOTIFY for \"%s\", name not in cache", + dnbuf); + hp->rcode = SERVFAIL; + return (Finish); + } + zn = findMyZone(np, class); + if (zn == DB_Z_CACHE || zones[zn].z_type != z_slave) { + /* this can come if a user did an AXFR of some zone somewhere + * and that zone's server now wants to tell us that the SOA + * has changed. AXFR's always come from nonpriv ports so it + * isn't possible to know whether it was the server or just + * "dig". this condition can be avoided by using secure zones + * since that way only real secondaries can AXFR from you. + */ + ns_info(ns_log_notify, + "NOTIFY for non-secondary name (%s), from %s", + dnbuf, sin_ntoa(from)); + goto refuse; + } + if (findZonePri(&zones[zn], from) == -1) { + ns_info(ns_log_notify, + "NOTIFY from non-master server (zone %s), from %s", + zones[zn].z_origin, sin_ntoa(from)); + goto refuse; + } + switch (type) { + case T_SOA: + if (strcasecmp(dnbuf, zones[zn].z_origin) != 0) { + ns_info(ns_log_notify, + "NOTIFY(SOA) for non-origin (%s), from %s", + dnbuf, sin_ntoa(from)); + goto refuse; + } + if (zones[zn].z_flags & + (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL|Z_XFER_RUNNING)) { + ns_info(ns_log_notify, + "NOTIFY(SOA) for zone already xferring (%s)", + dnbuf); + goto noerror; + } + zones[zn].z_time = tt.tv_sec; + qserial_query(&zones[zn]); + sched_zone_maint(&zones[zn]); + break; + default: + /* unimplemented, but it's not a protocol error, just + * something to be ignored. + */ + break; + } + noerror: + hp->rcode = NOERROR; + return (Finish); + refuse: + hp->rcode = REFUSED; + return (Finish); +} +#endif /*BIND_NOTIFY*/ + +static enum req_action +req_query(HEADER *hp, u_char **cpp, u_char *eom, struct qstream *qsp, + int *buflenp, int *msglenp, u_char *msg, int dfd, + struct sockaddr_in from) +{ + int n, class, type, count, zone, foundname, founddata, omsglen, cname; + u_int16_t id; + u_char **dpp, *omsg, *answers; + char dnbuf[MAXDNAME], *dname; + const char *fname; + struct hashbuf *htp; + struct databuf *nsp[NSMAX]; + struct namebuf *np, *anp; + struct qinfo *qp; + struct zoneinfo *zp; + struct databuf *dp; + + nameserIncr(from.sin_addr, nssRcvdQ); + + nsp[0] = NULL; + dpp = dnptrs; + *dpp++ = msg; + *dpp = NULL; + /* + * Make gcc happy. + */ + omsglen = 0; + omsg = NULL; + id = 0; + + /* valid queries have one question and zero answers */ + if ((ntohs(hp->qdcount) != 1) + || ntohs(hp->ancount) != 0 + || ntohs(hp->nscount) != 0 + || ntohs(hp->arcount) != 0) { + ns_debug(ns_log_default, 1, + "FORMERR Query header counts wrong"); + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = FORMERR; + return (Finish); + } + + /* + * Get domain name, class, and type. + */ + if ((**cpp & INDIR_MASK) == 0) + *dpp++ = *cpp; /* remember name for compression */ + *dpp = NULL; + n = dn_expand(msg, eom, *cpp, dnbuf, sizeof dnbuf); + if (n < 0) { + ns_debug(ns_log_default, 1, + "FORMERR Query expand name failed"); + hp->rcode = FORMERR; + return (Finish); + } + *cpp += n; + if (*cpp + 2 * INT16SZ > eom) { + ns_debug(ns_log_default, 1, + "FORMERR Query message length short"); + hp->rcode = FORMERR; + return (Finish); + } + GETSHORT(type, *cpp); + GETSHORT(class, *cpp); + if (*cpp < eom) { + ns_debug(ns_log_default, 6, + "message length > received message"); + *msglenp = *cpp - msg; + } + + qtypeIncr(type); + + /* + * Process query. + */ + if (type == T_AXFR) { + /* Refuse request if not a TCP connection. */ + if (qsp == NULL) { + ns_info(ns_log_default, + "rejected UDP AXFR from %s for \"%s\"", + sin_ntoa(from), *dnbuf ? dnbuf : "."); + return (Refuse); + } + /* The position of this is subtle. */ + nameserIncr(from.sin_addr, nssRcvdAXFR); + hp->rd = 0; /* Recursion not possible. */ + } + *buflenp -= *msglenp; + count = 0; + founddata = 0; + dname = dnbuf; + cname = 0; + +#ifdef QRYLOG + if (qrylog) { + ns_info(ns_log_queries, "XX /%s/%s/%s", + inet_ntoa(from.sin_addr), + (dname[0] == '\0') ? "." : dname, + p_type(type)); + } +#endif /*QRYLOG*/ + + try_again: + foundname = 0; + ns_debug(ns_log_default, 1, "req: nlookup(%s) id %d type=%d class=%d", + dname, ntohs(hp->id), type, class); + htp = hashtab; /* lookup relative to root */ + if ((anp = np = nlookup(dname, &htp, &fname, 0)) == NULL) + fname = ""; + ns_debug(ns_log_default, 1, "req: %s '%s' as '%s' (cname=%d)", + np == NULL ? "missed" : "found", + dname, fname, cname); + +#ifdef YPKLUDGE + /* Some braindamaged resolver software will not + recognize internet addresses in dot notation and + send out address queries for "names" such as + 128.93.8.1. This kludge will prevent those + from flooding higher level servers. + We simply claim to be authoritative and that + the domain doesn't exist. + Note that we could return the address but we + don't do that in order to encourage that broken + software is fixed. + */ + + if (!np && type == T_A && class == C_IN && dname) { + struct in_addr ina; + + if (inet_aton(dname, &ina)) { + hp->rcode = NXDOMAIN; + hp->aa = 1; + ns_debug(ns_log_default, 3, + "ypkludge: hit as '%s'", dname); + return (Finish); + } + } +#endif /*YPKLUDGE*/ + + /* + * Begin Access Control Point + */ + + zone = DB_Z_CACHE; + if (np) { + struct namebuf *access_np; + + /* + * Find out which zone this will be answered from. Note + * that we look for a zone with the same class as ours. + * The np that we found in the database might not be the + * one we asked for (i.e. dname might not equal fname). This + * is OK, since if a name doesn't exist, we need to go up + * the tree until we find the closest enclosing zone that + * is of the same class. + */ + for (access_np = np; access_np != NULL; + access_np = np_parent(access_np)) { + dp = access_np->n_data; + while (dp && dp->d_class != class) + dp = dp->d_next; + if (dp != NULL) { + zone = dp->d_zone; + break; + } + } + } + + zp = &zones[zone]; + + /* + * Are queries allowed from this host? + */ + if (type != T_AXFR) { + ip_match_list query_acl; + + if (zp->z_query_acl != NULL) + query_acl = zp->z_query_acl; + else + query_acl = server_options->query_acl; + + if (query_acl != NULL + && !ip_address_allowed(query_acl, from.sin_addr)) { + ns_notice(ns_log_security, + "unapproved query from %s for \"%s\"", + sin_ntoa(from), *dname ? dname : "."); + return (Refuse); + } + } else { + ip_match_list transfer_acl; + + /* Do they have permission to do a zone transfer? */ + + if (zp->z_transfer_acl != NULL) + transfer_acl = zp->z_transfer_acl; + else + transfer_acl = server_options->transfer_acl; + + if (transfer_acl != NULL + && !ip_address_allowed(transfer_acl, from.sin_addr)) { + ns_notice(ns_log_security, + "unapproved AXFR from %s for \"%s\" (acl)", + sin_ntoa(from), *dname ? dname : "."); + return (Refuse); + } + + /* Are we authoritative? */ + + if ((zp->z_flags & Z_AUTH) == 0) { + ns_notice(ns_log_security, + "unapproved AXFR from %s for \"%s\" (not auth)", + sin_ntoa(from), *dname ? dname : "."); + return (Refuse); + } + + /* Is the name at a zone cut? */ + + if (strcasecmp(zp->z_origin, dname) != 0) { + ns_notice(ns_log_security, + "unapproved AXFR from %s for \"%s\" (not zone top)", + sin_ntoa(from), *dname ? dname : "."); + return (Refuse); + } + + ns_info(ns_log_security, "approved AXFR from %s for \"%s\"", + sin_ntoa(from), *dname ? dname : "."); + } + + /* + * End Access Control Point + */ + + /* + * Yow! + */ + if (!strcasecmp(dnbuf, "VERSION.BIND") && + class == C_CHAOS && type == T_TXT) { + u_char *tp; + + hp->ancount = htons(1); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = NOERROR; + hp->aa = 1; + hp->ra = 0; + copyCharString(cpp, "VERSION"); /* Name */ + copyCharString(cpp, "BIND"); + *(*cpp)++ = 0x00; + PUTSHORT(T_TXT, *cpp); /* Type */ + PUTSHORT(C_CHAOS, *cpp); /* Class */ + PUTLONG(0, *cpp); /* TTL */ + tp = *cpp; /* Temp RdLength */ + PUTSHORT(0, *cpp); + copyCharString(cpp, ShortVersion); + PUTSHORT((*cpp) - (tp + INT16SZ), tp); /* Real RdLength */ + *msglenp = *cpp - msg; /* Total message length */ + return (Finish); + } + + /* + * If we don't know anything about the requested name, + * go look for nameservers. + */ + if (!np || fname != dname) + goto fetchns; + + foundname++; + answers = *cpp; + count = *cpp - msg; + + /* Look for NXDOMAIN record with appropriate class + * if found return immediately + */ + for (dp = np->n_data; dp; dp = dp->d_next) { + if (!stale(dp) && (dp->d_rcode == NXDOMAIN) && + (dp->d_class == class)) { +#ifdef RETURNSOA + n = finddata(np, class, T_SOA, hp, &dname, + buflenp, &count); + if (n != 0) { + if (count) { + *cpp += n; + *buflenp -= n; + *msglenp += n; + hp->nscount = htons((u_int16_t)count); + } + if (hp->rcode == NOERROR_NODATA) { + /* this should not occur */ + hp->rcode = NOERROR; + return (Finish); + } + } +#endif + hp->rcode = NXDOMAIN; + /* + * XXX forcing AA all the time isn't right, but + * we have to work that way by default + * for compatibility with older servers. + */ + if (!NS_OPTION_P(OPTION_NONAUTH_NXDOMAIN)) + hp->aa = 1; + ns_debug(ns_log_default, 3, "NXDOMAIN aa = %d", + hp->aa); + return (Finish); + } + } + + /* + * If not NXDOMAIN, the NOERROR_NODATA record might be + * anywhere in the chain. Have to go through the grind. + */ + + n = finddata(np, class, type, hp, &dname, buflenp, &count); + if (n == 0) { + /* + * NO data available. Refuse AXFR requests, or + * look for better servers for other requests. + */ + if (type == T_AXFR) { + ns_debug(ns_log_default, 1, + "T_AXFR refused: no data"); + return (Refuse); + } + goto fetchns; + } + + if (hp->rcode == NOERROR_NODATA) { + hp->rcode = NOERROR; +#ifdef RETURNSOA + if (count) { + *cpp += n; + *buflenp -= n; + *msglenp += n; + hp->nscount = htons(count); + } +#endif + founddata = 1; + return (Finish); + } + + *cpp += n; + *buflenp -= n; + *msglenp += n; + hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count); + if (fname != dname && type != T_CNAME && type != T_ANY) { + if (cname++ >= MAXCNAMES) { + ns_debug(ns_log_default, 3, + "resp: leaving, MAXCNAMES exceeded"); + hp->rcode = SERVFAIL; + return (Finish); + } + goto try_again; + } + founddata = 1; + ns_debug(ns_log_default, 3, + "req: foundname=%d, count=%d, founddata=%d, cname=%d", + foundname, count, founddata, cname); + + if (type == T_AXFR) { + ns_xfr(qsp, np, zone, class, type, hp->opcode, ntohs(hp->id)); + return (Return); + } + + fetchns: + /* + * If we're already out of room in the response, we're done. + */ + if (hp->tc) + return (Finish); + + /* + * Look for name servers to refer to and fill in the authority + * section or record the address for forwarding the query + * (recursion desired). + */ + free_nsp(nsp); + nsp[0] = NULL; + count = 0; + switch (findns(&np, class, nsp, &count, 0)) { + case NXDOMAIN: + /* We are authoritative for this np. */ + if (!foundname) + hp->rcode = NXDOMAIN; + ns_debug(ns_log_default, 3, "req: leaving (%s, rcode %d)", + dname, hp->rcode); + if (class != C_ANY) { + hp->aa = 1; + if (np && (!foundname || !founddata)) { + n = doaddauth(hp, *cpp, *buflenp, np, nsp[0]); + *cpp += n; + *buflenp -= n; +#ifdef ADDAUTH + } else if (ntohs(hp->ancount) != 0) { + /* don't add NS records for NOERROR NODATA + as some servers can get confused */ + free_nsp(nsp); + switch (findns(&np, class, nsp, &count, 1)) { + case NXDOMAIN: + case SERVFAIL: + break; + default: + if (np && + (type != T_NS || np != anp) + ) { + n = add_data(np, nsp, *cpp, + *buflenp, &count); + if (n < 0) { + hp->tc = 1; + n = (-n); + } + *cpp += n; + *buflenp -= n; + hp->nscount = + htons((u_int16_t) + count); + } + } +#endif /*ADDAUTH*/ + } + } + free_nsp(nsp); + return (Finish); + + case SERVFAIL: + /* We're authoritative but the zone isn't loaded. */ + if (!founddata && + !(NS_OPTION_P(OPTION_FORWARD_ONLY) && + server_options->fwdtab)) { + hp->rcode = SERVFAIL; + free_nsp(nsp); + return (Finish); + } + } + + /* + * If we successfully found the answer in the cache, + * or this is not a recursive query, or we are purposely + * never recursing, then add the nameserver references + * ("authority section") here and we're done. + */ + if (founddata || !hp->rd || NS_OPTION_P(OPTION_NORECURSE)) { + /* + * If the qtype was NS, and the np of the authority is + * the same as the np of the data, we don't need to add + * another copy of the answer here in the authority + * section. + */ + if (!founddata || type != T_NS || anp != np) { + n = add_data(np, nsp, *cpp, *buflenp, &count); + if (n < 0) { + hp->tc = 1; + n = (-n); + } + *cpp += n; + *buflenp -= n; + hp->nscount = htons((u_int16_t)count); + } + free_nsp(nsp); + + /* Our caller will handle the Additional section. */ + return (Finish); + } + + /* + * At this point, we don't have the answer, but we do + * have some NS's to try. If the user would like us + * to recurse, create the initial query. If a cname + * is involved, we need to build a new query and save + * the old one in cmsg/cmsglen. + */ + if (cname) { + omsg = (u_char *)memget((unsigned) *msglenp); + if (omsg == NULL) { + ns_info(ns_log_default, "ns_req: Out Of Memory"); + hp->rcode = SERVFAIL; + free_nsp(nsp); + return (Finish); + } + id = hp->id; + omsglen = *msglenp; + memcpy(omsg, msg, omsglen); + n = res_mkquery(QUERY, dname, class, type, + NULL, 0, NULL, msg, + *msglenp + *buflenp); + if (n < 0) { + ns_info(ns_log_default, "res_mkquery(%s) failed", + dname); + hp->rcode = SERVFAIL; + free_nsp(nsp); + return (Finish); + } + *msglenp = n; + } + n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp, + dname, class, type, np, 0); + if (n != FW_OK && cname) + memput(omsg, omsglen); + switch (n) { + case FW_OK: + if (cname) { + qp->q_cname = cname; + qp->q_cmsg = omsg; + qp->q_cmsglen = omsglen; + qp->q_id = id; + } + break; + case FW_DUP: + break; /* Duplicate request dropped */ + case FW_NOSERVER: + /* + * Don't go into an infinite loop if + * the admin gave root NS records in the cache + * file without giving address records + * for the root servers. + */ + if (np) { + if (NAME(*np)[0] == '\0') { + ns_notice(ns_log_default, + "ns_req: no address for root server"); + hp->rcode = SERVFAIL; + free_nsp(nsp); + return (Finish); + } + for (dp = np->n_data; dp ; dp = dp->d_next) + if (dp->d_zone && match(dp, class, T_NS)) + break; + if (dp) { + /* + * we know the child zone exists but are + * missing glue. + * + * nslookup has called sysquery() to get the + * missing glue. + * + * for UDP, drop the response and let the + * client retry. for TCP, we should probably + * (XXX) hold open the TCP connection for a + * while in case the sysquery() comes back + * soon. meanwhile we SERVFAIL. + */ + if (qsp) + goto do_servfail; + break; + } + np = np_parent(np); + } + goto fetchns; /* Try again. */ + case FW_SERVFAIL: + do_servfail: + hp->rcode = SERVFAIL; + free_nsp(nsp); + return (Finish); + } + free_nsp(nsp); + return (Return); +} + +static enum req_action +req_iquery(HEADER *hp, u_char **cpp, u_char *eom, int *buflenp, + u_char *msg, struct sockaddr_in from) +{ + int dlen, alen, n, type, class, count; + char dnbuf[MAXDNAME], anbuf[PACKETSZ], *data, *fname; + + nameserIncr(from.sin_addr, nssRcvdIQ); + + if (ntohs(hp->ancount) != 1 + || ntohs(hp->qdcount) != 0 + || ntohs(hp->nscount) != 0 + || ntohs(hp->arcount) != 0) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery header counts wrong"); + hp->qdcount = htons(0); + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = FORMERR; + return (Finish); + } + + /* + * Skip domain name, get class, and type. + */ + if ((n = dn_skipname(*cpp, eom)) < 0) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery packet name problem"); + hp->rcode = FORMERR; + return (Finish); + } + *cpp += n; + if (*cpp + 3 * INT16SZ + INT32SZ > eom) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery message too short"); + hp->rcode = FORMERR; + return (Finish); + } + GETSHORT(type, *cpp); + GETSHORT(class, *cpp); + *cpp += INT32SZ; /* ttl */ + GETSHORT(dlen, *cpp); + *cpp += dlen; + if (*cpp != eom) { + ns_debug(ns_log_default, 1, + "FORMERR IQuery message length off"); + hp->rcode = FORMERR; + return (Finish); + } + + /* + * not all inverse queries are handled. + */ + switch (type) { + case T_A: + if (!NS_OPTION_P(OPTION_FAKE_IQUERY) || dlen != INT32SZ) + return (Refuse); + break; + default: + return (Refuse); + } + ns_debug(ns_log_default, 1, + "req: IQuery class %d type %d", class, type); + + fname = (char *)msg + HFIXEDSZ; + alen = (char *)*cpp - fname; + if ((size_t)alen > sizeof anbuf) + return (Refuse); + memcpy(anbuf, fname, alen); + data = anbuf + alen - dlen; + *cpp = (u_char *)fname; + *buflenp -= HFIXEDSZ; + count = 0; + +#ifdef QRYLOG + if (qrylog) { + char tmp[sizeof "255.255.255.255"]; + + strcpy(tmp, inet_ntoa(from.sin_addr)); + ns_info(ns_log_queries, "XX /%s/%s/-%s", + tmp, inet_ntoa(ina_get((u_char *)data)), + p_type(type)); + } +#endif /*QRYLOG*/ + + /* + * We can only get here if the option "fake-iquery" is on in the boot + * file. + * + * What we do here is send back a bogus response of "[dottedquad]". + * A better strategy would be to turn this into a PTR query, but that + * would legitimize inverse queries in a way they do not deserve. + */ + sprintf(dnbuf, "[%s]", inet_ntoa(ina_get((u_char *)data))); + *buflenp -= QFIXEDSZ; + n = dn_comp(dnbuf, *cpp, *buflenp, NULL, NULL); + if (n < 0) { + hp->tc = 1; + return (Finish); + } + *cpp += n; + PUTSHORT((u_int16_t)type, *cpp); + PUTSHORT((u_int16_t)class, *cpp); + *buflenp -= n; + count++; + + ns_debug(ns_log_default, 1, "req: IQuery %d records", count); + hp->qdcount = htons((u_int16_t)count); + if (alen > *buflenp) { + hp->tc = 1; + return (Finish); + } + memcpy(*cpp, anbuf, alen); + *cpp += alen; + return (Finish); +} + +/* + * Test a datum for validity and return non-zero if it is out of date. + */ +int +stale(struct databuf *dp) { + struct zoneinfo *zp = &zones[dp->d_zone]; + + switch (zp->z_type) { + + case z_master: + return (0); + +#ifdef STUBS + case z_stub: + /* root stub zones have DB_F_HINT set */ + if (dp->d_flags & DB_F_HINT) + return (0); + /* FALLTROUGH */ +#endif + case z_slave: + /* + * Check to see whether a secondary zone has expired or + * time warped; if so clear authority flag for zone, + * schedule the zone for immediate maintenance, and + * return true. + */ + if ((int32_t)(tt.tv_sec - zp->z_lastupdate) + > (int32_t)zp->z_expire) { + ns_debug(ns_log_default, 1, + "stale: secondary zone %s expired", + zp->z_origin); + if (!haveComplained((u_long)zp, (u_long)stale)) { + ns_notice(ns_log_default, + "secondary zone \"%s\" expired", + zp->z_origin); + } + zp->z_flags &= ~Z_AUTH; + if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))) { + zp->z_time = tt.tv_sec; + sched_zone_maint(zp); + } + return (1); + } + if (zp->z_lastupdate > tt.tv_sec) { + if (!haveComplained((u_long)zp, (u_long)stale)) { + ns_notice(ns_log_default, + "secondary zone \"%s\" time warp", + zp->z_origin); + } + zp->z_flags &= ~Z_AUTH; + if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))) { + zp->z_time = tt.tv_sec; + sched_zone_maint(zp); + } + return (1); + } + return (0); + + case z_hint: + if (dp->d_flags & DB_F_HINT || + dp->d_ttl >= (u_int32_t)tt.tv_sec) + return (0); + ns_debug(ns_log_default, 3, "stale: ttl %d %ld (x%lx)", + dp->d_ttl, (long)(dp->d_ttl - tt.tv_sec), + (u_long)dp->d_flags); + return (1); + + default: + /* FALLTHROUGH */ ; + + } + panic("stale: impossible condition", NULL); + /* NOTREACHED */ + return (0); /* Make gcc happy. */ +} + +/* + * Copy databuf into a resource record for replies. + * Return size of RR if OK, -1 if buffer is full. + */ +int +make_rr(const char *name, struct databuf *dp, u_char *buf, + int buflen, int doadd, u_char **comp_ptrs, u_char **edp) +{ + u_char *cp; + u_char *cp1, *sp; + struct zoneinfo *zp; + int32_t n; + int16_t type = dp->d_type; + u_int32_t ttl; +#ifdef BIND_UPDATE + u_int32_t serial; +#endif + + ns_debug(ns_log_default, 5, + "make_rr(%s, %lx, %lx, %d, %d) %d zone %d ttl %lu", + name, (u_long)dp, (u_long)buf, + buflen, doadd, dp->d_size, dp->d_zone, (u_long)dp->d_ttl); + + if (dp->d_rcode +#ifdef RETURNSOA + && dp->d_size == 0 +#endif + ) + panic("make_rr: impossible d_rcode value", NULL); + + zp = &zones[dp->d_zone]; + /* check for outdated RR before updating comp_ptrs[] by dn_comp() */ + if (zp->z_type == Z_CACHE) { + if ((dp->d_flags & DB_F_HINT) != 0 + || dp->d_ttl < (u_int32_t)tt.tv_sec) { + ttl = 0; + } else + ttl = dp->d_ttl - (u_int32_t) tt.tv_sec; + } else { + if (dp->d_ttl != USE_MINIMUM) + ttl = dp->d_ttl; + else + ttl = zp->z_minimum; /* really default */ + } + + buflen -= RRFIXEDSZ; + if (buflen < 0) + return (-1); +#ifdef RETURNSOA + if (dp->d_rcode) { + name = (char *)dp->d_data; + name += strlen(name) +1; + name += strlen(name) +1; + name += 5 * INT32SZ; + type = T_SOA; + } +#endif + if ((n = dn_comp(name, buf, buflen, comp_ptrs, edp)) < 0) + return (-1); + cp = buf + n; + buflen -= n; + if (buflen < 0) + return (-1); + PUTSHORT((u_int16_t)type, cp); + PUTSHORT((u_int16_t)dp->d_class, cp); + PUTLONG(ttl, cp); + sp = cp; + cp += INT16SZ; + switch (type) { + case T_CNAME: + case T_MG: + case T_MR: + case T_PTR: + n = dn_comp((char *)dp->d_data, cp, buflen, comp_ptrs, edp); + if (n < 0) + return (-1); + PUTSHORT((u_int16_t)n, sp); + cp += n; + break; + + case T_MB: + case T_NS: + /* Store domain name in answer */ + n = dn_comp((char *)dp->d_data, cp, buflen, comp_ptrs, edp); + if (n < 0) + return (-1); + PUTSHORT((u_int16_t)n, sp); + cp += n; + if (doadd) + addname((char*)dp->d_data, name, + type, dp->d_class); + break; + + case T_SOA: + case T_MINFO: + case T_RP: + cp1 = dp->d_data; + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + return (-1); + cp += n; + buflen -= type == T_SOA ? n + 5 * INT32SZ : n; + if (buflen < 0) + return (-1); + cp1 += strlen((char *)cp1) + 1; + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + return (-1); + cp += n; + if (type == T_SOA) { + cp1 += strlen((char *)cp1) + 1; +#ifdef BIND_UPDATE + if (zp->z_flags & Z_NEED_SOAUPDATE) + if (incr_serial(zp) < 0) + ns_error(ns_log_default, + "error updating serial number for %s from %d", + zp->z_origin, zp->z_serial); +#endif + n = 5 * INT32SZ; + memcpy(cp, cp1, n); + cp += n; + } + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + break; + + case T_NAPTR: + /* cp1 == our data/ cp == data of RR */ + cp1 = dp->d_data; + + /* copy order */ + buflen -= INT16SZ; + if (buflen < 0) + return (-1); + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* copy preference */ + buflen -= INT16SZ; + if (buflen < 0) + return (-1); + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Flags */ + n = *cp1++; + ns_debug(ns_log_default, 1, "size of n at flags = %d", n); + buflen -= n + 1; + if (buflen < 0) + return (-1); + *cp++ = n; + memcpy(cp, cp1, n); + cp += n; + cp1 += n; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Service */ + n = *cp1++; + buflen -= n + 1; + if (buflen < 0) + return (-1); + *cp++ = n; + memcpy(cp, cp1, n); + cp += n; + cp1 += n; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Regexp */ + n = *cp1++; + buflen -= n + 1; + if (buflen < 0) + return (-1); + *cp++ = n; + memcpy(cp, cp1, n); + cp += n; + cp1 += n; + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "current size n = %u", n); + + /* Replacement */ + ns_debug(ns_log_default, 1, "Replacement = %s", cp1); + n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp); + ns_debug(ns_log_default, 1, "dn_comp's n = %u", n); + if (n < 0) + return (-1); + cp += n; + + /* save data length */ + n = (u_int16_t)((cp - sp) - INT16SZ); + ns_debug(ns_log_default, 1, "saved size n = %u", n); + PUTSHORT((u_int16_t)n, sp); + + break; + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* cp1 == our data/ cp == data of RR */ + cp1 = dp->d_data; + + if ((buflen -= INT16SZ) < 0) + return (-1); + + /* copy preference */ + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + + if (type == T_SRV) { + buflen -= INT16SZ*2; + if (buflen < 0) + return (-1); + memcpy(cp, cp1, INT16SZ*2); + cp += INT16SZ*2; + cp1 += INT16SZ*2; + } + + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + return (-1); + cp += n; + + /* save data length */ + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + if (doadd) + addname((char*)cp1, name, type, dp->d_class); + break; + + case T_PX: + cp1 = dp->d_data; + + if ((buflen -= INT16SZ) < 0) + return (-1); + + /* copy preference */ + memcpy(cp, cp1, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + return (-1); + cp += n; + buflen -= n; + cp1 += strlen((char *)cp1) + 1; + n = dn_comp((char *)cp1, cp, buflen, comp_ptrs, edp); + if (n < 0) + return (-1); + cp += n; + + /* save data length */ + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + break; + + case T_SIG: + /* cp1 == our data; cp == data of target RR */ + cp1 = dp->d_data; + + /* first just copy over the type_covered, algorithm, */ + /* labels, orig ttl, two timestamps, and the footprint */ + if ((dp->d_size - 18) > buflen) + return (-1); /* out of room! */ + memcpy(cp, cp1, 18); + cp += 18; + cp1 += 18; + buflen -= 18; + + /* then the signer's name */ + n = dn_comp((char *)cp1, cp, buflen, NULL, NULL); + if (n < 0) + return (-1); + cp += n; + buflen -= n; + cp1 += strlen((char*)cp1)+1; + + /* finally, we copy over the variable-length signature */ + n = dp->d_size - (u_int16_t)((cp1 - dp->d_data)); + if (n > buflen) + return (-1); /* out of room! */ + memcpy(cp, cp1, n); + cp += n; + + /* save data length & return */ + n = (u_int16_t)((cp - sp) - INT16SZ); + PUTSHORT((u_int16_t)n, sp); + break; + + default: + if (dp->d_size > buflen) + return (-1); + memcpy(cp, dp->d_data, dp->d_size); + PUTSHORT((u_int16_t)dp->d_size, sp); + cp += dp->d_size; + } + return (cp - buf); +} + +static void +addname(const char *dname, const char *rname, + u_int16_t rtype, u_int16_t class) +{ + struct addinfo *ap; + int n; + + for (ap = addinfo, n = addcount; --n >= 0; ap++) + if (strcasecmp(ap->a_dname, dname) == 0) + return; + + /* add domain name to additional section */ + if (addcount < NADDRECS) { + addcount++; + ap->a_dname = savestr(dname, 1); + ap->a_rname = savestr(rname, 1); + ap->a_rtype = rtype; + ap->a_class = class; + } +} + +/* + * Lookup addresses for names in addinfo and put into the message's + * additional section. + */ +int +doaddinfo(HEADER *hp, u_char *msg, int msglen) { + struct namebuf *np; + struct databuf *dp; + struct addinfo *ap; + u_char *cp; + struct hashbuf *htp; + const char *fname; + int n, count; + + if (!addcount) + return (0); + + ns_debug(ns_log_default, 3, "doaddinfo() addcount = %d", addcount); + + if (hp->tc) { + ns_debug(ns_log_default, 4, + "doaddinfo(): tc already set, bailing"); + return (0); + } + + count = 0; + cp = msg; + for (ap = addinfo; --addcount >= 0; ap++) { + int foundany = 0, + foundcname = 0, + save_count = count, + save_msglen = msglen; + u_char *save_cp = cp; + + ns_debug(ns_log_default, 3, + "do additional \"%s\" (from \"%s\")", + ap->a_dname, ap->a_rname); + htp = hashtab; /* because "nlookup" stomps on arg. */ + np = nlookup(ap->a_dname, &htp, &fname, 0); + if (np == NULL || fname != ap->a_dname) + goto next_rr; + ns_debug(ns_log_default, 3, "found it"); + /* look for the data */ + delete_stale(np); + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_rcode) + continue; + if (match(dp, (int)ap->a_class, T_CNAME) || + match(dp, C_IN, T_CNAME)) { + foundcname++; + break; + } + if (!match(dp, (int)ap->a_class, T_A) && + !match(dp, C_IN, T_A) && + !match(dp, (int)ap->a_class, T_AAAA) && + !match(dp, C_IN, T_AAAA)) { + continue; + } + foundany++; + /* + * Should be smart and eliminate duplicate + * data here. XXX + */ + if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0, + dnptrs, dnptrs_end)) < 0) { + /* truncation in the additional-data section + * is not all that serious. we do not set TC, + * since the answer and authority sections are + * OK; however, since we're not setting TC we + * have to make sure that none of the RR's for + * this name go out (!TC implies that all + * {name,type} appearances are complete -- and + * since we only do A RR's here, the name is + * the key). vixie, 23apr93 + */ + ns_debug(ns_log_default, 5, + "addinfo: not enough room, remaining msglen = %d", + save_msglen); + cp = save_cp; + msglen = save_msglen; + count = save_count; + break; + } + ns_debug(ns_log_default, 5, + "addinfo: adding address data n = %d", n); + cp += n; + msglen -= n; + count++; + } + next_rr: + if (!NS_OPTION_P(OPTION_NOFETCHGLUE) && + !foundcname && !foundany) { + /* ask a real server for this info */ + (void) sysquery(ap->a_dname, (int)ap->a_class, T_A, + NULL, 0, QUERY); + } + if (foundcname) { + if (!haveComplained(nhash(ap->a_dname), + nhash(ap->a_rname))) { + ns_info(ns_log_cname, + "\"%s %s %s\" points to a CNAME (%s)", + ap->a_rname, p_class(ap->a_class), + p_type(ap->a_rtype), ap->a_dname); + } + } + freestr(ap->a_dname); + freestr(ap->a_rname); + } + hp->arcount = htons((u_int16_t)count); + return (cp - msg); +} + +int +doaddauth(HEADER *hp, u_char *cp, int buflen, + struct namebuf *np, struct databuf *dp) +{ + char dnbuf[MAXDNAME]; + int n; + + getname(np, dnbuf, sizeof dnbuf); + if (stale(dp)) { + ns_debug(ns_log_default, 1, + "doaddauth: can't add stale '%s' (%d)", + dnbuf, buflen); + return (0); + } + n = make_rr(dnbuf, dp, cp, buflen, 1, dnptrs, dnptrs_end); + if (n <= 0) { + ns_debug(ns_log_default, 1, + "doaddauth: can't add oversize '%s' (%d) (n=%d)", + dnbuf, buflen, n); + if (n < 0) { + hp->tc = 1; + } + return (0); + } + hp->nscount = htons(ntohs(hp->nscount) + 1); + return (n); +} + +void +free_addinfo() { + struct addinfo *ap; + + for (ap = addinfo; --addcount >= 0; ap++) { + freestr(ap->a_dname); + freestr(ap->a_rname); + } + addcount = 0; +} + +void +free_nsp(struct databuf **nsp) { + while (*nsp) { + DRCNTDEC(*nsp); + if ((*nsp)->d_rcnt) + ns_debug(ns_log_default, 3, "free_nsp: %s rcnt %d", + (*nsp)->d_data, (*nsp)->d_rcnt); + else { + ns_debug(ns_log_default, 3, + "free_nsp: %s rcnt %d delayed", + (*nsp)->d_data, (*nsp)->d_rcnt); + db_freedata(*nsp); /* delayed free */ + } + *nsp++ = NULL; + } +} + +static void +copyCharString(u_char **dst, const char *src) { + size_t len = strlen(src) & 0xff; + *(*dst)++ = (u_char) len; + memcpy(*dst, src, len); + *dst += len; +} diff --git a/contrib/bind/bin/named/ns_resp.c b/contrib/bind/bin/named/ns_resp.c new file mode 100644 index 0000000..012f89e --- /dev/null +++ b/contrib/bind/bin/named/ns_resp.c @@ -0,0 +1,3298 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)ns_resp.c 4.65 (Berkeley) 3/3/91"; +static char rcsid[] = "$Id: ns_resp.c,v 8.56 1998/03/16 19:40:07 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986, 1988, 1990 + * 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, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/file.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <limits.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +static u_int8_t norootlogged[MAXCLASS]; /* XXX- should be a bitmap */ + +static const char skipnameFailedAnswer[] = "skipname failed in answer", + skipnameFailedAuth[] = "skipname failed in authority", + skipnameFailedQuery[] = "skipname failed in query", + outofDataQuery[] = "ran out of data in query", + outofDataAnswer[] = "ran out of data in answer", + notSingleQuery[] = "not exactly one query", + expandFailedQuery[] = "dn_expand failed in query", + expandFailedAnswer[] = "dn_expand failed in answer", + expandFailedAuth[] = "dn_expand failed in authority", + outofDataAuth[] = "ran out of data in authority", + dlenOverrunAnswer[] = "dlen overrun in answer", + dlenOverrunAuth[] = "dlen overrun in authority", + dlenUnderrunAnswer[] = "dlen underrun in answer", + outofDataFinal[] = "out of data in final pass", + outofDataAFinal[] = "out of data after final pass", + badNameFound[] = "found an invalid domain name", + wrongQuestion[] = "answer to wrong question", + danglingCname[] = "dangling CNAME pointer"; + +struct db_list { + struct db_list *db_next; + struct databuf *db_dp; +}; + +struct flush_set { + char * fs_name; + int fs_type; + int fs_class; + u_int fs_cred; + struct db_list *fs_list; + struct db_list *fs_last; +}; + +static void rrsetadd(struct flush_set *, const char *, + struct databuf *), + rrsetupdate(struct flush_set *, int flags, + struct sockaddr_in), + flushrrset(struct flush_set *, struct sockaddr_in), + free_flushset(struct flush_set *, int); +static int rrsetcmp(char *, struct db_list *), + check_root(void), + check_ns(void), + rrextract(u_char *, int, u_char *, + struct databuf **, char *, int, + struct sockaddr_in, char **); +static void sysnotify_slaves(const char *, const char *, + int, int, int *, int *); +static void sysnotify_ns(const char *, const char *, + int, int, int *, int *); +static void add_related_additional(char *); +static void free_related_additional(void); +static int related_additional(char *); +static void freestr_maybe(char **); + +#define MAX_RELATED 100 + +static int num_related = 0; +static char *related[MAX_RELATED]; + +static char * +learntFrom(struct qinfo *qp, struct sockaddr_in *server) { + static char *buf = NULL; + char *a, *ns, *na; + struct databuf *db; + int i; + + a = ns = na = "<Not Available>"; + + for (i = 0; (u_int)i < qp->q_naddr; i++) { + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, + server->sin_addr)) { + db = qp->q_addr[i].ns; + if (db != NULL) { + if (NS_OPTION_P(OPTION_HOSTSTATS)) { + char nsbuf[20]; + + if (db->d_ns != NULL) { + strcpy(nsbuf, + inet_ntoa(db->d_ns->addr)); + ns = nsbuf; + } else { + ns = zones[db->d_zone] + .z_origin; + } + } + if (db->d_rcode == 0) + na = (char*)qp->q_addr[i].ns->d_data; + } + + if (NS_OPTION_P(OPTION_HOSTSTATS)) { + char abuf[20]; + + db = qp->q_addr[i].nsdata; + if (db != NULL) { + if (db->d_ns != NULL) { + strcpy(abuf, + inet_ntoa(db->d_ns->addr)); + a = abuf; + } else { + a = zones[db->d_zone].z_origin; + } + } + } + break; + } + } + + if (a == ns && ns == na) /* all "UNKNOWN" */ + return (NULL); + + if (*a == '\0') + a = "\".\""; + if (*ns == '\0') + ns = "\".\""; + if (*na == '\0') + na = "\".\""; + + if (NS_OPTION_P(OPTION_HOSTSTATS)) { + static const char fmt[] = " '%s': learnt (A=%s,NS=%s)"; + + buf = newstr(sizeof fmt + strlen(na) + strlen(a) + strlen(ns), + 0); + if (buf == NULL) + return (NULL); + sprintf(buf, fmt, na, a, ns); + } else { + static const char fmt[] = " '%s'"; + + buf = newstr(sizeof fmt + strlen(na), 0); + if (buf == NULL) + return (NULL); + sprintf(buf, fmt, na); + } + + return (buf); +} + +void +ns_resp(u_char *msg, int msglen, struct sockaddr_in from, struct qstream *qsp) { + struct qinfo *qp; + HEADER *hp; + struct qserv *qs; + struct databuf *ns, *ns2; + u_char *cp; + u_char *eom = msg + msglen; + struct flush_set *flushset = NULL; + int flushset_size = 0; + struct sockaddr_in *nsa; + struct databuf *nsp[NSMAX]; + int i, c, n, qdcount, ancount, aucount, nscount, arcount, arfirst; + u_int qtype, qclass; + int restart; /* flag for processing cname response */ + int validanswer, dbflags; + int cname, lastwascname, externalcname; + int count, founddata, foundname; + int buflen; + int newmsglen; + char name[MAXDNAME], qname[MAXDNAME], aname[MAXDNAME]; + char msgbuf[MAXDNAME]; + char *dname, tmpdomain[MAXDNAME]; + const char *fname; + const char *formerrmsg = "brain damage"; + u_char newmsg[PACKETSZ]; + u_char **dpp, *tp; + time_t rtrip; + struct hashbuf *htp; + struct namebuf *np; + struct fwdinfo *fwd; + struct databuf *dp; + int forcecmsg = 0; + char *tname = NULL; + + nameserIncr(from.sin_addr, nssRcvdR); + nsp[0] = NULL; + hp = (HEADER *) msg; + if ((qp = qfindid(hp->id)) == NULL ) { + ns_debug(ns_log_default, 1, "DUP? dropped (id %d)", + ntohs(hp->id)); + nameserIncr(from.sin_addr, nssRcvdDupR); + return; + } + + ns_debug(ns_log_default, 2, "Response (%s %s %s) nsid=%d id=%d", + (qp->q_flags & Q_SYSTEM) ?"SYSTEM" :"USER", + (qp->q_flags & Q_PRIMING) ?"PRIMING" :"NORMAL", + (qp->q_flags & Q_ZSERIAL) ?"ZSERIAL" :"-", + ntohs(qp->q_nsid), ntohs(qp->q_id)); + + /* + * Here we handle high level formatting problems by parsing the header. + */ + qdcount = ntohs(hp->qdcount); + ancount = ntohs(hp->ancount); + aucount = ntohs(hp->nscount); /* !!! */ + arcount = ntohs(hp->arcount); + free_addinfo(); /* sets addcount to zero */ + cp = msg + HFIXEDSZ; + dpp = dnptrs; + *dpp++ = msg; + if ((*cp & INDIR_MASK) == 0) + *dpp++ = cp; + *dpp = NULL; + if (qdcount == 1) { + n = dn_expand(msg, eom, cp, qname, sizeof(qname)); + if (n <= 0) { + formerrmsg = expandFailedQuery; + goto formerr; + } + cp += n; + if (cp + 2 * INT16SZ > eom) { + formerrmsg = outofDataQuery; + goto formerr; + } + GETSHORT(qtype, cp); + GETSHORT(qclass, cp); + if (!ns_nameok(qname, qclass, NULL, response_trans, + ns_ownercontext(qtype, response_trans), + qname, from.sin_addr)) { + formerrmsg = badNameFound; + goto refused; + } + if (cp > eom) { + formerrmsg = outofDataQuery; + goto formerr; + } + if (qp->q_msg && qp->q_msglen && + !res_nameinquery(qname, qtype, qclass, + qp->q_msg, qp->q_msg + qp->q_msglen)) { + sprintf(msgbuf, + "query section mismatch (%s %s %s)", + qname, p_class(qclass), p_type(qtype)); + formerrmsg = msgbuf; + goto formerr; + } + if (strcasecmp(qp->q_name, qname) != 0 || + qp->q_class != qclass || + qp->q_type != qtype) { + formerrmsg = wrongQuestion; + goto formerr; + } + } else { + strcpy(qname, qp->q_name); + qclass = qp->q_class; + qtype = qp->q_type; + } + + /* cp now points after the query section. */ + + /* + * Here we handle bad responses from servers. + * Several possibilities come to mind: + * The server is sick and returns SERVFAIL + * The server returns some garbage opcode (it's sick) + * The server can't understand our query and return FORMERR + * In all these cases, we drop the packet, disable retries on + * this server and immediately force a retry. + */ + if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN) + || (hp->opcode != QUERY +#ifdef BIND_NOTIFY + && hp->opcode != NS_NOTIFY_OP +#endif + )) { + ns_debug(ns_log_default, 2, + "resp: error (ret %d, op %d), dropped", + hp->rcode, hp->opcode); + switch (hp->rcode) { + case SERVFAIL: + nameserIncr(from.sin_addr, nssRcvdFail); + break; + case FORMERR: + nameserIncr(from.sin_addr, nssRcvdFErr); + break; + default: + nameserIncr(from.sin_addr, nssRcvdErr); + break; + } + /* mark server as bad */ + if (!qp->q_fwd) + for (i = 0; i < (int)qp->q_naddr; i++) + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, + from.sin_addr)) + qp->q_addr[i].nretry = MAXRETRY; + /* + * XXX: doesn't handle responses sent from the wrong + * interface on a multihomed server. + */ + if (qp->q_fwd || + ina_equal(qp->q_addr[qp->q_curaddr].ns_addr.sin_addr, + from.sin_addr)) + retry(qp); + return; + } + + if (qdcount != 1) { + /* We don't generate or forward these (yet). */ + formerrmsg = notSingleQuery; + goto formerr; + } + + /* + * Determine if the response came from a forwarder. Packets from + * anyplace not listed as a forwarder or as a server to whom we + * might have forwarded the query will be dropped. + * XXX - should put this in STATS somewhere. + */ + for (fwd = server_options->fwdtab; fwd; fwd = fwd->next) + if (ina_equal(fwd->fwdaddr.sin_addr, from.sin_addr)) + break; + /* + * XXX: note bad ambiguity here. if one of our forwarders is also + * a delegated server for some domain, then we will not update + * the RTT information on any replies we get from those servers. + * Workaround: disable recursion on authoritative servers so that + * the ambiguity does not arise. + */ + /* + * If we weren't using a forwarder, find the qinfo pointer and update + * the rtt and fact that we have called on this server before. + */ + if (fwd == NULL) { + struct timeval *stp; + + for (n = 0, qs = qp->q_addr; + (u_int)n < qp->q_naddr; + n++, qs++) + if (ina_equal(qs->ns_addr.sin_addr, from.sin_addr)) + break; + if ((u_int)n >= qp->q_naddr) { + if (!haveComplained(ina_ulong(from.sin_addr), + (u_long)"unexpected source")) { + ns_info(ns_log_default, + "Response from unexpected source (%s)", + sin_ntoa(from)); + } + /* + * We don't know who this response came from so it + * gets dropped on the floor. + */ + return; + } + stp = &qs->stime; + + /* Handle response from different (untried) interface. */ + if ((qs->ns != NULL) && (stp->tv_sec == 0)) { + ns = qs->ns; + while (qs > qp->q_addr + && (qs->stime.tv_sec == 0 || qs->ns != ns)) + qs--; + *stp = qs->stime; + /* XXX - sometimes stp still ends up pointing to + * a zero timeval, in spite of the above attempt. + * Why? What should we do about it? + */ + /* XXX - catch aliases here */ + } + + /* compute query round trip time */ + /* XXX - avoid integer overflow, which is quite likely if stp + * points to a zero timeval (see above). + * rtrip is of type time_t, which we assume is at least + * as big as an int. + */ + if ((tt.tv_sec - stp->tv_sec) > (INT_MAX-999)/1000) { + rtrip = INT_MAX; + } else { + rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 + + (tt.tv_usec - stp->tv_usec) / 1000); + } + + ns_debug(ns_log_default, 3, + "stime %lu/%lu now %lu/%lu rtt %ld", + (u_long)stp->tv_sec, (u_long)stp->tv_usec, + (u_long)tt.tv_sec, (u_long)tt.tv_usec, + (long)rtrip); + + /* prevent floating point overflow, limit to 1000 sec */ + if (rtrip > 1000000) { + rtrip = 1000000; + } + ns = qs->nsdata; + /* + * Don't update nstime if this doesn't look + * like an address databuf now. XXX + */ + if (ns && + ns->d_type == T_A && + ns->d_class == qs->ns->d_class) { + u_long t; + + if (ns->d_nstime == 0) + t = rtrip; + else + t = ns->d_nstime * ALPHA + + + (1 - ALPHA) * rtrip; + if (t > 65535) + t = 65535; + ns->d_nstime = (u_int16_t)t; + } + + /* + * Record the source so that we do not use this NS again. + */ + if (ns && qs->ns && (qp->q_nusedns < NSMAX)) { + qp->q_usedns[qp->q_nusedns++] = qs->ns; + ns_debug(ns_log_default, 2, + "NS #%d addr %s used, rtt %d", + n, sin_ntoa(qs->ns_addr), ns->d_nstime); + } + + /* + * Penalize those who had earlier chances but failed + * by multiplying round-trip times by BETA (>1). + * Improve nstime for unused addresses by applying GAMMA. + * The GAMMA factor makes unused entries slowly + * improve, so they eventually get tried again. + * GAMMA should be slightly less than 1. + * Watch out for records that may have timed out + * and are no longer the correct type. XXX + */ + + for (n = 0, qs = qp->q_addr; + (u_int)n < qp->q_naddr; + n++, qs++) { + u_long t; + + ns2 = qs->nsdata; + if (!ns2 || ns2 == ns) + continue; + if (ns2->d_type != T_A || + ns2->d_class != qs->ns->d_class) /* XXX */ + continue; + if (qs->stime.tv_sec) { + if (ns2->d_nstime == 0) + t = (rtrip * BETA); + else + t = ns2->d_nstime * BETA + + + (1 - ALPHA) * rtrip; + } else + t = ns2->d_nstime * GAMMA; + if (t > 65535) + t = 65535; + ns2->d_nstime = (u_int16_t)t; + ns_debug(ns_log_default, 2, "NS #%d %s rtt now %d", n, + sin_ntoa(qs->ns_addr), + ns2->d_nstime); + } + } + +#ifdef BIND_NOTIFY + /* + * For now, NOTIFY isn't defined for ANCOUNT!=0, AUCOUNT!=0, + * or ADCOUNT!=0. Therefore the only real work to be done for + * a NOTIFY-QR is to remove it from the query queue. + */ + if (hp->opcode == NS_NOTIFY_OP) { + qremove(qp); + return; + } +#endif + + /* + * Non-authoritative, no answer, no error, with referral. + */ + if (hp->rcode == NOERROR && !hp->aa && ancount == 0 && aucount > 0 +#ifdef BIND_NOTIFY + && hp->opcode != NS_NOTIFY_OP +#endif + ) { + u_char *tp; + int type, class; +#ifdef DEBUG + if (debug > 0) + fp_nquery(msg, msglen, log_get_stream(packet_channel)); +#endif + /* + * Since there is no answer section (ancount == 0), + * we must be pointing at the authority section (aucount > 0). + */ + tp = cp; + n = dn_expand(msg, eom, tp, name, sizeof name); + if (n < 0) { + formerrmsg = expandFailedAuth; + goto formerr; + } + tp += n; + if (tp + 2 * INT16SZ > eom) { + formerrmsg = outofDataAuth; + goto formerr; + } + GETSHORT(type, tp); + GETSHORT(class, tp); + if (!ns_nameok(name, class, NULL, response_trans, + ns_ownercontext(type, response_trans), + name, from.sin_addr)) { + formerrmsg = badNameFound; + goto refused; + } + + /* + * If the answer delegates us either to the same level in + * the hierarchy or closer to the root, we consider this + * server lame. Note that for now we only log the message + * if the T_NS was C_IN, which is technically wrong (NS is + * visible in all classes) but necessary anyway (non-IN + * classes tend to not have good strong delegation graphs). + */ + + if (type == T_NS && samedomain(qp->q_domain, name)) { + nameserIncr(from.sin_addr, nssRcvdLDel); + /* mark server as bad */ + if (!qp->q_fwd) + for (i = 0; i < (int)qp->q_naddr; i++) + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, + from.sin_addr)) + qp->q_addr[i].nretry = MAXRETRY; + if (class == C_IN && + !haveComplained(ina_ulong(from.sin_addr), + nhash(qp->q_domain))) { + char *learnt_from = learntFrom(qp, &from); + + ns_info(ns_log_lame_servers, + "Lame server on '%s' (in '%s'?): %s%s", + qname, qp->q_domain, + sin_ntoa(from), + (learnt_from == NULL) ? "" : + learnt_from); + if (learnt_from != NULL) + freestr(learnt_from); + } + + /* XXX - doesn't handle responses sent from the wrong + * interface on a multihomed server + */ + if (qp->q_fwd || + ina_equal(qp->q_addr[qp->q_curaddr].ns_addr.sin_addr, + from.sin_addr)) + retry(qp); + return; + } + } + + if (qp->q_flags & Q_ZSERIAL) { + if (hp->aa && ancount > 0 && hp->rcode == NOERROR && + qtype == T_SOA && ((qclass == C_IN) || (qclass == C_HS))) + { + int n; + u_int type, class, dlen; + u_int32_t serial; + u_char *tp = cp; + u_char *rdatap; + + n = dn_expand(msg, eom, tp, name, sizeof name); + if (n < 0) { + formerrmsg = expandFailedAnswer; + goto formerr; + } + tp += n; /* name */ + if (tp + 3 * INT16SZ + INT32SZ > eom) { + formerrmsg = outofDataAnswer; + goto formerr; + } + GETSHORT(type, tp); /* type */ + GETSHORT(class, tp); /* class */ + tp += INT32SZ; /* ttl */ + GETSHORT(dlen, tp); /* dlen */ + rdatap = tp; /* start of rdata */ + if (!ns_nameok(name, class, NULL, response_trans, + ns_ownercontext(type, response_trans), + name, from.sin_addr)) { + formerrmsg = badNameFound; + goto refused; + } + if (strcasecmp(qname, name) || + qtype != type || + qclass != class) { + sprintf(msgbuf, + "qserial answer mismatch (%s %s %s)", + name, p_class(class), p_type(type)); + formerrmsg = msgbuf; + goto formerr; + } + if (0 >= (n = dn_skipname(tp, eom))) { + formerrmsg = skipnameFailedAnswer; + goto formerr; + } + tp += n; /* mname */ + if (0 >= (n = dn_skipname(tp, eom))) { + formerrmsg = skipnameFailedAnswer; + goto formerr; + } + tp += n; /* rname */ + if (tp + 5 * INT32SZ > eom) { + formerrmsg = dlenUnderrunAnswer; + goto formerr; + } + GETLONG(serial, tp); + tp += 4 * INT32SZ; /* Skip rest of SOA. */ + if ((u_int)(tp - rdatap) != dlen) { + formerrmsg = dlenOverrunAnswer; + goto formerr; + } + + qserial_answer(qp, serial, from); + qremove(qp); + } else { + retry(qp); + } + return; + } + + /* + * Add the info received in the response to the data base. + */ + arfirst = ancount + aucount; + c = arfirst + arcount; + + /* -ve $ing non-existence of record, must handle non-authoritative + * NOERRORs with c == 0. + */ + if (!hp->aa && hp->rcode == NOERROR && c == 0) + goto return_msg; + + if (qp->q_flags & Q_SYSTEM) + dbflags = DB_NOTAUTH | DB_NODATA; + else + dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS; + count = c; + if (qp->q_flags & Q_PRIMING) + dbflags |= DB_PRIMING; + if (hp->tc) { + count -= arcount; /* truncation had to affect this */ + if (!arcount) { + count -= aucount; /* guess it got this too */ + } + if (!(arcount || aucount)) { + count -= ancount; /* things are pretty grim */ + } + + /* retry using tcp provided this was not a tcp query */ + if (!(qp->q_flags & Q_USEVC)) { + qp->q_flags |= Q_USEVC; + unsched(qp); + schedretry(qp, 60); + if (tcp_send(qp) != NOERROR) + /* + * We're probably in trouble if tcp_send + * failed, but we'll try to press on because + * there isn't anything else to do. + */ + retry(qp); + return; + } else if (!qsp) { + /* outstanding udp response */ + return; + } + + /* XXX truncated tcp response */ + ns_error(ns_log_default, + "ns_resp: TCP truncated: \"%s\" %s %s", + qname, p_class(qclass), p_type(qtype)); + /* mark this server as bad */ + if (!qp->q_fwd) + for (i = 0; i < (int)qp->q_naddr; i++) + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, + from.sin_addr)) + qp->q_addr[i].nretry = MAXRETRY; + + /* try another server, it may have a bigger write buffer */ + retry(qp); + return; + } + + tp = cp; + + restart = 0; + validanswer = 0; + nscount = 0; + cname = 0; + lastwascname = 0; + externalcname = 0; + strcpy(aname, qname); + + if (count) { + /* allocate 1 extra record for end of set detection */ + flushset_size = (count + 1) * sizeof *flushset; + flushset = memget(flushset_size); + if (flushset == NULL) + panic("flushset: out of memory", NULL); + memset(flushset, 0, flushset_size); + } else + flushset = NULL; + + for (i = 0; i < count; i++) { + struct databuf *dp; + int type; + + freestr_maybe(&tname); + if (cp >= eom) { + free_related_additional(); + if (flushset != NULL) + free_flushset(flushset, flushset_size); + formerrmsg = outofDataFinal; + goto formerr; + } + n = rrextract(msg, msglen, cp, &dp, name, sizeof name, from, + &tname); + if (n < 0) { + free_related_additional(); + freestr_maybe(&tname); + if (flushset != NULL) + free_flushset(flushset, flushset_size); + formerrmsg = outofDataFinal; + if (hp->rcode == REFUSED) + goto refused; + else + goto formerr; + } + cp += n; + if (!dp) + continue; + type = dp->d_type; + if (i < ancount) { + /* Answer section. */ + if (externalcname || strcasecmp(name, aname) != 0) { + if (!externalcname) + ns_info(ns_log_resp_checks, + "wrong ans. name (%s != %s)", + name[0] ? name : ".", + aname[0] ? aname : "."); + else + ns_debug(ns_log_resp_checks, 3, + "ignoring answer '%s' after external cname", + name); + db_freedata(dp); + continue; + } + if (type == T_CNAME && + qtype != T_CNAME && qtype != T_ANY) { + strcpy(aname, (char *)dp->d_data); + if (!samedomain(aname, qp->q_domain)) + externalcname = 1; + cname++; + lastwascname = 1; + } else { + validanswer = 1; + lastwascname = 0; + } + + if (tname != NULL) { + add_related_additional(tname); + tname = NULL; + } + + dp->d_cred = (hp->aa && !strcasecmp(name, qname)) + ? DB_C_AUTH + : DB_C_ANSWER; + } else { + /* After answer section. */ + if (lastwascname) { + ns_debug(ns_log_resp_checks, 3, + "last was cname, ignoring auth. and add."); + db_freedata(dp); + break; + } + if (i < arfirst) { + /* Authority section. */ + switch (type) { + case T_NS: + case T_SOA: + if (!samedomain(aname, name)){ + ns_info(ns_log_resp_checks, + "bad referral (%s !< %s)", + aname[0] ? aname : ".", + name[0] ? name : "."); + db_freedata(dp); + continue; + } else if (!samedomain(name, + qp->q_domain)) { + if (!externalcname) + ns_info(ns_log_resp_checks, + "bad referral (%s !< %s)", + name[0] ? name : ".", + qp->q_domain[0] ? + qp->q_domain : "."); + db_freedata(dp); + continue; + } + if (type == T_NS) { + nscount++; + add_related_additional(tname); + tname = NULL; + } + break; + case T_NXT: + /* XXX check */ + break; + case T_SIG: + /* XXX check that it relates to an + NS or SOA or NXT */ + break; + default: + ns_info(ns_log_resp_checks, + "invalid RR type '%s' in authority section (name = '%s') from %s", + p_type(type), name, + sin_ntoa(from)); + db_freedata(dp); + continue; + } + } else { + /* Additional section. */ + switch (type) { + case T_A: + case T_AAAA: + if (externalcname || + !samedomain(name, qp->q_domain)) { + ns_debug(ns_log_resp_checks, 3, + "ignoring additional info '%s' type %s", + name, p_type(type)); + db_freedata(dp); + continue; + } + if (!related_additional(name)) { + ns_info(ns_log_resp_checks, + "unrelated additional info '%s' type %s from %s", + name, p_type(type), + sin_ntoa(from)); + db_freedata(dp); + continue; + } + break; + case T_KEY: + /* XXX check? */ + break; + case T_SIG: + /* + * XXX a SIG RR should relate + * to some other RR in this section, + * although if it's the last RR + * it might be a transaction signature. + */ + break; + default: + ns_info(ns_log_resp_checks, + "invalid RR type '%s' in additional section (name = '%s') from %s", + p_type(type), name, + sin_ntoa(from)); + db_freedata(dp); + continue; + } + } + dp->d_cred = (qp->q_flags & Q_PRIMING) + ? DB_C_ANSWER + : DB_C_ADDITIONAL; + } + rrsetadd(flushset, name, dp); + } + free_related_additional(); + freestr_maybe(&tname); + if (flushset != NULL) { + rrsetupdate(flushset, dbflags, from); + free_flushset(flushset, flushset_size); + } + if (lastwascname && !externalcname) + ns_info(ns_log_cname, "%s (%s)", danglingCname, aname); + + if (cp > eom) { + formerrmsg = outofDataAFinal; + goto formerr; + } + + if ((qp->q_flags & Q_SYSTEM) && ancount) { + if ((qp->q_flags & Q_PRIMING) && !check_root()) { + /* mark server as bad */ + if (!qp->q_fwd) + for (i = 0; i < (int)qp->q_naddr; i++) + if (ina_equal(qp->q_addr[i].ns_addr.sin_addr, + from.sin_addr)) + qp->q_addr[i].nretry = MAXRETRY; + /* XXX - doesn't handle responses sent from + * the wronginterface on a multihomed server + */ + if (qp->q_fwd || + qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr + == from.sin_addr.s_addr) + retry(qp); + return; + } + ns_debug(ns_log_default, 3, + "resp: leaving, SYSQUERY ancount %d", ancount); +#ifdef BIND_NOTIFY + if (qp->q_notifyzone != DB_Z_CACHE) { + struct zoneinfo *zp = &zones[qp->q_notifyzone]; + + /* Clear this first since sysnotify() might set it. */ + qp->q_notifyzone = DB_Z_CACHE; + sysnotify(zp->z_origin, zp->z_class, ns_t_soa); + } +#endif + qremove(qp); + return; + } + + if (ancount && count && !validanswer) { + /* + * Everything passed validation but we didn't get the + * final answer. The response must have contained + * a dangling CNAME. Force a restart of the query. + * + * Don't set restart if count==0, since this means + * the response was truncated in the answer section, + * causing us to set count to 0 which will cause + * validanswer to be 0 as well even though the answer + * section probably contained valid RRs (just not + * a complete set). + * XXX - this works right if we can just forward this + * response to the client, but not if we found a CNAME + * in a prior response and restarted the query. + */ + restart = 1; + } + + /* + * An answer to a T_ANY query or a successful answer to a + * regular query with no indirection, then just return answer. + */ + if (!restart && ancount && (qtype == T_ANY || !qp->q_cmsglen)) { + ns_debug(ns_log_default, 3, + "resp: got as much answer as there is"); + goto return_msg; + } + + /* + * We might want to cache this negative answer. + * + * if ancount != 0 and rcode == NOERROR we cannot determine if the + * CNAME chain has been processed to completion or not, so just + * restart the query. DNS needs a NODATA return code! + */ + if (((hp->rcode == NXDOMAIN) && (cname == ancount)) || + ((hp->rcode == NOERROR) && (ancount == 0) && (nscount == 0))) + { + cache_n_resp(msg, msglen, from); + + if (!qp->q_cmsglen) { + ns_debug(ns_log_default, 3, + "resp: leaving NO: auth = %d", hp->aa); + goto return_msg; + } + forcecmsg = 1; + } + + /* + * All messages in here need further processing. i.e. they + * are either CNAMEs or we got referred again. + */ + count = 0; + founddata = 0; + dname = name; + /* + * If restart==0 and ancount > 0, we should + * have some valid data because because the data in the answer + * section is owned by the query name and that passes the + * validation test by definition + * + * XXX - the restart stuff doesn't work if any of the answer RRs + * is not cacheable (TTL==0 or unknown RR type), since all of the + * answer must pass through the cache and be re-assembled. + */ + if ((forcecmsg && qp->q_cmsglen) || + ((!restart || !cname) && qp->q_cmsglen && ancount)) { + ns_debug(ns_log_default, 1, "Cname second pass"); + newmsglen = MIN(PACKETSZ, qp->q_cmsglen); + memcpy(newmsg, qp->q_cmsg, newmsglen); + } else { + newmsglen = MIN(PACKETSZ, msglen); + memcpy(newmsg, msg, newmsglen); + } + hp = (HEADER *) newmsg; + hp->ancount = htons(0); + hp->nscount = htons(0); + hp->arcount = htons(0); + hp->rcode = NOERROR; + dnptrs[0] = newmsg; + dnptrs[1] = NULL; + cp = newmsg + HFIXEDSZ; + /* + * Keep in mind that none of this code works when QDCOUNT>1. + * cp ends up pointed just past the query section in both cases. + */ + /* + * Arrange for dname to contain the query name. The query + * name can be either the original query name if restart==0 + * or the target of the last CNAME if we are following a + * CNAME chain and were referred. + */ + n = dn_expand(newmsg, newmsg + newmsglen, cp, dname, sizeof name); + if (n < 0) { + ns_debug(ns_log_default, 1, "dn_expand failed"); + goto servfail; + } + if (!res_dnok(dname)) { + ns_debug(ns_log_default, 1, "bad name (%s)", dname); + goto servfail; + } + cp += n + QFIXEDSZ; + buflen = sizeof(newmsg) - (cp - newmsg); + + cname = 0; + + try_again: + ns_debug(ns_log_default, 1, "resp: nlookup(%s) qtype=%d", dname, + qtype); + foundname = 0; + fname = ""; + htp = hashtab; /* lookup relative to root */ + np = nlookup(dname, &htp, &fname, 0); + ns_debug(ns_log_default, 1, "resp: %s '%s' as '%s' (cname=%d)", + np == NULL ? "missed" : "found", dname, fname, cname); + if (np == NULL || fname != dname) + goto fetch_ns; + + foundname++; + count = cp - newmsg; + /* + * Look for NXDOMAIN record. + */ + for (dp = np->n_data; dp; dp = dp->d_next) { + if (!stale(dp) && (dp->d_rcode == NXDOMAIN) && + (dp->d_class == (int)qclass)) { +#ifdef RETURNSOA + n = finddata(np, qclass, T_SOA, hp, &dname, + &buflen, &count); + if ( n != 0) { + if (count) { + cp += n; + buflen -= n; + newmsglen += n; + hp->nscount = htons((u_int16_t)count); + } + if (hp->rcode == NOERROR_NODATA) { + hp->rcode = NOERROR; + goto return_newmsg; + } + } +#endif + hp->rcode = NXDOMAIN; + /* + * XXX forcing AA all the time isn't right, but + * we have to work that way by default + * for compatibility with older servers. + */ + if (!NS_OPTION_P(OPTION_NONAUTH_NXDOMAIN)) + hp->aa = 1; + ns_debug(ns_log_default, 3, "resp: NXDOMAIN aa = %d", + hp->aa); + goto return_newmsg; + } + } + n = finddata(np, qclass, qtype, hp, &dname, &buflen, &count); + if (n == 0) + goto fetch_ns; /* NO data available */ + if (hp->rcode) { + if (hp->rcode == NOERROR_NODATA) + hp->rcode = NOERROR; +#ifdef RETURNSOA + if (count) { + cp += n; + buflen -= n; + hp->nscount = htons((u_int16_t)count); + } +#endif + goto return_newmsg; + } + cp += n; + buflen -= n; + hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count); + if (fname != dname && qtype != T_CNAME && qtype != T_ANY) { + cname++; + goto try_again; + } + founddata = 1; + + ns_debug(ns_log_default, 3, + "resp: foundname=%d, count=%d, founddata=%d, cname=%d", + foundname, count, founddata, cname); + + fetch_ns: + if (hp->tc) + goto return_newmsg; + + /* + * Look for name servers to refer to and fill in the authority + * section or record the address for forwarding the query + * (recursion desired). + */ + free_nsp(nsp); + switch (findns(&np, qclass, nsp, &count, 0)) { + case NXDOMAIN: /* shouldn't happen */ + ns_debug(ns_log_default, 3, "req: leaving (%s, rcode %d)", + dname, hp->rcode); + if (!foundname) + hp->rcode = NXDOMAIN; + if (qclass != C_ANY) { + hp->aa = 1; + if (np && (!foundname || !founddata)) { + n = doaddauth(hp, cp, buflen, np, nsp[0]); + cp += n; + buflen -= n; + } + } + goto return_newmsg; + + case SERVFAIL: + goto servfail; + } + + if (founddata) { + hp = (HEADER *)newmsg; + n = add_data(np, nsp, cp, buflen, &count); + if (n < 0) { + hp->tc = 1; + n = (-n); + } + cp += n; + buflen -= n; + hp->nscount = htons((u_int16_t)count); + goto return_newmsg; + } + + /* + * If we get here, we don't have the answer yet and are about + * to iterate to try and get it. First, infinite loop avoidance. + */ + if (qp->q_nqueries++ > MAXQUERIES) { + ns_debug(ns_log_default, 1, + "resp: MAXQUERIES exceeded (%s %s %s)", + dname, p_class(qclass), p_type(qtype)); + ns_info(ns_log_default, + "MAXQUERIES exceeded, possible data loop in resolving (%s)", + dname); + goto servfail; + } + + /* Reset the query control structure */ + + ns_freeqns(qp, "ns_resp"); + qp->q_naddr = 0; + qp->q_curaddr = 0; + qp->q_fwd = server_options->fwdtab; + + if (qp->q_domain != NULL) + freestr(qp->q_domain); + getname(np, tmpdomain, sizeof tmpdomain); + qp->q_domain = savestr(tmpdomain, 1); + + if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) { + if (n < 0) { + ns_debug(ns_log_default, 3, + "resp: nslookup reports danger"); + if (cname) /* a remote CNAME that does not have data */ + goto return_newmsg; + goto servfail; + } else { + ns_debug(ns_log_default, 3, + "resp: no addrs found for NS's"); + /* + * Timeout while sysquery looks up the NS addresses. + * + * Hopefully we'll have them when the client asks + * again. + * + * too bad we can't just wait for the sysquery + * response to restart this query (it's too hard). + * + * We could try to crawl back up the tree looking + * for reachable servers, but we may have just + * gotten delegated down here by a response with + * no A RRs for the servers. If we blindly tried + * this strategy, we bang on the same server forever. + */ + goto timeout; + } + } + for (n = 0; (u_int)n < qp->q_naddr; n++) + qp->q_addr[n].stime.tv_sec = 0; + if (!qp->q_fwd) + qp->q_addr[0].stime = tt; + if (cname) { + if (qp->q_cname++ == MAXCNAMES) { + ns_debug(ns_log_default, 3, + "resp: leaving, MAXCNAMES exceeded"); + goto servfail; + } + ns_debug(ns_log_default, 1, "q_cname = %d", qp->q_cname); + ns_debug(ns_log_default, 3, + "resp: building recursive query; nslookup"); + if (qp->q_cmsg == NULL) { + qp->q_cmsg = qp->q_msg; + qp->q_cmsglen = qp->q_msglen; + qp->q_cmsgsize = qp->q_msgsize; + } else if (qp->q_msg != NULL) + memput(qp->q_msg, qp->q_msgsize); + qp->q_msg = (u_char *)memget(PACKETSZ); + if (qp->q_msg == NULL) { + ns_notice(ns_log_default, "resp: memget error"); + goto servfail; + } + qp->q_msgsize = PACKETSZ; + n = res_mkquery(QUERY, dname, qclass, qtype, + NULL, 0, NULL, qp->q_msg, PACKETSZ); + if (n < 0) { + ns_info(ns_log_default, "resp: res_mkquery(%s) failed", + dname); + goto servfail; + } + if (qp->q_name != NULL) + freestr(qp->q_name); + qp->q_name = savestr(dname, 1); + qp->q_msglen = n; + hp = (HEADER *) qp->q_msg; + hp->rd = 0; + } else + hp = (HEADER *) qp->q_msg; + hp->id = qp->q_nsid = htons(nsid_next()); + if (qp->q_fwd) + hp->rd = 1; + unsched(qp); + schedretry(qp, retrytime(qp)); + nsa = Q_NEXTADDR(qp, 0); + ns_debug(ns_log_default, 1, + "resp: forw -> %s ds=%d nsid=%d id=%d %dms", + sin_ntoa(*nsa), ds, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (qp->q_addr[0].nsdata != NULL) + ? qp->q_addr[0].nsdata->d_nstime + : -1); +#ifdef DEBUG + if (debug >= 10) + fp_nquery(qp->q_msg, qp->q_msglen, + log_get_stream(packet_channel)); +#endif + if (qp->q_flags & Q_USEVC) { + if (tcp_send(qp) != NOERROR) { + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)tcpsendStr)) + ns_info(ns_log_default, + "ns_forw: tcp_send(%s) failed: %s", + sin_ntoa(*nsa), strerror(errno)); + } + } else if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0, + (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) + { + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, "ns_resp: sendto(%s): %s", + sin_ntoa(*nsa), strerror(errno)); + nameserIncr(nsa->sin_addr, nssSendtoErr); + } + hp->rd = 0; /* leave set to 0 for dup detection */ + nameserIncr(nsa->sin_addr, nssSentFwdR); + nameserIncr(qp->q_from.sin_addr, nssRcvdFwdR); + ns_debug(ns_log_default, 3, "resp: Query sent."); + free_nsp(nsp); + return; + + formerr: + if (!haveComplained(ina_ulong(from.sin_addr), (u_long)formerrmsg)) + ns_info(ns_log_resp_checks, "Malformed response from %s (%s)", + sin_ntoa(from), formerrmsg); + free_nsp(nsp); + return; + + return_msg: + nameserIncr(from.sin_addr, nssRcvdFwdR); + nameserIncr(qp->q_from.sin_addr, nssSentFwdR); + /* The "standard" return code */ + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg(msg, msglen, qp); + qremove(qp); + free_nsp(nsp); + return; + + return_newmsg: + nameserIncr(qp->q_from.sin_addr, nssSentAns); + + if (!hp->aa) + nameserIncr(qp->q_from.sin_addr, nssSentNaAns); + if (hp->rcode == NXDOMAIN) + nameserIncr(qp->q_from.sin_addr, nssSentNXD); + n = doaddinfo(hp, cp, buflen); + cp += n; + buflen -= n; + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg(newmsg, cp - newmsg, qp); + qremove(qp); + free_nsp(nsp); + return; + + refused: + hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg); + hp->rcode = REFUSED; + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg((u_char *)hp, + (qp->q_cmsglen ? qp->q_cmsglen : qp->q_msglen), + qp); + qremove(qp); + free_nsp(nsp); + return; + + servfail: + nameserIncr(qp->q_from.sin_addr, nssSentFail); + hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg); + hp->rcode = SERVFAIL; + hp->qr = 1; + hp->id = qp->q_id; + hp->rd = 1; + hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0); + (void) send_msg((u_char *)hp, + (qp->q_cmsglen ? qp->q_cmsglen : qp->q_msglen), + qp); + qremove(qp); + free_nsp(nsp); + return; + + timeout: + if (qp->q_stream) + sq_remove(qp->q_stream); + qremove(qp); + free_nsp(nsp); + return; +} + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + hp->rcode = FORMERR; \ + return (-1); \ + } \ + } while (0) + +static int +rrextract(u_char *msg, int msglen, u_char *rrp, struct databuf **dpp, + char *dname, int namelen, struct sockaddr_in from, char **tnamep) +{ + u_char *cp, *eom, *rdatap; + u_int class, type, dlen; + int n, n1; + u_int32_t ttl; + u_char *cp1, data[MAXDATA*2]; + HEADER *hp = (HEADER *)msg; + enum context context; + + if (tnamep != NULL) + *tnamep = NULL; + + *dpp = NULL; + cp = rrp; + eom = msg + msglen; + if ((n = dn_expand(msg, eom, cp, dname, namelen)) < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + GETSHORT(class, cp); + GETLONG(ttl, cp); + if (ttl > MAXIMUM_TTL) { + ns_debug(ns_log_default, 5, "%s: converted TTL > %u to 0", + dname, MAXIMUM_TTL); + ttl = 0; + } + GETSHORT(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; + if (!ns_nameok(dname, class, NULL, response_trans, + ns_ownercontext(type, response_trans), + dname, from.sin_addr)) { + hp->rcode = REFUSED; + return (-1); + } + ns_debug(ns_log_default, 3, + "rrextract: dname %s type %d class %d ttl %d", + dname, type, class, ttl); + /* + * Convert the resource record data into the internal + * database format. + * + * On entry to the switch: + * CP points to the RDATA section of the wire-format RR. + * DLEN is its length. + * The memory area at DATA is available for processing. + * + * On exit from the switch: + * CP has been incremented past the RR. + * CP1 points to the RDATA section of the database-format RR. + * N contains the length of the RDATA section of the dbase-format RR. + * + * The new data at CP1 for length N will be copied into the database, + * so it need not be in any particular storage location. + */ + switch (type) { + case T_A: + if (dlen != INT32SZ) { + hp->rcode = FORMERR; + return (-1); + } + /*FALLTHROUGH*/ + case T_WKS: + case T_HINFO: + case T_TXT: + case T_X25: + case T_ISDN: + case T_NSAP: + case T_AAAA: + case T_LOC: + case T_KEY: + cp1 = cp; + n = dlen; + cp += n; + break; + + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + n = dn_expand(msg, eom, cp, (char *)data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok((char *)data, class, NULL, response_trans, + type == T_PTR ?ns_ptrcontext(dname) :domain_ctx, + dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 = data; + n = strlen((char *)data) + 1; + if (tnamep != NULL && (type == T_NS || type == T_MB)) + *tnamep = savestr((char *)cp1, 1); + break; + + case T_SOA: + context = hostname_ctx; + goto soa_rp_minfo; + case T_RP: + case T_MINFO: + context = mailname_ctx; + /* FALLTHROUGH */ + soa_rp_minfo: + n = dn_expand(msg, eom, cp, (char *)data, sizeof data); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok((char *)data, class, NULL, response_trans, + context, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + /* + * The next use of 'cp' is dn_expand(), so we don't have + * to BOUNDS_CHECK() here. + */ + cp1 = data + (n = strlen((char *)data) + 1); + n1 = sizeof(data) - n; + if (type == T_SOA) + n1 -= 5 * INT32SZ; + n = dn_expand(msg, eom, cp, (char *)cp1, n1); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (type == T_RP) + context = domain_ctx; + else + context = mailname_ctx; + if (!ns_nameok((char *)cp1, class, NULL, response_trans, + context, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char *)cp1) + 1; + if (type == T_SOA) { + n = 5 * INT32SZ; + BOUNDS_CHECK(cp, n); + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + } + n = cp1 - data; + cp1 = data; + break; + + case T_NAPTR: + /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(data, cp, INT16SZ*2); + cp1 = data + INT16SZ*2; + cp += INT16SZ*2; + + /* Flags */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Service */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Regexp */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + *cp1++ = n; + memcpy(cp1, cp, n); + cp += n; cp1 += n; + + /* Replacement */ + n = dn_expand(msg, eom, cp, (char *)cp1, + sizeof data - (cp1 - data)); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok((char *)cp1, class, NULL, response_trans, + hostname_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + + /* compute end of data */ + cp1 += strlen((char *)cp1) + 1; + /* compute size of data */ + n = cp1 - data; + cp1 = data; + break; + + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = data + INT16SZ; + cp += INT16SZ; + + if (type == T_SRV) { + /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); + memcpy(cp1, cp, INT16SZ*2); + cp1 += INT16SZ*2; + cp += INT16SZ*2; + } + + /* get name */ + n = dn_expand(msg, eom, cp, (char *)cp1, + sizeof data - (cp1 - data)); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok((char *)cp1, class, NULL, response_trans, + hostname_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + + if (tnamep != NULL) + *tnamep = savestr((char *)cp1, 1); + + /* compute end of data */ + cp1 += strlen((char *)cp1) + 1; + /* compute size of data */ + n = cp1 - data; + cp1 = data; + break; + + case T_PX: + /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); + memcpy(data, cp, INT16SZ); + cp1 = data + INT16SZ; + cp += INT16SZ; + + /* get MAP822 name */ + n = dn_expand(msg, eom, cp, (char *)cp1, + sizeof data - INT16SZ); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok((char *)cp1, class, NULL, response_trans, + domain_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + /* + * The next use of 'cp' is dn_expand(), so we don't have + * to BOUNDS_CHECK() here. + */ + cp1 += (n = strlen((char *)cp1) + 1); + n1 = sizeof(data) - n; + n = dn_expand(msg, eom, cp, (char *)cp1, n1); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + if (!ns_nameok((char *)cp1, class, NULL, response_trans, + domain_ctx, dname, from.sin_addr)) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char *)cp1) + 1; + n = cp1 - data; + cp1 = data; + break; + + case T_SIG: { + u_long origTTL, exptime, signtime, timetilexp, now; + + /* Check signature time, expiration, and adjust TTL. */ + /* This code is similar to that in db_load.c. */ + + /* Skip coveredType, alg, labels */ + BOUNDS_CHECK(cp, INT16SZ + 1 + 1 + 3*INT32SZ); + cp1 = cp + INT16SZ + 1 + 1; + GETLONG(origTTL, cp1); + GETLONG(exptime, cp1); + GETLONG(signtime, cp1); + now = time(NULL); /* Get current time in GMT/UTC */ + + /* Don't let bogus name servers increase the signed TTL */ + if (ttl > origTTL) { + ns_debug(ns_log_default, 3, + "shrinking SIG TTL from %d to origTTL %d", + ttl, origTTL); + ttl = origTTL; + } + + /* Don't let bogus signers "sign" in the future. */ + if (signtime > now) { + ns_debug(ns_log_default, 3, + "ignoring SIG: signature date %s is in the future", + p_secstodate (signtime)); + return ((cp - rrp) + dlen); + } + + /* Ignore received SIG RR's that are already expired. */ + if (exptime <= now) { + ns_debug(ns_log_default, 3, + "ignoring SIG: expiration %s is in the past", + p_secstodate (exptime)); + return ((cp - rrp) + dlen); + } + + /* Lop off the TTL at the expiration time. */ + timetilexp = exptime - now; + if (timetilexp < ttl) { + ns_debug(ns_log_default, 3, + "shrinking expiring %s SIG TTL from %d to %d", + p_secstodate (exptime), ttl, timetilexp); + ttl = timetilexp; + } + + /* The following code is copied from named-xfer.c. */ + cp1 = (u_char *)data; + + /* first just copy over the type_covered, algorithm, */ + /* labels, orig ttl, two timestamps, and the footprint */ + BOUNDS_CHECK(cp, 18); + memcpy(cp1, cp, 18); + cp += 18; + cp1 += 18; + + /* then the signer's name */ + n = dn_expand(msg, eom, cp, (char *)cp1, (sizeof data) - 18); + if (n < 0) { + hp->rcode = FORMERR; + return (-1); + } + cp += n; + cp1 += strlen((char*)cp1)+1; + + /* finally, we copy over the variable-length signature. + Its size is the total data length, minus what we copied. */ + if (18 + (u_int)n > dlen) { + hp->rcode = FORMERR; + return (-1); + } + n = dlen - (18 + n); + if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) { + hp->rcode = FORMERR; + return (-1); /* out of room! */ + } + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + + /* compute size of data */ + n = cp1 - (u_char *)data; + cp1 = (u_char *)data; + break; + } + + default: + ns_debug(ns_log_default, 3, "unknown type %d", type); + return ((cp - rrp) + dlen); + } + + if (cp > eom) { + hp->rcode = FORMERR; + return (-1); + } + if ((u_int)(cp - rdatap) != dlen) { + ns_debug(ns_log_default, 3, + "encoded rdata length is %u, but actual length was %u", + dlen, (u_int)(cp - rdatap)); + hp->rcode = FORMERR; + return (-1); + } + if (n > MAXDATA) { + ns_debug(ns_log_default, 1, + "update type %d: %d bytes is too much data", + type, n); + hp->rcode = FORMERR; + return (-1); + } + + ttl += tt.tv_sec; + *dpp = savedata(class, type, ttl, cp1, n); + return (cp - rrp); +} + +int +send_msg(u_char *msg, int msglen, struct qinfo *qp) { + if (qp->q_flags & Q_SYSTEM) + return (1); + if (!qp->q_stream && (msglen > PACKETSZ)) + msglen = trunc_adjust(msg, msglen, PACKETSZ); + ns_debug(ns_log_default, 1, "send_msg -> %s (%s %d) id=%d", + sin_ntoa(qp->q_from), + qp->q_stream == NULL ? "UDP" : "TCP", + qp->q_stream == NULL ? qp->q_dfd : qp->q_stream->s_rfd, + ntohs(qp->q_id)); +#ifdef DEBUG + if (debug > 4) { + struct qinfo *tqp; + + for (tqp = nsqhead; tqp != NULL; tqp = tqp->q_link) { + ns_debug(ns_log_default, 4, + "qp %#lx q_id: %d q_nsid: %d q_msglen: %d", + (u_long)tqp, tqp->q_id, + tqp->q_nsid, tqp->q_msglen); + ns_debug(ns_log_default, 4, + "\tq_naddr: %d q_curaddr: %d", + tqp->q_naddr, tqp->q_curaddr); + ns_debug(ns_log_default, 4, + "\tq_next: %#lx q_link: %#lx", + (u_long)qp->q_next, (u_long)qp->q_link); + } + } + if (debug >= 6) + fp_nquery(msg, msglen, log_get_stream(packet_channel)); +#endif /* DEBUG */ + if (qp->q_stream == NULL) { + if (sendto(qp->q_dfd, (char*)msg, msglen, 0, + (struct sockaddr *)&qp->q_from, + sizeof(qp->q_from)) < 0) { + if (!haveComplained(ina_ulong(qp->q_from.sin_addr), + (u_long)sendtoStr)) +#if defined(SPURIOUS_ECONNREFUSED) + if (errno != ECONNREFUSED) +#endif + ns_info(ns_log_default, + "send_msg: sendto(%s): %s", + sin_ntoa(qp->q_from), + strerror(errno)); + nameserIncr(qp->q_from.sin_addr, nssSendtoErr); + return (1); + } + } else + writestream(qp->q_stream, (u_char*)msg, msglen); + return (0); +} + +#ifdef notdef +/* i don't quite understand this but the only ref to it is notdef'd --vix */ +prime(class, type, oqp) + int class, type; + struct qinfo *oqp; +{ + char dname[MAXDNAME]; + + if (oqp->q_msg == NULL) + return; + if (dn_expand((u_char *)oqp->q_msg, + (u_char *)oqp->q_msg + oqp->q_msglen, + (u_char *)oqp->q_msg + HFIXEDSZ, (u_char *)dname, + sizeof(dname)) < 0) + return; + ns_debug(ns_log_default, 2, "prime: %s", dname); + (void) sysquery(dname, class, type, NULL, 0, QUERY); +} +#endif + +void +prime_cache() { + struct qinfo *qp; + + /* + * XXX - should this always be skipped if OPTION_FORWARD_ONLY + * or should it be another option? What about when we are + * doing selective forwarding? + */ + if (!NS_OPTION_P(OPTION_FORWARD_ONLY)) { + ns_debug(ns_log_default, 1, "prime_cache: priming = %d", + priming); + if (!priming && fcachetab->h_tab[0] != NULL) { + priming++; + if (!(qp = sysquery("", C_IN, T_NS, NULL, 0, QUERY))) + priming = 0; + else + qp->q_flags |= (Q_SYSTEM | Q_PRIMING); + } + } + needs_prime_cache = 0; + return; +} + +#ifdef BIND_NOTIFY +/* + * sysnotify(dname, class, type) + * cause a NOTIFY request to be sysquery()'d to each secondary server + * of the zone that "dname" is within. + */ +void +sysnotify(const char *dname, int class, int type) { + const char *zname, *fname; + int nns, na, zn, n; + struct zoneinfo *zp; + struct hashbuf *htp; + struct namebuf *np; + struct databuf *dp; + + ns_debug(ns_log_notify, 3, "sysnotify(%s, %s, %s)", + dname, p_class(class), p_type(type)); + htp = hashtab; + np = nlookup(dname, &htp, &fname, 0); + if (np == NULL) { + ns_warning(ns_log_notify, "sysnotify: can't find \"%s\"", + dname); + return; + } + zn = findMyZone(np, class); + if (zn == DB_Z_CACHE) { + ns_warning(ns_log_notify, "sysnotify: not auth for zone %s", + dname); + return; + } + zp = &zones[zn]; + if (zp->z_notify == znotify_no || + (zp->z_notify == znotify_use_default && + NS_OPTION_P(OPTION_NONOTIFY))) + return; + if (zp->z_type != z_master && zp->z_type != z_slave) { + ns_warning(ns_log_notify, "sysnotify: %s not master or slave", + dname); + return; + } + zname = zp->z_origin; + nns = na = 0; + if (zp->z_type == z_master) + sysnotify_slaves(dname, zname, class, zn, &nns, &na); + if (zp->z_notify_count != 0) { + struct in_addr *also_addr = zp->z_also_notify; + int i; + + for (i = 0; i < zp->z_notify_count; i++) { + sysquery(dname, class, T_SOA, also_addr, 1, + NS_NOTIFY_OP); + also_addr++; + } + nns += zp->z_notify_count; + na += zp->z_notify_count; + } + if (nns != 0 || na != 0) + ns_info(ns_log_notify, + "Sent NOTIFY for \"%s %s %s\" (%s); %d NS, %d A", + dname, p_class(class), p_type(type), zname, nns, na); +} + +static void +sysnotify_slaves(const char *dname, const char *zname, int class, int zn, + int *nns, int *na) +{ + const char *mname, *fname; + struct hashbuf *htp; + struct namebuf *np; + struct databuf *dp; + + /* + * Master. + */ + htp = hashtab; + np = nlookup(zname, &htp, &fname, 0); + if (!np) { + ns_warning(ns_log_notify, + "sysnotify: found name \"%s\" but not zone", + dname); + return; + } + mname = NULL; + for (dp = np->n_data; dp; dp = dp->d_next) { + if (dp->d_zone == DB_Z_CACHE || !match(dp, class, T_SOA)) + continue; + if (mname) { + ns_notice(ns_log_notify, + "multiple SOA's for zone \"%s\"?", + zname); + return; + } + mname = (char *) dp->d_data; + } + if (mname == NULL) { + ns_notice(ns_log_notify, "no SOA found for zone \"%s\"", + zname); + return; + } + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_zone == DB_Z_CACHE || !match(dp, class, T_NS)) + continue; + if (strcasecmp((char*)dp->d_data, mname) == 0) + continue; + sysnotify_ns(dname, (char *)dp->d_data, class, zn, nns, na); + } +} + +static void +sysnotify_ns(const char *dname, const char *aname, + int class, int zn, int *nns, int *na) +{ + struct databuf *adp; + struct namebuf *anp; + const char *fname; + struct in_addr nss[NSMAX]; + struct hashbuf *htp; + int is_us, nsc; + + htp = hashtab; + anp = nlookup(aname, &htp, &fname, 0); + nsc = 0; + is_us = 0; + if (anp != NULL) + for (adp = anp->n_data; adp; adp = adp->d_next) { + struct in_addr ina; + + if (!match(adp, class, T_A)) + continue; + ina = ina_get(adp->d_data); + if (aIsUs(ina)) { + is_us = 1; + continue; + } + if (nsc < NSMAX) + nss[nsc++] = ina; + } /*next A*/ + if (nsc == 0) { + if (!is_us) { + struct qinfo *qp; + + qp = sysquery(aname, class, T_A, 0, 0, QUERY); + if (qp != NULL) + qp->q_notifyzone = zn; + } + return; + } + (void) sysquery(dname, class, T_SOA, nss, nsc, NS_NOTIFY_OP); + (*nns)++; + *na += nsc; +} +#endif /*BIND_NOTIFY*/ + +struct qinfo * +sysquery(const char *dname, int class, int type, + struct in_addr *nss, int nsc, int opcode) +{ + struct qinfo *qp, *oqp; + HEADER *hp; + char tmpdomain[MAXDNAME]; + struct namebuf *np; + struct databuf *nsp[NSMAX]; + struct hashbuf *htp; + struct sockaddr_in *nsa; + const char *fname; + int n, count; + + nsp[0] = NULL; + ns_debug(ns_log_default, 3, "sysquery(%s, %d, %d, %#x, %d)", + dname, class, type, nss, nsc); + qp = qnew(dname, class, type); + + if (nss && nsc) + np = NULL; + else { + htp = hashtab; + if (priming && dname[0] == '\0') { + np = NULL; + } else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) { + ns_info(ns_log_default, + "sysquery: nlookup error on %s?", + dname); + err1: + ns_freeqry(qp); + return (NULL); + } + + n = findns(&np, class, nsp, &count, 0); + switch (n) { + case NXDOMAIN: + case SERVFAIL: + ns_info(ns_log_default, + "sysquery: findns error (%s) on %s?", + n == NXDOMAIN ? "NXDOMAIN" : "SERVFAIL", + dname); + err2: + free_nsp(nsp); + goto err1; + } + } + + /* build new qinfo struct */ + qp->q_cmsg = qp->q_msg = NULL; + qp->q_dfd = ds; + if (nss && nsc) + qp->q_fwd = NULL; + else + qp->q_fwd = server_options->fwdtab; + qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2; + qp->q_flags |= Q_SYSTEM; + + getname(np, tmpdomain, sizeof tmpdomain); + qp->q_domain = savestr(tmpdomain, 1); + + if ((qp->q_msg = (u_char *)memget(PACKETSZ)) == NULL) { + ns_notice(ns_log_default, "sysquery: memget failed"); + goto err2; + } + qp->q_msgsize = PACKETSZ; + n = res_mkquery(opcode, dname, class, + type, NULL, 0, NULL, + qp->q_msg, PACKETSZ); + if (n < 0) { + ns_info(ns_log_default, + "sysquery: res_mkquery(%s) failed", dname); + goto err2; + } + qp->q_msglen = n; + hp = (HEADER *) qp->q_msg; + hp->id = qp->q_nsid = htons(nsid_next()); + hp->rd = (qp->q_fwd ? 1 : 0); + + /* First check for an already pending query for this data */ + for (oqp = nsqhead; oqp != NULL; oqp = oqp->q_link) { + if ((oqp != qp) + && (oqp->q_msglen == qp->q_msglen) + && memcmp(oqp->q_msg+2, qp->q_msg + 2, + qp->q_msglen - 2) == 0 + ) { +#ifdef BIND_NOTIFY + /* XXX - need fancier test to suppress duplicate + * NOTIFYs to the same server (compare nss?) + */ + if (opcode != NS_NOTIFY_OP) +#endif /*BIND_NOTIFY*/ + { + ns_debug(ns_log_default, 3, + "sysquery: duplicate"); + goto err2; + } + } + } + + if (nss && nsc) { + int i; + struct qserv *qs; + + for (i = 0, qs = qp->q_addr; + i < nsc; + i++, qs++) { + qs->ns_addr.sin_family = AF_INET; + qs->ns_addr.sin_addr = nss[i]; + qs->ns_addr.sin_port = ns_port; + qs->ns = NULL; + qs->nsdata = NULL; + qs->stime = tt; + qs->nretry = 0; + } + qp->q_naddr = nsc; + } else { + fetch_a: + count = nslookup(nsp, qp, dname, "sysquery"); + if (count <= 0) { + if (count < 0) { + ns_info(ns_log_default, + "sysquery: nslookup reports danger (%s)", + dname); + goto err2; + } else if (np && NAME(*np)[0] == '\0') { + /* + * It's not too serious if we don't have + * the root server addresses if we have to + * go through a forwarder anyway. Don't + * bother to log it, since prime_cache() + * won't do anything about it as currently + * implemented. + * + * XXX - should we skip setting + * needs_prime_cache as well? + * + * XXX - what happens when we implement + * selective forwarding? + */ + if (!NS_OPTION_P(OPTION_FORWARD_ONLY)) + ns_warning(ns_log_default, + "sysquery: no addrs found for root NS (%s)", + dname); + if (class == C_IN && !priming) + needs_prime_cache = 1; + goto err2; + } + if (np) { + free_nsp(nsp); + nsp[0] = NULL; + np = np_parent(np); + n = findns(&np, class, nsp, &count, 0); + switch (n) { + case NXDOMAIN: /*FALLTHROUGH*/ + case SERVFAIL: + ns_info(ns_log_default, + "sysquery: findns error (%d) on %s?", + n, dname); + goto err2; + } + goto fetch_a; + } + goto err2; + } + } + + schedretry(qp, retrytime(qp)); + if (qp->q_fwd == NULL) + qp->q_addr[0].stime = tt; /* XXX - why not every? */ + nsa = Q_NEXTADDR(qp, 0); + + ns_debug(ns_log_default, 1, + "sysquery: send -> %s dfd=%d nsid=%d id=%d retry=%ld", + sin_ntoa(*nsa), qp->q_dfd, + ntohs(qp->q_nsid), ntohs(qp->q_id), + (long)qp->q_time); +#ifdef DEBUG + if (debug >= 10) + fp_nquery(qp->q_msg, qp->q_msglen, + log_get_stream(packet_channel)); +#endif + if (sendto(qp->q_dfd, (char*)qp->q_msg, qp->q_msglen, 0, + (struct sockaddr *)nsa, + sizeof(struct sockaddr_in)) < 0) { + if (!haveComplained(ina_ulong(nsa->sin_addr), + (u_long)sendtoStr)) + ns_info(ns_log_default, "sysquery: sendto(%s): %s", + sin_ntoa(*nsa), strerror(errno)); + nameserIncr(nsa->sin_addr, nssSendtoErr); + } + nameserIncr(nsa->sin_addr, nssSentSysQ); + free_nsp(nsp); + return (qp); +} + +/* + * Check the list of root servers after receiving a response + * to a query for the root servers. + */ +static int +check_root() { + struct databuf *dp, *pdp; + struct namebuf *np; + int count = 0; + + priming = 0; + for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) + if (NAME(*np)[0] == '\0') + break; + if (np == NULL) { + ns_notice(ns_log_default, "check_root: Can't find root!"); + return (0); + } + for (dp = np->n_data; dp != NULL; dp = dp->d_next) + if (dp->d_type == T_NS) + count++; + ns_debug(ns_log_default, 1, "%d root servers", count); + if (count < MINROOTS) { + ns_notice(ns_log_default, + "check_root: %d root servers after query to root server < min", + count); + return (0); + } + pdp = NULL; + dp = np->n_data; + while (dp != NULL) { + if (dp->d_type == T_NS && dp->d_zone == DB_Z_CACHE && + dp->d_ttl < (u_int32_t)tt.tv_sec) { + ns_debug(ns_log_default, 1, + "deleting old root server '%s'", + dp->d_data); + dp = rm_datum(dp, np, pdp, NULL); + /* SHOULD DELETE FROM HINTS ALSO */ + continue; + } + pdp = dp; + dp = dp->d_next; + } + if (check_ns()) + return (1); + else { + priming = 1; + return (0); + } +} + +/* + * Check the root to make sure that for each NS record we have a A RR + */ +static int +check_ns() { + struct databuf *dp, *tdp; + struct namebuf *np, *tnp; + struct hashbuf *htp; + char *dname; + int found_arr; + const char *fname; + time_t curtime; + int servers = 0, rrsets = 0; + + ns_debug(ns_log_default, 2, "check_ns()"); + + curtime = (u_int32_t) tt.tv_sec; + for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) { + if (NAME(*np)[0] != '\0') + continue; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + int cnames = 0; + + if (dp->d_rcode) + continue; + + if (dp->d_type != T_NS) + continue; + + servers++; + + /* look for A records */ + dname = (caddr_t) dp->d_data; + htp = hashtab; + tnp = nlookup(dname, &htp, &fname, 0); + if (tnp == NULL || fname != dname) { + ns_debug(ns_log_default, 3, + "check_ns: %s: not found %s %#lx", + dname, fname, (u_long)tnp); + sysquery(dname, dp->d_class, T_A, NULL, + 0, QUERY); + continue; + } + /* look for name server addresses */ + found_arr = 0; + delete_stale(tnp); + for (tdp = tnp->n_data; + tdp != NULL; + tdp = tdp->d_next) { + if (tdp->d_rcode) + continue; + if (tdp->d_type == T_CNAME) + cnames++; + if (tdp->d_type != T_A || + tdp->d_class != dp->d_class) + continue; + if ((tdp->d_zone == DB_Z_CACHE) && + (tdp->d_ttl < (u_int32_t)curtime)) { + ns_debug(ns_log_default, 3, + "check_ns: stale entry '%s'", + NAME(*tnp)); + found_arr = 0; + break; + } + found_arr++; + } + if (found_arr) + rrsets++; + else if (cnames > 0) + ns_info(ns_log_default, + "Root NS %s -> CNAME %s", + NAME(*np), NAME(*tnp)); + else + sysquery(dname, dp->d_class, T_A, NULL, + 0, QUERY); + } + } + + ns_debug(ns_log_default, 2, "check_ns: %d %d", servers, rrsets); + return ((servers <= 2) + ? (rrsets == servers) + : ((rrsets * 2) >= servers) + ); +} + +/* int findns(npp, class, nsp, countp, flag) + * Find NS's or an SOA + * npp, class: + * dname whose most enclosing NS is wanted + * nsp, countp: + * result array and count; array will also be NULL terminated + * flag: + * boolean: we're being called from ADDAUTH, bypass authority checks + * return value: + * NXDOMAIN: we are authoritative for this {dname,class} + * *countp is bogus, but nsp[] has a single SOA returned in it. + * SERVFAIL: we are auth but zone isn't loaded; or, no root servers found + * *countp and nsp[] are bogus. + * OK: we are not authoritative, and here are the NS records we found. + * *countp and nsp[] return NS records of interest. + */ +int +findns(struct namebuf **npp, int class, + struct databuf **nsp, int *countp, int flag) +{ + struct namebuf *np = *npp; + struct databuf *dp; + struct databuf **nspp; + struct hashbuf *htp; + + nsp[0] = NULL; + + if (priming && (np == NULL || NAME(*np)[0] == '\0')) + htp = fcachetab; + else + htp = hashtab; + + try_again: + if (htp == fcachetab && class == C_IN && !priming) + /* + * XXX - do we want to set needs_prime_cache if + * OPTION_FORWARD_ONLY? + */ + needs_prime_cache = 1; + if (np == NULL) { + /* find the root */ + for (np = htp->h_tab[0]; np != NULL; np = np->n_next) + if (NAME(*np)[0] == '\0') + break; + } + while (np != NULL) { + ns_debug(ns_log_default, 5, "findns: np %#x '%s'", np, + NAME(*np)); + /* Look first for SOA records. */ +#ifdef ADDAUTH + if (!flag) +#endif + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_zone != DB_Z_CACHE && + ((zones[dp->d_zone].z_type == Z_PRIMARY) || + (zones[dp->d_zone].z_type == Z_SECONDARY)) && + match(dp, class, T_SOA)) { + ns_debug(ns_log_default, 3, + "findns: SOA found"); + if (zones[dp->d_zone].z_flags & Z_AUTH) { + *npp = np; + nsp[0] = dp; + nsp[1] = NULL; + DRCNTINC(dp); + return (NXDOMAIN); + } else { + /* XXX: zone isn't loaded but we're + * primary or secondary for it. + * should we fwd this? + */ + return (SERVFAIL); + } + } + } + + /* If no SOA records, look for NS records. */ + nspp = &nsp[0]; + *nspp = NULL; + delete_stale(np); + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, T_NS)) + continue; + if (dp->d_rcode) + continue; + /* + * Don't use records that may become invalid to + * reference later when we do the rtt computation. + * Never delete our safety-belt information! + * + * XXX: this is horribly bogus. + */ + if ((dp->d_zone == DB_Z_CACHE) && + (dp->d_ttl < (u_int32_t)tt.tv_sec) && + !(dp->d_flags & DB_F_HINT)) { + ns_debug(ns_log_default, 1, + "findns: stale entry '%s'", + NAME(*np)); + /* + * We may have already added NS databufs + * and are going to throw them away. Fix + * reference counts. We don't need to free + * them here as we just got them from the + * cache. + */ + while (nspp > &nsp[0]) { + nspp--; + DRCNTDEC(*nspp); + } + nsp[0] = NULL; + goto try_parent; + } + if (nspp < &nsp[NSMAX-1]) { + *nspp++ = dp; + DRCNTINC(dp); + } + } + + *countp = nspp - nsp; + if (*countp > 0) { + ns_debug(ns_log_default, 3, + "findns: %d NS's added for '%s'", + *countp, NAME(*np)); + *nspp = NULL; + *npp = np; + return (OK); /* Success, got some NS's */ + } + try_parent: + np = np_parent(np); + } + if (htp == hashtab) { + htp = fcachetab; + goto try_again; + } + ns_debug(ns_log_default, 1, + "findns: No root nameservers for class %s?", p_class(class)); + if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) { + norootlogged[class] = 1; + ns_info(ns_log_default, "No root nameservers for class %s", + p_class(class)); + } + return (SERVFAIL); +} + + +/* + * Extract RR's from the given node that match class and type. + * Return number of bytes added to response. + * If no matching data is found, then 0 is returned. + */ +int +finddata(struct namebuf *np, int class, int type, + HEADER *hp, char **dnamep, int *lenp, int *countp) +{ + struct databuf *dp; + char *cp; + int buflen, n, count = 0; + + delete_stale(np); + +#ifdef ROUND_ROBIN + if (type != T_ANY && type != T_PTR) { + /* cycle order of RRs, for a load balancing effect... */ + + struct databuf **dpp; + + for (dpp = &np->n_data; (dp = *dpp) != NULL; + dpp = &dp->d_next) { + if (dp->d_next && wanted(dp, class, type)) { + struct databuf *lp; + + *dpp = lp = dp->d_next; + dp->d_next = NULL; + + for (dpp = &lp->d_next; + *dpp; + dpp = &lp->d_next) + lp = *dpp; + *dpp = dp; + break; + } + } + } +#endif /*ROUND_ROBIN*/ + + buflen = *lenp; +#ifdef DEBUG + if (buflen > PACKETSZ) + ns_debug(ns_log_default, 1, "finddata(): buflen=%d", buflen); +#endif + cp = ((char *)hp) + *countp; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!wanted(dp, class, type)) { + if (type == T_CNAME && class == dp->d_class) { + /* any data means no CNAME exists */ + *countp = 0; + return 0; + } + continue; + } + if (dp->d_cred == DB_C_ADDITIONAL) { +#ifdef NOADDITIONAL + continue; +#else + /* we want to expire additional data very + * quickly. current strategy is to cut 5% + * off each time it is accessed. this makes + * stale(dp) true earlier when this datum is + * used often. + */ + dp->d_ttl = tt.tv_sec + + + 0.95 * (int) (dp->d_ttl - tt.tv_sec); +#endif + } + /* -ve $ing stuff, anant@isi.edu + * if we have a -ve $ed record, change the rcode on the + * header to reflect that + */ + if (dp->d_rcode == NOERROR_NODATA) { + if (count != 0) { + /* + * This should not happen, yet it does... + */ + ns_info(ns_log_default, + "NODATA & data for \"%s\" type %d class %d", + *dnamep, type, class); + continue; + } + if (type == T_ANY) + continue; + hp->rcode = NOERROR_NODATA; + if (dp->d_size == 0) { /* !RETURNSOA */ + *countp = 0; + return 1; /* XXX - we have to report success */ + } + } + if (dp->d_rcode == NXDOMAIN) { + if (count != 0) { + /* + * This should not happen, yet it might... + */ + ns_info(ns_log_default, + "NXDOMAIN & data for \"%s\" type %d class %d", + *dnamep, type, class); + continue; + } + hp->rcode = NXDOMAIN; + if (dp->d_size == 0) { /* !RETURNSOA */ + *countp = 0; + return 1; /* XXX - we have to report success */ + } + } + + /* Don't put anything but key or sig RR's in response to + requests for key or sig */ + if (((type == T_SIG) || (type == T_KEY)) && + (!((dp->d_type == T_SIG) || (dp->d_type == T_KEY))) ) + continue; + + if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1, + dnptrs, dnptrs_end)) < 0) { + hp->tc = 1; + *countp = count; + return (*lenp - buflen); + } + + cp += n; + buflen -= n; + count++; +#ifdef notdef + /* this isn't right for glue records, aa is set in ns_req */ + if (dp->d_zone != DB_Z_CACHE && + (zones[dp->d_zone].z_flags & Z_AUTH) != 0 && + class != C_ANY) + hp->aa = 1; /* XXX */ +#endif + if (dp->d_type == T_CNAME) { + /* don't alias if querying for key, sig, nxt, or any */ + if ((type != T_KEY) && + (type != T_SIG) && + (type != T_NXT) && + (type != T_ANY)) { /* or T_NS? */ + *dnamep = (caddr_t) dp->d_data; + } + break; + } + } + /* + * Cache invalidate the other RR's of same type + * if some have timed out + */ + ns_debug(ns_log_default, 3, "finddata: added %d class %d type %d RRs", + count, class, type); + *countp = count; + return (*lenp - buflen); +} + +/* + * Do we want this data record based on the class and type? + * (We always return found unexpired SIG RR's that cover the wanted rrtype.) + */ +int +wanted(const struct databuf *dp, int class, int type) { + const u_char *cp; + int coveredType; + time_t expiration; +#ifdef DEBUG + char pclass[15], ptype[15]; +#endif + +#ifdef DEBUG + strcpy(pclass, p_class(class)); + strcpy(ptype, p_type(type)); + ns_debug(ns_log_default, 3, "wanted(%#x, %s %s) [%s %s]", + dp, pclass, ptype, + p_class(dp->d_class), p_type(dp->d_type)); +#endif + + if (dp->d_class != class && class != C_ANY) + return (0); + /* + * Must check SIG for expiration below, other matches + * return OK here. + */ + if (type == dp->d_type && (type != T_SIG)) + return (1); + /* For a T_ANY query, we do not want to return -ve $ed RRs. */ + if (type == T_ANY && dp->d_rcode == NOERROR_NODATA) + return (0); + + /* First, look at the type of RR. */ + switch (dp->d_type) { + + /* Cases to deal with: + T_ANY search, return all unexpired SIGs. + T_SIG search, return all unexpired SIGs. + T_<foo> search, return all unexp SIG <FOO>s. + */ + case T_SIG: + cp = dp->d_data; + GETSHORT(coveredType, cp); + cp += INT16SZ + INT32SZ; /* skip alg, labels, & orig TTL */ + GETLONG(expiration,cp); + + if (type == T_ANY || type == T_SIG || type == coveredType) { + if (expiration > time(0)) + return (1); /* Unexpired matching SIG */ + } + return (0); /* We don't return this SIG. */ + + case T_ANY: + return (1); + case T_CNAME: + if (dp->d_rcode != NOERROR_NODATA) + return (1); + else + break; + } + /* OK, now look at the type of query. */ + switch (type) { + case T_ANY: + return (1); + + case T_MAILB: + switch (dp->d_type) { + case T_MR: + case T_MB: + case T_MG: + case T_MINFO: + return (1); + } + break; + + case T_AXFR: + /* T_AXFR needs an authoritative SOA */ + if (dp->d_type == T_SOA && dp->d_zone != DB_Z_CACHE + && (zones[dp->d_zone].z_flags & Z_AUTH)) + return (1); + break; + } + return (0); +} + +/* + * Add RR entries from dpp array to a query/response. + * Return the number of bytes added or negative the amount + * added if truncation occured. Typically you are + * adding NS records to a response. + */ +int +add_data(struct namebuf *np, struct databuf **dpp, + u_char *cp, int buflen, int *countp) +{ + struct databuf *dp; + char dname[MAXDNAME]; + int n, bytes; + + bytes = *countp = 0; + getname(np, dname, sizeof(dname)); + for (dp = *dpp++; dp != NULL; dp = *dpp++) { + if (stale(dp)) + continue; /* ignore old cache entry */ + if (dp->d_rcode) + continue; + if ((n = make_rr(dname, dp, cp, buflen, 1, + dnptrs, dnptrs_end)) < 0) + return (-bytes); /* Truncation */ + cp += n; + buflen -= n; + bytes += n; + (*countp)++; + } + return (bytes); +} + +static void +rrsetadd(struct flush_set *flushset, const char *name, struct databuf *dp) { + struct flush_set *fs = flushset; + struct db_list *dbl; + + while (fs->fs_name && ( + strcasecmp(fs->fs_name,name) || + (fs->fs_class != dp->d_class) || + (fs->fs_type != dp->d_type) || + (fs->fs_cred != dp->d_cred))) { + fs++; + } + if (!fs->fs_name) { + fs->fs_name = savestr(name, 1); + fs->fs_class = dp->d_class; + fs->fs_type = dp->d_type; + fs->fs_cred = dp->d_cred; + fs->fs_list = NULL; + fs->fs_last = NULL; + } + dbl = (struct db_list *)memget(sizeof(struct db_list)); + if (!dbl) + panic("rrsetadd: out of memory", NULL); + dbl->db_next = NULL; + dbl->db_dp = dp; + if (fs->fs_last == NULL) + fs->fs_list = dbl; + else + fs->fs_last->db_next = dbl; + fs->fs_last = dbl; +} + +static int +ttlcheck(const char *name, struct db_list *dbl, int update) { + int type = dbl->db_dp->d_type; + int class = dbl->db_dp->d_class; + struct hashbuf *htp = hashtab; + const char *fname; + struct namebuf *np; + struct db_list *dbp = dbl; + struct databuf *dp; + u_int32_t ttl = 0; /* Make gcc happy. */ + int first; + + + np = nlookup(name, &htp, &fname, 0); + if (np == NULL || fname != name || ns_wildcard(NAME(*np))) + return (1); + + /* check that all the ttl's we have are the same, if not return 1 */ + first = 1; + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, type)) + continue; + if (first) { + /* we can't update zone data so return early */ + if (dp->d_zone != DB_Z_CACHE) + return (0); + ttl = dp->d_ttl; + first = 0; + } else if (ttl != dp->d_ttl) + return (1); + } + + /* there are no records of this type in the cache */ + if (first) + return(1); + + /* + * the ttls of all records we have in the cache are the same + * if the ttls differ in the new set we don't want it. + */ + + /* check that all the ttl's we have are the same, if not return 0 */ + first = 1; + while (dbp) { + if (first) { + ttl = dbp->db_dp->d_ttl; + first = 0; + } else if (ttl != dbp->db_dp->d_ttl) { + return(0); + } + dbp = dbp->db_next; + } + + /* update ttl if required */ + if (update) { + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, type)) + continue; + if (dp->d_ttl > ttl) + break; + dp->d_ttl = ttl; + fixttl(dp); + } + } + + return(1); +} + +static int +rrsetcmp(name, dbl) + char *name; + struct db_list *dbl; +{ + int type = dbl->db_dp->d_type; + int class = dbl->db_dp->d_class; + struct hashbuf *htp = hashtab; + const char *fname; + struct namebuf *np; + struct db_list *dbp = dbl; + struct databuf *dp; + int exists = 0; + + + np = nlookup(name, &htp, &fname, 0); + if (np == NULL || fname != name || ns_wildcard(NAME(*np))) { + ns_debug(ns_log_default, 3, "rrsetcmp: name not in database"); + return (-1); + } + + /* check that all entries in dbl are in the cache */ + while (dbp) { + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (match(dp, class, type)) + exists++; + if (!db_cmp(dp, dbp->db_dp) +#ifdef NOADDITIONAL + && ((dp->d_cred == dbp->db_dp->d_cred) || + (dp->d_cred != DB_C_ADDITIONAL)) +#endif + ) + break; + } + if (!dp) { + ns_debug(ns_log_default, 3, + "rrsetcmp: %srecord%s in database", + exists ? "" : "no ", exists ? " not" : "s"); + return (exists ? 1 : -1); + } + dbp = dbp->db_next; + } + + /* Check that all cache entries are in the list. */ + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (!match(dp, class, type)) + continue; +#ifdef NCACHE + if (dp->d_rcode) + return (1); +#endif + dbp = dbl; + while (dbp) { + if (!db_cmp(dp, dbp->db_dp)) + break; + dbp = dbp->db_next; + } + if (!dbp) { + ns_debug(ns_log_default, 3, + "rrsetcmp: record not in rrset"); + return (1); + } + } + ns_debug(ns_log_default, 3, "rrsetcmp: rrsets matched"); + return (0); +} + +static void +rrsetupdate(struct flush_set * flushset, int flags, struct sockaddr_in from) { + struct flush_set *fs = flushset; + struct db_list *dbp, *odbp; + int n; + + while (fs->fs_name) { + ns_debug(ns_log_default, 2, "rrsetupdate: %s", + fs->fs_name[0] ? fs->fs_name : "."); + if ((n = rrsetcmp(fs->fs_name, fs->fs_list)) && + ttlcheck(fs->fs_name, fs->fs_list, 0)) { + if (n > 0) + flushrrset(fs, from); + + dbp = fs->fs_list; + while (dbp) { + n = db_update(fs->fs_name, dbp->db_dp, + dbp->db_dp, NULL, flags, + hashtab, from); + ns_debug(ns_log_default, 3, + "rrsetupdate: %s %d", + fs->fs_name[0] ? fs->fs_name : ".", + n); + if (n != OK) + db_freedata(dbp->db_dp); + odbp = dbp; + dbp = dbp->db_next; + memput(odbp, sizeof *odbp); + } + } else { + if (n == 0) + (void)ttlcheck(fs->fs_name,fs->fs_list, 1); + dbp = fs->fs_list; + while (dbp) { + db_freedata(dbp->db_dp); + odbp = dbp; + dbp = dbp->db_next; + memput(odbp, sizeof *odbp); + } + } + fs->fs_list = NULL; + fs++; + } +} + +static void +flushrrset(struct flush_set * fs, struct sockaddr_in from) { + struct databuf *dp; + int n; + + ns_debug(ns_log_default, 2, "flushrrset(%s, %s, %s, %d)", + fs->fs_name[0]?fs->fs_name:".", p_type(fs->fs_type), + p_class(fs->fs_class), fs->fs_cred); + dp = savedata(fs->fs_class, fs->fs_type, 0, NULL, 0); + dp->d_zone = DB_Z_CACHE; + dp->d_cred = fs->fs_cred; + dp->d_clev = 0; + do { + n = db_update(fs->fs_name, dp, NULL, NULL, DB_DELETE, hashtab, + from); + ns_debug(ns_log_default, 3, "flushrrset: %d", n); + } while (n == OK); + db_freedata(dp); +} + +static void +free_flushset(struct flush_set *flushset, int flushset_size) { + struct flush_set *fs; + + for (fs = flushset; fs->fs_name != NULL; fs++) + freestr(fs->fs_name); + memput(flushset, flushset_size); +} + +/* + * This is best thought of as a "cache invalidate" function. + * It is called whenever a piece of data is determined to have + * become invalid either through a timeout or a validation + * failure. It is better to have no information, than to + * have partial information you pass off as complete. + */ +void +delete_all(struct namebuf *np, int class, int type) { + struct databuf *dp, *pdp; + + ns_debug(ns_log_default, 3, "delete_all(%#x:\"%s\" %s %s)", + np, NAME(*np), p_class(class), p_type(type)); + pdp = NULL; + dp = np->n_data; + while (dp != NULL) { + if (dp->d_zone == DB_Z_CACHE && (dp->d_flags & DB_F_HINT) == 0 + && match(dp, class, type)) { + dp = rm_datum(dp, np, pdp, NULL); + continue; + } + pdp = dp; + dp = dp->d_next; + } +} + +/* delete_stale(np) + * for all RRs associated with this name, check for staleness (& delete) + * arguments: + * np = pointer to namebuf to be cleaned. + * returns: + * void. + * side effects: + * delete_all() can be called, freeing memory and relinking chains. + */ +void +delete_stale(np) + struct namebuf *np; +{ + struct databuf *dp; + again: + for (dp = np->n_data; dp != NULL; dp = dp->d_next) { + if (dp->d_zone == DB_Z_CACHE && stale(dp)) { + delete_all(np, dp->d_class, dp->d_type); + goto again; + } + } +} + + +/* + * Adjust answer message so that it fits in outlen. Set tc if required. + * + * If outlen = msglen, can be used to verify qdcount, ancount, nscount + * and arcount. + * + * return new length + */ + +int +trunc_adjust(u_char *msg, int msglen, int outlen) { + register HEADER *hp; + u_int qdcount, ancount, nscount, arcount, dlen; + u_char *cp = msg, *cp1, *eom_in, *eom_out; + int n; + + eom_in = msg + msglen; + eom_out = msg + outlen; + + hp = (HEADER *)msg; + qdcount = ntohs(hp->qdcount); + ancount = ntohs(hp->ancount); + nscount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + cp += HFIXEDSZ; + + while ((qdcount || ancount || nscount || arcount) && + cp < eom_in && cp < eom_out) { + + cp1 = cp; /* use temporary in case we break */ + + n = dn_skipname(cp1, eom_in); + if (n < 0) + break; + cp1 += n + 2 * INT16SZ; /* type, class */ + + if (!qdcount) { + cp1 += INT32SZ; /* ttl */ + if (cp1 + INT16SZ > eom_in) + break; + GETSHORT(dlen, cp1); + cp1 += dlen; + } + + if (cp1 > eom_in || cp1 > eom_out) + break; + + cp = cp1; + + if (qdcount) + qdcount--; + else if (ancount) + ancount--; + else if (nscount) + nscount--; + else + arcount--; + } + + if (qdcount || ancount || nscount || arcount) { + ns_debug(ns_log_default, 1, + "trunc_adjust:%s %d %d %d %d %d, %d %d %d %d %d", + hp->tc?" tc":"", msglen, + ntohs(hp->qdcount), ntohs(hp->ancount), + ntohs(hp->nscount), ntohs(hp->arcount), + cp-msg, qdcount, ancount, nscount, arcount); + hp->tc = 1; + hp->qdcount = htons(ntohs(hp->qdcount) - qdcount); + hp->ancount = htons(ntohs(hp->ancount) - ancount); + hp->nscount = htons(ntohs(hp->nscount) - nscount); + hp->arcount = htons(ntohs(hp->arcount) - arcount); + } + ENSURE(cp <= eom_out); + return (cp - msg); +} + +static void +add_related_additional(char *name) { + int i; + + if (num_related >= MAX_RELATED - 1) + return; + for (i = 0; i < num_related; i++) + if (strcasecmp(name, related[i]) == 0) { + freestr(name); + return; + } + related[num_related++] = name; +} + +static void +free_related_additional() { + int i; + + for (i = 0; i < num_related; i++) + freestr(related[i]); + num_related = 0; +} + +static int +related_additional(char *name) { + int i; + + for (i = 0; i < num_related; i++) + if (strcasecmp(name, related[i]) == 0) + return (1); + return (0); +} + +static void +freestr_maybe(char **tname) { + if (tname == NULL || *tname == NULL) + return; + freestr(*tname); + *tname = NULL; +} diff --git a/contrib/bind/bin/named/ns_stats.c b/contrib/bind/bin/named/ns_stats.c new file mode 100644 index 0000000..5be0257 --- /dev/null +++ b/contrib/bind/bin/named/ns_stats.c @@ -0,0 +1,415 @@ +#if !defined(lint) && !defined(SABER) +static char sccsid[] = "@(#)ns_stats.c 4.10 (Berkeley) 6/27/90"; +static char rcsid[] = "$Id: ns_stats.c,v 8.18 1998/02/13 19:50:24 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1986 + * 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) 1996, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> +#include <isc/tree.h> + +#include "port_after.h" + +#ifdef HAVE_GETRUSAGE /* XXX */ +#include <sys/time.h> +#include <sys/resource.h> +#endif + +#include "named.h" + +static u_long typestats[T_ANY+1]; +static const char *typenames[T_ANY+1] = { + /* 5 types per line */ + "Unknown", "A", "NS", "invalid(MD)", "invalid(MF)", + "CNAME", "SOA", "MB", "MG", "MR", + "NULL", "WKS", "PTR", "HINFO", "MINFO", + "MX", "TXT", "RP", "AFSDB", "X25", + "ISDN", "RT", "NSAP", "NSAP_PTR", "SIG", + "KEY", "PX", "invalid(GPOS)", "AAAA", "LOC", + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + /* 20 per line */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 100 */ + "UINFO", "UID", "GID", "UNSPEC", 0, 0, 0, 0, 0, 0, + /* 110 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 120 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 200 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 240 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 250 */ + 0, 0, "AXFR", "MAILB", "MAILA", "ANY" +}; + +static void nameserStats(FILE *); + +void +ns_stats() { + time_t timenow = time(NULL); + FILE *f; + int i; + + ns_notice(ns_log_statistics, "dumping nameserver stats"); + + if (!(f = fopen(server_options->stats_filename, "a"))) { + ns_notice(ns_log_statistics, "cannot open stat file, \"%s\"", + server_options->stats_filename); + return; + } + + fprintf(f, "+++ Statistics Dump +++ (%ld) %s", + (long)timenow, checked_ctime(&timenow)); + fprintf(f, "%ld\ttime since boot (secs)\n", + (long)(timenow - boottime)); + fprintf(f, "%ld\ttime since reset (secs)\n", + (long)(timenow - resettime)); + + /* query type statistics */ + fprintf(f, "%lu\tUnknown query types\n", (u_long)typestats[0]); + for(i=1; i < T_ANY+1; i++) + if (typestats[i]) { + if (typenames[i] != NULL) + fprintf(f, "%lu\t%s queries\n", + (u_long)typestats[i], typenames[i]); + else + fprintf(f, "%lu\ttype %d queries\n", + (u_long)typestats[i], i); + } + + /* name server statistics */ + nameserStats(f); + + fprintf(f, "++ Memory Statistics ++\n"); + memstats(f); + fprintf(f, "-- Memory Statistics --\n"); + fprintf(f, "--- Statistics Dump --- (%ld) %s", + (long)timenow, checked_ctime(&timenow)); + (void) my_fclose(f); + ns_notice(ns_log_statistics, "done dumping nameserver stats"); +} + +void +qtypeIncr(qtype) + int qtype; +{ + if (qtype < T_A || qtype > T_ANY) + qtype = 0; /* bad type */ + typestats[qtype]++; +} + +static tree *nameserTree; +static int nameserInit; + +static FILE *nameserStatsFile; +static const char *statNames[nssLast] = { + "RR", /* sent us an answer */ + "RNXD", /* sent us a negative response */ + "RFwdR", /* sent us a response we had to fwd */ + "RDupR", /* sent us an extra answer */ + "RFail", /* sent us a SERVFAIL */ + "RFErr", /* sent us a FORMERR */ + "RErr", /* sent us some other error */ + "RAXFR", /* sent us an AXFR */ + "RLame", /* sent us a lame delegation */ + "ROpts", /* sent us some IP options */ + "SSysQ", /* sent them a sysquery */ + "SAns", /* sent them an answer */ + "SFwdQ", /* fwdd a query to them */ + "SDupQ", /* sent them a retry */ + "SErr", /* sent failed (in sendto) */ + "RQ", /* sent us a query */ + "RIQ", /* sent us an inverse query */ + "RFwdQ", /* sent us a query we had to fwd */ + "RDupQ", /* sent us a retry */ + "RTCP", /* sent us a query using TCP */ + "SFwdR", /* fwdd a response to them */ + "SFail", /* sent them a SERVFAIL */ + "SFErr", /* sent them a FORMERR */ + "SNaAns", /* sent them a non autoritative answer */ + "SNXD", /* sent them a negative response */ + }; + +/* + * Note that addresses in network byte order always have the high byte first. + * XXX - this is horribly IPv4 dependent, but it's performance critical. + */ +static int +nameserCompar(const tree_t t1, const tree_t t2) { + u_char *p1 = (u_char *)t1, *p2 = (u_char *)t2; + int i; + + for (i = INADDRSZ; i > 0; i--) { + u_char c1 = *p1++, c2 = *p2++; + + if (c1 < c2) + return (-1); + if (c1 > c2) + return (1); + } + return (0); +} + +struct nameser * +nameserFind(addr, flags) + struct in_addr addr; + int flags; +{ + struct nameser dummy; + struct nameser *ns; + + if (!nameserInit) { + tree_init(&nameserTree); + nameserInit++; + } + + dummy.addr = addr; + ns = (struct nameser *)tree_srch(&nameserTree, nameserCompar, + (tree_t)&dummy); + if (ns == NULL && (flags & NS_F_INSERT) != 0) { + ns = (struct nameser *)memget(sizeof(struct nameser)); + if (ns == NULL) { + nomem: if (!haveComplained((u_long)nameserFind, 0)) + ns_notice(ns_log_statistics, + "nameserFind: memget failed; %s", + strerror(errno)); + return (NULL); + } + memset(ns, 0, sizeof *ns); + ns->addr = addr; + if (!tree_add(&nameserTree, nameserCompar, (tree_t)ns, NULL)) { + int save = errno; + memput(ns, sizeof *ns); + errno = save; + goto nomem; + } + } + return (ns); +} + +static void +nameserStatsOut(f, stats) + FILE *f; + u_long stats[]; +{ + int i; + const char *pre = "\t"; + + for (i = 0; i < (int)nssLast; i++) { + fprintf(f, "%s%lu", pre, (u_long)stats[i]); + pre = ((i+1) % 5) ? " " : " "; + } + fputc('\n', f); +} + +static void +nameserStatsHdr(f) + FILE *f; +{ + int i; + const char *pre = "\t"; + + fprintf(f, "(Legend)\n"); + for (i = 0; i < (int)nssLast; i++) { + fprintf(f, "%s%s", pre, + statNames[i] ? statNames[i] : ""); + pre = ((i+1) % 5) ? "\t" : "\n\t"; + } + fputc('\n', f); +} + +static int +nameserStatsTravUAR(t) + tree_t t; +{ + struct nameser *ns = (struct nameser *)t; + + fprintf(nameserStatsFile, "[%s]\n", /* : rtt %u */ + inet_ntoa(ns->addr) /*, ns->rtt*/ ); + nameserStatsOut(nameserStatsFile, ns->stats); + return (1); +} + +static void +nameserStats(f) + FILE *f; +{ + nameserStatsFile = f; + fprintf(f, "++ Name Server Statistics ++\n"); + nameserStatsHdr(f); + fprintf(f, "(Global)\n"); + nameserStatsOut(f, globalStats); + if (NS_OPTION_P(OPTION_HOSTSTATS)) + tree_trav(&nameserTree, nameserStatsTravUAR); + fprintf(f, "-- Name Server Statistics --\n"); + nameserStatsFile = NULL; +} + +void +ns_logstats(evContext ctx, void *uap, struct timespec due, + struct timespec inter) +{ + char buffer[1024]; + char buffer2[32], header[64]; + time_t timenow = time(NULL); + int i; +#ifdef HAVE_GETRUSAGE + struct rusage usage, childu; +#endif /*HAVE_GETRUSAGE*/ + +#ifdef HAVE_GETRUSAGE +# define tv_float(tv) ((tv).tv_sec + ((tv).tv_usec / 1000000.0)) + + getrusage(RUSAGE_SELF, &usage); + getrusage(RUSAGE_CHILDREN, &childu); + + sprintf(buffer, "CPU=%gu/%gs CHILDCPU=%gu/%gs", + tv_float(usage.ru_utime), tv_float(usage.ru_stime), + tv_float(childu.ru_utime), tv_float(childu.ru_stime)); + ns_info(ns_log_statistics, "USAGE %lu %lu %s", (u_long)timenow, + (u_long)boottime, buffer); +# undef tv_float +#endif /*HAVE_GETRUSAGE*/ + + sprintf(header, "NSTATS %lu %lu", (u_long)timenow, (u_long)boottime); + strcpy(buffer, header); + + for (i = 0; i < T_ANY+1; i++) { + if (typestats[i]) { + if (typenames[i]) + sprintf(buffer2, " %s=%lu", + typenames[i], typestats[i]); + else + sprintf(buffer2, " %d=%lu", i, typestats[i]); + if (strlen(buffer) + strlen(buffer2) > + sizeof(buffer) - 1) { + ns_info(ns_log_statistics, buffer); + strcpy(buffer, header); + } + strcat(buffer, buffer2); + } + } + ns_info(ns_log_statistics, buffer); + + sprintf(header, "XSTATS %lu %lu", (u_long)timenow, (u_long)boottime); + strcpy(buffer, header); + for (i = 0; i < (int)nssLast; i++) { + sprintf(buffer2, " %s=%lu", + statNames[i]?statNames[i]:"?", (u_long)globalStats[i]); + if (strlen(buffer) + strlen(buffer2) > sizeof(buffer) - 1) { + ns_info(ns_log_statistics, buffer); + strcpy(buffer, header); + } + strcat(buffer, buffer2); + } + ns_info(ns_log_statistics, buffer); +} + +static void +nameserFree(void *uap) { + struct nameser *ns = uap; + + memput(ns, sizeof *ns); +} + +void +ns_freestats(void) { + if (nameserTree == NULL) + return; + tree_mung(&nameserTree, nameserFree); + nameserInit = 0; +} diff --git a/contrib/bind/bin/named/ns_udp.c b/contrib/bind/bin/named/ns_udp.c new file mode 100644 index 0000000..8b1af5e --- /dev/null +++ b/contrib/bind/bin/named/ns_udp.c @@ -0,0 +1,123 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_udp.c,v 8.5 1997/05/21 19:52:26 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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 "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/file.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <nlist.h> +#include <resolv.h> +#include <stdio.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" + +void +ns_udp() { +#if defined(CHECK_UDP_SUM) || defined(FIX_UDP_SUM) + struct nlist nl[2]; + int fd; + int sum; + u_long res, offset; + + nl[0].n_name = UDPSUM; + nl[1].n_name = 0; + + if (nlist(KSYMS, nl)) { + ns_debug(ns_log_default, 1, "ns_udp: nlist (%s,%s) failed", + KSYMS, UDPSUM); + return; + } + + ns_debug(ns_log_default, 1, "ns_udp: %s %d %lu (%ld)", + nl[0].n_name, nl[0].n_type, nl[0].n_value, nl[0].n_value); + + if (!nl[0].n_type) + return; + + if ((fd = open(KMEM, O_RDWR, 0)) < 0) { + ns_debug(ns_log_default, 1, "ns_udp: open %s failed: %s", KMEM, + strerror(errno)); + return; + } + + offset = nl[0].n_value; +#ifdef KMAP + offset &= ((~0UL)>>1); +#endif + + res = lseek(fd, offset, SEEK_SET); + if (res != offset) { + ns_debug(ns_log_default, 1, "ns_udp: lseek %lu failed %lu: %s", + offset, res, strerror(errno)); + goto cleanup; + } + + if (read(fd, &sum, sizeof(sum)) != sizeof(sum)) { + ns_debug(ns_log_default, 1, "ns_udp: read failed: %s", + strerror(errno)); + goto cleanup; + } + + ns_debug(ns_log_default, 1, "ns_udp: %d", sum); + if (sum == 0) { +#ifdef FIX_UDP_SUM + sum = 1; + lseek(fd, offset, SEEK_SET); + if (res != offset) { + ns_debug(ns_log_default, 1, + "ns_udp: lseek %lu failed %lu: %s", + offset, res, strerror(errno)); + goto cleanup; + } + if (write(fd, &sum, sizeof(sum)) != sizeof(sum)) { + ns_debug(ns_log_default, 1, "ns_udp: write failed: %s", + strerror(errno)); + goto cleanup; + } + ns_warning(ns_log_default, "ns_udp: check sums turned on"); +#else + ns_panic(ns_log_default, 0, + "ns_udp: checksums NOT turned on, exiting"); +#endif + } +cleanup: + close(fd); +#endif +} diff --git a/contrib/bind/bin/named/ns_update.c b/contrib/bind/bin/named/ns_update.c new file mode 100644 index 0000000..e6fdd8d --- /dev/null +++ b/contrib/bind/bin/named/ns_update.c @@ -0,0 +1,2393 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_update.c,v 8.24 1998/03/20 00:49:16 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/uio.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +#define WRITEABLE_MASK (S_IWUSR | S_IWGRP | S_IWOTH) + +/* XXXRTH almost all funcs. in here should be static! + map rdata_dump to db_to_textual + map rdata_expand to wire_to_db + make a textual_to_db and use it in merge_logs? + replace all this "map" stuff with the new routines (from 4.9.5 I think) + */ + +/* from ns_req.c */ + +static struct map m_opcode[] = { + { "nxdomain", NXDOMAIN }, + { "yxdomain", YXDOMAIN }, + { "nxrrset", NXRRSET }, + { "yxrrset", YXRRSET }, + { "delete", DELETE }, + { "add", ADD }, +}; +#define M_OPCODE_CNT (sizeof(m_opcode) / sizeof(struct map)) + +/* XXXRTH workaround map difficulties */ +#define M_CLASS_CNT m_class_cnt +#define M_TYPE_CNT m_type_cnt + +static char *opcodes[] = { + "delete", + "add", + "", + "nxdomain", + "", + "", + "yxdomain", + "yxrrset", + "nxrrset", + "", + "", +}; + + +/* from db_load.c */ + +static struct map m_section[] = { + { "zone", S_ZONE }, + { "prereq", S_PREREQ }, + { "update", S_UPDATE }, + { "reserved", S_ADDT }, +}; +#define M_SECTION_CNT (sizeof(m_section) / sizeof(struct map)) + + +/* from ns_req.c */ + +static ns_updrec *rrecp_start = NULL, *rrecp_last = NULL; + + +/* forward */ +static int findzone(const char *, int, int, int *, int); +static int rdata_expand(const u_char *, const u_char *, const u_char *, + u_int, size_t, u_char *, size_t); + + +static FILE * +open_transaction_log(struct zoneinfo *zp) { + FILE *fp; + + fp = fopen(zp->z_updatelog, "a+"); + if (fp == NULL) { + ns_error(ns_log_update, "can't open %s: %s", zp->z_updatelog, + strerror(errno)); + return (NULL); + } + if (ftell(fp) == 0L) { + fprintf(fp, "%s", LogSignature); + } + return (fp); +} + + +static int +close_transaction_log(struct zoneinfo *zp, FILE *fp) { + if (fflush(fp) == EOF) { + ns_error(ns_log_update, "fflush() of %s failed: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + if (fsync(fileno(fp)) < 0) { + ns_error(ns_log_update, "fsync() of %s failed: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + if (fclose(fp) == EOF) { + ns_error(ns_log_update, "fclose() of %s failed: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + return (0); +} + +/* + * printupdatelog(srcaddr, firstp, hp, zp, old_serial) + * append an ascii form to the zone's transaction log file. + */ +static void +printupdatelog(struct sockaddr_in srcaddr, + ns_updrec *firstp, + HEADER *hp, + struct zoneinfo *zp, + u_int32_t old_serial) +{ + struct databuf *dp; + struct map *mp; + ns_updrec *rrecp; + int opcode; + char time[25]; + FILE *fp; + + if (!firstp) + return; + + fp = open_transaction_log(zp); + if (fp == NULL) + return; + + sprintf(time, "at %lu", (u_long)tt.tv_sec); + fprintf(fp, "[DYNAMIC_UPDATE] id %u from %s %s (named pid %ld):\n", + hp->id, sin_ntoa(srcaddr), time, (long)getpid()); + for (rrecp = firstp; rrecp; rrecp = rrecp->r_next) { + INSIST(zp == &zones[rrecp->r_zone]); + switch (rrecp->r_section) { + case S_ZONE: + fprintf(fp, "zone:\torigin %s class %s serial %u\n", + zp->z_origin, p_class(zp->z_class), + old_serial); + break; + case S_PREREQ: + opcode = rrecp->r_opcode; + fprintf(fp, "prereq:\t{%s} %s. %s ", + opcodes[opcode], rrecp->r_dname, + p_class(zp->z_class)); + if (opcode == NXRRSET || opcode == YXRRSET) { + fprintf(fp, "%s ", p_type(rrecp->r_type)); + if ((dp = rrecp->r_dp) && dp->d_size > 0) { + dp->d_class = zp->z_class; + (void) rdata_dump(dp, fp); + } + } + fprintf(fp, "\n"); + break; + case S_UPDATE: + opcode = rrecp->r_opcode; + fprintf(fp, "update:\t{%s} %s. ", + opcodes[opcode], rrecp->r_dname); + if (opcode == ADD) + fprintf(fp, "%u ", rrecp->r_ttl); + fprintf(fp, "%s ", p_class(zp->z_class)); + if (rrecp->r_type != T_ANY) + fprintf(fp, "%s ", p_type(rrecp->r_type)); + if ((dp = rrecp->r_dp) && dp->d_size > 0) { + dp->d_class = zp->z_class; + (void) rdata_dump(dp, fp); + } + fprintf(fp, "\n"); + break; + case S_ADDT: + break; + default: + ns_panic(ns_log_update, 1, + "printupdatelog - impossible condition"); + /*NOTREACHED*/ + } + } + fprintf(fp, "\n"); + (void) close_transaction_log(zp, fp); +} + +static void +cancel_soa_update(struct zoneinfo *zp) { + ns_debug(ns_log_update, 3, "cancel_soa_update for %s", zp->z_origin); + zp->z_flags &= ~Z_NEED_SOAUPDATE; + zp->z_soaincrtime = 0; + zp->z_updatecnt = 0; +} + +/* + * Figure out when a SOA serial number update should happen. + * Returns non-zero if the caller should call sched_zone_maint(zp). + */ +int +schedule_soa_update(struct zoneinfo *zp, int numupdated) { + (void) gettime(&tt); + + zp->z_flags |= Z_NEED_SOAUPDATE; + + /* + * Only z_deferupdcnt updates are allowed before we force + * a serial update. + */ + zp->z_updatecnt += numupdated; + if (zp->z_updatecnt >= zp->z_deferupdcnt) { + if (incr_serial(zp) < 0) { + ns_error(ns_log_update, + "error updating serial number for %s from %d", + zp->z_origin, zp->z_serial); + } else + return (0); + /* + * Note we continue scheduling if for some reason + * incr_serial fails. + */ + } + + if (zp->z_soaincrintvl > 0) { + /* We want automatic updates in this zone. */ + if (zp->z_soaincrtime > 0) { + /* Already scheduled. */ + ns_debug(ns_log_update, 3, + "schedule_soa_update('%s'): already scheduled", + zp->z_origin); + return (0); + } else { + /* First update since the soa was last incremented. */ + zp->z_updatecnt = numupdated; + zp->z_soaincrtime = tt.tv_sec + zp->z_soaincrintvl; + /* + * Never schedule soaincrtime to occur after + * dumptime. + */ + if (zp->z_soaincrtime > zp->z_dumptime) + zp->z_soaincrtime = zp->z_dumptime; + ns_debug(ns_log_update, 3, + "schedule_soa_update('%s'): scheduled for %lu", + zp->z_origin, (u_long)zp->z_soaincrtime); + return (1); + } + } + return (0); +} + +/* + * Figure out when a zone dump should happen. + * Returns non-zero if the caller should call sched_zone_maint(zp). + */ +int +schedule_dump(struct zoneinfo *zp) { + time_t half; + + (void) gettime(&tt); + + zp->z_flags |= Z_NEED_DUMP; + + if (zp->z_dumpintvl > 0) { + /* We want automatic dumping in this zone. */ + if (zp->z_dumptime > 0) { + /* Already scheduled. */ + ns_debug(ns_log_update, 3, + "schedule_dump('%s'): already scheduled", + zp->z_origin); + return (0); + } else { + /* + * Set new dump time for dynamic zone. Use a random + * number in the last half of the dump limit; we want + * it to be substantially correct while still + * preventing dump synchronization among various + * dynamic zones. + */ + half = (zp->z_dumpintvl + 1) / 2; + zp->z_dumptime = tt.tv_sec + half + (rand() % half); + /* + * Never schedule soaincrtime to occur after + * dumptime. + */ + if (zp->z_soaincrtime > zp->z_dumptime) + zp->z_soaincrtime = zp->z_dumptime; + ns_debug(ns_log_update, 3, + "schedule_dump('%s'): scheduled for %lu", + zp->z_origin, (u_long)zp->z_dumptime); + return (1); + } + } + return (0); +} + +/* + * int + * process_prereq(rec, rcodep) + * Process one prerequisite. + * returns: + * >0 prerequisite was satisfied. + * =0 prerequisite was not satisfied, or an error occurred. + * side effects: + * sets *rcodep if an error occurs or prerequisite isn't satisfied. + */ +static int +process_prereq(ns_updrec *ur, int *rcodep, u_int16_t zclass) { + const char *dname = ur->r_dname; + u_int16_t class = ur->r_class; + u_int16_t type = ur->r_type; + u_int32_t ttl = ur->r_ttl; + struct databuf *rdp = ur->r_dp; + const char *fname; + struct hashbuf *htp; + struct namebuf *np; + struct databuf *dp; + + /* + * An element in the list might have already been + * processed if it is in the same RRset as a previous + * RRset Exists (value dependent) prerequisite. + */ + if (rdp && (rdp->d_mark & D_MARK_FOUND) != 0) { + /* Already processed. */ + return (1); + } + if (ttl != 0) { + ns_debug(ns_log_update, 1, + "process_prereq: ttl!=0 in prereq section"); + *rcodep = FORMERR; + return (0); + } + htp = hashtab; + np = nlookup(dname, &htp, &fname, 0); + if (fname != dname) + np = NULL; /* Matching by wildcard not allowed here. */ + if (class == C_ANY) { + if (rdp->d_size) { + ns_debug(ns_log_update, 1, + "process_prereq: empty rdata required in prereq section with class=ANY"); + *rcodep = FORMERR; + return (0); + } + if (type == T_ANY) { + /* Name is in use. */ + ur->r_opcode = YXDOMAIN; + if (np == NULL || np->n_data == NULL) { + /* + * Name does not exist or is + * an empty nonterminal. + */ + ns_debug(ns_log_update, 1, + "process_prereq: %s not in use", + dname); + *rcodep = NXDOMAIN; + return (0); + } + } else { + /* RRset exists (value independent). */ + int found = 0; + + ur->r_opcode = YXRRSET; + if (np != NULL) + for (dp = np->n_data; + dp && !found; + dp = dp->d_next) + if (match(dp, class, type)) + found = 1; + if (!found) { + ns_debug(ns_log_update, 1, + "process_prereq: RRset (%s,%s,%s) does not exist", + dname, p_type(type), p_class(zclass)); + *rcodep = NXRRSET; + return (0); + } + } + } else if (class == C_NONE) { + if (rdp->d_size) { + ns_debug(ns_log_update, 1, + "process_prereq: empty rdata required in prereq section with class=NONE"); + *rcodep = FORMERR; + return (0); + } + if (type == T_ANY) { + /* Name is not in use. */ + ur->r_opcode = NXDOMAIN; + if (np != NULL && np->n_data != NULL) { + /* + * Name exists and is not an + * empty nonterminal. + */ + ns_debug(ns_log_update, 1, + "process_prereq: %s exists", + dname); + *rcodep = YXDOMAIN; + return (0); + } + } else { + /* RRset does not exist. */ + int found = 0; + + ur->r_opcode = NXRRSET; + class = zclass; + if (np != NULL) + for (dp = np->n_data; + dp && !found; + dp = dp->d_next) + if (match(dp, class, type)) + found = 1; + if (found) { + ns_debug(ns_log_update, 1, + "process_prereq: RRset (%s,%s) exists", + dname, p_type(type)); + *rcodep = YXRRSET; + return (0); + } + } + } else if (class == zclass) { + /* + * RRset exists (value dependent). + * + * Check for RRset equality also. + */ + ns_updrec *tmp; + + ur->r_opcode = YXRRSET; + if (!rdp) { + ns_debug(ns_log_update, 1, + "process_prereq: nonempty rdata required in prereq section with class=%s", + p_class(class)); + *rcodep = FORMERR; + return (0); + } + htp = hashtab; + np = nlookup(dname, &htp, &fname, 0); + if (np == NULL || fname != dname) { + *rcodep = NXRRSET; + return (0); + } + for (dp = np->n_data; dp; dp = dp->d_next) { + if (match(dp, class, type)) { + int found = 0; + + for (tmp = ur; + tmp && !found; + tmp = tmp->r_next) { + if (tmp->r_section != S_PREREQ) + break; + if (!db_cmp(dp, tmp->r_dp)) { + tmp->r_dp->d_mark |= + D_MARK_FOUND; + found = 1; + } + } + if (!found) { + *rcodep = NXRRSET; + return (0); + } + } + } + for (tmp = ur; tmp; tmp = tmp->r_next) + if (tmp->r_section == S_PREREQ && + !strcasecmp(dname, tmp->r_dname) && + tmp->r_class == class && + tmp->r_type == type && + (ur->r_dp->d_mark & D_MARK_FOUND) == 0) { + *rcodep = NXRRSET; + return (0); + } else { + tmp->r_opcode = YXRRSET; + } + } else { + ns_debug(ns_log_update, 1, + "process_prereq: incorrect class %s", + p_class(class)); + *rcodep = FORMERR; + return (0); + } + /* Through the gauntlet, and out. */ + return (1); +} + +/* + * int + * prescan_update(ur, rcodep) + * Process one prerequisite. + * returns: + * >0 update looks OK (format wise; who knows if it will succeed?) + * =0 update has something wrong with it. + * side effects: + * sets *rcodep if an error occurs or prerequisite isn't satisfied. + */ +static int +prescan_update(ns_updrec *ur, int *rcodep, u_int16_t zclass) { + const char *dname = ur->r_dname; + u_int16_t class = ur->r_class; + u_int16_t type = ur->r_type; + u_int32_t ttl = ur->r_ttl; + struct databuf *rdp = ur->r_dp; + const char *fname; + struct hashbuf *htp; + struct namebuf *np; + + if (class == zclass) { + if (type == T_ANY || + type == T_AXFR || type == T_IXFR || + type == T_MAILA || type == T_MAILB) { + ns_debug(ns_log_update, 1, + "prescan_update: invalid type (%s)", + p_type(type)); + *rcodep = FORMERR; + return (0); + } + } else if (class == C_ANY) { + if (ttl != 0 || rdp->d_size || + type == T_AXFR || type == T_IXFR || + type == T_MAILA || type == T_MAILB) { + ns_debug(ns_log_update, 1, + "prescan_update: formerr(#2)"); + *rcodep = FORMERR; + return (0); + } + } else if (class == C_NONE) { + if (ttl != 0 || type == T_ANY || + type == T_AXFR || type == T_IXFR || + type == T_MAILA || type == T_MAILB) { + ns_debug(ns_log_update, 1, + "prescan_update: formerr(#3)"); + *rcodep = FORMERR; + return (0); + } + } else { + ns_debug(ns_log_update, 1, + "prescan_update: invalid class (%s)", + p_class(class)); + *rcodep = FORMERR; + return (0); + } + /* No format errors found. */ + return (1); +} + +/* + * int + * process_updates(firstp, rcodep, from) + * Process prerequisites and apply updates from the list to the database. + * returns: + * number of successful updates, 0 if none were successful. + * side effects: + * *rcodep gets the transaction return code. + * can schedule maintainance for zone dumps and soa.serial# increments. + */ +static int +process_updates(ns_updrec *firstp, int *rcodep, struct sockaddr_in from) { + int i, j, n, dbflags, matches, zonenum; + int numupdated = 0, soaupdated = 0, schedmaint = 0; + u_int16_t zclass; + ns_updrec *ur; + const char *fname; + struct databuf *dp, *savedp; + struct zoneinfo *zp; + int zonelist[MAXDNAME]; + + *rcodep = SERVFAIL; + if (!firstp) + return (0); + if (firstp->r_section == S_ZONE) { + zclass = firstp->r_class; + zonenum = firstp->r_zone; + zp = &zones[zonenum]; + } else { + ns_debug(ns_log_update, 1, + "process_updates: missing zone record"); + return (0); + } + + /* Process prereq records and prescan update records. */ + for (ur = firstp; ur != NULL; ur = ur->r_next) { + const char * dname = ur->r_dname; + u_int16_t class = ur->r_class; + u_int16_t type = ur->r_type; + u_int32_t ttl = ur->r_ttl; + struct databuf *rdp = ur->r_dp; + u_int section = ur->r_section; + + ns_debug(ns_log_update, 3, +"process_update: record section=%s, dname=%s, \ +class=%s, type=%s, ttl=%d, dp=0x%0x", + p_section(section, ns_o_update), dname, + p_class(class), p_type(type), ttl, rdp); + + matches = findzone(dname, zclass, MAXDNAME, + zonelist, MAXDNAME); + ur->r_zone = 0; + for (j = 0; j < matches && !ur->r_zone; j++) + if (zonelist[j] == zonenum) + ur->r_zone = zonelist[j]; + if (!ur->r_zone) { + ns_debug(ns_log_update, 1, + "process_updates: record does not belong to the zone %s", + zones[zonenum].z_origin); + *rcodep = NOTZONE; + return (0); + } + + switch (section) { + case S_ZONE: + break; + case S_PREREQ: + if (!process_prereq(ur, rcodep, zclass)) + return (0); /* *rcodep has been set. */ + ns_debug(ns_log_update, 3, "prerequisite satisfied"); + break; + case S_UPDATE: + if (!prescan_update(ur, rcodep, zclass)) + return (0); /* *rcodep has been set. */ + ns_debug(ns_log_update, 3, "update prescan succeeded"); + break; + case S_ADDT: + break; + default: + ns_panic(ns_log_update, 1, + "process_updates: impossible section"); + /* NOTREACHED */ + } + } + + /* Now process the records in update section. */ + for (ur = firstp; ur != NULL; ur = ur->r_next) { + const char * dname = ur->r_dname; + u_int16_t class = ur->r_class; + + if (ur->r_section != S_UPDATE) + continue; + dbflags = 0; + savedp = NULL; + dp = ur->r_dp; + if (class == zp->z_class) { + /* ADD databuf dp to hash table */ + /* + * Handling of various SOA/WKS/CNAME scenarios + * is done in db_update(). + */ + ur->r_opcode = ADD; + dbflags |= DB_NODATA; + n = db_update(dname, dp, dp, &savedp, + dbflags, hashtab, from); + if (n != OK) { + ns_debug(ns_log_update, 3, + "process_updates: failed to add databuf (%d)", + n); + } else { + ns_debug(ns_log_update, 3, + "process_updates: added databuf 0x%0x", + dp); + dp->d_mark = D_MARK_ADDED; + numupdated++; + if (dp->d_type == T_SOA) + soaupdated = 1; + } + } else if (class == C_ANY || class == C_NONE) { + /* + * DELETE databuf's matching dp from the hash table. + * + * handling of various SOA/NS scenarios done + * in db_update(). + */ + ur->r_opcode = DELETE; + /* + * we know we're deleting now, and db_update won't + * match with class==C_NONE, so we use the zone's + * class. + */ + if (class == C_NONE) + ur->r_dp->d_class = zp->z_class; + dbflags |= DB_DELETE; + n = db_update(dname, dp, NULL, &savedp, + dbflags, hashtab, from); + if (n != OK) + ns_debug(ns_log_update, 3, + "process_updates: delete failed"); + else { + ns_debug(ns_log_update, 3, + "process_updates: delete succeeded"); + numupdated++; + } + } + /* + * Even an addition could have caused some deletions like + * replacing old SOA or CNAME or WKS record or records of + * lower cred/clev. + * + * We need to save the deleted databuf's in case we wish to + * abort this update transaction and roll back all updates + * applied from this packet. + */ + ur->r_deldp = savedp; + } + + /* + * If we got here, things are OK, so set rcodep to indicate so. + */ + *rcodep = NOERROR; + + if (!numupdated) + return (0); + + /* + * schedule maintenance for dumps and SOA.serial# increment + * (this also sets Z_NEED_DUMP and Z_NEED_SOAUPDATE appropriately) + */ + schedmaint = 0; + if (schedule_dump(zp)) + schedmaint = 1; + if (soaupdated) { + /* + * SOA updated by this update transaction, so + * we need to set the zone serial number, stop any + * automatic updates that may be pending, and send out + * a NOTIFY message. + */ + zp->z_serial = get_serial_unchecked(zp); + cancel_soa_update(zp); + schedmaint = 1; +#ifdef BIND_NOTIFY + sysnotify(zp->z_origin, zp->z_class, T_SOA); +#endif + } else { + if (schedule_soa_update(zp, numupdated)) + schedmaint = 1; + } + if (schedmaint) + sched_zone_maint(zp); + return (numupdated); +} + +static enum req_action +req_update_private(HEADER *hp, u_char *cp, u_char *eom, u_char *msg, + struct qstream *qsp, int dfd, struct sockaddr_in from) +{ + char dnbuf[MAXDNAME], *dname; + u_int zocount, prcount, upcount, adcount, class, type, dlen; + u_int32_t ttl; + int i, n, cnt, found, matches, zonenum, numupdated = 0; + int rcode = NOERROR; + u_int c, section; + u_char rdata[MAXDATA]; + struct qinfo *qp; + struct databuf *dp, *nsp[NSMAX]; + struct databuf **nspp = &nsp[0]; + struct zoneinfo *zp; + ns_updrec *rrecp; + int zonelist[MAXDNAME]; + int should_use_tcp; + u_int32_t old_serial; + + nsp[0] = NULL; + + zocount = ntohs(hp->qdcount); + prcount = ntohs(hp->ancount); + upcount = ntohs(hp->nscount); + adcount = ntohs(hp->arcount); + + /* Process zone section. */ + ns_debug(ns_log_update, 3, "req_update: section ZONE, count %d", + zocount); + if ((n = dn_expand(msg, eom, cp, dnbuf, sizeof(dnbuf))) < 0) { + ns_debug(ns_log_update, 1, "req_update: expand name failed"); + hp->rcode = FORMERR; + return (Finish); + } + dname = dnbuf; + cp += n; + if (cp + 2 * INT16SZ > eom) { + ns_debug(ns_log_update, 1, "req_update: too short"); + hp->rcode = FORMERR; + return (Finish); + } + GETSHORT(type, cp); + GETSHORT(class, cp); + if (zocount != 1 || type != T_SOA) { + ns_debug(ns_log_update, 1, + "req_update: incorrect count or type for zone section: %d", + zocount); + hp->rcode = FORMERR; + return (Finish); + } + + matches = findzone(dname, class, 0, zonelist, MAXDNAME); + if (matches == 1) { + zonenum = zonelist[0]; + zp = &zones[zonenum]; + old_serial = get_serial(zp); + if (zp->z_class != (int)class || + (zp->z_type != z_master && zp->z_type != z_slave)) + matches = 0; + } + if (matches != 1) { + ns_debug(ns_log_update, 1, + "req_update: non-authoritative server for %s", + dname); + hp->rcode = NOTAUTH; + return (Finish); + } + + /* + * Begin Access Control Point + */ + + if (!ip_address_allowed(zp->z_update_acl, from.sin_addr)) { + ns_notice(ns_log_security, "unapproved update from %s for %s", + sin_ntoa(from), *dname ? dname : "."); + return (Refuse); + } + + /* + * End Access Control Point + */ + + /* XXXVIX should check update key when we have one. */ + + /* we should be authoritative */ + if (!(zp->z_flags & Z_AUTH)) { + ns_debug(ns_log_update, 1, + "req_update: zone %s: Z_AUTH not set", + dname); + hp->rcode = NOTAUTH; + return (Finish); + } + + if (zp->z_type == Z_SECONDARY) { + /* + * XXX the code below is broken. Until fixed, we just + * refuse. + */ + return (Refuse); + + /* We are a slave for this zone, forward it to the master. */ + for (cnt = 0; cnt < zp->z_addrcnt; cnt++) + *nspp++ = savedata(zp->z_class, T_A, USE_MINIMUM, + (u_char *)&zp->z_addr[cnt].s_addr, + INT32SZ); + *nspp = NULL; + /* + * If the request came in over TCP, forward it over TCP + */ + should_use_tcp = (qsp != NULL); + n = ns_forw(nsp, msg, eom-msg, from, qsp, dfd, &qp, + dname, class, type, NULL, should_use_tcp); + free_nsp(nsp); + switch (n) { + case FW_OK: + case FW_DUP: + return (Return); + case FW_NOSERVER: + /* should not happen */ + case FW_SERVFAIL: + hp->rcode = SERVFAIL; + return (Finish); + } + } + /* + * We are the primary master server for this zone, + * proceed further and process update packet + */ + if (!(zp->z_flags & Z_DYNAMIC)) { + ns_debug(ns_log_update, 1, + "req_update: dynamic flag not set for zone %s", + dname); + return (Refuse); + } + ns_debug(ns_log_update, 3, + "req_update: update request for zone %s, class %s", + zp->z_origin, p_class(class)); + rrecp_start = res_mkupdrec(S_ZONE, dname, class, type, 0); + rrecp_start->r_zone = zonenum; + rrecp_start->r_prev = NULL; + rrecp_start->r_next = NULL; + rrecp_last = rrecp_start; + + /* + * Parse the prerequisite and update sections for format errors. + */ + for (i = 0; (u_int)i < prcount + upcount; i++) { + if ((n = dn_expand(msg, eom, cp, dnbuf, sizeof(dnbuf))) < 0) { + ns_debug(ns_log_update, 1, + "req_update: expand name failed"); + hp->rcode = FORMERR; + return (Finish); + } + dname = dnbuf; + cp += n; + if (cp + RRFIXEDSZ > eom) { + ns_debug(ns_log_update, 1, + "req_update: overrun in answer"); + hp->rcode = FORMERR; + return (Finish); + } + GETSHORT(type, cp); + GETSHORT(class, cp); + GETLONG(ttl, cp); + GETSHORT(dlen, cp); + n = 0; + dp = NULL; + if (dlen > 0) { + if (cp + dlen > eom) { + ns_debug(ns_log_update, 1, + "req_update: bad dlen"); + hp->rcode = FORMERR; + return (Finish); + } + n = rdata_expand(msg, eom, cp, type, dlen, + rdata, sizeof rdata); + if (n == 0 || n > MAXDATA) { + ns_debug(ns_log_update, 1, + "req_update: failed to expand record"); + hp->rcode = FORMERR; + return (Finish); + } + cp += dlen; + } + section = ((u_int)i < prcount) ? S_PREREQ : S_UPDATE; + rrecp = res_mkupdrec(section, dname, class, type, ttl); + dp = savedata(class, type, ttl, rdata, n); + dp->d_zone = zonenum; + dp->d_cred = DB_C_ZONE; + dp->d_clev = nlabels(zp->z_origin); + /* XXX - also record in dp->d_ns, which host this came from */ + rrecp->r_dp = dp; + /* Append the current record to the end of list of records. */ + rrecp_last->r_next = rrecp; + rrecp->r_prev = rrecp_last; + rrecp->r_next = NULL; + rrecp_last = rrecp; + if (cp > eom) { + ns_info(ns_log_update, + "Malformed response from %s (overrun)", + inet_ntoa(from.sin_addr)); + hp->rcode = FORMERR; + return (Finish); + } + } + + /* Now process all parsed records in the prereq and update sections. */ + numupdated = process_updates(rrecp_start, &rcode, from); + hp->rcode = rcode; + if (numupdated <= 0) { + ns_error(ns_log_update, + "error processing update packet id %d from %s", + hp->id, sin_ntoa(from)); + return (Finish); + } + + /* Make a log of the update. */ + (void) printupdatelog(from, rrecp_start, hp, zp, old_serial); + + return (Finish); +} + +static void +free_rrecp(ns_updrec **startpp, ns_updrec **lastpp, int rcode, + struct sockaddr_in from) +{ + ns_updrec *rrecp, *first_rrecp, *next_rrecp; + struct databuf *dp, *tmpdp; + char *dname, *msg; + + REQUIRE(startpp != NULL && lastpp != NULL); + + if (rcode == NOERROR) { + first_rrecp = *startpp; + msg = "free_rrecp: update transaction succeeded, cleaning up"; + } else { + first_rrecp = *lastpp; + msg = "free_rrecp: update transaction aborted, rolling back"; + } + ns_debug(ns_log_update, 1, msg); + for (rrecp = first_rrecp; rrecp != NULL; rrecp = next_rrecp) { + if (rcode == NOERROR) + next_rrecp = rrecp->r_next; + else + next_rrecp = rrecp->r_prev; + if (rrecp->r_section != S_UPDATE) { + if (rrecp->r_dp) + db_freedata(rrecp->r_dp); + res_freeupdrec(rrecp); + continue; + } + dname = rrecp->r_dname; + dp = rrecp->r_dp; + if ((dp->d_mark & D_MARK_ADDED) != 0) { + if (rcode == NOERROR) { + /* + * This databuf is now a part of hashtab, + * or has been deleted by a subsequent update. + * Either way, we must not free it. + */ + dp->d_mark &= ~D_MARK_ADDED; + } else { + /* Delete the databuf. */ + if (db_update(dname, dp, NULL, NULL, + DB_DELETE, hashtab, from) + != OK) { + ns_error(ns_log_update, + "free_rrecp: failed to delete databuf: dname=%s, type=%s", + dname, p_type(dp->d_type)); + } else { + ns_debug(ns_log_update, 3, + "free_rrecp: deleted databuf 0x%0x", + dp); + /* + * XXXRTH + * + * We used to db_freedata() here, + * but I removed it because 'dp' was + * part of a hashtab before we called + * db_update(), and since our delete + * has succeeded, it should have been + * freed. + */ + } + } + } else { + /* + * Databuf's matching this were deleted by this + * update, or were never executed (because we bailed + * out early). + */ + db_freedata(dp); + } + + /* Process deleted databuf's. */ + dp = rrecp->r_deldp; + while (dp != NULL) { + tmpdp = dp; + dp = dp->d_next; + if (rcode == NOERROR) { + if (tmpdp->d_rcnt) + ns_debug(ns_log_update, 1, + "free_rrecp: type = %d, rcnt = %d", + p_type(tmpdp->d_type), + tmpdp->d_rcnt); + else { + tmpdp->d_next = NULL; + db_freedata(tmpdp); + } + } else { + /* Add the databuf back. */ + tmpdp->d_mark &= ~D_MARK_DELETED; + if (db_update(dname, tmpdp, tmpdp, NULL, + 0, hashtab, from) != OK) { + ns_error(ns_log_update, + "free_rrecp: failed to add back databuf: dname=%s, type=%s", + dname, p_type(tmpdp->d_type)); + } else { + ns_debug(ns_log_update, 3, + "free_rrecp: added back databuf 0x%0x", + tmpdp); + } + } + } + res_freeupdrec(rrecp); + } + *startpp = NULL; + *lastpp = NULL; +} + +enum req_action +req_update(HEADER *hp, u_char *cp, u_char *eom, u_char *msg, + struct qstream *qsp, int dfd, struct sockaddr_in from) +{ + enum req_action ret; + + ret = req_update_private(hp, cp, eom, msg, qsp, dfd, from); + free_rrecp(&rrecp_start, &rrecp_last, hp->rcode, from); + if (ret == Finish) { + hp->qdcount = hp->ancount = hp->nscount = hp->arcount = 0; + memset(msg + HFIXEDSZ, 0, (eom - msg) - HFIXEDSZ); + } + return (ret); +} + +/* + * expand rdata portion of a compressed resource record at cp into cp1 + * and return the length of the expanded rdata (length of the compressed + * rdata is "dlen"). + */ +static int +rdata_expand(const u_char *msg, const u_char *eom, const u_char *cp, + u_int type, size_t dlen, u_char *cp1, size_t size) +{ + const u_char *cpinit = cp; + const u_char *cp1init = cp1; + int n, i; + + switch (type) { + case T_A: + if (dlen != INT32SZ) + return (0); + /*FALLTHROUGH*/ + case T_WKS: + case T_HINFO: + case T_TXT: + case T_X25: + case T_ISDN: + case T_NSAP: + case T_LOC: + if (size < dlen) + return (0); + memcpy(cp1, cp, dlen); + return (dlen); + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0 || (u_int)n != dlen) + return (0); + return (strlen((char *)cp1) + 1); + case T_MINFO: + case T_SOA: + case T_RP: + /* Get two compressed domain names. */ + for (i = 0; i < 2; i++) { + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + size -= n; + } + if (type == T_SOA) { + n = 5 * INT32SZ; + if (size < (size_t)n || cp + n > eom) + return(0); + size -= n; + memcpy(cp1, cp, n); + cp += n; + cp1 += n; + } + if (cp != cpinit + dlen) + return (0); + return (cp1 - cp1init); + case T_MX: + case T_AFSDB: + case T_RT: + case T_SRV: + /* Grab preference. */ + if (size < INT16SZ || cp + INT16SZ > eom) + return (0); + size -= INT16SZ; + memcpy(cp1, cp, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + + if (type == T_SRV) { + if (size < INT16SZ*2 || cp + INT16SZ*2 > eom) + return (0); + size -= INT16SZ*2; + /* Grab weight and port. */ + memcpy(cp1, cp, INT16SZ*2); + cp1 += INT16SZ*2; + cp += INT16SZ*2; + } + + /* Get name. */ + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + if (cp != cpinit + dlen) + return (0); + return (cp1 - cp1init); + case T_PX: + /* Grab preference. */ + if (size < INT16SZ || cp + INT16SZ > eom) + return (0); + size -= INT16SZ; + memcpy(cp1, cp, INT16SZ); + cp += INT16SZ; + cp1 += INT16SZ; + /* Get MAP822 name. */ + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + size -= n; + n = dn_expand(msg, eom, cp, (char *)cp1, size); + if (n < 0) + return (0); + cp += n; + n = strlen((char *)cp1) + 1; + cp1 += n; + if (cp != cpinit + dlen) + return (0); + return (cp1 - cp1init); + default: + ns_debug(ns_log_update, 3, "unknown type %d", type); + return (0); + } +} + +/* + * Print out rdata portion of a resource record from a databuf into a file. + * + * XXX - similar code in db_dump() should be replaced by a call to this + * function. + */ +void +rdata_dump(struct databuf *dp, FILE *fp) { + u_int32_t n, addr; + u_char *cp, *end; + int i, j; + const char *proto; + + cp = (u_char *)dp->d_data; + switch (dp->d_type) { + case T_A: + switch (dp->d_class) { + case C_IN: + case C_HS: + GETLONG(n, cp); + n = htonl(n); + fputs(inet_ntoa(*(struct in_addr *)&n), fp); + break; + } + if (dp->d_nstime) + fprintf(fp, ";\tNT=%d", dp->d_nstime); + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + fprintf(fp, "%s.", cp); + break; + case T_NS: + cp = (u_char *)dp->d_data; + if (cp[0] == '\0') + fprintf(fp, ".\t"); + else + fprintf(fp, "%s.", cp); + break; + case T_HINFO: + case T_ISDN: + if ((n = *cp++) != '\0') { + fprintf(fp, "\"%.*s\"", (int)n, cp); + cp += n; + } else + fprintf(fp, "\"\""); + if ((n = *cp++) != '\0') + fprintf(fp, " \"%.*s\"", (int)n, cp); + else + fprintf(fp, " \"\""); + break; + case T_SOA: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s. ( ", cp); +#if defined(RETURNSOA) && defined(NCACHE) + if (dp->d_rcode == NXDOMAIN) + fputs(";", fp); +#endif + cp += strlen((char *)cp) + 1; + GETLONG(n, cp); + fprintf(fp, "%u", n); + GETLONG(n, cp); + fprintf(fp, " %u", n); + GETLONG(n, cp); + fprintf(fp, " %u", n); + GETLONG(n, cp); + fprintf(fp, " %u", n); + GETLONG(n, cp); + fprintf(fp, " %u )", n); +#if defined(RETURNSOA) && defined(NCACHE) + if (dp->d_rcode == NXDOMAIN) + fprintf(fp, ";%s.;NXDOMAIN;\t-$", cp); +#endif + break; + case T_MX: + case T_AFSDB: + case T_RT: + GETSHORT(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + break; + case T_PX: + GETSHORT(n, cp); + fprintf(fp, "%u", n); + fprintf(fp, " %s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + case T_TXT: + case T_X25: + end = (u_char *)dp->d_data + dp->d_size; + (void) putc('"', fp); + while (cp < end) { + if ((n = *cp++) != '\0') { + for (j = n; j > 0 && cp < end; j--) + if (*cp == '\n') { + (void) putc('\\', fp); + (void) putc(*cp++, fp); + } else + (void) putc(*cp++, fp); + } + } + /* XXXVIX need to keep the segmentation (see 4.9.5). */ + (void) fputs("\"", fp); + break; + case T_NSAP: + (void) fputs(inet_nsap_ntoa(dp->d_size, dp->d_data, NULL), fp); + break; + case T_LOC: + (void) fputs(loc_ntoa(dp->d_data, NULL), fp); + break; + case T_WKS: + GETLONG(addr, cp); + addr = htonl(addr); + fputs(inet_ntoa(*(struct in_addr *)&addr), fp); + proto = protocolname((u_char)*cp); + cp += sizeof(char); + fprintf(fp, "%s ", proto); + i = 0; + while(cp < (u_char *)dp->d_data + dp->d_size) { + j = *cp++; + do { + if (j & 0200) + fprintf(fp, " %s", + servicename(i, proto)); + j <<= 1; + } while (++i & 07); + } + break; + case T_MINFO: + case T_RP: + fprintf(fp, "%s.", cp); + cp += strlen((char *)cp) + 1; + fprintf(fp, " %s.", cp); + break; + default: + fprintf(fp, "\t;?d_type=%d?", dp->d_type); + } +} + +/* + * Return the number of authoritative zones that "dname" could belong to by + * stripping up to "depth" labels from dname. Up to the first "maxzones" + * authoritative zone numbers will be stored in "zonelist", ordered + * deepest match first. + */ +static int +findzone(const char *dname, int class, int depth, int *zonelist, int maxzones){ + char *tmpdname; + char tmpdnamebuf[MAXDNAME]; + char *zonename, *cp; + int tmpdnamelen, zonenamelen, zonenum, i, j, c; + int matches = 0; + int escaped, found, done; + + ns_debug(ns_log_update, 4, "findzone(dname=%s, class=%d, depth=%d, \ +zonelist=0x%x, maxzones=%d)", + dname, class, depth, zonelist, maxzones); +#ifdef DEBUG + if (debug >= 5) { + ns_debug(ns_log_update, 5, "zone dump:"); + for (zonenum = 1; zonenum < nzones; zonenum++) + printzoneinfo(zonenum, ns_log_update, 5); + } +#endif + + strcpy(tmpdnamebuf, dname); + tmpdname = tmpdnamebuf; + /* + * The code to handle trailing dots and escapes is adapted + * from samedomain(). + */ + tmpdnamelen = strlen(tmpdname); + /* + * Ignore a trailing label separator (i.e. an unescaped dot) + * in 'tmpdname'. + */ + if (tmpdnamelen && tmpdname[tmpdnamelen-1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if tmpdnamelen==1 */ + for (j = tmpdnamelen - 2; j >= 0; j--) + if (tmpdname[j] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else { + break; + } + if (!escaped) { + tmpdnamelen--; + tmpdname[tmpdnamelen] = '\0'; + } + } + + for (done = i = 0; i <= depth && !done; i++) { + for (zonenum = 1; zonenum < nzones; zonenum++) { + if (zones[zonenum].z_type == z_nil) + continue; + if (zones[zonenum].z_class != class) + continue; + zonename = zones[zonenum].z_origin; + zonenamelen = strlen(zonename); + /* + * Ignore a trailing label separator + * (i.e. an unescaped dot) in 'zonename'. + */ + if (zonenamelen && zonename[zonenamelen-1] == '.') { + escaped = 0; + for (j = zonenamelen - 2; j >= 0; j--) + if (zonename[j] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else { + break; + } + if (!escaped) + zonenamelen--; + } + + if (tmpdnamelen != zonenamelen) + continue; + ns_debug(ns_log_update, 5, + "about to strncasecmp('%s', '%s', %d)", + tmpdname, zonename, tmpdnamelen); + /* XXXRTH I'm doing a special test for zonenamelen == 0 + because I worry that some implementations of + strncasecmp might not handle comparisions where + n==0 correctly */ + if (zonenamelen == 0 || + !strncasecmp(tmpdname, zonename, tmpdnamelen)) { + ns_debug(ns_log_update, 5, "match"); + zonelist[matches++] = zonenum; + if (matches == maxzones) { + /* XXX should signal error */ + return (matches); + } + } + } + + /* + * Strip off the first label if we're not already at + * the root label. + */ + if (*tmpdname != '\0') { + for (escaped = found = 0; + (c = *tmpdname) && !found; + tmpdname++) { + if (!escaped && (c == '.')) + /* + * Note the loop increment will + * make tmpdname point past the '.' + * before the '!found' test causes + * us to exit the loop. + */ + found = 1; + + if (escaped) + escaped = 0; + else if (c == '\\') + escaped = 1; + } + } else + done = 1; + + tmpdnamelen = strlen(tmpdname); + } + ns_debug(ns_log_update, 4, + "findzone: returning %d match(es)", matches); + return (matches); +} + +/* + * reapply lost updates from log file for the zone to the zone + * + * returns -1 on error, 0 on success, 1 if dump reload needed + */ +int +merge_logs(struct zoneinfo *zp) { + char origin[MAXDNAME], data[MAXDATA], dnbuf[MAXDNAME], sclass[3]; + char buf[BUFSIZ], buf2[100]; + FILE *fp; + u_int32_t serial, ttl, old_serial, new_serial; + char *dname, *cp, *cp1; + int type, class; + int i, c, section, opcode, matches, zonenum, err, multiline; + int nonempty_lineno = -1, prev_pktdone = 0, cont = 0, inside_next = 0; + int id, rcode = NOERROR; + u_int32_t n; + struct map *mp; + ns_updrec *rrecp; + struct databuf *dp; + struct in_addr ina; + int zonelist[MAXDNAME]; + struct stat st; + u_char *serialp; + struct sockaddr_in empty_from; + int datasize; + + empty_from.sin_family = AF_INET; + empty_from.sin_addr.s_addr = htonl(INADDR_ANY); + empty_from.sin_port = htons(0); + + /* XXX - much of this stuff is similar to that in nsupdate.c + * getword_str() was used in nsupdate.c for reasons described there + * getword() is used here just to be consistent with db_load() + */ + + /* If there is no log file, just return. */ + if (stat(zp->z_updatelog, &st) < 0) { + if (errno != ENOENT) + ns_error(ns_log_update, + "unexpected stat(%s) failure: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + fp = fopen(zp->z_updatelog, "r"); + if (fp == NULL) { + ns_error(ns_log_update, "fopen(%s) failed: %s", + zp->z_updatelog, strerror(errno)); + return (-1); + } + + /* + * See if we really have a log file -- it might be a zone dump + * that was in the process of being renamed, or it might + * be garbage! + */ + + if (fgets(buf, sizeof(buf), fp)==NULL) { + ns_error(ns_log_update, "fgets() from %s failed: %s", + zp->z_updatelog, strerror(errno)); + fclose(fp); + return (-1); + } + if (strcmp(buf, DumpSignature) == 0) { + /* It's a dump; finish rename that was interrupted. */ + ns_info(ns_log_update, + "completing interrupted dump rename for %s", + zp->z_source); + if (rename(zp->z_updatelog, zp->z_source) < 0) { + ns_error(ns_log_update, "rename(%s,%s) failed: %s", + zp->z_updatelog, zp->z_source, + strerror(errno)); + return (-1); + } + fclose(fp); + /* Finally, tell caller to reload zone. */ + return (1); + } + if (strcmp(buf, LogSignature) != 0) { + /* Not a dump and not a log; complain and then bail out. */ + ns_error(ns_log_update, "invalid log file %s", + zp->z_updatelog); + fclose(fp); + return (-1); + } + + ns_debug(ns_log_update, 3, "merging logs for %s from %s", + zp->z_origin, zp->z_updatelog); + lineno = 1; + rrecp_start = NULL; + rrecp_last = NULL; + for (;;) { + if (!getword(buf, sizeof buf, fp, 0)) { + if (lineno == (nonempty_lineno + 1)) { + /* + * End of a nonempty line inside an update + * packet or not inside an update packet. + */ + continue; + } + /* + * Empty line or EOF. + * + * Marks completion of current update packet. + */ + inside_next = 0; + prev_pktdone = 1; + cont = 1; + } else { + nonempty_lineno = lineno; + } + + if (!strcasecmp(buf, "[DYNAMIC_UPDATE]")) { + err = 0; + rcode = NOERROR; + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || !sscanf((char *)cp, "id %d", &id)) + id = -1; + inside_next = 1; + prev_pktdone = 1; + cont = 1; + } else if (!strcasecmp(buf, "[INCR_SERIAL]")) { + /* XXXRTH not enough error checking here */ + cp = fgets(buf, sizeof buf, fp); + if (cp != NULL) + lineno++; + if (cp == NULL || + !sscanf((char *)cp, "from %u to %u", + &old_serial, &new_serial)) { + ns_error(ns_log_update, + "incr_serial problem with %s", + zp->z_updatelog); + } else { + serial = get_serial(zp); + if (serial != old_serial) { + ns_error(ns_log_update, + "serial number mismatch (log=%u, zone=%u) in %s", old_serial, + serial, zp->z_updatelog); + } else { + set_serial(zp, new_serial); + /* + * The zone has changed; make sure + * a dump is scheduled. + */ + (void)schedule_dump(zp); + sched_zone_maint(zp); + ns_info(ns_log_update, + "set serial to %u (log file %s)", + new_serial, zp->z_updatelog); + } + } + prev_pktdone = 1; + cont = 1; + } + if (prev_pktdone) { + if (rrecp_start) { + n = process_updates(rrecp_start, &rcode, + empty_from); + if (n > 0) + ns_info(ns_log_update, + "successfully merged update id %d from log file %s", + id, zp->z_updatelog); + else + ns_error(ns_log_update, + "error merging update id %d from log file %s", + id, zp->z_updatelog); + free_rrecp(&rrecp_start, &rrecp_last, rcode, + empty_from); + } + prev_pktdone = 0; + if (feof(fp)) + break; + } + if (cont) { + cont = 0; + continue; + } + if (!inside_next) + continue; + /* + * inside the same update packet, + * continue accumulating records. + */ + section = -1; + n = strlen(buf); + if (buf[n-1] == ':') + buf[--n] = '\0'; + for (mp = m_section; mp < m_section+M_SECTION_CNT; mp++) + if (!strcasecmp(buf, mp->token)) { + section = mp->val; + break; + } + ttl = 0; + type = -1; + class = zp->z_class; + n = 0; + data[0] = '\0'; + switch (section) { + case S_ZONE: + cp = fgets(buf, sizeof buf, fp); + if (!cp) + *buf = '\0'; + n = sscanf(cp, "origin %s class %s serial %ul", + origin, sclass, &serial); + if (n != 3 || strcasecmp(origin, zp->z_origin)) + err++; + if (cp) + lineno++; + if (!err && serial != zp->z_serial) { + ns_error(ns_log_update, + "serial number mismatch in update id %d (log=%u, zone=%u) in %s", + id, serial, zp->z_serial, + zp->z_updatelog); + inside_next = 0; + err++; + } + if (!err && inside_next) { + int success; + + dname = origin; + type = T_SOA; + class = sym_ston(__p_class_syms, sclass, + &success); + if (!success) { + err++; + break; + } + matches = findzone(dname, class, 0, + zonelist, MAXDNAME); + if (matches) + zonenum = zonelist[0]; + else + err++; + } + break; + case S_PREREQ: + case S_UPDATE: + /* Operation code. */ + if (!getword(buf, sizeof buf, fp, 0)) { + err++; + break; + } + opcode = -1; + if (buf[0] == '{') { + n = strlen(buf); + for (i = 0; (u_int32_t)i < n; i++) + buf[i] = buf[i+1]; + if (buf[n-2] == '}') + buf[n-2] = '\0'; + } + for (mp = m_opcode; mp < m_opcode+M_OPCODE_CNT; mp++) + if (!strcasecmp(buf, mp->token)) { + opcode = mp->val; + break; + } + if (opcode == -1) { + err++; + break; + } + /* Owner's domain name. */ + if (!getword((char *)dnbuf, sizeof dnbuf, fp, 0)) { + err++; + break; + } + n = strlen((char *)dnbuf) - 1; + if (dnbuf[n] == '.') + dnbuf[n] = '\0'; + dname = dnbuf; + ttl = 0; + type = -1; + class = zp->z_class; + n = 0; + data[0] = '\0'; + (void) getword(buf, sizeof buf, fp, 1); + if (isdigit(buf[0])) { /* ttl */ + ttl = strtoul(buf, 0, 10); + if (errno == ERANGE && ttl == ULONG_MAX) { + err++; + break; + } + (void) getword(buf, sizeof buf, fp, 1); + } + + /* possibly class */ + if (buf[0] != '\0') { + int success; + int maybe_class; + + maybe_class = sym_ston(__p_class_syms, + buf, + &success); + if (success) { + class = maybe_class; + (void) getword(buf, + sizeof buf, + fp, 1); + } + } + /* possibly type */ + if (buf[0] != '\0') { + int success; + int maybe_type; + + maybe_type = sym_ston(__p_type_syms, + buf, + &success); + + if (success) { + type = maybe_type; + (void) getword(buf, + sizeof buf, + fp, 1); + } + } + if (buf[0] != '\0') /* possibly rdata */ + /* + * Convert the ascii data 'buf' to the proper + * format based on the type and pack into + * 'data'. + * + * XXX - same as in db_load(), + * consolidation needed + */ + switch (type) { + case T_A: + if (!inet_aton(buf, &ina)) { + err++; + break; + } + n = ntohl(ina.s_addr); + cp = data; + PUTLONG(n, cp); + n = INT32SZ; + break; + case T_HINFO: + case T_ISDN: + n = strlen(buf); + data[0] = n; + memcpy(data+1, buf, n); + n++; + if (!getword(buf, sizeof buf, + fp, 0)) { + i = 0; + } else { + endline(fp); + i = strlen(buf); + } + data[n] = i; + memcpy(data+n+1, buf, i); + break; + case T_SOA: + case T_MINFO: + case T_RP: + (void) strcpy(data, buf); + cp = data + strlen(data) + 1; + if (!getword((char *)cp, + sizeof data - (cp - data), + fp, 1)) { + err++; + break; + } + cp += strlen((char *)cp) + 1; + if (type != T_SOA) { + n = cp - data; + break; + } + if (class != zp->z_class || + strcasecmp(dname, zp->z_origin)) { + err++; + break; + } + c = getnonblank(fp, zp->z_updatelog); + if (c == '(') { + multiline = 1; + } else { + multiline = 0; + ungetc(c, fp); + } + for (i = 0; i < 5; i++) { + n = getnum(fp, zp->z_updatelog, + GETNUM_SERIAL); + if (getnum_error) { + err++; + break; + } + PUTLONG(n, cp); + } + if (multiline && + getnonblank(fp, zp->z_updatelog) + != ')') { + err++; + break; + } + endline(fp); + break; + case T_WKS: + if (!inet_aton(buf, &ina)) { + err++; + break; + } + n = ntohl(ina.s_addr); + cp = data; + PUTLONG(n, cp); + *cp = (char)getprotocol(fp, + zp->z_updatelog + ); + n = INT32SZ + sizeof(char); + n = getservices((int)n, data, + fp, zp->z_updatelog); + break; + case T_NS: + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_PTR: + (void) strcpy(data, buf); + if (makename(data, origin, + sizeof(data)) == -1) { + err++; + break; + } + n = strlen(data) + 1; + break; + case T_MX: + case T_AFSDB: + case T_RT: + n = 0; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + /* catch bad values */ + cp = data; + PUTSHORT((u_int16_t)n, cp); + if (!getword(buf, sizeof(buf), + fp, 1)) { + err++; + break; + } + (void) strcpy((char *)cp, buf); + if (makename((char *)cp, origin, + sizeof(data) - (cp-data)) + == -1) { + err++; + break; + } + /* advance pointer to end of data */ + cp += strlen((char *)cp) +1; + /* now save length */ + n = (cp - data); + break; + case T_PX: + n = 0; + data[0] = '\0'; + cp = buf; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + cp = data; + PUTSHORT((u_int16_t)n, cp); + for (i = 0; i < 2; i++) { + if (!getword(buf, + sizeof(buf), + fp, 0)) { + err++; + break; + } + (void) strcpy((char *)cp, + buf); + cp += strlen((char *)cp) + 1; + } + n = cp - data; + break; + case T_TXT: + case T_X25: + i = strlen(buf); + cp = data; + datasize = sizeof data; + cp1 = buf; + while (i > 255) { + if (datasize < 256) { + ns_error(ns_log_update, + "record too big"); + return (-1); + } + datasize -= 255; + *cp++ = 255; + memcpy(cp, cp1, 255); + cp += 255; + cp1 += 255; + i -= 255; + } + if (datasize < i + 1) { + ns_error(ns_log_update, + "record too big"); + return (-1); + } + *cp++ = i; + memcpy(cp, cp1, i); + cp += i; + n = cp - data; + endline(fp); + /* XXXVIX: segmented texts 4.9.5 */ + break; + case T_NSAP: + n = inet_nsap_addr(buf, + (u_char *)data, + sizeof data); + endline(fp); + break; + case T_LOC: + cp = buf + (n = strlen(buf)); + *cp = ' '; + cp++; + while ((i = getc(fp), *cp = i, + i != EOF) + && *cp != '\n' + && (n < MAXDATA)) { + cp++; + n++; + } + if (*cp == '\n') + ungetc(*cp, fp); + *cp = '\0'; + n = loc_aton(buf, (u_char *)data); + if (n == 0) { + err++; + break; + } + endline(fp); + break; + default: + err++; + } + if (section == S_PREREQ) { + ttl = 0; + if (opcode == NXDOMAIN) { + class = C_NONE; + type = T_ANY; + n = 0; + } else if (opcode == YXDOMAIN) { + class = C_ANY; + type = T_ANY; + n = 0; + } else if (opcode == NXRRSET) { + class = C_NONE; + n = 0; + } else if (opcode == YXRRSET) { + if (n == 0) + class = C_ANY; + } + } else { /* section == S_UPDATE */ + if (opcode == DELETE) { + if (n == 0) { + class = C_ANY; + if (type == -1) + type = T_ANY; + } else { + class = C_NONE; + } + } + } + break; + case S_ADDT: + default: + ns_debug(ns_log_update, 1, + "cannot interpret section: %d", section); + inside_next = 0; + err++; + } + if (err) { + inside_next = 0; + ns_debug(ns_log_update, 1, + "merge of update id %d failed due to error at line %d", + id, lineno); + free_rrecp(&rrecp_start, &rrecp_last, rcode, + empty_from); + continue; + } + rrecp = res_mkupdrec(section, dname, class, type, ttl); + if (section != S_ZONE) { + dp = savedata(class, type, ttl, (u_char *)data, n); + dp->d_zone = zonenum; + dp->d_cred = DB_C_ZONE; + dp->d_clev = nlabels(zp->z_origin); + rrecp->r_dp = dp; + } else { + rrecp->r_zone = zonenum; + } + if (rrecp_start == NULL) { + rrecp_start = rrecp; + rrecp_last = rrecp; + rrecp->r_prev = NULL; + rrecp->r_next = NULL; + } else { + rrecp_last->r_next = rrecp; + rrecp->r_prev = rrecp_last; + rrecp->r_next = NULL; + rrecp_last = rrecp; + } + } /* for (;;) */ + + fclose(fp); + return (0); +} + + +/* + * Create a disk database to back up zones + */ +int +zonedump(zp) + struct zoneinfo *zp; +{ + FILE *fp; + const char *fname; + struct hashbuf *htp; + char *op; + struct stat st; + char tmp_name[MAXPATHLEN]; + int escaped; + char c; + + /* + * We must check to see if Z_NEED_SOAUPDATE is set, and if so + * we must do it. This won't be the case normally + * (when called from ns_maint()), but it is possible if we're + * exiting named. + */ + + if (zp->z_flags & Z_NEED_SOAUPDATE) { + u_int32_t serial, old_serial; + + old_serial = get_serial(zp); + serial = old_serial + 1; + if (serial == 0) + serial = 1; + set_serial(zp, serial); + } + + /* Only dump zone if there is a cache specified */ + if (zp->z_source && *(zp->z_source)) { + ns_debug(ns_log_update, 1, "zonedump(%s)", zp->z_source); + + if (strlen(zp->z_source)+strlen(DumpSuffix) >= MAXPATHLEN) { + ns_error(ns_log_update, + "filename %s too long in zonedump", + zp->z_source); + /* + * This problem won't ever get better, so we + * clear the "need dump" flag. + */ + zp->z_flags &= ~Z_NEED_DUMP; + return (-1); + } + (void)sprintf(tmp_name, "%s%s", zp->z_source, DumpSuffix); + if ((fp = write_open(tmp_name)) == NULL) { + ns_error(ns_log_update, "fopen() of %s failed: %s", + tmp_name, strerror(errno)); + return (-1); + } + fprintf(fp, "%s", DumpSignature); + op = zp->z_origin; + escaped = 0; + while (*op && (((c = *op++) != '.') || escaped)) + escaped = (c == '\\') && !escaped; + gettime(&tt); + htp = hashtab; + if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) { + if (db_dump(htp, fp, zp-zones, op) != OK) { + ns_error(ns_log_update, + "error dumping zone file %s", + zp->z_source); + (void)fclose(fp); + return (-1); + } + } + if (fflush(fp) == EOF) { + ns_error(ns_log_update, "fflush() of %s failed: %s", + tmp_name, strerror(errno)); + return (-1); + } + if (fsync(fileno(fp)) < 0) { + ns_error(ns_log_update, "fsync() of %s failed: %s", + tmp_name, strerror(errno)); + return (-1); + } + if (fclose(fp) == EOF) { + ns_error(ns_log_update, "fclose() of %s failed: %s", + tmp_name, strerror(errno)); + return (-1); + } + /* + * Try to make read only, so people will be less likely to + * edit dynamic domains. + */ + if (stat(tmp_name, &st) < 0) { + ns_error(ns_log_update, + "stat(%s) failed, pressing on: %s", + tmp_name, strerror(errno)); + } else { + zp->z_ftime = st.st_mtime; + st.st_mode &= ~WRITEABLE_MASK; + if (chmod(tmp_name, st.st_mode) < 0) + ns_error(ns_log_update, + "chmod(%s,%o) failed, pressing on: %s", + tmp_name, st.st_mode, + strerror(errno)); + } + if (rename(tmp_name, zp->z_updatelog) < 0) { + ns_error(ns_log_update, "rename(%s,%s) failed: %s", + tmp_name, zp->z_updatelog, strerror(errno)); + return (-1); + } + if (rename(zp->z_updatelog, zp->z_source) < 0) { + ns_error(ns_log_update, "rename(%s,%s) failed: %s", + zp->z_updatelog, zp->z_source, + strerror(errno)); + return (-1); + } + } else + ns_debug(ns_log_update, 1, "zonedump: no zone to dump"); + + zp->z_flags &= ~Z_NEED_DUMP; + zp->z_dumptime = 0; + return (0); +} + +struct databuf * +findzonesoa(struct zoneinfo *zp) { + struct hashbuf *htp; + struct namebuf *np; + struct databuf *dp; + const char *fname; + + htp = hashtab; + np = nlookup(zp->z_origin, &htp, &fname, 0); + if (np == NULL || fname != zp->z_origin) + return (NULL); + foreach_rr(dp, np, T_SOA, zp->z_class, zp - zones) + return (dp); + return (NULL); +} + +u_char * +findsoaserial(u_char *data) { + char *cp = (char *)data; + + cp += strlen(cp) + 1; /* Nameserver. */ + cp += strlen(cp) + 1; /* Mailbox. */ + return ((u_char *)cp); +} + +u_int32_t +get_serial_unchecked(struct zoneinfo *zp) { + struct databuf *dp; + u_char *cp; + u_int32_t ret; + + dp = findzonesoa(zp); + if (!dp) + ns_panic(ns_log_update, 1, + "get_serial_unchecked(%s): can't locate zone SOA", + zp->z_origin); + cp = findsoaserial(dp->d_data); + GETLONG(ret, cp); + return (ret); +} + +u_int32_t +get_serial(struct zoneinfo *zp) { + u_int32_t ret; + + ret = get_serial_unchecked(zp); + if (ret != zp->z_serial) + ns_panic(ns_log_update, 1, + "get_serial(%s): db and zone serial numbers differ", + zp->z_origin); + return (ret); +} + +void +set_serial(struct zoneinfo *zp, u_int32_t serial) { + struct databuf *dp; + u_char *cp; + + dp = findzonesoa(zp); + if (!dp) + ns_panic(ns_log_update, 1, + "set_serial(%s): can't locate zone SOA", + zp->z_origin); + cp = findsoaserial(dp->d_data); + PUTLONG(serial, cp); + zp->z_serial = serial; + zp->z_flags &= ~Z_NEED_SOAUPDATE; + zp->z_soaincrtime = 0; + zp->z_updatecnt = 0; +#ifdef BIND_NOTIFY + sysnotify(zp->z_origin, zp->z_class, T_SOA); +#endif + /* + * Note: caller is responsible for scheduling a dump + */ +} + +/* + * Increment serial number in zoneinfo structure and hash table SOA databuf + */ + +int +incr_serial(struct zoneinfo *zp) { + u_int32_t serial, old_serial; + FILE *fp; + time_t t; + + old_serial = get_serial(zp); + serial = old_serial + 1; + if (serial == 0) + serial = 1; + set_serial(zp, serial); + + (void) gettime(&tt); + t = (time_t)tt.tv_sec; + fp = open_transaction_log(zp); + if (fp == NULL) + return (-1); + fprintf(fp, "[INCR_SERIAL] from %u to %u %s\n", + old_serial, serial, checked_ctime(&t)); + if (close_transaction_log(zp, fp)<0) + return (-1); + + /* + * This shouldn't happen, but we check to be sure. + */ + if (!(zp->z_flags & Z_NEED_DUMP)) { + ns_warning(ns_log_update, + "incr_serial: Z_NEED_DUMP not set for zone '%s'", + zp->z_origin); + (void)schedule_dump(zp); + } + + sched_zone_maint(zp); + + return (0); +} + +void +dynamic_about_to_exit(void) { + struct zoneinfo *zp; + + ns_debug(ns_log_update, 1, + "shutting down; dumping zones that need it"); + for (zp = zones; zp < &zones[nzones]; zp++) { + if ((zp->z_flags & Z_DYNAMIC) && + ((zp->z_flags & Z_NEED_SOAUPDATE) || + (zp->z_flags & Z_NEED_DUMP))) + (void)zonedump(zp); + } +} diff --git a/contrib/bind/bin/named/ns_xfr.c b/contrib/bind/bin/named/ns_xfr.c new file mode 100644 index 0000000..52d3464 --- /dev/null +++ b/contrib/bind/bin/named/ns_xfr.c @@ -0,0 +1,642 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: ns_xfr.c,v 8.25 1998/03/25 18:47:34 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996, 1997 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 "port_before.h" + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <fcntl.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "named.h" + +static struct qs_x_lev *sx_freelev(struct qs_x_lev *lev); + +static void sx_newmsg(struct qstream *qsp), + sx_sendlev(struct qstream *qsp), + sx_sendsoa(struct qstream *qsp); + +static int sx_flush(struct qstream *qsp), + sx_addrr(struct qstream *qsp, + const char *dname, + struct databuf *dp), + sx_nsrrs(struct qstream *qsp), + sx_allrrs(struct qstream *qsp), + sx_pushlev(struct qstream *qsp, struct namebuf *np); + +/* + * void + * ns_xfr(qsp, znp, zone, class, type, opcode, id) + * Initiate a concurrent (event driven) outgoing zone transfer. + */ +void +ns_xfr(struct qstream *qsp, struct namebuf *znp, + int zone, int class, int type, + int opcode, int id) +{ + FILE *rfp; + int fdstat; + pid_t pid; + server_info si; +#ifdef SO_SNDBUF + static const int sndbuf = XFER_BUFSIZE * 2; +#endif +#ifdef SO_SNDLOWAT + static const int sndlowat = XFER_BUFSIZE; +#endif + + ns_info(ns_log_xfer_out, "zone transfer of \"%s\" (%s) to %s", + zones[zone].z_origin, p_class(class), sin_ntoa(qsp->s_from)); + +#ifdef SO_SNDBUF + /* + * The default seems to be 4K, and we'd like it to have enough room + * to parallelize sending the pushed data with accumulating more + * write() data from us. + */ + (void) setsockopt(qsp->s_rfd, SOL_SOCKET, SO_SNDBUF, + (char *)&sndbuf, sizeof sndbuf); +#endif +#ifdef SO_SNDLOWAT + /* + * We don't want select() to show writability 'til we can write + * an XFER_BUFSIZE block of data. + */ + (void) setsockopt(qsp->s_rfd, SOL_SOCKET, SO_SNDLOWAT, + (char *)&sndlowat, sizeof sndlowat); +#endif + if (sq_openw(qsp, 64*1024) == -1) + goto abort; + memset(&qsp->xfr, 0, sizeof qsp->xfr); + qsp->xfr.top = znp; + qsp->xfr.zone = zone; + qsp->xfr.class = class; + qsp->xfr.id = id; + qsp->xfr.opcode = opcode; + qsp->xfr.msg = memget(XFER_BUFSIZE); + if (!qsp->xfr.msg) + goto abort; + qsp->xfr.eom = qsp->xfr.msg + XFER_BUFSIZE; + qsp->xfr.cp = NULL; + qsp->xfr.state = s_x_firstsoa; + zones[zone].z_numxfrs++; + qsp->flags |= STREAM_AXFR; + + si = find_server(qsp->s_from.sin_addr); + if (si != NULL && si->transfer_format != axfr_use_default) + qsp->xfr.transfer_format = si->transfer_format; + else + qsp->xfr.transfer_format = server_options->transfer_format; + + if (sx_pushlev(qsp, znp) < 0) { + abort: + (void) shutdown(qsp->s_rfd, 2); + sq_remove(qsp); + return; + } + (void) sq_writeh(qsp, sx_sendsoa); +} + +/* + * void + * ns_stopxfrs(zp) + * Stop (abort, reset) all transfers of the zone specified by 'zp'. + */ +void +ns_stopxfrs(struct zoneinfo *zp) { + struct qstream *this, *next; + u_int zone = (u_int)(zp - zones); + + for (this = streamq; this; this = next) { + next = this->s_next; + if (this->xfr.zone == zone) { + (void) shutdown(this->s_rfd, 2); + sq_remove(this); + } + } + INSIST(zp->z_numxfrs == 0); +} + +/* + * void + * ns_freexfr(qsp) + * Free all xfr-related dynamic data associated with qsp. + */ +void +ns_freexfr(struct qstream *qsp) { + if (qsp->xfr.msg != NULL) { + memput(qsp->xfr.msg, XFER_BUFSIZE); + qsp->xfr.msg = NULL; + } + while (qsp->xfr.lev) + qsp->xfr.lev = sx_freelev(qsp->xfr.lev); + zones[qsp->xfr.zone].z_numxfrs--; + qsp->flags &= ~STREAM_AXFR; +} + +/* + * u_char * + * renew_msg(msg) + * init the header of a message, reset the compression pointers, and + * reset the write pointer to the first byte following the header. + */ +static void +sx_newmsg(struct qstream *qsp) { + HEADER *hp = (HEADER *)qsp->xfr.msg; + + memset(hp, 0, HFIXEDSZ); + hp->id = htons(qsp->xfr.id); + hp->opcode = qsp->xfr.opcode; + hp->qr = 1; + hp->rcode = NOERROR; + + qsp->xfr.ptrs[0] = qsp->xfr.msg; + qsp->xfr.ptrs[1] = NULL; + + qsp->xfr.cp = qsp->xfr.msg + HFIXEDSZ; +} + +/* + * int + * sx_flush(qsp) + * flush the intermediate buffer out to the stream IO system. + * return: + * passed through from sq_write(). + */ +static int +sx_flush(struct qstream *qsp) { + int ret; + +#ifdef DEBUG + if (debug >= 10) + fp_nquery(qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg, + log_get_stream(packet_channel)); +#endif + ret = sq_write(qsp, qsp->xfr.msg, qsp->xfr.cp - qsp->xfr.msg); + if (ret >= 0) + qsp->xfr.cp = NULL; + return (ret); +} + +/* + * int + * sx_addrr(qsp, name, dp) + * add name/dp's RR to the current assembly message. if it won't fit, + * write current message out, renew the message, and then RR should fit. + * return: + * -1 = the sx_flush() failed so we could not queue the full message. + * 0 = one way or another, everything is fine. + * side effects: + * on success, the ANCOUNT is incremented and the pointers are advanced. + */ +static int +sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) { + HEADER *hp = (HEADER *)qsp->xfr.msg; + u_char **edp = qsp->xfr.ptrs + sizeof qsp->xfr.ptrs / sizeof(u_char*); + int n; + + if (qsp->xfr.cp != NULL) { + if (qsp->xfr.transfer_format == axfr_one_answer && + sx_flush(qsp) < 0) + return (-1); + } + if (qsp->xfr.cp == NULL) + sx_newmsg(qsp); + n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp, + 0, qsp->xfr.ptrs, edp); + if (n < 0) { + if (sx_flush(qsp) < 0) + return (-1); + if (qsp->xfr.cp == NULL) + sx_newmsg(qsp); + n = make_rr(dname, dp, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp, + 0, qsp->xfr.ptrs, edp); + INSIST(n >= 0); + } + hp->ancount = htons(ntohs(hp->ancount) + 1); + qsp->xfr.cp += n; + return (0); +} + +/* + * int + * sx_soarr(qsp) + * add the SOA RR's at the current level's top np to the assembly message. + * return: + * 0 = success + * -1 = write buffer full, cannot continue at this time + * side effects: + * if progress was made, header and pointers will be advanced. + */ +static int +sx_soarr(struct qstream *qsp) { + struct databuf *dp; + + foreach_rr(dp, qsp->xfr.top, T_SOA, qsp->xfr.class, qsp->xfr.zone) { + if (sx_addrr(qsp, zones[qsp->xfr.zone].z_origin, dp) < 0) { + /* RR wouldn't fit. Bail out. */ + return (-1); + } + return (0); + } + ns_panic(ns_log_xfer_out, 1, "no SOA at zone top"); +} + +/* + * int + * sx_nsrrs(qsp) + * add the NS RR's at the current level's current np, + * to the assembly message + * return: + * >1 = number of NS RRs added, note that there may be more + * 0 = success, there are no more NS RRs at this level + * -1 = write buffer full, cannot continue at this time + * side effects: + * if progress was made, header and pointers will be advanced. + * note: + * this is meant for AXFR, which includes glue as part of the answer + * sections. this is different from and incompatible with the additional + * data of a referral response. + */ +static int +sx_nsrrs(struct qstream *qsp) { + struct databuf *dp, *tdp, *gdp; + struct namebuf *gnp, *tnp, *top; + struct hashbuf *htp; + const char *fname; + int rrcount, class; + + class = qsp->xfr.class; + top = qsp->xfr.top; + rrcount = 0; + for ((void)NULL; + (dp = qsp->xfr.lev->dp) != NULL; + qsp->xfr.lev->dp = dp->d_next) { + /* XYZZY foreach_rr? */ + if (dp->d_class != class && class != C_ANY) + continue; + if (dp->d_rcode) + continue; + /* + * It might not be in the same zone, if we are authoritative + * for both parent and child, but it does have to be a zone. + * + * XXX: this is sort of a bug, since it means we merge the + * @ NS RRset into our parent's zone. But that is what + * db_load() does, so for now we have no choice. + */ + if (dp->d_zone == DB_Z_CACHE) + continue; + if (dp->d_type != T_NS) + continue; + if (!(qsp->xfr.lev->flags & SXL_GLUING)) { + if (sx_addrr(qsp, qsp->xfr.lev->dname, dp) < 0) { + /* RR wouldn't fit. Bail out. */ + return (-1); + } + rrcount++; + } + + /* + * Glue the sub domains together by sending the address + * records for the sub domain name servers along if necessary. + * Glue is necessary if the server is in any zone delegated + * from the current (top) zone. Such a delegated zone might + * or might not be that referred to by the NS record now + * being handled. + */ + htp = hashtab; + gnp = nlookup((char *)dp->d_data, &htp, &fname, 0); + if (gnp == NULL || fname != (char *)dp->d_data) + continue; + for (tnp = gnp; + tnp != NULL && tnp != top; + tnp = tnp->n_parent) + (void)NULL; + if (tnp == NULL && NAME(*top)[0] != '\0') + continue; /* name server is not below top domain */ + for (tnp = gnp; + tnp != NULL && tnp != top; + tnp = tnp->n_parent) { + foreach_rr(tdp, tnp, T_NS, class, DB_Z_CACHE) + break; + /* If we found a zone cut, we're outta here. */ + if (tdp != NULL) + break; + } + /* If name server is not in a delegated zone, skip it. */ + if (tnp == top || (tnp == NULL && NAME(*top)[0] == '\0')) + continue; + /* Now we know glue records are needed. Send them. */ + qsp->xfr.lev->flags |= SXL_GLUING; + foreach_rr(gdp, gnp, T_A, class, DB_Z_CACHE) + if (sx_addrr(qsp, fname, gdp) < 0) { + /* + * Rats. We already sent the NS RR, too. + * Note that SXL_GLUING is being left on. + */ + return (-1); + } + qsp->xfr.lev->flags &= ~SXL_GLUING; + } + return (rrcount); +} + +/* + * int + * sx_allrrs(qsp) + * add the non-(SOA,NS) RR's at the current level's current np, + * to the assembly message + * return: + * >0 = number of RR's added, note that there may be more + * 0 = success, there are no more RRs at this level + * -1 = write buffer full, cannot continue at this time + * side effects: + * if progress was made, header and pointers will be advanced. + * note: + * this is meant for AXFR, which includes glue as part of the answer + * sections. this is different from and incompatible with the additional + * data of a referral response. + */ +static int +sx_allrrs(struct qstream *qsp) { + struct databuf *dp, *tdp, *gdp; + struct namebuf *gnp, *tnp, *top; + struct hashbuf *htp; + const char *fname; + int rrcount, class; + u_int zone; + + class = qsp->xfr.class; + top = qsp->xfr.top; + zone = qsp->xfr.zone; + rrcount = 0; + for ((void)NULL; + (dp = qsp->xfr.lev->dp) != NULL; + qsp->xfr.lev->dp = dp->d_next) { + /* XYZZY foreach_rr? */ + if (dp->d_class != class && class != C_ANY) + continue; + if (dp->d_rcode) + continue; + if (dp->d_zone != zone || stale(dp)) + continue; + if (dp->d_type == T_SOA || dp->d_type == T_NS) + continue; + /* XXXRTH I presume this is still relevant and that + this is the right place... */ +#if 0 /* Not yet implemented. Only a SHOULD in the I-D. -gnu@toad.com */ + /* skip the SIG AXFR record because we did it first too. */ + if (dp->d_type == T_SIG) { + int sig_rrtype = GETSHORT (dp->d_data); + if (sig_rrtype == T_AXFR) + continue; + } +#endif /* 0 */ + INSIST(!(qsp->xfr.lev->flags & SXL_GLUING)); + + if (sx_addrr(qsp, qsp->xfr.lev->dname, dp) < 0) { + /* RR wouldn't fit. Bail out. */ + return (-1); + } + rrcount++; + } + return (rrcount); +} + +/* + * void + * sx_sendlev(qsp) + * send all the RRs at the current level (really a domain name), and + * do a decomposed recursion to get all subdomains up to and including + * but not exceeding bottom zone cuts. + * side effects: + * advances qsp->xfr pointers. changes qsp->xfr.lev quite often. + * causes messages to be sent to a remote TCP client. changes the + * qsp->xfr.state at the end of the topmost level. changes the + * qsp->xfr.lev->state several times per domain name. + */ +static void +sx_sendlev(struct qstream *qsp) { + struct qs_x_lev *lev; + int rrcount; + + again: + lev = qsp->xfr.lev; + switch (lev->state) { + case sxl_ns: { + while (lev->dp) { + rrcount = sx_nsrrs(qsp); + /* If we can't pack this one in, come back later. */ + if (rrcount < 0) + return; + /* + * NS RRs other than those at the + * zone top are zone cuts. + */ + if (rrcount > 0 && qsp->xfr.top != lev->np) + lev->flags |= SXL_ZONECUT; + } + /* No more DP's for the NS RR pass on this NP. */ + if (lev->flags & SXL_ZONECUT) { + /* Zone cut, so go directly to end of level. */ + break; + } + /* No NS RR's, so it's safe to send other types. */ + lev->state = sxl_all; + lev->dp = lev->np->n_data; + goto again; + } + case sxl_all: { + while (lev->dp) { + /* If we can't pack this one in, come back later. */ + if (sx_allrrs(qsp) < 0) + return; + } + /* No more non-NS DP's for this NP, do subdomains. */ + lev->state = sxl_sub; + goto again; + } + case sxl_sub: { + struct namebuf *np; + + /* Get next in-use hash chain if we're not following one. */ + while (lev->nnp == NULL) { + /* If no, or no more subdomains, end of level. */ + if (lev->npp == NULL || lev->npp == lev->npe) + break; + lev->nnp = *lev->npp++; + } + /* If we encountered the end of the level, we're outta here. */ + if ((np = lev->nnp) == NULL) + break; + /* Next time, we'll do the following NP, or the next chain. */ + lev->nnp = np->n_next; + /* Skip our own NP if it appears as a subdom (as in root). */ + if (np != lev->np) + sx_pushlev(qsp, np); + goto again; + } + default: + abort(); + } + + /* End of level. Pop it off the stack. */ + + if ((qsp->xfr.lev = sx_freelev(lev)) == NULL) { + /* End of topmost level. */ + qsp->xfr.state = s_x_lastsoa; + sq_writeh(qsp, sx_sendsoa); + return; + } + goto again; +} + +/* + * void + * sx_sendsoa(qsp) + * send either the first or last SOA needed for an AXFR. + * side effects: + * changes qsp->xfr.state. adds RR to output buffer. + */ +static void +sx_sendsoa(struct qstream *qsp) { + if (sx_soarr(qsp) == -1) + return; /* No state change, come back here later. */ + + switch (qsp->xfr.state) { + case s_x_firstsoa: { + /* Next thing to do is send the zone. */ + qsp->xfr.state = s_x_zone; + sq_writeh(qsp, sx_sendlev); + break; + } + case s_x_lastsoa: { + /* Next thing to do is go back and wait for another query. */ + (void)sx_flush(qsp); + qsp->xfr.state = s_x_done; + sq_writeh(qsp, sq_flushw); + break; + } + default: { + ns_panic(ns_log_xfer_out, 1, + "unexpected state %d in sx_sendsoa", qsp->xfr.state); + } + } +} + +/* int + * sx_pushlev(qsp, np) + * manage the decomposed recursion. set up for a new level (domain). + * returns: + * 0 = success + * -1 = failure (check errno) + */ +static int +sx_pushlev(struct qstream *qsp, struct namebuf *np) { + struct qs_x_lev *new = memget(sizeof *new); + struct hashbuf *htp; + + if (!new) { + errno = ENOMEM; + return (-1); + } + memset(new, 0, sizeof *new); + new->state = sxl_ns; + new->np = np; + new->dp = np->n_data; + getname(np, new->dname, sizeof new->dname); + /* + * We find the subdomains by looking in the hash table for this + * domain, but the root domain needs special treatment, because + * of the following wart in the database design: + * + * The top level hash table (pointed to by the global `hashtab' + * variable) contains pointers to the namebuf's for the root as + * well as for the top-level domains below the root, in contrast + * to the usual situation where a hash table contains entries + * for domains at the same level. The n_hash member of the + * namebuf for the root domain is NULL instead of pointing to a + * hashbuf for the top-level domains. The n_parent members of + * the namebufs for the top-level domains are NULL instead of + * pointing to the namebuf for the root. + * + * We work around the wart as follows: + * + * If we are not dealing with the root zone then we just set + * htp = np->n_hash, pointing to the hash table for the current + * domain, and we walk through the hash table as usual, + * processing the namebufs for all the subdomains. + * + * If we are dealing with the root zone, then we set + * htp = hashtab, pointing to the global hash table (because + * there is no hash table associated with the root domain's + * namebuf. While we walk this hash table, we take care not to + * recursively process the entry for the root namebuf. + * + * (apb@und nov1990) + */ + htp = ((new->dname[0] == '\0') ? hashtab : np->n_hash); + if (htp) { + new->npp = htp->h_tab; + new->npe = htp->h_tab + htp->h_size; + } else { + new->npp = NULL; + new->npe = NULL; + } + new->nnp = NULL; + new->next = qsp->xfr.lev; + qsp->xfr.lev = new; + return (0); +} + +/* + * qs_x_lev * + * sx_freelev(lev) + * free the memory occupied by a level descriptor + * return: + * pointer to "next" level descriptor + */ +static struct qs_x_lev * +sx_freelev(struct qs_x_lev *lev) { + struct qs_x_lev *next = lev->next; + + memput(lev, sizeof *lev); + return (next); +} diff --git a/contrib/bind/bin/named/pathnames.c b/contrib/bind/bin/named/pathnames.c new file mode 100644 index 0000000..2ba2415 --- /dev/null +++ b/contrib/bind/bin/named/pathnames.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: pathnames.c,v 8.5 1997/05/21 19:52:28 halley Exp $ + */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include <isc/eventlib.h> +#include <isc/logging.h> + +#include "port_after.h" + +#include "named.h" + +int +main(int argc, char *argv[], char *envp[]) { + char *arg; + + argc--, argv++; + while (argc-- && (arg = *argv++) != NULL) + if (!strcasecmp("_PATH_XFER", arg)) + puts(_PATH_XFER); + else if (!strcasecmp("_PATH_PIDFILE", arg)) + puts(_PATH_PIDFILE); + else if (!strcasecmp("_PATH_NAMED", arg)) + puts(_PATH_NAMED); + else + exit(1); + exit(0); +} diff --git a/contrib/bind/bin/named/pathtemplate.h b/contrib/bind/bin/named/pathtemplate.h new file mode 100644 index 0000000..d339ef8 --- /dev/null +++ b/contrib/bind/bin/named/pathtemplate.h @@ -0,0 +1,70 @@ +/* + * $Id: pathtemplate.h,v 8.1 1998/03/19 19:53:21 halley Exp $ + */ + +/* + * Copyright (c) 1996, 1997 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 <paths.h> + +#ifndef _PATH_CONF +#define _PATH_CONF "%DESTETC%/named.conf" +#endif + +#ifndef _PATH_DEBUG +#define _PATH_DEBUG "named.run" +#endif + +#ifndef _PATH_DUMPFILE +#define _PATH_DUMPFILE "named_dump.db" +#endif + +#ifndef _PATH_NAMED +#define _PATH_NAMED "%DESTSBIN%/named" +#endif + +#ifndef _PATH_PIDFILE +#define _PATH_PIDFILE "%DESTRUN%/named.pid" +#endif + +#ifndef _PATH_STATS +#define _PATH_STATS "named.stats" +#endif + +#ifndef _PATH_MEMSTATS +#define _PATH_MEMSTATS "named.memstats" +#endif + +#ifndef _PATH_TMPXFER +#define _PATH_TMPXFER "xfer.ddt.XXXXXX" +#endif + +#ifndef _PATH_XFER +#define _PATH_XFER "%DESTEXEC%/named-xfer" +#endif + +#ifndef _PATH_XFERTRACE +#define _PATH_XFERTRACE "xfer.trace" +#endif + +#ifndef _PATH_XFERDDT +#define _PATH_XFERDDT "xfer.ddt" +#endif + +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif diff --git a/contrib/bind/bin/named/test/127.0.0.zone b/contrib/bind/bin/named/test/127.0.0.zone new file mode 100644 index 0000000..b9b7bf5 --- /dev/null +++ b/contrib/bind/bin/named/test/127.0.0.zone @@ -0,0 +1,11 @@ +$ORIGIN 0.0.127.in-addr.arpa. + +@ 1D IN SOA localhost. root.localhost. ( + 42 ; serial (d. adams) + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS localhost. +1 1D IN PTR localhost. diff --git a/contrib/bind/bin/named/test/localhost.zone b/contrib/bind/bin/named/test/localhost.zone new file mode 100644 index 0000000..ad5e68e --- /dev/null +++ b/contrib/bind/bin/named/test/localhost.zone @@ -0,0 +1,10 @@ +$ORIGIN localhost. +@ 1D IN SOA @ root ( + 42 ; serial (d. adams) + 3H ; refresh + 15M ; retry + 1W ; expiry + 1D ) ; minimum + + 1D IN NS @ + 1D IN A 127.0.0.1 diff --git a/contrib/bind/bin/named/test/named.conf b/contrib/bind/bin/named/test/named.conf new file mode 100644 index 0000000..b852604 --- /dev/null +++ b/contrib/bind/bin/named/test/named.conf @@ -0,0 +1,29 @@ +// This is a configuration file for named (from BIND 8.1 or later). +// It would normally be installed as /etc/named.conf. + +options { +// directory "/var/named"; + check-names master warn; /* default. */ + datasize 20M; +}; + +zone "localhost" IN { + type master; + file "localhost.zone"; + check-names fail; + allow-update { none; }; + allow-transfer { any; }; +}; + +zone "0.0.127.in-addr.arpa" IN { + type master; + file "127.0.0.zone"; + check-names fail; + allow-update { none; }; + allow-transfer { any; }; +}; + +zone "." IN { + type hint; + file "root.hint"; +}; diff --git a/contrib/bind/bin/named/test/root.hint b/contrib/bind/bin/named/test/root.hint new file mode 100644 index 0000000..0b8f372 --- /dev/null +++ b/contrib/bind/bin/named/test/root.hint @@ -0,0 +1,37 @@ + +; <<>> DiG 2.2 <<>> @192.5.5.241 +; (1 server found) +;; res options: init recurs defnam dnsrch +;; got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10 +;; flags: qr aa rd; QUERY: 1, ANSWER: 9, AUTHORITY: 0, ADDITIONAL: 9 +;; QUERY SECTION: +;; ., type = NS, class = IN + +;; ANSWER SECTION: +. 6D IN NS C.ROOT-SERVERS.NET. +. 6D IN NS D.ROOT-SERVERS.NET. +. 6D IN NS E.ROOT-SERVERS.NET. +. 6D IN NS I.ROOT-SERVERS.NET. +. 6D IN NS F.ROOT-SERVERS.NET. +. 6D IN NS G.ROOT-SERVERS.NET. +. 6D IN NS A.ROOT-SERVERS.NET. +. 6D IN NS H.ROOT-SERVERS.NET. +. 6D IN NS B.ROOT-SERVERS.NET. + +;; ADDITIONAL SECTION: +C.ROOT-SERVERS.NET. 5w6d16h IN A 192.33.4.12 +D.ROOT-SERVERS.NET. 5w6d16h IN A 128.8.10.90 +E.ROOT-SERVERS.NET. 5w6d16h IN A 192.203.230.10 +I.ROOT-SERVERS.NET. 5w6d16h IN A 192.36.148.17 +F.ROOT-SERVERS.NET. 5w6d16h IN A 192.5.5.241 +G.ROOT-SERVERS.NET. 5w6d16h IN A 192.112.36.4 +A.ROOT-SERVERS.NET. 5w6d16h IN A 198.41.0.4 +H.ROOT-SERVERS.NET. 5w6d16h IN A 128.63.2.53 +B.ROOT-SERVERS.NET. 5w6d16h IN A 128.9.0.107 + +;; Total query time: 8 msec +;; FROM: wisdom.home.vix.com to SERVER: 192.5.5.241 +;; WHEN: Fri Nov 22 00:08:05 1996 +;; MSG SIZE sent: 17 rcvd: 312 + diff --git a/contrib/bind/bin/named/version.c b/contrib/bind/bin/named/version.c new file mode 100644 index 0000000..9468be2 --- /dev/null +++ b/contrib/bind/bin/named/version.c @@ -0,0 +1,89 @@ +/* + * @(#)Version.c 4.9 (Berkeley) 7/21/90 + * $Id: version.c,v 8.2 1997/04/24 23:59:02 vixie Exp $ + */ + +#ifndef lint +char sccsid[] = "@(#)named %VERSION% %WHEN% %WHOANDWHERE%"; +char rcsid[] = "$Id: version.c,v 8.2 1997/04/24 23:59:02 vixie Exp $"; +#endif /* not lint */ + +char Version[] = "named %VERSION% %WHEN%\n\t%WHOANDWHERE%"; +char ShortVersion[] = "%VERSION%"; + +#ifdef COMMENT + +SCCS/s.Version.c: + +D 4.8.3 90/06/27 17:05:21 bloom 37 35 00031/00028/00079 +Version distributed with 4.3 Reno tape (June 1990) + +D 4.8.2 89/09/18 13:57:11 bloom 35 34 00020/00014/00087 +Interim fixes release + +D 4.8.1 89/02/08 17:12:15 karels 34 33 00026/00017/00075 +branch for 4.8.1 + +D 4.8 88/07/09 14:27:00 karels 33 28 00043/00031/00049 +4.8 is here! + +D 4.7 87/11/20 13:15:52 karels 25 24 00000/00000/00062 +4.7.3 beta + +D 4.6 87/07/21 12:15:52 karels 25 24 00000/00000/00062 +4.6 declared stillborn + +D 4.5 87/02/10 12:33:25 kjd 24 18 00000/00000/00062 +February 1987, Network Release. Child (bind) grows up, parent (kevin) leaves home. + +D 4.4 86/10/01 10:06:26 kjd 18 12 00020/00017/00042 +October 1, 1986 Network Distribution + +D 4.3 86/06/04 12:12:18 kjd 12 7 00015/00028/00044 +Version distributed with 4.3BSD + +D 4.2 86/04/30 20:57:16 kjd 7 1 00056/00000/00016 +Network distribution Freeze and one more version until 4.3BSD + +D 1.1 86/04/30 19:30:00 kjd 1 0 00016/00000/00000 +date and time created 86/04/30 19:30:00 by kjd + +code versions: + +Makefile + Makefile 4.14 (Berkeley) 2/28/88 +db.h + db.h 4.13 (Berkeley) 2/17/88 +db_dump.c + db_dump.c 4.20 (Berkeley) 2/17/88 +db_load.c + db_load.c 4.26 (Berkeley) 2/28/88 +db_lookup.c + db_lookup.c 4.14 (Berkeley) 2/17/88 +db_reload.c + db_reload.c 4.15 (Berkeley) 2/28/88 +db_save.c + db_save.c 4.13 (Berkeley) 2/17/88 +db_update.c + db_update.c 4.16 (Berkeley) 2/28/88 +ns_forw.c + ns_forw.c 4.26 (Berkeley) 3/28/88 +ns_init.c + ns_init.c 4.23 (Berkeley) 2/28/88 +ns_main.c + Copyright (c) 1986 Regents of the University of California.\n\ + ns_main.c 4.30 (Berkeley) 3/7/88 +ns_maint.c + ns_maint.c 4.23 (Berkeley) 2/28/88 +ns_req.c + ns_req.c 4.32 (Berkeley) 3/31/88 +ns_resp.c + ns_resp.c 4.50 (Berkeley) 4/7/88 +ns_sort.c + ns_sort.c 4.3 (Berkeley) 2/17/88 +ns_stats.c + ns_stats.c 4.3 (Berkeley) 2/17/88 +newvers.sh + newvers.sh 4.4 (Berkeley) 3/28/88 + +#endif /* COMMENT */ diff --git a/contrib/bind/bin/ndc/Makefile b/contrib/bind/bin/ndc/Makefile new file mode 100644 index 0000000..13340c2 --- /dev/null +++ b/contrib/bind/bin/ndc/Makefile @@ -0,0 +1,87 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 1.6 1997/06/19 03:22:10 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +AR= ar cruv +INSTALL= install +STRIP=-s +PS=ps + +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} ${DEFS} + +PROG= ndc +SRCS= +OBJS= + +all: ${PROG} + +${PROG}: ${PROG}.sh ../named/pathnames ../named/pathnames.h Makefile + sed -e "s|%PIDFILE%|"`../named/pathnames _path_pidfile`"|" \ + -e "s|%NAMED%|"`../named/pathnames _path_named`"|" \ + -e "s|%PS%|${PS}|" \ + < ndc.sh > ndc + chmod +x ndc + +distclean: clean + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: + +${DESTDIR}${DESTSBIN}: + mkdir -p ${DESTDIR}${DESTSBIN} + +install: ${DESTDIR}${DESTSBIN} ${PROG} + ${INSTALL} -c -m 755 ${PROG} ${DESTDIR}${DESTSBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.sh . + +tags: FRC + ctags ${SRCS} *.h + +commands.c: commands.l + ${LEX} -t $< > $@ || rm $@ + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/ndc/ndc.sh b/contrib/bind/bin/ndc/ndc.sh new file mode 100644 index 0000000..a9b1018 --- /dev/null +++ b/contrib/bind/bin/ndc/ndc.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +USAGE='echo \ + "usage: $0 \ + (status|dumpdb|reload|stats|trace|notrace|querylog|start|stop|restart) \ + ... \ + "; exit 1' + +PATH=/bin:/usr/bin:/usr/ucb:$PATH; export PATH +PIDFILE=%PIDFILE% + +if [ -f $PIDFILE ] +then + PID=`cat $PIDFILE` + PS=`%PS% $PID | tail -1 | grep $PID` + RUNNING=1 + [ `echo $PS | wc -w` -ne 0 ] || { + PS="named (pid $PID?) not running" + RUNNING=0 + } +else + PS="named (no pid file) not running" + RUNNING=0 +fi + +for ARG +do + case $ARG in + start|stop|restart) + ;; + *) + [ $RUNNING -eq 0 ] && { + echo $PS + exit 1 + } + esac + + case $ARG in + status) echo "$PS";; + dumpdb) kill -INT $PID && echo Dumping Database;; + reload) kill -HUP $PID && echo Reloading Database;; + stats) kill -ILL $PID && echo Dumping Statistics;; + trace) kill -USR1 $PID && echo Trace Level Incremented;; + notrace) kill -USR2 $PID && echo Tracing Cleared;; + querylog|qrylog) kill -WINCH $PID && echo Query Logging Toggled;; + start) + [ $RUNNING -eq 1 ] && { + echo "$0: start: named (pid $PID) already running" + continue + } + rm -f $PIDFILE + %NAMED% && { + sleep 5 + echo Name Server Started + } + ;; + stop) + [ $RUNNING -eq 0 ] && { + echo "$0: stop: named not running" + continue + } + kill $PID && { + sleep 5 + rm -f $PIDFILE + echo Name Server Stopped + } + ;; + restart) + [ $RUNNING -eq 1 ] && { + kill $PID && sleep 5 + } + rm -f $PIDFILE + %NAMED% && { + sleep 5 + echo Name Server Restarted + } + ;; + *) eval "$USAGE";; + esac +done +test -z "$ARG" && eval "$USAGE" + +exit 0 diff --git a/contrib/bind/bin/nslookup/Makefile b/contrib/bind/bin/nslookup/Makefile new file mode 100644 index 0000000..15cc94f --- /dev/null +++ b/contrib/bind/bin/nslookup/Makefile @@ -0,0 +1,91 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.18 1997/12/03 22:55:16 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s + +LDFLAGS= +DEFS= -D_PATH_HELPFILE=\"${DESTDIR}${DESTHELP}/nslookup.help\" +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} ${DEFS} + +PROG= nslookup +CSRCS= main.c getinfo.c debug.c send.c skip.c list.c subr.c +SRCS= ${CSRCS} commands.l +OBJS= main.${O} getinfo.${O} debug.${O} send.${O} skip.${O} list.${O} \ + subr.${O} commands.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + rm -f commands.c + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + rm -f lex.yy.c lex.yy.o + +depend: ${SRCS} + mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${DEFS} ${CSRCS} + +${DESTDIR}${DESTHELP}: + mkdir -p ${DESTDIR}${DESTHELP} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${DESTDIR}${DESTHELP} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTBIN}/${PROG} + ${INSTALL} -c -o bin -g bin -m 444 nslookup.help ${DESTDIR}${DESTHELP}/ + +links: FRC + @set -e; ln -s SRC/*.[chl] SRC/nslookup.help . + +tags: FRC + ctags ${CSRCS} *.h + +commands.c: commands.l + ${LEX} -t $< > $@ || rm $@ + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/nslookup/commands.c b/contrib/bind/bin/nslookup/commands.c new file mode 100644 index 0000000..5564b28 --- /dev/null +++ b/contrib/bind/bin/nslookup/commands.c @@ -0,0 +1,2036 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * /master/usr.bin/lex/skel.c,v 1.2 1996/05/30 12:31:07 bostic Exp + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 22 +#define YY_END_OF_BUFFER 23 +static yyconst short int yy_accept[171] = + { 0, + 0, 0, 23, 22, 21, 22, 22, 19, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 0, 20, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 3, 0, 0, 13, 0, 9, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + + 0, 0, 12, 0, 0, 0, 17, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, + 0, 0, 0, 0, 9, 0, 0, 11, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 8, 0, 10, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 1, 5, 4, 6, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, + 6, 7, 8, 1, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 1, 9, 1, 1, 6, 1, 10, 4, 4, 11, + + 12, 13, 14, 15, 16, 4, 4, 17, 18, 19, + 20, 21, 4, 22, 23, 24, 4, 25, 26, 27, + 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[28] = + { 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 + } ; + +static yyconst short int yy_base[203] = + { 0, + 491, 0, 493, 611, 611, 489, 27, 611, 54, 56, + 63, 51, 48, 46, 54, 56, 60, 479, 611, 0, + 611, 446, 77, 0, 61, 70, 62, 64, 74, 76, + 103, 611, 439, 91, 611, 80, 94, 97, 113, 75, + 95, 104, 140, 149, 96, 112, 106, 158, 107, 108, + 73, 126, 110, 166, 611, 173, 182, 142, 0, 152, + 150, 168, 195, 202, 161, 191, 160, 226, 197, 235, + 198, 611, 244, 611, 184, 205, 611, 207, 611, 253, + 213, 219, 236, 237, 611, 237, 264, 273, 282, 291, + 255, 0, 275, 294, 302, 311, 299, 268, 320, 611, + + 327, 266, 611, 336, 345, 322, 611, 354, 611, 363, + 463, 372, 381, 304, 390, 398, 611, 405, 330, 611, + 414, 423, 432, 435, 611, 442, 451, 611, 460, 469, + 478, 481, 611, 488, 497, 338, 0, 347, 611, 500, + 507, 510, 517, 520, 611, 527, 536, 365, 611, 545, + 374, 548, 555, 564, 383, 567, 611, 574, 583, 400, + 0, 592, 601, 407, 611, 416, 611, 425, 611, 611, + 463, 454, 447, 446, 445, 435, 428, 419, 410, 403, + 393, 386, 377, 368, 357, 350, 341, 314, 296, 285, + 278, 240, 229, 222, 218, 191, 177, 145, 137, 129, + + 117, 98 + } ; + +static yyconst short int yy_def[203] = + { 0, + 171, 170, 170, 170, 170, 172, 170, 170, 173, 172, + 173, 11, 11, 11, 11, 11, 11, 172, 170, 7, + 170, 11, 172, 11, 11, 11, 11, 11, 11, 11, + 174, 170, 11, 172, 170, 11, 11, 11, 11, 11, + 11, 11, 175, 176, 11, 11, 11, 177, 11, 11, + 11, 11, 11, 172, 170, 175, 176, 57, 57, 11, + 11, 11, 178, 172, 11, 11, 11, 179, 11, 180, + 172, 170, 174, 170, 11, 73, 170, 172, 170, 178, + 172, 172, 11, 73, 170, 11, 181, 182, 183, 180, + 90, 90, 11, 90, 184, 185, 11, 11, 172, 170, + + 181, 172, 170, 186, 187, 172, 170, 188, 170, 189, + 90, 190, 191, 11, 192, 172, 170, 186, 172, 170, + 193, 194, 189, 172, 170, 190, 195, 170, 191, 196, + 197, 172, 170, 193, 194, 135, 135, 172, 170, 172, + 198, 172, 199, 172, 170, 197, 200, 172, 170, 201, + 172, 172, 198, 202, 172, 172, 170, 199, 200, 159, + 159, 201, 202, 172, 170, 172, 170, 172, 170, 0, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + + 170, 170 + } ; + +static yyconst short int yy_nxt[639] = + { 0, + 6, 7, 8, 9, 6, 6, 6, 10, 9, 9, + 9, 11, 12, 9, 13, 9, 14, 9, 9, 9, + 9, 15, 16, 9, 17, 9, 9, 18, 20, 21, + 22, 18, 18, 18, 23, 22, 22, 22, 24, 25, + 22, 26, 22, 27, 22, 22, 22, 22, 28, 29, + 22, 30, 22, 22, 18, 31, 32, 34, 35, 38, + 18, 18, 18, 18, 31, 32, 37, 41, 39, 18, + 18, 18, 33, 40, 33, 42, 37, 33, 34, 35, + 33, 38, 33, 40, 39, 41, 33, 33, 33, 36, + 33, 42, 34, 35, 50, 45, 33, 67, 163, 33, + + 33, 33, 33, 18, 31, 32, 33, 18, 18, 44, + 18, 18, 46, 47, 48, 53, 51, 162, 52, 60, + 33, 33, 33, 33, 49, 61, 62, 68, 65, 160, + 33, 66, 33, 33, 33, 69, 33, 158, 33, 33, + 18, 54, 55, 71, 72, 153, 18, 18, 18, 18, + 57, 19, 33, 73, 74, 59, 18, 18, 18, 48, + 32, 75, 64, 18, 44, 18, 18, 54, 55, 76, + 77, 86, 70, 18, 54, 55, 33, 146, 33, 18, + 18, 18, 18, 57, 19, 83, 33, 33, 18, 18, + 18, 143, 84, 85, 33, 18, 78, 79, 89, 71, + + 72, 18, 18, 18, 19, 93, 76, 77, 78, 79, + 33, 81, 81, 94, 95, 19, 81, 33, 141, 81, + 96, 19, 136, 33, 81, 82, 18, 68, 32, 134, + 88, 88, 44, 18, 18, 18, 90, 19, 84, 85, + 131, 92, 18, 18, 18, 73, 74, 97, 18, 18, + 44, 18, 18, 18, 78, 79, 106, 107, 98, 18, + 18, 18, 33, 33, 18, 99, 100, 102, 103, 115, + 18, 18, 18, 18, 102, 103, 108, 109, 129, 18, + 18, 18, 18, 89, 32, 126, 105, 105, 44, 18, + 18, 18, 90, 19, 33, 110, 123, 18, 18, 18, + + 111, 33, 18, 95, 19, 130, 18, 18, 18, 18, + 18, 18, 96, 19, 121, 18, 18, 18, 18, 18, + 114, 99, 100, 106, 107, 33, 70, 18, 99, 100, + 33, 119, 120, 18, 18, 18, 18, 116, 117, 148, + 149, 105, 18, 18, 18, 18, 119, 120, 138, 139, + 118, 18, 18, 18, 18, 108, 109, 113, 18, 18, + 122, 18, 18, 18, 110, 19, 148, 149, 112, 18, + 18, 18, 18, 124, 125, 150, 19, 104, 18, 18, + 18, 18, 127, 128, 154, 19, 88, 18, 18, 18, + 18, 115, 32, 101, 18, 18, 44, 18, 18, 116, + + 117, 164, 165, 91, 70, 18, 116, 117, 164, 165, + 87, 18, 18, 18, 18, 132, 133, 166, 167, 80, + 18, 18, 18, 18, 135, 19, 168, 169, 63, 137, + 18, 18, 18, 138, 139, 58, 124, 125, 18, 18, + 18, 140, 18, 124, 125, 56, 43, 33, 18, 18, + 18, 18, 127, 128, 18, 18, 18, 142, 18, 18, + 18, 127, 128, 4, 110, 33, 18, 18, 18, 18, + 130, 32, 33, 18, 18, 44, 18, 18, 18, 144, + 145, 19, 132, 133, 18, 18, 18, 147, 18, 132, + 133, 19, 170, 5, 18, 18, 18, 18, 135, 19, + + 170, 150, 19, 18, 18, 18, 151, 18, 152, 128, + 170, 154, 19, 18, 18, 18, 155, 18, 156, 157, + 170, 144, 145, 18, 18, 18, 70, 18, 144, 145, + 170, 170, 170, 18, 18, 18, 18, 159, 19, 170, + 170, 170, 161, 18, 18, 18, 150, 19, 170, 152, + 128, 18, 18, 18, 142, 18, 152, 128, 170, 170, + 170, 18, 18, 18, 18, 154, 19, 170, 156, 157, + 18, 18, 18, 70, 18, 156, 157, 170, 170, 170, + 18, 18, 18, 18, 159, 19, 170, 170, 170, 18, + 18, 18, 18, 166, 167, 170, 170, 170, 18, 18, + + 18, 18, 168, 169, 170, 170, 170, 18, 18, 18, + 3, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170 + } ; + +static yyconst short int yy_chk[639] = + { 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, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 9, 9, 9, 10, 10, 13, + 9, 9, 9, 11, 11, 11, 12, 16, 14, 11, + 11, 11, 14, 15, 13, 17, 25, 12, 23, 23, + 15, 26, 16, 28, 27, 29, 17, 25, 27, 11, + 28, 30, 34, 34, 40, 36, 26, 51, 202, 51, + + 29, 40, 30, 31, 31, 31, 36, 31, 31, 31, + 31, 31, 37, 38, 39, 42, 41, 201, 41, 45, + 37, 41, 45, 38, 39, 46, 47, 52, 49, 200, + 42, 50, 47, 49, 50, 53, 53, 199, 46, 39, + 43, 43, 43, 58, 58, 198, 43, 43, 43, 44, + 44, 44, 52, 60, 60, 44, 44, 44, 48, 48, + 48, 61, 48, 48, 48, 48, 48, 54, 54, 62, + 62, 67, 54, 56, 56, 56, 61, 197, 60, 56, + 56, 56, 57, 57, 57, 65, 67, 65, 57, 57, + 57, 196, 66, 66, 62, 63, 63, 63, 69, 71, + + 71, 63, 63, 63, 64, 75, 76, 76, 78, 78, + 75, 64, 64, 78, 81, 81, 64, 66, 195, 64, + 82, 82, 194, 69, 64, 64, 68, 68, 68, 193, + 68, 68, 68, 68, 68, 70, 70, 70, 84, 84, + 192, 70, 70, 70, 73, 73, 73, 83, 73, 73, + 73, 73, 73, 80, 80, 80, 91, 91, 86, 80, + 80, 80, 83, 86, 87, 87, 87, 102, 102, 98, + 87, 87, 87, 88, 88, 88, 93, 93, 191, 88, + 88, 88, 89, 89, 89, 190, 89, 89, 89, 89, + 89, 90, 90, 90, 98, 94, 189, 90, 90, 90, + + 94, 93, 95, 95, 95, 114, 95, 95, 95, 95, + 95, 96, 96, 96, 188, 96, 96, 96, 96, 96, + 97, 99, 99, 106, 106, 97, 99, 101, 101, 101, + 114, 119, 119, 101, 101, 101, 104, 104, 104, 136, + 136, 187, 104, 104, 104, 105, 105, 105, 138, 138, + 186, 105, 105, 105, 108, 108, 108, 185, 108, 108, + 108, 108, 108, 110, 110, 110, 148, 148, 184, 110, + 110, 110, 112, 112, 112, 151, 151, 183, 112, 112, + 112, 113, 113, 113, 155, 155, 182, 113, 113, 113, + 115, 115, 115, 181, 115, 115, 115, 115, 115, 116, + + 116, 160, 160, 180, 116, 118, 118, 118, 164, 164, + 179, 118, 118, 118, 121, 121, 121, 166, 166, 178, + 121, 121, 121, 122, 122, 122, 168, 168, 177, 122, + 122, 122, 123, 123, 123, 176, 124, 124, 123, 123, + 123, 124, 126, 126, 126, 175, 174, 173, 126, 126, + 126, 127, 127, 127, 172, 127, 127, 127, 127, 127, + 129, 129, 129, 171, 111, 33, 129, 129, 129, 130, + 130, 130, 22, 130, 130, 130, 130, 130, 131, 131, + 131, 18, 132, 132, 131, 131, 131, 132, 134, 134, + 134, 6, 3, 1, 134, 134, 134, 135, 135, 135, + + 0, 140, 140, 135, 135, 135, 140, 141, 141, 141, + 0, 142, 142, 141, 141, 141, 142, 143, 143, 143, + 0, 144, 144, 143, 143, 143, 144, 146, 146, 146, + 0, 0, 0, 146, 146, 146, 147, 147, 147, 0, + 0, 0, 147, 147, 147, 150, 150, 150, 0, 152, + 152, 150, 150, 150, 152, 153, 153, 153, 0, 0, + 0, 153, 153, 153, 154, 154, 154, 0, 156, 156, + 154, 154, 154, 156, 158, 158, 158, 0, 0, 0, + 158, 158, 158, 159, 159, 159, 0, 0, 0, 159, + 159, 159, 162, 162, 162, 0, 0, 0, 162, 162, + + 162, 163, 163, 163, 0, 0, 0, 163, 163, 163, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "commands.l" +#define INITIAL 0 +#line 2 "commands.l" + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)commands.l 5.13 (Berkeley) 7/24/90"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * commands.l + * + * Andrew Cherenson CS298-26 Fall 1985 + * + * Lex input file for the nslookup program command interpreter. + * When a sequence is recognized, the associated action + * routine is called. The action routine may need to + * parse the string for additional information. + * + * Recognized commands: (identifiers are shown in uppercase) + * + * server NAME - set default server to NAME, using default server + * lserver NAME - set default server to NAME, using initial server + * finger [NAME] - finger the optional NAME + * exit - exit the program + * root - set default server to the root + * ls NAME - list the domain NAME + * view FILE - sorts and view the file with more + * set OPTION - set an option + * help - print help information + * ? - print help information + * NAME - print info about the host/domain NAME + * using default server. + * NAME1 NAME2 - as above, but use NAME2 as server + * + * + * yylex Results: + * 0 upon end-of-file. + * 1 after each command. + * + ******************************************************************************* + */ + +#include "port_before.h" +#include <sys/types.h> +#include "port_after.h" +#include "res.h" + +extern char rootServerName[]; +extern void PrintHelp(); + + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + yy_current_buffer->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 109 "commands.l" + + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 171 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 611 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 110 "commands.l" +{ + /* + * 0 == use current server to find + * the new one. + * 1 == use original server to find + * the new one. + */ + SetDefaultServer(yytext, 0); + return(1); + } + YY_BREAK +case 2: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 120 "commands.l" +{ + SetDefaultServer(yytext, 1); + return(1); + } + YY_BREAK +case 3: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 124 "commands.l" +{ + return(0); + } + YY_BREAK +case 4: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 127 "commands.l" +{ + SetDefaultServer(rootServerName, 1); + return(1); + } + YY_BREAK +case 5: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 131 "commands.l" +{ + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + Finger(yytext, 1); + return(1); + } + YY_BREAK +case 6: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 140 "commands.l" +{ + Finger(yytext, 0); + return(1); + } + YY_BREAK +case 7: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 144 "commands.l" +{ + ViewList(yytext); + return(1); + } + YY_BREAK +case 8: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 148 "commands.l" +{ + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + ListHosts(yytext, 1); + return(1); + } + YY_BREAK +case 9: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 157 "commands.l" +{ + ListHosts(yytext, 0); + return(1); + } + YY_BREAK +case 10: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 161 "commands.l" +{ + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + ListHostsByType(yytext, 1); + return(1); + } + YY_BREAK +case 11: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 170 "commands.l" +{ + ListHostsByType(yytext, 0); + return(1); + } + YY_BREAK +case 12: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 174 "commands.l" +{ + SetOption(yytext); + return(1); + } + YY_BREAK +case 13: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 178 "commands.l" +{ + PrintHelp(); + return(1); + } + YY_BREAK +case 14: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 182 "commands.l" +{ + extern void PrintHelp(); + + PrintHelp(); + return(1); + } + YY_BREAK +case 15: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 188 "commands.l" +{ + /* + * 0 == output to stdout + * 1 == output to file + */ + LookupHost(yytext, 1); + return(1); + } + YY_BREAK +case 16: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 196 "commands.l" +{ + LookupHost(yytext, 0); + return(1); + } + YY_BREAK +case 17: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 200 "commands.l" +{ + /* + * 0 == output to stdout + * 1 == output to file + */ + LookupHostWithServer(yytext, 1); + return(1); + } + YY_BREAK +case 18: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 208 "commands.l" +{ + LookupHostWithServer(yytext, 0); + return(1); + } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 212 "commands.l" +{ + return(1); + } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 215 "commands.l" +{ + printf("Unrecognized command: %s", + yytext); + return(1); + } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 220 "commands.l" +{ ; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 221 "commands.l" +ECHO; + YY_BREAK +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 171 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 171 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 170); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = yytext_ptr + offset; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + yy_current_buffer->yy_at_bol = (c == '\n'); + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 221 "commands.l" + diff --git a/contrib/bind/bin/nslookup/commands.l b/contrib/bind/bin/nslookup/commands.l new file mode 100644 index 0000000..c3a220a --- /dev/null +++ b/contrib/bind/bin/nslookup/commands.l @@ -0,0 +1,221 @@ +%{ + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)commands.l 5.13 (Berkeley) 7/24/90"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * commands.l + * + * Andrew Cherenson CS298-26 Fall 1985 + * + * Lex input file for the nslookup program command interpreter. + * When a sequence is recognized, the associated action + * routine is called. The action routine may need to + * parse the string for additional information. + * + * Recognized commands: (identifiers are shown in uppercase) + * + * server NAME - set default server to NAME, using default server + * lserver NAME - set default server to NAME, using initial server + * finger [NAME] - finger the optional NAME + * exit - exit the program + * root - set default server to the root + * ls NAME - list the domain NAME + * view FILE - sorts and view the file with more + * set OPTION - set an option + * help - print help information + * ? - print help information + * NAME - print info about the host/domain NAME + * using default server. + * NAME1 NAME2 - as above, but use NAME2 as server + * + * + * yylex Results: + * 0 upon end-of-file. + * 1 after each command. + * + ******************************************************************************* + */ + +#include "port_before.h" +#include <sys/types.h> +#include "port_after.h" +#include "res.h" + +extern char rootServerName[]; +extern void PrintHelp(); + +%} +WS [ \t] +FLET [A-Za-z0-9.*\\] +LET [A-Za-z0-9.*] +NAME [A-Za-z0-9.*=_/-] +%% +^{WS}*server{WS}+{LET}{NAME}*{WS}*$ { + /* + * 0 == use current server to find + * the new one. + * 1 == use original server to find + * the new one. + */ + SetDefaultServer(yytext, 0); + return(1); + } +^{WS}*lserver{WS}+{LET}{NAME}*{WS}*$ { + SetDefaultServer(yytext, 1); + return(1); + } +^{WS}*exit{WS}*$ { + return(0); + } +^{WS}*root{WS}*$ { + SetDefaultServer(rootServerName, 1); + return(1); + } +^{WS}*finger({WS}+{LET}{NAME}*)?{WS}+>>?{WS}*{NAME}+{WS}*$ { + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + Finger(yytext, 1); + return(1); + } +^{WS}*finger({WS}+{LET}{NAME}*)?{WS}*$ { + Finger(yytext, 0); + return(1); + } +^{WS}*view{WS}+{NAME}+{WS}*$ { + ViewList(yytext); + return(1); + } +^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + ListHosts(yytext, 1); + return(1); + } +^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}*$ { + ListHosts(yytext, 0); + return(1); + } +^{WS}*ls{WS}+-t{WS}+({LET}{NAME}*{WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { + /* + * 2nd arg. + * 0 == output to stdout + * 1 == output to file + */ + ListHostsByType(yytext, 1); + return(1); + } +^{WS}*ls{WS}+-t{WS}+({LET}{NAME}*{WS}+)?{LET}{NAME}*{WS}*$ { + ListHostsByType(yytext, 0); + return(1); + } +^{WS}*set{WS}+{NAME}+{WS}*$ { + SetOption(yytext); + return(1); + } +^{WS}*help{WS}*$ { + PrintHelp(); + return(1); + } +^{WS}*"?"{WS}*$ { + extern void PrintHelp(); + + PrintHelp(); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { + /* + * 0 == output to stdout + * 1 == output to file + */ + LookupHost(yytext, 1); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}*$ { + LookupHost(yytext, 0); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { + /* + * 0 == output to stdout + * 1 == output to file + */ + LookupHostWithServer(yytext, 1); + return(1); + } +^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}*$ { + LookupHostWithServer(yytext, 0); + return(1); + } +^{WS}*\n { + return(1); + } +^.*\n { + printf("Unrecognized command: %s", + yytext); + return(1); + } +\n { ; } +%% diff --git a/contrib/bind/bin/nslookup/debug.c b/contrib/bind/bin/nslookup/debug.c new file mode 100644 index 0000000..76260e0 --- /dev/null +++ b/contrib/bind/bin/nslookup/debug.c @@ -0,0 +1,646 @@ +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)debug.c 5.26 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: debug.c,v 8.11 1998/03/19 19:30:54 halley Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * debug.c -- + * + * Routines to print out packets received from a name server query. + * + * Modified version of 4.3BSD BIND res_debug.c 5.30 6/27/90 + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> + +#include "port_after.h" + +#include "res.h" + +/* + * Imported from res_debug.c + */ +extern char *_res_resultcodes[]; +extern char *_res_opcodes[]; + +/* + * Used to highlight the start of a record when printing it. + */ +#define INDENT " -> " + +/* + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ + +void +Print_query(const u_char *msg, const u_char *eom, int printHeader) { + Fprint_query(msg, eom, printHeader, stdout); +} + +void +Fprint_query(const u_char *msg, const u_char *eom, int printHeader, FILE *file) +{ + const u_char *cp; + const HEADER *hp; + int n; + u_int class, type; + + /* + * Print header fields. + */ + hp = (HEADER *)msg; + cp = msg + HFIXEDSZ; + if (printHeader || (_res.options & RES_DEBUG2)) { + fprintf(file," HEADER:\n"); + fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); + fprintf(file,", id = %d", ntohs(hp->id)); + fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); + fprintf(file,"\theader flags: "); + if (hp->qr) { + fprintf(file," response"); + } else { + fprintf(file," query"); + } + if (hp->aa) + fprintf(file,", auth. answer"); + if (hp->tc) + fprintf(file,", truncation"); + if (hp->rd) + fprintf(file,", want recursion"); + if (hp->ra) + fprintf(file,", recursion avail."); + if (hp->unused) + fprintf(file,", UNUSED-QUERY_BIT"); + if (hp->ad) + fprintf(file,", authentic data"); + if (hp->cd) + fprintf(file,", checking disabled"); + fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount)); + fprintf(file,", answers = %d", ntohs(hp->ancount)); + fprintf(file,", authority records = %d", ntohs(hp->nscount)); + fprintf(file,", additional = %d\n\n", ntohs(hp->arcount)); + } + + /* + * Print question records. + */ + n = ntohs(hp->qdcount); + if (n > 0) { + fprintf(file," QUESTIONS:\n"); + while (--n >= 0) { + fprintf(file,"\t"); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) + return; + type = ns_get16((u_char*)cp); + cp += INT16SZ; + class = ns_get16((u_char*)cp); + cp += INT16SZ; + fprintf(file,", type = %s", p_type(type)); + fprintf(file,", class = %s\n", p_class(class)); + } + } + /* + * Print authoritative answer records + */ + n = ntohs(hp->ancount); + if (n > 0) { + fprintf(file," ANSWERS:\n"); + if (type == ns_t_a && n > MAXADDRS) { + printf("Limiting response to MAX Addrs = %d \n", + MAXADDRS); + n = MAXADDRS; + } + while (--n >= 0) { + fprintf(file, INDENT); + cp = Print_rr(cp, msg, eom, file); + if (cp == NULL) + return; + } + } + /* + * print name server records + */ + n = ntohs(hp->nscount); + if (n > 0) { + fprintf(file," AUTHORITY RECORDS:\n"); + while (--n >= 0) { + fprintf(file, INDENT); + cp = Print_rr(cp, msg, eom, file); + if (cp == NULL) + return; + } + } + /* + * print additional records + */ + n = ntohs(hp->arcount); + if (n > 0) { + fprintf(file," ADDITIONAL RECORDS:\n"); + while (--n >= 0) { + fprintf(file, INDENT); + cp = Print_rr(cp, msg, eom, file); + if (cp == NULL) + return; + } + } + fprintf(file,"\n------------\n"); +} + +const u_char * +Print_cdname_sub(const u_char *cp, const u_char *msg, const u_char *eom, + FILE *file, int format) +{ + char name[MAXDNAME]; + int n; + + n = dn_expand(msg, eom, cp, name, sizeof name); + if (n < 0) + return (NULL); + if (name[0] == '\0') + strcpy(name, "(root)"); + if (format) + fprintf(file, "%-30s", name); + else + fputs(name, file); + return (cp + n); +} + +const u_char * +Print_cdname(const u_char *cp, const u_char *msg, const u_char *eom, + FILE *file) +{ + return (Print_cdname_sub(cp, msg, eom, file, 0)); +} + +const u_char * +Print_cdname2(const u_char *cp, const u_char *msg, const u_char *eom, + FILE *file) +{ + return (Print_cdname_sub(cp, msg, eom, file, 1)); +} + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + fprintf(file, "(form error.)\n"); \ + return (NULL); \ + } \ + } while (0) + +/* + * Print resource record fields in human readable form (not master file form). + */ +const u_char * +Print_rr(const u_char *ocp, const u_char *msg, const u_char *eom, FILE *file) { + u_int type, class; + int dlen, n, c, debug; + u_long rrttl, ttl; + struct in_addr inaddr; + const u_char *cp, *cp1, *cp2; + + if ((cp = Print_cdname(ocp, msg, eom, file)) == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + NS_GET16(type, cp); + NS_GET16(class, cp); + NS_GET32(rrttl, cp); + NS_GET16(dlen, cp); + BOUNDS_CHECK(cp, dlen); + + debug = _res.options & (RES_DEBUG|RES_DEBUG2); + if (debug) { + if (_res.options & RES_DEBUG2) + fprintf(file,"\n\ttype = %s, class = %s, dlen = %d", + p_type(type), p_class(class), dlen); + if (type == T_SOA) + fprintf(file,"\n\tttl = %lu (%s)", + rrttl, p_time(rrttl)); + putc('\n', file); + } + + cp1 = cp; + + /* + * Print type specific data, if appropriate + */ + switch (type) { + case T_A: + BOUNDS_CHECK(cp, INADDRSZ); + memcpy(&inaddr, cp, INADDRSZ); + fprintf(file,"\tinternet address = %s\n", inet_ntoa(inaddr)); + cp += dlen; + break; + + case T_CNAME: + fprintf(file,"\tcanonical name = "); + goto doname; + + case T_MG: + fprintf(file,"\tmail group member = "); + goto doname; + + case T_MB: + fprintf(file,"\tmail box = "); + goto doname; + + case T_MR: + fprintf(file,"\tmailbox rename = "); + goto doname; + + case T_MX: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tpreference = %u",ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", mail exchanger = "); + goto doname; + + case T_NAPTR: + BOUNDS_CHECK(cp, 2 * INT16SZ); + fprintf(file, "\torder = %u",ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", preference = %u\n", ns_get16((u_char*)cp)); + cp += INT16SZ; + /* Flags */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + fprintf(file,"\tflags = \"%.*s\"\n", (int)n, cp); + cp += n; + /* Service */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + fprintf(file,"\tservices = \"%.*s\"\n", (int)n, cp); + cp += n; + /* Regexp */ + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); + fprintf(file,"\trule = \"%.*s\"\n", (int)n, cp); + cp += n; + /* Replacement */ + fprintf(file,"\treplacement = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(replacement truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_SRV: + BOUNDS_CHECK(cp, 3 * INT16SZ); + fprintf(file, "\tpriority = %u",ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", weight = %u", ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", port= %u\n", ns_get16((u_char*)cp)); + cp += INT16SZ; + + fprintf(file,"\thost = "); + goto doname; + + case T_PX: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tpreference = %u",ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", RFC 822 = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\nX.400 = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_RT: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tpreference = %u",ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", router = "); + goto doname; + + case T_AFSDB: + BOUNDS_CHECK(cp, INT16SZ); + fprintf(file,"\tsubtype = %d",ns_get16((u_char*)cp)); + cp += INT16SZ; + fprintf(file,", DCE/AFS server = "); + goto doname; + + case T_NS: + fprintf(file,"\tnameserver = "); + goto doname; + + case T_PTR: + fprintf(file,"\tname = "); + doname: + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_HINFO: + cp2 = cp + dlen; + BOUNDS_CHECK(cp, 1); + if ((n = *cp++) != 0) { + BOUNDS_CHECK(cp, n); + fprintf(file,"\tCPU = %.*s", n, cp); + cp += n; + } + if ((cp < cp2) && ((n = *cp++) != 0)) { + BOUNDS_CHECK(cp, n); + fprintf(file,"\tOS = %.*s\n", n, cp); + cp += n; + } else fprintf(file, "\n*** Warning *** OS-type missing\n"); + break; + + case T_ISDN: + cp2 = cp + dlen; + BOUNDS_CHECK(cp, 1); + n = *cp++; + if (n != 0) { + BOUNDS_CHECK(cp, n); + fprintf(file,"\tISDN = \"%.*s", n, cp); + cp += n; + } + if ((cp < cp2) && (n = *cp++)) { + BOUNDS_CHECK(cp, n); + fprintf(file,"-%.*s\"\n", n, cp); + cp += n; + } else fprintf(file,"\"\n"); + break; + + case T_SOA: + if (!debug) + putc('\n', file); + fprintf(file,"\torigin = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\n\tmail addr = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + BOUNDS_CHECK(cp, 5 * INT32SZ); + fprintf(file,"\n\tserial = %lu", ns_get32((u_char*)cp)); + cp += INT32SZ; + ttl = ns_get32((u_char*)cp); + fprintf(file,"\n\trefresh = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((u_char*)cp); + fprintf(file,"\n\tretry = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((u_char*)cp); + fprintf(file,"\n\texpire = %lu (%s)", ttl, p_time(ttl)); + cp += INT32SZ; + ttl = ns_get32((u_char*)cp); + fprintf(file, + "\n\tminimum ttl = %lu (%s)\n", ttl, p_time(ttl)); + cp += INT32SZ; + break; + + case T_MINFO: + if (!debug) + putc('\n', file); + fprintf(file,"\trequests = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\n\terrors = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_RP: + if (!debug) + putc('\n', file); + fprintf(file,"\tmailbox = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + fprintf(file,"\n\ttext = "); + cp = Print_cdname(cp, msg, eom, file); + if (cp == NULL) { + fprintf(file, "(name truncated?)\n"); + return (NULL); /* compression error */ + } + (void) putc('\n', file); + break; + + case T_TXT: + (void) fputs("\ttext = ", file); + cp2 = cp1 + dlen; + while (cp < cp2) { + (void) putc('"', file); + n = (unsigned char) *cp++; + if (n != 0) { + for (c = n; c > 0 && cp < cp2; c--) { + if ((*cp == '\n') || (*cp == '"') || (*cp == '\\')) + (void) putc('\\', file); + (void) putc(*cp++, file); + } + } + (void) putc('"', file); + if (cp < cp2) + (void) putc(' ', file); + } + (void) putc('\n', file); + break; + + case T_X25: + (void) fputs("\tX25 = \"", file); + cp2 = cp1 + dlen; + while (cp < cp2) { + n = (unsigned char) *cp++; + if (n != 0) { + for (c = n; c > 0 && cp < cp2; c--) + if (*cp == '\n') { + (void) putc('\\', file); + (void) putc(*cp++, file); + } else + (void) putc(*cp++, file); + } + } + (void) fputs("\"\n", file); + break; + + case T_NSAP: + fprintf(file, "\tnsap = %s\n", inet_nsap_ntoa(dlen, cp, NULL)); + cp += dlen; + break; + + case T_AAAA: { + char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + + BOUNDS_CHECK(cp, IN6ADDRSZ); + fprintf(file, "\tIPv6 address = %s\n", + inet_ntop(AF_INET6, cp, t, sizeof t)); + cp += IN6ADDRSZ; + break; + } + + case T_WKS: { + struct protoent *protoPtr; + + BOUNDS_CHECK(cp, INADDRSZ + 1); + if (!debug) + (void) putc('\n', file); + memcpy(&inaddr, cp, INADDRSZ); + cp += INADDRSZ; + if ((protoPtr = getprotobynumber(*cp)) != NULL) { + fprintf(file,"\tinet address = %s, protocol = %s\n\t", + inet_ntoa(inaddr), protoPtr->p_name); + } else { + fprintf(file,"\tinet address = %s, protocol = %d\n\t", + inet_ntoa(inaddr), *cp); + } + cp++; + n = 0; + while (cp < cp1 + dlen) { + c = *cp++; + do { + struct servent *s; + + if (c & 0200) { + s = getservbyport((int)htons(n), + protoPtr ? protoPtr->p_name : NULL); + if (s != NULL) { + fprintf(file," %s", s->s_name); + } else { + fprintf(file," #%d", n); + } + } + c <<= 1; + } while (++n & 07); + } + putc('\n',file); + break; + } + + case T_NULL: + fprintf(file, "\tNULL (dlen %d)\n", dlen); + cp += dlen; + break; + + case T_NXT: + case T_SIG: + case T_KEY: + default: { + char buf[2048]; /* XXX need to malloc/realloc. */ + + if (ns_sprintrrf(msg, eom - msg, "?", class, type, rrttl, + cp1, dlen, NULL, NULL, buf, sizeof buf) < 0) { + perror("ns_sprintrrf"); + } else { + fprintf(file, + "\trecord type %s, interpreted as:\n%s\n", + p_type(type), buf); + } + cp += dlen; + } + } + if (_res.options & RES_DEBUG && type != T_SOA) { + fprintf(file,"\tttl = %lu (%s)\n", rrttl, p_time(rrttl)); + } + if (cp != cp1 + dlen) { + fprintf(file, + "\n*** Error: record size incorrect (%d != %d)\n\n", + cp - cp1, dlen); + cp = NULL; + } + return (cp); +} diff --git a/contrib/bind/bin/nslookup/getinfo.c b/contrib/bind/bin/nslookup/getinfo.c new file mode 100644 index 0000000..20601e5 --- /dev/null +++ b/contrib/bind/bin/nslookup/getinfo.c @@ -0,0 +1,872 @@ +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)getinfo.c 5.26 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: getinfo.c,v 8.11 1998/03/19 19:30:55 halley Exp $"; +#endif /* not lint */ + +/* + ****************************************************************************** + * + * getinfo.c -- + * + * Routines to create requests to name servers + * and interpret the answers. + * + * Adapted from 4.3BSD BIND gethostnamadr.c + * + ****************************************************************************** + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> + +#include "port_after.h" + +#include "res.h" + +extern char *_res_resultcodes[]; +extern char *res_skip(); + +static char *addr_list[MAXADDRS + 1]; + +static char *host_aliases[MAXALIASES]; +static int host_aliases_len[MAXALIASES]; +static u_char hostbuf[MAXDNAME]; + +typedef struct { + char *name; + char *domain[MAXDOMAINS]; + int numDomains; + char *address[MAXADDRS]; + int numAddresses; +} ServerTable; + +ServerTable server[MAXSERVERS]; + +typedef union { + HEADER qb1; + u_char qb2[PACKETSZ*2]; +} querybuf; + +typedef union { + int32_t al; + char ac; +} align; + +#define GetShort(cp) ns_get16(cp); cp += INT16SZ; + + +/* + ****************************************************************************** + * + * GetAnswer -- + * + * Interprets an answer packet and retrieves the following + * information: + * + * Results: + * SUCCESS the info was retrieved. + * NO_INFO the packet did not contain an answer. + * NONAUTH non-authoritative information was found. + * ERROR the answer was malformed. + * Other errors returned in the packet header. + * + ****************************************************************************** + */ + +static int +GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) + struct in_addr *nsAddrPtr; + char *msg; + int queryType; + int msglen; + Boolean iquery; + register HostInfo *hostPtr; + Boolean isServer; +{ + register HEADER *headerPtr; + register u_char *cp; + querybuf answer; + char **aliasPtr; + u_char *eom, *bp; + char **addrPtr; + char *namePtr; + char *dnamePtr; + int type, class; + int qdcount, ancount, arcount, nscount, buflen; + int origClass; + int numAliases = 0; + int numAddresses = 0; + int n, i, j; + int len; + int dlen; + int status; + int numServers; + Boolean haveAnswer; + Boolean printedAnswers = FALSE; + + + /* + * If the hostPtr was used before, free up the calloc'd areas. + */ + FreeHostInfoPtr(hostPtr); + + status = SendRequest(nsAddrPtr, msg, msglen, (u_char *) &answer, + sizeof(answer), &n); + + if (status != SUCCESS) { + if (_res.options & RES_DEBUG2) + printf("SendRequest failed\n"); + return (status); + } + eom = (u_char *) &answer + n; + + headerPtr = (HEADER *) &answer; + + if (headerPtr->rcode != NOERROR) { + return (headerPtr->rcode); + } + + qdcount = ntohs(headerPtr->qdcount); + ancount = ntohs(headerPtr->ancount); + arcount = ntohs(headerPtr->arcount); + nscount = ntohs(headerPtr->nscount); + + /* + * If there are no answer, n.s. or additional records + * then return with an error. + */ + if (ancount == 0 && nscount == 0 && arcount == 0) { + return (NO_INFO); + } + + + bp = hostbuf; + buflen = sizeof(hostbuf); + cp = (u_char *) &answer + HFIXEDSZ; + + /* Skip over question section. */ + while (qdcount-- > 0) { + n = dn_skipname(cp, eom); + if (n < 0) + return (ERROR); + cp += n + QFIXEDSZ; + if (cp > eom) + return (ERROR); + } + + aliasPtr = host_aliases; + addrPtr = addr_list; + haveAnswer = FALSE; + + /* + * Scan through the answer resource records. + * Answers for address query types are saved. + * Other query type answers are just printed. + */ + if (ancount != 0) { + + if (headerPtr->ad) + printf("Answer crypto-validated by server:\n"); + + if (!isServer && !headerPtr->aa) { + printf("Non-authoritative answer:\n"); + } + + if (queryType != T_A && !(iquery && queryType == T_PTR)) { + while (--ancount >= 0 && cp < eom) { + if ((cp = (u_char *)Print_rr(cp, + (u_char *)&answer, eom, stdout)) == NULL) { + return(ERROR); + } + } + printedAnswers = TRUE; + } else { + while (--ancount >= 0 && cp < eom) { + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) + return(ERROR); + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (ERROR); + type = GetShort(cp); + class = GetShort(cp); + cp += INT32SZ; /* skip TTL */ + dlen = GetShort(cp); + if (cp + dlen > eom) + return (ERROR); + if (type == T_CNAME) { + /* + * Found an alias. + */ + cp += dlen; + if (aliasPtr >= &host_aliases[MAXALIASES-1]) { + continue; + } + *aliasPtr++ = (char *)bp; + n = strlen((char *)bp) + 1; + host_aliases_len[numAliases] = n; + numAliases++; + bp += n; + buflen -= n; + continue; + } else if (type == T_PTR) { + /* + * Found a "pointer" to the real name. + */ + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + cp += n; + continue; + } + cp += n; + len = strlen((char *)bp) + 1; + hostPtr->name = Calloc(1, len); + memcpy(hostPtr->name, bp, len); + haveAnswer = TRUE; + break; + } else if (type != T_A) { + cp += dlen; + continue; + } + if (dlen != INADDRSZ) + return (ERROR); + if (haveAnswer) { + /* + * If we've already got 1 address, we aren't interested + * in addresses with a different length or class. + */ + if (dlen != hostPtr->addrLen) { + cp += dlen; + continue; + } + if (class != origClass) { + cp += dlen; + continue; + } + } else { + /* + * First address: record its length and class so we + * only save additonal ones with the same attributes. + */ + hostPtr->addrLen = dlen; + origClass = class; + hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC; + len = strlen((char *)bp) + 1; + hostPtr->name = Calloc(1, len); + memcpy(hostPtr->name, bp, len); + } + bp += (((u_int32_t)bp) % sizeof(align)); + + if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) { + if (_res.options & RES_DEBUG) { + printf("Size (%d) too big\n", dlen); + } + break; + } + if (numAddresses >= MAXADDRS) { + printf("MAXADDRS exceeded: skipping address\n"); + cp += dlen; + continue; + } + memcpy(*addrPtr++ = (char *)bp, cp, dlen); + bp += dlen; + cp += dlen; + numAddresses++; + haveAnswer = TRUE; + } + } + } + + if ((queryType == T_A || queryType == T_PTR) && haveAnswer) { + + /* + * Go through the alias and address lists and return them + * in the hostPtr variable. + */ + + if (numAliases > 0) { + hostPtr->aliases = + (char **) Calloc(1 + numAliases, sizeof(char *)); + for (i = 0; i < numAliases; i++) { + hostPtr->aliases[i] = Calloc(1, host_aliases_len[i]); + memcpy(hostPtr->aliases[i], host_aliases[i], + host_aliases_len[i]); + } + hostPtr->aliases[i] = NULL; + } + if (numAddresses > 0) { + hostPtr->addrList = + (char **)Calloc(1+numAddresses, sizeof(char *)); + for (i = 0; i < numAddresses; i++) { + hostPtr->addrList[i] = Calloc(1, hostPtr->addrLen); + memcpy(hostPtr->addrList[i], addr_list[i], hostPtr->addrLen); + } + hostPtr->addrList[i] = NULL; + } +#ifdef verbose + if (headerPtr->aa || nscount == 0) { + hostPtr->servers = NULL; + return (SUCCESS); + } +#else + hostPtr->servers = NULL; + return (SUCCESS); +#endif + } + + /* + * At this point, for the T_A query type, only empty answers remain. + * For other query types, additional information might be found + * in the additional resource records part. + */ + + if (!headerPtr->aa && (queryType != T_A) && (nscount > 0 || arcount > 0)) { + if (printedAnswers) { + putchar('\n'); + } + printf("Authoritative answers can be found from:\n"); + } + + cp = (u_char *)res_skip((char *) &answer, 2, eom); + + numServers = 0; + if (queryType != T_A) { + /* + * If we don't need to save the record, just print it. + */ + while (--nscount >= 0 && cp < eom) { + if ((cp = (u_char *)Print_rr(cp, + (u_char *) &answer, eom, stdout)) == NULL) { + return(ERROR); + } + } + } else { + while (--nscount >= 0 && cp < eom) { + /* + * Go through the NS records and retrieve the names of hosts + * that serve the requested domain. + */ + + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + return(ERROR); + } + cp += n; + len = strlen((char *)bp) + 1; + dnamePtr = Calloc(1, len); /* domain name */ + memcpy(dnamePtr, bp, len); + + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (ERROR); + type = GetShort(cp); + class = GetShort(cp); + cp += INT32SZ; /* skip TTL */ + dlen = GetShort(cp); + if (cp + dlen > eom) + return (ERROR); + + if (type != T_NS) { + cp += dlen; + } else { + Boolean found; + + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + return(ERROR); + } + cp += n; + len = strlen((char *)bp) + 1; + namePtr = Calloc(1, len); /* server host name */ + memcpy(namePtr, bp, len); + + /* + * Store the information keyed by the server host name. + */ + found = FALSE; + for (j = 0; j < numServers; j++) { + if (strcmp(namePtr, server[j].name) == 0) { + found = TRUE; + free(namePtr); + break; + } + } + if (found) { + server[j].numDomains++; + if (server[j].numDomains <= MAXDOMAINS) { + server[j].domain[server[j].numDomains-1] = dnamePtr; + } + } else { + if (numServers >= MAXSERVERS) { + break; + } + server[numServers].name = namePtr; + server[numServers].domain[0] = dnamePtr; + server[numServers].numDomains = 1; + server[numServers].numAddresses = 0; + numServers++; + } + } + } + } + + /* + * Additional resource records contain addresses of servers. + */ + cp = (u_char *)res_skip((char *) &answer, 3, eom); + + if (queryType != T_A) { + /* + * If we don't need to save the record, just print it. + */ + while (--arcount >= 0 && cp < eom) { + if ((cp = (u_char *)Print_rr(cp, + (u_char *) &answer, eom, stdout)) == NULL) { + return(ERROR); + } + } + } else { + while (--arcount >= 0 && cp < eom) { + n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen); + if (n < 0) { + break; + } + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (ERROR); + type = GetShort(cp); + class = GetShort(cp); + cp += INT32SZ; /* skip TTL */ + dlen = GetShort(cp); + if (cp + dlen > eom) + return (ERROR); + + if (type != T_A) { + cp += dlen; + continue; + } else { + if (dlen != INADDRSZ) + return (ERROR); + for (j = 0; j < numServers; j++) { + if (strcmp((char *)bp, server[j].name) == 0) { + server[j].numAddresses++; + if (server[j].numAddresses <= MAXADDRS) { + server[j].address[server[j].numAddresses-1] = + Calloc(1,dlen); + memcpy(server[j].address[server[j].numAddresses-1], + cp, dlen); + break; + } + } + } + cp += dlen; + } + } + } + + /* + * If we are returning name server info, transfer it to the hostPtr. + */ + if (numServers > 0) { + hostPtr->servers = (ServerInfo **) + Calloc(numServers+1, sizeof(ServerInfo *)); + + for (i = 0; i < numServers; i++) { + hostPtr->servers[i] = (ServerInfo *) Calloc(1, sizeof(ServerInfo)); + hostPtr->servers[i]->name = server[i].name; + + + hostPtr->servers[i]->domains = (char **) + Calloc(server[i].numDomains+1,sizeof(char *)); + for (j = 0; j < server[i].numDomains; j++) { + hostPtr->servers[i]->domains[j] = server[i].domain[j]; + } + hostPtr->servers[i]->domains[j] = NULL; + + + hostPtr->servers[i]->addrList = (char **) + Calloc(server[i].numAddresses+1,sizeof(char *)); + for (j = 0; j < server[i].numAddresses; j++) { + hostPtr->servers[i]->addrList[j] = server[i].address[j]; + } + hostPtr->servers[i]->addrList[j] = NULL; + + } + hostPtr->servers[i] = NULL; + } + + switch (queryType) { + case T_A: + return NONAUTH; + case T_PTR: + if (iquery) + return NO_INFO; + /* fall through */ + default: + return SUCCESS; + } +} + +/* +******************************************************************************* +* +* GetHostInfo -- +* +* Retrieves host name, address and alias information +* for a domain. +* +* Algorithm from res_search(). +* +* Results: +* ERROR - res_mkquery failed. +* + return values from GetAnswer() +* +******************************************************************************* +*/ + +int +GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer) + struct in_addr *nsAddrPtr; + int queryClass; + int queryType; + char *name; + HostInfo *hostPtr; + Boolean isServer; +{ + int n; + register int result; + register char **domain; + const char *cp; + Boolean got_nodata = FALSE; + struct in_addr ina; + Boolean tried_as_is = FALSE; + + /* Catch explicit addresses */ + if ((queryType == T_A) && IsAddr(name, &ina)) { + hostPtr->name = Calloc(strlen(name)+3, 1); + (void)sprintf(hostPtr->name,"[%s]",name); + hostPtr->aliases = NULL; + hostPtr->servers = NULL; + hostPtr->addrType = AF_INET; + hostPtr->addrLen = INADDRSZ; + hostPtr->addrList = (char **)Calloc(2, sizeof(char *)); + hostPtr->addrList[0] = Calloc(INT32SZ, sizeof(char)); + memcpy(hostPtr->addrList[0], &ina, INADDRSZ); + hostPtr->addrList[1] = NULL; + return(SUCCESS); + } + + result = NXDOMAIN; + for (cp = name, n = 0; *cp; cp++) + if (*cp == '.') + n++; + if (n == 0 && (cp = hostalias(name))) { + printf("Aliased to \"%s\"\n\n", cp); + return (GetHostDomain(nsAddrPtr, queryClass, queryType, + cp, (char *)NULL, hostPtr, isServer)); + } + + /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + if (n >= (int)_res.ndots) { + result = GetHostDomain(nsAddrPtr, queryClass, queryType, + name, (char *)NULL, hostPtr, isServer); + if (result == SUCCESS) + return (result); + if (result == NO_INFO) + got_nodata++; + tried_as_is++; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((n == 0 && _res.options & RES_DEFNAMES) || + (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH)) + for (domain = _res.dnsrch; *domain; domain++) { + result = GetHostDomain(nsAddrPtr, queryClass, queryType, + name, *domain, hostPtr, isServer); + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_INFO error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's fully-qualified. + */ + if (result == SUCCESS || result == NO_RESPONSE) + return result; + if (result == NO_INFO) + got_nodata++; + if ((result != NXDOMAIN && result != NO_INFO) || + (_res.options & RES_DNSRCH) == 0) + break; + } + /* if we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!tried_as_is && + (result = GetHostDomain(nsAddrPtr, queryClass, queryType, + name, (char *)NULL, hostPtr, isServer) + ) == SUCCESS) + return (result); + if (got_nodata) + result = NO_INFO; + return (result); +} + +/* + * Perform a query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer) + struct in_addr *nsAddrPtr; + int queryClass; + int queryType; + char *name, *domain; + HostInfo *hostPtr; + Boolean isServer; +{ + querybuf buf; + char nbuf[2*MAXDNAME+2]; + char *longname = nbuf; + int n; + + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name) - 1; + if (name[n] == '.' && n < sizeof(nbuf) - 1) { + memcpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + (void)sprintf(nbuf, "%.*s.%.*s", + MAXDNAME, name, MAXDNAME, domain); + longname = nbuf; + } + n = res_mkquery(QUERY, longname, queryClass, queryType, + NULL, 0, 0, buf.qb2, sizeof(buf)); + if (n < 0) { + if (_res.options & RES_DEBUG) { + printf("Res_mkquery failed\n"); + } + return (ERROR); + } + + n = GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, isServer); + + /* + * GetAnswer didn't find a name, so set it to the specified one. + */ + if (n == NONAUTH) { + if (hostPtr->name == NULL) { + int len = strlen(longname) + 1; + hostPtr->name = Calloc(len, sizeof(char)); + memcpy(hostPtr->name, longname, len); + } + } + return(n); +} + + +/* +******************************************************************************* +* +* GetHostInfoByAddr -- +* +* Performs a PTR lookup in in-addr.arpa to find the host name +* that corresponds to the given address. +* +* Results: +* ERROR - res_mkquery failed. +* + return values from GetAnswer() +* +******************************************************************************* +*/ + +int +GetHostInfoByAddr(nsAddrPtr, address, hostPtr) + struct in_addr *nsAddrPtr; + struct in_addr *address; + HostInfo *hostPtr; +{ + int n; + querybuf buf; + char qbuf[MAXDNAME]; + char *p = (char *) &address->s_addr; + + (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + ((unsigned)p[3] & 0xff), + ((unsigned)p[2] & 0xff), + ((unsigned)p[1] & 0xff), + ((unsigned)p[0] & 0xff)); + n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, + buf.qb2, sizeof buf); + if (n < 0) { + if (_res.options & RES_DEBUG) { + printf("res_mkquery() failed\n"); + } + return (ERROR); + } + n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1); + if (n == SUCCESS) { + hostPtr->addrType = AF_INET; + hostPtr->addrLen = 4; + hostPtr->addrList = (char **)Calloc(2, sizeof(char *)); + hostPtr->addrList[0] = Calloc(INT32SZ, sizeof(char)); + memcpy(hostPtr->addrList[0], p, INADDRSZ); + hostPtr->addrList[1] = NULL; + } + return n; +} + +/* +******************************************************************************* +* +* FreeHostInfoPtr -- +* +* Deallocates all the calloc'd areas for a HostInfo variable. +* +******************************************************************************* +*/ + +void +FreeHostInfoPtr(hostPtr) + register HostInfo *hostPtr; +{ + int i, j; + + if (hostPtr->name != NULL) { + free(hostPtr->name); + hostPtr->name = NULL; + } + + if (hostPtr->aliases != NULL) { + i = 0; + while (hostPtr->aliases[i] != NULL) { + free(hostPtr->aliases[i]); + i++; + } + free((char *)hostPtr->aliases); + hostPtr->aliases = NULL; + } + + if (hostPtr->addrList != NULL) { + i = 0; + while (hostPtr->addrList[i] != NULL) { + free(hostPtr->addrList[i]); + i++; + } + free((char *)hostPtr->addrList); + hostPtr->addrList = NULL; + } + + if (hostPtr->servers != NULL) { + i = 0; + while (hostPtr->servers[i] != NULL) { + + if (hostPtr->servers[i]->name != NULL) { + free(hostPtr->servers[i]->name); + } + + if (hostPtr->servers[i]->domains != NULL) { + j = 0; + while (hostPtr->servers[i]->domains[j] != NULL) { + free(hostPtr->servers[i]->domains[j]); + j++; + } + free((char *)hostPtr->servers[i]->domains); + } + + if (hostPtr->servers[i]->addrList != NULL) { + j = 0; + while (hostPtr->servers[i]->addrList[j] != NULL) { + free(hostPtr->servers[i]->addrList[j]); + j++; + } + free((char *)hostPtr->servers[i]->addrList); + } + free((char *)hostPtr->servers[i]); + i++; + } + free((char *)hostPtr->servers); + hostPtr->servers = NULL; + } +} diff --git a/contrib/bind/bin/nslookup/list.c b/contrib/bind/bin/nslookup/list.c new file mode 100644 index 0000000..6d23e57 --- /dev/null +++ b/contrib/bind/bin/nslookup/list.c @@ -0,0 +1,622 @@ +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)list.c 5.23 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: list.c,v 8.13 1997/11/18 00:32:33 halley Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * list.c -- + * + * Routines to obtain info from name and finger servers. + * + * Adapted from 4.3BSD BIND ns_init.c and from finger.c. + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +#include "res.h" + +extern char *_res_resultcodes[]; /* res_debug.c */ +extern char *pager; + +typedef union { + HEADER qb1; + u_char qb2[PACKETSZ]; +} querybuf; + +extern HostInfo *defaultPtr; +extern HostInfo curHostInfo; +extern int curHostValid; +extern int queryType; +extern int queryClass; + +static int sockFD = -1; +int ListSubr(); + +/* + * During a listing to a file, hash marks are printed + * every HASH_SIZE records. + */ + +#define HASH_SIZE 50 + + +/* + ******************************************************************************* + * + * ListHosts -- + * ListHostsByType -- + * + * Requests the name server to do a zone transfer so we + * find out what hosts it knows about. + * + * For ListHosts, there are five types of output: + * - Internet addresses (default) + * - cpu type and operating system (-h option) + * - canonical and alias names (-a option) + * - well-known service names (-s option) + * - ALL records (-d option) + * ListHostsByType prints records of the default type or of a speicific + * type. + * + * To see all types of information sorted by name, do the following: + * ls -d domain.edu > file + * view file + * + * Results: + * SUCCESS the listing was successful. + * ERROR the server could not be contacted because + * a socket could not be obtained or an error + * occured while receiving, or the output file + * could not be opened. + * + ******************************************************************************* + */ + +void +ListHostsByType(char *string, int putToFile) { + char *namePtr, name[NAME_LEN], option[NAME_LEN]; + int i, qtype, result; + + /* + * Parse the command line. It maybe of the form "ls -t domain" + * or "ls -t type domain". + */ + + i = sscanf(string, " ls -t %s %s", option, name); + if (putToFile && i == 2 && name[0] == '>') + i--; + if (i == 2) { + qtype = StringToType(option, -1, stderr); + if (qtype == -1) + return; + namePtr = name; + } else if (i == 1) { + namePtr = option; + qtype = queryType; + } else { + fprintf(stderr, "*** ls: invalid request %s\n", string); + return; + } + result = ListSubr(qtype, namePtr, putToFile ? string : NULL); + if (result != SUCCESS) + fprintf(stderr, "*** Can't list domain %s: %s\n", + namePtr, DecodeError(result)); +} + +void +ListHosts(char *string, int putToFile) { + char *namePtr, name[NAME_LEN], option[NAME_LEN]; + int i, qtype, result; + + /* + * Parse the command line. It maybe of the form "ls domain", + * "ls -X domain". + */ + i = sscanf(string, " ls %s %s", option, name); + if (putToFile && i == 2 && name[0] == '>') + i--; + if (i == 2) { + if (strcmp("-a", option) == 0) + qtype = T_CNAME; + else if (strcmp("-h", option) == 0) + qtype = T_HINFO; + else if (strcmp("-m", option) == 0) + qtype = T_MX; + else if (strcmp("-p", option) == 0) + qtype = T_PX; + else if (strcmp("-s", option) == 0) + qtype = T_WKS; + else if (strcmp("-d", option) == 0) + qtype = T_ANY; + else if (strcmp("-n", option) == 0) + qtype = T_NAPTR; + else + qtype = T_A; + namePtr = name; + } else if (i == 1) { + namePtr = option; + qtype = T_A; + } else { + fprintf(stderr, "*** ls: invalid request %s\n",string); + return; + } + result = ListSubr(qtype, namePtr, putToFile ? string : NULL); + if (result != SUCCESS) + fprintf(stderr, "*** Can't list domain %s: %s\n", + namePtr, DecodeError(result)); +} + +int +ListSubr(int qtype, char *domain, char *cmd) { + static u_char *answer = NULL; + static int answerLen = 0; + + ns_msg handle; + querybuf buf; + struct sockaddr_in sin; + HEADER *headerPtr; + int msglen, amtToRead, numRead, n, count, soacnt; + u_int len; + int numAnswers = 0; + int numRecords = 0; + u_char tmp[INT16SZ], *cp; + char soaname[2][NAME_LEN], file[NAME_LEN]; + enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING } + error = NO_ERRORS; + + /* + * Create a query packet for the requested domain name. + */ + msglen = res_mkquery(QUERY, domain, queryClass, T_AXFR, + NULL, 0, 0, buf.qb2, sizeof buf); + if (msglen < 0) { + if (_res.options & RES_DEBUG) + fprintf(stderr, "*** ls: res_mkquery failed\n"); + return (ERROR); + } + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(nsport); + + /* + * Check to see if we have the address of the server or the + * address of a server who knows about this domain. + * + * For now, just use the first address in the list. XXX. + */ + + if (defaultPtr->addrList != NULL) + sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0]; + else + sin.sin_addr = *(struct in_addr *) + defaultPtr->servers[0]->addrList[0]; + + /* + * Set up a virtual circuit to the server. + */ + sockFD = socket(AF_INET, SOCK_STREAM, 0); + if (sockFD < 0) { + perror("ls: socket"); + return (ERROR); + } + if (connect(sockFD, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + int e; + + if (errno == ECONNREFUSED) + e = NO_RESPONSE; + else { + perror("ls: connect"); + e = ERROR; + } + (void) close(sockFD); + sockFD = -1; + return (e); + } + + /* + * Send length & message for zone transfer + */ + ns_put16(msglen, tmp); + if (write(sockFD, (char *)tmp, INT16SZ) != INT16SZ || + write(sockFD, (char *)buf.qb2, msglen) != msglen) { + perror("ls: write"); + (void) close(sockFD); + sockFD = -1; + return(ERROR); + } + + fprintf(stdout,"[%s]\n", (defaultPtr->addrList != NULL) + ? defaultPtr->name : defaultPtr->servers[0]->name); + + if (cmd == NULL) { + filePtr = stdout; + } else { + filePtr = OpenFile(cmd, file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", + file); + (void) close(sockFD); + sockFD = -1; + return (ERROR); + } + fprintf(filePtr, "> %s\n", cmd); + fprintf(filePtr, "[%s]\n", (defaultPtr->addrList != NULL) + ? defaultPtr->name : defaultPtr->servers[0]->name); + } + + soacnt = 0; + while (soacnt < 2) { + /* + * Read the length of the response. + */ + + cp = tmp; amtToRead = INT16SZ; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_LEN; + break; + } + + len = ns_get16(tmp); + if (len == 0) + break; /* nothing left to read */ + + /* + * If the server sent too much data to fit the existing + * buffer, allocate a new one. + */ + if (len > (u_int)answerLen) { + if (answerLen != 0) + free(answer); + answerLen = len; + answer = (u_char *)Malloc(answerLen); + } + + /* + * Read the response. + */ + amtToRead = len; cp = answer; + while (amtToRead > 0 && + (numRead = read(sockFD, cp, amtToRead)) > 0) { + cp += numRead; + amtToRead -= numRead; + } + if (numRead <= 0) { + error = ERR_READING_MSG; + break; + } + + if (ns_initparse(answer, cp - answer, &handle) < 0) { + perror("ns_initparse"); + error = ERR_PRINTING; + break; + } + if (ns_msg_getflag(handle, ns_f_rcode) != ns_r_noerror || + ns_msg_count(handle, ns_s_an) == 0) { + /* Signalled protocol error, or empty message. */ + error = ERR_PRINTING; + break; + } + + for (;;) { + static char origin[NS_MAXDNAME], name_ctx[NS_MAXDNAME]; + const char *name; + char buf[2048]; /* XXX need to malloc/realloc. */ + ns_rr rr; + + if (ns_parserr(&handle, ns_s_an, -1, &rr)) { + if (errno != ENODEV) { + perror("ns_parserr"); + error = ERR_PRINTING; + } + break; + } + name = ns_rr_name(rr); + if (origin[0] == '\0' && name[0] != '\0') { + fprintf(filePtr, "$ORIGIN %s.\n", name); + strcpy(origin, name); + } + if (qtype == T_ANY || ns_rr_type(rr) == qtype) { + if (ns_sprintrr(&handle, &rr, name_ctx, origin, + buf, sizeof buf) < 0) { + perror("ns_sprintrr"); + error = ERR_PRINTING; + break; + } + strcpy(name_ctx, name); + numAnswers++; + fputs(buf, filePtr); + fputc('\n', filePtr); + } + if (ns_rr_type(rr) == T_SOA) { + strcpy(soaname[soacnt], name); + if (soacnt == 0) + soacnt = 1; + else if (strcasecmp(soaname[0], + soaname[1]) == 0) { + soacnt = 2; + } + } + } + if (error != NO_ERRORS) + break; + numAnswers++; + if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) { + fprintf(stdout, "#"); + fflush(stdout); + } + } + + if (cmd != NULL) + fprintf(stdout, "%sReceived %d answer%s (%d record%s).\n", + (numAnswers >= HASH_SIZE) ? "\n" : "", + numAnswers, (numAnswers != 1) ? "s" : "", + numRecords, (numRecords != 1) ? "s" : ""); + + (void) close(sockFD); + sockFD = -1; + if (cmd != NULL && filePtr != NULL) { + fclose(filePtr); + filePtr = NULL; + } + + switch (error) { + case NO_ERRORS: + return (SUCCESS); + + case ERR_READING_LEN: + return (ERROR); + + case ERR_PRINTING: + return (ERROR); + + case ERR_READING_MSG: + headerPtr = (HEADER *) answer; + fprintf(stderr,"*** ls: error receiving zone transfer:\n"); + fprintf(stderr, + " result: %s, answers = %d, authority = %d, additional = %d\n", + _res_resultcodes[headerPtr->rcode], + ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), + ntohs(headerPtr->arcount)); + return (ERROR); + default: + return (ERROR); + } +} + +/* + ******************************************************************************* + * + * ViewList -- + * + * A hack to view the output of the ls command in sorted + * order using more. + * + ******************************************************************************* + */ + +ViewList(string) + char *string; +{ + char file[PATH_MAX]; + char command[PATH_MAX]; + + sscanf(string, " view %s", file); + (void)sprintf(command, "grep \"^ \" %s | sort | %s", file, pager); + system(command); +} + +/* + ******************************************************************************* + * + * Finger -- + * + * Connects with the finger server for the current host + * to request info on the specified person (long form) + * who is on the system (short form). + * + * Results: + * SUCCESS the finger server was contacted. + * ERROR the server could not be contacted because + * a socket could not be obtained or connected + * to or the service could not be found. + * + ******************************************************************************* + */ + +Finger(string, putToFile) + char *string; + int putToFile; +{ + struct servent *sp; + struct sockaddr_in sin; + FILE *f; + int c; + int lastc; + char name[NAME_LEN]; + char file[NAME_LEN]; + + /* + * We need a valid current host info to get an inet address. + */ + if (!curHostValid) { + fprintf(stderr, "Finger: no current host defined.\n"); + return (ERROR); + } + + if (sscanf(string, " finger %s", name) == 1) { + if (putToFile && (name[0] == '>')) { + name[0] = '\0'; + } + } else { + name[0] = '\0'; + } + + sp = getservbyname("finger", "tcp"); + if (sp == 0) { + fprintf(stderr, "Finger: unknown service\n"); + return (ERROR); + } + + memset(&sin, 0, sizeof sin); + sin.sin_family = curHostInfo.addrType; + sin.sin_port = sp->s_port; + memcpy(&sin.sin_addr, curHostInfo.addrList[0], curHostInfo.addrLen); + + /* + * Set up a virtual circuit to the host. + */ + + sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0); + if (sockFD < 0) { + fflush(stdout); + perror("finger: socket"); + return (ERROR); + } + + if (connect(sockFD, (struct sockaddr *)&sin, sizeof (sin)) < 0) { + fflush(stdout); + perror("finger: connect"); + close(sockFD); + sockFD = -1; + return (ERROR); + } + + if (!putToFile) { + filePtr = stdout; + } else { + filePtr = OpenFile(string, file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", file); + close(sockFD); + sockFD = -1; + return(ERROR); + } + fprintf(filePtr,"> %s\n", string); + } + fprintf(filePtr, "[%s]\n", curHostInfo.name); + + if (name[0] != '\0') { + write(sockFD, "/W ", 3); + } + write(sockFD, name, strlen(name)); + write(sockFD, "\r\n", 2); + f = fdopen(sockFD, "r"); + lastc = '\n'; + while ((c = getc(f)) != EOF) { + switch (c) { + case 0210: + case 0211: + case 0212: + case 0214: + c -= 0200; + break; + case 0215: + c = '\n'; + break; + } + putc(lastc = c, filePtr); + } + if (lastc != '\n') { + putc('\n', filePtr); + } + putc('\n', filePtr); + + close(sockFD); + sockFD = -1; + + if (putToFile) { + fclose(filePtr); + filePtr = NULL; + } + return (SUCCESS); +} + +ListHost_close() +{ + if (sockFD != -1) { + (void) close(sockFD); + sockFD = -1; + } +} diff --git a/contrib/bind/bin/nslookup/main.c b/contrib/bind/bin/nslookup/main.c new file mode 100644 index 0000000..3c97afe --- /dev/null +++ b/contrib/bind/bin/nslookup/main.c @@ -0,0 +1,1125 @@ +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1985,1989 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 5.42 (Berkeley) 3/3/91"; +static char rcsid[] = "$Id: main.c,v 8.7 1997/04/25 00:27:18 vixie Exp $"; +#endif /* not lint */ + +/* + ****************************************************************************** + * + * main.c -- + * + * Main routine and some action routines for the name server + * lookup program. + * + * Andrew Cherenson + * U.C. Berkeley Computer Science Div. + * CS298-26, Fall 1985 + * + ****************************************************************************** + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#include "res.h" +#include "pathnames.h" + +/* + * Name of a top-level name server. Can be changed with + * the "set root" command. + */ + +#ifndef ROOT_SERVER +#define ROOT_SERVER "a.root-servers.net." +#endif +char rootServerName[NAME_LEN] = ROOT_SERVER; + +/* + * Import the state information from the resolver library. + */ + +extern struct __res_state _res; + + +/* + * Info about the most recently queried host. + */ + +HostInfo curHostInfo; +int curHostValid = FALSE; + + +/* + * Info about the default name server. + */ + +HostInfo *defaultPtr = NULL; +char defaultServer[NAME_LEN]; +struct in_addr defaultAddr; + + +/* + * Initial name server query type is Address. + */ + +int queryType = T_A; +int queryClass = C_IN; + +/* + * Stuff for Interrupt (control-C) signal handler. + */ + +extern SIG_FN IntrHandler(); +FILE *filePtr; +jmp_buf env; + + +/* + * Browser command for help and view. + */ +char *pager; + +static void CvtAddrToPtr(); +static void ReadRC(); + + +/* + ****************************************************************************** + * + * main -- + * + * Initializes the resolver library and determines the address + * of the initial name server. The yylex routine is used to + * read and perform commands. + * + ****************************************************************************** + */ + +main(argc, argv) + int argc; + char **argv; +{ + char *wantedHost = NULL; + Boolean useLocalServer; + int result; + int i; + struct hostent *hp; + + /* + * Initialize the resolver library routines. + */ + + if (res_init() == -1) { + fprintf(stderr,"*** Can't initialize resolver.\n"); + exit(1); + } + + /* + * Allocate space for the default server's host info and + * find the server's address and name. If the resolver library + * already has some addresses for a potential name server, + * then use them. Otherwise, see if the current host has a server. + * Command line arguments may override the choice of initial server. + */ + + defaultPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); + + /* + * Parse the arguments: + * no args = go into interactive mode, use default host as server + * 1 arg = use as host name to be looked up, default host will be server + * non-interactive mode + * 2 args = 1st arg: + * if it is '-', then + * ignore but go into interactive mode + * else + * use as host name to be looked up, + * go into non-interactive mode + * 2nd arg: name or inet address of server + * + * "Set" options are specified with a leading - and must come before + * any arguments. For example, to find the well-known services for + * a host, type "nslookup -query=wks host" + */ + + ReadRC(); /* look for options file */ + + ++argv; --argc; /* skip prog name */ + + while (argc && *argv[0] == '-' && argv[0][1]) { + (void) SetOption (&(argv[0][1])); + ++argv; --argc; + } + if (argc > 2) { + Usage(); + } + if (argc && *argv[0] != '-') { + wantedHost = *argv; /* name of host to be looked up */ + } + + useLocalServer = FALSE; + if (argc == 2) { + struct in_addr addr; + + /* + * Use an explicit name server. If the hostname lookup fails, + * default to the server(s) in resolv.conf. + */ + + if (inet_aton(*++argv, &addr)) { + _res.nscount = 1; + _res.nsaddr.sin_addr = addr; + } else { + hp = gethostbyname(*argv); + if (hp == NULL) { + fprintf(stderr, "*** Can't find server address for '%s': ", + *argv); + herror((char *)NULL); + fputc('\n', stderr); + } else { + for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) { + memcpy(&_res.nsaddr_list[i].sin_addr, hp->h_addr_list[i], + hp->h_length); + } + _res.nscount = i; + } + } + } + + + if (_res.nscount == 0 || useLocalServer) { + LocalServer(defaultPtr); + } else { + for (i = 0; i < _res.nscount; i++) { + if (_res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) { + LocalServer(defaultPtr); + break; + } else { + result = GetHostInfoByAddr(&(_res.nsaddr_list[i].sin_addr), + &(_res.nsaddr_list[i].sin_addr), + defaultPtr); + if (result != SUCCESS) { + fprintf(stderr, + "*** Can't find server name for address %s: %s\n", + inet_ntoa(_res.nsaddr_list[i].sin_addr), + DecodeError(result)); + } else { + defaultAddr = _res.nsaddr_list[i].sin_addr; + break; + } + } + } + + /* + * If we have exhausted the list, tell the user about the + * command line argument to specify an address. + */ + + if (i == _res.nscount) { + fprintf(stderr, "*** Default servers are not available\n"); + exit(1); + } + + } + strcpy(defaultServer, defaultPtr->name); + + +#ifdef DEBUG +#ifdef DEBUG2 + _res.options |= RES_DEBUG2; +#endif + _res.options |= RES_DEBUG; + _res.retry = 2; +#endif /* DEBUG */ + + /* + * If we're in non-interactive mode, look up the wanted host and quit. + * Otherwise, print the initial server's name and continue with + * the initialization. + */ + + if (wantedHost != (char *) NULL) { + LookupHost(wantedHost, 0); + } else { + PrintHostInfo(stdout, "Default Server:", defaultPtr); + + pager = getenv("PAGER"); + if (pager == NULL) { + pager = _PATH_PAGERCMD; + } + + /* + * Setup the environment to allow the interrupt handler to return here. + */ + + (void) setjmp(env); + + /* + * Return here after a longjmp. + */ + + signal(SIGINT, IntrHandler); + signal(SIGPIPE, SIG_IGN); + + /* + * Read and evaluate commands. The commands are described in commands.l + * Yylex returns 0 when ^D or 'exit' is typed. + */ + + printf("> "); + fflush(stdout); + while(yylex()) { + printf("> "); + fflush(stdout); + } + } + exit(0); +} + + +LocalServer(defaultPtr) + HostInfo *defaultPtr; +{ + char hostName[NAME_LEN]; + + (void) gethostname(hostName, sizeof(hostName)); + + defaultAddr.s_addr = htonl(INADDR_ANY); + (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, + "0.0.0.0", defaultPtr, 1); + free(defaultPtr->name); + defaultPtr->name = Calloc(1, sizeof(hostName)+1); + strcpy(defaultPtr->name, hostName); +} + + +/* + ****************************************************************************** + * + * Usage -- + * + * Lists the proper methods to run the program and exits. + * + ****************************************************************************** + */ + +Usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, +" nslookup [-opt ...] # interactive mode using default server\n"); + fprintf(stderr, +" nslookup [-opt ...] - server # interactive mode using 'server'\n"); + fprintf(stderr, +" nslookup [-opt ...] host # just look up 'host' using default server\n"); + fprintf(stderr, +" nslookup [-opt ...] host server # just look up 'host' using 'server'\n"); + exit(1); +} + +/* + ****************************************************************************** + * + * IsAddr -- + * + * Returns TRUE if the string looks like an Internet address. + * A string with a trailing dot is not an address, even if it looks + * like one. + * + ****************************************************************************** + */ + +Boolean +IsAddr(host, addrPtr) + char *host; + struct in_addr *addrPtr; /* If return TRUE, contains IP address */ +{ + register char *cp; + + if (isdigit(host[0])) { + /* Make sure it has only digits and dots. */ + for (cp = host; *cp; ++cp) { + if (!isdigit(*cp) && *cp != '.') + return FALSE; + } + /* If it has a trailing dot, don't treat it as an address. */ + if (*--cp != '.') { + return inet_aton(host, addrPtr); + } + } + return FALSE; +} + + +/* + ****************************************************************************** + * + * SetDefaultServer -- + * + * Changes the default name server to the one specified by + * the first argument. The command "server name" uses the current + * default server to lookup the info for "name". The command + * "lserver name" uses the original server to lookup "name". + * + * Side effects: + * This routine will cause a core dump if the allocation requests fail. + * + * Results: + * SUCCESS The default server was changed successfully. + * NONAUTH The server was changed but addresses of + * other servers who know about the requested server + * were returned. + * Errors No info about the new server was found or + * requests to the current server timed-out. + * + ****************************************************************************** + */ + +int +SetDefaultServer(string, local) + char *string; + Boolean local; +{ + register HostInfo *newDefPtr; + struct in_addr *servAddrPtr; + struct in_addr addr; + char newServer[NAME_LEN]; + int result; + int i; + + /* + * Parse the command line. It maybe of the form "server name", + * "lserver name" or just "name". + */ + + if (local) { + i = sscanf(string, " lserver %s", newServer); + } else { + i = sscanf(string, " server %s", newServer); + } + if (i != 1) { + i = sscanf(string, " %s", newServer); + if (i != 1) { + fprintf(stderr,"SetDefaultServer: invalid name: %s\n", string); + return(ERROR); + } + } + + /* + * Allocate space for a HostInfo variable for the new server. Don't + * overwrite the old HostInfo struct because info about the new server + * might not be found and we need to have valid default server info. + */ + + newDefPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); + + + /* + * A 'local' lookup uses the original server that the program was + * initialized with. + * + * Check to see if we have the address of the server or the + * address of a server who knows about this domain. + * XXX For now, just use the first address in the list. + */ + + if (local) { + servAddrPtr = &defaultAddr; + } else if (defaultPtr->addrList != NULL) { + servAddrPtr = (struct in_addr *) defaultPtr->addrList[0]; + } else { + servAddrPtr = (struct in_addr *) defaultPtr->servers[0]->addrList[0]; + } + + result = ERROR; + if (IsAddr(newServer, &addr)) { + result = GetHostInfoByAddr(servAddrPtr, &addr, newDefPtr); + /* If we can't get the name, fall through... */ + } + if (result != SUCCESS && result != NONAUTH) { + result = GetHostInfoByName(servAddrPtr, C_IN, T_A, + newServer, newDefPtr, 1); + } + + /* If we ask for an A record and get none back, but get an NS + record for the NS server, this is the NONAUTH case. + We must check whether we got an IP address for the NS + server or not. */ + if ((result == SUCCESS || result == NONAUTH) && + ((newDefPtr->addrList && newDefPtr->addrList[0] != 0) || + (newDefPtr->servers && newDefPtr->servers[0] && + newDefPtr->servers[0]->addrList[0] != 0))) { + /* + * Found info about the new server. Free the resources for + * the old server. + */ + + FreeHostInfoPtr(defaultPtr); + free((char *)defaultPtr); + defaultPtr = newDefPtr; + strcpy(defaultServer, defaultPtr->name); + PrintHostInfo(stdout, "Default Server:", defaultPtr); + return(SUCCESS); + } else { + fprintf(stderr, "*** Can't find address for server %s: %s\n", + newServer, DecodeError(result)); + free((char *)newDefPtr); + + return(result); + } +} + +/* + ****************************************************************************** + * + * DoLoookup -- + * + * Common subroutine for LookupHost and LookupHostWithServer. + * + * Results: + * SUCCESS - the lookup was successful. + * Misc. Errors - an error message is printed if the lookup failed. + * + ****************************************************************************** + */ + +static int +DoLookup(host, servPtr, serverName) + char *host; + HostInfo *servPtr; + char *serverName; +{ + int result; + struct in_addr *servAddrPtr; + struct in_addr addr; + + /* Skip escape character */ + if (host[0] == '\\') + host++; + + /* + * If the user gives us an address for an address query, + * silently treat it as a PTR query. If the query type is already + * PTR, then convert the address into the in-addr.arpa format. + * + * Use the address of the server if it exists, otherwise use the + * address of a server who knows about this domain. + * XXX For now, just use the first address in the list. + */ + + if (servPtr->addrList != NULL) { + servAddrPtr = (struct in_addr *) servPtr->addrList[0]; + } else { + servAddrPtr = (struct in_addr *) servPtr->servers[0]->addrList[0]; + } + + /* + * RFC1123 says we "SHOULD check the string syntactically for a + * dotted-decimal number before looking it up [...]" (p. 13). + */ + if (queryType == T_A && IsAddr(host, &addr)) { + result = GetHostInfoByAddr(servAddrPtr, &addr, &curHostInfo); + } else { + if (queryType == T_PTR) { + CvtAddrToPtr(host); + } + result = GetHostInfoByName(servAddrPtr, queryClass, queryType, host, + &curHostInfo, 0); + } + + switch (result) { + case SUCCESS: + /* + * If the query was for an address, then the &curHostInfo + * variable can be used by Finger. + * There's no need to print anything for other query types + * because the info has already been printed. + */ + if (queryType == T_A) { + curHostValid = TRUE; + PrintHostInfo(filePtr, "Name:", &curHostInfo); + } + break; + + /* + * No Authoritative answer was available but we got names + * of servers who know about the host. + */ + case NONAUTH: + PrintHostInfo(filePtr, "Name:", &curHostInfo); + break; + + case NO_INFO: + fprintf(stderr, "*** No %s (%s) records available for %s\n", + DecodeType(queryType), p_type(queryType), host); + break; + + case TIME_OUT: + fprintf(stderr, "*** Request to %s timed-out\n", serverName); + break; + + default: + fprintf(stderr, "*** %s can't find %s: %s\n", serverName, host, + DecodeError(result)); + } + return result; +} + +/* + ****************************************************************************** + * + * LookupHost -- + * + * Asks the default name server for information about the + * specified host or domain. The information is printed + * if the lookup was successful. + * + * Results: + * ERROR - the output file could not be opened. + * + results of DoLookup + * + ****************************************************************************** + */ + +int +LookupHost(string, putToFile) + char *string; + Boolean putToFile; +{ + char host[NAME_LEN]; + char file[PATH_MAX]; + int result; + + /* + * Invalidate the current host information to prevent Finger + * from using bogus info. + */ + + curHostValid = FALSE; + + /* + * Parse the command string into the host and + * optional output file name. + * + */ + + sscanf(string, " %s", host); /* removes white space */ + if (!putToFile) { + filePtr = stdout; + } else { + filePtr = OpenFile(string, file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", file); + return(ERROR); + } + fprintf(filePtr,"> %s\n", string); + } + + PrintHostInfo(filePtr, "Server:", defaultPtr); + + result = DoLookup(host, defaultPtr, defaultServer); + + if (putToFile) { + fclose(filePtr); + filePtr = NULL; + } + return(result); +} + +/* + ****************************************************************************** + * + * LookupHostWithServer -- + * + * Asks the name server specified in the second argument for + * information about the host or domain specified in the first + * argument. The information is printed if the lookup was successful. + * + * Address info about the requested name server is obtained + * from the default name server. This routine will return an + * error if the default server doesn't have info about the + * requested server. Thus an error return status might not + * mean the requested name server doesn't have info about the + * requested host. + * + * Comments from LookupHost apply here, too. + * + * Results: + * ERROR - the output file could not be opened. + * + results of DoLookup + * + ****************************************************************************** + */ + +int +LookupHostWithServer(string, putToFile) + char *string; + Boolean putToFile; +{ + char file[PATH_MAX]; + char host[NAME_LEN]; + char server[NAME_LEN]; + int result; + static HostInfo serverInfo; + + curHostValid = FALSE; + + sscanf(string, " %s %s", host, server); + if (!putToFile) { + filePtr = stdout; + } else { + filePtr = OpenFile(string, file); + if (filePtr == NULL) { + fprintf(stderr, "*** Can't open %s for writing\n", file); + return(ERROR); + } + fprintf(filePtr,"> %s\n", string); + } + + result = GetHostInfoByName( + defaultPtr->addrList ? + (struct in_addr *) defaultPtr->addrList[0] : + (struct in_addr *) defaultPtr->servers[0]->addrList[0], + C_IN, T_A, server, &serverInfo, 1); + + if (result != SUCCESS) { + fprintf(stderr,"*** Can't find address for server %s: %s\n", server, + DecodeError(result)); + } else { + PrintHostInfo(filePtr, "Server:", &serverInfo); + + result = DoLookup(host, &serverInfo, server); + } + if (putToFile) { + fclose(filePtr); + filePtr = NULL; + } + return(result); +} + +/* + ****************************************************************************** + * + * SetOption -- + * + * This routine is used to change the state information + * that affect the lookups. The command format is + * set keyword[=value] + * Most keywords can be abbreviated. Parsing is very simplistic-- + * A value must not be separated from its keyword by white space. + * + * Valid keywords: Meaning: + * all lists current values of options. + * ALL lists current values of options, including + * hidden options. + * [no]d2 turn on/off extra debugging mode. + * [no]debug turn on/off debugging mode. + * [no]defname use/don't use default domain name. + * [no]search use/don't use domain search list. + * domain=NAME set default domain name to NAME. + * [no]ignore ignore/don't ignore trunc. errors. + * query=value set default query type to value, + * value is one of the query types in RFC883 + * without the leading T_. (e.g., A, HINFO) + * [no]recurse use/don't use recursive lookup. + * retry=# set number of retries to #. + * root=NAME change root server to NAME. + * time=# set timeout length to #. + * [no]vc use/don't use virtual circuit. + * port TCP/UDP port to server. + * + * Deprecated: + * [no]primary use/don't use primary server. + * + * Results: + * SUCCESS the command was parsed correctly. + * ERROR the command was not parsed correctly. + * + ****************************************************************************** + */ + +int +SetOption(option) + register char *option; +{ + char type[NAME_LEN]; + char *ptr; + int tmp; + + while (isspace(*option)) + ++option; + if (strncmp (option, "set ", 4) == 0) + option += 4; + while (isspace(*option)) + ++option; + + if (*option == 0) { + fprintf(stderr, "*** Invalid set command\n"); + return(ERROR); + } else { + if (strncmp(option, "all", 3) == 0) { + ShowOptions(); + } else if (strncmp(option, "ALL", 3) == 0) { + ShowOptions(); + } else if (strncmp(option, "d2", 2) == 0) { /* d2 (more debug) */ + _res.options |= (RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "nod2", 4) == 0) { + _res.options &= ~RES_DEBUG2; + printf("d2 mode disabled; still in debug mode\n"); + } else if (strncmp(option, "def", 3) == 0) { /* defname */ + _res.options |= RES_DEFNAMES; + } else if (strncmp(option, "nodef", 5) == 0) { + _res.options &= ~RES_DEFNAMES; + } else if (strncmp(option, "do", 2) == 0) { /* domain */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%s", _res.defdname); + res_re_init(); + } + } else if (strncmp(option, "deb", 1) == 0) { /* debug */ + _res.options |= RES_DEBUG; + } else if (strncmp(option, "nodeb", 5) == 0) { + _res.options &= ~(RES_DEBUG | RES_DEBUG2); + } else if (strncmp(option, "ig", 2) == 0) { /* ignore */ + _res.options |= RES_IGNTC; + } else if (strncmp(option, "noig", 4) == 0) { + _res.options &= ~RES_IGNTC; + } else if (strncmp(option, "po", 2) == 0) { /* port */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%hu", &nsport); + } +#ifdef deprecated + } else if (strncmp(option, "pri", 3) == 0) { /* primary */ + _res.options |= RES_PRIMARY; + } else if (strncmp(option, "nopri", 5) == 0) { + _res.options &= ~RES_PRIMARY; +#endif + } else if (strncmp(option, "q", 1) == 0 || /* querytype */ + strncmp(option, "ty", 2) == 0) { /* type */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%s", type); + queryType = StringToType(type, queryType, stderr); + } + } else if (strncmp(option, "cl", 2) == 0) { /* query class */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%s", type); + queryClass = StringToClass(type, queryClass, stderr); + } + } else if (strncmp(option, "rec", 3) == 0) { /* recurse */ + _res.options |= RES_RECURSE; + } else if (strncmp(option, "norec", 5) == 0) { + _res.options &= ~RES_RECURSE; + } else if (strncmp(option, "ret", 3) == 0) { /* retry */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%d", &tmp); + if (tmp >= 0) { + _res.retry = tmp; + } + } + } else if (strncmp(option, "ro", 2) == 0) { /* root */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%s", rootServerName); + } + } else if (strncmp(option, "sea", 3) == 0) { /* search list */ + _res.options |= RES_DNSRCH; + } else if (strncmp(option, "nosea", 5) == 0) { + _res.options &= ~RES_DNSRCH; + } else if (strncmp(option, "srchl", 5) == 0) { /* domain search list */ + ptr = strchr(option, '='); + if (ptr != NULL) { + res_dnsrch(++ptr); + } + } else if (strncmp(option, "ti", 2) == 0) { /* timeout */ + ptr = strchr(option, '='); + if (ptr != NULL) { + sscanf(++ptr, "%d", &tmp); + if (tmp >= 0) { + _res.retrans = tmp; + } + } + } else if (strncmp(option, "v", 1) == 0) { /* vc */ + _res.options |= RES_USEVC; + } else if (strncmp(option, "nov", 3) == 0) { + _res.options &= ~RES_USEVC; + } else { + fprintf(stderr, "*** Invalid option: %s\n", option); + return(ERROR); + } + } + return(SUCCESS); +} + +/* + * Fake a reinitialization when the domain is changed. + */ +res_re_init() +{ + register char *cp, **pp; + int n; + + /* find components of local domain that might be searched */ + pp = _res.dnsrch; + *pp++ = _res.defdname; + for (cp = _res.defdname, n = 0; *cp; cp++) + if (*cp == '.') + n++; + cp = _res.defdname; + for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; n--) { + cp = strchr(cp, '.'); + *pp++ = ++cp; + } + *pp = 0; + _res.options |= RES_INIT; +} + +#define SRCHLIST_SEP '/' + +res_dnsrch(cp) + register char *cp; +{ + register char **pp; + int n; + + (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + if ((cp = strchr(_res.defdname, '\n')) != NULL) + *cp = '\0'; + /* + * Set search list to be blank-separated strings + * on rest of line. + */ + cp = _res.defdname; + pp = _res.dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + if (*cp == SRCHLIST_SEP) { + *cp = '\0'; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + } + } + if ((cp = strchr(pp[-1], SRCHLIST_SEP)) != NULL) { + *cp = '\0'; + } + *pp = NULL; +} + + +/* + ****************************************************************************** + * + * ShowOptions -- + * + * Prints out the state information used by the resolver + * library and other options set by the user. + * + ****************************************************************************** + */ + +void +ShowOptions() +{ + register char **cp; + + PrintHostInfo(stdout, "Default Server:", defaultPtr); + if (curHostValid) { + PrintHostInfo(stdout, "Host:", &curHostInfo); + } + + printf("Set options:\n"); + printf(" %sdebug \t", (_res.options & RES_DEBUG) ? "" : "no"); + printf(" %sdefname\t", (_res.options & RES_DEFNAMES) ? "" : "no"); + printf(" %ssearch\t", (_res.options & RES_DNSRCH) ? "" : "no"); + printf(" %srecurse\n", (_res.options & RES_RECURSE) ? "" : "no"); + + printf(" %sd2\t\t", (_res.options & RES_DEBUG2) ? "" : "no"); + printf(" %svc\t\t", (_res.options & RES_USEVC) ? "" : "no"); + printf(" %signoretc\t", (_res.options & RES_IGNTC) ? "" : "no"); + printf(" port=%u\n", nsport); + + printf(" querytype=%s\t", p_type(queryType)); + printf(" class=%s\t", p_class(queryClass)); + printf(" timeout=%d\t", _res.retrans); + printf(" retry=%d\n", _res.retry); + printf(" root=%s\n", rootServerName); + printf(" domain=%s\n", _res.defdname); + + cp = _res.dnsrch; + if (cp != NULL) { + printf(" srchlist=%s", *cp); + for (cp++; *cp; cp++) { + printf("%c%s", SRCHLIST_SEP, *cp); + } + putchar('\n'); + } + putchar('\n'); +} +#undef SRCHLIST_SEP + +/* + ****************************************************************************** + * + * PrintHelp -- + * + * Displays the help file. + * + ****************************************************************************** + */ + +void +PrintHelp() +{ + char cmd[PATH_MAX]; + + sprintf(cmd, "%s %s", pager, _PATH_HELPFILE); + system(cmd); +} + +/* + ****************************************************************************** + * + * CvtAddrToPtr -- + * + * Convert a dotted-decimal Internet address into the standard + * PTR format (reversed address with .in-arpa. suffix). + * + * Assumes the argument buffer is large enougth to hold the result. + * + ****************************************************************************** + */ + +static void +CvtAddrToPtr(name) + char *name; +{ + char *p; + int ip[4]; + struct in_addr addr; + + if (IsAddr(name, &addr)) { + p = inet_ntoa(addr); + if (sscanf(p, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4) { + sprintf(name, "%d.%d.%d.%d.in-addr.arpa.", + ip[3], ip[2], ip[1], ip[0]); + } + } +} + +/* + ****************************************************************************** + * + * ReadRC -- + * + * Use the contents of ~/.nslookuprc as options. + * + ****************************************************************************** + */ + +static void +ReadRC() +{ + register FILE *fp; + register char *cp; + char buf[PATH_MAX]; + + if ((cp = getenv("HOME")) != NULL && + (strlen(cp) + strlen(_PATH_NSLOOKUPRC)) < sizeof(buf)) { + + (void) strcpy(buf, cp); + (void) strcat(buf, _PATH_NSLOOKUPRC); + + if ((fp = fopen(buf, "r")) != NULL) { + while (fgets(buf, sizeof(buf), fp) != NULL) { + if ((cp = strchr(buf, '\n')) != NULL) { + *cp = '\0'; + } + (void) SetOption(buf); + } + (void) fclose(fp); + } + } +} diff --git a/contrib/bind/bin/nslookup/nslookup.help b/contrib/bind/bin/nslookup/nslookup.help new file mode 100644 index 0000000..015bdc2 --- /dev/null +++ b/contrib/bind/bin/nslookup/nslookup.help @@ -0,0 +1,34 @@ +$Id: nslookup.help,v 8.4 1996/10/25 18:09:41 vixie Exp $ + +Commands: (identifiers are shown in uppercase, [] means optional) +NAME - print info about the host/domain NAME using default server +NAME1 NAME2 - as above, but use NAME2 as server +help or ? - print info on common commands; see nslookup(1) for details +set OPTION - set an option + all - print options, current server and host + [no]debug - print debugging information + [no]d2 - print exhaustive debugging information + [no]defname - append domain name to each query + [no]recurse - ask for recursive answer to query + [no]vc - always use a virtual circuit + domain=NAME - set default domain name to NAME + srchlist=N1[/N2/.../N6] - set domain to N1 and search list to N1,N2, etc. + root=NAME - set root server to NAME + retry=X - set number of retries to X + timeout=X - set initial time-out interval to X seconds + querytype=X - set query type, e.g., A,ANY,CNAME,HINFO,MX,PX,NS,PTR,SOA,TXT,WKS,SRV,NAPTR + port=X - set port number to send query on + type=X - synonym for querytype + class=X - set query class to one of IN (Internet), CHAOS, HESIOD or ANY +server NAME - set default server to NAME, using current default server +lserver NAME - set default server to NAME, using initial server +finger [USER] - finger the optional USER at the current default host +root - set current default server to the root +ls [opt] DOMAIN [> FILE] - list addresses in DOMAIN (optional: output to FILE) + -a - list canonical names and aliases + -h - list HINFO (CPU type and operating system) + -s - list well-known services + -d - list all records + -t TYPE - list records of the given type (e.g., A,CNAME,MX, etc.) +view FILE - sort an 'ls' output file and view it with more +exit - exit the program, ^D also exits diff --git a/contrib/bind/bin/nslookup/pathnames.h b/contrib/bind/bin/nslookup/pathnames.h new file mode 100644 index 0000000..bfeae4f --- /dev/null +++ b/contrib/bind/bin/nslookup/pathnames.h @@ -0,0 +1,71 @@ +/* + * ++Copyright++ 1990 + * - + * Copyright (c) 1990 + * 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. + * - + * --Copyright-- + */ + +/* + * @(#)pathnames.h 5.1 (Berkeley) 5/28/90 + * $Id: pathnames.h,v 8.1 1994/12/15 06:24:31 vixie Exp $ + */ + +#define _PATH_NSLOOKUPRC "/.nslookuprc" +#define _PATH_PAGERCMD "more" + +#ifndef _PATH_HELPFILE +#if defined(BSD) && BSD >= 198810 +#define _PATH_HELPFILE "/usr/share/misc/nslookup.help" +#else +#define _PATH_HELPFILE "/usr/lib/nslookup.help" +#endif +#endif + diff --git a/contrib/bind/bin/nslookup/res.h b/contrib/bind/bin/nslookup/res.h new file mode 100644 index 0000000..cffbe3c --- /dev/null +++ b/contrib/bind/bin/nslookup/res.h @@ -0,0 +1,183 @@ +/* + * ++Copyright++ 1985, 1989 + * - + * 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. + * - + * 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-- + */ + +/* + * @(#)res.h 5.10 (Berkeley) 6/1/90 + * $Id: res.h,v 8.4 1996/12/04 09:38:59 vixie Exp $ + */ + +/* + ******************************************************************************* + * + * res.h -- + * + * Definitions used by modules of the name server lookup program. + * + * Copyright (c) 1985 + * Andrew Cherenson + * U.C. Berkeley + * CS298-26 Fall 1985 + * + ******************************************************************************* + */ + +#define TRUE 1 +#define FALSE 0 +typedef int Boolean; + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define MAXDOMAINS 35 +#define MAXSERVERS 10 + +/* + * Define return statuses in addtion to the ones defined in namserv.h + * let SUCCESS be a synonym for NOERROR + * + * TIME_OUT - a socket connection timed out. + * NO_INFO - the server didn't find any info about the host. + * ERROR - one of the following types of errors: + * dn_expand, res_mkquery failed + * bad command line, socket operation failed, etc. + * NONAUTH - the server didn't have the desired info but + * returned the name(s) of some servers who should. + * NO_RESPONSE - the server didn't respond. + * + */ + +#define SUCCESS 0 +#define TIME_OUT -1 +#define NO_INFO -2 +#define ERROR -3 +#define NONAUTH -4 +#define NO_RESPONSE -5 + +/* + * Define additional options for the resolver state structure. + * + * RES_DEBUG2 more verbose debug level + */ + +#define RES_DEBUG2 0x80000000 + +/* + * Maximum length of server, host and file names. + */ + +#define NAME_LEN 256 + + +/* + * Modified struct hostent from <netdb.h> + * + * "Structures returned by network data base library. All addresses + * are supplied in host order, and returned in network order (suitable + * for use in system calls)." + */ + +typedef struct { + char *name; /* official name of host */ + char **domains; /* domains it serves */ + char **addrList; /* list of addresses from name server */ +} ServerInfo; + +typedef struct { + char *name; /* official name of host */ + char **aliases; /* alias list */ + char **addrList; /* list of addresses from name server */ + int addrType; /* host address type */ + int addrLen; /* length of address */ + ServerInfo **servers; +} HostInfo; + + +/* + * FilePtr is used for directing listings to a file. + * It is global so the Control-C handler can close it. + */ + +extern FILE *filePtr; + +/* + * TCP/UDP port of server. + */ +extern unsigned short nsport; + +/* + * External routines: + */ + +/* XXX need prototypes */ +extern Boolean IsAddr(); +void Print_query(const u_char *msg, const u_char *eom, int printHeader); +void Fprint_query(const u_char *msg, const u_char *eom, int printHeader, + FILE *file); +const u_char *Print_cdname(const u_char *cp, const u_char *msg, + const u_char *eom, FILE *file); +const u_char *Print_cdname2(const u_char *cp, const u_char *msg, + const u_char *eom, FILE *file); +const u_char *Print_rr(const u_char *ocp, const u_char *msg, + const u_char *eom, FILE *file); +extern const char *DecodeType(); /* descriptive version of p_type */ +extern const char *DecodeError(); +extern char *Calloc(); +extern char *Malloc(); +extern void NsError(); +extern void PrintServer(); +extern void PrintHostInfo(); +extern void ShowOptions(); +extern void FreeHostInfoPtr(); +extern FILE *OpenFile(); +extern char *res_skip(); diff --git a/contrib/bind/bin/nslookup/send.c b/contrib/bind/bin/nslookup/send.c new file mode 100644 index 0000000..e9ca590 --- /dev/null +++ b/contrib/bind/bin/nslookup/send.c @@ -0,0 +1,414 @@ +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)send.c 5.18 (Berkeley) 3/2/91"; +static char rcsid[] = "$Id: send.c,v 8.6 1997/05/21 19:49:58 halley Exp $"; +#endif /* not lint */ + +/* + ****************************************************************************** + * + * send.c -- + * + * Routine to send request packets to a name server. + * + * Based on "@(#)res_send.c 6.25 (Berkeley) 6/1/90". + * + ****************************************************************************** + */ + + +/* + * Send query to name server and wait for reply. + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <resolv.h> +#include <stdio.h> +#include <unistd.h> + +#include "port_after.h" + +#include "res.h" + +static int s = -1; /* socket used for communications */ + + +#ifndef FD_SET +#define NFDBITS 32 +#define FD_SETSIZE 32 +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) memset((p), 0, sizeof(*(p))) +#endif + + + +unsigned short nsport = NAMESERVER_PORT; + + + +/* + ****************************************************************************** + * + * SendRequest -- + * + * Sends a request packet to a name server whose address + * is specified by the first argument and returns with + * the answer packet. + * + * Results: + * SUCCESS - the request was sent and an answer + * was received. + * TIME_OUT - the virtual circuit connection timed-out + * or a reply to a datagram wasn't received. + * + * + ****************************************************************************** + */ + +int +SendRequest(struct in_addr *nsAddrPtr, const u_char *buf, int buflen, + u_char *answer, u_int anslen, int *trueLenPtr) +{ + int n, try, v_circuit, resplen, salen; + int gotsomewhere = 0, connected = 0; + int connreset = 0; + u_short id, len; + u_char *cp; + fd_set dsmask; + struct timeval timeout; + const HEADER *hp = (HEADER *) buf; + HEADER *anhp = (HEADER *) answer; + struct iovec iov[2]; + int terrno = ETIMEDOUT; + char junk[512]; + struct sockaddr_in sin, sa; + + if (_res.options & RES_DEBUG2) { + printf("------------\nSendRequest(), len %d\n", buflen); + Print_query(buf, buf + buflen, 1); + } + sin.sin_family = AF_INET; + sin.sin_port = htons(nsport); + sin.sin_addr = *nsAddrPtr; + v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; + id = hp->id; + /* + * Send request, RETRY times, or until successful + */ + for (try = 0; try < _res.retry; try++) { + usevc: + if (v_circuit) { + int truncated = 0; + + /* + * Use virtual circuit; + * at most one attempt per server. + */ + try = _res.retry; + if (s < 0) { + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + terrno = errno; + if (_res.options & RES_DEBUG) + perror("socket (vc) failed"); + continue; + } + if (connect(s, (struct sockaddr *)&sin, + sizeof(struct sockaddr)) < 0) { + terrno = errno; + if (_res.options & RES_DEBUG) + perror("connect failed"); + (void) close(s); + s = -1; + continue; + } + } + /* + * Send length & message + */ + __putshort(buflen, (u_char *)&len); + iov[0].iov_base = (caddr_t)&len; + iov[0].iov_len = INT16SZ; + iov[1].iov_base = (caddr_t)buf; + iov[1].iov_len = buflen; + if (writev(s, iov, 2) != INT16SZ + buflen) { + terrno = errno; + if (_res.options & RES_DEBUG) + perror("write failed"); + (void) close(s); + s = -1; + continue; + } + /* + * Receive length & response + */ + cp = answer; + len = INT16SZ; + while ((n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) <= 0) + break; + } + if (n <= 0) { + terrno = errno; + if (_res.options & RES_DEBUG) + perror("read failed"); + (void) close(s); + s = -1; + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (terrno == ECONNRESET && !connreset) { + connreset = 1; + } + continue; + } + cp = answer; + if ((resplen = ns_get16((u_char*)cp)) > anslen) { + if (_res.options & RES_DEBUG) + fprintf(stderr, "response truncated\n"); + len = anslen; + truncated = 1; + } else + len = resplen; + while (len != 0 && + (n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + len -= n; + } + if (n <= 0) { + terrno = errno; + if (_res.options & RES_DEBUG) + perror("read failed"); + (void) close(s); + s = -1; + continue; + } + if (truncated) { + /* + * Flush rest of answer + * so connection stays in synch. + */ + anhp->tc = 1; + len = resplen - anslen; + while (len != 0) { + n = (len > sizeof(junk) ? + sizeof(junk) : len); + if ((n = read(s, junk, n)) > 0) + len -= n; + else + break; + } + } + } else { + /* + * Use datagrams. + */ + if (s < 0) { + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + terrno = errno; + if (_res.options & RES_DEBUG) + perror("socket (dg) failed"); + continue; + } + } +#if BSD >= 43 + if (connected == 0) { + if (connect(s, (struct sockaddr *)&sin, + sizeof sin) < 0) { + if (_res.options & RES_DEBUG) + perror("connect"); + continue; + } + connected = 1; + } + if (send(s, buf, buflen, 0) != buflen) { + if (_res.options & RES_DEBUG) + perror("send"); + continue; + } +#else /* BSD */ + if (sendto(s, (const char *)buf, buflen, 0, + (struct sockaddr *) &sin, + sizeof sin) != buflen) { + if (_res.options & RES_DEBUG) + perror("sendto"); + continue; + } +#endif + + /* + * Wait for reply + */ + timeout.tv_sec = (_res.retrans << try); + if (timeout.tv_sec <= 0) + timeout.tv_sec = 1; + timeout.tv_usec = 0; + wait: + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + n = select(s+1, &dsmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout); + if (n < 0) { + if (_res.options & RES_DEBUG) + perror("select"); + continue; + } + if (n == 0) { + /* + * timeout + */ + if (_res.options & RES_DEBUG) + printf("timeout\n"); +#if BSD >= 43 + gotsomewhere = 1; +#endif + continue; + } + + salen = sizeof sa; + resplen = recvfrom(s, (char *)answer, anslen, 0, + (struct sockaddr *)&sa, &salen); + if (resplen <= 0) { + if (_res.options & RES_DEBUG) + perror("recvfrom"); + continue; + } + gotsomewhere = 1; + if (id != anhp->id) { + /* + * response from old query, ignore it + */ + if (_res.options & RES_DEBUG2) { + printf("------------\nOld answer:\n"); + Print_query(answer, answer+resplen, 1); + } + goto wait; + } + if (!(_res.options & RES_IGNTC) && anhp->tc) { + /* + * get rest of answer; + * use TCP with same server. + */ + if (_res.options & RES_DEBUG) + printf("truncated answer\n"); + (void) close(s); + s = -1; + v_circuit = 1; + goto usevc; + } + } + if (_res.options & RES_DEBUG) { + if (_res.options & RES_DEBUG2) + printf("------------\nGot answer (%d bytes):\n", + resplen); + else + printf("------------\nGot answer:\n"); + Print_query(answer, answer+resplen, 1); + } + (void) close(s); + s = -1; + *trueLenPtr = resplen; + return (SUCCESS); + } + if (s >= 0) { + (void) close(s); + s = -1; + } + if (v_circuit == 0) + if (gotsomewhere == 0) + return NO_RESPONSE; /* no nameservers found */ + else + return TIME_OUT; /* no answer obtained */ + else + if (errno == ECONNREFUSED) + return NO_RESPONSE; + else + return ERROR; +} + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. + * + * Called from the interrupt handler. + */ +void SendRequest_close() +{ + if (s != -1) { + (void) close(s); + s = -1; + } +} diff --git a/contrib/bind/bin/nslookup/skip.c b/contrib/bind/bin/nslookup/skip.c new file mode 100644 index 0000000..0290d98 --- /dev/null +++ b/contrib/bind/bin/nslookup/skip.c @@ -0,0 +1,218 @@ +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)skip.c 5.12 (Berkeley) 3/21/91"; +static char rcsid[] = "$Id: skip.c,v 8.4 1997/04/25 00:27:19 vixie Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * skip.c -- + * + * Routines to skip over portions of a query buffer. + * + * Note: this file has been submitted for inclusion in + * BIND resolver library. When this has been done, this file + * is no longer necessary (assuming there haven't been any + * changes). + * + * Adapted from 4.3BSD BIND res_debug.c + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <resolv.h> +#include <stdio.h> + +#include "port_after.h" + +char *res_skip_rr(); + + +/* + ******************************************************************************* + * + * res_skip -- + * + * Skip the contents of a query. + * + * Interpretation of numFieldsToSkip argument: + * res_skip returns pointer to: + * 1 -> start of question records. + * 2 -> start of authoritative answer records. + * 3 -> start of additional records. + * 4 -> first byte after end of additional records. + * + * Results: + * (address) - success operation. + * NULL - a resource record had an incorrect format. + * + ******************************************************************************* + */ + +char * +res_skip(msg, numFieldsToSkip, eom) + char *msg; + int numFieldsToSkip; + char *eom; +{ + register char *cp; + register HEADER *hp; + register int tmp; + register int n; + + /* + * Skip the header fields. + */ + hp = (HEADER *)msg; + cp = msg + HFIXEDSZ; + + /* + * skip question records. + */ + n = ntohs(hp->qdcount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + tmp = dn_skipname((u_char *)cp, (u_char *)eom); + if (tmp == -1) return(NULL); + cp += tmp; + cp += INT16SZ; /* type */ + cp += INT16SZ; /* class */ + } + } + if (--numFieldsToSkip <= 0) return(cp); + + /* + * skip authoritative answer records + */ + n = ntohs(hp->ancount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + cp = res_skip_rr(cp, eom); + if (cp == NULL) return(NULL); + } + } + if (--numFieldsToSkip == 0) return(cp); + + /* + * skip name server records + */ + n = ntohs(hp->nscount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + cp = res_skip_rr(cp, eom); + if (cp == NULL) return(NULL); + } + } + if (--numFieldsToSkip == 0) return(cp); + + /* + * skip additional records + */ + n = ntohs(hp->arcount); + if (n > 0) { + while (--n >= 0 && cp < eom) { + cp = res_skip_rr(cp, eom); + if (cp == NULL) return(NULL); + } + } + + return(cp); +} + + +/* + ******************************************************************************* + * + * res_skip_rr -- + * + * Skip over resource record fields. + * + * Results: + * (address) - success operation. + * NULL - a resource record had an incorrect format. + ******************************************************************************* + */ + +char * +res_skip_rr(cp, eom) + char *cp; + char *eom; +{ + int tmp; + int dlen; + + if ((tmp = dn_skipname((u_char *)cp, (u_char *)eom)) == -1) + return (NULL); /* compression error */ + cp += tmp; + if ((cp + RRFIXEDSZ) > eom) + return (NULL); + cp += INT16SZ; /* type */ + cp += INT16SZ; /* class */ + cp += INT32SZ; /* ttl */ + dlen = ns_get16((u_char*)cp); + cp += INT16SZ; /* dlen */ + cp += dlen; + if (cp > eom) + return (NULL); + return (cp); +} diff --git a/contrib/bind/bin/nslookup/subr.c b/contrib/bind/bin/nslookup/subr.c new file mode 100644 index 0000000..cefc2eb --- /dev/null +++ b/contrib/bind/bin/nslookup/subr.c @@ -0,0 +1,475 @@ +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)subr.c 5.24 (Berkeley) 3/2/91"; +static char rcsid[] = "$Id: subr.c,v 8.9 1997/04/25 00:27:19 vixie Exp $"; +#endif /* not lint */ + +/* + ******************************************************************************* + * + * subr.c -- + * + * Miscellaneous subroutines for the name server + * lookup program. + * + * Copyright (c) 1985 + * Andrew Cherenson + * U.C. Berkeley + * CS298-26 Fall 1985 + * + ******************************************************************************* + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <netdb.h> +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#include "resolv.h" +#include "res.h" + +/* + ******************************************************************************* + * + * IntrHandler -- + * + * This routine is called whenever a control-C is typed. + * It performs three main functions: + * - closes an open socket connection, + * - closes an open output file (used by LookupHost, et al.), + * - jumps back to the main read-eval loop. + * + * If a user types a ^C in the middle of a routine that uses a socket, + * the routine would not be able to close the socket. To prevent an + * overflow of the process's open file table, the socket and output + * file descriptors are closed by the interrupt handler. + * + * Side effects: + * Open file descriptors are closed. + * If filePtr is valid, it is closed. + * Flow of control returns to the main() routine. + * + ******************************************************************************* + */ + +SIG_FN +IntrHandler() +{ + extern jmp_buf env; +#if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) && !defined(__osf__) + extern FILE *yyin; /* scanner input file */ + extern void yyrestart(); /* routine to restart scanner after interrupt */ +#endif + + SendRequest_close(); + ListHost_close(); + if (filePtr != NULL && filePtr != stdout) { + fclose(filePtr); + filePtr = NULL; + } + printf("\n"); +#if defined(BSD) && BSD >= 199006 && !defined(RISCOS_BSD) && !defined(__osf__) + yyrestart(yyin); +#endif + longjmp(env, 1); +} + + +/* + ******************************************************************************* + * + * Malloc -- + * Calloc -- + * + * Calls the malloc library routine with SIGINT blocked to prevent + * corruption of malloc's data structures. We need to do this because + * a control-C doesn't kill the program -- it causes a return to the + * main command loop. + * + * NOTE: This method doesn't prevent the pointer returned by malloc + * from getting lost, so it is possible to get "core leaks". + * + * If malloc fails, the program exits. + * + * Results: + * (address) - address of new buffer. + * + ******************************************************************************* + */ + +char * +Malloc(size) + int size; +{ + char *ptr; + +#ifdef SYSV +#if defined(SVR3) || defined(SVR4) + sighold(SIGINT); + ptr = malloc((unsigned) size); + sigrelse(SIGINT); +#else + { SIG_FN (*old)(); + old = signal(SIGINT, SIG_IGN); + ptr = malloc((unsigned) size); + signal(SIGINT, old); + } +#endif +#else +#ifdef POSIX_SIGNALS + { sigset_t sset; + sigemptyset(&sset); + sigaddset(&sset,SIGINT); + sigprocmask(SIG_BLOCK,&sset,NULL); + ptr = malloc((unsigned) size); + sigprocmask(SIG_UNBLOCK,&sset,NULL); + } +#else + { int saveMask; + saveMask = sigblock(sigmask(SIGINT)); + ptr = malloc((unsigned) size); + (void) sigsetmask(saveMask); + } +#endif +#endif + if (ptr == NULL) { + fflush(stdout); + fprintf(stderr, "*** Can't allocate memory\n"); + fflush(stderr); + abort(); + /*NOTREACHED*/ + } else { + return(ptr); + } +} + +char * +Calloc(num, size) + register int num, size; +{ + char *ptr = Malloc(num*size); + memset(ptr, 0, num*size); + return(ptr); +} + + +/* + ******************************************************************************* + * + * PrintHostInfo -- + * + * Prints out the HostInfo structure for a host. + * + ******************************************************************************* + */ + +void +PrintHostInfo(file, title, hp) + FILE *file; + char *title; + register HostInfo *hp; +{ + register char **cp; + register ServerInfo **sp; + char comma; + int i; + + fprintf(file, "%-7s %s", title, hp->name); + + if (hp->addrList != NULL) { + if (hp->addrList[1] != NULL) { + fprintf(file, "\nAddresses:"); + } else { + fprintf(file, "\nAddress:"); + } + comma = ' '; + i = 0; + for (cp = hp->addrList; cp && *cp; cp++) { + i++; + if (i > 4) { + fprintf(file, "\n\t"); + comma = ' '; + i = 0; + } + fprintf(file,"%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); + comma = ','; + } + } + + if (hp->aliases != NULL) { + fprintf(file, "\nAliases:"); + comma = ' '; + i = 10; + for (cp = hp->aliases; cp && *cp && **cp; cp++) { + i += strlen(*cp) + 2; + if (i > 75) { + fprintf(file, "\n\t"); + comma = ' '; + i = 10; + } + fprintf(file, "%c %s", comma, *cp); + comma = ','; + } + } + + if (hp->servers != NULL) { + fprintf(file, "\nServed by:\n"); + for (sp = hp->servers; *sp != NULL ; sp++) { + + fprintf(file, "- %s\n\t", (*sp)->name); + + comma = ' '; + i = 0; + for (cp = (*sp)->addrList; cp && *cp && **cp; cp++) { + i++; + if (i > 4) { + fprintf(file, "\n\t"); + comma = ' '; + i = 0; + } + fprintf(file, + "%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); + comma = ','; + } + fprintf(file, "\n\t"); + + comma = ' '; + i = 10; + for (cp = (*sp)->domains; cp && *cp && **cp; cp++) { + i += strlen(*cp) + 2; + if (i > 75) { + fprintf(file, "\n\t"); + comma = ' '; + i = 10; + } + fprintf(file, "%c %s", comma, *cp); + comma = ','; + } + fprintf(file, "\n"); + } + } + + fprintf(file, "\n\n"); +} + +/* + ******************************************************************************* + * + * OpenFile -- + * + * Parses a command string for a file name and opens + * the file. + * + * Results: + * file pointer - the open was successful. + * NULL - there was an error opening the file or + * the input string was invalid. + * + ******************************************************************************* + */ + +FILE * +OpenFile(string, file) + char *string; + char *file; +{ + char *redirect; + FILE *tmpPtr; + + /* + * Open an output file if we see '>' or >>'. + * Check for overwrite (">") or concatenation (">>"). + */ + + redirect = strchr(string, '>'); + if (redirect == NULL) { + return(NULL); + } + if (redirect[1] == '>') { + sscanf(redirect, ">> %s", file); + tmpPtr = fopen(file, "a+"); + } else { + sscanf(redirect, "> %s", file); + tmpPtr = fopen(file, "w"); + } + + if (tmpPtr != NULL) { + redirect[0] = '\0'; + } + + return(tmpPtr); +} + +/* + ******************************************************************************* + * + * DecodeError -- + * + * Converts an error code into a character string. + * + ******************************************************************************* + */ + +const struct res_sym error_syms[] = { + { NOERROR, "Success" }, + { FORMERR, "Format error" }, + { SERVFAIL, "Server failed" }, + { NXDOMAIN, "Non-existent host/domain" }, + { NOTIMP, "Not implemented" }, + { REFUSED, "Query refused" }, +#ifdef NOCHANGE + { NOCHANGE, "No change" }, +#endif + { TIME_OUT, "Timed out" }, + { NO_INFO, "No information" }, + { ERROR, "Unspecified error" }, + { NONAUTH, "Non-authoritative answer" }, + { NO_RESPONSE, "No response from server" }, + { 0, NULL } +}; + +const char * +DecodeError(result) + int result; +{ + const char *string; + int success; + + string = sym_ntos(error_syms, result, &success); + if (success) + return string; + return ("BAD ERROR VALUE"); +} + + +int +StringToClass(class, dflt, errorfile) + char *class; + int dflt; + FILE *errorfile; +{ + int result, success; + + result = sym_ston(__p_class_syms, class, &success); + if (success) + return result; + + if (errorfile) + fprintf(errorfile, "unknown query class: %s\n", class); + return(dflt); +} + + +/* + ******************************************************************************* + * + * StringToType -- + * + * Converts a string form of a query type name to its + * corresponding integer value. + * + ******************************************************************************* + */ + +int +StringToType(type, dflt, errorfile) + char *type; + int dflt; + FILE *errorfile; +{ + int result, success; + + result = sym_ston(__p_type_syms, type, &success); + if (success) + return (result); + + if (errorfile) + fprintf(errorfile, "unknown query type: %s\n", type); + return (dflt); +} + +/* + ******************************************************************************* + * + * DecodeType -- + * + * Converts a query type to a descriptive name. + * (A more verbose form of p_type.) + * + * + ******************************************************************************* + */ + +const char * +DecodeType(type) + int type; +{ + + return (sym_ntop(__p_type_syms, type, (int *)0)); +} diff --git a/contrib/bind/bin/nsupdate/Makefile b/contrib/bind/bin/nsupdate/Makefile new file mode 100644 index 0000000..46806b6 --- /dev/null +++ b/contrib/bind/bin/nsupdate/Makefile @@ -0,0 +1,79 @@ +## Copyright (c) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# $Id: Makefile,v 8.18 1997/06/19 03:22:11 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s + +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +PROG= nsupdate +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep -p ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/nsupdate/nsupdate.c b/contrib/bind/bin/nsupdate/nsupdate.c new file mode 100644 index 0000000..2b31716 --- /dev/null +++ b/contrib/bind/bin/nsupdate/nsupdate.c @@ -0,0 +1,471 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: nsupdate.c,v 8.5 1998/02/14 20:54:48 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "port_before.h" +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "port_after.h" + +/* XXX all of this stuff should come from libbind.a */ + +/* + * Map class and type names to number + */ +struct map { + char token[10]; + int val; +}; + +struct map class_strs[] = { + { "in", C_IN }, + { "chaos", C_CHAOS }, + { "hs", C_HS }, +}; +#define M_CLASS_CNT (sizeof(class_strs) / sizeof(struct map)) + +struct map type_strs[] = { + { "a", T_A }, + { "ns", T_NS }, + { "cname", T_CNAME }, + { "soa", T_SOA }, + { "mb", T_MB }, + { "mg", T_MG }, + { "mr", T_MR }, + { "null", T_NULL }, + { "wks", T_WKS }, + { "ptr", T_PTR }, + { "hinfo", T_HINFO }, + { "minfo", T_MINFO }, + { "mx", T_MX }, + { "txt", T_TXT }, + { "rp", T_RP }, + { "afsdb", T_AFSDB }, + { "x25", T_X25 }, + { "isdn", T_ISDN }, + { "rt", T_RT }, + { "nsap", T_NSAP }, + { "nsap_ptr", T_NSAP_PTR }, + { "px", T_PX }, + { "loc", T_LOC }, +}; +#define M_TYPE_CNT (sizeof(type_strs) / sizeof(struct map)) + +struct map section_strs[] = { + { "zone", S_ZONE }, + { "prereq", S_PREREQ }, + { "update", S_UPDATE }, + { "reserved", S_ADDT }, +}; +#define M_SECTION_CNT (sizeof(section_strs) / sizeof(struct map)) + +struct map opcode_strs[] = { + { "nxdomain", NXDOMAIN }, + { "yxdomain", YXDOMAIN }, + { "nxrrset", NXRRSET }, + { "yxrrset", YXRRSET }, + { "delete", DELETE }, + { "add", ADD }, +}; +#define M_OPCODE_CNT (sizeof(opcode_strs) / sizeof(struct map)) + +static char *progname; +static FILE *log; + +static void usage(void); +static int getword_str(char *, int, char **, char *); + +/* + * format of file read by nsupdate is kept the same as the log + * file generated by updates, so that the log file can be fed + * to nsupdate to reconstruct lost updates. + * + * file is read on line at a time using fgets() rather than + * one word at a time using getword() so that it is easy to + * adapt nsupdate to read piped input from other scripts + * + * overloading of class/type has to be deferred to res_update() + * because class is needed by res_update() to determined the + * zone to which a resource record belongs + */ +int +main(argc, argv) + int argc; + char **argv; +{ + FILE *fp = NULL; + char buf[BUFSIZ], buf2[BUFSIZ], hostbuf[100], filebuf[100]; + char dnbuf[MAXDNAME]; + u_char packet[PACKETSZ], answer[PACKETSZ]; + char *host = hostbuf, *batchfile = filebuf; + char *r_dname, *cp, *startp, *endp, *svstartp; + char section[15], opcode[10]; + int i, c, n, n1, inside, lineno = 0, vc = 0, + debug = 0, r_size, r_section, r_opcode, + prompt = 0, ret = 0; + int16_t r_class, r_type; + u_int32_t r_ttl; + struct map *mp; + ns_updrec *rrecp_start = NULL, *rrecp, *tmprrecp; + struct in_addr hostaddr; + extern int getopt(); + extern char *optarg; + extern int optind, opterr, optopt; + + + progname = argv[0]; + + while ((c = getopt(argc, argv, "dv")) != EOF) { + switch (c) { + case 'v': + vc = 1; + break; + case 'd': + debug = 1; + break; + default: + usage(); + } + } + + if ((argc - optind) == 0) { + /* no file specified, read from stdin */ + ret = system("tty -s"); + if (ret == 0) /* terminal */ + prompt = 1; + else /* stdin redirect from a file or a pipe */ + prompt = 0; + } else { + /* file specified, open it */ + /* XXX - currently accepts only one filename */ + if ((fp = fopen(argv[optind], "r")) == NULL) { + fprintf(stderr, "error opening file: %s\n", argv[optind]); + exit (1); + } + } + for (;;) { + + inside = 1; + if (prompt) + fprintf(stdout, "> "); + if (!fp) + cp = fgets(buf, sizeof buf, stdin); + else + cp = fgets(buf, sizeof buf, fp); + if (cp == NULL) /* EOF */ + break; + lineno++; + + /* get rid of the trailing newline */ + n = strlen(buf); + buf[--n] = '\0'; + + startp = cp; + endp = strchr(cp, ';'); + if (endp != NULL) + endp--; + else + endp = cp + n - 1; + + /* verify section name */ + if (!getword_str(section, sizeof section, &startp, endp)) { + /* empty line */ + inside = 0; + } + if (inside) { + /* inside the same update packet, + * continue accumulating records */ + r_section = -1; + n1 = strlen(section); + if (section[n1-1] == ':') + section[--n1] = '\0'; + for (mp = section_strs; mp < section_strs+M_SECTION_CNT; mp++) + if (!strcasecmp(section, mp->token)) { + r_section = mp->val; + break; + } + if (r_section == -1) { + fprintf(stderr, "incorrect section name: %s\n", section); + exit (1); + } + if (r_section == S_ZONE) { + fprintf(stderr, "section ZONE not permitted\n"); + exit (1); + } + /* read operation code */ + if (!getword_str(opcode, sizeof opcode, &startp, endp)) { + fprintf(stderr, "failed to read operation code\n"); + exit (1); + } + r_opcode = -1; + if (opcode[0] == '{') { + n1 = strlen(opcode); + for (i = 0; i < n1; i++) + opcode[i] = opcode[i+1]; + if (opcode[n1-2] == '}') + opcode[n1-2] = '\0'; + } + for (mp = opcode_strs; mp < opcode_strs+M_OPCODE_CNT; mp++) { + if (!strcasecmp(opcode, mp->token)) { + r_opcode = mp->val; + break; + } + } + if (r_opcode == -1) { + fprintf(stderr, "incorrect operation code: %s\n", opcode); + exit (1); + } + /* read owner's domain name */ + if (!getword_str(dnbuf, sizeof dnbuf, &startp, endp)) { + fprintf(stderr, "failed to read owner name\n"); + exit (1); + } + r_dname = dnbuf; + r_ttl = 0; + r_type = -1; + r_class = C_IN; /* default to IN */ + r_size = 0; + + (void) getword_str(buf2, sizeof buf2, &startp, endp); + + if (isdigit(buf2[0])) { /* ttl */ + r_ttl = strtoul(buf2, 0, 10); + if (errno == ERANGE && r_ttl == ULONG_MAX) { + fprintf(stderr, "oversized ttl: %s\n", buf2); + exit (1); + } + (void) getword_str(buf2, sizeof buf2, &startp, endp); + } + + if (buf2[0]) { /* possibly class */ + for (mp = class_strs; mp < class_strs+M_CLASS_CNT; mp++) { + if (!strcasecmp(buf2, mp->token)) { + r_class = mp->val; + (void) getword_str(buf2, sizeof buf2, &startp, endp); + break; + } + } + } + /* + * type and rdata field may or may not be required depending + * on the section and operation + */ + switch (r_section) { + case S_PREREQ: + if (r_ttl) { + fprintf(stderr, "nonzero ttl in prereq section: %ul\n", + r_ttl); + r_ttl = 0; + } + switch (r_opcode) { + case NXDOMAIN: + case YXDOMAIN: + if (buf2[0]) { + fprintf (stderr, "invalid field: %s, ignored\n", + buf2); + exit (1); + } + break; + case NXRRSET: + case YXRRSET: + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + break; + } + if (r_type == -1) { + fprintf (stderr, "invalid type for RRset: %s\n", + buf2); + exit (1); + } + if (r_opcode == NXRRSET) + break; + /* + * for RRset exists (value dependent) case, + * nonempty rdata field will be present. + * simply copy the whole string now and let + * res_update() interpret the various fields + * depending on type + */ + cp = startp; + while (cp <= endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + break; + default: + fprintf (stderr, + "unknown operation in prereq section\"%s\"\n", + opcode); + exit (1); + } + break; + case S_UPDATE: + switch (r_opcode) { + case DELETE: + r_ttl = 0; + r_type = T_ANY; + /* read type, if specified */ + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + svstartp = startp; + (void) getword_str(buf2, sizeof buf2, + &startp, endp); + if (buf2[0]) /* unget preference */ + startp = svstartp; + break; + } + /* read rdata portion, if specified */ + cp = startp; + while (cp <= endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + break; + case ADD: + if (r_ttl == 0) { + fprintf (stderr, + "ttl must be specified for record to be added: %s\n", buf); + exit (1); + } + /* read type */ + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + break; + } + if (r_type == -1) { + fprintf(stderr, + "invalid type for record to be added: %s\n", buf2); + exit (1); + } + /* read rdata portion */ + cp = startp; + while (cp < endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + if (r_size <= 0) { + fprintf(stderr, + "nonempty rdata field needed to add the record at line %d\n", + lineno); + exit (1); + } + break; + default: + fprintf(stderr, + "unknown operation in update section\"%s\"\n", opcode); + exit (1); + } + break; + default: + fprintf(stderr, + "unknown section identifier \"%s\"\n", section); + exit (1); + } + + if ( !(rrecp = res_mkupdrec(r_section, r_dname, r_class, + r_type, r_ttl)) || + (r_size > 0 && !(rrecp->r_data = (u_char *)malloc(r_size))) ) { + fprintf(stderr, "saverrec error\n"); + exit (1); + } + rrecp->r_opcode = r_opcode; + rrecp->r_size = r_size; + (void) strncpy((char *)rrecp->r_data, cp, r_size); + /* append current record to the end of linked list of + * records seen so far */ + if (rrecp_start == NULL) + rrecp_start = rrecp; + else { + tmprrecp = rrecp_start; + while (tmprrecp->r_next != NULL) + tmprrecp = tmprrecp->r_next; + tmprrecp->r_next = rrecp; + } + } else { /* end of an update packet */ + (void) res_init(); + if (vc) + _res.options |= RES_USEVC | RES_STAYOPEN; + if (debug) + _res.options |= RES_DEBUG; + if (rrecp_start) { + if ((n = res_update(rrecp_start)) < 0) + fprintf(stderr, "failed update packet\n"); + /* free malloc'ed memory */ + while(rrecp_start) { + tmprrecp = rrecp_start; + rrecp_start = rrecp_start->r_next; + free((char *)tmprrecp->r_dname); + free((char *)tmprrecp); + } + } + } + } /* for */ + return (0); +} + +static void +usage() { + fprintf(stderr, "Usage: %s [-d] [-v] [file]\n", + progname); + exit(1); +} + +/* + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, char **startpp, char *endp) { + char *cp; + int c; + + for (cp = buf; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (cp != buf) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + (*startpp)++; + if (cp >= buf+size-1) + break; + *cp++ = (u_char)c; + } + *cp = '\0'; + return (cp != buf); +} diff --git a/contrib/bind/doc/bog/00title.me b/contrib/bind/doc/bog/00title.me index c9e708c..be95d8b 100644 --- a/contrib/bind/doc/bog/00title.me +++ b/contrib/bind/doc/bog/00title.me @@ -57,7 +57,7 @@ .b "Name Server Operations Guide" .b "for \s-1BIND\s+1" .sz -\fIRelease 4.9.5\fP +\fIRelease 4.9.3\fP .eh 'SMM:10-%''Name Server Operations Guide for \s-1BIND\s+1' .oh 'Name Server Operations Guide for \s-1BIND\s+1''\s-1SMM\s+1:10-%' .sp diff --git a/contrib/bind/doc/bog/Makefile b/contrib/bind/doc/bog/Makefile index 32456a0..09e1908 100644 --- a/contrib/bind/doc/bog/Makefile +++ b/contrib/bind/doc/bog/Makefile @@ -62,9 +62,6 @@ ME= -me NROFF= nroff -rb3 PRINTER= -Pdp TBL= dtbl $(PRINTER) -# For Linux: -#PRINTER= -#TBL= tbl $(PRINTER) TROFF= ditroff $(PRINTER) GROFF= groff -Tps -t $(ME) @@ -84,7 +81,6 @@ cat: $(FILES) clean: rm -f *.psf *.lst *.BAK *.CKP *~ *.orig - rm -f file spell: $(FILES) @for i in $(FILES); do \ diff --git a/contrib/bind/doc/bog/files.me b/contrib/bind/doc/bog/files.me index b630eea..ae755ff 100644 --- a/contrib/bind/doc/bog/files.me +++ b/contrib/bind/doc/bog/files.me @@ -543,7 +543,7 @@ resolver variable. Supported options at this time are: sets the \s-1RES_DEBUG\s+1 bit in \fB_res.options\fP. .ip \fBndots:\fP\fIn\fP sets the lower threshold (measured in ``number of dots'') on names given to -\fIres_query\fP() such that names with at least this number of dots will be +\fIres_query\fP() such that names with more than this number of dots will be tried as absolute names before any \fIlocal-domain\fP or \fIsearch-list\fP processing is done. The default for this internal variable is ``1''. .\" .pp @@ -1046,10 +1046,6 @@ recognize it. .sh 2 "Discussion about the TTL" .pp -The use of different Time To Live fields with in a RRset have been -deprecated and this is enforced by the server when loading a primary -zone. See the Security section for more discussion of differing TTLs. -.pp The Time To Live assigned to the records and to the zone via the Minimum field in the SOA record is very important. High values will lead to lower BIND network traffic and faster response time. Lower diff --git a/contrib/bind/doc/bog/ns.me b/contrib/bind/doc/bog/ns.me index b507e94..ec3ca3c 100644 --- a/contrib/bind/doc/bog/ns.me +++ b/contrib/bind/doc/bog/ns.me @@ -1,3 +1,5 @@ +.\" ++Copyright++ 1986, 1988 +.\" - .\" Copyright (c) 1986, 1988 .\" The Regents of the University of California. All rights reserved. .\" @@ -46,6 +48,8 @@ .\" PROFITS, WHETHER 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-- .\" .\" @(#)ns.me 6.3 (Berkeley) 9/19/89 .\" @@ -90,38 +94,3 @@ Berkeley would look as follows: .)b The top level domain for educational organizations is EDU; Berkeley is a subdomain of EDU and monet is the name of the host. -.sh 1 Security -.pp -This section examines some of the know security implications of various -versions of BIND. Some of these have been used to attack the nameservers -in the past. -.sh 2 "Unnecessary Glue" -.pp -Unnecessary glue can lead to incorrect records being loaded into the -server. This can result in connections going to the wrong machines. -.pp -To prevent unnecessary glue being loaded, all the servers of zones being -servered by a server and the servers of the parent zones need to be -upgraded to BIND 4.9.3 or later. -.sh 2 "Insertion of data into a zone that is being servered" -.pp -BIND versions prior to BIND 4.9.2 are subject to the insertion of -resource records into zone that they are serving. -.sh 2 "Denial of Service: Hash Bug Exploit" -.pp -September 1996 saw the COM TLD subject to a denial of service attack by -injecting into the DNS a record with a final label of COM, eight spaces -and COM. This effected BIND 4.9.4 servers. Similar attacks are possible -on BIND 4.9.3 and BIND 4.9.3-P1. -.pp -It is recommend that you run a BIND 4.9.4-P1 or later server to avoid -this exploit. -.sh 2 "Denial of Service: TTL Inconsistency Attacks" -.pp -If you are still using multiple TTL values within a RRset you can be -subject to a denial of service attack. BIND 4.9.5 onwards uses multiple -ttl values within a RRset to reject obviously bad RRset. -.pp -It is recommend that you upgrade to BIND 4.9.5 or later as these server -prevent you loading multiple TTL values and doesn't merge answers received -across the network. diff --git a/contrib/bind/doc/html/acl.html b/contrib/bind/doc/html/acl.html new file mode 100644 index 0000000..cf684b4 --- /dev/null +++ b/contrib/bind/doc/html/acl.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND acl Statement</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide--<CODE>acl</CODE> Statement</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +acl <VAR>name</VAR> { + <VAR><A HREF="address_list.html">address_match_list</A></VAR> +}; +</PRE> + +<HR> + +<A NAME="Usage"><H3>Definition and Usage</H3></A> + +<P>The <CODE>acl</CODE> statement creates a named 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 +<CODE>acl</CODE> before it can be used elsewhere; no forward +references are allowed.</P> + +The following ACLs are built-in: + +<DL> +<DT><CODE>any</CODE> +<DD> +Allows all hosts. + +<DT><CODE>none</CODE> +<DD> +Denies all hosts. + +<DT><CODE>localhost</CODE> +<DD> +Allows the IP addresses of all interfaces on the system. + +<DT><CODE>localnets</CODE> +<DD> +Allows any host on a network for which the system has an interface. +</DL> + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: acl.html,v 1.4 1998/03/21 01:03:10 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/address_list.html b/contrib/bind/doc/html/address_list.html new file mode 100644 index 0000000..894ef04 --- /dev/null +++ b/contrib/bind/doc/html/address_list.html @@ -0,0 +1,87 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND Address Match Lists</TITLE> +</HEAD> +<BODY> + +<H2>BIND Configuration File Guide--Address Match Lists</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +<VAR>address_match_list</VAR> = 1*<VAR>address_match_element</VAR> + +<VAR>address_match_element</VAR> = [ "!" ] (<VAR><A HREF="docdef.html">ip_address</A></VAR> / <VAR><A HREF="docdef.html">ip_prefix</A></VAR> / <VAR><A HREF="acl.html">acl_name</A></VAR> / <VAR>address_match_list</VAR>) ";" +</PRE> + +<HR> + +<A NAME="Usage"><H3>Definition and Usage</H3></A> + +<P>Address match lists are lists of elements. The elements can be any +of the following:</P> + +<UL> +<LI>an IP address (in dotted-decimal notation),</LI> + +<LI>an IP prefix (in the '/'-notation),</LI> + +<LI>the name of an address match list previously defined with +the <A HREF="acl.html"><CODE>acl</CODE></A> statment.</LI> + +<LI>an IP address match list</LI> +</UL> + +<P>The ACLs "any", "none", "localhost" and "localnets" are +predefined. More information can be found in the description of the +<A HREF="acl.html"><CODE>acl</CODE></A> statement. + +<P>Elements can be negated with a leading "!". + +<P>When a given IP address or prefix is compared to an address match +list, the list is traversed in order and the first match (regardless +of negation) is used. The interpretation of a match depends on +whether the list is being used for access control or as a +topology.</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 <CODE>allow-query</CODE>, +<CODE>allow-transfer</CODE> and <CODE>allow-update</CODE> all use +address match lists like this. Similarly, the <CODE>listen-on</CODE> +clause can use negation to define local addresses which should not be +used to accept nameserver connections.</P> + +<P>When used with the <CODE>topology</CODE> clause, a non-negated +match returns a distance based on its postion on the list (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.</P> + +<P>Because of the first-match aspect of the algorithm, 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 <CODE>1.2.3/24; ! 1.2.3.13;</CODE> 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 +<CODE>! 1.2.3.13; 1.2.3/24</CODE> fixes that problem by +having 1.2.3.13 blocked by the negation but all other 1.2.3.* hosts +fall through. + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: address_list.html,v 1.5 1998/03/21 01:03:10 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/comments.html b/contrib/bind/doc/html/comments.html new file mode 100644 index 0000000..8ada6b0 --- /dev/null +++ b/contrib/bind/doc/html/comments.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND Comment Syntax</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide--Comment Syntax</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +/* This is a BIND comment as in C */ + +// This is a BIND comment as in C++ + +# This is a BIND comment as in common Unix shells and perl +</PRE> + +<A NAME="Usage"><H3>Definition and Usage</H3></A> + +<P>Comments may appear anywhere that whitespace may appear in a BIND +configuration file.</P> + +<P>C-style comments start with the two characters <CODE>/*</CODE> +(slash, star) and end with <CODE>*/</CODE> (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 +<CODE>*/</CODE>: + +<PRE> +/* 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>C++-style comments start with the two characters <CODE>//</CODE> +(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 +<CODE>//</CODE> pair. For example: + +<PRE> +// 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>Shell-style (or perl-style, if you prefer) comments start with the +character <CODE>#</CODE> (hash or pound or number or octothorpe or +whatever) and continue to the end of the physical line, like C++ +comments.</P> For example: + +<PRE> +# 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><STRONG>WARNING:</STRONG> you cannot use the <CODE>;</CODE> +(semicolon) character to start a comment such as you would in a zone +file. The semicolon indicates the end of a configuration statement, +so whatever follows it will be interpreted as the start of the next +statement.</P> + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: comments.html,v 1.4 1998/03/21 01:03:11 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/config.html b/contrib/bind/doc/html/config.html new file mode 100644 index 0000000..dd8e0b4 --- /dev/null +++ b/contrib/bind/doc/html/config.html @@ -0,0 +1,83 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND Configuration File Guide</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide</H2> + +<HR> + +<H3>Overview</H3> + +<P>BIND 8 is much more configurable than previous release of BIND. +There are entirely new areas of configuration, such as access control lists +and categorized logging. Many options that previously applied to all zones +can now be used selectively. These features, plus a consideration of future +configuration needs led to the creation of a new configuration file format. + +<H3>The Configuration File</H3> + +<H4><A HREF="example.html">Example Configuration</A></H4> + +<H4>Statements</H4> + +<P>A BIND 8 configuration consists of statements and comments. +Statements end with a semicolon. Many statements contain a block of +substatements, which are also terminated with a semicolon.</P> + +<P>The following statements are supported: +<DL> +<DT><CODE><A HREF="acl.html">acl</A></CODE> +<DD> +defines a named IP address matching list, for access control and other uses + +<DT><CODE><A HREF="include.html">include</A></CODE> +<DD> +includes a file + +<DT><CODE><A HREF="key.html">key</A></CODE> +<DD> +specifies key information for use in authentication and authorization + +<DT><CODE><A HREF="logging.html">logging</A></CODE> +<DD> +specifies what the server logs, and where the log messages are sent + +<DT><CODE><A HREF="options.html">options</A></CODE> +<DD> +controls global server configuation options and sets defaults for other +statements + +<DT><CODE><A HREF="server.html">server</A></CODE> +<DD> +sets certain configuration options on a per-server basis + +<DT><CODE><A HREF="zone.html">zone</A></CODE> +<DD> +defines a zone +</DL> + +<P>The <CODE>logging</CODE> and <CODE>options</CODE> statements may only +occur once per configuration. + +<H4><A HREF="comments.html">Comments</A></H4> + +<H3>Converting from BIND 4.9.x</H3> + +<P>BIND 4.9.x configuration files can be converted to the new format +by using <CODE>src/bin/named/named-bootconf.pl</CODE>, a perl script that +is part of the BIND 8.1 source kit. + +<HR> + +<CENTER><P>[ <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: config.html,v 1.4 1998/03/21 01:03:11 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/docdef.html b/contrib/bind/doc/html/docdef.html new file mode 100644 index 0000000..da0c9d5 --- /dev/null +++ b/contrib/bind/doc/html/docdef.html @@ -0,0 +1,112 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND Documentation Definitions</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide--Documentation Definitions</H2> + +<HR> + +<H3>Syntactic Miscellany</H3> + +<P>Described below are elements used throughout the BIND configuration +file documentation. Elements which are only associated with one +statement are described only in the section describing that statement. + +<DL> +<DT><VAR>acl_name</VAR> +<DD> +The name of an <A HREF="address_list.html">address match list</A>, +as defined by the <A HREF="acl.html">acl</A> statement. + +<DT><VAR>address_match_list</VAR> +<DD> +A list of one or more <VAR>ip_address</VAR>, <VAR>ip_prefix</VAR> or +<VAR>acl_name</VAR> elements, as described in the +<A HREF="address_list.html">Address Match Lists</A> section. + +<DT><VAR>dotted-decimal</VAR> +<DD> +One or more integers valued 0 through 255 separated only by dots +("."), such as <CODE>123</CODE> or <CODE>45.67</CODE> or +<CODE>89.123.45.67</CODE>. + +<DT><VAR>domain_name</VAR> +<DD> +A quoted string which will be used as a DNS name, for example +<CODE>"my.test.domain"</CODE>. + +<DT><VAR>path_name</VAR> +<DD> +A quoted string which will be used as a pathname, such as +<CODE>"zones/master/my.test.domain"</CODE>. + +<DT><VAR>ip_addr</VAR> +<DD> +An IP address in with exactly four elements in +<VAR>dotted-decimal</VAR> notation. + +<DT><VAR>ip_port</VAR> +<DD> +An IP port <VAR>number</VAR>. <VAR>number</VAR> is limited to 0 +through 65535, with values below 1024 typically restricted to +root-owned processes. + +<DT><VAR>ip_prefix</VAR> +<DD> +An IP network specified in <VAR>dotted-decimal</VAR> form, followed by "/" +and then the number of bits in the netmask. E.g. <CODE>127/8</CODE> is +the network <CODE>127.0.0.0</CODE> with netmask <CODE>255.0.0.0</CODE>. +<CODE>1.2.3.0/24</CODE> is network <CODE>1.2.3.0</CODE> with netmask +<CODE>255.255.255.0</CODE>. + +<DT><VAR>number</VAR> +<DD> +A non-negative integer with an entire range limited by the range of a +C language signed integer (2,147,483,647 on a machine with 32 bit +integers). Its acceptable value might further be limited by the +context in which it is used. + +<DT><VAR>size_spec</VAR> +<DD> +A <VAR>number</VAR>, the word <CODE>unlimited</CODE>, or the word +<CODE>default</CODE>. + +<P>The maximum value of <VAR>size_spec</VAR> is that of unsigned long +integers on the machine. <CODE>unlimited</CODE> requests unlimited use, or +the maximum available amount. <CODE>default</CODE> uses the limit that +was in force when the server was started.</P> + +<P>A <VAR>number</VAR> can optionally be followed by a scaling factor: +<CODE>K</CODE> or <CODE>k</CODE> for kilobytes, <CODE>M</CODE> or +<CODE>m</CODE> for megabytes, and <CODE>G</CODE> or <CODE>g</CODE> for +gigabytes, which scale by 1024, 1024*1024, and 1024*1024*1024 +respectively. + +<P>Integer storage overflow is currently silently ignored during +conversion of scaled values, resulting in values less than intended, +possibly even negative. Using <CODE>unlimited</CODE> is the best way +to safely set a really large number.</P> + +<DT><VAR>yes_or_no</VAR> +<DD> +Either <CODE>yes</CODE> or <CODE>no</CODE>. The words +<CODE>true</CODE> and <CODE>false</CODE> are also accepted, as are the +numbers <CODE>1</CODE> and <CODE>0</CODE>. + +</DL> + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: docdef.html,v 1.4 1998/03/21 01:03:12 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/example.html b/contrib/bind/doc/html/example.html new file mode 100644 index 0000000..729b980 --- /dev/null +++ b/contrib/bind/doc/html/example.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND Configuration File Guide -- Example Config File</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide -- Example Config File</H2> + +<HR> + +<PRE> + +/* + * A simple BIND 8 configuration + */ + +options { + directory "/var/named"; +}; + +logging { + category lame-servers { null; }; + category cname { null; }; +}; + +zone "isc.org" in { + type master; + file "master/isc.org"; +}; + +zone "vix.com" in { + type slave; + file "slave/vix.com"; + masters { 10.0.0.53; }; +}; + +zone "." in { + type hint; + file "named.cache"; +}; + +zone "0.0.127.in-addr.arpa" in { + type master; + file "master/127.0.0"; +}; +</PRE> + +<HR> + +<CENTER><P>[ <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: example.html,v 1.1 1997/05/06 22:11:31 vixie Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/include.html b/contrib/bind/doc/html/include.html new file mode 100644 index 0000000..4184210 --- /dev/null +++ b/contrib/bind/doc/html/include.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND include Statement</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide--<CODE>include</CODE> Statement</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<P><CODE>include <VAR><A HREF="docdef.html">path_name</A></VAR>;</CODE></P> + +<HR> + +<A Name="#Usage"><H3>Definition and Usage</H3></A> + +<P>The <CODE>include</CODE> statement inserts the specified file at +the point that the <CODE>include</CODE> statement is encountered. It +cannot be used within another statement, though, so a line such as +<CODE>acl internal_hosts { "include internal_hosts.acl" }</CODE> is +not allowed.</P> + +<P>Use <CODE>include</CODE> to break the configuration up into +easily-managed chunks. For example:</P> + +<UL COMPACT> +<LI><CODE>include "/etc/security/keys.bind";</CODE></LI> +<LI><CODE>include "/etc/acls.bind";</CODE></LI> +</UL> + +<P>could be used at the top of a BIND configuration file in order to +include any ACL or key information.</P> + +<P>Be careful not to type +"<CODE>#include</CODE>", like you would in a C +program, because "<CODE>#</CODE>" is used to start a +comment.</P> + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: include.html,v 1.5 1998/03/21 01:03:12 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/index.html b/contrib/bind/doc/html/index.html new file mode 100644 index 0000000..ca8c73c --- /dev/null +++ b/contrib/bind/doc/html/index.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND Version 8 Online Documentation</TITLE> +</HEAD> + +<BODY> +<H2>BIND Version 8 Online Documentation</H2> + +<H3>BIND 8 Highlights</H3> + +<UL> +<LI>DNS Dynamic Updates +(<A HREF=http://ds.internic.net/rfc/rfc2136.txt>RFC 2136</A>)</LI> +<LI>DNS Change Notification +(<A HREF=http://ds.internic.net/rfc/rfc1996.txt>RFC 1996</A>)</LI> +<LI>Completely new configuration syntax</LI> +<LI>Flexible, categorized logging system</LI> +<LI>IP-address-based access control for queries, zone transfers, and +updates that may be specified on a zone-by-zone basis</LI> +<LI>More efficient zone transfers</LI> +<LI>Improved performance for servers with thousands of zones</LI> +<LI>The server no longer forks for outbound zone transfers</LI> +<LI>Many bug fixes</LI> +</UL> + +<H3><A HREF="config.html">Configuration File Guide</A></H3> + +<H3>Kits</H3> +<UL> +<LI><A HREF="ftp://ftp.isc.org/isc/bind/src/cur"> +The latest production release</A></LI> +<LI><A HREF="ftp://ftp.isc.org/isc/bind/src/testing"> +The latest public test release</A></LI> +</UL> + +<H3>Bug Reports and Comments</H3> +<P>Send bug reports to +<A HREF="mailto:bind-bugs@isc.org">bind-bugs@isc.org</A>. + +<H3>DNS Related Newsgroups</H3> +<UL> +<LI><A HREF="news:comp.protocols.dns.bind">Using BIND</A></LI> +<LI><A HREF="news:comp.protocols.dns.ops">DNS Operations</A></LI> +<LI><A HREF="news:comp.protocols.dns.std">DNS Standards</A></LI> +</UL> + +<H3><A HREF="http://www.isc.org/">The Internet Software Consortium</A></H3> + +BIND is supported by the Internet Software Consortium, and +although it is free for use and redistribution and incorporation into +vendor products and export and anything else you can think of, it +costs money to produce. That money comes from ISPs, hardware and +software vendors, companies who make extensive use of the software, +and generally kind hearted folk such as yourself. + +<HR> +<ADDRESS> +Last Updated: $Id: index.html,v 1.4 1998/03/21 01:03:12 halley Exp $ +</ADDRESS> + +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/key.html b/contrib/bind/doc/html/key.html new file mode 100644 index 0000000..bac6a96 --- /dev/null +++ b/contrib/bind/doc/html/key.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND key Statement</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide--<CODE>key</CODE> Statement</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +key <VAR>key_id</VAR> { + algorithm <VAR>algorithm_id</VAR>; + secret <VAR>secret_string</VAR>; +}; +</PRE> + +<HR> + +<A NAME="Usage"><H3>Definition and Usage</H3></A> + +<P>The <CODE>key</CODE> statement defines a key ID which can be used +in a <A HREF="server.html"><CODE>server</CODE> statement</A> to +associate an authentication method with a particular name server. + +<P>A key ID must be created with the <CODE>key</CODE> +statement before it can be used in a <CODE>server</CODE> +definition.</P> + +<P>The <VAR>algorithm_id</VAR> is a string that specifies a +security/authentication algorithm. +<VAR>secret_string</VAR> is the secret to be used by the algorithm. + +<P>The <CODE>key</CODE> statement is intended for future use by the +server. It is checked for syntax but is otherwise ignored. +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: key.html,v 1.5 1998/03/21 01:03:13 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/logging.html b/contrib/bind/doc/html/logging.html new file mode 100644 index 0000000..4af8050 --- /dev/null +++ b/contrib/bind/doc/html/logging.html @@ -0,0 +1,346 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND logging Statement</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide -- <CODE>logging</CODE> Statement</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +logging { + [ channel <VAR>channel_name</VAR> { + ( file <VAR><A HREF="docdef.html">path_name</A></VAR> + [ versions ( <VAR>number</VAR> | unlimited ) ] + [ size <VAR><A HREF="docdef.html">size_spec</A></VAR> ] + | syslog ( kern | user | mail | daemon | auth | syslog | lpr | + news | uucp | cron | authpriv | ftp | + local0 | local1 | local2 | local3 | + local4 | local5 | local6 | local7 ) + | null ); + + [ severity ( critical | error | warning | notice | + info | debug [ <VAR>level</VAR> ] | dynamic ); ] + [ print-category <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ print-severity <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ print-time <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + }; ] + + [ category <VAR>category_name</VAR> { + <VAR>channel_name</VAR>; [ <VAR>channel_name</VAR>; ... ] + }; ] + ... +}; +</PRE> + +<A NAME="Usage"><H3>Definition and Usage</H3></A> + +<P>The <CODE>logging</CODE> statement configures a wide variety of +logging options for the nameserver. Its <CODE>channel</CODE> phrase +associates output methods, format options and severity levels with +a name that can then be used with the <CODE>category</CODE> phrase to +select how various classes of messages are logged.</P> + +<P>Only one <CODE>logging</CODE> statement is used to define as many +channels and categories as are wanted. If there are multiple logging +statements in a configuration, the first defined determines the logging, +and warnings are issued for the others. If there is no logging statement, +the logging configuration will be:</P> + +<PRE> + logging { + category default { default_syslog; default_debug; }; + category panic { default_syslog; default_stderr; }; + category packet { default_debug; }; + category eventlib { default_debug; }; + }; +</PRE> + +<H4>The <CODE>channel</CODE> phrase</H4> + +<P>All log output goes to one or more "channels"; you can make as many +of them as you want.</P> + +<P>Every channel definition must include a clause that says whether +messages selected for the channel go to a file, to a particular syslog +facility, or are discarded. It can optionally also limit the message +severity level that will be accepted by the channel (default is +"info"), and whether to include a <CODE>named</CODE>-generated time +stamp, the category name and/or severity level (default is not to +include any).</P> + +<P>The word <CODE>null</CODE> as the destination option for the +channel will cause all messages sent to it to be discarded; other +options for the channel are meaningless.</P> + +<P>The <CODE>file</CODE> clause 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>The <CODE>size</CODE> option for files is simply a hard ceiling on +log growth. If the file ever exceeds the size, then +<CODE>named</CODE> will just not write anything more to it until the +file is reopened; exceeding the size does not automatically trigger a +reopen. The default behavior is to not limit the size of the file.</P> + +<P>If you use the <CODE>version</CODE> logfile option, then +<CODE>named</CODE> will retain that many backup versions of the file +by renaming them when opening. For example, if you choose to keep 3 +old versions of the file "lamers.log" then just before it is opened +lamers.log.1 is renamed to lames.log.2, lamers.log.0 is renamed to +lamers.log.1, and lamers.log is renamed to lamers.log.0. No rolled +versions are kept by default. The <CODE>unlimited</CODE> keyword is +synonymous with <CODE>99</CODE> in current BIND releases.</P> + +<P>The argument for the <CODE>syslog</CODE> clause is a syslog +facility as described in the <CODE>syslog</CODE> manual page. How +<CODE>syslogd</CODE> will handle messages sent to this facility is +described in the <CODE>syslog.conf</CODE> manual page. If you have a +system which uses a very old version of <CODE>syslog</CODE> that only +uses two arguments to the <CODE>openlog()</CODE> function, then this +clause is silently ignored.</P> + +<P>The <CODE>severity</CODE> clause works like <CODE>syslog</CODE>'s +"priorities", except that they can also be used if you are writing +straight to a file rather than using <CODE>syslog</CODE>. 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 <CODE>syslog</CODE>, then the +<CODE>syslog.conf</CODE> priorities will also determine what +eventually passes through. For example, defining a channel facility +and severity as <CODE>daemon</CODE> and <CODE>debug</CODE> but only +logging <CODE>daemon.warning</CODE> via <CODE>syslog.conf</CODE> will +cause messages of severity <CODE>info</CODE> and <CODE>notice</CODE> +to be dropped. If the situation were reversed, with +<CODE>named</CODE> writing messages of only <CODE>warning</CODE> or +higher, then <CODE>syslogd</CODE> would print all messages it received +from the channel.</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 server with the "-d" flag followed by a +positive integer, or by sending the server the SIGUSR1 signal (for +example, by using "ndc trace"). The global debug level can be set to +zero, and debugging mode turned off, by sending the server the SIGUSR2 +signal ("ndc notrace". All debugging messages in the server have a +debug level, and higher debug levels give more more detailed output. +Channels that specify a specific debug severity, e.g. + +<PRE> + 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 <code>dynamic</code> severity use the server's global +level to determine what messages to print. + +<P>If <CODE>print-time</CODE> has been turned on, then the date and +time will be logged. <CODE>print-time</CODE> may be specified for a +syslog channel, but is usually pointless since syslog also prints the +date and time. If <CODE>print-category</CODE> is requested, +then the category of the message will be logged as well. Finally, if +<CODE>print-severity</CODE> is on, then the severity level of the +message will be logged. The <CODE>print-</CODE> 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 +<CODE>print-</CODE> options are on: + +<PRE> + 28-Apr-1997 15:05:32.863 default: notice: Ready to answer queries. +</PRE> + +<P>There are four predefined channels that are used for +<CODE>named</CODE>'s default logging as follows. How they are used +used is described in the next section, The <CODE>category</CODE> phrase. + +<PRE> + 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 + severity dynamic; # log at the server's current debug level + }; + + channel default_stderr { # writes to stderr + file "<stderr>"; # this is illustrative only; there's currently + # no way of specifying an internal file + # descriptor in the configuration language. + severity info; # only send priority info and higher + }; + + channel null { + null; # toss anything sent to this channel + }; +</PRE> + +<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> + +<H4>The <CODE>category</CODE> phrase</H4> + +<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 <CODE>default</CODE> category instead. If you don't specify +a default category, the following "default default" is used: + +<PRE> + 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: + +<PRE> + 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 +<CODE>null</CODE> channel: + +<PRE> + category lame-servers { null; }; + category cname { null; }; +</PRE> + +<P>The following +categories are available:</P> + +<DL> +<DT><CODE>default</CODE> +<DD> +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. If you do not +define the default category, the following definition is used: +<CODE>category default { default_syslog; default_debug; };</CODE> + +<DT><CODE>config</CODE> +<DD> +High-level configuration file processing. + +<DT><CODE>parser</CODE> +<DD> +Low-level configuration file processing. + +<DT><CODE>queries</CODE> +<DD> +A short log message is generated for every query the server receives. + +<DT><CODE>lame-servers</CODE> +<DD> +Messages like "Lame server on ..." + +<DT><CODE>statistics</CODE> +<DD> +Statistics. + +<DT><CODE>panic</CODE> +<DD> +If the server has to shut itself down due to an internal problem, it +will log the problem in this category as well as in the problem's native +category. If you do not define the panic category, the following definition +is used: <CODE>category panic { default_syslog; default_stderr; };</CODE> + +<DT><CODE>update</CODE> +<DD> +Dynamic updates. + +<DT><CODE>ncache</CODE> +<DD> +Negative caching. + +<DT><CODE>xfer-in</CODE> +<DD> +Zone transfers the server is receiving. + +<DT><CODE>xfer-out</CODE> +<DD> +Zone transfers the server is sending. + +<DT><CODE>db</CODE> +<DD> +All database operations. + +<DT><CODE>eventlib</CODE> +<DD> +Debugging info from the event system. Only one channel may be specified for +this category, and it must be a file channel. If you do not define the +eventlib category, the following definition is used: <CODE>category eventlib +{ default_debug; };</CODE> + +<DT><CODE>packet</CODE> +<DD> +Dumps of packets received and sent. Only one channel may be specified for +this category, and it must be a file channel. If you do not define the +packet category, the following definition is used: <CODE>category packet +{ default_debug; };</CODE> + +<DT><CODE>notify</CODE> +<DD> +The NOTIFY protocol. + +<DT><CODE>cname</CODE> +<DD> +Messages like "... points to a CNAME". + +<DT><CODE>security</CODE> +<DD> +Approved/unapproved requests. + +<DT><CODE>os</CODE> +<DD> +Operating system problems. + +<DT><CODE>insist</CODE> +<DD> +Internal consistency check failures. + +<DT><CODE>maintenance</CODE> +<DD> +Periodic maintenance events. + +<DT><CODE>load</CODE> +<DD> +Zone loading messages. + +<DT><CODE>response-checks</CODE> +<DD> +Messages arising from response checking, such as +"Malformed response ...", "wrong ans. name ...", +"unrelated additional info ...", "invalid RR type ...", and "bad referral ...". + +</DL> + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: logging.html,v 1.6 1998/03/21 01:03:13 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/options.html b/contrib/bind/doc/html/options.html new file mode 100644 index 0000000..5f0ddce --- /dev/null +++ b/contrib/bind/doc/html/options.html @@ -0,0 +1,462 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND options Statement</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide -- <CODE>options</CODE> Statement</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +options { + [ directory <VAR>path_name</VAR>; ] + [ named-xfer <VAR>path_name</VAR>; ] + [ dump-file <VAR>path_name</VAR>; ] + [ memstatistics-file <VAR>path_name</VAR>; ] + [ pid-file <VAR>path_name</VAR>; ] + [ statistics-file <VAR>path_name</VAR>; ] + [ auth-nxdomain <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ deallocate-on-exit <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ fake-iquery <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ fetch-glue <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ multiple-cnames <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ notify <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ recursion <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ forward ( only | first ); ] + [ forwarders { [ <VAR><A HREF="docdef.html">in_addr</A></VAR> ; [ <VAR><A HREF="docdef.html">in_addr</A></VAR> ; ... ] ] }; ] + [ check-names ( master | slave | response ) ( warn | fail | ignore); ] + [ allow-query { <VAR>address_match_list</VAR> }; ] + [ allow-transfer { <VAR>address_match_list</VAR> }; ] + [ listen-on [ port <VAR><A HREF="docdef.html">ip_port</A></VAR> ] { <VAR>address_match_list</VAR> }; ] + [ query-source [ address ( <VAR><A HREF="docdef.html">ip_addr</A></VAR> | * ) ] [ port ( <VAR><A HREF="docdef.html">ip_port</A></VAR> | * ) ] ; ] + [ max-transfer-time-in <VAR>number</VAR>; ] + [ transfer-format ( one-answer | many-answers ); ] + [ transfers-in <VAR>number</VAR>; ] + [ transfers-out <VAR>number</VAR>; ] + [ transfers-per-ns <VAR>number</VAR>; ] + [ coresize <VAR><A HREF="docdef.html">size_spec</A></VAR> ; ] + [ datasize <VAR><A HREF="docdef.html">size_spec</A></VAR> ; ] + [ files <VAR><A HREF="docdef.html">size_spec</A></VAR> ; ] + [ stacksize <VAR><A HREF="docdef.html">size_spec</A></VAR> ; ] + [ cleaning-interval <VAR>number</VAR>; ] + [ interface-interval <VAR>number</VAR>; ] + [ statistics-interval <VAR>number</VAR>; ] + [ topology { <VAR>address_match_list</VAR> }; ] +}; +</PRE> +<HR> + +<A NAME="Usage"><H3>Definition and Use</H3></A> + +<P>The options statement sets up global options to be used by +BIND. This statement may appear at only once in a +configuration file; if more than one occurrence is found, the +first occurrence determines the actual options used, +and a warning will be generated. If there is no options statement, +an options block with each option set to its default will be used.</P> + +<H4>Pathnames</H4> + +<DL> +<DT><CODE>directory</CODE> +<DD> +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. "named.run") is this directory. If a directory is not +specified, the working directory defaults to ".", the directory from which the +server was started. The directory specified should be an absolute path. + +<DT><CODE>named-xfer</CODE> +<DD> +The pathname to the named-xfer program that the server uses for +inbound zone transfers. If not specified, the default is +system dependent (e.g. "/usr/sbin/named-xfer"). + +<DT><CODE>dump-file</CODE> +<DD> +The pathname of the file the server dumps the database to when it +receives <CODE>SIGINT</CODE> signal (<CODE>ndc dumpdb</CODE>). If not +specified, the default is "named_dump.db". + +<DT><CODE>memstatistics-file</CODE> +<DD> +The pathname of the file the server writes memory usage statistics to on exit, +if <CODE>deallocate-on-exit</CODE> is <CODE>yes</CODE>. If not +specified, the default is "named.memstats". + +<DT><CODE>pid-file</CODE> +<DD> +The pathname of the file the server writes its process ID in. If not +specified, the default is operating system dependent, but is usually +"/var/run/named.pid" or "/etc/named.pid". The pid-file is used by +programs like "ndc" that want to send signals to the running +nameserver. + +<DT><CODE>statistics-file</CODE> +<DD> +The pathname of the file the server appends statistics to when it +receives <CODE>SIGILL</CODE> signal (<CODE>ndc stats</CODE>). If not +specified, the default is "named.stats". +</DL> + +<A name="BooleanOptions"><H4>Boolean Options</H4></A> + +<DL> +<DT><CODE>auth-nxdomain</CODE> +<DD> +If <CODE>yes</CODE>, then the <CODE>AA</CODE> bit is always set on +NXDOMAIN responses, even if the server is not actually authoritative. +The default is <CODE>yes</CODE>. Do not turn off +<CODE>auth-nxdomain</CODE> unless you are sure you know what you are +doing, as some older software won't like it. + +<DT><CODE>deallocate-on-exit</CODE> +<DD> +If <CODE>yes</CODE>, then when the server exits it will painstakingly +deallocate every object it allocated, and then write a memory usage report to +the <CODE>memstatistics-file</CODE>. The default is <CODE>no</CODE>, because +it is faster to let the operating system clean up. +<CODE>deallocate-on-exit</CODE> is handy for detecting memory leaks. + +<DT><CODE>fake-iquery</CODE> +<DD> +If <CODE>yes</CODE>, the server will simulate the obsolete DNS query type +IQUERY. The default is <CODE>no</CODE>. + +<DT><CODE>fetch-glue</CODE> +<DD> +If <CODE>yes</CODE> (the default), the server will fetch "glue" resource +records it doesn't have when constructing the additional data section of +a response. <CODE>fetch-glue no</CODE> can be used in conjunction with +<CODE>recursion no</CODE> to prevent the server's cache from growing or +becoming corrupted (at the cost of requiring more work from the client). + +<DT><CODE>multiple-cnames</CODE> +<DD> +If <CODE>yes</CODE>, then multiple CNAME resource records will be +allowed for a domain name. The default is <CODE>no</CODE>. Allowing +multiple CNAME records is against standards and is not recommended. +Multiple CNAME support is available because previous versions of BIND +allowed multiple CNAME records, and these records have been used for load +balancing by a number of sites. + +<DT><CODE>notify</CODE> +<DD> +If <CODE>yes</CODE> (the default), DNS NOTIFY messages are sent when a +zone the server is authoritative for changes. The use of NOTIFY +speeds convergence between the master and its slaves. Slave servers +that receive a NOTIFY message and understand it will contact the +master server for the zone and see if they need to do a zone transfer, and +if they do, they will initiate it immediately. The <CODE>notify</CODE> +option may also be specified in the <CODE>zone</CODE> statement, in which +case it overrides the <CODE>options notify</CODE> statement. + +<DT><CODE>recursion</CODE> +<DD> +If <CODE>yes</CODE>, and a DNS query requests recursion, then the +server will attempt to do all the work required to answer the query. +If recursion is not on, the server will return a referral to the +client if it doesn't know the answer. The default is <CODE>yes</CODE>. +See also <CODE>fetch-glue</CODE> above. +</DL> + +<H4>Forwarding</H4> + +<P>The forwarding facility can be used to create a large sitewide +cache on a few servers, reducing traffic over links to external +nameservers. 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. + +<DL> +<DT><CODE>forward</CODE> +<DD> +This option is only meaningful if the <CODE>forwarders</CODE> list is +not empty. A value of <CODE>first</CODE>, the default, causes the +server to query the forwarders first, and if that doesn't answer the +question the server will then look for the answer itself. If +<CODE>only</CODE> is specified, the server will only query the +forwarders. + +<DT><CODE>forwarders</CODE> +<DD> +Specifies the IP addresses to be used for forwarding. The default is the +empty list (no forwarding). +</DL> + +<P>Future versions of BIND 8 will provide a more powerful forwarding +system. The syntax described above will continue to be supported. + +<a name="NameChecking"><H4>Name Checking</H4></a> + +<P>The server can check domain names based upon their expected client contexts. +For example, a domain name used as a hostname can be checked for compliance +with the RFCs defining valid hostnames. + +<P>Three checking methods are available: + +<DL> +<DT><CODE>ignore</CODE> +<DD> +No checking is done. + +<DT><CODE>warn</CODE> +<DD> +Names are checked against their expected client contexts. Invalid names are +logged, but processing continues normally. + +<DT><CODE>fail</CODE> +<DD> +Names are checked against their expected client contexts. Invalid names are +logged, and the offending data is rejected. +</DL> + +<P>The server can check names three areas: master zone files, slave +zone files, and in responses to queries the server has initiated. If +<CODE>check-names response fail</CODE> has been specified, and +answering the client's question would require sending an invalid name +to the client, the server will send a REFUSED response code to the +client. + +<P>The defaults are: + +<PRE> + check-names master fail; + check-names slave warn; + check-names response ignore; +</PRE> + +<P><CODE>check-names</CODE> may also be specified in the <CODE>zone</CODE> +statement, in which case it overrides the <CODE>options check-names</CODE> +statement. When used in a <CODE>zone</CODE> statement, the area is not +specified (because it can be deduced from the zone type). + +<A name="AccessControl"><H4>Access Control</H4></A> + +<P>Access to the server can be restricted based on the IP address of the +requesting system. See +<VAR><A HREF="address_list.html">address_match_list</A></VAR> for details +on how to specify IP address lists. + +<DL> +<DT><CODE>allow-query</CODE> +<DD> +Specifies which hosts are allowed to ask ordinary questions. +<CODE>allow-query</CODE> may also be specified in the +<CODE>zone</CODE> statement, in which case it overrides the +<CODE>options allow-query</CODE> statement. If not specified, the default is +to allow queries from all hosts. + +<DT><CODE>allow-transfer</CODE> +<DD> +Specifies which hosts are allowed to receive zone transfers from the +server. <CODE>allow-transfer</CODE> may also be specified in the +<CODE>zone</CODE> statement, in which case it overrides the +<CODE>options allow-transfer</CODE> statement. If not specified, the default +is to allow transfers from all hosts. +</DL> + +<H4>Interfaces</H4> + +<P>The interfaces and ports that the server will answer queries from may +be specified using the <CODE>listen-on</CODE> option. <CODE>listen-on</CODE> +takes an optional port, and an +<VAR><A HREF="address_list.html">address_match_list</A></VAR>. 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>Multiple <CODE>listen-on</CODE> statements are allowed. For example, + +<PRE> + listen-on { 5.6.7.8; }; + listen-on port 1234 { !1.2.3.4; 1.2/16; }; +</PRE> + +<P>If no <CODE>listen-on</CODE> is specified, the server will listen on port +53 on all interfaces. + +<H4>Query Address</H4> + +<P>If the server doesn't know the answer to a question, it will query +other nameservers. <CODE>query-source</CODE> specifies the address +and port used for such queries. If <CODE>address</CODE> is +<CODE>*</CODE> or is omitted, a wildcard IP address +(<CODE>INADDR_ANY</CODE>) will be used. If <CODE>port</CODE> is +<CODE>*</CODE> or is omitted, a random unprivileged port will be used. +The default is + +<PRE> + query-source address * port *; +</PRE> + +<P>Note: <CODE>query-source</CODE> currently applies only to UDP queries; +TCP queries always use a wildcard IP address and a random unprivileged +port. + +<A name="ZoneTransfers"><H4>Zone Transfers</H4></A> + +<DL> +<DT><CODE>max-transfer-time-in</CODE> +<DD> +Inbound zone transfers (<CODE>named-xfer</CODE> processes) running +longer than this many minutes will be terminated. The default is 120 +minutes (2 hours). + +<DT><CODE>transfer-format</CODE> +<DD> +The server supports two zone transfer methods. +<CODE>one-answer</CODE> uses one DNS message per resource record +transferred. <CODE>many-answers</CODE> packs as many resource records +as possible into a message. <CODE>many-answers</CODE> is more +efficient, but is only known to be understood by BIND 8.1 and patched +versions of BIND 4.9.5. The default is <CODE>one-answer</CODE>. +<CODE>transfer-format</CODE> may be +overridden on a per-server basis by using the <CODE>server</CODE> statement. + +<DT><CODE>transfers-in</CODE> +<DD> +The maximum number of inbound zone transfers that can be running +concurrently. The default value is 10. Increasing +<CODE>transfers-in</CODE> may speed up the convergence of slave zones, +but it also may increase the load on the local system. + +<DT><CODE>transfers-out</CODE> +<DD> +This option will be used in the future to limit the number of +concurrent outbound zone transfers. It is checked for syntax, but is +otherwise ignored. + +<DT><CODE>transfers-per-ns</CODE> +<DD> +The maximum number of inbound zone transfers (<CODE>named-xfer</CODE> +processes) that can be concurrently transferring from a given remote +nameserver. The default value is 2. Increasing +<CODE>transfers-per-ns</CODE> may speed up the convergence of slave +zones, but it also may increase the load on the remote nameserver. +<CODE>transfers-per-ns</CODE> may be overridden on a per-server basis +by using the <CODE>transfers</CODE> phrase of the <CODE>server</CODE> +statement. +</DL> + +<H4>Resource Limits</H4> + +<P>The server's usage of many system resources can be limited. Some +operating systems don't support some of the limits. On such systems, +a warning will be issued if the unsupported limit is used. Some +operating systems don't support limiting resources, and on these systems +a <CODE>cannot set resource limits on this system</CODE> message will +be logged. + +<P>Scaled values are allowed when specifying resource limits. For +example, <CODE>1G</CODE> can be used instead of +<CODE>1073741824</CODE> to specify a limit of one gigabyte. +<CODE>unlimited</CODE> requests unlimited use, or the maximum +available amount. <CODE>default</CODE> uses the limit that was in +force when the server was started. See +<VAR><AHREF="docdef.html">size_spec</A></VAR> for more details. + +<DL> +<DT><CODE>coresize</CODE> +<DD> +The maximum size of a core dump. The default is <CODE>default</CODE>. + +<DT><CODE>datasize</CODE> +<DD> +The maximum amount of data memory the server may use. The default is +<CODE>default</CODE>. + +<DT><CODE>files</CODE> +<DD> +The maximum number of files ther server may have open concurrently. +The default is <CODE>unlimited</CODE>. <I>Note:</I> on some operating +systems the server cannot set an unlimited value and cannot determine +the maximum number of open files the kernel can support. On such +systems, choosing <CODE>unlimited</CODE> will cause the server to use +the larger of the <CODE>rlim_max</CODE> for <CODE>RLIMIT_NOFILE</CODE> +and the value returned by <CODE>sysconf(_SC_OPEN_MAX)</CODE>. If the +actual kernel limit is larger than this value, use <CODE>limit +files</CODE> to specify the limit explicitly. + +<DT><CODE>stacksize</CODE> +<DD> +The maximum amount of stack memory the server may use. The default is +<CODE>default</CODE>. +</DL> + +<H4>Periodic Task Intervals</H4> + +<DL> +<DT><CODE>cleaning-interval</CODE> +<DD> +The server will remove expired resource records from the cache every +<CODE>cleaning-interval</CODE> minutes. The default is 60 minutes. If set +to 0, no periodic cleaning will occur. + +<DT><CODE>interface-interval</CODE> +<DD> +The server will scan the network interface list every +<CODE>interface-interval</CODE> minutes. The default is 60 minutes. +If set to 0, interface scanning will only occur when the configuration +file is loaded. After the scan, listeners will be started on any new +interfaces (provided they are allowed by the <CODE>listen-on</CODE> +configuration). Listeners on interfaces that have gone away will be +cleaned up. + +<DT><CODE>statistics-interval</CODE> +<DD> +Nameserver statisitics will be logged every <CODE>statistics-interval</CODE> +minutes. The default is 60. If set to 0, no statistics will be logged. +</DL> + +<H4>Topology</H4> + +<P>All other things being equal, when the server chooses a nameserver +to query from a list of nameservers, it prefers the one that is +topologically closest to itself. The <CODE>topology</CODE> statement +takes an <VAR><A HREF="address_list.html">address_match_list</A></VAR> +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, + +<PRE> + 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>The default topology is + +<PRE> + topology { localhost; localnets; }; +</PRE> + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: options.html,v 1.9 1998/03/21 01:02:59 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/server.html b/contrib/bind/doc/html/server.html new file mode 100644 index 0000000..0eb4dca --- /dev/null +++ b/contrib/bind/doc/html/server.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND server Statement</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide--<CODE>server</CODE> Statement</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +server <VAR><A HREF="docdef.html">ip_addr</A></VAR> { + [ bogus <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ transfers <VAR><A HREF="docdef.html">number</A></VAR>; ] + [ transfer-format ( one-answer | many-answers ); ] + [ keys { <VAR><A HREF="key.html">key_id</A></VAR> [<VAR>key_id</VAR> ... ] }; ] +}; +</PRE> + +<HR> + +<A NAME="Usage"><H3>Definition and Usage</H3></A> + +<P>The server statement defines the characteristics to be +associated with a remote name server.</P> + +<P>If you discover that a server is giving out bad data, marking it as +<CODE>bogus</CODE> will prevent further queries to it. The default value of +<CODE>bogus</CODE> is <CODE>no</CODE>. + +<P>The server supports two zone transfer methods. The first, +<CODE>one-answer</CODE>, uses one DNS message per resource record +transferred. <CODE>many-answers</CODE> packs as many resource records +as possible into a message. <CODE>many-answers</CODE> is more +efficient, but is only known to be understood by BIND 8.1 and patched +versions of BIND 4.9.5. You can specify which method to use for a +server with the <CODE>transfer-format</CODE> option. If +<CODE>transfer-format</CODE> is not specified, the <CODE>transfer-format</CODE> +specified by the <CODE>options</CODE> statement will be used. + +<P>The <CODE>transfers</CODE> will be used in a future release of the server +to limit the number of concurrent in-bound zone transfers from the specified +server. It is checked for syntax but is otherwise ignored. + +<P>The <CODE>keys</CODE> statement is intended for future use by the +server. It is checked for syntax but is otherwise ignored. + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: server.html,v 1.6 1998/03/21 01:03:13 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/html/zone.html b/contrib/bind/doc/html/zone.html new file mode 100644 index 0000000..b6edb38 --- /dev/null +++ b/contrib/bind/doc/html/zone.html @@ -0,0 +1,140 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>BIND zone Statement</TITLE> +</HEAD> + +<BODY> +<H2>BIND Configuration File Guide--<CODE>zone</CODE> Statement</H2> + +<HR> + +<A NAME="Syntax"><H3>Syntax</H3></A> + +<PRE> +zone <VAR><A HREF="docdef.html">domain_name</A></VAR> [ ( in | hs | hesiod | chaos ) ] { + type master; + file <VAR><A HREF="docdef.html">path_name</A></VAR>; + [ check-names ( warn | fail | ignore ); ] + [ allow-update { <VAR><A NAME="address_list.html">address_match_list</A></VAR> }; ] + [ allow-query { <VAR><A NAME="address_list.html">address_match_list</A></VAR> }; ] + [ allow-transfer { <VAR><A NAME="address_list.html">address_match_list</A></VAR> }; ] + [ notify <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ also-notify { <VAR><A HREF="docdef.html">ip_addr</A></VAR>; [ <VAR>ip_addr</VAR>; ... ] }; +}; + +zone <VAR><A HREF="docdef.html">domain_name</A></VAR> [ ( in | hs | hesiod | chaos ) ] { + type ( slave | stub ); + [ file <VAR><A HREF="docdef.html">path_name</A></VAR>; ] + masters { <VAR><A HREF="docdef.html">ip_addr</A></VAR>; [ <VAR>ip_addr</VAR>; ... ] }; + [ check-names ( warn | fail | ignore ); ] + [ allow-update { <VAR><A NAME="address_list.html">address_match_list</A></VAR> }; ] + [ allow-query { <VAR><A NAME="address_list.html">address_match_list</A></VAR> }; ] + [ allow-transfer { <VAR><A NAME="address_list.html">address_match_list</A></VAR> }; ] + [ max-transfer-time-in <VAR>number</VAR>; ] + [ notify <VAR><A HREF="docdef.html">yes_or_no</A></VAR>; ] + [ also-notify { <VAR><A HREF="docdef.html">ip_addr</A></VAR>; [ <VAR>ip_addr</VAR>; ... ] }; +}; + +zone "." [ ( in | hs | hesiod | chaos ) ] { + type hint; + file <VAR><A HREF="docdef.html">path_name</A></VAR>; + [ check-names ( warn | fail | ignore ); ] +}; +</PRE> + +<HR> + +<A NAME="Usage"><H3>Definition and Usage</H3></A> + +<H4>Zone Types</H4> + +<DL> +<DT><CODE>master</CODE> +<DD> +The master copy of the data in a zone. + +<DT><CODE>slave</CODE> +<DD> +A <CODE>slave</CODE> zone is a replica of a master zone. The +<CODE>masters</CODE> list specifies one or more IP addresses that the +slave contacts to update its copy of the zone. If <CODE>file</CODE> +is specified, then the replica will be written to the file. Use of +<CODE>file</CODE> is recommended, since it often speeds server startup +and eliminates a needless waste of bandwidth. + +<DT><CODE>stub</CODE> +<DD> +A <CODE>stub</CODE> zone is like a slave zone, except that it replicates +only the NS records of a master zone instead of the entire zone. + +<DT><CODE>hint</CODE> +<DD> +The initial set of root nameservers is specified using a +<CODE>hint</CODE> zone. When the server starts up, it uses the root hints +to find a root nameserver and get the most recent list of root nameservers. +</DL> + +<P>Note: previous releases of BIND used the term <EM>primary</EM> for a +master zone, <EM>secondary</EM> for a slave zone, and <EM>cache</EM> for +a hint zone.</P> + +<H4>Class</H4> + +<P>The zone's name may optionally be followed by a class. If a class is not +specified, class <CODE>in</CODE> is used. + +<H4>Options</H4> + +<DL> +<DT><CODE>check-names</CODE> +<DD> +See <A HREF="options.html#NameChecking">Name Checking</A>. + +<DT><CODE>allow-query</CODE> +<DD> +See the description of <CODE>allow-query</CODE> in the +<A HREF="options.html#AccessControl">Access Control</A> section. + +<DT><CODE>allow-update</CODE> +<DD> +Specifies which hosts are allowed to submit Dynamic DNS updates to the +server. The default is to deny updates from all hosts. + +<DT><CODE>allow-transfer</CODE> +<DD> +See the description of <CODE>allow-transfer</CODE> in +the <A HREF="options.html#AccessControl">Access Control</A> section. + +<DT><CODE>max-transfer-time-in</CODE> +<DD> +See the description of <CODE>max-transfer-time-in</CODE> in +the <A HREF="options.html#ZoneTransfers">Zone Transfers</A> section. + +<DT><CODE>notify</CODE> +<DD> +See the description of <CODE>notify</CODE> in +the <A HREF="options.html#BooleanOptions">Boolean Options</A> section. + +<DT><CODE>also-notify</CODE> +<DD> +<CODE>also-notify</CODE> is only meaningful if <CODE>notify</CODE> is +active for this zone. The set of machines that will receive a DNS +NOTIFY message for this zone is made up of all the listed nameservers +for the zone (other than the primary master) plus any IP addresses +specified with <CODE>also-notify</CODE>. <CODE>also-notify</CODE> is not +meaningful for <CODE>stub</CODE> zones. The default is the empty list. +</DL> + +<HR> + +<CENTER><P>[ <A HREF="config.html">BIND Config. File</A> +| <A HREF="http://www.vix.com/isc/bind.html">BIND Home</A> +| <A HREF="http://www.isc.org">ISC</A> ]</P></CENTER> + +<HR> +<ADDRESS> +Last Updated: $Id: zone.html,v 1.6 1998/03/21 01:03:14 halley Exp $ +</ADDRESS> +</BODY> +</HTML> diff --git a/contrib/bind/doc/man/Makefile b/contrib/bind/doc/man/Makefile new file mode 100644 index 0000000..4ac138f --- /dev/null +++ b/contrib/bind/doc/man/Makefile @@ -0,0 +1,385 @@ +## 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) 1996 by Internet Software Consortium +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. + +# +# Makefile to install the BIND 4.9 manual entries. +# +# Default Configuration: +# There are a set of default assignments immediately following this +# note. These defaults are for BSD4.4, BSD/386, other net2-alikes, +# and will install manual entries with following characteristics: +# o They will be catable (i.e., passed through nroff) +# o They will be installed in the directories +# /usr/share/man/catN, where N is 1, 3, 5, 7, 8 +# o They will have an extension of `.0' +# +# Don't change these defaults. Instead, following the default configuration +# are sets of commented values for particular systems that can be used +# to override the default values. +# + +# +# Target directory for the manual directory tree. Eg., may be used to +# specify the path of an NFS-mounted directory for common files. +# +DESTDIR= + +# +# Default location for manual section directories. +# +DESTMAN= /usr/share/man + +# +# Install manuals in ${MANDIR}N. For systems that generate catable manual +# entries on the fly, use +# MANDIR = man +# +MANDIR = cat + +# +# Default extension for manual entries. To install the manual entries under +# their `real' extensions use +# CATEXT = $$N +# +CATEXT = 0 + +# +# Command to install manual entries +# +INSTALL= install + +# +# `install' options to set Owner and Group for manual entries. Eg. for +# BSD `install' use +# MAN_OWNER = -o bin +# MAN_GROUP = -g bin +# +MAN_OWNER = +MAN_GROUP = + +SHELL= /bin/sh + +INDOT= +XFER_INDOT= +# +# Uppercase versions of the above variables (`INDOT_U' and `XFER_INDOT_U') +# are defined for use in `.TH' lines. +# + +# +# Command used to generate a manual entry. By default this produces catable +# manual entries. +# +# For systems that store manuals in MDOC form (eg modern BSD systems) and +# can generate catable manual entries on the fly the following assignment +# can be used. +# MANROFF = cat +# +MANROFF = ( tbl | nroff -mandoc ) + +# +# Default extensions for installed manual entries. The following variables +# have been defined to allow BIND's manual entries to be installed in the +# right place for a given platform. +# +# CMD_EXT = extension for user commands (eg, dig) +# LIB_NETWORK_EXT = extension for network library routines (eg, +# gethostbyname) +# FORMAT_EXT = extension for files describing file formats +# (eg, resolver) +# DESC_EXT = extension for descriptive files (eg, mailaddr) +# SYS_OPS_EXT = extension system operation and maintenance commands +# and applications. (eg, named, named-xfer, syslog) +# +# Associated with each variable is an additional variable with the suffix +# `_DIR' that specifies the suffix to ${MANDIR}. It's needed because on +# some systems, eg., Ultrix, multiple subsections (eg 3x, 3m 3n) are +# stored in generic manual section directories (eg., man3). +# +# Associated with each variable is an additional variable with the suffix +# `_U' which gives the upper case form of the variable for use in `.TH' +# commands. Useful for platforms (such as Solaris 2) that include letters +# in manual sections. +# +CMD_EXT = 1 +CMD_EXT_DIR = ${CMD_EXT} +LIB_NETWORK_EXT = 3 +LIB_NETWORK_EXT_DIR = ${LIB_NETWORK_EXT} +FORMAT_EXT = 5 +FORMAT_EXT_DIR = ${FORMAT_EXT} +DESC_EXT = 7 +DESC_EXT_DIR = ${DESC_EXT} +SYS_OPS_EXT = 8 +SYS_OPS_EXT_DIR = ${SYS_OPS_EXT} + +# +# Additional variables are defined for cross-references within manual +# entries: +# SYSCALL_EXT = extension for system calls +# BSD_SYSCALL_EXT = extension for BSD-specifc system calls. On some +# systems (eg Ultrix) these appear in section 2. +# On other system (eg SunOS 5) these are implemented +# via a BSD-compatibility library and appear in +# section 3. +# LIB_C_EXT = extension for C library routines (eg, signal) +# +SYSCALL_EXT = 2 +SYSCALL_EXT_DIR = ${SYSCALL_EXT} +BSD_SYSCALL_EXT = 2 +BSD_SYSCALL_EXT_DIR = ${BSD_SYSCALL_EXT} +LIB_C_EXT = 3 +LIB_C_EXT_DIR = ${LIB_C_EXT} + +###################################################################### +# +# No user changes needed past this point. +# +###################################################################### +# +# This sed command is used to update the manual entries so they refer to +# the appropriate section of the manual for a given platform. +# +EXT_SED_CMD = INDOT_U=`echo "${INDOT}"|tr "[a-z]" "[A-Z]"`; \ + export INDOT_U; \ + XFER_INDOT_U=`echo "${XFER_INDOT}"|tr "[a-z]" "[A-Z]"`; \ + export XFER_INDOT_U; \ + CMD_EXT_U=`echo "${CMD_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export CMD_EXT_U; \ + SYS_OPS_EXT_U=`echo "${SYS_OPS_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export SYS_OPS_EXT_U; \ + LIB_NETWORK_EXT_U=`echo "${LIB_NETWORK_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export LIB_NETWORK_EXT_U; \ + FORMAT_EXT_U=`echo "${FORMAT_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export FORMAT_EXT_U; \ + DESC_EXT_U=`echo "${DESC_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export DESC_EXT_U; \ + SYSCALL_EXT_U=`echo "${SYSCALL_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export SYSCALL_EXT_U; \ + BSD_SYSCALL_EXT_U=`echo "${BSD_SYSCALL_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export BSD_SYSCALL_EXT_U; \ + LIB_C_EXT_U=`echo "${LIB_C_EXT}"|tr "[a-z]" "[A-Z]"`; \ + export LIB_C_EXT_U; \ + sed -e "s/@INDOT@/${INDOT}/g" \ + -e "s/@INDOT_U@/$${INDOT_U}/g" \ + -e "s/@XFER_INDOT@/${XFER_INDOT}/g" \ + -e "s/@XFER_INDOT_U@/$${XFER_INDOT_U}/g" \ + -e "s/@CMD_EXT@/${CMD_EXT}/g" \ + -e "s/@CMD_EXT_U@/$${CMD_EXT_U}/g" \ + -e "s/@LIB_NETWORK_EXT@/${LIB_NETWORK_EXT}/g" \ + -e "s/@LIB_NETWORK_EXT_U@/$${LIB_NETWORK_EXT_U}/g" \ + -e "s/@FORMAT_EXT@/${FORMAT_EXT}/g" \ + -e "s/@FORMAT_EXT_U@/$${FORMAT_EXT_U}/g" \ + -e "s/@DESC_EXT@/${DESC_EXT}/g" \ + -e "s/@DESC_EXT_U@/$${DESC_EXT_U}/g" \ + -e "s/@SYS_OPS_EXT@/${SYS_OPS_EXT}/g" \ + -e "s/@SYS_OPS_EXT_U@/$${SYS_OPS_EXT_U}/g" \ + -e "s/@SYSCALL_EXT@/${SYSCALL_EXT}/g" \ + -e "s/@SYSCALL_EXT_U@/$${SYSCALL_EXT_U}/g" \ + -e "s/@BSD_SYSCALL_EXT@/${BSD_SYSCALL_EXT}/g" \ + -e "s/@BSD_SYSCALL_EXT_U@/$${BSD_SYSCALL_EXT_U}/g" \ + -e "s/@LIB_C_EXT@/${LIB_C_EXT}/g" \ + -e "s/@LIB_C_EXT_U@/$${LIB_C_EXT_U}/g" + +# +# Command used to produce manual entries +# +MK_MANFILE = ( ${EXT_SED_CMD} | ${MANROFF} ) + +# +# Extensions for the generated manual entries +# +OUT_EXT = lst +CMD_OUT_EXT = ${OUT_EXT}${CMD_EXT} +LIB_NETWORK_OUT_EXT = ${OUT_EXT}${LIB_NETWORK_EXT} +FORMAT_OUT_EXT = ${OUT_EXT}${FORMAT_EXT} +DESC_OUT_EXT = ${OUT_EXT}${DESC_EXT} +SYS_OPS_OUT_EXT = ${OUT_EXT}${SYS_OPS_EXT} + +# +# User command manual entries +# +CMD_BASE = dig host dnsquery +CMD_SRC_EXT = 1 +CMD_SRC = dig.${CMD_SRC_EXT} \ + host.${CMD_SRC_EXT} \ + dnsquery.${CMD_SRC_EXT} \ + dnskeygen.${CMD_SRC_EXT} \ + dnssigner.${CMD_SRC_EXT} +CMD_OUT = dig.${CMD_OUT_EXT} \ + host.${CMD_OUT_EXT} \ + dnsquery.${CMD_OUT_EXT} \ + dnskeygen.${CMD_OUT_EXT} \ + dnssigner.${CMD_OUT_EXT} + +# +# named manual entries +# +NAMED_BASE = named ndc +SYS_OPS_SRC_EXT = 8 +NAMED_SRC = named.${SYS_OPS_SRC_EXT} ndc.${SYS_OPS_SRC_EXT} +NAMED_OUT = named.${SYS_OPS_OUT_EXT} ndc.${SYS_OPS_OUT_EXT} + +# +# named-xfer manual entry +# +NAMED_XFER_BASE = named-xfer +NAMED_XFER_SRC = named-xfer.${SYS_OPS_SRC_EXT} +NAMED_XFER_OUT = named-xfer.${SYS_OPS_OUT_EXT} + +# +# nslookup manual entry +# +NSLOOKUP_BASE = nslookup +NSLOOKUP_SRC = nslookup.${SYS_OPS_SRC_EXT} +NSLOOKUP_OUT = nslookup.${SYS_OPS_OUT_EXT} + +# +# Network library routines manual entries +# +LIB_NETWORK_BASE = gethostbyname resolver getnetent +LIB_NETWORK_SRC_EXT = 3 +LIB_NETWORK_SRC = gethostbyname.${LIB_NETWORK_SRC_EXT} \ + resolver.${LIB_NETWORK_SRC_EXT} \ + getnetent.${LIB_NETWORK_SRC_EXT} +LIB_NETWORK_OUT = gethostbyname.${LIB_NETWORK_OUT_EXT} \ + resolver.${LIB_NETWORK_OUT_EXT} \ + getnetent.${LIB_NETWORK_OUT_EXT} + +# +# File format manual entries +# +FORMAT_BASE = resolver irs.conf +FORMAT_SRC_EXT = 5 +FORMAT_SRC = resolver.${FORMAT_SRC_EXT} \ + irs.conf.${FORMAT_SRC_EXT} +FORMAT_OUT = resolver.${FORMAT_OUT_EXT} \ + irs.conf.${FORMAT_OUT_EXT} + +# +# Feature Description manual entries +# +DESC_BASE = hostname mailaddr +DESC_SRC_EXT = 7 +DESC_SRC = hostname.${DESC_SRC_EXT} mailaddr.${DESC_SRC_EXT} +DESC_OUT = hostname.${DESC_OUT_EXT} mailaddr.${DESC_OUT_EXT} + +.SUFFIXES: .${CMD_SRC_EXT} .${CMD_OUT_EXT} \ + .${SYS_OPS_SRC_EXT} .${SYS_OPS_OUT_EXT} \ + .${LIB_NETWORK_SRC_EXT} .${LIB_NETWORK_OUT_EXT} \ + .${FORMAT_SRC_EXT} .${FORMAT_OUT_EXT} \ + .${DESC_SRC_EXT} .${DESC_OUT_EXT} + +.${CMD_SRC_EXT}.${CMD_OUT_EXT}: + @echo "$*.${CMD_SRC_EXT} -> $*.${CMD_OUT_EXT}" + @${MK_MANFILE} <$*.${CMD_SRC_EXT} >$*.${CMD_OUT_EXT} + +.${SYS_OPS_SRC_EXT}.${SYS_OPS_OUT_EXT}: + @echo "$*.${SYS_OPS_SRC_EXT} -> $*.${SYS_OPS_OUT_EXT}" + @${MK_MANFILE} <$*.${SYS_OPS_SRC_EXT} >$*.${SYS_OPS_OUT_EXT} + +.${LIB_NETWORK_SRC_EXT}.${LIB_NETWORK_OUT_EXT}: + @echo "$*.${LIB_NETWORK_SRC_EXT} -> $*.${LIB_NETWORK_OUT_EXT}" + @${MK_MANFILE} <$*.${LIB_NETWORK_SRC_EXT} >$*.${LIB_NETWORK_OUT_EXT} + +.${FORMAT_SRC_EXT}.${FORMAT_OUT_EXT}: + @echo "$*.${FORMAT_SRC_EXT} -> $*.${FORMAT_OUT_EXT}" + @${MK_MANFILE} <$*.${FORMAT_SRC_EXT} >$*.${FORMAT_OUT_EXT} + +.${DESC_SRC_EXT}.${DESC_OUT_EXT}: + @echo "$*.${DESC_SRC_EXT} -> $*.${DESC_OUT_EXT}" + @${MK_MANFILE} <$*.${DESC_SRC_EXT} >$*.${DESC_OUT_EXT} + +OUTFILES = ${CMD_OUT} ${NAMED_OUT} ${NAMED_XFER_OUT} ${NSLOOKUP_OUT} \ + ${LIB_NETWORK_OUT} ${FORMAT_OUT} ${DESC_OUT} + +all: ${OUTFILES} + +install: ${OUTFILES} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${CMD_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${LIB_NETWORK_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${FORMAT_EXT_DIR} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${DESC_EXT_DIR} + @set -x; N=${CMD_EXT}; for f in ${CMD_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${CMD_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${CMD_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NAMED_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/${INDOT}$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NAMED_XFER_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/${XFER_INDOT}$${f}.${CATEXT}; \ + done + @set -x; N=${SYS_OPS_EXT}; for f in ${NSLOOKUP_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${SYS_OPS_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${LIB_NETWORK_EXT}; for f in ${LIB_NETWORK_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${LIB_NETWORK_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${LIB_NETWORK_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${FORMAT_EXT}; for f in ${FORMAT_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${FORMAT_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${FORMAT_EXT_DIR}/$${f}.${CATEXT}; \ + done + @set -x; N=${DESC_EXT}; for f in ${DESC_BASE}; do \ + ${INSTALL} -c -m 444 ${MAN_OWNER} ${MAN_GROUP} \ + $${f}.${DESC_OUT_EXT} \ + ${DESTDIR}${DESTMAN}/${MANDIR}${DESC_EXT_DIR}/$${f}.${CATEXT}; \ + done + +${DESTDIR}${DESTMAN}/${MANDIR}${CMD_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${SYS_OPS_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${LIB_NETWORK_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${FORMAT_EXT_DIR} \ +${DESTDIR}${DESTMAN}/${MANDIR}${DESC_EXT_DIR}: + mkdir $@ + +links: FRC + @set -ex; ln -s SRC/*.[0-9] . + +depend: + +clean: + rm -f *~ *.BAK *.CKP *.orig + rm -f ${OUTFILES} + +FRC: diff --git a/contrib/bind/doc/man/dig.1 b/contrib/bind/doc/man/dig.1 new file mode 100644 index 0000000..72de71f --- /dev/null +++ b/contrib/bind/doc/man/dig.1 @@ -0,0 +1,680 @@ +.\" $Id: dig.1,v 8.3 1998/03/21 01:01:23 halley Exp $ +.\" +.\" ++Copyright++ 1993 +.\" - +.\" Copyright (c) 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. +.\" - +.\" --Copyright-- +.\" +.\" Distributed with 'dig' version 2.0 from University of Southern +.\" California Information Sciences Institute (USC-ISI). +.\" +.\" dig.1 2.0 (USC-ISI) 8/30/90 +.\" +.Dd August 30, 1990 +.Dt DIG @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm dig +.Nd send domain name query packets to name servers +.Sh SYNOPSIS +.Nm dig +.Op Ic @ Ns Ar server +.Ar domain +.Op Aq Ar query-type +.Op Aq Ar query-class +.Op Ic + Ns Aq Ar query-option +.Op Fl Aq Ar dig-option +.Op Ar %comment +.Sh DESCRIPTION +.Ic Dig +(domain information groper) is a flexible command line tool +which can be used to gather information from the Domain +Name System servers. +.Ic Dig +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. +.Pp +The usual simple use of +.Ic dig +will take the form: +.Pp +.Bd -ragged -offset indent-two +.Ic dig @ Ns Ar server domain query-type query-class +.Ed +.Pp +where: +.Bl -tag -width Fl +.It Ar server +may be either a domain name or a dot-notation +Internet address. If this optional field is omitted, +.Ic dig +will attempt to use the default name server for your machine. +.sp 1 +.Em Note: +If a domain name is specified, this will be resolved +using the domain name system resolver (i.e., BIND). If your +system does not support DNS, you may +.Em have +to specify a +dot-notation address. Alternatively, if there is a server +at your disposal somewhere, all that is required is that +.Pa /etc/resolv.conf +be present and indicate where the default +name servers reside, so that +.Ar server +itself can be resolved. See +.Xr resolver @FORMAT_EXT@ +for information on +.Pa /etc/resolv.conf . +.Sy WARNING: +Changing +.Pa /etc/resolv.conf +will affect both the standard resolver library and +.Pq potentially +several programs which use it. +As an option, the user may set the +environment variable +.Ev LOCALRES +to name a file which is to +be used instead of +.Pa /etc/resolv.conf +.Po Ns Ev LOCALRES +is specific to the +.Ic dig +resolver and is not referenced by the standard resolver +.Pc . +If the +.Ev LOCALRES +variable is not set or the specified file +is not readable, then +.Pa /etc/resolv.conf +will be used. +.It Ar domain +is the domain name for which you are requesting information. +See the +.Fl x +option (documented in the +.Sx OTHER OPTIONS +subsection of this section) for convenient way to specify inverse address +query. +.It Ar query-type +is the type of information (DNS query type) that +you are requesting. If omitted, the default is +.Dq Ar a +.Pq Dv T_A = Ar address . +The following types are recognized: +.Pp +.Bl -hang -width "hinfo T_HINFO " -compact +.It Ar a\ \ \ \ \ \ Dv T_A +network address +.It Ar any\ \ \ \ Dv T_ANY +all/any information about specified domain +.It Ar mx\ \ \ \ \ Dv T_MX +mail exchanger for the domain +.It Ar ns\ \ \ \ \ Dv T_NS +name servers +.It Ar soa\ \ \ \ Dv T_SOA +zone of authority record +.It Ar hinfo\ \ Dv T_HINFO +host information +.It Ar axfr\ \ \ Dv T_AXFR +zone transfer (must ask an authoritative server) +.It Ar txt\ \ \ \ Dv T_TXT +arbitrary number of strings +.El +.Pp +(See RFC 1035 for the complete list.) +.It Ar query-class +is the network class requested in the query. If +omitted, the default is +.Dq Ar in +.Pq Dv C_IN = Ar Internet . +The following classes are recognized: +.Pp +.Bl -tag -width "hinfo T_HINFO " -compact +.It Ar in\ \ \ \ \ Dv C_IN +Internet class domain +.It Ar any\ \ \ \ Dv C_ANY +all/any class information +.El +.Pp +(See RFC 1035 for the complete list.) +.Pp +.Em Note: +.Dq Ar Any +can be used to specify a +.Em class +and/or a +.Em type +of query. +.Ic Dig +will parse the first occurrence of +.Dq Ar any +to mean +.Ar query-type = Dv T_ANY . +To specify +.Ar query-class = Dv C_ANY , +you must either specify +.Dq any +twice, or set +.Ar query-class +using the +.Fl c +option (see below). +.El +.Ss OTHER OPTIONS +.Bl -tag -width Fl +.It % Ns Ar ignored-comment +.Dq % +is used to included an argument that is simply not +parsed. This may be useful if running +.Ic dig +in batch +mode. Instead of resolving every +.Ar @server-domain-name +in a list of queries, you can avoid the overhead of doing +so, and still have the domain name on the command line +as a reference. Example: +.Pp +.Bd -ragged -offset indent-two +.Ic dig @128.9.0.32 %venera.isi.edu mx isi.edu +.Ed +.Pp +.It Fl Aq Ar dig option +.Dq Fl +is used to specify an option which affects the operation of +.Ic dig . +The following options are currently +available (although not guaranteed to be useful): +.Bl -tag -width Fl +.It Fl x Ar dot-notation-address +Convenient form to specify inverse address mapping. +Instead of +.Dq Ic dig 32.0.9.128.in-addr.arpa , +one can simply +.Dq Ic dig -x 128.9.0.32 . +.It Fl f Ar file +File for +.Ic dig +batch mode. The file contains a list +of query specifications +( +.Ns Ic dig +command lines) which are to be executed successively. Lines beginning with +.Sq \&; , +.Sq # , +or +.Sq \en +are ignored. Other options +may still appear on command line, and will be in +effect for each batch query. +.It Fl T Ar time +Time in seconds between start of successive +queries when running in batch mode. Can be used +to keep two or more batch +.Ic dig +commands running +roughly in sync. Default is zero. +.It Fl p Ar port +Port number. Query a name server listening to a +non-standard port number. Default is 53. +.It Fl P Ns Bq Ar ping-string +After query returns, execute a +.Xr ping @SYS_OPS_EXT@ +command for response time comparison. This rather +unelegantly makes a call to the shell. The last +three lines of statistics is printed for the +command: +.Pp +.Bd -ragged -offset indent-two +.Ic ping Fl s server_name 56 3 +.Ed +.Pp +If the optional +.Dq Ar ping_string +is present, it +replaces +.Dq Ic ping Fl s +in the shell command. +.It Fl t Ar query-type +Specify type of query. May specify either an +integer value to be included in the type field +or use the abbreviated mnemonic as discussed +above (i.e., +.Ar mx = Dv T_MX ) . +.It Fl c Ar query-class +Specify class of query. May specify either an +integer value to be included in the class field +or use the abbreviated mnemonic as discussed +above (i.e., in = C_IN). +.It Fl envsav +This flag specifies that the +.Ic dig +environment +(defaults, print options, etc.), after +all of the arguments are parsed, should be saved +to a file to become the default environment. +This is useful if you do not like the standard set of +defaults and do not desire to include a +large number of options each time +.Ic dig +is used. The environment consists of resolver state +variable flags, timeout, and retries as well as the flags detailing +.Ic dig +output (see below). +If the shell environment variable +.Ev LOCALDEF +is set to the name of a file, this is where the default +.Ic dig +environment is saved. If not, the file +.Dq Pa DiG.env +is created in the current working directory. +.Pp +.Em Note: +.Ev LOCALDEF +is specific to the +.Ic dig +resolver, +and will not affect operation of the standard +resolver library. +.Pp +Each time +.Ic dig +is executed, it looks for +.Dq Pa ./DiG.env +or the file specified by the shell environment variable +.Ev LOCALDEF . +If such file exists and is readable, then the +environment is restored from this file before any arguments are parsed. +.It Fl envset +This flag only affects batch query runs. When +.Dq Fl envset +is specified on a line in a +.Ic dig +batch file, the +.Ic dig +environment after the arguments are parsed +becomes the default environment for the duration of +the batch file, or until the next line which specifies +.Dq Fl envset . +.It Xo +.Fl Op Cm no +.Ns Cm stick +.Xc +This flag only affects batch query runs. +It specifies that the +.Ic dig +environment (as read initially +or set by +.Dq Fl envset +switch) is to be restored before each query (line) in a +.Ic dig +batch file. +The default +.Dq Fl nostick +means that the +.Ic dig +environment does not stick, hence options specified on a single line +in a +.Ic dig +batch file will remain in effect for +subsequent lines (i.e. they are not restored to the +.Dq sticky +default). +.El +.It Ic + Ns Aq Ar query-option +.Dq + +is used to specify an option to be changed in the query packet or to change +.Ic dig +output specifics. Many of these are the same parameters accepted by +.Xr nslookup @SYS_OPS_EXT@ . +If an option requires a parameter, the form is as follows: +.Pp +.Bd -ragged -offset indent-two +.Ic + +.Ns Ar keyword +.Ns Op = Ns Ar value +.Ed +.Pp +Most keywords can be abbreviated. Parsing of the +.Dq + +options is very simplistic \(em a value must not be +separated from its keyword by white space. The following +keywords are currently available: +.Pp +Keyword Abbrev. Meaning [default] +.Pp +.Bl -tag -width "[no]primary (ret) " -compact +.It Xo +.Op Cm no +.Ns Cm debug\ \ \ \ +.Pq Cm deb +.Xc +turn on/off debugging mode +.Bq Cm deb +.It Xo +.Op Cm no +.Ns Cm d2\ \ \ \ \ \ \ \ \ \ +.Xc +turn on/off extra debugging mode +.Bq Cm nod2 +.It Xo +.Op Cm no +.Ns Cm recurse\ \ +.Pq Cm rec +.Xc +use/don't use recursive lookup +.Bq Cm rec +.It Xo +.Cm retry= Ns Ar # +.Cm \ \ \ \ \ +.Pq Cm ret +.Xc +set number of retries to # +.Bq 4 +.It Xo +.Cm time= Ns Ar # +.Cm \ \ \ \ \ \ +.Pq Cm ti +.Xc +set timeout length to # seconds +.Bq 4 +.It Xo +.Op Cm no +.Ns Cm ko +.Xc +keep open option (implies vc) +.Bq Cm noko +.It Xo +.Op Cm no +.Ns Cm vc +.Xc +use/don't use virtual circuit +.Bq Cm novc +.It Xo +.Op Cm no +.Ns Cm defname\ \ +.Pq Cm def +.Xc +use/don't use default domain name +.Bq Cm def +.It Xo +.Op Cm no +.Ns Cm search\ \ \ +.Pq Cm sea +.Xc +use/don't use domain search list +.Bq Cm sea +.It Xo +.Cm domain= Ns Ar NAME\ \ +.Pq Cm do +.Xc +set default domain name to +.Ar NAME +.It Xo +.Op Cm no +.Ns Cm ignore\ \ \ +.Pq Cm i +.Xc +ignore/don't ignore trunc. errors +.Bq Cm noi +.It Xo +.Op Cm no +.Ns Cm primary\ \ +.Pq Cm pr +.Xc +use/don't use primary server +.Bq Cm nopr +.It Xo +.Op Cm no +.Ns Cm aaonly\ \ \ +.Pq Cm aa +.Xc +authoritative query only flag +.Bq Cm noaa +.It Xo +.Op Cm no +.Ns Cm cmd +.Xc +echo parsed arguments +.Bq Cm cmd +.It Xo +.Op Cm no +.Ns Cm stats\ \ \ \ +.Pq Cm st +.Xc +print query statistics +.Bq Cm st +.It Xo +.Op Cm no +.Ns Cm Header\ \ \ +.Pq Cm H +.Xc +print basic header +.Bq Cm H +.It Xo +.Op Cm no +.Ns Cm header\ \ \ +.Pq Cm he +.Xc +print header flags +.Bq Cm he +.It Xo +.Op Cm no +.Ns Cm ttlid\ \ \ \ +.Pq Cm tt +.Xc +print TTLs +.Bq Cm tt +.It Xo +.Op Cm no +.Ns Cm cl +.Xc +print class info +.Bq Cm nocl +.It Xo +.Op Cm no +.Ns Cm qr +.Xc +print outgoing query +.Bq Cm noqr +.It Xo +.Op Cm no +.Ns Cm reply\ \ \ \ +.Pq Cm rep +.Xc +print reply +.Bq Cm rep +.It Xo +.Op Cm no +.Ns Cm ques\ \ \ \ \ +.Pq Cm qu +.Xc +print question section +.Bq Cm qu +.It Xo +.Op Cm no +.Ns Cm answer\ \ \ +.Pq Cm an +.Xc +print answer section +.Bq Cm an +.It Xo +.Op Cm no +.Ns Cm author\ \ \ +.Pq Cm au +.Xc +print authoritative section +.Bq Cm au +.It Xo +.Op Cm no +.Ns Cm addit\ \ \ \ +.Pq Cm ad +.Xc +print additional section +.Bq Cm ad +.It Cm pfdef +set to default print flags +.It Cm pfmin +set to minimal default print flags +.It Cm pfset= Ns Ar # +set print flags to # +(# can be hex/octal/decimal) +.It Cm pfand= Ns Ar # +bitwise and print flags with # +.It Cm pfor= Ns Ar # +bitwise or print flags with # +.El +.Pp +The +.Cm retry +and +.Cm time +options affect the retransmission strategy used by the resolver +library when sending datagram queries. The algorithm is as follows: +.Pp +.Bd -literal -offset indent +for i = 0 to retry - 1 + for j = 1 to num_servers + send_query + wait((time * (2**i)) / num_servers) + end +end +.Ed +.Pp +(Note: +.Ic dig +always uses a value of 1 for +.Dq Li num_servers . ) +.El +.Ss DETAILS +.Ic Dig +once required a slightly modified version of the BIND +.Xr resolver @LIB_NETWORK_EXT@ +library. As of BIND 4.9, BIND's resolver has been augmented to work +properly with +.Ic dig . +Essentially, +.Ic dig +is a straight-forward +(albeit not pretty) effort of parsing arguments and setting appropriate +parameters. +.Ic Dig +uses +.Xr resolver @LIB_NETWORK_EXT@ +routines +.Fn res_init , +.Fn res_mkquery , +.Fn res_send +as well as accessing the +.Ft _res +structure. +.Sh ENVIRONMENT +.Bl -tag -width "LOCALRES " -compact +.It Ev LOCALRES +file to use in place of Pa /etc/resolv.conf +.It Ev LOCALDEF +default environment file +.El +.Pp +See also the explanation of the +.Fl envsav , +.Fl envset , +and +.Xo +.Fl Op Cm no +.Ns Cm stick +.Xc +options, above. +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " -compact +.It Pa /etc/resolv.conf +initial domain name and name server addresses +.It Pa \./DiG.env +default save file for default options +.El +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +.Xr nslookup @SYS_OPS_EXT@ . +.Sh STANDARDS +RFC 1035. +.Sh AUTHOR +Steve Hotz +hotz@isi.edu +.Sh ACKNOWLEDGMENTS +.Ic Dig +uses functions from +.Xr nslookup @SYS_OPS_EXT@ +authored by Andrew Cherenson. +.Sh BUGS +.Ic Dig +has a serious case of "creeping featurism" -- the result of +considering several potential uses during it's development. It would +probably benefit from a rigorous diet. Similarly, the print flags +and granularity of the items they specify make evident their +rather ad hoc genesis. +.Pp +.Ic Dig +does not consistently exit nicely (with appropriate status) +when a problem occurs somewhere in the resolver +.Po Sy NOTE: +most of the common exit cases are handled +.Pc . +This is particularly annoying when running in +batch mode. If it exits abnormally (and is not caught), the entire +batch aborts; when such an event is trapped, +.Ic dig +simply +continues with the next query. diff --git a/contrib/bind/doc/man/dnskeygen.1 b/contrib/bind/doc/man/dnskeygen.1 new file mode 100644 index 0000000..bdc2df9 --- /dev/null +++ b/contrib/bind/doc/man/dnskeygen.1 @@ -0,0 +1,175 @@ +.\" Copyright (c) 1996 by Internet Software Consortium +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\" SOFTWARE. +.\" +.\" $Id: dnskeygen.1,v 8.2 1997/03/14 02:29:41 vixie Exp $ +.\" +.Dd October 25, 1996 +.Dt DNSKEYGEN @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm dnskeygen +.Nd generate and display public and private RSA keys for DNS +.Sh SYNOPSIS +.Nm dnskeygen +.Bo Fl g Ns Op Ar size +.Op Fl f +.Bc +.Bo Fl z +| +.Fl e +| +.Fl u +.Bc +.Op Fl i +.Op Fl m +.Op Fl p Ns Ar # +.Op Fl s Ns Ar # +.Op Fl x +.Ar name +.Sh DESCRIPTION +.Ic Dnskeygen +(DNS Key Generator) is a tool to generate and maintain RSA keys +for DNS (Domain Name System). +.Bl -tag -width Fl +.It Fl g Ns Op Ar size +.Ic Dnskeygen +will generate a new key when +the +.Dq Fl g +flag is specified. If the +.Dq Fl g +flag is not specified, then it +will attempt to display an existing key that is stored in the current +directory. If no +.Ar size +is specified after the +.Dq Fl g +flag, a key of 512 bits +will be generated; otherwise, +.Ar size +is the size of the modulus in the newly-generated key. +.It Fl f +flag can only be specified with the +.Dq Fl g +flag; this changes the +exponent used on the key. If +.Dq Fl f +is specified, the exponent is 65537, +which is suitable for encryption keys. If +.Dq Fl f +is not specified, +the exponent is 3, which is suitable for signatures and +verification of public data such as DNS records. Signing and +verifying with exponent of 65537 takes significantly more CPU time than +with exponent of 3. +.It Fl z Fl e Fl u +These flags define the type of key being generated: Zone (DNS +validation) key, End Entity (host or service) key or User (e.g. email) key, +respectively. +Each key is only allowed to be one of these. When +keys are displayed, the type of key can be changed. +.It Fl i +Indicates that the key can be used for IPSEC (Internet Protocol Security +services). +.It Fl m +Indicates that the key can be used for secure email. +.It Fl p Ns Ar # +Indicates that the key can be used for protocol number +.Ar # . +A value of +.Ar 0 +denies the use of the key for +.Em any +protocol (other than those specified by other option flags like +.Fl m ) . +A value of +.Ar 255 +allows it to be used with +.Em all +protocols. +These protocol numbers will be assigned in the latest Assigned Numbers +RFC from the Internet Assigned Numbers Authority (IANA). +.It Fl s Ns Ar # +Strength value; this value is only used when key is signing. +Interpretation of this field is to be specified later. Default value is 7. +.It Fl x +Experimental key. This indicates that software should not assume +that it should use secure protocols when talking to this zone, host, or user. +Instead, the key is being published experimentally, to debug the software +to be used to run the secure protocols, for example. +Data signed by Experimental keys will not be treated as trusted by DNS servers. +.It Ar name +The DNS name the key is for. This can be any valid DNS name. +.El +.Ss DETAILS +.Ic Dnskeygen +uses two files for each key: +.Pa <name>.priv +and +.Pa <name>.public . +File +.Pa <name>.public +contains the public key in the pubkey format: +.Pp +.D1 Ar <flags> <algorithm> <protocol> <exponent|modulus> +.Pp +.Ic Dnskeygen +.Ar name +displays the public key in both DNS RR format and pubkey format. +.Ic Dnskeygen +can display the key with different flags on subsequent runs. +The contents of the public key file will not be changed. +.Pa <name>.priv +stores the private key, in either a password-protected +format file or in a open file. The advantage of +a password-protected file is that it is harder to use the key if the file is +stolen. The disadvantage is that the password has to be given each time +the key is read. If the key is to be stored in a safe off-line place, +and only used for signing zones, then local policy may allow storing the +key in an unencrypted format. +.Sh ENVIRONMENT +No environmental variables are used. +.Sh SEE ALSO +RSAREF documentation, +.Em RFC 2065 +on secure DNS. +.Sh AUTHOR +Olafur Gudmundsson (ogud@tis.com). +.Sh ACKNOWLEDGMENTS +The underlying cryptographic math is done by the RSAREF or BSAFE libraries. +.Sh BUGS +.Ic Dnskeygen +renames old keys in such a way that only one +.Dq previous +key for a given name is kept; older keys are overwritten. (For example, +the third time a key is generated for a given name, the second key is kept +as the +.Dq previous +key, while the first key is lost. If a key is generated +.Em again +for this name--i.e., if the fourth key is generated--then the third key +will become the +.Dq previous +key and the second key will be lost.) +.Ic Dnskeygen +will not overwrite existing keys. +Only one key for each name can be stored in the current directory. If you +want to keep your old keys, rename the files before running +.Ic dnskeygen . +Otherwise you must delete them before running +.Ic dnskeygen . +.Pp +Portability of Private key file must be better tested between +different implementations of RSA. diff --git a/contrib/bind/doc/man/dnsquery.1 b/contrib/bind/doc/man/dnsquery.1 new file mode 100644 index 0000000..048d29e --- /dev/null +++ b/contrib/bind/doc/man/dnsquery.1 @@ -0,0 +1,178 @@ +.\" $Id: dnsquery.1,v 8.2 1997/03/14 02:29:41 vixie Exp $ +.\" +.\"Copyright (c) 1995, 1996 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd March 10, 1990 +.Dt DNSQUERY @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm dnsquery +.Nd query domain name servers using resolver +.Sh SYNOPSIS +.Nm dnsquery +.Op Fl n Ar nameserver +.Op Fl t Ar type +.Op Fl c Ar class +.Op Fl r Ar retry +.Op Fl p Ar period +.Op Fl d +.Op Fl s +.Op Fl v +.Ar host +.Sh DESCRIPTION +The +.Ic dnsquery +program is a general interface to nameservers via +BIND resolver library calls. The program supports +queries to the nameserver with an opcode of QUERY. +This program is intended to be a replacement or +supplement to programs like nstest, nsquery and +nslookup. All arguments except for +.Ar host +and +.Ar nameserver +are treated without case-sensitivity. +.Sh OPTIONS +.Bl -tag -width Fl +.It Fl n Ar nameserver +The nameserver to be used in the query. Nameservers can appear as either +Internet addresses of the form +.Ar w.x.y.z +or can appear as domain names. +(Default: as specified in +.Pa /etc/resolv.conf . ) +.It Fl t Ar type +The type of resource record of interest. Types include: +.Bl -tag -width "AFSDB " -compact -offset indent +.It Ar A +address +.It Ar NS +nameserver +.It Ar CNAME +canonical name +.It Ar PTR +domain name pointer +.It Ar SOA +start of authority +.It Ar WKS +well-known service +.It Ar HINFO +host information +.It Ar MINFO +mailbox information +.It Ar MX +mail exchange +.It Ar RP +responsible person +.It Ar MG +mail group member +.It Ar AFSDB +DCE or AFS server +.It Ar ANY +wildcard +.El +.Pp +Note that any case may be used. (Default: +.Ar ANY . ) +.It Fl c Ar class +The class of resource records of interest. +Classes include: +.Bl -tag -width "CHAOS " -compact -offset indent +.It Ar IN +Internet +.It Ar HS +Hesiod +.It Ar CHAOS +Chaos +.It Ar ANY +wildcard +.El +.Pp +Note that any case may be used. (Default: +.Ar IN . ) +.It Fl r Ar retry +The number of times to retry if the nameserver is +not responding. (Default: 4.) +.It Fl p Ar period +Period to wait before timing out. (Default: +.Dv RES_TIMEOUT . ) +.It Fl d +Turn on debugging. This sets the +.Dv RES_DEBUG +bit of the resolver's +.Ft options +field. (Default: no debugging.) +.It Fl s +Use a +.Em stream +rather than a packet. This uses a TCP stream connection with +the nameserver rather than a UDP datagram. This sets the +.Dv RES_USEVC +bit of the resolver's +.Ft options +field. (Default: UDP datagram.) +.It Fl v +Synonym for the +.Dq Fl s +flag. +.It Ar host +The name of the host (or domain) of interest. +.El +.Sh FILES +.Bl -tag -width "<arpa/nameser.h> " -compact +.It Pa /etc/resolv.conf +to get the default ns and search lists +.It Pa <arpa/nameser.h> +list of usable RR types and classes +.It Pa <resolv.h> +list of resolver flags +.El +.Sh DIAGNOSTICS +If the resolver fails to answer the query and debugging has not been +turned on, +.Ic dnsquery +will simply print a message like: +.Dl Query failed (rc = 1) : Unknown host +.Pp +The value of the return code is supplied by +.Ft h_errno . +.Sh SEE ALSO +.Xr nslookup @SYS_OPS_EXT@ , +.Xr nstest @CMD_EXT@ , +.Xr nsquery @CMD_EXT@ , +.Xr named @SYS_OPS_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Sh AUTHOR +Bryan Beecher +.Sh BUGS +Queries of a class other than +.Ar IN +can have interesting results +since ordinarily a nameserver only has a list of root nameservers +for class +.Ar IN +resource records. +.Pp +.Ic Dnsquery +uses a call to +.Fn inet_addr +to determine if the argument +for the +.Dq Fl n +option is a valid Internet address. Unfortunately, +.Fn inet_addr +seems to cause a segmentation fault with some (bad) +IP addresses (e.g., 1.2.3.4.5). diff --git a/contrib/bind/doc/man/dnssigner.1 b/contrib/bind/doc/man/dnssigner.1 new file mode 100644 index 0000000..1fb4ce4 --- /dev/null +++ b/contrib/bind/doc/man/dnssigner.1 @@ -0,0 +1,213 @@ +.\" Copyright (c) 1996 by Internet Software Consortium +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\" SOFTWARE. +.\" +.\" $Id: dnssigner.1,v 8.2 1997/03/14 02:29:42 vixie Exp $ +.\" +.Dd October 25, 1996 +.Dt DNSSIGNER @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm dnssigner +.Nd add signatures to DNS zone files +.Sh SYNOPSIS +.Nm dnssigner +.Op Cm signer-name Ar default_signer +.Op Cm boot-file Ar file +.Op Cm debug-file Ar file +.Op Cm out-dir Ar directory +.Op Cm seq-no Ar number +.Oo +.Cm expiration-time +.Oo Po Cm + +.Ns \&| +.Ns Cm = +.Pc Oc +.Ns Ar time +.Oc +.Op Cm hide +.Op Cm noaxfr +.Op Cm nosign +.Op Cm verify +.Op Cm update-zonekey +.Op Fl d Ns Ar level +.Sh DESCRIPTION +.Ic Dnssigner +(Sign DNS zone database) is a tool to generate signatures +for DNS (Domain Name System) resource records. It also generates +NXT records for each zone. +.Pp +.Bl -tag -width Fl +.It Cm signer-name Ar default_signer +Specifies a name of the key to use if no signer is defined using the +.Em Li $SIGNER +directive in the boot files. +.It Cm boot-file Ar file +Specifies the control file for +.Ic dnssigner , +which is in the same format as the BIND-4 +.Pa named.boot +file. +.It Cm debug-file Ar file +Redirect debug output to the specified +.Ar file ; +default is +.Pa signer_out +in the current directory. +.It Cm out-dir Ar directory +Write signed files to thie specified +.Ar directory ; +default is to use +.Pa /tmp . +.Pp +.Sy NOTE : +Specify the full path to this directory; relative paths may not work. +.It Xo Cm expiration-time +.Oo Po Cm + +.Ns \&| +.Ns Cm = +.Pc Oc +.Ns Ar time +.Xc +Time when the signature records are to +expire. Using either +.Dq Cm = +or +.Em no +sign before the +.Ar time +argument +.Po i.e., +.Do Op Cm = +.Ns Ar time +.Dc +.Pc , +the +.Ar time +is interpreted as an absolute time in seconds when the records will expire. +.Po Sy NOTE : + All such times are interpreted as Universal Times. +.Pc +With +.Dq Cm + +specified +.Pq i.e., Dq Cm + Ns Ar time , +the +.Ar time +time is interpreted as an offset into the future. +.Pp +If not specified on the command line, the default +.Cm expiration-time +is 3600*24*30 sec (30 days). +.It Cm seq-no Ar number +Force the serial number in the SOA records to the specified value. +If this parameter is not set, the serial number will be set to a value +based on the current time. +.It Cm hide +This flag will cause NXT records in zones with wildcard +records to point to +.Li *.<zone> +as the next host. The purpose of this +flag is to hide all information about valid names in a zone. +.It Cm noaxfr +Turn of generation of zone transfer signature records, +which validate the transfer of an entire zone. +.It Cm nosign +When this flag is specified, the boot files are read, NXT +records are generated and zone file is written to the output +directory. No SIG records are generated. This flag is useful for +quickly checking the format of the data in the boot files, and to +have boot files sorted into DNSSEC order. +.It Cm verify +When this flag is present, +.Ic dnssigner +will verify all +signed records and print out a confirmation message for each SIG +verified. The main use of this flag is to see how long it takes to +generate each signature. +.It Cm update-zonekey +If this flag is specified, then the zonekeys used +to sign files will be updated with new records. Specify this flag if +one or more of the keys have been updated. If there are no zonekeys +specified in the boot files, this flag will insert them. Omitting +zonekeys will cause primary nameservers to reject the zone. +.It Fl d Ns Ar level +Debug level to use for running +.Ic dnssigner ; +these levels are the same as those used by +.Xr @INDOT_U@NAMED @SYS_OPS_EXT_U@ +.El +.Ss DETAILS +.Ic Dnssigner +reads BIND-4 +.Pa named.boot +and zone files, adds SIG and NXT +records and writes out the records (to one file per zone, regardless of +how many include files the original zone was in). The files generated by +.Ic dnssigner +are ordinary textual zone files and are then normally +loaded by +.Xr @INDOT_U@NAMED @SYS_OPS_EXT_U@ +to serve the zone. +.Ic Dnssigner +\fBrequires that the PRIVATE key(s) reside in the input directory\fP. +.Pp +Making manual changes to the output files is hazardous, because most +changes will invalidate one or more signatures contained therein. This +will cause the zone to fail to load into +.Xr @INDOT_U@NAMED @SYS_OPS_EXT_U@ , +or will cause subsequent +failures in retrieving records from the zone. It is far better to make +changes in +.Ic dnssigner's +input files, and rerun +.Ic dnssigner . +.Pp +When +.Ic dnssigner +detects a delegation point, it creates a special file +.Pa <zone_name>.PARENT +which contains the RR's the parent zone signs for the +child zone (NS, KEY, NXT). The intent is that the child will include this +file when loading primary nameservers. Similarly, each zone file ends +with the +.Dq Li #include <zone_name>.PARENT +command. The records +in the +.Pa .PARENT +files are omitted from the SIG(AXFR) calculations as these +records usualy are on a different signing cycle. +.Pp +The +.Em Li Dq $SIGNER Op Ar keyname +directive can be used to change signers in a +zone. If +.Ar keyname +is omitted, signing is turned off. Keys are loaded the +first time the keys are accessed. Only records that are signed by the +zone signer (the key that signs the SOA) are included in the SIG(AXFR) +calculation. It is not generally recommended that multiple keys sign +records in the same zone, unless this is useful for dynamic updates. +.Sh ENVIRONMENT +No environmental variables are used. +.Sh SEE ALSO +.Xr @INDOT_U@NAMED @SYS_OPS_EXT_U@ , +RSAREF documentation, +Internet-Draft +.Em draft-ietf-dnssec-secext-10.txt +on Secure DNS, or its successor. +.Sh AUTHOR +Olafur Gudmundsson (ogud@tis.com) +.Sh ACKNOWLEDGMENTS +The underlying crypto math is done by the RSAREF or BSAFE libraries. diff --git a/contrib/bind/doc/man/gethostbyname.3 b/contrib/bind/doc/man/gethostbyname.3 new file mode 100644 index 0000000..0498bd8 --- /dev/null +++ b/contrib/bind/doc/man/gethostbyname.3 @@ -0,0 +1,246 @@ +.\" Copyright (c) 1983, 1987 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms are permitted provided +.\" that: (1) source distributions retain this entire copyright notice and +.\" comment, and (2) distributions including binaries display the following +.\" acknowledgement: ``This product includes software developed by the +.\" University of California, Berkeley and its contributors'' in the +.\" documentation or other materials provided with the distribution and in +.\" all advertising materials mentioning features or use of this software. +.\" 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. +.\" +.\" @(#)gethostbyname.3 6.12 (Berkeley) 6/23/90 +.\" +.Dd June 23, 1990 +.Dt GETHOSTBYNAME @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm gethostbyname , +.Nm gethostbyaddr , +.Nm gethostent , +.Nm sethostent , +.Nm endhostent , +.Nm herror +.Nd get network host entry +.Sh SYNOPSIS +.Fd #include <netdb.h> +.Ft extern int +.Fa h_errno; +.Pp +.Ft struct hostent * +.Fn gethostbyname "char *name"; +.Ft struct hostent * +.Fn gethostbyname2 "char *name" "int af"; +.Ft struct hostent * +.Fn gethostbyaddr "char *addr" "int len, type"; +.Ft struct hostent * +.Fn gethostent +.Fn sethostent "int stayopen"; +.Fn endhostent +.Fn herror "char *string"; +.Sh DESCRIPTION +.Fn Gethostbyname , +.Fn gethostbyname2 , +and +.Fn gethostbyaddr +each return a pointer to a +.Ft hostent +structure (see below) describing an internet host +referenced by name or by address, as the function names indicate. +This structure contains either the information obtained from the name server, +.Xr @INDOT@named @SYS_OPS_EXT@ , +or broken-out fields from a line in +.Pa /etc/hosts . +If the local name server is not running, these routines do a lookup in +.Pa /etc/hosts . +.Bd -literal -offset indent +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 */ +.Ed +.Pp +The members of this structure are: +.Bl -tag -width "h_addr_list" +.It h_name +Official name of the host. +.It h_aliases +A zero-terminated array of alternate names for the host. +.It h_addrtype +The type of address being returned; usually +.Dv AF_INET . +.It h_length +The length, in bytes, of the address. +.It h_addr_list +A zero-terminated array of network addresses for the host. +Host addresses are returned in network byte order. +.It h_addr +The first address in +.Li h_addr_list ; +this is for backward compatibility. +.El +.Pp +When using the nameserver, +.Fn gethostbyname +will search for the named host in each parent domain given in the +.Dq Li search +directive of +.Xr resolv.conf @FORMAT_EXT@ +unless the name contains a dot +.Pq Dq \&. . +If the name contains no dot, and if the environment variable +.Ev HOSTALIASES +contains the name of an alias file, the alias file will first be searched +for an alias matching the input name. +See +.Xr hostname @DESC_EXT@ +for the domain search procedure and the alias file format. +.Pp +.Fn Gethostbyname2 +is an evolution of +.Fn gethostbyname +intended to allow lookups in address families other than +.Dv AF_INET , +for example, +.Dv AF_INET6 . +Currently, the +.Fa af +argument must be specified as +.Dv AF_INET +else the function will return +.Dv NULL +after having set +.Ft h_errno +to +.Dv NETDB_INTERNAL . +.Pp +.Fn Sethostent +may be used to request the use of a connected TCP socket for queries. +If the +.Fa stayopen +flag is non-zero, +this sets the option to send all queries to the name server using TCP +and to retain the connection after each call to +.Fn gethostbyname +or +.Fn gethostbyaddr . +Otherwise, queries are performed using UDP datagrams. +.Pp +.Fn Endhostent +closes the TCP connection. +.Sh ENVIRONMENT +.Bl -tag -width "HOSTALIASES " -compress +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh FILES +.Bl -tag -width "HOSTALIASES " -compress +.It Pa /etc/hosts +See +.Xr hosts @FORMAT_EXT@ . +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh DIAGNOSTICS +.Pp +Error return status from +.Fn gethostbyname +and +.Fn gethostbyaddr +is indicated by return of a null pointer. +The external integer +.Ft h_errno +may then be checked to see whether this is a temporary failure +or an invalid or unknown host. +The routine +.Fn herror +can be used to print an error message describing the failure. +If its argument +.Fa string +is non-NULL, it is printed, followed by a colon and a space. +The error message is printed with a trailing newline. +.Pp +.Ft h_errno +can have the following values: +.Bl -tag -width "HOST_NOT_FOUND " -offset indent +.It Dv NETDB_INTERNAL +This indicates an internal error in the library, unrelated to the network +or name service. +.Ft errno +will be valid in this case; see +.Xr perror @SYSCALL_EXT@ . +.It Dv HOST_NOT_FOUND +No such host is known. +.It Dv TRY_AGAIN +This is usually a temporary error +and means that the local server did not receive +a response from an authoritative server. +A retry at some later time may succeed. +.It Dv NO_RECOVERY +Some unexpected server failure was encountered. +This is a non-recoverable error, as one might expect. +.It Dv NO_DATA +The requested name is valid but does not have an IP address; +this is not a temporary error. +This means that the name is known to the name server but there is no address +associated with this name. +Another type of request to the name server using this domain name +will result in an answer; +for example, a mail-forwarder may be registered for this domain. +.El +.Sh SEE ALSO +.Xr hosts @FORMAT_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Sh CAVEAT +.Pp +.Fn Gethostent +is defined, and +.Fn sethostent +and +.Fn endhostent +are redefined, +when +.Pa libc +is built to use only the routines to lookup in +.Pa /etc/hosts +and not the name server: +.Bd -filled -offset indent +.Pp +.Fn Gethostent +reads the next line of +.Pa /etc/hosts , +opening the file if necessary. +.Pp +.Fn Sethostent +is redefined to open and rewind the file. If the +.Fa stayopen +argument is non-zero, +the hosts data base will not be closed after each call to +.Fn gethostbyname +or +.Fn gethostbyaddr . +.Pp +.Fn Endhostent +is redefined to close the file. +.Ed +.Sh BUGS +All information is contained in a static area so it must be copied if it is +to be saved. Only the Internet address format is currently understood. diff --git a/contrib/bind/doc/man/getnetent.3 b/contrib/bind/doc/man/getnetent.3 new file mode 100644 index 0000000..3b941e2 --- /dev/null +++ b/contrib/bind/doc/man/getnetent.3 @@ -0,0 +1,153 @@ +.\" $Id: getnetent.3,v 8.3 1997/03/14 02:29:43 vixie Exp $ +.\" +.\"Copyright (c) 1995, 1996 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd May 20, 1996 +.Dt GETNETENT @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm getnetent , +.Nm getnetbyaddr , +.Nm getnetbyname , +.Nm setnetent , +.Nm endnetent +.Nd get networks entry +.Sh SYNOPSIS +.Fd #include <netdb.h> +.Ft struct netent * +.Fn getnetent +.Ft struct netent * +.Fn getnetbyname "char name"; +.Ft struct netent * +.Fn getnetbyaddr "unsigned long net" "int type"; +.Ft void +.Fn setnetent "int stayopen"; +.Ft void +.Fn endnetent +.Sh DESCRIPTION +The +.Fn getnetent , +.Fn getnetbyname , +and +.Fn getnetbyaddr +subroutines +each return a pointer to an object with the following structure +containing the broken-out fields of a line in the +.Pa networks +database. +.Bd -literal -offset indent +struct netent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + int n_addrtype; /* net number type */ + long n_net; /* net number */ +}; +.Ed +.Pp +The members of this structure are: +.Bl -tag -width "n_addrtype" +.It n_name +The official name of the network. +.It n_aliases +A zero-terminated list of alternate names for the network. +.It n_addrtype +The type of the network number returned: +.Dv AF_INET . +.It n_net +The network number. Network numbers are returned in machine byte +order. +.El +.Pp +If the +.Fa stayopen +flag on a +.Fn setnetent +subroutine is NULL, the +.Pa networks +database is opened. Otherwise, the +.Fn setnetent +has the effect of rewinding the +.Pa networks +database. +The +.Fn endnetent +subroutine may be called to +close the +.Pa networks +database when processing is complete. +.Pp +The +.Fn getnetent +subroutine simply reads the next +line while +.Fn getnetbyname +and +.Fn getnetbyaddr +search until a matching +.Fa name +or +.Fa net +number is found +(or until +.Dv EOF +is encountered). The +.Fa type must be +.Dv AF_INET . +The +.Fn getnetent +subroutine keeps a pointer in the database, allowing +successive calls to be used to search the entire file. +.Pp +Before a +.Ic while +loop using +.Fn getnetent , +a call to +.Fn setnetent +must be made +in order to perform initialization; a call to +.Fn endnetent +must be used after the loop. Both +.Fn getnetbyname +and +.Fn getnetbyaddr +make calls to +.Fn setnetent +and +.Fn endnetent . +.Sh FILES +.Pa /etc/networks +.Sh DIAGNOSTICS +Null pointer (0) returned on +.Dv EOF +or error. +.Sh SEE ALSO +.Xr networks @FORMAT_EXT@ , +RFC 1101. +.Sh HISTORY +The +.Fn "getnetent" , +.Fn "getnetbyaddr" , +.Fn "getnetbyname" , +.Fn "setnetent" , +and +.Fn "endnetent" +functions appeared in 4.2BSD. +.Sh BUGS +The data space used by these functions is static; if future use requires the +data, it should be copied before any subsequent calls to these functions +overwrite it. Only Internet network numbers are currently understood. +Expecting network numbers to fit in no more than 32 bits is probably naive. diff --git a/contrib/bind/doc/man/host.1 b/contrib/bind/doc/man/host.1 new file mode 100644 index 0000000..017d082 --- /dev/null +++ b/contrib/bind/doc/man/host.1 @@ -0,0 +1,316 @@ +.\" ++Copyright++ 1993 +.\" - +.\" Copyright (c) 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. +.\" - +.\" --Copyright-- +.\" $Id: host.1,v 8.2 1997/03/14 02:29:44 vixie Exp $ +.Dd December 15, 1994 +.Dt HOST @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm host +.Nd look up host names using domain server +.Sh SYNOPSIS +.Nm host +.Op Fl l +.Op Fl v +.Op Fl w +.Op Fl r +.Op Fl d +.Op Fl t Ar querytype +.Op Fl a +.Ar host +.Op Ar server +.Sh DESCRIPTION +.Ic Host +looks for information about Internet hosts. It gets this information +from a set of interconnected servers that are spread across the +country. By default, it simply converts between host names and +Internet addresses. However, with the +.Dq Fl t +or +.Dq Fl a +options, it can be used +to find all of the information about this host that is maintained +by the domain server. +.Pp +The arguments can be either host names or host numbers. The program +first attempts to interpret them as host numbers. If this fails, +it will treat them as host names. A host number consists of +first decimal numbers separated by dots, e.g. 128.6.4.194 +A host name consists of names separated by dots, e.g. topaz.rutgers.edu. +Unless the name ends in a dot, the local domain +is automatically tacked on the end. Thus, a Rutgers user can say +.Pp +.D1 Ic host topaz +.Pp +and it will actually look up "topaz.rutgers.edu". +If this fails, the name is tried unchanged (in this case, "topaz"). +This same convention is used for mail and other network utilities. +The actual suffix to tack on the end is obtained +by looking at the results of a +.Xr hostname @CMD_EXT@ +call, and using everything +starting at the first dot. (See below for a description of +.Sx CUSTOMIZING HOST NAME LOOKUP . ) +.Pp +The first argument is the host name you want to look up. +If this is a number, an +.Dq inverse query +is done, i.e. the domain +system looks in a separate set of databases used to convert numbers +to names. +.Pp +The second argument is optional. It +allows you to specify a particular server to query. If you don't +specify this argument, the default server (normally the local machine) +is used. +.Pp +If a name is specified, you may see output of three different kinds. +Here is an example that shows all of them: +.Pp +.D1 Ic % host sun4 +.Dl sun4.rutgers.edu is a nickname for ATHOS.RUTGERS.EDU +.Dl ATHOS.RUTGERS.EDU has address 128.6.5.46 +.Dl ATHOS.RUTGERS.EDU has address 128.6.4.4 +.Dl ATHOS.RUTGERS.EDU mail is handled by ARAMIS.RUTGERS.EDU +.Pp +The user has typed the command +.Dq Ic host sun4 . +The first line indicates that the name +.Dq Li sun4.rutgers.edu +is actually a nickname. The official host name is +.Dq Li ATHOS.RUTGERS.EDU . +The next two lines show the +address. If a system has more than one network interface, there +will be a separate address for each. The last line indicates +that +.Li ATHOS.RUTGERS.EDU +does not receive its own mail. Mail for +it is taken by +.Li ARAMIS.RUTGERS.EDU . +There may be more than one +such line, since some systems have more than one other system +that will handle mail for them. Technically, every system that +can receive mail is supposed to have an entry of this kind. If +the system receives its own mail, there should be an entry +the mentions the system itself; for example, +.Pp +.D1 Li XXX mail is handled by XXX +.Pp +However, many systems that receive +their own mail do not bother to mention that fact. If a system +has a +.Dq Li mail is handled by +entry, but no address, this indicates +that it is not really part of the Internet, but a system that is +on the network will forward mail to it. Systems on Usenet, Bitnet, +and a number of other networks have entries of this kind. +.Sh OPTIONS +There are a number of options that can be used before the +host name. Most of these options are meaningful only to the +staff who have to maintain the domain database. +.Bl -tag -width Fl +.It Fl w +This causes +.Ic host +to wait forever for a response. Normally +it will time out after approximate one minute. +.It Fl v +Use "verbose" format for printout. This +is the official domain master file format, which is documented +in the man page for +.Xr @INDOT@named @SYS_OPS_EXT@ . +Without this option, output still follows +this format in general terms, but some attempt is made to make it +more intelligible to normal users. Without +.Dq Fl v , +any "a", "mx", and "cname" records +are written out as "has address", "mail is handled by", and +"is a nickname for" (respectively), and TTL and class fields are not shown. +.It Fl r +Turn off recursion in the request. +This means that the name server will return only data it has in +its own database. It will not ask other servers for more +information. +.It Fl d +Turn on debugging. Network transactions are shown in detail. +.It Fl t Ar querytype +Allows you to specify a particular +.Ar querytype +of information +to be looked up. The arguments are defined in the man page for +.Xr @INDOT@named @SYS_OPS_EXT@ . +Currently-supported types include: +.Dq Cm a , +.Dq Cm ns , +.Dq Cm md , +.Dq Cm mf , +.Dq Cm cname , +.Dq Cm soa , +.Dq Cm mb , +.Dq Cm mg , +.Dq Cm mr , +.Dq Cm null , +.Dq Cm wks , +.Dq Cm ptr , +.Dq Cm hinfo , +.Dq Cm minfo , +.Dq Cm mx , +.Dq Cm uinfo , +.Dq Cm uid , +.Dq Cm gid , +.Dq Cm unspec . +Additionally, the wildcard, which may be written +as either +.Dq Cm any +or +.Dq Cm * , +can be used to specify any (all) of the above types. +Types must be given in lower case. +Note that the default is to look first for +.Dq Cm a , +and then +.Dq Cm mx , +except that if the verbose option is turned on, the default is only +.Dq Cm a . +The +.Dq Fl t +option is particularly useful for filtering information returned by +.Ic host ; +see the explanation of the +.Dq Fl l +option, below, for more information. +.It Fl a +.Dq all ; +this is equivalent to +.Dq Fl v Fl t Cm any . +.It Fl l +List a complete domain; e.g.: +.Pp +.D1 Ic host -l rutgers.edu +.Pp +will give a listing of all hosts in the rutgers.edu domain. The +.Dq Fl t +option is used to filter what information is presented, as you +would expect. The default is address information, which also +include PTR and NS records. The command +.Pp +.D1 Ic host -l -v -t any rutgers.edu +.Pp +will give a complete download of the zone data for rutgers.edu, +in the official master file format. (However the SOA record is +listed twice, for arcane reasons.) +.Pp +.Sy NOTE: +.Dq Fl l +is implemented by +doing a complete zone transfer and then filtering out the information +the you have asked for. This command should be used only if it +is absolutely necessary. +.Sh CUSTOMIZING HOST NAME LOOKUP +In general, if the name supplied by the user does not +have any dots in it, a default domain is appended to the end. +This domain can be defined in +.Pa /etc/resolv.conf , +but is normally derived +by taking the local hostname after its first dot. The user can override +this, and specify a different default domain, using the environment +variable +.Ev LOCALDOMAIN . +In addition, the user can supply his own abbreviations for host names. +They should be in a file consisting of one line per abbreviation. +Each line contains an abbreviation, a space, and then the full +host name. The name file must be contained in the +.Ev HOSTALIASES +environment variable. +.Sh ENVIRONMENT +.Bl -tag -width "/etc/resolv.conf " -compress +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " -compress +.It Pa /etc/resolv.conf +See +.Xr resolver @FORMAT_EXT@ . +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Sh BUGS +Unexpected effects can happen when you type a name that is not +part of the local domain. Please always keep in mind the +fact that the local domain name is tacked onto the end of every +name, unless it ends in a dot. Only if this fails is the name +used unchanged. +.Pp +The +.Dq Fl l +option only tries the first name server listed for the +domain that you have requested. If this server is dead, you +may need to specify a server manually. E.g., to get a listing +of foo.edu, you could try +.Pp +.D1 Ic host -t ns foo.edu +.Pp +to get a list of all the name servers for foo.edu, and then try +.Pp +.D1 Ic host -l foo.edu xxx +.Pp +for all +.Dq Ic xxx +on the list of name servers, until you find one that works. diff --git a/contrib/bind/doc/man/hostname.7 b/contrib/bind/doc/man/hostname.7 new file mode 100644 index 0000000..6a92d64 --- /dev/null +++ b/contrib/bind/doc/man/hostname.7 @@ -0,0 +1,171 @@ +.\" Copyright (c) 1987 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms are permitted +.\" provided that the above copyright notice and this paragraph are +.\" duplicated in all such forms and that any documentation, +.\" advertising materials, and other materials related to such +.\" distribution and use acknowledge that the software was developed +.\" by the University of California, 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'' AND WITHOUT ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" @(#)hostname.7 6.4 (Berkeley) 1/16/90 +.\" +.Dd February 16, 1994 +.Dt HOSTNAME @DESC_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm hostname +.Nd host name resolution description +.Sh DESCRIPTION +Hostnames are domains. A domain is a hierarchical, dot-separated list +of subdomains. For example, the machine +.Dq Li monet , +in the +.Dq Li Berkeley +subdomain of the +.Dq Li EDU +subdomain of the Internet Domain Name System would be represented as +.Pp +.Dl monet.Berkeley.EDU +.Pp +(with no trailing dot). +.Pp +Hostnames are often used with network client and server programs, +which must generally translate the name to an address for use. +(This task is usually performed by the library routine +.Xr gethostbyname @LIB_NETWORK_EXT@ . ) +The default method for resolving hostnames by the Internet name resolver is +to follow RFC 1535's security recommendations. Actions can be taken +by the administrator to override these recommendations and to have the +resolver behave the same as earlier, non-RFC 1535 +resolvers. +.Pp +The default method (using RFC 1535 guidelines) follows: +.Pp +If the name consists of a single component, i.e. contains no dot, and if the +environment variable +.Dq Ev HOSTALIASES +is set to the name of a file, +that file is searched for a string matching the input hostname. The file +should consist of lines made up of two strings separated by white-space, the +first of which is the hostname alias, and the second of which is the complete +hostname to be substituted for that alias. If a case-insensitive match is +found between the hostname to be resolved and the first field of a line in +the file, the substituted name is looked up with no further processing. +.Pp +If there is at least one dot in the name, then the name is first tried +.Dq as-is . +The number of dots to cause this action is configurable by setting the +threshold using the +.Dq Li ndots +option in +.Pa /etc/resolv.conf +(default: 1). If the name ends with a dot, the trailing dot is +removed, and the remaining name is looked up (regardless of the setting of +the +.Li ndots +option), without further processing. +.Pp +If the input name does not end with a trailing dot, it is looked up by +searching through a list of domains until a match is found. If neither the +search option in the +.Pa /etc/resolv.conf +file or the +.Dq Ev LOCALDOMAIN +environment variable is used, then the +search list of domains contains only the full domain specified by the +.Li domain +option (in +.Pa /etc/resolv.conf ) +or the domain used in the local hostname (see +.Xr hostname @CMD_EXT@ +and +.Xr resolver @FORMAT_EXT@ ) . +For example, if the +.Dq Li domain +option is set to +.Li CS.Berkeley.EDU , +then only +.Li CS.Berkeley.EDU +will be in the search list, and this will be the only +domain appended to the partial hostname. For example, if +.Dq Li lithium +is the name to be resolved, this would make +.Li lithium.CS.Berkeley.EDU +the only name to be tried using the search list. +.Pp +If the +.Li search +option is used in +.Pa /etc/resolv.conf +or the environment variable +.Dq Ev LOCALDOMAIN +is set by the user, then +the search list will include what is set by these methods. For +example, if the +.Dq Li search +option contained +.Pp +.Dl CS.Berkeley.EDU CChem.Berkeley.EDU Berkeley.EDU +.Pp +then the partial hostname (e.g., +.Dq Li lithium ) +will be tried with +.Em each +domain name appended (in the same order specified); the resulting hostnames +that would be tried are: +.Bd -literal -offset indent +lithium.CS.Berkeley.EDU +lithium.CChem.Berkeley.EDU +lithium.Berkeley.EDU +.Ed +.Pp +The environment variable +.Dq Ev LOCALDOMAIN +overrides the +.Dq Li search +and +.Dq Li domain +options, and if both +.Li search +and +.Li domain +options are present in the resolver configuration file, then only the +.Em last +one listed is used (see +.Xr resolver @FORMAT_EXT@ ) . +.Pp +If the name was not previously tried +.Dq as-is +(i.e., it fell below the +.Dq Li ndots +threshold or did not contain a dot), then the name as +originally provided is attempted. +.Sh ENVIRONMENT +.Bl -tag -width "/etc/resolv.conf " -compress +.It Ev LOCALDOMAIN +Affects domains appended to partial hostnames. +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.El +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " -compress +.It Pa /etc/resolv.conf +See +.Xr resolve @FORMAT_EXT@ . +.It Ev HOSTALIASES +Name of file containing +.Pq Ar host alias , full hostname +pairs. +.Sh SEE ALSO +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +.Xr mailaddr @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ . diff --git a/contrib/bind/doc/man/irs.conf.5 b/contrib/bind/doc/man/irs.conf.5 new file mode 100644 index 0000000..50216e3 --- /dev/null +++ b/contrib/bind/doc/man/irs.conf.5 @@ -0,0 +1,197 @@ +.\" Copyright (c) 1996 by Internet Software Consortium +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\" CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\" SOFTWARE. +.\" +.\" Copyright (c) 1986, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 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: irs.conf.5,v 8.2 1997/11/17 06:46:27 vixie Exp $ +.\" +.Dd November 16, 1997 +.Dt IRS.CONF 5 +.Os BIND 8.1 +.Sh NAME +.Nm irs.conf +.Nd Information Retrieval System configuration file +.Sh SYNOPSIS +.Nm irs.conf +.Sh DESCRIPTION +The +.Xr irs 3 +functions are a set of routines in the C library which provide access to +various system maps. +The maps that irs currently controls are the following: passwd, group, +services, protocols, hosts, networks and netgroup. +When a program first calls a function that accesses one of these maps, +the irs configuration file is read, +and the source of each map is determined for the life of the process. +.Pp +If this file does not exist, +the irs routines default to using local sources for all information, +with the exception of the host and networks maps, +which use the Domain Name System (DNS). +.Pp +Each record in the file consists of one line. +A record consists of a map-name, an access-method and possibly a (comma +delimited) set of options, +separated by tabs or spaces. +Blank lines, and text between a # and a newline are ignored. +.Pp +Available maps: +.Bd -literal -offset indent +Map name Information in map +========= ================================== +passwd User authentication information +group User group membership information +services Network services directory +protocols Network protocols directory +hosts Network hosts directory +networks Network "network names" directory +netgroup Network "host groups" directory +.Ed +.Pp +Available access methods: +.Bd -literal -offset indent +Access method Description +============= ================================================= +local Use a local file, usually in /etc +dns Use the domain name service (includes hesiod) +nis Use the Sun-compatible Network Information Service +.Ed +.Pp +Available options: +.Bd -literal -offset indent +Option Description +======== ================================================ +continue don't stop searching if you can't find something +merge don't stop searching if you CAN find something +.Ed +.Pp +The continue option creates +.Dq "union namespaces" +whereby subsequent access methods of the same map type can be tried +if a name cannot be found using earlier access methods. +This can be quite confusing in the case of host names, +since the name to address and address to name mappings can be visibly +asymmetric even though the data used by any given access method is +entirely consistent. This behavior is, therefore, not the default. +.Pp +The merge option only affects lookups in the groups map. +If set, subsequent access methods will be tried in order to cause +local users to appear in NIS (or other remote) groups in addition +to the local groups. +.Sh EXAMPLE +.Bd -literal -offset indent +# Get password entries from local file, or failing that, NIS +passwd local continue +passwd nis + +# Build group membership from both local file, and NIS. +group local continue,merge +group nis + +# Services comes from just the local file. +services local + +protocols local + +# Hosts comes first from DNS, failing that, the local file +hosts dns continue +hosts local + +networks local + +netgroup local +.Ed +.Sh NOTES +If a local user needs to be in the local host's +.Dq wheel +group but not in every host's +.Dq wheel +group, put them in the local host's +.Pa /etc/group +.Dq wheel +entry and set up the +.Dq groups +portion of your +.Pa /etc/irs.conf +file as: +.Bd -literal -offset indent +group local continue,merge +group nis +.Ed +.Pp +NIS takes a long time to time out. +Especially for hosts if you use the +.Fl d +option to your server's +.Dq ypserv +daemon. +.Pp +It is important that the +.Pa irs.conf +file contain an entry for each map. +If a map is not mentioned in the +.Pa irs.conf +file, all queries to that map will fail. +.Pp +The classic NIS mechanism for specifying union namespaces is to add an entry +to a local map file whose name is ``+''. In IRS, this is done via ``continue'' +and/or ``merge'' map options. While this results in a small incompatibility +when local map files are imported from non-IRS systems to IRS systems, there +are compensating advantages in security and configurability. +.Sh FILES +.Bl -tag -width /etc/irs.confXXXX -compact +.It Pa /etc/irs.conf +The file +.Nm irs.conf +resides in +.Pa /etc . +.El +.Sh SEE ALSO +.Xr groups 5 , +.Xr hosts 5 , +.Xr netgroup 5 , +.Xr networks 5 , +.Xr passwd 5 , +.Xr protocols 5 , +.Xr services 5 diff --git a/contrib/bind/doc/man/mailaddr.7 b/contrib/bind/doc/man/mailaddr.7 new file mode 100644 index 0000000..270fe9c --- /dev/null +++ b/contrib/bind/doc/man/mailaddr.7 @@ -0,0 +1,179 @@ +.\" Copyright (c) 1983, 1987 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms are permitted +.\" provided that the above copyright notice and this paragraph are +.\" duplicated in all such forms and that any documentation, +.\" advertising materials, and other materials related to such +.\" distribution and use acknowledge that the software was developed +.\" by the University of California, 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'' AND WITHOUT ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" @(#)mailaddr.7 6.5 (Berkeley) 2/14/89 +.\" +.Dd February 14, 1989 +.Dt MAILADDR @DESC_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm mailaddr +.Nd mail addressing description +.Sh DESCRIPTION +Mail addresses are based on the ARPANET protocol listed at the end of this +manual page. These addresses are in the general format +.Pp +.Bd -ragged -offset indent-two +.Li user@domain +.Ed +.Pp +where a domain is a hierarchical, dot-separated list of subdomains. For +example, the address +.Pp +.Bd -ragged -offset indent-two +.Li eric@monet.berkeley.edu +.Ed +.Pp +is normally interpreted from right to left: the message should go to the +ARPA name tables (which do not correspond exactly to the physical ARPANET), +then to the Berkeley gateway, after which it should go to the local host +.Dq Li monet . +When the message reaches +.Li monet , +it is delivered to the user +.Dq Li eric . +.Pp +Unlike some other forms of addressing, this does not imply any routing. +Thus, although this address is specified as an ARPA address, it might +travel by an alternate route if that were more convenient or efficient. +For example, at Berkeley, the associated message would probably go directly +to +.Li monet +over the Ethernet rather than going via the Berkeley ARPANET gateway. +.Ss Abbreviation +.Pp +Under certain circumstances, it may not be necessary to type the entire +domain name. In general, anything following the first dot may be omitted +if it is the same as the domain from which you are sending the message. +For example, a user on +.Dq Li calder.berkeley.edu +could send to +.Dq Li eric@monet +without adding the +.Dq Li berkeley.edu +since it is the same on both sending and receiving hosts. +.Pp +Certain other abbreviations may be permitted as special cases. For +example, at Berkeley, ARPANET hosts may be referenced without adding the +.Dq Li berkeley.edu +as long as their names do not conflict with a local host name. +.Ss Compatibility +.Pp +Certain old address formats are converted to the new format to provide +compatibility with the previous mail system. In particular, +.Bd -ragged -offset indent-two +.Li user@host.ARPA +.Ed +.Pp +is allowed and +.Bd -ragged -offset indent-two +.Li host:user +.Ed +.Pp +is converted to +.Bd -ragged -offset indent-two +.Li user@host +.Ed +.Pp +in order to be consistent with the +.Xr rcp @CMD_EXT@ +command. +.Pp +Also, the syntax +.Bd -ragged -offset indent-two +.Li host!user +.Ed +.Pp +is converted to: +.Bd -ragged -offset indent-two +.Li user@host.UUCP +.Ed +.Pp +This is normally converted back to the +.Dq Li host!user +form before being sent on, for compatibility with older UUCP hosts. +.Pp +The current implementation is not able to route messages automatically through +the UUCP network. Until that time you must explicitly tell the mail system +which hosts to send your message through to get to your final destination. +.Ss Case Distinctions +.Pp +Domain names (i.e., anything after the +.Dq Li @ +sign) may be given in any mixture +of upper and lower case with the exception of UUCP hostnames. Most hosts +accept any combination of case in user names, with the notable exception of +MULTICS sites. +.Ss Route-addrs. +.Pp +Under some circumstances it may be necessary to route a message through +several hosts to get it to the final destination. Normally this routing +is done automatically, but sometimes it is desirable to route the message +manually. Addresses which show these relays are termed +.Dq route-addrs. +These use the syntax: +.Bd -ragged -offset indent-two +.Li <@hosta,@hostb:user@hostc> +.Ed +.Pp +This specifies that the message should be sent to +.Li hosta , +from there to +.Li hostb , +and finally to +.Li hostc . +This path is forced even if there is a more efficient path to +.Li hostc . +.Pp +Route-addrs occur frequently on return addresses, since these are generally +augmented by the software at each host. It is generally possible to ignore +all but the +.Dq Li user@domain +part of the address to determine the actual sender. +.Ss Postmaster +.Pp +Every site is required to have a user or user alias designated +.Dq Li postmaster +to which problems with the mail system may be addressed. +.Ss Other Networks +.Pp +Some other networks can be reached by giving the name of the network as the +last component of the domain. +.Em This is not a standard feature +and may +.Em not +be supported at all sites. For example, messages to CSNET or BITNET sites +can often be sent to +.Dq Li user@host.CSNET +or +.Dq Li user@host.BITNET , +respectively. +.Sh BUGS +The RFC822 group syntax +.Pq Dq Li group:user1,user2,user3; +is not supported except in the special case of +.Dq LI group:; +because of a conflict with old berknet-style addresses. +.Pp +Route-Address syntax is grotty. +.Pp +UUCP- and ARPANET-style addresses do not coexist politely. +.Sh SEE ALSO +.Xr mail @CMD_EXT@ , +.Xr sendmail @SYS_OPS_EXT@ ; +Crocker, D. H., RFC822, +.Do +Standard for the Format of Arpa Internet Text Messages +.Dc . diff --git a/contrib/bind/doc/man/mkdep.1 b/contrib/bind/doc/man/mkdep.1 new file mode 100644 index 0000000..177ab1a --- /dev/null +++ b/contrib/bind/doc/man/mkdep.1 @@ -0,0 +1,84 @@ +.\" Copyright (c) 1987 Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms are permitted +.\" provided that the above copyright notice and this paragraph are +.\" duplicated in all such forms and that any documentation, +.\" advertising materials, and other materials related to such +.\" distribution and use acknowledge that the software was developed +.\" by the University of California, 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'' AND WITHOUT ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" @(#)mkdep.1 5.8 (Berkeley) 10/24/88 +.\" +.Dd October 24, 1988 +.Dt MKDEP @CMD_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm mkdep +.Nd construct Makefile dependency list +.Sh SYNOPSIS +.Nm mkdep +.Op Fl ap +.Op Fl f Ar depend_file +.Op Ar flags +.Ar file ... +.Sh DESCRIPTION +.Ic Mkdep +takes a set of flags for the C compiler and a list +of C source files as arguments and constructs a set of +.Li include +file dependencies which are written into the file +.Pa depend_file , +or +.Dq Pa .depend +by default. An example of its use in a +.Pa Makefile +might be: +.Bd -literal -offset indent +CFLAGS= -O -DDEBUG -I../include -I. +SRCS= file1.c file2.c + +depend: + mkdep ${CFLAGS} ${SRCS} +.Ed +.Pp +where the macro +.Dq Li SRCS +is the list of C source files and the macro +.Dq Li CFLAGS +is the list of flags for the C compiler. +.Pp +If the +.Dq Fl p +option is provided, +.Ic mkdep +produces dependencies +of the form +.Dq Li program: program.c +so that subsequent calls to +.Xr make @CMD_EXT@ +will produce +.Dq Pa program +directly from its C module rather than using an intermediate +.Dq Pa \&.o +module. This is useful in directories which +contain many programs, each of whose source is contained in a single +C module. +.Pp +The +.Dq Fl a +option causes appending to the output file, so that multiple +.Xo Ic mkdep +.Ns 's +.Xc +may be run from a single +.Pa Makefile . +.Sh SEE ALSO +.Xr cc @CMD_EXT@ , +.Xr cpp @CMD_EXT@ , +.Xr make @CMD_EXT@ . diff --git a/contrib/bind/doc/man/named-xfer.8 b/contrib/bind/doc/man/named-xfer.8 new file mode 100644 index 0000000..766d583 --- /dev/null +++ b/contrib/bind/doc/man/named-xfer.8 @@ -0,0 +1,147 @@ +.\" ++Copyright++ 1985 +.\" - +.\" 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. +.\" - +.\" --Copyright-- +.\" +.\" from named.8 6.6 (Berkeley) 2/14/89 +.\" +.Dd June 26, 1993 +.Dt @XFER_INDOT_U@NAMED-XFER @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm @XFER_INDOT@named-xfer +.Nd ancillary agent for inbound zone transfers +.Sh SYNOPSIS +.Nm named-xfer +.Fl z Ar zone_to_transfer +.Fl f Ar db_file +.Fl s Ar serial_no +.Op Fl d Ar debuglevel +.Op Fl l Ar debug_log_file +.Op Fl t Ar trace_file +.Op Fl p Ar port# +.Op Fl S +.Ar nameserver ... +.Sh DESCRIPTION +.Ic Named-xfer +is an ancillary program executed by +.Xr @INDOT@named @SYS_OPS_EXT@ +to perform an inbound zone transfer. It is rarely executed directly, and then +only by system administrators who are trying to debug a zone transfer problem. +See RFC's 1033, 1034, and 1035 for more information on the Internet +name-domain system. +.Pp +Options are: +.Bl -tag -width Fl +.It Fl z Ar zone_to_transfer +specifies the name of the zone to be transferred. +.It Fl f Ar db_file +specifies the name of the +.Ar db_file +into which the zone should be dumped +when it is received from the primary server. +.It Fl s Ar serial_no +specifies the serial number of our current copy of this zone. If the +.Sy SOA RR +we get from the primary server does not have a serial +number higher than this, the transfer will be aborted. +.It Fl d Ar debuglevel +Print debugging information. +The +.Ar debuglevel +is a number determines the level of messages printed. +.It Fl l Ar debug_log_file +Specifies a log file for debugging messages. The default is system- +dependent but is usually in +.Pa /var/tmp +or +.Pa /usr/tmp . +Note that this only applies if +.Dq Fl d +is also specified. +.It Fl t Ar trace_file +Specifies a +.Ar trace_file +which will contain a protocol trace of the zone +transfer. This is probably only of interest to people debugging the name +server itself. +.It Fl p Ar port# +Use a different port number. The default is the standard port number +as returned by +.Xr getservbyname @LIB_NETWORK_EXT@ +for the service +.Dq Li domain . +.It Fl S +Perform a restricted transfer of only the SOA, NS records and glue A records +for the zone. The SOA record will not be loaded by +.Xr @INDOT@named @SYS_OPS_EXT@ +but will be used to +determine when to verify the NS records. See the +.Dq Li stubs +directive in +.Xr @INDOT@named @SYS_OPS_EXT@ +for more information. +.El +.Pp +Additional arguments are taken as name server addresses in so-called +.Dq dotted-quad +syntax +.Em only; +no host name are allowed here. At least one address must be specified. +Any additional addresses will be tried, in order, if the first one fails +to transfer to us successfully. +.Sh SEE ALSO +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +RFC 882, RFC 883, RFC 973, RFC 974, RFC 1033, RFC 1034, RFC 1035, RFC 1123, +.Dq Name Server Operations Guide for Sy BIND . diff --git a/contrib/bind/doc/man/named.8 b/contrib/bind/doc/man/named.8 new file mode 100644 index 0000000..e3c0b82 --- /dev/null +++ b/contrib/bind/doc/man/named.8 @@ -0,0 +1,417 @@ +.\" ++Copyright++ 1985, 1996 +.\" - +.\" Copyright (c) 1985, 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 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-- +.\" +.\" @(#)named.8 6.6 (Berkeley) 2/14/89 +.\" +.Dd February 1, 1996 +.Dt @INDOT_U@NAMED @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm @INDOT@named +.Nd Internet domain name server (DNS) +.Sh SYNOPSIS +.Nm @INDOT@NAMED +.Op Fl d Ar debuglevel +.Op Fl p Ar port# +.Oo Fl Po +.Cm b Ns \&| Ns Cm c +.Pc +.Ar config_file +.Oc +.Op Fl f q r +.Op Fl w Ar directory +.Op Ar config_file +.Sh DESCRIPTION +.Ic Named +is the Internet domain name server. +See RFC's 1033, 1034, and 1035 for more information on the Internet +name-domain system. Without any arguments, +.Ic named +will read the default configuration file +.Pa /etc/named.conf , +read any initial data, and listen for queries. A +.Ar config_file +argument given at the end of the command line will override any +.Ar config_file +specified by using the +.Dq Fl b +or +.Dq Fl c +flags. +.Pp +.Sy NOTE: +Several of +.Nm named Ns 's +options, and much more of its behaviour, can be controlled in the configuration +file. Please refer to the configuration file guide included with this +.Sy BIND +distribution for further information. +.Pp +Options are: +.Bl -tag -width Fl +.It Fl d Ar debuglevel +Print debugging information. +The +.Ar debuglevel +is a number determines the level of messages printed. If negative, +.Ar debuglevel +is set to +.Dq 1 . +.Pp +.Sy NOTE: +The new debugging framework is considerably more sophisticated than it +was in older versions of +.Nm @INDOT@NAMED . +The configuration file's +.Dq Li logging +statement allows for multiple, distinct levels of debugging for each of +a large set of categories of events (such as queries, transfers in or out, +etc.). Please refer to the configuration file guide included with this +.Sy BIND +distribution for further information about these extensive new capabilities. +.It Fl p Ar port# +Use the specified remote port number; this is the port number to which +.Nm @INDOT@NAMED +will send queries. The default value is the standard port number, i.e., +the port number returned by +.Xr getservbyname @LIB_NETWORK_EXT@ +for service +.Dq Li domain . +.Pp +.Sy NOTE: +Previously, the syntax +.Dq Fl p Ar port# Ns Op Ar \&/localport# +was supported; the first port was that used when contacting +.Em remote +servers, and the second one was the service port bound by the +.Em local +instance of +.Nm @INDOT_U@NAMED . +The current usage is equivalent to the old usage without the +.Ar localport# +specified; this functionality can be specified with the +.Dq Li listen-on +clause of the configuration file's +.Dq Li options +statement. +.It Xo Fl Po +.Cm b Ns \&| Ns Cm c +.Pc Ar config_file +.Xc +Use an alternate +.Ar config_file ; +this argument is overridden by any +.Ar config_file +which is specified at the end of the command line. +The default value is +.Pa /etc/named.conf . +.It Fl f +Run this process in the foreground; don't +.Xr fork @SYSCALL_EXT@ +and daemonize. (The default is to daemonize.) +.It Fl q +Trace all incoming queries if +.Nm @INDOT_U@NAMED +has been compiled with +.Li QRYLOG +defined. +.Pp +.Sy NOTE: +This option is deprecated in favor of the +.Dq Li queries +.Em logging category +of the configuration file's +.Dq Li logging +statement; for more information, please refer to the configuration file guide +included with this distribution of +.Sy BIND . +.It Fl r +Turns recursion off in the server. Answers can come only from local +(primary or secondary) zones. This can be used on root servers. +The default is to use recursion. +.Pp +.Sy NOTE: +This option can be overridden by and is deprecated in favor of the +.Dq Li recursion +clause of the configuration file's +.Dq Li options +statement. +.It Fl w Ar directory +Sets the working directory of the server. The +.Dq Li directory +clause of the configuration file's +.Dq Li options +statement overrides any value specified on the command line. +The default working directory is the current directory +.Pq Dq \&. . +.El +.Pp +Any additional argument is taken as the name of the configuration file, for +compatibility with older implementations; as noted above, this argument +overrides any +.Ar config_file +specified by the use of the +.Dq Fl b +or +.Dq Fl c +flags. If no further argument is given, then the default configuration file +is used +.Pq Pa /etc/named.conf . +.Ss Master File Format +The master file consists of control information and a list of resource +records for objects in the zone of the forms: +.Bd -literal -offset indent +$INCLUDE <filename> <opt_domain> +$ORIGIN <domain> +<domain> <opt_ttl> <opt_class> <type> <resource_record_data> +.Ed +.Pp +where: +.Bl -tag -width "opt_domain " +.It Ar domain +is +.Dq Li \&. +for root, +.Dq Li @ +for the current origin, or a standard domain name. If +.Ar domain +is a standard domain name that does +.Em not +end with +.Dq Li \&. , +the current origin is appended to the domain. Domain names ending with +.Dq Li \&. +are unmodified. +.It Ar opt_domain +This field is used to define an origin for the data in an included file. +It is equivalent to placing an +.Li $ORIGIN +statement before the first line of the included file. The field is optional. +Neither the +.Ar opt_domain +field nor +.Li $ORIGIN +statements in the included file modify the current origin for this file. +.It Ar opt_ttl +An optional integer number for the time-to-live field. +It defaults to zero, meaning the minimum value specified in the SOA +record for the zone. +.It Ar opt_class +The object address type; currently only one type is supported, +.Dv IN , +for objects connected to the DARPA Internet. +.It Ar type +This field contains one of the following tokens; the data expected in the +.Ar resource_record_data +field is in parentheses: +.Bl -tag -width "HINFO " -offset indent +.It Dv A +a host address (dotted-quad IP address) +.It Dv NS +an authoritative name server (domain) +.It Dv MX +a mail exchanger (domain), preceded by a preference value (0..32767), +with lower numeric values representing higher logical preferences. +.It Dv CNAME +the canonical name for an alias (domain) +.It Dv SOA +marks the start of a zone of authority (domain of originating host, +domain address of maintainer, a serial number and the following +parameters in seconds: refresh, retry, expire and minimum TTL (see RFC 883)). +.It Dv NULL +a null resource record (no format or data) +.It Dv RP +a Responsible Person for some domain name (mailbox, TXT-referral) +.It Dv PTR +a domain name pointer (domain) +.It Dv HINFO +host information (cpu_type OS_type) +.El +.El +.Pp +Resource records normally end at the end of a line, +but may be continued across lines between opening and closing parentheses. +Comments are introduced by semicolons and continue to the end of the line. +.Pp +.Sy NOTE: +There are other resource record types not shown here. You should +consult the +.Sy BIND +Operations Guide +.Pq Dq BOG +for the complete +list. Some resource record types may have been standardized in newer RFC's +but not yet implemented in this version of +.Sy BIND . +.Ss SOA Record Format +Each master zone file should begin with an SOA record for the zone. +An example SOA record is as follows: +.Bd -literal +@ IN SOA ucbvax.Berkeley.EDU. rwh.ucbvax.Berkeley.EDU. ( + 1989020501 ; serial + 10800 ; refresh + 3600 ; retry + 3600000 ; expire + 86400 ) ; minimum +.Ed +.Pp +The SOA specifies a serial number, which should be changed each time the +master file is changed. Note that the serial number can be given as a +dotted number, but this is a +.Em very +unwise thing to do since the +translation to normal integers is via concatenation rather than +multiplication and addition. You can spell out the year, month, day of +month, and 0..99 version number and still fit inside the unsigned 32-bit +size of this field. (It's true that we will have to rethink this strategy in +the year 4294, but we're not worried about it.) +.Pp +Secondary servers +check the serial number at intervals specified by the refresh time in +seconds; if the serial number changes, a zone transfer will be done to load +the new data. If a master server cannot be contacted when a refresh is due, +the retry time specifies the interval at which refreshes should be attempted. +If a master server cannot be contacted within the interval given by the +expire time, all data from the zone is discarded by secondary servers. The +minimum value is the time-to-live +.Pq Dq TTL +used by records in the file with no explicit time-to-live value. +.Sh NOTES +The boot file directives +.Dq Li domain +and +.Dq Li suffixes +have been +obsoleted by a more useful, resolver-based implementation of +suffixing for partially-qualified domain names. The prior mechanisms +could fail under a number of situations, especially when then local +nameserver did not have complete information. +.Pp +The following signals have the specified effect when sent to the +server process using the +.Xr kill @CMD_EXT@ +command: +.Pp +.Bl -tag -width "SIGWINCH" +.It Dv SIGHUP +Causes server to read +.Pa named.conf +and reload the database. If the server +is built with the +.Li FORCED_RELOAD +compile-time option, then +.Dv SIGHUP +will +also cause the server to check the serial number on all secondary zones; +normally, the serial numbers are only checked at the SOA-specified intervals. +.It Dv SIGINT +Dumps the current data base and cache to +.Dq Pa /var/tmp/named_dump.db +or the value of +.Dv _PATH_DUMPFILE . +.It Dv SIGILL +Dumps statistics data into +.Pa named.stats +if the server is compiled with +.Li -DSTATS . +Statistics data is appended to the file. +.It Dv SIGSYS +Dumps the profiling data in +.Pa /var/tmp +if the server is compiled with profiling (server forks, chdirs and exits). +.It Dv SIGTERM +Dumps the primary and secondary database files. +Used to save modified data on shutdown if the +server is compiled with dynamic updating enabled. +.It Dv SIGUSR1 +Turns on debugging; each +.Dv SIGUSR1 +increments debug level. +.Po Dv SIGEMT +on older systems without +.Dv SIGUSR1 . +.Pc +.It Dv SIGUSR2 +Turns off debugging completely. +.Po Dv SIGFPE +on older systems without +.Dv SIGUSR2 . +.Pc +.It Dv SIGWINCH +Toggles logging of all incoming queries via +.Xr syslog @SYS_OPS_EXT@ +(requires server to have been built with the +.Li QRYLOG +option). +.Sh FILES +.Bl -tag -width "/var/tmp/named_dump.db (_PATH_DUMPFILE) " -compact +.It Pa /etc/named.conf +default name server configuration file +.It Pa /var/run/named.pid Pq Dv _PATH_PIDFILE +the process id +.It Pa /var/tmp/named_dump.db Pq Dv _PATH_DUMPFILE +dump of the name server database +.It Pa /var/tmp/named.run Pq file: Dv _PATH_DEBUG +debug output +.It Pa /var/tmp/named.stats Pq file: Dv _PATH_STATS +nameserver statistics data +.El +.Sh SEE ALSO +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr kill @CMD_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ , +.Xr signal @SYSCALL_EXT@ , +RFC 882, RFC 883, RFC 973, RFC 974, RFC 1033, RFC 1034, RFC 1035, RFC 1123, +.Dq Name Server Operations Guide for Sy BIND diff --git a/contrib/bind/doc/man/ndc.8 b/contrib/bind/doc/man/ndc.8 new file mode 100644 index 0000000..247ef96 --- /dev/null +++ b/contrib/bind/doc/man/ndc.8 @@ -0,0 +1,142 @@ +.\" Copyright (c) 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. +.\" +.Dd November 27, 1994 +.Dt @INDOT_U@NDC @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm @INDOT@ndc +.Nd name daemon control interface +.Sh SYNOPSIS +.Nm @INDOT@ndc +.Ar directive +.Op Ar ... +.Sh DESCRIPTION +This command allows the name server administrator to send various signals +to the name server, or to restart it. Zero or more directives may be given, +from the following list: +.Bl -tag -width "querylog" +.It Ic status +Displays the current status of +.Xr @INDOT@named @SYS_OPS_EXT@ +as shown by +.Xr ps @CMD_EXT@ . +.It Ic dumpdb +Causes +.Ic @INDOT@named +to dump its database and cache to +.Pa /var/tmp/named_dump.db +(uses the +.Dv INT +signal.) +.It Ic reload +Causes +.Ic @INDOT@named +to check the serial numbers of all primary and secondary zones +and to reload those that have changed (uses the +.Dv HUP +signal.) +.It Ic stats +Causes +.Ic @INDOT@named +to dump its statistics to +.Pa /var/tmp/named.stats +(uses the +.Dv IOT +or +.Dv ABRT +signal.) +.It Ic trace +Causes +.Ic @INDOT@named +to increment its +.Dq tracing level +by one. Whenever the tracing level +is nonzero, trace information will be written to +.Pa /var/tmp/named.run . +Higher tracing levels result in more detailed information. +(Uses the +.Dv USR1 +signal.) +.It Ic notrace +Causes +.Ic @INDOT@named +to set its +.Dq tracing level +to zero, closing +.Pa /var/tmp/named.run , +if it is open (uses the +.Dv USR2 +signal.) +.It Ic querylog +Causes +.Ic @INDOT@named +to toggle the +.Dq query logging +feature, which while on will result in a +.Xr syslog @SYSCALL_EXT@ +of each incoming query (uses the +.Dv WINCH +signal.) Note that query logging +consumes quite a lot of log file space. This directive may also be given as +.Ic qrylog . +.It Ic start +Causes +.Ic @INDOT@named +to be started, as long as it isn't already running. +.It Ic stop +Causes +.Ic @INDOT@named +to be stopped, if it is running. +.It Ic restart +Causes +.Ic @INDOT@named +to be killed and restarted. +.El +.Sh BUGS +Arguments to +.Ic @INDOT@named +are not preserved by +.Ic restart , +or known by +.Ic start . +.Pp +Some mechanism for controlling the parameters and environment should exist. +.Pp +Implemented as a +.Xr sh @CMD_EXT@ +script. +.Sh AUTHOR +Paul Vixie (Internet Software Consortium) +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr @INDOT@named.reload @SYS_OPS_EXT@ , +.Xr @INDOT@named.restart @SYS_OPS_EXT@ . diff --git a/contrib/bind/doc/man/nslookup.8 b/contrib/bind/doc/man/nslookup.8 new file mode 100644 index 0000000..5ba1850 --- /dev/null +++ b/contrib/bind/doc/man/nslookup.8 @@ -0,0 +1,534 @@ +.\" +.\" ++Copyright++ 1985, 1989 +.\" - +.\" 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. +.\" - +.\" 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-- +.\" +.\" @(#)nslookup.8 5.3 (Berkeley) 6/24/90 +.\" +.Dd June 24, 1990 +.Dt NSLOOKUP @SYS_OPS_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm nslookup +.Nd query Internet name servers interactively +.Sh SYNOPSIS +.Nm nslookup +.Op Fl option Ar ... +.Op Ar host-to-find | Fl Op Ar server +.Sh DESCRIPTION +.Ic Nslookup +is a program to query Internet domain name servers. +.Ic Nslookup +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 +Interactive mode is entered in the following cases: +.Bl -tag -width "a) " +.It a) +when no arguments are given (the default name server will be used), +.It b) +when the first argument is a hyphen (-) and the second argument +is the host name or Internet address of a name server. +.El +.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 +The options listed under the +.Dq Li set +command below can be specified in +the +.Pa .nslookuprc +file in the user's home directory if they are listed +one per line. 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: +.Bd -literal -offset indent + nslookup -query=hinfo -timeout=10 +.Ed +.Sh INTERACTIVE COMMANDS +Commands may be interrupted at any time by typing a control-C. +To exit, type a control-D +.Pq Dv EOF +or type +.Li exit . +The command line length must be less than 256 characters. +To treat a built-in command as a host name, +precede it with an escape character +.Pq .&\\ . +.Sy N.B.: An unrecognized command will be interpreted as a host name. +.Bl -tag -width "lserver" +.It Ar host Op Ar server +Look up information for +.Ar host +using the current default server or using +.Ar server , +if specified. +If +.Ar host +is an Internet address and the query type is +.Dv A +or +.Dv PTR , +the name of the host is returned. +If +.Ar host +is a name and does not have a trailing period, the default +domain name is appended to the name. (This behavior depends on the state of the +.Ic set +options +.Ic domain , srchlist , defname , +and +.Ic search . ) +.Pp +To look up a host not in the current domain, append a period to +the name. +.It Ic server Ar domain +.It Ic lserver Ar domain +Change the default server to +.Ar domain ; +.Ic lserver +uses the initial server to look up information about +.Ar domain , +while +.Ic server +uses the current default server. +If an authoritative answer can't be found, the names of servers +that might have the answer are returned. +.It Ic root +Changes the default server to the server for the root of the domain name space. +Currently, the host +.Li ns.internic.net +is used. +(This command is a synonym for +.Dq Ic lserver ns.internic.net . ) +The name of the root server can be changed with the +.Dq Ic set root +command. +.It Xo Ic finger Op Ar name +.Op Ic > Ar filename +.Xc +.It Xo Ic finger Op Ar name +.Op Ic >> Ar filename +.Xc +Connects with the finger server on the current host. +The current host is defined when a previous lookup for a host +was successful and returned address information (see the +.Dq Ic set querytype=A +command). +The +.Ar name +is optional. +.Ic > +and +.Ic >> +can be used to redirect output in the usual manner. +.It Xo Ic ls Op Ar option +.Ar domain Op Ic > Ar filename +.Xc +.It Xo Ic ls Op Ar option +.Ar domain Op Ic >> Ar filename +.Xc +List the information available for +.Ar domain , +optionally creating or appending to +.Ar filename . +The default output contains host names and their Internet addresses. +.Ar Option +can be one of the following: +.Bl -tag -width "-a " +.It Fl t Ar querytype +lists all records of the specified type (see +.Ar querytype +below). +.It Fl a +lists aliases of hosts in the domain; +synonym for +.Dq Fl t Dv CNAME . +.It Fl d +lists all records for the domain; +synonym for +.Dq Fl t Dv ANY . +.It Fl h +lists CPU and operating system information for the domain; +synonym for +.Dq Fl t Dv HINFO . +.It Fl s +lists well-known services of hosts in the domain; +synonym for +.Dq Fl t Dv WKS . +.El +.Pp +When output is directed to a file, hash marks are printed for every +50 records received from the server. +.It Ic view Ar filename +Sorts and lists the output of previous +.Ic ls +command(s) with +.Xr more @CMD_EXT@ . +.It Ic help +.It Ic ? +Prints a brief summary of commands. +.It Ic exit +Exits the program. +.It Xo Ic set Ar keyword +.Ns Op = Ns Ar value +.Xc +This command is used to change state information that affects the lookups. +Valid keywords are: +.Bl -tag -width "class=v" +.It Ic all +Prints the current values of the frequently-used options to +.Ic set . +Information about the current default server and host is also printed. +.It Ic class= Ns Ar value +Change the query class to one of: +.Bl -tag -width "HESIOD " +.It Dv IN +the Internet class +.It Dv CHAOS +the Chaos class +.It Dv HESIOD +the MIT Athena Hesiod class +.It Dv ANY +wildcard (any of the above) +.El +.Pp +The class specifies the protocol group of the information. +.Pp +(Default = +.Dv IN ; +abbreviation = +.Ic cl ) +.It Xo Op Ic no +.Ns Ic debug +.Xc +Turn debugging mode on. A lot more information is printed about the +packet sent to the server and the resulting answer. +.Pp +(Default = +.Ic nodebug ; +abbreviation = +.Xo Op Ic no +.Ns Ic deb ) +.Xc +.It Xo Op Ic no +.Ns Ic d2 +.Xc +Turn exhaustive debugging mode on. +Essentially all fields of every packet are printed. +.Pp +(Default = +.Ic nod2 ) +.It Ic domain= Ns Ar name +Change the default domain name to +.Ar name . +The default domain name is appended to a lookup request depending on the +state of the +.Ic defname +and +.Ic search +options. +The domain search list contains the parents of the default domain if it has +at least two components in its name. +For example, if the default domain +is CC.Berkeley.EDU, the search list is CC.Berkeley.EDU and Berkeley.EDU. +Use the +.Dq Ic set srchlist +command to specify a different list. +Use the +.Dq Ic set all +command to display the list. +.Pp +(Default = value from +.Xr hostname @CMD_EXT@ , +.Pa /etc/resolv.conf , +or +.Ev LOCALDOMAIN; +abbreviation = +.Ic do ) +.It Ic srchlist= Ns Ar name1/name2/... +Change the default domain name to +.Ar name1 +and the domain search list +to +.Ar name1 , name2 , +etc. A maximum of 6 names separated by slashes (/) +can be specified. +For example, +.Bd -literal -offset indent +set srchlist=lcs.MIT.EDU/ai.MIT.EDU/MIT.EDU +.Ed +.Pp +sets the domain to lcs.MIT.EDU and the search list to the three names. +This command overrides the +default domain name and search list of the +.Dq Ic set domain +command. +Use the +.Dq Ic set all +command to display the list. +.Pp +(Default = value based on +.Xr hostname @CMD_EXT@ , +.Pa /etc/resolv.conf , +or +.Ev LOCALDOMAIN; +abbreviation = +.Ic srchl ) +.It Xo Op Ic no +.Ns Ic defname +.Xc +If set, append the default domain name to a single-component lookup request +(i.e., one that does not contain a period). +.Pp +(Default = +.Ic defname ; +abbreviation = +.Xo Op Ic no +.Ns Ic defname ) +.Xc +.It Xo Op Ic no +.Ns Ic search +.Xc +If the lookup request contains at least one period but +.Em doesn't +end with a trailing period, append the domain names in the domain search list +to the request until an answer is received. +.Pp +(Default = +.Ic search ; +abbreviation = +.Xo Op Ic no +.Ns Ic sea ) +.Xc +.It Ic port= Ns Ar value +Change the default TCP/UDP name server port to +.Ar value . +.Pp +(Default = 53; +abbreviation = +.Ic \&po ) +.It Ic querytype= Ns Ar value +.It Ic type= Ns Ar value +Change the type of information query to one of: +.Bl -tag -width "HINFO " +.It Dv A +the host's Internet address. +.It Dv CNAME +the canonical name for an alias. +.It Dv HINFO +the host CPU and operating system type. +.It Dv MINFO +the mailbox or mail list information. +.It Dv MX +the mail exchanger. +.It Dv NS +the name server for the named zone. +.It Dv PTR +the host name if the query is an Internet address; +otherwise, the pointer to other information. +.It Dv SOA +the domain's +.Dq start-of-authority +information. +.It Dv TXT +the text information. +.It Dv UINFO +the user information. +.It Dv WKS +the supported well-known services. +.El +.Pp +Other types +.Pq Dv ANY, AXFR, MB, MD, MF, NULL +are described in the RFC-1035 document. +.Pp +(Default = +.Dv A ; +abbreviations = +.Ic q , ty ) +.It Xo Op Ic no +.Ns Ic recurse +.Xc +Tell the name server to query other servers if it does not have the +information. +.Pp +(Default = +.Ic recurse ; +abbreviation = +.Xo Op Ic no +.Ns Ic rec ) +.Xc +.It Ic retry= Ns Ar number +Set the number of retries to +.Ar number . +When a reply to a request is not received within a certain +amount of time (changed with +.Dq Ic set timeout ) , +the timeout period is doubled and the request is resent. +The retry value controls how many times a request is resent before giving up. +.Pp +(Default = 4, abbreviation = +.Ic ret ) +.It Ic root= Ns Ar host +Change the name of the root server to +.Ar host . +This affects the +.Dq Ic root +command. +.Pp +(Default = +.Ic ns.internic.net. ; +abbreviation = +.Ic ro ) +.It Ic timeout= Ns Ar number +Change the initial timeout interval for waiting for a reply to +.Ar number +seconds. Each retry doubles the timeout period. +.Pp +(Default = 5 seconds; abbreviation = +.Ic ti ) +.It Xo Op Ic no +.Ns Ic vc +.Xc +Always use a virtual circuit when sending requests to the server. +.Pp +(Default = +.Ic novc ; +abbreviation = +.Xo Op Ic no +.Ns Ic v ) +.Xc +.It Xo Op Ic no +.Ns Ic ignoretc +.Xc +Ignore packet truncation errors. +.Pp +(Default = +.Ic noignoretc ; +abbreviation = +.Xo Op Ic no +.Ns Ic ig ) +.Xc +.El +.El +.Sh DIAGNOSTICS +If the lookup request was not successful, an error message is printed. +Possible errors are: +.Bl -tag -width "Timed" +.It Li Timed out +The server did not respond to a request after a certain amount of +time (changed with +.Dq Ic set timeout= Ns Ar value ) +and a certain number of retries (changed with +.Dq Ic set retry= Ns Ar value ) . +.It Li \&No response from server +No name server is running on the server machine. +.It Li \&No records +The server does not have resource records of the current query type for the +host, although the host name is valid. +The query type is specified with the +.Dq Ic set querytype +command. +.It Li Non-existent domain +The host or domain name does not exist. +.It Li Connection refused +.It Li Network is unreachable +The connection to the name or finger server could not be made +at the current time. +This error commonly occurs with +.Ic ls +and +.Ic finger +requests. +.It Li Server failure +The name server found an internal inconsistency in its database +and could not return a valid answer. +.It Li Refused +The name server refused to service the request. +.It Li Format error +The name server found that the request packet was not in the proper format. +It may indicate an error in +.Nm nslookup . +.El +.Sh FILES +.Bl -tag -width "/usr/share/misc/nslookup.helpXXX" -compact +.It Pa /etc/resolv.conf +initial domain name and name server addresses +.It Pa $HOME/.nslookuprc +user's initial options +.It Pa /usr/share/misc/nslookup.help +summary of commands +.Sh ENVIRONMENT +.Bl -tag -width "HOSTALIASESXXXX" -compact +.It Ev HOSTALIASES +file containing host aliases +.It Ev LOCALDOMAIN +overrides default domain +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ ; +RFC-1034, +.Dq Domain Names - Concepts and Facilities ; +RFC-1035, +.Dq Domain Names - Implementation and Specification . +.Sh AUTHOR +Andrew Cherenson diff --git a/contrib/bind/doc/man/resolver.3 b/contrib/bind/doc/man/resolver.3 new file mode 100644 index 0000000..fe0c3f7 --- /dev/null +++ b/contrib/bind/doc/man/resolver.3 @@ -0,0 +1,300 @@ +.\" Copyright (c) 1985, 1995 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms are permitted provided +.\" that: (1) source distributions retain this entire copyright notice and +.\" comment, and (2) distributions including binaries display the following +.\" acknowledgement: ``This product includes software developed by the +.\" University of California, Berkeley and its contributors'' in the +.\" documentation or other materials provided with the distribution and in +.\" all advertising materials mentioning features or use of this software. +.\" 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. +.\" +.\" @(#)resolver.3 6.5 (Berkeley) 6/23/90 +.\" $Id: resolver.3,v 8.5 1997/03/14 02:29:48 vixie Exp $ +.\" +.Dd December 11, 1995 +.Dt RESOLVER @LIB_NETWORK_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm res_query , +.Nm res_search , +.Nm res_mkquery , +.Nm res_send , +.Nm res_init , +.Nm dn_comp , +.Nm dn_expand +.Nd resolver routines +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <netinet/in.h> +.Fd #include <arpa/nameser.h> +.Fd #include <resolv.h> +.Fn res_query "const char *dname" "int class, type" "u_char *answer" "int anslen" +.Fn res_search "const char *dname" "int class, type" "u_char *answer" "int anslen" +.Fn res_mkquery "int op" "const char *dname" "int class, type" "const char *data" "int datalen" "struct rrec *newrr" "u_char *buf" "int buflen" +.Fn res_send "const u_char *msg" "int msglen" "u_char *answer" "int anslen" +.Fn res_init +.Fn dn_comp "const char *exp_dn" "u_char *comp_dn" "int length" "u_char **dnptrs, **lastdnptr" +.Fn dn_expand "const u_char *msg, *eomorig, *comp_dn" "char *exp_dn" "int length" +.Fn herror "const char *s" +.Fn hstrerror "int err" +.Sh DESCRIPTION +These routines are used for making, sending and interpreting +query and reply messages with Internet domain name servers. +.Pp +Global configuration and state information that is used by the +resolver routines is kept in the structure +.Ft _res . +Most of the values have reasonable defaults and can be ignored. +Options +stored in +.Ft _res.options +are defined in +.Pa resolv.h +and are as follows. +Options are stored as a simple bit mask containing the bitwise +.Dq OR +of the options enabled. +.Bl -tag -width "RES_DEB" +.It Dv RES_INIT +True if the initial name server address and default domain name are +initialized (i.e., +.Fn res_init +has been called). +.It Dv RES_DEBUG +Print debugging messages. +.It Dv RES_AAONLY +Accept authoritative answers only. +With this option, +.Fn res_send +should continue until it finds an authoritative answer or finds an error. +Currently this is not implemented. +.It Dv RES_USEVC +Use TCP connections for queries instead of UDP datagrams. +.It Dv RES_STAYOPEN +Used with +.Dv RES_USEVC +to keep the TCP connection open between queries. +This is useful only in programs that regularly do many queries. +UDP should be the normal mode used. +.It Dv RES_IGNTC +Unused currently (ignore truncation errors, i.e., don't retry with TCP). +.It Dv RES_RECURSE +Set the recursion-desired bit in queries. +This is the default. +(\c +.Fn res_send +does not do iterative queries and expects the name server +to handle recursion.) +.It Dv RES_DEFNAMES +If set, +.Fn res_search +will append the default domain name to single-component names +(those that do not contain a dot). +This option is enabled by default. +.It Dv RES_DNSRCH +If this option is set, +.Fn res_search +will search for host names in the current domain and in parent domains; see +.Xr hostname @DESC_EXT@ . +This is used by the standard host lookup routine +.Xr gethostbyname @LIB_NETWORK_EXT@ . +This option is enabled by default. +.It Dv RES_NOALIASES +This option turns off the user level aliasing feature controlled by +the +.Ev HOSTALIASES +environment variable. Network daemons should set this option. +.El +.Pp +The +.Fn res_init +routine +reads the configuration file (if any; see +.Xr resolver @FORMAT_EXT@ ) +to get the default domain name, search list and +the Internet address of the local name server(s). +If no server is configured, the host running the resolver is tried. +The current domain name is defined by the hostname +if not specified in the configuration file; +it can be overridden by the environment variable +.Ev LOCALDOMAIN . +This environment variable may contain several blank-separated +tokens if you wish to override the +.Dq search list +on a per-process basis. This is similar to the +.Ic search +command in the configuration file. +Another environment variable +.Pq Dq Ev RES_OPTIONS +can be set to override certain internal resolver options which are otherwise +set by changing fields in the +.Ft _res +structure or are inherited from the configuration file's +.Ic options +command. The syntax of the +.Dq Ev RES_OPTIONS +environment variable is explained in +.Xr resolver @FORMAT_EXT@ . +Initialization normally occurs on the first call +to one of the other resolver routines. +.Pp +The +.Fn res_query +function provides an interface to the server query mechanism. +It constructs a query, sends it to the local server, +awaits a response, and makes preliminary checks on the reply. +The query requests information of the specified +.Fa type +and +.Fa class +for the specified fully-qualified domain name +.Fa dname . +The reply message is left in the +.Fa answer +buffer with length +.Fa anslen +supplied by the caller. +.Pp +The +.Fn res_search +routine makes a query and awaits a response like +.Fn res_query , +but in addition, it implements the default and search rules +controlled by the +.Dv RES_DEFNAMES +and +.Dv RES_DNSRCH +options. +It returns the first successful reply. +.Pp +The remaining routines are lower-level routines used by +.Fn res_query . +The +.Fn res_mkquery +function +constructs a standard query message and places it in +.Fa buf . +It returns the size of the query, or \-1 if the query is +larger than +.Fa buflen . +The query type +.Fa op +is usually +.Dv QUERY , +but can be any of the query types defined in +.Pa <arpa/nameser.h> . +The domain name for the query is given by +.Fa dname . +.Fa Newrr +is currently unused but is intended for making update messages. +.Pp +The +.Fn res_send +routine +sends a pre-formatted query and returns an answer. +It will call +.Fn res_init +if +.Dv RES_INIT +is not set, send the query to the local name server, and +handle timeouts and retries. +The length of the reply message is returned, or \-1 if there were errors. +.Pp +The +.Fn dn_comp +function +compresses the domain name +.Fa exp_dn +and stores it in +.Fa comp_dn . +The size of the compressed name is returned or \-1 if there were errors. +The size of the array pointed to by +.Fa comp_dn +is given by +.Fa length . +The compression uses +an array of pointers +.Fa dnptrs +to previously-compressed names in the current message. +The first pointer points to +to the beginning of the message and the list ends with +.Dv NULL . +The limit to the array is specified by +.Fa lastdnptr . +A side effect of +.Fn dn_comp +is to update the list of pointers for labels inserted into the message +as the name is compressed. If +.Fa dnptr +is +.Dv NULL , +names are not compressed. If +.Fa lastdnptr +is +.Dv NULL , +the list of labels is not updated. +.Pp +The +.Fn dn_expand +entry +expands the compressed domain name +.Fa comp_dn +to a full domain name. +The compressed name is contained in a query or reply message; +.Fa msg +is a pointer to the beginning of the message. +The uncompressed name is placed in the buffer indicated by +.Fa exp_dn +which is of size +.Fa length . +The size of compressed name is returned or \-1 if there was an error. +.Pp +The external variable +.Ft h_errno +is set whenever an error occurs during resolver operation. The following +definitions are given in +.Pa <netdb.h> : +.Bd -literal +#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 not found, or SERVFAIL */ +#define NO_RECOVERY 3 /* Nonrecoverable: FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data for requested type */ +.Ed +.Pp +The +.Fn herror +function writes a message to the diagnostic output consisting of the string +parameter +.Fa s , +the constant string ": ", and a message corresponding to the value of +.Ft h_errno . +.Pp +The +.Fn hstrerror +function returns a string which is the message text corresponding to the +value of the +.Fa err +parameter. +.Sh FILES +.Bl -tag -width "/etc/resolv.conf " +.It Pa /etc/resolv.conf +See +.Xr resolver @FORMAT_EXT@ . +.El +.Sh SEE ALSO +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @FORMAT_EXT@ ; +RFC1032, RFC1033, RFC1034, RFC1035, RFC974; +SMM:11, +.Dq Name Server Operations Guide for Sy BIND diff --git a/contrib/bind/doc/man/resolver.5 b/contrib/bind/doc/man/resolver.5 new file mode 100644 index 0000000..044bf60 --- /dev/null +++ b/contrib/bind/doc/man/resolver.5 @@ -0,0 +1,183 @@ +.\" Copyright (c) 1986 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms are permitted +.\" provided that the above copyright notice and this paragraph are +.\" duplicated in all such forms and that any documentation, +.\" advertising materials, and other materials related to such +.\" distribution and use acknowledge that the software was developed +.\" by the University of California, 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'' AND WITHOUT ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.\" @(#)resolver.5 5.9 (Berkeley) 12/14/89 +.\" $Id: resolver.5,v 8.4 1997/03/14 02:29:49 vixie Exp $ +.\" +.Dd November 11, 1993 +.Dt RESOLVER @FORMAT_EXT_U@ +.Os BSD 4 +.Sh NAME +.Nm resolver +.Nd resolver configuration file +.Sh SYNOPSIS +.Pa /etc/resolv.conf +.Sh DESCRIPTION +The +.Nm resolver +is a set of routines in the C library +.Pq Xr resolve @LIB_NETWORK_EXT@ +that provide access to the Internet Domain Name System. +The +.Nm resolver +configuration file contains information that is read +by the +.Nm resolver +routines the first time they are invoked by a process. +The file is designed to be human readable and contains a list of +keywords with values that provide various types of +.Nm resolver +information. +.Pp +On a normally configured system, this file should not be necessary. +The only name server to be queried will be on the local machine, +the domain name is determined from the host name, +and the domain search path is constructed from the domain name. +.Pp +The different configuration options are: +.Bl -tag -width "nameser" +.It Li nameserver +Internet address (in dot notation) of a name server that the +.Nm resolver +should query. Up to +.Dv MAXNS +(currently 3) name servers may be listed, one per keyword. +If there are multiple servers, the +.Nm resolver +library queries them in the order listed. +If no +.Li nameserver +entries are present, the default is to use the name server on the local machine. +(The algorithm used is to try a name server, and if the query times out, +try the next, until out of name servers, +then repeat trying all the name servers +until a maximum number of retries are made). +.It Li domain +Local domain name. +Most queries for names within this domain can use short names +relative to the local domain. +If no +.Li domain +entry is present, the domain is determined from the local host name returned by +.Xr gethostname @BSD_SYSCALL_EXT@ ; +the domain part is taken to be everything after the first +.Sq \&. . +Finally, if the host name does not contain a domain part, the root +domain is assumed. +.It Li search +Search list for host-name lookup. +The search list is normally determined from the local domain name; +by default, it contains only the local domain name. +This may be changed by listing the desired domain search path +following the +.Li search +keyword with spaces or tabs separating the names. +Most +.Nm resolver +queries will be attempted using each component +of the search path in turn until a match is found. +Note that this process may be slow and will generate a lot of network +traffic if the servers for the listed domains are not local, +and that queries will time out if no server is available +for one of the domains. +.Pp +The search list is currently limited to six domains +with a total of 256 characters. +.It Li sortlist +Allows addresses returned by gethostbyname to be sorted. +A +.Li sortlist +is specified by IP address netmask pairs. The netmask is +optional and defaults to the natural netmask of the net. The IP address +and optional network pairs are separated by slashes. Up to 10 pairs may +be specified. For example: +.Bd -literal -offset indent +sortlist 130.155.160.0/255.255.240.0 130.155.0.0 +.Ed +.It Li options +Allows certain internal +.Nm resolver +variables to be modified. +The syntax is +.D1 Li options Ar option ... +where +.Ar option +is one of the following: +.Bl -tag -width "ndots:n " +.It Li debug +sets +.Dv RES_DEBUG +in +.Ft _res.options . +.It Li ndots: Ns Ar n +sets a threshold for the number of dots which +must appear in a name given to +.Fn res_query +(see +.Xr resolver @LIB_NETWORK_EXT@ ) +before an +.Em initial absolute query +will be made. The default for +.Ar n +is +.Dq 1 , +meaning that if there are +.Em any +dots in a name, the name will be tried first as an absolute name before any +.Em search list +elements are appended to it. +.El +.El +.Pp +The +.Li domain +and +.Li search +keywords are mutually exclusive. +If more than one instance of these keywords is present, +the last instance wins. +.Pp +The +.Li search +keyword of a system's +.Pa resolv.conf +file can be +overridden on a per-process basis by setting the environment variable +.Dq Ev LOCALDOMAIN +to a space-separated list of search domains. +.Pp +The +.Li options +keyword of a system's +.Pa resolv.conf +file can be amended on a per-process basis by setting the environment variable +.Dq Ev RES_OPTIONS to a space-separated list of +.Nm resolver +options as explained above under +.Li options . +.Pp +The keyword and value must appear on a single line, and the keyword +(e.g., +.Li nameserver ) +must start the line. The value follows the keyword, separated by white space. +.Sh FILES +.Pa /etc/resolv.conf +.Sh SEE ALSO +.Xr gethostbyname @LIB_NETWORK_EXT@ , +.Xr hostname @DESC_EXT@ , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr resolver @LIB_NETWORK_EXT@ , +.Xr resolver @FORMAT_EXT@ . +.Dq Name Server Operations Guide for Sy BIND diff --git a/contrib/bind/doc/misc/DynamicUpdate b/contrib/bind/doc/misc/DynamicUpdate index 4cd43a1..fb4152c 100644 --- a/contrib/bind/doc/misc/DynamicUpdate +++ b/contrib/bind/doc/misc/DynamicUpdate @@ -1,5 +1,3 @@ -[ Deprecated, unsupported, nonfunctional, but not yet completely excised. ] - Description of Dynamic Update and T_UNSPEC Code diff --git a/contrib/bind/doc/misc/FAQ.1of2 b/contrib/bind/doc/misc/FAQ.1of2 index e1d7c0a..99619eb 100644 --- a/contrib/bind/doc/misc/FAQ.1of2 +++ b/contrib/bind/doc/misc/FAQ.1of2 @@ -25,7 +25,7 @@ Revision: 1.14 1996/12/07 06:42:05 Note that this posting has been split into two parts because of its size. -$Id: FAQ.1of2,v 8.4 1996/12/18 04:09:47 vixie Exp $ +$Id: FAQ.1of2,v 8.4 1996/12/18 04:22:33 vixie Exp $ A new version of this document appears monthly. If this copy is more than a month old it may be out of date. diff --git a/contrib/bind/doc/secure/copyright.txt b/contrib/bind/doc/secure/copyright.txt new file mode 100644 index 0000000..cc38356 --- /dev/null +++ b/contrib/bind/doc/secure/copyright.txt @@ -0,0 +1,28 @@ +/* + * Portions Copyright (c) 1995,1996 by Trusted Information Systems, 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 TRUSTED INFORMATION SYSTEMS DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TRUSTED INFORMATION + * SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Trusted Information Systems, Inc. has received approval from the + * United States Government for export and reexport of TIS/DNSSEC + * software from the United States of America under the provisions of + * the Export Administration Regulations (EAR) General Software Note + * (GSN) license exception for mass market software. Under the + * provisions of this license, this software may be exported or + * reexported to all destinations except for the embargoed countries of + * Cuba, Iran, Iraq, Libya, North Korea, Sudan and Syria. Any export + * or reexport of TIS/DNSSEC software to the embargoed countries + * requires additional, specific licensing approval from the United + * States Government. + */ diff --git a/contrib/bind/doc/secure/install.txt b/contrib/bind/doc/secure/install.txt new file mode 100644 index 0000000..bb5bc94 --- /dev/null +++ b/contrib/bind/doc/secure/install.txt @@ -0,0 +1,155 @@ + +INSTALL_SEC + + Bind with Secure DNS (TIS/DNSSEC) + Version 1.3.0 Beta + September 1996 + +This version has been compiled and tested on SUNOS 4.1.3, +FreeBSD-2.1.5-REL and Linux 2.0.11. +There may be still be portability problems. +If you have access to other hardware platforms please let us know if +there are any problems porting and send us patches, to include in +future releases. + +This version of secure Bind uses RSAREF-2.0 library from RSA, +First you should get/read the RSAREF FAQ + http://www.consensus.com/rsaref-faq.html +Then you can copy RSAREF from + ftp://ftp.rsa.com/rsaref/README + +You need to read this README file carefully for further instructions. + +Installation: (this version is based on 4.9.4-REL-P1). + +1. The tar ball will create a directory sec_bind in the current directory + untar the archive + The content of the sec_bind directory has the same directory + structure as bind distribution with the addition of the directories + dnssec_lib/ and signer/, some named directories have been + deleted from the distribution. + + dnssec_lib/ contains the library files for signature generation + signer/ contains tools for signing bind boot files and + generating keys. + + In addition, there is a new file, "res/res_sign.c", which + contains library routines that are required in the resolver + for displaying new RR types. + + You need to tailor sec_bind/Makefile to your system as you do + with bind distributions. + + The sec_bind distribution expects to find RSAREF in the + rsaref/ subdirectory. If you install RSAREF in a different + place you can place a pointer to the RSAREF installation + directory in place of sec_bind/rsaref. + + sec_bind/Makefile expects to find the RSAREF library file + at sec_bind/rsaref/lib/rsaref.a. The RSAREF distribution + does not contain that directory. If you are installing RSAREF + for the first time create that directory copy the correct + Makefile from the appropriate rsaref/install/ subdirectory. + Sec_bind will compile RSAREF for you. + + We recommend that you use an ANSI C compliant compiler to + compile this distribution. + +2. Follow Bind installation guidelines on your system + + Set your normal configuration in conf/options.h with the + following exceptions/additions: + ROUND_ROBIN must be OFF (for right now) + DNS_SECURITY must be ON + RSAREF must be ON if you have a copy of RSAREF. + This version of sec_bind does not work well without RSAREF. + +3. make + If you are going to use make install everything will work right + out of the box. If you are going to run programs out of the + sec_bind directory you need to set the DESTEXEC variables + accordingly. + +4. Once everything compiles you can run the simple test that is include in + the distribution. + + First you need to edit the file signer/simple_test/test.boot to + set directory directive to the full path of the directory this + file is in. + + Now the signer program can be run to sign the simple_test data. + The signed zone will be written to /tmp + % cd sec_bind/signer + % make test + The passwords for the keys in the distribution are: + Key: Password: + foo.bar foo.bar + mobile.foo.bar mobile + fix.foo.bar fix.foo.bar + sub.foo.bar sub.foo.bar + some.bar some.bar + + Notice the differences between simple_test/test.boot and + /tmp/test.boot. The pubkey directive are required for correct + behavior of new named. + + To check the if named can read the new zone files and verify + the signatures run following commands + % cd ../named + % make test + + Exit/error code 66 indicates that program completed normally + in "load-only" mode (new -l flag). + + If you want to load up named run same command as make test does + without -l flag. (the -d 3 flag is to make sure the process + does not do a fork). + % ./named -p 12345 -b /tmp/test.boot -d 3 + + % cd ../tools + % ./dig @localhost snore.foo.bar. -p 12345 + This should return an A record + SIG(A) record + % ./dig @localhost no_such_name.foo.bar. -p 12345 + This should return a NXT record +SIG(NXT) for *.foo.bar. + + You can also test against our nameserver for zone sd-bogus.tis.com + the host is uranus.hq.tis.com(192.94.214.95) + % ./dig @uranus.hq.tis.com sd-bogus.tis.com. soa + will return the SOA and SIG(SOA) + KEY + % ./dig @uranus.hq.tis.com sd-bogus.tis.com. mb + will return NXT for sd-bogus.tis.com + % ./dig @uranus.hq.tis.com foo.sd-bogus.tis.com. ns + will NS +KEY for foo.sd-bog.tis.com. + +5. Converting your setup to secure DNS zones. + need to create a key for your zone. + If you have a copy of the last release of sec_bind the key file + format has changed and you need to regenerate all your keys, Sorry. + The new format for private key files is portable between + different architectures and operating systems, the encryption + of the key file is compatible with the des program. + + To generate key use sec_bind/signer/key_gen. To generate zone key + for name you.bar, with 512 bit modulus and exponent of 3, + execute following command + + % cd signer + % ./key_gen -z -g 512 you.bar + + key_gen will ask for an encryption password for the private + key file, if you do not want to encrypt the key hit <Return>. + The program will output resource record suitable for zone file. + key_gen creates two files you.bar.priv and foo.bar.public. + + If you want, at any time, to display the public key for foo.bar + run key_gen without the -g flag or cat file foo.bar.public. + key_gen without any flags will print out the usage information. + key_gen has extensive error checking on flags. + + To modify the flags field for an existing key run key_gen with + the new flags but without the -g flag. + + Note: The key above is suitable for signing records but not for + encrypting data. + +6. Send problems, fixes and suggestions to dns-security@tis.com. diff --git a/contrib/bind/doc/secure/readme.txt b/contrib/bind/doc/secure/readme.txt new file mode 100644 index 0000000..d7b422a --- /dev/null +++ b/contrib/bind/doc/secure/readme.txt @@ -0,0 +1,93 @@ + + Secure DNS (TIS/DNSSEC) + September 1996 + +Copyright (C) 1995,1996 Trusted Information Systems, Incorporated + +Trusted Information Systems, Inc. has received approval from the +United States Government for export and reexport of TIS/DNSSEC +software from the United States of America under the provisions of +the Export Administration Regulations (EAR) General Software Note +(GSN) license exception for mass market software. Under the +provisions of this license, this software may be exported or +reexported to all destinations except for the embargoed countries of +Cuba, Iran, Iraq, Libya, North Korea, Sudan and Syria. Any export +or reexport of TIS/DNSSEC software to the embargoed countries +requires additional, specific licensing approval from the United +States Government. + +Trusted Information Systems, Inc., is pleased to +provide a reference implementation of the secure Domain Name System +(TIS/DNSSEC). In order to foster acceptance of secure DNS and provide +the community with a usable, working version of this technology, +TIS/DNSSEC is being made available for broad use on the following basis. + +- Trusted Information Systems makes no representation about the + suitability of this software for any purpose. It is provided "as is" + without express or implied warranty. + +- TIS/DNSSEC is distributed in source code form, with all modules written + in the C programming language. It runs on many UNIX derived platforms + and is integrated with the Bind implementation of the DNS protocol. + +- This beta version of TIS/DNSSEC may be used, copied, and modified for + testing and evaluation purposes without fee during the beta test + period, provided that this notice appears in supporting documentation + and is retained in all software modules in which it appears. Any other + use requires specific, written prior permission from Trusted Information + Systems. + +TIS maintains the email distribution list dns-security@tis.com for +discussion of secure DNS. To join, send email to + dns-security-request@tis.com. + +TIS/DNSSEC technical questions and bug reports should be addressed to + dns-security@tis.com. + +To reach the maintainers of TIS/DNSSEC send mail to + tisdnssec-support@tis.com + +TIS/DNSSEC is a product of Trusted Information Systems, Inc. + +This is an beta version of Bind with secure DNS extensions it uses +RSAREF which you must obtain separately. + +Implemented and tested in this version: + Portable key storage format. + Improved authentication API + Support for using different authentication packages. + All Security RRs including KEY SIG, NXT, and support for wild cards + tool for generating KEYs + tool for signing RRs in boot files + verification of RRs on load + verification of RRs over the wire + transmission of SIG RRs + returns NXT when name and/or type does not exist + storage of NXT, KEY, and SIG RRs with CNAME RR + AD/ID bits added to header and setting of these bits + key storage and retrieval + dig and nslookup can display new header bits and RRs + AXFR signature RR + keyfile directive + $SIGNER directive (to turn on and off signing) + adding KEY to answers with NS or SOA + SOA sequence numbers are now set each time zone is signed + SIG AXFR ignores label count of names + generation and inclusion of .PARENT files + Returns only one NXT at delegation points unless two are required + Expired SIG records are now returned in response to query + +Implemented but not fully tested: + +Known bugs: + +Not implemented: + ROUND_ROBIN behaviour + zone transfer in SIG(AXFR) sort order. + transaction SIGs + verification in resolver. (stub resolvers must trust local servers + resolver library is to low level to implement security) + knowing when to trust the AD bit in responses + +Read files INSTALL_SEC and USAGE_SEC for installation and user +instructions, respectively. diff --git a/contrib/bind/doc/secure/usage.txt b/contrib/bind/doc/secure/usage.txt new file mode 100644 index 0000000..aa8eebc --- /dev/null +++ b/contrib/bind/doc/secure/usage.txt @@ -0,0 +1,215 @@ + + USAGE_SEC + Secure DNS (TIS/DNSSEC) + September 1996 + +This is the usage documentation for TIS' Secure DNS (TIS/DNSSEC) version +BETA-1.3. This looks like a standard named distribution, with +the following exceptions + + this version is coded against BIND-4.9.4-P1 + + there are three new directories in this distribution + dnssec_lib + signer + rsaref + + + rsaref/ is place holder directory for RSAREF distribution. + You must get RSAREF on your own. + + signer/ contains two applications needed by DNSSEC: + signer: tool to sign zones + key_gen: tool to generate keys + dnssec_lib/ contains common library routines that are used by + named, key_gen and signer. + This is where most of the DNSSEC work is done. + +Before compiling you need to do your standard configurations for named +and the edits explained in INSTALL_SEC. This version has been tested +on SUNOS4.1.3. This version includes portability fixes from previous +beta releases for Linux, Solaris-2.4, HPUX-9 and FreeBSD. + +CHANGES TO BIND + +res/ + + There are minor changes to the files in the res directory. Most of + the changes have to do with displaying NXT + records. There are also some changes related to translating + domain names into uncompressed lower case names upon request. + +tools/ + Minor changes to recognize NXT records and display them. + +named/ + Added code to read and write new record types. + Added code to do signature validation on read. + Added code to return appropriate SIG records. + Added security flags to databuf and zoneinfo structures. + Names can now have CNAME record and security RR's. + Records are stored and transmitted in DNS SEC sort order. + +conf/ + + Turned off ROUND_ROBIN option and installed new sorting required + for signature verification. + +signer/ + NXT record generation. + Key generation + Signing of zones + Converting data records to format required for signatures. + +dnssec_lib/ + Interfacing with Crypto library. + Verifying signatures, + preparing data for signing and verification + +The role of <zone>.PARENT files: + +DNSSEC specification requires change who is authorative for certain +resource records. In order to support certification hierarchy each +zone KEY RR must be signed by parent zone. The parent signed KEY RR +must be distributed by the zone itself as it is the most authorative +for its own records. + +To facilitate this TIS/DNSSEC signer program creates a <name>.PARENT +file for every name in a zone that has a NS record. This file contains +the KEY records stored under this name and +NXT record and corresponding SIG records. If no KEY record is found +for a name with a NS record a NULL-KEY record is generated to indicate +that the child is INSECURE. + +Each <zone>.PARENT file must be sent via an out of band mechanism to +the appropriate primary for the zone, for inclusion. signer program +adds an $INCLUDE <zone>.PARENT command at the end of each zone file, +if no file exists an warning message is printed. + +Potential PROBLEM: It is likely that the parent and child are on a +different signing schedule. If new <zone>.PARENT file is put on the +primary, due to the fact that the zone data changed but the SOA did +not, it may take a long time for new records to propagate to the +secondaries. This is only a problem if zone has added/deleted a KEY +or if the the signatures will expire in the near future. To overcome +this problem, resign your zone when any of above conditions is true. +DNS NOTIFY and/or DNS DYNUPDATE may fix this problem in the future. + +TIS/DNSSEC SOA serial numbers. To facilitate prompt distribution of +zone data to secondaries, signer takes over the management of SOA +serial numbers. Each time signer signs a zone it sets the serial +number to a value reflecting the time the zone was signed, in standard +Unix time seconds since 1970/1/1 0:0:0 GMT. + +How to configure a secure zone. + Create a directory <zone> to contain your zone files. + Create a output directory <outdir> for the signer output. + Put in <zone> a boot file that includes the files from that zone. + Create a KEY for the zone by running key_gen, Name the key <domain>. + + Run signer on your zone writing to the output directory <outdir>. + Signer will rewrite the boot file to include new directive + "pubkey" of the key used to sign the file. If there where + any pubkey declarations in the input boot file they will be + deleted. + Signer generates files that correspond to the load files specified. + + In case of load file that $INCLUDEs another load file, signer will + merge them to the output file. + You will notice that the output files are significantly larger. + The output files will be in a different order than the input files, + all records are sorted into DNSSEC sort order. + NXT and SIG records have been added. + + If there are any NS records for a name other than the zone name of + each input file you will see messages that NULL KEY records + have been created, if this is not correct behavior, add + the correct KEY RRs. + For each domain name that has a NS record but is not a zone name + of load file you will see a file named <name>.PARENT, + this file contains the KEY record for that name and an + NXT record + 2 SIG records. + This file needs to be sent to the nameserver that is primary for that + zone. There are two reasons for this: + 1. To support Certification Hierarchy, each zone key is + signed by the parent zone key. + 2. Zone is the most trustworthy source for itself unless + these records are loaded into the primary server for + the zone, the records may not get propagated. + +how to run SEC_NAMED: + +Included in the distribution there is a small test setup: + +# run signer +./signer boot-f simple_test/test.boot [out-dir /tmp] +# or +make test +# This takes few minutes to run depending on your machine and the size +# of the key selected +# all output files will be stored in /tmp unless out-dir is specified + +# +# Now we are ready to run named +cd ../named +./named -p 12345 -b /tmp/test.boot.save [-d x] + +# +# you can now check for data in the data base +# using the new dig. +# +cd ../tools +./dig @yourhost snore.foo.bar. any in -p 12345 + +# +# Output from new dig will be something like this +# +; <<>> DiG 2.1 <<>> @dnssrv snore.foo.bar. any in -p +; (1 server found) +;; res options: init recurs defnam dnsrch +;; got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10 +;; flags: qr rd ra; Ques: 1, Ans: 11, Auth: 0, Addit: 1 +;; QUESTIONS: +;; snore.foo.bar, type = ANY, class = IN + +;; ANSWERS: +snore.foo.bar. 259200 A 10.17.3.20 +snore.foo.bar. 259200 SIG A ( + 1 3; alg labels + 259200 ; TTL + 19950506200636 ; Signature expiration + 19950406200659 ; time signed + 47437 ; Key foot print + foo.bar. ; Signers name + FsqeW3hstM8Q6v8PMCGPsVMfO6dEpHjFgKm2dJRaofFtCQ/CT9O6Vo7J5zgkV+5ciWQwuZwvzW071jnZ1i27Ip/8vqdKGHC63tjWkCHSZV0= + ) ; END Signature +snore.foo.bar. 259200 MX 96 who.foo.bar. +snore.foo.bar. 259200 MX 100 foo.bar. +snore.foo.bar. 259200 MX 120 xxx.foo.bar. +snore.foo.bar. 259200 MX 130 maGellan.foo.bar. +snore.foo.bar. 259200 MX 140 bozo.foo.bar. +snore.foo.bar. 259200 SIG MX ( + 1 3; alg labels + 259200 ; TTL + 19950506200636 ; Signature expiration + 19950406200659 ; time signed + 47437 ; Key foot print + foo.bar. ; Signers name + EV0cJqF3pUOgktggTrFf55YGwQFbUqPJAMTnAkHK3+Z/Ya6GgwwNOGRzq/FYm5P4E+yIj6WUYFh9Ex5eX5TwiIsjM/hy173lSa3qm/ljDk8= + ) ; END Signature +snore.foo.bar. 259200 NXT xxx.foo.bar. +snore.foo.bar. 259200 SIG NXT ( + 1 3; alg labels + 259200 ; TTL + 19950506200636 ; Signature expiration + 19950406200659 ; time signed + 47437 ; Key foot print + foo.bar. ; Signers name + eJUHVm5Q5qYQYFVOW0L5Of67HQvQ9+7T7sQqHv7ayTT2sMnXudxviYv43vALMMwBcJFXFEhLhwYwN7pUDssD/w5si/6JJQTi1o30S8si3zE= + ) ; END Signature + +;; Total query time: 195 msec +;; FROM: dnssrv to SERVER: dnssrv 10.17.3.1 +;; WHEN: Thu Apr 6 16:20:32 1995 +;; MSG SIZE sent: 31 rcvd: 662 diff --git a/contrib/bind/include/Makefile b/contrib/bind/include/Makefile index 13df424..d0a13a8 100644 --- a/contrib/bind/include/Makefile +++ b/contrib/bind/include/Makefile @@ -1,74 +1,53 @@ -# ++Copyright++ 1993 -# - -# Copyright (c) -# 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. -# +# Copyright (c) 1996 by Internet Software Consortium +# # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies, 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 +# 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. -# - -# --Copyright-- -SUBDIRS = arpa -HFILES = netdb.h resolv.h +SUBDIRS = arpa isc +HFILES = netdb.h resolv.h irs.h hesiod.h DESTDIR= -DESTINC= /usr/include +DESTINC= /usr/local/bind/include +INSTALL= install MARGS= DESTDIR="${DESTDIR}" DESTINC="${DESTINC}" INSTALL="${INSTALL}" \ MAKE="${MAKE}" -all depend clean install:: +all depend clean distclean install:: @for x in ${SUBDIRS}; do \ (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ done -clean:: +distclean:: clean + +clean:: FRC rm -f *~ *.BAK *.CKP *.orig -install:: +install:: ${DESTDIR}${DESTINC} @set -x; for x in ${HFILES}; do \ ${INSTALL} -c -m 444 $$x ${DESTDIR}${DESTINC}/$$x; \ done + +${DESTDIR}${DESTINC}: + mkdir -p ${DESTDIR}${DESTINC}; + +links:: FRC + @set -e; ln -s SRC/*.h .; \ + for x in $(SUBDIRS); do \ + ( mkdir $$x; cd $$x; pwd; ln -s ../SRC/$$x SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + $(MAKE) $(MARGS) links; \ + ); \ + done + +FRC: diff --git a/contrib/bind/include/arpa/Makefile b/contrib/bind/include/arpa/Makefile index 2ebfe2c..279c569 100644 --- a/contrib/bind/include/arpa/Makefile +++ b/contrib/bind/include/arpa/Makefile @@ -1,64 +1,28 @@ -# ++Copyright++ 1993 -# - -# Copyright (c) -# 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. -# +# Copyright (c) 1996 by Internet Software Consortium +# # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies, 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 +# 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. -# - -# --Copyright-- -HFILES = inet.h nameser.h +HFILES = inet.h nameser.h nameser_compat.h DESTDIR = -DESTINC = /usr/include +DESTINC = /usr/local/bind/include all depend: -clean: +distclean: clean + +clean: FRC rm -f *~ *.BAK *.CKP *.orig install: ${DESTDIR}${DESTINC}/arpa @@ -67,4 +31,9 @@ install: ${DESTDIR}${DESTINC}/arpa done ${DESTDIR}${DESTINC}/arpa: - mkdir $@ + mkdir -p ${DESTDIR}${DESTINC}/arpa + +links: FRC + @set -e; ln -s SRC/*.h . + +FRC: diff --git a/contrib/bind/include/arpa/inet.h b/contrib/bind/include/arpa/inet.h index 2a4460f..6065980 100644 --- a/contrib/bind/include/arpa/inet.h +++ b/contrib/bind/include/arpa/inet.h @@ -55,7 +55,7 @@ /* * @(#)inet.h 8.1 (Berkeley) 6/2/93 - * $Id: inet.h,v 8.6 1996/08/08 06:54:29 vixie Exp $ + * $Id: inet.h,v 8.5 1997/01/29 08:48:09 vixie Exp $ */ #ifndef _INET_H_ @@ -71,6 +71,21 @@ #endif #include <sys/cdefs.h> +#define inet_addr __inet_addr +#define inet_aton __inet_aton +#define inet_lnaof __inet_lnaof +#define inet_makeaddr __inet_makeaddr +#define inet_neta __inet_neta +#define inet_netof __inet_netof +#define inet_network __inet_network +#define inet_net_ntop __inet_net_ntop +#define inet_net_pton __inet_net_pton +#define inet_ntoa __inet_ntoa +#define inet_pton __inet_pton +#define inet_ntop __inet_ntop +#define inet_nsap_addr __inet_nsap_addr +#define inet_nsap_ntoa __inet_nsap_ntoa + __BEGIN_DECLS unsigned long inet_addr __P((const char *)); int inet_aton __P((const char *, struct in_addr *)); diff --git a/contrib/bind/include/arpa/nameser.h b/contrib/bind/include/arpa/nameser.h index f029e64..8d0faf5 100644 --- a/contrib/bind/include/arpa/nameser.h +++ b/contrib/bind/include/arpa/nameser.h @@ -1,6 +1,4 @@ /* - * ++Copyright++ 1983, 1989, 1993 - * - * Copyright (c) 1983, 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -31,57 +29,33 @@ * LIABILITY, OR TORT (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. - * + */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. - * - - * Portions Copyright (c) 1995 by International Business Machines, Inc. - * - * International Business Machines, Inc. (hereinafter called IBM) grants - * permission under its copyrights to use, copy, modify, and distribute this - * Software with or without fee, provided that the above copyright notice and - * all paragraphs of this notice appear in all copies, and that the name of IBM - * not be used in connection with the marketing of any product incorporating - * the Software or modifications thereof, without specific, written prior - * permission. - * - * To the extent it has a right to do so, IBM grants an immunity from suit - * under its patents, if any, for the use, sale or manufacture of products to - * the extent that such products are used for performing Domain Name System - * dynamic updates in TCP/IP networks by means of the Software. No immunity is - * granted for any product per se or for any other function of any product. - * - * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - * --Copyright-- */ /* - * @(#)nameser.h 8.1 (Berkeley) 6/2/93 - * $Id: nameser.h,v 8.11 1996/10/08 04:51:02 vixie Exp $ + * $Id: nameser.h,v 8.16 1998/02/06 00:35:58 halley Exp $ */ -#ifndef _NAMESER_H_ -#define _NAMESER_H_ +#ifndef _ARPA_NAMESER_H_ +#define _ARPA_NAMESER_H_ + +#define BIND_4_COMPAT #include <sys/param.h> #if (!defined(BSD)) || (BSD < 199306) @@ -91,302 +65,388 @@ #endif #include <sys/cdefs.h> -#ifdef _AUX_SOURCE -# include <sys/types.h> -#endif - /* * revision information. this is the release date in YYYYMMDD format. * it can change every day so the right thing to do with it is use it - * in preprocessor commands such as "#if (__BIND > 19931104)". do not - * compare for equality; rather, use it to determine whether your resolver + * in preprocessor commands such as "#if (__NAMESER > 19931104)". do not + * compare for equality; rather, use it to determine whether your libnameser.a * is new enough to contain a certain feature. */ -#define __BIND 19960801 /* interface version stamp */ +/* XXXRTH I made this bigger than __BIND in 4.9.5 T6B */ +#define __NAMESER 19961001 /* New interface version stamp. */ /* - * Define constants based on rfc883 + * Define constants based on RFC 883, RFC 1034, RFC 1035 */ -#define PACKETSZ 512 /* maximum packet size */ -#define MAXDNAME 1025 /* maximum presentation domain name */ -#define MAXCDNAME 255 /* maximum compressed domain name */ -#define MAXLABEL 63 /* maximum length of domain label */ -#define HFIXEDSZ 12 /* #/bytes of fixed data in header */ -#define QFIXEDSZ 4 /* #/bytes of fixed data in query */ -#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ -#define INT32SZ 4 /* for systems without 32-bit ints */ -#define INT16SZ 2 /* for systems without 16-bit ints */ -#define INADDRSZ 4 /* IPv4 T_A */ -#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#define NS_PACKETSZ 512 /* maximum packet size */ +#define NS_MAXDNAME 1025 /* maximum domain name */ +#define NS_MAXCDNAME 255 /* maximum compressed domain name */ +#define NS_MAXLABEL 63 /* maximum length of domain label */ +#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */ +#define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */ +#define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */ +#define NS_INADDRSZ 4 /* IPv4 T_A */ +#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ +#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ /* - * Internet nameserver port number + * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() + * in synch with it. */ -#define NAMESERVER_PORT 53 +typedef enum __ns_sect { + ns_s_qd = 0, /* Query: Question. */ + ns_s_zn = 0, /* Update: Zone. */ + ns_s_an = 1, /* Query: Answer. */ + ns_s_pr = 1, /* Update: Prerequisites. */ + ns_s_ns = 2, /* Query: Name servers. */ + ns_s_ud = 2, /* Update: Update. */ + ns_s_ar = 3, /* Query|Update: Additional records. */ + ns_s_max = 4 +} ns_sect; /* - * Currently defined opcodes + * This is a message handle. It is caller allocated and has no dynamic data. + * This structure is intended to be opaque to all but ns_parse.c, thus the + * leading _'s on the member names. Use the accessor functions, not the _'s. */ -#define QUERY 0x0 /* standard query */ -#define IQUERY 0x1 /* inverse query */ -#define STATUS 0x2 /* nameserver status query */ -/*#define xxx 0x3*/ /* 0x3 reserved */ -#define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */ +typedef struct __ns_msg { + const u_char *_msg, *_eom; + u_int16_t _id, _flags, _counts[ns_s_max]; + const u_char *_sections[ns_s_max]; + ns_sect _sect; + int _rrnum; + const u_char *_ptr; +} ns_msg; + +/* Private data structure - do not use from outside library. */ +struct _ns_flagdata { int mask, shift; }; +extern struct _ns_flagdata _ns_flagdata[]; + +/* Accessor macros - this is part of the public interface. */ +#define ns_msg_getflag(handle, flag) ( \ + ((handle)._flags & _ns_flagdata[flag].mask) \ + >> _ns_flagdata[flag].shift \ + ) +#define ns_msg_id(handle) ((handle)._id + 0) +#define ns_msg_base(handle) ((handle)._msg + 0) +#define ns_msg_end(handle) ((handle)._eom + 0) +#define ns_msg_size(handle) ((handle)._eom - (handle)._msg) +#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) + /* - * Currently defined response codes + * This is a parsed record. It is caller allocated and has no dynamic data. */ -#define NOERROR 0 /* no error */ -#define FORMERR 1 /* format error */ -#define SERVFAIL 2 /* server failure */ -#define NXDOMAIN 3 /* non existent domain */ -#define NOTIMP 4 /* not implemented */ -#define REFUSED 5 /* query refused */ +typedef struct __ns_rr { + char name[NS_MAXDNAME]; /* XXX need to malloc */ + u_int16_t type; + u_int16_t class; + u_int32_t ttl; + u_int16_t rdlength; + const u_char *rdata; +} ns_rr; + +/* Accessor macros - this is part of the public interface. */ +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") +#define ns_rr_type(rr) ((rr).type + 0) +#define ns_rr_class(rr) ((rr).class + 0) +#define ns_rr_ttl(rr) ((rr).ttl + 0) +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) /* - * Type values for resources and queries + * These don't have to be in the same order as in the packet flags word, + * and they can even overlap in some cases, but they will need to be kept + * in synch with ns_parse.c:ns_flagdata[]. */ -#define T_A 1 /* host address */ -#define T_NS 2 /* authoritative server */ -#define T_MD 3 /* mail destination */ -#define T_MF 4 /* mail forwarder */ -#define T_CNAME 5 /* canonical name */ -#define T_SOA 6 /* start of authority zone */ -#define T_MB 7 /* mailbox domain name */ -#define T_MG 8 /* mail group member */ -#define T_MR 9 /* mail rename name */ -#define T_NULL 10 /* null resource record */ -#define T_WKS 11 /* well known service */ -#define T_PTR 12 /* domain name pointer */ -#define T_HINFO 13 /* host information */ -#define T_MINFO 14 /* mailbox information */ -#define T_MX 15 /* mail routing information */ -#define T_TXT 16 /* text strings */ -#define T_RP 17 /* responsible person */ -#define T_AFSDB 18 /* AFS cell database */ -#define T_X25 19 /* X_25 calling address */ -#define T_ISDN 20 /* ISDN calling address */ -#define T_RT 21 /* router */ -#define T_NSAP 22 /* NSAP address */ -#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ -#define T_SIG 24 /* security signature */ -#define T_KEY 25 /* security key */ -#define T_PX 26 /* X.400 mail mapping */ -#define T_GPOS 27 /* geographical position (withdrawn) */ -#define T_AAAA 28 /* IP6 Address */ -#define T_LOC 29 /* Location Information */ -#define T_NXT 30 /* Next Valid Name in Zone */ -#define T_EID 31 /* Endpoint identifier */ -#define T_NIMLOC 32 /* Nimrod locator */ -#define T_SRV 33 /* Server selection */ -#define T_ATMA 34 /* ATM Address */ -#define T_NAPTR 35 /* Naming Authority PoinTeR */ - /* non standard */ -#define T_UINFO 100 /* user (finger) information */ -#define T_UID 101 /* user ID */ -#define T_GID 102 /* group ID */ -#define T_UNSPEC 103 /* Unspecified format (binary data) */ - /* Query type values which do not appear in resource records */ -#define T_IXFR 251 /* incremental zone transfer */ -#define T_AXFR 252 /* transfer zone of authority */ -#define T_MAILB 253 /* transfer mailbox records */ -#define T_MAILA 254 /* transfer mail agent records */ -#define T_ANY 255 /* wildcard match */ +typedef enum __ns_flag { + ns_f_qr, /* Question/Response. */ + ns_f_opcode, /* Operation code. */ + ns_f_aa, /* Authoritative Answer. */ + ns_f_tc, /* Truncation occurred. */ + ns_f_rd, /* Recursion Desired. */ + ns_f_ra, /* Recursion Available. */ + ns_f_z, /* MBZ. */ + ns_f_ad, /* Authentic Data (DNSSEC). */ + ns_f_cd, /* Checking Disabled (DNSSEC). */ + ns_f_rcode, /* Response code. */ + ns_f_max +} ns_flag; /* - * Values for class field + * Currently defined opcodes. */ - -#define C_IN 1 /* the arpa internet */ -#define C_CHAOS 3 /* for chaos net (MIT) */ -#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ - /* Query class values which do not appear in resource records */ -#define C_ANY 255 /* wildcard match */ +typedef enum __ns_opcode { + ns_o_query = 0, /* Standard query. */ + ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /* Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /* Zone change notification. */ + ns_o_update = 5, /* Zone update message. */ + ns_o_max = 6 +} ns_opcode; /* - * Flags field of the KEY RR rdata + * Currently defined response codes. */ -#define KEYFLAG_TYPEMASK 0xC000 /* Mask for "type" bits */ -#define KEYFLAG_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ -#define KEYFLAG_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ -#define KEYFLAG_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ -#define KEYFLAG_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ -/* The type bits can also be interpreted independently, as single bits: */ -#define KEYFLAG_NO_AUTH 0x8000 /* Key not usable for authentication */ -#define KEYFLAG_NO_CONF 0x4000 /* Key not usable for confidentiality */ - -#define KEYFLAG_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */ -#define KEYFLAG_RESERVED3 0x1000 /* reserved - must be zero */ -#define KEYFLAG_RESERVED4 0x0800 /* reserved - must be zero */ -#define KEYFLAG_USERACCOUNT 0x0400 /* key is assoc. with a user acct */ -#define KEYFLAG_ENTITY 0x0200 /* key is assoc. with entity eg host */ -#define KEYFLAG_ZONEKEY 0x0100 /* key is zone key for the zone named */ -#define KEYFLAG_IPSEC 0x0080 /* key is for IPSEC use (host or user)*/ -#define KEYFLAG_EMAIL 0x0040 /* key is for email (MIME security) */ -#define KEYFLAG_RESERVED10 0x0020 /* reserved - must be zero */ -#define KEYFLAG_RESERVED11 0x0010 /* reserved - must be zero */ -#define KEYFLAG_SIGNATORYMASK 0x000F /* key can sign DNS RR's of same name */ - -#define KEYFLAG_RESERVED_BITMASK ( KEYFLAG_RESERVED3 | \ - KEYFLAG_RESERVED4 | \ - KEYFLAG_RESERVED10| KEYFLAG_RESERVED11) - -/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ -#define ALGORITHM_MD5RSA 1 /* MD5 with RSA */ -#define ALGORITHM_EXPIRE_ONLY 253 /* No alg, no security */ -#define ALGORITHM_PRIVATE_OID 254 /* Key begins with OID indicating alg */ +typedef enum __ns_rcode { + ns_r_noerror = 0, /* No error occurred. */ + ns_r_formerr = 1, /* Format error. */ + ns_r_servfail = 2, /* Server failure. */ + ns_r_nxdomain = 3, /* Name error. */ + ns_r_notimpl = 4, /* Unimplemented. */ + ns_r_refused = 5, /* Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /* Name exists */ + ns_r_yxrrset = 7, /* RRset exists */ + ns_r_nxrrset = 8, /* RRset does not exist */ + ns_r_notauth = 9, /* Not authoritative for zone */ + ns_r_notzone = 10, /* Zone of record different from zone section */ + ns_r_max = 11 +} ns_rcode; -/* Signatures */ - /* Size of a mod or exp in bits */ -#define MIN_MD5RSA_KEY_PART_BITS 512 -#define MAX_MD5RSA_KEY_PART_BITS 2552 - /* Total of binary mod and exp, bytes */ -#define MAX_MD5RSA_KEY_BYTES ((MAX_MD5RSA_KEY_PART_BITS+7/8)*2+3) - /* Max length of text sig block */ -#define MAX_KEY_BASE64 (((MAX_MD5RSA_KEY_BYTES+2)/3)*4) +/* BIND_UPDATE */ +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; /* - * Status return codes for T_UNSPEC conversion routines + * This RR-like structure is particular to UPDATE. */ -#define CONV_SUCCESS 0 -#define CONV_OVERFLOW (-1) -#define CONV_BADFMT (-2) -#define CONV_BADCKSUM (-3) -#define CONV_BADBUFLEN (-4) - -#ifndef BYTE_ORDER -#if (BSD >= 199103) -# include <machine/endian.h> -#else -#ifdef linux -# include <endian.h> -#else -#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ -#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ -#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ - -#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ - defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ - defined(__alpha__) || defined(__alpha) -#define BYTE_ORDER LITTLE_ENDIAN -#endif - -#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ - defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ - defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ - defined(apollo) || defined(__convex__) || defined(_CRAY) || \ - defined(__hppa) || defined(__hp9000) || \ - defined(__hp9000s300) || defined(__hp9000s700) || \ - defined (BIT_ZERO_ON_LEFT) || defined(m68k) -#define BYTE_ORDER BIG_ENDIAN -#endif -#endif /* linux */ -#endif /* BSD */ -#endif /* BYTE_ORDER */ - -#if !defined(BYTE_ORDER) || \ - (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ - BYTE_ORDER != PDP_ENDIAN) - /* you must determine what the correct bit order is for - * your compiler - the next line is an intentional error - * which will force your compiles to bomb until you fix - * the above macros. - */ - error "Undefined or invalid BYTE_ORDER"; -#endif +struct ns_updrec { + struct ns_updrec *r_prev; /* prev record */ + struct ns_updrec *r_next; /* next record */ + u_int8_t r_section; /* ZONE/PREREQUISITE/UPDATE */ + char * r_dname; /* owner of the RR */ + u_int16_t r_class; /* class number */ + u_int16_t r_type; /* type number */ + u_int32_t r_ttl; /* time to live */ + u_char * r_data; /* rdata fields as text string */ + u_int16_t r_size; /* size of r_data field */ + int r_opcode; /* type of operation */ + /* following fields for private use by the resolver/server routines */ + struct ns_updrec *r_grpnext; /* next record when grouped */ + struct databuf *r_dp; /* databuf to process */ + struct databuf *r_deldp; /* databuf's deleted/overwritten */ + u_int16_t r_zone; /* zone number on server */ +}; +typedef struct ns_updrec ns_updrec; /* - * Structure for query header. The order of the fields is machine- and - * compiler-dependent, depending on the byte/bit order and the layout - * of bit fields. We use bit fields only in int variables, as this - * is all ANSI requires. This requires a somewhat confusing rearrangement. + * Currently defined type values for resources and queries. */ +typedef enum __ns_type { + ns_t_a = 1, /* Host address. */ + ns_t_ns = 2, /* Authoritative server. */ + ns_t_md = 3, /* Mail destination. */ + ns_t_mf = 4, /* Mail forwarder. */ + ns_t_cname = 5, /* Canonical name. */ + ns_t_soa = 6, /* Start of authority zone. */ + ns_t_mb = 7, /* Mailbox domain name. */ + ns_t_mg = 8, /* Mail group member. */ + ns_t_mr = 9, /* Mail rename name. */ + ns_t_null = 10, /* Null resource record. */ + ns_t_wks = 11, /* Well known service. */ + ns_t_ptr = 12, /* Domain name pointer. */ + ns_t_hinfo = 13, /* Host information. */ + ns_t_minfo = 14, /* Mailbox information. */ + ns_t_mx = 15, /* Mail routing information. */ + ns_t_txt = 16, /* Text strings. */ + ns_t_rp = 17, /* Responsible person. */ + ns_t_afsdb = 18, /* AFS cell database. */ + ns_t_x25 = 19, /* X_25 calling address. */ + ns_t_isdn = 20, /* ISDN calling address. */ + ns_t_rt = 21, /* Router. */ + ns_t_nsap = 22, /* NSAP address. */ + ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */ + ns_t_sig = 24, /* Security signature. */ + ns_t_key = 25, /* Security key. */ + ns_t_px = 26, /* X.400 mail mapping. */ + ns_t_gpos = 27, /* Geographical position (withdrawn). */ + ns_t_aaaa = 28, /* Ip6 Address. */ + ns_t_loc = 29, /* Location Information. */ + ns_t_nxt = 30, /* Next domain (security). */ + ns_t_eid = 31, /* Endpoint identifier. */ + ns_t_nimloc = 32, /* Nimrod Locator. */ + ns_t_srv = 33, /* Server Selection. */ + ns_t_atma = 34, /* ATM Address */ + ns_t_naptr = 35, /* Naming Authority PoinTeR */ + /* Query type values which do not appear in resource records. */ + ns_t_ixfr = 251, /* Incremental zone transfer. */ + ns_t_axfr = 252, /* Transfer zone of authority. */ + ns_t_mailb = 253, /* Transfer mailbox records. */ + ns_t_maila = 254, /* Transfer mail agent records. */ + ns_t_any = 255, /* Wildcard match. */ + ns_t_max = 65536 +} ns_type; -typedef struct { - unsigned id :16; /* query identification number */ -#if BYTE_ORDER == BIG_ENDIAN - /* fields in third byte */ - unsigned qr: 1; /* response flag */ - unsigned opcode: 4; /* purpose of message */ - unsigned aa: 1; /* authoritive answer */ - unsigned tc: 1; /* truncated message */ - unsigned rd: 1; /* recursion desired */ - /* fields in fourth byte */ - unsigned ra: 1; /* recursion available */ - unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ - unsigned ad: 1; /* authentic data from named */ - unsigned cd: 1; /* checking disabled by resolver */ - unsigned rcode :4; /* response code */ -#endif -#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN - /* fields in third byte */ - unsigned rd :1; /* recursion desired */ - unsigned tc :1; /* truncated message */ - unsigned aa :1; /* authoritive answer */ - unsigned opcode :4; /* purpose of message */ - unsigned qr :1; /* response flag */ - /* fields in fourth byte */ - unsigned rcode :4; /* response code */ - unsigned cd: 1; /* checking disabled by resolver */ - unsigned ad: 1; /* authentic data from named */ - unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ - unsigned ra :1; /* recursion available */ -#endif - /* remaining bytes */ - unsigned qdcount :16; /* number of question entries */ - unsigned ancount :16; /* number of answer entries */ - unsigned nscount :16; /* number of authority entries */ - unsigned arcount :16; /* number of resource entries */ -} HEADER; +/* + * Values for class field + */ +typedef enum __ns_class { + ns_c_in = 1, /* Internet. */ + /* Class 2 unallocated/unsupported. */ + ns_c_chaos = 3, /* MIT Chaos-net. */ + ns_c_hs = 4, /* MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /* for prereq. sections in update requests */ + ns_c_any = 255, /* Wildcard match. */ + ns_c_max = 65536 +} ns_class; /* - * Defines for handling compressed domain names + * Flags field of the KEY RR rdata */ -#define INDIR_MASK 0xc0 +#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */ +#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ +#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ +#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ +#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ +/* The type bits can also be interpreted independently, as single bits: */ +#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */ +#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */ +#define NS_KEY_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */ +#define NS_KEY_RESERVED3 0x1000 /* reserved - must be zero */ +#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */ +#define NS_KEY_USERACCOUNT 0x0400 /* key is assoc. with a user acct */ +#define NS_KEY_ENTITY 0x0200 /* key is assoc. with entity eg host */ +#define NS_KEY_ZONEKEY 0x0100 /* key is zone key */ +#define NS_KEY_IPSEC 0x0080 /* key is for IPSEC (host or user)*/ +#define NS_KEY_EMAIL 0x0040 /* key is for email (MIME security) */ +#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */ +#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */ +#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */ + +#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED3 | \ + NS_KEY_RESERVED4 | \ + NS_KEY_RESERVED10 | \ + NS_KEY_RESERVED11 ) + +/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ +#define NS_ALG_MD5RSA 1 /* MD5 with RSA */ +#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */ +#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */ + +/* Signatures */ +#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */ +#define NS_MD5RSA_MAX_BITS 2552 + /* Total of binary mod and exp */ +#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) + /* Max length of text sig block */ +#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) + +/* Offsets into SIG record rdata to find various values */ +#define NS_SIG_TYPE 0 /* Type flags */ +#define NS_SIG_ALG 2 /* Algorithm */ +#define NS_SIG_LABELS 3 /* How many labels in name */ +#define NS_SIG_OTTL 4 /* Original TTL */ +#define NS_SIG_EXPIR 8 /* Expiration time */ +#define NS_SIG_SIGNED 12 /* Signature time */ +#define NS_SIG_FOOT 16 /* Key footprint */ +#define NS_SIG_SIGNER 18 /* Domain name of who signed it */ + +/* How RR types are represented as bit-flags in NXT records */ +#define NS_NXT_BITS 8 +#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) -extern u_int16_t _getshort __P((const u_char *)); -extern u_int32_t _getlong __P((const u_char *)); /* * Inline versions of get/put short/long. Pointer is advanced. - * - * These macros demonstrate the property of C whereby it can be - * portable or it can be elegant but rarely both. */ -#define GETSHORT(s, cp) { \ +#define NS_GET16(s, cp) { \ register u_char *t_cp = (u_char *)(cp); \ (s) = ((u_int16_t)t_cp[0] << 8) \ | ((u_int16_t)t_cp[1]) \ ; \ - (cp) += INT16SZ; \ + (cp) += NS_INT16SZ; \ } -#define GETLONG(l, cp) { \ +#define NS_GET32(l, cp) { \ register u_char *t_cp = (u_char *)(cp); \ (l) = ((u_int32_t)t_cp[0] << 24) \ | ((u_int32_t)t_cp[1] << 16) \ | ((u_int32_t)t_cp[2] << 8) \ | ((u_int32_t)t_cp[3]) \ ; \ - (cp) += INT32SZ; \ + (cp) += NS_INT32SZ; \ } -#define PUTSHORT(s, cp) { \ +#define NS_PUT16(s, cp) { \ register u_int16_t t_s = (u_int16_t)(s); \ register u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ - (cp) += INT16SZ; \ + (cp) += NS_INT16SZ; \ } -#define PUTLONG(l, cp) { \ +#define NS_PUT32(l, cp) { \ register u_int32_t t_l = (u_int32_t)(l); \ register u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_l >> 24; \ *t_cp++ = t_l >> 16; \ *t_cp++ = t_l >> 8; \ *t_cp = t_l; \ - (cp) += INT32SZ; \ + (cp) += NS_INT32SZ; \ } -#endif /* !_NAMESER_H_ */ +/* + * ANSI C identifier hiding. + */ +#define ns_get16 __ns_get16 +#define ns_get32 __ns_get32 +#define ns_put16 __ns_put16 +#define ns_put32 __ns_put32 +#define ns_initparse __ns_initparse +#define ns_parserr __ns_parserr +#define ns_sprintrr __ns_sprintrr +#define ns_sprintrrf __ns_sprintrrf +#define ns_format_ttl __ns_format_ttl +#define ns_parse_ttl __ns_parse_ttl +#define ns_name_ntop __ns_name_ntop +#define ns_name_pton __ns_name_pton +#define ns_name_unpack __ns_name_unpack +#define ns_name_pack __ns_name_pack +#define ns_name_compress __ns_name_compress +#define ns_name_uncompress __ns_name_uncompress + +__BEGIN_DECLS +u_int ns_get16 __P((const u_char *)); +u_long ns_get32 __P((const u_char *)); +void ns_put16 __P((u_int, u_char *)); +void ns_put32 __P((u_long, u_char *)); +int ns_initparse __P((const u_char *, int, ns_msg *)); +int ns_parserr __P((ns_msg *, ns_sect, int, ns_rr *)); +int ns_sprintrr __P((const ns_msg *, const ns_rr *, + const char *, const char *, char *, size_t)); +int ns_sprintrrf __P((const u_char *, size_t, const char *, + ns_class, ns_type, u_long, const u_char *, + size_t, const char *, const char *, + char *, size_t)); +int ns_format_ttl __P((u_long, char *, size_t)); +int ns_parse_ttl __P((const char *, u_long *)); +int ns_name_ntop __P((const u_char *, char *, size_t)); +int ns_name_pton __P((const char *, u_char *, size_t)); +int ns_name_unpack __P((const u_char *, const u_char *, + const u_char *, u_char *, size_t)); +int ns_name_pack __P((const u_char *, u_char *, int, + const u_char **, const u_char **)); +int ns_name_uncompress __P((const u_char *, const u_char *, + const u_char *, char *, size_t)); +int ns_name_compress __P((const char *, u_char *, size_t, + const u_char **, const u_char **)); +int ns_name_skip __P((const u_char **, const u_char *)); +__END_DECLS + +#ifdef BIND_4_COMPAT +#include <arpa/nameser_compat.h> +#endif + +#endif /* !_ARPA_NAMESER_H_ */ diff --git a/contrib/bind/include/arpa/nameser_compat.h b/contrib/bind/include/arpa/nameser_compat.h new file mode 100644 index 0000000..82b4c4d --- /dev/null +++ b/contrib/bind/include/arpa/nameser_compat.h @@ -0,0 +1,224 @@ +/* Copyright (c) 1983, 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. + */ + +/* + * from nameser.h 8.1 (Berkeley) 6/2/93 + * $Id: nameser_compat.h,v 8.9 1998/03/20 23:25:10 halley Exp $ + */ + +#ifndef _ARPA_NAMESER_COMPAT_ +#define _ARPA_NAMESER_COMPAT_ + +#define __BIND 19950621 /* (DEAD) interface version stamp. */ + +#ifndef BYTE_ORDER +#if (BSD >= 199103) +# include <machine/endian.h> +#else +#ifdef linux +# include <endian.h> +#else +#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ +#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ + +#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) || \ + (defined(__Lynx__) && defined(__x86__)) +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || \ + defined (BIT_ZERO_ON_LEFT) || defined(m68k) || \ + (defined(__Lynx__) && \ + (defined(__68k__) || defined(__sparc__) || defined(__powerpc__))) +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif /* linux */ +#endif /* BSD */ +#endif /* BYTE_ORDER */ + +#if !defined(BYTE_ORDER) || \ + (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ + BYTE_ORDER != PDP_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ + error "Undefined or invalid BYTE_ORDER"; +#endif + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritive answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /* authentic data from named */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned rcode :4; /* response code */ +#endif +#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritive answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned ad: 1; /* authentic data from named */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} HEADER; + +#define PACKETSZ NS_PACKETSZ +#define MAXDNAME NS_MAXDNAME +#define MAXCDNAME NS_MAXCDNAME +#define MAXLABEL NS_MAXLABEL +#define HFIXEDSZ NS_HFIXEDSZ +#define QFIXEDSZ NS_QFIXEDSZ +#define RRFIXEDSZ NS_RRFIXEDSZ +#define INT32SZ NS_INT32SZ +#define INT16SZ NS_INT16SZ +#define INADDRSZ NS_INADDRSZ +#define IN6ADDRSZ NS_IN6ADDRSZ +#define INDIR_MASK NS_CMPRSFLGS +#define NAMESERVER_PORT NS_DEFAULTPORT + +#define S_ZONE ns_s_zn +#define S_PREREQ ns_s_pr +#define S_UPDATE ns_s_ud +#define S_ADDT ns_s_ar + +#define QUERY ns_o_query +#define IQUERY ns_o_iquery +#define STATUS ns_o_status +#define NS_NOTIFY_OP ns_o_notify +#define NS_UPDATE_OP ns_o_update + +#define NOERROR ns_r_noerror +#define FORMERR ns_r_formerr +#define SERVFAIL ns_r_servfail +#define NXDOMAIN ns_r_nxdomain +#define NOTIMP ns_r_notimpl +#define REFUSED ns_r_refused +#define YXDOMAIN ns_r_yxdomain +#define YXRRSET ns_r_yxrrset +#define NXRRSET ns_r_nxrrset +#define NOTAUTH ns_r_notauth +#define NOTZONE ns_r_notzone + +#define DELETE ns_uop_delete +#define ADD ns_uop_add + +#define T_A ns_t_a +#define T_NS ns_t_ns +#define T_MD ns_t_md +#define T_MF ns_t_mf +#define T_CNAME ns_t_cname +#define T_SOA ns_t_soa +#define T_MB ns_t_mb +#define T_MG ns_t_mg +#define T_MR ns_t_mr +#define T_NULL ns_t_null +#define T_WKS ns_t_wks +#define T_PTR ns_t_ptr +#define T_HINFO ns_t_hinfo +#define T_MINFO ns_t_minfo +#define T_MX ns_t_mx +#define T_TXT ns_t_txt +#define T_RP ns_t_rp +#define T_AFSDB ns_t_afsdb +#define T_X25 ns_t_x25 +#define T_ISDN ns_t_isdn +#define T_RT ns_t_rt +#define T_NSAP ns_t_nsap +#define T_NSAP_PTR ns_t_nsap_ptr +#define T_SIG ns_t_sig +#define T_KEY ns_t_key +#define T_PX ns_t_px +#define T_GPOS ns_t_gpos +#define T_AAAA ns_t_aaaa +#define T_LOC ns_t_loc +#define T_NXT ns_t_nxt +#define T_EID ns_t_eid +#define T_NIMLOC ns_t_nimloc +#define T_SRV ns_t_srv +#define T_ATMA ns_t_atma +#define T_NAPTR ns_t_naptr +#define T_IXFR ns_t_ixfr +#define T_AXFR ns_t_axfr +#define T_MAILB ns_t_mailb +#define T_MAILA ns_t_maila +#define T_ANY ns_t_any + +#define C_IN ns_c_in +#define C_CHAOS ns_c_chaos +#define C_HS ns_c_hs +/* BIND_UPDATE */ +#define C_NONE ns_c_none +#define C_ANY ns_c_any + +#define GETSHORT NS_GET16 +#define GETLONG NS_GET32 +#define PUTSHORT NS_PUT16 +#define PUTLONG NS_PUT32 + +#endif /* _ARPA_NAMESER_COMPAT_ */ diff --git a/contrib/bind/include/fd_setsize.h b/contrib/bind/include/fd_setsize.h new file mode 100644 index 0000000..235b1ad --- /dev/null +++ b/contrib/bind/include/fd_setsize.h @@ -0,0 +1,9 @@ +#ifndef _FD_SETSIZE_H +#define _FD_SETSIZE_H + +/* + * If you need a bigger FD_SETSIZE, this is NOT the place to set it. + * This file is a fallback for BIND ports which don't specify their own. + */ + +#endif /* _FD_SETSIZE_H */ diff --git a/contrib/bind/include/hesiod.h b/contrib/bind/include/hesiod.h new file mode 100644 index 0000000..b0a3e45 --- /dev/null +++ b/contrib/bind/include/hesiod.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* + * $Id: hesiod.h,v 1.5 1996/12/04 09:39:00 vixie Exp $ + */ + +#ifndef _HESIOD_H_INCLUDED +#define _HESIOD_H_INCLUDED + +int hesiod_init __P((void **context)); +void hesiod_end __P((void *context)); +char * hesiod_to_bind __P((void *context, const char *name, + const char *type)); +char ** hesiod_resolve __P((void *context, const char *name, + const char *type)); +void hesiod_free_list __P((void *context, char **list)); + +#endif /*_HESIOD_H_INCLUDED*/ diff --git a/contrib/bind/include/irs.h b/contrib/bind/include/irs.h new file mode 100644 index 0000000..0606e01 --- /dev/null +++ b/contrib/bind/include/irs.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irs.h,v 8.1 1997/12/04 04:55:19 halley Exp $ + */ + +#ifndef _IRS_H_INCLUDED +#define _IRS_H_INCLUDED + +#include <sys/types.h> + +#include <netdb.h> +#include <grp.h> +#include <pwd.h> + +/* + * This is the group map class. + */ +struct irs_gr { + void * private; + void (*close) __P((struct irs_gr *)); + struct group * (*next) __P((struct irs_gr *)); + struct group * (*byname) __P((struct irs_gr *, const char *)); + struct group * (*bygid) __P((struct irs_gr *, gid_t)); + int (*list) __P((struct irs_gr *, const char *, + gid_t, gid_t *, int *)); + void (*rewind) __P((struct irs_gr *)); + void (*minimize) __P((struct irs_gr *)); +}; + +/* + * This is the password map class. + */ +struct irs_pw { + void * private; + void (*close) __P((struct irs_pw *)); + struct passwd * (*next) __P((struct irs_pw *)); + struct passwd * (*byname) __P((struct irs_pw *, const char *)); + struct passwd * (*byuid) __P((struct irs_pw *, uid_t)); + void (*rewind) __P((struct irs_pw *)); + void (*minimize) __P((struct irs_pw *)); +}; + +/* + * This is the service map class. + */ +struct irs_sv { + void * private; + void (*close) __P((struct irs_sv *)); + struct servent *(*byname) __P((struct irs_sv *, + const char *, const char *)); + struct servent *(*byport) __P((struct irs_sv *, int, const char *)); + struct servent *(*next) __P((struct irs_sv *)); + void (*rewind) __P((struct irs_sv *)); + void (*minimize) __P((struct irs_sv *)); +}; + +/* + * This is the protocols map class. + */ +struct irs_pr { + void * private; + void (*close) __P((struct irs_pr *)); + struct protoent *(*byname) __P((struct irs_pr *, const char *)); + struct protoent *(*bynumber) __P((struct irs_pr *, int)); + struct protoent *(*next) __P((struct irs_pr *)); + void (*rewind) __P((struct irs_pr *)); + void (*minimize) __P((struct irs_pr *)); +}; + +/* + * This is the hosts map class. + */ +struct irs_ho { + void * private; + void (*close) __P((struct irs_ho *)); + struct hostent *(*byname) __P((struct irs_ho *, const char *)); + struct hostent *(*byname2) __P((struct irs_ho *, const char *, int)); + struct hostent *(*byaddr) __P((struct irs_ho *, + const void *, int, int)); + struct hostent *(*next) __P((struct irs_ho *)); + void (*rewind) __P((struct irs_ho *)); + void (*minimize) __P((struct irs_ho *)); +}; + +/* + * This is the networks map class. + */ +struct irs_nw { + void * private; + void (*close) __P((struct irs_nw *)); + struct nwent * (*byname) __P((struct irs_nw *, const char *, int)); + struct nwent * (*byaddr) __P((struct irs_nw *, void *, int, int)); + struct nwent * (*next) __P((struct irs_nw *)); + void (*rewind) __P((struct irs_nw *)); + void (*minimize) __P((struct irs_nw *)); +}; + +/* + * This is the netgroups map class. + */ +struct irs_ng { + void * private; + void (*close) __P((struct irs_ng *)); + int (*next) __P((struct irs_ng *, char **, char **, + char **)); + int (*test) __P((struct irs_ng *, const char *, + const char *, const char *, + const char *)); + void (*rewind) __P((struct irs_ng *, const char *)); + void (*minimize) __P((struct irs_ng *)); +}; + +/* + * This is the generic map class, which copies the front of all others. + */ +struct irs_map { + void * private; + void (*close) __P((void *)); +}; + +/* + * This is the accessor class. It contains pointers to all of the + * initializers for the map classes for a particular accessor. + */ +struct irs_acc { + void * private; + void (*close) __P((struct irs_acc *)); + struct irs_gr * (*gr_map) __P((struct irs_acc *)); + struct irs_pw * (*pw_map) __P((struct irs_acc *)); + struct irs_sv * (*sv_map) __P((struct irs_acc *)); + struct irs_pr * (*pr_map) __P((struct irs_acc *)); + struct irs_ho * (*ho_map) __P((struct irs_acc *)); + struct irs_nw * (*nw_map) __P((struct irs_acc *)); + struct irs_ng * (*ng_map) __P((struct irs_acc *)); +}; + +/* + * This is because the official definition of "struct netent" has no + * concept of CIDR even though it allows variant address families (on + * output but not input). The compatibility stubs convert the structs + * below into "struct netent"'s. + */ +struct nwent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + int n_addrtype; /* net address type */ + void *n_addr; /* network address */ + int n_length; /* address length, in bits */ +}; + +/* + * Hide external function names from POSIX. + */ +#define irs_gen_acc __irs_gen_acc +#define irs_lcl_acc __irs_lcl_acc +#define irs_dns_acc __irs_dns_acc +#define irs_nis_acc __irs_nis_acc + +/* + * Externs. + */ +extern struct irs_acc * irs_gen_acc __P((const char *options)); +extern struct irs_acc * irs_lcl_acc __P((const char *options)); +extern struct irs_acc * irs_dns_acc __P((const char *options)); +extern struct irs_acc * irs_nis_acc __P((const char *options)); + +#endif /*_IRS_H_INCLUDED*/ diff --git a/contrib/bind/include/isc/Makefile b/contrib/bind/include/isc/Makefile new file mode 100644 index 0000000..4e8fc8c --- /dev/null +++ b/contrib/bind/include/isc/Makefile @@ -0,0 +1,40 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +HFILES = eventlib.h misc.h tree.h logging.h heap.h memcluster.h \ + assertions.h list.h + +DESTDIR = +DESTINC = /usr/local/bind/include + +all depend: + +distclean: clean + +clean: FRC + rm -f *~ *.BAK *.CKP *.orig + +install: ${DESTDIR}${DESTINC}/isc + set -x; for x in ${HFILES}; do \ + ${INSTALL} -c -m 444 $$x ${DESTDIR}${DESTINC}/isc/$$x; \ + done + +${DESTDIR}${DESTINC}/isc: + mkdir -p ${DESTDIR}${DESTINC}/isc + +links: FRC + @set -e; ln -s SRC/*.h . + +FRC: diff --git a/contrib/bind/include/isc/assertions.h b/contrib/bind/include/isc/assertions.h new file mode 100644 index 0000000..95a9556 --- /dev/null +++ b/contrib/bind/include/isc/assertions.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1997 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. + */ + +/* + * $Id: assertions.h,v 8.1 1997/12/03 22:34:50 halley Exp $ + */ + +#ifndef ASSERTIONS_H +#define ASSERTIONS_H 1 + +typedef enum { + assert_require, assert_ensure, assert_insist, assert_invariant +} assertion_type; + +typedef void (*assertion_failure_callback)(char *, int, assertion_type, char *, + int); + +extern assertion_failure_callback __assertion_failed; +void set_assertion_failure_callback(assertion_failure_callback f); +char *assertion_type_to_text(assertion_type type); + +#ifdef CHECK_ALL +#define CHECK_REQUIRE 1 +#define CHECK_ENSURE 1 +#define CHECK_INSIST 1 +#define CHECK_INVARIANT 1 +#endif + +#ifdef CHECK_NONE +#define CHECK_REQUIRE 0 +#define CHECK_ENSURE 0 +#define CHECK_INSIST 0 +#define CHECK_INVARIANT 0 +#endif + +#ifndef CHECK_REQUIRE +#define CHECK_REQUIRE 1 +#endif + +#ifndef CHECK_ENSURE +#define CHECK_ENSURE 1 +#endif + +#ifndef CHECK_INSIST +#define CHECK_INSIST 1 +#endif + +#ifndef CHECK_INVARIANT +#define CHECK_INVARIANT 1 +#endif + +#if CHECK_REQUIRE != 0 +#define REQUIRE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 0), 0))) +#define REQUIRE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 1), 0))) +#else +#define REQUIRE(cond) ((void) 0) +#define REQUIRE_ERR(cond) ((void) 0) +#endif /* CHECK_REQUIRE */ + +#if CHECK_ENSURE != 0 +#define ENSURE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 0), 0))) +#define ENSURE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 1), 0))) +#else +#define ENSURE(cond) ((void) 0) +#define ENSURE_ERR(cond) ((void) 0) +#endif /* CHECK_ENSURE */ + +#if CHECK_INSIST != 0 +#define INSIST(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 0), 0))) +#define INSIST_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 1), 0))) +#else +#define INSIST(cond) ((void) 0) +#define INSIST_ERR(cond) ((void) 0) +#endif /* CHECK_INSIST */ + +#if CHECK_INVARIANT != 0 +#define INVARIANT(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 0), 0))) +#define INVARIANT_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 1), 0))) +#else +#define INVARIANT(cond) ((void) 0) +#define INVARIANT_ERR(cond) ((void) 0) +#endif /* CHECK_INVARIANT */ + +#endif /* ASSERTIONS_H */ diff --git a/contrib/bind/include/isc/eventlib.h b/contrib/bind/include/isc/eventlib.h new file mode 100644 index 0000000..98a0f46 --- /dev/null +++ b/contrib/bind/include/isc/eventlib.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* eventlib.h - exported interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib.h,v 1.19 1998/02/06 01:55:51 halley Exp $ + */ + +#ifndef _EVENTLIB_H +#define _EVENTLIB_H + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <stdio.h> + +#ifndef __P +# define __EVENTLIB_P_DEFINED +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/* In the absence of branded types... */ +typedef struct { void *opaque; } evConnID; +typedef struct { void *opaque; } evFileID; +typedef struct { void *opaque; } evStreamID; +typedef struct { void *opaque; } evTimerID; +typedef struct { void *opaque; } evWaitID; +typedef struct { void *opaque; } evContext; +typedef struct { void *opaque; } evEvent; + +typedef void (*evConnFunc)__P((evContext ctx, void *uap, int fd, + const void *la, int lalen, + const void *ra, int ralen)); +typedef void (*evFileFunc)__P((evContext ctx, void *uap, int fd, int evmask)); +typedef void (*evStreamFunc)__P((evContext ctx, void *uap, int fd, int bytes)); +typedef void (*evTimerFunc)__P((evContext ctx, void *uap, + struct timespec due, struct timespec inter)); +typedef void (*evWaitFunc)__P((evContext ctx, void *uap, const void *tag)); + +typedef struct { unsigned char mask[256/8]; } evByteMask; +#define EV_BYTEMASK_BYTE(b) ((b) / 8) +#define EV_BYTEMASK_MASK(b) (1 << ((b) % 8)) +#define EV_BYTEMASK_SET(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] |= EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_CLR(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] &= ~EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_TST(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] & EV_BYTEMASK_MASK(b)) + +#define EV_POLL 1 +#define EV_WAIT 2 +#define EV_NULL 4 + +#define EV_READ 1 +#define EV_WRITE 2 +#define EV_EXCEPT 4 + +/* eventlib.c */ +#define evCreate __evCreate +#define evSetDebug __evSetDebug +#define evDestroy __evDestroy +#define evGetNext __evGetNext +#define evDispatch __evDispatch +#define evDrop __evDrop +#define evMainLoop __evMainLoop + +int evCreate __P((evContext *ctx)); +void evSetDebug __P((evContext ctx, int lev, FILE *out)); +int evDestroy __P((evContext ctx)); +int evGetNext __P((evContext ctx, evEvent *ev, int options)); +int evDispatch __P((evContext ctx, evEvent ev)); +void evDrop __P((evContext ctx, evEvent ev)); +int evMainLoop __P((evContext ctx)); + +/* ev_connects.c */ +#define evListen __evListen +#define evConnect __evConnect +#define evCancelConn __evCancelConn +#define evHold __evHold +#define evUnhold __evUnhold +#define evTryAccept __evTryAccept + +int evListen __P((evContext ctx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id)); +int evConnect __P((evContext ctx, int fd, void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id)); +int evCancelConn __P((evContext ctx, evConnID id)); +int evHold __P((evContext, evConnID)); +int evUnhold __P((evContext, evConnID)); +int evTryAccept __P((evContext, evConnID, int *)); + +/* ev_files.c */ +#define evSelectFD __evSelectFD +#define evDeselectFD __evDeselectFD + +int evSelectFD __P((evContext ctx, int fd, int eventmask, + evFileFunc func, void *uap, evFileID *id)); +int evDeselectFD __P((evContext ctx, evFileID id)); + +/* ev_streams.c */ +#define evConsIovec __evConsIovec +#define evWrite __evWrite +#define evRead __evRead +#define evTimeRW __evTimeRW +#define evUntimeRW __evUntimeRW +#define evCancelRW __evCancelRW + +struct iovec evConsIovec __P((void *buf, size_t cnt)); +int evWrite __P((evContext ctx, int fd, const struct iovec *iov, int cnt, + evStreamFunc func, void *uap, evStreamID *id)); +int evRead __P((evContext ctx, int fd, const struct iovec *iov, int cnt, + evStreamFunc func, void *uap, evStreamID *id)); +int evTimeRW __P((evContext ctx, evStreamID id, evTimerID timer)); +int evUntimeRW __P((evContext ctx, evStreamID id)); +int evCancelRW __P((evContext ctx, evStreamID id)); + +/* ev_timers.c */ +#define evConsTime __evConsTime +#define evAddTime __evAddTime +#define evSubTime __evSubTime +#define evCmpTime __evCmpTime +#define evTimeSpec __evTimeSpec +#define evTimeVal __evTimeVal + +#define evNowTime __evNowTime +#define evLastEventTime __evLastEventTime +#define evSetTimer __evSetTimer +#define evClearTimer __evClearTimer +#define evResetTimer __evResetTimer +#define evSetIdleTimer __evSetIdleTimer +#define evClearIdleTimer __evClearIdleTimer +#define evResetIdleTimer __evResetIdleTimer +#define evTouchIdleTimer __evTouchIdleTimer + +struct timespec evConsTime __P((time_t sec, long nsec)); +struct timespec evAddTime __P((struct timespec add1, struct timespec add2)); +struct timespec evSubTime __P((struct timespec minu, struct timespec subtra)); +struct timespec evNowTime __P((void)); +struct timespec evLastEventTime __P((evContext)); +struct timespec evTimeSpec __P((struct timeval)); +struct timeval evTimeVal __P((struct timespec)); +int evCmpTime __P((struct timespec a, struct timespec b)); +int evSetTimer __P((evContext ctx, evTimerFunc func, void *uap, + struct timespec due, struct timespec inter, + evTimerID *id)); +int evClearTimer __P((evContext ctx, evTimerID id)); +int evResetTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec, struct timespec)); +int evSetIdleTimer __P((evContext, evTimerFunc, void *, struct timespec, + evTimerID *)); +int evClearIdleTimer __P((evContext, evTimerID)); +int evResetIdleTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec)); +int evTouchIdleTimer __P((evContext, evTimerID)); + +/* ev_waits.c */ +#define evWaitFor __evWaitFor +#define evDo __evDo +#define evUnwait __evUnwait +#define evDefer __evDefer + +int evWaitFor __P((evContext ctx, const void *tag, evWaitFunc func, void *uap, + evWaitID *id)); +int evDo __P((evContext ctx, const void *tag)); +int evUnwait __P((evContext ctx, evWaitID id)); +int evDefer __P((evContext, evWaitFunc, void *)); + +#ifdef __EVENTLIB_P_DEFINED +# undef __P +#endif + +#endif /*_EVENTLIB_H*/ diff --git a/contrib/bind/include/isc/heap.h b/contrib/bind/include/isc/heap.h new file mode 100644 index 0000000..5df73e8 --- /dev/null +++ b/contrib/bind/include/isc/heap.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1997 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. + */ + +typedef int (*heap_higher_priority_func)(void *, void *); +typedef void (*heap_index_func)(void *, int); +typedef void (*heap_for_each_func)(void *, void *); + +typedef struct heap_context { + int array_size; + int array_size_increment; + int heap_size; + void **heap; + heap_higher_priority_func higher_priority; + heap_index_func index; +} *heap_context; + +#define heap_new __heap_new +#define heap_free __heap_free +#define heap_insert __heap_insert +#define heap_delete __heap_delete +#define heap_increased __heap_increased +#define heap_decreased __heap_decreased +#define heap_element __heap_element +#define heap_for_each __heap_for_each + +heap_context heap_new(heap_higher_priority_func, heap_index_func, int); +int heap_free(heap_context); +int heap_insert(heap_context, void *); +int heap_delete(heap_context, int); +int heap_increased(heap_context, int); +int heap_decreased(heap_context, int); +void * heap_element(heap_context, int); +int heap_for_each(heap_context, heap_for_each_func, void *); diff --git a/contrib/bind/include/isc/list.h b/contrib/bind/include/isc/list.h new file mode 100644 index 0000000..b78ba4f --- /dev/null +++ b/contrib/bind/include/isc/list.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1997 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. + */ + +#ifndef LIST_H +#define LIST_H 1 + +#define LIST(type) struct { type *head, *tail; } +#define INIT_LIST(list) \ + do { (list).head = NULL; (list).tail = NULL; } while (0) + +#define LINK(type) struct { type *prev, *next; } +#define INIT_LINK(elt, link) \ + do { \ + (elt)->link.prev = (void *)(-1); \ + (elt)->link.next = (void *)(-1); \ + } while (0) +#define LINKED(elt, link) ((elt)->link.prev != (void *)(-1)) + +#define HEAD(list) ((list).head) +#define TAIL(list) ((list).tail) +#define EMPTY(list) ((list).head == NULL) + +#define 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 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 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; \ + } while (0) + +#define PREV(elt, link) ((elt)->link.prev) +#define NEXT(elt, link) ((elt)->link.next) + +#define INSERT_BEFORE(list, before, elt, link) \ + do { \ + if ((before)->link.prev == NULL) \ + 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 INSERT_AFTER(list, after, elt, link) \ + do { \ + if ((after)->link.next == NULL) \ + 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 ENQUEUE(list, elt, link) APPEND(list, elt, link) +#define DEQUEUE(list, elt, link) UNLINK(list, elt, link) + +#endif /* LIST_H */ diff --git a/contrib/bind/include/isc/logging.h b/contrib/bind/include/isc/logging.h new file mode 100644 index 0000000..5b11906 --- /dev/null +++ b/contrib/bind/include/isc/logging.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1996, 1997, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef LOGGING_H +#define LOGGING_H + +#include <stdio.h> +#include <stdarg.h> + +#define log_critical (-5) +#define log_error (-4) +#define log_warning (-3) +#define log_notice (-2) +#define log_info (-1) +#define log_debug(level) (level) + +typedef enum { log_syslog, log_file, log_null } log_channel_type; + +#define LOG_MAX_VERSIONS 99 + +#define LOG_CLOSE_STREAM 0x0001 +#define LOG_TIMESTAMP 0x0002 +#define LOG_TRUNCATE 0x0004 +#define LOG_USE_CONTEXT_LEVEL 0x0008 +#define LOG_PRINT_LEVEL 0x0010 +#define LOG_REQUIRE_DEBUG 0x0020 +#define LOG_CHANNEL_BROKEN 0x0040 +#define LOG_PRINT_CATEGORY 0x0080 +#define LOG_CHANNEL_OFF 0x0100 + +typedef struct log_context *log_context; +typedef struct log_channel *log_channel; + +#define LOG_OPTION_DEBUG 0x01 +#define LOG_OPTION_LEVEL 0x02 + +#define log_open_stream __log_open_stream +#define log_close_stream __log_close_stream +#define log_get_stream __log_get_stream +#define log_get_filename __log_get_filename +#define log_check_channel __log_check_channel +#define log_check __log_check +#define log_vwrite __log_vwrite +#define log_write __log_write +#define log_new_context __log_new_context +#define log_free_context __log_free_context +#define log_add_channel __log_add_channel +#define log_remove_channel __log_remove_channel +#define log_option __log_option +#define log_category_is_active __log_category_is_active +#define log_new_syslog_channel __log_new_syslog_channel +#define log_new_file_channel __log_new_file_channel +#define log_new_null_channel __log_new_null_channel +#define log_inc_references __log_inc_references +#define log_dec_references __log_dec_references +#define log_get_channel_type __log_get_channel_type +#define log_free_channel __log_free_channel + +FILE * log_open_stream(log_channel); +int log_close_stream(log_channel); +FILE * log_get_stream(log_channel); +char * log_get_filename(log_channel); +int log_check_channel(log_context, int, log_channel); +int log_check(log_context, int, int); +void log_vwrite(log_context, int, int, const char *, + va_list args); +void log_write(log_context, int, int, const char *, ...); +int log_new_context(int, char **, log_context *); +void log_free_context(log_context); +int log_add_channel(log_context, int, log_channel); +int log_remove_channel(log_context, int, log_channel); +int log_option(log_context, int, int); +int log_category_is_active(log_context, int); +log_channel log_new_syslog_channel(unsigned int, int, int); +log_channel log_new_file_channel(unsigned int, int, char *, + FILE *, unsigned int, + unsigned long); +log_channel log_new_null_channel(void); +int log_inc_references(log_channel); +int log_dec_references(log_channel); +log_channel_type log_get_channel_type(log_channel); +int log_free_channel(log_channel); + +#endif /* !LOGGING_H */ diff --git a/contrib/bind/include/isc/memcluster.h b/contrib/bind/include/isc/memcluster.h new file mode 100644 index 0000000..e5f0c75 --- /dev/null +++ b/contrib/bind/include/isc/memcluster.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1997 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. + */ + +#ifndef MEMCLUSTER_H +#define MEMCLUSTER_H + +#include <stdio.h> + +#define meminit __meminit +#ifdef MEMCLUSTER_DEBUG +#define memget(s) __memget_debug(s, __FILE__, __LINE__) +#define memput(p, s) __memput_debug(p, s, __FILE__, __LINE__) +#else +#define memget __memget +#define memput __memput +#endif +#define memstats __memstats + +int meminit(size_t, size_t); +void * __memget(size_t); +void __memput(void *, size_t); +void * __memget_debug(size_t, const char *, int); +void __memput_debug(void *, size_t, const char *, int); +void memstats(FILE *); + +#endif /* MEMCLUSTER_H */ diff --git a/contrib/bind/include/isc/misc.h b/contrib/bind/include/isc/misc.h new file mode 100644 index 0000000..09b593f --- /dev/null +++ b/contrib/bind/include/isc/misc.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1995, 1996 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: misc.h,v 8.1 1996/11/12 03:19:13 vixie Exp $ + */ + +#ifndef _ISC_MISC_H +#define _ISC_MISC_H + +#define bitncmp __bitncmp + +extern int bitncmp(const void *l, const void *r, int n); + +#endif /*_ISC_MISC_H*/ diff --git a/contrib/bind/include/isc/tree.h b/contrib/bind/include/isc/tree.h new file mode 100644 index 0000000..24e2a10 --- /dev/null +++ b/contrib/bind/include/isc/tree.h @@ -0,0 +1,48 @@ +/* tree.h - declare structures used by tree library + * + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 27jun86 [broken out of tree.c] + * + * $Id: tree.h,v 8.2 1996/10/25 18:11:03 vixie Exp $ + */ + + +#ifndef _TREE_H_INCLUDED +#define _TREE_H_INCLUDED + + +#ifndef __P +# if defined(__STDC__) || defined(__GNUC__) +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/* + * tree_t is our package-specific anonymous pointer. + */ +#if defined(__STDC__) || defined(__GNUC__) +typedef void *tree_t; +#else +typedef char *tree_t; +#endif + + +typedef struct tree_s { + tree_t data; + struct tree_s *left, *right; + short bal; + } + tree; + + +void tree_init __P((tree **)); +tree_t tree_srch __P((tree **, int (*)(), tree_t)); +tree_t tree_add __P((tree **, int (*)(), tree_t, void (*)())); +int tree_delete __P((tree **, int (*)(), tree_t, void (*)())); +int tree_trav __P((tree **, int (*)())); +void tree_mung __P((tree **, void (*)())); + + +#endif /* _TREE_H_INCLUDED */ diff --git a/contrib/bind/include/netdb.h b/contrib/bind/include/netdb.h index cd11afa..7527cc9 100644 --- a/contrib/bind/include/netdb.h +++ b/contrib/bind/include/netdb.h @@ -55,7 +55,7 @@ /* * @(#)netdb.h 8.1 (Berkeley) 6/2/93 - * $Id: netdb.h,v 8.8 1997/06/01 20:34:32 vixie Exp $ + * $Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $ */ #ifndef _NETDB_H_ @@ -67,7 +67,9 @@ #endif #include <sys/cdefs.h> -#define _PATH_HEQUIV "/etc/hosts.equiv" +#ifndef _PATH_HEQUIV +# define _PATH_HEQUIV "/etc/hosts.equiv" +#endif #define _PATH_HOSTS "/etc/hosts" #define _PATH_NETWORKS "/etc/networks" #define _PATH_PROTOCOLS "/etc/protocols" @@ -167,12 +169,4 @@ struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); #endif /* __GNU_LIBRARY__ */ #endif /* sun */ -/* - * The Motorola kernel will only support 64 characters for hostname - * also defined in /usr/ucbinclude/netdb.h - */ -#ifdef __m88k__ -#define MAXHOSTNAMELEN 64 -#endif - #endif /* !_NETDB_H_ */ diff --git a/contrib/bind/include/resolv.h b/contrib/bind/include/resolv.h index 9db2202..7f359fe 100644 --- a/contrib/bind/include/resolv.h +++ b/contrib/bind/include/resolv.h @@ -1,7 +1,5 @@ /* - * ++Copyright++ 1983, 1987, 1989, 1993 - * - - * Copyright (c) 1983, 1987, 1989, 1993 + * Copyright (c) 1983, 1987, 1989 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,31 +29,28 @@ * LIABILITY, OR TORT (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. - * + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, 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 + * 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. - * - - * --Copyright-- */ /* * @(#)resolv.h 8.1 (Berkeley) 6/2/93 - * $Id: resolv.h,v 8.18 1997/06/01 20:34:32 vixie Exp $ + * $Id: resolv.h,v 8.11 1998/01/26 23:09:53 halley Exp $ */ #ifndef _RESOLV_H_ @@ -81,6 +76,15 @@ #define __RES 19960801 /* + * This used to be defined in res_query.c, now it's in herror.c. It was + * never extern'd by any *.h file before it was placed here. herror.c is + * part of libresolv.a even though it might make more sense in libnetdb.a + * or even libnet.a. + */ + +extern int h_errno; + +/* * Resolver configuration file. * Normally not present, but may contain the address of the * inital name server(s) to query and the domain search list. @@ -121,7 +125,7 @@ struct __res_state { struct in_addr addr; u_int32_t mask; } sort_list[MAXRESOLVSORT]; - char pad[72]; /* on an i386 this means 512b total */ + char pad[72]; /* On an i386 this means 512b total. */ }; /* @@ -148,7 +152,7 @@ struct __res_state { * Resolver "pfcode" values. Used by dig. */ #define RES_PRF_STATS 0x00000001 -/* 0x00000002 */ +#define RES_PRF_UPDATE 0x00000002 #define RES_PRF_CLASS 0x00000004 #define RES_PRF_CMD 0x00000008 #define RES_PRF_QUES 0x00000010 @@ -161,10 +165,9 @@ struct __res_state { #define RES_PRF_HEADX 0x00000800 #define RES_PRF_QUERY 0x00001000 #define RES_PRF_REPLY 0x00002000 -#define RES_PRF_INIT 0x00004000 +#define RES_PRF_INIT 0x00004000 /* 0x00008000 */ -/* hooks are still experimental as of 4.9.2 */ typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } res_sendhookact; @@ -192,66 +195,66 @@ extern struct __res_state _res; extern const struct res_sym __p_class_syms[]; extern const struct res_sym __p_type_syms[]; -/* Private routines shared between libc/net, named, nslookup and others. */ -#define res_hnok __res_hnok -#define res_ownok __res_ownok -#define res_mailok __res_mailok -#define res_dnok __res_dnok -#define sym_ston __sym_ston -#define sym_ntos __sym_ntos -#define sym_ntop __sym_ntop -#define b64_ntop __b64_ntop -#define b64_pton __b64_pton -#define loc_ntoa __loc_ntoa -#define loc_aton __loc_aton -#define dn_skipname __dn_skipname -#define fp_resstat __fp_resstat -#define fp_query __fp_query -#define fp_nquery __fp_nquery -#define hostalias __hostalias -#define putlong __putlong -#define putshort __putshort -#define p_class __p_class -#define p_time __p_time -#define p_type __p_type -#define p_query __p_query -#define p_cdnname __p_cdnname -#define p_cdname __p_cdname -#define p_fqnname __p_fqnname -#define p_fqname __p_fqname -#define p_rr __p_rr -#define p_option __p_option -#define p_secstodate __p_secstodate -#define dn_count_labels __dn_count_labels -#define dn_comp __dn_comp -#define res_randomid __res_randomid -#define res_isourserver __res_isourserver -#define res_nameinquery __res_nameinquery -#define res_queriesmatch __res_queriesmatch -#define res_close __res_close - -#ifdef BIND_RES_POSIX3 -#define dn_expand __dn_expand -#define res_init __res_init -#define res_query __res_query -#define res_search __res_search -#define res_querydomain __res_querydomain -#define res_mkquery __res_mkquery -#define res_send __res_send -#endif - +#define res_hnok __res_hnok +#define res_ownok __res_ownok +#define res_mailok __res_mailok +#define res_dnok __res_dnok +#define sym_ston __sym_ston +#define sym_ntos __sym_ntos +#define sym_ntop __sym_ntop +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define loc_ntoa __loc_ntoa +#define loc_aton __loc_aton +#define fp_resstat __fp_resstat +#define p_query __p_query +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define fp_query __fp_query +#define fp_nquery __fp_nquery +#define hostalias __hostalias +#define putlong __putlong +#define putshort __putshort +#define p_class __p_class +#define p_time __p_time +#define p_type __p_type +#define p_query __p_query +#define p_cdnname __p_cdnname +#define p_section __p_section +#define p_cdname __p_cdname +#define p_fqnname __p_fqnname +#define p_fqname __p_fqname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define dn_count_labels __dn_count_labels +#define dn_comp __dn_comp +#define dn_expand __dn_expand +#define res_init __res_init +#define res_randomid __res_randomid +#define res_query __res_query +#define res_search __res_search +#define res_querydomain __res_querydomain +#define res_mkquery __res_mkquery +#define res_send __res_send +#define res_isourserver __res_isourserver +#define res_nameinquery __res_nameinquery +#define res_queriesmatch __res_queriesmatch +#define res_close __res_close +#define res_mkupdate __res_mkupdate +#define res_mkupdrec __res_mkupdrec +#define res_freeupdrec __res_freeupdrec __BEGIN_DECLS int res_hnok __P((const char *)); int res_ownok __P((const char *)); int res_mailok __P((const char *)); int res_dnok __P((const char *)); -int sym_ston __P((const struct res_sym *, char *, int *)); +int sym_ston __P((const struct res_sym *, const char *, int *)); const char * sym_ntos __P((const struct res_sym *, int, int *)); const char * sym_ntop __P((const struct res_sym *, int, int *)); int b64_ntop __P((u_char const *, size_t, char *, size_t)); int b64_pton __P((char const *, u_char *, size_t)); -int loc_aton __P((const char *, u_char *)); -const char * loc_ntoa __P((const u_char *, char *)); +int loc_aton __P((const char *ascii, u_char *binary)); +const char * loc_ntoa __P((const u_char *binary, char *ascii)); int dn_skipname __P((const u_char *, const u_char *)); void fp_resstat __P((struct __res_state *, FILE *)); void fp_query __P((const u_char *, FILE *)); @@ -268,10 +271,9 @@ const u_char * p_cdname __P((const u_char *, const u_char *, FILE *)); const u_char * p_fqnname __P((const u_char *cp, const u_char *msg, int, char *, int)); const u_char * p_fqname __P((const u_char *, const u_char *, FILE *)); -const u_char * p_rr __P((const u_char *, const u_char *, FILE *)); const char * p_option __P((u_long option)); char * p_secstodate __P((u_long)); -int dn_count_labels __P((char *)); +int dn_count_labels __P((const char *)); int dn_comp __P((const char *, u_char *, int, u_char **, u_char **)); int dn_expand __P((const u_char *, const u_char *, const u_char *, @@ -282,8 +284,8 @@ int res_query __P((const char *, int, int, u_char *, int)); int res_search __P((const char *, int, int, u_char *, int)); int res_querydomain __P((const char *, const char *, int, int, u_char *, int)); -int res_mkquery __P((int, const char *, int, int, const u_char *, int, - const u_char *, u_char *, int)); +int res_mkquery __P((int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int)); int res_send __P((const u_char *, int, u_char *, int)); int res_isourserver __P((const struct sockaddr_in *)); int res_nameinquery __P((const char *, int, int, @@ -291,6 +293,11 @@ int res_nameinquery __P((const char *, int, int, int res_queriesmatch __P((const u_char *, const u_char *, const u_char *, const u_char *)); void res_close __P((void)); +const char * p_section __P((int section, int opcode)); +int res_update __P((ns_updrec *)); +int res_mkupdate __P((ns_updrec *, u_char *, int)); +ns_updrec * res_mkupdrec __P((int, const char *, u_int, u_int, u_long)); +void res_freeupdrec(ns_updrec *rrecp); __END_DECLS #endif /* !_RESOLV_H_ */ diff --git a/contrib/bind/lib/Makefile b/contrib/bind/lib/Makefile new file mode 100644 index 0000000..5029f2f --- /dev/null +++ b/contrib/bind/lib/Makefile @@ -0,0 +1,90 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# $Id: Makefile,v 8.10 1997/09/26 17:56:00 halley Exp $ + +SUBDIRS = resolv irs isc bsd inet nameser + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsdos +SHELL= /bin/sh +O=o +A=a +DESTDIR= +DESTINC= /usr/local/bind/include +DESTLIB= /usr/local/bind/lib +TOP= .. +INCL= ${TOP}/include +PORTINCL= ${TOP}/port/${SYSTYPE}/include +LIBBIND= ${TOP}/lib/libbind.${A} +LIBPORT= ${TOP}/port/libport.${A} +RANLIB= ranlib +AR= ar cruv +INSTALL= install +CDEBUG= -g + +# Warning: this MARGS has RANLIB=: to prevent submakes from running ranlib +MARGS = "SYSTYPE=${SYSTYPE}" "SHELL=${SHELL}" "A=${A}" "O=${O}" \ + "CC=${CC}" "LEX=${LEX}" "YACC=${YACC}" "CDEBUG=${CDEBUG}" \ + "SYSLIBS=${SYSLIBS}" "LDFLAGS=${LDFLAGS}" \ + "DESTDIR=${DESTDIR}" "PIDDIR=${PIDDIR}" "DESTMAN=${DESTMAN}" \ + "DESTBIN=${DESTBIN}" "DESTSBIN=${DESTSBIN}" "DESTEXEC=${DESTEXEC}" \ + "DESTLIB=${DESTLIB}" "DESTINC=${DESTINC}" "DESTHELP=${DESTHELP}" \ + "RANLIB=:" "AR=${AR}" "ARPREF=${ARPREF}" "ARSUFF=${ARSUFF}" \ + "INCL=../${INCL}" "PORTINCL=../${PORTINCL}" \ + "LIBBIND=../${LIBBIND}" "LIBPORT=../${LIBPORT}" \ + "INSTALL=${INSTALL}" "CPPFLAGS=${CPPFLAGS}" "TOP=../${TOP}" + +LIB = libbind.${A} +LIBTS = ${TOP}/lib/libbind.ts + +all depend clean install distclean:: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ + done + +all:: ${LIBTS} + +${LIBTS}: ${LIBBIND} + ${RANLIB} ${LIBBIND} + touch ${LIBTS} + +distclean:: clean + +clean:: FRC + rm -f *~ *.BAK *.CKP *.orig + rm -f ${LIBBIND} ${LIBTS} + +install:: ${DESTDIR}${DESTLIB} ${DESTDIR}${DESTLIB}/${LIB} + +${DESTDIR}${DESTLIB}: + mkdir -p ${DESTDIR}${DESTLIB} + +${DESTDIR}${DESTLIB}/${LIB}: ${LIBBIND} + ${INSTALL} -c -o bin -g bin -m 644 ${LIBBIND} \ + ${DESTDIR}${DESTLIB}/${LIB} + ( cd ${DESTDIR}${DESTLIB} ; ${RANLIB} ${LIB} ) + +links:: FRC + @set -e; for x in ${SUBDIRS}; do \ + ( mkdir $$x; cd $$x; pwd; ln -s ../SRC/$$x SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + ${MAKE} ${MARGS} links; \ + ); \ + done + +FRC: diff --git a/contrib/bind/lib/inet/Makefile b/contrib/bind/lib/inet/Makefile new file mode 100644 index 0000000..80bff87 --- /dev/null +++ b/contrib/bind/lib/inet/Makefile @@ -0,0 +1,76 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# $Id: Makefile,v 8.8 1997/05/21 19:32:07 halley Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cruv +RANLIB= ranlib +INSTALL= install + +SRCS= nsap_addr.c inet_addr.c inet_ntop.c inet_pton.c \ + inet_ntoa.c inet_neta.c inet_net_ntop.c inet_net_pton.c \ + inet_lnaof.c inet_makeaddr.c inet_netof.c inet_network.c + +OBJS= nsap_addr.${O} inet_addr.${O} inet_ntop.${O} inet_pton.${O} \ + inet_ntoa.${O} inet_neta.${O} inet_net_ntop.${O} inet_net_pton.${O} \ + inet_lnaof.${O} inet_makeaddr.${O} inet_netof.${O} inet_network.${O} + + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/lib/inet/hostnamelen.c b/contrib/bind/lib/inet/hostnamelen.c new file mode 100644 index 0000000..9388062 --- /dev/null +++ b/contrib/bind/lib/inet/hostnamelen.c @@ -0,0 +1,94 @@ +/* + * ++Copyright++ 1995 + * - + * Copyright (c) 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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-- + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: hostnamelen.c,v 8.2 1995/08/22 05:01:47 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#if defined(BSD) && (BSD >= 199103) +# include <string.h> +#else +# include "../conf/portability.h" +#endif +#if defined(USE_OPTIONS_H) +# include <../conf/options.h> +#endif + +#ifndef ultrix +int __local_hostname_length_unneeded; +#else +int +local_hostname_length(hostname) + const char *hostname; +{ + int len_host, len_domain; + + if (!*_res.defdname) + res_init(); + len_host = strlen(hostname); + len_domain = strlen(_res.defdname); + if (len_host > len_domain && + !strcasecmp(hostname + len_host - len_domain, _res.defdname) && + hostname[len_host - len_domain - 1] == '.') + return (len_host - len_domain - 1); + return (0); +} +#endif diff --git a/contrib/bind/lib/inet/inet_addr.c b/contrib/bind/lib/inet/inet_addr.c new file mode 100644 index 0000000..1d3943b --- /dev/null +++ b/contrib/bind/lib/inet/inet_addr.c @@ -0,0 +1,185 @@ +/* + * ++Copyright++ 1983, 1990, 1993 + * - + * 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. + * - + * --Copyright-- + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; +static char rcsid[] = "$Id: inet_addr.c,v 8.7 1996/11/18 09:09:07 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> +#include "port_after.h" + +/* these are compatibility routines, not needed on recent BSD releases */ + +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +u_long +inet_addr(cp) + register const char *cp; +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(cp, addr) + register const char *cp; + struct in_addr *addr; +{ + register u_long val; + register int base, n; + register char c; + u_int parts[4]; + register u_int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + 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) + addr->s_addr = htonl(val); + return (1); +} diff --git a/contrib/bind/lib/inet/inet_lnaof.c b/contrib/bind/lib/inet/inet_lnaof.c new file mode 100644 index 0000000..9562024 --- /dev/null +++ b/contrib/bind/lib/inet/inet_lnaof.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1983, 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 char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/* + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +u_long +inet_lnaof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return ((i)&IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return ((i)&IN_CLASSB_HOST); + else + return ((i)&IN_CLASSC_HOST); +} diff --git a/contrib/bind/lib/inet/inet_makeaddr.c b/contrib/bind/lib/inet/inet_makeaddr.c new file mode 100644 index 0000000..8a4b082 --- /dev/null +++ b/contrib/bind/lib/inet/inet_makeaddr.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1983, 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 char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/* + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +struct in_addr +inet_makeaddr(net, host) + u_long net, host; +{ + u_long addr; + + if (net < 128) + addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536) + addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216L) + addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + addr = net | host; + addr = htonl(addr); + return (*(struct in_addr *)&addr); +} diff --git a/contrib/bind/lib/inet/inet_net_ntop.c b/contrib/bind/lib/inet/inet_net_ntop.c new file mode 100644 index 0000000..7f6526f --- /dev/null +++ b/contrib/bind/lib/inet/inet_net_ntop.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.4 1996/11/18 09:09:08 vixie Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits, + char *dst, size_t size)); + +/* + * char * + * inet_net_ntop(af, src, bits, dst, size) + * convert network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_net_ntop(af, src, bits, dst, size) + int af; + const void *src; + int bits; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_ntop_ipv4(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +/* + * static char * + * inet_net_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), July 1996 + */ +static char * +inet_net_ntop_ipv4(src, bits, dst, size) + const u_char *src; + int bits; + char *dst; + size_t size; +{ + char *odst = dst; + char *t; + u_int m; + int b; + + if (bits < 0 || bits > 32) { + errno = EINVAL; + return (NULL); + } + if (bits == 0) { + if (size < sizeof "0") + goto emsgsize; + *dst++ = '0'; + *dst = '\0'; + } + + /* Format whole octets. */ + for (b = bits / 8; b > 0; b--) { + if (size < sizeof "255.") + goto emsgsize; + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b > 1) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + + /* Format partial octet. */ + b = bits % 8; + if (b > 0) { + if (size < sizeof ".255") + goto emsgsize; + t = dst; + if (dst != odst) + *dst++ = '.'; + m = ((1 << b) - 1) << (8 - b); + dst += SPRINTF((dst, "%u", *src & m)); + size -= (size_t)(dst - t); + } + + /* Format CIDR /width. */ + if (size < sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} diff --git a/contrib/bind/lib/inet/inet_net_pton.c b/contrib/bind/lib/inet/inet_net_pton.c new file mode 100644 index 0000000..5f381c5 --- /dev/null +++ b/contrib/bind/lib/inet/inet_net_pton.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static int inet_net_pton_ipv4 __P((const char *src, u_char *dst, + size_t size)); + +/* + * static int + * inet_net_pton(af, src, dst, size) + * convert network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not a valid network specification. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +inet_net_pton(af, src, dst, size) + int af; + const char *src; + void *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +/* + * static int + * inet_net_pton_ipv4(src, dst, size) + * convert IPv4 network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not an IPv4 network specification. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +static int +inet_net_pton_ipv4(src, dst, size) + const char *src; + u_char *dst; + size_t size; +{ + static const char + xdigits[] = "0123456789abcdef", + digits[] = "0123456789"; + int n, ch, tmp, dirty, bits; + const u_char *odst = dst; + + ch = *src++; + if (ch == '0' && (src[0] == 'x' || src[0] == 'X') + && isascii(src[1]) && isxdigit(src[1])) { + /* Hexadecimal: Eat nybble string. */ + if (size <= 0) + goto emsgsize; + *dst = 0, dirty = 0; + src++; /* skip x or X. */ + while ((ch = *src++) != '\0' && + isascii(ch) && isxdigit(ch)) { + if (isupper(ch)) + ch = tolower(ch); + n = strchr(xdigits, ch) - xdigits; + assert(n >= 0 && n <= 15); + *dst |= n; + if (!dirty++) + *dst <<= 4; + else if (size-- > 0) + *++dst = 0, dirty = 0; + else + goto emsgsize; + } + if (dirty) + size--; + } else if (isascii(ch) && isdigit(ch)) { + /* Decimal: eat dotted digit string. */ + for (;;) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + assert(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && + isascii(ch) && isdigit(ch)); + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + ch = *src++; + if (!isascii(ch) || !isdigit(ch)) + goto enoent; + } + } else + goto enoent; + + bits = -1; + if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) { + /* CIDR width specifier. Nothing can follow it. */ + ch = *src++; /* Skip over the /. */ + bits = 0; + do { + n = strchr(digits, ch) - digits; + assert(n >= 0 && n <= 9); + bits *= 10; + bits += n; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (ch != '\0') + goto enoent; + if (bits > 32) + goto emsgsize; + if (bits > 32) + goto emsgsize; + } + + /* Firey death and destruction unless we prefetched EOS. */ + if (ch != '\0') + goto enoent; + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + /* If no CIDR spec was given, infer width from net class. */ + if (bits == -1) { + if (*odst >= 240) /* Class E */ + bits = 32; + else if (*odst >= 224) /* Class D */ + bits = 4; + else if (*odst >= 192) /* Class C */ + bits = 24; + else if (*odst >= 128) /* Class B */ + bits = 16; + else /* Class A */ + bits = 8; + /* If imputed mask is narrower than specified octets, widen. */ + if (bits >= 8 && bits < ((dst - odst) * 8)) + bits = (dst - odst) * 8; + } + /* Extend network to cover the actual mask. */ + while (bits > ((dst - odst) * 8)) { + if (size-- <= 0) + goto emsgsize; + *dst++ = '\0'; + } + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} diff --git a/contrib/bind/lib/inet/inet_neta.c b/contrib/bind/lib/inet/inet_neta.c new file mode 100644 index 0000000..96c24f3 --- /dev/null +++ b/contrib/bind/lib/inet/inet_neta.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_neta.c,v 1.5 1997/09/26 17:56:01 halley Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * char * + * inet_neta(src, dst, size) + * format a u_long network number into presentation format. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * format of ``src'' is as for inet_network(). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_neta(src, dst, size) + u_long src; + char *dst; + size_t size; +{ + char *odst = dst; + char *tp; + + while (src & 0xffffffff) { + u_char b = (src & 0xff000000) >> 24; + + src <<= 8; + if (b) { + if (size < sizeof "255.") + goto emsgsize; + tp = dst; + dst += SPRINTF((dst, "%u", b)); + if (src != 0L) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - tp); + } + } + if (dst == odst) { + if (size < sizeof "0.0.0.0") + goto emsgsize; + strcpy(dst, "0.0.0.0"); + } + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} diff --git a/contrib/bind/lib/inet/inet_netof.c b/contrib/bind/lib/inet/inet_netof.c new file mode 100644 index 0000000..54b700c --- /dev/null +++ b/contrib/bind/lib/inet/inet_netof.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1983, 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 char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/* + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +u_long +inet_netof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} diff --git a/contrib/bind/lib/inet/inet_network.c b/contrib/bind/lib/inet/inet_network.c new file mode 100644 index 0000000..485b0b9 --- /dev/null +++ b/contrib/bind/lib/inet/inet_network.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1983, 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 char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> + +#include "port_after.h" + +/* + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +u_long +inet_network(cp) + register const char *cp; +{ + register u_long val, base, n, i; + register char c; + u_long parts[4], *pp = parts; + +again: + val = 0; base = 10; + if (*cp == '0') + base = 8, cp++; + if (*cp == 'x' || *cp == 'X') + base = 16, cp++; + while ((c = *cp) != 0) { + if (isdigit(c)) { + val = (val * base) + (c - '0'); + cp++; + continue; + } + if (base == 16 && isxdigit(c)) { + val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); + cp++; + continue; + } + break; + } + if (*cp == '.') { + if (pp >= parts + 4) + return (INADDR_NONE); + *pp++ = val, cp++; + goto again; + } + if (*cp && !isspace(*cp)) + return (INADDR_NONE); + *pp++ = val; + n = pp - parts; + if (n > 4) + return (INADDR_NONE); + for (val = 0, i = 0; i < n; i++) { + val <<= 8; + val |= parts[i] & 0xff; + } + return (val); +} diff --git a/contrib/bind/lib/inet/inet_ntoa.c b/contrib/bind/lib/inet/inet_ntoa.c new file mode 100644 index 0000000..6d1ec29 --- /dev/null +++ b/contrib/bind/lib/inet/inet_ntoa.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1983, 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 char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: inet_ntoa.c,v 1.5 1997/09/26 17:56:01 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */ +char * +inet_ntoa(struct in_addr in) { + static char ret[18]; + + strcpy(ret, "[inet_ntoa error]"); + (void) inet_ntop(AF_INET, &in, ret, sizeof ret); + return (ret); +} diff --git a/contrib/bind/lib/inet/inet_ntop.c b/contrib/bind/lib/inet/inet_ntop.c new file mode 100644 index 0000000..f575fce --- /dev/null +++ b/contrib/bind/lib/inet/inet_ntop.c @@ -0,0 +1,201 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_ntop.c,v 1.4 1996/11/18 09:09:10 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); +static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > 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. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_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); +} diff --git a/contrib/bind/lib/inet/inet_pton.c b/contrib/bind/lib/inet/inet_pton.c new file mode 100644 index 0000000..021e840 --- /dev/null +++ b/contrib/bind/lib/inet/inet_pton.c @@ -0,0 +1,215 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_pton.c,v 1.4 1996/11/18 09:09:11 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <string.h> +#include <errno.h> +#include "port_after.h" + +/* + * 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 __P((const char *src, u_char *dst)); +static int inet_pton6 __P((const char *src, u_char *dst)); + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(af, src, dst) + int af; + const char *src; + void *dst; +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); + case AF_INET6: + return (inet_pton6(src, dst)); + default: + 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(src, dst) + const char *src; + u_char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + u_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) { + u_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(src, dst) + const char *src; + u_char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_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; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_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/contrib/bind/lib/inet/nsap_addr.c b/contrib/bind/lib/inet/nsap_addr.c new file mode 100644 index 0000000..e8dec96 --- /dev/null +++ b/contrib/bind/lib/inet/nsap_addr.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAI! + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANT! + * 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 TH! + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: nsap_addr.c,v 8.8 1998/02/13 01:11:12 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#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 <resolv.h> + +#include "port_after.h" + +static char +xtob(int c) { + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) { + u_char c, nib; + u_int len = 0; + + while ((c = *ascii++) != '\0' && len < (u_int)maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + c = *ascii++; + if (c != '\0') { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { + int nib; + int i; + static char tmpbuf[255*3]; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} diff --git a/contrib/bind/lib/irs/Makefile b/contrib/bind/lib/irs/Makefile new file mode 100644 index 0000000..55130d0 --- /dev/null +++ b/contrib/bind/lib/irs/Makefile @@ -0,0 +1,83 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# $Id: Makefile,v 8.6 1997/05/21 19:23:18 halley Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cruv +RANLIB= ranlib +INSTALL= install + +SRCS= dns.c dns_gr.c dns_ho.c dns_nw.c dns_pr.c dns_pw.c dns_sv.c gen.c \ + gen_gr.c gen_ho.c gen_ng.c gen_nw.c gen_pr.c gen_pw.c gen_sv.c \ + getgrent.c gethostent.c getnetent.c getnetgrent.c getprotoent.c \ + getpwent.c getservent.c hesiod.c irs_data.c lcl.c lcl_gr.c lcl_ho.c \ + lcl_ng.c lcl_nw.c lcl_pr.c lcl_pw.c lcl_sv.c nis.c nis_gr.c nis_ho.c \ + nis_ng.c nis_nw.c nis_pr.c nis_pw.c nis_sv.c nul_ng.c util.c + +OBJS= dns.${O} dns_gr.${O} dns_ho.${O} dns_nw.${O} dns_pr.${O} dns_pw.${O} \ + dns_sv.${O} gen.${O} gen_gr.${O} gen_ho.${O} gen_ng.${O} gen_nw.${O} \ + gen_pr.${O} gen_pw.${O} gen_sv.${O} getgrent.${O} gethostent.${O} \ + getnetent.${O} getnetgrent.${O} getprotoent.${O} getpwent.${O} \ + getservent.${O} hesiod.${O} irs_data.${O} lcl.${O} lcl_gr.${O} \ + lcl_ho.${O} lcl_ng.${O} lcl_nw.${O} lcl_pr.${O} lcl_pw.${O} \ + lcl_sv.${O} nis.${O} nis_gr.${O} nis_ho.${O} nis_ng.${O} nis_nw.${O} \ + nis_pr.${O} nis_pw.${O} nis_sv.${O} nul_ng.${O} util.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/lib/irs/Makefile.BSD b/contrib/bind/lib/irs/Makefile.BSD new file mode 100644 index 0000000..197e739 --- /dev/null +++ b/contrib/bind/lib/irs/Makefile.BSD @@ -0,0 +1,24 @@ +# BSDI $Id: Makefile.BSD,v 1.4 1996/10/25 07:22:55 vixie Exp $ +# +# @(#)Makefile 5.12 (Berkeley) 7/15/92 + +CFLAGS= -g + +CC= gcc2 +CFLAGS+= -Wall -Wno-unused + +LIB= irs +CFLAGS+= -I${.CURDIR}/.. +SRCS= lcl.c lcl_gr.c lcl_pw.c lcl_sv.c lcl_pr.c lcl_ho.c lcl_nw.c lcl_ng.c \ + dns.c dns_gr.c dns_pw.c dns_sv.c dns_pr.c dns_ho.c dns_nw.c \ + nis.c nis_gr.c nis_pw.c nis_sv.c nis_pr.c nis_ho.c nis_nw.c nis_ng.c \ + gen.c gen_gr.c gen_pw.c gen_sv.c gen_pr.c gen_ho.c gen_nw.c gen_ng.c \ + getgrent.c getpwent.c getservent.c getprotoent.c gethostent.c \ + getnetent.c getnetgrent.c \ + nul_ng.c irs_data.c \ + hesiod.c util.c bitncmp.c +NOMAN= + +all: libirs.a + +.include <bsd.lib.mk> diff --git a/contrib/bind/lib/irs/README b/contrib/bind/lib/irs/README new file mode 100644 index 0000000..d6b8792 --- /dev/null +++ b/contrib/bind/lib/irs/README @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +This is the Information Retrieval Service (IRS). +Designed by Paul Vixie (ISC) and Ted T'so (MIT), 1995. +Written by Paul Vixie, Ted T'so and Sam Stoller, 1996. +$Id: README,v 1.4 1996/10/25 07:22:56 vixie Exp $ + +Introduction: + + The /etc/irs.conf file defines access methods (like DNS or NIS or +LOCAL) for each map (like PASSWD or GROUP or HOSTS). One of the access +methods is "generic" in that it uses the rules from /etc/irs.conf to decide +which of potentially several different access methods to use for any given +map. Stubs have been written for all of the system getXbyY() functions so +that old programs can get this new "multiple access method" capability without +any source code changes. + +Thread Safety: + + It is possible for a thread safe program to be altered to call the +underlying interface (rather than the standard getXbyY() stubs) and get some +reentrance capabilities. Note that the underlying libraries (which we call) +are not all thread-safe, for example, the YP and DNS resolvers. A lot more +work will need to be done before we have full thread safety. But we believe +that the native API for this system does not impose any reentrancy problems. +We don't use global or static variables anywhere except in the getXbyY() stubs. + +Apologies: + + We did cheap object orientation without using C++. This stuff is +standard C, and it suffers from some of the defects shared by all object +systems implemented in C. Even so, this is the smallest design we could +think of that would be extensible to more access methods, more map types, +and more map operations (like BYNAME or BYGID or whatever) in the future. + + There's a fair amount of duplicated code between the different +access methods for a given map. For example, the code that parses the +passwd entries is almost identical between the DNS and NIS map objects. To +clean this up, the almost-identical functions need to be split into similar +and dissimilar parts, and some parts of the "struct pvt"'s need to be made +shared via substructures. diff --git a/contrib/bind/lib/irs/dns.c b/contrib/bind/lib/irs/dns.c new file mode 100644 index 0000000..e7aa125 --- /dev/null +++ b/contrib/bind/lib/irs/dns.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns.c,v 1.11 1998/03/21 00:59:45 halley Exp $"; +#endif + +/* + * dns.c --- this is the top-level accessor function for the dns + */ + +#include "port_before.h" + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* forward */ + +static void dns_close(struct irs_acc *); + +/* public */ + +struct irs_acc * +irs_dns_acc(const char *options) { + struct irs_acc *acc; + struct dns_p *dns; + + if (!(acc = malloc(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(dns = malloc(sizeof *dns))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + memset(dns, 0x5e, sizeof *dns); + if (hesiod_init(&dns->hes_ctx) < 0) { + /* + * We allow the dns accessor class to initialize + * despite hesiod failing to initialize correctly, + * since dns host queries don't depend on hesiod. + */ + dns->hes_ctx = NULL; + } + acc->private = dns; +#ifdef WANT_IRS_GR + acc->gr_map = irs_dns_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_dns_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_dns_sv; + acc->pr_map = irs_dns_pr; + acc->ho_map = irs_dns_ho; + acc->nw_map = irs_dns_nw; + acc->ng_map = irs_nul_ng; + acc->close = dns_close; + return (acc); +} + +/* methods */ + +static void +dns_close(struct irs_acc *this) { + struct dns_p *dns; + + dns = (struct dns_p *)this->private; + if (dns->hes_ctx) + hesiod_end(dns->hes_ctx); + free(dns); + free(this); +} + diff --git a/contrib/bind/lib/irs/dns_gr.c b/contrib/bind/lib/irs/dns_gr.c new file mode 100644 index 0000000..9c91719 --- /dev/null +++ b/contrib/bind/lib/irs/dns_gr.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_gr.c,v 1.15 1998/03/21 00:59:46 halley Exp $"; +#endif + +/* + * dns_gr.c --- this file contains the functions for accessing + * group information from Hesiod. + */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + /* + * This is our private accessor data. It has a shared hesiod context. + */ + struct dns_p *dns; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_close(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); + +static struct group * get_hes_group(struct irs_gr *this, + const char *name, + const char *type); + +/* Public. */ + +struct irs_gr * +irs_dns_gr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(gr = (struct irs_gr *)malloc(sizeof *gr))) { + free(pvt); + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + gr->private = pvt; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->close = gr_close; + gr->list = gr_list; + gr->minimize = gr_minimize; + return (gr); +} + +/* methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + free(pvt); + free(this); +} + +static struct group * +gr_next(struct irs_gr *this) { + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + return (get_hes_group(this, name, "group")); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + char name[32]; + + sprintf(name, "%ld", (long)gid); + return (get_hes_group(this, name, "gid")); +} + +static void +gr_rewind(struct irs_gr *this) { + /* NOOP */ +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + *ngroups = 0; + /* There's some way to do this in Hesiod. */ + return (-1); +} + +static void +gr_minimize(struct irs_gr *this) { + /* NOOP */ +} + +/* Private. */ + +static struct group * +get_hes_group(struct irs_gr *this, const char *name, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp, **new; + size_t num_members = 0; + u_long t; + + hes_list = hesiod_resolve(pvt->dns->hes_ctx, name, type); + if (!hes_list) + return (NULL); + + /* + * Copy the returned hesiod string into storage space. + */ + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = -1; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (!pvt->group.gr_mem) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +#endif /* WANT_IRS_GR */ diff --git a/contrib/bind/lib/irs/dns_ho.c b/contrib/bind/lib/irs/dns_ho.c new file mode 100644 index 0000000..3a8c402 --- /dev/null +++ b/contrib/bind/lib/irs/dns_ho.c @@ -0,0 +1,637 @@ +/* + * Copyright (c) 1985, 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. + */ + +/* + * Portions Copyright (c) 1996,1997 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. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: dns_ho.c,v 1.18 1998/01/26 23:08:22 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#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 <stdlib.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern int h_errno; + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +#define BOUNDS_CHECK(ptr, count) \ + if ((ptr) + (count) > eom) { \ + had_error++; \ + continue; \ + } else (void)0 + +struct pvt { + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + +/* Forwards. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +static void map_v4v6_hostent(struct hostent *hp, char **bp, + int *len); +static void addrsort(char **, int); +static struct hostent * gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, + const char *qname, int qtype, + int af, int size); + +/* Exports. */ + +struct irs_ho * +irs_dns_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = (struct irs_ho *)malloc(sizeof *ho))) { + free(pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt) + free(pvt); + free(this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct hostent *hp; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + if (_res.options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int n, size, type, len; + u_char buf[MAXPACKET]; + const char *cp; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + + switch (af) { + case AF_INET: + size = INADDRSZ; + type = T_A; + break; + case AF_INET6: + size = IN6ADDRSZ; + type = T_AAAA; + break; + default: + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return (NULL); + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_query() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = hostalias(name))) + name = cp; + + if ((n = res_search(name, C_IN, type, buf, sizeof buf)) < 0) + return (NULL); + return (gethostans(this, buf, n, name, type, af, size)); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + char qbuf[MAXDNAME+1], *qp; + u_char buf[MAXPACKET]; + struct hostent *hp; + int n, size; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; + return (NULL); + } + if (size > len) { + errno = EINVAL; + h_errno = NETDB_INTERNAL; + return (NULL); + } + switch (af) { + case AF_INET: + (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + qp = qbuf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + } + strcpy(qp, "ip6.int"); + break; + default: + abort(); + } + n = res_query(qbuf, C_IN, T_PTR, buf, sizeof buf); + if (n < 0) + return (NULL); + hp = gethostans(this, buf, n, qbuf, T_PTR, af, size); + if (!hp) + return (NULL); /* h_errno was set by gethostans() */ + memcpy(pvt->host_addr, addr, len); + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + if (af == AF_INET && (_res.options & RES_USE_INET6)) { + map_v4v6_address((char*)pvt->host_addr, (char*)pvt->host_addr); + pvt->host.h_addrtype = AF_INET6; + pvt->host.h_length = IN6ADDRSZ; + } + h_errno = NETDB_SUCCESS; + return (hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + /* NOOP */ +} + +static void +ho_minimize(struct irs_ho *this) { + /* NOOP */ +} + +/* Private. */ + +static struct hostent * +gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, const char *qname, int qtype, + int af, int size) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, buflen, ancount, qdcount, n, haveanswer, had_error; + int (*name_ok)(const char *); + const HEADER *hp; + const u_char *eom; + const u_char *cp; + const char *tname; + char *bp, **ap, **hap; + char tbuf[MAXDNAME+1]; + + tname = qname; + eom = ansbuf + anslen; + switch (qtype) { + case T_A: + case T_AAAA: + name_ok = res_hnok; + break; + case T_PTR: + name_ok = res_dnok; + break; + default: + abort(); + } + + pvt->host.h_addrtype = af; + pvt->host.h_length = size; + pvt->host.h_name = NULL; + + /* + * Find first satisfactory answer. + */ + if (ansbuf + HFIXEDSZ > eom) { + h_errno = NO_RECOVERY; + return (NULL); + } + hp = (HEADER *)ansbuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + bp = pvt->hostbuf; + buflen = sizeof pvt->hostbuf; + cp = ansbuf + HFIXEDSZ; + if (qdcount != 1) { + h_errno = NO_RECOVERY; + return (NULL); + } + n = dn_expand(ansbuf, eom, cp, bp, buflen); + if ((n < 0) || !(*name_ok)(bp)) { + h_errno = NO_RECOVERY; + return (NULL); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + h_errno = NO_RECOVERY; + return (NULL); + } + if (qtype == T_A || qtype == T_AAAA) { + /* res_send() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + if (n > MAXHOSTNAMELEN) { + h_errno = NO_RECOVERY; + return (NULL); + } + pvt->host.h_name = bp; + bp += n; + buflen -= n; + /* The qname can be abbreviated, but h_name is now absolute. */ + qname = pvt->host.h_name; + } + ap = pvt->host_aliases; + *ap = NULL; + pvt->host.h_aliases = pvt->host_aliases; + hap = pvt->h_addr_ptrs; + *hap = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(ansbuf, eom, cp, bp, buflen); + if ((n < 0) || !(*name_ok)(bp)) { + had_error++; + continue; + } + cp += n; /* name */ + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + BOUNDS_CHECK(cp, n); + if (class != C_IN) { + cp += n; + continue; + } + if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { + if (ap >= &pvt->host_aliases[MAXALIASES-1]) + continue; + n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + if ((n < 0) || !(*name_ok)(tbuf)) { + had_error++; + continue; + } + cp += n; + /* Store alias. */ + *ap++ = bp; + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen || n > MAXHOSTNAMELEN) { + had_error++; + continue; + } + strcpy(bp, tbuf); + pvt->host.h_name = bp; + bp += n; + buflen -= n; + continue; + } + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf); + if (n < 0 || !res_dnok(tbuf)) { + had_error++; + continue; + } + cp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); + tname = bp; + bp += n; + buflen -= n; + continue; + } + if (type != qtype) { + cp += n; + continue; + } + switch (type) { + case T_PTR: + if (strcasecmp(tname, bp) != 0) { + cp += n; + continue; + } + n = dn_expand(ansbuf, eom, cp, bp, buflen); + if (n < 0 || !res_hnok(bp) || n >= MAXHOSTNAMELEN) { + had_error++; + break; + } + cp += n; + if (!haveanswer) + pvt->host.h_name = bp; + else if (ap < &pvt->host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + } + break; + case T_A: + case T_AAAA: + if (strcasecmp(pvt->host.h_name, bp) != 0) { + cp += n; + continue; + } + if (n != pvt->host.h_length) { + cp += n; + continue; + } + if (!haveanswer) { + int nn; + + nn = strlen(bp) + 1; /* for the \0 */ + if (nn >= MAXHOSTNAMELEN) { + cp += n; + had_error++; + continue; + } + pvt->host.h_name = bp; + bp += nn; + buflen -= nn; + } + + bp += sizeof(align) - ((u_long)bp % sizeof(align)); + + if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) { + had_error++; + continue; + } + if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1]) { + cp += n; + continue; + } + memcpy(*hap++ = bp, cp, n); + bp += n; + cp += n; + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + *ap = NULL; + *hap = NULL; + + if (_res.nsort && haveanswer > 1 && qtype == T_A) + addrsort(pvt->h_addr_ptrs, haveanswer); + if (!pvt->host.h_name) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > buflen || n >= MAXHOSTNAMELEN) + goto no_recovery; + strcpy(bp, qname); + pvt->host.h_name = bp; + bp += n; + buflen -= n; + } + if (_res.options & RES_USE_INET6) + map_v4v6_hostent(&pvt->host, &bp, &buflen); + h_errno = NETDB_SUCCESS; + return (&pvt->host); + } + no_recovery: + h_errno = NO_RECOVERY; + return (NULL); +} + +static void +map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) { + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); + + if (*lenp < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. */ + *ap = NULL; + return; + } + *bpp += i; + *lenp -= i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + *lenp -= IN6ADDRSZ; + } +} + +static void +addrsort(char **ap, int num) { + int i, j, needsort = 0, aval[MAXADDRS]; + char **p; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; (unsigned)j < _res.nsort; j++) + if (_res.sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & + _res.sort_list[j].mask)) + break; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort < num) { + for (j = needsort - 1; j >= 0; j--) { + if (aval[j] > aval[j+1]) { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + + } else + break; + } + needsort++; + } +} diff --git a/contrib/bind/lib/irs/dns_nw.c b/contrib/bind/lib/irs/dns_nw.c new file mode 100644 index 0000000..30767e7 --- /dev/null +++ b/contrib/bind/lib/irs/dns_nw.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_nw.c,v 1.13 1998/02/13 01:10:40 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.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 <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern int h_errno; + +/* Definitions. */ + +#define MAXALIASES 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + struct nwent net; + char * ali[MAXALIASES]; + char buf[BUFSIZ+1]; +}; + +typedef union { + long al; + char ac; +} align; + +enum by_what { by_addr, by_name }; + +/* Forwards. */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); +static struct nwent * get1101byname(struct irs_nw *, const char *); +static struct nwent * get1101answer(struct irs_nw *, + u_char *ansbuf, int anslen, + enum by_what by_what, + int af, const char *name, + const u_char *addr, int addrlen); +static struct nwent * get1101mask(struct nwent *); +static int make1101inaddr(const u_char *, int, char *, int); +static void normalize_name(char *name); + +/* Exports. */ + +struct irs_nw * +irs_dns_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) { + free(pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods. */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free(pvt); + free(this); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + switch (af) { + case AF_INET: + return (get1101byname(this, name)); + default: + (void)NULL; + } + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int len, int af) { + switch (af) { + case AF_INET: + return (get1101byaddr(this, net, len)); + default: + (void)NULL; + } + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + /* NOOP */ +} + +static void +nw_minimize(struct irs_nw *this) { + /* NOOP */ +} + +/* Private. */ + +static struct nwent * +get1101byname(struct irs_nw *this, const char *name) { + u_char ansbuf[MAXPACKET]; + int anslen; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + anslen = res_search(name, C_IN, T_PTR, ansbuf, sizeof ansbuf); + if (anslen < 0) + return (NULL); + return (get1101mask(get1101answer(this, ansbuf, anslen, by_name, + AF_INET, name, NULL, 0))); +} + +static struct nwent * +get1101byaddr(struct irs_nw *this, u_char *net, int len) { + u_char ansbuf[MAXPACKET]; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; + int anslen; + + if (len < 1 || len > 32) { + errno = EINVAL; + h_errno = NETDB_INTERNAL; + return (NULL); + } + if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) + return (NULL); + anslen = res_query(qbuf, C_IN, T_PTR, ansbuf, sizeof ansbuf); + if (anslen < 0) + return (NULL); + return (get1101mask(get1101answer(this, ansbuf, anslen, by_addr, + AF_INET, NULL, net, len))); +} + +static struct nwent * +get1101answer(struct irs_nw *this, + u_char *ansbuf, int anslen, enum by_what by_what, + int af, const char *name, const u_char *addr, int addrlen) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, buflen, ancount, qdcount, haveanswer; + char *bp, **ap; + u_char *cp, *eom; + HEADER *hp; + + /* Initialize, and parse header. */ + eom = ansbuf + anslen; + if (ansbuf + HFIXEDSZ > eom) { + h_errno = NO_RECOVERY; + return (NULL); + } + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + h_errno = NO_RECOVERY; + return (NULL); + } + } + ancount = ntohs(hp->ancount); + if (!ancount) { + if (hp->aa) + h_errno = HOST_NOT_FOUND; + else + h_errno = TRY_AGAIN; + return (NULL); + } + + /* Prepare a return structure. */ + bp = pvt->buf; + buflen = sizeof pvt->buf; + pvt->net.n_name = NULL; + pvt->net.n_aliases = pvt->ali; + pvt->net.n_addrtype = af; + pvt->net.n_addr = NULL; + pvt->net.n_length = addrlen; + + /* Save input key if given. */ + switch (by_what) { + case by_name: + if (name != NULL) { + int n = strlen(name) + 1; + + if (n > buflen) { + h_errno = NO_RECOVERY; + return (NULL); + } + pvt->net.n_name = strcpy(bp, name); + bp += n; + buflen -= n; + } + break; + case by_addr: + if (addr != NULL && addrlen != 0) { + int n = addrlen / 8 + ((addrlen % 8) != 0); + + if (INADDRSZ > buflen) { + h_errno = NO_RECOVERY; + return (NULL); + } + memset(bp, 0, INADDRSZ); + memcpy(bp, addr, n); + pvt->net.n_addr = bp; + bp += INADDRSZ; + buflen -= INADDRSZ; + } + break; + default: + abort(); + } + + /* Parse the answer, collect aliases. */ + ap = pvt->ali; + haveanswer = 0; + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, bp, buflen); + + cp += n; /* Owner */ + if (n < 0 || !res_dnok(bp) || + cp + 3 * INT16SZ + INT32SZ > eom) { + h_errno = NO_RECOVERY; + return (NULL); + } + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (class == C_IN && type == T_PTR) { + int nn; + + nn = dn_expand(ansbuf, eom, cp, bp, buflen); + if (nn < 0 || !res_hnok(bp) || nn != n) { + h_errno = NO_RECOVERY; + return (NULL); + } + normalize_name(bp); + switch (by_what) { + case by_addr: { + if (pvt->net.n_name == NULL) + pvt->net.n_name = bp; + else if (strcasecmp(pvt->net.n_name, bp) == 0) + break; + else + *ap++ = bp; + nn = strlen(bp) + 1; + bp += nn; + buflen -= nn; + haveanswer++; + break; + } + case by_name: { + u_int b1, b2, b3, b4; + + if (pvt->net.n_addr != NULL || + sscanf(bp, "%u.%u.%u.%u.in-addr.arpa", + &b1, &b2, &b3, &b4) != 4) + break; + if (buflen < INADDRSZ) { + h_errno = NO_RECOVERY; + return (NULL); + } + pvt->net.n_addr = bp; + *bp++ = b4; + *bp++ = b3; + *bp++ = b2; + *bp++ = b1; + buflen -= INADDRSZ; + pvt->net.n_length = INADDRSZ * 8; + haveanswer++; + } + } + } + cp += n; /* RDATA */ + } + if (!haveanswer) { + h_errno = TRY_AGAIN; + return (NULL); + } + *ap = NULL; + + return (&pvt->net); +} + +static struct nwent * +get1101mask(struct nwent *nwent) { + char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; + int anslen, type, class, ancount, qdcount; + u_char ansbuf[MAXPACKET], *cp, *eom; + HEADER *hp; + + if (!nwent) + return (NULL); + if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf) + < 0) { + /* "First, do no harm." */ + return (nwent); + } + + /* Query for the A RR that would hold this network's mask. */ + anslen = res_query(qbuf, C_IN, T_A, ansbuf, sizeof ansbuf); + if (anslen < HFIXEDSZ) + return (nwent); + + /* Initialize, and parse header. */ + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + eom = ansbuf + anslen; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) + return (nwent); + } + ancount = ntohs(hp->ancount); + + /* Parse the answer, collect aliases. */ + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); + + if (n < 0 || !res_dnok(owner)) + break; + cp += n; /* Owner */ + if (cp + 3 * INT16SZ + INT32SZ > eom) + break; + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (cp + n > eom) + break; + if (n == INADDRSZ && class == C_IN && type == T_A && + !strcasecmp(qbuf, owner)) { + /* This A RR indicates the actual netmask. */ + int nn, mm; + + nwent->n_length = 0; + for (nn = 0; nn < INADDRSZ; nn++) + for (mm = 7; mm >= 0; mm--) + if (cp[nn] & (1 << mm)) + nwent->n_length++; + else + break; + } + cp += n; /* RDATA */ + } + return (nwent); +} + +static int +make1101inaddr(const u_char *net, int bits, char *name, int size) { + int n, m; + + /* Zero fill any whole bytes left out of the prefix. */ + for (n = (32 - bits) / 8; n > 0; n--) { + if (size < (int)(sizeof "0.")) + goto emsgsize; + m = SPRINTF((name, "0.")); + name += m; + size -= m; + } + + /* Format the partial byte, if any, within the prefix. */ + if ((n = bits % 8) != 0) { + if (size < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", + net[bits / 8] & ~((1 << (8 - n)) - 1))); + name += m; + size -= m; + } + + /* Format the whole bytes within the prefix. */ + for (n = bits / 8; n > 0; n--) { + if (size < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", net[n - 1])); + name += m; + size -= m; + } + + /* Add the static text. */ + if (size < (int)(sizeof "in-addr.arpa")) + goto emsgsize; + (void) SPRINTF((name, "in-addr.arpa")); + return (0); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static void +normalize_name(char *name) { + char *t; + + /* Make lower case. */ + for (t = name; *t; t++) + if (isascii(*t) && isupper(*t)) + *t = tolower(*t); + + /* Remove trailing dots. */ + while (t > name && t[-1] == '.') + *--t = '\0'; +} diff --git a/contrib/bind/lib/irs/dns_p.h b/contrib/bind/lib/irs/dns_p.h new file mode 100644 index 0000000..5a4ef84 --- /dev/null +++ b/contrib/bind/lib/irs/dns_p.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: dns_p.h,v 1.7 1996/10/25 07:22:59 vixie Exp $ + */ + +#ifndef _DNS_P_H_INCLUDED +#define _DNS_P_H_INCLUDED + +/* + * Object state. + */ +struct dns_p { + void *hes_ctx; +}; + +/* + * Methods. + */ + +extern struct irs_gr * irs_dns_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_dns_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_dns_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_dns_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_dns_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_dns_nw __P((struct irs_acc *)); + +#endif /*_DNS_P_H_INCLUDED*/ diff --git a/contrib/bind/lib/irs/dns_pr.c b/contrib/bind/lib/irs/dns_pr.c new file mode 100644 index 0000000..2ca6aaf --- /dev/null +++ b/contrib/bind/lib/irs/dns_pr.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pr.c,v 1.9 1997/12/04 04:57:48 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct protoent proto; + char * prbuf; +}; + +/* Forward. */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static struct protoent * parse_hes_list(struct irs_pr *, char **); + +/* Public. */ + +struct irs_pr * +irs_dns_pr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct pvt *pvt; + struct irs_pr *pr; + + if (!dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = malloc(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(pr = malloc(sizeof *pr))) { + free(pvt); + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + pvt->dns = dns; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + free(this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char numstr[16]; + char **hes_list; + + sprintf(numstr, "%d", num); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + errno = ENODEV; + return (NULL); +} + +static void +pr_rewind(struct irs_pr *this) { + /* NOOP */ +} + +static void +pr_minimize(struct irs_pr *this) { + /* NOOP */ +} + +/* Private. */ + +static struct protoent * +parse_hes_list(struct irs_pr *this, char **hes_list) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Skip blank lines. */ + p = cp; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = strdup(cp); + + p = pvt->prbuf; + pvt->proto.p_name = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->proto.p_proto = atoi(p); + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->proto.p_aliases) { + max += 10; + new = realloc(pvt->proto.p_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = new; + } + pvt->proto.p_aliases[num++] = p; + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[num] = NULL; + return (&pvt->proto); + } + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} diff --git a/contrib/bind/lib/irs/dns_pw.c b/contrib/bind/lib/irs/dns_pw.c new file mode 100644 index 0000000..97612d1 --- /dev/null +++ b/contrib/bind/lib/irs/dns_pw.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pw.c,v 1.13 1997/12/04 04:57:48 halley Exp $"; +#endif + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p *dns; + struct passwd passwd; + char * pwbuf; +}; + +/* Forward. */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static struct passwd * pw_next(struct irs_pw *); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static struct passwd * getpwcommon(struct irs_pw *, const char *, + const char *); + +/* Public. */ + +struct irs_pw * +irs_dns_pw(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = malloc(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(pw = malloc(sizeof *pw))) { + free(pvt); + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + pw->private = pvt; + pw->close = pw_close; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->next = pw_next; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + return (pw); +} + +/* Methods. */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + free(this); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *nam) { + return (getpwcommon(this, nam, "passwd")); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + char uidstr[16]; + + sprintf(uidstr, "%lu", (u_long)uid); + return (getpwcommon(this, uidstr, "uid")); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + errno = ENODEV; + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + /* NOOP */ +} + +static void +pw_minimize(struct irs_pw *this) { + /* NOOP */ +} + +/* Private. */ + +static struct passwd * +getpwcommon(struct irs_pw *this, const char *arg, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp; + + if (!(hes_list = hesiod_resolve(pvt->dns->hes_ctx, arg, type))) + return (NULL); + if (!*hes_list) { + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + errno = ENOENT; + return (NULL); + } + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +#endif /* WANT_IRS_PW */ diff --git a/contrib/bind/lib/irs/dns_sv.c b/contrib/bind/lib/irs/dns_sv.c new file mode 100644 index 0000000..064e80a --- /dev/null +++ b/contrib/bind/lib/irs/dns_sv.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_sv.c,v 1.12 1997/12/04 04:57:49 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Definitions */ + +struct pvt { + struct dns_p * dns; + struct servent serv; + char * svbuf; +}; + +/* Forward. */ + +static void sv_close(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, + const char *, const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static struct servent * sv_next(struct irs_sv *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static struct servent * parse_hes_list(struct irs_sv *, + char **, const char *); + +/* Public */ + +struct irs_sv * +irs_dns_sv(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(sv = malloc(sizeof *sv))) { + free(pvt); + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + sv->private = pvt; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->next = sv_next; + sv->rewind = sv_rewind; + sv->close = sv_close; + sv->minimize = sv_minimize; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + free(this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "service"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char portstr[16]; + char **hes_list; + + sprintf(portstr, "%d", port); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, portstr, "port"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_next(struct irs_sv *this) { + errno = ENODEV; + return (NULL); +} + +static void +sv_rewind(struct irs_sv *this) { + /* NOOP */ +} + +/* Private */ + +static struct servent * +parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int proto_len; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Check to make sure the protocol matches. */ + p = cp; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + proto_len = strlen(proto); + if (strncasecmp(++p, proto, proto_len) != 0) + continue; + if (p[proto_len] && !isspace(p[proto_len])) + continue; + + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = strdup(cp); + + p = pvt->svbuf; + pvt->serv.s_name = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_proto = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_port = htons((u_short) atoi(p)); + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->serv.s_aliases) { + max += 10; + new = realloc(pvt->serv.s_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = new; + } + pvt->serv.s_aliases[num++] = p; + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[num] = NULL; + return (&pvt->serv); + } + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +sv_minimize(struct irs_sv *this) { + /* NOOP */ +} diff --git a/contrib/bind/lib/irs/gen.c b/contrib/bind/lib/irs/gen.c new file mode 100644 index 0000000..325a526 --- /dev/null +++ b/contrib/bind/lib/irs/gen.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gen.c,v 1.18 1998/03/21 00:59:46 halley Exp $"; +#endif + +/* + * this is the top level dispatcher + * + * The dispatcher is implemented as an accessor class; it is an + * accessor class that calls other accessor classes, as controlled by a + * configuration file. + * + * A big difference between this accessor class and others is that the + * map class initializers are NULL, and the map classes are already + * filled in with method functions that will do the right thing. + */ + +/* Imports */ + +#include "port_before.h" + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct nameval { + const char * name; + int val; +}; + +static const struct nameval acc_names[irs_nacc+1] = { + { "local", irs_lcl }, + { "dns", irs_dns }, + { "nis", irs_nis }, + { NULL, irs_nacc } +}; + +typedef struct irs_acc *(*accinit) __P((const char *options)); + +static const accinit accs[irs_nacc+1] = { + irs_lcl_acc, + irs_dns_acc, +#ifdef WANT_IRS_NIS + irs_nis_acc, +#else + NULL, +#endif + NULL +}; + +static const struct nameval map_names[irs_nmap+1] = { + { "group", irs_gr }, + { "passwd", irs_pw }, + { "services", irs_sv }, + { "protocols", irs_pr }, + { "hosts", irs_ho }, + { "networks", irs_nw }, + { "netgroup", irs_ng }, + { NULL, irs_nmap } +}; + +static const struct nameval option_names[] = { + { "merge", IRS_MERGE }, + { "continue", IRS_CONTINUE }, + { NULL, 0 } +}; + +/* Forward */ + +static void gen_close(struct irs_acc *); +static int find_name(const char *, const struct nameval nv[]); +static void init_map_rules(struct gen_p *); +static struct irs_rule *release_rule(struct irs_rule *); +static int add_rule(struct gen_p *, + enum irs_map_id, enum irs_acc_id, + const char *); + +/* Public */ + +struct irs_acc * +irs_gen_acc(const char *options) { + struct irs_acc *acc; + struct gen_p *irs; + + if (!(acc = malloc(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irs = malloc(sizeof *irs))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + memset(irs, 0x5e, sizeof *irs); + irs->options = strdup(options); + memset(irs->accessors, 0, sizeof irs->accessors); + memset(irs->map_rules, 0, sizeof irs->map_rules); + init_map_rules(irs); + acc->private = irs; +#ifdef WANT_IRS_GR + acc->gr_map = irs_gen_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_gen_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_gen_sv; + acc->pr_map = irs_gen_pr; + acc->ho_map = irs_gen_ho; + acc->nw_map = irs_gen_nw; + acc->ng_map = irs_gen_ng; + acc->close = gen_close; + return (acc); +} + +/* Methods */ + +static void +gen_close(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + int n; + + /* Search rules. */ + for (n = 0; n < irs_nmap; n++) + while (irs->map_rules[n] != NULL) + irs->map_rules[n] = release_rule(irs->map_rules[n]); + + /* Access methods. */ + for (n = 0; n < irs_nacc; n++) { + /* Map objects. */ + if (irs->accessors[n].gr != NULL) + (*irs->accessors[n].gr->close)(irs->accessors[n].gr); + if (irs->accessors[n].pw != NULL) + (*irs->accessors[n].pw->close)(irs->accessors[n].pw); + if (irs->accessors[n].sv != NULL) + (*irs->accessors[n].sv->close)(irs->accessors[n].sv); + if (irs->accessors[n].pr != NULL) + (*irs->accessors[n].pr->close)(irs->accessors[n].pr); + if (irs->accessors[n].ho != NULL) + (*irs->accessors[n].ho->close)(irs->accessors[n].ho); + if (irs->accessors[n].nw != NULL) + (*irs->accessors[n].nw->close)(irs->accessors[n].nw); + if (irs->accessors[n].ng != NULL) + (*irs->accessors[n].ng->close)(irs->accessors[n].ng); + /* Enclosing accessor. */ + if (irs->accessors[n].acc != NULL) + (*irs->accessors[n].acc->close)(irs->accessors[n].acc); + } + + /* The options string was strdup'd. */ + free((void*)irs->options); + + /* The private data container. */ + free(irs); + + /* The object. */ + free(this); +} + +/* Private */ + +static int +find_name(const char *name, const struct nameval names[]) { + int n; + + for (n = 0; names[n].name != NULL; n++) + if (strcmp(name, names[n].name) == 0) + return (names[n].val); + return (-1); +} + +static struct irs_rule * +release_rule(struct irs_rule *rule) { + struct irs_rule *next = rule->next; + + free(rule); + return (next); +} + +static int +add_rule(struct gen_p *irs, + enum irs_map_id map, enum irs_acc_id acc, + const char *options) +{ + struct irs_rule **rules, *last, *tmp, *new; + struct irs_inst *inst; + const char *cp; + int n; + +#ifndef WANT_IRS_GR + if (map == irs_gr) + return (-1); +#endif +#ifndef WANT_IRS_PW + if (map == irs_pw) + return (-1); +#endif +#ifndef WANT_IRS_NIS + if (acc == irs_nis) + return (-1); +#endif + new = (struct irs_rule *)malloc(sizeof *new); + if (new == NULL) + return (-1); + memset(new, 0x5e, sizeof *new); + new->next = NULL; + + new->inst = &irs->accessors[acc]; + + new->flags = 0; + cp = options; + while (cp && *cp) { + char option[50], *next; + + next = strchr(cp, ','); + if (next) + n = next++ - cp; + else + n = strlen(cp); + if ((size_t)n > sizeof option - 1) + n = sizeof option - 1; + strncpy(option, cp, n); + option[n] = '\0'; + + n = find_name(option, option_names); + if (n >= 0) + new->flags |= n; + + cp = next; + } + + rules = &irs->map_rules[map]; + for (last = NULL, tmp = *rules; + tmp != NULL; + last = tmp, tmp = tmp->next) + (void)NULL; + if (last == NULL) + *rules = new; + else + last->next = new; + + /* Try to instantiate map accessors for this if necessary & approp. */ + inst = &irs->accessors[acc]; + if (inst->acc == NULL && accs[acc] != NULL) + inst->acc = (*accs[acc])(irs->options); + if (inst->acc != NULL) { + if (inst->gr == NULL && inst->acc->gr_map != NULL) + inst->gr = (*inst->acc->gr_map)(inst->acc); + if (inst->pw == NULL && inst->acc->pw_map != NULL) + inst->pw = (*inst->acc->pw_map)(inst->acc); + if (inst->sv == NULL && inst->acc->sv_map != NULL) + inst->sv = (*inst->acc->sv_map)(inst->acc); + if (inst->pr == NULL && inst->acc->pr_map != NULL) + inst->pr = (*inst->acc->pr_map)(inst->acc); + if (inst->ho == NULL && inst->acc->ho_map != NULL) + inst->ho = (*inst->acc->ho_map)(inst->acc); + if (inst->nw == NULL && inst->acc->nw_map != NULL) + inst->nw = (*inst->acc->nw_map)(inst->acc); + if (inst->ng == NULL && inst->acc->ng_map != NULL) + inst->ng = (*inst->acc->ng_map)(inst->acc); + } + + return (0); +} + +static void +default_map_rules(struct gen_p *irs) { + /* Install time honoured and proved BSD style rules as default. */ + add_rule(irs, irs_gr, irs_lcl, ""); + add_rule(irs, irs_pw, irs_lcl, ""); + add_rule(irs, irs_sv, irs_lcl, ""); + add_rule(irs, irs_pr, irs_lcl, ""); + add_rule(irs, irs_ho, irs_dns, "continue"); + add_rule(irs, irs_ho, irs_lcl, ""); + add_rule(irs, irs_nw, irs_dns, "continue"); + add_rule(irs, irs_nw, irs_lcl, ""); + add_rule(irs, irs_ng, irs_lcl, ""); +} + +static void +init_map_rules(struct gen_p *irs) { + char line[1024], pattern[40], mapname[20], accname[20], options[100]; + FILE *conf; + + if ((conf = fopen(_PATH_IRS_CONF, "r")) == NULL) { + default_map_rules(irs); + return; + } + (void) sprintf(pattern, "%%%ds %%%ds %%%ds\n", + sizeof mapname, sizeof accname, sizeof options); + while (fgets(line, sizeof line, conf)) { + enum irs_map_id map; + enum irs_acc_id acc; + char *tmp; + int n; + + for (tmp = line; isascii(*tmp) && isspace(*tmp); tmp++) + (void)NULL; + if (*tmp == '#' || *tmp == '\n' || *tmp == '\0') + continue; + n = sscanf(tmp, pattern, mapname, accname, options); + if (n < 2) + continue; + if (n < 3) + options[0] = '\0'; + + n = find_name(mapname, map_names); + assert(n < irs_nmap); + if (n < 0) + continue; + map = (enum irs_map_id) n; + + n = find_name(accname, acc_names); + assert(n < irs_nacc); + if (n < 0) + continue; + acc = (enum irs_acc_id) n; + + add_rule(irs, map, acc, options); + } + fclose(conf); +} diff --git a/contrib/bind/lib/irs/gen_gr.c b/contrib/bind/lib/irs/gen_gr.c new file mode 100644 index 0000000..b0c61a8 --- /dev/null +++ b/contrib/bind/lib/irs/gen_gr.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gen_gr.c,v 1.16 1998/03/21 00:59:47 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_gr * gr; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); + +static void grmerge(struct irs_gr *gr, const struct group *src, + int preserve); + +static int countvec(char **vec); +static int isnew(char **old, char *new); +static int countnew(char **old, char **new); +static size_t sizenew(char **old, char **new); +static int newgid(int, gid_t *, gid_t); + +/* Public */ + +struct irs_gr * +irs_gen_gr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = malloc(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = malloc(sizeof *pvt))) { + free(gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_gr]; + pvt->rule = pvt->rules; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = gr_list; + gr->minimize = gr_minimize; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free(pvt); + free(this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + struct irs_gr *gr; + + while (pvt->rule) { + gr = pvt->rule->inst->gr; + rval = (*gr->next)(gr); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } + } + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->byname)(gr, name); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->bygid)(gr, gid); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_gr *gr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_gr *gr; + int t_ngroups, maxgroups; + gid_t *t_groups; + int n, t, rval = 0; + + maxgroups = *ngroups; + *ngroups = 0; + t_groups = (gid_t *)malloc(maxgroups * sizeof(gid_t)); + if (!t_groups) { + errno = ENOMEM; + return (-1); + } + + for (rule = pvt->rules; rule; rule = rule->next) { + t_ngroups = maxgroups; + gr = rule->inst->gr; + t = (*gr->list)(gr, name, basegid, t_groups, &t_ngroups); + for (n = 0; n < t_ngroups; n++) { + if (newgid(*ngroups, groups, t_groups[n])) { + if (*ngroups == maxgroups) { + rval = -1; + goto done; + } + groups[(*ngroups)++] = t_groups[n]; + } + } + if (t == 0) { + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + done: + free(t_groups); + return (rval); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_gr *gr = rule->inst->gr; + + (*gr->minimize)(gr); + } +} + +/* Private. */ + +static void +grmerge(struct irs_gr *this, const struct group *src, int preserve) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **m, **p; + int n, ndst, nnew; + + if (!preserve) { + pvt->group.gr_gid = src->gr_gid; + if (pvt->nmemb < 1) { + m = malloc(sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = 1; + } + pvt->group.gr_mem[0] = NULL; + } + ndst = countvec(pvt->group.gr_mem); + nnew = countnew(pvt->group.gr_mem, src->gr_mem); + + /* + * Make sure destination member array is large enough. + * p points to new portion. + */ + n = ndst + nnew + 1; + if ((size_t)n > pvt->nmemb) { + m = realloc(pvt->group.gr_mem, n * sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + p = pvt->group.gr_mem + ndst; + + /* + * Enlarge destination membuf; cp points at new portion. + */ + n = sizenew(pvt->group.gr_mem, src->gr_mem); + assert((nnew == 0) == (n == 0)); + if (!preserve) { + n += strlen(src->gr_name) + 1; + n += strlen(src->gr_passwd) + 1; + } + if (n == 0) { + /* No work to do. */ + return; + } + cp = realloc(pvt->membuf, pvt->membufsize + n); + if (!cp) { + /* No harm done, no work done. */ + return; + } + pvt->membuf = cp; + cp += pvt->membufsize; + pvt->membufsize += n; + + /* + * Add new elements. + */ + for (m = src->gr_mem; *m; m++) + if (isnew(pvt->group.gr_mem, *m)) { + *p++ = cp; + *p = NULL; + strcpy(cp, *m); + cp += strlen(cp) + 1; + } + if (!preserve) { + pvt->group.gr_name = cp; + strcpy(cp, src->gr_name); + cp += strlen(src->gr_name) + 1; + pvt->group.gr_passwd = cp; + strcpy(cp, src->gr_passwd); + cp += strlen(src->gr_passwd) + 1; + } + assert(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]); +} + +static int +countvec(char **vec) { + int n = 0; + + while (*vec++) + n++; + return (n); +} + +static int +isnew(char **old, char *new) { + for (; *old; old++) + if (strcmp(*old, new) == 0) + return (0); + return (1); +} + +static int +countnew(char **old, char **new) { + int n = 0; + + for (; *new; new++) + n += isnew(old, *new); + return (n); +} + +static size_t +sizenew(char **old, char **new) { + size_t n = 0; + + for (; *new; new++) + if (isnew(old, *new)) + n += strlen(*new) + 1; + return (n); +} + +static int +newgid(int ngroups, gid_t *groups, gid_t group) { + ngroups--, groups++; + for (; ngroups-- > 0; groups++) + if (*groups == group) + return (0); + return (1); +} + +#endif /* WANT_IRS_GR */ diff --git a/contrib/bind/lib/irs/gen_ho.c b/contrib/bind/lib/irs/gen_ho.c new file mode 100644 index 0000000..7da829d --- /dev/null +++ b/contrib/bind/lib/irs/gen_ho.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: gen_ho.c,v 1.9 1997/12/04 04:57:50 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +extern int h_errno; + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_ho * ho; +}; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +/* Exports */ + +struct irs_ho * +irs_gen_ho(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ho *ho; + struct pvt *pvt; + + if (!(ho = malloc(sizeof *ho))) { + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(ho); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_ho]; + pvt->rule = pvt->rules; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free(pvt); + free(this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + h_errno = NETDB_INTERNAL; + errno = 0; + rval = (*ho->byname)(ho, name); + if (rval != NULL) + return (rval); + if (rule->flags & IRS_CONTINUE) + continue; + /* + * The value TRY_AGAIN can mean that the service + * is not available, or just that this particular name + * cannot be resolved now. We use the errno ECONNREFUSED + * to distinguish. If a lookup sets that errno when + * h_errno is TRY_AGAIN, we continue to try other lookup + * functions, otherwise we return the TRY_AGAIN error. + */ + if (h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + return (NULL); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + h_errno = NETDB_INTERNAL; + errno = 0; + rval = (*ho->byname2)(ho, name, af); + if (rval != NULL) + return (rval); + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + return (NULL); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + h_errno = NETDB_INTERNAL; + errno = 0; + rval = (*ho->byaddr)(ho, addr, len, af); + if (rval != NULL) + return (rval); + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + return (NULL); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + struct irs_ho *ho; + + while (pvt->rule) { + ho = pvt->rule->inst->ho; + rval = (*ho->next)(ho); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } + } + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ho *ho; + + pvt->rule = pvt->rules; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->minimize)(ho); + } +} diff --git a/contrib/bind/lib/irs/gen_ng.c b/contrib/bind/lib/irs/gen_ng.c new file mode 100644 index 0000000..3958380 --- /dev/null +++ b/contrib/bind/lib/irs/gen_ng.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gen_ng.c,v 1.9 1997/12/04 04:57:50 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + char * curgroup; +}; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_gen_ng(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = malloc(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = malloc(sizeof *pvt))) { + free(ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_ng]; + pvt->rule = pvt->rules; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->curgroup) + free(pvt->curgroup); + free(pvt); + free(this); +} + +static int +ng_next(struct irs_ng *this, char **host, char **user, char **domain) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + while (pvt->rule) { + ng = pvt->rule->inst->ng; + if ((*ng->next)(ng, host, user, domain) == 1) + return (1); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } + } + return (0); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_ng *ng; + int rval; + + rval = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + ng = rule->inst->ng; + rval = (*ng->test)(ng, name, user, host, domain); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + pvt->rule = pvt->rules; + if (pvt->rule) { + if (pvt->curgroup) + free(pvt->curgroup); + pvt->curgroup = strdup(group); + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ng *ng = rule->inst->ng; + + (*ng->minimize)(ng); + } +} diff --git a/contrib/bind/lib/irs/gen_nw.c b/contrib/bind/lib/irs/gen_nw.c new file mode 100644 index 0000000..8ae8074 --- /dev/null +++ b/contrib/bind/lib/irs/gen_nw.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gen_nw.c,v 1.8 1997/12/04 04:57:50 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; +}; + +/* Forward */ + +static void nw_close(struct irs_nw*); +static struct nwent * nw_next(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +/* Public */ + +struct irs_nw * +irs_gen_nw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_nw *nw; + struct pvt *pvt; + + if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) { + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(nw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_nw]; + pvt->rule = pvt->rules; + nw->private = pvt; + nw->close = nw_close; + nw->next = nw_next; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free(pvt); + free(this); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + struct irs_nw *nw; + + while (pvt->rule) { + nw = pvt->rule->inst->nw; + rval = (*nw->next)(nw); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } + } + return (NULL); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + h_errno = NETDB_INTERNAL; + rval = (*nw->byname)(nw, name, type); + if (rval != NULL) + return (rval); + if (h_errno != TRY_AGAIN && !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + h_errno = NETDB_INTERNAL; + rval = (*nw->byaddr)(nw, net, length, type); + if (rval != NULL) + return (rval); + if (h_errno != TRY_AGAIN && !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_nw *nw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->minimize)(nw); + } +} diff --git a/contrib/bind/lib/irs/gen_p.h b/contrib/bind/lib/irs/gen_p.h new file mode 100644 index 0000000..92e115d --- /dev/null +++ b/contrib/bind/lib/irs/gen_p.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: gen_p.h,v 1.7 1996/11/21 10:28:15 vixie Exp $ + */ + +/* Notes: + * We hope to create a complete set of thread-safe entry points someday, + * which will mean a set of getXbyY() functions that take as an argument + * a pointer to the map class, which will have a pointer to the private + * data, which will be used preferentially to the static variables that + * are necessary to support the "classic" interface. This "classic" + * interface will then be reimplemented as stubs on top of the thread + * safe modules, and will keep the map class pointers as their only + * static data. HOWEVER, we are not there yet. So while we will call + * the just-barely-converted map class methods with map class pointers, + * right now they probably all still use statics. We're not fooling + * anybody, and we're not trying to (yet). + */ + +#ifndef _GEN_P_H_INCLUDED +#define _GEN_P_H_INCLUDED + +/* + * These are the access methods. + */ +enum irs_acc_id { + irs_lcl, /* Local. */ + irs_dns, /* DNS or Hesiod. */ + irs_nis, /* Sun NIS ("YP"). */ + irs_nacc +}; + +/* + * These are the map types. + */ +enum irs_map_id { + irs_gr, /* "group" */ + irs_pw, /* "passwd" */ + irs_sv, /* "services" */ + irs_pr, /* "protocols" */ + irs_ho, /* "hosts" */ + irs_nw, /* "networks" */ + irs_ng, /* "netgroup" */ + irs_nmap +}; + +/* + * This is an accessor instance. + */ +struct irs_inst { + struct irs_acc *acc; + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; +}; + +/* + * This is a search rule for some map type. + */ +struct irs_rule { + struct irs_rule * next; + struct irs_inst * inst; + int flags; +}; +#define IRS_MERGE 0x0001 /* Don't stop if acc. has data? */ +#define IRS_CONTINUE 0x0002 /* Don't stop if acc. has no data? */ + +/* + * This is the private data for a search access class. + */ +struct gen_p { + const char * options; + struct irs_rule * map_rules[(int)irs_nmap]; + struct irs_inst accessors[(int)irs_nacc]; +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_gen_acc __P((const char *)); +extern struct irs_gr * irs_gen_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_gen_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_gen_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_gen_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_gen_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_gen_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_gen_ng __P((struct irs_acc *)); + +#endif /*_IRS_P_H_INCLUDED*/ diff --git a/contrib/bind/lib/irs/gen_pr.c b/contrib/bind/lib/irs/gen_pr.c new file mode 100644 index 0000000..096be51 --- /dev/null +++ b/contrib/bind/lib/irs/gen_pr.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gen_pr.c,v 1.8 1997/12/04 04:57:51 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; +}; + +/* Forward */ + +static void pr_close(struct irs_pr*); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +/* Public */ + +struct irs_pr * +irs_gen_pr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = (struct irs_pr *)malloc(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pr]; + pvt->rule = pvt->rules; + pr->private = pvt; + pr->close = pr_close; + pr->next = pr_next; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free(pvt); + free(this); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + struct irs_pr *pr; + + while (pvt->rule) { + pr = pvt->rule->inst->pr; + rval = (*pr->next)(pr); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } + } + return (NULL); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->byname)(pr, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->bynumber)(pr, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pr *pr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + (*pr->minimize)(pr); + } +} diff --git a/contrib/bind/lib/irs/gen_pw.c b/contrib/bind/lib/irs/gen_pw.c new file mode 100644 index 0000000..aaa82df --- /dev/null +++ b/contrib/bind/lib/irs/gen_pw.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gen_pw.c,v 1.10 1997/12/04 04:57:51 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <sys/types.h> + +#include <errno.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +/* Public */ + +struct irs_pw * +irs_gen_pw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = (struct irs_pw *)malloc(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pw]; + pvt->rule = pvt->rules; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free(pvt); + free(this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + struct irs_pw *pw; + + while (pvt->rule) { + pw = pvt->rule->inst->pw; + rval = (*pw->next)(pw); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } + } + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pw *pw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byname)(pw, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byuid)(pw, uid); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pw *pw = rule->inst->pw; + + (*pw->minimize)(pw); + } +} + +#endif /* WANT_IRS_PW */ diff --git a/contrib/bind/lib/irs/gen_sv.c b/contrib/bind/lib/irs/gen_sv.c new file mode 100644 index 0000000..22f0cde --- /dev/null +++ b/contrib/bind/lib/irs/gen_sv.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gen_sv.c,v 1.8 1997/12/04 04:57:52 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +/* Public */ + +struct irs_sv * +irs_gen_sv(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = (struct irs_sv *)malloc(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_sv]; + pvt->rule = pvt->rules; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free(pvt); + free(this); +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + struct irs_sv *sv; + + while (pvt->rule) { + sv = pvt->rule->inst->sv; + rval = (*sv->next)(sv); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } + } + return (NULL); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byname)(sv, name, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byport)(sv, port, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_sv *sv; + + pvt->rule = pvt->rules; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + (*sv->minimize)(sv); + } +} diff --git a/contrib/bind/lib/irs/getgrent.c b/contrib/bind/lib/irs/getgrent.c new file mode 100644 index 0000000..df34447fb0 --- /dev/null +++ b/contrib/bind/lib/irs/getgrent.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: getgrent.c,v 1.13 1998/03/21 00:59:47 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include <sys/types.h> + +#include <errno.h> +#include <grp.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct irs_gr * init(void); +void endgrent(void); + +/* Public */ + +struct group * +getgrent() { + struct irs_gr *gr = init(); + + if (!gr) + return (NULL); + net_data.gr_last = (*gr->next)(gr); + return (net_data.gr_last); +} + +struct group * +getgrnam(const char *name) { + struct irs_gr *gr = init(); + + if (!gr) + return (NULL); + if (net_data.gr_stayopen && net_data.gr_last && + !strcmp(net_data.gr_last->gr_name, name)) + return (net_data.gr_last); + net_data.gr_last = (*gr->byname)(gr, name); + if (!net_data.gr_stayopen) + endgrent(); + return (net_data.gr_last); +} + +struct group * +getgrgid(gid_t gid) { + struct irs_gr *gr = init(); + + if (!gr) + return (NULL); + if (net_data.gr_stayopen && net_data.gr_last && + net_data.gr_last->gr_gid == gid) + return (net_data.gr_last); + net_data.gr_last = (*gr->bygid)(gr, gid); + if (!net_data.gr_stayopen) + endgrent(); + return (net_data.gr_last); +} + +int +setgroupent(int stayopen) { + struct irs_gr *gr = init(); + + if (!gr) + return (0); + (*gr->rewind)(gr); + net_data.gr_stayopen = (stayopen != 0); + return (1); +} + +#ifdef SETGRENT_VOID +void +setgrent() { + (void)setgroupent(0); +} +#else +int +setgrent() { + return (setgroupent(0)); +} +#endif /* SETGRENT_VOID */ + +void +endgrent() { + struct irs_gr *gr = init(); + + if (gr != NULL) + (*gr->minimize)(gr); +} + +int +getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroups) { + struct irs_gr *gr = init(); + + if (!gr) { + *ngroups = 0; + return (-1); + } + return ((*gr->list)(gr, name, basegid, groups, ngroups)); +} + +/* Private */ + +static struct irs_gr * +init() { + if (!net_data_init()) + goto error; + if (!net_data.gr) + net_data.gr = (*net_data.irs->gr_map)(net_data.irs); + if (!net_data.gr) { + error: + errno = EIO; + return (NULL); + } + return (net_data.gr); +} + +#endif /* WANT_IRS_GR */ diff --git a/contrib/bind/lib/irs/gethostent.c b/contrib/bind/lib/irs/gethostent.c new file mode 100644 index 0000000..669cb95 --- /dev/null +++ b/contrib/bind/lib/irs/gethostent.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1996,1997 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: gethostent.c,v 1.13 1997/12/04 04:57:52 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#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 <stdlib.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + char * aliases[1]; + char * addrs[2]; + char addr[NS_IN6ADDRSZ]; + char name[NS_MAXDNAME + 1]; + struct hostent host; +}; + +/* Forward */ + +static struct irs_ho * init(void); +static void freepvt(void); +static struct hostent * fakeaddr(const char *, int); + +/* Public */ + +struct hostent * +gethostbyname(const char *name) { + struct hostent *hp; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + if (_res.options & RES_USE_INET6) { + hp = gethostbyname2(name, AF_INET6); + if (hp) + return (hp); + } + return (gethostbyname2(name, AF_INET)); +} + +struct hostent * +gethostbyname2(const char *name, int af) { + struct irs_ho *ho = init(); + struct hostent *hp; + const char *cp; + char **hap; + + if (!ho) + return (NULL); + if (net_data.ho_stayopen && net_data.ho_last) { + if (!strcasecmp(name, net_data.ho_last->h_name)) + return (net_data.ho_last); + for (hap = net_data.ho_last->h_aliases; hap && *hap; hap++) + if (!strcasecmp(name, *hap)) + return (net_data.ho_last); + } + if (!strchr(name, '.') && (cp = hostalias(name))) + name = cp; + if ((hp = fakeaddr(name, af)) != NULL) + return (hp); + net_data.ho_last = (*ho->byname2)(ho, name, af); + if (!net_data.ho_stayopen) + endhostent(); + return (net_data.ho_last); +} + +struct hostent * +gethostbyaddr(const char *addr, int len, int af) { + struct irs_ho *ho = init(); + char **hap; + + if (!ho) + return (NULL); + if (net_data.ho_stayopen && net_data.ho_last && + net_data.ho_last->h_length == len) + for (hap = net_data.ho_last->h_addr_list; + hap && *hap; + hap++) + if (!memcmp(addr, *hap, len)) + return (net_data.ho_last); + net_data.ho_last = (*ho->byaddr)(ho, addr, len, af); + if (!net_data.ho_stayopen) + endhostent(); + return (net_data.ho_last); +} + +struct hostent * +gethostent() { + struct irs_ho *ho = init(); + + if (!ho) + return (NULL); + net_data.ho_last = (*ho->next)(ho); + return (net_data.ho_last); +} + +void +sethostent(int stayopen) { + struct irs_ho *ho = init(); + + if (!ho) + return; + freepvt(); + (*ho->rewind)(ho); + net_data.ho_stayopen = (stayopen != 0); +} + +void +endhostent() { + struct irs_ho *ho = init(); + + if (ho != NULL) + (*ho->minimize)(ho); +} + +/* Private */ + +static struct irs_ho * +init() { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + if (!net_data_init()) + goto error; + if (!net_data.ho) + net_data.ho = (*net_data.irs->ho_map)(net_data.irs); + if (!net_data.ho) { + error: errno = EIO; + h_errno = NETDB_INTERNAL; + return (NULL); + } + return (net_data.ho); +} + +static void +freepvt() { + if (net_data.ho_data) { + free(net_data.ho_data); + net_data.ho_data = NULL; + } +} + +static struct hostent * +fakeaddr(const char *name, int af) { + struct pvt *pvt; + const char *cp; + + freepvt(); + net_data.ho_data = malloc(sizeof(struct pvt)); + if (!net_data.ho_data) { + errno = ENOMEM; + h_errno = NETDB_INTERNAL; + return (NULL); + } + pvt = net_data.ho_data; + /* + * Unlike its forebear (inet_aton), our friendly inet_pton() is strict + * in its interpretation of its input, and it will only return "1" if + * the input string is a formally valid (and thus unambiguous with + * respect to host names) internet address specification for this AF. + * + * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now. + */ + if (inet_pton(af, name, pvt->addr) != 1) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + strncpy(pvt->name, name, NS_MAXDNAME); + pvt->name[NS_MAXDNAME] = '\0'; + pvt->host.h_addrtype = af; + switch (af) { + case AF_INET: + pvt->host.h_length = NS_INADDRSZ; + break; + case AF_INET6: + pvt->host.h_length = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; + return (NULL); + } + pvt->host.h_name = pvt->name; + pvt->host.h_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->addrs[0] = (char *)pvt->addr; + pvt->addrs[1] = NULL; + pvt->host.h_addr_list = pvt->addrs; + if (af == AF_INET && (_res.options & RES_USE_INET6)) + map_v4v6_address(pvt->addr, pvt->addr); + h_errno = NETDB_SUCCESS; + return (&pvt->host); +} + +#ifdef grot /* for future use in gethostbyaddr(), for "SUNSECURITY" */ + struct hostent *rhp; + char **haddr; + u_long old_options; + char hname2[MAXDNAME+1]; + + if (af == AF_INET) { + /* + * turn off search as the name should be absolute, + * 'localhost' should be matched by defnames + */ + strncpy(hname2, hp->h_name, MAXDNAME); + hname2[MAXDNAME] = '\0'; + old_options = _res.options; + _res.options &= ~RES_DNSRCH; + _res.options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hname2))) { + _res.options = old_options; + h_errno = HOST_NOT_FOUND; + return (NULL); + } + _res.options = old_options; + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + } +#endif /* grot */ diff --git a/contrib/bind/lib/irs/getnetent.c b/contrib/bind/lib/irs/getnetent.c new file mode 100644 index 0000000..17132f6 --- /dev/null +++ b/contrib/bind/lib/irs/getnetent.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: getnetent.c,v 1.10 1997/12/04 04:57:53 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + struct netent netent; + char * aliases[1]; + char name[MAXDNAME + 1]; +}; + +/* Forward */ + +static struct irs_nw * init(void); +static struct netent * nw_to_net(struct nwent *); +static void freepvt(void); +static struct netent * fakeaddr(const char *, int af); + +/* Portability */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffff +#endif + +/* Public */ + +struct netent * +getnetent() { + struct irs_nw *nw = init(); + + if (!nw) + return (NULL); + net_data.nw_last = nw_to_net((*nw->next)(nw)); + return (net_data.nw_last); +} + +struct netent * +getnetbyname(const char *name) { + struct irs_nw *nw = init(); + struct netent *np; + char **nap; + + if (!nw) + return (NULL); + if (net_data.nw_stayopen && net_data.nw_last) { + if (!strcmp(net_data.nw_last->n_name, name)) + return (net_data.nw_last); + for (nap = net_data.nw_last->n_aliases; nap && *nap; nap++) + if (!strcmp(name, *nap)) + return (net_data.nw_last); + } + if ((np = fakeaddr(name, AF_INET)) != NULL) + return (np); + net_data.nw_last = nw_to_net((*nw->byname)(nw, name, AF_INET)); + if (!net_data.nw_stayopen) + endnetent(); + return (net_data.nw_last); +} + +struct netent * +getnetbyaddr(unsigned long net, int type) { + struct irs_nw *nw = init(); + u_char addr[4]; + int bits; + + if (!nw) + return (NULL); + if (net_data.nw_stayopen && net_data.nw_last) + if (type == net_data.nw_last->n_addrtype && + net == net_data.nw_last->n_net) + return (net_data.nw_last); + + addr[3] = (0xFF000000 & net) >> 24; + addr[2] = (0x00FF0000 & net) >> 16; + addr[1] = (0x0000FF00 & net) >> 8; + addr[0] = (0x000000FF & net); + + /* Use the old class rules to figure out the network bits. */ + if (addr[3] >= 240) + bits = 32; + else if (addr[3] >= 224) + bits = 4; + else if (addr[3] >= 192) + bits = 24; + else if (addr[3] >= 128) + bits = 16; + else + bits = 8; + + net_data.nw_last = nw_to_net((*nw->byaddr)(nw, addr, bits, AF_INET)); + if (!net_data.nw_stayopen) + endnetent(); + return (net_data.nw_last); +} + +void +setnetent(int stayopen) { + struct irs_nw *nw = init(); + + if (!nw) + return; + freepvt(); + (*nw->rewind)(nw); + net_data.nw_stayopen = (stayopen != 0); +} + +void +endnetent() { + struct irs_nw *nw = init(); + + if (nw != NULL) + (*nw->minimize)(nw); +} + +/* Private */ + +static struct irs_nw * +init() { + if (!net_data_init()) + goto error; + if (!net_data.nw) + net_data.nw = (*net_data.irs->nw_map)(net_data.irs); + if (!net_data.nw) { + error: + errno = EIO; + return (NULL); + } + return (net_data.nw); +} + +static void +freepvt() { + if (net_data.nw_data) { + free(net_data.nw_data); + net_data.nw_data = NULL; + } +} + +static struct netent * +fakeaddr(const char *name, int af) { + struct pvt *pvt; + const char *cp; + u_long tmp; + + if (af != AF_INET) { + /* XXX should support IPv6 some day */ + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; + return (NULL); + } + if (!isascii(name[0]) || !isdigit(name[0])) + return (NULL); + for (cp = name; *cp; ++cp) + if (!isascii(*cp) || (!isdigit(*cp) && *cp != '.')) + return (NULL); + if (*--cp == '.') + return (NULL); + + /* All-numeric, no dot at the end. */ + + tmp = inet_network(name); + if (tmp == INADDR_NONE) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + + /* Valid network number specified. + * Fake up a netent as if we'd actually + * done a lookup. + */ + freepvt(); + net_data.nw_data = malloc(sizeof(struct pvt)); + if (!net_data.nw_data) { + errno = ENOMEM; + h_errno = NETDB_INTERNAL; + return (NULL); + } + pvt = net_data.nw_data; + + strncpy(pvt->name, name, MAXDNAME); + pvt->name[MAXDNAME] = '\0'; + pvt->netent.n_name = pvt->name; + pvt->netent.n_addrtype = AF_INET; + pvt->netent.n_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->netent.n_net = tmp; + + return (&pvt->netent); +} + +static struct netent * +nw_to_net(struct nwent *nwent) { + struct pvt *pvt; + u_long addr = 0; + int i; + int msbyte; + + if (!nwent || nwent->n_addrtype != AF_INET) + return (NULL); + freepvt(); + net_data.nw_data = malloc(sizeof(struct pvt)); + if (!net_data.nw_data) { + errno = ENOMEM; + h_errno = NETDB_INTERNAL; + return (NULL); + } + pvt = net_data.nw_data; + pvt->netent.n_name = nwent->n_name; + pvt->netent.n_aliases = nwent->n_aliases; + pvt->netent.n_addrtype = nwent->n_addrtype; + +/* + * What this code does: Converts net addresses from network to host form. + * + * msbyte: the index of the most significant byte in the n_addr array. + * + * Shift bytes in significant order into addr. When all signicant + * bytes are in, zero out bits in the LSB that are not part of the network. + */ + msbyte = nwent->n_length / 8 + + ((nwent->n_length % 8) != 0 ? 1 : 0) - 1; + for (i = 0; i <= msbyte; i++) + addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i]; + i = (32 - nwent->n_length) % 8; + if (i != 0) + addr &= ~((1 << (i + 1)) - 1); + pvt->netent.n_net = addr; + return (&pvt->netent); +} + + diff --git a/contrib/bind/lib/irs/getnetgrent.c b/contrib/bind/lib/irs/getnetgrent.c new file mode 100644 index 0000000..0acb776 --- /dev/null +++ b/contrib/bind/lib/irs/getnetgrent.c @@ -0,0 +1,93 @@ +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent.c,v 1.9 1997/12/04 04:57:53 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include <errno.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct irs_ng * init(void); + +/* Public */ + +void +setnetgrent(const char *netgroup) { + struct irs_ng *ng = init(); + + if (ng != NULL) + (*ng->rewind)(ng, netgroup); +} + +void +endnetgrent(void) { + struct irs_ng *ng = init(); + + if (ng) + (*ng->close)(ng); + net_data.ng = NULL; +} + +int +innetgr(const char *netgroup, const char *host, + const char *user, const char *domain) { + struct irs_ng *ng = init(); + + if (!ng) + return (0); + return ((*ng->test)(ng, netgroup, host, user, domain)); +} + +int +getnetgrent(char **host, char **user, char **domain) { + struct irs_ng *ng = init(); + struct netgrp *ngent; + + if (!ng) + return (0); + return ((*ng->next)(ng, host, user, domain)); +} + +/* Private */ + +static struct irs_ng * +init(void) { + + if (!net_data_init()) + goto error; + if (!net_data.ng) + net_data.ng = (*net_data.irs->ng_map)(net_data.irs); + if (!net_data.ng) { +error: + errno = EIO; + return (NULL); + } + return (net_data.ng); +} diff --git a/contrib/bind/lib/irs/getprotoent.c b/contrib/bind/lib/irs/getprotoent.c new file mode 100644 index 0000000..f79a1c6 --- /dev/null +++ b/contrib/bind/lib/irs/getprotoent.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: getprotoent.c,v 1.9 1997/12/04 04:57:53 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <errno.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct irs_pr * init(void); + +/* Public */ + +struct protoent * +getprotoent() { + struct irs_pr *pr = init(); + + if (!pr) + return (NULL); + net_data.pr_last = (*pr->next)(pr); + return (net_data.pr_last); +} + +struct protoent * +getprotobyname(const char *name) { + struct irs_pr *pr = init(); + char **pap; + + if (!pr) + return (NULL); + if (net_data.pr_stayopen && net_data.pr_last) { + if (!strcmp(net_data.pr_last->p_name, name)) + return (net_data.pr_last); + for (pap = net_data.pr_last->p_aliases; pap && *pap; pap++) + if (!strcmp(name, *pap)) + return (net_data.pr_last); + } + net_data.pr_last = (*pr->byname)(pr, name); + if (!net_data.pr_stayopen) + endprotoent(); + return (net_data.pr_last); +} + +struct protoent * +getprotobynumber(int proto) { + struct irs_pr *pr = init(); + + if (!pr) + return (NULL); + if (net_data.pr_stayopen && net_data.pr_last) + if (net_data.pr_last->p_proto == proto) + return (net_data.pr_last); + net_data.pr_last = (*pr->bynumber)(pr, proto); + if (!net_data.pr_stayopen) + endprotoent(); + return (net_data.pr_last); +} + +void +setprotoent(int stayopen) { + struct irs_pr *pr = init(); + + if (!pr) + return; + (*pr->rewind)(pr); + net_data.pr_stayopen = (stayopen != 0); +} + +void +endprotoent() { + struct irs_pr *pr = init(); + + if (pr != NULL) + (*pr->minimize)(pr); +} + +/* Private */ + +static struct irs_pr * +init() { + if (!net_data_init()) + goto error; + if (!net_data.pr) + net_data.pr = (*net_data.irs->pr_map)(net_data.irs); + if (!net_data.pr) { + error: + errno = EIO; + return (NULL); + } + return (net_data.pr); +} diff --git a/contrib/bind/lib/irs/getpwent.c b/contrib/bind/lib/irs/getpwent.c new file mode 100644 index 0000000..8e4d897 --- /dev/null +++ b/contrib/bind/lib/irs/getpwent.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: getpwent.c,v 1.13 1998/03/21 00:59:48 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <sys/types.h> + +#include <errno.h> +#include <pwd.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct irs_pw * init(void); + +/* Public */ + +struct passwd * +getpwent(void) { + struct irs_pw *pw = init(); + + if (!pw) + return (NULL); + net_data.pw_last = (*pw->next)(pw); + return (net_data.pw_last); +} + +struct passwd * +getpwnam(const char *name) { + struct irs_pw *pw = init(); + + if (!pw) + return (NULL); + if (net_data.pw_stayopen && net_data.pw_last && + !strcmp(net_data.pw_last->pw_name, name)) + return (net_data.pw_last); + net_data.pw_last = (*pw->byname)(pw, name); + if (!net_data.pw_stayopen) + endpwent(); + return (net_data.pw_last); +} + +struct passwd * +getpwuid(uid_t uid) { + struct irs_pw *pw = init(); + + if (!pw) + return (NULL); + if (net_data.pw_stayopen && net_data.pw_last && + net_data.pw_last->pw_uid == uid) + return (net_data.pw_last); + net_data.pw_last = (*pw->byuid)(pw, uid); + if (!net_data.pw_stayopen) + endpwent(); + return (net_data.pw_last); +} + +int +setpassent(int stayopen) { + struct irs_pw *pw = init(); + + if (!pw) + return (0); + (*pw->rewind)(pw); + net_data.pw_stayopen = (stayopen != 0); + return (1); +} + +#ifdef SETPWENT_VOID +void +setpwent() { + (void) setpassent(0); +} +#else +int +setpwent() { + return (setpassent(0)); +} +#endif + +void +endpwent() { + struct irs_pw *pw = init(); + + if (pw != NULL) + (*pw->minimize)(pw); +} + +/* Private */ + +static struct irs_pw * +init() { + if (!net_data_init()) + goto error; + if (!net_data.pw) + net_data.pw = (*net_data.irs->pw_map)(net_data.irs); + if (!net_data.pw) { + error: + errno = EIO; + return (NULL); + } + return (net_data.pw); +} + +#endif /* WANT_IRS_PW */ diff --git a/contrib/bind/lib/irs/getservent.c b/contrib/bind/lib/irs/getservent.c new file mode 100644 index 0000000..64ac2dc --- /dev/null +++ b/contrib/bind/lib/irs/getservent.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: getservent.c,v 1.10 1997/12/04 04:57:54 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <errno.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct irs_sv * init(void); + +/* Public */ + +struct servent * +getservent(void) { + struct irs_sv *sv = init(); + + if (!sv) + return (NULL); + net_data.sv_last = (*sv->next)(sv); + return (net_data.sv_last); +} + +struct servent * +getservbyname(const char *name, const char *proto) { + struct irs_sv *sv = init(); + char **sap; + + if (!sv) + return (NULL); + if (net_data.sv_stayopen && net_data.sv_last) + if (!proto || !strcmp(net_data.sv_last->s_proto,proto)) { + if (!strcmp(net_data.sv_last->s_name, name)) + return (net_data.sv_last); + for (sap = net_data.sv_last->s_aliases; + sap && *sap; sap++) + if (!strcmp(name, *sap)) + return (net_data.sv_last); + } + net_data.sv_last = (*sv->byname)(sv, name, proto); + if (!net_data.sv_stayopen) + endservent(); + return (net_data.sv_last); +} + +struct servent * +getservbyport(int port, const char *proto) { + struct irs_sv *sv = init(); + + if (!sv) + return (NULL); + if (net_data.sv_stayopen && net_data.sv_last) + if (port == net_data.sv_last->s_port && + ( !proto || + !strcmp(net_data.sv_last->s_proto, proto))) + return (net_data.sv_last); + net_data.sv_last = (*sv->byport)(sv, port,proto); + return (net_data.sv_last); +} + +void +setservent(int stayopen) { + struct irs_sv *sv = init(); + + if (!sv) + return; + (*sv->rewind)(sv); + net_data.sv_stayopen = (stayopen != 0); +} + +void +endservent() { + struct irs_sv *sv = init(); + + if (sv != NULL) + (*sv->minimize)(sv); +} + +/* Private */ + +static struct irs_sv * +init() { + if (!net_data_init()) + goto error; + if (!net_data.sv) + net_data.sv = (*net_data.irs->sv_map)(net_data.irs); + if (!net_data.sv) { + error: + errno = EIO; + return (NULL); + } + return (net_data.sv); +} diff --git a/contrib/bind/lib/irs/hesiod.c b/contrib/bind/lib/irs/hesiod.c new file mode 100644 index 0000000..a56d213 --- /dev/null +++ b/contrib/bind/lib/irs/hesiod.c @@ -0,0 +1,454 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: hesiod.c,v 1.15 1998/01/26 23:08:24 halley Exp $"; +#endif + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* + * hesiod.c --- the core portion of the hesiod resolver. + * + * This file is derived from the hesiod library from Project Athena; + * It has been extensively rewritten by Theodore Ts'o to have a more + * thread-safe interface. + */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#include "pathnames.h" +#include "hesiod.h" +#include "hesiod_p.h" + +/* Forward */ + +int hesiod_init(void **context); +void hesiod_end(void *context); +char * hesiod_to_bind(void *context, const char *name, + const char *type); +char ** hesiod_resolve(void *context, const char *name, + const char *type); +void hesiod_free_list(void *context, char **list); + +static int parse_config_file(struct hesiod_p *ctx, const char *filename); +static char ** get_txt_records(struct hesiod_p *ctx, int class, + const char *name); + +/* Public */ + +/* + * This function is called to initialize a hesiod_p. + */ +int +hesiod_init(void **context) { + struct hesiod_p *ctx; + char *cp; + + ctx = malloc(sizeof(struct hesiod_p)); + if (ctx == 0) { + errno = ENOMEM; + return (-1); + } + + ctx->LHS = NULL; + ctx->RHS = NULL; + + if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { +#ifdef DEF_RHS + /* + * Use compiled in defaults. + */ + ctx->LHS = malloc(strlen(DEF_LHS)+1); + ctx->RHS = malloc(strlen(DEF_RHS)+1); + if (ctx->LHS == 0 || ctx->RHS == 0) { + errno = ENOMEM; + goto cleanup; + } + strcpy(ctx->LHS, DEF_LHS); + strcpy(ctx->RHS, DEF_RHS); +#else + goto cleanup; +#endif + } + /* + * The default RHS can be overridden by an environment + * variable. + */ + if ((cp = getenv("HES_DOMAIN")) != NULL) { + if (ctx->RHS) + free(ctx->RHS); + ctx->RHS = malloc(strlen(cp)+2); + if (!ctx->RHS) { + errno = ENOMEM; + goto cleanup; + } + if (cp[0] == '.') + strcpy(ctx->RHS, cp); + else { + strcpy(ctx->RHS, "."); + strcat(ctx->RHS, cp); + } + } + + /* + * If there is no default hesiod realm set, we return an + * error. + */ + if (!ctx->RHS) { + errno = ENOEXEC; + goto cleanup; + } + + *context = ctx; + return (0); + + cleanup: + if (ctx->LHS) + free(ctx->LHS); + if (ctx->RHS) + free(ctx->RHS); + free(ctx); + return (-1); +} + +/* + * This function deallocates the hesiod_p + */ +void +hesiod_end(void *context) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + free(ctx); +} + +/* + * This function takes a hesiod (name, type) and returns a DNS + * name which is to be resolved. + */ +char * +hesiod_to_bind(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname; + char **rhs_list = NULL; + const char *RHS, *cp; + + /* Decide what our RHS is, and set cp to the end of the actual name. */ + if ((cp = strchr(name, '@')) != NULL) { + if (strchr(cp + 1, '.')) + RHS = cp + 1; + else if ((rhs_list = hesiod_resolve(context, cp + 1, + "rhs-extension")) != NULL) + RHS = *rhs_list; + else { + errno = ENOENT; + return (NULL); + } + } else { + RHS = ctx->RHS; + cp = name + strlen(name); + } + + /* + * Allocate the space we need, including up to three periods and + * the terminating NUL. + */ + if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + + (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { + errno = ENOMEM; + if (rhs_list) + hesiod_free_list(context, rhs_list); + return NULL; + } + + /* Now put together the DNS name. */ + memcpy(bindname, name, cp - name); + bindname[cp - name] = '\0'; + strcat(bindname, "."); + strcat(bindname, type); + if (ctx->LHS) { + if (ctx->LHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, ctx->LHS); + } + if (RHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, RHS); + + if (rhs_list) + hesiod_free_list(context, rhs_list); + + return (bindname); +} + +/* + * This is the core function. Given a hesiod (name, type), it + * returns an array of strings returned by the resolver. + */ +char ** +hesiod_resolve(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname = hesiod_to_bind(context, name, type); + char **retvec; + + if (!bindname) + return (NULL); + + if ((retvec = get_txt_records(ctx, C_IN, bindname))) + return (retvec); + + if (errno != ENOENT) + return (NULL); + + retvec = get_txt_records(ctx, C_HS, bindname); + free(bindname); + return (retvec); +} + +void +hesiod_free_list(void *context, char **list) { + char **p; + + for (p = list; *p; p++) + free(*p); + free(list); +} + +/* + * This function parses the /etc/hesiod.conf file + */ +static int +parse_config_file(struct hesiod_p *ctx, const char *filename) { + char *key, *data, *cp, **cpp; + char buf[MAXDNAME+7]; + FILE *fp; + + /* + * Clear the existing configuration variable, just in case + * they're set. + */ + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + + /* + * Now open and parse the file... + */ + if (!(fp = fopen(filename, "r"))) + return (-1); + + while (fgets(buf, sizeof(buf), fp) != NULL) { + cp = buf; + if (*cp == '#' || *cp == '\n' || *cp == '\r') + continue; + while(*cp == ' ' || *cp == '\t') + cp++; + key = cp; + while(*cp != ' ' && *cp != '\t' && *cp != '=') + cp++; + *cp++ = '\0'; + + while(*cp == ' ' || *cp == '\t' || *cp == '=') + cp++; + data = cp; + while(*cp != ' ' && *cp != '\n' && *cp != '\r') + cp++; + *cp++ = '\0'; + + if (strcmp(key, "lhs") == 0) + cpp = &ctx->LHS; + else if (strcmp(key, "rhs") == 0) + cpp = &ctx->RHS; + else + continue; + + *cpp = malloc(strlen(data) + 1); + if (!*cpp) { + errno = ENOMEM; + goto cleanup; + } + strcpy(*cpp, data); + } + fclose(fp); + return (0); + + cleanup: + fclose(fp); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + return (-1); +} + +/* + * Given a DNS class and a DNS name, do a lookup for TXT records, and + * return a list of them. + * + * XXX we're still using the non-thread safe res_* routines. + */ +static char ** +get_txt_records(struct hesiod_p *ctx, int class, const char *name) { + struct { + int type; /* RR type */ + int class; /* RR class */ + int dlen; /* len of data section */ + u_char *data; /* pointer to data */ + } rr; + struct __res_state save_res; + HEADER *hp; + u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; + u_char *cp, *erdata, *eom; + char *dst, *edst, **list; + int ancount, qdcount; + int i, j, n, skip; + + /* + * Construct the query and send it. We play games with _res + * since we don't have our own resolver state. Once the + * resolver routines are rewritten to use their own context + * variable, we'll use it here. + */ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + save_res = _res; + n = res_mkquery(QUERY, name, class, T_TXT, NULL, 0, + NULL, qbuf, MAX_HESRESP); + if (n < 0) { + errno = EMSGSIZE; + return (NULL); + } + n = res_send(qbuf, n, abuf, MAX_HESRESP); + _res = save_res; + if (n < 0) { + errno = ECONNREFUSED; + return (NULL); + } + if (n < HFIXEDSZ) { + errno = EMSGSIZE; + return (NULL); + } + + /* + * OK, parse the result. + */ + hp = (HEADER *) abuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + cp = abuf + sizeof(HEADER); + eom = abuf + n; + + /* Skip query, trying to get to the answer section which follows. */ + for (i = 0; i < qdcount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0 || cp + skip + QFIXEDSZ > eom) { + errno = EMSGSIZE; + return (NULL); + } + cp += skip + QFIXEDSZ; + } + + list = malloc((ancount + 1) * sizeof(char *)); + if (!list) { + errno = ENOMEM; + return (NULL); + } + j = 0; + for (i = 0; i < ancount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0) { + errno = EMSGSIZE; + goto cleanup; + } + cp += skip; + if (cp + 3 * INT16SZ + INT32SZ > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.type = ns_get16(cp); + cp += INT16SZ; + rr.class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* skip the ttl, too */ + rr.dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + rr.dlen > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.data = cp; + cp += rr.dlen; + if (rr.class != class || rr.type != T_TXT) + continue; + if (!(list[j] = malloc(rr.dlen))) + goto cleanup; + dst = list[j++]; + edst = dst + rr.dlen; + erdata = rr.data + rr.dlen; + cp = rr.data; + while (cp < erdata) { + n = (unsigned char) *cp++; + if (cp + n > eom || dst + n > edst) { + errno = EMSGSIZE; + goto cleanup; + } + memcpy(dst, cp, n); + cp += n; + dst += n; + } + if (cp != erdata) { + errno = EMSGSIZE; + goto cleanup; + } + *dst = '\0'; + } + list[j] = NULL; + if (j == 0) { + errno = ENOENT; + goto cleanup; + } + return (list); + + cleanup: + for (i = 0; i < j; i++) + free(list[i]); + free(list); + return (NULL); +} diff --git a/contrib/bind/lib/irs/hesiod_p.h b/contrib/bind/lib/irs/hesiod_p.h new file mode 100644 index 0000000..d2204db --- /dev/null +++ b/contrib/bind/lib/irs/hesiod_p.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* + * $Id: hesiod_p.h,v 1.6 1996/11/18 09:09:32 vixie Exp $ + */ + +/* + * hesiod_p.h -- private definitions for the hesiod library + */ + +#ifndef _HESIOD_P_H_INCLUDED +#define _HESIOD_P_H_INCLUDED + +#define DEF_RHS ".Athena.MIT.EDU" /* Defaults if HESIOD_CONF */ +#define DEF_LHS ".ns" /* file is not */ + /* present. */ +struct hesiod_p { + char * LHS; /* normally ".ns" */ + char * RHS; /* AKA the default hesiod domain */ +}; + +#define MAX_HESRESP 1024 + +#endif /*_HESIOD_P_H_INCLUDED*/ diff --git a/contrib/bind/lib/irs/irs_data.c b/contrib/bind/lib/irs/irs_data.c new file mode 100644 index 0000000..7f23751 --- /dev/null +++ b/contrib/bind/lib/irs/irs_data.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: irs_data.c,v 1.7 1997/12/04 04:57:54 halley Exp $"; +#endif + +#include "port_before.h" + +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +struct net_data net_data; + +int +net_data_init() { + if (!net_data.irs) + net_data.irs = irs_gen_acc(""); + return (net_data.irs != NULL); +} diff --git a/contrib/bind/lib/irs/irs_data.h b/contrib/bind/lib/irs/irs_data.h new file mode 100644 index 0000000..4356b57 --- /dev/null +++ b/contrib/bind/lib/irs/irs_data.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irs_data.h,v 1.7 1997/12/04 04:57:55 halley Exp $ + */ + +#define net_data __net_data +#define net_data_init __net_data_init + +struct net_data { + struct irs_acc * irs; + + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; + + struct group * gr_last; + struct passwd * pw_last; + struct servent * sv_last; + struct protoent * pr_last; + struct netent * nw_last; + struct hostent * ho_last; + + unsigned int gr_stayopen :1; + unsigned int pw_stayopen :1; + unsigned int sv_stayopen :1; + unsigned int pr_stayopen :1; + unsigned int ho_stayopen :1; + unsigned int nw_stayopen :1; + + void * nw_data; + void * ho_data; + + char fill[512 - 68]; /* 68 = sizeof(above) */ +}; + +extern struct net_data net_data; +extern int net_data_init(void); diff --git a/contrib/bind/lib/irs/irs_p.h b/contrib/bind/lib/irs/irs_p.h new file mode 100644 index 0000000..bc49665 --- /dev/null +++ b/contrib/bind/lib/irs/irs_p.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irs_p.h,v 1.6 1997/12/04 04:57:55 halley Exp $ + */ + +#ifndef _IRS_P_H_INCLUDED +#define _IRS_P_H_INCLUDED + +#include "pathnames.h" + +#define irs_nul_ng __irs_nul_ng +#define map_v4v6_address __map_v4v6_address +#define make_group_list __make_group_list + +extern void map_v4v6_address(const char *src, char *dst); +extern int make_group_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +extern struct irs_ng * irs_nul_ng(struct irs_acc *); + +#endif diff --git a/contrib/bind/lib/irs/lcl.c b/contrib/bind/lib/irs/lcl.c new file mode 100644 index 0000000..badbdfe --- /dev/null +++ b/contrib/bind/lib/irs/lcl.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: lcl.c,v 1.11 1998/03/21 00:59:49 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Forward. */ + +static void lcl_close(struct irs_acc *); + +/* Public */ + +struct irs_acc * +irs_lcl_acc(const char *options) { + struct irs_acc *acc; + struct lcl_p *lcl; + + if (!(acc = malloc(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(lcl = malloc(sizeof *lcl))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + memset(lcl, 0x5e, sizeof *lcl); + acc->private = lcl; +#ifdef WANT_IRS_GR + acc->gr_map = irs_lcl_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_lcl_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_lcl_sv; + acc->pr_map = irs_lcl_pr; + acc->ho_map = irs_lcl_ho; + acc->nw_map = irs_lcl_nw; + acc->ng_map = irs_lcl_ng; + acc->close = lcl_close; + return (acc); +} + +/* Methods */ + +static void +lcl_close(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl) + free(lcl); + free(this); +} diff --git a/contrib/bind/lib/irs/lcl_gr.c b/contrib/bind/lib/irs/lcl_gr.c new file mode 100644 index 0000000..5a5d503 --- /dev/null +++ b/contrib/bind/lib/irs/lcl_gr.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_gr.c,v 1.20 1998/03/21 00:59:49 halley Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_gr_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> + +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Types. */ + +struct pvt { + FILE * fp; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static int grstart(struct pvt *); +static char * grnext(struct pvt *); +static struct group * grscan(struct irs_gr *, int, gid_t, const char *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_gr * +irs_lcl_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = malloc(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = malloc(sizeof *pvt))) { + free(gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void)fclose(pvt->fp); + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + free(pvt); + free(this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->fp && !grstart(pvt)) + return (NULL); + return (grscan(this, 0, 0, NULL)); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, 0, name)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, gid, NULL)); +} + +static void +gr_rewind(struct irs_gr *this) { + (void) grstart((struct pvt *)this->private); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private. */ + +static int +grstart(struct pvt *pvt) { + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return (1); + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_GROUP, "r"))) + return (0); + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + fclose(pvt->fp); + return (0); + } + return (1); +} + +#define INITIAL_NMEMB 30 /* about 120 bytes */ +#define INITIAL_BUFSIZ (INITIAL_NMEMB * 8) /* about 240 bytes */ + +static char * +grnext(struct pvt *pvt) { + char *w, *e; + int ch; + + /* Make sure we have a buffer. */ + if (pvt->membuf == NULL) { + pvt->membuf = malloc(INITIAL_BUFSIZ); + if (pvt->membuf == NULL) { + enomem: + errno = ENOMEM; + return (NULL); + } + pvt->membufsize = INITIAL_BUFSIZ; + } + + /* Read until EOF or EOL. */ + w = pvt->membuf; + e = pvt->membuf + pvt->membufsize; + while ((ch = fgetc(pvt->fp)) != EOF && ch != '\n') { + /* Make sure we have room for this character and a \0. */ + if (w + 1 == e) { + size_t o = w - pvt->membuf; + size_t n = pvt->membufsize * 2; + char *t = realloc(pvt->membuf, n); + + if (t == NULL) + goto enomem; + pvt->membuf = t; + pvt->membufsize = n; + w = pvt->membuf + o; + e = pvt->membuf + pvt->membufsize; + } + /* Store it. */ + *w++ = (char)ch; + } + + /* Hitting EOF on the first character really does mean EOF. */ + if (w == pvt->membuf && ch == EOF) { + errno = ENOENT; + return (NULL); + } + + /* Last line of /etc/group need not end with \n; we don't care. */ + *w = '\0'; + return (pvt->membuf); +} + +static struct group * +grscan(struct irs_gr *this, int search, gid_t gid, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + size_t linelen, n; + char *bp, **m, *p; + + /* Read lines until we find one that matches our search criteria. */ + for (;;) { + bp = grnext(pvt); + if (bp == NULL) + return (NULL); + + /* Optimize the usual case of searching for a name. */ + pvt->group.gr_name = strsep(&bp, ":"); + if (search && name != NULL && + strcmp(pvt->group.gr_name, name) != 0) + continue; + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Skip past the password field. */ + pvt->group.gr_passwd = strsep(&bp, ":"); + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Checking for a gid. */ + if ((p = strsep(&bp, ":")) == NULL) + continue; + /* + * Unlike the tests above, the test below is supposed to be + * testing 'p' and not 'bp', in case you think it's a typo. + */ + if (p == NULL || *p == '\0') { + corrupt: + /* warning: corrupted %s file!", _PATH_GROUP */ + continue; + } + pvt->group.gr_gid = atoi(p); + if (search && name == NULL && pvt->group.gr_gid != gid) + continue; + + /* We want this record. */ + break; + } + + /* + * Count commas to find out how many members there might be. + * Note that commas separate, so if there is one comma there + * can be two members (group:*:id:user1,user2). Add another + * to account for the NULL terminator. As above, allocate + * largest of INITIAL_NMEMB, or 2*n. + */ + for (n = 2, p = bp; (p = strpbrk(p, ", ")) != NULL; ++p, ++n) + (void)NULL; + if (n > pvt->nmemb || pvt->group.gr_mem == NULL) { + if ((n *= 2) < INITIAL_NMEMB) + n = INITIAL_NMEMB; + if ((m = realloc(pvt->group.gr_mem, n * sizeof *m)) == NULL) + return (NULL); + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + + /* Set the name pointers. */ + for (m = pvt->group.gr_mem; (p = strsep(&bp, ", ")) != NULL;) + if (p[0] != '\0') + *m++ = p; + *m = NULL; + + return (&pvt->group); +} + +#endif /* WANT_IRS_GR */ diff --git a/contrib/bind/lib/irs/lcl_ho.c b/contrib/bind/lib/irs/lcl_ho.c new file mode 100644 index 0000000..b285d1c --- /dev/null +++ b/contrib/bind/lib/irs/lcl_ho.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 1985, 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. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: lcl_ho.c,v 1.15 1997/12/04 04:57:56 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#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 <fcntl.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern int h_errno; + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + FILE * fp; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +static size_t ns_namelen(const char *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_ho * +irs_lcl_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = malloc(sizeof *ho))) { + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void) fclose(pvt->fp); + free(pvt); + free(this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct hostent *hp; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + if (_res.options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct hostent *hp; + char **hap; + size_t n; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + ho_rewind(this); + n = ns_namelen(name); + while ((hp = ho_next(this)) != NULL) { + size_t nn; + + if (hp->h_addrtype != af) + continue; + nn = ns_namelen(hp->h_name); + if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0) + goto found; + for (hap = hp->h_aliases; *hap; hap++) { + nn = ns_namelen(*hap); + if (strncasecmp(*hap, name, Max(n, nn)) == 0) + goto found; + } + } + found: + if (!hp) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + h_errno = NETDB_SUCCESS; + return (hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + const u_char *uaddr = addr; + struct hostent *hp; + int size; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; + return (NULL); + } + if (size > len) { + errno = EINVAL; + h_errno = NETDB_INTERNAL; + return (NULL); + } + + /* + * Do the search. + */ + ho_rewind(this); + while ((hp = ho_next(this)) != NULL) { + char **hap; + + for (hap = hp->h_addr_list; *hap; hap++) { + const u_char *taddr = (const u_char *)*hap; + int taf = hp->h_addrtype; + int tlen = hp->h_length; + + if (taf == AF_INET6 && tlen == IN6ADDRSZ && + (!memcmp(taddr, mapped, sizeof mapped) || + !memcmp(taddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + taddr += sizeof mapped; + taf = AF_INET; + tlen = INADDRSZ; + } + if (taf == af && tlen == len && + !memcmp(taddr, uaddr, tlen)) + goto found; + } + } + found: + if (!hp) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + h_errno = NETDB_SUCCESS; + return (hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **q, *p; + int af, len; + + if (!pvt->fp) + ho_rewind(this); + if (!pvt->fp) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + again: + if (!(p = fgets(pvt->hostbuf, sizeof pvt->hostbuf, pvt->fp))) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + if (*p == '#') + goto again; + if (!(cp = strpbrk(p, "#\n"))) + goto again; + *cp = '\0'; + if (!(cp = strpbrk(p, " \t"))) + goto again; + *cp++ = '\0'; + if ((_res.options & RES_USE_INET6) && + inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) { + if (_res.options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + goto again; + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + while (*cp == ' ' || *cp == '\t') + cp++; + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + } + *q = NULL; + h_errno = NETDB_SUCCESS; + return (&pvt->host); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_HOSTS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private. */ + +static size_t +ns_namelen(const char *s) { + int i; + + for (i = strlen(s); i > 0 && s[i-1] == '.'; i--) + (void)NULL; + return ((size_t) i); +} diff --git a/contrib/bind/lib/irs/lcl_ng.c b/contrib/bind/lib/irs/lcl_ng.c new file mode 100644 index 0000000..ca7e7e2 --- /dev/null +++ b/contrib/bind/lib/irs/lcl_ng.c @@ -0,0 +1,433 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: lcl_ng.c,v 1.12 1998/02/13 01:10:41 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" + +/* Definitions */ + +#define NG_HOST 0 /* Host name */ +#define NG_USER 1 /* User name */ +#define NG_DOM 2 /* and Domain name */ +#define LINSIZ 1024 /* Length of netgroup file line */ + +/* + * XXX Warning XXX + * This code is a hack-and-slash special. It realy needs to be + * rewritten with things like strdup, and realloc in mind. + * More reasonable data structures would not be a bad thing. + */ + +/* + * Static Variables and functions used by setnetgrent(), getnetgrent() and + * endnetgrent(). + * There are two linked lists: + * - linelist is just used by setnetgrent() to parse the net group file via. + * parse_netgrp() + * - netgrp is the list of entries for the current netgroup + */ +struct linelist { + struct linelist *l_next; /* Chain ptr. */ + int l_parsed; /* Flag for cycles */ + char * l_groupname; /* Name of netgroup */ + char * l_line; /* Netgroup entrie(s) to be parsed */ +}; + +struct ng_old_struct { + struct ng_old_struct *ng_next; /* Chain ptr */ + char * ng_str[3]; /* Field pointers, see below */ +}; + +struct pvt { + FILE *fp; + struct linelist *linehead; + struct ng_old_struct *nextgrp; + struct { + struct ng_old_struct *gr; + char *grname; + } grouphead; +}; + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + +static int parse_netgrp(struct irs_ng *, const char*); +static struct linelist *read_for_group(struct irs_ng *, const char *); +static void freelists(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_lcl_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = malloc(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = malloc(sizeof *pvt))) { + free(ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) + fclose(pvt->fp); + freelists(this); + free(pvt); + free(this); +} + +/* + * Parse the netgroup file looking for the netgroup and build the list + * of netgrp structures. Let parse_netgrp() and read_for_group() do + * most of the work. + */ +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) { + fclose(pvt->fp); + pvt->fp = NULL; + } + + if (pvt->fp == NULL || pvt->grouphead.gr == NULL || + strcmp(group, pvt->grouphead.grname)) { + freelists(this); + if (pvt->fp != NULL) + fclose(pvt->fp); + pvt->fp = fopen(_PATH_NETGROUP, "r"); + if (pvt->fp != NULL) { + if (parse_netgrp(this, group)) + freelists(this); + if (!(pvt->grouphead.grname = strdup(group))) + freelists(this); + fclose(pvt->fp); + pvt->fp = NULL; + } + } + pvt->nextgrp = pvt->grouphead.gr; +} + +/* + * Get the next netgroup off the list. + */ +static int +ng_next(struct irs_ng *this, char **host, char **user, char **domain) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->nextgrp) { + *host = pvt->nextgrp->ng_str[NG_HOST]; + *user = pvt->nextgrp->ng_str[NG_USER]; + *domain = pvt->nextgrp->ng_str[NG_DOM]; + pvt->nextgrp = pvt->nextgrp->ng_next; + return (1); + } + return (0); +} + +/* + * Search for a match in a netgroup. + */ +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + char *ng_host, *ng_user, *ng_domain; + + ng_rewind(this, name); + while (ng_next(this, &ng_host, &ng_user, &ng_domain)) + if ((host == NULL || ng_host == NULL || + !strcmp(host, ng_host)) && + (user == NULL || ng_user == NULL || + !strcmp(user, ng_user)) && + (domain == NULL || ng_domain == NULL || + !strcmp(domain, ng_domain))) { + freelists(this); + return (1); + } + freelists(this); + return (0); +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private */ + +/* + * endnetgrent() - cleanup + */ +static void +freelists(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct linelist *lp, *olp; + struct ng_old_struct *gp, *ogp; + + lp = pvt->linehead; + while (lp) { + olp = lp; + lp = lp->l_next; + free(olp->l_groupname); + free(olp->l_line); + free((char *)olp); + } + pvt->linehead = NULL; + if (pvt->grouphead.grname) { + free(pvt->grouphead.grname); + pvt->grouphead.grname = NULL; + } + gp = pvt->grouphead.gr; + while (gp) { + ogp = gp; + gp = gp->ng_next; + if (ogp->ng_str[NG_HOST]) + free(ogp->ng_str[NG_HOST]); + if (ogp->ng_str[NG_USER]) + free(ogp->ng_str[NG_USER]); + if (ogp->ng_str[NG_DOM]) + free(ogp->ng_str[NG_DOM]); + free((char *)ogp); + } + pvt->grouphead.gr = NULL; +} + +/* + * Parse the netgroup file setting up the linked lists. + */ +static int +parse_netgrp(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *spos, *epos; + int len, strpos; + char *pos, *gpos; + struct ng_old_struct *grp; + struct linelist *lp = pvt->linehead; + + /* + * First, see if the line has already been read in. + */ + while (lp) { + if (!strcmp(group, lp->l_groupname)) + break; + lp = lp->l_next; + } + if (lp == NULL && + (lp = read_for_group(this, group)) == NULL) + return (1); + if (lp->l_parsed) { + /*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/ + return (1); + } else + lp->l_parsed = 1; + pos = lp->l_line; + while (*pos != '\0') { + if (*pos == '(') { + if (!(grp = malloc(sizeof (struct ng_old_struct)))) { + freelists(this); + errno = ENOMEM; + return (1); + } + memset(grp, 0, sizeof (struct ng_old_struct)); + grp->ng_next = pvt->grouphead.gr; + pvt->grouphead.gr = grp; + pos++; + gpos = strsep(&pos, ")"); + for (strpos = 0; strpos < 3; strpos++) { + if ((spos = strsep(&gpos, ","))) { + while (*spos == ' ' || *spos == '\t') + spos++; + if ((epos = strpbrk(spos, " \t"))) { + *epos = '\0'; + len = epos - spos; + } else + len = strlen(spos); + if (len > 0) { + if(!(grp->ng_str[strpos] + = (char *) + malloc(len + 1))) { + freelists(this); + return (1); + } + memcpy(grp->ng_str[strpos], + spos, + len + 1); + } + } else + goto errout; + } + } else { + spos = strsep(&pos, ", \t"); + if (spos != NULL && parse_netgrp(this, spos)) { + freelists(this); + return (1); + } + } + if (pos == NULL) + break; + while (*pos == ' ' || *pos == ',' || *pos == '\t') + pos++; + } + return (0); + errout: + /*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, + spos);*/ + return (1); +} + +/* + * Read the netgroup file and save lines until the line for the netgroup + * is found. Return 1 if eof is encountered. + */ +static struct linelist * +read_for_group(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *pos, *spos, *linep, *olinep; + int len, olen, cont; + struct linelist *lp; + char line[LINSIZ + 1]; + + while (fgets(line, LINSIZ, pvt->fp) != NULL) { + pos = line; + if (*pos == '#') + continue; + while (*pos == ' ' || *pos == '\t') + pos++; + spos = pos; + while (*pos != ' ' && *pos != '\t' && *pos != '\n' && + *pos != '\0') + pos++; + len = pos - spos; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\n' && *pos != '\0') { + if (!(lp = malloc(sizeof (*lp)))) { + freelists(this); + return (NULL); + } + lp->l_parsed = 0; + if (!(lp->l_groupname = malloc(len + 1))) { + free(lp); + freelists(this); + return (NULL); + } + memcpy(lp->l_groupname, spos, len); + *(lp->l_groupname + len) = '\0'; + len = strlen(pos); + olen = 0; + olinep = NULL; + + /* + * Loop around handling line continuations. + */ + do { + if (*(pos + len - 1) == '\n') + len--; + if (*(pos + len - 1) == '\\') { + len--; + cont = 1; + } else + cont = 0; + if (len > 0) { + if (!(linep = malloc(olen + len + 1))){ + if (olen > 0) + free(olinep); + free(lp->l_groupname); + free(lp); + freelists(this); + errno = ENOMEM; + return (NULL); + } + if (olen > 0) { + memcpy(linep, olinep, olen); + free(olinep); + } + memcpy(linep + olen, pos, len); + olen += len; + *(linep + olen) = '\0'; + olinep = linep; + } + if (cont) { + if (fgets(line, LINSIZ, pvt->fp)) { + pos = line; + len = strlen(pos); + } else + cont = 0; + } + } while (cont); + lp->l_line = linep; + lp->l_next = pvt->linehead; + pvt->linehead = lp; + + /* + * If this is the one we wanted, we are done. + */ + if (!strcmp(lp->l_groupname, group)) + return (lp); + } + } + return (NULL); +} diff --git a/contrib/bind/lib/irs/lcl_nw.c b/contrib/bind/lib/irs/lcl_nw.c new file mode 100644 index 0000000..09a324c --- /dev/null +++ b/contrib/bind/lib/irs/lcl_nw.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_nw.c,v 1.13 1997/12/04 04:57:57 halley Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include <isc/misc.h> +#include "irs_p.h" +#include "lcl_p.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct nwent net; + char * aliases[MAXALIASES]; + char addr[MAXADDRSIZE]; +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_nw * +irs_lcl_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) { + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(nw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void)fclose(pvt->fp); + free(pvt); + free(this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct nwent *p; + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) + if (p->n_addrtype == type && p->n_length == length) + if (bitncmp(p->n_addr, net, length) == 0) + break; + return (p); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct nwent *p; + char **ap; + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) { + if (strcasecmp(p->n_name, name) == 0 && + p->n_addrtype == type) + break; + for (ap = p->n_aliases; *ap; ap++) + if ((strcasecmp(*ap, name) == 0) && + (p->n_addrtype == type)) + goto found; + } + found: + return (p); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_NETWORKS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **q; + + if (pvt->fp == NULL) + nw_rewind(this); + if (pvt->fp == NULL) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + again: + p = fgets(pvt->line, BUFSIZ, pvt->fp); + if (p == NULL) + return (NULL); + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + pvt->net.n_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr, + sizeof pvt->addr); + if (pvt->net.n_length < 0) + goto again; + pvt->net.n_addrtype = AF_INET; + pvt->net.n_addr = pvt->addr; + q = pvt->net.n_aliases = pvt->aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + return (&pvt->net); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} diff --git a/contrib/bind/lib/irs/lcl_p.h b/contrib/bind/lib/irs/lcl_p.h new file mode 100644 index 0000000..058aeaa --- /dev/null +++ b/contrib/bind/lib/irs/lcl_p.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: lcl_p.h,v 1.5 1996/10/25 07:23:19 vixie Exp $ + */ + +/* + * lcl_p.h - private include file for the local accessor functions. + */ + +#ifndef _LCL_P_H_INCLUDED +#define _LCL_P_H_INCLUDED + +/* + * Object state. + */ +struct lcl_p { + void *placeholder; +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_lcl_acc __P((const char *)); +extern struct irs_gr * irs_lcl_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_lcl_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_lcl_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_lcl_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_lcl_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_lcl_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_lcl_ng __P((struct irs_acc *)); + +#endif /*_LCL_P_H_INCLUDED*/ diff --git a/contrib/bind/lib/irs/lcl_pr.c b/contrib/bind/lib/irs/lcl_pr.c new file mode 100644 index 0000000..101f99d --- /dev/null +++ b/contrib/bind/lib/irs/lcl_pr.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pr.c,v 1.11 1997/12/04 04:57:57 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifndef _PATH_PROTOCOLS +#define _PATH_PROTOCOLS "/etc/protocols" +#endif +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + FILE *fp; + char line[BUFSIZ+1]; + struct protoent proto; + char *proto_aliases[MAXALIASES]; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_pr * +irs_lcl_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = (struct irs_pr *)malloc(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void) fclose(pvt->fp); + free(pvt); + free(this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + + struct protoent *p; + char **cp; + + pr_rewind(this); + while ((p = pr_next(this))) { + if (!strcmp(p->p_name, name)) + goto found; + for (cp = p->p_aliases; *cp; cp++) + if (!strcmp(*cp, name)) + goto found; + } + found: + return (p); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct protoent *p; + + pr_rewind(this); + while ((p = pr_next(this))) + if (p->p_proto == proto) + break; + return (p); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_PROTOCOLS, "r" ))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **q; + + if (!pvt->fp) + pr_rewind(this); + if (!pvt->fp) + return (NULL); + again: + if ((p = fgets(pvt->line, BUFSIZ, pvt->fp)) == NULL) + return (NULL); + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + pvt->proto.p_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->proto.p_proto = atoi(cp); + q = pvt->proto.p_aliases = pvt->proto_aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->proto_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + return (&pvt->proto); +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} diff --git a/contrib/bind/lib/irs/lcl_pw.c b/contrib/bind/lib/irs/lcl_pw.c new file mode 100644 index 0000000..1f3e870 --- /dev/null +++ b/contrib/bind/lib/irs/lcl_pw.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pw.c,v 1.16 1998/02/13 01:10:42 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <sys/param.h> + +#include <db.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <utmp.h> +#include <unistd.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* + * The lookup techniques and data extraction code here must be kept + * in sync with that in `pwd_mkdb'. + */ + + +/* Types */ + +struct pvt { + struct passwd passwd; /* password structure */ + DB *pw_db; /* password database */ + int pw_keynum; /* key counter */ + int warned; + u_int max; + char * line; +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static int initdb(struct pvt *); +static int hashpw(struct irs_pw *, DBT *); + +/* Public */ +struct irs_pw * +irs_lcl_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = malloc(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = malloc(sizeof *pvt))) { + free(pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db) { + (void)(pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } + if (pvt->line) + free(pvt->line); + free(pvt); + free(this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + DBT key; + char bf[sizeof(pvt->pw_keynum) + 1]; + + if (!initdb(pvt)) + return (NULL); + + ++pvt->pw_keynum; + bf[0] = _PW_KEYBYNUM; + memcpy(bf + 1, (char *)&pvt->pw_keynum, sizeof(pvt->pw_keynum)); + key.data = (u_char *)bf; + key.size = sizeof(pvt->pw_keynum) + 1; + return (hashpw(this, &key) ? &pvt->passwd : NULL); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int len, rval; + char bf[UT_NAMESIZE + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYNAME; + len = strlen(name); + memcpy(bf + 1, name, MIN(len, UT_NAMESIZE)); + key.data = (u_char *)bf; + key.size = len + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int keyuid, rval; + char bf[sizeof(keyuid) + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYUID; + keyuid = uid; + memcpy(bf + 1, &keyuid, sizeof(keyuid)); + key.data = (u_char *)bf; + key.size = sizeof(keyuid) + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->pw_keynum = 0; +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db != NULL) { + (void) (*pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } +} + +/* Private. */ + +static int +initdb(struct pvt *pvt) { + const char *p; + + if (pvt->pw_db) { + if (lseek((*pvt->pw_db->fd)(pvt->pw_db), 0L, SEEK_CUR) >= 0L) + return (1); + else + (void) (*pvt->pw_db->close)(pvt->pw_db); + } + pvt->pw_db = dbopen((p = _PATH_SMP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (!pvt->pw_db) + pvt->pw_db = dbopen((p =_PATH_MP_DB), O_RDONLY, + 0, DB_HASH, NULL); + if (pvt->pw_db) + return (1); + if (!pvt->warned) { + syslog(LOG_ERR, "%s: %m", p); + pvt->warned++; + } + return (0); +} + +static int +hashpw(struct irs_pw *this, DBT *key) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *t, *l; + DBT data; + + if ((pvt->pw_db->get)(pvt->pw_db, key, &data, 0)) + return (0); + p = (char *)data.data; + if (data.size > pvt->max && + (pvt->line = realloc(pvt->line, pvt->max += 1024)) == NULL) + return (0); + /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ + t = pvt->line; + l = pvt->line + pvt->max; +#define EXPAND(e) if ((e = t) == NULL) return (0); else \ + do if (t >= l) return (0); while ((*t++ = *p++) != '\0') +#define SCALAR(v) if (t + sizeof v >= l) return (0); else \ + (memmove(&(v), p, sizeof v), p += sizeof v) + EXPAND(pvt->passwd.pw_name); + EXPAND(pvt->passwd.pw_passwd); + SCALAR(pvt->passwd.pw_uid); + SCALAR(pvt->passwd.pw_gid); + SCALAR(pvt->passwd.pw_change); + EXPAND(pvt->passwd.pw_class); + EXPAND(pvt->passwd.pw_gecos); + EXPAND(pvt->passwd.pw_dir); + EXPAND(pvt->passwd.pw_shell); + SCALAR(pvt->passwd.pw_expire); + return (1); +} + +#endif /* WANT_IRS_PW */ diff --git a/contrib/bind/lib/irs/lcl_sv.c b/contrib/bind/lib/irs/lcl_sv.c new file mode 100644 index 0000000..0da9984 --- /dev/null +++ b/contrib/bind/lib/irs/lcl_sv.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_sv.c,v 1.11 1997/12/04 04:57:58 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct servent serv; + char * serv_aliases[MAXALIASES]; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +/* Portability */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_sv * +irs_lcl_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = (struct irs_sv *)malloc(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + fclose(pvt->fp); + free(pvt); + free(this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + register struct servent *p; + register char **cp; + + sv_rewind(this); + while ((p = sv_next(this))) { + if (strcmp(name, p->s_name) == 0) + goto gotname; + for (cp = p->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; + gotname: + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + register struct servent *p; + + sv_rewind(this); + while ((p = sv_next(this))) { + if (p->s_port != port) + continue; + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_SERVICES, "r" ))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p; + register char *cp, **q; + + if (!pvt->fp) + sv_rewind(this); + if (!pvt->fp) + return (NULL); + again: + if ((p = fgets(pvt->line, BUFSIZ, pvt->fp)) == NULL) + return (NULL); + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + pvt->serv.s_name = p; + p = strpbrk(p, " \t"); + if (p == NULL) + goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + cp = strpbrk(p, ",/"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + pvt->serv.s_port = htons((u_short)atoi(p)); + pvt->serv.s_proto = cp; + q = pvt->serv.s_aliases = pvt->serv_aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->serv_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + *q = NULL; + return (&pvt->serv); +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} diff --git a/contrib/bind/lib/irs/nis.c b/contrib/bind/lib/irs/nis.c new file mode 100644 index 0000000..d53bde9 --- /dev/null +++ b/contrib/bind/lib/irs/nis.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis.c,v 1.10 1998/03/21 00:59:50 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifdef WANT_IRS_NIS + +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "nis_p.h" + +/* Forward */ + +static void nis_close(struct irs_acc *); + +/* Public */ + +struct irs_acc * +irs_nis_acc(const char *options) { + struct nis_p *nis; + struct irs_acc *acc; + char *domain; + + if (yp_get_default_domain(&domain) != 0) + return (NULL); + if (!(nis = malloc(sizeof *nis))) { + errno = ENOMEM; + return (NULL); + } + memset(nis, 0, sizeof *nis); + if (!(acc = malloc(sizeof *acc))) { + free(nis); + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + acc->private = nis; + nis->domain = strdup(domain); +#ifdef WANT_IRS_GR + acc->gr_map = irs_nis_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_nis_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_nis_sv; + acc->pr_map = irs_nis_pr; + acc->ho_map = irs_nis_ho; + acc->nw_map = irs_nis_nw; + acc->ng_map = irs_nis_ng; + acc->close = nis_close; + return (acc); +} + +/* Methods */ + +static void +nis_close(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + free(nis->domain); + free(nis); + free(this); +} + +#endif /*WANT_IRS_NIS*/ diff --git a/contrib/bind/lib/irs/nis_gr.c b/contrib/bind/lib/irs/nis_gr.c new file mode 100644 index 0000000..aa2f30c --- /dev/null +++ b/contrib/bind/lib/irs/nis_gr.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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) 1996, 1997, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_gr.c,v 1.13 1998/03/21 00:59:50 halley Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_GR) || !defined(WANT_IRS_NIS) +static int __bind_irs_gr_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> + +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <errno.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char group_bygid[] = "group.bygid"; +static /*const*/ char group_byname[] = "group.byname"; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static struct group * makegroupent(struct irs_gr *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_gr * +irs_nis_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = malloc(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = malloc(sizeof *pvt))) { + free(gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + return (gr); +} + +/* Methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + free(pvt); + free(this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, group_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, group_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makegroupent(this); + } while (rval == NULL); + return (rval); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, group_byname, (char *)name, strlen(name), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)gid); + r = yp_match(pvt->nis_domain, group_bygid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +gr_minimize(struct irs_gr *this) { + /* NOOP */ +} + +/* Private */ + +static struct group * +makegroupent(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + int num_members = 0; + char *cp, **new; + u_long t; + + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = -1; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (pvt->group.gr_mem == NULL) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + pvt->nmemb = 1; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_GR && WANT_IRS_NIS */ diff --git a/contrib/bind/lib/irs/nis_ho.c b/contrib/bind/lib/irs/nis_ho.c new file mode 100644 index 0000000..65bdb4b --- /dev/null +++ b/contrib/bind/lib/irs/nis_ho.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: nis_ho.c,v 1.10 1997/12/04 04:57:59 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#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 <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +extern int h_errno; + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES + 1]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; +static /*const*/ char hosts_byname[] = "hosts.byname"; +static /*const*/ char hosts_byaddr[] = "hosts.byaddr"; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +static struct hostent * makehostent(struct irs_ho *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_ho * +irs_nis_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(ho = malloc(sizeof *ho))) { + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(ho); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + return (ho); +} + +/* Methods */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + free(pvt); + free(this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct hostent *hp; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (NULL); + if (_res.options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, hosts_byname, (char *)name, strlen(name), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + const u_char *uaddr = addr; + int r; + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + if (inet_ntop(af, uaddr, tmp, sizeof tmp) == NULL) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, hosts_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, hosts_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, hosts_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + rval = makehostent(this); + } while (rval == NULL); + return (rval); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +ho_minimize(struct irs_ho *this) { + /* NOOP */ +} + +/* Private */ + +static struct hostent * +makehostent(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *cp, **q, *p; + int af, len; + + p = pvt->curval_data; + if ((cp = strchr(p, '#')) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, spaces))) + return (NULL); + *cp++ = '\0'; + if ((_res.options & RES_USE_INET6) && + inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, pvt->host_addr) > 0) { + if (_res.options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + return (NULL); + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + cp += strspn(cp, spaces); + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES]) + *q++ = cp; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + } + *q = NULL; + h_errno = NETDB_SUCCESS; + return (&pvt->host); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/contrib/bind/lib/irs/nis_ng.c b/contrib/bind/lib/irs/nis_ng.c new file mode 100644 index 0000000..1667ca6 --- /dev/null +++ b/contrib/bind/lib/irs/nis_ng.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_ng.c,v 1.10 1997/12/04 04:58:00 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <netinet/in.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct tmpgrp { + const char * name; + const char * host; + const char * user; + const char * domain; + struct tmpgrp * next; +}; + +struct pvt { + char * nis_domain; + struct tmpgrp * tmp; + struct tmpgrp * cur; + char * tmpgroup; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char netgroup_map[] = "netgroup"; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +static void add_group_to_list(struct pvt *, const char *, int); +static void add_tuple_to_list(struct pvt *, const char *, char *); +static void tmpfree(struct pvt *); + +/* Public */ + +struct irs_ng * +irs_nis_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = malloc(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + tmpfree(pvt); + free(pvt); + free(this); +} + +static int +ng_next(struct irs_ng *this, char **host, char **user, char **domain) { + struct pvt *pvt = (struct pvt *)this->private; + struct netgrp *rval; + + if (!pvt->cur) + return (0); + *host = (/*const*/ char *)pvt->cur->host; + *user = (/*const*/ char *)pvt->cur->user; + *domain = (/*const*/ char *)pvt->cur->domain; + pvt->cur = pvt->cur->next; + return (1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct tmpgrp *cur; + + tmpfree(pvt); + add_group_to_list(pvt, name, strlen(name)); + for (cur = pvt->tmp; cur; cur = cur->next) { + if ((!host || !cur->host || !strcmp(host, cur->host)) && + (!user || !cur->user || !strcmp(user, cur->user)) && + (!domain || !cur->domain || !strcmp(domain, cur->domain))) + break; + } + tmpfree(pvt); + return ((cur == NULL) ? 0 : 1); +} + +static void +ng_rewind(struct irs_ng *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct netgrp *rval; + + /* Either hand back or free the existing list. */ + if (pvt->tmpgroup) { + if (pvt->tmp && !strcmp(pvt->tmpgroup, name)) + goto reset; + tmpfree(pvt); + } + pvt->tmpgroup = strdup(name); + add_group_to_list(pvt, name, strlen(name)); + reset: + pvt->cur = pvt->tmp; +} + +static void +ng_minimize(struct irs_ng *this) { + /* NOOP */ +} + +/* Private */ + +static void +add_group_to_list(struct pvt *pvt, const char *name, int len) { + char *vdata, *cp, *np; + struct tmpgrp *tmp; + int vlen, r; + + /* Don't add the same group to the list more than once. */ + for (tmp = pvt->tmp; tmp; tmp = tmp->next) + if (!strcmp(tmp->name, name)) + return; + + r = yp_match(pvt->nis_domain, netgroup_map, (char *)name, len, + &vdata, &vlen); + if (r == 0) { + for (cp = vdata; cp; cp = np) { + np = strchr(cp, ' '); + if (np) + *np++ = '\0'; + if (*cp == '(') + add_tuple_to_list(pvt, name, cp); + else + add_group_to_list(pvt, cp, strlen(cp)); + } + free(vdata); + } +} + +static void +add_tuple_to_list(struct pvt *pvt, const char *name, char *cp) { + struct tmpgrp *tmp; + char *tp, *np; + + assert(*cp++ == '('); + + tmp = malloc(sizeof *tmp + strlen(name) + sizeof '\0' + + strlen(cp) - sizeof ')'); + if (!tmp) + return; + memset(tmp, 0, sizeof *tmp); + tp = ((char *)tmp) + sizeof *tmp; + + /* Name */ + strcpy(tp, name); + tmp->name = tp; + tp += strlen(tp) + 1; + + /* Host */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->host = tp; + tp += strlen(tp) + 1; + cp = np; + + /* User */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->user = tp; + tp += strlen(tp) + 1; + cp = np; + + /* Domain */ + if (!(np = strchr(cp, ')'))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->domain = tp; + + /* + * Empty string in file means wildcard, but + * NULL string in return value means wildcard. + */ + if (!*tmp->host) + tmp->host = NULL; + if (!*tmp->user) + tmp->user = NULL; + if (!*tmp->domain) + tmp->domain = NULL; + + /* Add to list (LIFO). */ + tmp->next = pvt->tmp; + pvt->tmp = tmp; + return; + + cleanup: + free(tmp); +} + +static void +tmpfree(struct pvt *pvt) { + struct tmpgrp *cur, *next; + + if (pvt->tmpgroup) { + free(pvt->tmpgroup); + pvt->tmpgroup = NULL; + } + for (cur = pvt->tmp; cur; cur = next) { + next = cur->next; + free(cur); + } + pvt->tmp = NULL; +} + +#endif /*WANT_IRS_NIS*/ diff --git a/contrib/bind/lib/irs/nis_nw.c b/contrib/bind/lib/irs/nis_nw.c new file mode 100644 index 0000000..b9e9e79 --- /dev/null +++ b/contrib/bind/lib/irs/nis_nw.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_nw.c,v 1.10 1997/12/04 04:58:00 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + + struct nwent nwent; + char * nwbuf; + + char * aliases[MAXALIASES + 1]; + u_char addr[MAXADDRSIZE]; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char networks_byname[] = "networks.byname"; +static /*const*/ char networks_byaddr[] = "networks.byaddr"; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +static struct nwent * makenwent(struct irs_nw *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_nw * +irs_nis_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(nw = (struct irs_nw *)malloc(sizeof *nw))) { + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(nw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->nwbuf) + free(pvt->nwbuf); + free(pvt); + free(this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "255.255.255.255/32"], *t; + int r; + + if (af != AF_INET) { + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + /* Try it with /CIDR first. */ + if (inet_net_ntop(AF_INET, net, length, tmp, sizeof tmp) == NULL) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + r = yp_match(pvt->nis_domain, networks_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + /* Give it a shot without the /CIDR. */ + if ((t = strchr(tmp, '/')) != NULL) { + *t = '\0'; + r = yp_match(pvt->nis_domain, networks_byaddr, + tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + } + if (r != 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + } + return (makenwent(this)); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + if (af != AF_INET) { + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, networks_byname, (char *)name, + strlen(name), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + return (makenwent(this)); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, networks_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, networks_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + rval = makenwent(this); + } while (rval == NULL); + return (rval); +} + +static void +nw_minimize(struct irs_nw *this) { + /* NOOP */ +} + +/* Private */ + +static struct nwent * +makenwent(struct irs_nw *this) { + static const char spaces[] = " \t"; + struct pvt *pvt = (struct pvt *)this->private; + char *t, *cp, **ap; + + if (pvt->nwbuf) + free(pvt->nwbuf); + pvt->nwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if ((cp = strchr(pvt->nwbuf, '#')) != NULL) + *cp = '\0'; + cp = pvt->nwbuf; + + /* Name */ + pvt->nwent.n_name = cp; + cp += strcspn(cp, spaces); + if (!*cp) + goto cleanup; + *cp++ = '\0'; + cp += strspn(cp, spaces); + + /* Network */ + pvt->nwent.n_addrtype = AF_INET; + t = cp + strcspn(cp, spaces); + if (*t) + *t++ = '\0'; + pvt->nwent.n_length = inet_net_pton(AF_INET, cp, + pvt->addr, sizeof pvt->addr); + if (pvt->nwent.n_length < 0) + goto cleanup; + pvt->nwent.n_addr = pvt->addr; + cp = t; + + /* Aliases */ + ap = pvt->nwent.n_aliases = pvt->aliases; + while (*cp) { + if (ap >= &pvt->aliases[MAXALIASES]) + break; + *ap++ = cp; + cp += strcspn(cp, spaces); + if (!*cp) + break; + *cp++ = '\0'; + cp += strspn(cp, spaces); + } + *ap = NULL; + + return (&pvt->nwent); + + cleanup: + if (pvt->nwbuf) { + free(pvt->nwbuf); + pvt->nwbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/contrib/bind/lib/irs/nis_p.h b/contrib/bind/lib/irs/nis_p.h new file mode 100644 index 0000000..92d2647 --- /dev/null +++ b/contrib/bind/lib/irs/nis_p.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: nis_p.h,v 1.4 1996/10/25 07:23:24 vixie Exp $ + */ + +/* + * nis_p.h - private include file for the NIS functions. + */ + +/* + * Object state. + */ +struct nis_p { + char * domain; +}; + + +/* + * Methods. + */ + +extern struct irs_gr * irs_nis_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_nis_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_nis_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_nis_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_nis_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_nis_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_nis_ng __P((struct irs_acc *)); diff --git a/contrib/bind/lib/irs/nis_pr.c b/contrib/bind/lib/irs/nis_pr.c new file mode 100644 index 0000000..1653692 --- /dev/null +++ b/contrib/bind/lib/irs/nis_pr.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pr.c,v 1.9 1997/12/04 04:58:00 halley Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <netinet/in.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct protoent proto; + char * prbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char protocols_byname[] = "protocols.byname"; +static /*const*/ char protocols_bynumber[] = "protocols.bynumber"; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static struct protoent * makeprotoent(struct irs_pr *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pr * +irs_nis_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = malloc(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = malloc(sizeof *pvt))) { + free(pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + free(pvt); + free(this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, protocols_byname, (char *)name, + strlen(name), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "-4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%d", num); + r = yp_match(pvt->nis_domain, protocols_bynumber, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, protocols_bynumber, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, protocols_bynumber, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + rval = makeprotoent(this); + } while (rval == NULL); + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pr_minimize(struct irs_pr *this) { + /* NOOP */ +} + +/* Private */ + +static struct protoent * +makeprotoent(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, **t; + int n, m; + + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = pvt->curval_data; + pvt->curval_data = NULL; + + for (p = pvt->prbuf; *p && *p != '#'; p++) + NULL; + while (p > pvt->prbuf && isspace(p[-1])) + p--; + *p = '\0'; + + p = pvt->prbuf; + n = m = 0; + + pvt->proto.p_name = p; + while (*p && !isspace(*p)) + p++; + if (!*p) + return (NULL); + *p++ = '\0'; + + while (*p && isspace(*p)) + p++; + pvt->proto.p_proto = atoi(p); + while (*p && !isspace(*p)) + p++; + *p++ = '\0'; + + while (*p) { + if ((n + 1) >= m || !pvt->proto.p_aliases) { + m += 10; + t = realloc(pvt->proto.p_aliases, + m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = t; + } + pvt->proto.p_aliases[n++] = p; + while (*p && !isspace(*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[n] = NULL; + return (&pvt->proto); + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/contrib/bind/lib/irs/nis_pw.c b/contrib/bind/lib/irs/nis_pw.c new file mode 100644 index 0000000..f06f796 --- /dev/null +++ b/contrib/bind/lib/irs/nis_pw.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pw.c,v 1.10 1997/12/04 04:58:01 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_PW) || !defined(WANT_IRS_NIS) +static int __bind_irs_pw_unneeded; +#else + +#include <sys/param.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <errno.h> +#include <fcntl.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct passwd passwd; + char * pwbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char passwd_byname[] = "passwd.byname"; +static /*const*/ char passwd_byuid[] = "passwd.byuid"; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static struct passwd * makepasswdent(struct irs_pw *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pw * +irs_nis_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = malloc(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = malloc(sizeof *pvt))) { + free(pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + nisfree(pvt, do_all); + free(pvt); + free(this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, passwd_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, passwd_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makepasswdent(this); + } while (rval == NULL); + return (rval); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, passwd_byname, name, strlen(name), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)uid); + r = yp_match(pvt->nis_domain, passwd_byuid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pw_minimize(struct irs_pw *this) { + /* NOOP */ +} + +/* Private */ + +static struct passwd * +makepasswdent(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp; + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + pvt->passwd.pw_class = cp; /* Needs to point at a \0. */ + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_PW && WANT_IRS_NIS */ diff --git a/contrib/bind/lib/irs/nis_sv.c b/contrib/bind/lib/irs/nis_sv.c new file mode 100644 index 0000000..1dacc2f --- /dev/null +++ b/contrib/bind/lib/irs/nis_sv.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_sv.c,v 1.10 1997/12/04 04:58:01 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <sys/socket.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + char line[BUFSIZ+1]; + struct servent serv; + char * svbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char services_byname[] = "services.byname"; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static struct servent * makeservent(struct irs_sv *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_sv * +irs_nis_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = (struct irs_sv *)malloc(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = (struct pvt *)malloc(sizeof *pvt))) { + free(sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + free(pvt); + free(this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct servent *serv; + char **sap; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (!strcmp(name, serv->s_name)) + break; + for (sap = serv->s_aliases; sap && *sap; sap++) + if (!strcmp(name, *sap)) + break; + } + return (serv); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct servent *serv; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (serv->s_port == port) + break; + } + return (serv); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, services_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, services_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makeservent(this); + } while (rval == NULL); + return (rval); +} + +static void +sv_minimize(struct irs_sv *this) { + /* NOOP */ +} + +/* Private */ + +static struct servent * +makeservent(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *p, **t; + int n, m; + + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + + if ((p = strchr(pvt->svbuf, '#'))) + *p = '\0'; + + p = pvt->svbuf; + + pvt->serv.s_name = p; + p += strcspn(p, spaces); + if (!*p) + goto cleanup; + *p++ = '\0'; + p += strspn(p, spaces); + + pvt->serv.s_port = htons((u_short) atoi(p)); + pvt->serv.s_proto = NULL; + + while (*p && !isspace(*p)) + if (*p++ == '/') + pvt->serv.s_proto = p; + if (!pvt->serv.s_proto) + goto cleanup; + if (*p) { + *p++ = '\0'; + p += strspn(p, spaces); + } + + n = m = 0; + while (*p) { + if ((n + 1) >= m || !pvt->serv.s_aliases) { + m += 10; + t = realloc(pvt->serv.s_aliases, m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = t; + } + pvt->serv.s_aliases[n++] = p; + p += strcspn(p, spaces); + if (!*p) + break; + *p++ = '\0'; + p += strspn(p, spaces); + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[n] = NULL; + return (&pvt->serv); + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/contrib/bind/lib/irs/nul_ng.c b/contrib/bind/lib/irs/nul_ng.c new file mode 100644 index 0000000..0910d57 --- /dev/null +++ b/contrib/bind/lib/irs/nul_ng.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nul_ng.c,v 1.7 1997/12/04 04:58:01 halley Exp $"; +#endif + +/* + * nul_ng.c - the netgroup accessor null map + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Forward. */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, char **, char **, char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public. */ + +struct irs_ng * +irs_nul_ng(struct irs_acc *this) { + struct irs_ng *ng; + + if (!(ng = malloc(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + ng->private = NULL; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods. */ + +static void +ng_close(struct irs_ng *this) { + free(this); +} + +/* ARGSUSED */ +static int +ng_next(struct irs_ng *this, char **host, char **user, char **domain) { + errno = ENOENT; + return (-1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + errno = ENODEV; + return (-1); +} + +static void +ng_rewind(struct irs_ng *this, const char *netgroup) { + /* NOOP */ +} + +static void +ng_minimize(struct irs_ng *this) { + /* NOOP */ +} diff --git a/contrib/bind/lib/irs/pathnames.h b/contrib/bind/lib/irs/pathnames.h new file mode 100644 index 0000000..40a0472 --- /dev/null +++ b/contrib/bind/lib/irs/pathnames.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: pathnames.h,v 1.5 1996/10/25 07:23:28 vixie Exp $ + */ + +#ifndef _PATH_IRS_CONF +#define _PATH_IRS_CONF "/etc/irs.conf" +#endif + +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif + +#ifndef _PATH_GROUP +#define _PATH_GROUP "/etc/group" +#endif + +#ifndef _PATH_NETGROUP +#define _PATH_NETGROUP "/etc/netgroup" +#endif + +#ifndef _PATH_SERVICES +#define _PATH_SERVICES "/etc/services" +#endif + +#ifndef _PATH_HESIOD_CONF +#define _PATH_HESIOD_CONF "/etc/hesiod.conf" +#endif diff --git a/contrib/bind/lib/irs/util.c b/contrib/bind/lib/irs/util.c new file mode 100644 index 0000000..f58f5ca2 --- /dev/null +++ b/contrib/bind/lib/irs/util.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: util.c,v 1.7 1997/12/04 04:58:02 halley Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +void +map_v4v6_address(const char *src, char *dst) { + u_char *p = (u_char *)dst; + char tmp[INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + memcpy(tmp, src, INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + memcpy((void*)p, tmp, INADDRSZ); +} + +int +make_group_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct group *grp; + int i, ng; + int ret, maxgroups; + + ret = -1; + ng = 0; + maxgroups = *ngroups; + /* + * When installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + /* + * Scan the group file to find additional groups. + */ + (*this->rewind)(this); + while ((grp = (*this->next)(this)) != NULL) { + if (grp->gr_gid == basegid) + continue; + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], name)) { + if (ng >= maxgroups) + goto done; + groups[ng++] = grp->gr_gid; + break; + } + } + } + ret = 0; + done: + *ngroups = ng; + return (ret); +} diff --git a/contrib/bind/lib/isc/Makefile b/contrib/bind/lib/isc/Makefile new file mode 100644 index 0000000..cdcac69 --- /dev/null +++ b/contrib/bind/lib/isc/Makefile @@ -0,0 +1,77 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# $Id: Makefile,v 8.15 1997/12/03 22:36:08 halley Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cruv +RANLIB= ranlib +INSTALL= install + +SRCS= tree.c base64.c bitncmp.c assertions.c \ + memcluster.c logging.c heap.c \ + eventlib.c ev_connects.c ev_files.c \ + ev_timers.c ev_streams.c ev_waits.c + +OBJS= tree.${O} base64.${O} bitncmp.${O} assertions.${O} \ + memcluster.${O} logging.${O} heap.${O} \ + eventlib.${O} ev_connects.${O} ev_files.${O} \ + ev_timers.${O} ev_streams.${O} ev_waits.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/lib/isc/assertions.c b/contrib/bind/lib/isc/assertions.c new file mode 100644 index 0000000..949d4d2 --- /dev/null +++ b/contrib/bind/lib/isc/assertions.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: assertions.c,v 8.2 1997/12/08 21:29:05 halley Exp $"; +#endif + +#include "port_before.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/assertions.h> + +#include "port_after.h" + +/* + * Forward. + */ + +static void default_assertion_failed(char *, int, assertion_type, char *, int); + +/* + * Public. + */ + +assertion_failure_callback __assertion_failed = default_assertion_failed; + +void +set_assertion_failure_callback(assertion_failure_callback f) { + if (f == NULL) + __assertion_failed = default_assertion_failed; + else + __assertion_failed = f; +} + +char * +assertion_type_to_text(assertion_type type) { + char *result; + + switch (type) { + case assert_require: + result = "REQUIRE"; + break; + case assert_ensure: + result = "ENSURE"; + break; + case assert_insist: + result = "INSIST"; + break; + case assert_invariant: + result = "INVARIANT"; + break; + default: + result = NULL; + } + return (result); +} + +/* + * Private. + */ + +static void +default_assertion_failed(char *file, int line, assertion_type type, char *cond, + int print_errno) +{ + fprintf(stderr, "%s:%d: %s(%s)%s%s failed.\n", + file, line, assertion_type_to_text(type), cond, + (print_errno) ? ": " : "", + (print_errno) ? strerror(errno) : ""); + abort(); + /* NOTREACHED */ +} diff --git a/contrib/bind/lib/isc/assertions.mdoc b/contrib/bind/lib/isc/assertions.mdoc new file mode 100644 index 0000000..e82d9f9 --- /dev/null +++ b/contrib/bind/lib/isc/assertions.mdoc @@ -0,0 +1,134 @@ +.\" $Id: assertions.mdoc,v 8.1 1997/12/03 22:33:30 halley Exp $ +.\" +.\"Copyright (c) 1997 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. +.\" +.Dd November 17, 1997 +.Dt ASSERTIONS 3 +.Os ISC +.Sh NAME +.Nm REQUIRE , +.Nm REQUIRE_ERR , +.Nm ENSURE , +.Nm ENSURE_ERR , +.Nm INSIST , +.Nm INSIST_ERR , +.Nm INVARIANT , +.Nm INVARIANT_ERR , +.Nm set_assertion_failure_callback +.Nd assertion system +.Sh SYNOPSIS +.Fd #include <isc/assertions.h> +.Fo "typedef void (*assertion_failure_callback)" +.Fa "char *filename" +.Fa "int line" +.Fa "assertion_type type" +.Fa "char *condition" +.Fa "int print_errno" +.Fc +.Fn REQUIRE "int boolean_expression" +.Fn REQUIRE_ERR "int boolean_expression" +.Fn ENSURE "int boolean_expression" +.Fn ENSURE_ERR "int boolean_expression" +.Fn INSIST "int boolean_expression" +.Fn INSIST_ERR "int boolean_expression" +.Fn INVARIANT "int boolean_expression" +.Fn INVARIANT_ERR "int boolean_expression" +.Ft void +.Fn set_assertion_failure_callback "assertion_failure_callback callback" +.Ft char * +.Fn assertion_type_to_text "assertion_type type" +.Sh DESCRIPTION +The +.Fn REQUIRE , +.Fn ENSURE , +.Fn INSIST , +and +.Fn INVARIANT +macros evaluate a boolean expression, and if it is false, they invoke the +current assertion failure callback. The default callback will print a message +to +.Li stderr +describing the failure, and then cause the program to dump core. +If the +.Dq Fn _ERR +variant of the assertion is used, the callback will include +.Fn strerror "errno" +in its message. +.Pp +Each assertion type has an associated +.Li CHECK +macro. If this macro's value is +.Dq 0 +when +.Dq "<isc/assertions.h>" +is included, then assertions of that type will not be checked. E.g. + +.Dl #define CHECK_ENSURE 0 + +will disable checking of +.Fn ENSURE +and +.Fn ENSURE_ERR . +The macros +.Li CHECK_ALL +and +.Li CHECK_NONE +may also be used, respectively specifying that either all or none of the +assertion types should be checked. +.Pp +.Fn set_assertion_failure_callback +specifies the function to call when an assertion fails. +.Pp +When an +.li +assertion_failure_callback +is called, the +.Fa filename +and +.Fa line +arguments specify the filename and line number of the failing assertion. +The +.Fa type +is one of: +.Bd -literal -offset indent +assert_require +assert_ensure +assert_insist +assert_invariant +.Ed + +and may be used by the callback to determine the type of the failing +assertion. +.Fa condition +is the literal text of the assertion that failed. +.Fa print_errno +will be non-zero if the callback should print +.Fa strerror "errno" +as part of its output. +.Pp +.Fn assertion_type_to_text +returns a textual representation of +.Fa type . +For example, +.Fn assertion_type_to_text "assert_require" +returns the string +.Dq REQUIRE . +.Sh SEE ALSO +Bertrand Meyer, +.Sy Object-Oriented Software Construction, +2nd edition, Prentice\-Hall, 1997, ISBN 0\-13\-629155\-4, chapter 11. +.Sh AUTHOR +Bob Halley (ISC). diff --git a/contrib/bind/lib/isc/base64.c b/contrib/bind/lib/isc/base64.c new file mode 100644 index 0000000..58e700e --- /dev/null +++ b/contrib/bind/lib/isc/base64.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: base64.c,v 8.5 1998/03/27 00:17:46 halley Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#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 <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/contrib/bind/lib/isc/bitncmp.c b/contrib/bind/lib/isc/bitncmp.c new file mode 100644 index 0000000..473f4f7 --- /dev/null +++ b/contrib/bind/lib/isc/bitncmp.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: bitncmp.c,v 1.5 1996/11/18 09:09:48 vixie Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> + +#include <string.h> + +#include "port_after.h" + +#include <isc/misc.h> + +/* + * int + * bitncmp(l, r, n) + * compare bit masks l and r, for n bits. + * return: + * -1, 1, or 0 in the libc tradition. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +bitncmp(const void *l, const void *r, int n) { + u_int lb, rb; + int x, b; + + b = n / 8; + x = memcmp(l, r, b); + if (x) + return (x); + + lb = ((u_char *)l)[b]; + rb = ((u_char *)r)[b]; + for (b = n % 8; b > 0; b--) { + if ((lb & 0x80) != (rb & 0x80)) { + if (lb & 0x80) + return (1); + return (-1); + } + lb <<= 1; + rb <<= 1; + } + return (0); +} diff --git a/contrib/bind/lib/isc/bitncmp.mdoc b/contrib/bind/lib/isc/bitncmp.mdoc new file mode 100644 index 0000000..99c6c25 --- /dev/null +++ b/contrib/bind/lib/isc/bitncmp.mdoc @@ -0,0 +1,82 @@ +.\" $Id: bitncmp.mdoc,v 8.1 1997/01/30 20:27:23 vixie Exp $ +.\" +.\"Copyright (c) 1996 by Internet Software Consortium. +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd June 1, 1996 +.Dt BITNCMP 3 +.Os BSD 4 +.Sh NAME +.Nm bitncmp +.Nd compare bit masks +.Sh SYNOPSIS +.Ft int +.Fn bitncmp "const void *l" "const void *r" "int n" +.Sh DESCRIPTION +The function +.Fn bitncmp +compares the +.Dq Fa n +most-significant bits of the two masks pointed to by +.Dq Fa l +and +.Dq Fa r , +and returns an integer less than, equal to, or greater than 0, according to +whether or not +.Dq Fa l +is lexicographically less than, equal to, or greater than +.Dq Fa r +when taken to be unsigned characters (this behaviour is just like that of +.Xr memcmp 3 ) . +.Pp +.Sy NOTE: +.Fn Bitncmp +assumes +.Sy network byte order ; +this means that the fourth octet of +.Li 192.5.5.240/28 +.Li 0x11110000 . +.Sh RETURN VALUES +.Fn Bitncmp +returns values in the manner of +.Xr memcmp 3 : +.Bd -filled -offset indent ++1 if +.Dq Fa 1 +is greater than +.Dq Fa r ; +.Pp +-1 if +.Dq Fa l +is less than +.Dq Fa r ; +and +.Pp +0 if +.Dq Fa l +is equal to +.Dq Fa r , +.Ed +.Pp +where +.Dq Fa l +and +.Dq Fa r +are both interpreted as strings of unsigned characters (through bit +.Dq Fa n .) +.Sh SEE ALSO +.Xr memcmp 3 . +.Sh AUTHOR +Paul Vixie (ISC). diff --git a/contrib/bind/lib/isc/ev_connects.c b/contrib/bind/lib/isc/ev_connects.c new file mode 100644 index 0000000..1cf7291 --- /dev/null +++ b/contrib/bind/lib/isc/ev_connects.c @@ -0,0 +1,316 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_connects.c - implement asynch connect/accept for the eventlib + * vix 16sep96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_connects.c,v 8.19 1998/03/20 23:26:22 halley Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void listener(evContext ctx, void *uap, int fd, int evmask); +static void connector(evContext ctx, void *uap, int fd, int evmask); + +/* Public. */ + +int +evListen(evContext opaqueCtx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + int mode; + + OKNEW(new); + new->flags = EV_CONN_LISTEN; + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + /* + * Remember the nonblocking status. We assume that either evSelectFD + * has not been done to this fd, or that if it has then the caller + * will evCancelConn before they evDeselectFD. If our assumptions + * are not met, then we might restore the old nonblocking status + * incorrectly. + */ + if ((mode & O_NONBLOCK) == 0) { + OK(fcntl(fd, F_SETFL, mode | O_NONBLOCK)); + new->flags |= EV_CONN_BLOCK; + } + OK(listen(fd, maxconn)); + if (evSelectFD(opaqueCtx, fd, EV_READ, listener, new, &new->file) < 0){ + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evConnect(evContext opaqueCtx, int fd, void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + + OKNEW(new); + new->flags = 0; + /* Do the select() first to get the socket into nonblocking mode. */ + if (evSelectFD(opaqueCtx, fd, EV_MASK_ALL, + connector, new, &new->file) < 0) { + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + if (connect(fd, ra, ralen) < 0 && + errno != EWOULDBLOCK && + errno != EAGAIN && + errno != EINPROGRESS) { + int save = errno; + + (void) evDeselectFD(opaqueCtx, new->file); + FREE(new); + errno = save; + return (-1); + } + /* No error, or EWOULDBLOCK. select() tells when it's ready. */ + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evCancelConn(evContext opaqueCtx, evConnID id) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *this = id.opaque; + evAccept *acc, *nxtacc; + int mode; + + if ((this->flags & EV_CONN_SELECTED) != 0) + (void) evDeselectFD(opaqueCtx, this->file); + if ((this->flags & EV_CONN_BLOCK) != 0) { + mode = fcntl(this->fd, F_GETFL, NULL); + if (mode == -1) { + if (errno != EBADF) + return (-1); + } else + OK(fcntl(this->fd, F_SETFL, mode | O_NONBLOCK)); + } + + /* Unlink from ctx->conns. */ + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->conns = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + + /* + * Remove `this' from the ctx->accepts list (zero or more times). + */ + for (acc = HEAD(ctx->accepts), nxtacc = NULL; + acc != NULL; + acc = nxtacc) + { + nxtacc = NEXT(acc, link); + if (acc->conn == this) { + UNLINK(ctx->accepts, acc, link); + close(acc->fd); + FREE(acc); + } + } + + /* Wrap up and get out. */ + FREE(this); + return (0); +} + +int evHold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) == 0) + return (0); + this->flags &= ~EV_CONN_SELECTED; + return (evDeselectFD(opaqueCtx, this->file)); +} + +int evUnhold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + int ret; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) != 0) + return (0); + ret = evSelectFD(opaqueCtx, this->fd, EV_READ, listener, this, + &this->file); + if (ret == 0) + this->flags |= EV_CONN_SELECTED; + return (ret); +} + +int +evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = id.opaque; + evAccept *new; + + if ((conn->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + OKNEW(new); + new->conn = conn; + new->ralen = sizeof new->ra; + new->fd = accept(conn->fd, &new->ra, &new->ralen); + if (new->fd >= 0) { + new->lalen = sizeof new->la; + if (getsockname(new->fd, &new->la, &new->lalen) < 0) { + new->ioErrno = errno; + (void) close(new->fd); + new->fd = -1; + } else + new->ioErrno = 0; + } else { + new->ioErrno = errno; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + FREE(new); + return (-1); + } + } + APPEND(ctx->accepts, new, link); + *sys_errno = new->ioErrno; + return (0); +} + +/* Private. */ + +static void +listener(evContext opaqueCtx, void *uap, int fd, int evmask) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = uap; + struct sockaddr la, ra; + int new, lalen, ralen; + + REQUIRE((evmask & EV_READ) != 0); + ralen = sizeof ra; + new = accept(fd, &ra, &ralen); + if (new >= 0) { + lalen = sizeof la; + if (getsockname(new, &la, &lalen) < 0) { + int save = errno; + + (void) close(new); + errno = save; + new = -1; + } + } else if (errno == EAGAIN || errno == EWOULDBLOCK) + return; + (*conn->func)(opaqueCtx, conn->uap, new, &la, lalen, &ra, ralen); +} + +static void +connector(evContext opaqueCtx, void *uap, int fd, int evmask) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = uap; + struct sockaddr la, ra; + int lalen, ralen; + char buf[1]; + void *conn_uap; + evConnFunc conn_func; + evConnID id; + int socket_errno = 0; + int optlen; + + lalen = sizeof la; + ralen = sizeof ra; + conn_uap = conn->uap; + conn_func = conn->func; + id.opaque = conn; +#ifdef SO_ERROR + optlen = sizeof socket_errno; + if (fd < 0 && + getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *)&socket_errno, + &optlen) < 0) + socket_errno = errno; + else + errno = socket_errno; +#endif + if (evCancelConn(opaqueCtx, id) < 0 || + socket_errno || +#ifdef NETREAD_BROKEN + 0 || +#else + read(fd, buf, 0) < 0 || +#endif + getsockname(fd, &la, &lalen) < 0 || + getpeername(fd, &ra, &ralen) < 0) { + int save = errno; + + (void) close(fd); /* XXX closing caller's fd */ + errno = save; + fd = -1; + } + (*conn_func)(opaqueCtx, conn_uap, fd, &la, lalen, &ra, ralen); +} diff --git a/contrib/bind/lib/isc/ev_files.c b/contrib/bind/lib/isc/ev_files.c new file mode 100644 index 0000000..6cd1d41 --- /dev/null +++ b/contrib/bind/lib/isc/ev_files.c @@ -0,0 +1,271 @@ +/* Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_files.c - implement asynch file IO for the eventlib + * vix 11sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_files.c,v 1.15 1998/02/06 01:53:52 halley Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/time.h> + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include "eventlib_p.h" + +#include "port_after.h" + +static evFile *FindFD(const evContext_p *ctx, int fd, int eventmask); + +int +evSelectFD(evContext opaqueCtx, + int fd, + int eventmask, + evFileFunc func, + void *uap, + evFileID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *id; + int mode; + + evPrintf(ctx, 1, + "evSelectFD(ctx %#x, fd %d, mask 0x%x, func %#x, uap %#x)\n", + ctx, fd, eventmask, func, uap); + if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0) + ERR(EINVAL); + if (fd >= FD_SETSIZE) + ERR(EINVAL); + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + + /* + * The first time we touch a file descriptor, we need to check to see + * if the application already had it in O_NONBLOCK mode and if so, all + * of our deselect()'s have to leave it in O_NONBLOCK. If not, then + * all but our last deselect() has to leave it in O_NONBLOCK. + */ + id = FindFD(ctx, fd, EV_MASK_ALL); + if (id == NULL) { + if (mode & O_NONBLOCK) + FD_SET(fd, &ctx->nonblockBefore); + else { + OK(fcntl(fd, F_SETFL, mode | O_NONBLOCK)); + FD_CLR(fd, &ctx->nonblockBefore); + } + } + + /* + * If this descriptor is already in use, search for it again to see + * if any of the eventmask bits we want to set are already captured. + * We cannot usefully capture the same fd event more than once in the + * same context. + */ + if (id != NULL && FindFD(ctx, fd, eventmask) != NULL) + ERR(ETOOMANYREFS); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->fd = fd; + id->eventmask = eventmask; + + /* + * Insert at head. Order could be important for performance if we + * believe that evGetNext()'s accesses to the fd_sets will be more + * serial and therefore more cache-lucky if the list is ordered by + * ``fd.'' We do not believe these things, so we don't do it. + * + * The interesting sequence is where GetNext() has cached a select() + * result and the caller decides to evSelectFD() on some descriptor. + * Since GetNext() starts at the head, it can miss new entries we add + * at the head. This is not a serious problem since the event being + * evSelectFD()'d for has to occur before evSelectFD() is called for + * the file event to be considered "missed" -- a real corner case. + * Maintaining a "tail" pointer for ctx->files would fix this, but I'm + * not sure it would be ``more correct.'' + */ + if (ctx->files != NULL) + ctx->files->prev = id; + id->prev = NULL; + id->next = ctx->files; + ctx->files = id; + + /* Insert into fd table. */ + if (ctx->fdTable[fd] != NULL) + ctx->fdTable[fd]->fdprev = id; + id->fdprev = NULL; + id->fdnext = ctx->fdTable[fd]; + ctx->fdTable[fd] = id; + + /* Turn on the appropriate bits in the {rd,wr,ex}Next fd_set's. */ + if (eventmask & EV_READ) + FD_SET(fd, &ctx->rdNext); + if (eventmask & EV_WRITE) + FD_SET(fd, &ctx->wrNext); + if (eventmask & EV_EXCEPT) + FD_SET(fd, &ctx->exNext); + + /* Update fdMax. */ + if (fd > ctx->fdMax) + ctx->fdMax = fd; + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + evPrintf(ctx, 5, + "evSelectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); + + return (0); +} + +int +evDeselectFD(evContext opaqueCtx, evFileID opaqueID) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *del = opaqueID.opaque; + evFile *old, *cur; + int mode, eventmask; + + if (!del) { + evPrintf(ctx, 11, "evDeselectFD(NULL) ignored\n"); + errno = EINVAL; + return (-1); + } + + evPrintf(ctx, 1, "evDeselectFD(fd %d, mask 0x%x)\n", + del->fd, del->eventmask); + + /* Get the mode. Unless the file has been closed, errors are bad. */ + mode = fcntl(del->fd, F_GETFL, NULL); + if (mode == -1 && errno != EBADF) + ERR(errno); + + /* Remove from the list of files. */ + if (del->prev != NULL) + del->prev->next = del->next; + else + ctx->files = del->next; + if (del->next != NULL) + del->next->prev = del->prev; + + /* Remove from the fd table. */ + if (del->fdprev != NULL) + del->fdprev->fdnext = del->fdnext; + else + ctx->fdTable[del->fd] = del->fdnext; + if (del->fdnext != NULL) + del->fdnext->fdprev = del->fdprev; + + /* + * If the file descriptor does not appear in any other select() entry, + * and if !EV_WASNONBLOCK, and if we got no EBADF when we got the mode + * earlier, then: restore the fd to blocking status. + */ + if (!(cur = FindFD(ctx, del->fd, EV_MASK_ALL)) && + !FD_ISSET(del->fd, &ctx->nonblockBefore) && + mode != -1) { + /* + * Note that we won't return an error status to the caller if + * this fcntl() fails since (a) we've already done the work + * and (b) the caller didn't ask us anything about O_NONBLOCK. + */ + (void) fcntl(del->fd, F_SETFL, mode & ~O_NONBLOCK); + } + + /* + * Now find all other uses of this descriptor and OR together an event + * mask so that we don't turn off {rd,wr,ex}Next bits that some other + * file event is using. As an optimization, stop if the event mask + * fills. + */ + eventmask = 0; + for ((void)NULL; + cur != NULL && eventmask != EV_MASK_ALL; + cur = cur->next) + if (cur->fd == del->fd) + eventmask |= cur->eventmask; + + /* OK, now we know which bits we can clear out. */ + if (!(eventmask & EV_READ)) { + FD_CLR(del->fd, &ctx->rdNext); + if (FD_ISSET(del->fd, &ctx->rdLast)) { + FD_CLR(del->fd, &ctx->rdLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_WRITE)) { + FD_CLR(del->fd, &ctx->wrNext); + if (FD_ISSET(del->fd, &ctx->wrLast)) { + FD_CLR(del->fd, &ctx->wrLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_EXCEPT)) { + FD_CLR(del->fd, &ctx->exNext); + if (FD_ISSET(del->fd, &ctx->exLast)) { + FD_CLR(del->fd, &ctx->exLast); + ctx->fdCount--; + } + } + + /* If this was the maxFD, find the new one. */ + if (del->fd == ctx->fdMax) { + ctx->fdMax = -1; + for (cur = ctx->files; cur; cur = cur->next) + if (cur->fd > ctx->fdMax) + ctx->fdMax = cur->fd; + } + + /* If this was the fdNext, cycle that to the next entry. */ + if (del == ctx->fdNext) + ctx->fdNext = del->next; + + evPrintf(ctx, 5, + "evDeselectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + del->fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); + + /* Couldn't free it before now since we were using fields out of it. */ + FREE(del); + + return (0); +} + +static evFile * +FindFD(const evContext_p *ctx, int fd, int eventmask) { + evFile *id; + + for (id = ctx->fdTable[fd]; id != NULL; id = id->fdnext) + if (id->fd == fd && (id->eventmask & eventmask) != 0) + break; + return (id); +} diff --git a/contrib/bind/lib/isc/ev_streams.c b/contrib/bind/lib/isc/ev_streams.c new file mode 100644 index 0000000..aa4270b --- /dev/null +++ b/contrib/bind/lib/isc/ev_streams.c @@ -0,0 +1,301 @@ +/* Copyright (c) 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_streams.c - implement asynch stream file IO for the eventlib + * vix 04mar96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_streams.c,v 8.18 1998/03/20 23:26:22 halley Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/uio.h> + +#include <errno.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +static int copyvec(evStream *str, const struct iovec *iov, int iocnt); +static void consume(evStream *str, size_t bytes); +static void done(evContext opaqueCtx, evStream *str); +static void writable(evContext opaqueCtx, void *uap, int fd, int evmask); +static void readable(evContext opaqueCtx, void *uap, int fd, int evmask); + +struct iovec +evConsIovec(void *buf, size_t cnt) { + struct iovec ret; + + memset(&ret, 0xf5, sizeof ret); + ret.iov_base = buf; + ret.iov_len = cnt; + return (ret); +} + +int +evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id != NULL) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + err: + return (-1); +} + +int +evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + err: + return (-1); +} + +int +evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ { + evContext_p *ctx = opaqueCtx.opaque; + evStream *str = id.opaque; + + str->timer = timer; + str->flags |= EV_STR_TIMEROK; + return (0); +} + +int +evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ { + evContext_p *ctx = opaqueCtx.opaque; + evStream *str = id.opaque; + + str->flags &= ~EV_STR_TIMEROK; + return (0); +} + +int +evCancelRW(evContext opaqueCtx, evStreamID id) { + evContext_p *ctx = opaqueCtx.opaque; + evStream *old = id.opaque; + + /* + * The streams list is doubly threaded. First, there's ctx->streams + * that's used by evDestroy() to find and cancel all streams. Second, + * there's ctx->strDone (head) and ctx->strLast (tail) which thread + * through the potentially smaller number of "IO completed" streams, + * used in evGetNext() to avoid scanning the entire list. + */ + + /* Unlink from ctx->streams. */ + if (old->prev != NULL) + old->prev->next = old->next; + else + ctx->streams = old->next; + if (old->next != NULL) + old->next->prev = old->prev; + + /* + * If 'old' is on the ctx->strDone list, remove it. Update + * ctx->strLast if necessary. + */ + if (old->prevDone == NULL && old->nextDone == NULL) { + /* + * Either 'old' is the only item on the done list, or it's + * not on the done list. If the former, then we unlink it + * from the list. If the latter, we leave the list alone. + */ + if (ctx->strDone == old) { + ctx->strDone = NULL; + ctx->strLast = NULL; + } + } else { + if (old->prevDone != NULL) + old->prevDone->nextDone = old->nextDone; + else + ctx->strDone = old->nextDone; + if (old->nextDone != NULL) + old->nextDone->prevDone = old->prevDone; + else + ctx->strLast = old->prevDone; + } + + /* Deallocate the stream. */ + if (old->file.opaque) + evDeselectFD(opaqueCtx, old->file); + memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount); + FREE(old); + return (0); +} + +/* Copy a scatter/gather vector and initialize a stream handler's IO. */ +static int +copyvec(evStream *str, const struct iovec *iov, int iocnt) { + int i; + + str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt); + if (str->iovOrig == NULL) { + errno = ENOMEM; + return (-1); + } + str->ioTotal = 0; + for (i = 0; i < iocnt; i++) { + str->iovOrig[i] = iov[i]; + str->ioTotal += iov[i].iov_len; + } + str->iovOrigCount = iocnt; + str->iovCur = str->iovOrig; + str->iovCurCount = str->iovOrigCount; + str->ioDone = 0; + return (0); +} + +/* Pull off or truncate lead iovec(s). */ +static void +consume(evStream *str, size_t bytes) { + while (bytes > 0) { + if (bytes < str->iovCur->iov_len) { + str->iovCur->iov_len -= bytes; + str->iovCur->iov_base = (void *) + ((u_char *)str->iovCur->iov_base + bytes); + str->ioDone += bytes; + bytes = 0; + } else { + bytes -= str->iovCur->iov_len; + str->ioDone += str->iovCur->iov_len; + str->iovCur++; + str->iovCurCount--; + } + } +} + +/* Add a stream to Done list and deselect the FD. */ +static void +done(evContext opaqueCtx, evStream *str) { + evContext_p *ctx = opaqueCtx.opaque; + + if (ctx->strLast != NULL) { + str->prevDone = ctx->strLast; + ctx->strLast->nextDone = str; + ctx->strLast = str; + } else { + INSIST(ctx->strDone == NULL); + ctx->strDone = ctx->strLast = str; + } + evDeselectFD(opaqueCtx, str->file); + str->file.opaque = NULL; + /* evDrop() will call evCancelRW() on us. */ +} + +/* Dribble out some bytes on the stream. (Called by evDispatch().) */ +static void +writable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + bytes = writev(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes < 0 && errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + if (str->ioDone == -1 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} + +/* Scoop up some bytes from the stream. (Called by evDispatch().) */ +static void +readable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + bytes = readv(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes == 0) + str->ioDone = 0; + else { + if (errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + } + if (str->ioDone <= 0 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} diff --git a/contrib/bind/lib/isc/ev_timers.c b/contrib/bind/lib/isc/ev_timers.c new file mode 100644 index 0000000..198f27c --- /dev/null +++ b/contrib/bind/lib/isc/ev_timers.c @@ -0,0 +1,406 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_timers.c - implement timers for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_timers.c,v 1.23 1998/03/20 23:26:23 halley Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <errno.h> + +#include <isc/eventlib.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Constants. */ + +#define BILLION 1000000000 + +/* Forward. */ + +static int due_sooner(void *, void *); +static void set_index(void *, int); +static void free_timer(void *, void *); +static void print_timer(void *, void *); +static void idle_timeout(evContext, void *, struct timespec, struct timespec); + +/* Private type. */ + +typedef struct { + evTimerFunc func; + void * uap; + struct timespec lastTouched; + struct timespec max_idle; + evTimer * timer; +} idle_timer; + +/* Public. */ + +struct timespec +evConsTime(time_t sec, long nsec) { + struct timespec x; + + x.tv_sec = sec; + x.tv_nsec = nsec; + return (x); +} + +struct timespec +evAddTime(struct timespec addend1, struct timespec addend2) { + struct timespec x; + + x.tv_sec = addend1.tv_sec + addend2.tv_sec; + x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec; + if (x.tv_nsec >= BILLION) { + x.tv_sec++; + x.tv_nsec -= BILLION; + } + return (x); +} + +struct timespec +evSubTime(struct timespec minuend, struct timespec subtrahend) { + struct timespec x; + + x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; + if (minuend.tv_nsec >= subtrahend.tv_nsec) + x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec; + else { + x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec; + x.tv_sec--; + } + return (x); +} + +int +evCmpTime(struct timespec a, struct timespec b) { + long x = a.tv_sec - b.tv_sec; + + if (x == 0L) + x = a.tv_nsec - b.tv_nsec; + return (x < 0L ? (-1) : x > 0L ? (1) : (0)); +} + +struct timespec +evNowTime() { + struct timeval now; + struct timespec ret; + + if (gettimeofday(&now, NULL) < 0) + return (evConsTime(0, 0)); + return (evTimeSpec(now)); +} + +struct timespec +evLastEventTime(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->lastEventTime); +} + +struct timespec +evTimeSpec(struct timeval tv) { + struct timespec ts; + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return (ts); +} + +struct timeval +evTimeVal(struct timespec ts) { + struct timeval tv; + + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return (tv); +} + +int +evSetTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *id; + + evPrintf(ctx, 1, +"evSetTimer(ctx %#x, func %#x, uap %#x, due %d.%09ld, inter %d.%09ld)\n", + ctx, func, uap, + due.tv_sec, due.tv_nsec, + inter.tv_sec, inter.tv_nsec); + + /* due={0,0} is a magic cookie meaning "now." */ + if (due.tv_sec == 0 && due.tv_nsec == 0L) + due = evNowTime(); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->due = due; + id->inter = inter; + + if (heap_insert(ctx->timers, id) < 0) + return (-1); + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evSetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evClearTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *del = id.opaque; + + if (ctx->cur != NULL && + ctx->cur->type == Timer && + ctx->cur->u.timer.this == del) { + evPrintf(ctx, 8, "deferring delete of timer (executing)\n"); + /* + * Setting the interval to zero ensures that evDrop() will + * clean up the timer. + */ + del->inter = evConsTime(0, 0); + return (0); + } + + if (heap_element(ctx->timers, del->index) != del) + ERR(ENOENT); + + if (heap_delete(ctx->timers, del->index) < 0) + return (-1); + FREE(del); + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evClearTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evResetTimer(evContext opaqueCtx, + evTimerID id, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = id.opaque; + struct timespec old_due; + int result=0; + + if (heap_element(ctx->timers, timer->index) != timer) + ERR(ENOENT); + + old_due = timer->due; + + timer->func = func; + timer->uap = uap; + timer->due = due; + timer->inter = inter; + + switch (evCmpTime(due, old_due)) { + case -1: + result = heap_increased(ctx->timers, timer->index); + break; + case 0: + result = 0; + break; + case 1: + result = heap_decreased(ctx->timers, timer->index); + break; + } + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evResetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (result); +} + +int +evSetIdleTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec max_idle, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *tt; + + /* Allocate and fill. */ + OKNEW(tt); + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + if (evSetTimer(opaqueCtx, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle, opaqueID) < 0) { + FREE(tt); + return (-1); + } + + tt->timer = opaqueID->opaque; + + return (0); +} + +int +evClearIdleTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *del = id.opaque; + idle_timer *tt = del->uap; + + FREE(tt); + return (evClearTimer(opaqueCtx, id)); +} + +int +evResetIdleTimer(evContext opaqueCtx, + evTimerID opaqueID, + evTimerFunc func, + void *uap, + struct timespec max_idle +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = opaqueID.opaque; + idle_timer *tt = timer->uap; + + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle)); +} + +int +evTouchIdleTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *t = id.opaque; + idle_timer *tt = t->uap; + + tt->lastTouched = ctx->lastEventTime; + + return (0); +} + +/* Public to the rest of eventlib. */ + +heap_context +evCreateTimers(const evContext_p *ctx) { + return (heap_new(due_sooner, set_index, 2048)); +} + +void +evDestroyTimers(const evContext_p *ctx) { + (void) heap_for_each(ctx->timers, free_timer, NULL); + (void) heap_free(ctx->timers); +} + +/* Private. */ + +static int +due_sooner(void *a, void *b) { + evTimer *a_timer, *b_timer; + + a_timer = a; + b_timer = b; + return (evCmpTime(a_timer->due, b_timer->due) < 0); +} + +static void +set_index(void *what, int index) { + evTimer *timer; + + timer = what; + timer->index = index; +} + +static void +free_timer(void *what, void *uap) { + evTimer *t = what; + FREE(t); +} + +static void +print_timer(void *what, void *uap) { + evTimer *cur = what; + evContext_p *ctx = uap; + + cur = what; + evPrintf(ctx, 7, + " func %p, uap %p, due %d.%09ld, inter %d.%09ld\n", + cur->func, cur->uap, + cur->due.tv_sec, cur->due.tv_nsec, + cur->inter.tv_sec, cur->inter.tv_nsec); +} + +static void +idle_timeout(evContext opaqueCtx, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *this = uap; + struct timespec idle; + + idle = evSubTime(ctx->lastEventTime, this->lastTouched); + if (evCmpTime(idle, this->max_idle) >= 0) { + (this->func)(opaqueCtx, this->uap, this->timer->due, + this->max_idle); + /* + * Setting the interval to zero will cause the timer to + * be cleaned up in evDrop(). + */ + this->timer->inter = evConsTime(0, 0); + FREE(this); + } else { + /* evDrop() will reschedule the timer. */ + this->timer->inter = evSubTime(this->max_idle, idle); + } +} diff --git a/contrib/bind/lib/isc/ev_waits.c b/contrib/bind/lib/isc/ev_waits.c new file mode 100644 index 0000000..a45adf1 --- /dev/null +++ b/contrib/bind/lib/isc/ev_waits.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* ev_waits.c - implement deferred function calls for the eventlib + * vix 05dec95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_waits.c,v 8.6 1998/03/20 23:26:23 halley Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <errno.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void print_waits(evContext_p *ctx); +static evWaitList * evNewWaitList(evContext_p *); +static void evFreeWaitList(evContext_p *, evWaitList *); +static evWaitList * evGetWaitList(evContext_p *, const void *, int); + + +/* Public. */ + +/* + * Enter a new wait function on the queue. + */ +int +evWaitFor(evContext opaqueCtx, const void *tag, + evWaitFunc func, void *uap, evWaitID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + evWaitList *wl = evGetWaitList(ctx, tag, 1); + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = tag; + new->next = NULL; + if (wl->last != NULL) { + wl->last->next = new; + } else { + wl->first = new; + } + wl->last = new; + if (id != NULL) + id->opaque = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* + * Mark runnable all waiting functions having a certain tag. + */ +int +evDo(evContext opaqueCtx, const void *tag) { + evContext_p *ctx = opaqueCtx.opaque; + evWaitList *wl = evGetWaitList(ctx, tag, 0); + evWait *first; + + if (!wl) { + errno = ENOENT; + return (-1); + } + + first = wl->first; + INSIST(first != NULL); + + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = first; + else + ctx->waitDone.first = first; + ctx->waitDone.last = wl->last; + evFreeWaitList(ctx, wl); + + return (0); +} + +/* + * Remove a waiting (or ready to run) function from the queue. + */ +int +evUnwait(evContext opaqueCtx, evWaitID id) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *this, *prev; + evWaitList *wl; + int found = 0; + + this = id.opaque; + INSIST(this != NULL); + wl = evGetWaitList(ctx, this->tag, 0); + if (wl != NULL) { + for (prev = NULL, this = wl->first; + this != NULL; + prev = this, this = this->next) + if (this == id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + wl->first = this->next; + if (wl->last == this) + wl->last = prev; + if (wl->first == NULL) + evFreeWaitList(ctx, wl); + break; + } + } + + if (!found) { + /* Maybe it's done */ + for (prev = NULL, this = ctx->waitDone.first; + this != NULL; + prev = this, this = this->next) + if (this == id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + ctx->waitDone.first = this->next; + if (ctx->waitDone.last == this) + ctx->waitDone.last = prev; + break; + } + } + + if (!found) { + errno = ENOENT; + return (-1); + } + + FREE(this); + + if (ctx->debug >= 9) + print_waits(ctx); + + return (0); +} + +int +evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = NULL; + new->next = NULL; + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = new; + else + ctx->waitDone.first = new; + ctx->waitDone.last = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* Private. */ + +static void +print_waits(evContext_p *ctx) { + evWaitList *wl; + evWait *this; + + evPrintf(ctx, 9, "wait waiting:\n"); + for (wl = ctx->waitLists; wl != NULL; wl = wl->next) { + INSIST(wl->first != NULL); + evPrintf(ctx, 9, " tag %#x:", wl->first->tag); + for (this = wl->first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %#x", this); + evPrintf(ctx, 9, "\n"); + } + evPrintf(ctx, 9, "wait done:"); + for (this = ctx->waitDone.first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %#x", this); + evPrintf(ctx, 9, "\n"); +} + +static evWaitList * +evNewWaitList(evContext_p *ctx) { + evWaitList *new; + + NEW(new); + if (new == NULL) + return (NULL); + new->first = new->last = NULL; + new->prev = NULL; + new->next = ctx->waitLists; + ctx->waitLists = new; + return (new); +} + +static void +evFreeWaitList(evContext_p *ctx, evWaitList *this) { + evWaitList *prev; + + INSIST(this != NULL); + + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->waitLists = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + FREE(this); +} + +static evWaitList * +evGetWaitList(evContext_p *ctx, const void *tag, int should_create) { + evWaitList *this; + + for (this = ctx->waitLists; this != NULL; this = this->next) { + if (this->first != NULL && this->first->tag == tag) + break; + } + if (this == NULL && should_create) + this = evNewWaitList(ctx); + return (this); +} diff --git a/contrib/bind/lib/isc/eventlib.c b/contrib/bind/lib/isc/eventlib.c new file mode 100644 index 0000000..afb9d9d --- /dev/null +++ b/contrib/bind/lib/isc/eventlib.c @@ -0,0 +1,656 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* eventlib.c - implement glue for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: eventlib.c,v 1.38 1998/03/20 23:26:24 halley Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> + +#include <errno.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +#ifdef NEED_PSELECT +static int pselect(int, void *, void *, void *, struct timespec*); +#endif + +/* Public. */ + +int +evCreate(evContext *opaqueCtx) { + evContext_p *ctx; + int i; + + /* Make sure the memory heap is initialized. */ + if (meminit(0, 0) < 0 && errno != EEXIST) + return (-1); + + OKNEW(ctx); + + /* Global. */ + ctx->cur = NULL; + + /* Debugging. */ + ctx->debug = 0; + ctx->output = NULL; + + /* Connections. */ + ctx->conns = NULL; + INIT_LIST(ctx->accepts); + + /* Files. */ + ctx->files = NULL; + FD_ZERO(&ctx->rdNext); + FD_ZERO(&ctx->wrNext); + FD_ZERO(&ctx->exNext); + ctx->fdMax = -1; + ctx->fdNext = NULL; + ctx->fdCount = 0; /* Invalidate {rd,wr,ex}Last. */ +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = 0; +#endif + for (i = 0; i < FD_SETSIZE; i++) + ctx->fdTable[i] = NULL; + + /* Streams. */ + ctx->streams = NULL; + ctx->strDone = NULL; + ctx->strLast = NULL; + + /* Timers. */ + ctx->lastEventTime = evNowTime(); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + ctx->timers = evCreateTimers(ctx); + if (ctx->timers == NULL) + return (-1); + + /* Waits. */ + ctx->waitLists = NULL; + ctx->waitDone.first = ctx->waitDone.last = NULL; + ctx->waitDone.prev = ctx->waitDone.next = NULL; + + opaqueCtx->opaque = ctx; + return (0); +} + +void +evSetDebug(evContext opaqueCtx, int level, FILE *output) { + evContext_p *ctx = opaqueCtx.opaque; + + ctx->debug = level; + ctx->output = output; +} + +int +evDestroy(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + int revs = 424242; /* Doug Adams. */ + evWaitList *this_wl, *next_wl; + evWait *this_wait, *next_wait; + + /* Connections. */ + while (revs-- > 0 && ctx->conns != NULL) { + evConnID id; + + id.opaque = ctx->conns; + (void) evCancelConn(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Streams. */ + while (revs-- > 0 && ctx->streams != NULL) { + evStreamID id; + + id.opaque = ctx->streams; + (void) evCancelRW(opaqueCtx, id); + } + + /* Files. */ + while (revs-- > 0 && ctx->files != NULL) { + evFileID id; + + id.opaque = ctx->files; + (void) evDeselectFD(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Timers. */ + evDestroyTimers(ctx); + + /* Waits. */ + for (this_wl = ctx->waitLists; + revs-- > 0 && this_wl != NULL; + this_wl = next_wl) { + next_wl = this_wl->next; + for (this_wait = this_wl->first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + FREE(this_wl); + } + for (this_wait = ctx->waitDone.first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + + FREE(ctx); + return (0); +} + +int +evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { + evContext_p *ctx = opaqueCtx.opaque; + struct timespec nextTime; + evTimer *nextTimer; + evEvent_p *new; + int x, pselect_errno, timerPast; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec interval; +#endif + + /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ + x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); + if (x != 1) + ERR(EINVAL); + + /* Get the time of day. We'll do this again after select() blocks. */ + ctx->lastEventTime = evNowTime(); + + again: + /* Finished accept()'s do not require a select(). */ + if (!EMPTY(ctx->accepts)) { + OKNEW(new); + new->type = Accept; + new->u.accept.this = HEAD(ctx->accepts); + UNLINK(ctx->accepts, HEAD(ctx->accepts), link); + opaqueEv->opaque = new; + return (0); + } + + /* Stream IO does not require a select(). */ + if (ctx->strDone != NULL) { + OKNEW(new); + new->type = Stream; + new->u.stream.this = ctx->strDone; + ctx->strDone = ctx->strDone->nextDone; + if (ctx->strDone == NULL) + ctx->strLast = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Waits do not require a select(). */ + if (ctx->waitDone.first != NULL) { + OKNEW(new); + new->type = Wait; + new->u.wait.this = ctx->waitDone.first; + ctx->waitDone.first = ctx->waitDone.first->next; + if (ctx->waitDone.first == NULL) + ctx->waitDone.last = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Get the status and content of the next timer. */ + if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) { + nextTime = nextTimer->due; + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } else + timerPast = 0; /* Make gcc happy. */ + + evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount); + if (ctx->fdCount == 0) { + static const struct timespec NoTime = {0, 0L}; + enum { JustPoll, Block, Timer } m; + struct timespec t, *tp; + + /* Are there any events at all? */ + if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1) + ERR(ENOENT); + + /* Figure out what select()'s timeout parameter should be. */ + if ((options & EV_POLL) != 0) { + m = JustPoll; + t = NoTime; + tp = &t; + } else if (nextTimer == NULL) { + m = Block; + /* ``t'' unused. */ + tp = NULL; + } else if (timerPast) { + m = JustPoll; + t = NoTime; + tp = &t; + } else { + m = Timer; + /* ``t'' filled in later. */ + tp = &t; + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(ctx->lastEventTime, + ctx->lastSelectTime); + if (interval.tv_sec > 0) + evPrintf(ctx, 1, + "time between pselect() %u.%09u count %d\n", + interval.tv_sec, interval.tv_nsec, + ctx->lastFdCount); + } +#endif + do { + /* XXX need to copy only the bits we are using. */ + ctx->rdLast = ctx->rdNext; + ctx->wrLast = ctx->wrNext; + ctx->exLast = ctx->exNext; + + if (m == Timer) { + INSIST(tp == &t); + t = evSubTime(nextTime, ctx->lastEventTime); + } + + evPrintf(ctx, 4, + "pselect(%d, 0x%lx, 0x%lx, 0x%lx, %d.%09ld)\n", + ctx->fdMax+1, + (u_long)ctx->rdLast.fds_bits[0], + (u_long)ctx->wrLast.fds_bits[0], + (u_long)ctx->exLast.fds_bits[0], + tp ? tp->tv_sec : -1, + tp ? tp->tv_nsec : -1); + + /* XXX should predict system's earliness and adjust. */ + x = pselect(ctx->fdMax+1, + &ctx->rdLast, &ctx->wrLast, &ctx->exLast, + tp); + pselect_errno = errno; + + evPrintf(ctx, 4, "select() returns %d (err: %s)\n", + x, (x == -1) ? strerror(errno) : "none"); + + /* Anything but a poll can change the time. */ + if (m != JustPoll) + ctx->lastEventTime = evNowTime(); + + /* Select() likes to finish about 10ms early. */ + } while (x == 0 && m == Timer && + evCmpTime(ctx->lastEventTime, nextTime) < 0); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + if (x < 0) { + if (pselect_errno == EINTR) { + if ((options & EV_NULL) != 0) + goto again; + OKNEW(new); + new->type = Null; + /* No data. */ + opaqueEv->opaque = new; + return (0); + } + if (pselect_errno == EBADF) { + for (x = 0; x <= ctx->fdMax; x++) { + struct stat sb; + + if (FD_ISSET(x, &ctx->rdNext) == 0 && + FD_ISSET(x, &ctx->wrNext) == 0 && + FD_ISSET(x, &ctx->exNext) == 0) + continue; + if (fstat(x, &sb) == -1 && + errno == EBADF) + evPrintf(ctx, 1, "EBADF: %d\n", + x); + } + abort(); + } + ERR(pselect_errno); + } + if (x == 0 && (nextTimer && !timerPast) && (options & EV_POLL)) + ERR(EWOULDBLOCK); + ctx->fdCount = x; +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = x; +#endif + } + INSIST(nextTimer || ctx->fdCount); + + /* Timers go first since we'd like them to be accurate. */ + if (nextTimer && !timerPast) { + /* Has anything happened since we blocked? */ + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } + if (nextTimer && timerPast) { + OKNEW(new); + new->type = Timer; + new->u.timer.this = nextTimer; + opaqueEv->opaque = new; + return (0); + } + + /* No timers, so there should be a ready file descriptor. */ + x = 0; + while (ctx->fdCount > 0) { + evFile *fid; + int fd, eventmask; + + if (ctx->fdNext == NULL) { + if (++x == 2) { + /* + * Hitting the end twice means that the last + * select() found some FD's which have since + * been deselected. + * + * On some systems, the count returned by + * selects is the total number of bits in + * all masks that are set, and on others it's + * the number of fd's that have some bit set, + * and on others, it's just broken. We + * always assume that it's the number of + * bits set in all masks, because that's what + * the man page says it should do, and + * the worst that can happen is we do an + * extra select(). + */ + ctx->fdCount = 0; + break; + } + ctx->fdNext = ctx->files; + } + fid = ctx->fdNext; + ctx->fdNext = fid->next; + + fd = fid->fd; + eventmask = 0; + if (FD_ISSET(fd, &ctx->rdLast)) + eventmask |= EV_READ; + if (FD_ISSET(fd, &ctx->wrLast)) + eventmask |= EV_WRITE; + if (FD_ISSET(fd, &ctx->exLast)) + eventmask |= EV_EXCEPT; + eventmask &= fid->eventmask; + if (eventmask != 0) { + if ((eventmask & EV_READ) != 0) { + FD_CLR(fd, &ctx->rdLast); + ctx->fdCount--; + } + if ((eventmask & EV_WRITE) != 0) { + FD_CLR(fd, &ctx->wrLast); + ctx->fdCount--; + } + if ((eventmask & EV_EXCEPT) != 0) { + FD_CLR(fd, &ctx->exLast); + ctx->fdCount--; + } + OKNEW(new); + new->type = File; + new->u.file.this = fid; + new->u.file.eventmask = eventmask; + opaqueEv->opaque = new; + return (0); + } + } + if (ctx->fdCount < 0) { + /* + * select()'s count is off on a number of systems, and + * can result in fdCount < 0. + */ + evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount); + ctx->fdCount = 0; + } + + /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ + goto again; +} + +int +evDispatch(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; +#ifdef EVENTLIB_TIME_CHECKS + void *func; + struct timespec start_time; + struct timespec interval; +#endif + +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) + start_time = evNowTime(); +#endif + ctx->cur = ev; + switch (ev->type) { + case Accept: { + evAccept *this = ev->u.accept.this; + + evPrintf(ctx, 5, + "Dispatch.Accept: fd %d -> %d, func %#x, uap %#x\n", + this->conn->fd, this->fd, + this->conn->func, this->conn->uap); + errno = this->ioErrno; + (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, + &this->la, this->lalen, + &this->ra, this->ralen); +#ifdef EVENTLIB_TIME_CHECKS + func = this->conn->func; +#endif + break; + } + case File: { + evFile *this = ev->u.file.this; + int eventmask = ev->u.file.eventmask; + + evPrintf(ctx, 5, + "Dispatch.File: fd %d, mask 0x%x, func %#x, uap %#x\n", + this->fd, this->eventmask, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->fd, eventmask); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Stream: { + evStream *this = ev->u.stream.this; + + evPrintf(ctx, 5, + "Dispatch.Stream: fd %d, func %#x, uap %#x\n", + this->fd, this->func, this->uap); + errno = this->ioErrno; + (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + + evPrintf(ctx, 5, "Dispatch.Timer: func %#x, uap %#x\n", + this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->due, this->inter); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Wait: { + evWait *this = ev->u.wait.this; + + evPrintf(ctx, 5, + "Dispatch.Wait: tag %#x, func %#x, uap %#x\n", + this->tag, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->tag); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Null: { + /* No work. */ +#ifdef EVENTLIB_TIME_CHECKS + func = NULL; +#endif + break; + } + default: { + abort(); + } + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(evNowTime(), start_time); + /* + * Complain if it took longer than 50 milliseconds. + * + * We call getuid() to make an easy to find mark in a kernel + * trace. + */ + if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) + evPrintf(ctx, 1, + "dispatch interval %u.%09u uid %d type %d func %p\n", + interval.tv_sec, interval.tv_nsec, + getuid(), ev->type, func); + } +#endif + ctx->cur = NULL; + evDrop(opaqueCtx, opaqueEv); + return (0); +} + +void +evDrop(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; + + switch (ev->type) { + case Accept: { + FREE(ev->u.accept.this); + break; + } + case File: { + /* No work. */ + break; + } + case Stream: { + evStreamID id; + + id.opaque = ev->u.stream.this; + (void) evCancelRW(opaqueCtx, id); + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + evTimerID opaque; + + /* Check to see whether the user func cleared the timer. */ + if (heap_element(ctx->timers, this->index) != this) { + evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); + break; + } + /* + * Timer is still there. Delete it if it has expired, + * otherwise set it according to its next interval. + */ + if (this->inter.tv_sec == 0 && this->inter.tv_nsec == 0L) { + opaque.opaque = this; + (void) evClearTimer(opaqueCtx, opaque); + } else { + opaque.opaque = this; + (void) evResetTimer(opaqueCtx, opaque, this->func, + this->uap, + evAddTime(ctx->lastEventTime, + this->inter), + this->inter); + } + break; + } + case Wait: { + FREE(ev->u.wait.this); + break; + } + case Null: { + /* No work. */ + break; + } + default: { + abort(); + } + } + FREE(ev); +} + +int +evMainLoop(evContext opaqueCtx) { + evEvent event; + int x; + + while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; + return (x); +} + +void +evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (ctx->output != NULL && ctx->debug >= level) { + vfprintf(ctx->output, fmt, ap); + fflush(ctx->output); + } + va_end(ap); +} + +#ifdef NEED_PSELECT +static int +pselect(int nfds, void *rfds, void *wfds, void *efds, struct timespec *tsp) { + struct timeval tv, *tvp; + int n; + + if (tsp) { + tvp = &tv; + tv = evTimeVal(*tsp); + } else + tvp = NULL; + n = select(nfds, rfds, wfds, efds, tvp); + if (tsp) + *tsp = evTimeSpec(tv); + return (n); +} +#endif diff --git a/contrib/bind/lib/isc/eventlib.mdoc b/contrib/bind/lib/isc/eventlib.mdoc new file mode 100644 index 0000000..f0e31e1 --- /dev/null +++ b/contrib/bind/lib/isc/eventlib.mdoc @@ -0,0 +1,829 @@ +.\" $Id: eventlib.mdoc,v 1.18 1998/01/26 23:00:56 halley Exp $ +.\" +.\"Copyright (c) 1995, 1996, 1997 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. +.\" +.Dd March 6, 1996 +.Dt EVENTLIB 3 +.Os BSD 4 +.Sh NAME +.Nm evConnFunc , +.Nm evFileFunc , +.Nm evStreamFunc , +.Nm evTimerFunc , +.Nm evWaitFunc , +.Nm evCreate , +.Nm evDestroy , +.Nm evGetNext , +.Nm evDispatch , +.Nm evDrop , +.Nm evMainLoop , +.Nm evConsTime , +.Nm evTimeSpec , +.Nm evTimeVal , +.Nm evAddTime , +.Nm evSubTime , +.Nm evCmpTime , +.Nm evNowTime , +.Nm evLastEventTime , +.Nm evSetTimer , +.Nm evResetTimer , +.Nm evClearTimer , +.Nm evSetIdleTimer , +.Nm evTouchIdleTimer , +.Nm evClearIdleTimer , +.Nm evWaitFor , +.Nm evDo , +.Nm evUnwait , +.Nm evDefer , +.Nm evSelectFD , +.Nm evDeselectFD , +.Nm evWrite , +.Nm evRead , +.Nm evCancelRW , +.Nm evTimeRW , +.Nm evUntimeRW , +.Nm evListen , +.Nm evConnect , +.Nm evCancelConn , +.Nm evHold , +.Nm evUnhold , +.Nm evTryAccept , +.Nm evConsIovec , +.Nm evSetDebug , +.Nm evPrintf +.Nd event handling library +.Sh SYNOPSIS +.Fd #include <isc/eventlib.h> +.Ft typedef void +.Fn (*evConnFunc) "evContext ctx" "void *uap" "int fd" \ +"const void *la" "int lalen" "const void *ra" "int ralen" +.Ft typedef void +.Fn (*evTimerFunc) "evContext ctx" "void *uap" \ +"struct timespec due" "struct timespec inter" +.Ft typedef void +.Fn (*evFileFunc) "evContext ctx" "void *uap" "int fd" "int eventmask" +.Ft typedef void +.Fn (*evStreamFunc) "evContext ctx" "void *uap" "int fd" "int bytes" +.Ft typedef void +.Fn (*evWaitFunc) "evContext ctx" "void *uap" "const void *tag" +.Ft int +.Fn evCreate "evContext *ctx" +.Ft int +.Fn evDestroy "evContext ctx" +.Ft int +.Fn evGetNext "evContext ctx" "evEvent *ev" "int options" +.Ft int +.Fn evDispatch "evContext ctx" "evEvent ev" +.Ft void +.Fn evDrop "evContext ctx" "evEvent ev" +.Ft int +.Fn evMainLoop "evContext ctx" +.Ft struct timespec +.Fn evConsTime "int sec" "int usec" +.Ft struct timespec +.Fn evTimeSpec "struct timeval tv" +.Ft struct timeval +.Fn evTimeVal "struct timespec ts" +.Ft struct timespec +.Fn evAddTime "struct timespec addend1" "struct timespec addend2" +.Ft struct timespec +.Fn evSubTime "struct timespec minuend" "struct timespec subtrahend" +.Ft struct timespec +.Fn evCmpTime "struct timespec a" "struct timespec b" +.Ft struct timespec +.Fn evNowTime "void" +.Ft struct timespec +.Fn evLastEventTime "evContext opaqueCtx" +.Ft int +.Fn evSetTimer "evContext ctx" "evTimerFunc func" "void *uap" \ +"struct timespec due" "struct timespec inter" "evTimerID *id" +.Ft int +.Fn evResetTimer "evContext ctx" "evTimerID id" "evTimerFunc func" \ +"void *uap" "struct timespec due" "struct timespec inter" +.Ft int +.Fn evClearTimer "evContext ctx" "evTimerID id" +.Ft int +.Fn evSetIdleTimer "evContext opaqueCtx" "evTimerFunc func" "void *uap" \ +"struct timespec max_idle" "evTimerID *opaqueID" +.Ft int +.Fn evTouchIdleTimer "evContext opaqueCtx" "evTimerID id" +.Ft int +.Fn evResetIdleTimer "evContext opaqueCtx" "evTimerID id" "evTimerFunc func" \ +"void *uap" "struct timespec max_idle" +.Ft int +.Fn evClearIdleTimer "evContext opaqueCtx" "evTimerID id" +.Ft int +.Fn evWaitFor "evContext opaqueCtx" "const void *tag" \ +"evWaitFunc func" "void *uap" "evWaitID *id" +.Ft int +.Fn evDo "evContext opaqueCtx" "const void *tag" +.Ft int +.Fn evUnwait "evContext opaqueCtx" "evWaitID id" +.Ft int +.Fn evDefer "evContext opaqueCtx" "evWaitFunc func" "void *uap" +.Ft int +.Fn evSelectFD "evContext ctx" "int fd" "int eventmask" \ +"evFileFunc func" "void *uap" "evFileID *id" +.Ft int +.Fn evDeselectFD "evContext ctx" "evFileID id" +.Ft struct iovec +.Fn evConsIovec "void *buf" "size_t cnt" +.Ft int +.Fn evWrite "evContext ctx" "int fd" "const struct iovec *iov" "int cnt" \ +"evStreamFunc func" "void *uap" "evStreamID *id" +.Ft int +.Fn evRead "evContext ctx" "int fd" "const struct iovec *iov" "int cnt" \ +"evStreamFunc func" "void *uap" "evStreamID *id" +.Ft int +.Fn evCancelRW "evContext ctx" "evStreamID id" +.Ft int +.Fn evTimeRW "evContext opaqueCtx" "evStreamID id" "evTimerID timer" +.Ft int +.Fn evUntimeRW "evContext opaqueCtx" "evStreamID id" +.Ft int +.Fn evListen "evContext ctx" "int fd" "int maxconn" \ +"evConnFunc func" "void *uap" "evConnID *id" +.Ft int +.Fn evConnect "evContext ctx" "int fd" "void *ra" "int ralen" \ +"evConnFunc func" "void *uap" "evConnID *id" +.Ft int +.Fn evCancelConn "evContext ctx" "evConnID id" +.Ft int +.Fn evHold "evContext ctx" "evConnID id" +.Ft int +.Fn evUnhold "evContext ctx" "evConnID id" +.Ft int +.Fn evTryAccept "evContext ctx" "evConnID id" "int *sys_errno" +.Ft void +.Fn evSetDebug "evContext ctx" "int level" "FILE *output" +.Ft void +.Fn evPrintf "const evContext_p *ctx" "int level" "const char *fmt" "..." +.Sh DESCRIPTION +This library provides multiple outstanding asynchronous timers and I/O +to a cooperating application. The model is similar to that of the X +Toolkit, in that events are registered with the library and the application +spends most of its time in the +.Fn evMainLoop +function. If an application already has a main loop, it can safely register +events with this library as long as it periodically calls the +.Fn evGetNext +and +.Fn evDispatch +functions. (Note that +.Fn evGetNext +has both polling and blocking modes.) +.Pp +The function +.Fn evCreate +creates an event context which is needed by all the other functions in this +library. All information used internally by this library is bound to this +context, rather than to static storage. This makes the library +.Dq thread safe, +and permits other library functions to use events without +disrupting the application's use of events. +.Pp +The function +.Fn evDestroy +destroys a context that has been created by +.Fn evCreate . +All dynamic memory bound to this context will be freed. An implicit +.Fn evTimerClear +will be done on all timers set in this event context. An implicit +.Fn evDeselectFD +will be done on all file descriptors selected in this event context. +.Pp +The function +.Fn evGetNext +potentially waits for and then retrieves the next asynchronous event, +placing it in the object of the +.Fa ev +pointer argument. The following +.Fa options +are available: +.Fa EV_POLL , +meaning that +.Fn evGetNext +should not block, but rather return +.Dq Fa -1 +with +.Fa errno +set to +.Fa EWOULDBLOCK +if no events have occurred; +.Fa EV_WAIT , +which tells +.Fn evGetNext +to block internally until the next event occurs; and +.Fa EV_NULL , +which tells +.Fn evGetNext +that it should return a special +.Dq no-op +event, which is ignored by +.Fn evDispatch +but handled correctly by +.Fn evDrop . +.Fa EV_NULL +can be necessary to the correct functioning of a caller\-written equivilent to +.Fn evMainLoop , +wherein perterbations caused by external system events must be polled for, and +the default behaviour of internally ignoring such events is undesirable. +Note that +.Fa EV_POLL +and +.Fa EV_WAIT +are mutually exclusive. +.Pp +The function +.Fn evDispatch +dispatches an event retrieved by +.Fn evGetNext . +This usually involves calling the function that was associated with the event +when the event was registered with +.Fn evSetTimer , +.Fn evResetTimer , +or +.Fn evSelectFD . +All events retrieved by +.Fn evGetNext +must be given over to +.Fn evDispatch +at some point, since there is some dynamic memory associated with each event. +.Pp +The function +.Fn evDrop +deallocates dynamic memory that has been allocated by +.Fn evGetNext . +Calling +.Fn evDispatch +has the side effect of calling +.Fn evDrop , +but if you are going to drop the event rather than dispatch it, you will have +to call +.Fn evDrop +directly. +.Pp +The function +.Fn evMainLoop +is just: +.Bd -literal -offset indent +while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; +return (x); +.Ed +.Pp +In other words, get events and dispatch them until an error occurs. One such +error would be that all the events under this context become unregistered; in +that event, there will be nothing to wait for and +.Fn evGetNext +becomes an undefined operation. +.Pp +The function +.Fn evConsTime +is a constructor for +.Dq Fa struct timespec +which allows these structures to be created and then passed as arguments to +other functions without the use of temporary variables. (If C had inline +constructors, there would be no need for this function.) +.Pp +The functions +.Fn evTimeSpec +and +.Fn evTimeVal +are utilities which allow the caller to convert a +.Dq Fa struct timeval +to a +.Dq Fa struct timespec +(the function of +.Fn evTimeSpec ) +or vice versa (the function of +.Fn evTimeVal ) . +Note that the name of the function indicates the type of the return value. +.Pp +The function +.Fn evAddTime +adds two +.Dq Fa struct timespec +values and returns the result as a +.Dq Fa struct timespec. +.Pp +The function +.Fn evSubTime +subtracts its second +.Dq Fa struct timespec +argument from its first +.Dq Fa struct timespec +argument and returns the result as a +.Dq Fa struct timespec. +.Pp +The function +.Fn evCmpTime +compares its two +.Dq Fa struct timespec +arguments and returns an +.Dq Fa int +that is less than zero if the first argument specifies an earlier time than +the second, or more than zero if the first argument specifies a later time +than the second, or equal to zero if both arguments specify the same time. +.Pp +The function +.Fn evNowTime +returns a +.Dq Fa struct timespec +which either describes the current time (using +.Xr gettimeofday 2 ) , +if successful, or has its fields set to zero, if there is an error. +(In the latter case, the caller can check +.Va errno , +since it will be set by +.Xr gettimeofday 2 . ) +.Pp +The function +.Fn evLastEventTime +returns the +.Dq Fa struct timespec +which describes the last time that certain events happened to the +event context indicated by +.Fa opaqueCtx . +This value is updated by +.Fn evCreate +and +.Fn evGetNext +(upon entry and after +.Xr select 2 +returns); it is routinely compared with other times in the internal handling +of, e.g., timers. +.Pp +The function +.Fn evSetTimer +registers a timer event, which will be delivered as a function call to the +function specified by the +.Fa func +argument. The event will be delivered at absolute time +.Fa due , +and then if time +.Fa inter +is not equal to +.Dq Fa evConsTime(0,0) , +subsequently at intervals equal to time +.Fa inter . +As a special case, specifying a +.Fa due +argument equal to +.Dq Fa evConsTime(0,0) +means +.Dq due immediately. +The +.Fa opaqueID +argument, if specified as a value other than +.Fa NULL , +will be used to store the resulting +.Dq timer \s-1ID\s+1 , +useful as an argument to +.Fn evClearTimer . +Note that in a +.Dq one\-shot +timer (which has an +.Fa inter +argument equal to +.Dq Fa evConsTime(0,0) +.\" putting the ) after the Dq Fa arg did not work well. --vix +) the user function +.Fa func +should deallocate any dynamic memory that is uniquely bound to the +.Fa uap , +since no handles to this memory will exist within the event library +after a one\-shot timer has been delivered. +.Pp +The function +.Fn evResetTimer +resets the values of the timer specified by +.Fa id +to the given arguments. The arguments are the same as in the description of +.Fn evSetTimer +above. +.Pp +The function +.Fn evClearTimer +will unregister the timer event specified by +.Fa id . +Note that if the +.Fa uap +specified in the corresponding +.Fn evSetTimer +call is uniquely bound to any dynamic memory, then that dynamic memory should +be freed by the caller before the handle is lost. After a call to +.Fn evClearTimer , +no handles to this +.Fa uap +will exist within the event library. +.Pp +The function +.Fn evSetIdleTimer +is similar to (and built on) +.Fn evSetTimer ; +it registers an idle timer event which provides for the function call to +.Fa func +to occur. However, for an +.Em idle +timer, the call will occur after at least +.Dq Fa max_idle +time has passed since the time the idle timer was +.Dq last touched ; +originally, this is set to the time returned by +.Fn evLastEventTime +(described above) for the event context specified by +.Fa opaqueCtx . +This is a +.Dq one\-shot +timer, but the time at which the +.Fa func +is actually called can be changed by recourse to +.Fn evTouchIdleTimer +(described below). The pointer to the underlying +.Dq timer \s-1ID\s+1 +is returned in +.Fa opaqueID , +if it is +.No non- Ns Dv NULL . +.Pp +The +.Fn evTouchIdleTimer +function updates the idle timer associated with +.Fa id , +setting its idea of the time it was last accessed to the value returned by +.Fn evLastEventTime +(described above) for the event context specified by +.Fa opaqueCtx . +This means that the idle timer will expire after at least +.Fa max_idle +time has passed since this (possibly new) time, providing a caller mechanism +for resetting the call to the +.Fa func +associated with the idle timer. (See the description of +.Fn evSetIdleTimer , +above, for information about +.Fa func +and +.Fa max_idle . ) +.Pp +The +.Fn evResetIdleTimer +function reschedules a timer and resets the callback function and its argument. +Note that resetting a timer also ``touches'' it. +.Pp +The +.Fn evClearIdleTimer +function unregisters the idle timer associated with +.Fa id . +See the discussion under +.Fn evClearTimer , +above, for information regarding caller handling of the +.Fa uap +associated with the corresponding +.Fn evSetIdleTimer +call. +.Pp +The function +.Fn evWaitFor +places the function +.Fa func +on the given event context's wait queue with the associated (possibly +.Dv NULL ) +.Dq Fa tag ; +if +.Fa id +is +.No non- Ns Dv NULL , +then it will contain the +.Dq wait \s-1ID\s+1 +associated with the created queue element. +.Pp +The function +.Fn evDo +marks +.Em all +of the +.Dq waiting +functions in the given event context's wait queue with the associated (possibly +.Dv NULL ) +.Dq Fa tag +as runnable. This places these functions in a +.Dq done +queue which will be read by +.Fn evGetNext . +.Pp +The function +.Fn evUnwait +will search for the +.Dq wait \s-1ID\s+1 +.Fa id +in the wait queue of the given event context; if an element with the given +.Fa id +is not found, then the +.Dq done +queue of that context is searched. If found, the queue element is removed +from the appropriate list. +.Pp +The function +.Fn evDefer +causes a function (specified as +.Fa func , +with argument +.Fa uap ) +to be dispatched at some later time. Note that the +.Fa tag +argument to +.Fa func +will always be +.Fa NULL +when dispatched. +.Pp +The function +.Fn evSelectFD +registers a file I/O event for the file descriptor specified by +.Fa fd . +Bits in the +.Fa eventmask +argument are named +.Fa EV_READ , +.Fa EV_WRITE , +and +.Fa EV_EXCEPT . +At least one of these bits must be specified. If the +.Fa id +argument is not equal to +.Fa NULL , +it will be used to store a unique ``file event \s-1ID\s+1'' for this event, +which is useful in subsequent calls to +.Fn evDeselectFD . +A file descriptor will be made nonblocking using the +.Fa O_NONBLOCK +flag with +.Xr fcntl 2 +on its first concurrent registration via +.Fn evSelectFD . +An +.Fn evSelectFD +remains in effect until cancelled via +.Fn evDeselectFD . +.Pp +The function +.Fn evDeselectFD +unregisters the ``file event'' specified by the +.Fa id +argument. If the corresponding +.Fa uap +uniquely points to dynamic memory, that memory should be freed before its +handle is lost, since after a call to +.Fn evDeselectFD , +no handles to this event's +.Fa uap +will remain within the event library. A file descriptor will be taken out of +nonblocking mode (see +.Fa O_NONBLOCK +and +.Xr fcntl 2 ) +when its last event registration is removed via +.Fn evDeselectFD , +if it was in blocking mode before the first registration via +.Fn evSelectFD . +.Pp +The function +.Fn evConsIovec +is a constructor for a single +.Ft struct iovec +structure, which is useful for +.Fn evWrite +and +.Fn evRead . +.Pp +The functions +.Fn evWrite +and +.Fn evRead +start asynchronous stream I/O operations on file descriptor +.Fa fd . +The data to be written or read is in the scatter/gather descriptor specified by +.Fa iov +and +.Fa cnt . +The supplied function +.Fa func +will be called with argument +.Fa uap +when the I/O operation is complete. If +.Fa id +is not +.Fa NULL , +it will be filled a with the stream event identifier suitable for use with +.Fn evCancelRW . +.Pp +The function +.Fn evCancelRW +extinguishes an outstanding +.Fn evWrite +or +.Fn evRead +call. System I/O calls cannot always be cancelled, but you are guaranteed +that the +.Fa func +function supplied to +.Fn evWrite +or +.Fn evRead +will not be called after a call to +.Fn evCancelRW . +Care should be taken not to deallocate or otherwise reuse the space pointed +to by the segment descriptors in +.Fa iov +unless the underlying file descriptor is closed first. +.Pp +The function +.Fn evTimeRW +sets the stream associated with the given stream \s-1ID\s+1 +.Dq Fa id +to have the idle timer associated with the timer \s-1ID\s+1 +.Dq Fa timer . +.Pp +The function +.Fn evUntimeRW +says that the stream associated with the given stream \s-1ID\s+1 +.Dq Fa id +should ignore its idle timer, if present. +.Pp +The functions +.Fn evListen , +.Fn evConnect , +and +.Fn evCancelConn +can be used to manage asynchronous incoming and outgoing socket connections. +Sockets to be used with these functions should first be created with +.Xr socket 2 +and given a local name with +.Xr bind 2 . +It is extremely unlikely that the same socket will ever be +useful for both incoming and outgoing connections. The +.Fa id +argument to +.Fn evListen +and +.Fn evConnect +is either +.Fa NULL +or the address of a +.Ft evFileID +variable which can then be used in a subsequent call to +.Fn evCancelConn . +.Pp +After a call to +.Fn evListen , +each incoming connection arriving on +.Fa fd +will cause +.Fa func +to be called with +.Fa uap +as one of its arguments. +.Fn evConnect +initiates an outgoing connection on +.Fa fd +to destination address +.Fa ra +(whose length is +.Fa ralen ). +When the connection is complete, +.Fa func +will be called with +.Fa uap +as one of its arguments. The argument +.Fa fd +to +.Fn (*func)() +will be +.Fa -1 +if an error occurred that prevented this connection from completing +successfully. In this case +.Fn errno +will have been set and the socket described by +.Fa fd +will have been closed. The +.Fn evCancelConn +function will prevent delivery of all pending and subsequent +events for the outstanding connection. The +.Fn evHold +function will suspend the acceptance of new connections on the listener +specified by +.Fa id . +Connections will be queued by the protocol stack up to the system's limit. The +.Fn evUnhold +function will reverse the effects of +.Fn evHold , +allowing incoming connections to be delivered for listener +.Fa id . +The +.Fn evTryAccept +function will poll the listener specified by +.Fa id , +accepting a new connection if one is available, and queuing a connection event +for later retrieval by +.Fn evGetNext . +If the connection event queued is an accept error(), sys_errno will contain +the error code; otherwise it will be zero. All connection events queued by +.Fn evTryAccept +will be delivered by +.Fn evGetNext +before a new select is done on the listener. +.Pp +The function +.Fn evSetDebug +sets the debugging +.Fa level +and diagnostic +.Fa output +file handle for an event context. Greater numeric levels will +result in more verbose output being sent to the output FILE during program +execution. +.Pp +The function +.Fn evPrintf +prints a message with the format +.Dq Fa fmt +and the following arguments (if any), on the output stream associated +with the event context pointed to by +.Fa ctx . +The message is output if the event context's debug level is greater than +or equal to the indicated +.Fa level . +.Sh RETURN VALUES +All the functions whose return type is +.Dq Fa int +use the standard convention of returning zero (0) to indicate success, or +returning +.Dq Fa -1 +and setting +.Fa errno +to indicate failure. +.Sh FILE +.Pa heap.h , +which is in the +.Pa src/lib/isc +directory of the current +.Sy BIND +distribution. +.Sh ERRORS +The possible values for +.Fa errno +when one of the +.Dq Fa int +functions in this library returns +.Dq Fa -1 +include those of the Standard C Library and also: +.Bl -tag -width EWOULDBLOCKAA +.It Bq Er EINVAL +Some function argument has an unreasonable value. +.It Bq Er EINVAL +The specified file descriptor has an integer value greater than the default +.Fa FD_SETSIZE , +meaning that the application's limit is higher than the library's. +.It Bq Er ENOENT +The specified +.Dq event \s-1ID\s+1 +does not exist. +.It Bq Er EWOULDBLOCK +No events have occurred and the +.Fa EV_POLL +option was specified. +.It Bq Er EBADF +The specified signal was unblocked outside the library. +.El +.Sh SEE ALSO +.Xr gettimeofday 2 , +.Xr select 2 , +.Xr fcntl 3 , +.Xr malloc 3 , +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr readv 3 , +.Xr writev 3 . +.Sh BUGS +This huge man page needs to be broken up into a handful of smaller ones. +.Sh HISTORY +The +.Nm eventlib +library was designed by Paul Vixie with excellent advice from his friends +and with tips 'o the cap to the X Consortium and the implementors of DEC SRC +Modula-3. diff --git a/contrib/bind/lib/isc/eventlib_p.h b/contrib/bind/lib/isc/eventlib_p.h new file mode 100644 index 0000000..2606333 --- /dev/null +++ b/contrib/bind/lib/isc/eventlib_p.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* eventlib_p.h - private interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib_p.h,v 1.25 1998/02/06 01:53:54 halley Exp $ + */ + +#ifndef _EVENTLIB_P_H +#define _EVENTLIB_P_H + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> + +#define EVENTLIB_DEBUG 1 + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/heap.h> +#include <isc/list.h> +#include <isc/memcluster.h> + +#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT) +#define ERR(e) return (errno = (e), -1) +#define OK(x) if ((x) < 0) ERR(errno); else (void)NULL + +#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \ + FILL(p); \ + else \ + (void)NULL; +#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \ + errno = ENOMEM; \ + return (-1); \ + } else \ + FILL(p) +#define FREE(p) memput((p), sizeof *(p)) + +#if EVENTLIB_DEBUG +#define FILL(p) memset((p), 0xF5, sizeof *(p)) +#else +#define FILL(p) +#endif + +typedef struct evConn { + evConnFunc func; + void * uap; + int fd; + int flags; +#define EV_CONN_LISTEN 0x0001 /* Connection is a listener. */ +#define EV_CONN_SELECTED 0x0002 /* evSelectFD(conn->file). */ +#define EV_CONN_BLOCK 0x0004 /* Listener fd was blocking. */ + evFileID file; + struct evConn * prev; + struct evConn * next; +} evConn; + +typedef struct evAccept { + int fd; + struct sockaddr la; + int lalen; + struct sockaddr ra; + int ralen; + int ioErrno; + evConn * conn; + LINK(struct evAccept) link; +} evAccept; + +typedef struct evFile { + evFileFunc func; + void * uap; + int fd; + int eventmask; + int preemptive; + struct evFile * prev; + struct evFile * next; + struct evFile * fdprev; + struct evFile * fdnext; +} evFile; + +typedef struct evStream { + evStreamFunc func; + void * uap; + evFileID file; + evTimerID timer; + int flags; +#define EV_STR_TIMEROK 0x0001 /* IFF timer valid. */ + int fd; + struct iovec * iovOrig; + int iovOrigCount; + struct iovec * iovCur; + int iovCurCount; + int ioTotal; + int ioDone; + int ioErrno; + struct evStream *prevDone, *nextDone; + struct evStream *prev, *next; +} evStream; + +typedef struct evTimer { + evTimerFunc func; + void * uap; + struct timespec due, inter; + int index; +} evTimer; + +typedef struct evWait { + evWaitFunc func; + void * uap; + const void * tag; + struct evWait * next; +} evWait; + +typedef struct evWaitList { + evWait * first; + evWait * last; + struct evWaitList * prev; + struct evWaitList * next; +} evWaitList; + +typedef struct evEvent_p { + enum { Accept, File, Stream, Timer, Wait, Free, Null } type; + union { + struct { evAccept *this; } accept; + struct { evFile *this; int eventmask; } file; + struct { evStream *this; } stream; + struct { evTimer *this; } timer; + struct { evWait *this; } wait; + struct { struct evEvent_p *next; } free; + struct { const void *placeholder; } null; + } u; +} evEvent_p; + +typedef struct { + /* Global. */ + const evEvent_p *cur; + /* Debugging. */ + int debug; + FILE *output; + /* Connections. */ + evConn *conns; + LIST(evAccept) accepts; + /* Files. */ + evFile *files, *fdNext; + fd_set rdLast, rdNext; + fd_set wrLast, wrNext; + fd_set exLast, exNext; + fd_set nonblockBefore; + int fdMax, fdCount; + evFile *fdTable[FD_SETSIZE]; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec lastSelectTime; + int lastFdCount; +#endif + /* Streams. */ + evStream *streams; + evStream *strDone, *strLast; + /* Timers. */ + struct timespec lastEventTime; + heap_context timers; + /* Waits. */ + evWaitList *waitLists; + evWaitList waitDone; +} evContext_p; + +/* eventlib.c */ +#define evPrintf __evPrintf +void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...); + +/* ev_timers.c */ +#define evCreateTimers __evCreateTimers +heap_context evCreateTimers(const evContext_p *); +#define evDestroyTimers __evDestroyTimers +void evDestroyTimers(const evContext_p *); + +/* ev_waits.c */ +#define evFreeWait __evFreeWait +evWait *evFreeWait(evContext_p *ctx, evWait *old); + +#endif /*_EVENTLIB_P_H*/ diff --git a/contrib/bind/lib/isc/heap.c b/contrib/bind/lib/isc/heap.c new file mode 100644 index 0000000..821d323 --- /dev/null +++ b/contrib/bind/lib/isc/heap.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1997 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. + */ + +/* + * Heap implementation of priority queues adapted from the following: + * + * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest, + * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7. + * + * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988, + * ISBN 0-201-06673-4, chapter 11. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: heap.c,v 8.5 1998/03/27 00:17:47 halley Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <stddef.h> +#include <stdlib.h> +#include <errno.h> + +#include "port_after.h" + +#include <isc/heap.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. + */ +#define heap_parent(i) ((i) >> 1) +#define heap_left(i) ((i) << 1) + +#define ARRAY_SIZE_INCREMENT 512 + +heap_context +heap_new(heap_higher_priority_func higher_priority, heap_index_func index, + int array_size_increment) { + heap_context ctx; + + ctx = (heap_context)malloc(sizeof (struct heap_context)); + if (ctx == NULL || higher_priority == NULL) + return (NULL); + ctx->array_size = 0; + if (array_size_increment == 0) + ctx->array_size_increment = ARRAY_SIZE_INCREMENT; + else + ctx->array_size_increment = array_size_increment; + ctx->heap_size = 0; + ctx->heap = NULL; + ctx->higher_priority = higher_priority; + ctx->index = index; + return (ctx); +} + +int +heap_free(heap_context ctx) { + if (ctx == NULL) { + errno = EINVAL; + return (-1); + } + + if (ctx->heap != NULL) + free(ctx->heap); + free(ctx); + + return (0); +} + +static int +heap_resize(heap_context ctx) { + void **new_heap; + + ctx->array_size += ctx->array_size_increment; + new_heap = (void **)realloc(ctx->heap, + (ctx->array_size) * (sizeof (void *))); + if (new_heap == NULL) { + errno = ENOMEM; + return (-1); + } + ctx->heap = new_heap; + return (0); +} + +static void +float_up(heap_context ctx, int i, void *elt) { + int p; + + for ( p = heap_parent(i); + i > 1 && ctx->higher_priority(elt, ctx->heap[p]); + i = p, p = heap_parent(i) ) { + ctx->heap[i] = ctx->heap[p]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +static void +sink_down(heap_context ctx, int i, void *elt) { + int j, size, half_size; + + size = ctx->heap_size; + half_size = size / 2; + while (i <= half_size) { + /* find smallest of the (at most) two children */ + j = heap_left(i); + if (j < size && ctx->higher_priority(ctx->heap[j+1], + ctx->heap[j])) + j++; + if (ctx->higher_priority(elt, ctx->heap[j])) + break; + ctx->heap[i] = ctx->heap[j]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + i = j; + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +int +heap_insert(heap_context ctx, void *elt) { + int i; + + if (ctx == NULL || elt == NULL) { + errno = EINVAL; + return (-1); + } + + i = ++ctx->heap_size; + if (ctx->heap_size >= ctx->array_size && heap_resize(ctx) < 0) + return (-1); + + float_up(ctx, i, elt); + + return (0); +} + +int +heap_delete(heap_context ctx, int i) { + void *elt; + + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + elt = ctx->heap[ctx->heap_size]; + if (--ctx->heap_size > 0) + sink_down(ctx, i, elt); + + return (0); +} + +int +heap_increased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + float_up(ctx, i, ctx->heap[i]); + + return (0); +} + +int +heap_decreased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + sink_down(ctx, i, ctx->heap[i]); + + return (0); +} + +void * +heap_element(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (NULL); + } + + return (ctx->heap[i]); +} + +int +heap_for_each(heap_context ctx, heap_for_each_func action, void *uap) { + int i; + + if (ctx == NULL || action == NULL) { + errno = EINVAL; + return (-1); + } + + for (i = 1; i <= ctx->heap_size; i++) + (action)(ctx->heap[i], uap); + return (0); +} diff --git a/contrib/bind/lib/isc/heap.mdoc b/contrib/bind/lib/isc/heap.mdoc new file mode 100644 index 0000000..2c22bc2 --- /dev/null +++ b/contrib/bind/lib/isc/heap.mdoc @@ -0,0 +1,369 @@ +.\" $Id: heap.mdoc,v 8.4 1997/04/26 04:00:55 vixie Exp $ +.\" +.\"Copyright (c) 1997 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. +.\" +.Dd Jan 1, 1997 +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\" TODO--get correct section # below!! +.Dt HEAP @SYSCALL_EXT@ +.Sh DESCRIPTION +.Nm heap_new , +.Nm heap_free , +.Nm heap_insert , +.Nm heap_delete , +.Nm heap_increased , +.Nm heap_decreased , +.Nm heap_element , +.Nm heap_for_each +.Nd heap implementation of priority queues +.Sh SYNOPSIS +.Fd #include \&"heap.h\&" +.Ft heap_context +.Fn heap_new "heap_higher_priority_func higher_priority" \ +"heap_index_func index" "int array_size_increment" +.Ft int +.Fn heap_free "heap_context ctx" +.Ft int +.Fn heap_insert "heap_context ctx" "void *elt" +.Ft int +.Fn heap_delete "heap_context ctx" "int i" +.Ft int +.Fn heap_increased "heap_context ctx" "int i" +.Ft int +.Fn heap_decreased "heap_context ctx" "int i" +.Ft void * +.Fn heap_element "heap_context ctx" "int i" +.Ft int +.Fn heap_for_each "heap_context ctx" "heap_for_each_func action" "void *uap" +.Sh DESCRIPTION +These functions implement heap\-based priority queues. The user defines a +priority scheme, and provides a function for comparison of the priority +of heap elements +.Po see the description of the +.Ft heap_higher_priority_func +function pointer, below +.Pc . +.Pp +Each of the functions depends upon the +.Ft heap_context +type, which is a pointer to a +.Ft struct heap_context +.Pq see Pa heap.h No for more information . +.Pp +The +.Pa heap.h +header file also defines the following set of function +function pointers: +.Bd -literal -offset indent +typedef int (*heap_higher_priority_func)(void *, void *); +typedef void (*heap_index_func)(void *, int); +typedef void (*heap_for_each_func)(void *, void *); +.Ed +.Pp +These are pointers to user-defined functions. +The +.Ft heap_higher_priority_func +type is a pointer to a function which compares two +different heap (queue) elements and returns an +.Ft int +which answers the question, "Does the first queue element +have a higher priority than the second?" In other words, +a function pointer of this type +.Em must +return a number greater than zero +if the element indicated by the first argument is of a higher priority than +that indicated by the second element, and zero otherwise. +.Pp +The other two function pointers are documented in the descriptions +of +.Fn heap_new +.Pq Va heap_index_func +and +.Fn heap_for_each +.Pq Va heap_for_each_func , +below. +.Pp +The function +.Fn heap_new +initializes a +.Ft struct heap_context +and returns a pointer to it. The +.Fa higher_priority +function pointer +.Em must +be +.No non\- Ns Dv NULL . +As explained above, this refers to a +function supplied by the user which compares the priority of two different +queue or heap elements; see above for more information. +The second argument, +.Fa index , +is a pointer to a user-defined function whose arguments are +a heap element and its index in the heap. +.Fa Index +is intended to provide the user a means of knowing the internal index +of an element in the heap while maintaining the opacity of the implementation; +since the user has to know the actual indexes of heap elements in order to use, +e.g., +.Fn heap_delete +or +.Fn heap_element , +the user +.Fa index +function could store the index in the heap element, itself. If +.Fa index +is +.No non\- Ns Dv NULL , +then it is called +.Em whenever +the index of an element changes, allowing the user to stay up\-to\-date +with index changes. +The last argument, +.Fa array_size_increment +will be used, as its name suggests, by +.Xr malloc 3 +or +.Xr realloc 3 +to increment the array which implements the heap; if zero, a default value +will be used. +.Pp +The +.Fn heap_free +function frees the given +.Ft heap_context +argument +.Pq Fa ctx , +which also frees the entire +.Nm heap , +if it is +.No non\- Ns Dv NULL . +The argument +.Fa ctx +should be +.No non\- Ns Dv NULL . +.Pp +The +.Fn heap_insert +function is used to insert the new heap element +.Fa elt +into the appropriate place (priority\-wise) in the +.Ft heap +indicated by +.Fa ctx +.Po a pointer to a +.Ft heap_context +.Pc . +If +.No non\- Ns Dv NULL , +the user-defined +.Ft higher_priority +function pointer associated with the indicated +.Nm heap +is used to determine that +.Dq appropriate place ; +the highest\-priority elements are at the front of the queue (top of +the heap). +(See the description of +.Fn heap_new , +above, for more information.) +.Pp +The function +.Fn heap_delete +is used to delete the +.Fa i\- Ns th +element of the queue (heap), and fixing up the queue (heap) from that +element onward via the priority as determined by the user function +pointed to by +.Ft higher_priority +function pointer +.Pq see description of Fn heap_new, No above . +.Pp +.Fn heap_increased +.Pp +.Fn heap_decreased +.Pp +The +.Fn heap_element +function returns the +.Fa i\- Ns th +element of the queue/heap indicated by +.Fa ctx , +if possible. +.Pp +The +.Fn heap_for_each +function provides a mechanism for the user to increment through the entire +queue (heap) and perform some +.Fa action +upon each of the queue elements. This +.Fa action +is pointer to a user\-defined function with two arguments, the first of +which should be interpreted by the user's function as a heap element. The +second value passed to the user function is just the +.Fa uap +argument to +.Fn heap_for_each ; +this allows the user to specify additional arguments, if necessary, to +the function pointed to by +.Fa action . +.\" The following requests should be uncommented and +.\" used where appropriate. This next request is +.\" for sections 2 and 3 function return values only. +.Sh RETURN VALUES +.Bl -tag -width "heap_decreased()" +.It Fn heap_new +.Dv NULL +if unable to +.Xr malloc 3 +a +.Ft struct heap_context +or if the +.Fa higher_priority +function pointer is +.Dv NULL; +otherwise, a valid +.Ft heap_context +.Ns . +.It Fn heap_free +-1 if +.Fa ctx +is +.Dv NULL +(with +.Va errno +set to +.Dv EINVAL ) ; +otherwise, 0. +.It Fn heap_insert +-1 +if either +.Fa ctx +or +.Fa elt +is +.Dv NULL , +or if an attempt to +.Xr malloc 3 +or +.Xr realloc 3 +the heap array fails (with +.Va errno +set to +.Dv EINVAL +or +.Dv ENOMEM , +respectively). +Otherwise, 0. +.It Fn heap_delete +-1 if +.Fa ctx +is +.Dv NULL +or +.Fa i +is out\-of\-range (with +.Va errno +set to +.Dv EINVAL ) ; +0 otherwise. +.It Fn heap_increased +As for +.Fn heap_delete . +.It Fn heap_decreased +As for +.Fn heap_delete . +.It Fn heap_element +NULL if +.Fa ctx +is +.Dv NULL +or +.Fa i +out\-of-bounds (with +.Va errno +set to +.Dv EINVAL ) ; +otherwise, a pointer to the +.Fa i\- Ns th +queue element. +.It Fn heap_for_each +-1 if either +.Fa ctx +or +.Fa action +is +.Dv NULL +(with +.Va errno +set to +.Dv EINVAL ) ; +0 otherwise. +.El +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width "heap.h000" +.It Pa heap.h + heap library header file +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.Sh DIAGNOSTICS +Please refer to +.Sx RETURN VALUES . +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +The variable +.Va errno +is set by +.Fn heap_free , +.Fn heap_insert , +.Fn heap_delete , +.Fn heap_increased , +and +.Fn heap_decreased +under the conditions of invalid input +.Pq Dv EINVAL +or lack of memory +.Pq Dv ENOMEM ; +please refer to +.Sx RETURN VALUES . +.Sh SEE ALSO +.Xr malloc 3 , +.Xr realloc 3 . +.Pp +Cormen, Leiserson, and Rivest, +.Sy Introduction to Algorithms, +MIT Press / McGraw Hill, 1990, ISBN 0\-262\-03141\-8, chapter 7. +.Pp +Sedgewick, +.Sy Algorithms, +2nd ed'n, Addison\-Wesley, 1988, ISBN 0\-201\-06673\-4, chapter 11. +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +The +.Nm heap +library was implemented by Bob Halley (halley@vix.com) of Vixie Enterprises, +Inc., for the Internet Software consortium, and was adapted from +the two books listed in the +.Sx SEE ALSO +section, above. +.\" .Sh BUGS diff --git a/contrib/bind/lib/isc/logging.c b/contrib/bind/lib/isc/logging.c new file mode 100644 index 0000000..e5264ff --- /dev/null +++ b/contrib/bind/lib/isc/logging.c @@ -0,0 +1,674 @@ +/* + * Copyright (c) 1996, 1997, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: logging.c,v 8.18 1998/03/27 00:17:47 halley Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <syslog.h> +#include <errno.h> +#include <time.h> +#include <unistd.h> + +#include <isc/assertions.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#ifdef VSPRINTF_CHAR +# define VSPRINTF(x) strlen(vsprintf/**/x) +#else +# define VSPRINTF(x) ((size_t)vsprintf x) +#endif + +#include "logging_p.h" + +static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, + LOG_WARNING, LOG_ERR, LOG_CRIT }; + +static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +static char *level_text[] = { "info: ", "notice: ", "warning: ", "error: ", + "critical: " }; + +static void +version_rename(log_channel chan) { + unsigned int ver; + char old_name[PATH_MAX+1]; + char new_name[PATH_MAX+1]; + + ver = chan->out.file.versions; + if (ver < 1) + return; + if (ver > LOG_MAX_VERSIONS) + ver = LOG_MAX_VERSIONS; + /* + * Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100) + */ + if (strlen(chan->out.file.name) > (PATH_MAX-3)) + return; + for (ver--; ver > 0; ver--) { + sprintf(old_name, "%s.%d", chan->out.file.name, ver-1); + sprintf(new_name, "%s.%d", chan->out.file.name, ver); + (void)rename(old_name, new_name); + } + sprintf(new_name, "%s.0", chan->out.file.name); + (void)rename(chan->out.file.name, new_name); +} + +FILE * +log_open_stream(log_channel chan) { + FILE *stream; + int fd, flags; + struct stat sb; + int regular; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + + /* + * Don't open already open streams + */ + if (chan->out.file.stream != NULL) + return (chan->out.file.stream); + + if (stat(chan->out.file.name, &sb) < 0) { + if (errno != ENOENT) { + syslog(LOG_ERR, + "log_open_stream: stat of %s failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + regular = 1; + } else + regular = (sb.st_mode & S_IFREG); + + if (chan->out.file.versions) { + if (regular) + version_rename(chan); + else { + syslog(LOG_ERR, + "log_open_stream: want versions but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + flags = O_WRONLY|O_CREAT|O_APPEND; + + if (chan->flags & LOG_TRUNCATE) { + if (regular) { + (void)unlink(chan->out.file.name); + flags |= O_EXCL; + } else { + syslog(LOG_ERR, + "log_open_stream: want truncation but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + fd = open(chan->out.file.name, flags, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fd < 0) { + syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + stream = fdopen(fd, "a"); + if (stream == NULL) { + syslog(LOG_ERR, "log_open_stream: fdopen() failed"); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + + chan->out.file.stream = stream; + return (stream); +} + +int +log_close_stream(log_channel chan) { + FILE *stream; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (0); + } + stream = chan->out.file.stream; + chan->out.file.stream = NULL; + if (stream != NULL && fclose(stream) == EOF) + return (-1); + return (0); +} + +FILE * +log_get_stream(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.stream); +} + +char * +log_get_filename(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.name); +} + +int +log_check_channel(log_context lc, int level, log_channel chan) { + int debugging, chan_level; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0) + return (0); + + /* Some channels only log when debugging is on. */ + if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging) + return (0); + + /* Some channels use the global level. */ + if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) { + chan_level = lc->level; + } else + chan_level = chan->level; + + if (level > chan_level) + return (0); + + return (1); +} + +int +log_check(log_context lc, int category, int level) { + log_channel_list lcl; + int debugging; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + if (log_check_channel(lc, level, lcl->channel)) + return (1); + } + return (0); +} + +void +log_vwrite(log_context lc, int category, int level, const char *format, + va_list args) { + log_channel_list lcl; + int pri, debugging, did_vsprintf = 0; + int original_category; + FILE *stream; + int chan_level; + log_channel chan; + struct timeval tv; + struct tm *local_tm; + char *category_name; + char *level_str; + char time_buf[256]; + char level_buf[256]; + + REQUIRE(lc != NULL); + + debugging = (lc->flags & LOG_OPTION_DEBUG); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return; + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + original_category = category; + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + /* + * Get the current time and format it. + */ + time_buf[0]='\0'; + if (gettimeofday(&tv, NULL) < 0) { + syslog(LOG_INFO, "gettimeofday failed in log_vwrite()"); + } else { + local_tm = localtime((time_t *)&tv.tv_sec); + if (local_tm != NULL) { + sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ", + local_tm->tm_mday, months[local_tm->tm_mon], + local_tm->tm_year+1900, local_tm->tm_hour, + local_tm->tm_min, local_tm->tm_sec, + (long)tv.tv_usec/1000); + } + } + + /* + * Make a string representation of the current category and level + */ + + if (lc->category_names != NULL && + lc->category_names[original_category] != NULL) + category_name = lc->category_names[original_category]; + else + category_name = ""; + + if (level >= log_critical) { + if (level >= 0) { + sprintf(level_buf, "debug %d: ", level); + level_str = level_buf; + } else + level_str = level_text[-level-1]; + } else { + sprintf(level_buf, "level %d: ", level); + level_str = level_buf; + } + + /* + * Write the message to channels. + */ + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + chan = lcl->channel; + + if (!log_check_channel(lc, level, chan)) + continue; + + if (!did_vsprintf) { + if (VSPRINTF((lc->buffer, format, args)) > + LOG_BUFFER_SIZE) { + syslog(LOG_CRIT, + "memory overrun in log_vwrite()"); + exit(1); + } + did_vsprintf = 1; + } + + switch (chan->type) { + case log_syslog: + if (level >= log_critical) + pri = (level >= 0) ? 0 : -level; + else + pri = -log_critical; + syslog(chan->out.facility|syslog_priority[pri], + "%s%s%s%s", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + break; + case log_file: + stream = chan->out.file.stream; + if (stream == NULL) { + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + if (chan->out.file.max_size != ULONG_MAX) { + long pos; + + pos = ftell(stream); + if (pos >= 0 && + (unsigned long)pos > + chan->out.file.max_size) + break; + } + fprintf(stream, "%s%s%s%s\n", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + fflush(stream); + break; + case log_null: + break; + default: + syslog(LOG_ERR, + "unknown channel type in log_vwrite()"); + } + } +} + +void +log_write(log_context lc, int category, int level, const char *format, ...) { + va_list args; + + va_start(args, format); + log_vwrite(lc, category, level, format, args); + va_end(args); +} + +/* + * Functions to create, set, or destroy contexts + */ + +int +log_new_context(int num_categories, char **category_names, log_context *lc) { + log_context nlc; + + nlc = memget(sizeof (struct log_context)); + if (nlc == NULL) { + errno = ENOMEM; + return (-1); + } + nlc->num_categories = num_categories; + nlc->category_names = category_names; + nlc->categories = memget(num_categories * sizeof (log_channel_list)); + if (nlc->categories == NULL) { + memput(nlc, sizeof (struct log_context)); + errno = ENOMEM; + return (-1); + } + memset(nlc->categories, '\0', + num_categories * sizeof (log_channel_list)); + nlc->flags = 0U; + nlc->level = 0; + *lc = nlc; + return (0); +} + +void +log_free_context(log_context lc) { + log_channel_list lcl, lcl_next; + log_channel chan; + int i; + + REQUIRE(lc != NULL); + + for (i = 0; i < lc->num_categories; i++) + for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl_next) { + lcl_next = lcl->next; + chan = lcl->channel; + (void)log_free_channel(chan); + memput(lcl, sizeof (struct log_channel_list)); + } + memput(lc->categories, + lc->num_categories * sizeof (log_channel_list)); + memput(lc, sizeof (struct log_context)); +} + +int +log_add_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + lcl = memget(sizeof (struct log_channel_list)); + if (lcl == NULL) { + errno = ENOMEM; + return(-1); + } + lcl->channel = chan; + lcl->next = lc->categories[category]; + lc->categories[category] = lcl; + chan->references++; + return (0); +} + +int +log_remove_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl, prev_lcl, next_lcl; + int found = 0; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + for (prev_lcl = NULL, lcl = lc->categories[category]; + lcl != NULL; + lcl = next_lcl) { + next_lcl = lcl->next; + if (lcl->channel == chan) { + log_free_channel(chan); + if (prev_lcl != NULL) + prev_lcl->next = next_lcl; + else + lc->categories[category] = next_lcl; + memput(lcl, sizeof (struct log_channel_list)); + /* + * We just set found instead of returning because + * the channel might be on the list more than once. + */ + found = 1; + } else + prev_lcl = lcl; + } + if (!found) { + errno = ENOENT; + return (-1); + } + return (0); +} + +int +log_option(log_context lc, int option, int value) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + switch (option) { + case LOG_OPTION_DEBUG: + if (value) + lc->flags |= option; + else + lc->flags &= ~option; + break; + case LOG_OPTION_LEVEL: + lc->level = value; + break; + default: + errno = EINVAL; + return (-1); + } + return (0); +} + +int +log_category_is_active(log_context lc, int category) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + if (category >= 0 && category < lc->num_categories && + lc->categories[category] != NULL) + return (1); + return (0); +} + +log_channel +log_new_syslog_channel(unsigned int flags, int level, int facility) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_syslog; + chan->flags = flags; + chan->level = level; + chan->out.facility = facility; + chan->references = 0; + return (chan); +} + +log_channel +log_new_file_channel(unsigned int flags, int level, + char *name, FILE *stream, unsigned int versions, + unsigned long max_size) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_file; + chan->flags = flags; + chan->level = level; + if (name != NULL) { + size_t len; + + len = strlen(name); + /* + * Quantize length to a multiple of 256. There's space for the + * NUL, since if len is a multiple of 256, the size chosen will + * be the next multiple. + */ + chan->out.file.name_size = ((len / 256) + 1) * 256; + chan->out.file.name = memget(chan->out.file.name_size); + if (chan->out.file.name == NULL) { + memput(chan, sizeof (struct log_channel)); + errno = ENOMEM; + return (NULL); + } + /* This is safe. */ + strcpy(chan->out.file.name, name); + } else { + chan->out.file.name_size = 0; + chan->out.file.name = NULL; + } + chan->out.file.stream = stream; + chan->out.file.versions = versions; + chan->out.file.max_size = max_size; + chan->references = 0; + return (chan); +} + +log_channel +log_new_null_channel() { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_null; + chan->flags = LOG_CHANNEL_OFF; + chan->level = log_info; + chan->references = 0; + return (chan); +} + +int +log_inc_references(log_channel chan) { + if (chan == NULL) { + errno = EINVAL; + return (-1); + } + chan->references++; + return (0); +} + +int +log_dec_references(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + return (0); +} + +log_channel_type +log_get_channel_type(log_channel chan) { + REQUIRE(chan != NULL); + + return (chan->type); +} + +int +log_free_channel(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + if (chan->references == 0) { + if (chan->type == log_file) { + if ((chan->flags & LOG_CLOSE_STREAM) && + chan->out.file.stream != NULL) + (void)fclose(chan->out.file.stream); + if (chan->out.file.name != NULL) + memput(chan->out.file.name, + chan->out.file.name_size); + } + memput(chan, sizeof (struct log_channel)); + } + return (0); +} diff --git a/contrib/bind/lib/isc/logging.mdoc b/contrib/bind/lib/isc/logging.mdoc new file mode 100644 index 0000000..6fdb618 --- /dev/null +++ b/contrib/bind/lib/isc/logging.mdoc @@ -0,0 +1,1044 @@ +.\" $Id: logging.mdoc,v 8.2 1998/02/06 01:54:34 halley Exp $ +.\" +.\"Copyright (c) 1995, 1996, 1997, 1998 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.\" The following six UNCOMMENTED lines are required. +.Dd January 1, 1996 +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\"Dt DOCUMENT_TITLE [section number] [volume] +.Dt LOGGING @SYSCALL_EXT@ +.Sh NAME +.Nm log_open_stream , +.Nm log_close_stream , +.Nm log_get_stream , +.Nm log_get_filename , +.Nm log_vwrite , +.Nm log_write , +.Nm log_new_context , +.Nm log_free_context , +.Nm log_add_channel , +.Nm log_remove_channel , +.Nm log_option , +.Nm log_category_is_active , +.Nm log_new_syslog_channel , +.Nm log_new_file_channel , +.Nm log_new_null_channel , +.Nm log_inc_references , +.Nm log_dec_references , +.Nm log_free_channel +.Nd logging system +.Sh SYNOPSIS +.Fd #include <isc/logging.h> +.Ft FILE * +.Fn log_open_stream "log_channel chan" +.Ft int +.Fn log_close_stream "log_channel chan" +.Ft FILE * +.Fn log_get_stream "log_channel chan" +.Ft char * +.Fn log_get_filename "log_channel chan" +.Ft void +.Fn log_vwrite "log_context lc" "int category" "int level" \ + "const char *format" va_list args" +.Ft void +.Fn log_write "log_context lc" "int category" "int level" \ + "const char *format" "..." +.Ft int +.Fn log_check_channel "log_context lc" "int level" "log_channel chan" +.Ft int +.Fn log_check "log_context lc" "int category" "int level" +.Ft int +.Fn log_new_context "int num_categories" "char **category_names" \ + "log_context *lc" +.Ft void +.Fn log_free_context "log_context lc" +.Ft int +.Fn log_add_channel "log_context lc" "int category" "log_channel chan" +.Ft int +.Fn log_remove_channel "log_context lc" "int category" "log_channel chan" +.Ft int +.Fn log_option "log_context lc" "int option" "int value" +.Ft int +.Fn log_category_is_active "log_context lc" "int category" +.Ft log_channel +.Fn log_new_syslog_channel "unsigned int flags" "int level" "int facility" +.Ft log_channel +.Fn log_new_file_channel "unsigned int flags" "int level" \ + "char *name" "FILE *stream" "unsigned int versions" \ + "unsigned long max_size" +.Ft log_channel +.Fn log_new_null_channel "void" +.Ft int +.Fn log_inc_references "log_channel chan" +.Ft int +.Fn log_dec_references "log_channel chan" +.Ft int +.Fn log_free_channel "log_channel chan" +.Sh DESCRIPTION +The +.Sy ISC +.Nm logging library +is flexible logging system which is based upon a set of concepts: +.Nm logging channels , +.Nm categories , +and +.Nm logging contexts . +.Pp +The basic building block is the +.Dq Nm logging channel , +which includes a +.Nm priority +(logging level), which type of logging is to occur, and other +flags and information associated with technical aspects of the logging. +The set of priorities which are supported is shown below, in the section +.Sx Message Priorities . +A priority sets a threshold for message logging; a logging channel will +.Em only +log those messages which are +.Em at least as important +as its priority indicates. (The fact that +.Dq more important +means +.Dq more negative , +under the current scheme, is an implementation detail; if a channel has +a priority of +.Dv log_error , +then it will +.Em not +log messages with the +.Dv log_warning +priority, but it +.Em will +log messages with the +.Dv log_error +or +.Dv log_critical +priority.) +.Pp +The +.Nm logging channel +also has an indication of the type of logging performed. Currently, +the supported +.Nm logging types +include (see also +.Sx Logging Types , +below): +.Bl -tag -width "log_syslog" -compact -offset indent +.It Dv log_syslog +for +.Xr syslog 3 Ns -style +logging +.It Dv log_file +for use of a file +.It Dv log_null +for +.Em no +logging +.El +A new logging channel is created by calling either +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +or +.Fn log_new_null_channel , +respectively. +When a channel is no longer to be used, it can be freed using +.Fn log_free_channel . +.Pp +Both +.Dv log_syslog +and +.Dv log_file +channel types can include more information; for instance, a +.Dv log_syslog Ns -type +channel allows the specification of a +.Xr syslog 3 Ns -style +.Dq facility , +and a +.Dv log_file Ns -type +channels allows the caller to set a maximum file size and number +of versions. (See +.Fn log_new_syslog_channel +or +.Fn log_new_file_channel , +below.) +Additionally, once a logging channel of type +.Dv log_file +is defined, the functions +.Fn log_open_stream +and +.Fn log_close_stream +can open or close the stream associated with the logging channel's logging +filename. The +.Fn log_get_stream +and +.Fn log_get_filename +functions return the stream or filename, respectively, of such a logging +channel. +.Pp +Callers provide +.Dq Nm categories , +determining both the number of such categories and any (optional) names. +Categories are like array indexes in C; if the caller declares +.Dq Va n +categories, then they are considered to run from 0 to +.Va n-1 ; +with this scheme, a category number would be invalid if it were negative or +greater than/equal to +.Va n . +Each category can have its own list of +.Nm logging channels +associated with it; we say that such a channel is +.Dq in +the particular category. +.Sy NOTE: +Individual logging channels can appear in more than one category. +.Pp +A +.Dq Nm logging context +is the set of all +.Nm logging channels +associated with the context's +.Nm categories; +thus, a particular +.Nm category +scheme is associated with a particular +.Nm logging context. +.Sy NOTE: +A logging channel may appear in more than one logging context, and in +multiple categories within each logging context. +.Pp +Use +.Fn log_add_channel +and +.Fn log_remove_channel +to add or remove a logging channel to some category in a logging context. +To see if a given category in a logging context is being used, use the +Boolean test +.Fn log_category_is_active . +.Pp +A +.Nm logging context +can also have a +.Nm priority +(logging level) +and various flags associated with the whole context; in order to alter the +flags or change the priority of a context, use +.Fn log_option . +.Ss Message Priorities +Currently, five +.Nm priorities +(logging levels) are supported (they can also be found in the header file): +.Bd -literal -offset indent +#define log_critical (-5) +#define log_error (-4) +#define log_warning (-3) +#define log_notice (-2) +#define log_info (-1) +.Ed +.Pp +In the current implementation, logging messages which have a level greater +than 0 are considered to be debugging messages. +.Ss Logging Types +The three different +.Nm logging types +currently supported are different values of the enumerated type +.Ft log_output_type +(these are also listed in the header file): +.Bd -literal -offset indent +typedef enum { log_syslog, log_file, log_null } log_output_type; +.Ed +.Ss Logging Channel Flags +There are several flags which can be set on a logging channel; the flags +and their meanings are as follows (they are also found in the header file): +.Bl -tag -width "LOG_USE_CONTEXT_LEVEL " -offset indent +.It Dv LOG_CHANNEL_BROKEN +This is set only when some portion of +.Fn log_open_stream +fails: +.Xr open 2 +or +.Xr fdopen 3 +fail; +.Xr stat 2 +fails in a +.Dq bad +way; versioning or truncation is requested on a non-normal file. +.It Dv LOG_CHANNEL_OFF +This is set for channels opened by +.Fn log_new_null_channel . +.It Dv LOG_CLOSE_STREAM +If this flag is set, then +.Fn log_free_channel +will free a +.No non- Dv NULL +stream of a logging channel which is being +.Xr free 3 Ns -d +(if the logging channel is of type +.Dv log_file , +of course). +.It Dv LOG_PRINT_CATEGORY +If set, +.Fn log_vwrite +will insert the category name, if available, into logging messages which are +logged to channels of type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_PRINT_LEVEL +If set, +.Fn log_vwrite +will insert a string identifying the message priority level into the +information logged to channels of type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_REQUIRE_DEBUG +Only log debugging messages (i.e., those with a priority greater than zero). +.It Dv LOG_TIMESTAMP +If set, +.Fn log_vwrite +will insert a timestamp into logging messages which are logged to channels of +type +.Dv log_syslog +or +.Dv log_file . +.It Dv LOG_TRUNCATE +Truncate logging file when re-opened ( +.Fn log_open_stream +will +.Xr unlink 2 +the file and then +.Xr open 2 +a new file of the same name with the +.Dv O_EXCL +bit set). +.It Dv LOG_USE_CONTEXT_LEVEL +Use the logging context's priority or logging level, rather than the logging +channel's own priority. This can be useful for those channels which are +included in multiple logging contexts. +.El +.Ss FUNCTION DESCRIPTIONS +The function +.Fn log_open_stream +is for use with channels which log to a file; i.e., logging channels with a +.Va type +field set to +.Dq Dv log_file . +If the logging channel pointed to by +.Dq Fa chan +is valid, it attempts to open (and return) the stream associated with that +channel. If the stream is already opened, then it is returned; otherwise, +.Xr stat 2 +is used to test the filename for the stream. +.Pp +At this point, if the logging file is supposed to have different +.Va versions +(i.e., incremented version numbers; higher numbers indicate older versions +of the logging file). If so, then any existing versions are +.Xr rename 2 Ns -d +to have one version-number higher than previously, and the +.Dq current +filename for the stream is set to the +.Dq \&.0 +form of the name. Next, if the logging file is supposed to be truncated +(i.e., the +.Dv LOG_TRUNCATE +bit of the +.Va flags +field of the logging channel structure is set), then any file with the +.Dq current +filename for the stream is +.X4 unlink 2 Ns -d . +.Sy NOTE: +If the logging file is +.Em not +a regular file, and either of the above operations (version numbering +or truncation) is supposed to take place, a +.Dv NULL +file pointer is returned. +.Pp +Finally, the filename associated with the logging channel is +.Xr open 2 Ns -d +using the appropriate flags and a mode which sets the read/write permissions +for the user, group, and others. The file descriptor returned by +.Xr open 2 +is then passed to +.Xr fopen 3 , +with the append mode set, and the stream returned by this call is stored +in the +.Fa chan +structure and returned. +.Pp +If +.Fn log_open_stream +fails at any point, then the +.Dv LOG_CHANNEL_BROKEN +bit of the +.Va flags +field of the logging channel pointed to by +.Fa chan +is set, a +.Dv NULL +is returned, and +.Va errno +contains pertinent information. +.Pp +The +.Fn log_close_stream +function closes the stream associated with the logging channel pointed to by +.Dq Fa chan +(if +.Fa chan +is valid and the stream exists and can be closed properly by +.Xr fclose 3 ) . +The stream is set to +.Dv NULL +even if the call to +.Xr fclose 3 +fails. +.Pp +The function +.Fn log_get_stream +returns the stream associated with the logging channel pointed to by +.Dq Fa chan , +if it is +.No non- Ns Dv NULL +and specifies a logging channel which has a +.Dv FILE * +or stream associated with it. +.Pp +The +.Fn log_get_filename +function returns the name of the file associated with the logging channel +pointed to by +.Dq Fa chan , +if it is +.No non- Ns Dv NULL +and specifies a logging channel which has a file associated with it. +.Pp +The +.Fn log_vwrite +function performs the actual logging of a message to the various logging +channels of a logging context +.Fa lc . +The message consists of an +.Xr fprint 3 Ns -style +.Fa format +and its associated +.Fa args +(if any); it will be written to all logging channels in the given +.Fa category +which have a priority set to +.Fa level +or any +.Em less important +priority value. If the +.Fa category +is not valid or has no logging channels, then the category defaults to 0. +.Pp +There are a number of conditions under which a call to +.Fn log_vwrite +will not result in actually logging the message: if there is no logging channel +at even the default category (0), or if a given channel is either +.Dq broken +or +.Dq off +(i.e., its flags have +.Dv LOG_CHANNEL_BROKEN +or +.Dv LOG_CHANNEL_OFF +set, respectively), or if the logging channel channel is of type +.Dv log_null . +Additionally, if the logging channel's flag has +.Dv LOG_REQUIRE_DEBUG +set and the message is not a debugging message (i.e., has a level greater +than 0), then it will not be logged. +Finally, if the message's priority is less important than the +channel's logging level (the priority threshold), will not be logged. +.Sy NOTE: +If a logging channel's flag has +.Dv LOG_USE_CONTEXT_LEVEL +set, it will use the logging context's priority, rather than its own. +.Pp +If all of these hurdles are passed, then only +.Dv log_syslog +and +.Dv log_file +channels actually can have logging. For channels which use +.Xr syslog 3 , +the channel's +.Xr syslog 3 +facility is used in conjunction with a potentially modified form of the +message's priority level, since +.Xr syslog 3 +has its own system of priorities +.Pq Pa /usr/include/syslog.h . +All debug messages (priority >= 0) are mapped to +.Xr syslog 3 Ns 's +.Dv LOG_DEBUG +priority, all messages +.Dq more important +than +.Dv log_critical +are mapped to +.Dv LOG_CRIT , +and the priorities corresponding to the ones listed in the section +.Sx Message Priorities +are given the obvious corresponding +.Xr syslog 3 +priority. +.Pp +For +.Dv log_file +type logging channels, if the file size is greater than the maximum file +size, then no logging occurs. (The same thing happens if a +.Dv NULL +stream is encountered and +.Fn log_open_stream +fails to open the channel's stream.) +.Pp +For both logging to normal files and logging via +.Xr syslog 3 , +the value of the flags +.Dv LOG_TIMESTAMP , +.Dv LOG_PRINT_CATEGORY , +and +.Dv LOG_PRINT_LEVEL +are used in determining whether or not these items are included in the logged +information. +.Pp +The +.Fn log_write +function is merely a front-end to a call to +.Fn log_vwrite ; +see the description of that function, above, for more information. +.Pp +.Fn log_check +and +.Fn log_check_channel +are used to see if a contemplated logging call will actually generate any +output, which is useful when creating a log message involves non-trivial +work. +.Fn log_check +will return non-zero if a call to +.Fn log_vwrite +with the given +.Fa category +and +.Fa level +would generate output on any channels, and zero otherwise. +.Fn log_check_channel +will return non-zero if writing to the +.Fa chan +at the given +.Fa level +would generate output. +.Pp +The function +.Fn log_new_context +creates a new +.Nm logging context , +and stores this in the +.Dq Va opaque +field of the argument +.Dq Fa lc , +and opaque structure used internally. This new +.Nm context +will include the +.Dq Fa num_categories +and +.Dq Fa category_names +which are supplied; the latter can be +.Dv NULL . +.Sy NOTE: +Since +.Dq Fa category_names +is used directly, it +.Em must not +be freed by the caller, if it is +.No non- Ns Dv NULL . +The initial logging flags and priority are both set to zero. +.Pp +The +.Fn log_free_context +function is used to free the opaque structure +.Dq Va lc.opaque +and its components. +.Sy NOTE: +The +.Dq Va opaque +field of +.Dq Fa lc +.Em must +be +.No non- Ns Dv NULL . +For each of the various +.Dq categories +(indicated by the +.Dq Va num_categories +which were in the corresponding call to +.Fn log_new_context ) +associated with the given +.Nm logging context , +.Em all +of the +.Nm logging channels +are +.Xr free 3 Ns -d . +The opaque structure itself is then +.Xr free 3 Ns -d , +and +.Dq Va lc.opaque +is set to +.Dv NULL . +.Pp +.Sy NOTE: +The function +.Fn log_free_context +does +.Em not +free the memory associated with +.Fa category_names , +since the logging library did not allocate the memory for it, originally; +it was supplied in the call to +.Fn log_new_context . +.Pp +The function +.Fn log_add_channel +adds the +.Nm logging channel +.Dq Fa chan +to the list of logging channels in the given +.Fa category +of the +.Nm logging context +.Dq Fa lc . +No checking is performed to see whether or not +.Fa chan +is already present in the given +.Fa category , +so multiple instances in a single +.Fa category +can occur (but see +.Fn log_remove_channel , +below). +.Pp +The +.Fn log_remove_channel +function +removes +.Em all +occurrences of the +.Nm logging channel +.Dq Fa chan +from the list of logging channels in the given +.Fa category +of the +.Nm logging context +.Dq Fa lc . +It also attempts to free the channel by calling +.Fn log_free_channel +(see its description, below). +.Pp +The +.Fn log_option +function is used to change the +.Fa option +of the indicated logging context +.Fa lc +to the given +.Fa value . +The +.Fa option +can be either +.Dv LOG_OPTION_LEVEL +or +.Dv LOG_OPTION_DEBUG ; +in the first case, the log context's debugging level is reset to the +indicated level. If the +.Fa option +is +.Dv LOG_OPTION_DEBUG , +then a non-zero +.Fa value +results in setting the debug flag of the logging context, while a zero +.Fa value +means that the debug flag is reset. +.Pp +The +.Fn log_category_is_active +test returns a 1 if the given +.Fa category +of the indicated logging context +.Fa lc +has at least one logging channel, and 0, otherwise. +.Pp +The functions +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +and +.Fn log_new_null_channel +create a new channel of the type specified (thus, the difference in arguments); +the +.Dq Va type +field of the new +.Dq Ft struct log_channel +is always set to the appropriate value. +.Pp +The +.Fn log_new_syslog_channel +function +.Xr malloc 3 Ns -s +a new +.Ft struct log_channel +of +.Va type +.Dv log_syslog , +i.e., a logging channel which will use +.Xr syslog 3 . +The new structure is filled out with the +.Dq Fa flags , +.Dq Fa level , +and +.Dq Fa facility +which are given; the +.Va references +field is initialized to zero. +See +.Sx Logging Channel Flags +and +.Sx Message Priorities , +above, or the header file for information about acceptable values for +.Dq Fa flags , +and +.Dq Fa level . +The +.Dq Fa facility . +can be any valid +.Xr syslog 3 +facility; see the appropriate system header file or manpage for more +information. +.Pp +.Ft log_channel +.Fn log_new_file_channel "unsigned int flags" "int level" \ + "char *name" "FILE *stream" "unsigned int versions" \ + "unsigned long max_size" +.Pp +.Fn log_new_null_channel +.Pp +The functions +.Fn log_inc_references +and +.Fn log_dec_references +increment or decrements, respectively, the +.Va references +field of the logging channel pointed to by +.Dq Fa chan , +if it is a valid channel (and if the +.Va references +field is strictly positive, in the case of +.Fn log_dec_references ) . +These functions are meant to track changes in the number of different clients +which refer to the given logging channel. +.Pp +The +.Fn log_free_channel +function frees the +field of the logging channel pointed to by +.Dq Fa chan +if there are no more outstanding references to it. If the channel uses a file, +the stream is +.Xr fclose 3 Ns -d +(if the +.Dv LOG_CLOSE_STREAM +flag is set), and the filename, if +.No non- Ns Dv NULL , +is +.Xr free 3 Ns -d +before +.Dq Fa chan +is +.Xr free 3 Ns -d . +.Pp +.\" The following requests should be uncommented and +.\" used where appropriate. This next request is +.\" for sections 2 and 3 function return values only. +.Sh RETURN VALUES +.\" This next request is for sections 1, 6, 7 & 8 only +.Bl -tag -width "log_category_is_active()" +.It Fn log_open_stream +.Dv NULL +is returned under any of several error conditions: +a) if +.Dq Fa chan +is either +.Dv NULL +or a +.No non- Ns Dv log_file +channel +.Pq Va errno No is set to Dv EINVAL ; +b) if either versioning or truncation is requested for a non-normal file +.Pq Va errno No is set to Dv EINVAL ; +c) if any of +.Xr stat 2 , +.Xr open 2 , +or +.Xr fdopen 3 +fails +.Po Va errno +is set by the call which failed +.Pc . +If some value other than +.Dv NULL +is returned, then it is a valid logging stream (either newly-opened or +already-open). +.It Fn log_close_stream +-1 if the stream associated with +.Dq Fa chan +is +.No non- Ns Dv NULL +and the call to +.Xr fclose 3 +fails. +0 if successful or the logging channel pointed to by +.Dq Fa chan +is invalid (i.e., +.Dv NULL +or not a logging channel which has uses a file); in the latter case, +.Va errno +is set to +.Dv EINVAL . +.It Fn log_get_stream +.Dv NULL +under the same conditions as those under which +.Fn log_close_stream , +above, returns 0 (including the setting of +.Va errno ) . +Otherwise, the stream associated with the logging channel is returned. +.It Fn log_get_filename +.Dv NULL +under the same conditions as those under which +.Fn log_close_stream , +above, returns 0 (including the setting of +.Va errno ) . +Otherwise, the name of the file associated with the logging channel is +returned. +.It Fn log_new_context +-1 if +.Xr malloc 3 +fails +.Pq with Va errno No set to Dv ENOMEM . +Otherwise, 0, with +.Dq Va lc->opaque +containing the new structures and information. +.It Fn log_add_channel +-1 if +a) either +.Dq Va lc.opaque +is +.Dv NULL +or +.Fa category +is invalid (negative or greater than or equal to +.Va lcp->num_categories ), with +.Va errno +set to +.Dv EINVAL ; +b) +.Xr malloc 3 +fails +.Pq with Va errno No set to Dv ENOMEM . +Otherwise, 0. +.It Fn log_remove_channel +-1 if +a) either +.Dq Va lc.opaque +is +.Dv NULL +or +.Fa category +is invalid, as under failure condition a) for +.Fn log_add_channel , +above, including the setting of +.Va errno ; +b) no channel numbered +.Fa chan +is found in the logging context indicated by +.Fa lc +.Pq with Va errno No set to Dv ENOENT . +Otherwise, 0. +.It Fn log_option +-1 if +a) +.Dq Va lc.opaque +is +.Dv NULL , +b) +.Fa option +specifies an unknown logging option ; +in either case, +.Va errno +is set to +.Dv EINVAL . +Otherwise, 0. +.It Fn log_category_is_active +-1 if +.Dq Va lc.opaque +is +.Dv NULL +.Pq with Va errno No set to Dv EINVAL ; +1 if the +.Fa category +number is valid and there are logging channels in this +.Fa category +within the indicated logging context; 0 if the +.Fa category +number is invalid or there are no logging channels in this +.Fa category +within the indicated logging context. +.It Fn log_new_syslog_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_syslog Ns -type +.Ft log_channel . +.It Fn log_new_file_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_file Ns -type +.Ft log_channel . +.It Fn log_new_null_channel +.Dv NULL +if +.Xr malloc 3 +fails +.Pq with Va errno No set to ENOMEM ; +otherwise, a valid +.Dv log_null Ns -type +.Ft log_channel . +.It Fn log_inc_references +-1 if +.Dq Fa chan +is +.Dv NULL +.Pq with Va errno set to Dv EINVAL . +Otherwise, 0. +.It Fn log_dec_references +-1 if +.Dq Fa chan +is +.Dv NULL +or its +.Va references +field is already <= 0 +.Pq with Va errno set to Dv EINVAL . +Otherwise, 0. +.It Fn log_free_channel +-1 under the same conditions as +.Fn log_dec_references , +above, including the setting of +.Va errno ; +0 otherwise. +.El +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width "isc/logging.h" +.It Pa isc/logging.h +include file for logging library +.It Pa syslog.h +.Xr syslog 3 Ns -style +priorities +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.\" .Sh DIAGNOSTICS +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +This table shows which functions can return the indicated error in the +.Va errno +variable; see the +.Sx RETURN VALUES +section, above, for more information. +.Bl -tag -width "(any0other0value)0" +.It Dv EINVAL +.Fn log_open_stream , +.Fn log_close_stream , +.Fn log_get_stream , +.Fn log_get_filename , +.Fn log_add_channel , +.Fn log_remove_channel , +.Fn log_option , +.Fn log_category_is_active , +.Fn log_inc_references , +.Fn log_dec_references , +.Fn log_free_channel . +.It Dv ENOENT +.Fn log_remove_channel . +.It Dv ENOMEM +.Fn log_new_context , +.Fn log_add_channel , +.Fn log_new_syslog_channel , +.Fn log_new_file_channel , +.Fn log_new_null_channel . +.It (any other value) +returned via a pass-through of an error code from +.Xr stat 2 , +.Xr open 2 , +or +.Xr fdopen 3 , +which can occur in +.Fn log_open_stream +and functions which call it +.Pq currently, only Fn log_vwrite . +.El +.Pp +Additionally, +.Fn log_vwrite +and +.Fn log_free_context +will fail via +.Fn assert +if +.Dq Va lc.opaque +is +.Dv NULL . +The function +.Fn log_vwrite +can also exit with a critical error logged via +.Xr syslog 3 +indicating a memory overrun +.Sh SEE ALSO +.Xr @INDOT@named @SYS_OPS_EXT@ , +.Xr syslog 3 . +The HTML documentation includes a file, +.Pa logging.html , +which has more information about this logging system. +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +Bob Halley...TODO +.\" .Sh BUGS diff --git a/contrib/bind/lib/isc/logging_p.h b/contrib/bind/lib/isc/logging_p.h new file mode 100644 index 0000000..317582d --- /dev/null +++ b/contrib/bind/lib/isc/logging_p.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1996, 1997 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. + */ + +#ifndef LOGGING_P_H +#define LOGGING_P_H + +typedef struct log_file_desc { + char *name; + size_t name_size; + FILE *stream; + unsigned int versions; + unsigned long max_size; +} log_file_desc; + +typedef union log_output { + int facility; + log_file_desc file; +} log_output; + +struct log_channel { + int level; /* don't log messages > level */ + log_channel_type type; + log_output out; + unsigned int flags; + int references; +}; + +typedef struct log_channel_list { + log_channel channel; + struct log_channel_list *next; +} *log_channel_list; + +#define LOG_BUFFER_SIZE 20480 + +struct log_context { + int num_categories; + char **category_names; + log_channel_list *categories; + int flags; + int level; + char buffer[LOG_BUFFER_SIZE]; +}; + +#endif /* !LOGGING_P_H */ diff --git a/contrib/bind/lib/isc/memcluster.c b/contrib/bind/lib/isc/memcluster.c new file mode 100644 index 0000000..0cdd3d4 --- /dev/null +++ b/contrib/bind/lib/isc/memcluster.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 1997 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: memcluster.c,v 8.7 1998/03/27 00:17:31 halley Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <isc/memcluster.h> +#include <isc/assertions.h> + +#include "port_after.h" + +#define DEF_MAX_SIZE 1100 +#define DEF_MEM_TARGET 4096 + +typedef struct { + void * next; +} memcluster_element; + +#define SMALL_SIZE_LIMIT sizeof(memcluster_element) +#define P_SIZE sizeof(void *) + +struct stats { + u_long gets; + u_long puts; + u_long blocks; + u_long freefrags; +}; + +/* Private data. */ + +static size_t max_size; +static size_t mem_target; +static size_t mem_target_half; +static size_t mem_target_fudge; +static memcluster_element ** freelists; +static struct stats * stats; + +/* Forward. */ + +static size_t quantize(size_t); + +/* Public. */ + +int +meminit(size_t init_max_size, size_t target_size) { + int i; + + if (freelists != NULL) { + errno = EEXIST; + return (-1); + } + if (init_max_size == 0) + max_size = DEF_MAX_SIZE; + else + max_size = init_max_size; + if (target_size == 0) + mem_target = DEF_MEM_TARGET; + else + mem_target = target_size; + mem_target_half = mem_target / 2; + mem_target_fudge = mem_target + mem_target / 4; + freelists = malloc(max_size * sizeof (memcluster_element *)); + stats = malloc((max_size+1) * sizeof (struct stats)); + if (freelists == NULL || stats == NULL) { + errno = ENOMEM; + return (-1); + } + memset(freelists, 0, + max_size * sizeof (memcluster_element *)); + memset(stats, 0, (max_size + 1) * sizeof (struct stats)); + + return (0); +} + +void * +__memget(size_t size) { + size_t new_size = quantize(size); + void *ret; + + if (freelists == NULL) + if (meminit(0, 0) == -1) + return (NULL); + if (size == 0) { + errno = EINVAL; + return (NULL); + } + if (size >= max_size || new_size >= max_size) { + /* memget() was called on something beyond our upper limit. */ + stats[max_size].gets++; + return (malloc(size)); + } + + /* + * 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 (freelists[new_size] == NULL) { + int i, frags; + size_t total_size; + void *new; + char *curr, *next; + + if (new_size > mem_target_half) + total_size = mem_target_fudge; + else + total_size = mem_target; + new = malloc(total_size); + if (new == NULL) { + errno = ENOMEM; + return (NULL); + } + frags = total_size / new_size; + stats[new_size].blocks++; + stats[new_size].freefrags += frags; + /* Set up a linked-list of blocks of size "new_size". */ + curr = new; + next = curr + new_size; + for (i = 0; i < (frags - 1); i++) { + ((memcluster_element *)curr)->next = next; + curr = next; + next += new_size; + } + /* curr is now pointing at the last block in the array. */ + ((memcluster_element *)curr)->next = freelists[new_size]; + freelists[new_size] = new; + } + + /* The free list uses the "rounded-up" size "new_size": */ + ret = freelists[new_size]; + freelists[new_size] = 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. + */ + stats[size].gets++; + stats[new_size].freefrags--; + return (ret); +} + +/* + * This is a call from an external caller, + * so we want to count this as a user "put". + */ +void +__memput(void *mem, size_t size) { + size_t new_size = quantize(size); + + REQUIRE(freelists != NULL); + + if (size == 0) { + errno = EINVAL; + return; + } + if (size == max_size || new_size >= max_size) { + /* memput() called on something beyond our upper limit */ + free(mem); + INSIST(stats[max_size].puts < stats[max_size].gets); + stats[max_size].puts++; + return; + } + + /* The free list uses the "rounded-up" size "new_size": */ + ((memcluster_element *)mem)->next = freelists[new_size]; + freelists[new_size] = (memcluster_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(stats[size].puts < stats[size].gets); + stats[size].puts++; + stats[new_size].freefrags++; +} + +void * +__memget_debug(size_t size, const char *file, int line) { + void *ptr; + ptr = __memget(size); + fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line, + (u_long)size, ptr); + return (ptr); +} + +void +__memput_debug(void *ptr, size_t size, const char *file, int line) { + fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr, + (u_long)size); + __memput(ptr, size); +} + +/* + * Print the stats[] on the stream "out" with suitable formatting. + */ +void +memstats(FILE *out) { + size_t i; + + if (freelists == NULL) + return; + for (i = 1; i <= max_size; i++) { + const struct stats *s = &stats[i]; + + if (s->gets == 0 && s->puts == 0) + continue; + INSIST(s->gets >= s->puts); + fprintf(out, "%s%5d: %11lu get, %11lu put, %11lu rem", + (i == max_size) ? ">=" : " ", + i, s->gets, s->puts, s->gets - s->puts); + if (s->blocks != 0) + fprintf(out, " (%lu bl, %lu ff)", + s->blocks, s->freefrags); + fputc('\n', out); + } +} + +/* Private. */ + +/* + * Round up size to a multiple of sizeof(void *). This guarantees that a + * block is at least sizeof void *, and that we won't violate alignment + * restrictions, both of which are needed to make lists of blocks. + */ +static size_t +quantize(size_t size) { + int remainder; + /* + * If there is no remainder for the integer division of + * + * (rightsize/P_SIZE) + * + * then we already have a good size; if not, then we need + * to round up the result in order to get a size big + * enough to satisfy the request _and_ aligned on P_SIZE boundaries. + */ + remainder = size % P_SIZE; + if (remainder != 0) + size += P_SIZE - remainder; + return (size); +} + diff --git a/contrib/bind/lib/isc/memcluster.mdoc b/contrib/bind/lib/isc/memcluster.mdoc new file mode 100644 index 0000000..c076972 --- /dev/null +++ b/contrib/bind/lib/isc/memcluster.mdoc @@ -0,0 +1,375 @@ +.\" $Id: memcluster.mdoc,v 8.1 1997/09/26 17:56:10 halley Exp $ +.\" +.\"Copyright (c) 1995, 1996 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.\" The following six UNCOMMENTED lines are required. +.Dd Month day, year +.\"Os OPERATING_SYSTEM [version/release] +.Os BSD 4 +.\"Dt DOCUMENT_TITLE [section number] [volume] +.Dt memcluster 3 +.Sh NAME +.Nm meminit , +.Nm memget , +.Nm memput , +.Nm memstats +.Nd memory allocation/deallocation system +.Sh SYNOPSIS +.Fd #include \&<isc/memcluster.h\&> +.Ft void * +.Fn memget "size_t size" +.Ft void +.Fn memput "void *mem" "size_t size" +.Ft void +.Fn memstats "FILE *out" +.Sh DESCRIPTION +These functions access a memory management system which allows callers to not +fragment memory to the extent which can ordinarily occur through many random +calls to +.Xr malloc 3 . +Instead, +.Fn memget +gets a large contiguous chunk of blocks of the requested +.Fa size +and parcels out these blocks as requested. The symmetric call is +.Fn memput , +which callers use to return a piece of memory obtained from +.Fn memget . +Statistics about memory usage are returned by +.Fn memstats , +which prints a report on the stream +.Fa out . +.Ss INTERNALS +Internally, linked lists of free memory blocks are stored in an array. +The size of this array is determined by the value +.Dv MEM_FREECOUNT , +currently set to 1100. In general, for any requested blocksize +.Dq Fa size , +any free blocks will be stored on the linked list at that index. +No free lists are managed for blocks greater than or equal to +.Dv MEM_FREECOUNT +bytes; instead, calls to +.Xr malloc 3 +or +.Xr free 3 +are made, directly. +.Pp +Since the blocks are actually stored as linked lists, they must at least +be large enough to hold a pointer to the next block. This size, which is +.Dv SMALL_SIZE_LIMIT , +is currently defined as +.Bd -literal -offset indent +#define SMALL_SIZE_LIMIT sizeof(struct { void *next; }) +.Ed +.Pp +Both +.Fn memget +and +.Fn memput +enforce this limit; for example, any call to +.Fn memget +requesting a block smaller than +.Dv SMALL_SIZE_LIMIT +bytes will actually be considered to be of size +.Dv SMALL_SIZE_LIMIT +internally. (Such a caller request will be logged for +.Fn memstats +purposes using the caller-requested +.Fa size ; +see the discussion of +.Fn memstats , +below, for more information.) +.Pp +Additionally, the requested +.Fa size +will be adjusted so that when a large +.Xr malloc 3 Ns No -d +chunk of memory is broken up into a linked list, the blocks will all fall on +the correct memory alignment boundaries. Thus, one can conceptualize a call +which mentions +.Fa size +as resulting in a +.Fa new_size +which is used internally. +.Pp +In order to more efficiently allocate memory, there is a +.Dq target +size for calls to +.Xr malloc 3 . +It is given by the pre-defined value +.Dv MEM_TARGET , +which is currently 4096 bytes. +For any requested block +.Fa size , +enough memory is +.Xr malloc 3 Ns No -d +in order to fill up a block of about +.Dv MEM_TARGET +bytes. +.No [ Ns Sy NOTE : +For allocations larger than +.Dv MEM_TARGET Ns No /2 +bytes, there is a +.Dq fudge factor +introduced which boosts the target size by 25% of +.Dv MEM_TARGET . +This means that enough memory for two blocks +will actually be allocated for any +.Fa size +such that +.Pq Dv MEM_TARGET Ns No / 3 +.No < Fa size No < +.Pq Dv MEM_TARGET Ns No *5/8 , +provided that the value of +.Dv MEM_FREECOUNT +is at least as large as the upper limit shown above.] +.Pp +.Ss FUNCTION DESCRIPTIONS +.Pp +The function +.Fn memget +returns a pointer to a block of memory of at least the requested +.Fa size . +After adjusting +.Fa size +to the value +.Va new_size +as mentioned above in the +.Sx INTERNALS +subsection, the internal array of free lists is checked. +If there is no block of the needed +.Va new_size , +then +.Fn memget +will +.Xr malloc 3 +a chunk of memory which is as many times as +.Va new_size +will fit into the target size. This memory is then turned into a linked list +of +.Va new_size Ns No -sized +blocks which are given out as requested; the last such block is the first one +returned by +.Fn memget . +If the requested +.Fa size +is zero or negative, then +.Dv NULL +is returned and +.Va errno +is set to +.Dv EINVAL ; +if +.Fa size +is larger than or equal to the pre-defined maximum size +.Dv MEM_FREECOUNT , +then only a single block of exactly +.Fa size +will be +.Xr malloc 3 Ns No -d +and returned. +.Pp +The +.Fn memput +call is used to return memory once the caller is finished with it. +After adjusting +.Fa size +the the value +.Va new_size +as mentioned in the +.Sx INTERNALS +subsection, above, the block is placed at the head of the free list of +.Va new_size Ns No -sized blocks. +If the given +.Fa size +is zero or negative, then +.Va errno +is set to +.Dv EINVAL , +as for +.Fn memget . +If +.Fa size +is larger than or equal to the pre-defined maximum size +.Dv MEM_FREECOUNT , +then the block is immediately +.Xr free 3 Ns No -d . +.Pp +.Sy NOTE : +It is important that callers give +.Fn memput +.Em only +blocks of memory which were previously obtained from +.Fn memget +if the block is +.Em actually +less than +.Dv SMALL_SIZE_LIMIT +bytes in size. Since all blocks will be added to a free list, any block +which is not at least +.Dv SMALL_SIZE_LIMIT +bytes long will not be able to hold a pointer to the next block in the +free list. +.Pp +The +.Fn memstats +function will summarize the number of calls to +.Fn memget +and +.Fn memput +for any block size from 1 byte up to +.Pq Dv MEM_FREECOUNT No - 1 +bytes, followed by a single line for any calls using a +.Fa size +greater than or equal to +.Dv MEM_FREECOUNT ; +a brief header with shell-style comment lines prefaces the report and +explains the information. The +.Dv FILE +pointer +.Fa out +identifies the stream which is used for this report. Currently, +.Fn memstat +reports the number of calls to +.Fn memget +and +.Fn memput +using the caller-supplied value +.Fa size ; +the percentage of outstanding blocks of a given size (i.e., the percentage +by which calls to +.Fn memget +exceed +.Fn memput ) +are also reported on the line for blocks of the given +.Fa size . +However, the percent of blocks used is computed using the number of +blocks allocated according to the internal parameter +.Va new_size ; +it is the percentage of blocks used to those available at a given +.Va new_size , +and is computed using the +.Em total +number of caller +.Dq gets +for any caller +.Fa size Ns No -s +which map to the internally-computed +.Va new_size . +Keep in mind that +.Va new_size +is generally +.Em not +equal to +.Fa size , +which has these implications: +.Bl -enum -offset -indent means that, for +.It +For +.Fa size +smaller than +.Dv SMALL_SIZE_LIMIT , +.Fn memstat +.Em will +show statistics for caller requests under +.Fa size , +but "percent used" information about such blocks will be reported under +.Dv SMALL_SIZE_LIMIT Ns No -sized +blocks. +.It +As a general case of point 1, internal statistics are reported on the the +line corresponding to +.Va new_size , +so that, for a given caller-supplied +.Fa size , +the associated internal information will appear on that line or on the next +line which shows "percent used" information. +.El +.Pp +.Sy NOTE : +If the caller returns blocks of a given +.Fa size +and requests others of +.Fa size Ns No -s +which map to the same internal +.Va new_size , +it is possible for +.Fn memstats +to report usage of greater than 100% for blocks of size +.Va new_size . +This should be viewed as A Good Thing. +.Sh RETURN VALUES +The function +.Fn memget +returns a +.No non- Ns Dv NULL +pointer to a block of memory of the requested +.Fa size . +It returns +.Dv NULL +if either the +.Fa size +is invalid (less than or equal to zero) or a +.Xr malloc 3 +of a new block of memory fails. In the former case, +.Va errno +is set to +.Dv EINVAL ; +in the latter, it is set to +.Dv ENOMEM . +.Pp +Neither +.Fn memput +nor +.Fn memstats +return a value. +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.\" .Sh FILES +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and +.\" fprintf/stderr type diagnostics) +.\" .Sh DIAGNOSTICS +.\" The next request is for sections 2 and 3 error +.\" and signal handling only. +.Sh ERRORS +.Va errno +is set as follows: +.Bl -tag -width "ENOMEM " -offset indent +.It Dv EINVAL +set by both +.Fn memget +and +.Fn memput +if the +.Fa size +is zero or negative +.It Dv ENOMEM +set by +.Fn memget +if a call to +.Xr malloc 3 +fails +.El +.Sh SEE ALSO +.Xr free 3 , +.Xr malloc 3 . +.\" .Sh STANDARDS +.\" .Sh HISTORY +.Sh AUTHORS +Steven J. Richardson and Paul Vixie, Vixie Enterprises. +.\" .Sh BUGS diff --git a/contrib/bind/lib/isc/tree.c b/contrib/bind/lib/isc/tree.c new file mode 100644 index 0000000..ce500ec --- /dev/null +++ b/contrib/bind/lib/isc/tree.c @@ -0,0 +1,532 @@ +#ifndef LINT +static char RCSid[] = "$Id: tree.c,v 8.6 1997/09/26 17:56:11 halley Exp $"; +#endif + +/* + * tree - balanced binary tree library + * + * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names] + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 23jun86 [added delete uar to add for replaced nodes] + * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224] + * vix 06feb86 [added tree_mung()] + * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221] + * vix 14dec85 [written] + */ + +/* + * This program text was created by Paul Vixie using examples from the book: + * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN + * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul + * Vixie's. + */ + +/* + * Portions Copyright (c) 1996,1997 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. + */ + +/*#define DEBUG "tree"*/ + +#include "port_before.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "port_after.h" + +#include <isc/memcluster.h> +#include <isc/tree.h> + +#ifdef DEBUG +static int debugDepth = 0; +static char *debugFuncs[256]; +# define ENTER(proc) { \ + debugFuncs[debugDepth] = proc; \ + fprintf(stderr, "ENTER(%d:%s.%s)\n", \ + debugDepth, DEBUG, + debugFuncs[debugDepth]); \ + debugDepth++; \ + } +# define RET(value) { \ + debugDepth--; \ + fprintf(stderr, "RET(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return (value); \ + } +# define RETV { \ + debugDepth--; \ + fprintf(stderr, "RETV(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return; \ + } +# define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg); +#else +# define ENTER(proc) ; +# define RET(value) return (value); +# define RETV return; +# define MSG(msg) ; +#endif + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)()); +static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *); +static void del(tree **, int *, tree **, void (*)(), int *); +static void bal_L(tree **, int *); +static void bal_R(tree **, int *); + +void +tree_init(tree **ppr_tree) { + ENTER("tree_init") + *ppr_tree = NULL; + RETV +} + +tree_t +tree_srch(tree **ppr_tree, int (*pfi_compare)(), tree_t p_user) { + ENTER("tree_srch") + + if (*ppr_tree) { + int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data); + + if (i_comp > 0) + RET(tree_srch(&(**ppr_tree).right, + pfi_compare, + p_user)) + + if (i_comp < 0) + RET(tree_srch(&(**ppr_tree).left, + pfi_compare, + p_user)) + + /* not higher, not lower... this must be the one. + */ + RET((**ppr_tree).data) + } + + /* grounded. NOT found. + */ + RET(NULL) +} + +tree_t +tree_add(tree **ppr_tree, int (*pfi_compare)(), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE; + + ENTER("tree_add") + if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar)) + RET(NULL) + RET(p_user) +} + +int +tree_delete(tree **ppr_p, int (*pfi_compare)(), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE, i_uar_called = FALSE; + + ENTER("tree_delete"); + RET(delete(ppr_p, pfi_compare, p_user, pfv_uar, + &i_balance, &i_uar_called)) +} + +int +tree_trav(tree **ppr_tree, int (*pfi_uar)()) { + ENTER("tree_trav") + + if (!*ppr_tree) + RET(TRUE) + + if (!tree_trav(&(**ppr_tree).left, pfi_uar)) + RET(FALSE) + if (!(*pfi_uar)((**ppr_tree).data)) + RET(FALSE) + if (!tree_trav(&(**ppr_tree).right, pfi_uar)) + RET(FALSE) + RET(TRUE) +} + +void +tree_mung(tree **ppr_tree, void (*pfv_uar)()) { + ENTER("tree_mung") + if (*ppr_tree) { + tree_mung(&(**ppr_tree).left, pfv_uar); + tree_mung(&(**ppr_tree).right, pfv_uar); + if (pfv_uar) + (*pfv_uar)((**ppr_tree).data); + memput(*ppr_tree, sizeof(tree)); + *ppr_tree = NULL; + } + RETV +} + +static tree * +sprout(tree **ppr, tree_t p_data, int *pi_balance, + int (*pfi_compare)(), void (*pfv_delete)()) +{ + tree *p1, *p2, *sub; + int cmp; + + ENTER("sprout") + + /* are we grounded? if so, add the node "here" and set the rebalance + * flag, then exit. + */ + if (!*ppr) { + MSG("grounded. adding new node, setting h=true") + *ppr = (tree *) memget(sizeof(tree)); + if (*ppr) { + (*ppr)->left = NULL; + (*ppr)->right = NULL; + (*ppr)->bal = 0; + (*ppr)->data = p_data; + *pi_balance = TRUE; + } + RET(*ppr); + } + + /* compare the data using routine passed by caller. + */ + cmp = (*pfi_compare)(p_data, (*ppr)->data); + + /* if LESS, prepare to move to the left. + */ + if (cmp < 0) { + MSG("LESS. sprouting left.") + sub = sprout(&(*ppr)->left, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { /* left branch has grown */ + MSG("LESS: left branch has grown") + switch ((*ppr)->bal) { + case 1: + /* right branch WAS longer; bal is ok now */ + MSG("LESS: case 1.. bal restored implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + /* balance WAS okay; now left branch longer */ + MSG("LESS: case 0.. balnce bad but still ok") + (*ppr)->bal = -1; + break; + case -1: + /* left branch was already too long. rebal */ + MSG("LESS: case -1: rebalancing") + p1 = (*ppr)->left; + if (p1->bal == -1) { /* LL */ + MSG("LESS: single LL") + (*ppr)->left = p1->right; + p1->right = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double LR */ + MSG("LESS: double LR") + + p2 = p1->right; + p1->right = p2->left; + p2->left = p1; + + (*ppr)->left = p2->right; + p2->right = *ppr; + + if (p2->bal == -1) + (*ppr)->bal = 1; + else + (*ppr)->bal = 0; + + if (p2->bal == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* if MORE, prepare to move to the right. + */ + if (cmp > 0) { + MSG("MORE: sprouting to the right") + sub = sprout(&(*ppr)->right, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { + MSG("MORE: right branch has grown") + + switch ((*ppr)->bal) { + case -1: + MSG("MORE: balance was off, fixed implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + MSG("MORE: balance was okay, now off but ok") + (*ppr)->bal = 1; + break; + case 1: + MSG("MORE: balance was off, need to rebalance") + p1 = (*ppr)->right; + if (p1->bal == 1) { /* RR */ + MSG("MORE: single RR") + (*ppr)->right = p1->left; + p1->left = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double RL */ + MSG("MORE: double RL") + + p2 = p1->left; + p1->left = p2->right; + p2->right = p1; + + (*ppr)->right = p2->left; + p2->left = *ppr; + + if (p2->bal == 1) + (*ppr)->bal = -1; + else + (*ppr)->bal = 0; + + if (p2->bal == -1) + p1->bal = 1; + else + p1->bal = 0; + + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* not less, not more: this is the same key! replace... + */ + MSG("FOUND: Replacing data value") + *pi_balance = FALSE; + if (pfv_delete) + (*pfv_delete)((*ppr)->data); + (*ppr)->data = p_data; + RET(*ppr) +} + +static int +delete(tree **ppr_p, int (*pfi_compare)(), tree_t p_user, + void (*pfv_uar)(), int *pi_balance, int *pi_uar_called) +{ + tree *pr_q; + int i_comp, i_ret; + + ENTER("delete") + + if (*ppr_p == NULL) { + MSG("key not in tree") + RET(FALSE) + } + + i_comp = (*pfi_compare)((*ppr_p)->data, p_user); + if (i_comp > 0) { + MSG("too high - scan left") + i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } else if (i_comp < 0) { + MSG("too low - scan right") + i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_R(ppr_p, pi_balance); + } else { + MSG("equal") + pr_q = *ppr_p; + if (pr_q->right == NULL) { + MSG("right subtree null") + *ppr_p = pr_q->left; + *pi_balance = TRUE; + } else if (pr_q->left == NULL) { + MSG("right subtree non-null, left subtree null") + *ppr_p = pr_q->right; + *pi_balance = TRUE; + } else { + MSG("neither subtree null") + del(&pr_q->left, pi_balance, &pr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } + if (!*pi_uar_called && pfv_uar) + (*pfv_uar)(pr_q->data); + /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */ + memput(pr_q, sizeof(tree)); + i_ret = TRUE; + } + RET(i_ret) +} + +static void +del(tree **ppr_r, int *pi_balance, tree **ppr_q, + void (*pfv_uar)(), int *pi_uar_called) +{ + ENTER("del") + + if ((*ppr_r)->right != NULL) { + del(&(*ppr_r)->right, pi_balance, ppr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_R(ppr_r, pi_balance); + } else { + if (pfv_uar) + (*pfv_uar)((*ppr_q)->data); + *pi_uar_called = TRUE; + (*ppr_q)->data = (*ppr_r)->data; + *ppr_q = *ppr_r; + *ppr_r = (*ppr_r)->left; + *pi_balance = TRUE; + } + + RETV +} + +static void +bal_L(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_L") + MSG("left branch has shrunk") + + switch ((*ppr_p)->bal) { + case -1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = 1; + *pi_balance = FALSE; + break; + case 1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->right; + b1 = p1->bal; + if (b1 >= 0) { + MSG("single RR") + (*ppr_p)->right = p1->left; + p1->left = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = 1; + p1->bal = -1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double RL") + p2 = p1->left; + b2 = p2->bal; + p1->left = p2->right; + p2->right = p1; + (*ppr_p)->right = p2->left; + p2->left = *ppr_p; + if (b2 == 1) + (*ppr_p)->bal = -1; + else + (*ppr_p)->bal = 0; + if (b2 == -1) + p1->bal = 1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} + +static void +bal_R(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_R") + MSG("right branch has shrunk") + switch ((*ppr_p)->bal) { + case 1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = -1; + *pi_balance = FALSE; + break; + case -1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->left; + b1 = p1->bal; + if (b1 <= 0) { + MSG("single LL") + (*ppr_p)->left = p1->right; + p1->right = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = -1; + p1->bal = 1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double LR") + p2 = p1->right; + b2 = p2->bal; + p1->right = p2->left; + p2->left = p1; + (*ppr_p)->left = p2->right; + p2->right = *ppr_p; + if (b2 == -1) + (*ppr_p)->bal = 1; + else + (*ppr_p)->bal = 0; + if (b2 == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} diff --git a/contrib/bind/lib/isc/tree.mdoc b/contrib/bind/lib/isc/tree.mdoc new file mode 100644 index 0000000..2406219 --- /dev/null +++ b/contrib/bind/lib/isc/tree.mdoc @@ -0,0 +1,154 @@ +.\" $Id: tree.mdoc,v 8.1 1997/01/30 20:27:25 vixie Exp $ +.\" +.\"Copyright (c) 1995, 1996 by Internet Software Consortium +.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +.\"ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +.\"OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +.\"CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\"DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\"PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\"ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +.\"SOFTWARE. +.\" +.Dd April 5, 1994 +.Dt TREE 3 +.Os BSD 4 +.Sh NAME +.Nm tree_init , +.Nm tree_mung , +.Nm tree_srch , +.Nm tree_add , +.Nm tree_delete , +.Nm tree_trav +.Nd balanced binary tree routines +.Sh SYNOPSIS +.Ft void +.Fn tree_init "void **tree" +.Ft void * +.Fn tree_srch "void **tree" "int (*compare)()" "void *data" +.Ft void +.Fn tree_add(tree, compare, data, del_uar) "void **tree" "int (*compare)()" \ +"void *data" "void (*del_uar)()" +.Ft int +.Fn tree_delete(tree, compare, data, del_uar) "void **tree" "int (*compare)()" \ +"void *data" "void (*del_uar)()" +.Ft int +.Fn tree_trav(tree, trav_uar) "void **tree" "int (*trav_uar)()" +.Ft void +.Fn tree_mung(tree, del_uar) "void **tree" "void (*del_uar)()" +.Sh DESCRIPTION +These functions create and manipulate a balanced binary (AVL) tree. Each node +of the tree contains the expected left & right subtree pointers, a short int +balance indicator, and a pointer to the user data. On a 32 bit system, this +means an overhead of 4+4+2+4 bytes per node (or, on a RISC or otherwise +alignment constrained system with implied padding, 4+4+4+4 bytes per node). +There is no key data type enforced by this package; a caller supplied +compare routine is used to compare user data blocks. +.Pp +Balanced binary trees are very fast on searches and replacements, but have a +moderately high cost for additions and deletions. If your application does a +lot more searches and replacements than it does additions and deletions, the +balanced (AVL) binary tree is a good choice for a data structure. +.Pp +.Fn Tree_init +creates an empty tree and binds it to +.Dq Fa tree +(which for this and all other routines in this package should be declared as +a pointer to void or int, and passed by reference), which can then be used by +other routines in this package. Note that more than one +.Dq Fa tree +variable can exist at once; thus multiple trees can be manipulated +simultaneously. +.Pp +.Fn Tree_srch +searches a tree for a specific node and returns either +.Fa NULL +if no node was found, or the value of the user data pointer if the node +was found. +.Fn compare +is the address of a function to compare two user data blocks. This routine +should work much the way +.Xr strcmp 3 +does; in fact, +.Xr strcmp +could be used if the user data was a \s-2NUL\s+2 terminated string. +.Dq Fa Data +is the address of a user data block to be used by +.Fn compare +as the search criteria. The tree is searched for a node where +.Fn compare +returns 0. +.Pp +.Fn Tree_add +inserts or replaces a node in the specified tree. The tree specified by +.Dq Fa tree +is searched as in +.Fn tree_srch, +and if a node is found to match +.Dq Fa data, +then the +.Fn del_uar +function, if non\-\s-2NULL\s+2, is called with the address of the user data +block for the node (this routine should deallocate any dynamic memory which +is referenced exclusively by the node); the user data pointer for the node +is then replaced by the value of +.Dq Fa data. +If no node is found to match, a new node is added (which may or may not +cause a transparent rebalance operation), with a user data pointer equal to +.Dq Fa data. +A rebalance may or may not occur, depending on where the node is added +and what the rest of the tree looks like. +.Fn Tree_add +will return the +.Dq Fa data +pointer unless catastrophe occurs in which case it will return \s-2NULL\s+2. +.Pp +.Fn Tree_delete +deletes a node from +.Dq Fa tree. +A rebalance may or may not occur, depending on where the node is removed from +and what the rest of the tree looks like. +.Fn Tree_delete +returns TRUE if a node was deleted, FALSE otherwise. +.Pp +.Fn Tree_trav +traverses all of +.Dq Fa tree, +calling +.Fn trav_uar +with the address of each user data block. If +.Fn trav_uar +returns FALSE at any time, +.Fn tree_trav +will immediately return FALSE to its caller. Otherwise all nodes will be +reached and +.Fn tree_trav +will return TRUE. +.Pp +.Fn Tree_mung +deletes every node in +.Dq Fa tree, +calling +.Fn del_uar +(if it is not \s-2NULL\s+2) with the user data address from each node (see +.Fn tree_add +and +.Fn tree_delete +above). The tree is left in the same state that +.Fn tree_init +leaves it in \- i.e., empty. +.Sh BUGS +Should have a way for the caller to specify application-specific +.Xr malloc +and +.Xr free +functions to be used internally when allocating meta data. +.Sh AUTHOR +Paul Vixie, converted and augumented from Modula\-2 examples in +.Dq Algorithms & Data Structures , +Niklaus Wirth, Prentice\-Hall, ISBN 0\-13\-022005\-1. diff --git a/contrib/bind/lib/nameser/Makefile b/contrib/bind/lib/nameser/Makefile new file mode 100644 index 0000000..d86dc74 --- /dev/null +++ b/contrib/bind/lib/nameser/Makefile @@ -0,0 +1,73 @@ +# +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. +# + +# $Id: Makefile,v 8.7 1997/05/21 19:32:08 halley Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cruv +RANLIB= ranlib +INSTALL= install + +SRCS= ns_parse.c ns_print.c ns_netint.c ns_ttl.c ns_name.c + +OBJS= ns_parse.${O} ns_print.${O} ns_netint.${O} ns_ttl.${O} ns_name.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/lib/nameser/ns_name.c b/contrib/bind/lib/nameser/ns_name.c new file mode 100644 index 0000000..86c0bbb --- /dev/null +++ b/contrib/bind/lib/nameser/ns_name.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_name.c,v 8.3 1997/04/24 22:10:54 vixie Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> + +#include "port_after.h" + +/* Data. */ + +static char digits[] = "0123456789"; + +/* Forward. */ + +static int special(int); +static int printable(int); +static int dn_find(const u_char *, const u_char *, + const u_char * const *, + const u_char * const *); + +/* Public. */ + +/* + * ns_name_ntop(src, dst, dstsiz) + * Convert an encoded domain name to printable ascii as per RFC1035. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * The root is returned as "." + * All other domains are returned in non absolute form + */ +int +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) != 0) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + if (dn != dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if (dn + n >= eom) { + errno = EMSGSIZE; + return (-1); + } + for ((void)NULL; n > 0; n--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\0'; + return (dn - dst); +} + +/* + * ns_name_pton(src, dst, dstsiz) + * Convert a ascii string into an encoded domain name as per RFC1035. + * return: + * -1 if it fails + * 1 if string was fully qualified + * 0 is string was not fully qualified + * notes: + * Enforces label and domain length limits. + */ + +int +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { + u_char *label, *bp, *eom; + int c, n, escaped; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + if ((cp = strchr(digits, c)) != NULL) { + n = (cp - digits) * 100; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits) * 10; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits); + if (n > 255) { + errno = EMSGSIZE; + return (-1); + } + c = n; + } + escaped = 0; + } else if (c == '\\') { + escaped = 1; + continue; + } else if (c == '.') { + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + /* Fully qualified ? */ + if (*src == '\0') { + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = '\0'; + } + if ((bp - dst) > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + return (1); + } + if (c == 0) { + errno = EMSGSIZE; + return (-1); + } + label = bp++; + continue; + } + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = (u_char)c; + } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = 0; + } + if ((bp - dst) > MAXCDNAME) { /* src too big */ + errno = EMSGSIZE; + return (-1); + } + return (0); +} + +/* + * ns_name_unpack(msg, eom, src, dst, dstsiz) + * Unpack a domain name from a message, source may be compressed. + * return: + * -1 if it fails, or consumed octets if it succeeds. + */ +int +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, c, len, checked; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + /* Limit checks. */ + if (dstp + n + 1 >= dstlim || srcp + n >= eom) { + errno = EMSGSIZE; + return (-1); + } + checked += n + 1; + *dstp++ = n; + memcpy(dstp, srcp, n); + dstp += n; + srcp += n; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /* Out of range. */ + errno = EMSGSIZE; + return (-1); + } + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eom - msg) { + errno = EMSGSIZE; + return (-1); + } + break; + + default: + errno = EMSGSIZE; + return (-1); /* flag error */ + } + } + *dstp = '\0'; + if (len < 0) + len = srcp - src; + return (len); +} + +/* + * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) + * Pack domain name 'domain' into 'comp_dn'. + * return: + * Size of the compressed name, or -1. + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. The array + * ends with NULL. + * 'lastdnptr' is a pointer to the end of the array pointed to + * by 'dnptrs'. + * Side effects: + * The list of pointers in dnptrs is updated for labels inserted into + * the message as we compress the name. If 'dnptr' is NULL, we don't + * try to compress names. If 'lastdnptr' is NULL, we don't update the + * list. + */ +int +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char *dstp; + const u_char **cpp, **lpp, *eob, *msg; + const u_char *srcp; + int n, l; + + srcp = src; + dstp = dst; + eob = dstp + dstsiz; + lpp = cpp = NULL; + if (dnptrs != NULL) { + if ((msg = *dnptrs++) != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + (void)NULL; + lpp = cpp; /* end of list to search */ + } + } else + msg = NULL; + + /* make sure the domain we are about to add is legal */ + l = 0; + do { + n = *srcp; + if ((n & NS_CMPRSFLGS) != 0) { + errno = EMSGSIZE; + return (-1); + } + l += n + 1; + if (l > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + srcp += n + 1; + } while (n != 0); + + srcp = src; + do { + /* Look to see if we can use pointers. */ + n = *srcp; + if (n != 0 && msg != NULL) { + l = dn_find(srcp, msg, (const u_char * const *)dnptrs, + (const u_char * const *)lpp); + if (l >= 0) { + if (dstp + 1 >= eob) { + errno = EMSGSIZE; + return (-1); + } + *dstp++ = (l >> 8) | NS_CMPRSFLGS; + *dstp++ = l % 256; + return (dstp - dst); + } + /* Not found, save it. */ + if (lastdnptr != NULL && cpp < lastdnptr - 1 && + (dstp - msg) < 0x4000) { + *cpp++ = dstp; + *cpp = NULL; + } + } + /* copy label to buffer */ + if (n & NS_CMPRSFLGS) { /* Should not happen. */ + errno = EMSGSIZE; + return (-1); + } + if (dstp + 1 + n >= eob) { + errno = EMSGSIZE; + return (-1); + } + memcpy(dstp, srcp, n + 1); + srcp += n + 1; + dstp += n + 1; + } while (n != 0); + + if (dstp > eob) { + if (msg != NULL) + *lpp = NULL; + errno = EMSGSIZE; + return (-1); + } + return (dstp - dst); +} + +/* + * ns_name_uncompress(msg, eom, src, dst, dstsiz) + * Expand compressed domain name to presentation format. + * return: + * Number of bytes read out of `src', or -1 (with errno set). + * note: + * Root domain returns as "." not "". + */ +int +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + return (-1); + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return (-1); + return (n); +} + +/* + * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) + * Compress a domain name into wire format, using compression pointers. + * return: + * Number of bytes consumed in `dst' or -1 (with errno set). + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. + * The list ends with NULL. 'lastdnptr' is a pointer to the end of the + * array pointed to by 'dnptrs'. Side effect is to update the list of + * pointers for labels inserted into the message as we compress the name. + * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' + * is NULL, we don't update the list. + */ +int +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char tmp[NS_MAXCDNAME]; + + if (ns_name_pton(src, tmp, sizeof tmp) == -1) + return (-1); + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); +} + +/* + * ns_name_skip(ptrptr, eom) + * Advance *ptrptr to skip over the compressed name it points at. + * return: + * 0 on success, -1 (with errno set) on failure. + */ +int +ns_name_skip(const u_char **ptrptr, const u_char *eom) { + const u_char *cp; + u_int n; + + cp = *ptrptr; + while (cp < eom && (n = *cp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + cp += n; + continue; + case NS_CMPRSFLGS: /* indirection */ + cp++; + break; + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + break; + } + if (cp > eom) { + errno = EMSGSIZE; + return (-1); + } + *ptrptr = cp; + return (0); +} + +/* Private. */ + +/* + * special(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? + * return: + * boolean. + */ +static int +special(int ch) { + switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ + /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ + return (1); + default: + return (0); + } +} + +/* + * printable(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + * return: + * boolean. + */ +static int +printable(int ch) { + return (ch > 0x20 && ch < 0x7f); +} + +/* + * Thinking in noninternationalized USASCII (per the DNS spec), + * convert this character to lower case if it's upper case. + */ +static int +mklower(int ch) { + if (ch >= 0x41 && ch <= 0x5A) + return (ch + 0x20); + return (ch); +} + +/* + * dn_find(domain, msg, dnptrs, lastdnptr) + * Search for the counted-label name in an array of compressed names. + * return: + * offset from msg if found, or -1. + * notes: + * dnptrs is the pointer to the first name on the list, + * not the pointer to the start of the message. + */ +static int +dn_find(const u_char *domain, const u_char *msg, + const u_char * const *dnptrs, + const u_char * const *lastdnptr) +{ + const u_char *dn, *cp, *sp; + const u_char * const *cpp; + u_int n; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + dn = domain; + sp = cp = *cpp; + while ((n = *cp++) != 0) { + /* + * check for indirection + */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + if (n != *dn++) + goto next; + for ((void)NULL; n > 0; n--) + if (mklower(*dn++) != mklower(*cp++)) + goto next; + /* Is next root for both ? */ + if (*dn == '\0' && *cp == '\0') + return (sp - msg); + if (*dn) + continue; + goto next; + + case NS_CMPRSFLGS: /* indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + } + next: ; + } + errno = ENOENT; + return (-1); +} diff --git a/contrib/bind/lib/nameser/ns_netint.c b/contrib/bind/lib/nameser/ns_netint.c new file mode 100644 index 0000000..1f640a5 --- /dev/null +++ b/contrib/bind/lib/nameser/ns_netint.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_netint.c,v 8.1 1996/11/18 09:09:57 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +/*#include <sys/types.h>*/ +/*#include <sys/socket.h>*/ + +/*#include <netinet/in.h>*/ +#include <arpa/nameser.h> + +#include "port_after.h" + +u_int +ns_get16(const u_char *src) { + u_int dst; + + NS_GET16(dst, src); + return (dst); +} + +u_long +ns_get32(const u_char *src) { + u_long dst; + + NS_GET32(dst, src); + return (dst); +} + +void +ns_put16(u_int src, u_char *dst) { + NS_PUT16(src, dst); +} + +void +ns_put32(u_long src, u_char *dst) { + NS_PUT32(src, dst); +} diff --git a/contrib/bind/lib/nameser/ns_parse.c b/contrib/bind/lib/nameser/ns_parse.c new file mode 100644 index 0000000..800ea19 --- /dev/null +++ b/contrib/bind/lib/nameser/ns_parse.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_parse.c,v 8.8 1998/02/17 17:20:33 vixie Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> + +#include "port_after.h" + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata _ns_flagdata[16] = { + { 0x8000, 15 }, /* qr. */ + { 0x7800, 11 }, /* opcode. */ + { 0x0400, 10 }, /* aa. */ + { 0x0200, 9 }, /* tc. */ + { 0x0100, 8 }, /* rd. */ + { 0x0080, 7 }, /* ra. */ + { 0x0040, 6 }, /* z. */ + { 0x0020, 5 }, /* ad. */ + { 0x0010, 4 }, /* cd. */ + { 0x000f, 0 }, /* rcode. */ + { 0x0000, 0 }, /* expansion (1/6). */ + { 0x0000, 0 }, /* expansion (2/6). */ + { 0x0000, 0 }, /* expansion (3/6). */ + { 0x0000, 0 }, /* expansion (4/6). */ + { 0x0000, 0 }, /* expansion (5/6). */ + { 0x0000, 0 }, /* expansion (6/6). */ +}; + +static int +skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { + const u_char *optr = ptr; + + for ((void)NULL; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) + goto emsgsize; + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ > eom) + goto emsgsize; + ptr += NS_INT32SZ/*TTL*/; + if (ptr + NS_INT16SZ > eom) + goto emsgsize; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + if (ptr > eom) + goto emsgsize; + return (ptr - optr); + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { + const u_char *eom = msg + msglen; + int i; + + memset(handle, 0x5e, sizeof *handle); + handle->_msg = msg; + handle->_eom = eom; + if (msg + NS_INT16SZ > eom) + goto emsgsize; + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) + goto emsgsize; + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) + goto emsgsize; + NS_GET16(handle->_counts[i], msg); + } + for (i = 0; i < ns_s_max; i++) + if (handle->_counts[i] == 0) + handle->_sections[i] = NULL; + else { + int b = skiprr(msg, eom, (ns_sect)i, + handle->_counts[i]); + + if (b < 0) + return (-1); + handle->_sections[i] = msg; + msg += b; + } + if (msg != eom) + goto emsgsize; + handle->_sect = ns_s_max; + handle->_rrnum = -1; + handle->_ptr = NULL; + return (0); + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { + int b; + + /* Make section right. */ + if (section < 0 || section >= ns_s_max) + goto enodev; + if ((int)section != (int)handle->_sect) { + handle->_sect = section; + handle->_rrnum = 0; + handle->_ptr = handle->_sections[(int)section]; + } + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + goto enodev; + if (rrnum < handle->_rrnum) { + handle->_rrnum = 0; + handle->_ptr = handle->_sections[(int)section]; + } + + b = skiprr(handle->_msg, handle->_eom, section, + rrnum - handle->_rrnum); + if (b < 0) + return (-1); + handle->_ptr += b; + handle->_rrnum = rrnum; + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_ptr += b; + if (handle->_ptr + NS_INT16SZ > handle->_eom) + goto emsgsize; + NS_GET16(rr->type, handle->_ptr); + if (handle->_ptr + NS_INT16SZ > handle->_eom) + goto emsgsize; + NS_GET16(rr->class, handle->_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_ptr + NS_INT32SZ > handle->_eom) + goto emsgsize; + NS_GET32(rr->ttl, handle->_ptr); + if (handle->_ptr + NS_INT16SZ > handle->_eom) + goto emsgsize; + NS_GET16(rr->rdlength, handle->_ptr); + if (handle->_ptr + rr->rdlength > handle->_eom) + goto emsgsize; + rr->rdata = handle->_ptr; + handle->_ptr += rr->rdlength; + } + handle->_rrnum++; + + /* All done. */ + return (0); + enodev: + errno = ENODEV; + return (-1); + emsgsize: + errno = EMSGSIZE; + return (-1); +} diff --git a/contrib/bind/lib/nameser/ns_print.c b/contrib/bind/lib/nameser/ns_print.c new file mode 100644 index 0000000..8ab4766 --- /dev/null +++ b/contrib/bind/lib/nameser/ns_print.c @@ -0,0 +1,751 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_print.c,v 8.4 1998/02/13 01:16:37 halley Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <assert.h> +#include <errno.h> +#include <resolv.h> +#include <string.h> +#include <ctype.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static size_t prune_origin(const char *name, const char *origin); +static int charstr(const u_char *rdata, const u_char *edata, + char **buf, size_t *buflen); +static int addname(const u_char *msg, size_t msglen, + const u_char **p, const char *origin, + char **buf, size_t *buflen); +static void addlen(size_t len, char **buf, size_t *buflen); +static int addstr(const char *src, size_t len, + char **buf, size_t *buflen); +static int addtab(size_t len, size_t target, int spaced, + char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) \ + do { \ + if ((x) < 0) \ + return (-1); \ + } while (0) + +/* Public. */ + +/* + * int + * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) + * Convert an RR to presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrr(const ns_msg *handle, const ns_rr *rr, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + int n; + + n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), + ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), + ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), + name_ctx, origin, buf, buflen); + return (n); +} + +/* + * int + * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, + * name_ctx, origin, buf, buflen) + * Convert the fields of an RR into presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrrf(const u_char *msg, size_t msglen, + const char *name, ns_class class, ns_type type, + u_long ttl, const u_char *rdata, size_t rdlen, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + const char *obuf = buf; + const u_char *edata = rdata + rdlen; + int spaced = 0; + + const char *comment; + char tmp[100]; + int len, x; + + /* + * Owner. + */ + if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) { + T(addstr("\t\t\t", 3, &buf, &buflen)); + } else { + len = prune_origin(name, origin); + if (len == 0) { + T(addstr("@\t\t\t", 4, &buf, &buflen)); + } else { + T(addstr(name, len, &buf, &buflen)); + /* Origin not used and no trailing dot? */ + if ((!origin || !origin[0] || name[len] == '\0') && + name[len - 1] != '.') { + T(addstr(".", 1, &buf, &buflen)); + len++; + } + T(spaced = addtab(len, 24, spaced, &buf, &buflen)); + } + } + + /* + * TTL, Class, Type. + */ + T(x = ns_format_ttl(ttl, buf, buflen)); + addlen(x, &buf, &buflen); + len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); + + /* + * RData. + */ + switch (type) { + case ns_t_a: + if (rdlen != NS_INADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + + case ns_t_hinfo: + case ns_t_isdn: + /* First word. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Second word. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_soa: { + u_long t; + + /* Server name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Administrator name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" (\n", 3, &buf, &buflen)); + spaced = 0; + + if ((edata - rdata) != 5*NS_INT32SZ) + goto formerr; + + /* Serial number. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + len = SPRINTF((tmp, "%lu", t)); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; serial\n", 9, &buf, &buflen)); + spaced = 0; + + /* Refresh interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; refresh\n", 10, &buf, &buflen)); + spaced = 0; + + /* Retry interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; retry\n", 8, &buf, &buflen)); + spaced = 0; + + /* Expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; expiry\n", 9, &buf, &buflen)); + spaced = 0; + + /* Minimum TTL. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(addstr(" )", 2, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; minimum\n", 10, &buf, &buflen)); + + break; + } + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Target. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_px: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_x25: + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_txt: + while (rdata < edata) { + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + if (rdata < edata) + T(addstr(" ", 1, &buf, &buflen)); + } + break; + + case ns_t_nsap: { + char t[255*3]; + + (void) inet_nsap_ntoa(rdlen, rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_aaaa: + if (rdlen != NS_IN6ADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET6, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_loc: { + char t[255]; + + /* XXX protocol format checking? */ + (void) loc_ntoa(rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_naptr: { + u_int order, preference; + char t[50]; + + if (rdlen < 2*NS_INT16SZ) + goto formerr; + + /* Order, Precedence. */ + order = ns_get16(rdata); rdata += NS_INT16SZ; + preference = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u ", order, preference)); + T(addstr(t, len, &buf, &buflen)); + + /* Flags. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Service. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Regexp. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len < 0) + return (-1); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_srv: { + u_int priority, weight, port; + char t[50]; + + if (rdlen < NS_INT16SZ*3) + goto formerr; + + /* Priority, Weight, Port. */ + priority = ns_get16(rdata); rdata += NS_INT16SZ; + weight = ns_get16(rdata); rdata += NS_INT16SZ; + port = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u %u ", priority, weight, port)); + T(addstr(t, len, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_minfo: + case ns_t_rp: + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + + case ns_t_wks: { + int n, lcnt; + + if (rdlen < NS_INT32SZ + 1) + goto formerr; + + /* Address. */ + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += NS_INADDRSZ; + + /* Protocol. */ + len = SPRINTF((tmp, " %u ( ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata += NS_INT8SZ; + + /* Bit map. */ + n = 0; + lcnt = 0; + while (rdata < edata) { + u_int c = *rdata++; + do { + if (c & 0200) { + if (lcnt == 0) { + T(addstr("\n\t\t\t\t", 5, + &buf, &buflen)); + lcnt = 10; + spaced = 0; + } + len = SPRINTF((tmp, "%d ", n)); + T(addstr(tmp, len, &buf, &buflen)); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + T(addstr(")", 1, &buf, &buflen)); + + break; + } + + case ns_t_key: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int keyflags, protocol, algorithm; + const char *leader; + int n; + + if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) + goto formerr; + + /* Key flags, Protocol, Algorithm. */ + keyflags = ns_get16(rdata); rdata += NS_INT16SZ; + protocol = *rdata++; + algorithm = *rdata++; + len = SPRINTF((tmp, "0x%04x %u %u", + keyflags, protocol, algorithm)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Public key data. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len < 0) + goto formerr; + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + + break; + } + + case ns_t_sig: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int type, algorithm, labels, footprint; + const char *leader; + u_long t; + int n; + + if (rdlen < 22) + goto formerr; + + /* Type covered, Algorithm, Label count, Original TTL. */ + type = ns_get16(rdata); rdata += NS_INT16SZ; + algorithm = *rdata++; + labels = *rdata++; + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, " %s %d %lu ", + p_type(type), algorithm, t)); + T(addstr(tmp, len, &buf, &buflen)); + if (labels != (u_int)dn_count_labels(name)) + goto formerr; + + /* Signature expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Time signed. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signature Footprint. */ + footprint = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", footprint)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signer's name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Signature. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + if (len < 0) + goto formerr; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + + break; + } + + case ns_t_nxt: { + int n, c; + + /* Next domain name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Type bit map. */ + n = edata - rdata; + for (c = 0; c < n*8; c++) + if (NS_NXT_BIT_ISSET(c, rdata)) { + len = SPRINTF((tmp, " %s", p_type(c))); + T(addstr(tmp, len, &buf, &buflen)); + } + break; + } + + default: + comment = "unknown RR type"; + goto hexify; + } + return (buf - obuf); + formerr: + comment = "RR format error"; + hexify: { + int n, m; + char *p; + + len = SPRINTF((tmp, "\\#(\t\t; %s", comment)); + T(addstr(tmp, len, &buf, &buflen)); + while (rdata < edata) { + p = tmp; + p += SPRINTF((p, "\n\t")); + spaced = 0; + n = MIN(16, edata - rdata); + for (m = 0; m < n; m++) + p += SPRINTF((p, "%02x ", rdata[m])); + T(addstr(tmp, p - tmp, &buf, &buflen)); + if (n < 16) { + T(addstr(")", 1, &buf, &buflen)); + T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); + } + p = tmp; + p += SPRINTF((p, "; ")); + for (m = 0; m < n; m++) + *p++ = (isascii(rdata[m]) && isprint(rdata[m])) + ? rdata[m] + : '.'; + T(addstr(tmp, p - tmp, &buf, &buflen)); + rdata += n; + } + return (buf - obuf); + } +} + +/* Private. */ + +/* + * size_t + * prune_origin(name, origin) + * Find out if the name is at or under the current origin. + * return: + * Number of characters in name before start of origin, + * or length of name if origin does not match. + * notes: + * This function should share code with samedomain(). + */ +static size_t +prune_origin(const char *name, const char *origin) { + const char *oname = name; + + while (*name != '\0') { + if (origin != NULL && strcasecmp(name, origin) == 0) + return (name - oname - (name > oname)); + while (*name != '\0') { + if (*name == '\\') { + name++; + /* XXX need to handle \nnn form. */ + if (*name == '\0') + break; + } else if (*name == '.') { + name++; + break; + } + name++; + } + } + return (name - oname); +} + +/* + * int + * charstr(rdata, edata, buf, buflen) + * Format a <character-string> into the presentation buffer. + * return: + * Number of rdata octets consumed + * 0 for protocol format error + * -1 for output buffer error + * side effects: + * buffer is advanced on success. + */ +static int +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { + const u_char *odata = rdata; + size_t save_buflen = *buflen; + char *save_buf = *buf; + + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + if (rdata < edata) { + int n = *rdata; + + if (rdata + 1 + n <= edata) { + rdata++; + while (n-- > 0) { + if (strchr("\n\"\\", *rdata) != NULL) + if (addstr("\\", 1, buf, buflen) < 0) + goto enospc; + if (addstr((const char *)rdata, 1, + buf, buflen) < 0) + goto enospc; + rdata++; + } + } + } + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + return (rdata - odata); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static int +addname(const u_char *msg, size_t msglen, + const u_char **pp, const char *origin, + char **buf, size_t *buflen) +{ + size_t newlen, save_buflen = *buflen; + char *save_buf = *buf; + int n; + + n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); + if (n < 0) + goto enospc; /* Guess. */ + newlen = prune_origin(*buf, origin); + if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') && + (newlen == 0 || (*buf)[newlen - 1] != '.')) { + /* No trailing dot. */ + if (newlen + 2 > *buflen) + goto enospc; /* No room for ".\0". */ + (*buf)[newlen++] = '.'; + (*buf)[newlen] = '\0'; + } + if (newlen == 0) { + /* Use "@" instead of name. */ + if (newlen + 2 > *buflen) + goto enospc; /* No room for "@\0". */ + (*buf)[newlen++] = '@'; + (*buf)[newlen] = '\0'; + } + *pp += n; + addlen(newlen, buf, buflen); + **buf = '\0'; + return (newlen); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static void +addlen(size_t len, char **buf, size_t *buflen) { + assert(len <= *buflen); + *buf += len; + *buflen -= len; +} + +static int +addstr(const char *src, size_t len, char **buf, size_t *buflen) { + if (len > *buflen) { + errno = ENOSPC; + return (-1); + } + memcpy(*buf, src, len); + addlen(len, buf, buflen); + **buf = '\0'; + return (0); +} + +static int +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { + size_t save_buflen = *buflen; + char *save_buf = *buf; + int t; + + if (spaced || len >= target - 1) { + T(addstr(" ", 2, buf, buflen)); + spaced = 1; + } else { + for (t = (target - len - 1) / 8; t >= 0; t--) + if (addstr("\t", 1, buf, buflen) < 0) { + *buflen = save_buflen; + *buf = save_buf; + return (-1); + } + spaced = 0; + } + return (spaced); +} diff --git a/contrib/bind/lib/nameser/ns_ttl.c b/contrib/bind/lib/nameser/ns_ttl.c new file mode 100644 index 0000000..a71d3c7 --- /dev/null +++ b/contrib/bind/lib/nameser/ns_ttl.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_ttl.c,v 8.5 1998/02/13 01:16:38 halley Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int fmt1(int t, char s, char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) if ((x) < 0) return (-1); else (void)NULL + +/* Public. */ + +int +ns_format_ttl(u_long src, char *dst, size_t dstlen) { + char *odst = dst; + int secs, mins, hours, days, weeks, x; + char tmp[50], *p; + + 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) { + T(fmt1(weeks, 'W', &dst, &dstlen)); + x++; + } + if (days) { + T(fmt1(days, 'D', &dst, &dstlen)); + x++; + } + if (hours) { + T(fmt1(hours, 'H', &dst, &dstlen)); + x++; + } + if (mins) { + T(fmt1(mins, 'M', &dst, &dstlen)); + x++; + } + if (secs || !(weeks || days || hours || mins)) { + T(fmt1(secs, 'S', &dst, &dstlen)); + x++; + } + + if (x > 1) { + int ch; + + for (p = odst; (ch = *p) != '\0'; p++) + if (isascii(ch) && isupper(ch)) + *p = tolower(ch); + } + + return (dst - odst); +} + +int +ns_parse_ttl(const char *src, u_long *dst) { + u_long ttl, tmp; + int ch, digits, dirty; + + ttl = 0; + tmp = 0; + digits = 0; + dirty = 0; + while ((ch = *src++) != '\0') { + if (!isascii(ch) || !isprint(ch)) + goto einval; + if (isdigit(ch)) { + tmp *= 10; + tmp += (ch - '0'); + digits++; + continue; + } + if (digits == 0) + goto einval; + if (islower(ch)) + ch = toupper(ch); + switch (ch) { + case 'W': tmp *= 7; + case 'D': tmp *= 24; + case 'H': tmp *= 60; + case 'M': tmp *= 60; + case 'S': break; + default: goto einval; + } + ttl += tmp; + tmp = 0; + digits = 0; + dirty = 1; + } + if (digits > 0) { + if (dirty) + goto einval; + else + ttl += tmp; + } + *dst = ttl; + return (0); + + einval: + errno = EINVAL; + return (-1); +} + +/* Private. */ + +static int +fmt1(int t, char s, char **buf, size_t *buflen) { + char tmp[50]; + size_t len; + + len = SPRINTF((tmp, "%d%c", t, s)); + if (len + 1 > *buflen) + return (-1); + strcpy(*buf, tmp); + *buf += len; + *buflen -= len; + return (0); +} diff --git a/contrib/bind/lib/resolv/Makefile b/contrib/bind/lib/resolv/Makefile new file mode 100644 index 0000000..5be600d --- /dev/null +++ b/contrib/bind/lib/resolv/Makefile @@ -0,0 +1,75 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# $Id: Makefile,v 8.17 1997/05/21 19:32:09 halley Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsdos +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cruv +RANLIB= ranlib +INSTALL= install + +SRCS= herror.c res_debug.c res_data.c res_comp.c res_init.c \ + res_mkquery.c res_query.c res_send.c res_mkupdate.c \ + res_update.c + +OBJS= herror.${O} res_debug.${O} res_data.${O} res_comp.${O} res_init.${O} \ + res_mkquery.${O} res_query.${O} res_send.${O} res_mkupdate.${O} \ + res_update.${O} + +all: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O} + +distclean: clean + +clean: FRC + rm -f .depend a.out core ${LIB} tags + rm -f *.${O} *.BAK *.CKP *~ + +depend: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +install: + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/lib/resolv/herror.c b/contrib/bind/lib/resolv/herror.c new file mode 100644 index 0000000..38217db --- /dev/null +++ b/contrib/bind/lib/resolv/herror.c @@ -0,0 +1,112 @@ +/* + * 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. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: herror.c,v 8.7 1996/11/18 09:10:00 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <sys/uio.h> +#include <netdb.h> +#include <string.h> +#include <unistd.h> +#include "port_after.h" + +const char *h_errlist[] = { + "Resolver 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 */ +}; +int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; + +int h_errno; + +/* + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(s) + const char *s; +{ + struct iovec iov[4]; + register struct iovec *v = iov; + + if (s && *s) { + v->iov_base = (char *)s; + v->iov_len = strlen(s); + v++; + v->iov_base = ": "; + v->iov_len = 2; + v++; + } + v->iov_base = (char *)hstrerror(h_errno); + v->iov_len = strlen(v->iov_base); + v++; + v->iov_base = "\n"; + v->iov_len = 1; + writev(STDERR_FILENO, iov, (v - iov) + 1); +} + +const char * +hstrerror(err) + 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/contrib/bind/lib/resolv/res_comp.c b/contrib/bind/lib/resolv/res_comp.c new file mode 100644 index 0000000..c1f946e --- /dev/null +++ b/contrib/bind/lib/resolv/res_comp.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 1985, 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. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: res_comp.c,v 8.11 1997/05/21 19:31:04 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "port_after.h" + +/* + * Expand compressed domain name 'comp_dn' to full domain name. + * 'msg' is a pointer to the begining of the message, + * 'eomorig' points to the first location after the message, + * 'exp_dn' is a pointer to a buffer of size 'length' for the result. + * Return size of compressed name or -1 if there was an error. + */ +int +dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return (n); +} + +/* + * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + */ +int +dn_comp(const char *src, u_char *dst, int dstsiz, + u_char **dnptrs, u_char **lastdnptr) +{ + return (ns_name_compress(src, dst, (size_t)dstsiz, + (const u_char **)dnptrs, + (const u_char **)lastdnptr)); +} + +/* + * Skip over a compressed domain name. Return the size or -1. + */ +int +dn_skipname(const u_char *ptr, const u_char *eom) { + const u_char *saveptr = ptr; + + if (ns_name_skip(&ptr, eom) == -1) + return (-1); + return (ptr - saveptr); +} + +/* + * Verify that a domain name uses an acceptable character set. + */ + +/* + * Note the conspicuous absence of ctype macros in these definitions. On + * non-ASCII hosts, we can't depend on string literals or ctype macros to + * tell us anything about network-format data. The rest of the BIND system + * is not careful about this, but for some reason, we're doing it right here. + */ +#define PERIOD 0x2e +#define hyphenchar(c) ((c) == 0x2d) +#define bslashchar(c) ((c) == 0x5c) +#define periodchar(c) ((c) == PERIOD) +#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) + +int +res_hnok(const char *dn) { + int ppch = '\0', pch = PERIOD, ch = *dn++; + + while (ch != '\0') { + int nch = *dn++; + + if (periodchar(ch)) { + (void)NULL; + } else if (periodchar(pch)) { + if (!borderchar(ch)) + return (0); + } else if (periodchar(nch) || nch == '\0') { + if (!borderchar(ch)) + return (0); + } else { + if (!middlechar(ch)) + return (0); + } + ppch = pch, pch = ch, ch = nch; + } + return (1); +} + +/* + * hostname-like (A, MX, WKS) owners can have "*" as their first label + * but must otherwise be as a host name. + */ +int +res_ownok(const char *dn) { + if (asterchar(dn[0])) { + if (periodchar(dn[1])) + return (res_hnok(dn+2)); + if (dn[1] == '\0') + return (1); + } + return (res_hnok(dn)); +} + +/* + * SOA RNAMEs and RP RNAMEs can have any printable character in their first + * label, but the rest of the name has to look like a host name. + */ +int +res_mailok(const char *dn) { + int ch, escaped = 0; + + /* "." is a valid missing representation */ + if (*dn == '\0') + return (1); + + /* otherwise <label>.<hostname> */ + while ((ch = *dn++) != '\0') { + if (!domainchar(ch)) + return (0); + if (!escaped && periodchar(ch)) + break; + if (escaped) + escaped = 0; + else if (bslashchar(ch)) + escaped = 1; + } + if (periodchar(ch)) + return (res_hnok(dn)); + return (0); +} + +/* + * This function is quite liberal, since RFC 1034's character sets are only + * recommendations. + */ +int +res_dnok(const char *dn) { + int ch; + + while ((ch = *dn++) != '\0') + if (!domainchar(ch)) + return (0); + return (1); +} + +#ifdef BIND_4_COMPAT +/* + * This module must export the following externally-visible symbols: + * ___putlong + * ___putshort + * __getlong + * __getshort + * Note that one _ comes from C and the others come from us. + */ +void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } +void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } +u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } +u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } +#endif /*BIND_4_COMPAT*/ diff --git a/contrib/bind/lib/resolv/res_data.c b/contrib/bind/lib/resolv/res_data.c new file mode 100644 index 0000000..ca06d64 --- /dev/null +++ b/contrib/bind/lib/resolv/res_data.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1995,1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: res_data.c,v 8.5 1996/11/18 09:10:02 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "port_after.h" + +const char *_res_opcodes[] = { + "QUERY", + "IQUERY", + "CQUERYM", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ + "UPDATE", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "ZONEINIT", + "ZONEREF", +}; + +const char *_res_resultcodes[] = { + "NOERROR", + "FORMERR", + "SERVFAIL", + "NXDOMAIN", + "NOTIMP", + "REFUSED", + "YXDOMAIN", + "YXRRSET", + "NXRRSET", + "NOTAUTH", + "ZONEERR", + "11", + "12", + "13", + "14", + "NOCHANGE", +}; + +#ifdef BIND_UPDATE +const char *_res_sectioncodes[] = { + "ZONE", + "PREREQUISITES", + "UPDATE", + "ADDITIONAL", +}; +#endif diff --git a/contrib/bind/lib/resolv/res_debug.c b/contrib/bind/lib/resolv/res_debug.c new file mode 100644 index 0000000..80d1477 --- /dev/null +++ b/contrib/bind/lib/resolv/res_debug.c @@ -0,0 +1,974 @@ +/* + * 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 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: res_debug.c,v 8.20 1998/02/13 01:11:34 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#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 "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern const char *_res_opcodes[]; +extern const char *_res_resultcodes[]; +extern const char *_res_sectioncodes[]; + +/* + * Print the current options. + */ +void +fp_resstat(struct __res_state *statp, FILE *file) { + u_long mask; + + fprintf(file, ";; res options:"); + if (!statp) + statp = &_res; + for (mask = 1; mask != 0; mask <<= 1) + if (statp->options & mask) + fprintf(file, " %s", p_option(mask)); + putc('\n', file); +} + +static void +do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) { + int n, sflag, rrnum; + char buf[2048]; /* XXX need to malloc */ + ns_opcode opcode; + ns_rr rr; + + /* + * Print answer records. + */ + sflag = (_res.pfcode & pflag); + if (_res.pfcode && !sflag) + return; + + opcode = ns_msg_getflag(*handle, ns_f_opcode); + rrnum = 0; + for (;;) { + if (ns_parserr(handle, section, rrnum, &rr)) { + if (errno != ENODEV) + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + else if (rrnum > 0 && sflag != 0 && + (_res.pfcode & RES_PRF_HEAD1)) + putc('\n', file); + return; + } + if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1)) + fprintf(file, ";; %s SECTION:\n", + p_section(section, opcode)); + if (section == ns_s_qd) + fprintf(file, ";;\t%s, type = %s, class = %s\n", + ns_rr_name(rr), + p_type(ns_rr_type(rr)), + p_class(ns_rr_class(rr))); + else { + n = ns_sprintrr(handle, &rr, NULL, NULL, + buf, sizeof buf); + if (n < 0) { + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + return; + } + fputs(buf, file); + fputc('\n', file); + } + rrnum++; + } +} + +void +p_query(const u_char *msg) { + fp_query(msg, stdout); +} + +void +fp_query(const u_char *msg, FILE *file) { + fp_nquery(msg, PACKETSZ, file); +} + +/* + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ +void +fp_nquery(const u_char *msg, int len, FILE *file) { + ns_msg handle; + int n, qdcount, ancount, nscount, arcount; + u_int opcode, rcode, id; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return; + + if (ns_initparse(msg, len, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return; + } + opcode = ns_msg_getflag(handle, ns_f_opcode); + rcode = ns_msg_getflag(handle, ns_f_rcode); + id = ns_msg_id(handle); + qdcount = ns_msg_count(handle, ns_s_qd); + ancount = ns_msg_count(handle, ns_s_an); + nscount = ns_msg_count(handle, ns_s_ns); + arcount = ns_msg_count(handle, ns_s_ar); + + /* + * Print header fields. + */ + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode) + fprintf(file, + ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", + _res_opcodes[opcode], _res_resultcodes[rcode], id); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX)) + putc(';', file); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { + fprintf(file, "; flags:"); + if (ns_msg_getflag(handle, ns_f_qr)) + fprintf(file, " qr"); + if (ns_msg_getflag(handle, ns_f_aa)) + fprintf(file, " aa"); + if (ns_msg_getflag(handle, ns_f_tc)) + fprintf(file, " tc"); + if (ns_msg_getflag(handle, ns_f_rd)) + fprintf(file, " rd"); + if (ns_msg_getflag(handle, ns_f_ra)) + fprintf(file, " ra"); + if (ns_msg_getflag(handle, ns_f_z)) + fprintf(file, " ??"); + if (ns_msg_getflag(handle, ns_f_ad)) + fprintf(file, " ad"); + if (ns_msg_getflag(handle, ns_f_cd)) + fprintf(file, " cd"); + } + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { + fprintf(file, "; %s: %d", + p_section(ns_s_qd, opcode), qdcount); + fprintf(file, ", %s: %d", + p_section(ns_s_an, opcode), ancount); + fprintf(file, ", %s: %d", + p_section(ns_s_ns, opcode), nscount); + fprintf(file, ", %s: %d", + p_section(ns_s_ar, opcode), arcount); + } + if ((!_res.pfcode) || (_res.pfcode & + (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { + putc('\n',file); + } + /* + * Print the various sections. + */ + do_section(&handle, ns_s_qd, RES_PRF_QUES, file); + do_section(&handle, ns_s_an, RES_PRF_ANS, file); + do_section(&handle, ns_s_ns, RES_PRF_AUTH, file); + do_section(&handle, ns_s_ar, RES_PRF_ADD, file); + if (qdcount == 0 && ancount == 0 && + nscount == 0 && arcount == 0) + putc('\n', file); +} + +const u_char * +p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { + char name[MAXDNAME]; + int n; + + if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') + putc('.', file); + else + fputs(name, file); + return (cp + n); +} + +const u_char * +p_cdname(const u_char *cp, const u_char *msg, FILE *file) { + return (p_cdnname(cp, msg, PACKETSZ, file)); +} + +/* Return a fully-qualified domain name from a compressed name (with + length supplied). */ + +const u_char * +p_fqnname(cp, msg, msglen, name, namelen) + const u_char *cp, *msg; + int msglen; + char *name; + int namelen; +{ + int n, newlen; + + if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) + return (NULL); + newlen = strlen(name); + if (newlen == 0 || name[newlen - 1] != '.') { + if (newlen + 1 >= namelen) /* Lack space for final dot */ + return (NULL); + else + strcpy(name + newlen, "."); + } + return (cp + n); +} + +/* XXX: the rest of these functions need to become length-limited, too. */ + +const u_char * +p_fqname(const u_char *cp, const u_char *msg, FILE *file) { + char name[MAXDNAME]; + const u_char *n; + + n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); + if (n == NULL) + return (NULL); + fputs(name, file); + return (n); +} + +/* + * Names of RR classes and qclasses. Classes and qclasses are the same, except + * that C_ANY is a qclass but not a class. (You can ask for records of class + * C_ANY, but you can't have any records of that class in the database.) + */ +const struct res_sym __p_class_syms[] = { + {C_IN, "IN"}, + {C_CHAOS, "CHAOS"}, + {C_HS, "HS"}, + {C_HS, "HESIOD"}, + {C_ANY, "ANY"}, + {C_NONE, "NONE"}, + {C_IN, (char *)0} +}; + +/* + * Names of message sections. + */ +const struct res_sym __p_default_section_syms[] = { + {ns_s_qd, "QUERY"}, + {ns_s_an, "ANSWER"}, + {ns_s_ns, "AUTHORITY"}, + {ns_s_ar, "ADDITIONAL"}, + {0, (char *)0} +}; + +const struct res_sym __p_update_section_syms[] = { + {S_ZONE, "ZONE"}, + {S_PREREQ, "PREREQUISITE"}, + {S_UPDATE, "UPDATE"}, + {S_ADDT, "ADDITIONAL"}, + {0, (char *)0} +}; + +/* + * Names of RR types and qtypes. Types and qtypes are the same, except + * that T_ANY is a qtype but not a type. (You can ask for records of type + * T_ANY, but you can't have any records of that type in the database.) + */ +const struct res_sym __p_type_syms[] = { + {T_A, "A", "address"}, + {T_NS, "NS", "name server"}, + {T_MD, "MD", "mail destination (deprecated)"}, + {T_MF, "MF", "mail forwarder (deprecated)"}, + {T_CNAME, "CNAME", "canonical name"}, + {T_SOA, "SOA", "start of authority"}, + {T_MB, "MB", "mailbox"}, + {T_MG, "MG", "mail group member"}, + {T_MR, "MR", "mail rename"}, + {T_NULL, "NULL", "null"}, + {T_WKS, "WKS", "well-known service (deprecated)"}, + {T_PTR, "PTR", "domain name pointer"}, + {T_HINFO, "HINFO", "host information"}, + {T_MINFO, "MINFO", "mailbox information"}, + {T_MX, "MX", "mail exchanger"}, + {T_TXT, "TXT", "text"}, + {T_RP, "RP", "responsible person"}, + {T_AFSDB, "AFSDB", "DCE or AFS server"}, + {T_X25, "X25", "X25 address"}, + {T_ISDN, "ISDN", "ISDN address"}, + {T_RT, "RT", "router"}, + {T_NSAP, "NSAP", "nsap address"}, + {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"}, + {T_SIG, "SIG", "signature"}, + {T_KEY, "KEY", "key"}, + {T_PX, "PX", "mapping information"}, + {T_GPOS, "GPOS", "geographical position (withdrawn)"}, + {T_AAAA, "AAAA", "IPv6 address"}, + {T_LOC, "LOC", "location"}, + {T_NXT, "NXT", "next valid name (unimplemented)"}, + {T_EID, "EID", "endpoint identifier (unimplemented)"}, + {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"}, + {T_SRV, "SRV", "server selection"}, + {T_ATMA, "ATMA", "ATM address (unimplemented)"}, + {T_IXFR, "IXFR", "incremental zone transfer"}, + {T_AXFR, "AXFR", "zone transfer"}, + {T_MAILB, "MAILB", "mailbox-related data (deprecated)"}, + {T_MAILA, "MAILA", "mail agent (deprecated)"}, + {T_NAPTR, "NAPTR", "URN Naming Authority"}, + {T_ANY, "ANY", "\"any\""}, + {0, NULL, NULL} +}; + +int +sym_ston(const struct res_sym *syms, const char *name, int *success) { + for ((void)NULL; syms->name != 0; syms++) { + if (strcasecmp (name, syms->name) == 0) { + if (success) + *success = 1; + return (syms->number); + } + } + if (success) + *success = 0; + return (syms->number); /* The default value. */ +} + +const char * +sym_ntos(const struct res_sym *syms, int number, int *success) { + static char unname[20]; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->name); + } + } + + sprintf(unname, "%d", number); + if (success) + *success = 0; + return (unname); +} + +const char * +sym_ntop(const struct res_sym *syms, int number, int *success) { + static char unname[20]; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->humanname); + } + } + sprintf(unname, "%d", number); + if (success) + *success = 0; + return (unname); +} + +/* + * Return a string for the type. + */ +const char * +p_type(int type) { + return (sym_ntos(__p_type_syms, type, (int *)0)); +} + +/* + * Return a string for the type. + */ +const char * +p_section(int section, int opcode) { + const struct res_sym *symbols; + + switch (opcode) { + case ns_o_update: + symbols = __p_update_section_syms; + break; + default: + symbols = __p_default_section_syms; + break; + } + return (sym_ntos(symbols, section, (int *)0)); +} + +/* + * Return a mnemonic for class. + */ +const char * +p_class(int class) { + return (sym_ntos(__p_class_syms, class, (int *)0)); +} + +/* + * Return a mnemonic for an option + */ +const char * +p_option(u_long option) { + static char nbuf[40]; + + switch (option) { + case RES_INIT: return "init"; + case RES_DEBUG: return "debug"; + case RES_AAONLY: return "aaonly(unimpl)"; + case RES_USEVC: return "usevc"; + case RES_PRIMARY: return "primry(unimpl)"; + case RES_IGNTC: return "igntc"; + case RES_RECURSE: return "recurs"; + case RES_DEFNAMES: return "defnam"; + case RES_STAYOPEN: return "styopn"; + case RES_DNSRCH: return "dnsrch"; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; + default: sprintf(nbuf, "?0x%lx?", (u_long)option); + return (nbuf); + } +} + +/* + * Return a mnemonic for a time to live. + */ +const char * +p_time(u_int32_t value) { + static char nbuf[40]; + + if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) + sprintf(nbuf, "%u", value); + return (nbuf); +} + + +/* + * 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, "%ld.%.2ld", 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; + char *cp; + int exponent; + int mantissa; + + cp = *strptr; + + while (isdigit(*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* centimeters */ + cp++; + if (isdigit(*cp)) { + 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; +{ + 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'); + + 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) { + 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. */ +int +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); + + 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++; + + 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 formats it in a human readable format. */ +const char * +loc_ntoa(binary, ascii) + const u_char *binary; + char *ascii; +{ + static char *error = "?"; + 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 (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); +} + + +/* Return the number of DNS hierarchy levels in the name. */ +int +dn_count_labels(const char *name) { + int i, len, count; + + len = strlen(name); + for (i = 0, count = 0; i < len; i++) { + /* XXX need to check for \. or use named's nlabels(). */ + if (name[i] == '.') + count++; + } + + /* don't count initial wildcard */ + if (name[0] == '*') + if (count) + count--; + + /* don't count the null label for root. */ + /* if terminating '.' not found, must adjust */ + /* count to include last label */ + if (len > 0 && name[len-1] != '.') + count++; + return (count); +} + + +/* + * Make dates expressed in seconds-since-Jan-1-1970 easy to read. + * SIG records are required to be printed like this, by the Secure DNS RFC. + */ +char * +p_secstodate (u_long secs) { + static char output[15]; /* YYYYMMDDHHMMSS and null */ + time_t clock = secs; + struct tm *time; + + time = gmtime(&clock); + time->tm_year += 1900; + time->tm_mon += 1; + sprintf(output, "%04d%02d%02d%02d%02d%02d", + time->tm_year, time->tm_mon, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); + return (output); +} diff --git a/contrib/bind/lib/resolv/res_init.c b/contrib/bind/lib/resolv/res_init.c new file mode 100644 index 0000000..f374d51 --- /dev/null +++ b/contrib/bind/lib/resolv/res_init.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; +static char rcsid[] = "$Id: res_init.c,v 8.7 1996/11/18 09:10:04 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "port_after.h" + +/* Options. Should all be left alone. */ +#define RESOLVSORT +#define RFC1535 +#define DEBUG + +static void res_setoptions __P((char *, char *)); + +#ifdef RESOLVSORT +static const char sort_mask[] = "/&"; +#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) +static u_int32_t net_mask __P((struct in_addr)); +#endif + +#if !defined(isascii) /* XXX - could be a function */ +# define isascii(c) (!(c & 0200)) +#endif + +/* + * Resolver state default settings. + */ + +struct __res_state _res +# if defined(__BIND_RES_TEXT) + = { RES_TIMEOUT, } /* Motorola, et al. */ +# endif + ; + + +/* + * Set up default settings. If the configuration file exist, the values + * there will have precedence. Otherwise, the server address is set to + * INADDR_ANY and the default domain name comes from the gethostname(). + * + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. + * + * Return 0 if completes successfully, -1 on error + */ +int +res_init() { + register FILE *fp; + register char *cp, **pp; + register int n; + char buf[BUFSIZ]; + int nserv = 0; /* number of nameserver records read from file */ + int haveenv = 0; + int havesearch = 0; +#ifdef RESOLVSORT + int nsort = 0; + char *net; +#endif +#ifndef RFC1535 + int dots; +#endif + + /* + * These three fields used to be statically initialized. This made + * it hard to use this code in a shared library. It is necessary, + * now that we're doing dynamic initialization here, that we preserve + * the old semantics: if an application modifies one of these three + * fields of _res before res_init() is called, res_init() will not + * alter them. Of course, if an application is setting them to + * _zero_ before calling res_init(), hoping to override what used + * to be the static default, we can't detect it and unexpected results + * will follow. Zero for any of these fields would make no sense, + * so one can safely assume that the applications were already getting + * unexpected results. + * + * _res.options is tricky since some apps were known to diddle the bits + * before res_init() was first called. We can't replicate that semantic + * with dynamic initialization (they may have turned bits off that are + * set in RES_DEFAULT). Our solution is to declare such applications + * "broken". They could fool us by setting RES_INIT but none do (yet). + */ + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!(_res.options & RES_INIT)) + _res.options = RES_DEFAULT; + + /* + * This one used to initialize implicitly to zero, so unless the app + * has set it to something in particular, we can randomize it now. + */ + if (!_res.id) + _res.id = res_randomid(); + +#ifdef USELOOPBACK + _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); +#else + _res.nsaddr.sin_addr.s_addr = INADDR_ANY; +#endif + _res.nsaddr.sin_family = AF_INET; + _res.nsaddr.sin_port = htons(NAMESERVER_PORT); + _res.nscount = 1; + _res.ndots = 1; + _res.pfcode = 0; + + /* Allow user to override the local domain definition */ + if ((cp = getenv("LOCALDOMAIN")) != NULL) { + (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + haveenv++; + + /* + * Set search list to be blank-separated strings + * from rest of env value. Permits users of LOCALDOMAIN + * to still have a search list, and anyone to set the + * one that they want to use as an individual (even more + * important now that the rfc1535 stuff restricts searches) + */ + cp = _res.defdname; + pp = _res.dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + if (*cp == '\n') /* silly backwards compat */ + break; + else if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + havesearch = 1; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') + cp++; + *cp = '\0'; + *pp++ = 0; + } + +#define MATCH(line, name) \ + (!strncmp(line, name, sizeof(name) - 1) && \ + (line[sizeof(name) - 1] == ' ' || \ + line[sizeof(name) - 1] == '\t')) + + if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { + /* read the config file */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + /* skip comments */ + if (*buf == ';' || *buf == '#') + continue; + /* read default domain name */ + if (MATCH(buf, "domain")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("domain") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) + *cp = '\0'; + havesearch = 0; + continue; + } + /* set search list */ + if (MATCH(buf, "search")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("search") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + if ((cp = strchr(_res.defdname, '\n')) != NULL) + *cp = '\0'; + /* + * Set search list to be blank-separated strings + * on rest of line. + */ + cp = _res.defdname; + pp = _res.dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t') + cp++; + *cp = '\0'; + *pp++ = 0; + havesearch = 1; + continue; + } + /* read nameservers to query */ + if (MATCH(buf, "nameserver") && nserv < MAXNS) { + struct in_addr a; + + cp = buf + sizeof("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { + _res.nsaddr_list[nserv].sin_addr = a; + _res.nsaddr_list[nserv].sin_family = AF_INET; + _res.nsaddr_list[nserv].sin_port = + htons(NAMESERVER_PORT); + nserv++; + } + continue; + } +#ifdef RESOLVSORT + if (MATCH(buf, "sortlist")) { + struct in_addr a; + + cp = buf + sizeof("sortlist") - 1; + while (nsort < MAXRESOLVSORT) { + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\0' || *cp == '\n' || *cp == ';') + break; + net = cp; + while (*cp && !ISSORTMASK(*cp) && *cp != ';' && + isascii(*cp) && !isspace(*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + _res.sort_list[nsort].addr = a; + if (ISSORTMASK(n)) { + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && !isspace(*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + _res.sort_list[nsort].mask = a.s_addr; + } else { + _res.sort_list[nsort].mask = + net_mask(_res.sort_list[nsort].addr); + } + } else { + _res.sort_list[nsort].mask = + net_mask(_res.sort_list[nsort].addr); + } + nsort++; + } + *cp = n; + } + continue; + } +#endif + if (MATCH(buf, "options")) { + res_setoptions(buf + sizeof("options") - 1, "conf"); + continue; + } + } + if (nserv > 1) + _res.nscount = nserv; +#ifdef RESOLVSORT + _res.nsort = nsort; +#endif + (void) fclose(fp); + } + if (_res.defdname[0] == 0 && + gethostname(buf, sizeof(_res.defdname) - 1) == 0 && + (cp = strchr(buf, '.')) != NULL) + strcpy(_res.defdname, cp + 1); + + /* find components of local domain that might be searched */ + if (havesearch == 0) { + pp = _res.dnsrch; + *pp++ = _res.defdname; + *pp = NULL; + +#ifndef RFC1535 + dots = 0; + for (cp = _res.defdname; *cp; cp++) + dots += (*cp == '.'); + + cp = _res.defdname; + while (pp < _res.dnsrch + MAXDFLSRCH) { + if (dots < LOCALDOMAINPARTS) + break; + cp = strchr(cp, '.') + 1; /* we know there is one */ + *pp++ = cp; + dots--; + } + *pp = NULL; +#ifdef DEBUG + if (_res.options & RES_DEBUG) { + printf(";; res_init()... default dnsrch list:\n"); + for (pp = _res.dnsrch; *pp; pp++) + printf(";;\t%s\n", *pp); + printf(";;\t..END..\n"); + } +#endif +#endif /* !RFC1535 */ + } + + if ((cp = getenv("RES_OPTIONS")) != NULL) + res_setoptions(cp, "env"); + _res.options |= RES_INIT; + return (0); +} + +static void +res_setoptions(options, source) + char *options, *source; +{ + char *cp = options; + int i; + +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_setoptions(\"%s\", \"%s\")...\n", + options, source); +#endif + while (*cp) { + /* skip leading and inner runs of spaces */ + while (*cp == ' ' || *cp == '\t') + cp++; + /* search for and process individual options */ + if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { + i = atoi(cp + sizeof("ndots:") - 1); + if (i <= RES_MAXNDOTS) + _res.ndots = i; + else + _res.ndots = RES_MAXNDOTS; +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";;\tndots=%d\n", _res.ndots); +#endif + } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { +#ifdef DEBUG + if (!(_res.options & RES_DEBUG)) { + printf(";; res_setoptions(\"%s\", \"%s\")..\n", + options, source); + _res.options |= RES_DEBUG; + } + printf(";;\tdebug\n"); +#endif + } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { + _res.options |= RES_USE_INET6; + } else { + /* XXX - print a warning here? */ + } + /* skip to next run of spaces */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +#ifdef RESOLVSORT +/* XXX - should really support CIDR which means explicit masks always. */ +static u_int32_t +net_mask(in) /* XXX - should really use system's version of this */ + struct in_addr in; +{ + register u_int32_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (htonl(IN_CLASSA_NET)); + else if (IN_CLASSB(i)) + return (htonl(IN_CLASSB_NET)); + return (htonl(IN_CLASSC_NET)); +} +#endif + +u_int +res_randomid() +{ + struct timeval now; + + gettimeofday(&now, NULL); + return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); +} diff --git a/contrib/bind/lib/resolv/res_mkquery.c b/contrib/bind/lib/resolv/res_mkquery.c new file mode 100644 index 0000000..74be28b --- /dev/null +++ b/contrib/bind/lib/resolv/res_mkquery.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 1985, 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. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: res_mkquery.c,v 8.9 1997/04/24 22:22:36 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +/* + * Form all types of queries. + * Returns the size of the result or -1. + */ +int +res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) + int op; /* opcode of query */ + const char *dname; /* domain name */ + int class, type; /* class and type of query */ + const u_char *data; /* resource record data */ + int datalen; /* length of data */ + const u_char *newrr_in; /* new rr for modify or append */ + u_char *buf; /* buffer to put query */ + int buflen; /* size of buffer */ +{ + register HEADER *hp; + register u_char *cp; + register int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_mkquery(%d, %s, %d, %d)\n", + op, dname, class, type); +#endif + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + hp->id = htons(++_res.id); + hp->opcode = op; + hp->rd = (_res.options & RES_RECURSE) != 0; + hp->rcode = NOERROR; + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + /* + * perform opcode specific processing + */ + switch (op) { + case QUERY: /*FALLTHROUGH*/ + case NS_NOTIFY_OP: + if ((buflen -= QFIXEDSZ) < 0) + return (-1); + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) + return (-1); + cp += n; + buflen -= n; + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + hp->qdcount = htons(1); + if (op == QUERY || data == NULL) + break; + /* + * Make an additional record for completion domain. + */ + buflen -= RRFIXEDSZ; + n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + buflen -= n; + __putshort(T_NULL, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(0, cp); + cp += INT16SZ; + hp->arcount = htons(1); + break; + + case IQUERY: + /* + * Initialize answer section + */ + if (buflen < 1 + RRFIXEDSZ + datalen) + return (-1); + *cp++ = '\0'; /* no domain name */ + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(datalen, cp); + cp += INT16SZ; + if (datalen) { + memcpy(cp, data, datalen); + cp += datalen; + } + hp->ancount = htons(1); + break; + + default: + return (-1); + } + return (cp - buf); +} diff --git a/contrib/bind/lib/resolv/res_mkupdate.c b/contrib/bind/lib/resolv/res_mkupdate.c new file mode 100644 index 0000000..c6e7f4a1 --- /dev/null +++ b/contrib/bind/lib/resolv/res_mkupdate.c @@ -0,0 +1,419 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: res_mkupdate.c,v 1.11 1998/01/26 23:08:45 halley Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +static int getnum_str(u_char **, u_char *); +static int getword_str(char *, int, u_char **, u_char *); + +#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2); + +/* + * Form update packets. + * Returns the size of the resulting packet if no error + * On error, + * returns -1 if error in reading a word/number in rdata + * portion for update packets + * -2 if length of buffer passed is insufficient + * -3 if zone section is not the first section in + * the linked list, or section order has a problem + * -4 on a number overflow + * -5 unknown operation or no records + */ +int +res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { + ns_updrec *rrecp_start = rrecp_in; + HEADER *hp; + u_char c, *cp, *cp1, *sp1, *sp2, *startp, *endp; + int n, i, j, found, soanum, multiline; + ns_updrec *rrecp, *tmprrecp, *recptr = NULL; + struct in_addr ina; + char buf2[MAXDNAME]; + int section, numrrs = 0, counts[ns_s_max]; + u_int16_t rtype, rclass; + u_int32_t n1, rttl; + u_char *dnptrs[20], **dpp, **lastdnptr; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } + + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + hp->id = htons(++_res.id); + hp->opcode = ns_o_update; + hp->rcode = NOERROR; + sp1 = buf + 2*INT16SZ; /* save pointer to zocount */ + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + + if (rrecp_start == NULL) + return (-5); + else if (rrecp_start->r_section != S_ZONE) + return (-3); + + memset(counts, 0, sizeof counts); + for (rrecp = rrecp_start; rrecp; rrecp = rrecp->r_grpnext) { + numrrs++; + section = rrecp->r_section; + if (section < 0 || section >= ns_s_max) + return (-1); + counts[section]++; + for (i = section + 1; i < ns_s_max; i++) + if (counts[i]) + return (-3); + rtype = rrecp->r_type; + rclass = rrecp->r_class; + rttl = rrecp->r_ttl; + /* overload class and type */ + if (section == S_PREREQ) { + rttl = 0; + switch (rrecp->r_opcode) { + case YXDOMAIN: + rclass = C_ANY; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXDOMAIN: + rclass = C_NONE; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXRRSET: + rclass = C_NONE; + rrecp->r_size = 0; + break; + case YXRRSET: + if (rrecp->r_size == 0) + rclass = C_ANY; + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } else if (section == S_UPDATE) { + switch (rrecp->r_opcode) { + case DELETE: + rclass = rrecp->r_size == 0 ? C_ANY : C_NONE; + break; + case ADD: + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } + + /* + * XXX appending default domain to owner name is omitted, + * fqdn must be provided + */ + if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs, + lastdnptr)) < 0) + return (-1); + cp += n; + ShrinkBuffer(n + 2*INT16SZ); + PUTSHORT(rtype, cp); + PUTSHORT(rclass, cp); + if (section == S_ZONE) { + if (numrrs != 1 || rrecp->r_type != T_SOA) + return (-3); + continue; + } + ShrinkBuffer(INT32SZ + INT16SZ); + PUTLONG(rttl, cp); + sp2 = cp; /* save pointer to length byte */ + cp += INT16SZ; + if (rrecp->r_size == 0) { + if (section == S_UPDATE && rclass != C_ANY) + return (-1); + else { + PUTSHORT(0, sp2); + continue; + } + } + startp = rrecp->r_data; + endp = startp + rrecp->r_size - 1; + /* XXX this should be done centrally. */ + switch (rrecp->r_type) { + case T_A: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (!inet_aton(buf2, &ina)) + return (-1); + n1 = ntohl(ina.s_addr); + ShrinkBuffer(INT32SZ); + PUTLONG(n1, cp); + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_MINFO: + case T_SOA: + case T_RP: + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, + dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + if (rrecp->r_type == T_SOA) { + ShrinkBuffer(5 * INT32SZ); + while (isspace(*startp) || !*startp) + startp++; + if (*startp == '(') { + multiline = 1; + startp++; + } else + multiline = 0; + /* serial, refresh, retry, expire, minimum */ + for (i = 0; i < 5; i++) { + soanum = getnum_str(&startp, endp); + if (soanum < 0) + return (-1); + PUTLONG(soanum, cp); + } + if (multiline) { + while (isspace(*startp) || !*startp) + startp++; + if (*startp != ')') + return (-1); + } + } + break; + case T_MX: + case T_AFSDB: + case T_RT: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + PUTSHORT(n, cp); + ShrinkBuffer(INT16SZ); + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_PX: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + PUTSHORT(n, cp); + ShrinkBuffer(INT16SZ); + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, + lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + break; + case T_WKS: + case T_HINFO: + case T_TXT: + case T_X25: + case T_ISDN: + case T_NSAP: + case T_LOC: + /* XXX - more fine tuning needed here */ + ShrinkBuffer(rrecp->r_size); + memcpy(cp, rrecp->r_data, rrecp->r_size); + cp += rrecp->r_size; + break; + default: + return (-1); + } /*switch*/ + n = (u_int16_t)((cp - sp2) - INT16SZ); + PUTSHORT(n, sp2); + } /*for*/ + + hp->qdcount = htons(counts[0]); + hp->ancount = htons(counts[1]); + hp->nscount = htons(counts[2]); + hp->arcount = htons(counts[3]); + return (cp - buf); +} + +/* + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, u_char **startpp, u_char *endp) { + char *cp; + int c; + + for (cp = buf; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (cp != buf) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + (*startpp)++; + if (cp >= buf+size-1) + break; + *cp++ = (u_char)c; + } + *cp = '\0'; + return (cp != buf); +} + +/* + * Get a whitespace delimited number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +getnum_str(u_char **startpp, u_char *endp) { + int c, n; + int seendigit = 0; + int seendecimal = 0; + int m = 0; + + for (n = 0; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (seendigit) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + if (c == ';') { + while ((*startpp <= endp) && + ((c = **startpp) != '\n')) + (*startpp)++; + if (seendigit) + break; + continue; + } + if (!isdigit(c)) { + if (c == ')' && seendigit) { + (*startpp)--; + break; + } + return (-1); + } + (*startpp)++; + n = n * 10 + (c - '0'); + seendigit = 1; + } + return (n + m); +} + +/* + * Allocate a resource record buffer & save rr info. + */ +ns_updrec * +res_mkupdrec(int section, const char *dname, + u_int class, u_int type, u_long ttl) { + ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec)); + + if (!rrecp || !(rrecp->r_dname = strdup(dname))) + return (NULL); + rrecp->r_class = class; + rrecp->r_type = type; + rrecp->r_ttl = ttl; + rrecp->r_section = section; + return (rrecp); +} + +/* + * Free a resource record buffer created by res_mkupdrec. + */ +void +res_freeupdrec(ns_updrec *rrecp) { + /* Note: freeing r_dp is the caller's responsibility. */ + if (rrecp->r_dname != NULL) + free(rrecp->r_dname); + free(rrecp); +} diff --git a/contrib/bind/lib/resolv/res_mkupdate.h b/contrib/bind/lib/resolv/res_mkupdate.h new file mode 100644 index 0000000..eb2be3f --- /dev/null +++ b/contrib/bind/lib/resolv/res_mkupdate.h @@ -0,0 +1,7 @@ +#ifndef _RES_MKUPDATE_H_ +#define _RES_MKUPDATE_H_ + +__BEGIN_DECLS +__END_DECLS + +#endif /* _RES_MKUPDATE_H_ */ diff --git a/contrib/bind/lib/resolv/res_query.c b/contrib/bind/lib/resolv/res_query.c new file mode 100644 index 0000000..aeef49d --- /dev/null +++ b/contrib/bind/lib/resolv/res_query.c @@ -0,0 +1,408 @@ +/* + * 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. + */ + +/* + * 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) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +/* + * Formulate a normal query, send, and await answer. + * Returned answer is placed in supplied buffer "answer". + * Perform preliminary check of answer, returning success only + * if no error is indicated and the answer count is nonzero. + * Return the size of the response on success, -1 on error. + * Error number is left in h_errno. + * + * Caller must parse answer and determine whether it answers the question. + */ +int +res_query(name, class, type, answer, anslen) + const char *name; /* domain name */ + int class, type; /* class and type of query */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer buffer */ +{ + u_char buf[MAXPACKET]; + HEADER *hp = (HEADER *) answer; + int n; + + hp->rcode = NOERROR; /* default */ + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_query(%s, %d, %d)\n", name, class, type); +#endif + + n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); + if (n <= 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_query: mkquery failed\n"); +#endif + h_errno = NO_RECOVERY; + return (n); + } + n = res_send(buf, n, answer, anslen); + if (n < 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_query: send error\n"); +#endif + h_errno = TRY_AGAIN; + return (n); + } + + if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; rcode = %d, ancount=%d\n", hp->rcode, + ntohs(hp->ancount)); +#endif + switch (hp->rcode) { + case NXDOMAIN: + h_errno = HOST_NOT_FOUND; + break; + case SERVFAIL: + h_errno = TRY_AGAIN; + break; + case NOERROR: + h_errno = NO_DATA; + break; + case FORMERR: + case NOTIMP: + case REFUSED: + default: + h_errno = NO_RECOVERY; + break; + } + return (-1); + } + return (n); +} + +/* + * Formulate a normal query, send, and retrieve answer in supplied buffer. + * Return the size of the response on success, -1 on error. + * If enabled, implement search rules until answer or unrecoverable failure + * is detected. Error code, if any, is left in h_errno. + */ +int +res_search(name, class, type, answer, anslen) + const char *name; /* domain name */ + int class, type; /* class and type of query */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer */ +{ + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; + u_int dots; + int trailing_dot, ret, saved_herrno; + int got_nodata = 0, got_servfail = 0, tried_as_is = 0; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } + errno = 0; + h_errno = HOST_NOT_FOUND; /* default, if we never query */ + dots = 0; + for (cp = name; *cp; cp++) + dots += (*cp == '.'); + trailing_dot = 0; + if (cp > name && *--cp == '.') + trailing_dot++; + + /* If there aren't any dots, it could be a user-level alias. */ + if (!dots && (cp = hostalias(name)) != NULL) + return (res_query(cp, class, type, answer, anslen)); + + /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + saved_herrno = -1; + if (dots >= _res.ndots) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return (ret); + saved_herrno = h_errno; + tried_as_is++; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((!dots && (_res.options & RES_DEFNAMES)) || + (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { + int done = 0; + + for (domain = (const char * const *)_res.dnsrch; + *domain && !done; + domain++) { + + ret = res_querydomain(name, *domain, class, type, + answer, anslen); + if (ret > 0) + return (ret); + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + h_errno = TRY_AGAIN; + return (-1); + } + + switch (h_errno) { + case NO_DATA: + got_nodata++; + /* FALLTHROUGH */ + case HOST_NOT_FOUND: + /* keep trying */ + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + got_servfail++; + break; + } + /* FALLTHROUGH */ + default: + /* anything else implies that we're done */ + done++; + } + + /* if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + if (!(_res.options & RES_DNSRCH)) + done++; + } + } + + /* + * If we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!tried_as_is) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return (ret); + } + + /* if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's h_errno + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless h_errno, that being the one from + * the last DNSRCH we did. + */ + if (saved_herrno != -1) + h_errno = saved_herrno; + else if (got_nodata) + h_errno = NO_DATA; + else if (got_servfail) + h_errno = TRY_AGAIN; + return (-1); +} + +/* + * Perform a call on res_query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +int +res_querydomain(name, domain, class, type, answer, anslen) + const char *name, *domain; + int class, type; /* class and type of query */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer */ +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + int n, d; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_querydomain(%s, %s, %d, %d)\n", + name, domain?domain:"<Nil>", class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n >= MAXDNAME) { + h_errno = NO_RECOVERY; + return (-1); + } + n--; + if (n >= 0 && name[n] == '.') { + strncpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + d + 1 >= MAXDNAME) { + h_errno = NO_RECOVERY; + return (-1); + } + sprintf(nbuf, "%s.%s", name, domain); + } + return (res_query(longname, class, type, answer, anslen)); +} + +const char * +hostalias(const char *name) { + char *cp1, *cp2; + FILE *fp; + char *file; + char buf[BUFSIZ]; + static char abuf[MAXDNAME]; + + if (_res.options & RES_NOALIASES) + return (NULL); + file = getenv("HOSTALIASES"); + if (file == NULL || (fp = fopen(file, "r")) == NULL) + return (NULL); + setbuf(fp, NULL); + buf[sizeof(buf) - 1] = '\0'; + while (fgets(buf, sizeof(buf), fp)) { + for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1) + ; + if (!*cp1) + break; + *cp1 = '\0'; + if (!strcasecmp(buf, name)) { + while (isspace(*++cp1)) + ; + if (!*cp1) + break; + for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2) + ; + abuf[sizeof(abuf) - 1] = *cp2 = '\0'; + strncpy(abuf, cp1, sizeof(abuf) - 1); + fclose(fp); + return (abuf); + } + } + fclose(fp); + return (NULL); +} diff --git a/contrib/bind/lib/resolv/res_send.c b/contrib/bind/lib/resolv/res_send.c new file mode 100644 index 0000000..f8ac77b --- /dev/null +++ b/contrib/bind/lib/resolv/res_send.c @@ -0,0 +1,809 @@ +/* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Send query to name server and wait for reply. + */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG +#define CHECK_SRVR_ADDR + +static int s = -1; /* socket used for communications */ +static int connected = 0; /* is the socket connected */ +static int vc = 0; /* is the socket a virtual circuit? */ +static res_send_qhook Qhook = NULL; +static res_send_rhook Rhook = NULL; + + +#ifndef DEBUG +# define Dprint(cond, args) /*empty*/ +# define DprintQ(cond, args, query, size) /*empty*/ +# define Aerror(file, string, error, address) /*empty*/ +# define Perror(file, string, error) /*empty*/ +#else +# define Dprint(cond, args) if (cond) {fprintf args;} else {} +# define DprintQ(cond, args, query, size) if (cond) {\ + fprintf args;\ + __fp_nquery(query, size, stdout);\ + } else {} + static void + Aerror(file, string, error, address) + FILE *file; + char *string; + int error; + struct sockaddr_in address; + { + int save = errno; + + if (_res.options & RES_DEBUG) { + fprintf(file, "res_send: %s ([%s].%u): %s\n", + string, + inet_ntoa(address.sin_addr), + ntohs(address.sin_port), + strerror(error)); + } + errno = save; + } + static void + Perror(file, string, error) + FILE *file; + char *string; + int error; + { + int save = errno; + + if (_res.options & RES_DEBUG) { + fprintf(file, "res_send: %s: %s\n", + string, strerror(error)); + } + errno = save; + } +#endif + +void +res_send_setqhook(res_send_qhook hook) { + Qhook = hook; +} + +void +res_send_setrhook(res_send_rhook hook) { + Rhook = hook; +} + +/* int + * res_isourserver(ina) + * looks up "ina" in _res.ns_addr_list[] + * returns: + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_isourserver(const struct sockaddr_in *inp) { + struct sockaddr_in ina; + int ns, ret; + + ina = *inp; + ret = 0; + for (ns = 0; ns < _res.nscount; ns++) { + const struct sockaddr_in *srv = &_res.nsaddr_list[ns]; + + if (srv->sin_family == ina.sin_family && + srv->sin_port == ina.sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == ina.sin_addr.s_addr)) { + ret++; + break; + } + } + return (ret); +} + +/* int + * res_nameinquery(name, type, class, buf, eom) + * look for (name,type,class) in the query section of packet (buf,eom) + * requires: + * buf + HFIXEDSZ <= eom + * returns: + * -1 : format error + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_nameinquery(const char *name, int type, int class, + const u_char *buf, const u_char *eom) +{ + const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (ttype == type && + tclass == class && + strcasecmp(tname, name) == 0) + return (1); + } + return (0); +} + +/* int + * res_queriesmatch(buf1, eom1, buf2, eom2) + * is there a 1:1 mapping of (name,type,class) + * in (buf1,eom1) and (buf2,eom2)? + * returns: + * -1 : format error + * 0 : not a 1:1 mapping + * >0 : is a 1:1 mapping + * author: + * paul vixie, 29may94 + */ +int +res_queriesmatch(const u_char *buf1, const u_char *eom1, + const u_char *buf2, const u_char *eom2) +{ + const u_char *cp = buf1 + HFIXEDSZ; + int qdcount = ntohs(((HEADER*)buf1)->qdcount); + + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) + return (-1); + + /* + * Only header section present in replies to + * dynamic update packets. + */ + if ( (((HEADER *)buf1)->opcode == ns_o_update) && + (((HEADER *)buf2)->opcode == ns_o_update) ) + return (1); + + if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) + return (0); + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom1) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} + +int +res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { + HEADER *hp = (HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns, n; + u_int badns; /* XXX NSMAX can't exceed #/bits in this variable */ + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); + } + if (anssiz < HFIXEDSZ) { + errno = EINVAL; + return (-1); + } + DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), + (stdout, ";; res_send()\n"), buf, buflen); + v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; + gotsomewhere = 0; + connreset = 0; + terrno = ETIMEDOUT; + badns = 0; + + /* + * Send request, RETRY times, or until successful + */ + for (try = 0; try < _res.retry; try++) { + for (ns = 0; ns < _res.nscount; ns++) { + struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; + same_ns: + if (badns & (1 << ns)) { + res_close(); + goto next_ns; + } + + if (Qhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*Qhook)(&nsap, &buf, &buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + done = 1; + break; + case res_nextns: + res_close(); + goto next_ns; + case res_done: + return (resplen); + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + return (-1); + } + } while (!done); + } + + Dprint(_res.options & RES_DEBUG, + (stdout, ";; Querying server (# %d) address = %s\n", + ns + 1, inet_ntoa(nsap->sin_addr))); + + if (v_circuit) { + int truncated; + struct iovec iov[2]; + u_short len; + u_char *cp; + + /* + * Use virtual circuit; + * at most one attempt per server. + */ + try = _res.retry; + truncated = 0; + if (s < 0 || !vc || hp->opcode == ns_o_update) { + if (s >= 0) + res_close(); + + s = socket(PF_INET, SOCK_STREAM, 0); + if (s < 0) { + terrno = errno; + Perror(stderr, "socket(vc)", errno); + return (-1); + } + errno = 0; + if (connect(s, (struct sockaddr *)nsap, + sizeof *nsap) < 0) { + terrno = errno; + Aerror(stderr, "connect/vc", + errno, *nsap); + badns |= (1 << ns); + res_close(); + goto next_ns; + } + vc = 1; + } + /* + * Send length & message + */ + putshort((u_short)buflen, (u_char*)&len); + iov[0].iov_base = (caddr_t)&len; + iov[0].iov_len = INT16SZ; + iov[1].iov_base = (caddr_t)buf; + iov[1].iov_len = buflen; + if (writev(s, iov, 2) != (INT16SZ + buflen)) { + terrno = errno; + Perror(stderr, "write failed", errno); + badns |= (1 << ns); + res_close(); + goto next_ns; + } + /* + * Receive length & response + */ + read_len: + cp = ans; + len = INT16SZ; + while ((n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) <= 0) + break; + } + if (n <= 0) { + terrno = errno; + Perror(stderr, "read failed", errno); + res_close(); + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (terrno == ECONNRESET && !connreset) { + connreset = 1; + res_close(); + goto same_ns; + } + res_close(); + goto next_ns; + } + resplen = ns_get16(ans); + if (resplen > anssiz) { + Dprint(_res.options & RES_DEBUG, + (stdout, ";; response truncated\n") + ); + truncated = 1; + len = anssiz; + } else + len = resplen; + if (len < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; undersized: %d\n", len)); + terrno = EMSGSIZE; + badns |= (1 << ns); + res_close(); + goto next_ns; + } + cp = ans; + while (len != 0 && + (n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + len -= n; + } + if (n <= 0) { + terrno = errno; + Perror(stderr, "read(vc)", errno); + res_close(); + goto next_ns; + } + if (truncated) { + /* + * Flush rest of answer + * so connection stays in synch. + */ + anhp->tc = 1; + len = resplen - anssiz; + while (len != 0) { + char junk[PACKETSZ]; + + n = (len > sizeof(junk) + ? sizeof(junk) + : len); + if ((n = read(s, junk, n)) > 0) + len -= n; + else + break; + } + } + /* + * The calling applicating has bailed out of + * a previous call and failed to arrange to have + * the circuit closed or the server has got + * itself confused. Anyway drop the packet and + * wait for the correct one. + */ + if (hp->id != anhp->id) { + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; old answer (unexpected):\n"), + ans, (resplen>anssiz)?anssiz:resplen); + goto read_len; + } + } else { + /* + * Use datagrams. + */ + struct timeval timeout; + fd_set dsmask; + struct sockaddr_in from; + int fromlen; + + if ((s < 0) || vc) { + if (vc) + res_close(); + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { +#ifndef CAN_RECONNECT + bad_dg_sock: +#endif + terrno = errno; + Perror(stderr, "socket(dg)", errno); + return (-1); + } + connected = 0; + } +#ifndef CANNOT_CONNECT_DGRAM + /* + * On a 4.3BSD+ machine (client and server, + * actually), sending to a nameserver datagram + * port with no nameserver will cause an + * ICMP port unreachable message to be returned. + * If our datagram socket is "connected" to the + * server, we get an ECONNREFUSED error on the next + * socket operation, and select returns if the + * error message is received. We can thus detect + * the absence of a nameserver without timing out. + * If we have sent queries to at least two servers, + * however, we don't want to remain connected, + * as we wish to receive answers from the first + * server to respond. + */ + if (_res.nscount == 1 || (try == 0 && ns == 0)) { + /* + * Connect only if we are sure we won't + * receive a response from another server. + */ + if (!connected) { + if (connect(s, (struct sockaddr *)nsap, + sizeof *nsap + ) < 0) { + Aerror(stderr, + "connect(dg)", + errno, *nsap); + badns |= (1 << ns); + res_close(); + goto next_ns; + } + connected = 1; + } + if (send(s, (char*)buf, buflen, 0) != buflen) { + Perror(stderr, "send", errno); + badns |= (1 << ns); + res_close(); + goto next_ns; + } + } else { + /* + * Disconnect if we want to listen + * for responses from more than one server. + */ + if (connected) { +#ifdef CAN_RECONNECT + struct sockaddr_in no_addr; + + no_addr.sin_family = AF_INET; + no_addr.sin_addr.s_addr = INADDR_ANY; + no_addr.sin_port = 0; + (void) connect(s, + (struct sockaddr *) + &no_addr, + sizeof no_addr); +#else + int s1 = socket(PF_INET, SOCK_DGRAM,0); + if (s1 < 0) + goto bad_dg_sock; + (void) dup2(s1, s); + (void) close(s1); + Dprint(_res.options & RES_DEBUG, + (stdout, ";; new DG socket\n")) +#endif /* CAN_RECONNECT */ + connected = 0; + errno = 0; + } +#endif /* !CANNOT_CONNECT_DGRAM */ + if (sendto(s, (char*)buf, buflen, 0, + (struct sockaddr *)nsap, + sizeof *nsap) + != buflen) { + Aerror(stderr, "sendto", errno, *nsap); + badns |= (1 << ns); + res_close(); + goto next_ns; + } +#ifndef CANNOT_CONNECT_DGRAM + } +#endif /* !CANNOT_CONNECT_DGRAM */ + + /* + * Wait for reply + */ + timeout.tv_sec = (_res.retrans << try); + if (try > 0) + timeout.tv_sec /= _res.nscount; + if ((long) timeout.tv_sec <= 0) + timeout.tv_sec = 1; + timeout.tv_usec = 0; + wait: + if (s < 0 || s >= FD_SETSIZE) { + Perror(stderr, "s out-of-bounds", EMFILE); + res_close(); + goto next_ns; + } + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + n = select(s+1, &dsmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout); + if (n < 0) { + if (errno == EINTR) + goto wait; + Perror(stderr, "select", errno); + res_close(); + goto next_ns; + } + if (n == 0) { + /* + * timeout + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; timeout\n")); + gotsomewhere = 1; + res_close(); + goto next_ns; + } + errno = 0; + fromlen = sizeof(struct sockaddr_in); + resplen = recvfrom(s, (char*)ans, anssiz, 0, + (struct sockaddr *)&from, &fromlen); + if (resplen <= 0) { + Perror(stderr, "recvfrom", errno); + res_close(); + goto next_ns; + } + gotsomewhere = 1; + if (resplen < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; undersized: %d\n", + resplen)); + terrno = EMSGSIZE; + badns |= (1 << ns); + res_close(); + goto next_ns; + } + if (hp->id != anhp->id) { + /* + * response from old query, ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; old answer:\n"), + ans, (resplen>anssiz)?anssiz:resplen); + goto wait; + } +#ifdef CHECK_SRVR_ADDR + if (!(_res.options & RES_INSECURE1) && + !res_isourserver(&from)) { + /* + * response from wrong server? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; not our server:\n"), + ans, (resplen>anssiz)?anssiz:resplen); + goto wait; + } +#endif + if (!(_res.options & RES_INSECURE2) && + !res_queriesmatch(buf, buf + buflen, + ans, ans + anssiz)) { + /* + * response contains wrong query? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; wrong query name:\n"), + ans, (resplen>anssiz)?anssiz:resplen); + goto wait; + } + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { + DprintQ(_res.options & RES_DEBUG, + (stdout, "server rejected query:\n"), + ans, (resplen>anssiz)?anssiz:resplen); + badns |= (1 << ns); + res_close(); + /* don't retry if called from dig */ + if (!_res.pfcode) + goto next_ns; + } + if (!(_res.options & RES_IGNTC) && anhp->tc) { + /* + * get rest of answer; + * use TCP with same server. + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; truncated answer\n")); + v_circuit = 1; + res_close(); + goto same_ns; + } + } /*if vc/dg*/ + Dprint((_res.options & RES_DEBUG) || + ((_res.pfcode & RES_PRF_REPLY) && + (_res.pfcode & RES_PRF_HEAD1)), + (stdout, ";; got answer:\n")); + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ""), + ans, (resplen>anssiz)?anssiz:resplen); + /* + * If using virtual circuits, we assume that the first server + * is preferred over the rest (i.e. it is on the local + * machine) and only keep that one open. + * If we have temporarily opened a virtual circuit, + * or if we haven't been asked to keep a socket open, + * close the socket. + */ + if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || + !(_res.options & RES_STAYOPEN)) { + res_close(); + } + if (Rhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*Rhook)(nsap, buf, buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + case res_done: + done = 1; + break; + case res_nextns: + res_close(); + goto next_ns; + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + return (-1); + } + } while (!done); + + } + return (resplen); + next_ns: ; + } /*foreach ns*/ + } /*foreach retry*/ + res_close(); + if (!v_circuit) { + if (!gotsomewhere) + errno = ECONNREFUSED; /* no nameservers found */ + else + errno = ETIMEDOUT; /* no answer obtained */ + } else + errno = terrno; + return (-1); +} + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. This provides support for endhostent() + * which expects to close the socket. + * + * This routine is not expected to be user visible. + */ +void +res_close() { + if (s >= 0) { + (void) close(s); + s = -1; + connected = 0; + vc = 0; + } +} diff --git a/contrib/bind/lib/resolv/res_update.c b/contrib/bind/lib/resolv/res_update.c new file mode 100644 index 0000000..8e6c448 --- /dev/null +++ b/contrib/bind/lib/resolv/res_update.c @@ -0,0 +1,518 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: res_update.c,v 1.14 1998/03/10 22:04:48 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#include "port_before.h" +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "port_after.h" + +/* + * Separate a linked list of records into groups so that all records + * in a group will belong to a single zone on the nameserver. + * Create a dynamic update packet for each zone and send it to the + * nameservers for that zone, and await answer. + * Abort if error occurs in updating any zone. + * Return the number of zones updated on success, < 0 on error. + * + * On error, caller must deal with the unsynchronized zones + * eg. an A record might have been successfully added to the forward + * zone but the corresponding PTR record would be missing if error + * was encountered while updating the reverse zone. + */ + +#define NSMAX 16 + +struct ns1 { + char nsname[MAXDNAME]; + struct in_addr nsaddr1; +}; + +struct zonegrp { + char z_origin[MAXDNAME]; + int16_t z_class; + char z_soardata[MAXDNAME + 5 * INT32SZ]; + struct ns1 z_ns[NSMAX]; + int z_nscount; + ns_updrec * z_rr; + struct zonegrp *z_next; +}; + + +int +res_update(ns_updrec *rrecp_in) { + ns_updrec *rrecp, *tmprrecp; + u_char buf[PACKETSZ], answer[PACKETSZ], packet[2*PACKETSZ]; + char name[MAXDNAME], zname[MAXDNAME], primary[MAXDNAME], + mailaddr[MAXDNAME]; + u_char soardata[2*MAXCDNAME+5*INT32SZ]; + char *dname, *svdname, *cp1, *target; + u_char *cp, *eom; + HEADER *hp = (HEADER *) answer; + struct zonegrp *zptr = NULL, *tmpzptr, *prevzptr, *zgrp_start = NULL; + int i, j, k = 0, n, ancount, nscount, arcount, rcode, rdatasize, + newgroup, done, myzone, seen_before, numzones = 0; + u_int16_t dlen, class, qclass, type, qtype; + u_int32_t ttl; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } + + for (rrecp = rrecp_in; rrecp; rrecp = rrecp->r_next) { + dname = rrecp->r_dname; + n = strlen(dname); + if (dname[n-1] == '.') + dname[n-1] = '\0'; + qtype = T_SOA; + qclass = rrecp->r_class; + done = 0; + seen_before = 0; + + while (!done && dname) { + if (qtype == T_SOA) { + for (tmpzptr = zgrp_start; + tmpzptr && !seen_before; + tmpzptr = tmpzptr->z_next) { + if (strcasecmp(dname, + tmpzptr->z_origin) == 0 && + tmpzptr->z_class == qclass) + seen_before++; + for (tmprrecp = tmpzptr->z_rr; + tmprrecp && !seen_before; + tmprrecp = tmprrecp->r_grpnext) + if (strcasecmp(dname, tmprrecp->r_dname) == 0 + && tmprrecp->r_class == qclass) { + seen_before++; + break; + } + if (seen_before) { + /* + * Append to the end of + * current group. + */ + for (tmprrecp = tmpzptr->z_rr; + tmprrecp->r_grpnext; + tmprrecp = tmprrecp->r_grpnext) + (void)NULL; + tmprrecp->r_grpnext = rrecp; + rrecp->r_grpnext = NULL; + done = 1; + break; + } + } + } else if (qtype == T_A) { + for (tmpzptr = zgrp_start; + tmpzptr && !done; + tmpzptr = tmpzptr->z_next) + for (i = 0; i < tmpzptr->z_nscount; i++) + if (tmpzptr->z_class == qclass && + strcasecmp(tmpzptr->z_ns[i].nsname, + dname) == 0 && + tmpzptr->z_ns[i].nsaddr1.s_addr != 0) { + zptr->z_ns[k].nsaddr1.s_addr = + tmpzptr->z_ns[i].nsaddr1.s_addr; + done = 1; + break; + } + } + if (done) + break; + n = res_mkquery(QUERY, dname, qclass, qtype, NULL, + 0, NULL, buf, sizeof buf); + if (n <= 0) { + fprintf(stderr, "res_update: mkquery failed\n"); + return (n); + } + n = res_send(buf, n, answer, sizeof answer); + if (n < 0) { + fprintf(stderr, "res_update: send error for %s\n", + rrecp->r_dname); + return (n); + } + if (n < HFIXEDSZ) + return (-1); + ancount = ntohs(hp->ancount); + nscount = ntohs(hp->nscount); + arcount = ntohs(hp->arcount); + rcode = hp->rcode; + cp = answer + HFIXEDSZ; + eom = answer + n; + /* skip the question section */ + n = dn_skipname(cp, eom); + if (n < 0 || cp + n + 2 * INT16SZ > eom) + return (-1); + cp += n + 2 * INT16SZ; + + if (qtype == T_SOA) { + if (ancount == 0 && nscount == 0 && arcount == 0) { + /* + * if (rcode == NOERROR) then the dname exists but + * has no soa record associated with it. + * if (rcode == NXDOMAIN) then the dname does not + * exist and the server is replying out of NCACHE. + * in either case, proceed with the next try + */ + dname = strchr(dname, '.'); + if (dname != NULL) + dname++; + continue; + } else if ((rcode == NOERROR || rcode == NXDOMAIN) && + ancount == 0 && + nscount == 1 && arcount == 0) { + /* + * name/data does not exist, soa record supplied in the + * authority section + */ + /* authority section must contain the soa record */ + if ((n = dn_expand(answer, eom, cp, zname, + sizeof zname)) < 0) + return (n); + cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); + GETSHORT(type, cp); + GETSHORT(class, cp); + if (type != T_SOA || class != qclass) { + fprintf(stderr, "unknown answer\n"); + return (-1); + } + myzone = 0; + svdname = dname; + while (dname) + if (strcasecmp(dname, zname) == 0) { + myzone = 1; + break; + } else if ((dname = strchr(dname, '.')) != NULL) + dname++; + if (!myzone) { + dname = strchr(svdname, '.'); + if (dname != NULL) + dname++; + continue; + } + nscount = 0; + /* fallthrough */ + } else if (rcode == NOERROR && ancount == 1) { + /* + * found the zone name + * new servers will supply NS records for the zone + * in authority section and A records for those + * nameservers in the additional section + * older servers have to be explicitly queried for + * NS records for the zone + */ + /* answer section must contain the soa record */ + if ((n = dn_expand(answer, eom, cp, zname, + sizeof zname)) < 0) + return (n); + else + cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); + GETSHORT(type, cp); + GETSHORT(class, cp); + if (type == T_CNAME) { + dname = strchr(dname, '.'); + if (dname != NULL) + dname++; + continue; + } + if (strcasecmp(dname, zname) != 0 || + type != T_SOA || + class != rrecp->r_class) { + fprintf(stderr, "unknown answer\n"); + return (-1); + } + /* FALLTHROUGH */ + } else { + fprintf(stderr, + "unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n", + ancount, nscount, arcount, hp->rcode); + return (-1); + } + if (cp + INT32SZ + INT16SZ > eom) + return (-1); + /* continue processing the soa record */ + GETLONG(ttl, cp); + GETSHORT(dlen, cp); + if (cp + dlen > eom) + return (-1); + newgroup = 1; + zptr = zgrp_start; + prevzptr = NULL; + while (zptr) { + if (strcasecmp(zname, zptr->z_origin) == 0 && + type == T_SOA && class == qclass) { + newgroup = 0; + break; + } + prevzptr = zptr; + zptr = zptr->z_next; + } + if (!newgroup) { + for (tmprrecp = zptr->z_rr; + tmprrecp->r_grpnext; + tmprrecp = tmprrecp->r_grpnext) + ; + tmprrecp->r_grpnext = rrecp; + rrecp->r_grpnext = NULL; + done = 1; + cp += dlen; + break; + } else { + if ((n = dn_expand(answer, eom, cp, primary, + sizeof primary)) < 0) + return (n); + cp += n; + /* + * We don't have to bounds check here because the + * next use of 'cp' is in dn_expand(). + */ + cp1 = (char *)soardata; + strcpy(cp1, primary); + cp1 += strlen(cp1) + 1; + if ((n = dn_expand(answer, eom, cp, mailaddr, + sizeof mailaddr)) < 0) + return (n); + cp += n; + strcpy(cp1, mailaddr); + cp1 += strlen(cp1) + 1; + if (cp + 5*INT32SZ > eom) + return (-1); + memcpy(cp1, cp, 5*INT32SZ); + cp += 5*INT32SZ; + cp1 += 5*INT32SZ; + rdatasize = (u_char *)cp1 - soardata; + zptr = calloc(1, sizeof(struct zonegrp)); + if (zptr == NULL) + return (-1); + if (zgrp_start == NULL) + zgrp_start = zptr; + else + prevzptr->z_next = zptr; + zptr->z_rr = rrecp; + rrecp->r_grpnext = NULL; + strcpy(zptr->z_origin, zname); + zptr->z_class = class; + memcpy(zptr->z_soardata, soardata, rdatasize); + /* fallthrough to process NS and A records */ + } + } else if (qtype == T_NS) { + if (rcode == NOERROR && ancount > 0) { + strcpy(zname, dname); + for (zptr = zgrp_start; zptr; zptr = zptr->z_next) { + if (strcasecmp(zname, zptr->z_origin) == 0) + break; + } + if (zptr == NULL) + /* should not happen */ + return (-1); + if (nscount > 0) { + /* + * answer and authority sections contain + * the same information, skip answer section + */ + for (j = 0; j < ancount; j++) { + n = dn_skipname(cp, eom); + if (n < 0) + return (-1); + n += 2*INT16SZ + INT32SZ; + if (cp + n + INT16SZ > eom) + return (-1); + cp += n; + GETSHORT(dlen, cp); + cp += dlen; + } + } else + nscount = ancount; + /* fallthrough to process NS and A records */ + } else { + fprintf(stderr, "cannot determine nameservers for %s:\ +ans=%d, auth=%d, add=%d, rcode=%d\n", + dname, ancount, nscount, arcount, hp->rcode); + return (-1); + } + } else if (qtype == T_A) { + if (rcode == NOERROR && ancount > 0) { + arcount = ancount; + ancount = nscount = 0; + /* fallthrough to process A records */ + } else { + fprintf(stderr, "cannot determine address for %s:\ +ans=%d, auth=%d, add=%d, rcode=%d\n", + dname, ancount, nscount, arcount, hp->rcode); + return (-1); + } + } + /* process NS records for the zone */ + j = 0; + for (i = 0; i < nscount; i++) { + if ((n = dn_expand(answer, eom, cp, name, + sizeof name)) < 0) + return (n); + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (-1); + GETSHORT(type, cp); + GETSHORT(class, cp); + GETLONG(ttl, cp); + GETSHORT(dlen, cp); + if (cp + dlen > eom) + return (-1); + if (strcasecmp(name, zname) == 0 && + type == T_NS && class == qclass) { + if ((n = dn_expand(answer, eom, cp, + name, sizeof name)) < 0) + return (n); + target = zptr->z_ns[j++].nsname; + strcpy(target, name); + } + cp += dlen; + } + if (zptr->z_nscount == 0) + zptr->z_nscount = j; + /* get addresses for the nameservers */ + for (i = 0; i < arcount; i++) { + if ((n = dn_expand(answer, eom, cp, name, + sizeof name)) < 0) + return (n); + cp += n; + if (cp + 3 * INT16SZ + INT32SZ > eom) + return (-1); + GETSHORT(type, cp); + GETSHORT(class, cp); + GETLONG(ttl, cp); + GETSHORT(dlen, cp); + if (cp + dlen > eom) + return (-1); + if (type == T_A && dlen == INT32SZ && class == qclass) { + for (j = 0; j < zptr->z_nscount; j++) + if (strcasecmp(name, zptr->z_ns[j].nsname) == 0) { + memcpy(&zptr->z_ns[j].nsaddr1.s_addr, cp, + INT32SZ); + break; + } + } + cp += dlen; + } + if (zptr->z_nscount == 0) { + dname = zname; + qtype = T_NS; + continue; + } + done = 1; + for (k = 0; k < zptr->z_nscount; k++) + if (zptr->z_ns[k].nsaddr1.s_addr == 0) { + done = 0; + dname = zptr->z_ns[k].nsname; + qtype = T_A; + } + + } /* while */ + } + + _res.options |= RES_DEBUG; + for (zptr = zgrp_start; zptr; zptr = zptr->z_next) { + + /* append zone section */ + rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin, + zptr->z_class, ns_t_soa, 0); + if (rrecp == NULL) { + fprintf(stderr, "saverrec error\n"); + fflush(stderr); + return (-1); + } + rrecp->r_grpnext = zptr->z_rr; + zptr->z_rr = rrecp; + + n = res_mkupdate(zptr->z_rr, packet, sizeof packet); + if (n < 0) { + fprintf(stderr, "res_mkupdate error\n"); + fflush(stderr); + return (-1); + } else + fprintf(stdout, "res_mkupdate: packet size = %d\n", n); + + /* + * Override the list of NS records from res_init() with + * the authoritative nameservers for the zone being updated. + * Sort primary to be the first in the list of nameservers. + */ + for (i = 0; i < zptr->z_nscount; i++) { + if (strcasecmp(zptr->z_ns[i].nsname, + zptr->z_soardata) == 0) { + struct in_addr tmpaddr; + + if (i != 0) { + strcpy(zptr->z_ns[i].nsname, + zptr->z_ns[0].nsname); + strcpy(zptr->z_ns[0].nsname, + zptr->z_soardata); + tmpaddr = zptr->z_ns[i].nsaddr1; + zptr->z_ns[i].nsaddr1 = + zptr->z_ns[0].nsaddr1; + zptr->z_ns[0].nsaddr1 = tmpaddr; + } + break; + } + } + for (i = 0; i < MAXNS; i++) { + _res.nsaddr_list[i].sin_addr = zptr->z_ns[i].nsaddr1; + _res.nsaddr_list[i].sin_family = AF_INET; + _res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); + } + _res.nscount = (zptr->z_nscount < MAXNS) ? + zptr->z_nscount : MAXNS; + n = res_send(packet, n, answer, sizeof(answer)); + if (n < 0) { + fprintf(stderr, "res_send: send error, n=%d\n", n); + break; + } else + numzones++; + } + + /* free malloc'ed memory */ + while(zgrp_start) { + zptr = zgrp_start; + zgrp_start = zgrp_start->z_next; + res_freeupdrec(zptr->z_rr); /* Zone section we allocated. */ + free((char *)zptr); + } + + return (numzones); +} diff --git a/contrib/bind/port/Makefile b/contrib/bind/port/Makefile new file mode 100644 index 0000000..803ba0d --- /dev/null +++ b/contrib/bind/port/Makefile @@ -0,0 +1,75 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# $Id: Makefile,v 8.12 1997/06/19 03:22:17 halley Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsdos +SHELL= /bin/sh +O=o +A=a +DESTDIR= +DESTINC= /usr/local/bind/include +DESTLIB= /usr/local/lib +TOP= .. +INCL= ${TOP}/include +PORTINCL= ${TOP}/port/${SYSTYPE}/include +LIBBIND= ${TOP}/lib/libbind.${A} +RANLIB= ranlib +AR= ar cruv +INSTALL= install +CDEBUG= -g + +SUBDIRS = bsdos decunix linux netbsd sunos ultrix + +MARGS = "SYSTYPE=${SYSTYPE}" "SHELL=${SHELL}" "A=${A}" "O=${O}" \ + "CC=${CC}" "LEX=${LEX}" "CDEBUG=${CDEBUG}" \ + "SYSLIBS=${SYSLIBS}" "LDFLAGS=${LDFLAGS}" \ + "DESTDIR=${DESTDIR}" "PIDDIR=${PIDDIR}" "DESTMAN=${DESTMAN}" \ + "DESTBIN=${DESTBIN}" "DESTSBIN=${DESTSBIN}" "DESTEXEC=${DESTEXEC}" \ + "DESTLIB=${DESTLIB}" "DESTINC=${DESTINC}" "DESTHELP=${DESTHELP}" \ + "RANLIB=${RANLIB}" "AR=${AR}" "ARPREF=${ARPREF}" "ARSUFF=${ARSUFF}" \ + "INCL=../${INCL}" "PORTINCL=../${PORTINCL}" \ + "LIBBIND=../${LIBBIND}" \ + "INSTALL=${INSTALL}" "CPPFLAGS=${CPPFLAGS}" "TOP=../${TOP}" + +all:: + +all depend install:: + @(cd ${SYSTYPE}; pwd; ${MAKE} ${MARGS} $@) + +distclean:: clean + @set -e; for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ + done + +clean:: + @set -e; cd ${SYSTYPE}; pwd; ${MAKE} ${MARGS} clean + +clean:: FRC + rm -f *~ *.BAK *.CKP *.orig .systype + +install:: + +links:: FRC + @set -e; \ + ln -s SRC/systype SRC/settings .; \ + mkdir ${SYSTYPE}; cd ${SYSTYPE}; pwd; ln -s ../SRC/${SYSTYPE} SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + ${MAKE} ${MARGS} links + +FRC: diff --git a/contrib/bind/port/README b/contrib/bind/port/README new file mode 100644 index 0000000..d8dbd10 --- /dev/null +++ b/contrib/bind/port/README @@ -0,0 +1,66 @@ + +Porting BIND 8 to Another System + + Make sure to base your port on an existing one. If your port is + for a new release of an already supported operating system, please + try to make the existing port support the new release instead of + making a new port directory. For an example of how to do this, + look at how the Solaris port uses os_version.h in port_after.h. See + port/solaris/include/Makefile and port/solaris/bin/make_os_version + to learn how an os_version.h is made. + + Porting problems fall into broad categories which have simple answers: + + Include File Missing or Broken + + Make one (possibly empty) in port/*/include or in + port/*/include/sys. Broken include files can be fixed; see + the BSD/OS and ULTRIX ports for examples of how to do this. + + Library Function Missing: + + Make one (possibly copying it from some other port and hacking) + and cause it to appear in port/libport.a by virtue of building + it in port/*/Makefile. An example is the __ansi_realloc() + routine in the SunOS port. + + Desired system feature absent or not prototyped or whatever: + + Edit port/*/include/port_{before,after}.h. read a few source + files in lib/ or bin/ to see when/why these are #included. + + "Make" doesn't work even though my system has a port/* subdir: + + Type "uname -s -r" at your shell and see if the resulting + string is present in your system's putative port/*/probe + file. If not, try adding it. If it works, send mail to + bind-bugs@isc.org. + + My system doesn't have enough of ANSI and POSIX to allow a port: + + Give up. Get a different system. + + Porting mistakes also fall into broad categories with simple answers: + + I Can't Get It To Build Without Compiler (Not Linker!) Warnings: + + Keep trying, you're not done yet. + + I Need To Add Another Portability #define And Some #ifdef's: + + Make sure it won't hurt any other port. Send us some mail. + + I Just Have To Edit A Source File To Get It To Compile: + + You are probably missing one of the above opportunities to do + the right thing and you should rethink your approach and get + some advice before you send in your port. But it's possible + that a non-UNIX system will need a different porting layer, + especially in isc/eventlib.c and its friends, so contact us + if you're stuck on this point, there may be something we can + do. Send mail to bind-bugs@isc.org. + + My Employer Won't Allow Me To Send In Porting Diffs: + + You probably need a new employer. But try really hard, OK? + diff --git a/contrib/bind/port/freebsd/Makefile b/contrib/bind/port/freebsd/Makefile new file mode 100644 index 0000000..966cd56 --- /dev/null +++ b/contrib/bind/port/freebsd/Makefile @@ -0,0 +1,85 @@ +# Copyright (c) 1996 by Internet Software Consortium +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# $Id: Makefile,v 1.6 1997/06/19 03:22:25 halley Exp $ + +# these are only appropriate for BSD 4.4 or derivatives, and are used in +# development. normal builds will be done in the top level directory and +# this Makefile will be invoked with a lot of overrides for the following: +SYSTYPE= bsd +DESTDIR = +DESTLIB = /usr/local/lib +O=o +A=a +CC= cc +LD= ld +SHELL= /bin/sh +CDEBUG= -g +TOP= ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.${A} +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} +LD_LIBFLAGS= -x -r +AR= ar cruv +RANLIB= ranlib +INSTALL= install + +SUBDIRS= include + +SRCS= noop.c + +OBJS= noop.${O} + +MARGS= DESTDIR="${DESTDIR}" DESTINC="${DESTINC}" INSTALL="${INSTALL}" + +all depend clean distclean install:: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ + done + +all:: ${LIBBIND} + +${LIBBIND}: ${OBJS} + ${AR} ${LIBBIND} ${ARPREF} ${OBJS} ${ARSUFF} + ${RANLIB} ${LIBBIND} + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + -${LDS} ${LD} ${LD_LIBFLAGS} $*.${O} && ${LDS} mv a.out $*.${O} + +distclean:: clean + +clean:: FRC + rm -f .depend a.out core tags + rm -f *.${O} *.BAK *.CKP *~ + +depend:: FRC + mkdep -I${INCL} -I${PORTINCL} ${CPPFLAGS} ${SRCS} + +links: FRC + @set -e; ln -s SRC/*.[ch] SRC/bin SRC/Makefile.set SRC/probe . + @set -e; for x in ${SUBDIRS}; do \ + ( mkdir $$x; cd $$x; pwd; ln -s ../SRC/$$x SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + ${MAKE} ${MARGS} links ); \ + done + +install:: FRC + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/port/freebsd/Makefile.set b/contrib/bind/port/freebsd/Makefile.set new file mode 100644 index 0000000..fe256bc --- /dev/null +++ b/contrib/bind/port/freebsd/Makefile.set @@ -0,0 +1,18 @@ +'CC=cc' +'CDEBUG=-O2 -g' +'DESTBIN=/usr/bin' +'DESTSBIN=/usr/sbin' +'DESTEXEC=/usr/libexec' +'DESTMAN=/usr/share/man' +'DESTHELP=/usr/share/misc' +'DESTETC=/etc' +'DESTRUN=/var/run' +'LEX=lex -I' +'YACC=yacc -d' +'SYSLIBS=-ll -lutil' +'INSTALL=install' +'MANDIR=cat' +'MANROFF=(tbl|nroff -man)' +'CATEXT=0' +'PS=ps' +'RANLIB=ranlib' diff --git a/contrib/bind/port/freebsd/include/Makefile b/contrib/bind/port/freebsd/include/Makefile new file mode 100644 index 0000000..dd8b4e9 --- /dev/null +++ b/contrib/bind/port/freebsd/include/Makefile @@ -0,0 +1,91 @@ +# ++Copyright++ +# - +# Copyright (c) +# 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. +# - +# --Copyright-- + +SUBDIRS = sys +HFILES = + +DESTDIR= +DESTINC= /usr/local/bind/include +INSTALL= install + +MARGS= DESTDIR="${DESTDIR}" DESTINC="${DESTINC}" INSTALL="${INSTALL}" + +all depend clean distclean install:: + @for x in ${SUBDIRS}; do \ + (cd $$x; pwd; ${MAKE} ${MARGS} $@); \ + done + +distclean:: clean + +clean:: + rm -f *~ *.BAK *.CKP *.orig + +links: FRC + @set -e; ln -s SRC/*.h . + @set -e; for x in ${SUBDIRS}; do \ + ( mkdir $$x; cd $$x; pwd; ln -s ../SRC/$$x SRC; \ + cp SRC/Makefile Makefile; chmod +w Makefile; \ + ${MAKE} ${MARGS} links ); \ + done + +install:: ${DESTDIR}${DESTINC} + -for x in "" ${HFILES}; do \ + if [ -n "$$x" ]; then \ + ${INSTALL} -c -m 444 $$x ${DESTDIR}${DESTINC}/$$x; \ + fi; \ + done + +${DESTDIR}${DESTINC}: + mkdir -p ${DESTDIR}${DESTINC} + +FRC: diff --git a/contrib/bind/port/freebsd/include/port_after.h b/contrib/bind/port/freebsd/include/port_after.h new file mode 100644 index 0000000..c2bc49a --- /dev/null +++ b/contrib/bind/port/freebsd/include/port_after.h @@ -0,0 +1,33 @@ +#define CAN_RECONNECT +#define USE_POSIX +#define POSIX_SIGNALS +#define USE_UTIME +#define USE_WAITPID +#define HAVE_GETRUSAGE +#define HAVE_FCHMOD +#define NEED_PSELECT +#define HAVE_SA_LEN +#define USE_LOG_CONS +#define HAVE_CHROOT +#define CAN_CHANGE_ID + +#define _TIMEZONE timezone + +#define PORT_NONBLOCK O_NONBLOCK +#define PORT_WOULDBLK EWOULDBLOCK +#define WAIT_T int +#define KSYMS "/kernel" +#define KMEM "/dev/kmem" +#define UDPSUM "udpcksum" + +/* + * We need to know the IPv6 address family number even on IPv4-only systems. + * Note that this is NOT a protocol constant, and that if the system has its + * own AF_INET6, different from ours below, all of BIND's libraries and + * executables will need to be recompiled after the system <sys/socket.h> + * has had this type added. The type number below is correct on most BSD- + * derived systems for which AF_INET6 is defined. + */ +#ifndef AF_INET6 +#define AF_INET6 24 +#endif diff --git a/contrib/bind/port/freebsd/include/port_before.h b/contrib/bind/port/freebsd/include/port_before.h new file mode 100644 index 0000000..bc6b89c --- /dev/null +++ b/contrib/bind/port/freebsd/include/port_before.h @@ -0,0 +1,6 @@ +#define WANT_IRS_NIS +#define WANT_IRS_PW +#define WANT_IRS_GR +#define SIG_FN void +#define ts_sec tv_sec +#define ts_nsec tv_nsec diff --git a/contrib/bind/port/freebsd/include/sys/Makefile b/contrib/bind/port/freebsd/include/sys/Makefile new file mode 100644 index 0000000..ad7751c --- /dev/null +++ b/contrib/bind/port/freebsd/include/sys/Makefile @@ -0,0 +1,77 @@ +# ++Copyright++ +# - +# Copyright (c) +# 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. +# - +# --Copyright-- + +HFILES= bitypes.h cdefs.h + +DESTDIR= +DESTINC= /usr/local/bind/include + +all depend: + +distclean: clean + +clean: + rm -f *~ *.BAK *.CKP *.orig time.h stat.h + +links: + @set -e; ln -s SRC/*.h . + +install: ${DESTDIR}${DESTINC}/sys + for x in ${HFILES}; do \ + if [ -f $$x ]; then \ + ${INSTALL} -c -m 444 $$x ${DESTDIR}${DESTINC}/sys/$$x;\ + fi; \ + done + +${DESTDIR}${DESTINC}/sys: + mkdir -p ${DESTDIR}${DESTINC}/sys diff --git a/contrib/bind/port/freebsd/include/sys/bitypes.h b/contrib/bind/port/freebsd/include/sys/bitypes.h new file mode 100644 index 0000000..ad0dfcb --- /dev/null +++ b/contrib/bind/port/freebsd/include/sys/bitypes.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ + + /* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ + typedef /*signed*/ char int8_t; + typedef unsigned char u_int8_t; + typedef short int16_t; + typedef unsigned short u_int16_t; + typedef int int32_t; + typedef unsigned int u_int32_t; + +# if 0 /* don't fight with these unless you need them */ + typedef long long int64_t; + typedef unsigned long long u_int64_t; +# endif + +#endif /* __BIT_TYPES_DEFINED__ */ diff --git a/contrib/bind/port/freebsd/noop.c b/contrib/bind/port/freebsd/noop.c new file mode 100644 index 0000000..f8eb9f4 --- /dev/null +++ b/contrib/bind/port/freebsd/noop.c @@ -0,0 +1,4 @@ +static void +noop() { + /* NOOP */ +} diff --git a/contrib/bind/port/freebsd/probe b/contrib/bind/port/freebsd/probe new file mode 100755 index 0000000..d1b0cfe --- /dev/null +++ b/contrib/bind/port/freebsd/probe @@ -0,0 +1,11 @@ +#!/bin/sh + +uname=/usr/bin/uname + +if [ -f $uname ]; then + case `$uname -s` in + FreeBSD) exit 0 ;; + esac +fi + +exit 1 diff --git a/contrib/bind/port/settings b/contrib/bind/port/settings new file mode 100755 index 0000000..942236e --- /dev/null +++ b/contrib/bind/port/settings @@ -0,0 +1,35 @@ +#!/bin/sh + +# this process is necessary because make(1) puts its command line into +# the environment, and when we exec a sub-make we need these command +# line settings (like CDEBUG=-g for example) to override what we get out +# of port/$systype/Makefile.set. therefore feed Makefile.set to this +# and it will merge things appropriately. a cache file is maintained +# to avoid calling this script way too often. + +cachefile=${1-//} +if [ -f "$cachefile" ]; then + echo "Using $cachefile" >&2 + exec cat $cachefile +fi + +case $cachefile in +//) ;; +*) echo "Making $cachefile" >&2 ;; +esac + +result='' +while read setting; do + var=`expr "$setting" : "'\([A-Z0-9_]*\)="` + val=`expr "$setting" : "'[A-Z0-9_]*=\([^']*\)'\$"` + eval "env=`echo \\${\$var-'$val'}`" + result="$result '$var=$env'" +done + +case $cachefile in +//) echo $result ;; +*) echo $result > $cachefile + exec cat $cachefile ;; +esac + +exit diff --git a/contrib/bind/port/systype b/contrib/bind/port/systype new file mode 100755 index 0000000..b022651 --- /dev/null +++ b/contrib/bind/port/systype @@ -0,0 +1,31 @@ +#!/bin/sh + +cachefile=${1-//} + +if [ -f $cachefile ]; then + echo "Using $cachefile" >&2 + exec cat $cachefile +fi + +case $cachefile in +/*) ;; +*) cachefile=`pwd`/$cachefile ;; +esac + +cd `dirname $0` +for systype in [a-z]*; do + if [ -f $systype/probe ]; then + if sh $systype/probe; then + case $cachefile in + //) ;; + *) echo "Making $cachefile" >&2 + echo $systype > $cachefile + ;; + esac + exec echo $systype + fi + fi +done + +echo unknown +exit 0 |