added djbdns patch provided by Johnny Halfmoon
authorMarkus Wigge <mwigge@marcant.net>
Tue, 5 May 2009 09:27:07 +0000 (09:27 +0000)
committerMarkus Wigge <mwigge@marcant.net>
Tue, 5 May 2009 09:27:07 +0000 (09:27 +0000)
removed dnsmasq.patch as the options were included upstream already.

SVN-Revision: 15612

36 files changed:
net/djbdns/Changelog [new file with mode: 0644]
net/djbdns/Makefile [new file with mode: 0644]
net/djbdns/README [new file with mode: 0644]
net/djbdns/files/axfrdns.init [new file with mode: 0644]
net/djbdns/files/axfrdns/tcp [new file with mode: 0644]
net/djbdns/files/djbdns.conf [new file with mode: 0644]
net/djbdns/files/dnscache.init [new file with mode: 0644]
net/djbdns/files/dnscache/dnsroots.global [new file with mode: 0644]
net/djbdns/files/dnscache/servers/@ [new file with mode: 0644]
net/djbdns/files/dnsqrx [new file with mode: 0644]
net/djbdns/files/dnsroots-update [new file with mode: 0644]
net/djbdns/files/rbldns.init [new file with mode: 0644]
net/djbdns/files/rbldns/data [new file with mode: 0644]
net/djbdns/files/tinydns.init [new file with mode: 0644]
net/djbdns/files/tinydns/add-alias [new file with mode: 0644]
net/djbdns/files/tinydns/add-childns [new file with mode: 0644]
net/djbdns/files/tinydns/add-host [new file with mode: 0644]
net/djbdns/files/tinydns/add-mx [new file with mode: 0644]
net/djbdns/files/tinydns/add-ns [new file with mode: 0644]
net/djbdns/files/tinydns/data [new file with mode: 0644]
net/djbdns/files/walldns.init [new file with mode: 0644]
net/djbdns/patches/100-crosscompile.patch [new file with mode: 0644]
net/djbdns/patches/110-cachestats.patch [new file with mode: 0644]
net/djbdns/patches/120-compiler-temporary-filename.patch [new file with mode: 0644]
net/djbdns/patches/130-dnscache-multiple-ip.patch [new file with mode: 0644]
net/djbdns/patches/140-dnsnamex-extra-command.patch [new file with mode: 0644]
net/djbdns/patches/200-dnscache-cname-handling.patch [new file with mode: 0644]
net/djbdns/patches/210-dnscache-strict-forwardonly.patch [new file with mode: 0644]
net/djbdns/patches/220-dnscacheip-space-separator.patch [new file with mode: 0644]
net/djbdns/patches/230-tinydns-data-semantic-error.patch [new file with mode: 0644]
net/djbdns/patches/240-tinydns-alias-chain-truncation.patch [new file with mode: 0644]
net/djbdns/patches/250-djbdns-1.05-slogging.patch [new file with mode: 0644]
net/djbdns/patches/260-djbdns-1.05-dnsfilter-replace.patch [new file with mode: 0644]
net/djbdns/patches/300-bugfix1-dempsky.patch [new file with mode: 0644]
net/djbdns/patches/310-bugfix2-merge-outgoing-requests.patch [new file with mode: 0644]
net/djbdns/patches/320-bugfix3-cache-soa-records.patch [new file with mode: 0644]

diff --git a/net/djbdns/Changelog b/net/djbdns/Changelog
new file mode 100644 (file)
index 0000000..31056ee
--- /dev/null
@@ -0,0 +1,24 @@
+#Changelog for the djbdns port for OpenWRT
+
+4 20090418 jhalfmoon
+bugfix - The dnscache postinst script had a bug that prevented djbdns from being compiled into a firmware image.
+bugfix - The dnscache startup script now uses /dev/urandom instead of /dev/random as a source of randomness. Using /dev/random does not work on 2.6 kernels.
+bugfix - dnscache no longer tries to use /tmp/resolv.conf.auto but /etc/resolv.conf instead. This only applies when useresolvconf==1.
+change - In menuconfig: djbdns moved from network to network/DNS 
+change - Removed the dnscache postinst script to the dnscache startup script. The script configures dnscache to accept connections from certain local network adresses.
+change - The dnscache startup script was cleaned up a bit. 
+change - default logging level is now info instead of notice.
+enhancement - Added option to add list of resolvers to UCI config for use in forwardonly mode. Two OpenDNS example addresses are added as a default.
+
+3 20090409 jhalfmoon
+bugfix - The restart routines of all scripts were broken causing restart to fail
+bugfix - dnsqrx was broken, script accidentally relied on bash instead of sh
+
+2 20090406 jhalfmoon
+bugfix - dnscache init script did not correctly handle /tmp/resolv.conf.auto
+enhancement - Addded the dnsqr command from http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/dnsqrx
+change - Default dnscache CACHESIZE was set too low, was 200KB, is now 1MB
+change - Added list of patches and made some overall adjustments to the README
+
+1 20090404 jhalfmoon
+Initial release
diff --git a/net/djbdns/Makefile b/net/djbdns/Makefile
new file mode 100644 (file)
index 0000000..bcd1f22
--- /dev/null
@@ -0,0 +1,205 @@
+# Copyright (C) 2007 OpenWrt.org
+# Original port by FreeWRT project.
+#
+# 2007     Alexander Tsvyashchenko  Adapted FreeWRT port for OpenWRT (Trac ticket 2497)
+# 2008     Some Danish guy          Created a port for OpenWRT 7.09
+# 20090403 jhalfmoon                Modified and augmented existing packages to work on OpenWRT buildroot (v8.09)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=djbdns
+PKG_VERSION:=1.05
+PKG_RELEASE:=4
+
+PKG_SOURCE:=${PKG_NAME}-${PKG_VERSION}.tar.gz
+PKG_SOURCE_URL:=http://cr.yp.to/djbdns/
+PKG_MD5SUM:=3147c5cd56832aa3b41955c7a51cbeb2
+PKG_BUILD_DEPENDS:=daemontools ucspi-tcp
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/djbdns/Default
+  SECTION:=net
+  CATEGORY:=Network
+  URL:=http://cr.yp.to/djbdns.html
+  SUBMENU:=DNS
+#  SUBMENU:=djbdns
+endef
+
+define Package/djbdns-base
+  $(call Package/djbdns/Default)
+  TITLE:=djbdns base configuration file
+endef
+
+define Package/djbdns-dnscache
+  $(call Package/djbdns/Default)
+  TITLE:=Recursive and forwarding caching name server
+  DEPENDS:= +djbdns-base
+endef
+
+define Package/djbdns-tinydns
+  $(call Package/djbdns/Default)
+  TITLE:=Authoritative name server
+  DEPENDS:= +djbdns-base
+endef
+
+define Package/djbdns-axfrdns
+  $(call Package/djbdns/Default)
+  TITLE:=Zone transfer server
+  DEPENDS:= +djbdns-base +djbdns-tinydns +ucspi-tcp
+endef
+
+define Package/djbdns-rbldns
+  $(call Package/djbdns/Default)
+  TITLE:=Real-time Block List name server
+  DEPENDS:= +djbdns-base
+endef
+
+define Package/djbdns-walldns
+  $(call Package/djbdns/Default)
+  TITLE:=Reverse DNS wall
+  DEPENDS:= +djbdns-base
+endef
+
+define Package/djbdns-tools
+  $(call Package/djbdns/Default)
+  TITLE:=Tools for testing and debugging DNS issues
+endef
+
+define Package/djdbns/description
+       djbdns is a collection of Domain Name System tools.
+               It includes software for all the fundamental DNS operations: 
+       * DNS server: publishing addresses of Internet hosts.
+       * DNS cache: finding addresses of Internet hosts.
+       * DNS client: talking to a DNS cache.
+               
+       Also included is a DNS client C library, several command-line
+               DNS client utilities, several DNS debugging tools.
+endef
+
+define Package/djbdns-base/description
+       The shared config file for the djbdns daemons.
+endef
+
+define Package/djbdns-dnscache/description
+       dnscache is a DNS cache.
+               It accepts recursive DNS queries from local clients such as web
+               browsers and mail transfer agents. It collects responses from
+       remote DNS servers. It caches the responses to save time later. 
+endef
+
+define Package/djbdns-tinydns/description
+       tinydns is a DNS server.
+       It accepts iterative DNS queries from hosts around the Internet
+               and responds with locally configured information. 
+endef
+
+define Package/djbdns-axfrdns/description
+       axfrdns is a DNS zone-transfer server.
+       It reads a zone-transfer request in DNS-over-TINSTALL_DATA format
+               from its standard input and responds with locally configured
+       information. 
+endef
+
+define Package/djbdns-rbldns/description
+       rbldns is an IP-address-listing DNS server.
+       It accepts iterative DNS queries from hosts around the Internet asking
+               about various IP addresses. It provides responses showing whether the
+       addresses are on a locally configured list, such as RBL or DUL. 
+endef
+
+define Package/djbdns-walldns/description
+       walldns is a reverse DNS wall.
+       It accepts iterative DNS queries for in-addr.arpa domains from hosts
+               around the Internet and supplies generic responses that avoid
+       revealing local host information. 
+endef
+
+define Package/djbdns-tools/description
+       Several command-line DNS client utilities and DNS debugging tools.
+endef
+
+define Build/Compile
+       TARGET_CC="$(TARGET_CC)" \
+       TARGET_CFLAGS="$(TARGET_CFLAGS)" \
+       TARGET_LDFLAGS="$(TARGET_LDFLAGS)" \
+       $(MAKE) -C $(PKG_BUILD_DIR)
+endef
+
+define Package/djbdns-base/install
+       $(INSTALL_DIR) $(1)/etc/config
+       $(INSTALL_DATA) ./files/djbdns.conf $(1)/etc/config/djbdns
+endef
+
+define Package/djbdns-dnscache/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       (cd $(PKG_BUILD_DIR); \
+       $(INSTALL_BIN) dnscache pickdns pickdns-data \
+       $(1)/usr/bin)
+       $(INSTALL_DIR) $(1)/etc
+       $(CP) -r ./files/dnscache $(1)/etc/
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/dnscache.init $(1)/etc/init.d/dnscache
+endef
+
+define Package/djbdns-tinydns/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       (cd $(PKG_BUILD_DIR); \
+       $(INSTALL_BIN) tinydns tinydns-data tinydns-edit tinydns-get \
+       $(1)/usr/bin)
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/tinydns.init $(1)/etc/init.d/tinydns
+       $(CP) -r ./files/tinydns $(1)/etc/
+endef
+
+define Package/djbdns-axfrdns/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       (cd $(PKG_BUILD_DIR); \
+       $(INSTALL_BIN) axfrdns axfr-get \
+       $(1)/usr/bin)
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/axfrdns.init $(1)/etc/init.d/axfrdns
+       $(CP) -r ./files/axfrdns $(1)/etc/
+endef
+
+define Package/djbdns-rbldns/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       (cd $(PKG_BUILD_DIR); \
+       $(INSTALL_BIN) rbldns rbldns-data \
+       $(1)/usr/bin)
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/rbldns.init $(1)/etc/init.d/rbldns
+       $(CP) -r ./files/rbldns $(1)/etc/
+endef
+
+define Package/djbdns-walldns/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       (cd $(PKG_BUILD_DIR); \
+       $(INSTALL_BIN) walldns \
+       $(1)/usr/bin)
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/walldns.init $(1)/etc/init.d/walldns
+endef
+
+define Package/djbdns-tools/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       (cd $(PKG_BUILD_DIR); \
+       $(INSTALL_BIN) dnsfilter dnsip dnsipq dnsmx dnsname dnsnamex dnsq \
+                       dnsqr dnstrace dnstracesort dnstxt random-ip \
+       $(1)/usr/bin)
+       $(INSTALL_BIN) ./files/dnsroots-update $(1)/usr/bin/
+       $(INSTALL_BIN) ./files/dnsqrx $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,djbdns-base))
+$(eval $(call BuildPackage,djbdns-tinydns))
+$(eval $(call BuildPackage,djbdns-dnscache))
+$(eval $(call BuildPackage,djbdns-axfrdns))
+$(eval $(call BuildPackage,djbdns-rbldns))
+$(eval $(call BuildPackage,djbdns-walldns))
+$(eval $(call BuildPackage,djbdns-tools))
+
diff --git a/net/djbdns/README b/net/djbdns/README
new file mode 100644 (file)
index 0000000..f6a9478
--- /dev/null
@@ -0,0 +1,278 @@
+
+# 20090409 jhalfmoon@milksnot.com - Don't hesitate to let me know if you decide to use it and/or what you think of it.
+
+This is a port of djbdns for OpenWRT (>= v8.09). Features:
+
+- works with the most current buildroot
+- makes use of the UCI configuration system
+- components are seperately packaged to minimize package footprint
+- most of the popular and necessary available patches are applied
+- documentation available (you're reading it)
+
+The djbdns package is a set of compact, reliable and fast DNS daemons and tools. This port is based on the work done by a few other people:
+
+- The FreeWRT project
+- Alexander Tsvyashchenko - https://dev.openwrt.org/ticket/2497
+- Some anonymous (Danish?) person - https://dev.openwrt.org/ticket/3837
+
+Using the previous work as a base, time went into rewriting the Make file, adding patches, adding the config system and writing this documentation. The ucspi-tcp and daemontools packages were not touched; they work just fine in the state they were found on OpenWRT TRAC.
+
+The following document meant to give some useful information about this package. You do not need to know all of the following to install or compile this package; it is only meant as an addition to help potential users on their way. An installation could theoretically be as simple as: "opkg install dnscache.ipk ; /etc/init.d/dnscache start". To find more about the workings of djbdns, visit:
+
+http://cr.yp.to/djbdns.html
+
+On the following sites you can find even more info, including text about the patches included in this package:
+
+http://www.lifewithdjbdns.com/
+http://www.thedjbway.org/djbdns/resources.html
+http://www.fefe.de/djbdns/
+http://homepages.tesco.net/~J.deBoynePollard/FGA/#DNS
+http://binarios.com/miscnotes/djbdns.html
+http://web.archive.org/web/20061013054303/http://ezine.daemonnews.org/200210/ezdjbdns.html
+
+Some info about the bugfixes:
+
+http://www.securityfocus.com/archive/1/501294/30/0/threaded
+http://www.your.org/dnscache/
+
+How to build
+============
+- copy the folders djbdns, ucspi-tcp (and optionally daemontools) to your buildroot/package directory 
+- make menuconfig
+- select the packages under network/DNS/djbdns and network/ucspi-tcp (and optionally network/daemontools)
+- make
+- after compilation, the package can be found at bin/packages/<targetname>
+- now do what you normally do to install self-compiled packages on your OpenWRT machine
+
+If you wish to tinker with the code, then here are some useful commands to run in the buildroot:
+    rm -rf build_dir/<targetname>/djbdns-1.05
+    make package/cleanup
+    make package/djbdns/compile V=99
+    make package/index
+Once you have done a "make menuconfig;make" you can use these commands to quickly rebuild only the djbdns package.
+
+Usage pointers
+==============
+- After installation, you can make the servers start automatically on boot by running "/etc/init.d/<servicename> enable" . The script will then appear in the /etc/rc.d directory. This is standard OpenWRT functionality.
+- All djbdns parameters are stored in the UCI configuration system. Run "uci show djbdns" to see the settings. Data files are not implemented in the UCI system, so these files must be manually backed up when and if you intend to do a sysupgrade (=reflash the firmware). Those files include: dnscache dnsroot.global, dnscache @ file, tinydns data file, axfrdns tcp file, rbldns data file, each in their individual directories in /etc.
+- Each package is ready to run out-of-the-box, once installed. The default settings allow you to start playing immediately. The defaults are reasonably secure, but do not take my word for it. Verify it. Note: dnscache has two default example resolver IP addresses. The two default addresses are the OpenDNS resolvers, which might work at the moment, but this may change in the future.
+- You will most likely want to customize the settings for each seperate service you wish to use. Read the docs on the weblinks listed above for pointers on how to do so.
+- The ucspi-tcp package is only needed if you wish to install and run axfrdns.
+- The daemontools package is strictly optional. It is in no way linked to the djbdns package (yet). It is just there for you to play with.
+- Starting the init.d scripts from the command line with the environment variable DEBUG set to 1 will prevent the servers from daemonizing and show the servers's log dumped to stdout / stderr instead of /dev/null. Example: "DEBUG=1 /etc/init.d/dnscache start"
+- By default, all logging is disabled. Each daemon has a seperate option to activate logging. When logging activated the daemon logs to syslog using facility local1.info.
+- Each djbdns server requires an IP address on which to listen on. This port of djbdns allows you to define an interface on which to listen instead of an IP address. The advantage of this is that an interface can get a different IP address assigned, the djbdns stuff will not break. The dnscache server has a patch applied so that it is possible to define multiple interfaces on which to listen, separated by slashes. Example: wan/lan .
+- By default, dnscache acts as a recursive name server. If you wish to operate in forwardonly mode, then you need to set the forwardonly flag to '1'. Then you need to do either one of the following: Put the ip addresses of the name servers you wish to use as resolvers in the UCI config (djbdns.dnscache.resolver) or alternatively you can set the useresolvconf flag which will cause the dns servers assigned by dhcp to be used.
+- If you want your OpenWRT machine to make use of its own dnscache, then you must make /etc/resolv.conf reflect this. One way of doin this is as follows: uci set network.wan.dns=127.0.0.1 . If you have dnscache listening on some other interface, you would naturally replace 127.0.0.1 by the address of that interface.
+- OpenWRT has several applications that can do DNS serving in one way or another (dnsmasq, Maradns, Bind). Make sure you have none of these apps running when you start running a djbdns name server because having two DNS apps listening on the same address is not something you would usually want. A patch for the dnsmasq configuration script and its config file is included with this package. The patch will allow you to configure dnsmasq to listen only on certain interfaces, instead of on all them as it does by default on OpenWRT. Alternatively, you could completely disable and / or remove dnsmasq, if you do not intend to use any of its functionality (which is serving DNS and DHCP).
+
+To apply the dnsmasq patch
+==========================
+NOTE: This patch has been incorporated into OpenWRT trunk per 20090409 as seen in https://dev.openwrt.org/ticket/4900 and https://dev.openwrt.org/changeset/15172.
+
+This is a patch to allow you to use dnsmasq alongside dnscache. It will allow you to configure dnsmasq to listen only on certain interfaces, instead of on all them as it does by default on OpenWRT. It only patches the startup script and configuration file of dnsmasq, not dnsmasq itself. If you need or desire to apply the patch yourself, then there are two possible ways to go about it:
+
+Patch the dnsmasq package source:
+- cd to svn/openwrt/branches/8.09/packages/dnsmasq/files
+- do 'patch < dnsmasq.patch
+- if all went well you can now compile the package as you nomally would
+- you can now either reinstall dnsmasq on your router or re-flash the firmware image. If you reinstall the dnsmasq package then you waste some flash memory, as dnsmasq is usually already included as a part of the firmware image. One way to reinstall the dnsmasq package is to use SSH to upload the image to the router and do: opkg update ; opgk install -force-reinstall dnsmasq.ipk . Or you could configure your OpenWRT build machine as an http server that serves OpenWRT packages and then configure opkg to use your server as an ipkg repository. This is generally a pretty good idea if you are building your own firmware and packages.
+
+Alternatively, you can patch the dnsmasq files on the router itself:
+Look at the patch file and manually patch the files on the router. There are only four lines to modify, so it is not hard.
+
+NOTE: The dnsmasq paramaters added by this patch are not shown on the Luci webinterface. You will manually have to configure dnsmasq. An example of how to make dnsmasq serve DNS and DHCP only on the lan:
+uci set dhcp.@dnsmasq[0].nonwildcard=1
+uci set dhcp.@dnsmasq[0].interfaces=br-lan
+uci commit
+This will prevent dnsmasq from binding to the wildcard IP address and instead make it listen on the designated (lan) interface. You are then free to run a DNS server on, for example, the loopback and/or the wan interface.
+
+Assorted notes
+==============
+- This port was put together with reasonable care. It is not a dirty hack, but that is ofcourse a very subjective statement.
+- It was created on and for Kamikaze 8.09 with both a 2.4 and a 2.6 kernel. It was not tested to work on older versions of OpenWRT, but it might.
+- This package will build into several packages. Most of the packages rely on the package djbdnsbase. It contains the shared config data for all daemons. It should automatically get installed along with the daemons by opkg.
+- The ucspi-tcp package is a requirement for installing axfrdns. If you don't user afrxdns, you won't need to install ucspi-tcp.
+- The daemontool package is supplied as a part of this port, but it is not needed or used by anything in the djbdns packages. It is included in case anyone feels the want or need to make use of it.
+- Among the applied patches are the latest (as of the 2nd of april 2009) notorious bug fixes for dnscache.
+- Most patches are vanilla, ie. unmodified as they can be found on the net. The only patch modified is the djbdns-1.05-slogging patch, which was merged with the server-1.05-nxdomain-logging patch.
+- The dnscache gets a patch applied to be able to listen on multiple IP addresses. Tinydns is not patched to have that functionality, although the patch for that is available on the net.
+- dnscache is also patched to deliver additional statistics in its log files, including hits/misses and what types of records were queried. These can be used to monitor and/or graph the behaviour of your dnscache server.
+- The dnscache package gets configured to listen to 127.0.0.1 and the lan subnet by default. See "ls /etc/dnscache/ip" and  "uci show djbdns|grep dnscache" .
+- tinydns, axfrdns and rbldns include example data files that are installed by default. Their purpose is to ease installation and testing of the packages and to act as a guide to people who are not familiar with these applications. 
+- The dnstools part of this package contains a script called dnsroots-update with which you can update the global root file. This is quite useful because IP addresses of the root servers change now and then, although not very often. I seems that few people actually bother to update the global roots file once they have installed dnscache. It is important to run the update script every now and them, or at least at installation time. Do the following to update the list: dnsroots-update > /etc/dnscache/dnsroots.global and then copy the file dnsroots.global to /etc/dnscache/server/@ . The dnstools package is quite large (400K installed) for an embedded system. What you could do instead of running the update script on the router, is to install the djbdns package on some big machine and run the script on there and then copy the output to the dnsroots file on the router. The dnsroots.global file included in this package is up to date as per the date of this writing (2nd of april 2009).
+
+Testing the installation
+========================
+The following may ease any debugging you might wish/need to do:
+- Set the syslog buffer to something like 64K or more and make it log to IP address localhost (reboot to activate the changes):
+    uci set system.@system[0].log_ip=127.0.0.1
+    uci set system.@system[0].log_size=64
+    uci commit
+- Use "logread|less" to browse through the buffered syslog output.
+- For realtime log monitoring: Install netcat and make it listen to the syslog output:
+    opkg install netcat
+    netcat -ulp 514
+
+This paragraph gives a few brief pointers on how to test your installation. The general idea is as follows: Log in to the OpenWRT machine using two seperate SSH sessions or a single session and then use 'screen' to gain multiple sessions. In the first session you have to start the daemon you wish to test. In the second session you run the diagnostic commands. In the following examples, for each daemon and each diagnostic tool, I have supplied the commandline and the expected, approximate output.
+
+NOTE1: Make sure no other DNS servers are running. Check with "netstat -an|grep 53" and/or do a "killall dnsmasq" just to be sure.
+NOTE2: dnscache requires an active internet connection it to work
+NOTE3: In the following examples, the servers were running on IP address 10.1.1.2
+NOTE4: Most of these tests require the dnstools package to be installed
+
+-dnscache
+session1 "DEBUG=1 /etc/init.d/dnscache start"
+        Starting Caching nameserver: dnscachelistening on 0a010102
+        starting
+        <a whole truckload of log data will follow>
+session2 "DNSCACHEIP=$yourwanip dnsqr a example.com"  (note: you do no have to modify /etc/resolv.conf to use this command)
+        1 example.com:
+        45 bytes, 1+1+0+0 records, response, noerror
+        query: 1 example.com
+        answer: example.com 172800 A 208.77.188.166
+session2 "dnsip example.com" (note: /etc/resolv.conf must point to the address on which dnscache is listening)
+        208.77.188.166
+session2 "nslookup example.com" (note: /etc/resolv.conf must point to the address on which dnscache is listening)
+        Server:    10.1.1.2
+        Address 1: 10.1.1.2
+        Name:      example.com
+        Address 1: 208.77.188.166 www.example.com
+
+-tinydns
+session1 "DEBUG=1 /etc/init.d/tinydns start"
+        Starting Authoritative nameserver: tinydnsstarting tinydns
+        0a010102:4eee:fdd8 + 0001 example.net
+        stats 1 1 0 0 0 0 0
+session2 "dnsq a example.net $yourwanip"
+        1 example.net:
+        79 bytes, 1+0+1+0 records, response, authoritative, noerror
+        query: 1 example.net
+        authority: example.net 2560 SOA ns.example.net hostmaster.example.net 1238703484 16384 2048 1048576 2560
+
+-axfrdns
+session1 "DEBUG=1 /etc/init.d/axfrdns start"
+        Starting Zone transfer name server: tcpservertcpserver: status: 0/10
+        tcpserver: status: 1/10
+        tcpserver: pid 1140 from 10.1.1.2
+        tcpserver: ok 1140 0:10.1.1.2:53 :10.1.1.2::1034
+        0a010102:040a:0000 0006 example.net
+        tcpserver: end 1140 status 0
+        tcpserver: status: 0/10
+session2 "tcpclient -RHl0 $yourwanip 53 axfr-get example.net /tmp/zone /tmp/zone.tmp"
+        The file /tmp/zone should now contain the example.net zone in tinydns-data format.
+
+-rbldns
+session1 "DEBUG=1 /etc/init.d/rbldns start"
+        Starting Reverse DNS wall: rbldnsstarting rbldns
+        0a010102:881d:01ca + 0010 8.4.2.1.test
+        stats 1 1 0 0 0 0 0
+        0a010102:674a:e70f N 0010 9.4.2.1.test
+session2 "dnsq txt 8.4.2.1.test $yourwanip"
+        16 8.4.2.1.test:
+        59 bytes, 1+1+0+0 records, response, authoritative, noerror
+        query: 16 8.4.2.1.test
+        answer: 8.4.2.1.test 2048 16 \020www.somesite.com
+session2 "dnsq txt 9.4.2.1.test $yourwanip"
+        16 9.4.2.1.test:
+        30 bytes, 1+0+0+0 records, response, authoritative, nxdomain
+        query: 16 9.4.2.1.test
+
+-walldns
+session1 "DEBUG=1 /etc/init.d/walldns start"
+        Starting Reverse DNS wall: walldnsstarting walldns
+        0a010102:7b76:3d97 + 0001 4.3.2.1.in-addr.arpa
+        stats 1 1 0 0 0 0 0
+session2 "dnsq a 4.3.2.1.in-addr.arpa $yourwanip"
+        1 4.3.2.1.in-addr.arpa:
+        54 bytes, 1+1+0+0 records, response, authoritative, noerror
+        query: 1 4.3.2.1.in-addr.arpa
+        answer: 4.3.2.1.in-addr.arpa 655360 A 1.2.3.4
+
+axfrdns defaults
+================
+axfrdns is run using tcpserver from the ucspi-tcp package. The following parameters are used to start the tcpserver daemon (which runs as root BTW):
+-D: Never delay sending data; enable TCP_NODELAY.
+-R: Do not attempt to obtain $TCPREMOTEINFO from the remote host. To avoid loops, you must use this option for servers on TCP ports 53 and 113.
+-H: Do not look up the remote host name in DNS; remove the environment variable $TCPREMOTEHOST. To avoid loops, you must use this option for servers on TCP port 53. 
+-l localname: Do not look up the local host name in DNS; use localname for the environment variable $TCPLOCALHOST. A common choice for localname is 0. To avoid loops, you must use this option for servers on TCP port 53. 
+-c n (=40): Do not handle more than n simultaneous connections. If there are n simultaneous copies of prog running, defer acceptance of a new connection until one copy finishes. n must be a positive integer. Default: 40. 
+-b n (=10): Allow a backlog of approximately n TCP SYNs. On some systems, n is silently limited to 5. On systems supporting SYN cookies, the backlog is irrelevant. 
+
+In debug mode and when logging is activated, the following parameter is also active:
+-v: Verbose. Print error messages and status messages.
+
+Applied patches
+===============
+100-crosscompile.patch
+https://dev.openwrt.org/ticket/2497
+Patch to make djbdns compile correctly for OpenWRT. I understand that the original patch comes from FreeWRT and was adapted for OpenWRT by Alexander Tsvyashchenko.
+
+110-cachestats.patch
+http://romana.now.ie/#djbdns-cachestats
+This patch modifies the dnscache program to keep a counter of cache hits and cache misses. Two new fields are added to the stats output line: the fifth number is the number of cache hits; the sixth number is the number of cache misses.
+
+120-compiler-temporary-filename.patch
+http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/#compiler-temporary-filename
+A bit of a nit-picky patch that adjusts the names of generated temorary files to be more 'correct'. A bit silly really.
+
+130-dnscache-multiple-ip.patch
+http://danp.net/djbdns/patches.html
+When applied, dnscache will accept a /-delimited list of IP address in $IP and bind to each in turn. NOTE: This patch is only really useful on embedded systems with very limited memory. On 'big' systems, ther are other ways to achieve listening on multiple IP adresses. Example: http://www.faqts.com/knowledge_base/view.phtml/aid/9644/fid/699
+
+140-dnsnamex-extra-command.patch
+http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/#dnsnamex
+Not really a patch, but an extra command. dnsnamex prints all of the domain names that the IP address supplied to it maps to, on a single line.
+
+200-dnscache-cname-handling.patch
+http://homepages.tesco.net/~J.deBoynePollard/FGA/#DNS
+Fixes mis-handling of client-side aliases
+
+210-dnscache-strict-forwardonly.patch
+http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/#dnscache-strict-forwardonly
+This patch modifies the behaviour of dnscache such that "forwardonly" mode is fully enforced.
+
+220-dnscacheip-space-separator.patch
+http://homepages.tesco.net/~J.deBoynePollard/FGA/djbdns-problems.html#dnscacheip-separator-character
+Patch to change the separator in ${DNSCACHEIP} to the space character
+
+230-tinydns-data-semantic-error.patch
+http://homepages.tesco.net/~J.deBoynePollard/FGA/djbdns-problems.html#tinydns-data-semantic-error
+Fixes the fact that stock tinydns-data doesn't handle semantic errors in its input
+
+240-tinydns-alias-chain-truncation.patch
+http://homepages.tesco.net/~J.deBoynePollard/FGA/djbdns-problems.html#tinydns-alias-chain-truncation
+Fixes truncation of alias chains by tinydns and axfrdns
+
+250-djbdns-1.05-slogging.patch
+http://www.ohse.de/uwe/patches.html
+Patch to enable statistics logging of queried resource records.
+This patch is merged with the patch server-1.05-nxdomain-logging.patch that logs nxdomain queries.
+http://danp.net/djbdns/
+
+260-djbdns-1.05-dnsfilter-replace.patch
+http://www.ohse.de/uwe/patches.html
+This patch adds an option to the dnsfilter program (-r). It's use makes dnsfilter simply replace the IP address by the host name if possible. If the IP address cannot be determined for whatever reason then it will be left alone. -r stands for replace. 
+
+300-bugfix1-dempsky.patch
+http://www.securityfocus.com/archive/1/501294/30/0/threaded
+Patch to fix a potential cache-poisoning attack. This bug only affects domains that serve DNS content using tinydns and axfrdns (only for DNS queries over TCP; clients do not need AXFR permissions) from djbdns 1.05 and allow untrusted users to include arbitrary records.
+
+310-bugfix2-merge-outgoing-requests.patch
+http://www.your.org/dnscache/
+This patch prevents a class of poisoning attack by combining identical requests from clients into one outgoing query. Without this patch, an attacker can coerce dnscache into launching hundreds of identical queries at once, making a specific type of attack several orders of magnitude easier. 
+
+320-bugfix3-cache-soa-records.patch
+http://www.your.org/dnscache/
+This patch allows dnscache to store the responses of "SOA" type queries in its cache. SOA responses are the only type of response unconditionally uncached. dnscache uses its internal cache to prevent certain classes of poisoning attack. Attackers may choose to send floods of SOA requests to bypass these protections. 
+
+dnrqx
+http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/dnsqrx
+Not really a patch, but a handy script to make dnsq query a given name server instead of the one in /etc/resolv.conf.
+
+Possible future enhancements to this package
+============================================
+- add a Luci webinterface
+- add scripts to make the DNS daemons run using daemontools to increase the reliability of the services
+- ipv6 support
diff --git a/net/djbdns/files/axfrdns.init b/net/djbdns/files/axfrdns.init
new file mode 100644 (file)
index 0000000..b797141
--- /dev/null
@@ -0,0 +1,74 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+#
+# version 20090401 jhalfmoon
+
+START=47
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/bin/tcpserver
+NAME=tcpserver
+DESC="Zone transfer name server"
+
+APP=/usr/bin/axfrdns
+ROOT=/tmp/tinydns
+
+if [ ! -e /etc/tinydns/data ] ; then
+    echo Error: Dependency tinydns not found.
+    exit 111
+fi
+
+start() {
+    echo "Starting $DESC: $NAME"
+    config_load djbdns
+    mkdir -p $ROOT
+    ln -sf /etc/tinydns/data $ROOT/data
+    cd $ROOT
+    tinydns-data
+    chown -R $UID:$GID $ROOT
+    tcprules $ROOT/tcp.cdb $ROOT/tcp.cdb.tmp < /etc/axfrdns/tcp
+    config_foreach get_userids global
+    config_foreach start_daemon axfrdns
+}
+
+get_userids() {
+    local cfg="$1"
+    config_get UID "$cfg" runasuser
+    config_get GID "$cfg" runasgroup
+    UID=`id -u $UID`
+    GID=`id -g $GID`
+}
+
+start_daemon() {
+    local cfg="$1"
+    config_get logging  "$cfg" logging
+    config_get iface    "$cfg" interface
+    config_get AXFR     "$cfg" allowedzones
+# Unset AXFR if it is empty
+    [ -z $AXFR ] && export -n AXFR
+# Translate listening interfaces to ip addresses
+    include /lib/network
+    scan_interfaces
+    config_get IP "$iface" ipaddr
+    export ROOT
+    if [ "$DEBUG" == 1 ] ; then
+        $DAEMON -vDRHl0 -c40 -b10 -x $ROOT/tcp.cdb -- $IP 53 $APP
+    elif [ "$logging" == '1' ] ; then
+        $DAEMON -vDRHl0 -c40 -b10 -x $ROOT/tcp.cdb -- $IP 53 $APP 2>&1 | logger -p local1.info -t $NAME &    
+    else
+        $DAEMON -DRHl0 -c40 -b10 -x $ROOT/tcp.cdb -- $IP 53 $APP > /dev/null 2>&1 &
+    fi
+}
+
+stop() {
+    echo -n "Stopping $DESC: $NAME"
+    kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1
+    echo " ."
+}
+
+restart() {
+    echo "Restarting $DESC: $NAME... "
+    stop
+    sleep 2
+    start
+}
+
diff --git a/net/djbdns/files/axfrdns/tcp b/net/djbdns/files/axfrdns/tcp
new file mode 100644 (file)
index 0000000..1dc715b
--- /dev/null
@@ -0,0 +1,5 @@
+#Example rules for djb's tcpserver
+127.0.0.:allow
+10.1.1.:allow
+192.168.1.:allow
+:deny
diff --git a/net/djbdns/files/djbdns.conf b/net/djbdns/files/djbdns.conf
new file mode 100644 (file)
index 0000000..7e9dfd4
--- /dev/null
@@ -0,0 +1,34 @@
+
+config 'global'
+       option 'runasuser' 'nobody'
+       option 'runasgroup' 'nobody'
+
+config 'dnscache'
+       option 'interface' 'wan'
+       option 'interfacesend' 'wan'
+       option 'defaultallowif' 'lan wan'
+       option 'cachesize' '1000000'
+       option 'forwardonly' '1'
+       option 'useresolvconf' '1'
+       list 'resolver' '208.67.222.222'
+       list 'resolver' '208.67.220.220'
+       option 'logging' '0'
+
+config 'tinydns'
+       option 'interface' 'wan'
+       option 'logging' '0'
+
+config 'axfrdns'
+       option 'interface' 'wan'
+       option 'allowedzones' ''
+       option 'logging' '0'
+
+config 'rbldns'
+       option 'interface' 'wan'
+       option 'base' 'test'
+       option 'logging' '0'
+
+config 'walldns'
+       option 'interface' 'wan'
+       option 'logging' '0'
+
diff --git a/net/djbdns/files/dnscache.init b/net/djbdns/files/dnscache.init
new file mode 100644 (file)
index 0000000..e1295ec
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+
+# Preferably start dnscache after udhcpd/dnsmasq, to be sure /etc/resolv.conf is set correctly. dnsmasq is at S60, so dnscache is put at S65 as seen below. If /etc/resolv.conf is not used, then dnscache may be started at S47, just after the firewall has been set up.
+START=65
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/bin/dnscache
+NAME=dnscache
+DESC="Caching name server"
+
+ROOT="/tmp/dnscache"
+resolvfile="/etc/resolv.conf"
+
+start() {
+    echo "Starting $DESC: $NAME"
+    config_load djbdns
+    config_foreach get_userids global
+    mkdir -p $ROOT
+    cp -fa /etc/dnscache/ip $ROOT
+    cp -fa /etc/dnscache/servers $ROOT
+    rm -f $ROOT/resolvers
+    chown -R $UID:$GID $ROOT
+    config_foreach start_dnscache dnscache
+}
+
+get_userids() {
+    local cfg="$1"
+    config_get UID "$cfg" runasuser
+    config_get GID "$cfg" runasgroup
+    UID=`id -u $UID`
+    GID=`id -g $GID`
+}
+
+append_server() {
+    echo $1 >> $ROOT/resolvers
+}
+
+start_dnscache() {
+    local cfg="$1"
+    config_get logging        "$cfg" logging
+    config_get useresolvconf  "$cfg" useresolvconf
+    config_get ifaces         "$cfg" interface
+    config_get ifacesend      "$cfg" interfacesend
+    config_get defaultallowif "$cfg" defaultallowif
+    config_get CACHESIZE      "$cfg" cachesize
+    config_get FORWARDONLY    "$cfg" forwardonly
+    config_list_foreach       "$cfg" "resolver" append_server
+# Add some interface network addresses to list of allowed IP addresses (assumes /24 networks)
+    include /lib/network
+    scan_interfaces
+    if [ -n "$defaultallowif" ] ; then
+        for myinterface in `echo $defaultallowif`; do
+            config_get addr $myinterface ipaddr
+            # the next line strips the last octet from the ip address
+            addr=`echo $addr|sed 's/.[0-9]\+$//'`
+            touch $ROOT/ip/$addr
+            echo Adding $ROOT/ip/$addr
+        done
+    fi
+# Translate listen interface names to IP addresses
+    IP=""
+    for iface in $ifaces; do
+       config_get ipaddr "$iface" ipaddr
+       IP="$ipaddr/$IP"
+    done
+# Strip trailing slashes
+    IP=`echo $IP|sed 's/\/\+$//g'`
+# Translante send interface name to an IP address
+    config_get IPSEND "$ifacesend" ipaddr
+# If forwardingonly set then activate list of resolvers
+    if [ "$FORWARDONLY" == "0" ] ; then
+        # Unset FORWARDONLY if equal to '0'
+        export -n FORWARDONLY
+    else
+# Use either fixed list of dnsservers or resolv.conf data
+        if [ "$useresolvconf" == "1" ] ; then
+            if [ -s "$resolvfile" ] ; then
+               cat $resolvfile|grep nameserver|sed 's/nameserver //g' > $ROOT/resolvers
+            else
+               echo Error: $resolvfile does not exist.
+               exit 1
+            fi
+        fi
+        if [ ! "`cat $ROOT/resolvers|wc -L`" == "0" ] ; then
+            cp -f $ROOT/resolvers $ROOT/servers/@ > /dev/null 2>&1
+        else
+            echo Error: No resolvers are defined.
+            exit 1
+        fi
+     fi
+    export IP 
+    export ROOT
+# dnscache likes to receive a 128bit random seed
+    dd if=/dev/urandom of=$ROOT/randomseed bs=128 count=1  > /dev/null 2>&1
+    if [ "$DEBUG" == 1 ] ; then
+        $DAEMON < /$ROOT/randomseed
+    elif [ "$logging" == '1' ] ; then
+        $DAEMON 2>&1 < /$ROOT/randomseed | logger -p local1.info -t $NAME &
+    else
+        $DAEMON > /dev/null 2>&1 < /$ROOT/randomseed &
+    fi
+}
+
+stop() {
+    echo -n "Stopping $DESC: $NAME"
+    kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1
+    echo " ."
+}
+
+restart() {
+    echo "Restarting $DESC: $NAME... "
+    stop
+    sleep 2
+    start
+}
+
diff --git a/net/djbdns/files/dnscache/dnsroots.global b/net/djbdns/files/dnscache/dnsroots.global
new file mode 100644 (file)
index 0000000..00e7528
--- /dev/null
@@ -0,0 +1,13 @@
+198.41.0.4 
+192.228.79.201 
+192.33.4.12 
+128.8.10.90 
+192.203.230.10 
+192.5.5.241 
+192.112.36.4 
+128.63.2.53 
+192.36.148.17 
+192.58.128.30 
+193.0.14.129 
+199.7.83.42 
+202.12.27.33 
diff --git a/net/djbdns/files/dnscache/servers/@ b/net/djbdns/files/dnscache/servers/@
new file mode 100644 (file)
index 0000000..00e7528
--- /dev/null
@@ -0,0 +1,13 @@
+198.41.0.4 
+192.228.79.201 
+192.33.4.12 
+128.8.10.90 
+192.203.230.10 
+192.5.5.241 
+192.112.36.4 
+128.63.2.53 
+192.36.148.17 
+192.58.128.30 
+193.0.14.129 
+199.7.83.42 
+202.12.27.33 
diff --git a/net/djbdns/files/dnsqrx b/net/djbdns/files/dnsqrx
new file mode 100644 (file)
index 0000000..3202e94
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+# (c) Copyright 2003-2003 Jonathan de Boyne Pollard. All rights reserved. "Moral" rights asserted.
+# Permission is hereby granted to distribute this script unmodified.
+# This script requires the patch that changes the ${DNSCACHEIP} separator, which can be found at <URL:http://homepages.tesco.net./~J.deBoynePollard/Softwares/djbdns.html>.
+t=${1?Missing type}
+n=${2?Missing name}
+s=${3?Missing server}
+i=`dnsip $s`
+DNSCACHEIP=${i:?Bad server name} dnsqr $t $n
diff --git a/net/djbdns/files/dnsroots-update b/net/djbdns/files/dnsroots-update
new file mode 100644 (file)
index 0000000..29ffc16
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# This is a script that outputs the current list of active DNS
+# root servers. To run, it requires an active internet connection
+# and a working resolving DNS server. It also requires that the
+# djbdns dnstools be installed, or at least the tools dnsqr and
+# dnsip.
+
+dnsqr ns .|grep answer|cut -f 5 -d " "|sort|while read server; do dnsip $server; done
diff --git a/net/djbdns/files/rbldns.init b/net/djbdns/files/rbldns.init
new file mode 100644 (file)
index 0000000..0c259c6
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+#
+# version 20090401 jhalfmoon
+
+START=46
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/bin/rbldns
+NAME=rbldns
+DESC="Reverse DNS wall"
+
+ROOT=/tmp/rbldns
+
+start() {
+    echo "Starting $DESC: $NAME"
+    config_load djbdns
+    config_foreach get_userids global
+    rm -rf $ROOT
+    mkdir -p $ROOT
+    ln -fs /etc/rbldns/data $ROOT/data
+    cd $ROOT
+    rbldns-data
+    chown -R $UID:$GID $ROOT
+    config_foreach start_daemon rbldns
+}
+
+get_userids() {
+    local cfg="$1"
+    config_get UID "$cfg" runasuser
+    config_get GID "$cfg" runasgroup
+    UID=`id -u $UID`
+    GID=`id -g $GID`
+}
+
+start_daemon() {
+    local cfg="$1"
+    config_get logging "$cfg" logging
+    config_get iface   "$cfg" interface
+    config_get BASE    "$cfg" base
+# Unset BASE if it is empty
+    [ -z $BASE ] && export -n BASE
+# Translate listening interfaces to ip addresses
+    include /lib/network
+    scan_interfaces
+    config_get IP "$iface" ipaddr
+    export ROOT
+    if [ "$DEBUG" == 1 ] ; then
+            $DAEMON
+    elif [ "$logging" == '1' ] ; then
+        $DAEMON 2>&1 | logger -p local1.info -t $NAME &
+    else
+        $DAEMON > /dev/null 2>&1 &
+    fi
+}
+
+stop() {
+    echo -n "Stopping $DESC: $NAME"
+    kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1
+    echo " ."
+}
+
+restart() {
+    echo "Restarting $DESC: $NAME... "
+    stop
+    sleep 2
+    start
+}
+
diff --git a/net/djbdns/files/rbldns/data b/net/djbdns/files/rbldns/data
new file mode 100644 (file)
index 0000000..85aae01
--- /dev/null
@@ -0,0 +1,5 @@
+#example rdldns data file
+1.2.4.8
+10.0.0.1
+192.168.0.0/16
+:127.0.0.1:www.somesite.com
diff --git a/net/djbdns/files/tinydns.init b/net/djbdns/files/tinydns.init
new file mode 100644 (file)
index 0000000..30c5d6f
--- /dev/null
@@ -0,0 +1,64 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+#
+# version 20090401 jhalfmoon
+
+START=46
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/bin/tinydns
+NAME=tinydns
+DESC="Authoritative nameserver"
+
+ROOT=/tmp/tinydns
+
+start() {
+    echo "Starting $DESC: $NAME"
+    config_load djbdns
+    config_foreach get_userids global
+    mkdir -p $ROOT
+    ln -sf /etc/tinydns/data $ROOT/data
+    cd $ROOT
+    tinydns-data
+    chown -R $UID:$GID $ROOT
+    config_foreach start_daemon tinydns
+}
+
+get_userids() {
+    local cfg="$1"
+    config_get UID "$cfg" runasuser
+    config_get GID "$cfg" runasgroup
+    UID=`id -u $UID`
+    GID=`id -g $GID`
+}
+
+start_daemon() {
+    local cfg="$1"
+    config_get logging "$cfg" logging
+    config_get iface   "$cfg" interface
+    include /lib/network
+    scan_interfaces
+# Translate listening interfaces to ip addresses
+    config_get IP "$iface" ipaddr
+    export ROOT
+    if [ "$DEBUG" == 1 ] ; then
+        $DAEMON
+    elif [ "$logging" == '1' ] ; then
+        $DAEMON 2>&1 | logger -p local1.info -t $NAME &
+    else
+        $DAEMON > /dev/null 2>&1 &
+    fi
+}
+
+stop() {
+    echo -n "Stopping $DESC: $NAME"
+    kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1
+    echo " ."
+}
+
+restart() {
+    echo "Restarting $DESC: $NAME... "
+    stop
+    sleep 2
+    start
+}
+
diff --git a/net/djbdns/files/tinydns/add-alias b/net/djbdns/files/tinydns/add-alias
new file mode 100644 (file)
index 0000000..eada7a0
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/local/bin/tinydns-edit data data.new add alias ${1+"$@"}
diff --git a/net/djbdns/files/tinydns/add-childns b/net/djbdns/files/tinydns/add-childns
new file mode 100644 (file)
index 0000000..4114b3e
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/local/bin/tinydns-edit data data.new add childns ${1+"$@"}
diff --git a/net/djbdns/files/tinydns/add-host b/net/djbdns/files/tinydns/add-host
new file mode 100644 (file)
index 0000000..9c61b4e
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/local/bin/tinydns-edit data data.new add host ${1+"$@"}
diff --git a/net/djbdns/files/tinydns/add-mx b/net/djbdns/files/tinydns/add-mx
new file mode 100644 (file)
index 0000000..c31a37f
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/local/bin/tinydns-edit data data.new add mx ${1+"$@"}
diff --git a/net/djbdns/files/tinydns/add-ns b/net/djbdns/files/tinydns/add-ns
new file mode 100644 (file)
index 0000000..b35d2b0
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/local/bin/tinydns-edit data data.new add ns ${1+"$@"}
diff --git a/net/djbdns/files/tinydns/data b/net/djbdns/files/tinydns/data
new file mode 100644 (file)
index 0000000..001311e
--- /dev/null
@@ -0,0 +1,59 @@
+# example verbose tinydns data file
+# from http://www.pjvenda.org/linux/doc/tinydns/
+# Copyright (C) 2001-2009 by Pedro Venda
+# licensed under a Creative Commons Attribution 2.5 License
+#
+# REVERSE ZONE
+#
+# (reverse) dns servers: primary and secondary
+Z45.168.192.in-addr.arpa:ns.example.net:hostmaster.example.net::::::::
+
+# NS records
+&45.168.192.in-addr.arpa::ns.example.net:::
+&45.168.192.in-addr.arpa::ns2.example.net:::
+
+# MX handlers
+@45.168.192.in-addr.arpa::relay.example.net:10
+@45.168.192.in-addr.arpa::relay2.example.net:20
+
+#
+# FORWARD ZONE:
+#
+# SOA record: primary nameserver is ns.example.net and hostmaster
+#             mail address is hostmaster@example.net
+#             (the 'Z' configuration line is the only one that
+#             allows specifying the hostmaster mail address)
+Zexample.net:ns.example.net:hostmaster.example.net::::::::
+
+# NS records: primary and secondary nameservers
+&example.net::ns.example.net:::
+&example.net::ns2.example.net:::
+
+# MX records: relay.example.net, distance = 10
+#             relay2.example.net, distance = 20
+@example.net::relay.example.net:10
+@example.net::relay2.example.net:20
+
+# A records: ns.example.net, ns2.example.net
+=ns.example.net:192.168.45.1:::
+=ns2.example.net:192.168.45.2:::
+
+# PTR records: relays are in the same hosts as dns servers
++relay.example.net:192.168.45.1:::
++relay2.example.net:192.168.45.2:::
+
+# more A records: gateway.example.net
+=gateway.example.net:192.168.45.254:::
+
+# CNAME record: nscache.example.net is alias to gateway.example.net
+Cnscache.example.net:gateway.example.net:::
+
+#
+# SUB DOMAIN DELEGATION
+#
+
+# NS record
+&dmz.example.net::ns.dmz.example.net:::
+
+# A/PTR record for nameserver
+=ns.dmz.example.net:192.168.90.1:::
diff --git a/net/djbdns/files/walldns.init b/net/djbdns/files/walldns.init
new file mode 100644 (file)
index 0000000..d5d714f
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+#
+# version 20090401 jhalfmoon
+
+START=46
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/bin/walldns
+NAME=walldns
+DESC="Reverse DNS wall"
+
+ROOT=/tmp/walldns
+
+start() {
+    echo "Starting $DESC: $NAME"
+    config_load djbdns
+    config_foreach get_userids global
+    rm -rf $ROOT
+    mkdir -p $ROOT
+    chown -R $UID:$GID $ROOT
+    config_foreach start_daemon walldns
+}
+
+get_userids() {
+    local cfg="$1"
+    config_get UID "$cfg" runasuser
+    config_get GID "$cfg" runasgroup
+    UID=`id -u $UID`
+    GID=`id -g $GID`
+}
+
+start_daemon() {
+    local cfg="$1"
+    config_get logging "$cfg" logging
+    config_get iface   "$cfg" interface
+# Translate listening interfaces to ip addresses
+    include /lib/network
+    scan_interfaces
+    config_get IP "$iface" ipaddr
+    export ROOT
+    if [ "$DEBUG" == 1 ] ; then
+        $DAEMON
+    elif [ "$logging" == '1' ] ; then
+        $DAEMON 2>&1 | logger -p local1.info -t $NAME &
+    else
+        $DAEMON > /dev/null 2>&1 &
+    fi
+}
+
+stop() {
+    echo -n "Stopping $DESC: $NAME"
+    kill `pidof $NAME|sed "s/$$//g"` > /dev/null 2>&1
+    echo " ."
+}
+
+restart() {
+    echo "Restarting $DESC: $NAME... "
+    stop
+    sleep 2
+    start
+}
+
diff --git a/net/djbdns/patches/100-crosscompile.patch b/net/djbdns/patches/100-crosscompile.patch
new file mode 100644 (file)
index 0000000..78df74c
--- /dev/null
@@ -0,0 +1,171 @@
+diff -urN djbdns-1.05/Makefile djbdns-1.05.new/Makefile
+--- djbdns-1.05/Makefile       2001-02-11 23:11:45.000000000 +0200
++++ djbdns-1.05.new/Makefile   2007-09-30 15:09:51.000000000 +0300
+@@ -29,10 +29,6 @@
+ compile auto-str.c buffer.h exit.h
+       ./compile auto-str.c
+-auto_home.c: \
+-auto-str conf-home
+-      ./auto-str auto_home `head -1 conf-home` > auto_home.c
+-
+ auto_home.o: \
+ compile auto_home.c
+       ./compile auto_home.c
+@@ -221,10 +217,6 @@
+ uint64.h taia.h dd.h
+       ./compile dd.c
+-direntry.h: \
+-choose compile trydrent.c direntry.h1 direntry.h2
+-      ./choose c trydrent direntry.h1 direntry.h2 > direntry.h
+-
+ dns.a: \
+ makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o dns_mx.o \
+ dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
+@@ -508,12 +500,6 @@
+         *) cat hasdevtcp.h1 ;; \
+       esac ) > hasdevtcp.h
+-hasshsgr.h: \
+-choose compile load tryshsgr.c hasshsgr.h1 hasshsgr.h2 chkshsgr \
+-warn-shsgr
+-      ./chkshsgr || ( cat warn-shsgr; exit 1 )
+-      ./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h
+-
+ hier.o: \
+ compile hier.c auto_home.h
+       ./compile hier.c
+@@ -534,10 +520,6 @@
+ compile instcheck.c strerr.h error.h exit.h
+       ./compile instcheck.c
+-iopause.h: \
+-choose compile load trypoll.c iopause.h1 iopause.h2
+-      ./choose clr trypoll iopause.h1 iopause.h2 > iopause.h
+-
+ iopause.o: \
+ compile iopause.c taia.h tai.h uint64.h select.h iopause.h taia.h
+       ./compile iopause.c
+@@ -766,10 +748,6 @@
+ compile seek_set.c seek.h
+       ./compile seek_set.c
+-select.h: \
+-choose compile trysysel.c select.h1 select.h2
+-      ./choose c trysysel select.h1 select.h2 > select.h
+-
+ server.o: \
+ compile server.c byte.h case.h env.h buffer.h strerr.h ip4.h uint16.h \
+ ndelay.h socket.h uint16.h droproot.h qlog.h uint16.h response.h \
+@@ -1060,10 +1038,6 @@
+ compile uint32_unpack.c uint32.h
+       ./compile uint32_unpack.c
+-uint64.h: \
+-choose compile load tryulong64.c uint64.h1 uint64.h2
+-      ./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h
+-
+ unix.a: \
+ makelib buffer_read.o buffer_write.o error.o error_str.o ndelay_off.o \
+ ndelay_on.o open_read.o open_trunc.o openreadclose.o readclose.o \
+diff -urN djbdns-1.05/auto_home.c djbdns-1.05.new/auto_home.c
+--- djbdns-1.05/auto_home.c    1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/auto_home.c        2007-09-30 13:32:06.000000000 +0300
+@@ -0,0 +1,3 @@
++const char auto_home[] = "\
++\057\165\163\162\
++";
+diff -urN djbdns-1.05/conf-cc djbdns-1.05.new/conf-cc
+--- djbdns-1.05/conf-cc        2007-09-30 14:11:35.000000000 +0300
++++ djbdns-1.05.new/conf-cc    2007-09-30 15:10:46.000000000 +0300
+@@ -1,3 +1,3 @@
+-gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings
++$TARGET_CC $TARGET_CFLAGS -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -include errno.h
+ This will be used to compile .c files.
+diff -urN djbdns-1.05/conf-home djbdns-1.05.new/conf-home
+--- djbdns-1.05/conf-home      2001-02-11 23:11:45.000000000 +0200
++++ djbdns-1.05.new/conf-home  2007-09-30 14:10:46.000000000 +0300
+@@ -1,4 +1,4 @@
+-/usr/local
++/usr
+ This is the dnscache home directory. Programs will be installed in
+ .../bin.
+diff -urN djbdns-1.05/conf-ld djbdns-1.05.new/conf-ld
+--- djbdns-1.05/conf-ld        2001-02-11 23:11:45.000000000 +0200
++++ djbdns-1.05.new/conf-ld    2007-09-30 15:11:00.000000000 +0300
+@@ -1,3 +1,3 @@
+-gcc -s
++$TARGET_CC -s $TARGET_LDFLAGS
+ This will be used to link .o files into an executable.
+diff -urN djbdns-1.05/direntry.h djbdns-1.05.new/direntry.h
+--- djbdns-1.05/direntry.h     1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/direntry.h 2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1,10 @@
++#ifndef DIRENTRY_H
++#define DIRENTRY_H
++
++/* sysdep: +dirent */
++
++#include <sys/types.h>
++#include <dirent.h>
++#define direntry struct dirent
++
++#endif
+diff -urN djbdns-1.05/hasshsgr.h djbdns-1.05.new/hasshsgr.h
+--- djbdns-1.05/hasshsgr.h     1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/hasshsgr.h 2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1 @@
++/* sysdep: -shortsetgroups */
+diff -urN djbdns-1.05/iopause.h djbdns-1.05.new/iopause.h
+--- djbdns-1.05/iopause.h      1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/iopause.h  2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1,18 @@
++#ifndef IOPAUSE_H
++#define IOPAUSE_H
++
++/* sysdep: +poll */
++#define IOPAUSE_POLL
++
++#include <sys/types.h>
++#include <poll.h>
++
++typedef struct pollfd iopause_fd;
++#define IOPAUSE_READ POLLIN
++#define IOPAUSE_WRITE POLLOUT
++
++#include "taia.h"
++
++extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *);
++
++#endif
+diff -urN djbdns-1.05/select.h djbdns-1.05.new/select.h
+--- djbdns-1.05/select.h       1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/select.h   2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1,11 @@
++#ifndef SELECT_H
++#define SELECT_H
++
++/* sysdep: +sysselect */
++
++#include <sys/types.h>
++#include <sys/time.h>
++#include <sys/select.h>
++extern int select();
++
++#endif
+diff -urN djbdns-1.05/uint64.h djbdns-1.05.new/uint64.h
+--- djbdns-1.05/uint64.h       1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/uint64.h   2007-09-30 13:23:48.000000000 +0300
+@@ -0,0 +1,8 @@
++#ifndef UINT64_H
++#define UINT64_H
++
++/* sysdep: -ulong64 */
++
++typedef unsigned long long uint64;
++
++#endif
diff --git a/net/djbdns/patches/110-cachestats.patch b/net/djbdns/patches/110-cachestats.patch
new file mode 100644 (file)
index 0000000..9676f07
--- /dev/null
@@ -0,0 +1,89 @@
+#
+# This patch to djbdns 1.05 modifies the dnscache program to keep a
+# counter of cache hits and cache misses.
+#
+# Two new fields are added to the ``stats'' output line:
+#  . the fifth number is the number of cache hits
+#  . the sixth number is the number of cache misses
+# e.g.
+#  @400000003fa92ccc317d70f4 stats 3 1201 1 0 21 49
+# indicates 21 hits and 49 misses.
+#
+# James Raftery <james@now.ie>  6 Nov. 2003
+#
+--- djbdns-1.05.orig/cache.c   Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/cache.c        Wed Nov  5 17:21:06 2003
+@@ -7,6 +7,11 @@
+ uint64 cache_motion = 0;
++/* record cache stats */
++/* James Raftery <james@now.ie> 6 Nov. 2003 */
++uint64 cache_hit = 0;
++uint64 cache_miss = 0;
++
+ static char *x = 0;
+ static uint32 size;
+ static uint32 hsize;
+@@ -112,15 +117,20 @@
+         if (u > size - pos - 20 - keylen) cache_impossible();
+         *datalen = u;
++        cache_hit++;
+         return x + pos + 20 + keylen;
+       }
+     }
+     nextpos = prevpos ^ get4(pos);
+     prevpos = pos;
+     pos = nextpos;
+-    if (++loop > 100) return 0; /* to protect against hash flooding */
++    if (++loop > 100) { /* to protect against hash flooding */
++      cache_miss++;
++      return 0;
++    }
+   }
++  cache_miss++;
+   return 0;
+ }
+--- djbdns-1.05.orig/cache.h   Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/cache.h        Wed Nov  5 17:13:36 2003
+@@ -5,6 +5,12 @@
+ #include "uint64.h"
+ extern uint64 cache_motion;
++
++/* record cache stats */
++/* James Raftery <james@now.ie> 6 Nov. 2003 */
++extern uint64 cache_hit;
++extern uint64 cache_miss;
++
+ extern int cache_init(unsigned int);
+ extern void cache_set(const char *,unsigned int,const char *,unsigned int,uint32);
+ extern char *cache_get(const char *,unsigned int,unsigned int *,uint32 *);
+--- djbdns-1.05.orig/log.c     Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/log.c  Wed Nov  5 17:21:12 2003
+@@ -276,6 +276,12 @@
+ {
+   extern uint64 numqueries;
+   extern uint64 cache_motion;
++
++  /* record cache stats */
++  /* James Raftery <james@now.ie> 6 Nov. 2003 */
++  extern uint64 cache_hit;
++  extern uint64 cache_miss;
++
+   extern int uactive;
+   extern int tactive;
+@@ -283,6 +289,8 @@
+   number(numqueries); space();
+   number(cache_motion); space();
+   number(uactive); space();
+-  number(tactive);
++  number(tactive); space();
++  number(cache_hit); space();
++  number(cache_miss);
+   line();
+ }
diff --git a/net/djbdns/patches/120-compiler-temporary-filename.patch b/net/djbdns/patches/120-compiler-temporary-filename.patch
new file mode 100644 (file)
index 0000000..3fcde45
--- /dev/null
@@ -0,0 +1,93 @@
+--- djbdns-1.05.original/pickdns-data.c        2001-02-11 21:11:45.000000000 +0000
++++ djbdns-1.05/pickdns-data.c 2003-10-19 10:47:17.000000000 +0100
+@@ -123,7 +123,7 @@
+ }
+ void die_datatmp(void)
+ {
+-  strerr_die2sys(111,FATAL,"unable to create data.tmp: ");
++  strerr_die2sys(111,FATAL,"unable to create data.cdb.tmp: ");
+ }
+ int main()
+@@ -142,7 +142,7 @@
+   if (fd == -1) strerr_die2sys(111,FATAL,"unable to open data: ");
+   buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace);
+-  fdcdb = open_trunc("data.tmp");
++  fdcdb = open_trunc("data.cdb.tmp");
+   if (fdcdb == -1) die_datatmp();
+   if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
+@@ -223,8 +223,8 @@
+   if (cdb_make_finish(&cdb) == -1) die_datatmp();
+   if (fsync(fdcdb) == -1) die_datatmp();
+   if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
+-  if (rename("data.tmp","data.cdb") == -1)
+-    strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
++  if (rename("data.cdb.tmp","data.cdb") == -1)
++    strerr_die2sys(111,FATAL,"unable to move data.cdb.tmp to data.cdb: ");
+   _exit(0);
+ }
+--- djbdns-1.05.original/rbldns-data.c 2001-02-11 21:11:45.000000000 +0000
++++ djbdns-1.05/rbldns-data.c  2003-10-19 10:47:30.000000000 +0100
+@@ -42,7 +42,7 @@
+ }
+ void die_datatmp(void)
+ {
+-  strerr_die2sys(111,FATAL,"unable to create data.tmp: ");
++  strerr_die2sys(111,FATAL,"unable to create data.cdb.tmp: ");
+ }
+ int main()
+@@ -59,7 +59,7 @@
+   if (fd == -1) strerr_die2sys(111,FATAL,"unable to open data: ");
+   buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace);
+-  fdcdb = open_trunc("data.tmp");
++  fdcdb = open_trunc("data.cdb.tmp");
+   if (fdcdb == -1) die_datatmp();
+   if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
+@@ -121,8 +121,8 @@
+   if (cdb_make_finish(&cdb) == -1) die_datatmp();
+   if (fsync(fdcdb) == -1) die_datatmp();
+   if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
+-  if (rename("data.tmp","data.cdb") == -1)
+-    strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
++  if (rename("data.cdb.tmp","data.cdb") == -1)
++    strerr_die2sys(111,FATAL,"unable to move data.cdb.tmp to data.cdb: ");
+   _exit(0);
+ }
+--- djbdns-1.05.original/tinydns-data.c        2001-02-11 21:11:45.000000000 +0000
++++ djbdns-1.05/tinydns-data.c 2003-10-19 11:59:16.000000000 +0100
+@@ -27,7 +27,7 @@
+ void die_datatmp(void)
+ {
+-  strerr_die2sys(111,FATAL,"unable to create data.tmp: ");
++  strerr_die2sys(111,FATAL,"unable to create data.cdb.tmp: ");
+ }
+ void nomem(void)
+ {
+@@ -206,7 +206,7 @@
+   buffer_init(&b,buffer_unixread,fddata,bspace,sizeof bspace);
+-  fdcdb = open_trunc("data.tmp");
++  fdcdb = open_trunc("data.cdb.tmp");
+   if (fdcdb == -1) die_datatmp();
+   if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
+@@ -449,8 +449,8 @@
+   if (cdb_make_finish(&cdb) == -1) die_datatmp();
+   if (fsync(fdcdb) == -1) die_datatmp();
+   if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
+-  if (rename("data.tmp","data.cdb") == -1)
+-    strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
++  if (rename("data.cdb.tmp","data.cdb") == -1)
++    strerr_die2sys(111,FATAL,"unable to move data.cdb.tmp to data.cdb: ");
+   _exit(0);
+ }
diff --git a/net/djbdns/patches/130-dnscache-multiple-ip.patch b/net/djbdns/patches/130-dnscache-multiple-ip.patch
new file mode 100644 (file)
index 0000000..d257466
--- /dev/null
@@ -0,0 +1,301 @@
+--- djbdns-1.05.orig/dnscache.c.orig   Tue Feb 27 00:32:52 2001
++++ djbdns-1.05/dnscache.c     Tue Feb 27 00:30:58 2001
+@@ -5,6 +5,7 @@
+ #include "strerr.h"
+ #include "error.h"
+ #include "ip4.h"
++#include "str.h"
+ #include "uint16.h"
+ #include "uint64.h"
+ #include "socket.h"
+@@ -47,12 +48,20 @@
+ static char myipoutgoing[4];
+-static char myipincoming[4];
+ static char buf[1024];
+ uint64 numqueries = 0;
++struct interf {
++  char ip[4];
++  int udp53;
++  int tcp53;
++  iopause_fd *udp53io;
++  iopause_fd *tcp53io;
++  
++  struct interf *next;
++} ;
+-static int udp53;
++struct interf *interhead = 0;
+ #define MAXUDP 200
+ static struct udpclient {
+@@ -60,6 +69,7 @@
+   struct taia start;
+   uint64 active; /* query number, if active; otherwise 0 */
+   iopause_fd *io;
++  int fd;
+   char ip[4];
+   uint16 port;
+   char id[2];
+@@ -78,12 +88,12 @@
+   if (!u[j].active) return;
+   response_id(u[j].id);
+   if (response_len > 512) response_tc();
+-  socket_send4(udp53,response,response_len,u[j].ip,u[j].port);
++  socket_send4(u[j].fd,response,response_len,u[j].ip,u[j].port);
+   log_querydone(&u[j].active,response_len);
+   u[j].active = 0; --uactive;
+ }
+-void u_new(void)
++void u_new(int fd)
+ {
+   int j;
+   int i;
+@@ -108,8 +118,9 @@
+   x = u + j;
+   taia_now(&x->start);
++  x->fd = fd;
+-  len = socket_recv4(udp53,buf,sizeof buf,x->ip,&x->port);
++  len = socket_recv4(x->fd,buf,sizeof buf,x->ip,&x->port);
+   if (len == -1) return;
+   if (len >= sizeof buf) return;
+   if (x->port < 1024) if (x->port != 53) return;
+@@ -129,8 +140,6 @@
+ }
+-static int tcp53;
+-
+ #define MAXTCP 20
+ struct tcpclient {
+   struct query q;
+@@ -138,6 +147,7 @@
+   struct taia timeout;
+   uint64 active; /* query number or 1, if active; otherwise 0 */
+   iopause_fd *io;
++  int fd;
+   char ip[4]; /* send response to this address */
+   uint16 port; /* send response to this port */
+   char id[2];
+@@ -266,7 +276,7 @@
+   x->state = 0;
+ }
+-void t_new(void)
++void t_new(int fd)
+ {
+   int i;
+   int j;
+@@ -290,8 +300,9 @@
+   x = t + j;
+   taia_now(&x->start);
++  x->fd = fd;
+-  x->tcp = socket_accept4(tcp53,x->ip,&x->port);
++  x->tcp = socket_accept4(x->fd,x->ip,&x->port);
+   if (x->tcp == -1) return;
+   if (x->port < 1024) if (x->port != 53) { close(x->tcp); return; }
+   if (!okclient(x->ip)) { close(x->tcp); return; }
+@@ -304,19 +315,24 @@
+   log_tcpopen(x->ip,x->port);
+ }
++#define FATAL "dnscache: fatal: "
+-iopause_fd io[3 + MAXUDP + MAXTCP];
+-iopause_fd *udp53io;
+-iopause_fd *tcp53io;
++iopause_fd *io = 0;
++int numio;
+ static void doit(void)
+ {
+   int j;
+   struct taia deadline;
+   struct taia stamp;
++  struct interf *inter;
+   int iolen;
+   int r;
++  io = (iopause_fd *) alloc((numio + 1 + MAXUDP + MAXTCP) * sizeof(iopause_fd));
++  if (!io)
++    strerr_die2sys(111,FATAL,"unable to alloc io: ");
++
+   for (;;) {
+     taia_now(&stamp);
+     taia_uint(&deadline,120);
+@@ -324,13 +340,15 @@
+     iolen = 0;
+-    udp53io = io + iolen++;
+-    udp53io->fd = udp53;
+-    udp53io->events = IOPAUSE_READ;
+-
+-    tcp53io = io + iolen++;
+-    tcp53io->fd = tcp53;
+-    tcp53io->events = IOPAUSE_READ;
++    for (inter = interhead; inter != 0; inter = inter->next) {
++      inter->udp53io = io + iolen++;
++      inter->udp53io->fd = inter->udp53;
++      inter->udp53io->events = IOPAUSE_READ;
++
++      inter->tcp53io = io + iolen++;
++      inter->tcp53io->fd = inter->tcp53;
++      inter->tcp53io->events = IOPAUSE_READ;
++    }
+     for (j = 0;j < MAXUDP;++j)
+       if (u[j].active) {
+@@ -372,46 +390,82 @@
+           t_rw(j);
+       }
+-    if (udp53io)
+-      if (udp53io->revents)
+-      u_new();
+-
+-    if (tcp53io)
+-      if (tcp53io->revents)
+-      t_new();
++    for (inter = interhead; inter != 0; inter = inter->next) {
++      if (inter->udp53io)
++        if (inter->udp53io->revents)
++        u_new(inter->udp53);
++
++      if (inter->tcp53io)
++        if (inter->tcp53io->revents)
++        t_new(inter->tcp53);
++    }
+   }
+ }
+   
+-#define FATAL "dnscache: fatal: "
+-
+ char seed[128];
+ int main()
+ {
+   char *x;
++  int len;
++  int pos;
++  int oldpos;
++  char iptmp[4];
++  char iperr[IP4_FMT];
++  struct interf *inter;
++  struct interf *itmp;
+   unsigned long cachesize;
+   x = env_get("IP");
+   if (!x)
+     strerr_die2x(111,FATAL,"$IP not set");
+-  if (!ip4_scan(x,myipincoming))
+-    strerr_die3x(111,FATAL,"unable to parse IP address ",x);
+-  udp53 = socket_udp();
+-  if (udp53 == -1)
+-    strerr_die2sys(111,FATAL,"unable to create UDP socket: ");
+-  if (socket_bind4_reuse(udp53,myipincoming,53) == -1)
+-    strerr_die2sys(111,FATAL,"unable to bind UDP socket: ");
+-
+-  tcp53 = socket_tcp();
+-  if (tcp53 == -1)
+-    strerr_die2sys(111,FATAL,"unable to create TCP socket: ");
+-  if (socket_bind4_reuse(tcp53,myipincoming,53) == -1)
+-    strerr_die2sys(111,FATAL,"unable to bind TCP socket: ");
++  len = str_len(x);
++  numio = pos = oldpos = 0;
++  
++  while (pos < len) {
++    if (pos) oldpos = pos + 1;
++    pos = oldpos + str_chr(x + oldpos,'/');
++    x[pos] = 0;
++    if (!str_len(x + oldpos)) continue;
++    
++    if (!ip4_scan(x + oldpos,iptmp))
++      strerr_die3x(111,FATAL,"unable to parse IP address ",x + oldpos);
++      
++    inter = (struct interf *) alloc(sizeof(struct interf));
++    
++    if (interhead == 0) interhead = inter;
++    else if (interhead->next == 0) interhead->next = inter;
++    else {
++      for (itmp = interhead; itmp->next != 0; itmp = itmp->next);
++      itmp->next = inter;
++    }
++    
++    inter->next = 0;
++    
++    inter->udp53 = socket_udp();
++    if (inter->udp53 == -1)
++      strerr_die4sys(111,FATAL,"unable to create UDP socket for IP address ",x + oldpos,": ");
++    if (socket_bind4_reuse(inter->udp53,iptmp,53) == -1)
++      strerr_die4sys(111,FATAL,"unable to bind UDP socket for IP address ",x + oldpos,": ");
++      
++    inter->tcp53 = socket_tcp();
++    if (inter->tcp53 == -1)
++      strerr_die4sys(111,FATAL,"unable to create TCP socket for IP address ",x + oldpos,": ");
++    if (socket_bind4_reuse(inter->tcp53,iptmp,53) == -1)
++      strerr_die4sys(111,FATAL,"unable to bind TCP socket for IP address ",x + oldpos,": ");
++      
++    numio++;
++    log_listen(iptmp);
++  }
++
++  if (interhead == 0)
++    strerr_die2x(111,FATAL,"no interfaces to listen on");
+   droproot(FATAL);
+-  socket_tryreservein(udp53,131072);
++  for (inter = interhead; inter != 0; inter = inter->next)
++    socket_tryreservein(inter->udp53,131072);
+   byte_zero(seed,sizeof seed);
+   read(0,seed,sizeof seed);
+@@ -439,8 +493,11 @@
+   if (!roots_init())
+     strerr_die2sys(111,FATAL,"unable to read servers: ");
+-  if (socket_listen(tcp53,20) == -1)
+-    strerr_die2sys(111,FATAL,"unable to listen on TCP socket: ");
++  for (inter = interhead; inter != 0; inter = inter->next)
++    if (socket_listen(inter->tcp53,20) == -1) {
++      iperr[ip4_fmt(iperr,inter->ip)] = 0;
++      strerr_die4sys(111,FATAL,"unable to listen on TCP socket for IP ",iperr,": ");
++    }
+   log_startup();
+   doit();
+--- djbdns-1.05.orig/log.c.orig        Tue Feb 27 00:33:02 2001
++++ djbdns-1.05/log.c  Tue Feb 27 00:30:58 2001
+@@ -94,6 +94,13 @@
+   line();
+ }
++void log_listen(const char addr[4])
++{
++  string("listening on ");
++  ip(addr);
++  line();
++}
++
+ void log_query(uint64 *qnum,const char client[4],unsigned int port,const char id[2],const char *q,const char qtype[2])
+ {
+   string("query "); number(*qnum); space();
+--- djbdns-1.05.orig/log.h.orig        Tue Feb 27 00:33:09 2001
++++ djbdns-1.05/log.h  Tue Feb 27 00:30:58 2001
+@@ -4,6 +4,7 @@
+ #include "uint64.h"
+ extern void log_startup(void);
++extern void log_listen(const char *);
+ extern void log_query(uint64 *,const char *,unsigned int,const char *,const char *,const char *);
+ extern void log_querydrop(uint64 *);
diff --git a/net/djbdns/patches/140-dnsnamex-extra-command.patch b/net/djbdns/patches/140-dnsnamex-extra-command.patch
new file mode 100644 (file)
index 0000000..7b75e7d
--- /dev/null
@@ -0,0 +1,156 @@
+--- ../djbdns-1.05-original/dnsnamex.c Tue May 27 02:17:04 2003
++++ ./dnsnamex.c       Tue May 27 02:18:52 2003
+@@ -0,0 +1,34 @@
++#include "buffer.h"
++#include "exit.h"
++#include "strerr.h"
++#include "ip4.h"
++#include "dns.h"
++
++#define FATAL "dnsnamex: fatal: "
++
++static char seed[128];
++
++char ip[4];
++static stralloc out;
++
++int main(int argc,char **argv)
++{
++  dns_random_init(seed);
++
++  if (*argv) ++argv;
++
++  while (*argv) {
++    if (!ip4_scan(*argv,ip))
++      strerr_die3x(111,FATAL,"unable to parse IP address ",*argv);
++    if (dns_name4_multi(&out,ip) == -1)
++      strerr_die4sys(111,FATAL,"unable to find host name for ",*argv,": ");
++
++    buffer_put(buffer_1,out.s,out.len);
++    buffer_puts(buffer_1,"\n");
++
++    ++argv;
++  }
++
++  buffer_flush(buffer_1);
++  _exit(0);
++}
+--- ../djbdns-1.05-original/dns_namex.c        Tue May 27 02:17:09 2003
++++ ./dns_namex.c      Tue May 27 02:15:15 2003
+@@ -0,0 +1,48 @@
++#include "stralloc.h"
++#include "uint16.h"
++#include "byte.h"
++#include "dns.h"
++
++static char *q = 0;
++
++int dns_name_packet_multi(stralloc *out,const char *buf,unsigned int len)
++{
++  unsigned int pos;
++  char header[12];
++  uint16 numanswers;
++  uint16 datalen;
++
++  if (!stralloc_copys(out,"")) return -1;
++
++  pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
++  uint16_unpack_big(header + 6,&numanswers);
++  pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
++  pos += 4;
++
++  while (numanswers--) {
++    pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
++    pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
++    uint16_unpack_big(header + 8,&datalen);
++    if (byte_equal(header,2,DNS_T_PTR))
++      if (byte_equal(header + 2,2,DNS_C_IN)) {
++      if (!dns_packet_getname(buf,len,pos,&q)) return -1;
++      if (!dns_domain_todot_cat(out,q)) return -1;
++      if (!stralloc_cats(out, " ")) return -1 ; 
++      }
++    pos += datalen;
++  }
++
++  return 0;
++}
++
++int dns_name4_multi(stralloc *out,const char ip[4])
++{
++  char name[DNS_NAME4_DOMAIN];
++
++  dns_name4_domain(name,ip);
++  if (dns_resolve(name,DNS_T_PTR) == -1) return -1;
++  if (dns_name_packet_multi(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
++  dns_transmit_free(&dns_resolve_tx);
++  dns_domain_free(&q);
++  return 0;
++}
+--- ../djbdns-1.05-original/dns.h      Sun Feb 11 21:11:45 2001
++++ ./dns.h    Tue May 27 02:10:30 2003
+@@ -69,9 +69,11 @@
+ extern int dns_ip4_packet(stralloc *,const char *,unsigned int);
+ extern int dns_ip4(stralloc *,const stralloc *);
+ extern int dns_name_packet(stralloc *,const char *,unsigned int);
++extern int dns_name_packet_multi(stralloc *,const char *,unsigned int);
+ extern void dns_name4_domain(char *,const char *);
+ #define DNS_NAME4_DOMAIN 31
+ extern int dns_name4(stralloc *,const char *);
++extern int dns_name4_multi(stralloc *,const char *);
+ extern int dns_txt_packet(stralloc *,const char *,unsigned int);
+ extern int dns_txt(stralloc *,const stralloc *);
+ extern int dns_mx_packet(stralloc *,const char *,unsigned int);
+--- ../djbdns-1.05-original/Makefile   Sun Feb 11 21:11:45 2001
++++ ./Makefile Tue May 27 02:21:00 2003
+@@ -227,10 +227,10 @@
+ dns.a: \
+ makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o dns_mx.o \
+-dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
++dns_name.o dns_namex.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
+ dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o
+       ./makelib dns.a dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o \
+-      dns_ipq.o dns_mx.o dns_name.o dns_nd.o dns_packet.o \
++      dns_ipq.o dns_mx.o dns_name.o dns_namex.o dns_nd.o dns_packet.o \
+       dns_random.o dns_rcip.o dns_rcrw.o dns_resolve.o \
+       dns_sortip.o dns_transmit.o dns_txt.o
+@@ -269,6 +269,11 @@
+ stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+       ./compile dns_name.c
++dns_namex.o: \
++compile dns_namex.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
++stralloc.h iopause.h taia.h tai.h uint64.h taia.h
++      ./compile dns_namex.c
++
+ dns_nd.o: \
+ compile dns_nd.c byte.h fmt.h dns.h stralloc.h gen_alloc.h iopause.h \
+ taia.h tai.h uint64.h taia.h
+@@ -402,6 +407,17 @@
+ gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
+       ./compile dnsname.c
++dnsnamex: \
++load dnsnamex.o iopause.o dns.a env.a libtai.a alloc.a buffer.a unix.a \
++byte.a socket.lib
++      ./load dnsnamex iopause.o dns.a env.a libtai.a alloc.a \
++      buffer.a unix.a byte.a  `cat socket.lib`
++
++dnsnamex.o: \
++compile dnsnamex.c buffer.h exit.h strerr.h ip4.h dns.h stralloc.h \
++gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
++      ./compile dnsnamex.c
++
+ dnsq: \
+ load dnsq.o iopause.o printrecord.o printpacket.o parsetype.o dns.a \
+ env.a libtai.a buffer.a alloc.a unix.a byte.a socket.lib
+@@ -676,7 +692,7 @@
+ dnscache-conf dnscache walldns-conf walldns rbldns-conf rbldns \
+ rbldns-data pickdns-conf pickdns pickdns-data tinydns-conf tinydns \
+ tinydns-data tinydns-get tinydns-edit axfr-get axfrdns-conf axfrdns \
+-dnsip dnsipq dnsname dnstxt dnsmx dnsfilter random-ip dnsqr dnsq \
++dnsip dnsipq dnsname dnsnamex dnstxt dnsmx dnsfilter random-ip dnsqr dnsq \
+ dnstrace dnstracesort cachetest utime rts
+ prot.o: \
diff --git a/net/djbdns/patches/200-dnscache-cname-handling.patch b/net/djbdns/patches/200-dnscache-cname-handling.patch
new file mode 100644 (file)
index 0000000..339c8fa
--- /dev/null
@@ -0,0 +1,226 @@
+--- djbdns-1.05-original/query.c       Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/query.c        Wed Mar 26 15:48:20 2003
+@@ -91,6 +91,21 @@
+   }
+ }
++static int move_name_to_alias(struct query *z,uint32 ttl)
++{
++  int j ;
++
++  if (z->alias[QUERY_MAXALIAS - 1]) return 0 ;
++  for (j = QUERY_MAXALIAS - 1;j > 0;--j)
++    z->alias[j] = z->alias[j - 1];
++  for (j = QUERY_MAXALIAS - 1;j > 0;--j)
++    z->aliasttl[j] = z->aliasttl[j - 1];
++  z->alias[0] = z->name[0];
++  z->aliasttl[0] = ttl;
++  z->name[0] = 0;
++  return 1 ;
++}
++
+ static int rqa(struct query *z)
+ {
+   int i;
+@@ -123,7 +138,6 @@
+ static char *t1 = 0;
+ static char *t2 = 0;
+ static char *t3 = 0;
+-static char *cname = 0;
+ static char *referral = 0;
+ static unsigned int *records = 0;
+@@ -179,15 +193,14 @@
+   uint16 datalen;
+   char *control;
+   char *d;
++  char *owner_name = 0 ;
+   const char *dtype;
+   unsigned int dlen;
+   int flagout;
+-  int flagcname;
+   int flagreferral;
+   int flagsoa;
+   uint32 ttl;
+   uint32 soattl;
+-  uint32 cnamettl;
+   int i;
+   int j;
+   int k;
+@@ -252,7 +265,10 @@
+     byte_copy(key,2,DNS_T_CNAME);
+     cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+-    if (cached) {
++    /* A previous explicit query might have caused an empty RRSet to have been
++    ** cached.  Take care to ignore such a thing. 
++    */
++    if (cached && cachedlen) {
+       if (typematch(DNS_T_CNAME,dtype)) {
+         log_cachedanswer(d,DNS_T_CNAME);
+         if (!rqa(z)) goto DIE;
+@@ -261,8 +277,11 @@
+       return 1;
+       }
+       log_cachedcname(d,cached);
+-      if (!dns_domain_copy(&cname,cached)) goto DIE;
+-      goto CNAME;
++      if (!z->level) {
++      if (!move_name_to_alias(z,ttl)) goto DIE ;
++      }
++      if (!dns_domain_copy(&z->name[z->level],cached)) goto DIE;
++      goto NEWNAME;
+     }
+     if (typematch(DNS_T_NS,dtype)) {
+@@ -351,7 +370,7 @@
+       }
+     }
+-    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
++    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
+       byte_copy(key,2,dtype);
+       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
+@@ -471,29 +490,31 @@
+   if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */
+   flagout = 0;
+-  flagcname = 0;
+   flagreferral = 0;
+   flagsoa = 0;
+   soattl = 0;
+-  cnamettl = 0;
++  if (!dns_domain_copy(&owner_name,d)) goto DIE;
++  /* This code assumes that the CNAME chain is presented in the correct 
++  ** order.  The example algorithm in RFC 1034 will actually result in this
++  ** being the case, but the words do not require it to be so.
++  */
+   for (j = 0;j < numanswers;++j) {
+     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
+     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
+-    if (dns_domain_equal(t1,d))
++    if (dns_domain_equal(t1,owner_name))
+       if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */
+         if (typematch(header,dtype))
+           flagout = 1;
+         else if (typematch(header,DNS_T_CNAME)) {
+-          if (!dns_packet_getname(buf,len,pos,&cname)) goto DIE;
+-          flagcname = 1;
+-        cnamettl = ttlget(header + 4);
++          if (!dns_packet_getname(buf,len,pos,&owner_name)) goto DIE;
+         }
+       }
+   
+     uint16_unpack_big(header + 8,&datalen);
+     pos += datalen;
+   }
++  dns_domain_free(&owner_name) ;
+   posauthority = pos;
+   for (j = 0;j < numauthority;++j) {
+@@ -515,15 +536,6 @@
+   }
+   posglue = pos;
+-
+-  if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
+-    if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
+-      log_lame(whichserver,control,referral);
+-      byte_zero(whichserver,4);
+-      goto HAVENS;
+-    }
+-
+-
+   if (records) { alloc_free(records); records = 0; }
+   k = numanswers + numauthority + numglue;
+@@ -670,24 +682,36 @@
+   alloc_free(records); records = 0;
++  if (byte_diff(DNS_T_CNAME,2,dtype)) {
++    /* This code assumes that the CNAME chain is presented in the correct 
++    ** order.  The example algorithm in RFC 1034 will actually result in this
++    ** being the case, but the words do not require it to be so.
++    */
++    pos = posanswers;
++    for (j = 0;j < numanswers;++j) {
++      pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
++      pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
++
++      if (dns_domain_equal(t1,d))
++      if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */
++        if (typematch(header,DNS_T_CNAME)) {
++          ttl = ttlget(header + 4);
++          if (z->level == 0) {
++            if (!move_name_to_alias(z,ttl)) goto DIE ;
++          }
++          if (!dns_packet_getname(buf,len,pos,&z->name[z->level])) goto DIE;
++          d = z->name[z->level];
++          if (!dns_domain_suffix(d,control) || !roots_same(d,control))
++            goto NEWNAME ;  /* Cannot trust the chain further - restart using current name */
++        }
++      }
+-  if (flagcname) {
+-    ttl = cnamettl;
+-    CNAME:
+-    if (!z->level) {
+-      if (z->alias[QUERY_MAXALIAS - 1]) goto DIE;
+-      for (j = QUERY_MAXALIAS - 1;j > 0;--j)
+-        z->alias[j] = z->alias[j - 1];
+-      for (j = QUERY_MAXALIAS - 1;j > 0;--j)
+-        z->aliasttl[j] = z->aliasttl[j - 1];
+-      z->alias[0] = z->name[0];
+-      z->aliasttl[0] = ttl;
+-      z->name[0] = 0;
++      uint16_unpack_big(header + 8,&datalen);
++      pos += datalen;
+     }
+-    if (!dns_domain_copy(&z->name[z->level],cname)) goto DIE;
+-    goto NEWNAME;
+   }
++  /* A "no such name" error applies to the end of any CNAME chain, not to the start. */
+   if (rcode == 3) {
+     log_nxdomain(whichserver,d,soattl);
+     cachegeneric(DNS_T_ANY,d,"",0,soattl);
+@@ -700,10 +724,26 @@
+     return 1;
+   }
++  /* We check for a lame server _after_ we have cached any records that it
++  ** might have returned to us.  This copes better with the incorrect
++  ** behaviour of one content DNS server software that doesn't return
++  ** complete CNAME chains but instead returns only the first link in a
++  ** chain followed by a lame delegation to the same server.
++  ** Also: We check for a lame server _after_ following the CNAME chain.  The
++  ** delegation in a referral answer applies to the _end_ of the chain, not
++  ** to the beginning.
++  */
++  if (!rcode && !flagout && flagreferral && !flagsoa)
++    if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
++      log_lame(whichserver,control,referral);
++      byte_zero(whichserver,4);
++      goto HAVENS;
++    }
++
+   if (!flagout && flagsoa)
++    /* Don't save empty RRSets for those types that we use as special markers. */
+     if (byte_diff(DNS_T_ANY,2,dtype))
+-      if (byte_diff(DNS_T_AXFR,2,dtype))
+-        if (byte_diff(DNS_T_CNAME,2,dtype)) {
++      if (byte_diff(DNS_T_AXFR,2,dtype)) {
+           save_start();
+           save_finish(dtype,d,soattl);
+         log_nodata(whichserver,d,dtype,soattl);
+@@ -815,6 +855,7 @@
+   DIE:
+   cleanup(z);
+   if (records) { alloc_free(records); records = 0; }
++  dns_domain_free(&owner_name) ;
+   return -1;
+ }
diff --git a/net/djbdns/patches/210-dnscache-strict-forwardonly.patch b/net/djbdns/patches/210-dnscache-strict-forwardonly.patch
new file mode 100644 (file)
index 0000000..1602e4c
--- /dev/null
@@ -0,0 +1,47 @@
+--- djbdns-1.05.original/log.h 2001-02-11 21:11:45.000000000 +0000
++++ djbdns-1.05/log.h  2003-07-29 17:12:44.000000000 +0100
+@@ -23,6 +23,7 @@
+ extern void log_nodata(const char *,const char *,const char *,unsigned int);
+ extern void log_servfail(const char *);
+ extern void log_lame(const char *,const char *,const char *);
++extern void log_ignore_referral(const char *,const char *,const char *);
+ extern void log_rr(const char *,const char *,const char *,const char *,unsigned int,unsigned int);
+ extern void log_rrns(const char *,const char *,const char *,unsigned int);
+--- djbdns-1.05.original/log.c 2001-02-11 21:11:45.000000000 +0000
++++ djbdns-1.05/log.c  2003-07-29 17:12:33.000000000 +0100
+@@ -196,6 +196,13 @@
+   line();
+ }
++void log_ignore_referral(const char server[4],const char * control, const char *referral)
++{
++  string("ignored referral "); ip(server); space();
++  name(control); space(); name(referral);
++  line();
++}
++
+ void log_servfail(const char *dn)
+ {
+   const char *x = error_str(errno);
+--- djbdns-1.05.original/query.c       2001-02-11 21:11:45.000000000 +0000
++++ djbdns-1.05/query.c        2003-07-29 17:13:13.000000000 +0100
+@@ -781,6 +781,18 @@
+   if (!dns_domain_suffix(d,referral)) goto DIE;
++
++  /* In strict "forwardonly" mode, we don't, as the manual states,
++  ** contact a chain of servers according to "NS" resource records.
++  ** We don't obey any referral responses, therefore.  Instead, we
++  ** eliminate the server from the list and try the next one.
++  */
++  if (flagforwardonly) {
++      log_ignore_referral(whichserver,control,referral);
++      byte_zero(whichserver,4);
++      goto HAVENS;
++  }
++
+   control = d + dns_domain_suffixpos(d,referral);
+   z->control[z->level] = control;
+   byte_zero(z->servers[z->level],64);
diff --git a/net/djbdns/patches/220-dnscacheip-space-separator.patch b/net/djbdns/patches/220-dnscacheip-space-separator.patch
new file mode 100644 (file)
index 0000000..d3ad8a3
--- /dev/null
@@ -0,0 +1,11 @@
+--- djbdns-1.05.original/dns_rcip.c    2001-02-11 21:11:45.000000000 +0000
++++ djbdns-1.05/dns_rcip.c     2003-11-03 14:55:10.000000000 +0000
+@@ -17,7 +17,7 @@
+   x = env_get("DNSCACHEIP");
+   if (x)
+     while (iplen <= 60) {
+-      if (*x == '.')
++      if (*x == ' ' || *x == '\t' || *x == '\n')
+       ++x;
+       else {
+         i = ip4_scan(x,ip + iplen);
diff --git a/net/djbdns/patches/230-tinydns-data-semantic-error.patch b/net/djbdns/patches/230-tinydns-data-semantic-error.patch
new file mode 100644 (file)
index 0000000..cdfd0b2
--- /dev/null
@@ -0,0 +1,194 @@
+--- djbdns-1.05.orig/tinydns-data.c.orig       2004-01-10 02:20:08.000000000 +0000
++++ djbdns-1.05/tinydns-data.c 2004-01-10 02:28:50.000000000 +0000
+@@ -25,6 +25,14 @@
+ #define FATAL "tinydns-data: fatal: "
++void die_semantic2(const char * s1, const char * s2)
++{
++  strerr_die3x(111,FATAL,s1,s2) ;
++}
++void die_semantic4(const char * s1, const char * s2,const char * s3, const char * s4)
++{
++  strerr_die5x(111,FATAL,s1,s2,s3,s4) ;
++}
+ void die_datatmp(void)
+ {
+   strerr_die2sys(111,FATAL,"unable to create data.tmp: ");
+@@ -34,20 +42,39 @@
+   strerr_die1sys(111,FATAL);
+ }
++void ttlparse(stralloc *sa,unsigned long * ttl, unsigned long defttl, const char * ltype)
++{
++    int ttllen ;
++
++    if (sa->len > 0) {
++      if (!stralloc_0(sa)) nomem();
++      ttllen = scan_ulong(sa->s,ttl) ;
++      if (ttllen + 1 != sa->len)
++          die_semantic4("unparseable TTL in ",ltype," line: ", sa->s) ;
++    } else
++      *ttl = defttl;
++}
++
+ void ttdparse(stralloc *sa,char ttd[8])
+ {
+   unsigned int i;
+   char ch;
+   byte_zero(ttd,8);
+-  for (i = 0;(i < 16) && (i < sa->len);++i) {
++  for (i = 0;i < sa->len;++i) {
++    if (i >= 16) {
++      if (!stralloc_0(sa)) nomem() ;
++      die_semantic2("timestamp is too long: ", sa->s) ;
++    }
+     ch = sa->s[i];
+     if ((ch >= '0') && (ch <= '9'))
+       ch -= '0';
+     else if ((ch >= 'a') && (ch <= 'f'))
+       ch -= 'a' - 10;
+-    else
+-      ch = 0;
++    else {
++      if (!stralloc_0(sa)) nomem() ;
++      die_semantic2("timestamp contains an invalid character: ", sa->s) ;
++    }
+     if (!(i & 1)) ch <<= 4;
+     ttd[i >> 1] |= ch;
+   }
+@@ -55,6 +82,10 @@
+ void locparse(stralloc *sa,char loc[2])
+ {
++  if (sa->len > 2) {
++    if (!stralloc_0(sa)) nomem() ;
++    die_semantic2("location code longer than two characters: ", sa->s) ;
++  }
+   loc[0] = (sa->len > 0) ? sa->s[0] : 0;
+   loc[1] = (sa->len > 1) ? sa->s[1] : 0;
+ }
+@@ -187,6 +218,7 @@
+   int i;
+   int j;
+   int k;
++  int iplen ;
+   char ch;
+   unsigned long ttl;
+   char ttd[8];
+@@ -266,8 +298,7 @@
+       if (!scan_ulong(f[7].s,&u)) uint32_unpack_big(defaultsoa + 16,&u);
+       uint32_pack_big(soa + 16,u);
+-      if (!stralloc_0(&f[8])) nomem();
+-      if (!scan_ulong(f[8].s,&ttl)) ttl = TTL_NEGATIVE;
++      ttlparse(&f[8],&ttl,TTL_NEGATIVE,"Z");
+       ttdparse(&f[9],ttd);
+       locparse(&f[10],loc);
+@@ -282,8 +313,7 @@
+       case '.': case '&':
+       if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+-      if (!stralloc_0(&f[3])) nomem();
+-      if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS;
++      ttlparse(&f[3],&ttl,TTL_NS,". or &");
+       ttdparse(&f[4],ttd);
+       locparse(&f[5],loc);
+@@ -308,24 +338,26 @@
+       rr_addname(d2);
+       rr_finish(d1);
+-      if (ip4_scan(f[1].s,ip)) {
++      iplen = ip4_scan(f[1].s,ip) ;
++      if (iplen != 0 && iplen + 1 == f[1].len) {
+         rr_start(DNS_T_A,ttl,ttd,loc);
+         rr_add(ip,4);
+         rr_finish(d2);
+-      }
++      } else if (f[1].len > 1)
++        die_semantic4("unparseable IP address in ","& or ."," line: ", f[1].s) ;
+       break;
+       case '+': case '=':
+       if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+-      if (!stralloc_0(&f[2])) nomem();
+-      if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE;
++      ttlparse(&f[2],&ttl,TTL_POSITIVE,"+ or =");
+       ttdparse(&f[3],ttd);
+       locparse(&f[4],loc);
+       if (!stralloc_0(&f[1])) nomem();
+-      if (ip4_scan(f[1].s,ip)) {
++      iplen = ip4_scan(f[1].s,ip) ;
++      if (iplen != 0 && iplen + 1 == f[1].len) {
+         rr_start(DNS_T_A,ttl,ttd,loc);
+         rr_add(ip,4);
+         rr_finish(d1);
+@@ -336,13 +368,15 @@
+           rr_addname(d1);
+           rr_finish(dptr);
+         }
+-      }
++      } else if (f[1].len > 1)
++        die_semantic4("unparseable IP address in ","+ or ="," line: ", f[1].s) ;
++      else
++        die_semantic4("missing IP address in ","+ or ="," line: ", f[1].s) ;
+       break;
+       case '@':
+       if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+-      if (!stralloc_0(&f[4])) nomem();
+-      if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE;
++      ttlparse(&f[4],&ttl,TTL_POSITIVE,"@");
+       ttdparse(&f[5],ttd);
+       locparse(&f[6],loc);
+@@ -363,18 +397,19 @@
+       rr_addname(d2);
+       rr_finish(d1);
+-      if (ip4_scan(f[1].s,ip)) {
++      iplen = ip4_scan(f[1].s,ip) ;
++      if (iplen != 0 && iplen + 1 == f[1].len) {
+         rr_start(DNS_T_A,ttl,ttd,loc);
+         rr_add(ip,4);
+         rr_finish(d2);
+-      }
++      } else if (f[1].len > 1)
++        die_semantic4("unparseable IP address in ","@"," line: ", f[1].s) ;
+       break;
+       case '^': case 'C':
+       if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+       if (!dns_domain_fromdot(&d2,f[1].s,f[1].len)) nomem();
+-      if (!stralloc_0(&f[2])) nomem();
+-      if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE;
++      ttlparse(&f[2],&ttl,TTL_POSITIVE,"^ or C");
+       ttdparse(&f[3],ttd);
+       locparse(&f[4],loc);
+@@ -388,8 +423,7 @@
+       case '\'':
+       if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+-      if (!stralloc_0(&f[2])) nomem();
+-      if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE;
++      ttlparse(&f[2],&ttl,TTL_POSITIVE,"\'");
+       ttdparse(&f[3],ttd);
+       locparse(&f[4],loc);
+@@ -411,8 +445,7 @@
+       case ':':
+       if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+-      if (!stralloc_0(&f[3])) nomem();
+-      if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_POSITIVE;
++      ttlparse(&f[3],&ttl,TTL_POSITIVE,":");
+       ttdparse(&f[4],ttd);
+       locparse(&f[5],loc);
diff --git a/net/djbdns/patches/240-tinydns-alias-chain-truncation.patch b/net/djbdns/patches/240-tinydns-alias-chain-truncation.patch
new file mode 100644 (file)
index 0000000..20d3e1b
--- /dev/null
@@ -0,0 +1,86 @@
+--- djbdns-1.05-original/tdlookup.c    Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/tdlookup.c     Thu Apr  3 11:56:47 2003
+@@ -103,12 +103,13 @@
+   return response_addname(d1);
+ }
+-static int doit(char *q,char qtype[2])
++static int doit1(char **pqname,char qtype[2])
+ {
+   unsigned int bpos;
+   unsigned int anpos;
+   unsigned int aupos;
+   unsigned int arpos;
++  char *q;
+   char *control;
+   char *wild;
+   int flaggavesoa;
+@@ -122,6 +123,12 @@
+   int addrnum;
+   uint32 addrttl;
+   int i;
++  int loop = 0 ;
++
++RESTART:
++  if (loop++ >= 100) return 0 ;
++
++  q = *pqname ;
+   anpos = response_len;
+@@ -136,7 +143,14 @@
+       if (byte_equal(type,2,DNS_T_NS)) flagns = 1;
+     }
+     if (flagns) break;
+-    if (!*control) return 0; /* q is not within our bailiwick */
++    if (!*control) { /* q is not within our bailiwick */
++      if (loop <= 1)
++        return 0 ;
++      else {
++        response[2] &= ~4;
++        goto DONE; /* The administrator has issued contradictory instructions */
++      }
++    }
+     control += *control;
+     control += 1;
+   }
+@@ -172,8 +186,16 @@
+       continue;
+       }
+       if (!response_rstart(q,type,ttl)) return 0;
+-      if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_CNAME) || byte_equal(type,2,DNS_T_PTR)) {
++      if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_PTR)) {
++      if (!doname()) return 0;
++      }
++      else if (byte_equal(type,2,DNS_T_CNAME)) {
+       if (!doname()) return 0;
++        if (byte_diff(type,2,qtype)) {
++        response_rfinish(RESPONSE_ANSWER);
++        if (!dns_domain_copy(pqname,d1)) return 0 ;
++        goto RESTART ;
++      }
+       }
+       else if (byte_equal(type,2,DNS_T_MX)) {
+       if (!dobytes(2)) return 0;
+@@ -275,9 +297,21 @@
+     }
+   }
++DONE:
+   return 1;
+ }
++static int doit(char *qname,char qtype[2])
++{
++  int r ;
++  char * q = 0 ;
++
++  if (!dns_domain_copy(&q, qname)) return 0 ;
++  r = doit1(&q, qtype) ;
++  dns_domain_free(&q) ;
++  return r ;
++}
++
+ int respond(char *q,char qtype[2],char ip[4])
+ {
+   int fd;
diff --git a/net/djbdns/patches/250-djbdns-1.05-slogging.patch b/net/djbdns/patches/250-djbdns-1.05-slogging.patch
new file mode 100644 (file)
index 0000000..a0f2d16
--- /dev/null
@@ -0,0 +1,122 @@
+--- /home/uwe/djbdns-1.05/server.c     Sun Feb 11 21:11:45 2001
++++ ./server.c Fri May  4 07:40:54 2001
+@@ -25,12 +25,63 @@
+ static char *q;
++static uint64 stats_numq;
++static uint64 stats_plus;
++static uint64 stats_minus;
++static uint64 stats_nx;
++static uint64 stats_notimp;
++static uint64 stats_weird;
++static uint64 stats_noq;
++
++/* work around gcc 2.95.2 bug */
++#define number(x) ( (u64 = (x)), u64_print() )
++static uint64 u64;
++static void u64_print(void)
++{
++  char ubuf[20];
++  unsigned int pos;
++
++  pos = sizeof ubuf;
++  do {
++    if (!pos) break;
++    ubuf[--pos] = '0' + (u64 % 10);
++    u64 /= 10;
++  } while(u64);
++
++  buffer_put(buffer_2,ubuf + pos,sizeof ubuf - pos);
++}
++
++static void string(const char *s)
++{
++  buffer_puts(buffer_2,s);
++}
++
++static void line(void)
++{
++  string("\n");
++  buffer_flush(buffer_2);
++}
++
++static void log_stats(void)
++{
++  string("stats ");
++  number(stats_numq); string(" ");
++  number(stats_plus); string(" ");
++  number(stats_minus); string(" ");
++  number(stats_nx); string(" ");
++  number(stats_notimp); string(" ");
++  number(stats_weird); string(" ");
++  number(stats_noq);
++  line();
++}
++
+ static int doit(void)
+ {
+   unsigned int pos;
+   char header[12];
+   char qtype[2];
+   char qclass[2];
++  stats_numq++;
+   if (len >= sizeof buf) goto NOQ;
+   pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ;
+@@ -56,25 +105,37 @@
+   case_lowerb(q,dns_domain_length(q));
+   if (!respond(q,qtype,ip)) {
++    stats_minus++;
+     qlog(ip,port,header,q,qtype," - ");
+     return 0;
+   }
+-  qlog(ip,port,header,q,qtype," + ");
++
++  if ((response[2] & 4) && (response[3] & 3)) {
++    stats_nx++;
++    qlog(ip,port,header,q,qtype," N ");
++  }
++  else {
++    stats_plus++;
++    qlog(ip,port,header,q,qtype," + ");
++  }
+   return 1;
+   NOTIMP:
++  stats_notimp++;
+   response[3] &= ~15;
+   response[3] |= 4;
+   qlog(ip,port,header,q,qtype," I ");
+   return 1;
+   WEIRDCLASS:
++  stats_weird++;
+   response[3] &= ~15;
+   response[3] |= 1;
+   qlog(ip,port,header,q,qtype," C ");
+   return 1;
+   NOQ:
++  stats_noq++;
+   qlog(ip,port,"\0\0","","\0\0"," / ");
+   return 0;
+ }
+@@ -83,6 +137,7 @@
+ {
+   char *x;
+   int udp53;
++  unsigned char flag=0;
+   x = env_get("IP");
+   if (!x)
+@@ -106,6 +161,8 @@
+   buffer_putsflush(buffer_2,starting);
+   for (;;) {
++    if ((flag++)%32==1)
++      log_stats();
+     len = socket_recv4(udp53,buf,sizeof buf,ip,&port);
+     if (len < 0) continue;
+     if (!doit()) continue;
diff --git a/net/djbdns/patches/260-djbdns-1.05-dnsfilter-replace.patch b/net/djbdns/patches/260-djbdns-1.05-dnsfilter-replace.patch
new file mode 100644 (file)
index 0000000..3c272e3
--- /dev/null
@@ -0,0 +1,71 @@
+--- a/dnsfilter.c      Thu Feb 15 21:29:28 2001
++++ b/dnsfilter.c      Thu Feb 15 21:57:36 2001
+@@ -41,6 +41,7 @@
+ iopause_fd *inio;
+ int flag0 = 1;
++int opt_replace = 0;
+ iopause_fd *io;
+ int iolen;
+@@ -51,12 +52,16 @@
+ void errout(int i)
+ {
+   int j;
+-
+-  if (!stralloc_copys(&x[i].middle,":")) nomem();
+-  if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
+-  for (j = 0;j < x[i].middle.len;++j)
+-    if (x[i].middle.s[j] == ' ')
+-      x[i].middle.s[j] = '-';
++ 
++  if (opt_replace) 
++    x[i].middle.len=0;
++  else {
++    if (!stralloc_copys(&x[i].middle,":")) nomem();
++    if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
++    for (j = 0;j < x[i].middle.len;++j)
++      if (x[i].middle.s[j] == ' ')
++        x[i].middle.s[j] = '-';
++  }
+ }
+ int main(int argc,char **argv)
+@@ -69,7 +74,7 @@
+   int j;
+   int r;
+-  while ((opt = getopt(argc,argv,"c:l:")) != opteof)
++  while ((opt = getopt(argc,argv,"c:l:r")) != opteof)
+     switch(opt) {
+       case 'c':
+       scan_ulong(optarg,&u);
+@@ -83,8 +88,11 @@
+       if (u > 1000000) u = 1000000;
+       xmax = u;
+       break;
++      case 'r':
++      opt_replace = 1;          
++      break;
+       default:
+-      strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ]");
++      strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ] [-r]");
+     }
+   x = (struct line *) alloc(xmax * sizeof(struct line));
+@@ -140,8 +148,13 @@
+       else if (r == 1) {
+         if (dns_name_packet(&x[i].middle,x[i].dt.packet,x[i].dt.packetlen) == -1)
+           errout(i);
+-        if (x[i].middle.len)
+-          if (!stralloc_cats(&x[i].left,"=")) nomem();
++        if (x[i].middle.len) {
++          if (opt_replace) {
++            if (!stralloc_copys(&x[i].left, "")) nomem();
++          } else {
++            if (!stralloc_cats(&x[i].left, "=")) nomem();
++          }
++        }
+         x[i].flagactive = 0;
+         --numactive;
+       }
diff --git a/net/djbdns/patches/300-bugfix1-dempsky.patch b/net/djbdns/patches/300-bugfix1-dempsky.patch
new file mode 100644 (file)
index 0000000..2d616af
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/response.c.orig  2009-02-24 21:04:06.000000000 -0800
++++ b/response.c       2009-02-24 21:04:25.000000000 -0800
+@@ -34,7 +34,7 @@
+         uint16_pack_big(buf,49152 + name_ptr[i]);
+         return response_addbytes(buf,2);
+       }
+-    if (dlen <= 128)
++    if ((dlen <= 128) && (response_len < 16384))
+       if (name_num < NAMES) {
+       byte_copy(name[name_num],dlen,d);
+       name_ptr[name_num] = response_len;
diff --git a/net/djbdns/patches/310-bugfix2-merge-outgoing-requests.patch b/net/djbdns/patches/310-bugfix2-merge-outgoing-requests.patch
new file mode 100644 (file)
index 0000000..a0391ff
--- /dev/null
@@ -0,0 +1,349 @@
+diff --git a/Makefile b/Makefile
+index 1429643..bc047c0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -318,11 +318,11 @@ stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+       ./compile dns_txt.c
+ dnscache: \
+-load dnscache.o droproot.o okclient.o log.o cache.o query.o \
++load dnscache.o droproot.o okclient.o log.o cache.o query.o qmerge.o \
+ response.o dd.o roots.o iopause.o prot.o dns.a env.a alloc.a buffer.a \
+ libtai.a unix.a byte.a socket.lib
+       ./load dnscache droproot.o okclient.o log.o cache.o \
+-      query.o response.o dd.o roots.o iopause.o prot.o dns.a \
++      query.o qmerge.o response.o dd.o roots.o iopause.o prot.o dns.a \
+       env.a alloc.a buffer.a libtai.a unix.a byte.a  `cat \
+       socket.lib`
+@@ -343,7 +343,7 @@ compile dnscache.c env.h exit.h scan.h strerr.h error.h ip4.h \
+ uint16.h uint64.h socket.h uint16.h dns.h stralloc.h gen_alloc.h \
+ iopause.h taia.h tai.h uint64.h taia.h taia.h byte.h roots.h fmt.h \
+ iopause.h query.h dns.h uint32.h alloc.h response.h uint32.h cache.h \
+-uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h
++uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h maxclient.h
+       ./compile dnscache.c
+ dnsfilter: \
+@@ -687,11 +687,16 @@ qlog.o: \
+ compile qlog.c buffer.h qlog.h uint16.h
+       ./compile qlog.c
++qmerge.o: \
++compile qmerge.c qmerge.h dns.h stralloc.h gen_alloc.h iopause.h \
++taia.h tai.h uint64.h log.h maxclient.h
++      ./compile qmerge.c
++
+ query.o: \
+ compile query.c error.h roots.h log.h uint64.h case.h cache.h \
+ uint32.h uint64.h byte.h dns.h stralloc.h gen_alloc.h iopause.h \
+ taia.h tai.h uint64.h taia.h uint64.h uint32.h uint16.h dd.h alloc.h \
+-response.h uint32.h query.h dns.h uint32.h
++response.h uint32.h query.h dns.h uint32.h qmerge.h
+       ./compile query.c
+ random-ip: \
+diff --git a/dnscache.c b/dnscache.c
+index 8c899a3..5ccb16a 100644
+--- a/dnscache.c
++++ b/dnscache.c
+@@ -22,6 +22,7 @@
+ #include "log.h"
+ #include "okclient.h"
+ #include "droproot.h"
++#include "maxclient.h"
+ static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2])
+ {
+@@ -54,7 +55,6 @@ uint64 numqueries = 0;
+ static int udp53;
+-#define MAXUDP 200
+ static struct udpclient {
+   struct query q;
+   struct taia start;
+@@ -131,7 +131,6 @@ void u_new(void)
+ static int tcp53;
+-#define MAXTCP 20
+ struct tcpclient {
+   struct query q;
+   struct taia start;
+diff --git a/log.c b/log.c
+index c43e8b0..b8cd7ce 100644
+--- a/log.c
++++ b/log.c
+@@ -150,6 +150,13 @@ void log_tx(const char *q,const char qtype[2],const char *control,const char ser
+   line();
+ }
++void log_tx_piggyback(const char *q, const char qtype[2], const char *control)
++{
++  string("txpb ");
++  logtype(qtype); space(); name(q); space(); name(control);
++  line();
++}
++
+ void log_cachedanswer(const char *q,const char type[2])
+ {
+   string("cached "); logtype(type); space();
+diff --git a/log.h b/log.h
+index fe62fa3..d9a829b 100644
+--- a/log.h
++++ b/log.h
+@@ -18,6 +18,7 @@ extern void log_cachednxdomain(const char *);
+ extern void log_cachedns(const char *,const char *);
+ extern void log_tx(const char *,const char *,const char *,const char *,unsigned int);
++extern void log_tx_piggyback(const char *,const char *,const char *);
+ extern void log_nxdomain(const char *,const char *,unsigned int);
+ extern void log_nodata(const char *,const char *,const char *,unsigned int);
+diff --git a/maxclient.h b/maxclient.h
+new file mode 100644
+index 0000000..e52fcd1
+--- /dev/null
++++ b/maxclient.h
+@@ -0,0 +1,7 @@
++#ifndef MAXCLIENT_H
++#define MAXCLIENT_H
++
++#define MAXUDP 200
++#define MAXTCP 20
++
++#endif /* MAXCLIENT_H */
+diff --git a/qmerge.c b/qmerge.c
+new file mode 100644
+index 0000000..7c92299
+--- /dev/null
++++ b/qmerge.c
+@@ -0,0 +1,115 @@
++#include "qmerge.h"
++#include "byte.h"
++#include "log.h"
++#include "maxclient.h"
++
++#define QMERGE_MAX (MAXUDP+MAXTCP)
++struct qmerge inprogress[QMERGE_MAX];
++
++static
++int qmerge_key_init(struct qmerge_key *qmk, const char *q, const char qtype[2],
++    const char *control)
++{
++  if (!dns_domain_copy(&qmk->q, q)) return 0;
++  byte_copy(qmk->qtype, 2, qtype);
++  if (!dns_domain_copy(&qmk->control, control)) return 0;
++  return 1;
++}
++
++static
++int qmerge_key_equal(struct qmerge_key *a, struct qmerge_key *b)
++{
++  return
++    byte_equal(a->qtype, 2, b->qtype) &&
++    dns_domain_equal(a->q, b->q) &&
++    dns_domain_equal(a->control, b->control);
++}
++
++static
++void qmerge_key_free(struct qmerge_key *qmk)
++{
++  dns_domain_free(&qmk->q);
++  dns_domain_free(&qmk->control);
++}
++
++void qmerge_free(struct qmerge **x)
++{
++  struct qmerge *qm;
++
++  qm = *x;
++  *x = 0;
++  if (!qm || !qm->active) return;
++
++  qm->active--;
++  if (!qm->active) {
++    qmerge_key_free(&qm->key);
++    dns_transmit_free(&qm->dt);
++  }
++}
++
++int qmerge_start(struct qmerge **qm, const char servers[64], int flagrecursive,
++    const char *q, const char qtype[2], const char localip[4],
++    const char *control)
++{
++  struct qmerge_key k;
++  int i;
++  int r;
++
++  qmerge_free(qm);
++
++  byte_zero(&k, sizeof k);
++  if (!qmerge_key_init(&k, q, qtype, control)) return -1;
++  for (i = 0; i < QMERGE_MAX; i++) {
++    if (!inprogress[i].active) continue;
++    if (!qmerge_key_equal(&k, &inprogress[i].key)) continue;
++    log_tx_piggyback(q, qtype, control);
++    inprogress[i].active++;
++    *qm = &inprogress[i];
++    qmerge_key_free(&k);
++    return 0;
++  }
++
++  for (i = 0; i < QMERGE_MAX; i++)
++    if (!inprogress[i].active)
++      break;
++  if (i == QMERGE_MAX) return -1;
++
++  log_tx(q, qtype, control, servers, 0);
++  r = dns_transmit_start(&inprogress[i].dt, servers, flagrecursive, q, qtype, localip);
++  if (r == -1) { qmerge_key_free(&k); return -1; }
++  inprogress[i].active++;
++  inprogress[i].state = 0;
++  qmerge_key_free(&inprogress[i].key);
++  byte_copy(&inprogress[i].key, sizeof k, &k);
++  *qm = &inprogress[i];
++  return 0;
++}
++
++void qmerge_io(struct qmerge *qm, iopause_fd *io, struct taia *deadline)
++{
++  if (qm->state == 0) {
++    dns_transmit_io(&qm->dt, io, deadline);
++    qm->state = 1;
++  }
++  else {
++    io->fd = -1;
++    io->events = 0;
++  }
++}
++
++int qmerge_get(struct qmerge **x, const iopause_fd *io, const struct taia *when)
++{
++  int r;
++  struct qmerge *qm;
++
++  qm = *x;
++  if (qm->state == -1) return -1; /* previous error */
++  if (qm->state == 0) return 0; /* no packet */
++  if (qm->state == 2) return 1; /* already got packet */
++
++  r = dns_transmit_get(&qm->dt, io, when);
++  if (r == -1) { qm->state = -1; return -1; } /* error */
++  if (r == 0) { qm->state = 0; return 0; } /* must wait for i/o */
++  if (r == 1) { qm->state = 2; return 1; } /* got packet */
++  return -1; /* bug */
++}
+diff --git a/qmerge.h b/qmerge.h
+new file mode 100644
+index 0000000..9a58157
+--- /dev/null
++++ b/qmerge.h
+@@ -0,0 +1,24 @@
++#ifndef QMERGE_H
++#define QMERGE_H
++
++#include "dns.h"
++
++struct qmerge_key {
++  char *q;
++  char qtype[2];
++  char *control;
++};
++
++struct qmerge {
++  int active;
++  struct qmerge_key key;
++  struct dns_transmit dt;
++  int state; /* -1 = error, 0 = need io, 1 = need get, 2 = got packet */
++};
++
++extern int qmerge_start(struct qmerge **,const char *,int,const char *,const char *,const char *,const char *);
++extern void qmerge_io(struct qmerge *,iopause_fd *,struct taia *);
++extern int qmerge_get(struct qmerge **,const iopause_fd *,const struct taia *);
++extern void qmerge_free(struct qmerge **);
++
++#endif /* QMERGE_H */
+diff --git a/query.c b/query.c
+index 46cdc00..f091fdd 100644
+--- a/query.c
++++ b/query.c
+@@ -81,7 +81,7 @@ static void cleanup(struct query *z)
+   int j;
+   int k;
+-  dns_transmit_free(&z->dt);
++  qmerge_free(&z->qm);
+   for (j = 0;j < QUERY_MAXALIAS;++j)
+     dns_domain_free(&z->alias[j]);
+   for (j = 0;j < QUERY_MAXLEVEL;++j) {
+@@ -429,14 +429,8 @@ static int doit(struct query *z,int state)
+   if (j == 64) goto SERVFAIL;
+   dns_sortip(z->servers[z->level],64);
+-  if (z->level) {
+-    log_tx(z->name[z->level],DNS_T_A,z->control[z->level],z->servers[z->level],z->level);
+-    if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],DNS_T_A,z->localip) == -1) goto DIE;
+-  }
+-  else {
+-    log_tx(z->name[0],z->type,z->control[0],z->servers[0],0);
+-    if (dns_transmit_start(&z->dt,z->servers[0],flagforwardonly,z->name[0],z->type,z->localip) == -1) goto DIE;
+-  }
++  dtype = z->level ? DNS_T_A : z->type;
++  if (qmerge_start(&z->qm,z->servers[z->level],flagforwardonly,z->name[z->level],dtype,z->localip,z->control[z->level]) == -1) goto DIE;
+   return 0;
+@@ -450,10 +444,10 @@ static int doit(struct query *z,int state)
+   HAVEPACKET:
+   if (++z->loop == 100) goto DIE;
+-  buf = z->dt.packet;
+-  len = z->dt.packetlen;
++  buf = z->qm->dt.packet;
++  len = z->qm->dt.packetlen;
+-  whichserver = z->dt.servers + 4 * z->dt.curserver;
++  whichserver = z->qm->dt.servers + 4 * z->qm->dt.curserver;
+   control = z->control[z->level];
+   d = z->name[z->level];
+   dtype = z->level ? DNS_T_A : z->type;
+@@ -836,7 +830,7 @@ int query_start(struct query *z,char *dn,char type[2],char class[2],char localip
+ int query_get(struct query *z,iopause_fd *x,struct taia *stamp)
+ {
+-  switch(dns_transmit_get(&z->dt,x,stamp)) {
++  switch(qmerge_get(&z->qm,x,stamp)) {
+     case 1:
+       return doit(z,1);
+     case -1:
+@@ -847,5 +841,5 @@ int query_get(struct query *z,iopause_fd *x,struct taia *stamp)
+ void query_io(struct query *z,iopause_fd *x,struct taia *deadline)
+ {
+-  dns_transmit_io(&z->dt,x,deadline);
++  qmerge_io(z->qm,x,deadline);
+ }
+diff --git a/query.h b/query.h
+index eff68b2..06feab4 100644
+--- a/query.h
++++ b/query.h
+@@ -1,7 +1,7 @@
+ #ifndef QUERY_H
+ #define QUERY_H
+-#include "dns.h"
++#include "qmerge.h"
+ #include "uint32.h"
+ #define QUERY_MAXLEVEL 5
+@@ -20,7 +20,7 @@ struct query {
+   char localip[4];
+   char type[2];
+   char class[2];
+-  struct dns_transmit dt;
++  struct qmerge *qm;
+ } ;
+ extern int query_start(struct query *,char *,char *,char *,char *);
diff --git a/net/djbdns/patches/320-bugfix3-cache-soa-records.patch b/net/djbdns/patches/320-bugfix3-cache-soa-records.patch
new file mode 100644 (file)
index 0000000..8457039
--- /dev/null
@@ -0,0 +1,70 @@
+diff --git a/query.c b/query.c
+index 46cdc00..4574e97 100644
+--- a/query.c
++++ b/query.c
+@@ -319,6 +319,29 @@ static int doit(struct query *z,int state)
+       }
+     }
++    if (typematch(DNS_T_SOA,dtype)) {
++      byte_copy(key,2,DNS_T_SOA);
++      cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
++      if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
++        log_cachedanswer(d,DNS_T_SOA);
++        if (!rqa(z)) goto DIE;
++        pos = 0;
++        while (pos = dns_packet_copy(cached,cachedlen,pos,misc,20)) {
++          pos = dns_packet_getname(cached,cachedlen,pos,&t2);
++          if (!pos) break;
++          pos = dns_packet_getname(cached,cachedlen,pos,&t3);
++          if (!pos) break;
++          if (!response_rstart(d,DNS_T_SOA,ttl)) goto DIE;
++          if (!response_addname(t2)) goto DIE;
++          if (!response_addname(t3)) goto DIE;
++          if (!response_addbytes(misc,20)) goto DIE;
++          response_rfinish(RESPONSE_ANSWER);
++        }
++        cleanup(z);
++        return 1;
++      }
++    }
++
+     if (typematch(DNS_T_A,dtype)) {
+       byte_copy(key,2,DNS_T_A);
+       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+@@ -351,7 +374,7 @@ static int doit(struct query *z,int state)
+       }
+     }
+-    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
++    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_SOA,dtype)) {
+       byte_copy(key,2,dtype);
+       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
+@@ -585,15 +608,24 @@ static int doit(struct query *z,int state)
+     else if (byte_equal(type,2,DNS_T_AXFR))
+       ;
+     else if (byte_equal(type,2,DNS_T_SOA)) {
++      int non_authority = 0;
++      save_start();
+       while (i < j) {
+         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
+         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
+         pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE;
+         pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE;
+-        if (records[i] < posauthority)
++        if (records[i] < posauthority) {
+           log_rrsoa(whichserver,t1,t2,t3,misc,ttl);
++          save_data(misc,20);
++          save_data(t2,dns_domain_length(t2));
++          save_data(t3,dns_domain_length(t3));
++          non_authority++;
++        }
+         ++i;
+       }
++      if (non_authority)
++        save_finish(DNS_T_SOA,t1,ttl);
+     }
+     else if (byte_equal(type,2,DNS_T_CNAME)) {
+       pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE;
+