Source code upload 2.0alpha master 2.0_alpha submit/master/20120920.151046
authorSeungyoun Ju <sy39.ju@samsung.com>
Tue, 21 Aug 2012 09:23:32 +0000 (18:23 +0900)
committerSeungyoun Ju <sy39.ju@samsung.com>
Tue, 21 Aug 2012 09:23:32 +0000 (18:23 +0900)
107 files changed:
Android.mk [new file with mode: 0644]
CHANGELOG [new file with mode: 0644]
CHANGELOG.archive [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
COPYING [new file with mode: 0644]
COPYING-v3 [new file with mode: 0644]
FAQ [new file with mode: 0644]
Makefile [new file with mode: 0644]
bld/Android.mk [new file with mode: 0644]
bld/install-man [new file with mode: 0755]
bld/install-mo [new file with mode: 0755]
bld/pkg-wrapper [new file with mode: 0755]
contrib/CPE-WAN/README [new file with mode: 0644]
contrib/MacOSX-launchd/launchd-README.txt [new file with mode: 0644]
contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist [new file with mode: 0644]
contrib/Solaris10/README [new file with mode: 0644]
contrib/Solaris10/README-sparc [new file with mode: 0644]
contrib/Solaris10/README.create_package [new file with mode: 0644]
contrib/Solaris10/create_package [new file with mode: 0644]
contrib/Solaris10/dnsmasq.xml [new file with mode: 0644]
contrib/Suse/README [new file with mode: 0644]
contrib/Suse/README.susefirewall [new file with mode: 0644]
contrib/Suse/dnsmasq-SuSE.patch [new file with mode: 0644]
contrib/Suse/dnsmasq-suse.spec [new file with mode: 0644]
contrib/Suse/rc.dnsmasq-suse [new file with mode: 0644]
contrib/dns-loc/README [new file with mode: 0644]
contrib/dns-loc/dnsmasq2-loc-rfc1876.patch [new file with mode: 0644]
contrib/dnslist/dhcp.css [new file with mode: 0644]
contrib/dnslist/dnslist.pl [new file with mode: 0755]
contrib/dnslist/dnslist.tt2 [new file with mode: 0644]
contrib/dnsmasq_MacOSX-pre10.4/DNSmasq [new file with mode: 0755]
contrib/dnsmasq_MacOSX-pre10.4/README.rtf [new file with mode: 0644]
contrib/dnsmasq_MacOSX-pre10.4/StartupParameters.plist [new file with mode: 0644]
contrib/dynamic-dnsmasq/dynamic-dnsmasq.pl [new file with mode: 0755]
contrib/lease-access/README [new file with mode: 0644]
contrib/lease-access/lease.access.patch [new file with mode: 0644]
contrib/openvpn/README [new file with mode: 0644]
contrib/openvpn/dhclient-enter-hooks [new file with mode: 0644]
contrib/openvpn/dnsmasq.patch [new file with mode: 0644]
contrib/port-forward/dnsmasq-portforward [new file with mode: 0755]
contrib/port-forward/portforward [new file with mode: 0644]
contrib/slackware-dnsmasq/dnsmasq.SlackBuild [new file with mode: 0755]
contrib/slackware-dnsmasq/dnsmasq.leasedir.diff.gz [new file with mode: 0644]
contrib/slackware-dnsmasq/doinst.sh.gz [new file with mode: 0644]
contrib/slackware-dnsmasq/rc.dnsmasq.gz [new file with mode: 0644]
contrib/slackware-dnsmasq/slack-desc [new file with mode: 0644]
contrib/static-arp/static-arp [new file with mode: 0644]
contrib/try-all-ns/README [new file with mode: 0644]
contrib/try-all-ns/README-2.47 [new file with mode: 0644]
contrib/try-all-ns/dnsmasq-2.35-try-all-ns.patch [new file with mode: 0644]
contrib/try-all-ns/dnsmasq-2.47_no_nxdomain_until_end.patch [new file with mode: 0644]
contrib/webmin/README [new file with mode: 0644]
contrib/webmin/dnsmasq.wbm [new file with mode: 0644]
contrib/wrt/Makefile [new file with mode: 0644]
contrib/wrt/README [new file with mode: 0644]
contrib/wrt/dhcp_lease_time.c [new file with mode: 0644]
contrib/wrt/dhcp_release.c [new file with mode: 0644]
contrib/wrt/lease_update.sh [new file with mode: 0755]
dbus/DBus-interface [new file with mode: 0644]
dbus/dnsmasq.conf [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/dnsmasq.install.in [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/source/format [new file with mode: 0644]
dnsmasq.conf.example [new file with mode: 0644]
doc.html [new file with mode: 0644]
logo/README [new file with mode: 0644]
logo/favicon.ico [new file with mode: 0644]
logo/icon.png [new file with mode: 0644]
logo/icon.svg [new file with mode: 0644]
man/dnsmasq.8 [new file with mode: 0644]
man/es/dnsmasq.8 [new file with mode: 0644]
man/fr/dnsmasq.8 [new file with mode: 0644]
packaging/dnsmasq.spec [new file with mode: 0644]
po/de.po [new file with mode: 0644]
po/es.po [new file with mode: 0644]
po/fi.po [new file with mode: 0644]
po/fr.po [new file with mode: 0644]
po/id.po [new file with mode: 0644]
po/it.po [new file with mode: 0644]
po/no.po [new file with mode: 0644]
po/pl.po [new file with mode: 0644]
po/pt_BR.po [new file with mode: 0644]
po/ro.po [new file with mode: 0644]
setup.html [new file with mode: 0644]
src/bpf.c [new file with mode: 0644]
src/cache.c [new file with mode: 0644]
src/config.h [new file with mode: 0644]
src/dbus.c [new file with mode: 0644]
src/dhcp.c [new file with mode: 0644]
src/dhcp_protocol.h [new file with mode: 0644]
src/dns_protocol.h [new file with mode: 0644]
src/dnsmasq.c [new file with mode: 0644]
src/dnsmasq.h [new file with mode: 0644]
src/forward.c [new file with mode: 0644]
src/helper.c [new file with mode: 0644]
src/lease.c [new file with mode: 0644]
src/log.c [new file with mode: 0644]
src/netlink.c [new file with mode: 0644]
src/network.c [new file with mode: 0644]
src/option.c [new file with mode: 0644]
src/rfc1035.c [new file with mode: 0644]
src/rfc2131.c [new file with mode: 0644]
src/tftp.c [new file with mode: 0644]
src/util.c [new file with mode: 0644]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..ba187a6
--- /dev/null
@@ -0,0 +1,3 @@
+ifneq ($(TARGET_SIMULATOR),true)
+include $(call all-subdir-makefiles)
+endif
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..fb15e3d
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,873 @@
+version 2.57
+           Add patches to allow build under Android.
+
+           Provide our own header for the DNS protocol, rather than
+           relying on arpa/nameser.h. This has proved more or less
+           defective over the years and the final straw is that it's
+           effectively empty on Android.
+
+           Fix regression in 2.56 which caused hex constants in
+           configuration to be rejected if they contain the '*'
+           wildcard.
+
+           Correct wrong casts of arguments to ctype.h functions,
+           isdigit(), isxdigit() etc. Thanks to Matthias Andree for
+           spotting this.
+
+           Allow build with IDN support independently from i18n. 
+            IDN support continues to be included automatically 
+           when i18n is included. 
+            'make COPTS=-DHAVE_IDN' is the magic incantation. 
+
+           Modify check on extraneous command line junk (added in
+           2.56) so that it doesn't complain about extra _empty_ 
+           arguments. Otherwise this breaks libvirt.
+
+
+version 2.56
+            Add a patch to allow dnsmasq to get interface names right in a
+            Solaris zone. Thanks to Dj Padzensky for this.
+
+           Improve data-type parsing heuristics so that
+           --dhcp-option=option:domain-search,. 
+           treats the value as a string and not an IP address.
+           Thanks to Clemens Fischer for spotting that.
+
+           Add IPv6 support to the TFTP server. Many thanks to Jan 
+           'RedBully' Seiffert for the patches.
+           
+           Log DNS queries at level LOG_INFO, rather then
+           LOG_DEBUG. This makes things consistent with DHCP
+           logging. Thanks to Adam Pribyl for spotting the problem.
+
+            Ensure that dnsmasq terminates cleanly when using
+            --syslog-async even if it cannot make a connection to the
+            syslogd.
+
+           Add --add-mac option. This is to support currently 
+           experimental DNS filtering facilities. Thanks to Benjamin
+           Petrin for the orignal patch. 
+
+           Fix bug which meant that tags were ignored in dhcp-range
+           configuration specifying PXE-proxy service. Thanks to
+           Cristiano Cumer for spotting this.
+
+           Raise an error if there is extra junk, not part of an
+           option, on the command line.
+
+           Flag a couple of log messages in cache.c as coming from
+           the DHCP subsystem. Thanks to Olaf Westrik for the patch.
+
+           Omit timestamps from logs when a) logging to stderr and 
+           b) --keep-in-forground is set. The logging facility on the
+           other end of stderr can be assumned to supply them. Thanks
+           to John Hallam for the patch.
+
+           Don't complain about strings longer than 255 characters in
+           --txt-record, just split the long strings into 255
+           character chunks instead.
+
+           Fix crash on double-free. This bug can only happen when
+           dhcp-script is in use and then only in rare circumstances
+           triggered by high DHCP transaction rate and a slow
+           script. Thanks to Ferenc Wagner for finding the problem.
+
+           Only log that a file has been sent by TFTP after the
+           transfer has completed succesfully. 
+
+           A good suggestion from Ferenc Wagner: extend
+           the --domain option to allow this sort of thing:
+            --domain=thekelleys.org.uk,192.168.0.0/24,local
+           which automatically creates
+           --local=/thekelleys.org.uk/
+           --local=/0.168.192.in-addr.arpa/ 
+
+           Tighten up syntax checking of hex contants in the config
+           file.  Thanks to Fred Damen for spotting this.
+
+           Add dnsmasq logo/icon, contributed by Justin Swift. Many
+           thanks for that.
+
+           Never cache DNS replies which have the 'cd' bit set, or
+           which result from queries forwarded with the 'cd' bit
+           set. The 'cd' bit instructs a DNSSEC validating server
+           upstream to ignore signature failures and return replies
+           anyway. Without this change it's possible to pollute the
+           dnsmasq cache with bad data by making a query with the
+           'cd' bit set and subsequent queries would return this data
+           without its being marked as suspect. Thanks to Anders
+           Kaseorg for pointing out this problem.
+
+           Add --proxy-dnssec flag, for compliance with RFC
+           4035. Dnsmasq will now clear the 'ad' bit in answers returned
+           from upstream validating nameservers unless this option is
+           set.
+
+           Allow a filename of "-" for --conf-file to read
+           stdin. Suggestion from Timothy Redaelli.
+
+           Rotate the order of SRV records in replies, to provide
+           round-robin load balancing when all the priorities are
+           equal. Thanks to Peter McKinney for the suggestion. 
+
+           Edit
+           contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist 
+           so that it doesn't log all queries to a file by
+           default. Thanks again to Peter McKinney.    
+
+           By default, setting an IPv4 address for a domain but not
+           an IPv6 address causes dnsmasq to return
+           an NODATA reply for IPv6 (or vice-versa). So
+           --address=/google.com/1.2.3.4 stops IPv6 queries for
+           *google.com from being forwarded. Make it possible to
+           override this behaviour by defining the sematics if the
+           same domain appears in  both --server and --address.
+           In that case, the --address has priority for the address
+           family in which is appears, but the --server has priority
+           of the address family which doesn't appear in --adddress  
+           So:
+           --address=/google.com/1.2.3.4
+           --server=/google.com/#
+           will return 1.2.3.4 for IPv4 queries for *.google.com but
+           forward IPv6 queries to the normal upstream nameserver.
+           Similarly when setting an IPv6 address
+           only this will allow forwarding of IPv4 queries. Thanks to
+           William for pointing out the need for this.
+
+           Allow more than one --dhcp-optsfile and --dhcp-hostsfile
+           and make them understand directories as arguments in the
+           same way as --addn-hosts. Suggestion from John Hanks. 
+
+           Ignore rebinding requests for leases we don't know
+           about. Rebind is broadcast, so we might get to overhear a
+           request meant for another DHCP server. NAKing this is
+           wrong. Thanks to Brad D'Hondt for assistance with this.
+
+            Fix cosmetic bug which produced strange output when
+            dumping cache statistics with some configurations. Thanks
+            to Fedor Kozhevnikov for spotting this.
+
+
+version 2.55
+            Fix crash when /etc/ethers is in use. Thanks to 
+           Gianluigi Tiesi for finding this.
+
+           Fix crash in netlink_multicast(). Thanks to Arno Wald for
+           finding this one.
+
+           Allow the empty domain "." in dhcp domain-search (119)
+           options. 
+
+
+version 2.54
+            There is no version 2.54 to avoid confusion with 2.53,
+            which incorrectly identifies itself as 2.54.
+
+
+version 2.53
+            Fix failure to compile on Debian/kFreeBSD. Thanks to 
+           Axel Beckert and Petr Salinger.
+
+           Fix code to avoid scary strict-aliasing warnings
+           generated by gcc 4.4.
+           
+           Added FAQ entry warning about DHCP failures with Vista
+           when firewalls block 255.255.255.255.
+           
+           Fixed bug which caused bad things to happen if a 
+           resolv.conf file which exists is subsequently removed.
+           Thanks to Nikolai Saoukh for the patch.
+
+           Rationalised the DHCP tag system. Every configuration item
+           which can set a tag does so by adding "set:<tag>" and
+           every configuration item which is conditional on a tag is
+           made so by "tag:<tag>". The NOT operator changes to '!',
+           which is a bit more intuitive too. Dhcp-host directives
+           can set more than one tag now. The old '#' NOT, 
+           "net:" prefix and no-prefixes are still honoured, so 
+           no existing config file needs to be changed, but 
+           the documentation and new-style config files should be 
+           much less confusing. 
+
+           Added --tag-if to allow boolean operations on tags. 
+           This allows complicated logic to be clearer and more 
+           general. A great suggestion from Richard Voigt. 
+
+           Add broadcast/unicast information to DHCP logging.
+
+           Allow --dhcp-broadcast to be unconditional.
+
+           Fixed incorrect behaviour with NOT <tag> conditionals in
+           dhcp-options. Thanks to Max Turkewitz for assistance
+           finding this.
+
+           If we send vendor-class encapsulated options based on the
+           vendor-class supplied by the client, and no explicit 
+           vendor-class option is given, echo back the vendor-class
+           from the client.
+           Fix bug which stopped dnsmasq from matching both a
+           circuitid and a remoteid. Thanks to Ignacio Bravo for
+           finding this.
+
+           Add --dhcp-proxy, which makes it possible to configure
+           dnsmasq to use a DHCP relay agent as a full proxy, with
+           all DHCP messages passing through the proxy. This is
+           useful if the relay adds extra information to the packets
+           it forwards, but cannot be configured with the RFC 5107 
+           server-override option.
+
+           Added interface:<iface name> part to dhcp-range. The
+           semantics of this are very odd at first sight, but it
+           allows a single line  of the form
+               dhcp-range=interface:virt0,192.168.0.4,192.168.0.200
+           to be added to dnsmasq configuration which then supplies
+           DHCP and DNS services to that interface, without affecting
+           what services are supplied to other interfaces and 
+           irrespective of the existance or lack of 
+                interface=<interface> 
+            lines elsewhere in the dnsmasq configuration. The idea is
+           that such a line can be added automatically by libvirt
+           or equivalent systems, without disturbing any manual
+           configuration.
+
+           Similarly to the above, allow --enable-tftp=<interface>
+
+           Allow a TFTP root to be set separately for requests via
+           different interfaces, --tftp-root=<path>,<interface>             
+
+           Correctly handle and log clashes between CNAMES and 
+           DNS names being given to DHCP leases. This fixes a bug 
+           which caused nonsense IP addresses to be logged. Thanks to 
+            Sergei Zhirikov for finding and analysing the problem.
+
+           Tweak flush_log so as to avoid leaving the log
+           file in non-blocking mode. O_NONBLOCK is a property of the
+           file, not the process/descriptor.
+
+           Fix contrib/Solaris10/create_package
+           (/usr/man -> /usr/share/man) Thanks to Vita Batrla.
+
+           Fix a problem where, if a client got a lease, then went
+           to another subnet and got another lease, then moved back,
+           it couldn't resume the old lease, but would instead get 
+           a new address. Thanks to Leonardo Rodrigues for spotting
+           this and testing the fix.
+           
+           Fix weird bug which sometimes omitted certain characters
+           from the start of quoted strings in dhcp-options. Thanks
+           to Dayton Turner for spotting the problem.
+
+           Add facility to redirect some domains to the standard
+           upstream servers: this allows something like 
+           --server=/google.com/1.2.3.4 --server=/www.google.com/#
+           which will send queries for *.google.com to 1.2.3.4,
+           except *www.google.com which will be forwarded as usual.
+           Thanks to AJ Weber for prompting this addition.
+           Improve the hash-algorithm used to generate IP addresses
+           from MAC addresses during initial DHCP address
+           allocation. This improves performance when large numbers
+           of hosts with similar MAC addresses all try and get an IP
+           address at the same time. Thanks to Paul Smith for his
+           work on this.
+
+           Tweak DHCP code so that --bridge-interface can be used to
+           select which IP alias of an interface should be used for
+           DHCP purposes on Linux. If eth0 has an alias eth0:dhcp
+           then adding  --bridge-interface=eth0:dhcp,eth0 will use 
+           the address of eth0:dhcp to determine the correct subnet 
+           for DHCP address allocation. Thanks to Pawel Golaszewski 
+            for prompting this and Eric Cooper for further testing.
+
+           Add --dhcp-generate-names. Suggestion by Ferenc Wagner.
+
+           Tweak DNS server selection algorithm when there is more
+           than one server available for a domain, eg.
+            --server=/mydomain/1.1.1.1
+            --server=/mydomain/2.2.2.2
+           Thanks to Alberto Cuesta-Canada for spotting a weakness
+           here.
+
+           Add --max-ttl. Thanks to Fredrik Ringertz for the patch.
+
+           Allow --log-facility=- to force all logging to
+           stderr. Suggestion from Clemens Fischer.
+
+           Fix regression which caused configuration like
+           --address=/.domain.com/1.2.3.4 to be rejected. The dot to the 
+           left of the domain has been implied and not required for a
+           long time, but it should be accepted for backward
+           compatibility. Thanks to Andrew Burcin for spotting this.
+    
+            Add --rebind-domain-ok and --rebind-localhost-ok.
+           Suggestion from Clemens Fischer.
+
+           Log replies to queries of type TXT, when --log-queries 
+           is set.
+
+           Fix compiler warnings when compiled with -DNO_DHCP. Thanks
+           to Shantanu Gadgil for the patch.
+
+            Updated French translation. Thanks to Gildas Le Nadan.
+
+           Updated Polish translation. Thanks to Jan Psota.
+
+           Updated German translation. Thanks to Matthias Andree.
+
+           Added contrib/static-arp, thanks to Darren Hoo.
+           Fix corruption of the domain when a name from /etc/hosts
+           overrides one supplied by a DHCP client. Thanks to Fedor
+           Kozhevnikov for spotting the problem.
+
+            Updated Spanish translation. Thanks to Chris Chatham.
+
+
+version 2.52
+            Work around a Linux kernel bug which insists that the 
+           length of the option passed to setsockopt must be at least
+            sizeof(int) bytes, even if we're calling SO_BINDTODEVICE
+            and the device name is "lo".  Note that this is fixed 
+           in kernel 2.6.31, but the workaround is harmless and 
+           allows earlier kernels to be used. Also fix dnsmasq 
+           bug which reported the wrong address when this failed. 
+           Thanks to Fedor for finding this.
+
+           The API for IPv6 PKTINFO changed around Linux kernel
+           2.6.14. Workaround the case where dnsmasq is compiled
+           against newer headers, but then run on an old kernel:
+           necessary for some *WRT distros.
+
+           Re-read the set of network interfaces when re-loading
+           /etc/resolv.conf if --bind-interfaces is not set. This
+           handles the case that loopback interfaces do not exist
+           when dnsmasq is first started.
+
+           Tweak the PXE code to support port 4011. This should
+           reduce broadcasts and make things more reliable when other
+           servers are around. It also improves inter-operability
+           with certain clients.
+
+           Make a pxe-service configuration with no filename or boot 
+           service type legal: this does a local boot. eg.
+           pxe-service=x86PC, "Local boot" 
+
+           Be more conservative in detecting "A for A"
+           queries. Dnsmasq checks if the name in a type=A query looks
+           like a dotted-quad IP address and answers the query itself
+           if so, rather than forwarding it. Previously dnsmasq
+           relied in the library function inet_addr() to convert
+           addresses, and that will accept some things which are
+           confusing in this context, like 1.2.3 or even just
+           1234. Now we only do A for A processing for four decimal
+           numbers delimited by dots.
+
+           A couple of tweaks to fix compilation on Solaris. Thanks
+           to Joel Macklow for help with this.
+
+           Another Solaris compilation tweak, needed for Solaris
+           2009.06. Thanks to Lee Essen for that.
+
+           Added extract packaging stuff from Lee Essen to 
+           contrib/Solaris10.
+          
+            Increased the default limit on number of leases to 1000
+            (from 150). This is mainly a defence against DoS attacks,
+            and for the average "one for two class C networks"
+            installation, IP address exhaustion does that just as
+            well. Making the limit greater than the number of IP
+            addresses available in such an installation removes a
+            surprise which otherwise can catch people out.
+
+           Removed extraneous trailing space in the value of the
+           DNSMASQ_TIME_REMAINING DNSMASQ_LEASE_LENGTH and
+           DNSMASQ_LEASE_EXPIRES environment variables. Thanks to
+           Gildas Le Nadan for spotting this.
+
+           Provide the network-id tags for a DHCP transaction to 
+           the lease-change script in the environment variable
+           DNSMASQ_TAGS. A good suggestion from Gildas Le Nadan.  
+
+           Add support for RFC3925 "Vendor-Identifying Vendor
+           Options". The syntax looks like this:  
+           --dhcp-option=vi-encap:<enterprise number>, .........
+
+           Add support to --dhcp-match to allow matching against
+           RFC3925 "Vendor-Identifying Vendor Classes". The syntax
+           looks like this:
+           --dhcp-match=tag,vi-encap<enterprise number>, <value>
+           
+           Add some application specific code to assist in
+           implementing the Broadband forum TR069 CPE-WAN
+           specification. The details are in contrib/CPE-WAN/README
+
+           Increase the default DNS packet size limit to 4096, as
+           recommended by RFC5625 section 4.4.3. This can be
+           reconfigured using --edns-packet-max if needed. Thanks to
+           Francis Dupont for pointing this out.
+
+           Rewrite query-ids even for TSIG signed packets, since
+           this is allowed by RFC5625 section 4.5.
+           
+           Use getopt_long by default on OS X. It has been supported
+           since version 10.3.0. Thanks to Arek Dreyer for spotting
+           this.
+
+           Added up-to-date startup configuration for MacOSX/launchd
+           in contrib/MacOSX-launchd. Thanks to Arek Dreyer for
+           providing this.
+
+           Fix link error when including Dbus but excluding DHCP. 
+           Thanks to Oschtan for the bug report.
+
+            Updated French translation. Thanks to Gildas Le Nadan.
+            Updated Polish translation. Thanks to Jan Psota.
+
+           Updated Spanish translation. Thanks to Chris Chatham.
+
+           Fixed confusion about domains, when looking up DHCP hosts
+           in /etc/hosts. This could cause spurious "Ignoring
+           domain..." messages. Thanks to Fedor Kozhevnikov for
+           finding and analysing the problem.
+
+           
+version 2.51
+            Add support for internationalised DNS. Non-ASCII characters
+            in domain names found in /etc/hosts, /etc/ethers and 
+           /etc/dnsmasq.conf will be correctly handled by translation to
+            punycode, as specified in RFC3490. This function is only
+            available if dnsmasq is compiled with internationalisation
+            support, and adds a dependency on GNU libidn. Without i18n
+            support, dnsmasq continues to be compilable with just
+            standard tools. Thanks to Yves Dorfsman for the
+            suggestion. 
+
+            Add two more environment variables for lease-change scripts:
+           First, DNSMASQ_SUPPLIED_HOSTNAME; this is set to the hostname
+           supplied by a client, even if the actual hostname used is
+           over-ridden by dhcp-host or dhcp-ignore-names directives.
+           Also DNSMASQ_RELAY_ADDRESS which gives the address of 
+            a DHCP relay, if used.
+           Suggestions from Michael Rack.
+
+           Fix regression which broke echo of relay-agent
+           options. Thanks to Michael Rack for spotting this.
+          
+            Don't treat option 67 as being interchangeable with
+            dhcp-boot parameters if it's specified as
+            dhcp-option-force.
+
+           Make the code to call scripts on lease-change compile-time
+           optional. It can be switched off by editing src/config.h
+           or building with "make COPTS=-DNO_SCRIPT".
+           Make the TFTP server cope with filenames from Windows/DOS
+           which use '\' as pathname separator. Thanks to Ralf for
+           the patch.
+
+           Updated Polish translation. Thanks to Jan Psota.
+           Warn if an IP address is duplicated in /etc/ethers. Thanks
+           to Felix Schwarz for pointing this out.
+
+           Teach --conf-dir to take an option list of file suffices
+           which will be ignored when scanning the directory. Useful
+           for backup files etc. Thanks to Helmut Hullen for the
+           suggestion. 
+
+           Add new DHCP option named tftpserver-address, which
+           corresponds to the third argument of dhcp-boot. This
+           allows the complete functionality of dhcp-boot to be
+           replicated with dhcp-option. Useful when using 
+           dhcp-optsfile.
+
+           Test which upstream nameserver to use every 10 seconds
+            or 50 queries and not just when a query times out and 
+            is retried. This should improve performance when there
+            is a slow nameserver in the list. Thanks to Joe for the
+            suggestion. 
+
+           Don't do any PXE processing, even for clients with the 
+           correct vendorclass, unless at least one pxe-prompt or 
+            pxe-service option is given. This stops dnsmasq 
+            interfering with proxy PXE subsystems when it is just 
+            the DHCP server. Thanks to Spencer Clark for spotting this.
+
+           Limit the blocksize used for TFTP transfers to a value
+           which avoids packet fragmentation, based on the MTU of the
+           local interface. Many netboot ROMs can't cope with
+           fragmented packets.
+
+           Honour dhcp-ignore configuration for PXE and proxy-PXE 
+           requests. Thanks to Niels Basjes for the bug report.
+
+            Updated French translation. Thanks to Gildas Le Nadan.
+
+
+version 2.50
+           Fix security problem which allowed any host permitted to 
+            do TFTP to possibly compromise dnsmasq by remote buffer 
+            overflow when TFTP enabled. Thanks to Core Security 
+           Technologies and Iván Arce, Pablo Hernán Jorge, Alejandro 
+           Pablo Rodriguez, Martín Coco, Alberto Soliño Testa and
+           Pablo Annetta. This problem has Bugtraq id: 36121 
+            and CVE: 2009-2957
+
+            Fix a problem which allowed a malicious TFTP client to 
+            crash dnsmasq. Thanks to Steve Grubb at Red Hat for 
+            spotting this. This problem has Bugtraq id: 36120 and 
+            CVE: 2009-2958
+
+
+version 2.49
+            Fix regression in 2.48 which disables the lease-change
+            script. Thanks to Jose Luis Duran for spotting this.
+
+           Log TFTP "file not found" errors. These were not logged,
+           since a normal PXELinux boot generates many of them, but
+           the lack of the messages seems to be more confusing than
+           routinely seeing them when there is no real error.
+
+           Update Spanish translation. Thanks to Chris Chatham.
+
+version 2.48
+            Archived the extensive, backwards, changelog to
+            CHANGELOG.archive. The current changelog now runs from
+            version 2.43 and runs conventionally.
+
+           Fixed bug which broke binding of servers to physical
+           interfaces when interface names were longer than four
+           characters. Thanks to MURASE Katsunori for the patch.
+
+           Fixed netlink code to check that messages come from the
+           correct source, and not another userspace process. Thanks
+           to Steve Grubb for the patch.
+
+           Maintainability drive: removed bug and missing feature
+           workarounds for some old platforms. Solaris 9, OpenBSD
+           older than 4.1, Glibc older than 2.2, Linux 2.2.x and 
+            DBus older than 1.1.x are no longer supported. 
+
+           Don't read included configuration files more than once:
+           allows complex configuration structures without problems.
+
+           Mark log messages from the various subsystems in dnsmasq:
+           messages from the DHCP subsystem now have the ident string
+           "dnsmasq-dhcp" and messages from TFTP have ident
+           "dnsmasq-tftp". Thanks to Olaf Westrik for the patch.
+
+           Fix possible infinite DHCP protocol loop when an IP
+           address nailed to a hostname (not a MAC address)  and a 
+           host sometimes provides the name, sometimes not.
+
+           Allow --addn-hosts to take a directory: all the files 
+           in the directory are read. Thanks to Phil Cornelius for 
+           the suggestion. 
+
+           Support --bridge-interface on all platforms, not just BSD.
+            Added support for advanced PXE functions. It's now
+            possible to define a prompt and menu options which will
+            be displayed when a client PXE boots. It's also possible to
+            hand-off booting to other boot servers. Proxy-DHCP, where
+            dnsmasq just supplies the PXE information and another DHCP
+            server does address allocation, is also allowed. See the
+            --pxe-prompt and --pxe-service keywords. Thanks to 
+           Alkis Georgopoulos for the suggestion and Guilherme Moro
+            and Michael Brown for assistance.
+
+           Improvements to DHCP logging. Thanks to Tom Metro for
+           useful suggestions.
+           
+           Add ability to build dnsmasq without DHCP support. To do
+           this, edit src/config.h or build with
+           "make COPTS=-DNO_DHCP". Thanks to Mahavir Jain for the patch. 
+           
+           Added --test command-line switch - syntax check
+           configuration files only.
+            Updated French translation. Thanks to Gildas Le Nadan.
+
+
+version 2.47
+           Updated French translation. Thanks to Gildas Le Nadan.
+
+           Fixed interface enumeration code to work on NetBSD
+           5.0. Thanks to Roy Marples for the patch. 
+
+           Updated config.h to use the same location for the lease
+           file on NetBSD as the other *BSD variants. Also allow
+           LEASEFILE and CONFFILE symbols to be overriden in CFLAGS.  
+
+            Handle duplicate address detection on IPv6 more
+            intelligently. In IPv6, an interface can have an address
+            which is not usable, because it is still undergoing DAD
+            (such addresses are marked "tentative"). Attempting to
+            bind to an address in this state returns an error,
+            EADDRNOTAVAIL. Previously, on getting such an error,
+            dnsmasq would silently abandon the address, and never
+            listen on it. Now, it retries once per second for 20
+            seconds before generating a fatal error. 20 seconds should
+            be long enough for any DAD process to complete, but can be
+            adjusted in src/config.h if necessary. Thanks to Martin
+            Krafft for the bug report.
+
+           Add DBus introspection. Patch from Jeremy Laine.
+
+           Update Dbus configuration file. Patch from Colin Walters.
+           Fix for this bug:
+            http://bugs.freedesktop.org/show_bug.cgi?id=18961
+
+           Support arbitrarily encapsulated DHCP options, suggestion
+           and initial patch from Samium Gromoff. This is useful for
+           (eg) gPXE, which expect all its private options to be
+           encapsulated inside a single option 175. So, eg, 
+
+            dhcp-option = encap:175, 190, "iscsi-client0"
+            dhcp-option = encap:175, 191, "iscsi-client0-secret"
+           
+           will provide iSCSI parameters to gPXE.
+
+           Enhance --dhcp-match to allow testing of the contents of a
+           client-sent option, as well as its presence. This
+           application in mind for this is RFC 4578
+           client-architecture specifiers, but it's generally useful.
+           Joey Korkames suggested the enhancement. 
+
+           Move from using the IP_XMIT_IF ioctl to IP_BOUND_IF on
+           OpenSolaris. Thanks to Bastian Machek for the heads-up.
+
+           No longer complain about blank lines in
+           /etc/ethers. Thanks to Jon Nelson for the patch.
+
+           Fix binding of servers to physical devices, eg
+           --server=/domain/1.2.3.4@eth0 which was broken from 2.43
+           onwards unless --query-port=0 set. Thanks to Peter Naulls
+           for the bug report.
+
+           Reply to DHCPINFORM requests even when the supplied ciaddr
+           doesn't fall in any dhcp-range. In this case it's not
+           possible to supply a complete configuration, but
+           individually-configured options (eg PAC) may be useful.
+
+           Allow the source address of an alias to be a range:
+           --alias=192.168.0.0,10.0.0.0,255.255.255.0 maps the whole
+           subnet 192.168.0.0->192.168.0.255 to 10.0.0.0->10.0.0.255,
+           as before.
+           --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
+           maps only the 192.168.0.10->192.168.0.40 region. Thanks to
+           Ib Uhrskov for the suggestion.
+
+           Don't dynamically allocate DHCP addresses which may break
+           Windows.  Addresses which end in .255 or .0 are broken in
+           Windows even when using supernetting.
+           --dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0 means 
+           192.168.0.255 is a valid IP address, but not for Windows. 
+           See Microsoft KB281579. We therefore no longer allocate 
+           these addresses to avoid hard-to-diagnose problems. 
+
+           Update Polish translation. Thanks to Jan Psota.
+
+           Delete the PID-file when dnsmasq shuts down. Note that by
+           this time, dnsmasq is normally not running as root, so
+           this will fail if the PID-file is stored in a root-owned
+           directory; such failure is silently ignored. To take
+           advantage of this feature, the PID-file must be stored in a
+           directory owned and write-able by the user running
+           dnsmasq.
+
+
+version 2.46
+           Allow --bootp-dynamic to take a netid tag, so that it may
+           be selectively enabled. Thanks to Olaf Westrik for the
+           suggestion. 
+
+           Remove ISC-leasefile reading code. This has been
+           deprecated for a long time, and last time I removed it, it
+           ended up going back by request of one user. This time,
+           it's gone for good; otherwise it would need to be
+           re-worked to support multiple domains (see below).
+
+           Support DHCP clients in multiple DNS domains. This is a
+           long-standing request. Clients are assigned to a domain
+           based in their IP address.  
+
+            Add --dhcp-fqdn flag, which changes behaviour if DNS names
+            assigned to DHCP clients. When this is set, there must be
+            a domain associated with each client, and only
+            fully-qualified domain names are added to the DNS. The
+            advantage is that the only the FQDN needs to be unique,
+            so that two or more DHCP clients can share a hostname, as
+            long as they are in different domains.
+
+           Set environment variable DNSMASQ_DOMAIN when invoking
+           lease-change script. This may be useful information to
+           have now that it's variable.
+
+           Tighten up data-checking code for DNS packet
+           handling. Thanks to Steve Dodd who found certain illegal
+           packets which could crash dnsmasq. No memory overwrite was
+           possible, so this is not a security issue beyond the DoS
+           potential.  
+
+           Update example config dhcp option 47, the previous
+           suggestion generated an illegal, zero-length,
+           option. Thanks to Matthias Andree for finding this.
+
+           Rewrite hosts-file reading code to remove the limit of
+           1024 characters per line. John C Meuser found this.
+
+           Create a net-id tag with the name of the interface on
+           which the DHCP request was received.
+
+           Fixed minor memory leak in DBus code, thanks to Jeremy
+           Laine for the patch.
+
+           Emit DBus signals as the DHCP lease database
+           changes. Thanks to Jeremy Laine for the patch.
+
+           Allow for more that one MAC address in a dhcp-host
+           line. This configuration tells dnsmasq that it's OK to
+           abandon a DHCP lease of the fixed address to one MAC
+           address, if another MAC address in the dhcp-host statement 
+           asks for an address. This is useful to give a fixed
+           address to a host which has two network interfaces
+           (say, a laptop with wired and wireless interfaces.) 
+            It's very important to ensure that only one interface 
+           at a time is up, since dnsmasq abandons the first lease 
+           and re-uses the address before the leased time has
+           elapsed. John Gray suggested this.
+
+           Tweak the response to a DHCP request packet with a wrong
+           server-id when --dhcp-authoritative is set; dnsmasq now
+           returns a DHCPNAK, rather than silently ignoring the
+           packet. Thanks to Chris Marget for spotting this
+           improvement.
+
+           Add --cname option. This provides a limited alias
+           function, usable for DHCP names. Thanks to AJ Weber for
+           suggestions on this.
+
+           Updated contrib/webmin with latest version from Neil
+           Fisher.
+
+           Updated Polish translation. Thanks to Jan Psota.
+           
+           Correct the text names for DHCP options 64 and 65 to be
+           "nis+-domain" and "nis+-servers".
+
+           Updated Spanish translation. Thanks to Chris Chatham.
+
+           Force re-reading of /etc/resolv.conf when an "interface
+           up" event occurs.
+
+
+version 2.45
+            Fix total DNS failure in release 2.44 unless --min-port 
+            specified. Thanks to Steven Barth and Grant Coady for
+            bugreport. Also reject out-of-range port spec, which could
+            break things too: suggestion from Gilles Espinasse.
+           
+
+version 2.44
+            Fix  crash when unknown client attempts to renew a DHCP
+            lease, problem introduced in version 2.43. Thanks to
+            Carlos Carvalho for help chasing this down.
+
+           Fix potential crash when a host which doesn't have a lease
+           does DHCPINFORM. Again introduced in 2.43. This bug has
+           never been reported in the wild.
+
+            Fix crash in netlink code introduced in 2.43. Thanks to
+            Jean Wolter for finding this.
+
+           Change implementation of min_port to work even if min-port
+           is large.
+
+           Patch to enable compilation of latest Mac OS X. Thanks to
+           David Gilman.
+
+           Update Spanish translation. Thanks to Christopher Chatham.
+
+
+version 2.43
+           Updated Polish translation. Thanks to Jan Psota.
+
+           Flag errors when configuration options are repeated
+           illegally.
+
+           Further tweaks for GNU/kFreeBSD
+
+           Add --no-wrap to msgmerge call - provides nicer .po file
+           format.
+
+           Honour lease-time spec in dhcp-host lines even for
+           BOOTP. The user is assumed to known what they are doing in
+           this case. (Hosts without the time spec still get infinite
+           leases for BOOTP, over-riding the default in the
+           dhcp-range.) Thanks to Peter Katzmann for uncovering this.
+
+           Fix problem matching relay-agent ids. Thanks to Michael
+           Rack for the bug report.
+
+           Add --naptr-record option. Suggestion from Johan
+           Bergquist.
+
+           Implement RFC 5107 server-id-override DHCP relay agent
+           option.
+
+           Apply patches from Stefan Kruger for compilation on
+           Solaris 10 under Sun studio.
+
+           Yet more tweaking of Linux capability code, to suppress
+           pointless wingeing from kernel 2.6.25 and above.
+
+           Improve error checking during startup. Previously, some
+           errors which occurred during startup would be worked
+           around, with dnsmasq still starting up. Some were logged,
+            some silent. Now, they all cause a fatal error and dnsmasq 
+            terminates with a non-zero exit code. The errors are those
+            associated with changing uid and gid, setting process 
+            capabilities and writing the pidfile. Thanks to Uwe
+           Gansert and the Suse security team for pointing out 
+           this improvement, and Bill Reimers for good implementation
+           suggestions.
+
+           Provide NO_LARGEFILE compile option to switch off largefile
+           support when compiling against versions of uclibc which
+           don't support it. Thanks to Stephane Billiart for the patch.
+  
+            Implement random source ports for interactions with
+            upstream nameservers. New spoofing attacks have been found
+            against nameservers which do not do this, though it is not
+            clear if dnsmasq is vulnerable, since to doesn't implement
+            recursion. By default dnsmasq will now use a different
+            source port (and socket) for each query it sends
+            upstream. This behaviour can suppressed using the
+            --query-port option, and the old default behaviour
+            restored using --query-port=0. Explicit source-port
+            specifications in --server configs are still honoured.
+
+           Replace the random number generator, for better
+           security. On most BSD systems, dnsmasq uses the
+           arc4random() RNG, which is secure, but on other platforms,
+           it relied on the C-library RNG, which may be
+           guessable and therefore allow spoofing. This release
+           replaces the libc RNG with the SURF RNG, from Daniel
+           J. Berstein's DJBDNS package.  
+
+           Don't attempt to change user or group or set capabilities
+           if dnsmasq is run as a non-root user. Without this, the
+           change from soft to hard errors when these fail causes
+           problems for non-root daemons listening on high
+           ports. Thanks to Patrick McLean for spotting this.
+
+           Updated French translation. Thanks to Gildas Le Nadan.
+
+
+version 2.42
+            The changelog for version 2.42 and earlier is 
+            available in CHANGELOG.archive.
diff --git a/CHANGELOG.archive b/CHANGELOG.archive
new file mode 100644 (file)
index 0000000..c9973cc
--- /dev/null
@@ -0,0 +1,2509 @@
+release 0.4 - initial public release
+
+release 0.5 - added caching, removed compiler warning on linux PPC
+
+release 0.6 - TCP handling: close socket and return to connect state if we 
+              can't read the first byte. This corrects a problem seen very 
+              occasionally where dnsmasq would loop using all available CPU.
+
+             Added a patch from Cris Bailiff <c.bailiff@e-secure.com.au>
+             to set SO_REUSEADDR on the tcp socket which stops problems when
+              dnsmasq is restarted and old connections still exist.
+
+             Stopped claiming in doc.html that smail is the default Debian
+             mailer, since it isn't any longer. (Pointed out by
+             David Karlin <dkarlin@coloradomtn.edu>)
+
+release 0.7   Create a pidfile at /var/run/dnsmasq.pid
+
+             Extensive armouring against "poison packets" courtesy of
+              Thomas Moestl <tmoestl@gmx.net>
+
+             Set sockaddr.sa_family on outgoing address, patch from
+             David Symonds <xoxus@usa.net>
+
+              Patch to clear cache on SIGHUP 
+             from Jason L. Wagner <nialscorva@yahoo.com> 
+
+             Fix bad bug resulting from not initialising value-result  
+             address-length parameter to recvfrom() and accept() - it
+             worked by luck before!
+
+release 0.95  Major rewrite: remove calls to gethostbyname() and talk
+              directly to the upstream server(s) instead.
+              This has many advantages.
+              (1) Dnsmasq no longer blocks during long lookups.
+              (2) All query types are handled now, (eg MX) not just internet
+                  address queries. Addresses are cached, all other
+                  queries are forwarded directly.
+              (3) Time-to-live data from upstream server is read and
+                  used by dnsmasq to purge entries from the cache.
+              (4) /etc/hosts is still read and its contents served (unless 
+                 the -h option is given).
+              (5) Dnsmasq can get its upstream servers from
+                  a file other than /etc/resolv.conf (-r option) this allows
+                  dnsmasq to serve names to the machine it is running
+                  on (put nameserver 127.0.0.1 in /etc/resolv.conf and
+                  give dnsmasq the option -r /etc/resolv.dnsmasq)
+              (6) Dnsmasq will re-read its servers if the
+                  modification time of resolv.conf changes. Along with
+                  4 above this allows nameservers to be set
+                 automatically by ppp or dhcp.  
+
+              A really clever NAT-like technique allows the daemon to have lots
+              of queries in progress, but still remain very lightweight.
+             Dnsmasq has a small footprint and normally doesn't allocate
+              any more memory after start-up. The NAT-like forwarding was
+              inspired by a suggestion from Eli Chen <eli@routefree.com>
+
+release 0.96  Fixed embarrasing thinko in cache linked-list code.
+                             
+release 0.98  Some enhancements and bug-fixes. 
+              Thanks to "Denis Carre" <denis.carre@laposte.net> and Martin 
+              Otte <otte@essc.psu.edu> 
+              
+             (1) Dnsmasq now always sets the IP source address
+                  of its replies correctly. Older versions would not always
+                  do this on multi-homed and IP aliased hosts, which violates 
+                  the RFC.
+              (2) Dnsmasq no longer crashes if a server loop is created
+                 (ie dnsmasq is told to use itself as an upstream server.)
+                  Now it just logs the problem and doesn't use the bad 
+                  server address.
+              (3) Dnsmasq should now forward (but not cache) inverse queries 
+                  and server status queries; this feature has not been tested.
+              (4) Don't write the pid file when in non-daemon mode.
+             (5) Create the pid file mode 644, rather then 666 (!).
+              (6) Generate queries to upstream nameservers with unpredictable
+                  ids, to thwart DNS spoofers.
+              (7) Dnsmasq no longer forwards queries when the 
+                 "recursion desired" bit is not set in the header.
+             (8) Fixed getopt code to work on compliers with unsigned char.
+              
+release 0.991 Added -b flag: when set causes dnsmasq to always answer
+             reverse queries on the RFC 1918 private IP space itself and
+              never forward them to an upstream server. If the name is not in
+             /etc/hosts, dnsmasq replies with the dotted-quad address.
+              
+              Fixed a bug which stopped dnsmasq working on a box with
+              two or more interfaces with the same IP address. 
+
+              Fixed cacheing of CNAMEs. Previously, a CNAME which pointed
+              to  a name with many A records would not have all the addresses
+              returned when being answered from the cache.
+
+             Thanks to "Steve Hardy" <s.a.hardy@connectux.com> for his input 
+              on these fixes.
+
+              Fixed race which could cause dnsmasq to miss the second of
+              two closely-spaced updates of resolv.conf (Thanks to Eli Chen
+              for pointing this out.)
+
+             Fixed a bug which could cause dnsmasq to fail to cache some
+              dns names.
+
+release 0.992 Small change to memory allocation so that names in /etc/hosts
+              don't use cache slots. Also make "-c 0" flag meaningfully 
+              disable caching completely.                            
+
+release 0.993 Return only the first (canonical) name from an entry in
+             /etc/hosts as reply to reverse query.
+              
+              Handle wildcard queries for names/addresses in /etc/hosts
+             this is mainly to allow reverse lookups by dig to succeed.
+             (Bug reported by Simon J. Rowe" <srowe@mose.org.uk>)  
+              
+              Subtle change to the logic which selects which of multiple
+             upstream servers we send queries to. This fixes a problem 
+              where dnsmasq continuously sends queries to a server which
+             is returning error codes and ignores one which is working.
+              
+release 0.994 Fixed bug which broke lookup of names in /etc/hosts
+              which have upper-case letters in them. Thanks for Joao Clemente
+              for spotting that one. 
+
+             Output cache statistics on receipt of SIGUSR1. These go
+              to syslog except in debug (-d) mode, when a complete cache
+             dump goes to stdout. Suggestion from Joao Clemente, code
+              based in John Volpe's.
+              
+             Accept GNU long options on the command line. Code from 
+             John Volpe for this. 
+
+              Split source code into multiple files and produced 
+             a proper makefile. 
+              
+              Included code from John Volpe to parse dhcp.leases file
+              written by ISC dhcpd. The hostnames in the leases file are
+              added to the cache and updated as dhcpd updates the 
+              leases file. The code has been heavily re-worked by me,
+              so any bugs are probably mine.
+
+release 0.995 Small tidy-ups to signal handling and cache code.
+
+release 0.996 Added negative caching: If dnsmasq gets a "no such domain" reply
+              from an upstream nameserver, it will cache that information
+              for a time specified by the SOA RR in the reply. See RFC 2308
+              for details. This is useful with  resolver libraries
+              which append assorted suffices to non-FQDN in an attempt to 
+              resolve them, causing useless cache misses.
+
+              Added -i flag, which restricts dnsmasq to offering name service
+              only on specified interfaces.
+
+release 0.997 Deleted INSTALL script and added "install" target to makefile.
+
+              Stopped distributing binaries in the tarball to avoid 
+              libc version clashes.
+
+              Fixed  interface detection code to
+              remove spurious startup errors in rare circumstances.
+
+              Dnsmasq now changes its uid, irrevocably, to nobody after
+              startup for security reasons. Thanks to Peter Bailey for
+              this patch.
+
+             Cope with infinite DHCP leases. Patch thanks to 
+             Yaacov Akiba Slama.
+
+             Added rpm control files to .tar.gz distribution. Thanks to
+              Peter Baldwin at ClarkConnect for those.
+
+              Improved startup script for rpms. Thanks to Yaacov Akiba Slama.
+
+release 1.0   Stable release: dnsmasq is now considered feature-complete
+              and stable.
+              
+release 1.1   Added --user argument to allow user to change to
+              a different userid.
+
+              Added --mx-target argument to allow mail to be delivered
+              away from the gateway machine running dnsmasq.
+
+              Fixed highly  obscure bug with wildcard queries for
+              DHCP lease derived names.
+
+              Moved manpage from section 1 to section 8.
+
+              Added --no-poll option.
+              Added Suse-rpm support.
+              Thanks to Joerg Mayer for the last two.
+
+release 1.2   Added IPv6 DNS record support. AAAA records are cached
+              and read from /etc/hosts. Reverse-lookups in the
+             ip6.int and ip6.arpa domains are suppored. Dnsmasq can
+              talk to upstream servers via IPv6 if it finds IP6 addresses
+              in /etc/resolv.conf and it offers DNS service automatically
+              if IPv6 support is present in the kernel.
+
+              Extended negative caching to NODATA replies.
+
+              Re-vamped CNAME processing to cope with RFC 2317's use of
+              CNAMES to PTR RRs in CIDR.
+
+              Added config.h and a couple of symbols to aid
+              compilation on non-linux systems.
+
+release 1.3   Some versions of the Linux kernel return EINVAL rather
+              then ENPROTONOSUPPORT when IPv6 is not available, 
+              causing dnsmasq to bomb out. This release fixes that.
+              Thanks to Steve Davis for pointing this one out.
+
+              Trivial change to startup logic so that dnsmasq logs
+              its stuff and reads config files straight away on
+              starting, rather than after the first query - principle 
+              of least surprise applies here.     
+
+release 1.4   Fix a bug with DHPC lease parsing which broke in
+              non-UTC timezones. Thanks to Mark Wormgoor for
+              spotting and diagnosing this. Fixed versions in
+              the .spec files this time. Fixed bug in Suse startup
+              script. Thanks to Didi Niklaus for pointing this out.
+
+release 1.5   Added --filterwin2k option which stops dnsmasq from forwarding
+             "spam" queries from win2k boxes. This is useful to stop spurious
+              connections over dial-on-demand links. Thanks to Steve Hardy 
+              for this code.
+
+              Clear "truncated" bit in replies we return from upstream. This
+              stops resolvers from switching to TCP, which is pointless since
+              dnsmasq doesn't support TCP. This should solve problems
+              in resolving hotmail.com domains.
+
+              Don't include getopt.h when Gnu-long-options are disabled -
+              hopefully this will allow compilation on FreeBSD.
+
+             Added the --listen-address and --pid-file flags.
+
+              Fixed a bug which caused old entries in the DHCP leases file
+              to be used in preference to current ones under certain
+              circumstances.
+
+release 1.6   If a machine gets named via DHCP and the DHCP name doesn't have
+              a domain part and domain suffix is set using the -s flag, then
+              that machine has two names with the same address, with and 
+              without the domain suffix. When doing a _reverse_ lookup to
+              get the name, the "without suffix" name used to be returned,
+              now the "with suffix" one gets returned instead. This change
+             suggested by Arnold Schulz.
+
+              Fixed assorted typos in the documentation. Thanks 
+              to David Kimdon.
+
+              Subtle rearrangement to the downloadable tarball, and stopped
+              distributing .debs, since dnsmasq is now an official Debian
+              package.
+
+release 1.7   Fix a problem with cache not clearing properly
+              on receipt of SIGHUP. Bug spotted by Sat Deshpande.
+
+              In group-id changing code:
+             1) Drop supplimentary groups.
+              2) Change gid before dropping root (patch from Soewono Effendi.)
+              3) Change group to "dip" if it exists, to allow access
+                 to /etc/ppp/resolv.conf (suggestion from Jorg Sommer.)
+              Update docs to reflect above changes.
+
+              Other documentation changes from David Miller.
+              Added suggested script fragment for dhcpcd.exe.
+
+release 1.8   Fix unsafe use of tolower() macro - allows linking against 
+              ulibc. (Patches from Soewono Effendi and Bjorn Andersson.)
+
+              Fix typo in usage string.
+
+             Added advice about RedHat PPP configuration to
+              documentation. (Thanks to C. Lee Taylor.)
+
+             Patches to fix problems on BSD systems from Marc Huber
+              and Can Erkin Acar. These add the options
+              HAVE_ARC4RANDOM and HAVE_SOCKADDR_SA_LEN to config.h.
+             Elaborated config.h - should really use autoconf.
+
+             Fix time-to-live calculation when chasing CNAMEs.
+
+             Fix use-after-free and missing initialisation bugs in
+              the cache code. (Thanks to Marc Huber.)
+
+              Builds on Solaris 9. (Thanks to Marc Huber.)           
+
+release 1.9   Fixes to rpm .spec files.
+
+              Don't put expired DHCP entries into the cache only to 
+             throw them away again.
+
+              Put dnsmasq on a severe memory diet: this reduces both
+              the amount of heap space used and the stack size
+              required. The difference is not really visible with
+              bloated libcs like glibc, but should dramatically reduce
+              memory requirements when linked against ulibc for use on
+              embeded routers, and that's the point really. Thanks to
+              Matthew Natalier for prompting this.   
+
+             Changed debug mode (-d) so that all logging appears on
+              stderr as well as going to syslogd. 
+
+             Added HAVE_IPV6 config symbol to allow compilation
+              against a libc which doesn't have IPv6 support.
+
+             Added a facility to log all queries, enabled with -q flag.
+
+             Fixed packet size checking bug in address extraction code.
+
+             Halved default cache size - 300 was way OTT in typical use.
+
+             Added self-MX function, enabled by -e flag. Thanks to
+              Lyonel Vincent for the patch.
+
+             Added HAVE_FORK config symbol and stuff to support
+              uClinux. Thanks to Matthew Natalier for uClinux stuff. 
+
+release 1.10  Log warnings if resolv.conf or dhcp.leases are not
+              accessable for any reason, as suggested by Hinrich Eilts.
+
+             Fixed wrong address printing in error message about
+             no interface with address.
+
+             Updated docs and split installation instuctions into setup.html.
+
+             Fix bug in CNAME chasing code: One CNAME pointing
+             to many A records would lose A records after the 
+             first. This bug was introduced in version 1.9.
+
+             Log startup failures at level Critical as well as 
+             printing them to standard error.
+             Exit with return code 1 when given bad options.
+
+             Cleaned up code for no-cache operation.
+
+              Added -o option which forces dnsmasq to use to
+              upstream servers in the order they appear in /etc/resolv.conf.
+
+              Added upstream server use logging.
+
+              Log full cache dump on receipt of SIGUSR1 when query 
+              logging is enabled (-q switch).
+
+             Added -S option to directly specify upstream servers and
+              added ability to direct queries for specific domains to
+              specfic servers. Suggested by Jens Vonderheide.
+
+             Upgraded random ID generation - patch from Rob Funk.            
+
+             Fixed reading of domains in arguments with capital
+              letters or trailing periods.
+
+             Fixed potential SEGV when given bad options.
+
+             Read options from /etc/dnsmasq.conf if it exists.
+              Do sensible things with missing parameters, eg 
+              "--resolv-file=" turns off reading /etc/resolv.conf.
+
+release 1.11  Actually implement the -R flag promised in the 1.10 man page.
+
+              Improve and rationalise the return codes in answers to
+              queries. In the case that there are no available
+              upstream servers to forward a query to, return REFUSED.
+              This makes sendmail work better on modem connected
+              systems when the modem link is down (Thanks to Roger Plant).
+             Cache and return the NXDOMAIN status of failed queries:
+              this makes the `host` command work when traversing search
+              paths (Thanks to Peter Bailey). Set the "authoritative"
+              bit in replies containing names from /etc/hosts or DHCP.
+
+              Tolerate MS-DOS style line ending codes in /etc/hosts
+             and /etc/resolv.conf, for people who copy from winsock
+              installations.
+
+             Allow specification of more than one resolv.conf file. This is 
+              intended for laptops which connect via DHCP or
+              PPP. Whichever resolv.conf was updated last is used.
+
+              Allow -S flags which specify a domain but no server
+              address. This gives local domains which are never forwarded.
+
+             Add -E flag to automatically add the domain suffix to
+              names in /etc/hosts -suggestion from Phil Harman.
+
+             Always return a zero time-to-live for names derived from 
+             DHCP which stops anthing else caching these
+              names. Previously the TTL was derived from the lease
+              time but that is incorrect since a lease can be given
+              up early: dnsmasq would know this but anything with the
+              name cached with long TTL would not be updated.
+
+             Extended HAVE_IPV6 config flag to allow compliation on
+             old systems which don't have modern library routines
+             like inet_ntop(). Thanks to Phil Harman for the patch.
+
+release 1.12  Allow more than one domain in server config lines and
+             make "local" a synonym for "server". This makes things
+             like "local=/localnet/thekelleys.org.uk/" legal. Allow
+              port to specified as part of server address.
+
+             Allow whole domains to have an IP address specified
+              in /etc/dnsmasq.conf. (/etc/hosts doesn't work domains).
+              address=/doubleclick.net/127.0.0.1 should catch all
+              those nasty banner ads. Inspired by a patch 
+             from Daniel Gryniewicz
+
+             Log the source of each query when logging switched on. 
+
+             Fix bug in script fragment for dhcpcd - thanks to Barry Stewart.
+             
+             Fix bug which meant that strict-order and self-mx were
+             always enabled.
+
+             Builds with Linux libc5 now - for the Freesco project.
+
+             Fixed Makefile installation script (patch from Silvan
+             Minghetti) and added CC and CFLAGS variables.
+
+             Improve resource allocation to reduce vulnerability to
+             DOS attacks - the old version could have all queries
+             blocked by a continuous high-speed stream of
+             queries. Now some queries will succeed, and the excess
+             will be rejected with a server fail error. This change also
+             protects against server-loops; setting up a resolving
+              loop between two instances of dnsmasq is no longer
+             catastrophic. The servers will continue to run, looped
+             queries fail and a warning is logged. Thanks to C. Lee
+             Taylor for help with this.
+             
+release 1.13  Added support for building rpms suitable for modern Suse 
+             systems. (patch from Andi <cambeis@netplace.de>)
+             
+             Added options --group, --localmx, --local-ttl,
+             --no-negcache, --addn-host.
+             
+             Moved all the various rpm-building bits into /rpm.
+             
+             Fix builds with glibc 2.1 (thanks to Cristian
+             Ionescu-Idbohrn)
+             
+             Preserve case in domain names, as per RFC1035.
+             
+             Fixed ANY queries to domains with --address specification.
+             
+             Fixed FreeBSD build. (thanks to Steven Honson)
+             
+             Added -Q option which allows a specified port to be used
+             to talk to upstream servers. Useful for people who want
+             very paranoid firewalls which open individual UDP port.
+             (thanks to David Coe for the patch)
+                     
+release 1.14  Fixed man page description of -b option which confused 
+             /etc/hosts with /etc/resolv.conf. (thanks to Christopher
+             Weimann)
+             
+             Fixed config.h to allow building under MACOS X and glibc
+             2.0.x. (thanks to Matthew Gregan and Serge Caron)
+             
+             Added --except-interface option. (Suggested by Serge Caron)
+
+             Added SIGUSR2 facility to re-scan for new
+             interfaces. (Suggested by Serge Caron)
+
+             Fixed SEGV in option-reading code for invalid options.
+             (Thanks to Klaas Teschauer)
+
+              Fixed man page to clarify effect of SIGUSR1 on
+             /etc/resolv.conf.
+             (Thanks to Klaas Teschauer)
+             
+             Check that recieved queries have only rfc1035-legal characters
+             in them. This check is mainly to avoid bad strings being
+             sent to syslog.
+
+             Fixed &&/& confusion in option.c and added DESTDIR
+             variable for "make install" (Thanks to Osvaldo 
+              Marques for the patch.)
+
+             Fixed /etc/hosts parsing code to cope with MS-DOS
+             line-ends in the file. This was supposed to be done in
+             version 1.11, but something got missed. (Thanks to Doug
+             Copestake for helping to find this.)
+
+             Squash repeated name/address pairs read from hosts
+             files.
+
+             Tidied up resource handling in util.c (Thanks to
+             Cristian Ionescu-Idbohrn).
+
+             Added hashed searching of domain names. People are starting
+             to use dnsmasq with larger loads now, and bigger caches,
+             and large lists of ad-block addresses. This means doing
+             linear searches can start to use lots of CPU so I added hashed
+             searching and seriously optimised the cache code for 
+             algorithmic efficiency. Also upped the limit on cache 
+             size to 10000.
+
+             Fixed logging of the source of names from the additional
+             hosts file and from the "bogus private address" option.
+
+             Fixed spurious re-reading of empty lease files. (Thanks
+             to Lewis Baughman for spotting this.)
+
+             Fixed building under uclibc (patch from Cristian Ionescu-Idbohrn)
+             
+             Do some socket tweaking to allow dnsmasq to co-exist
+             with BIND. Thanks to Stefan 'Sec' Zehl for the patch.
+
+release 1.15  Added --bogus-nxdomain option.
+
+              Restrict checking of resolv.conf and DHCP leases files
+              to once per second. This is intended to improve
+              performance under heavy loads. Also make a system call
+             to get the current time once per query, rather than four
+              times.
+
+             Increased number of outstanding queries to 150 in
+             config.h
+
+release 1.16  Allow "/" characters in domain names - this fixes
+              caching of RFC 2317 CNAME-PTR records.
+
+             Fixed brain-fart in -B option when GETOPT_LONG not
+             enabled - thanks to Steven Young and Jason Miller 
+             for pointing this out.
+
+             Generalised bogus-nxdomain code: allow more than one
+             address to check, and deal with replies with multiple
+             answer records. (Based on contribution from Humberto
+             Massa.)
+
+             Updated the documentation to include information about
+             bogus-nxdomain and the Verisign tragedy.
+
+             Added libraries needed on Solaris to Makefile.
+
+             Added facility to set source address in queries to
+             upstream nameservers. This is useful with multihomed
+             hosts, especially when using VPNs. Thanks to Tom Fanning
+             for suggesting this feature.
+
+             Tweaked logging: log to facility LOCAL0 when in
+             debug/no-daemon mode and changed level of query logging
+             from INFO to DEBUG. Make log options controllable in
+             config.h
+
+release 1.17  Fixed crash with DHCP hostnames > 40 characters.
+
+              Fixed name-comparision routines to not depend on Locale,
+              in theory this versions since 1.15 could lock up or give
+              wrong results when run with locale != 'C'.
+
+             Fix potential lockup in cache code. (thanks to Henning
+             Glawe for help chasing this down.)
+
+             Made lease-file reader bullet-proof.
+
+             Added -D option, suggested by Peter Fichtner.
+
+release 1.18  Added round-robin DNS for names which have more than one
+              address. In this case all the addresses will be
+              returned, as before, but the order will change on each
+              query.
+
+             Remove stray tolower() and isalnum() calls missed in 
+             last release to complete LOCALE independence.
+
+             Allow port numbers in source-address specifications.
+
+             For hostnames without a domain part which don't get
+             forwarded because -D is in effect, return NXDOMAIN not
+             an empty reply.
+
+             Add code to return the software version in repsonse to the
+             correct magic query in the same way as BIND. Use  
+             "dig version.bind chaos txt" to make the query.
+
+             Added negative caching for PTR (address to name) records.
+
+              Ensure that names of the form typically used in PTR queries
+              (ie w.x.yz.in-addr.arpa and IPv6 equivalents) get
+              correct answers when queried as other types. It's
+              unlikely that anyone would do this, but the change makes
+              things pedantically correct.
+
+             Taught dnsmasq to understand "bitstring" names, as these
+             are used for PTR lookups of IPv6 addresses by some 
+             resolvers and lookup tools. Dnsmasq now understands both
+             the ip6.int domain and the ip6.arpa domain and both
+             nibble and bitstring formats so it should work with any
+             client code. Standards for this stuff have flip-flopped
+             over the last few years, leaving many different clients
+             in their wake. See RFC2673 for details of bitstrings.
+             
+             Allow '_' characters in domain names: Legal characters
+             are now [a-z][A-Z].-_ Check names read from hosts files
+             and leases files and reject illegal ones with a message
+             in syslog. 
+
+             Make empty domain names in server and address options 
+             have the special meaning "unqualified
+             names". (unqualified names are names without any dots in
+             them). It's now possible to do server=//1.2.3.4 and have 
+             unqualified names sent to a special nameserver.
+
+release 2.0rc1  
+              Moved source code into src/ directory.
+
+             Fixes to cure compilation breakage when HAVE_IPV6 not
+             set, thanks to Claas Hilbrecht.
+
+             BIG CHANGE: added an integrated DHCP server and removed
+             the code to read ISC dhcp.leases. This wins in terms 
+             of ease of setup and configuration flexibility and 
+             total machine resources consumed. 
+
+             Re-jiged the signal handling code to remove a race
+             condition and to be more portable.
+
+release 2.0
+            Thanks to David Ashworth for feedback which informed many 
+            of the fixes below.
+
+             Allow hosts to be specified by client ID in dhcp-hosts
+             options. These are now one of 
+             dhcp-host=<hardware addr>,.... 
+             dhcp-host=id:<hex client id>,..... 
+             dhcp-host=id:<ascii client id>,.....
+            
+            Allow dhcp-host options to specify any IP address on the
+             DHCP-served network, not just the range available for
+             dynamic allocation.
+
+            Allow dhcp-host options for the same host with different
+            IP adresses where the correct one will be selected for
+            the network the host appears on.
+
+            Fix parsing of --dhcp-option to allow more than one
+            IP address and to allow text-type options.      
+
+            Inhibit use of --dhcp-option to send hostname DHCP options.
+            
+            Update the DNS with DHCP information after re-reading
+            /etc/hosts so that any DHCP derived names which have been
+            shadowed by now-deleted hosts entries become visible.
+
+            Fix typos in dnsmasq.conf.example
+
+            Fixes to Makefile(s) to help pkgsrc packaging - patch 
+            from "pancake".
+
+            Add dhcp-boot option to support network boot.
+
+            Check for duplicate IP addresses in dhcp-hosts lines
+            and refuse to run if found. If allowed to remain these 
+            can provoke an infinite loop in the DHCP protocol.
+
+            Attempted to rationalise the .spec files for rpm
+            building. There are now files for Redhat, Suse and
+            Mandrake. I hope they work OK.
+
+            Fixed hard-to-reproduce crash involving use of local
+            domains and IPv6 queries. Thanks to Roy Marples for
+            helping to track that one down.
+
+release 2.1  
+             Thanks to Matt Swift and Dag Wieers for many suggestions 
+            which went into this release.
+           
+            Tweak include files to allow compilation on FreeBSD 5
+             
+             Fix unaligned access warnings on BSD/Alpha.
+
+            Allow empty DHCP options, like so: dhpc-option=44
+             Allow single-byte DHCP options like so: dhcp-option=20,1
+
+            Allow comments on the same line as options in
+            /etc/dnsmasq.conf
+
+            Don't complain when the same name and address is
+            allocated to a host using DHCP and /etc/hosts.
+            
+            Added to the example configuration the dnsmasq equivalent
+            of the ISC dhcpd settings given in 
+             http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
+
+            Fixed long-existing strangeness in Linux IPv6 interface
+            discovery code. The flags field in /proc/net/if_inet6 is
+            _not_ the interface flags. 
+
+            Fail gracefully when getting an ENODEV error when trying
+            to bind an IPv6 socket, rather than bailing out. Thanks
+            to Jan Ischebeck for feedback on that.
+
+            Allow the name->address mapping for static DHCP leases to
+            be set by /etc/hosts. It's now possible to have
+               dhcp-host=<mac addr>,wibble
+            or even
+                dhcp-host=wibble
+            and in /etc/hosts have
+               wibble 1.2.3.4
+            and for the correct thing to happen. Note that some sort
+            of dhcp-host line is still needed, it's not possible for
+            random host to claim an address in /etc/hosts without
+            some explicit configuration.
+
+            Make 0.0.0.0 in a dhcp-option to mean "the machine
+            running dnsmasq".
+                   
+             Fix lease time spec when specified in dhcp-range and not
+            in dhcp-host, previously this was always one hour.
+
+             Fix problem with setting domains as "local only". -
+             thanks to Chris Schank.
+
+            Added support for max message size DHCP option.
+
+release 2.2
+             Fix total lack for DHCP functionality on
+            Linux systems with IPv6 enabled. - thanks to
+            Jonathon Hudson for spotting that.
+
+            Move default config file under FreeBSD - patch from
+            Steven Honson 
+
+release 2.3
+             Fix "install" makefile target. (reported by Rob Stevens)
+
+            Ensure that "local=/domain/" flag is obeyed for all
+            queries on a domain, not just A and AAAA. (Reported by
+            Peter Fichtner.)
+
+            Handle DHCPDECLINE messages and provide an error message
+            in DHCPNAK messages.
+            
+            Add "domain" setting example to
+            dnsmasq.conf.example. Thanks to K P Kirchdorfer for
+            spotting that it was missing.
+
+            Subtle change to the DHCPREQUEST handling code to work
+            around a bug in the DHCP client in HP Jetdirect printers.
+            Thanks to Marko Stolle for finding this problem.
+
+            Return DHCP T1 and T2 times, with "fuzz" to desychronise lease
+            renewals, as specified in the RFC.
+            
+            Ensure that the END option is always present in DHCP
+            packets , even if the packet is too small to fit all 
+            the requested options.
+
+            Handle larger-than-default DHCP packets if required, up
+            to the ethernet MTU.
+
+            Fix a couple of places where the return code from
+            malloc() was not checked.
+
+            Cope with a machine taking a DHCP lease and then moving
+            network so that the lease address is no longer valid.
+
+            The DHCP server will now work via a BOOTP relay - remote
+            networks are configured with the dhcp-range option the
+            same as directly connected ones, but they need an
+            additional netmask parameter. Eg
+            --dhcp-range=192.168.4.10,192.168.4.50,255.255,255.0
+             will enable DHCP service via a BOOTP relay on the
+            192.168.4.0 network. 
+
+            Add a limit on the number of available DHCP leases,
+            otherwise the daemon could be DOSed by a malicious
+            host. The default is 150, but it can be changed by the 
+            dhcp-lease-max option.
+
+            Fixed compilation on OpenBSD (thanks to Frederic Brodbeck
+            for help with that.)
+            
+            Reworked the DHCP network handling code for two good
+            effects: (1) The limit of one network only for DHCP on
+            FreeBSD is now gone, (2) The DHCP server copes with
+            dynamically created interfaces. The one-interface
+            limitation remains for OpenBSD, which is missing
+            extensions to the socket API which have been in Linux
+            since version 2.2 and FreeBSD since version 4.8.
+
+            Reworked the DNS network code to also cope with
+            dynamically created interfaces. dnsmasq will now listen
+            to the wildcard address and port 53 by default, so if no
+            --interface or --address options are given it will handle
+            dynamically created interfaces. The old behaviour can be
+            restored with --bind-interfaces for people running BIND
+            on one interface and dnsmasq on another. Note that
+            --interface and --address options still work, but the
+            filtering is done by dnsmasq, rather then the kernel.
+            This works on Linux, and FreeBSD>=5.0. On systems which
+            don't support the required API extensions, the old 
+            behaviour is used, just as if --bind-interfaces had been set.
+
+            Allow IPv6 support to be disabled at compile time. To do
+            that, add -DNO_IPV6 to the CFLAGS. Thanks to Oleg
+            I. Vdovikin for the suggestion to do that.
+
+            Add ability to set DHCP options per network. This is done
+            by giving a network an identifier like this:
+            dhcp-range=red-net,192.168.0.10,192.168.0.50
+            and then labeling options intended for that network only
+            like this:
+            dhcp-option=red-net,6,1.1.1.1
+            Thanks to Oleg Vdovikin for arguing that one through.
+
+            Made errors in the configuration file non-fatal: dnsmasq
+            will now complain bitterly, but continue.
+
+            Added --read-ethers option, to allow dnsmasq to pull
+            static DHCP information from that file. 
+            Thanks to Andi Cambeis for that suggestion.
+
+            Added HAVE_BROKEN_RTC compilation option to support
+            embedded systems without a stable RTC. Oleg Vdovikin
+            helped work out how to make that work.
+
+release 2.4
+            Fixed inability to start when the lease file doesn't
+            already exist. Thanks to Dag Wieers for reporting that.
+
+            Fixed problem were dhcp-host configuration options did
+            not play well with entries in /etc/ethers for the same
+            host. Thanks again to Dag Wieers.
+
+            Tweaked DHCP code to favour moving to a newly-configured
+            static IP address rather than an old lease when doing
+            DHCP allocation.
+
+            Added --alias configuration option. This provides IPv4
+            rewrite facilities like Cisco "DNS doctoring". Suggested
+            by Chad Skeeters.
+
+            Fixed bug in /etc/ethers parsing code triggered by tab
+            characters. Qudos to Dag Wieers for hepling to nail that
+            one.
+            
+            Added "bind-interfaces" option correctly.       
+
+release 2.5
+            Made "where are we allocating addresses?" code in DHCP
+            server cope with requests via a relay which is on a
+            directly connected network for which there is not a
+            configured netmask. This strange state of affairs occurs
+            with win4lin. Thanks to Alex Melt and Jim Horner for bug
+            reports and testing with this. 
+
+            Fixed trivial-but-irritating missing #include which broke
+            compilation on *BSD.
+
+            Force --bind-interfaces if IP-aliased interface
+            specifications are used, since the sockets API provides
+            no other sane way to determine which alias of an
+            interface a packet was sent to. Thanks to Javier Kohen
+            for the bug report.
+
+release 2.6 
+            Support Token Ring DHCP. Thanks to Dag Wieers for help
+            testing. Note that Token ring support only works on Linux 
+            currently.
+
+            Fix compilation on MacOS X. Thanks to Bernhard Ehlers for
+            the patch.
+
+            Added new "ignore" keyword for
+            dhcp-host. "dhcp-host=11:22:33:44:55:66,ignore" will
+            cause the DHCP server to ignore any host with the given
+            MAC address, leaving it to other servers on the
+            network. This also works with client-id and hostnames.
+            Suggestion by Alex Melt.
+
+            Fixed parsing of hex client IDs. Problem spotted by Peter
+            Fichtner.
+
+            Allow conf-file options in configuration file, to
+            provide an include function.
+            
+            Re-read /etc/ethers on receipt of SIGHUP.
+
+            Added back the ability to read ISC dhcpd lease files, by
+            popular demand. Note that this is deprecated and for
+            backwards compatibility only. You can get back the 4K of
+            memory that the code occupies by undefining
+            "HAVE_ISC_READER" in src/config.h
+
+            Added ability to disable "pool" DHCP address allocation
+            whilst leaving static leases working. The syntax is
+            "dhcp-range=192.168.0.0,static"
+            Thanks to Grzegorz Nosek for the suggestion.
+
+            Generalized dnsmasq-rh.spec file to work on Mandrake too,
+            and removed dnsmasq-mdk.spec. Thanks to Doug Keller.
+
+            Allow DHCP options which are tied to specific static
+            leases in the same way as to specific networks.
+
+            Generalised the dhcp-option parser a bit to allow hex
+            strings as parameters. This is now legal:
+            dhcp-option=128,e4:45:74:68:00:00
+            Inspired by a patch from Joel Nordell.
+
+            Changed the semantics of argument-less dhcp-options for
+            the default-setting ones, ie 1, 3, 6 and 28. Now, doing
+            eg, dhcp-option=3 stops dnsmasq from sending a default
+            router option at all. Thanks to Scott Emmons for pointing
+            out that this is useful.
+
+            Fixed dnsmasq.conf parsing bug which interpreted port
+            numbers in server= lines as a comment. To start a
+            comment, a '#' character must now be a the start of a
+            line or preceded by whitespace. Thanks to Christian
+            Haggstrom for the bug report.
+
+release 2.7  
+             Allow the dhcp-host specification of id:* which makes 
+            dnsmasq ignore any client-id. This is useful to ensure 
+            that a dual-boot machine sees the same lease when one OS 
+            gives a client-id and the other doesn't. It's also useful
+            when PXE boot DHCP does not use client IDs but the OS it boots 
+             does. Thanks to Grzegorz Nosek for suggesting this enhancement.
+
+            No longer assume that ciaddr is zero in received DHCPDISCOVER 
+            messages, just for security against broken clients.
+
+            Set default of siaddr field to the address of the machine running 
+             dnsmasq when not explicitly set using dhcp-boot
+             option. This is the ISC dhcpd behaviour.  
+
+             Send T1 and T2 options in DHCPOFFER packets. This is required
+            by the DHCP client in some JetDirect printers. Thanks 
+             to Paul Mattal for work on this.
+
+            Fixed bug with DHCP on OpenBSD reported by Dominique Jacquel.
+            The code which added loopback interfaces to the list
+            was confusing the DHCP code, which expected one interface only.
+            Solved by adding loopback interfaces to address list instead.
+
+            Add dhcp-vendorclass option to allow options to be sent only
+            to certain classes of clients.
+
+            Tweaked option search code so that if a netid-qualified
+            option is used, any unqualified option is ignored.
+            
+            Changed the method of picking new dynamic IP
+            addresses. This used to use the next consecutive
+            address as long it was free, now it uses a hash
+            from the client hardware address. This reduces the amount
+            of address movement for clients which let their lease
+            expire and allows consecutive DHCPOFFERS to the same host
+            to (almost always) be for the same address, without
+            storing state before a lease is granted.
+            Tweaked option handling code to return all possible
+            options rather than none when DHCP "requested options"
+            field is missing. This fixes interoperability with
+            ancient IBM LANMAN DHCP clients. Thanks to Jim Louvau for
+            help with this.
+
+release 2.8
+            Pad DHCP packets to a minimum size of 300 bytes. This
+            fixes interoperability problems with the Linux in-kernel
+            DHCP/BOOTP client. Thanks to Richard Musil for
+            diagnosing this and supplying a patch.
+
+            Fixed option-parsing bug and potential memory leak. Patch
+            from Richard Musil.
+
+            Improved vendor class configuration and added user class
+            configuration. Specifically: (1) options are matched on
+            the netids from dhcp-range, dhcp-host, vendor class and
+            user class(es). Multiple net-ids are allowed and options
+            are searched on them all. (2) matches agains vendor class
+            and user class are now on a substring, if the given
+            string is a substring of the vendor/user class, then a
+            match occurs. Thanks again to Richard Musil for prompting
+            this.
+
+            Make "#" match any domain on --address and --server
+            flags. --address=/#/1.2.3.4 will return 1.2.3.4 for _any_
+            domain not otherwise matched. Of course
+            --server=/#/1.2.3.4 is exactly equivalent to
+            --server=1.2.3.4. Special request from Josh Howlett.
+       
+            Fixed a nasty bug which would cause dnsmasq to lose track
+            of leases for hosts which had a --dhcp-host flag without
+            a name specification. The mechanism for this was that
+            the hostname could get erroneously set as a zero-length
+            string and then written to the leases file as a
+            mal-formed line. Restarting dnsmasq would then lose the lease.
+            Alex Hermann's work helped chase down this problem.
+
+            Add checks against DHCP clients which return zero-length
+            hostnames. This avoids the potential lease-loss problems
+            reffered to above. Also, if a client sends a hostname when
+            it creates a lease but subsequently sends no or a
+            zero-length hostname whilst renewing, continue to use the
+            existing hostname, don't wipe it out. 
+            
+            Tweaked option parsing to flag some parameter errors.
+
+release 2.9
+            Fixed interface filter code for two effects: 1) Fixed bug
+            where queries sent via loopback interface
+            but to the address of another interface were ignored
+            unless the loopback interface was explicitly configured.
+            2) on OpenBSD failure to configure one interface now
+            causes a fatal error on startup rather than an huge
+            stream of log messages. Thanks to Erik Jan Tromp for 
+            finding that bug.
+
+            Changed server selection strategy to improve performance
+            when there are many available servers and some are
+            broken. The new algorithm is to pick as before for the
+            first try, but if a query is retried, to send to all
+            available servers in parallel. The first one to reply
+            then becomes prefered for the next query. This should 
+            improve reliability without generating significant extra
+            upstream load.
+
+            Fixed breakage of special servers/addresses for
+            unqualified domains introduced in version 2.8 
+             
+            Allow fallback to "bind-interfaces" at runtime: Some
+            verions of *BSD seem to have enough stuff in the header
+            files to build but no kernel support. Also now log if
+            "bind-interfaces" is forced on.
+
+            Log replies from upstream servers which refuse to do
+            recursion - dnsmasq is not a recursive nameserver and
+            relies on upstream servers to do the recursion, this
+            flags a configuration error.
+
+            Disable client-id matching for hosts whose MAC address is
+            read from /etc/ethers. Patch from Oleg I. Vdovikin.
+
+            Extended --mx-host flag to allow arbitrary targets for MX
+            records, suggested by Moritz Bunkus.
+
+            Fixed build under NetBSD 2.0 - thanks to Felix Deichmann
+            for the patch.
+            
+            Deal correctly with repeated addresses in /etc/hosts. The
+            first name found is now returned for reverse lookups,
+            rather than all of them.
+
+            Add back fatal errors when nonexistant 
+            interfaces or interface addresses are given but only in
+            "bind-interfaces" mode. Principle of least surprise applies.
+            
+            Allow # as the argument to --domain, meaning "read the
+            domain from the first search directive in
+            /etc.resolv.conf". Feature suggested by Evan Jones.
+
+release 2.10
+           Allow --query-port to be set to a low port by creating and
+           binding the socket before dropping root. (Suggestion from
+           Jamie Lokier) 
+
+           Support TCP queries. It turned out to be possible to do
+           this with a couple of hundred lines of code, once I knew
+           how. The executable size went up by a few K on i386.
+           There are a few limitations: data obtained via TCP is not
+           cached, and dynamically-created interfaces may break under
+           certain circumstances. Source-address or query-port
+           specifications are ignored for TCP.
+
+           NAK attempts to renew a DHCP lease where the DHCP range
+           has changed and the lease is no longer in the allowed
+           range. Jamie Lokier pointed out this bug.
+
+           NAK attempts to renew a pool DHCP lease when a statically
+           allocated address has become available, forcing a host to
+           move to its allocated address. Lots of people have
+           suggested this change and been rebuffed (they know who
+           they are) the straws that broke the camel's back were Tim
+           Cutts and Jamie Lokier.
+
+           Remove any nameserver records from answers which are
+           modified by --alias flags. If the answer is modified, it
+           cannot any longer be authoritative.
+
+           Change behaviour of "bogus-priv" option to return NXDOMAIN
+           rather than a PTR record with the dotted-quad address as
+           name. The new behaviour doesn't provoke tcpwrappers like
+           the old behavior did.
+
+           Added a patch for the Suse rpm. That changes the default
+           group to one suitable for Suse and disables inclusion of
+           the ISC lease-file reader code. Thanks to Andy Cambeis for
+           his ongoing work on Suse packaging.
+
+           Support forwarding of EDNS.0 The maximum UDP packet size 
+           defaults to 1280, but may be changed with the
+           --edns-packet-max option. Detect queries with the do bit
+           set and always forward them, since DNSSEC records are 
+           not cached. This behaviour is required to make
+           DNSSECbis work properly though dnsmasq. Thanks to Simon
+           Josefsson for help with this.
+
+           Move default config file location under OpenBSD from
+           /usr/local/etc/dnsmasq.conf to /etc/dnsmasq.conf. Bug
+           report from Jonathan Weiss.
+
+           Use a lease with matching MAC address for a host which
+           doesn't present a client-id, even if there was a client ID 
+           at some point in the past. This reduces surprises when
+           changing DHCP clients, adding id:* to a host, and from the
+           semantics change of /etc/ethers in 2.9. Thanks to Bernard
+           Sammer for finding that.
+
+           Added a "contrib" directory and in it the dnslist utility,
+           from Thomas Tuttle.
+
+           Fixed "fail to start up" problems under Linux with IPv6
+           enabled. It's not clear that these were an issue in
+           released versions, but they manifested themselves when TCP
+           support was added. Thanks to Michael Hamilton for
+           assistance with this.
+
+version 2.11
+           Fixed DHCP problem which could result in two leases in the
+            database with the same address. This looked much more
+            alarming then it was, since it could only happen when a
+            machine changes MAC address but kept the same name. The
+            old lease would persist until it timed out but things
+            would still work OK. 
+
+           Check that IP addresses in all dhcp-host directives are
+           unique and die horribly if they are not, since otherwise
+           endless protocol loops can occur. 
+           
+           Use IPV6_RECVPKTINFO as socket option rather than
+           IPV6_PKTINFO where available. This keeps late-model FreeBSD
+           happy.
+
+           Set source interface when replying to IPv6 UDP
+           queries. This is needed to cope with link-local addresses.
+
+version 2.12
+            Added extra checks to ensure that DHCP created DNS entries 
+           cannot generate multiple DNS address->name entries. Thanks to 
+           Stefan Monnier for finding the exact set of configuration
+            options which could create this.
+
+           Don't set the the filterwin2k option in the example config
+           file and add warnings that is breaks Kerberos. Thanks to
+           Simon Josefsson and Timothy Folks for pointing that out.
+           
+           Log types of incoming queries as well as source and domain.
+
+           Log NODATA replies generated as a result of the
+           filterwin2k option.
+
+version 2.13
+           Fixed crash with un-named DHCP hosts introduced in 2.12.
+           Thanks to Nicolo Wojewoda and Gregory Gathy for bug reports.
+
+version 2.14
+           Fix DHCP network detection for hosts which talk via a
+           relay. This makes lease renewal for such hosts work
+           correctly.
+
+           Support RFC3011 subnet selectors in the DHCP server.
+
+           Fix DHCP code to generate RFC-compliant responses
+            to hosts in the INIT-REBOOT state.
+
+           In the DHCP server, set the receive buffer size on 
+           the transmit-only packet socket to zero, to avoid 
+           waste of kernel buffers.
+
+           Fix DHCP address allocation code to use the whole of
+           the DHCP range, including the start and end addresses.
+           
+           Attempt an ICMP "ping" on new addresses before allocating 
+           them to leases, to avoid allocating addresses which are in use.
+
+           Handle rfc951 BOOTP as well as DHCP for hosts which have
+           MAC address to IP address mapping defined.
+
+           Fix compilation under MacOS X. Thanks to Chris Tomlinson.
+
+           Fix compilation under NetBSD. Thanks to Felix Deichmann.
+
+           Added "keep-in-foreground" option. Thanks to Sean
+           MacLennan for the patch.
+
+version 2.15
+            Fixed NXDOMAIN/NODATA confusion for locally known
+            names. We now return a NODATA reponse for names which are
+            locally known. Now a query for (eg AAAA or MX) for a name
+           with an IPv4 address in /etc/hosts which fails upstream
+            will generate a NODATA response. Note that the query 
+           is still tried upstream, but a NXDOMAIN reply gets
+            converted to NODATA. Thanks to Eric de Thouars, Eric
+            Spakman and Mike Mestnik for bug reports/testing.
+
+           Allow multiple dhcp-ranges within the same network. The
+           original intention was that there would be a dhcp-range
+           option for each network served, but there's no real reason
+           not to allow discontinuous ranges within a network so this
+           release adds support for that.
+
+           Check for dhcp-ranges which are inconsistent with their 
+           netmask, and generate errors or warnings.
+           
+           Improve error messages when there are problems with
+           configuration.
+
+version 2.16
+           Fixed typo in OpenBSD-only code which stopped compilation
+            under that OS. Chris Weinhaupl gets credit for reporting 
+            this.
+
+           Added dhcp-authoritative option which restores non-RFC 
+           compliant but desirable behaviour of pre-2.14 versions and
+            avoids long timeouts while DHCP clients try to renew leases
+            which are unknown to dnsmasq. Thanks to John Mastwijk for 
+           help with this.      
+
+           Added support to the DHCP option code to allow RFC-3397 
+           domain search DHCP option (119) to be sent.
+
+            Set NONBLOCK on all listening sockets to workaround non-POSIX
+            compliance in Linux 2.4 and 2.6. This fixes rare hangs which
+            occured when corrupted packets were received. Thanks to
+           Joris van Rantwijk for chasing that down.
+           Updated config.h for NetBSD. Thanks to Martin Lambers.
+
+            Do a better job of distinguishing between retransmissions
+           and new queries when forwarding. This fixes a bug
+           triggered by the polipo web cache which sends A and AAAA
+           queries both with the same transaction-ID. Thanks to 
+           Joachim Berdal Haga and Juliusz Chroboczek for help with this.
+
+           Rewrote cache code to store CNAMES, rather then chasing
+           them before storage. This eliminates bad situations when
+           clients get inconsistent views depending on if data comes
+           from the cache.
+
+           Allow for more than one --addn-hosts flag.
+
+           Clarify logged message when a DHCP lease clashes with an
+           /etc/hosts entry. Thanks to Mat Swift for the suggestion.
+
+           Added dynamic-dnsmasq from Peter Willis to the contrib
+           section.
+
+version 2.17
+           Correctly deduce the size of numeric dhcp-options, rather
+           than making wild guesses. Also cope with negative values.
+
+           Fixed use of C library reserved symbol "index" which broke
+           under certain combinations of library and compiler.
+
+           Make bind-interfaces work for IPv6 interfaces too.
+
+           Warn if an interface is given for listening which doesn't
+           currently exist when not in bind-interfaces mode. (This is
+           already a fatal error when bind-interfaces is set.)
+
+           Allow the --interface and --except-interface options to
+           take a comma-separated list of interfaces.
+
+           Tweak --dhcp-userclass matching code to work with the
+           ISC dhclient which violates RFC3004 unless its
+           configuration is very warped. Thanks to Cedric Duval for
+           the bug report. 
+
+           Allow more than one network-id tag in a dhcp-option. All
+           the tags must match to enable the option.
+
+           Added dhcp-ignore option to disable classes of hosts based
+           on network-id tags. Also allow BOOTP options to be
+           controlled by network tags.
+
+           Fill in sname, file and siaddr fields in replies to
+           DHCPINFORM messages.
+
+           Don't send NAK replies to DHCPREQUEST packets for disabled
+           clients. Credit to Cedric Duval for spotting this.
+
+           Fix rare crash associated with long DNS names and CNAME
+           records. Thanks to Holger Hoffstatte and especially Steve
+           Grecni for help chasing that one down.
+
+version 2.18
+            Reworked the Linux interface discovery code (again) to
+           cope with interfaces which have only IPv6 addresses and 
+           interfaces with more than one IPv6 address. Thanks to
+            Martin Pels for help with that.
+
+           Fix problems which occured when more than one dhcp-range
+           was specified in the same subnet: sometimes parameters
+           (lease time, network-id tag) from the wrong one would be
+           used. Thanks to Rory Campbell-Lange for the bug report.
+
+           Reset cache statistics when clearing the cache.
+
+           Enable long command line options on FreeBSD when the
+           C library supports them.
+
+version 2.19 
+            Tweaked the Linux-only interface discovery code to cope 
+           with interface-indexes larger than 8 bits in
+            /proc/net/if_inet6. This only affects Linux, obviously.  
+           Thanks to Richard Atterer for the bug report.
+
+           Check for under-length option fields in DHCP packets, a
+           zero length client-id, in particluar, could seriously
+           confuse dnsmasq 'till now. Thanks to Will Murname for help
+           with that.
+
+           If a DHCP-allocated address has an associated name in
+           /etc/hosts, and the client does not provide a hostname
+           parameter and there is no hostname in a matching dhcp-host
+           option, send the /etc/hosts name as the hostname in 
+           the DHCP lease. Thanks to Will Murname for the suggestion.
+
+version 2.20
+           Allow more than one instance of dnsmasq to run on a
+           machine, each providing DHCP service on a different
+           interface, provided that --bind-interfaces is set. This
+           configuration used to work, but regressed in version 2.14
+
+           Fix compilation on Mac OS X. Thanks to Kevin Bullock.
+       
+           Protect against overlong names and overlong
+           labels in configuration and from DHCP.
+
+           Fix interesting corner case in CNAME handling. This occurs
+           when a CNAME has a target which "shadowed" by a name in
+           /etc/hosts or from DHCP. Resolving the CNAME would sneak
+           the upstream value of the CNAME's target into the cache,
+           alongside the local value. Now that doesn't happen, though
+           resolving the CNAME still gives the unshadowed value. This
+           is arguably wrong but rather difficult to fix. The main
+           thing is to avoid getting strange results for the target
+           due to the cache pollution when resolving the
+           CNAME. Thanks to Pierre Habouzit for exploring the corner
+           and submitting a very clear bug report.
+
+           Fix subtle bug in the DNS packet parsing code. It's almost
+           impossible to describe this succinctly, but the one known
+           manifestation is the inability to cache the A record for
+           www.apple.com. Thanks to Bob Alexander for spotting that.
+
+           Support SRV records. Thanks to Robert Kean for the patches
+           for this.
+
+           Fixed sign confusion in the vendor-id matching code which
+           could cause crashes sometimes. (Credit to Mark Wiater for
+           help finding this.)
+
+           Added the ability to match the netid tag in a
+           dhcp-range. Combined with the ability to have multiple
+           ranges in a single subnet, this provides a means to
+           segregate hosts on different address ranges based on
+           vendorclass or userclass. Thanks to Mark Wiater for
+           prompting this enhancement.    
+
+           Added preference values for MX records.
+
+           Added the --localise-queries option.
+
+version 2.21
+            Improve handling of SERVFAIL and REFUSED errors. Receiving
+           these now initiates search for a new good server, and a 
+           server which returns them is not a candidate as a good
+            server. Thanks to Istvan Varadi for pointing out the
+            problem.
+
+           Tweak the time code in BROKEN_RTC mode.
+
+           Sanity check lease times in dhcp-range and dhcp-host
+           configurations and force them to be at least two minutes
+           (120s) leases shorter than a minute confuse some clients,
+           notably Apple MacOS X. Rory Campbell-Lange found this
+           problem.
+
+           Only warn once about an upstream server which is refusing to do
+           recursive queries.
+
+           Fix DHCP address allocation problem when netid tags are in
+           use. Thanks to Will Murnane for the bug report and
+           subsequent testing.
+
+           Add an additional data section to the reply for MX and SRV
+           queries. Add support for DNS TXT records. Thanks to Robert 
+           Kean and John Hampton for prompts and testing of these.
+
+           Apply address rewriting to records in the additional data section
+           of DNS packets. This makes things like MX records work
+           with the alias function. Thanks to Chad Skeeters for
+           pointing out the need for this.
+
+           Added support for quoted strings in config file.
+
+           Detect and defeat cache-poisoning attacks which attempt to
+           send (malicious) answers to questions we didn't
+           send. These are ignored now even if the attacker manages
+           to guess a random query-id.
+
+           Provide DHCP support for interfaces with multiple IP
+           addresses or aliases. This in only enabled under Linux.
+           See the FAQ entry for details.
+
+           Revisit the MAC-address and client-id matching code to
+           provide saner behaviour with PXE boots, where some
+           requests have a client-id and some don't.
+
+           Fixed off-by-one buffer overflow in lease file reading
+           code. Thanks to Rob Holland for the bug report.
+
+           Added wildcard matching for MAC addresses in dhcp-host
+           options. A sensible suggestion by Nathaniel McCallum.
+
+version 2.22
+            Fixed build problems on (many) systems with older libc
+            headers where <linux/types.h> is required before
+            <linux/netlink.h>. Enabled HAVE_RTNETLINK under uclibc now
+            that this fix is in place.
+
+           Added support for encapsulated vendor-class-specific DHCP
+           options. Thanks to Eric Shattow for help with this.
+
+           Fix regression in 2.21 which broke commas in filenames and
+           corrupted argv. Thanks to Eric Scott for the bugreport.
+
+           Fixed stupid thinko which caused dnsmasq to wedge during
+           startup with certain MX-record options. Another 2.21 regression.
+
+           Fixed broken-ness when reading /etc/ethers. 2.21 broke
+           this too.
+
+           Fixed wedge with certain DHCP options. Yet another 2.21
+           regression. Rob Holland and Roy Marples chased this one
+           down.
+
+version 2.23
+           Added a check to ensure that there cannot be more than one
+           dhcp-host option for any one IP address, even if the
+           addresses are assigned indirectly via a hostname and
+           /etc/hosts.
+
+           Include a "server identifier" in DHCPNAK replies, as
+           required by RFC2131.
+
+           Added method  support for DBus
+           (http://www.freedesktop.org/Software/dbus)
+           This is a superior way to re-configure dnsmasq on-the-fly
+           with different upstream nameservers, as the host moves
+           between networks. DBus support must be enabled in
+           src/config.h and should be considered experimental at this
+           point. See DBus-interface for the specification of the
+           DBus method calls supported.
+
+           Added information to the FAQ about setting the DNS domain
+           in windows XP and Mac OS X, thanks to Rick Hull.
+
+           Added sanity check to resolv.conf polling code to cope
+           with backwards-moving clocks. Thanks to Leonardo Canducci
+           for help with this.
+
+           Handle so-called "A-for-A" queries, which are queries for
+           the address associated with a name which is already a
+           dotted-quad address. These should be handled by the
+           resolver code, but sometimes aren't and there's no point
+           in forwarding them.
+
+           Added "no-dhcp-interface" option to disable DHCP service
+            on an interface, whilst still providing DNS.
+
+           Fix format-string problem - config file names get passed
+           to fprintf as a format string, so % characters could cause
+           crashes. Thanks to Rob Holland for sleuthing that one.
+
+           Fixed multiple compiler warnings from gcc 4. Thanks to 
+           Tim Cutts for the report.
+
+           Send the hostname option on DHCP offer messages as well as
+           DHCP ack messages. This is required by the Rio Digital 
+           Audio Receiver. Thanks to Ron Frederick for the patch.
+            Add 'd' (for day) as a possible time multiplier in lease 
+           time specifications. Thanks to Michael Deegan.
+
+           Make quoting suppress recognition of IP addresses, so
+           dhcp-option=66,1.2.3.4 now means something different to
+            dhcp-option=66,"1.2.3.4", which sets the option to a
+           string value. Thanks to Brian Macauley for the bug report.
+
+           Fixed the option parsing code to avoid segfaults from some
+           invalid configurations. Thanks to Wookey for spotting that one.
+            Provide information about which compile-time options were 
+           selected, both in the log at startup and as part of the output 
+            from dnsmasq --version. Thanks to Dirk Schenkewitz for 
+            the suggestion. 
+
+           Fix pathalogical behaviour when a broken client keeps sending
+            DHCPDISCOVER messages repeatedly and fast. Because dealing with
+            each of these takes a few seconds, (because of the ping) then a 
+           queue of DHCP packets could build up. Now, the results of a ping 
+            test are assumed to be valid for 30 seconds, so repeated waits are
+            not required. Thanks to Luca Landi for finding this.
+
+           Allow DHCPINFORM requests without hardware address
+           information. These are generated by some browsers, looking
+           for proxy information. Thanks to Stanley Jaddoe for the
+           bug report on that.
+
+           Add support of the "client FQDN" DHCP option. If present,
+           this is used to allow the client to tell dnsmasq its name,
+           in preference to (mis)using the hostname option. See 
+              http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/\
+                draft-ietf-dhc-fqdn-option-10.txt
+            for details of the draft spec.
+
+           Added startup scripts for MacOS X Tiger/Panther to the 
+            contrib collection. Thanks to Tim Cutts.
+
+           Tweak DHCP network selection so that clients which turn up
+           on our network in REBINDING state and with a lease for a
+           foreign network will get a NAK response. Thanks to Dan
+           Shechter for work on this and an initial patch and thanks
+           to Gyorgy Farkas for further testing.
+
+           Fix DNS query forwarding for empty queries and forward
+           queries even when the recursion-desired bit is clear. This
+           allows "dig +trace" to work. Problem report from Uwe
+           Gansert.
+
+           Added "const" declarations where appropriate, thanks to
+           Andreas Mohr for the patch.
+
+           Added --bootp-dynamic option and associated
+           functionality. Thanks to Josef Wolf for the suggestion.
+version 2.24
+            Updated contrib/openvpn/dnsmasq.patch from Joseph Tate.
+
+           Tweaked DHCP NAK code, a DHCP NAK is now unicast as a
+           fallback in cases where a broadcast is futile: namely in
+           response to a unicast REQUEST from a non-local network
+           which was not sent via a relay.
+
+           Slightly changed the semantics of domain matching in
+           --server and --address configs. --server=/domain.com/ still
+           matches domain.com and sub.domain.com but does not 
+           now match newdomain.com The semantics of 
+            --server=/.domain.com/ are unchanged. 
+           Thanks to Chris Blaise for the patch.
+
+           Added backwards-compatible internationalisation support.
+           The existing make targets, (all, dnsmasq, install) work as
+           before. New ones (all-i18n, and install-i18n) add gettext.
+           The translations live in po/ There are not too many
+           strings, so if anybody can provide translations (and for
+           the manpage....) please send them in.
+
+           Tweak behaviour on receipt of REFUSED or SERVFAIL rcodes,
+           now the query gets retried on all servers before returning
+           the error to the source of the query. Thanks to Javier
+           Kohen for the report.
+           Added Polish translation - thanks to Tomasz Sochanski.
+
+           Changed default manpage install location from /usr/man 
+           to /usr/share/man 
+
+           Added Spanish translation - thanks to Christopher Chatham.
+
+           Log a warning when a DHCP packet is truncated due to lack
+           of space. (Thanks to Michael Welle for the prompt to do
+           this.)
+           
+           Added French translation - thanks to Lionel Tricon.
+
+           Added Indonesian translation - thanks to Salman AS.
+
+           Tweaked the netlink code to cope with interface broadcast
+           address not set, or set to 0.0.0.0.
+
+           Fixed problem assigning fixed addresses to hosts when more
+           than one dhcp-range is available. Thanks to Sorin Panca
+           for help chasing this down.
+
+           Added more explict error mesages to the hosts file and
+           ethers file reading code. Markus Kaiserswerth suffered to
+           make this happen.
+
+           Ensure that a hostname supplied by a DHCP client can never
+           override one configured on the server. Previously, any
+           host claiming a name would be given it, even if that
+           over-rode a dhcp-host declaration, leading to potentially 
+            confusing situations.
+
+           Added Slackware package-build stuff into contrib/ The i18n
+           effort broke the current scripts, and working ones were
+           needed for testing, so they ended up here rather than make
+           Pat re-invent the wheel.
+           
+           Added Romanian translation, thanks to Sorin Panca for
+           that.
+
+version 2.25
+            Fixed RedHat spec file for FC4 - thanks to Werner Hoelzl
+            and Andrew Bird.
+
+            Fixed Suse spec file - thanks to Steven Springl.
+
+           Fixed DHCP bug when two distict subnets are on the same
+           physical interface. Thanks to Pawel Zawora for finding
+           this and suggesting the fix.
+
+           Added logging to make it explicit when dnsmasq falls back
+           from using RT-netlink sockets to the old ioctl API for
+           getting information about interfaces. Doing this
+           completely silently made remote debugging hard.
+
+           Merged uclibc build fixes from the OpenWRT package into
+           src/config.h 
+
+           Added Norwegian translation - thanks to Jan Erik Askildt.
+
+version 2.26
+           Fixed SuSe rpm patch problem - thanks to Steven Springl.
+
+           Fixed crash when attempting to send a DHCP NAK to a host
+           which believes it has a lease on an unknown
+           network. Thanks to Lutz Pressler for the bug report and
+           patch.
+
+version 2.27
+           Tweaked DHCP behaviour when a client attempts to renew a lease
+            which dnsmasq doesn't know about. Previously that would always
+            result in a DHCPNAK. Now, in dhcp-authoritative mode, the
+            lease will be created, if it's legal. This makes dnsmasq work
+            better if the lease database is lost, for example on an OpenWRT
+           system which reboots. Thanks to Stephen Rose for work on
+           this.
+
+           Added the ability to support RFC-3442 style destination
+           descriptors in dhcp-options. This makes classless static
+           routes easy to do, eg dhcp-option=121,192.168.1.0/24,1.2.3.4
+
+           Added error-checking to the code which writes the lease
+           file. If this fails for any reason, an error is logged,
+           and a retry occurs after one minute. This should improve
+           things eg when a filesystem is full. Thanks to Jens Holze
+           for the bug report.
+
+           Fixed breakage of the "/#/ matches any domain" facility
+           which happened in 2.24. Thanks to Peter Surda for the bug
+           report.
+
+           Use "size_t" and "ssize_t" types where appropriate in the
+           code.
+
+           Fix buggy CNAME handling in mixed IPv4 and IPv6
+           queries. Thanks to Andreas Pelme for help finding that.
+
+           Added some code to attempt to re-transmit DNS queries when 
+           a network interface comes up.  This helps on DoD links, 
+           where frequently the packet which triggers dialling is
+            a DNS query, which then gets lost. By re-sending, we can 
+           avoid the lookup failing. This function is only active
+           when netlink support is compiled in, and therefore only
+           under Linux. Thanks to Jean Wolter for help with this.
+
+           Tweaked the DHCP tag-matching code to work correctly with
+           NOT-tag conditions. Thanks to Lutz Pressler for finding
+           the bug.
+
+           Generalised netid-tag matching in dhcp-range statements to
+           allow more than one tag.
+
+           Added --dhcp-mac to do MAC address matching in the same
+           way as vendorclass and userclass matching. A good
+           suggestion from Lutz Pressler.
+
+           Add workaround for buggy early Microsoft DHCP clients
+           which need zero-termination in string options.
+           Thanks to Fabiano Pires for help with this.
+
+           Generalised the DHCP code to cope with any hardware
+           address type, at least on Linux. *BSD is still limited to
+           ethernet only.
+
+version 2.28
+            Eliminated all raw network access when running on
+            Linux. All DHCP network activity now goes through the IP
+            stack. Packet sockets are no longer required. Apart from
+            being a neat hack, this should also allow DHCP over IPsec
+            to work better. On *BSD and OS X, the old method of raw net
+            access through BPF is retained.
+
+           Simplified build options. Networking is now slimmed down
+           to a choice of "linux" or "other". Netlink is always used
+           under Linux. Since netlink has been available since 2.2
+           and non-optional in an IPv4-configured  kernel since 2.4,
+           and the dnsmasq netlink code is now well tested, this 
+           should work out fine. 
+
+           Removed decayed build support for libc5 and Solaris.
+           
+           Removed pselect code: use a pipe for race-free signal
+           handling instead, as this works everywhere.
+
+           No longer enable the ISC leasefile reading code in the
+           distributed sources. I doubt there are many people left
+           using this 1.x compatibility code. Those that are will
+           have to explicitly enable it in src/config.h.
+
+           Don't send the "DHCP maximum message size" option, even if 
+           requested. RFC2131 says this is a "MUST NOT".
+
+           Support larger-than-minimum DHCP message. Dnsmasq is now
+           happy to get larger than 576-byte DHCP messages, and will
+           return large messages, if permitted by the "maximum
+           message size" option of the message to which it is
+           replying. There's now an arbitrary sanity limit of 16384
+           bytes.
+
+           Added --no-ping option. This fixes an RFC2131 "SHOULD".
+
+           Building on the 2.27 MAC-address changes, allow clients to 
+           provide no MAC address at all, relying on the client-id as
+           a unique identifier. This should make things like DHCP for
+           USB come easier.
+
+           Fixed regression in netlink code under 2.2.x kernels which 
+           occurred in 2.27. Erik Jan Tromp is the vintage kernel fan 
+           who found this. P.S. It looks like this "netlink bind:
+           permission denied" problem occured in kernels at least as
+           late a 2.4.18. Good information from Alain Richoux.
+
+           Added a warning when it's impossible to give a host its
+           configured address because the address is leased
+           elsewhere.  A sensible suggestion from Mircea Bardac.
+
+           Added minimal support for RFC 3046 DHCP relay agent-id
+           options. The DHCP server now echoes these back to the
+           relay, as required by the RFC. Also, RFC 3527 link selection 
+           sub-options are honoured.
+
+           Set the process "dumpable" flag when running in debug
+           mode: this makes getting core dumps from root processes
+           much easier.
+           
+           Fixed one-byte buffer overflow which seems to only cause
+           problems when dnsmasq is linked with uclibc. Thanks to
+           Eric House and Eric Spakman for help in chasing this down.
+
+           Tolerate configuration screwups which lead to the DHCP
+           server attemping to allocate its own address to a
+           client; eg setting the whole subnet range as a DHCP
+           range. Addresses in use by the server are now excluded
+           from use by clients.
+
+           Did some thinking about HAVE_BROKEN_RTC mode, and made it
+           much simpler and better. The key is to just keep lease
+           lengths in the lease file. Since these normally never
+           change, even as the lease is renewed, the lease file never
+           needs to change except when machines arrive on the network
+           or leave. This eliminates the code for timed writes, and
+           reduces the amount of wear on a flash filesystem to the
+           absolute minimum. Also re-did the basic time function in
+           this mode to use the portable times(), rather than parsing
+           /proc/uptime.
+
+           Believe the source port number when replying to unicast 
+           DHCP requests and DHCP requests via a relay, instead of always 
+            using the standard ports.  This will allow relays on 
+            non-standard ports and DHCPINFORM from unprivileged ports
+            to work. The source port sent by unconfigured clients is still 
+            ignored, since this may be unreliable. This means that a DHCP 
+            client must use the standard port to do full configuration.
+version 2.29
+           Fixed compilation on OpenBSD (thanks to Tom Hensel for the
+           report). 
+
+           Fixed false "no interface" errors when --bind-interfaces is
+           set along with --interface=lo or --listen-address. Thanks
+           to Paul Wise for the report.
+
+           Updated patch for SuSE rpm. Thanks to Steven Springl.
+
+           It turns out that there are some Linux kernel
+           configurations which make using the capability system
+           impossible. If this situation occurs then continue, running
+           as root, and log a warning. Thanks to Scott Wehrenberg
+           for help tracking this down.
+
+version 2.30
+            Fixed crash when a DHCP client requested a broadcast
+            reply. This problem was introduced in version 2.28.
+           Thanks to Sandra Dekkers for the bug report.
+
+version 2.31
+           Added --dhcp-script option. There have been calls for this
+           for a long time from many good people. Fabio Muzzi gets
+           the prize for finally convincing me.
+
+           Added example dbus config file and moved dbus stuff into
+           its own directory.
+
+           Removed horribly outdated Redhat RPM build files. These
+           are obsolete now that dnsmasq in in Fedora extras. Thanks
+           to Patrick "Jima" Laughton, the Fedora package
+           maintainer.
+
+           Added workaround for Linux kernel bug. This manifests
+           itself as failure of DHCP on kernels with "support for
+           classical IP over ATM" configured. That includes most
+           Debian kernel packages. Many thanks to A. Costa and
+           Benjamin Kudria for their huge efforts in chasing this
+           down.
+
+           Force-kill child processes when dnsmasq is sent a sigterm,
+           otherwise an unclosed TCP connection could keep dnsmasq
+           hanging round for a few minutes.
+
+           Tweaked config.h logic for uclibc build. It will now pick
+           up MMU and IPV6 status correctly on every system I tested.
+
+version 2.32 
+           Attempt a better job of replacing previous configuration
+           when re-reading /etc/hosts and /etc/ethers. SIGHUP is
+           still not identical to a restart under all circumstances,
+           but it is for the common case of name->MAC address in
+           /etc/ethers and name->IP address in /etc/hosts.
+
+           Fall back to broadcast for DHCP to an unconfigured client
+           when the MAC address size is greater than 14 bytes.
+
+           Fix problem in 2.28-onwards releases which breaks DNS on
+           Mac OS X. Thanks to Doug Fields for the bug report and
+           testing.
+
+           Added fix to allow compilation on c89-only compilers.
+           Thanks to John Mastwijk for the patch.
+          
+           Tweak resolv file polling code to work better if there is
+           a race between updating the mtime and file contents. This
+           is not normally a problem, but it can be on systems which
+           replace nameservers whilst active. The code now continues
+           to read resolv.conf until it gets at least one usable
+           server. Thanks to Holger Mauermann for help with this.
+
+           If a client DECLINEs an address which is allocated to it
+           via dhcp-host or /etc/hosts, lock that address out of use
+           for ten minutes, instead of forever, and log when it's not
+           being used because of the lock-out. This should provide
+           less surprising behaviour when a configured address can't be
+           used. Thanks to Peter Surda and Heinz Deinhart for input
+           on this.
+
+           Fixed *BSD DHCP breakage with only some
+           arches/compilers, depending on structure padding rules.
+           Thanks to Jeb Campbell and Tom Hensel for help with this.
+
+           Added --conf-dir option. Suggestion from Aaron Tygart.
+
+           Applied patch from Brent Cook which allows netids in
+           dhcp-option configuration lines to be prefixed by
+           "net:". This is not required by the syntax, but it is
+           consistent with other configuration items.
+
+           Added --log-facility option. Suggestion from Fabio Muzzi.
+
+           Major update to Spanish translation. Many thanks to Chris
+           Chatham. 
+
+           Fixed gcc-4.1 strict-alias compilation warning.
+
+version 2.33
+            Remove bash-specific shellcode from the Makefile.
+
+           Fix breakage with some DHCP relay implementations which
+           was introduced in 2.28. Believing the source port in
+           DHCP requests and sending the reply there is sometimes a
+           bad thing to do, so I've reverted to always sending to
+           the relay on port 68. Thanks to Daniel Hamlin and Alex
+           (alde) for bug reports on this.
+
+           Moved the SuSe packaging files to contrib. I will no
+           longer attempt to maintain this in the source tarball. It
+           will be done externally, in the same way as packaging for
+           other distros. Suse packages are available from 
+           ftp://ftp.suse.com/pub/people/ug/
+           
+           Merged patch from Gentoo to honour $LDFLAGS environment.
+
+           Fix bug in resolv.conf processing when more than one file
+           is being checked.
+
+           Add --dns-forward-max option.
+
+           Warn if --resolv-file flags are ignored because of
+           --no-resolv. Thanks to Martin F Krafft for spotting this
+           one.
+
+            Add --leasefile-ro option which allows the use of an 
+            external lease database. Many thanks to Steve Horbachuk 
+           for assistance developing this feature.
+
+           Provide extra information to lease-change script via its
+           environment. If the host has a client-id, then
+           DNSMASQ_CLIENT_ID will be set. Either the lease length (in
+           DNSMASQ_LEASE_LENGTH) or lease expiry time (in
+           DNSMASQ_LEASE_EXPIRES) will be set, depending on the
+           HAVE_BROKEN_RTC compile-time option. This extra
+           information should make it possible to maintain the lease
+           database in external storage such as LDAP or a relational
+           database. Note that while leasefile-ro is set, the script
+            will be called with "old"  events more often, since 
+           changes to the client-id and lease length
+           (HAVE_BROKEN_RTC) or lease expiry time (otherwise) 
+           are now flagged. 
+
+           Add contrib/wrt/* which is an example implementation of an
+           external persistent lease database for *WRT distros with 
+           the nvram command.
+
+           Add contrib/wrt/dhcp_release.c which is a small utility 
+           which removes DHCP leases using DHCPRELEASE operation in
+           the DHCP protocol.
+
+version 2.34
+           Tweak network-determination code for another corner case:
+           in this case a host forced to move between dhcp-ranges on
+           the same physical interface. Thanks to Matthias Andree.
+           
+           Improve handling of high DNS loads by throttling acceptance of
+           new queries when resources are tight. This should be a
+           better response than the "forwarding table full..."
+           message which was logged before.
+
+           Fixed intermittent infinite loop when re-reading
+           /etc/ethers after SIGHUP. Thanks to Eldon Ziegler for the
+           bug report.
+
+           Provide extra information to the lease-change script: when
+           a lease loses its hostname (because a new lease comes
+           along and claims the same new), the "old" action is called 
+           with the current state of the lease, ie no name. The
+           change is to provide the former name which the lease had
+           in the environment variable DNSMASQ_OLD_HOSTNAME. This
+           helps scripts which do stuff based on hostname, rather
+           than IP address. Also provide vendor-class and user-class
+           information to the lease-change script when a new lease is
+           created in the DNSMASQ_VENDOR_CLASS and
+           DNSMASQ_USER_CLASS<n> environment variables. Suggestion 
+            from Francois-Xavier Le Bail.
+
+           Run the lease change script as root, even when dnsmasq is
+           configured to change UID to an unprivileged user. Since
+           most uses of the lease change script need root, this
+           allows its use whilst keeping the security advantages of
+           running the daemon without privs. The script is invoked
+           via a small helper process which keeps root UID, and
+           validates all data received from the main process. To get
+           root, an attacker would have to break dnsmasq and then
+           break the helper through the restricted comms channel 
+           linking the two.
+           
+           Add contrib/port-forward/* which is a script to set up 
+           port-forwards using the DHCP lease-change script. It's
+           possible to add a host to a config file by name, and when
+           that host gets a DHCP lease, the script will use iptables
+           to set up port-forwards to configured ports at the address
+           which the host is allocated. The script also handles
+           setting up the port-forward iptables entries after reboot,
+           using the persistent lease database, and removing them
+           when a host leaves and its DHCP lease expires.
+
+           Fix unaligned access problem which caused wrong log
+           messages with some clients on some architectures. Thanks
+           to Francois-Xavier Le Bail for the bugreport.
+
+           Fixed problem with DHCPRELEASE and multi-address
+           interfaces. Enhanced contrib/wrt/dhcp_release to cope
+           under these circumstances too. Thanks to Eldon Ziegler for
+           input on this.
+
+           Updated French translation: thanks to Gildas Le Nadan.
+
+           Upgraded the name hash function in the DNS cache. Thanks
+           to Oleg Khovayko for good work on this.
+
+           Added --clear-on-reload flag.  Suggestion from Johannes
+           Stezenbach.
+
+           Treat a nameserver address of 0.0.0.0 as "nothing". Erwin 
+            Cabrera spotted that specifying a nameserver as 0.0.0.0 
+           breaks things badly; this is because the network stack
+           treats is as "this host" and an endless loop ensues.
+                  
+            Added Webmin module in contrib/webmin. Thanks to Neil
+            Fisher for that.
+
+version 2.35
+           Generate an "old" script event when a client does a DHCPREQUEST
+           in INIT-REBOOT or SELECTING state and the lease already
+           exists. Supply vendor and user class information to these
+           script calls.
+
+           Added support for Dragonfly BSD to src/config.h
+
+           Removed "Upgrading to 2.0" document, which is ancient
+           history now.
+
+           Tweak DHCP networking code for BSD, esp OpenBSD. Added a 
+           workaround for a bug in OpenBSD 4.0: there should finally
+            be support for multiple interfaces under OpenBSD now.
+           Note that no version of dnsmasq before 2.35 will work for 
+           DHCP under OpenBSD 4.0 because of a kernel bug.
+           Thanks to Claudio Jeker, Jeb Campbell and Cristobal 
+           Palmer for help with this.
+
+           Optimised the cache code for the case of large
+           /etc/hosts. This is mainly to remove the O(n-squared)
+           algorithm which made reading large (50000 lines) files 
+           slow, but it also takes into account the size of 
+           /etc/hosts when building hash tables, so overall 
+           performance should be better. Thanks to "koko" for 
+           pointing out the problem.
+
+version 2.36
+           Added --dhcp-ignore-names flag which tells dnsmasq not to
+           use names provided by DHCP clients. Suggestion from 
+           Thomas M Steenholdt.
+
+           Send netmask and broadcast address DHCP options always,
+           even if the client doesn't request them. This makes a few
+           odd clients work better.
+
+           Added simple TFTP function, optimised for net-boot. It is
+           now possible to net boot hosts using only dnsmasq. The
+           TFTP server is read-only, binary-mode only, and designed to be
+           secure; it adds about 4K to the dnsmasq binary. 
+           Support DHCP option 120, SIP servers, (RFC 3361). Both
+            encodings are supported, so both --dhcp-option=120,192.168.2.3
+            and        --dhcp-option=120,sip.example.net will work. Brian
+            Candler pointed out the need for this.
+
+           Allow spaces in domain names, to support DNS-SD.
+
+           Add --ptr-record flag, again for DNS-SD. Thanks to Stephan 
+           Sokolow for the suggestion.
+           
+           Tolerate leading space on lines in the config file. Thanks
+           to Luigi Rizzo for pointing this out.
+
+           Fixed netlink.c to cope with headers from the Linux 2.6.19
+           kernel. Thanks to Philip Wall for the bug report.
+
+           Added --dhcp-bridge option, but only to the FreeBSD
+           build. This fixes an oddity with a a particular bridged
+           network configuration on FreeBSD. Thanks to Luigi Rizzo
+           for the patch.
+
+           Added FAQ entry about running dnsmasq in a Linux
+           vserver. Thanks to Gildas le Nadan for the information.  
+
+           Fixed problem with option parsing which interpreted "/" as
+           an address and not a string. Thanks to Luigi Rizzo
+           for the patch.
+
+           Ignore the --domain-needed flag when forwarding NS
+           and SOA queries, since NS queries of TLDs are always legit.
+           Marcus Better pointed out this problem.
+
+           Take care to forward signed DNS requests bit-perfect, so
+           as not to affect the validity of the signature. This
+           should allow DDNS updates to be forwarded.
+
+version 2.37
+            Add better support for RFC-2855 DHCP-over-firewire and RFC
+           -4390 DHCP-over-InfiniBand. A good suggestion from Karl Svec.
+
+           Some efficiency tweaks to the cache code for very large
+           /etc/hosts files. Should improve reverse (address->name)
+           lookups and garbage collection. Thanks to Jan 'RedBully'
+           Seiffert for input on this.
+
+           Fix regression in 2.36 which made bogus-nxdomain
+           and DNS caching unreliable. Thanks to Dennis DeDonatis
+           and Jan Seiffert for bug reports.
+
+           Make DHCP encapsulated vendor-class options sane. Be
+           warned that some conceivable existing configurations 
+           using these may break, but they work in a much 
+           simpler and more logical way now. Prepending
+           "vendor:<client-id>" to an option encapsulates it 
+           in option 43, and the option is sent only if the 
+           client-supplied vendor-class substring-matches with 
+           the given client-id. Thanks to Dennis DeDonatis for 
+           help with this.
+
+           Apply patch from Jan Seiffert to tidy up tftp.c
+
+           Add support for overloading the filename and servername 
+           fields in DHCP packet. This gives extra option-space when
+           these fields are not being used or with a modern client
+           which supports moving them into options.
+
+           Added a LIMITS section to the man-page, with guidance on
+           maximum numbers of clients, file sizes and tuning.
+
+release 2.38
+           Fix compilation on *BSD. Thanks to Tom Hensel.
+
+           Don't send length zero DHCP option 43 and cope with 
+           encapsulated options whose total length exceeds 255 octets
+           by splitting them into multiple option 43 pieces.
+
+           Avoid queries being retried forever when --strict-order is
+           set and an upstream server returns a SERVFAIL
+           error. Thanks to Johannes Stezenbach for spotting this.
+
+           Fix BOOTP support, broken in version 2.37.
+
+           Add example dhcp-options for Etherboot.
+
+           Add \e (for ASCII ESCape) to the set of valid escapes
+           in config-file strings.
+
+           Added --dhcp-option-force flag and examples in the
+           configuration file which use this to control PXELinux.
+
+           Added --tftp-no-blocksize option.
+
+           Set netid tag "bootp" when BOOTP (rather than DHCP) is in
+           use. This makes it easy to customise which options are
+           sent to BOOTP clients. (BOOTP allows only 64 octets for
+           options, so it can be necessary to trim things.)
+
+           Fix rare hang in cache code, a 2.37 regression. This
+           probably needs an infinite DHCP lease and some bad luck to
+           trigger. Thanks to Detlef Reichelt for bug reports and testing.
+
+release 2.39
+           Apply patch from Mike Baker/OpenWRT to ensure that names
+           like "localhost." in /etc/hosts with trailing period 
+           are treated as fully-qualified.
+
+           Tolerate and ignore spaces around commas in the
+           configuration file in all circumstances. Note that this
+           may change the meaning of a few existing config files, for
+           instance
+           txt-record=mydomain.com, string
+           would have a leading space in the string before, and now
+           will not. To get the old behaviour back, use quotes:
+           txt-record=mydomain.com," string"
+
+           /a is no longer a valid escape in quoted strings.
+
+           Added symbolic DHCP option names. Instead of
+           dhcp-option = 3, 1.2.3.4 
+           it is now possible to do
+           dhcp-option = option:router, 1.2.3.4
+           To see the list of known DHCP options, use the 
+            command "dnsmasq --help dhcp"
+           Thanks to Luigi Rizzo for a patch and good work on this.
+
+           Overhauled the log code so that logging can be asynchronous; 
+           dnsmasq then no longer blocks waiting for the syslog() library
+           call. This is important on systems where syslog
+           is being used to log over the network (and therefore doing
+           DNS lookups) and syslog is using dnsmasq as its DNS
+           server. Having dnsmasq block awaiting syslog under 
+           such circumstances can lead to syslog and dnsmasq 
+           deadlocking. The new behaviour is enabled with a new
+            --log-async flag, which can also be used to tune the
+           queue length. Paul Chambers found and diagnosed 
+           this trap for the unwary. He also did much testing of 
+           the solution along with Carlos Carvalho.
+
+           --log-facility can now take a file-name instead of a 
+           facility name. When this is done, dnsmasq logs to the 
+           file and not via syslog. (Failures early in startup, 
+           whilst reading configuration, will still go to syslog, 
+           and syslog is used as a log-of-last-resort if the file
+           cannot be written.)
+
+           Added --log-dhcp flag. Suggestion from Carlos Carvalho.
+
+           Made BINDIR, MANDIR and LOCALEDIR independently
+           over-rideable in the makefile. Suggestion from Thomas
+           Klausner.
+
+           Added 127.0.0.0/8 and 169.254.0.0/16 to the address
+           ranges affected by --bogus-priv. Thanks to  Paul 
+           Chambers for the patch.
+
+           Fixed failure of TFTP server with --listen-address. Thanks
+           to William Dinkel for the bug report.
+
+           Added --dhcp-circuitid and --dhcp-remoteid for RFC3046
+           relay agent data matching.
+           Added --dhcp-subscrid for RFC3993 subscriber-id relay
+           agent data matching.
+
+           Correctly garbage-collect connections when upstream
+           servers go away as a result of DBus transactions.
+
+           Allow absolute paths for TFTP transfers even when
+           --tftp-root is set, as long as the path matches the root,
+           so /var/ftp/myfile is OK with tftp-root=/var/ftp.
+           Thanks for Thomas Mizzi for the patch.
+
+           Updated Spanish translation - thanks to Chris Chatham.
+
+           Updated French translation - thanks to Gildas Le Nadan.
+
+           Added to example conf file example of routing PTR queries
+           for a subnet to a different nameserver. Suggestion from
+           Jon Nicholson.
+
+           Added --interface-name option. This provides a facility 
+           to add a domain name with a dynamic IP address taken from
+           the address of a local network interface. Useful for
+           networks with dynamic IPs.
+
+version 2.40
+            Make SIGUSR2 close-and-reopen the logfile when logging 
+           direct to a file. Thanks to Carlos Carvalho for 
+           suggesting this. When a logfile is created, change
+           its ownership to the user dnsmasq will run as, don't
+           leave it owned by root.
+
+           Set a special tag, "known" for hosts which are matched by
+           a dhcp-host or /etc/ethers line. This is especially
+           useful to be able to do --dhcp-ignore=#known, like ISCs
+           "deny unknown-clients".
+
+           Explicitly set a umask before creating the leases file,
+           rather than relying on whatever we inherited. The
+           permissions are set to 644.
+
+           Fix handling of fully-qualified names in --dhcp-host
+           directives and in /etc/ethers. These are now rejected 
+           if the domain doesn't match that given by --domain,   
+           and used correctly otherwise. Before, putting
+           a FQDN here could cause the whole FQDN to be used as
+           hostname. Thanks to Michael Heimpold for the bug report.
+
+           Massive but trivial edit to make the "daemon" variable 
+           global, instead of copying the same value around as the
+           first argument to half the functions in the program.
+           
+           Updated Spanish manpage and message catalog. Thanks 
+           to Chris Chatham.
+           
+           Added patch for support of DNS LOC records in
+           contrib/dns-loc. Thanks to Lorenz Schori.
+
+           Fixed error in manpage: dhcp-ignore-name ->
+           dhcp-ignore-names. Thanks to Daniel Mentz for spotting
+           this.
+
+           Use client-id as hash-seed for DHCP address allocation
+           with Firewire and Infiniband, as these don't supply an MAC
+           address. 
+
+           Tweaked TFTP file-open code to make it behave sensibly
+           when the filesystem changes under its feet.
+
+           Added DNSMASQ_TIME_REMAINING environment variable to the 
+           lease-script.
+
+           Always send replies to DHCPINFORM requests to the source
+           of the request and not to the address in ciaddr. This
+           allows third-party queries.
+           
+           Return "lease time remaining" in the reply to a DHCPINFORM
+           request if there exists a lease for the host sending the
+           request.
+
+           Added --dhcp-hostsfile option. This gives a superset of
+           the functionality provided by /etc/ethers. Thanks to 
+           Greg Kurtzer for the suggestion.
+
+           Accept keyword "server" as a synonym for "nameserver" in 
+           resolv.conf. Thanks to Andrew Bartlett for the report.
+
+           Add --tftp-unique-root option. Suggestion from Dermot
+           Bradley.
+
+           Tweak TFTP retry timer to avoid problems with difficult
+           clients. Thanks to Dermot Bradley for assistance with
+           this. 
+           
+           Continue to use unqualified hostnames provided by DHCP
+           clients, even if the domain part is illegal. (The domain
+           is  ignored, and an error logged.) Previously in this
+           situation, the whole name whould have been
+           rejected. Thanks to Jima for the patch.
+           
+           Handle EINTR returns from wait() correctly and reap
+           our children's children if necessary. This fixes 
+           a problem with zombie-creation under *BSD when using
+           --dhcp-script.
+
+           Escape spaces in hostnames when they are stored in the
+           leases file and passed to the lease-change
+           script. Suggestion from Ben Voigt.
+
+           Re-run the lease chamge script with an "old" event for
+           each lease when dnsmasq receives a SIGHUP.
+
+           Added more useful exit codes, including passing on a
+           non-zero exit code from the lease-script "init" call when
+           --leasefile-ro is set.
+
+           Log memory allocation failure whilst the daemon is
+           running. Allocation failures during startup are fatal, 
+           but lack of memory whilst running is worked around.
+           This used to be silent, but now is logged.
+
+           Fixed misaligned memory access which caused problems on
+           Blackfin CPUs. Thanks to Alex Landau for the patch.
+
+           Don't include (useless) script-calling code when NO_FORK
+           is set. Since this tends to be used on very small uclinux 
+           systems, it's worth-while to save some code-size.
+
+           Don't set REUSEADDR on TFTP listening socket. There's no
+           need to do so, and it creates confusing behaviour when
+           inetd is also listening on the same port. Thanks to Erik
+           Brown for spotting the problem.
+
+version 2.41
+            Remove deprecated calls when compiled against libdbus 1.1.
+           
+           Fix "strict-alias" warning in bpf.c
+
+           Reduce dependency on Gnu-make in build system: dnsmasq now
+           builds with system make under OpenBSD.
+
+           Port to Solaris. Dnsmasq 1.x used to run under Solaris,
+           and this release does so again, for Solaris 9 or better.
+
+           Allow the DNS function to be completely disabled, by
+           setting the port to zero "--port=0". The allows dnsmasq to
+           be used as a simple DHCP server, simple TFTP server, or
+           both, but without the DNS server getting in the way.
+
+           Fix a bug where NXDOMAIN could be returned for a query
+           even if the name's value was known for a different query
+           type. This bug could be prodded with 
+            --local=/domain/ --address=/name.domain/1.2.3.4 
+           An IPv6 query for name.domain would return NXDOMAIN, and
+           not the correct NOERROR. Thanks to Lars Nooden for
+           spotting the bug and Jima for diagnosis of the problem.
+
+           Added per-server stats to the information logged when
+           dnsmasq gets SIGUSR1.
+
+           Added counts of queries forwarded and queries answered
+           locally (from the cache, /etc/hosts or config).
+
+           Fixed possible crash bug in DBus IPv6 code. Thanks to Matt
+           Domsch and Jima.
+
+           Tighten checks for clashes between hosts-file and
+           DHCP-derived names. Multiple addresses associated with a
+           name in hosts-file no longer confuses the check.
+
+           Add --dhcp-no-override option to fix problems with some
+           combinations of stage zero and stage one
+           bootloaders. Thanks to Steve Alexander for the bug report.
+  
+           Add --tftp-port-range option. Thanks to Daniel Mierswa for
+           the suggestion.
+           Add --stop-dns-rebind option. Thanks to Collin Mulliner
+           for the patch.
+
+           Added GPL version 3 as a license option.
+           Added --all-servers option. Thanks to Peter Naulls for the
+           patch.
+
+           Extend source address mechanism so that the interface used
+           to contact an upstream DNS server can be nailed
+           down. Something like "--server=1.2.3.4@eth1" will force
+           the use of eth1 for traffic to DNS-server 1.2.3.4. This
+           facility is only available on Linux and Solaris. Thanks to
+           Peter Naulls for prompting this.         
+       
+           Add --dhcp-optsfile option. Thanks to Carlos Carvalho for
+            the suggestion.
+
+           Fixed failure to set source address for server connections
+           when using TCP. Thanks to Simon Capper for finding this
+           bug.
+
+           Refuse to give a DHCP client the address it asks for if
+           the address range in question is not available to that
+           particular host. Thanks to Cedric Duval for the bug
+           report. 
+
+           Changed behavior of DHCP server to always return total length of
+           a new lease in DHCPOFFER, even if an existing lease
+           exists. (It used to return the time remaining on the lease
+           whne one existed.) This fixes problems with the Sony Ericsson
+           K610i phone. Thanks to Hakon Stordahl for finding and
+           fixing this.
+
+           Add DNSMASQ_INTERFACE to the environment of the
+           lease-change script. Thanks to Nikos Mavrogiannopoulos for
+           the patch.
+
+           Fixed broken --alias functionality. Thanks to Michael
+           Meelis for the bug report.
+
+           Added French translation of the man page. Thank to Gildas
+           Le Nadan for that.
+
+           Add --dhcp-match flag, to check for arbitrary options in
+           DHCP messages from clients. This enables use of dnsmasq
+           with gPXE. Thanks to Rance Hall for the suggestion.
+
+           Added --dhcp-broadcast, to force broadcast replies to DHCP
+           clients which need them but are too dumb or too old to
+           ask. Thanks to Bodo Bellut for the suggestion.
+
+           Disable path-MTU discovery on DHCP and TFTP sockets. This
+           is never needed, and the presence of DF flags in the IP
+           header confuses some broken PXE ROMS. Thanks again to Bodo
+           Bellut for spotting this.
+
+           Fix problems with addresses which have multiple PTR
+           records - all but one of these could get lost. 
+
+           Fix bug with --address and ANY query type seeing REFUSED
+           return code in replies. Thanks to Mike Wright for spotting
+           the problem.
+
+           Update Spanish translation. Thanks to Chris Chatham.
+
+           Add --neg-ttl option.
+           
+           Add warnings about the bad effects of --filterwin2k on
+           SIP, XMPP and Google-talk to the example config file.
+           
+           Fix va_list abuse in log.c. This fixes crashes on powerpc
+           when debug mode is set. Thanks to Cedric Duval for the
+           patch. 
+
+version 2.42
+            Define _GNU_SOURCE to avoid problems with later glibc
+            headers. Thanks to Jima for spotting the problem.
+
+           Add --dhcp-alternate-port option. Thanks to Jan Psota for
+           the suggestion.
+
+           Fix typo in code which is only used on BSD, when Dbus and
+           IPv6 support is enabled. Thanks to Roy Marples.
+           
+           Updated Polish translations - thank to Jan Psota.
+
+           Fix OS detection logic to cope with GNU/FreeBSD.
+
+           Fix unitialised variable in DBus code - thanks to Roy
+           Marples.
+
+           Fix network enumeration code to work on later NetBSD -
+           thanks to Roy Marples.
+           
+           Provide --dhcp-bridge on all BSD variants.
+
+           Define _LARGEFILE_SOURCE which removes an arbitrary 2GB
+            limit on logfiles. Thanks to Paul Chambers for spotting 
+            the problem.
+
+           Fix RFC3046 agent-id echo code, broken for many
+           releases. Thanks to Jeremy Laine for spotting the problem
+           and providing a patch.
+
+           Added Solaris 10 service manifest from David Connelly in
+           contrib/Solaris10
+                    
+           Add --dhcp-scriptuser option.           
+
+           Support new capability interface on suitable Linux 
+           kernels, removes "legacy support in use" messages. Thanks 
+            to Jorge Bastos for pointing this out. 
+
+           Fix subtle bug in cache code which could cause dnsmasq to
+           lock spinning CPU in rare circumstances. Thanks to Alex
+           Chekholko for bug reports and help debugging. 
+
+           Support netascii transfer mode for TFTP.
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..25e9554
--- /dev/null
@@ -0,0 +1,60 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(dnsmasq C)
+
+SET(SRCS       src/bpf.c
+               src/cache.c
+               src/dbus.c
+               src/dhcp.c
+               src/dnsmasq.c
+               src/forward.c
+               src/helper.c
+               src/lease.c
+               src/log.c
+               src/netlink.c
+               src/network.c
+               src/option.c
+               src/rfc1035.c
+               src/rfc2131.c
+               src/tftp.c
+               src/util.c
+   )
+
+SET(VENDOR "samsung")
+SET(PACKAGE ${PROJECT_NAME})
+SET(PKGNAME ${PACKAGE})
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(BINDIR "${PREFIX}/bin")
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+       SET(CMAKE_BUILD_TYPE "Release")
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+#INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED dbus-1)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"")
+ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"")
+ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"")
+ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+#IF("${ARCH}" STREQUAL "arm")
+#      ADD_DEFINITIONS("-D_MMICHECK_ARM_CODE_")
+#ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..60549be
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/COPYING-v3 b/COPYING-v3
new file mode 100644 (file)
index 0000000..94a9ed0
--- /dev/null
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/FAQ b/FAQ
new file mode 100644 (file)
index 0000000..a930516
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,482 @@
+Q: Why does dnsmasq open UDP ports >1024 as well as port 53.
+   Is this a security problem/trojan/backdoor?
+
+A: The high ports that dnsmasq opens are for replies from the upstream
+   nameserver(s). Queries from dnsmasq to upstream nameservers are sent
+   from these ports and replies received to them. The reason for doing this is
+   that most firewall setups block incoming packets _to_ port 53, in order
+   to stop DNS queries from the outside world. If dnsmasq sent its queries
+   from port 53 the replies would be _to_ port 53 and get blocked.
+
+   This is not a security hole since dnsmasq will only accept replies to that
+   port: queries are  dropped. The replies must be to oustanding queries
+   which dnsmasq has forwarded, otherwise they are dropped too.
+   Addendum: dnsmasq now has the option "query-port" (-Q), which allows
+   you to specify the UDP port to be used for this purpose.  If not
+   specified, the operating system will select an available port number
+   just as it did before.
+
+   Second addendum: following the discovery of a security flaw in the
+   DNS protocol, dnsmasq from version 2.43 has changed behavior. It
+   now uses a new, randomly selected, port for each query. The old
+   default behaviour (use one port allocated by the OS) is available by
+   setting --query-port=0, and setting the query port to a positive
+   value is still works. You should think hard and know what you are
+   doing before using either of these options.
+Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify
+   that?
+
+A: Update: from version 2.10, it does. There are a few limitations:
+   data obtained via TCP is not cached, and source-address
+   or query-port specifications are ignored for TCP.
+
+Q: When I send SIGUSR1 to dump the contents of the cache, some entries have
+   no IP address and are for names like mymachine.mydomain.com.mydomain.com.
+   What are these?
+
+A: They are negative entries: that's what the N flag means. Dnsmasq asked 
+   an upstream nameserver to resolve that address and it replied "doesn't 
+   exist, and won't exist for <n> hours" so dnsmasq saved that information so
+   that if _it_ gets asked the same question it can answer directly without
+   having to go back to the upstream server again. The strange repeated domains
+   result from the way resolvers search short names. See "man resolv.conf" for
+   details.
+
+
+Q: Will dnsmasq compile/run on non-Linux systems?
+
+A: Yes, there is explicit support for *BSD and MacOS X and Solaris. 
+   There are start-up scripts for MacOS X Tiger and Panther 
+   in /contrib. Dnsmasq will link with uclibc to provide small
+   binaries suitable for use in embedded systems such as
+   routers. (There's special code to support machines with flash
+   filesystems and no battery-backed RTC.)
+   If you encounter make errors with *BSD, try installing gmake from
+   ports and building dnsmasq with "make MAKE=gmake" 
+   For other systems, try altering the settings in config.h.
+Q: My company's nameserver knows about some names which aren't in the
+   public DNS. Even though I put it first in /etc/resolv.conf, it
+   dosen't work: dnsmasq seems not to use the nameservers in the order
+   given. What am I doing wrong?
+
+A: By default, dnsmasq treats all the nameservers it knows about as
+   equal: it picks the one to use using an algorithm designed to avoid 
+   nameservers which aren't responding. To make dnsmasq use the
+   servers in order, give it the -o flag. If you want some queries
+   sent to a special server, think about using the -S flag to give the
+   IP address of that server, and telling dnsmasq exactly which
+   domains to use the server for.
+
+Q: OK, I've got queries to a private nameserver working, now how about 
+   reverse queries for a range of IP addresses?
+
+A: Use the standard DNS convention of <reversed address>.in-addr.arpa.
+   For instance to send reverse queries on the range 192.168.0.0 to 
+   192.168.0.255 to a nameserver at 10.0.0.1 do
+   server=/0.168.192.in-addr.arpa/10.0.0.1
+   Note that the "bogus-priv" option take priority over this option,
+   so the above will not work when the bogus-priv option is set.
+
+Q: Dnsmasq fails to start with an error like this: "dnsmasq: bind
+   failed: Cannot assign requested address". What's the problem?
+
+A: This has been seen when a system is bringing up a PPP interface at
+   boot time: by the time dnsmasq start the interface has been
+   created, but not brought up and assigned an address. The easiest
+   solution is to use --interface flags to specify which interfaces
+   dnsmasq should listen on. Since you are unlikely to want dnsmasq to
+   listen on a PPP interface and offer DNS service to the world, the
+   problem is solved.
+
+Q: I'm running on BSD and dnsmasq won't accept long options on the
+   command line. 
+
+A: Dnsmasq when built on some BSD systems doesn't use GNU getopt by
+   default. You can either just use the single-letter options or
+   change config.h and the Makefile to use getopt-long. Note that
+   options in /etc/dnsmasq.conf must always be the long form,
+   on all platforms.
+
+Q: Names on the internet are working fine, but looking up local names 
+   from /etc/hosts or DHCP doesn't seem to work.
+
+A: Resolver code sometime does strange things when given names without
+   any dots in. Win2k and WinXP may not use the DNS at all and just
+   try and look up the name using WINS. On unix look at "options ndots:"
+   in "man resolv.conf" for details on this topic. Testing lookups
+   using "nslookup" or "dig" will work, but then attempting to run
+   "ping" will get a lookup failure, appending a dot to the end of the
+   hostname  will fix things. (ie "ping myhost" fails, but "ping
+   myhost." works. The solution is to make sure that all your hosts
+   have a domain set ("domain" in resolv.conf, or set a domain in 
+   your DHCP server, see below fr Windows XP and Mac OS X). 
+   Any domain  will do, but "localnet" is traditional. Now when you
+   resolve "myhost" the resolver will attempt to look up 
+   "myhost.localnet" so you need to have dnsmasq reply to that name. 
+   The way to do that is to include the domain in each name on
+   /etc/hosts  and/or to use the --expand-hosts and --domain options.
+
+Q: How do I set the DNS domain in Windows XP or MacOS X (ref: previous
+   question)?
+
+A: for XP, Control Panel > Network Connections > { Connection to gateway /
+   DNS } > Properties > { Highlight TCP/IP } > Properties > Advanced >
+   DNS Tab > DNS suffix for this connection: 
+
+A: for OS X, System Preferences > Network > {Connection to gateway / DNS } >
+   Search domains:
+
+Q: Can I get dnsmasq to save the contents of its cache to disk when
+   I shut my machine down and re-load when it starts again?
+
+A: No, that facility is not provided. Very few names in the DNS have
+   their time-to-live set for longer than a few hours so most of the
+   cache entries would have expired after a shutdown. For longer-lived
+   names it's much cheaper to just reload them from the upstream
+   server. Note that dnsmasq is not shut down between PPP sessions so
+   go off-line and then on-line again will not lose the contents of
+   the cache.
+
+Q: Who are Verisign, what do they have to do with the bogus-nxdomain
+   option in dnsmasq and why should I wory about it?
+
+A: [note: this was written in September 2003, things may well change.]
+   Versign run the .com and .net top-level-domains. They have just
+   changed the configuration of their servers so that unknown .com and
+   .net domains, instead of returning an error code NXDOMAIN, (no such
+   domain) return the address of a host at Versign which runs a web
+   server showing a search page. Most right-thinking people regard
+   this new behaviour as broken :-).  You can test to see if you are
+   suffering Versign brokeness by run a command like 
+   
+   host jlsdajkdalld.com
+
+   If you get "jlsdajkdalld.com" does not exist, then all is fine, if
+   host returns an IP address, then the DNS is broken. (Try a few
+   different unlikely domains, just in case you picked a wierd one
+   which really _is_ registered.)
+
+   Assuming that your DNS is broken, and you want to fix it, simply
+   note the IP address being returned and pass it to dnsmasq using the
+   --bogus-nxdomain flag. Dnsmasq will check for results returning
+   that address and substitute an NXDOMAIN instead. 
+
+   As of writing, the IP address in question for the .com and .net
+   domains is is 64.94.110.11. Various other, less prominent,
+   registries pull the same stunt; there is a list of them all, and
+   the addresses to block, at http://winware.org/bogus-domains.txt
+
+Q: This new DHCP server is well and good, but it doesn't work for me.
+   What's the problem?
+
+A: There are a couple of configuration gotchas which have been
+   encountered by people moving from the ISC dhcpd to the dnsmasq
+   integrated DHCP daemon. Both are related to differences in 
+   in the way the two daemons bypass the IP stack to do "ground up"
+   IP configuration and can lead to the dnsmasq daemon failing
+   whilst the ISC one works.
+
+   The first thing to check is the broadcast address set for the
+   ethernet interface. This is normally the adddress on the connected
+   network with all ones in the host part. For instance if the 
+   address of the ethernet interface is 192.168.55.7 and the netmask
+   is 255.255.255.0 then the broadcast address should be
+   192.168.55.255. Having a broadcast address which is not on the
+   network to which the interface is connected kills things stone
+   dead.
+
+   The second potential problem relates to firewall rules: since the ISC 
+   daemon in some configurations bypasses the kernel firewall rules 
+   entirely, the ability to run the ISC daemon does not indicate 
+   that the current configuration is OK for the dnsmasq daemon.
+   For the dnsmasq daemon to operate it's vital that UDP packets to 
+   and from ports 67 and 68 and broadcast packets with source 
+   address 0.0.0.0 and destination address 255.255.255.255 are not 
+   dropped by iptables/ipchains.
+
+Q: I'm running Debian, and my machines get an address fine with DHCP,
+   but their names are not appearing in the DNS.
+
+A: By default, none of the DHCP clients send the host-name when asking
+   for a lease. For most of the clients, you can set the host-name to
+   send with the "hostname" keyword in /etc/network/interfaces. (See
+   "man interfaces" for details.) That doesn't work for dhclient, were
+   you have to add something like "send host-name daisy" to
+   /etc/dhclient.conf [Update: the lastest dhcpcd packages _do_ send
+   the hostname by default.
+
+Q: I'm network booting my machines, and trying to give them static
+   DHCP-assigned addresses. The machine gets its correct address
+   whilst booting, but then the OS starts and it seems to get
+   allocated a different address.
+
+A: What is happening is this: The boot process sends a DHCP
+   request and gets allocated the static address corresponding to its
+   MAC address. The boot loader does not send a client-id. Then the OS
+   starts and repeats the DHCP process, but it it does send a
+   client-id. Dnsmasq cannot assume that the two requests are from the
+   same machine (since the client ID's don't match) and even though
+   the MAC address has a static allocation, that address is still in
+   use by the first incarnation of the machine (the one from the boot,
+   without a client ID.) dnsmasq therefore has to give the machine a
+   dynamic address from its pool. There are three ways to solve this:
+   (1) persuade your DHCP client not to send a client ID, or (2) set up
+   the static assignment to the client ID, not the MAC address. The
+   default client-id will be 01:<MAC address>, so change the dhcp-host
+   line from "dhcp-host=11:22:33:44:55:66,1.2.3.4" to
+   "dhcp-host=id:01:11:22:33:44:55:66,1.2.3.4" or (3) tell dnsmasq to
+   ignore client IDs for a particular MAC address, like this:
+   dhcp-host=11:22:33:44:55:66,id:*
+
+Q: What network types are supported by the DHCP server?
+  
+A: Ethernet (and 802.11 wireless) are supported on all platforms. On
+   Linux all network types (including FireWire) are supported.
+
+Q: What is this strange "bind-interface" option?
+
+A: The DNS spec says that the reply to a DNS query must come from the
+   same address it was sent to. The traditional way to write an UDP
+   server to do this is to find all of the addresses belonging to the
+   machine (ie all the interfaces on the machine) and then create a
+   socket for each interface which is bound to the address of the
+   interface. Then when a packet is sent to address A, it is received
+   on the socket bound to address A and when the reply is also sent
+   via that socket, the source address is set to A by the kernel and
+   everything works. This is the how dnsmasq works when
+   "bind-interfaces" is set, with the obvious extension that is misses
+   out creating sockets for some interfaces depending on the
+   --interface, --address and --except-interface flags.  The
+   disadvantage of this approach is that it breaks if interfaces don't
+   exist or are not configured when the daemon starts and does the
+   socket creation step. In a hotplug-aware world this is a real
+   problem.
+
+   The alternative approach is to have only one socket, which is bound
+   to the correct port and the wildcard IP address (0.0.0.0). That
+   socket will receive _all_ packets sent to port 53, no matter what
+   destination address they have. This solves the problem of
+   interfaces which are created or reconfigured after daemon
+   start-up. To make this work is more complicated because of the
+   "reply source address" problem. When a UDP packet is sent by a
+   socket bound to 0.0.0.0 its source address will be set to the
+   address of one of the machine's interfaces, but which one is not
+   determined and can vary depending on the OS being run. To get round
+   this it is neccessary to use a scary advanced API to determine the
+   address to which a query was sent, and force that to be the source
+   address in the reply. For IPv4 this stuff in non-portable and quite
+   often not even available (It's different between FreeBSD 5.x and
+   Linux, for instance, and FreeBSD 4.x, Linux 2.0.x and OpenBSD don't
+   have it at all.) Hence "bind-interfaces" has to always be available
+   as a fall back. For IPv6 the API is standard and universally
+   available.
+
+   It could be argued that if the --interface or --address flags are
+   used then binding interfaces is more appropriate, but using
+   wildcard binding means that dnsmasq will quite happily start up
+   after being told to use interfaces which don't exist, but which are
+   created later. Wildcard binding breaks the scenario when dnsmasq is
+   listening on one interface and another server (most probably BIND)
+   is listening on another. It's not possible for BIND to bind to an
+   (address,port) pair when dnsmasq has bound (wildcard,port), hence
+   the ability to explicitly turn off wildcard binding.
+
+Q: Why doesn't Kerberos work/why can't I get sensible answers to
+   queries for SRV records.
+
+A: Probably because you have the "filterwin2k" option set. Note that
+   it was on by default in example configuration files included in 
+   versions before 2.12, so you might have it set on without
+   realising.
+
+Q: Can I get email notification when a new version of dnsmasq is
+   released?
+
+A: Yes, new releases of dnsmasq are always announced through
+   freshmeat.net, and they allow you to subcribe to email alerts when
+   new versions of particular projects are released. New releases are
+   also announced in the dnsmasq-discuss mailing list, subscribe at 
+   http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
+
+Q: What does the dhcp-authoritative option do? 
+
+A: See http://www.isc.org/index.pl?/sw/dhcp/authoritative.php - that's
+   for the ISC daemon, but the same applies to dnsmasq.
+
+Q: Why does my Gentoo box pause for a minute before getting a new
+   lease?
+
+A: Because when a Gentoo box shuts down, it releases its lease with
+   the server but remembers it on the client; this seems to be a 
+   Gentoo-specific patch to dhcpcd. On restart it tries to renew
+   a lease which is long gone, as far as dnsmasq is concerned, and
+   dnsmasq ignores it until is times out and restarts the process.
+   To fix this, set the dhcp-authoritative flag in dnsmasq.
+
+Q: My laptop has two network interfaces, a wired one and a wireless
+   one. I never use both interfaces at the same time, and I'd like the
+   same IP and configuration to be used irrespective of which
+   interface is in use. How can I do that?
+
+A: By default, the identity of a machine is determined by using the
+   MAC address, which is associated with interface hardware. Once an
+   IP is bound to the MAC address of one interface, it cannot be
+   associated with another MAC address until after the DHCP lease
+   expires. The solution to this is to use a client-id as the machine
+   identity rather than the MAC address. If you arrange for the same
+   client-id to sent when either interface is in use, the DHCP server
+   will recognise the same machine, and use the same address. The
+   method for setting the client-id varies with DHCP client software,
+   dhcpcd uses the "-I" flag. Windows uses a registry setting,
+   see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
+Addendum:
+   From version 2.46, dnsmasq has a solution to this which doesn't
+   involve setting client-IDs. It's possible to put more than one MAC
+   address in a --dhcp-host configuration. This tells dnsmasq that it
+   should use the specified IP for any of the specified MAC addresses,
+   and furthermore it gives dnsmasq permission to sumarily abandon a
+   lease to one of the MAC addresses if another one comes along. Note
+   that this will work fine only as longer as only one interface is
+   up at any time. There is no way for dnsmasq to enforce this
+   constraint: if you configure multiple MAC addresses and violate 
+   this rule, bad things will happen.
+
+Q: Can dnsmasq do DHCP on IP-alias interfaces?
+
+A: Yes, from version-2.21. The support is only available running under
+   Linux, on a kernel which provides the RT-netlink facility. All 2.4 
+   and 2.6 kernels provide RT-netlink and it's an option in 2.2
+   kernels. 
+   
+   If a physical interface has more than one IP address or aliases
+   with extra IP addresses, then any dhcp-ranges corresponding to
+   these addresses can be used for address allocation. So if an
+   interface has addresses 192.168.1.0/24 and 192.168.2.0/24 and there
+   are DHCP ranges 192.168.1.100-192.168.1.200 and
+   192.168.2.100-192.168.2.200 then both ranges would be used for host
+   connected to the physical interface. A more typical use might be to
+   have one of the address-ranges as static-only, and have known
+   hosts allocated addresses on that subnet using dhcp-host options,
+   while  anonymous hosts go on the other.
+
+
+Q: Dnsmasq sometimes logs "nameserver xxx.xxx.xxx.xxx refused
+   to do a recursive query" and DNS stops working. What's going on?
+
+A: Probably the nameserver is an authoritative nameserver for a
+   particular domain, but is not configured to answer general DNS
+   queries for an arbitrary domain. It is not suitable for use by
+   dnsmasq as an upstream server and should be removed from the
+   configuration. Note that if you have more than one upstream
+   nameserver configured dnsmasq will load-balance across them and
+   it may be some time before dnsmasq gets around to using a 
+   particular nameserver. This means that a particular configuration
+   may work for sometime with a broken upstream nameserver
+   configuration.
+
+
+Q: Does the dnsmasq DHCP server probe addresses before allocating
+   them, as recommended in RFC2131?
+
+A: Yes, dynmaically allocated IP addresses are checked by sending an
+   ICMP echo request (ping). If a reply is received, then dnsmasq
+   assumes that the address is in use, and attempts to allocate an
+   different address. The wait for a reply is between two and three
+   seconds. Because the DHCP server is not re-entrant, it cannot serve
+   other DHCP requests during this time. To avoid dropping requests,
+   the address probe may be skipped when dnsmasq is under heavy load.
+
+
+Q: I'm using dnsmasq on a machine with the Firestarter firewall, and
+   DHCP doesn't work. What's the problem?
+
+A: This a variant on the iptables problem. Explicit details on how to
+   proceed can be found at 
+   http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2005q3/000431.html
+
+Q: I'm using dnsmasq on a machine with the shorewall firewall, and
+   DHCP doesn't work. What's the problem?
+
+A: This a variant on the iptables problem. Explicit details on how to
+   proceed can be found at 
+   http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2007q4/001764.html
+
+
+Q: Dnsmasq fails to start up with a message about capabilities.
+   Why did that happen and what can do to fix it?
+
+A: Change your kernel configuration: either deselect CONFIG_SECURITY
+   _or_ select CONFIG_SECURITY_CAPABILITIES. Alternatively, you can 
+   remove the need to set capabilities by running dnsmasq as root.
+
+
+Q: Where can I get .rpms Suitable for openSUSE/SLES?
+
+A: Dnsmasq is in openSUSE itself, and the latest releases are also
+   available at http://download.opensuse.org/repositories/network/
+
+
+Q: Can I run dnsmasq in a Linux vserver?
+
+A: Yes, as a DNS server, dnsmasq will just work in a vserver.
+   To use dnsmasq's DHCP function you need to give the vserver
+   extra system capabilities. Please note that doing so will lesser 
+   the overall security of your system. The capabilities 
+   required are NET_ADMIN and NET_RAW. NET_ADMIN is essential, NET_RAW
+   is required to do an ICMP "ping" check on newly allocated
+   addresses. If you don't need this check, you can disable it with
+   --no-ping and omit the NET_RAW capability. 
+   Adding the capabilities is done by adding them, one per line, to
+   either /etc/vservers/<vservername>/ccapabilities for a 2.4 kernel or
+   /etc/vservers/<vservername>/bcapabilities for a 2.6 kernel (please
+   refer to the vserver documentation for more information).
+
+
+Q: What's the problem with syslog and dnsmasq?
+
+A: In almost all cases: none. If you have the normal arrangement with
+   local daemons logging to a local syslog, which then writes to disk,
+   then there's never a problem. If you use network logging, then
+   there's a potential problem with deadlock: the syslog daemon will
+   do DNS lookups so that it can log the source of log messages,
+   these lookups will (depending on exact configuration) go through
+   dnsmasq, which also sends log messages. With bad timing, you can 
+   arrive at a situation where syslog is waiting for dnsmasq, and
+   dnsmasq is waiting for syslog; they will both wait forever. This
+   problem is fixed from dnsmasq-2.39, which introduces asynchronous
+   logging: dnsmasq no longer waits for syslog and the deadlock is
+   broken. There is a remaining problem in 2.39, where "log-queries"
+   is in use. In this case most DNS queries generate two log lines, if
+   these go to a syslog which is doing a DNS lookup for each log line,
+   then those queries will in turn generate two more log lines, and a 
+   chain reaction runaway will occur. To avoid this, use syslog-ng
+   and turn on syslog-ng's dns-cache function.
+
+
+Q: DHCP doesn't work with windows Vista, but everything else is fine.
+
+A: The DHCP client on windows Vista (and possibly later versions)
+   demands that the DHCP server send replies as broadcasts. Most other
+   clients don't do this. The broadcasts are send to
+   255.255.255.255. A badly configured firewall which blocks such
+   packets will show exactly these symptoms (Vista fails, others
+   work).
+
+  
+
+
+
+
+
+
+
+
+
+   
+
+             
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..16c69e4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,99 @@
+# dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 dated June, 1991, or
+#  (at your option) version 3 dated 29 June, 2007.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#    
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+PREFIX = /usr/local
+BINDIR = ${PREFIX}/sbin
+MANDIR = ${PREFIX}/share/man
+LOCALEDIR = ${PREFIX}/share/locale
+
+PKG_CONFIG = pkg-config
+INSTALL = install
+MSGMERGE = msgmerge
+MSGFMT = msgfmt
+XGETTEXT = xgettext
+
+CFLAGS = -Wall -W -O2
+
+#################################################################
+
+SRC = src
+PO = po
+MAN = man
+
+DNSMASQ_CFLAGS=`echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1` 
+DNSMASQ_LIBS=  `echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1` 
+IDN_CFLAGS=`echo $(COPTS) | ../bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn` 
+IDN_LIBS=  `echo $(COPTS) | ../bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn` 
+SUNOS_LIBS= `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi`
+
+OBJS = cache.o rfc1035.o util.o option.o forward.o network.o \
+       dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
+       helper.o tftp.o log.o
+
+all :
+       @cd $(SRC) && $(MAKE) \
+ BUILD_CFLAGS="$(DNSMASQ_CFLAGS) $(IDN_CFLAGS)" \
+ BUILD_LIBS="$(DNSMASQ_LIBS) $(IDN_LIBS) $(SUNOS_LIBS)" \
+ -f ../Makefile dnsmasq 
+
+clean :
+       rm -f *~ $(SRC)/*.mo contrib/*/*~ */*~ $(SRC)/*.pot 
+       rm -f $(SRC)/*.o $(SRC)/dnsmasq.a $(SRC)/dnsmasq core */core
+
+install : all install-common
+
+install-common :
+       $(INSTALL) -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8
+       $(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8 
+       $(INSTALL) -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR)
+
+all-i18n :
+       @cd $(SRC) && $(MAKE) \
+ I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \
+ BUILD_CFLAGS="$(DNSMASQ_CFLAGS) `$(PKG_CONFIG) --cflags libidn`" \
+ BUILD_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS) `$(PKG_CONFIG) --libs libidn`"  \
+ -f ../Makefile dnsmasq
+       @cd $(PO); for f in *.po; do \
+               cd ../$(SRC) && $(MAKE) \
+ -f ../Makefile $${f%.po}.mo; \
+       done
+
+install-i18n : all-i18n install-common
+       cd $(SRC); ../bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL)
+       cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
+
+merge :
+       @cd $(SRC) && $(MAKE) -f ../Makefile dnsmasq.pot
+       @cd $(PO); for f in *.po; do \
+               echo -n msgmerge $$f && $(MSGMERGE) --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \
+       done
+
+
+# rules below are targets in recusive makes with cwd=$(SRC)
+
+.c.o:
+       $(CC) $(CFLAGS) $(COPTS) $(I18N) $(BUILD_CFLAGS) $(RPM_OPT_FLAGS) -c $<
+
+dnsmasq : $(OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS) $(BUILD_LIBS) $(LIBS) 
+
+dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h
+       $(XGETTEXT) -d dnsmasq --foreign-user --omit-header --keyword=_ -o $@ -i $(OBJS:.o=.c)
+
+%.mo : ../po/%.po dnsmasq.pot
+       $(MSGMERGE) -o - ../po/$*.po dnsmasq.pot | $(MSGFMT) -o $*.mo -
+
+
+.PHONY : all clean install install-common all-i18n install-i18n merge 
diff --git a/bld/Android.mk b/bld/Android.mk
new file mode 100644 (file)
index 0000000..373a783
--- /dev/null
@@ -0,0 +1,18 @@
+LOCAL_PATH := external/dnsmasq/src
+
+#########################
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES :=  bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
+                    forward.c helper.c lease.c log.c \
+                    netlink.c network.c option.c rfc1035.c \
+                   rfc2131.c tftp.c util.c
+
+LOCAL_MODULE := dnsmasq
+
+LOCAL_C_INCLUDES := external/dnsmasq/src
+
+LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/bld/install-man b/bld/install-man
new file mode 100755 (executable)
index 0000000..f4cf3dc
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+for f in *; do
+  if [ -d $f ]; then
+     $2 -m 755 -d $1/$f/man8 
+     $2 -m 644 $f/dnsmasq.8 $1/$f/man8
+     echo installing $1/$f/man8/dnsmasq.8
+  fi
+done
diff --git a/bld/install-mo b/bld/install-mo
new file mode 100755 (executable)
index 0000000..d11fa9f
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+for f in *.mo; do
+  $2 -m 755 -d $1/${f%.mo}/LC_MESSAGES
+  $2 -m 644 $f $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
+  echo installing $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
+done
+
+
diff --git a/bld/pkg-wrapper b/bld/pkg-wrapper
new file mode 100755 (executable)
index 0000000..4f3b76b
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+search=$1
+shift
+
+if grep "^\#.*define.*$search" config.h 2>&1 >/dev/null || \
+   grep $search 2>&1 >/dev/null ; then
+  exec $*
+fi
+
+
diff --git a/contrib/CPE-WAN/README b/contrib/CPE-WAN/README
new file mode 100644 (file)
index 0000000..4d56347
--- /dev/null
@@ -0,0 +1,36 @@
+Dnsmasq from version 2.52 has a couple of rather application-specific
+features designed to allow for implementation of the DHCP part of CPE
+WAN management protocol.
+
+http://www.broadband-forum.org/technical/download/TR-069_Amendment-2.pdf
+http://en.wikipedia.org/wiki/TR-069
+
+The relevant sections are F.2.1 "Gateway Requirements" and F.2.5 "DHCP
+Vendor Options".
+
+First, dnsmasq checks for DHCP requests which contain an option-125
+vendor-class option which in turn holds a vendor section for IANA
+enterprise number 3561 which contains sub-options codes 1 and 2. If
+this is present  then the network-tag "cpewan-id" is set. 
+This allows dnsmasq to be configured to reply with the correct 
+GatewayManufacturerOUI, GatewaySerialNumber and GatewayProductClass like this:
+
+dhcp-option=cpewan-id,vi-encap:3561,4,"<GatewayManufacturerOUI>"
+dhcp-option=cpewan-id,vi-encap:3561,5,"<SerialNumber>"
+dhcp-option=cpewan-id,vi-encap:3561,6,"<ProductClass>"
+
+Second, the received sub-options 1, 2, and 3 are passed to the DHCP
+lease-change script as the environment variables DNSMASQ_CPEWAN_OUI,
+DNSMASQ_CPEWAN_SERIAL, and DNSMASQ_CPEWAN_CLASS respectively. This allows
+the script to be used to maintain a ManageableDevice table as
+specified in F.2.1. Note that this data is not retained in dnsmasq's
+internal DHCP lease database, so it is not available on every call to 
+the script (this is the same as some other data such as vendor and
+user classes). It will however be available for at least the "add"
+call, and should be stored then against the IP address as primary 
+key for future use.
+
+
+This feature was added to dnsmasq under sponsorship from Ericsson.
+
+
diff --git a/contrib/MacOSX-launchd/launchd-README.txt b/contrib/MacOSX-launchd/launchd-README.txt
new file mode 100644 (file)
index 0000000..4783221
--- /dev/null
@@ -0,0 +1,38 @@
+This is a launchd item for Mac OS X and Mac OS X Server.
+For more information about launchd, the
+"System wide and per-user daemon/agent manager", see the launchd
+man page, or the wikipedia page: http://en.wikipedia.org/wiki/Launchd
+
+This launchd item uses the following flags:
+--keep-in-foreground - this is crucial for use with launchd
+--log-queries - this is optional and you can remove it
+--log-facility=/var/log/dnsmasq.log - again optional instead of system.log
+
+To use this launchd item for dnsmasq:
+
+If you don't already have a folder /Library/LaunchDaemons, then create one:
+sudo mkdir /Library/LaunchDaemons
+sudo chown root:admin /Library/LaunchDaemons
+sudo chmod 775 /Library/LaunchDaemons 
+
+Copy uk.org.thekelleys.dnsmasq.plist there and then set ownership/permissions:
+sudo cp uk.org.thekelleys.dnsmasq.plist /Library/LaunchDaemons/
+sudo chown root:admin /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
+sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
+
+Optionally, edit your dnsmasq configuration file to your liking.
+
+To start the launchd job, which starts dnsmaq, reboot or use the command:
+sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
+
+To stop the launchd job, which stops dnsmasq, use the command:
+sudo launchctl unload /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
+
+If you want to permanently stop the launchd job, so it doesn't start the job even after a reboot, use the following command:
+sudo launchctl unload -w /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
+
+If you make a change to the configuration file, you should relaunch dnsmasq;
+to do this unload and then load again:
+
+sudo launchctl unload /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
+sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
diff --git a/contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist b/contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist
new file mode 100644 (file)
index 0000000..87725b1
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Label</key>
+       <string>uk.org.thekelleys.dnsmasq</string>
+       <key>ProgramArguments</key>
+       <array>
+               <string>/usr/local/sbin/dnsmasq</string>
+               <string>--keep-in-foreground</string>
+       </array>
+       <key>RunAtLoad</key>
+       <true/>
+</dict>
+</plist>
diff --git a/contrib/Solaris10/README b/contrib/Solaris10/README
new file mode 100644 (file)
index 0000000..a035875
--- /dev/null
@@ -0,0 +1,28 @@
+From: David Connelly <dconnelly@gmail.com>
+Date: Mon, Apr 7, 2008 at 3:31 AM
+Subject: Solaris 10 service manifest
+To: dnsmasq-discuss@lists.thekelleys.org.uk
+
+
+I've found dnsmasq much easier to set up on my home server running Solaris
+10 than the stock dhcp/dns server, which is probably overkill anyway for my
+simple home network needs. Since Solaris now uses SMF (Service Management
+Facility) to manage services I thought I'd create a simple service manifest
+for the dnsmasq service. The manifest currently assumes that dnsmasq has
+been installed in '/usr/local/sbin/dnsmasq' and the configuration file in
+'/usr/local/etc/dnsmasq.conf', so you may have to adjust these paths for
+your local installation. Here are the steps I followed to install and enable
+the dnsmasq service:
+  # svccfg import dnsmasq.xml
+  # svcadm enable dnsmasq
+
+To confirm that the service is enabled and online:
+
+  # svcs -l dnsmasq
+
+I've just started learning about SMF so if anyone has any
+corrections/feedback they are more than welcome.
+
+Thanks,
+David
+
diff --git a/contrib/Solaris10/README-sparc b/contrib/Solaris10/README-sparc
new file mode 100644 (file)
index 0000000..327b65c
--- /dev/null
@@ -0,0 +1,8 @@
+Hi Simon,
+
+I just wanted to let you know that I have built a Solaris .pkg install package of your dnsmasq utility for people to use.  Feel free to point them in my direction if you have people who want this sort of thing.
+
+http://ejesconsulting.wordpress.com/2010/05/12/gnu-dnsmasq-for-opensolaris-sparc/
+
+Thanks
+-evan
diff --git a/contrib/Solaris10/README.create_package b/contrib/Solaris10/README.create_package
new file mode 100644 (file)
index 0000000..676899a
--- /dev/null
@@ -0,0 +1,25 @@
+Ok, script attached ... seems to be working ok for me, 
+tried to install and remove a few times. It does the
+right thing with the smf when installing, you can then 
+simply enable the service. Upon removal it cleans up the
+files but won't clean up the services (I think until
+a reboot) ... I've only started looking at the new 
+packages stuff in the last day or two, so I could be 
+missing something, but I can't find any way to force
+ a proper cleanup.
+
+It requires that you have a writable repository setup 
+as per the docs on the opensolaris website and it will
+create a dnsmasq package (package name is a variable 
+in the script). The script takes a version number for 
+the package and assumes that it's in the contrib/Solaris10 
+directory, it then works out the base tree directory 
+from $0.
+
+i.e.  $ contrib/Solaris10/create_package 2.52-1
+or   $ cd contrib/Solaris10; ./create_package 2.52-1
+
+It's a bit more complex than it could be because I 
+prefer putting the daemon in /usr/sbin and the config 
+in /etc, so the script will actually create a new 
+version of the existing contrib dnsmasq.xml.
diff --git a/contrib/Solaris10/create_package b/contrib/Solaris10/create_package
new file mode 100644 (file)
index 0000000..acfa2a1
--- /dev/null
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+#
+# For our package, and for the SMF script, we need to define where we
+# want things to go...
+#
+BIN_DIR="/usr/sbin"
+CONF_DIR="/etc"
+MAN_DIR="/usr/share/man/man8"
+
+PACKAGE_NAME="dnsmasq"
+
+#
+# Since we know we are in the contrib directory we can work out where
+# the rest of the tree is...
+#
+BASEDIR="`dirname $0`/../.."
+
+#
+# We need a version number to use for the package creation...
+#
+if [ $# != 1 ]; then
+       echo "Usage: $0 <package_version_number>" >&2
+       exit 1
+fi
+VERSION="$1"
+
+#
+# First thing we do is fix-up the smf file to use the paths we prefer...
+#
+if [ ! -f "${BASEDIR}/contrib/Solaris10/dnsmasq.xml" ]; then
+       echo "$0: unable to find contrib/Solaris10/dnsmasq.xml" >&2
+       exit 1
+fi
+
+echo "Fixing up smf file ... \c"
+cat "${BASEDIR}/contrib/Solaris10/dnsmasq.xml" | \
+       sed     -e "s%/usr/local/etc%${CONF_DIR}%" \
+               -e "s%/usr/local/sbin%${BIN_DIR}%" \
+               -e "s%/usr/local/man%${MAN_DIR}%" > ${BASEDIR}/contrib/Solaris10/dnsmasq-pkg.xml
+echo "done."
+
+echo "Creating packaging file ... \c"
+cat <<EOF >${BASEDIR}/contrib/Solaris10/dnsmasq_package.inc
+#
+# header
+#
+set name=pkg.name              value="dnsmasq"
+set name=pkg.description       value="dnsmasq daemon - dns, dhcp, tftp etc"
+set name=pkg.detailed_url      value="http://www.thekelleys.org.uk/dnsmasq/doc.html"
+set name=info.maintainer       value="TBD (tbd@tbd.com)"
+set name=info.upstream         value="dnsmasq-discuss@lists.thekelleys.org.uk"
+set name=info.upstream_url     value="http://www.thekelleys.org.uk/dnsmasq/doc.html"
+#
+# dependencies ... none?
+#
+
+#
+# directories
+#
+dir mode=0755 owner=root group=bin path=${BIN_DIR}/
+dir mode=0755 owner=root group=sys path=${CONF_DIR}/
+dir mode=0755 owner=root group=sys path=${MAN_DIR}/
+dir mode=0755 owner=root group=sys path=/var/
+dir mode=0755 owner=root group=sys path=/var/svc
+dir mode=0755 owner=root group=sys path=/var/svc/manifest
+dir mode=0755 owner=root group=sys path=/var/svc/manifest/network
+
+#
+# files
+#
+file ${BASEDIR}/src/dnsmasq mode=0555 owner=root group=bin path=${BIN_DIR}/dnsmasq
+file ${BASEDIR}/man/dnsmasq.8 mode=0555 owner=root group=bin path=${MAN_DIR}/dnsmasq.8
+file ${BASEDIR}/dnsmasq.conf.example mode=0644 owner=root group=sys path=${CONF_DIR}/dnsmasq.conf preserve=strawberry
+file ${BASEDIR}/contrib/Solaris10/dnsmasq-pkg.xml mode=0644 owner=root group=sys path=/var/svc/manifest/network/dnsmasq.xml restart_fmri=svc:/system/manifest-import:default
+
+EOF
+echo "done."
+
+echo "Creating package..."
+eval `pkgsend open ${PACKAGE_NAME}@${VERSION}`
+pkgsend include ${BASEDIR}/contrib/Solaris10/dnsmasq_package.inc
+if [ "$?" = 0 ]; then
+       pkgsend close
+else
+       echo "Errors"
+fi
diff --git a/contrib/Solaris10/dnsmasq.xml b/contrib/Solaris10/dnsmasq.xml
new file mode 100644 (file)
index 0000000..7da0253
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version='1.0'?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+
+<!-- Service manifest for dnsmasq -->
+
+<service_bundle type='manifest' name='dnsmasq'>
+  <service name='network/dnsmasq' type='service' version='1'>
+
+    <create_default_instance enabled='false'/>
+    <single_instance/>
+
+    <dependency name='multi-user'
+                grouping='require_all'
+                restart_on='refresh'
+                type='service'>
+      <service_fmri value='svc:/milestone/multi-user'/>
+    </dependency>
+
+    <dependency name='config'
+               grouping='require_all'
+               restart_on='restart'
+               type='path'>
+      <service_fmri value='file:///usr/local/etc/dnsmasq.conf'/>
+    </dependency>
+
+    <dependent name='dnsmasq_multi-user-server'
+               grouping='optional_all'
+               restart_on='none'>
+      <service_fmri value='svc:/milestone/multi-user-server' />
+    </dependent>
+
+    <exec_method type='method' name='start'
+                 exec='/usr/local/sbin/dnsmasq -C /usr/local/etc/dnsmasq.conf'
+                 timeout_seconds='60' >
+      <method_context>
+        <method_credential user='root' group='root' privileges='all'/>
+      </method_context>
+    </exec_method>
+
+    <exec_method type='method'
+                 name='stop'
+                 exec=':kill'
+                 timeout_seconds='60'/>
+
+    <exec_method type='method'
+                 name='refresh'
+                 exec=':kill -HUP'
+                 timeout_seconds='60' />
+
+    <template>
+      <common_name>
+        <loctext xml:lang='C'>dnsmasq server</loctext>
+      </common_name>
+      <description>
+        <loctext xml:lang='C'>
+dnsmasq - A lightweight DHCP and caching DNS server.
+        </loctext>
+      </description>
+      <documentation>
+        <manpage title='dnsmasq' section='8' manpath='/usr/local/man'/>
+      </documentation>
+    </template>
+
+  </service>
+</service_bundle>
diff --git a/contrib/Suse/README b/contrib/Suse/README
new file mode 100644 (file)
index 0000000..3fdc186
--- /dev/null
@@ -0,0 +1,6 @@
+This packaging is now unmaintained in the dnsmasq source: dnsmasq is
+included in Suse proper, and up-to-date packages are now available
+from 
+
+ftp://ftp.suse.com/pub/people/ug/
+
diff --git a/contrib/Suse/README.susefirewall b/contrib/Suse/README.susefirewall
new file mode 100644 (file)
index 0000000..2f19ca6
--- /dev/null
@@ -0,0 +1,27 @@
+This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
+It fixes the depancy from the dns daemon name 'named'
+After appending the patch, the SuSEfirewall is again able to autodetect 
+the dnsmasq named service.
+This is a very old bug in the SuSEfirewall script.
+The SuSE people think the name of the dns server will allways 'named'
+
+
+--- /sbin/SuSEfirewall2.orig   2004-01-23 13:30:09.000000000 +0100
++++ /sbin/SuSEfirewall2        2004-01-23 13:31:56.000000000 +0100
+@@ -764,7 +764,7 @@
+     echo 'FW_ALLOW_INCOMING_HIGHPORTS_UDP should be set to yes, if you are running a DNS server!'
+ test "$FW_SERVICE_AUTODETECT" = yes -o "$FW_SERVICE_AUTODETECT" = dmz -o "$FW_SERVICE_AUTODETECT" = ext && {
+-    test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv named && {
++    test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv dnsmasq && {
+       echo -e 'Warning: detected activated named, enabling FW_SERVICE_DNS!
+ You still have to allow tcp/udp port 53 on internal, dmz and/or external.'
+       FW_SERVICE_DNS=$FW_SERVICE_AUTODETECT
+@@ -878,7 +878,7 @@
+ test -e /etc/resolv.conf || echo "Warning: /etc/resolv.conf not found"
+ # Get ports/IP bindings of NAMED/SQUID
+ test "$FW_SERVICE_DNS" = yes -o "$FW_SERVICE_DNS" = dmz -o "$FW_SERVICE_DNS" = ext -o "$START_NAMED" = yes && DNS_PORT=`$LSOF -i -n -P | \
+-    $AWK -F: '/^named .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
++    $AWK -F: '/^dnsmasq .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
+ test "$FW_SERVICE_SQUID" = yes -o "$FW_SERVICE_SQUID" = dmz -o "$FW_SERVICE_SQUID" = ext -o "$START_SQUID" = yes && SQUID_PORT=`$LSOF -i -n -P | \
+     $AWK -F: '/^squid .* UDP/ {print $2}'| $SORT -un`
diff --git a/contrib/Suse/dnsmasq-SuSE.patch b/contrib/Suse/dnsmasq-SuSE.patch
new file mode 100644 (file)
index 0000000..626245f
--- /dev/null
@@ -0,0 +1,23 @@
+--- man/dnsmasq.8      2004-08-08 20:57:56.000000000 +0200
++++ man/dnsmasq.8      2004-08-12 00:40:01.000000000 +0200
+@@ -69,7 +69,7 @@
+ .TP
+ .B \-g, --group=<groupname> 
+ Specify the group which dnsmasq will run
+-as. The defaults to "dip", if available, to facilitate access to
++as. The defaults to "dialout", if available, to facilitate access to
+ /etc/ppp/resolv.conf which is not normally world readable.
+ .TP
+ .B \-v, --version
+--- src/config.h       2004-08-11 11:39:18.000000000 +0200
++++ src/config.h       2004-08-12 00:40:01.000000000 +0200
+@@ -44,7 +44,7 @@
+ #endif
+ #define DEFLEASE 3600 /* default lease time, 1 hour */
+ #define CHUSER "nobody"
+-#define CHGRP "dip"
++#define CHGRP "dialout"
+ #define DHCP_SERVER_PORT 67
+ #define DHCP_CLIENT_PORT 68
+
diff --git a/contrib/Suse/dnsmasq-suse.spec b/contrib/Suse/dnsmasq-suse.spec
new file mode 100644 (file)
index 0000000..ff8ba8f
--- /dev/null
@@ -0,0 +1,111 @@
+###############################################################################
+#
+# General
+#
+###############################################################################
+
+Name: dnsmasq
+Version: 2.33
+Release: 1
+Copyright: GPL
+Group: Productivity/Networking/DNS/Servers
+Vendor: Simon Kelley
+Packager: Simon Kelley
+URL: http://www.thekelleys.org.uk/dnsmasq
+Provides: dns_daemon
+Conflicts: bind bind8 bind9
+PreReq: %fillup_prereq %insserv_prereq
+Autoreqprov: on
+Source0: %{name}-%{version}.tar.bz2
+BuildRoot: /var/tmp/%{name}-%{version}
+Summary: A lightweight caching nameserver
+
+%description
+Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. It 
+is designed to provide DNS and, optionally, DHCP, to a small network. It can
+serve the names of local machines which are not in the global DNS. The DHCP 
+server integrates with the DNS server and allows machines with DHCP-allocated
+addresses to appear in the DNS with names configured either in each host or 
+in a central configuration file. Dnsmasq supports static and dynamic DHCP 
+leases and BOOTP for network booting of diskless machines.
+
+
+
+###############################################################################
+#
+# Build
+#
+###############################################################################
+
+%prep
+%setup -q
+patch -p0 <rpm/%{name}-SuSE.patch
+
+%build
+%{?suse_update_config:%{suse_update_config -f}}
+make all-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
+
+###############################################################################
+#
+# Install
+#
+###############################################################################
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p ${RPM_BUILD_ROOT}/etc/init.d
+make install-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
+install -o root -g root -m 755 rpm/rc.dnsmasq-suse $RPM_BUILD_ROOT/etc/init.d/dnsmasq
+install -o root -g root -m 644 dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
+strip $RPM_BUILD_ROOT/usr/sbin/dnsmasq
+ln -sf ../../etc/init.d/dnsmasq $RPM_BUILD_ROOT/usr/sbin/rcdnsmasq
+
+###############################################################################
+#
+# Clean up
+#
+###############################################################################
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+###############################################################################
+#
+# Post-install scriptlet
+#
+###############################################################################
+
+%post
+%{fillup_and_insserv dnsmasq}
+
+###############################################################################
+#
+# Post-uninstall scriptlet
+#
+# The %postun script executes after the package has been removed. It is the
+# last chance for a package to clean up after itself.
+#
+###############################################################################
+
+%postun
+%{insserv_cleanup}
+
+###############################################################################
+#
+# File list
+#
+###############################################################################
+
+%files
+%defattr(-,root,root)
+%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0 rpm/README.susefirewall
+%doc contrib
+%config /etc/init.d/dnsmasq
+%config /etc/dnsmasq.conf
+/usr/sbin/rcdnsmasq
+/usr/sbin/dnsmasq
+/usr/share/locale/*/LC_MESSAGES/*
+%doc %{_mandir}/man8/dnsmasq.8.gz
+%doc %{_mandir}/*/man8/dnsmasq.8.gz
+
+
diff --git a/contrib/Suse/rc.dnsmasq-suse b/contrib/Suse/rc.dnsmasq-suse
new file mode 100644 (file)
index 0000000..71f4c72
--- /dev/null
@@ -0,0 +1,79 @@
+#! /bin/sh
+#
+# init.d/dnsmasq
+#
+### BEGIN INIT INFO
+# Provides:       dnsmasq
+# Required-Start: $network $remote_fs $syslog
+# Required-Stop:
+# Default-Start:  3 5
+# Default-Stop:
+# Description:    Starts internet name service masq caching server (DNS)
+### END INIT INFO
+
+NAMED_BIN=/usr/sbin/dnsmasq
+NAMED_PID=/var/run/dnsmasq.pid
+NAMED_CONF=/etc/dnsmasq.conf
+
+if [ ! -x $NAMED_BIN ] ; then
+       echo -n "dnsmasq not installed ! "
+       exit 5
+fi
+
+. /etc/rc.status
+rc_reset
+
+case "$1" in
+    start)
+       echo -n "Starting name service masq caching server "
+        checkproc -p $NAMED_PID $NAMED_BIN
+        if [ $? -eq 0 ] ; then
+           echo -n "- Warning: dnsmasq already running ! "
+        else
+           [ -e $NAMED_PID ] && echo -n "- Warning: $NAMED_PID exists ! "
+       fi
+       startproc -p $NAMED_PID $NAMED_BIN -u nobody
+       rc_status -v
+       ;;
+    stop)
+       echo -n "Shutting name service masq caching server "
+       checkproc -p $NAMED_PID $NAMED_BIN
+       [ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
+       killproc -p $NAMED_PID -TERM $NAMED_BIN
+       rc_status -v
+       ;;
+    try-restart)
+       $0 stop  &&  $0 start
+       rc_status
+       ;;
+    restart)
+       $0 stop
+       $0 start
+       rc_status
+       ;;
+    force-reload)
+       $0 reload
+       rc_status
+       ;;
+    reload)
+       echo -n "Reloading name service masq caching server "
+       checkproc -p $NAMED_PID $NAMED_BIN
+       [ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
+       killproc -p $NAMED_PID -HUP $NAMED_BIN
+       rc_status -v
+       ;;
+    status)
+       echo -n "Checking for name service masq caching server "
+       checkproc -p $NAMED_PID $NAMED_BIN
+       rc_status -v
+       ;;
+    probe)
+       test $NAMED_CONF -nt $NAMED_PID && echo reload
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
+       exit 1
+       ;;
+esac
+rc_exit
+
diff --git a/contrib/dns-loc/README b/contrib/dns-loc/README
new file mode 100644 (file)
index 0000000..6f43a8d
--- /dev/null
@@ -0,0 +1,12 @@
+Hi Simon
+
+Here is a patch against dnsmasq 2.39 which provides support for LOC  
+entries in order to assign location information to dns records  
+(rfc1876). I tested it on OSX and on OpenWRT.
+
+Cheers
+Lorenz
+
+More info:
+http://www.ckdhr.com/dns-loc/
+http://www.faqs.org/rfcs/rfc1876.html
diff --git a/contrib/dns-loc/dnsmasq2-loc-rfc1876.patch b/contrib/dns-loc/dnsmasq2-loc-rfc1876.patch
new file mode 100644 (file)
index 0000000..d950321
--- /dev/null
@@ -0,0 +1,522 @@
+diff -Nur dnsmasq-2.39-orig/bld/Makefile dnsmasq-2.39/bld/Makefile
+--- dnsmasq-2.39-orig/bld/Makefile     2007-02-17 14:37:06.000000000 +0100
++++ dnsmasq-2.39/bld/Makefile  2007-05-20 18:23:44.000000000 +0200
+@@ -2,7 +2,7 @@
+ PKG_CONFIG ?= pkg-config
+-OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o network.o \
++OBJS = cache.o rfc1035.o rfc1876.o util.o option.o forward.o isc.o network.o \
+        dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
+        helper.o tftp.o log.o
+diff -Nur dnsmasq-2.39-orig/src/dnsmasq.h dnsmasq-2.39/src/dnsmasq.h
+--- dnsmasq-2.39-orig/src/dnsmasq.h    2007-04-20 12:53:38.000000000 +0200
++++ dnsmasq-2.39/src/dnsmasq.h 2007-05-20 19:50:37.000000000 +0200
+@@ -162,6 +162,12 @@
+   struct interface_name *next;
+ };
++struct loc_record {
++  char *name, loc[16];
++  unsigned short class;
++  struct loc_record *next;
++};
++
+ union bigname {
+   char name[MAXDNAME];
+   union bigname *next; /* freelist */
+@@ -476,6 +482,7 @@
+   struct mx_srv_record *mxnames;
+   struct txt_record *txt;
+   struct ptr_record *ptr;
++      struct loc_record *loc;
+   struct interface_name *int_names;
+   char *mxtarget;
+   char *lease_file; 
+@@ -725,3 +732,6 @@
+ void tftp_request(struct listener *listen, struct daemon *daemon, time_t now);
+ void check_tftp_listeners(struct daemon *daemon, fd_set *rset, time_t now);
+ #endif
++
++/* rfc1876 */
++u_int32_t loc_aton(const char *ascii, u_char *binary);
+diff -Nur dnsmasq-2.39-orig/src/option.c dnsmasq-2.39/src/option.c
+--- dnsmasq-2.39-orig/src/option.c     2007-04-19 23:34:49.000000000 +0200
++++ dnsmasq-2.39/src/option.c  2007-05-20 20:15:15.000000000 +0200
+@@ -43,6 +43,7 @@
+ #define LOPT_REMOTE    269
+ #define LOPT_SUBSCR    270
+ #define LOPT_INTNAME   271
++#define LOPT_LOC       272
+ #ifdef HAVE_GETOPT_LONG
+ static const struct option opts[] =  
+@@ -122,6 +123,7 @@
+     {"tftp-root", 1, 0, LOPT_PREFIX },
+     {"tftp-max", 1, 0, LOPT_TFTP_MAX },
+     {"ptr-record", 1, 0, LOPT_PTR },
++    {"loc-record", 1, 0, LOPT_LOC },
+ #if defined(__FreeBSD__) || defined(__DragonFly__)
+     {"bridge-interface", 1, 0 , LOPT_BRIDGE },
+ #endif
+@@ -235,6 +237,7 @@
+   { "-y, --localise-queries", gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
+   { "-Y  --txt-record=name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
+   { "    --ptr-record=name,target", gettext_noop("Specify PTR DNS record."), NULL },
++  { "    --loc-record=name,lat lon alt", gettext_noop("Specify LOC DNS record."), NULL },
+   { "    --interface-name=name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
+   { "-z, --bind-interfaces", gettext_noop("Bind only to interfaces in use."), NULL },
+   { "-Z, --read-ethers", gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
+@@ -1835,6 +1838,37 @@
+       new->intr = safe_string_alloc(comma);
+       break;
+       }
++      
++    case LOPT_LOC:
++      {
++      struct loc_record *new;
++      unsigned char *p, *q;
++      
++      comma = split(arg);
++      
++      if (!canonicalise_opt(arg))
++        {
++          option = '?';
++          problem = _("bad LOC record");
++          break;
++        }
++      
++      new = safe_malloc(sizeof(struct loc_record));
++      new->next = daemon->loc;
++      daemon->loc = new;
++      new->class = C_IN;
++      if (!comma || loc_aton(comma,new->loc)!=16)
++        {
++          option = '?';
++          problem = _("bad LOC record");
++          break;
++        }
++
++      if (comma)
++        *comma = 0;
++      new->name = safe_string_alloc(arg);
++      break;
++      }
+     case LOPT_PTR:  /* --ptr-record */
+       {
+diff -Nur dnsmasq-2.39-orig/src/rfc1035.c dnsmasq-2.39/src/rfc1035.c
+--- dnsmasq-2.39-orig/src/rfc1035.c    2007-04-20 12:54:26.000000000 +0200
++++ dnsmasq-2.39/src/rfc1035.c 2007-05-20 18:22:46.000000000 +0200
+@@ -1112,6 +1112,27 @@
+           }
+       }
++      if (qtype == T_LOC || qtype == T_ANY)
++      {
++        struct loc_record *t;
++        for(t = daemon->loc; t ; t = t->next)
++          {
++            if (t->class == qclass && hostname_isequal(name, t->name))
++              {
++                ans = 1;
++                if (!dryrun)
++                  {
++                    log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, 0, NULL, 0);
++                    if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
++                                            daemon->local_ttl, NULL,
++                                            T_LOC, t->class, "t", 16, t->loc))
++                      anscount++;
++
++                  }
++              }
++          }
++      }
++
+       if (qclass == C_IN)
+       {
+         if (qtype == T_PTR || qtype == T_ANY)
+diff -Nur dnsmasq-2.39-orig/src/rfc1876.c dnsmasq-2.39/src/rfc1876.c
+--- dnsmasq-2.39-orig/src/rfc1876.c    1970-01-01 01:00:00.000000000 +0100
++++ dnsmasq-2.39/src/rfc1876.c 2007-05-20 19:50:10.000000000 +0200
+@@ -0,0 +1,379 @@
++/*
++ * routines to convert between on-the-wire RR format and zone file
++ * format.  Does not contain conversion to/from decimal degrees;
++ * divide or multiply by 60*60*1000 for that.
++ */
++
++#include "dnsmasq.h"
++
++static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
++                                 1000000,10000000,100000000,1000000000};
++
++/* takes an XeY precision/size value, returns a string representation.*/
++static const char *
++precsize_ntoa(u_int8_t prec)
++{
++        static char retbuf[sizeof("90000000.00")];
++        unsigned long val;
++        int mantissa, exponent;
++
++        mantissa = (int)((prec >> 4) & 0x0f) % 10;
++        exponent = (int)((prec >> 0) & 0x0f) % 10;
++
++        val = mantissa * poweroften[exponent];
++
++        (void) sprintf(retbuf,"%d.%.2d", val/100, val%100);
++        return (retbuf);
++}
++
++/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/
++static u_int8_t
++precsize_aton(char **strptr)
++{
++        unsigned int mval = 0, cmval = 0;
++        u_int8_t retval = 0;
++        register char *cp;
++        register int exponent;
++        register int mantissa;
++
++        cp = *strptr;
++
++        while (isdigit(*cp))
++                mval = mval * 10 + (*cp++ - '0');
++
++        if (*cp == '.') {               /* centimeters */
++                cp++;
++                if (isdigit(*cp)) {
++                        cmval = (*cp++ - '0') * 10;
++                        if (isdigit(*cp)) {
++                                cmval += (*cp++ - '0');
++                        }
++                }
++        }
++        cmval = (mval * 100) + cmval;
++
++        for (exponent = 0; exponent < 9; exponent++)
++                if (cmval < poweroften[exponent+1])
++                        break;
++
++        mantissa = cmval / poweroften[exponent];
++        if (mantissa > 9)
++                mantissa = 9;
++
++        retval = (mantissa << 4) | exponent;
++
++        *strptr = cp;
++
++        return (retval);
++}
++
++/* converts ascii lat/lon to unsigned encoded 32-bit number.
++ *  moves pointer. */
++static u_int32_t
++latlon2ul(char **latlonstrptr,int *which)
++{
++        register char *cp;
++        u_int32_t retval;
++        int deg = 0, min = 0, secs = 0, secsfrac = 0;
++
++        cp = *latlonstrptr;
++
++        while (isdigit(*cp))
++                deg = deg * 10 + (*cp++ - '0');
++
++        while (isspace(*cp))
++                cp++;
++
++        if (!(isdigit(*cp)))
++                goto fndhemi;
++
++        while (isdigit(*cp))
++                min = min * 10 + (*cp++ - '0');
++        while (isspace(*cp))
++                cp++;
++
++        if (!(isdigit(*cp)))
++                goto fndhemi;
++
++        while (isdigit(*cp))
++                secs = secs * 10 + (*cp++ - '0');
++
++        if (*cp == '.') {               /* decimal seconds */
++                cp++;
++                if (isdigit(*cp)) {
++                        secsfrac = (*cp++ - '0') * 100;
++                        if (isdigit(*cp)) {
++                                secsfrac += (*cp++ - '0') * 10;
++                                if (isdigit(*cp)) {
++                                        secsfrac += (*cp++ - '0');
++                                }
++                        }
++                }
++        }
++
++        while (!isspace(*cp))   /* if any trailing garbage */
++                cp++;
++
++        while (isspace(*cp))
++                cp++;
++
++ fndhemi:
++        switch (*cp) {
++        case 'N': case 'n':
++        case 'E': case 'e':
++                retval = ((unsigned)1<<31)
++                        + (((((deg * 60) + min) * 60) + secs) * 1000)
++                        + secsfrac;
++                break;
++        case 'S': case 's':
++        case 'W': case 'w':
++                retval = ((unsigned)1<<31)
++                        - (((((deg * 60) + min) * 60) + secs) * 1000)
++                        - secsfrac;
++                break;
++        default:
++                retval = 0;     /* invalid value -- indicates error */
++                break;
++        }
++
++        switch (*cp) {
++        case 'N': case 'n':
++        case 'S': case 's':
++                *which = 1;     /* latitude */
++                break;
++        case 'E': case 'e':
++        case 'W': case 'w':
++                *which = 2;     /* longitude */
++                break;
++        default:
++                *which = 0;     /* error */
++                break;
++        }
++
++        cp++;                   /* skip the hemisphere */
++
++        while (!isspace(*cp))   /* if any trailing garbage */
++                cp++;
++
++        while (isspace(*cp))    /* move to next field */
++                cp++;
++
++        *latlonstrptr = cp;
++
++        return (retval);
++}
++
++/* converts a zone file representation in a string to an RDATA
++ * on-the-wire representation. */
++u_int32_t
++loc_aton(const char *ascii, u_char *binary)
++{
++        const char *cp, *maxcp;
++        u_char *bcp;
++
++        u_int32_t latit = 0, longit = 0, alt = 0;
++        u_int32_t lltemp1 = 0, lltemp2 = 0;
++        int altmeters = 0, altfrac = 0, altsign = 1;
++        u_int8_t hp = 0x16;    /* default = 1e6 cm = 10000.00m = 10km */
++        u_int8_t vp = 0x13;    /* default = 1e3 cm = 10.00m */
++        u_int8_t siz = 0x12;   /* default = 1e2 cm = 1.00m */
++        int which1 = 0, which2 = 0;
++
++        cp = ascii;
++        maxcp = cp + strlen(ascii);
++
++        lltemp1 = latlon2ul(&cp, &which1);
++        lltemp2 = latlon2ul(&cp, &which2);
++
++        switch (which1 + which2) {
++        case 3:                 /* 1 + 2, the only valid combination */
++                if ((which1 == 1) && (which2 == 2)) { /* normal case */
++                        latit = lltemp1;
++                        longit = lltemp2;
++                } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/
++                        longit = lltemp1;
++                        latit = lltemp2;
++                } else {        /* some kind of brokenness */
++                        return 0;
++                }
++                break;
++        default:                /* we didn't get one of each */
++                return 0;
++        }
++
++        /* altitude */
++        if (*cp == '-') {
++                altsign = -1;
++                cp++;
++        }
++
++        if (*cp == '+')
++                cp++;
++
++        while (isdigit(*cp))
++                altmeters = altmeters * 10 + (*cp++ - '0');
++
++        if (*cp == '.') {               /* decimal meters */
++                cp++;
++                if (isdigit(*cp)) {
++                        altfrac = (*cp++ - '0') * 10;
++                        if (isdigit(*cp)) {
++                                altfrac += (*cp++ - '0');
++                        }
++                }
++        }
++
++        alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
++
++        while (!isspace(*cp) && (cp < maxcp))
++                                           /* if trailing garbage or m */
++                cp++;
++
++        while (isspace(*cp) && (cp < maxcp))
++                cp++;
++        if (cp >= maxcp)
++                goto defaults;
++
++        siz = precsize_aton(&cp);
++
++        while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
++                cp++;
++
++        while (isspace(*cp) && (cp < maxcp))
++                cp++;
++
++        if (cp >= maxcp)
++                goto defaults;
++
++        hp = precsize_aton(&cp);
++
++        while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
++                cp++;
++
++        while (isspace(*cp) && (cp < maxcp))
++                cp++;
++
++        if (cp >= maxcp)
++                goto defaults;
++
++        vp = precsize_aton(&cp);
++
++ defaults:
++
++        bcp = binary;
++        *bcp++ = (u_int8_t) 0;  /* version byte */
++        *bcp++ = siz;
++        *bcp++ = hp;
++        *bcp++ = vp;
++        PUTLONG(latit,bcp);
++        PUTLONG(longit,bcp);
++        PUTLONG(alt,bcp);
++
++        return (16);            /* size of RR in octets */
++}
++
++/* takes an on-the-wire LOC RR and prints it in zone file
++ * (human readable) format. */
++char *
++loc_ntoa(const u_char *binary,char *ascii)
++{
++        static char tmpbuf[255*3];
++
++        register char *cp;
++        register const u_char *rcp;
++
++        int latdeg, latmin, latsec, latsecfrac;
++        int longdeg, longmin, longsec, longsecfrac;
++        char northsouth, eastwest;
++        int altmeters, altfrac, altsign;
++
++        const int referencealt = 100000 * 100;
++
++        int32_t latval, longval, altval;
++        u_int32_t templ;
++        u_int8_t sizeval, hpval, vpval, versionval;
++
++        char *sizestr, *hpstr, *vpstr;
++
++        rcp = binary;
++        if (ascii)
++                cp = ascii;
++        else {
++                cp = tmpbuf;
++        }
++
++        versionval = *rcp++;
++
++        if (versionval) {
++                sprintf(cp,"; error: unknown LOC RR version");
++                return (cp);
++        }
++
++        sizeval = *rcp++;
++
++        hpval = *rcp++;
++        vpval = *rcp++;
++
++        GETLONG(templ,rcp);
++        latval = (templ - ((unsigned)1<<31));
++
++        GETLONG(templ,rcp);
++        longval = (templ - ((unsigned)1<<31));
++
++        GETLONG(templ,rcp);
++        if (templ < referencealt) { /* below WGS 84 spheroid */
++                altval = referencealt - templ;
++                altsign = -1;
++        } else {
++                altval = templ - referencealt;
++                altsign = 1;
++        }
++
++        if (latval < 0) {
++                northsouth = 'S';
++                latval = -latval;
++        }
++        else
++                northsouth = 'N';
++
++        latsecfrac = latval % 1000;
++        latval = latval / 1000;
++        latsec = latval % 60;
++        latval = latval / 60;
++        latmin = latval % 60;
++        latval = latval / 60;
++        latdeg = latval;
++
++        if (longval < 0) {
++                eastwest = 'W';
++                longval = -longval;
++        }
++        else
++                eastwest = 'E';
++
++        longsecfrac = longval % 1000;
++        longval = longval / 1000;
++        longsec = longval % 60;
++        longval = longval / 60;
++        longmin = longval % 60;
++        longval = longval / 60;
++        longdeg = longval;
++
++        altfrac = altval % 100;
++        altmeters = (altval / 100) * altsign;
++
++        sizestr = strdup(precsize_ntoa(sizeval));
++        hpstr = strdup(precsize_ntoa(hpval));
++        vpstr = strdup(precsize_ntoa(vpval));
++
++        sprintf(cp,
++                "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
++                latdeg, latmin, latsec, latsecfrac, northsouth,
++                longdeg, longmin, longsec, longsecfrac, eastwest,
++                altmeters, altfrac, sizestr, hpstr, vpstr);
++        free(sizestr);
++        free(hpstr);
++        free(vpstr);
++
++        return (cp);
++}
diff --git a/contrib/dnslist/dhcp.css b/contrib/dnslist/dhcp.css
new file mode 100644 (file)
index 0000000..79cea39
--- /dev/null
@@ -0,0 +1,57 @@
+body
+{
+       font-family: sans-serif;
+       color: #000;
+}
+
+h1
+{
+       font-size: medium;
+       font-weight: bold;
+}
+
+h1 .updated
+{
+       color: #999;
+}
+
+table
+{
+       border-collapse: collapse;
+       border-bottom: 2px solid #000;
+}
+
+th
+{
+       background: #DDD;
+       border-top: 2px solid #000;
+       text-align: left;
+       font-weight: bold;
+}
+
+/* Any row */
+
+tr
+{
+       border-top: 2px solid #000;
+}
+
+/* Any row but the first or second (overrides above rule) */
+
+tr + tr + tr
+{
+       border-top: 2px solid #999;
+}
+
+tr.offline td.hostname
+{
+       color: #999;
+}
+
+.hostname   { width: 10em; }
+.ip_addr    { width: 10em; background: #DDD; }
+.ether_addr { width: 15em; }
+.client_id  { width: 15em; background: #DDD; }
+.status     { width: 5em;  }
+.since      { width: 10em; background: #DDD; }
+.lease      { width: 10em; }
diff --git a/contrib/dnslist/dnslist.pl b/contrib/dnslist/dnslist.pl
new file mode 100755 (executable)
index 0000000..7ce2720
--- /dev/null
@@ -0,0 +1,608 @@
+#!/usr/bin/perl
+
+# dnslist - Read state file from dnsmasq and create a nice web page to display
+#           a list of DHCP clients.
+# 
+# Copyright (C) 2004  Thomas Tuttle
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program*; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# 
+# * The license is in fact included at the end of this file, and can
+#   either be viewed by reading everything after "__DATA__" or by
+#   running dnslist with the '-l' option.
+# 
+# Version: 0.2
+# Author:  Thomas Tuttle
+# Email:   dnslist.20.thinkinginbinary@spamgourmet.org
+# License: GNU General Public License, version 2.0
+#
+# v. 0.0: Too ugly to publish, thrown out.
+#
+# v. 0.1: First rewrite.
+#         Added master host list so offline hosts can still be displayed.
+#         Fixed modification detection (a newer modification time is lower.)
+#
+# v. 0.2: Fixed Client ID = "*" => "None"
+#         Fixed HTML entities (a client ID of ????<? screwed it up)
+#         Fixed command-line argument processing (apparently, "shift @ARGV" !=
+#             "$_ = shift @ARGV"...)
+#         Added license information.
+
+use Template;
+
+# Location of state file.  (This is the dnsmasq default.)
+# Change with -s <file>
+my $dnsmasq_state_file = '/var/lib/misc/dnsmasq.leases';
+# Location of template.  (Assumed to be in current directory.)
+# Change with -t <file>
+my $html_template_file = 'dnslist.tt2';
+# File to write HTML page to.  (This is where Slackware puts WWW pages.  It may
+# be different on other systems.  Make sure the permissions are set correctly
+# for it.)
+my $html_output_file = '/var/www/htdocs/dhcp.html';
+# Time to wait after each page update.  (The state file is checked for changes
+# before each update but is not read in each time, in case it is very big.  The
+# page is rewritten just so the "(updated __/__ __:__:__)" text changes ;-)
+my $wait_time = 2;
+
+# Read command-line arguments.
+while ($_ = shift @ARGV) {
+       if (/-s/) { $dnsmasq_state_file = shift; next; }
+       if (/-t/) { $html_template_file = shift; next; }
+       if (/-o/) { $html_output_file = shift;   next; }
+       if (/-d/) { $wait_time = shift;          next; }
+       if (/-l/) { show_license();              exit; }
+       die "usage: dnslist [-s state_file] [-t template_file] [-o output_file] [-d delay_time]\n";
+}
+
+# Master list of clients, offline and online.
+my $list = {};
+# Sorted host list.  (It's actually sorted by IP--the sub &byip() compares two
+# IP addresses, octet by octet, and figures out which is higher.)
+my @hosts = ();
+# Last time the state file was changed.
+my $last_state_change;
+
+# Check for a change to the state file.
+sub check_state {
+       if (defined $last_state_change) {
+               if (-M $dnsmasq_state_file < $last_state_change) {
+                       print "check_state: state file has been changed.\n";
+                       $last_state_change = -M $dnsmasq_state_file;
+                       return 1;
+               } else {
+                       return 0;
+               }
+       } else {
+               # Last change undefined, so we are running for the first time.
+               print "check_state: reading state file at startup.\n";
+               read_state();
+               $last_state_change = -M $dnsmasq_state_file;
+               return 1;
+       }
+}
+
+# Read data in state file.
+sub read_state {
+       my $old;
+       my $new;
+       # Open file.
+       unless (open STATE, $dnsmasq_state_file) {
+               warn "read_state: can't open $dnsmasq_state_file!\n";
+               return 0;
+       }
+       # Mark all hosts as offline, saving old state.
+       foreach $ether (keys %{$list}) {
+               $list->{$ether}->{'old_online'} = $list->{$ether}->{'online'};
+               $list->{$ether}->{'online'} = 0;
+       }
+       # Read hosts.
+       while (<STATE>) {
+               chomp;
+               @host{qw/raw_lease ether_addr ip_addr hostname raw_client_id/} = split /\s+/;
+               $ether = $host{ether_addr};
+               # Mark each online host as online.
+               $list->{$ether}->{'online'} = 1;
+               # Copy data to master list.
+               foreach $key (keys %host) {
+                       $list->{$ether}->{$key} = $host{$key};
+               }
+       }
+       close STATE;
+       # Handle changes in offline/online state.  (The sub &do_host() handles
+       # all of the extra stuff to do with a host's data once it is read.
+       foreach $ether (keys %{$list}) {
+               $old = $list->{$ether}->{'old_online'};
+               $new = $list->{$ether}->{'online'};
+               if (not $old) {
+                       if (not $new) {
+                               do_host($ether, 'offline');
+                       } else {
+                               do_host($ether, 'join');
+                       }
+               } else {
+                       if (not $new) {
+                               do_host($ether, 'leave');
+                       } else {
+                               do_host($ether, 'online');
+                       }
+               }
+       }
+       # Sort hosts by IP ;-)
+       @hosts = sort byip values %{$list};
+       # Copy sorted list to template data store.
+       $data->{'hosts'} = [ @hosts ];
+}
+
+# Do stuff per host.
+sub do_host {
+       my ($ether, $status) = @_;
+       
+       # Find textual representation of DHCP client ID.
+       if ($list->{$ether}->{'raw_client_id'} eq '*') {
+               $list->{$ether}->{'text_client_id'} = 'None';
+       } else {
+               my $text = "";
+               foreach $char (split /:/, $list->{$ether}->{'raw_client_id'}) {
+                       $char = pack('H2', $char);
+                       if (ord($char) >= 32 and ord($char) <= 127) {
+                               $text .= $char;
+                       } else {
+                               $text .= "?";
+                       }
+               }
+               $list->{$ether}->{'text_client_id'} = $text;
+       }
+               
+       # Convert lease expiration date/time to text.
+       if ($list->{$ether}->{'raw_lease'} == 0) {
+               $list->{$ether}->{'text_lease'} = 'Never';
+       } else {
+               $list->{$ether}->{'text_lease'} = nice_time($list->{$ether}->{'raw_lease'});
+       }
+       
+       if ($status eq 'offline') {
+               # Nothing to do.
+       } elsif ($status eq 'online') {
+               # Nothing to do.
+       } elsif ($status eq 'join') {
+               # Update times for joining host.
+               print "do_host: $ether joined the network.\n";
+               $list->{$ether}->{'join_time'} = time;
+               $list->{$ether}->{'since'} = nice_time(time);
+       } elsif ($status eq 'leave') {
+               # Update times for leaving host.
+               print "do_host: $ether left the network.\n";
+               $list->{$ether}->{'leave_time'} = time;
+               $list->{$ether}->{'since'} = nice_time(time);
+       }
+       
+}
+
+# Convert time to a string representation.
+sub nice_time {
+       my $time = shift;
+       my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $dst) = localtime($time);
+       $sec = pad($sec, '0', 2);
+       $min = pad($min, '0', 2);
+       $hour = pad($hour, '0', 2);
+       $mon = pad($mon, '0', 2);
+       $mday = pad($mday, '0', 2);
+       return "$mon/$mday $hour:$min:$sec";
+}
+
+# Pad string to a certain length by repeatedly prepending another string.
+sub pad {
+       my ($text, $pad, $length) = @_;
+       while (length($text) < $length) {
+               $text = "$pad$text";
+       }
+       return $text;
+}
+
+# Compare two IP addresses.  (Uses $a and $b from sort.)
+sub byip {
+       # Split into octets.
+       my @a = split /\./, $a->{ip_addr};
+       my @b = split /\./, $b->{ip_addr};
+       # Compare octets.
+       foreach $n (0..3) {
+               return $a[$n] <=> $b[$n] if ($a[$n] != $b[$n]);
+       }
+       # If we get here there is no difference.
+       return 0;
+}
+               
+# Output HTML file.
+sub write_output {
+       # Create new template object.
+       my $template = Template->new(
+               {
+                       ABSOLUTE => 1, # /var/www/... is an absolute path
+                       OUTPUT => $html_output_file # put it here, not STDOUT
+               }
+       );
+       $data->{'updated'} = nice_time(time); # add "(updated ...)" to file
+       unless ($template->process($html_template_file, $data)) { # do it
+               warn "write_output: Template Toolkit error: " . $template->error() . "\n";
+               return 0;
+       }
+       print "write_output: page updated.\n";
+       return 1;
+}
+
+sub show_license {
+       while (<DATA>) {
+               print;
+               $line++;
+               if ($line == 24) { <>; $line = 1; }
+       }
+}
+
+# Main loop.
+while (1) {
+       # Check for state change.
+       if (check_state()) {
+               read_state();
+               sleep 1; # Sleep for a second just so we don't wear anything
+                        # out.  (By not sleeping the whole time after a change
+                        # we can detect rapid changes more easily--like if 300
+                        # hosts all come back online, they show up quicker.)
+       } else {
+               sleep $wait_time; # Take a nap.
+       }
+       write_output(); # Write the file anyway.
+}
+__DATA__
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/contrib/dnslist/dnslist.tt2 b/contrib/dnslist/dnslist.tt2
new file mode 100644 (file)
index 0000000..1998e5f
--- /dev/null
@@ -0,0 +1,32 @@
+<html>
+       <head>
+               <title>DHCP Clients</title>
+               <link rel="stylesheet" href="dhcp.css"/>
+               <meta http-equiv="Refresh" content="2"/>
+       </head>
+       <body>
+               <h1>DHCP Clients <span class="updated">(updated [% updated %])</span></h1>
+               <table cols="7">
+               <tr>
+                       <th class="hostname">Hostname</th>
+                       <th class="ip_addr">IP Address</th>
+                       <th class="ether_addr">Ethernet Address</th>
+                       <th class="client_id">DHCP Client ID</th>
+                       <th class="status">Status</th>
+                       <th class="since">Since</th>
+                       <th class="lease">Lease Expires</th>
+               </tr>
+               [% FOREACH host IN hosts %]
+                       <tr class="[% IF host.online %]online[% ELSE %]offline[% END %]">
+                               <td class="hostname">[% host.hostname %]</td>
+                               <td class="ip_addr">[% host.ip_addr %]</td>
+                               <td class="ether_addr">[% host.ether_addr %]</td>
+                               <td class="client_id">[% host.text_client_id %] ([% host.raw_client_id %])</td>
+                               <td class="status">[% IF host.online %]Online[% ELSE %]Offline[% END %]</td>
+                               <td class="since">[% host.since %]</td>
+                               <td class="lease">[% host.text_lease %]</td>
+                       </tr>
+               [% END %]
+               </table>
+       </body>
+</html>
diff --git a/contrib/dnsmasq_MacOSX-pre10.4/DNSmasq b/contrib/dnsmasq_MacOSX-pre10.4/DNSmasq
new file mode 100755 (executable)
index 0000000..6b62118
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+. /etc/rc.common
+
+StartService() {
+  if [ "${DNSMASQ:=-NO-}" = "-YES-" ] ; then
+    /usr/local/sbin/dnsmasq -q -n
+  fi
+}
+
+StopService() {
+  pid=`GetPID dnsmasq`
+  if [ $? -eq 0 ]; then
+    kill $pid
+  fi
+}
+
+RestartService() {
+  StopService "$@"
+  StartService "$@"
+}
+
+RunService "$1"
diff --git a/contrib/dnsmasq_MacOSX-pre10.4/README.rtf b/contrib/dnsmasq_MacOSX-pre10.4/README.rtf
new file mode 100644 (file)
index 0000000..da48411
--- /dev/null
@@ -0,0 +1,42 @@
+{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf100
+{\fonttbl\f0\fswiss\fcharset77 Helvetica;\f1\fnil\fcharset77 Monaco;}
+{\colortbl;\red255\green255\blue255;}
+\paperw11900\paperh16840\margl1440\margr1440\vieww11120\viewh10100\viewkind0
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
+
+\f0\fs24 \cf0 1.       If you've used DNSenabler, or if you're using Mac OS X Server, or if you have in any other way activated Mac OS X's built-in DHCP and/or DNS servers, disable them.  This would usually involve checking that they are either set to -NO- or absent altogether in 
+\f1 /etc/hostconfig
+\f0 .  If you've never done anything to do with DNS or DHCP servers on a client version of MacOS X, you won't need to worry about this; it will already be configured for you.\
+\
+2.     Add a configuration item to 
+\f1 /etc/hostconfig
+\f0  as follows:\
+\
+
+\f1 DNSMASQ=-YES-
+\f0 \
+\
+3.     Create a system-wide StartupItems directory for dnsmasq:\
+\
+
+\f1 sudo mkdir -p /Library/StartupItems/DNSmasq\
+
+\f0 \
+4.     Copy the files 
+\f1 DNSmasq
+\f0  and 
+\f1 StartupParameters.plist
+\f0  into this directory, and make sure the former is executable:\
+\
+
+\f1 sudo cp DNSmasq StartupParameters.plist /Library/StartupItems/DNSmasq\
+sudo chmod 755 /Library/StartupItems/DNSmasq/DNSmasq\
+
+\f0 \
+5.     Start the service:\
+\
+
+\f1 sudo /Library/StartupItems/DNSmasq/DNSmasq start\
+
+\f0 \cf0 \
+That should be all...}
\ No newline at end of file
diff --git a/contrib/dnsmasq_MacOSX-pre10.4/StartupParameters.plist b/contrib/dnsmasq_MacOSX-pre10.4/StartupParameters.plist
new file mode 100644 (file)
index 0000000..454bda0
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Description</key>
+       <string>DNSmasq</string>
+       <key>OrderPreference</key>
+       <string>None</string>
+       <key>Provides</key>
+       <array>
+               <string>DNSmasq</string>
+       </array>
+       <key>Uses</key>
+       <array>
+               <string>Network</string>
+       </array>
+       </dict>
+</plist>
diff --git a/contrib/dynamic-dnsmasq/dynamic-dnsmasq.pl b/contrib/dynamic-dnsmasq/dynamic-dnsmasq.pl
new file mode 100755 (executable)
index 0000000..3c4a1f1
--- /dev/null
@@ -0,0 +1,249 @@
+#!/usr/bin/perl
+# dynamic-dnsmasq.pl - update dnsmasq's internal dns entries dynamically
+# Copyright (C) 2004  Peter Willis
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# 
+# the purpose of this script is to be able to update dnsmasq's dns
+# records from a remote dynamic dns client.
+# 
+# basic use of this script:
+# dynamic-dnsmasq.pl add testaccount 1234 testaccount.mydomain.com
+# dynamic-dnsmasq.pl listen &
+# 
+# this script tries to emulate DynDNS.org's dynamic dns service, so
+# technically you should be able to use any DynDNS.org client to
+# update the records here. tested and confirmed to work with ddnsu
+# 1.3.1. just point the client's host to the IP of this machine,
+# port 9020, and include the hostname, user and pass, and it should
+# work.
+# 
+# make sure "addn-hosts=/etc/dyndns-hosts" is in your /etc/dnsmasq.conf
+# file and "nopoll" is commented out.
+
+use strict;
+use IO::Socket;
+use MIME::Base64;
+use DB_File;
+use Fcntl;
+
+my $accountdb = "accounts.db";
+my $recordfile = "/etc/dyndns-hosts";
+my $dnsmasqpidfile = "/var/run/dnsmasq.pid"; # if this doesn't exist, will look for process in /proc
+my $listenaddress = "0.0.0.0";
+my $listenport = 9020;
+
+# no editing past this point should be necessary
+
+if ( @ARGV < 1 ) {
+       die "Usage: $0 ADD|DEL|LISTUSERS|WRITEHOSTSFILE|LISTEN\n";
+} elsif ( lc $ARGV[0] eq "add" ) {
+       die "Usage: $0 ADD USER PASS HOSTNAME\n" unless @ARGV == 4;
+       add_acct($ARGV[1], $ARGV[2], $ARGV[3]);
+} elsif ( lc $ARGV[0] eq "del" ) {
+       die "Usage: $0 DEL USER\n" unless @ARGV == 2;
+       print "Are you sure you want to delete user \"$ARGV[1]\"? [N/y] ";
+       my $resp = <STDIN>;
+       chomp $resp;
+       if ( lc substr($resp,0,1) eq "y" ) {
+               del_acct($ARGV[1]);
+       }
+} elsif ( lc $ARGV[0] eq "listusers" or lc $ARGV[0] eq "writehostsfile" ) {
+       my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
+       my $fh;
+       if ( lc $ARGV[0] eq "writehostsfile" ) {
+               open($fh, ">$recordfile") || die "Couldn't open recordfile \"$recordfile\": $!\n";
+               flock($fh, 2);
+               seek($fh, 0, 0);
+               truncate($fh, 0);
+        }
+       while ( my ($key, $val) = each %h ) {
+               my ($pass, $domain, $ip) = split("\t",$val);
+               if ( lc $ARGV[0] eq "listusers" ) {
+                       print "user $key, hostname $domain, ip $ip\n";
+               } else {
+                       if ( defined $ip ) {
+                               print $fh "$ip\t$domain\n";
+                       }
+               }
+       }
+       if ( lc $ARGV[0] eq "writehostsfile" ) {
+               flock($fh, 8);
+               close($fh);
+               dnsmasq_rescan_configs();
+       }
+       undef $X;
+       untie %h;
+} elsif ( lc $ARGV[0] eq "listen" ) {
+       listen_for_updates();
+}
+
+sub listen_for_updates {
+       my $sock = IO::Socket::INET->new(Listen    => 5,
+               LocalAddr => $listenaddress, LocalPort => $listenport,
+               Proto     => 'tcp', ReuseAddr => 1,
+               MultiHomed => 1) || die "Could not open listening socket: $!\n";
+       $SIG{'CHLD'} = 'IGNORE';
+       while ( my $client = $sock->accept() ) {
+               my $p = fork();
+               if ( $p != 0 ) {
+                       next;
+               }
+               $SIG{'CHLD'} = 'DEFAULT';
+               my @headers;
+               my %cgi;
+               while ( <$client> ) {
+                       s/(\r|\n)//g;
+                       last if $_ eq "";
+                       push @headers, $_;
+               }
+               foreach my $header (@headers) {
+                       if ( $header =~ /^GET \/nic\/update\?([^\s].+) HTTP\/1\.[01]$/ ) {
+                               foreach my $element (split('&', $1)) {
+                                       $cgi{(split '=', $element)[0]} = (split '=', $element)[1];
+                               }
+                       } elsif ( $header =~ /^Authorization: basic (.+)$/ ) {
+                               unless ( defined $cgi{'hostname'} ) {
+                                       print_http_response($client, undef, "badsys");
+                                       exit(1);
+                               }
+                               if ( !exists $cgi{'myip'} ) {
+                                       $cgi{'myip'} = $client->peerhost();
+                               }
+                               my ($user,$pass) = split ":", MIME::Base64::decode($1);
+                               if ( authorize($user, $pass, $cgi{'hostname'}, $cgi{'myip'}) == 0 ) {
+                                       print_http_response($client, $cgi{'myip'}, "good");
+                                       update_dns(\%cgi);
+                               } else {
+                                       print_http_response($client, undef, "badauth");
+                                       exit(1);
+                               }
+                               last;
+                       }
+               }
+               exit(0);
+       }
+       return(0);
+}
+
+sub add_acct {
+       my ($user, $pass, $hostname) = @_;
+       my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
+       $X->put($user, join("\t", ($pass, $hostname)));
+       undef $X;
+       untie %h;
+}
+
+sub del_acct {
+        my ($user, $pass, $hostname) = @_;
+        my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
+        $X->del($user);
+        undef $X;
+        untie %h;
+}
+
+
+sub authorize {
+       my $user = shift;
+       my $pass = shift;
+       my $hostname = shift;
+       my $ip = shift;;
+       my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
+       my ($spass, $shost) = split("\t", $h{$user});
+       if ( defined $h{$user} and ($spass eq $pass) and ($shost eq $hostname) ) {
+               $X->put($user, join("\t", $spass, $shost, $ip));
+               undef $X;
+               untie %h;
+               return(0);
+       }
+       undef $X;
+       untie %h;
+       return(1);
+}
+
+sub print_http_response {
+       my $sock = shift;
+       my $ip = shift;
+       my $response = shift;
+       print $sock "HTTP/1.0 200 OK\n";
+       my @tmp = split /\s+/, scalar gmtime();
+       print $sock "Date: $tmp[0], $tmp[2] $tmp[1] $tmp[4] $tmp[3] GMT\n";
+       print $sock "Server: Peter's Fake DynDNS.org Server/1.0\n";
+       print $sock "Content-Type: text/plain; charset=ISO-8859-1\n";
+       print $sock "Connection: close\n";
+       print $sock "Transfer-Encoding: chunked\n";
+       print $sock "\n";
+       #print $sock "12\n"; # this was part of the dyndns response but i'm not sure what it is
+       print $sock "$response", defined($ip)? " $ip" : "" . "\n";
+}
+
+sub update_dns {
+       my $hashref = shift;
+       my @records;
+       my $found = 0;
+       # update the addn-hosts file
+       open(FILE, "+<$recordfile") || die "Couldn't open recordfile \"$recordfile\": $!\n";
+       flock(FILE, 2);
+       while ( <FILE> ) {
+               if ( /^(\d+\.\d+\.\d+\.\d+)\s+$$hashref{'hostname'}\n$/si ) {
+                       if ( $1 ne $$hashref{'myip'} ) {
+                               push @records, "$$hashref{'myip'}\t$$hashref{'hostname'}\n";
+                               $found = 1;
+                       }
+               } else {
+                       push @records, $_;
+               }
+       }
+       unless ( $found ) {
+               push @records, "$$hashref{'myip'}\t$$hashref{'hostname'}\n";
+       }
+       sysseek(FILE, 0, 0);
+       truncate(FILE, 0);
+       syswrite(FILE, join("", @records));
+       flock(FILE, 8);
+       close(FILE);
+       dnsmasq_rescan_configs();
+       return(0);
+}
+
+sub dnsmasq_rescan_configs {
+       # send the HUP signal to dnsmasq
+       if ( -r $dnsmasqpidfile ) {
+               open(PID,"<$dnsmasqpidfile") || die "Could not open PID file \"$dnsmasqpidfile\": $!\n";
+               my $pid = <PID>;
+               close(PID);
+               chomp $pid;
+               if ( kill(0, $pid) ) {
+                       kill(1, $pid);
+               } else {
+                       goto LOOKFORDNSMASQ;
+               }
+       } else {
+               LOOKFORDNSMASQ:
+               opendir(DIR,"/proc") || die "Couldn't opendir /proc: $!\n";
+               my @dirs = grep(/^\d+$/, readdir(DIR));
+               closedir(DIR);
+               foreach my $process (@dirs) {
+                       if ( open(FILE,"</proc/$process/cmdline") ) {
+                               my $cmdline = <FILE>;
+                               close(FILE);
+                               if ( (split(/\0/,$cmdline))[0] =~ /dnsmasq/ ) {
+                                       kill(1, $process);
+                               }
+                       }
+               }
+       }
+       return(0);
+}
diff --git a/contrib/lease-access/README b/contrib/lease-access/README
new file mode 100644 (file)
index 0000000..fc66bdf
--- /dev/null
@@ -0,0 +1,20 @@
+Hello,
+
+For some specific application I needed to deny access to a MAC address
+to a lease. For this reason I modified the dhcp-script behavior and is
+called with an extra parameter "access" once a dhcp request or discover
+is received. In that case if the exit code of the script is zero,
+dnsmasq continues normally, and if non-zero the packet is ignored.
+
+This was not added as a security feature but as a mean to handle
+differently some addresses. It is also quite intrusive since it requires
+changes in several other subsystems.
+
+It attach the patch in case someone is interested.
+
+regards,
+Nikos
+
+nmav@gennetsa.com
+
+
diff --git a/contrib/lease-access/lease.access.patch b/contrib/lease-access/lease.access.patch
new file mode 100644 (file)
index 0000000..ad76e25
--- /dev/null
@@ -0,0 +1,578 @@
+Index: src/dnsmasq.c
+===================================================================
+--- src/dnsmasq.c      (revision 696)
++++ src/dnsmasq.c      (revision 821)
+@@ -59,7 +59,6 @@
+ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
+ static void check_dns_listeners(fd_set *set, time_t now);
+ static void sig_handler(int sig);
+-static void async_event(int pipe, time_t now);
+ static void fatal_event(struct event_desc *ev);
+ static void poll_resolv(void);
+@@ -275,7 +274,7 @@
+   piperead = pipefd[0];
+   pipewrite = pipefd[1];
+   /* prime the pipe to load stuff first time. */
+-  send_event(pipewrite, EVENT_RELOAD, 0); 
++  send_event(pipewrite, EVENT_RELOAD, 0, 0); 
+   err_pipe[1] = -1;
+   
+@@ -340,7 +339,7 @@
+           }
+         else if (getuid() == 0)
+           {
+-            send_event(err_pipe[1], EVENT_PIDFILE, errno);
++            send_event(err_pipe[1], EVENT_PIDFILE, errno, 0);
+             _exit(0);
+           }
+       }
+@@ -372,7 +371,7 @@
+         (setgroups(0, &dummy) == -1 ||
+          setgid(gp->gr_gid) == -1))
+       {
+-        send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
++        send_event(err_pipe[1], EVENT_GROUP_ERR, errno, 0);
+         _exit(0);
+       }
+   
+@@ -415,14 +414,14 @@
+         if (bad_capabilities != 0)
+           {
+-            send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities);
++            send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, 0);
+             _exit(0);
+           }
+         
+         /* finally drop root */
+         if (setuid(ent_pw->pw_uid) == -1)
+           {
+-            send_event(err_pipe[1], EVENT_USER_ERR, errno);
++            send_event(err_pipe[1], EVENT_USER_ERR, errno, 0);
+             _exit(0);
+           }     
+@@ -434,7 +433,7 @@
+         /* lose the setuid and setgid capbilities */
+         if (capset(hdr, data) == -1)
+           {
+-            send_event(err_pipe[1], EVENT_CAP_ERR, errno);
++            send_event(err_pipe[1], EVENT_CAP_ERR, errno, 0);
+             _exit(0);
+           }
+ #endif
+@@ -647,7 +646,7 @@
+       }
+       
+       if (FD_ISSET(piperead, &rset))
+-      async_event(piperead, now);
++      async_event(piperead, now, NULL, 0);
+       
+ #ifdef HAVE_LINUX_NETWORK
+       if (FD_ISSET(daemon->netlinkfd, &rset))
+@@ -674,7 +673,7 @@
+ #endif      
+       if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
+-      dhcp_packet(now);
++      dhcp_packet(piperead, now);
+ #ifndef NO_FORK
+       if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
+@@ -719,17 +718,18 @@
+       else
+       return;
+-      send_event(pipewrite, event, 0); 
++      send_event(pipewrite, event, 0, 0); 
+       errno = errsave;
+     }
+ }
+-void send_event(int fd, int event, int data)
++void send_event(int fd, int event, int data, int priv)
+ {
+   struct event_desc ev;
+   
+   ev.event = event;
+   ev.data = data;
++  ev.priv = priv;
+   
+   /* error pipe, debug mode. */
+   if (fd == -1)
+@@ -771,14 +771,17 @@
+       die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
+     }
+ }     
+-      
+-static void async_event(int pipe, time_t now)
++
++/* returns the private data of the event
++ */
++int async_event(int pipe, time_t now, struct event_desc* event, unsigned int secs)
+ {
+   pid_t p;
+   struct event_desc ev;
+   int i;
+-  if (read_write(pipe, (unsigned char *)&ev, sizeof(ev), 1))
++  if (read_timeout(pipe, (unsigned char *)&ev, sizeof(ev), now, secs) > 0) 
++    {
+     switch (ev.event)
+       {
+       case EVENT_RELOAD:
+@@ -872,6 +875,14 @@
+       flush_log();
+       exit(EC_GOOD);
+       }
++    }
++  else
++    return -1; /* timeout */
++
++  if (event)
++    memcpy( event, &ev, sizeof(ev));
++    
++  return 0;
+ }
+ static void poll_resolv()
+Index: src/config.h
+===================================================================
+--- src/config.h       (revision 696)
++++ src/config.h       (revision 821)
+@@ -51,6 +51,8 @@
+ #define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
+ #define LOG_MAX 5 /* log-queue length */
+ #define RANDFILE "/dev/urandom"
++#define SCRIPT_TIMEOUT 6
++#define LEASE_CHECK_TIMEOUT 10
+ /* DBUS interface specifics */
+ #define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
+Index: src/dnsmasq.h
+===================================================================
+--- src/dnsmasq.h      (revision 696)
++++ src/dnsmasq.h      (revision 821)
+@@ -116,6 +116,7 @@
+ /* Async event queue */
+ struct event_desc {
+   int event, data;
++  unsigned int priv;
+ };
+ #define EVENT_RELOAD    1
+@@ -390,6 +391,7 @@
+ #define ACTION_OLD_HOSTNAME  2
+ #define ACTION_OLD           3
+ #define ACTION_ADD           4
++#define ACTION_ACCESS        5
+ #define DHCP_CHADDR_MAX 16
+@@ -709,6 +711,7 @@
+ char *print_mac(char *buff, unsigned char *mac, int len);
+ void bump_maxfd(int fd, int *max);
+ int read_write(int fd, unsigned char *packet, int size, int rw);
++int read_timeout(int fd, unsigned char *packet, int size, time_t now, int secs);
+ /* log.c */
+ void die(char *message, char *arg1, int exit_code);
+@@ -748,7 +751,7 @@
+ /* dhcp.c */
+ void dhcp_init(void);
+-void dhcp_packet(time_t now);
++void dhcp_packet(int piperead, time_t now);
+ struct dhcp_context *address_available(struct dhcp_context *context, 
+                                      struct in_addr addr,
+@@ -792,14 +795,16 @@
+ void rerun_scripts(void);
+ /* rfc2131.c */
+-size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
++size_t dhcp_reply(int pipefd, struct dhcp_context *context, char *iface_name, int int_index,
+                 size_t sz, time_t now, int unicast_dest, int *is_inform);
+ /* dnsmasq.c */
+ int make_icmp_sock(void);
+ int icmp_ping(struct in_addr addr);
+-void send_event(int fd, int event, int data);
++void send_event(int fd, int event, int data, int priv);
+ void clear_cache_and_reload(time_t now);
++int wait_for_child(int pipe);
++int async_event(int pipe, time_t now, struct event_desc*, unsigned int timeout);
+ /* isc.c */
+ #ifdef HAVE_ISC_READER
+@@ -832,9 +837,9 @@
+ /* helper.c */
+ #ifndef NO_FORK
+ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
+-void helper_write(void);
++int helper_write(void);
+ void queue_script(int action, struct dhcp_lease *lease, 
+-                char *hostname, time_t now);
++                char *hostname, time_t now, unsigned int uid);
+ int helper_buf_empty(void);
+ #endif
+Index: src/util.c
+===================================================================
+--- src/util.c (revision 696)
++++ src/util.c (revision 821)
+@@ -444,3 +444,38 @@
+   return 1;
+ }
++int read_timeout(int fd, unsigned char *packet, int size, time_t now, int secs)
++{
++  ssize_t n, done;
++  time_t expire;
++  
++  expire = now + secs;
++  
++  for (done = 0; done < size; done += n)
++    {
++    retry:
++      if (secs > 0) alarm(secs);
++      n = read(fd, &packet[done], (size_t)(size - done));
++
++      if (n == 0)
++        return 0;
++      else if (n == -1)
++        {
++          if (errno == EINTR) {
++            my_syslog(LOG_INFO, _("read timed out (errno %d)"), errno);
++            return 0;
++          }
++
++          if (retry_send() || errno == ENOMEM || errno == ENOBUFS || errno == EAGAIN)
++            {
++              if (secs == 0 || (secs > 0 && dnsmasq_time() < expire))
++                goto retry;
++            }
++
++          my_syslog(LOG_INFO, _("error in read (timeout %d, errno %d)"), secs, errno);
++          return 0;
++        }
++    }
++  return 1;
++}
++
+Index: src/dhcp.c
+===================================================================
+--- src/dhcp.c (revision 696)
++++ src/dhcp.c (revision 821)
+@@ -103,7 +103,7 @@
+   daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
+ }
+   
+-void dhcp_packet(time_t now)
++void dhcp_packet(int piperead, time_t now)
+ {
+   struct dhcp_packet *mess;
+   struct dhcp_context *context;
+@@ -239,7 +239,8 @@
+   if (!iface_enumerate(&parm, complete_context, NULL))
+     return;
+   lease_prune(NULL, now); /* lose any expired leases */
+-  iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, 
++
++  iov.iov_len = dhcp_reply(piperead, parm.current, ifr.ifr_name, iface_index, (size_t)sz, 
+                          now, unicast_dest, &is_inform);
+   lease_update_file(now);
+   lease_update_dns();
+Index: src/helper.c
+===================================================================
+--- src/helper.c       (revision 696)
++++ src/helper.c       (revision 821)
+@@ -45,6 +45,7 @@
+ #endif
+   unsigned char hwaddr[DHCP_CHADDR_MAX];
+   char interface[IF_NAMESIZE];
++  unsigned int uid;
+ };
+ static struct script_data *buf = NULL;
+@@ -60,7 +61,7 @@
+      then fork our process. */
+   if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
+     {
+-      send_event(err_fd, EVENT_PIPE_ERR, errno);
++      send_event(err_fd, EVENT_PIPE_ERR, errno, 0);
+       _exit(0);
+     }
+@@ -87,13 +88,13 @@
+       {
+         if (daemon->options & OPT_NO_FORK)
+           /* send error to daemon process if no-fork */
+-          send_event(event_fd, EVENT_HUSER_ERR, errno);
++          send_event(event_fd, EVENT_HUSER_ERR, errno, 0);
+         else
+           {
+             /* kill daemon */
+-            send_event(event_fd, EVENT_DIE, 0);
++            send_event(event_fd, EVENT_DIE, 0, 0);
+             /* return error */
+-            send_event(err_fd, EVENT_HUSER_ERR, errno);;
++            send_event(err_fd, EVENT_HUSER_ERR, errno, 0);
+           }
+         _exit(0);
+       }
+@@ -122,6 +123,8 @@
+       action_str = "del";
+       else if (data.action == ACTION_ADD)
+       action_str = "add";
++      else if (data.action == ACTION_ACCESS)
++      action_str = "access";
+       else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME)
+       action_str = "old";
+       else
+@@ -178,9 +181,11 @@
+               {
+                 /* On error send event back to main process for logging */
+                 if (WIFSIGNALED(status))
+-                  send_event(event_fd, EVENT_KILLED, WTERMSIG(status));
+-                else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
+-                  send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status));
++                  send_event(event_fd, EVENT_KILLED, WTERMSIG(status), data.uid);
++                else if (WIFEXITED(status))
++                  send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status), data.uid);
++                  else
++                  send_event(event_fd, EVENT_EXITED, -1, data.uid);
+                 break;
+               }
+             
+@@ -263,7 +268,7 @@
+         err = errno;
+       }
+       /* failed, send event so the main process logs the problem */
+-      send_event(event_fd, EVENT_EXEC_ERR, err);
++      send_event(event_fd, EVENT_EXEC_ERR, err, data.uid);
+       _exit(0); 
+     }
+ }
+@@ -295,7 +300,7 @@
+ }
+  
+ /* pack up lease data into a buffer */    
+-void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now)
++void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now, unsigned int uid)
+ {
+   unsigned char *p;
+   size_t size;
+@@ -332,6 +337,7 @@
+       buf_size = size;
+     }
++  buf->uid = uid;
+   buf->action = action;
+   buf->hwaddr_len = lease->hwaddr_len;
+   buf->hwaddr_type = lease->hwaddr_type;
+@@ -393,12 +399,15 @@
+   return bytes_in_buf == 0;
+ }
+-void helper_write(void)
++/* returns -1 if write failed for a reason, 1 if no data exist
++ * and 0 if everything was ok.
++ */
++int helper_write(void)
+ {
+   ssize_t rc;
+   if (bytes_in_buf == 0)
+-    return;
++    return 1;
+   
+   if ((rc = write(daemon->helperfd, buf, bytes_in_buf)) != -1)
+     {
+@@ -409,9 +418,11 @@
+   else
+     {
+       if (errno == EAGAIN || errno == EINTR)
+-      return;
++      return -1;
+       bytes_in_buf = 0;
+     }
++    
++  return 0;
+ }
+ #endif
+Index: src/rfc2131.c
+===================================================================
+--- src/rfc2131.c      (revision 696)
++++ src/rfc2131.c      (revision 821)
+@@ -100,8 +100,49 @@
+                                     int clid_len, unsigned char *clid, int *len_out);
+ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); 
++static int check_access_script( int piperead, struct dhcp_lease *lease, struct dhcp_packet *mess, time_t now)
++{
++#ifndef NO_FORK
++unsigned int uid;
++struct event_desc ev;
++int ret;
++struct dhcp_lease _lease;
++
++  if (daemon->lease_change_command == NULL) return 0; /* ok */
++
++  if (!lease) { /* if host has not been seen before lease is NULL */
++      memset(&_lease, 0, sizeof(_lease));
++      lease = &_lease;
++      lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
++  }
++
++  uid = rand16();
++  queue_script(ACTION_ACCESS, lease, NULL, now, uid);
++
++  /* send all data to helper process */
++  do 
++    {
++      helper_write();
++    } while (helper_buf_empty() == 0);
++
++  /* wait for our event */
++  ret = 0;
++  do 
++    {
++      ret = async_event( piperead, now, &ev, SCRIPT_TIMEOUT);
++    }
++  while(ev.priv != uid && ret >= 0);
++
++  if (ret < 0 || ev.data != 0) /* timeout or error */
++    {
++      return -1;
++    }
++
++#endif
++  return 0; /* ok */
++}
+         
+-size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
++size_t dhcp_reply(int piperead, struct dhcp_context *context, char *iface_name, int int_index,
+                 size_t sz, time_t now, int unicast_dest, int *is_inform)
+ {
+   unsigned char *opt, *clid = NULL;
+@@ -252,7 +293,7 @@
+       mac->netid.next = netid;
+       netid = &mac->netid;
+       }
+-  
++
+   /* Determine network for this packet. Our caller will have already linked all the 
+      contexts which match the addresses of the receiving interface but if the 
+      machine has an address already, or came via a relay, or we have a subnet selector, 
+@@ -329,7 +370,7 @@
+           my_syslog(LOG_INFO, _("Available DHCP range: %s -- %s"), daemon->namebuff, inet_ntoa(context_tmp->end));
+       }
+     }
+-
++    
+   mess->op = BOOTREPLY;
+   
+   config = find_config(daemon->dhcp_conf, context, clid, clid_len, 
+@@ -418,7 +459,7 @@
+             else
+               mess->yiaddr = lease->addr;
+           }
+-        
++
+         if (!message && 
+             !lease && 
+             (!(lease = lease_allocate(mess->yiaddr))))
+@@ -641,7 +682,14 @@
+       memcpy(req_options, option_ptr(opt, 0), option_len(opt));
+       req_options[option_len(opt)] = OPTION_END;
+     }
+-  
++
++  if (mess_type == DHCPREQUEST || mess_type == DHCPDISCOVER)
++    if (check_access_script(piperead, lease, mess, now) < 0)
++      {
++        my_syslog(LOG_INFO, _("Ignoring client due to access script"));
++        return 0;
++      }
++
+   switch (mess_type)
+     {
+     case DHCPDECLINE:
+Index: src/log.c
+===================================================================
+--- src/log.c  (revision 696)
++++ src/log.c  (revision 821)
+@@ -73,7 +73,7 @@
+   if (!log_reopen(daemon->log_file))
+     {
+-      send_event(errfd, EVENT_LOG_ERR, errno);
++      send_event(errfd, EVENT_LOG_ERR, errno, 0);
+       _exit(0);
+     }
+Index: src/lease.c
+===================================================================
+--- src/lease.c        (revision 696)
++++ src/lease.c        (revision 821)
+@@ -511,7 +511,7 @@
+       if (lease->old_hostname)
+       {
+ #ifndef NO_FORK
+-        queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
++        queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now, 0);
+ #endif
+         free(lease->old_hostname);
+         lease->old_hostname = NULL;
+@@ -520,7 +520,7 @@
+       else 
+       {
+ #ifndef NO_FORK
+-        queue_script(ACTION_DEL, lease, lease->hostname, now);
++        queue_script(ACTION_DEL, lease, lease->hostname, now, 0);
+ #endif
+         old_leases = lease->next;
+         
+@@ -540,7 +540,7 @@
+     if (lease->old_hostname)
+       {       
+ #ifndef NO_FORK
+-      queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
++      queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now, 0);
+ #endif
+       free(lease->old_hostname);
+       lease->old_hostname = NULL;
+@@ -552,7 +552,7 @@
+       (lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
+       {
+ #ifndef NO_FORK
+-      queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now);
++      queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now, 0);
+ #endif
+       lease->new = lease->changed = lease->aux_changed = 0;
+       
+Index: man/dnsmasq.8
+===================================================================
+--- man/dnsmasq.8      (revision 696)
++++ man/dnsmasq.8      (revision 821)
+@@ -724,12 +724,15 @@
+ .B \-6 --dhcp-script=<path>
+ Whenever a new DHCP lease is created, or an old one destroyed, the
+ binary specified by this option is run. The arguments to the process
+-are "add", "old" or "del", the MAC
++are "add", "old", "access" or "del", the MAC
+ address of the host (or "<null>"), the IP address, and the hostname,
+ if known. "add" means a lease has been created, "del" means it has
+ been destroyed, "old" is a notification of an existing lease when
+ dnsmasq starts or a change to MAC address or hostname of an existing
+ lease (also, lease length or expiry and client-id, if leasefile-ro is set).
++The "access" keyword means that a request was just received and depending
++on the script exit status request for address will be granted, if exit status
++is zero or not if it is non-zero.
+ The process is run as root (assuming that dnsmasq was originally run as
+ root) even if dnsmasq is configured to change UID to an unprivileged user.
+ The environment is inherited from the invoker of dnsmasq, and if the
diff --git a/contrib/openvpn/README b/contrib/openvpn/README
new file mode 100644 (file)
index 0000000..dd99600
--- /dev/null
@@ -0,0 +1,44 @@
+The patch I have attached lets me get the behavior I wish out of
+dnsmasq.  I also include my version of dhclient-enter-hooks as
+required for the switchover from pre-dnsmasq and dhclient.
+
+On 8/16/05, Joseph Tate <dragonstrider@gmail.com> wrote:
+> I'm trying to use dnsmasq on a laptop in order to facilitate openvpn
+> connections.  As such, the only configuration option I'm concerned
+> about is a single server=3D/example.com/192.168.0.1 line.
+>
+> The way I currently have it set up is I modified dhclient to write its
+> resolv.conf data to /etc/resolv.conf.dhclient and configured
+> /etc/dnsmasq.conf to look there for its upstream dns servers.
+> /etc/resolv.conf is set to nameserver 127.0.0.1
+>
+> All of this works great.  When I start the openvpn service, it the
+> routes, and queries to the domain in the server=3D line work just fine.
+>
+> The only problem is that the hostname for my system doesn't get set
+> correctly.  With the resolv.conf data written to something other than
+> /etc/resolv.conf, the ifup scripts don't have a valid dns server to do
+> the ipcalc call to set the laptop's hostname.  If I start dnsmasq
+> before the network comes up, something gets fubar'd.  I'm not sure how
+> to describe it exactly, but network services are slow to load, and
+> restarting networking and dnsmasq doesn't solve the problem.  Perhaps
+> dnsmasq is answering the dhcp request when the network starts?
+> Certainly not desired behavior.
+>
+> Anyway, my question: is there a way to have the best of both worlds?
+> DHCP requests to another server, and DNS lookups that work at all
+> times?
+>
+> My current best idea on how to solve this problem is modifying the
+> dnsmasq initscript to tweak /etc/dhclient-enter-hooks to change where
+> dhclient writes resolv.conf data, and fixing up /etc/resolv.conf on
+> the fly to set 127.0.0.1 to the nameserver (and somehow keep the
+> search domains intact), but I'm hoping that I'm just missing some key
+> piece of the puzzle and that this problem has been solved before.  Any
+> insights?
+>
+> --
+> Joseph Tate
+> Personal e-mail: jtate AT dragonstrider DOT com
+> Web: http://www.dragonstrider.com
+>
diff --git a/contrib/openvpn/dhclient-enter-hooks b/contrib/openvpn/dhclient-enter-hooks
new file mode 100644 (file)
index 0000000..cb78e2a
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+function save_previous() {
+  if [ -e $1 -a ! -e $1.predhclient ]; then
+    mv $1 $1.predhclient 
+  fi
+}
+
+function write_resolv_conf() {
+  RESOLVCONF=$1
+  if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
+    save_previous $RESOLVCONF
+    echo '; generated by /etc/dhclient-enter-hooks' > $RESOLVCONF
+    if [ -n "$SEARCH" ]; then
+       echo search $SEARCH >> $RESOLVCONF
+    else
+       if [ -n "$new_domain_name" ]; then
+           echo search $new_domain_name >> $RESOLVCONF
+       fi
+    fi
+    chmod 644 $RESOLVCONF
+    for nameserver in $new_domain_name_servers; do
+      echo nameserver $nameserver >>$RESOLVCONF
+    done
+  fi
+}
+
+make_resolv_conf() {
+  write_resolv_conf /etc/resolv.conf
+}
diff --git a/contrib/openvpn/dnsmasq.patch b/contrib/openvpn/dnsmasq.patch
new file mode 100644 (file)
index 0000000..5c11881
--- /dev/null
@@ -0,0 +1,61 @@
+--- dnsmasq-2.22/rpm/dnsmasq.rh        2005-03-24 09:51:18.000000000 -0500
++++ dnsmasq-2.22/rpm/dnsmasq.rh.new    2005-08-25 10:52:04.310568784 -0400
+@@ -2,7 +2,7 @@
+ #
+ # Startup script for the DNS caching server
+ #
+-# chkconfig: 2345 99 01
++# chkconfig: 2345 07 89
+ # description: This script starts your DNS caching server
+ # processname: dnsmasq
+ # pidfile: /var/run/dnsmasq.pid
+@@ -10,6 +10,25 @@
+ # Source function library.
+ . /etc/rc.d/init.d/functions
++function setup_dhclient_enter_hooks() {
++    if [ -f /etc/dhclient-enter-hooks ]; then
++        . /etc/dhclient-enter-hooks
++        cp /etc/resolv.conf /etc/resolv.conf.dnsmasq
++        cp /etc/dhclient-enter-hooks /etc/dhclient-enter-hooks.dnsmasq
++        sed -e 's/resolv\.conf$/resolv.conf.dnsmasq/' /etc/dhclient-enter-hooks.dnsmasq > /etc/dhclient-enter-hooks
++        sed -e 's/\(nameserver[ tab]\+\)[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/\1127.0.0.1/' /etc/resolv.conf.dnsmasq > /etc/resolv.conf
++    fi
++}
++
++function teardown_dhclient_enter_hooks() {
++    if [ -f /etc/dhclient-enter-hooks -a -f /etc/dhclient-enter-hooks.dnsmasq ]; then
++        if [ -f /etc/resolv.conf.dnsmasq ]; then
++            mv /etc/resolv.conf.dnsmasq /etc/resolv.conf
++        fi
++        mv /etc/dhclient-enter-hooks.dnsmasq /etc/dhclient-enter-hooks
++    fi
++}
++
+ # Source networking configuration.
+ . /etc/sysconfig/network
+@@ -24,7 +43,7 @@
+ MAILHOSTNAME=""
+ # change this line if you want dns to get its upstream servers from
+ # somewhere other that /etc/resolv.conf 
+-RESOLV_CONF=""
++RESOLV_CONF="/etc/resolv.conf.dnsmasq"
+ # change this if you want dnsmasq to cache any "hostname" or "client-hostname" from
+ # a dhcpd's lease file
+@@ -54,6 +73,7 @@
+ case "$1" in
+   start)
+         echo -n "Starting dnsmasq: "
++        setup_dhclient_enter_hooks
+         daemon $dnsmasq $OPTIONS
+       RETVAL=$?
+         echo
+@@ -62,6 +82,7 @@
+   stop)
+         if test "x`pidof dnsmasq`" != x; then
+             echo -n "Shutting down dnsmasq: "
++            teardown_dhclient_enter_hooks
+             killproc dnsmasq
+         fi
+       RETVAL=$?
diff --git a/contrib/port-forward/dnsmasq-portforward b/contrib/port-forward/dnsmasq-portforward
new file mode 100755 (executable)
index 0000000..f9bb857
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/bash
+# 
+# /usr/sbin/dnsmasq-portforward
+#
+# A script which gets run when the dnsmasq DHCP lease database changes.
+# It logs to $LOGFILE, if it exists, and maintains port-forwards using
+# IP-tables so that they always point to the correct host. See
+# $PORTSFILE for details on configuring this. dnsmasq must be version 2.34 
+# or later.
+#
+# To enable this script, add 
+#    dhcp-script=/usr/sbin/dnsmasq-portforward
+# to /etc/dnsmasq.conf
+#
+# To enable logging, touch $LOGFILE
+#
+
+PORTSFILE=/etc/portforward
+LOGFILE=/var/log/dhcp.log
+IPTABLES=/sbin/iptables
+
+action=${1:-0}
+hostname=${4}
+
+# log what's going on.
+if [ -f ${LOGFILE} ] ; then
+    date +"%D %T $*" >>${LOGFILE}
+fi
+
+# If a lease gets stripped of a name, we see that as an "old" action
+# with DNSMASQ_OLD_HOSTNAME set, convert it into a "del" 
+if [ ${DNSMASQ_OLD_HOSTNAME} ] && [ ${action} = old ] ; then
+    action=del
+    hostname=${DNSMASQ_OLD_HOSTNAME}
+fi
+
+# action init is not relevant, and will only be seen when leasefile-ro is set.
+if [ ${action} = init ] ; then
+    exit 0
+fi
+
+if [ ${hostname} ]; then
+    ports=$(sed -n -e "/^${hostname}\ .*/ s/^.* //p" ${PORTSFILE})
+
+    for port in $ports; do
+       verb=removed
+       protocol=tcp
+       if [ ${port:0:1} = u ] ; then
+           protocol=udp 
+           port=${port/u/}
+       fi
+       src=${port/:*/}
+       dst=${port/*:/}
+# delete first, to avoid multiple copies of rules.
+       ${IPTABLES} -t nat -D PREROUTING -p $protocol --destination-port $src -j DNAT --to-destination ${3}:$dst
+        if [ ${action} != del ] ; then
+           ${IPTABLES} -t nat -A PREROUTING -p $protocol --destination-port $src -j DNAT --to-destination ${3}:$dst
+           verb=added
+       fi
+       if [ -f ${LOGFILE} ] ; then
+           echo "     DNAT $protocol $src to ${3}:$dst ${verb}." >>${LOGFILE}
+       fi
+    done
+fi
+    
+exit 0
+
+
diff --git a/contrib/port-forward/portforward b/contrib/port-forward/portforward
new file mode 100644 (file)
index 0000000..1a97c3a
--- /dev/null
@@ -0,0 +1,28 @@
+# This file is read by /usr/sbin/dnsmasq-portforward and used to set up port 
+# forwarding to hostnames. If the dnsmasq-determined hostname matches the
+# first column of this file, then a DNAT port-forward will be set up 
+# to the address which has just been allocated by DHCP . The second field 
+# is port number(s). If there is only one, then the port-forward goes to 
+# the same port on the DHCP-client, if there are two seperated with a 
+# colon, then the second number is the port to which the connection 
+# is forwarded on the DHCP-client. By default, forwarding is set up 
+# for TCP, but it can done for UDP instead by prefixing the port to "u". 
+# To forward both TCP and UDP, two lines are required. 
+#
+# eg.
+# wwwserver 80
+# will set up a port forward from port 80 on this host to port 80 
+# at the address allocated to wwwserver whenever wwwserver gets a DHCP lease.
+#
+# wwwserver 8080:80
+# will set up a port forward from port 8080 on this host to port 80
+# on the DHCP-client.
+#
+# dnsserver 53
+# dnsserver u53
+# will port forward port 53 UDP and TCP from this host to port 53 on dnsserver.
+#
+# Port forwards will recreated when dnsmasq restarts after a reboot, and
+# removed when DHCP leases expire. After editing this file, send
+# SIGHUP to dnsmasq to install new iptables entries in the kernel.
+
diff --git a/contrib/slackware-dnsmasq/dnsmasq.SlackBuild b/contrib/slackware-dnsmasq/dnsmasq.SlackBuild
new file mode 100755 (executable)
index 0000000..c5ba083
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+CWD=`pwd`
+PKG=/tmp/package-dnsmasq
+
+VERSION=2.24
+ARCH=${ARCH:-i486}
+BUILD=${BUILD:-1}
+
+if [ "$ARCH" = "i386" ]; then
+  SLKCFLAGS="-O2 -march=i386 -mcpu=i686"
+elif [ "$ARCH" = "i486" ]; then
+  SLKCFLAGS="-O2 -march=i486 -mcpu=i686"
+elif [ "$ARCH" = "s390" ]; then
+  SLKCFLAGS="-O2"
+elif [ "$ARCH" = "x86_64" ]; then
+  SLKCFLAGS="-O2"
+fi
+
+rm -rf $PKG
+mkdir -p $PKG
+cd /tmp
+rm -rf dnsmasq-$VERSION
+tar xzvf $CWD/dnsmasq-$VERSION.tar.gz
+cd dnsmasq-$VERSION
+zcat $CWD/dnsmasq.leasedir.diff.gz | patch -p1 --verbose --backup --suffix=.orig || exit
+chown -R root.root .
+make install-i18n PREFIX=/usr DESTDIR=$PKG MANDIR=/usr/man
+chmod 755 $PKG/usr/sbin/dnsmasq
+chown -R root.bin $PKG/usr/sbin
+gzip -9 $PKG/usr/man/man8/dnsmasq.8
+for f in $PKG/usr/share/man/*; do 
+   if [ -f $$f/man8/dnsmasq.8 ]; then 
+        gzip -9 $$f/man8/dnsmasq.8 ; 
+   fi 
+done
+gzip -9 $PKG/usr/man/*/man8/dnsmasq.8
+mkdir -p $PKG/var/state/dnsmasq
+( cd $PKG
+  find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
+  find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
+)
+mkdir $PKG/etc
+cat dnsmasq.conf.example > $PKG/etc/dnsmasq.conf.new
+mkdir $PKG/etc/rc.d
+zcat $CWD/rc.dnsmasq.gz > $PKG/etc/rc.d/rc.dnsmasq.new
+mkdir -p $PKG/usr/doc/dnsmasq-$VERSION
+cp -a \
+  CHANGELOG COPYING FAQ UPGRADING_to_2.0 doc.html setup.html \
+  $PKG/usr/doc/dnsmasq-$VERSION
+mkdir -p $PKG/install
+cat $CWD/slack-desc > $PKG/install/slack-desc
+zcat $CWD/doinst.sh.gz > $PKG/install/doinst.sh
+
+cd $PKG
+makepkg -l y -c n ../dnsmasq-$VERSION-$ARCH-$BUILD.tgz
+
diff --git a/contrib/slackware-dnsmasq/dnsmasq.leasedir.diff.gz b/contrib/slackware-dnsmasq/dnsmasq.leasedir.diff.gz
new file mode 100644 (file)
index 0000000..22fc32b
Binary files /dev/null and b/contrib/slackware-dnsmasq/dnsmasq.leasedir.diff.gz differ
diff --git a/contrib/slackware-dnsmasq/doinst.sh.gz b/contrib/slackware-dnsmasq/doinst.sh.gz
new file mode 100644 (file)
index 0000000..3b44227
Binary files /dev/null and b/contrib/slackware-dnsmasq/doinst.sh.gz differ
diff --git a/contrib/slackware-dnsmasq/rc.dnsmasq.gz b/contrib/slackware-dnsmasq/rc.dnsmasq.gz
new file mode 100644 (file)
index 0000000..a86abbb
Binary files /dev/null and b/contrib/slackware-dnsmasq/rc.dnsmasq.gz differ
diff --git a/contrib/slackware-dnsmasq/slack-desc b/contrib/slackware-dnsmasq/slack-desc
new file mode 100644 (file)
index 0000000..0a0c577
--- /dev/null
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description.  Line
+# up the first '|' above the ':' following the base package name, and the '|' on
+# the right side marks the last column you can put a character in.  You must make
+# exactly 11 lines for the formatting to be correct.  It's also customary to
+# leave one space after the ':'.
+
+       |-----handy-ruler------------------------------------------------------|
+dnsmasq: dnsmasq (small DNS and DHCP server)
+dnsmasq:
+dnsmasq: Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP
+dnsmasq: server.  It is designed to provide DNS (and optionally DHCP) to a
+dnsmasq: small network, and can serve the names of local machines which are not
+dnsmasq: in the global DNS. 
+dnsmasq:
+dnsmasq: Dnsmasq was written by Simon Kelley.
+dnsmasq:
+dnsmasq:
+dnsmasq:
diff --git a/contrib/static-arp/static-arp b/contrib/static-arp/static-arp
new file mode 100644 (file)
index 0000000..82115b7
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Contributed by Darren Hoo <darren.hoo@gmail.com>
+
+# If you use dnsmasq as DHCP server on a router, you may have
+# met with attackers trying ARP Poison Routing (APR) on your
+# local area network. This script will setup a 'permanent' entry
+# in the router's ARP table upon each DHCP transaction so as to
+# make the attacker's efforts less successful.
+
+# Usage:
+# edit /etc/dnsmasq.conf and specify the path of this script
+# to  dhcp-script, for example:
+#  dhcp-script=/usr/sbin/static-arp
+
+# if $1 is add or old, update the static arp table entry.
+# if $1 is del, then delete the entry from the table
+# if $1 is init which is called by dnsmasq at startup, it's ignored
+
+ARP=/usr/sbin/arp
+
+# Arguments.
+# $1 is action (add, del, old)
+# $2 is MAC
+# $3 is address
+# $4 is hostname (optional, may be unset)
+
+if [ ${1} = del ] ; then
+         ${ARP} -d $3
+fi
+
+if [ ${1} = old ] || [ ${1} = add ] ; then
+         ${ARP} -s $3 $2
+fi
+
diff --git a/contrib/try-all-ns/README b/contrib/try-all-ns/README
new file mode 100644 (file)
index 0000000..224d554
--- /dev/null
@@ -0,0 +1,19 @@
+Date: Thu, 07 Dec 2006 00:41:43 -0500
+From: Bob Carroll <bob.carroll@rit.edu>
+Subject: dnsmasq suggestion
+To: simon@thekelleys.org.uk
+
+
+Hello,
+
+I recently needed a feature in dnsmasq for a very bizarre situation. I 
+placed a list of name servers in a special resolve file and told dnsmasq 
+to use that. But I wanted it to try requests in order and treat NXDOMAIN 
+requests as a failed tcp connection. I wrote the feature into dnsmasq 
+and it seems to work. I prepared a patch in the event that others might 
+find it useful as well.
+
+Thanks and keep up the good work.
+
+--Bob
+
diff --git a/contrib/try-all-ns/README-2.47 b/contrib/try-all-ns/README-2.47
new file mode 100644 (file)
index 0000000..3ebec65
--- /dev/null
@@ -0,0 +1,11 @@
+A remake of patch Bob Carroll had posted to dnsmasq,
+now compatible with version 2.47. Hopefully he doesn't 
+mind (sending a copy of this mail to him too).
+
+Maybe the patch in question is not acceptible
+as it doesn't add new switch, rather it binds itself to "strict-order".
+
+What it does is: if you have strict-order in the 
+dnsmasq config file and query a domain that would result 
+in NXDOMAIN, it iterates the whole given nameserver list 
+until the last one says NXDOMAIN.
diff --git a/contrib/try-all-ns/dnsmasq-2.35-try-all-ns.patch b/contrib/try-all-ns/dnsmasq-2.35-try-all-ns.patch
new file mode 100644 (file)
index 0000000..ec3f3e0
--- /dev/null
@@ -0,0 +1,61 @@
+diff -Nau dnsmasq-2.35/src/dnsmasq.h dnsmasq/src/dnsmasq.h
+--- dnsmasq-2.35/src/dnsmasq.h 2006-10-18 16:24:50.000000000 -0400
++++ dnsmasq/src/dnsmasq.h      2006-11-16 22:06:31.000000000 -0500
+@@ -112,6 +112,7 @@
+ #define OPT_NO_PING        2097152
+ #define OPT_LEASE_RO       4194304
+ #define OPT_RELOAD         8388608
++#define OPT_TRY_ALL_NS     16777216
+ struct all_addr {
+   union {
+diff -Nau dnsmasq-2.35/src/forward.c dnsmasq/src/forward.c
+--- dnsmasq-2.35/src/forward.c 2006-10-18 16:24:50.000000000 -0400
++++ dnsmasq/src/forward.c      2006-11-16 22:08:19.000000000 -0500
+@@ -445,6 +445,10 @@
+     {
+        struct server *server = forward->sentto;
+        
++       // If strict-order and try-all-ns are set, treat NXDOMAIN as a failed request
++       if( (daemon->options & OPT_ORDER) && (daemon->options && OPT_TRY_ALL_NS)
++           && header->rcode == NXDOMAIN ) header->rcode = SERVFAIL;
++
+        if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0)
+        /* for broken servers, attempt to send to another one. */
+        {
+diff -Nau dnsmasq-2.35/src/option.c dnsmasq/src/option.c
+--- dnsmasq-2.35/src/option.c  2006-10-18 16:24:50.000000000 -0400
++++ dnsmasq/src/option.c       2006-11-16 22:10:36.000000000 -0500
+@@ -28,7 +28,7 @@
+ /* options which don't have a one-char version */
+ #define LOPT_RELOAD 256
+-
++#define LOPT_TRY_ALL_NS 257
+ #ifdef HAVE_GETOPT_LONG
+ static const struct option opts[] =  
+@@ -102,6 +102,7 @@
+     {"leasefile-ro", 0, 0, '9'},
+     {"dns-forward-max", 1, 0, '0'},
+     {"clear-on-reload", 0, 0, LOPT_RELOAD },
++    {"try-all-ns", 0, 0, LOPT_TRY_ALL_NS },
+     { NULL, 0, 0, 0 }
+   };
+@@ -134,6 +135,7 @@
+   { '5',            OPT_NO_PING },
+   { '9',            OPT_LEASE_RO },
+   { LOPT_RELOAD,    OPT_RELOAD },
++  { LOPT_TRY_ALL_NS,OPT_TRY_ALL_NS },
+   { 'v',            0},
+   { 'w',            0},
+   { 0, 0 }
+@@ -208,6 +210,7 @@
+   { "-9, --leasefile-ro", gettext_noop("Read leases at startup, but never write the lease file."), NULL },
+   { "-0, --dns-forward-max=<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" }, 
+   { "    --clear-on-reload", gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
++  { "    --try-all-ns", gettext_noop("Try all name servers in tandem on NXDOMAIN replies (use with strict-order)."), NULL },
+   { NULL, NULL, NULL }
+ }; 
diff --git a/contrib/try-all-ns/dnsmasq-2.47_no_nxdomain_until_end.patch b/contrib/try-all-ns/dnsmasq-2.47_no_nxdomain_until_end.patch
new file mode 100644 (file)
index 0000000..7586003
--- /dev/null
@@ -0,0 +1,17 @@
+diff -ur dnsmasq-2.47/src/forward.c dnsmasq-2.47-patched/src/forward.c
+--- dnsmasq-2.47/src/forward.c 2009-02-01 17:59:48.000000000 +0200
++++ dnsmasq-2.47-patched/src/forward.c 2009-03-18 19:10:22.000000000 +0200
+@@ -488,9 +488,12 @@
+     return;
+    
+   server = forward->sentto;
++
++  if ( (header->rcode == NXDOMAIN) && ((daemon->options & OPT_ORDER) != 0) && (server->next != NULL) )
++    header->rcode = SERVFAIL;
+   
+   if ((header->rcode == SERVFAIL || header->rcode == REFUSED) &&
+-      !(daemon->options & OPT_ORDER) &&
++      ((daemon->options & OPT_ORDER) != 0) &&
+       forward->forwardall == 0)
+     /* for broken servers, attempt to send to another one. */
+     {
diff --git a/contrib/webmin/README b/contrib/webmin/README
new file mode 100644 (file)
index 0000000..8a8f937
--- /dev/null
@@ -0,0 +1,54 @@
+
+This is the README for the DNSmasq webmin module.
+
+Problems:
+
+1) There's only basic error checking - if you enter some bad
+addresses or names, they will go straight into the config file
+although we do check for things like IP addresses being of
+the correct form (no letters, 4 groups of up to 3 digits
+separated by dots etc). One thing that ISN'T CHECKED FOR is
+that IP dotted quads are all numbers < 256. Another is that
+netmasks are logical (you could enter a netmask of 255.0.255.0 
+for example). Essentially, if it'll pass the config file
+regex scanner (and the above examples will), it won't be 
+flagged as "bad" even if it is a big no-no for dnsmasq itself. 
+
+2) Code is ugly and a kludge - I ain't a programmer! There are probably 
+a lot of things that could be done to tidy up the code - eg, 
+it probably wouldn't hurt to move some common stuff into the lib file.
+
+3) I've used the %text hash and written an english lang file, but
+I am mono-lingual so no other language support as yet.
+
+4) for reasons unknown to me, the icon does not appear properly
+on the servers page of webmin (at least it doesn't for me!)
+
+5) icons have been shamelessly stolen from the ipfilter module,
+specifically the up and down arrows.
+
+6) if you delete an item, the config file will contain
+an otherwise empty, but commented line. This means that if
+you add some new stuff, then delete it, the config file
+will have a number of lines at the end that are just comments.
+Therefore, the config file could possibly grow quite large.
+
+7) NO INCLUDE FILES!
+if you use an include file, it'll be flagged as an error. 
+OK if the include file line is commented out though.
+
+8) deprecated lines not supported (eg user and group) - they
+may produce an error! (user and group don't, but you can't change
+them)
+
+IOW, it works, it's just not very elegant and not very robust.
+
+Hope you find it useful though - I do, as I prevents me having to ever
+wade through the config file and man pages again.
+
+If you modify it, or add a language file, and you have a spare moment,
+please e-mail me - I won't be upset at all if you fix my poor coding!
+(rather the opposite - I'd be pleased someone found it usefull)
+
+Cheers,
+       Neil Fisher <neil@magnecor.com.au>
diff --git a/contrib/webmin/dnsmasq.wbm b/contrib/webmin/dnsmasq.wbm
new file mode 100644 (file)
index 0000000..7307e23
Binary files /dev/null and b/contrib/webmin/dnsmasq.wbm differ
diff --git a/contrib/wrt/Makefile b/contrib/wrt/Makefile
new file mode 100644 (file)
index 0000000..68e8d32
--- /dev/null
@@ -0,0 +1,6 @@
+CFLAGS?= -O2 -Wall -W
+
+all: dhcp_release dhcp_lease_time
+
+clean:
+       rm -f *~ *.o core dhcp_release dhcp_lease_time
diff --git a/contrib/wrt/README b/contrib/wrt/README
new file mode 100644 (file)
index 0000000..862046f
--- /dev/null
@@ -0,0 +1,81 @@
+This script can be used to implement persistent leases on openWRT, DD-WRT
+etc. Persistent leases are good: if the lease database is lost on a
+reboot, then it will eventually be restored as hosts renew their
+leases. Until a host renews (which may take hours/days) it will
+not exist in the DNS if dnsmasq's DDNS function is in use.
+
+*WRT systems remount all non-volatile fileystems read-only after boot,
+so the normal leasefile will not work. They do, however have NV
+storage, accessed with the nvram command:
+
+/usr/lib #  nvram
+usage: nvram [get name] [set name=value] [unset name] [show]
+
+The principle is that leases are kept in NV variable with data
+corresponding to the line in a leasefile:
+
+dnsmasq_lease_192.168.1.56=3600 00:41:4a:05:80:74 192.168.1.56 * *
+
+By giving dnsmasq the leasefile-ro command, it no longer creates or writes a
+leasefile; responsibility for maintaining the lease database transfers
+to the lease change script. At startup, in leasefile-ro mode,
+dnsmasq will run
+
+"<lease_change_script> init" 
+
+and read whatever that command spits out, expecting it to
+be in dnsmasq leasefile format.
+
+So the lease change script, given "init" as argv[1] will 
+suck existing leases out of the NVRAM and emit them from
+stdout in the correct format.
+
+The second part of the problem is keeping the NVRAM up-to-date: this
+is done by the lease-change script which dnsmasq runs when a lease is
+updated. When it is called with argv[1] as "old", "add", or "del"
+it updates the relevant nvram entry.
+
+So, dnsmasq should be run as :
+
+dnsmasq --leasefile-ro --dhcp-script=/path/to/lease_update.sh
+
+or the same flags added to /etc/dnsmasq.conf
+
+
+
+Notes: 
+
+This needs dnsmasq-2.33 or later to work.
+
+This technique will work with, or without, compilation with
+HAVE_BROKEN_RTC. Compiling with HAVE_BROKEN_RTC is
+_highly_recommended_ for this application since is avoids problems
+with the system clock being warped by NTP, and it vastly reduces the
+number of writes to the NVRAM. With HAVE_BROKEN_RTC, NVRAM is updated
+only when a lease is created or destroyed; without it, a write occurs
+every time a lease is renewed.
+
+It probably makes sense to restrict the number of active DHCP leases
+to an appropriate number using dhcp-lease-max. On a new DD_WRT system,
+there are about 10K bytes free in the NVRAM. Each lease record is
+about 100 bytes, so restricting the number of leases to 50 will limit
+use to half that. (The default limit in the distributed source is 150)
+
+Any UI script which reads the dnsmasq leasefile will have to be
+ammended, probably by changing it to read the output of 
+`lease_update init` instead.
+
+Thanks:
+
+To Steve Horbachuk for checks on the script and debugging beyond the 
+call of duty.
+
+
+Simon Kelley
+Fri Jul 28 11:51:13 BST 2006
+
+
+
+
+
diff --git a/contrib/wrt/dhcp_lease_time.c b/contrib/wrt/dhcp_lease_time.c
new file mode 100644 (file)
index 0000000..2866bb5
--- /dev/null
@@ -0,0 +1,214 @@
+/* Copyright (c) 2007 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+/* dhcp_lease_time <address> */
+
+/* Send a DHCPINFORM message to a dnsmasq server running on the local host
+   and print (to stdout) the time remaining in any lease for the given
+   address. The time is given as string printed to stdout.
+
+   If an error occurs or no lease exists for the given address, 
+   nothing is sent to stdout a message is sent to stderr and a
+   non-zero error code is returned.
+
+   Requires dnsmasq 2.40 or later. 
+*/
+
+#include <sys/types.h> 
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <errno.h>
+
+#define DHCP_CHADDR_MAX          16
+#define BOOTREQUEST              1
+#define DHCP_COOKIE              0x63825363
+#define OPTION_PAD               0
+#define OPTION_LEASE_TIME        51
+#define OPTION_OVERLOAD          52
+#define OPTION_MESSAGE_TYPE      53
+#define OPTION_END               255
+#define DHCPINFORM               8
+#define DHCP_SERVER_PORT         67
+
+#define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
+#define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2]))
+
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+struct dhcp_packet {
+  u8 op, htype, hlen, hops;
+  u32 xid;
+  u16 secs, flags;
+  struct in_addr ciaddr, yiaddr, siaddr, giaddr;
+  u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
+  u32 cookie;
+  unsigned char options[308];
+};
+
+static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
+{
+  while (*p != OPTION_END) 
+    {
+      if (p >= end)
+        return NULL; /* malformed packet */
+      else if (*p == OPTION_PAD)
+        p++;
+      else 
+        { 
+          int opt_len;
+          if (p >= end - 2)
+            return NULL; /* malformed packet */
+          opt_len = option_len(p);
+          if (p >= end - (2 + opt_len))
+            return NULL; /* malformed packet */
+          if (*p == opt && opt_len >= minsize)
+            return p;
+          p += opt_len + 2;
+        }
+    }
+  
+  return opt == OPTION_END ? p : NULL;
+}
+static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
+{
+  unsigned char *ret, *overload;
+  
+  /* skip over DHCP cookie; */
+  if ((ret = option_find1(&mess->options[0], ((unsigned char *)mess) + size, opt_type, minsize)))
+    return ret;
+
+  /* look for overload option. */
+  if (!(overload = option_find1(&mess->options[0], ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
+    return NULL;
+  
+  /* Can we look in filename area ? */
+  if ((overload[2] & 1) &&
+      (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
+    return ret;
+
+  /* finally try sname area */
+  if ((overload[2] & 2) &&
+      (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
+    return ret;
+
+  return NULL;
+}
+
+static unsigned int option_uint(unsigned char *opt, int size)
+{
+  /* this worries about unaligned data and byte order */
+  unsigned int ret = 0;
+  int i;
+  unsigned char *p = option_ptr(opt);
+  
+  for (i = 0; i < size; i++)
+    ret = (ret << 8) | *p++;
+
+  return ret;
+}
+
+int main(int argc, char **argv)
+{ 
+  struct in_addr lease;
+  struct dhcp_packet packet;
+  unsigned char *p = packet.options;
+  struct sockaddr_in dest;
+  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  ssize_t rc;
+  
+  if (argc < 2)
+    { 
+      fprintf(stderr, "usage: dhcp_lease_time <address>\n");
+      exit(1);
+    }
+
+  if (fd == -1)
+    {
+      perror("cannot create socket");
+      exit(1);
+    }
+  lease.s_addr = inet_addr(argv[1]);
+   
+  memset(&packet, 0, sizeof(packet));
+  packet.hlen = 0;
+  packet.htype = 0;
+
+  packet.op = BOOTREQUEST;
+  packet.ciaddr = lease;
+  packet.cookie = htonl(DHCP_COOKIE);
+
+  *(p++) = OPTION_MESSAGE_TYPE;
+  *(p++) = 1;
+  *(p++) = DHCPINFORM;
+
+  *(p++) = OPTION_END;
+  dest.sin_family = AF_INET; 
+  dest.sin_addr.s_addr = inet_addr("127.0.0.1");
+  dest.sin_port = ntohs(DHCP_SERVER_PORT);
+  
+  if (sendto(fd, &packet, sizeof(packet), 0, 
+            (struct sockaddr *)&dest, sizeof(dest)) == -1)
+    {
+      perror("sendto failed");
+      exit(1);
+    }
+
+  alarm(3); /* noddy timeout. */
+
+  rc = recv(fd, &packet, sizeof(packet), 0);
+  
+  if (rc < (ssize_t)(sizeof(packet) - sizeof(packet.options)))
+    {
+      perror("recv failed");
+      exit(1);
+    }
+
+  if ((p = option_find(&packet, (size_t)rc, OPTION_LEASE_TIME, 4)))
+    {
+      unsigned int t = option_uint(p, 4);
+      if (t == 0xffffffff)
+       printf("infinite");
+      else
+       {
+         unsigned int x;
+         if ((x = t/86400))
+           printf("%dd", x);
+         if ((x = (t/3600)%24))
+           printf("%dh", x);
+         if ((x = (t/60)%60))
+           printf("%dm", x);
+         if ((x = t%60))
+           printf("%ds", x);
+       }
+      return 0;
+    }
+
+  return 1; /* no lease */
+}
diff --git a/contrib/wrt/dhcp_release.c b/contrib/wrt/dhcp_release.c
new file mode 100644 (file)
index 0000000..c66d3a0
--- /dev/null
@@ -0,0 +1,331 @@
+/* Copyright (c) 2006 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+/* dhcp_release <interface> <address> <MAC address> <client_id>
+   MUST be run as root - will fail otherwise. */
+
+/* Send a DHCPRELEASE message via the specified interface 
+   to tell the local DHCP server to delete a particular lease. 
+   
+   The interface argument is the interface in which a DHCP
+   request _would_ be received if it was coming from the client, 
+   rather than being faked up here.
+   
+   The address argument is a dotted-quad IP addresses and mandatory. 
+   
+   The MAC address is colon separated hex, and is mandatory. It may be 
+   prefixed by an address-type byte followed by -, eg
+
+   10-11:22:33:44:55:66
+
+   but if the address-type byte is missing it is assumed to be 1, the type 
+   for ethernet. This encoding is the one used in dnsmasq lease files.
+
+   The client-id is optional. If it is "*" then it treated as being missing.
+*/
+
+#include <sys/types.h> 
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <errno.h>
+
+#define DHCP_CHADDR_MAX          16
+#define BOOTREQUEST              1
+#define DHCP_COOKIE              0x63825363
+#define OPTION_SERVER_IDENTIFIER 54
+#define OPTION_CLIENT_ID         61
+#define OPTION_MESSAGE_TYPE      53
+#define OPTION_END               255
+#define DHCPRELEASE              7
+#define DHCP_SERVER_PORT         67
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+struct dhcp_packet {
+  u8 op, htype, hlen, hops;
+  u32 xid;
+  u16 secs, flags;
+  struct in_addr ciaddr, yiaddr, siaddr, giaddr;
+  u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
+  u32 cookie;
+  unsigned char options[308];
+};
+
+static struct iovec iov;
+
+static int expand_buf(struct iovec *iov, size_t size)
+{
+  void *new;
+
+  if (size <= iov->iov_len)
+    return 1;
+
+  if (!(new = malloc(size)))
+    {
+      errno = ENOMEM;
+      return 0;
+    }
+
+  if (iov->iov_base)
+    {
+      memcpy(new, iov->iov_base, iov->iov_len);
+      free(iov->iov_base);
+    }
+
+  iov->iov_base = new;
+  iov->iov_len = size;
+
+  return 1;
+}
+
+static ssize_t netlink_recv(int fd)
+{
+  struct msghdr msg;
+  ssize_t rc;
+
+  msg.msg_control = NULL;
+  msg.msg_controllen = 0;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+    
+  while (1)
+    {
+      msg.msg_flags = 0;
+      while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
+      
+      /* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a 
+         big buffer and pray in that case. */
+      if (rc == -1 && errno == EOPNOTSUPP)
+        {
+          if (!expand_buf(&iov, 2000))
+            return -1;
+          break;
+        }
+      
+      if (rc == -1 || !(msg.msg_flags & MSG_TRUNC))
+        break;
+            
+      if (!expand_buf(&iov, iov.iov_len + 100))
+        return -1;
+    }
+
+  /* finally, read it for real */
+  while ((rc = recvmsg(fd, &msg, 0)) == -1 && errno == EINTR);
+  
+  return rc;
+}
+
+static int parse_hex(char *in, unsigned char *out, int maxlen, int *mac_type)
+{
+  int i = 0;
+  char *r;
+    
+  if (mac_type)
+    *mac_type = 0;
+  
+  while (maxlen == -1 || i < maxlen)
+    {
+      for (r = in; *r != 0 && *r != ':' && *r != '-'; r++);
+      if (*r == 0)
+        maxlen = i;
+      
+      if (r != in )
+        {
+          if (*r == '-' && i == 0 && mac_type)
+           {
+              *r = 0;
+              *mac_type = strtol(in, NULL, 16);
+              mac_type = NULL;
+           }
+          else
+            {
+              *r = 0;
+             out[i] = strtol(in, NULL, 16);
+              i++;
+            }
+        }
+      in = r+1;
+    }
+    return i;
+}
+
+static int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
+{
+  return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
+}
+
+static struct in_addr find_interface(struct in_addr client, int fd, int index)
+{
+  struct sockaddr_nl addr;
+  struct nlmsghdr *h;
+  ssize_t len;
+  struct {
+    struct nlmsghdr nlh;
+    struct rtgenmsg g; 
+  } req;
+
+  addr.nl_family = AF_NETLINK;
+  addr.nl_pad = 0;
+  addr.nl_groups = 0;
+  addr.nl_pid = 0; /* address to kernel */
+
+  req.nlh.nlmsg_len = sizeof(req);
+  req.nlh.nlmsg_type = RTM_GETADDR;
+  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK; 
+  req.nlh.nlmsg_pid = 0;
+  req.nlh.nlmsg_seq = 1;
+  req.g.rtgen_family = AF_INET; 
+
+  if (sendto(fd, (void *)&req, sizeof(req), 0, 
+            (struct sockaddr *)&addr, sizeof(addr)) == -1)
+    {
+      perror("sendto failed");
+      exit(1);
+    }
+  
+  while (1)
+    {
+      if ((len = netlink_recv(fd)) == -1)
+       {
+         perror("netlink");
+         exit(1);
+       }
+
+      for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
+       if (h->nlmsg_type == NLMSG_DONE)
+         exit(0);
+       else if (h->nlmsg_type == RTM_NEWADDR)
+          {
+            struct ifaddrmsg *ifa = NLMSG_DATA(h);  
+            struct rtattr *rta;
+            unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
+            
+            if (ifa->ifa_index == index && ifa->ifa_family == AF_INET)
+              {
+                struct in_addr netmask, addr;
+                
+                netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
+                addr.s_addr = 0;
+                
+                for (rta = IFA_RTA(ifa); RTA_OK(rta, len1); rta = RTA_NEXT(rta, len1))
+                 if (rta->rta_type == IFA_LOCAL)
+                   addr = *((struct in_addr *)(rta+1));
+               
+                if (addr.s_addr && is_same_net(addr, client, netmask))
+                 return addr;
+             }
+         }
+    }
+  exit(0);
+}
+
+int main(int argc, char **argv)
+{ 
+  struct in_addr server, lease;
+  int mac_type;
+  struct dhcp_packet packet;
+  unsigned char *p = packet.options;
+  struct sockaddr_in dest;
+  struct ifreq ifr;
+  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+  struct iovec iov;
+  iov.iov_len = 200;
+  iov.iov_base = malloc(iov.iov_len);
+
+  if (argc < 4 || argc > 5)
+    { 
+      fprintf(stderr, "usage: dhcp_release <interface> <addr> <mac> [<client_id>]\n");
+      exit(1);
+    }
+
+  if (fd == -1 || nl == -1)
+    {
+      perror("cannot create socket");
+      exit(1);
+    }
+  
+  /* This voodoo fakes up a packet coming from the correct interface, which really matters for 
+     a DHCP server */
+  strcpy(ifr.ifr_name, argv[1]);
+  if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
+    {
+      perror("cannot setup interface");
+      exit(1);
+    }
+  
+  
+  lease.s_addr = inet_addr(argv[2]);
+  server = find_interface(lease, nl, if_nametoindex(argv[1]));
+  
+  memset(&packet, 0, sizeof(packet));
+  packet.hlen = parse_hex(argv[3], packet.chaddr, DHCP_CHADDR_MAX, &mac_type);
+  if (mac_type == 0)
+    packet.htype = ARPHRD_ETHER;
+  else
+    packet.htype = mac_type;
+
+  packet.op = BOOTREQUEST;
+  packet.ciaddr = lease;
+  packet.cookie = htonl(DHCP_COOKIE);
+
+  *(p++) = OPTION_MESSAGE_TYPE;
+  *(p++) = 1;
+  *(p++) = DHCPRELEASE;
+
+  *(p++) = OPTION_SERVER_IDENTIFIER;
+  *(p++) = sizeof(server);
+  memcpy(p, &server, sizeof(server));
+  p += sizeof(server);
+
+  if (argc == 5 && strcmp(argv[4], "*") != 0)
+    {
+      unsigned int clid_len = parse_hex(argv[4], p+2, 255, NULL);
+      *(p++) = OPTION_CLIENT_ID;
+      *(p++) = clid_len;
+      p += clid_len;
+    }
+  
+  *(p++) = OPTION_END;
+  dest.sin_family = AF_INET;
+  dest.sin_port = ntohs(DHCP_SERVER_PORT);
+  dest.sin_addr = server;
+
+  if (sendto(fd, &packet, sizeof(packet), 0, 
+            (struct sockaddr *)&dest, sizeof(dest)) == -1)
+    {
+      perror("sendto failed");
+      exit(1);
+    }
+
+  return 0;
+}
diff --git a/contrib/wrt/lease_update.sh b/contrib/wrt/lease_update.sh
new file mode 100755 (executable)
index 0000000..46509b3
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# Copyright (c) 2006 Simon Kelley
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 dated June, 1991.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+
+
+# if $1 is add del or old, this is a dnsmasq-called lease-change
+# script, update the nvram database. if $1 is init, emit a 
+# dnsmasq-format lease file to stdout representing the current state of the 
+# database, this is called by dnsmasq at startup.
+
+NVRAM=/usr/sbin/nvram
+PREFIX=dnsmasq_lease_
+
+# Arguments.
+# $1 is action (add, del, old)
+# $2 is MAC 
+# $3 is address
+# $4 is hostname (optional, may be unset)
+
+# env.
+# DNSMASQ_LEASE_LENGTH or DNSMASQ_LEASE_EXPIRES (which depends on HAVE_BROKEN_RTC)
+# DNSMASQ_CLIENT_ID (optional, may be unset)
+
+# File.
+# length|expires MAC addr hostname|* CLID|* 
+
+# Primary key is address.
+
+if [ ${1} = init ] ; then
+     ${NVRAM} show | sed -n -e "/^${PREFIX}.*/ s/^.*=//p"
+else
+     if [ ${1} = del ] ; then
+          ${NVRAM} unset ${PREFIX}${3}
+     fi
+
+     if [ ${1} = old ] || [ ${1} = add ] ; then
+          ${NVRAM} set ${PREFIX}${3}="${DNSMASQ_LEASE_LENGTH:-}${DNSMASQ_LEASE_EXPIRES:-} ${2} ${3} ${4:-*} ${DNSMASQ_CLIENT_ID:-*}"
+     fi
+     ${NVRAM} commit
+fi
+
+
+
+
diff --git a/dbus/DBus-interface b/dbus/DBus-interface
new file mode 100644 (file)
index 0000000..8d578ca
--- /dev/null
@@ -0,0 +1,131 @@
+DBus support must be enabled at compile-time and run-time. Ensure 
+that src/config.h contains the line
+
+#define HAVE_DBUS.
+
+and that /etc/dnsmasq.conf contains the line
+
+enable-dbus
+
+Because dnsmasq can operate stand-alone from the DBus, and may need to provide
+service before the dbus daemon is available, it will continue to run
+if the DBus connection is not available at startup. The DBus will be polled 
+every 250ms until a connection is established. Start of polling and final
+connection establishment are both logged. When dnsmasq establishes a
+connection to the dbus, it sends the signal "Up". Anything controlling
+the server settings in dnsmasq should re-invoke the SetServers method
+(q.v.) when it sees this signal. This allows dnsmasq to be restarted
+and avoids startup races with the provider of nameserver information.
+
+
+Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq
+and a single object: /uk/org/thekelleys/dnsmasq
+
+1. METHODS
+----------
+
+Methods are of the form
+
+uk.org.thekelleys.<method>
+
+Available methods are:
+
+GetVersion
+----------
+Returns a string containing the version of dnsmasq running.
+
+ClearCache
+----------
+Returns nothing. Clears the domain name cache and re-reads
+/etc/hosts. The same as sending dnsmasq a HUP signal.
+
+SetServers
+----------
+Returns nothing. Takes a set of arguments representing the new
+upstream DNS servers to be used by dnsmasq. IPv4 addresses are
+represented as a UINT32 (in network byte order) and IPv6 addresses
+are represented as sixteen BYTEs (since there is no UINT128 type).
+Each server address may be followed by one or more STRINGS, which are
+the domains for which the preceding server should be used.
+
+Examples.
+
+UINT32: <address1>
+UNIT32: <address2>
+
+is equivalent to
+
+--server=<address1> --server=<address2>
+
+
+UINT32 <address1>
+UINT32 <address2>
+STRING "somedomain.com"
+
+is equivalent to
+
+--server=<address1> --server=/somedomain.com/<address2> 
+
+UINT32 <address1>
+UINT32 <address2>
+STRING "somedomain.com"
+UINT32 <address3>
+STRING "anotherdomain.com"
+STRING "thirddomain.com"
+
+is equivalent to
+
+--server=<address1> 
+--server=/somedomain.com/<address2> 
+--server=/anotherdomain.com/thirddomain.com/<address3>
+
+Am IPv4 address of 0.0.0.0 is interpreted as "no address, local only",
+so
+
+UINT32: <0.0.0.0>
+STRING  "local.domain"
+
+is equivalent to
+
+--local=/local.domain/
+
+
+Each call to SetServers completely replaces the set of servers
+specified by via the DBus, but it leaves any servers specified via the
+command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
+
+2. SIGNALS
+----------
+
+If dnsmasq's DHCP server is active, it will send signals over DBUS whenever
+the DHCP lease database changes. Think of these signals as transactions on
+a database with the IP address acting as the primary key.
+
+Signals are of the form:
+
+uk.org.thekelleys.<signal>
+
+and their parameters are:
+
+STRING "192.168.1.115"
+STRING "01:23:45:67:89:ab"
+STRING "hostname.or.fqdn"
+
+
+Available signals are:
+
+DhcpLeaseAdded
+---------------
+
+This signal is emitted when a DHCP lease for a given IP address is created.
+
+DhcpLeaseDeleted
+----------------
+
+This signal is emitted when a DHCP lease for a given IP address is deleted.
+
+DhcpLeaseUpdated
+----------------
+
+This signal is emitted when a DHCP lease for a given IP address is updated.
diff --git a/dbus/dnsmasq.conf b/dbus/dnsmasq.conf
new file mode 100644 (file)
index 0000000..82b1c76
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+       <policy user="root">
+               <allow own="uk.org.thekelleys.dnsmasq"/>
+               <allow send_destination="uk.org.thekelleys.dnsmasq"/>
+       </policy>
+       <policy context="default">
+                <deny own="uk.org.thekelleys.dnsmasq"/>
+                <deny send_destination="uk.org.thekelleys.dnsmasq"/>
+        </policy>
+</busconfig>
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..2cbf56b
--- /dev/null
@@ -0,0 +1,23 @@
+dnsmasq (2.57-slp2+3) unstable; urgency=low
+
+  * Enable dbus feature
+  * Git: 165.213.180.234:/slp/pkgs/d/dnsmasq
+  * Tag: dnsmasq_2.57-slp2+3
+
+ -- Byeongho Shim <bh.shim@samsung.com>  Mon, 07 Nov 2011 21:26:30 +0900
+
+dnsmasq (2.57-slp2+2) unstable; urgency=low
+
+  * Change the section on control file
+  * Git: 165.213.180.234:/slp/pkgs/d/dnsmasq
+  * Tag: dnsmasq_2.57-slp2+2
+
+ -- Byeongho Shim <bh.shim@samsung.com>  Tue, 30 Aug 2011 09:59:52 +0900
+
+dnsmasq (2.57-slp2+1) unstable; urgency=low
+
+  * Initial Release.
+  * Git: 165.213.180.234:/slp/pkgs/d/dnsmasq
+  * Tag: dnsmasq_2.57-slp2+1
+
+ -- Byeongho Shim <bh.shim@samsung.com>  Tue, 16 Aug 2011 16:43:13 +0900
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7f8f011
--- /dev/null
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..edba10b
--- /dev/null
@@ -0,0 +1,20 @@
+Source: dnsmasq
+Section: base
+Priority: extra
+Maintainer: Seungyoun Ju <sy39.ju@samsung.com>, Hocheol Seo <hocheol.seo@samsung.com>
+Build-Depends: debhelper (>= 5), libdbus-1-dev
+Standards-Version: 3.7.2
+
+Package: dnsmasq
+Section: base
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Dnsmasq is a lightweight, easy to configure DNS forwarder
+ and DHCP server.
+
+Package: dnsmasq-dbg
+Section: debug
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, dnsmasq (= ${Source-Version})
+Description: Dnsmasq is a lightweight, easy to configure DNS forwarder
+ and DHCP server.
diff --git a/debian/dnsmasq.install.in b/debian/dnsmasq.install.in
new file mode 100644 (file)
index 0000000..7346c45
--- /dev/null
@@ -0,0 +1 @@
+@PREFIX@/bin/*
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..be777c3
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+CFLAGS ?= -Wall -g
+CXXFLAGS ?=  -Wall -g
+LDFLAGS ?=
+PREFIX ?= /usr
+DATADIR ?= /opt
+
+CFLAGS += -fPIE
+CXXFLAGS += -fPIE
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+       CXXFLAGS += -O0
+else
+       CFLAGS += -O2
+       CXXFLAGS += -O2
+endif
+
+LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--hash-style=both -Wl,--as-needed -pie
+
+CMAKE_BUILD_DIR ?= $(CURDIR)/cmake_build_tmp
+
+configure: configure-stamp
+configure-stamp:
+       dh_testdir
+       mkdir -p $(CMAKE_BUILD_DIR) && cd $(CMAKE_BUILD_DIR) && \
+       CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake .. -DCMAKE_INSTALL_PREFIX=$(PREFIX)
+
+       touch configure-stamp
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+       dh_testdir
+
+       cd $(CMAKE_BUILD_DIR) && $(MAKE)
+
+       #docbook-to-man debian/wavplayer.sgml > wavplayer.1
+
+       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+               cat $$f > $${f%.in}; \
+               sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
+               sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
+       done
+
+
+       touch $@
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp configure-stamp
+
+       rm -rf $(CMAKE_BUILD_DIR)
+
+       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+               rm -f $${f%.in}; \
+       done
+
+       dh_clean
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k 
+       dh_installdirs
+
+       # Add here commands to install the package into debian/wavplayer.
+       cd $(CMAKE_BUILD_DIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+#      dh_installchangelogs 
+#      dh_installdocs
+#      dh_installexamples
+       dh_install --sourcedir=debian/tmp
+#      dh_installmenu
+#      dh_installdebconf       
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+#      dh_python
+#      dh_installinit
+#      dh_installcron
+#      dh_installinfo
+#      dh_installman
+       dh_link
+       dh_strip --dbg-package=dnsmasq-dbg
+       dh_compress
+       dh_fixperms
+#      dh_perl
+       dh_makeshlibs
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..89ae9db
--- /dev/null
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example
new file mode 100644 (file)
index 0000000..719dcff
--- /dev/null
@@ -0,0 +1,553 @@
+# Configuration file for dnsmasq.
+#
+# Format is one option per line, legal options are the same
+# as the long options legal on the command line. See
+# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details.
+
+# The following two options make you a better netizen, since they
+# tell dnsmasq to filter out queries which the public DNS cannot
+# answer, and which load the servers (especially the root servers)
+# unnecessarily. If you have a dial-on-demand link they also stop
+# these requests from bringing up the link unnecessarily.
+
+# Never forward plain names (without a dot or domain part)
+#domain-needed
+# Never forward addresses in the non-routed address spaces.
+#bogus-priv
+
+
+# Uncomment this to filter useless windows-originated DNS requests
+# which can trigger dial-on-demand links needlessly.
+# Note that (amongst other things) this blocks all SRV requests,
+# so don't use it if you use eg Kerberos, SIP, XMMP or Google-talk.
+# This option only affects forwarding, SRV records originating for
+# dnsmasq (via srv-host= lines) are not suppressed by it.
+#filterwin2k
+
+# Change this line if you want dns to get its upstream servers from
+# somewhere other that /etc/resolv.conf
+#resolv-file=
+
+# By  default,  dnsmasq  will  send queries to any of the upstream
+# servers it knows about and tries to favour servers to are  known
+# to  be  up.  Uncommenting this forces dnsmasq to try each query
+# with  each  server  strictly  in  the  order  they   appear   in
+# /etc/resolv.conf
+#strict-order
+
+# If you don't want dnsmasq to read /etc/resolv.conf or any other
+# file, getting its servers from this file instead (see below), then
+# uncomment this.
+#no-resolv
+
+# If you don't want dnsmasq to poll /etc/resolv.conf or other resolv
+# files for changes and re-read them then uncomment this.
+#no-poll
+
+# Add other name servers here, with domain specs if they are for
+# non-public domains.
+#server=/localnet/192.168.0.1
+
+# Example of routing PTR queries to nameservers: this will send all
+# address->name queries for 192.168.3/24 to nameserver 10.1.2.3
+#server=/3.168.192.in-addr.arpa/10.1.2.3
+
+# Add local-only domains here, queries in these domains are answered
+# from /etc/hosts or DHCP only.
+#local=/localnet/
+
+# Add domains which you want to force to an IP address here.
+# The example below send any host in double-click.net to a local
+# web-server.
+#address=/double-click.net/127.0.0.1
+
+# --address (and --server) work with IPv6 addresses too.
+#address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83
+
+# You can control how dnsmasq talks to a server: this forces
+# queries to 10.1.2.3 to be routed via eth1
+# server=10.1.2.3@eth1
+
+# and this sets the source (ie local) address used to talk to
+# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
+# IP on the machine, obviously).
+# server=10.1.2.3@192.168.1.1#55
+
+# If you want dnsmasq to change uid and gid to something other
+# than the default, edit the following lines.
+#user=
+#group=
+
+# If you want dnsmasq to listen for DHCP and DNS requests only on
+# specified interfaces (and the loopback) give the name of the
+# interface (eg eth0) here.
+# Repeat the line for more than one interface.
+#interface=
+# Or you can specify which interface _not_ to listen on
+#except-interface=
+# Or which to listen on by address (remember to include 127.0.0.1 if
+# you use this.)
+#listen-address=
+# If you want dnsmasq to provide only DNS service on an interface,
+# configure it as shown above, and then use the following line to
+# disable DHCP and TFTP on it.
+#no-dhcp-interface=
+
+# On systems which support it, dnsmasq binds the wildcard address,
+# even when it is listening on only some interfaces. It then discards
+# requests that it shouldn't reply to. This has the advantage of
+# working even when interfaces come and go and change address. If you
+# want dnsmasq to really bind only the interfaces it is listening on,
+# uncomment this option. About the only time you may need this is when
+# running another nameserver on the same machine.
+#bind-interfaces
+
+# If you don't want dnsmasq to read /etc/hosts, uncomment the
+# following line.
+#no-hosts
+# or if you want it to read another file, as well as /etc/hosts, use
+# this.
+#addn-hosts=/etc/banner_add_hosts
+
+# Set this (and domain: see below) if you want to have a domain
+# automatically added to simple names in a hosts-file.
+#expand-hosts
+
+# Set the domain for dnsmasq. this is optional, but if it is set, it
+# does the following things.
+# 1) Allows DHCP hosts to have fully qualified domain names, as long
+#     as the domain part matches this setting.
+# 2) Sets the "domain" DHCP option thereby potentially setting the
+#    domain of all systems configured by DHCP
+# 3) Provides the domain part for "expand-hosts"
+#domain=thekelleys.org.uk
+
+# Set a different domain for a particular subnet
+#domain=wireless.thekelleys.org.uk,192.168.2.0/24
+
+# Same idea, but range rather then subnet
+#domain=reserved.thekelleys.org.uk,192.68.3.100,192.168.3.200
+
+# Uncomment this to enable the integrated DHCP server, you need
+# to supply the range of addresses available for lease and optionally
+# a lease time. If you have more than one network, you will need to
+# repeat this for each network on which you want to supply DHCP
+# service.
+#dhcp-range=192.168.0.50,192.168.0.150,12h
+
+# This is an example of a DHCP range where the netmask is given. This
+# is needed for networks we reach the dnsmasq DHCP server via a relay
+# agent. If you don't know what a DHCP relay agent is, you probably
+# don't need to worry about this.
+#dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h
+
+# This is an example of a DHCP range which sets a tag, so that
+# some DHCP options may be set only for this network.
+#dhcp-range=set:red,192.168.0.50,192.168.0.150
+
+# Use this DHCP range only when the tag "green" is set.
+#dhcp-range=tag:green,192.168.0.50,192.168.0.150,12h
+
+# Specify a subnet which can't be used for dynamic address allocation,
+# is available for hosts with matching --dhcp-host lines. Note that
+# dhcp-host declarations will be ignored unless there is a dhcp-range
+# of some type for the subnet in question.
+# In this case the netmask is implied (it comes from the network
+# configuration on the machine running dnsmasq) it is possible to give
+# an explicit netmask instead.
+#dhcp-range=192.168.0.0,static
+
+# Supply parameters for specified hosts using DHCP. There are lots
+# of valid alternatives, so we will give examples of each. Note that
+# IP addresses DO NOT have to be in the range given above, they just
+# need to be on the same network. The order of the parameters in these
+# do not matter, it's permissible to give name, address and MAC in any
+# order.
+
+# Always allocate the host with Ethernet address 11:22:33:44:55:66
+# The IP address 192.168.0.60
+#dhcp-host=11:22:33:44:55:66,192.168.0.60
+
+# Always set the name of the host with hardware address
+# 11:22:33:44:55:66 to be "fred"
+#dhcp-host=11:22:33:44:55:66,fred
+
+# Always give the host with Ethernet address 11:22:33:44:55:66
+# the name fred and IP address 192.168.0.60 and lease time 45 minutes
+#dhcp-host=11:22:33:44:55:66,fred,192.168.0.60,45m
+
+# Give a host with Ethernet address 11:22:33:44:55:66 or
+# 12:34:56:78:90:12 the IP address 192.168.0.60. Dnsmasq will assume
+# that these two Ethernet interfaces will never be in use at the same
+# time, and give the IP address to the second, even if it is already
+# in use by the first. Useful for laptops with wired and wireless
+# addresses.
+#dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.60
+
+# Give the machine which says its name is "bert" IP address
+# 192.168.0.70 and an infinite lease
+#dhcp-host=bert,192.168.0.70,infinite
+
+# Always give the host with client identifier 01:02:02:04
+# the IP address 192.168.0.60
+#dhcp-host=id:01:02:02:04,192.168.0.60
+
+# Always give the host with client identifier "marjorie"
+# the IP address 192.168.0.60
+#dhcp-host=id:marjorie,192.168.0.60
+
+# Enable the address given for "judge" in /etc/hosts
+# to be given to a machine presenting the name "judge" when
+# it asks for a DHCP lease.
+#dhcp-host=judge
+
+# Never offer DHCP service to a machine whose Ethernet
+# address is 11:22:33:44:55:66
+#dhcp-host=11:22:33:44:55:66,ignore
+
+# Ignore any client-id presented by the machine with Ethernet
+# address 11:22:33:44:55:66. This is useful to prevent a machine
+# being treated differently when running under different OS's or
+# between PXE boot and OS boot.
+#dhcp-host=11:22:33:44:55:66,id:*
+
+# Send extra options which are tagged as "red" to
+# the machine with Ethernet address 11:22:33:44:55:66
+#dhcp-host=11:22:33:44:55:66,set:red
+
+# Send extra options which are tagged as "red" to
+# any machine with Ethernet address starting 11:22:33:
+#dhcp-host=11:22:33:*:*:*,set:red
+
+# Ignore any clients which are specified in dhcp-host lines
+# or /etc/ethers. Equivalent to ISC "deny unknown-clients".
+# This relies on the special "known" tag which is set when
+# a host is matched.
+#dhcp-ignore=tag:!known
+
+# Send extra options which are tagged as "red" to any machine whose
+# DHCP vendorclass string includes the substring "Linux"
+#dhcp-vendorclass=set:red,Linux
+
+# Send extra options which are tagged as "red" to any machine one
+# of whose DHCP userclass strings includes the substring "accounts"
+#dhcp-userclass=set:red,accounts
+
+# Send extra options which are tagged as "red" to any machine whose
+# MAC address matches the pattern.
+#dhcp-mac=set:red,00:60:8C:*:*:*
+
+# If this line is uncommented, dnsmasq will read /etc/ethers and act
+# on the ethernet-address/IP pairs found there just as if they had
+# been given as --dhcp-host options. Useful if you keep
+# MAC-address/host mappings there for other purposes.
+#read-ethers
+
+# Send options to hosts which ask for a DHCP lease.
+# See RFC 2132 for details of available options.
+# Common options can be given to dnsmasq by name:
+# run "dnsmasq --help dhcp" to get a list.
+# Note that all the common settings, such as netmask and
+# broadcast address, DNS server and default route, are given
+# sane defaults by dnsmasq. You very likely will not need
+# any dhcp-options. If you use Windows clients and Samba, there
+# are some options which are recommended, they are detailed at the
+# end of this section.
+
+# Override the default route supplied by dnsmasq, which assumes the
+# router is the same machine as the one running dnsmasq.
+#dhcp-option=3,1.2.3.4
+
+# Do the same thing, but using the option name
+#dhcp-option=option:router,1.2.3.4
+
+# Override the default route supplied by dnsmasq and send no default
+# route at all. Note that this only works for the options sent by
+# default (1, 3, 6, 12, 28) the same line will send a zero-length option
+# for all other option numbers.
+#dhcp-option=3
+
+# Set the NTP time server addresses to 192.168.0.4 and 10.10.0.5
+#dhcp-option=option:ntp-server,192.168.0.4,10.10.0.5
+
+# Set the NTP time server address to be the same machine as
+# is running dnsmasq
+#dhcp-option=42,0.0.0.0
+
+# Set the NIS domain name to "welly"
+#dhcp-option=40,welly
+
+# Set the default time-to-live to 50
+#dhcp-option=23,50
+
+# Set the "all subnets are local" flag
+#dhcp-option=27,1
+
+# Send the etherboot magic flag and then etherboot options (a string).
+#dhcp-option=128,e4:45:74:68:00:00
+#dhcp-option=129,NIC=eepro100
+
+# Specify an option which will only be sent to the "red" network
+# (see dhcp-range for the declaration of the "red" network)
+# Note that the tag: part must precede the option: part.
+#dhcp-option = tag:red, option:ntp-server, 192.168.1.1
+
+# The following DHCP options set up dnsmasq in the same way as is specified
+# for the ISC dhcpcd in
+# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
+# adapted for a typical dnsmasq installation where the host running
+# dnsmasq is also the host running samba.
+# you may want to uncomment some or all of them if you use
+# Windows clients and Samba.
+#dhcp-option=19,0           # option ip-forwarding off
+#dhcp-option=44,0.0.0.0     # set netbios-over-TCP/IP nameserver(s) aka WINS server(s)
+#dhcp-option=45,0.0.0.0     # netbios datagram distribution server
+#dhcp-option=46,8           # netbios node type
+
+# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
+# probably doesn't support this......
+#dhcp-option=option:domain-search,eng.apple.com,marketing.apple.com
+
+# Send RFC-3442 classless static routes (note the netmask encoding)
+#dhcp-option=121,192.168.1.0/24,1.2.3.4,10.0.0.0/8,5.6.7.8
+
+# Send vendor-class specific options encapsulated in DHCP option 43.
+# The meaning of the options is defined by the vendor-class so
+# options are sent only when the client supplied vendor class
+# matches the class given here. (A substring match is OK, so "MSFT"
+# matches "MSFT" and "MSFT 5.0"). This example sets the
+# mtftp address to 0.0.0.0 for PXEClients.
+#dhcp-option=vendor:PXEClient,1,0.0.0.0
+
+# Send microsoft-specific option to tell windows to release the DHCP lease
+# when it shuts down. Note the "i" flag, to tell dnsmasq to send the
+# value as a four-byte integer - that's what microsoft wants. See
+# http://technet2.microsoft.com/WindowsServer/en/library/a70f1bb7-d2d4-49f0-96d6-4b7414ecfaae1033.mspx?mfr=true
+#dhcp-option=vendor:MSFT,2,1i
+
+# Send the Encapsulated-vendor-class ID needed by some configurations of
+# Etherboot to allow is to recognise the DHCP server.
+#dhcp-option=vendor:Etherboot,60,"Etherboot"
+
+# Send options to PXELinux. Note that we need to send the options even
+# though they don't appear in the parameter request list, so we need
+# to use dhcp-option-force here.
+# See http://syslinux.zytor.com/pxe.php#special for details.
+# Magic number - needed before anything else is recognised
+#dhcp-option-force=208,f1:00:74:7e
+# Configuration file name
+#dhcp-option-force=209,configs/common
+# Path prefix
+#dhcp-option-force=210,/tftpboot/pxelinux/files/
+# Reboot time. (Note 'i' to send 32-bit value)
+#dhcp-option-force=211,30i
+
+# Set the boot filename for netboot/PXE. You will only need
+# this is you want to boot machines over the network and you will need
+# a TFTP server; either dnsmasq's built in TFTP server or an
+# external one. (See below for how to enable the TFTP server.)
+#dhcp-boot=pxelinux.0
+
+# Boot for Etherboot gPXE. The idea is to send two different
+# filenames, the first loads gPXE, and the second tells gPXE what to
+# load. The dhcp-match sets the gpxe tag for requests from gPXE.
+#dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
+#dhcp-boot=tag:!gpxe,undionly.kpxe
+#dhcp-boot=mybootimage
+
+# Encapsulated options for Etherboot gPXE. All the options are
+# encapsulated within option 175
+#dhcp-option=encap:175, 1, 5b         # priority code
+#dhcp-option=encap:175, 176, 1b       # no-proxydhcp
+#dhcp-option=encap:175, 177, string   # bus-id
+#dhcp-option=encap:175, 189, 1b       # BIOS drive code
+#dhcp-option=encap:175, 190, user     # iSCSI username
+#dhcp-option=encap:175, 191, pass     # iSCSI password
+
+# Test for the architecture of a netboot client. PXE clients are
+# supposed to send their architecture as option 93. (See RFC 4578)
+#dhcp-match=peecees, option:client-arch, 0 #x86-32
+#dhcp-match=itanics, option:client-arch, 2 #IA64
+#dhcp-match=hammers, option:client-arch, 6 #x86-64
+#dhcp-match=mactels, option:client-arch, 7 #EFI x86-64
+
+# Do real PXE, rather than just booting a single file, this is an
+# alternative to dhcp-boot.
+#pxe-prompt="What system shall I netboot?"
+# or with timeout before first available action is taken:
+#pxe-prompt="Press F8 for menu.", 60
+
+# Available boot services. for PXE.
+#pxe-service=x86PC, "Boot from local disk"
+
+# Loads <tftp-root>/pxelinux.0 from dnsmasq TFTP server.
+#pxe-service=x86PC, "Install Linux", pxelinux
+
+# Loads <tftp-root>/pxelinux.0 from TFTP server at 1.2.3.4.
+# Beware this fails on old PXE ROMS.
+#pxe-service=x86PC, "Install Linux", pxelinux, 1.2.3.4
+
+# Use bootserver on network, found my multicast or broadcast.
+#pxe-service=x86PC, "Install windows from RIS server", 1
+
+# Use bootserver at a known IP address.
+#pxe-service=x86PC, "Install windows from RIS server", 1, 1.2.3.4
+
+# If you have multicast-FTP available,
+# information for that can be passed in a similar way using options 1
+# to 5. See page 19 of
+# http://download.intel.com/design/archives/wfm/downloads/pxespec.pdf
+
+
+# Enable dnsmasq's built-in TFTP server
+#enable-tftp
+
+# Set the root directory for files available via FTP.
+#tftp-root=/var/ftpd
+
+# Make the TFTP server more secure: with this set, only files owned by
+# the user dnsmasq is running as will be send over the net.
+#tftp-secure
+
+# This option stops dnsmasq from negotiating a larger blocksize for TFTP
+# transfers. It will slow things down, but may rescue some broken TFTP
+# clients.
+#tftp-no-blocksize
+
+# Set the boot file name only when the "red" tag is set.
+#dhcp-boot=net:red,pxelinux.red-net
+
+# An example of dhcp-boot with an external TFTP server: the name and IP
+# address of the server are given after the filename.
+# Can fail with old PXE ROMS. Overridden by --pxe-service.
+#dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3
+
+# Set the limit on DHCP leases, the default is 150
+#dhcp-lease-max=150
+
+# The DHCP server needs somewhere on disk to keep its lease database.
+# This defaults to a sane location, but if you want to change it, use
+# the line below.
+#dhcp-leasefile=/var/lib/misc/dnsmasq.leases
+
+# Set the DHCP server to authoritative mode. In this mode it will barge in
+# and take over the lease for any client which broadcasts on the network,
+# whether it has a record of the lease or not. This avoids long timeouts
+# when a machine wakes up on a new network. DO NOT enable this if there's
+# the slightest chance that you might end up accidentally configuring a DHCP
+# server for your campus/company accidentally. The ISC server uses
+# the same option, and this URL provides more information:
+# http://www.isc.org/files/auth.html
+#dhcp-authoritative
+
+# Run an executable when a DHCP lease is created or destroyed.
+# The arguments sent to the script are "add" or "del",
+# then the MAC address, the IP address and finally the hostname
+# if there is one.
+#dhcp-script=/bin/echo
+
+# Set the cachesize here.
+#cache-size=150
+
+# If you want to disable negative caching, uncomment this.
+#no-negcache
+
+# Normally responses which come form /etc/hosts and the DHCP lease
+# file have Time-To-Live set as zero, which conventionally means
+# do not cache further. If you are happy to trade lower load on the
+# server for potentially stale date, you can set a time-to-live (in
+# seconds) here.
+#local-ttl=
+
+# If you want dnsmasq to detect attempts by Verisign to send queries
+# to unregistered .com and .net hosts to its sitefinder service and
+# have dnsmasq instead return the correct NXDOMAIN response, uncomment
+# this line. You can add similar lines to do the same for other
+# registries which have implemented wildcard A records.
+#bogus-nxdomain=64.94.110.11
+
+# If you want to fix up DNS results from upstream servers, use the
+# alias option. This only works for IPv4.
+# This alias makes a result of 1.2.3.4 appear as 5.6.7.8
+#alias=1.2.3.4,5.6.7.8
+# and this maps 1.2.3.x to 5.6.7.x
+#alias=1.2.3.0,5.6.7.0,255.255.255.0
+# and this maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40
+#alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
+
+# Change these lines if you want dnsmasq to serve MX records.
+
+# Return an MX record named "maildomain.com" with target
+# servermachine.com and preference 50
+#mx-host=maildomain.com,servermachine.com,50
+
+# Set the default target for MX records created using the localmx option.
+#mx-target=servermachine.com
+
+# Return an MX record pointing to the mx-target for all local
+# machines.
+#localmx
+
+# Return an MX record pointing to itself for all local machines.
+#selfmx
+
+# Change the following lines if you want dnsmasq to serve SRV
+# records.  These are useful if you want to serve ldap requests for
+# Active Directory and other windows-originated DNS requests.
+# See RFC 2782.
+# You may add multiple srv-host lines.
+# The fields are <name>,<target>,<port>,<priority>,<weight>
+# If the domain part if missing from the name (so that is just has the
+# service and protocol sections) then the domain given by the domain=
+# config option is used. (Note that expand-hosts does not need to be
+# set for this to work.)
+
+# A SRV record sending LDAP for the example.com domain to
+# ldapserver.example.com port 389
+#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389
+
+# A SRV record sending LDAP for the example.com domain to
+# ldapserver.example.com port 389 (using domain=)
+#domain=example.com
+#srv-host=_ldap._tcp,ldapserver.example.com,389
+
+# Two SRV records for LDAP, each with different priorities
+#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,1
+#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,2
+
+# A SRV record indicating that there is no LDAP server for the domain
+# example.com
+#srv-host=_ldap._tcp.example.com
+
+# The following line shows how to make dnsmasq serve an arbitrary PTR
+# record. This is useful for DNS-SD. (Note that the
+# domain-name expansion done for SRV records _does_not
+# occur for PTR records.)
+#ptr-record=_http._tcp.dns-sd-services,"New Employee Page._http._tcp.dns-sd-services"
+
+# Change the following lines to enable dnsmasq to serve TXT records.
+# These are used for things like SPF and zeroconf. (Note that the
+# domain-name expansion done for SRV records _does_not
+# occur for TXT records.)
+
+#Example SPF.
+#txt-record=example.com,"v=spf1 a -all"
+
+#Example zeroconf
+#txt-record=_http._tcp.example.com,name=value,paper=A4
+
+# Provide an alias for a "local" DNS name. Note that this _only_ works
+# for targets which are names from DHCP or /etc/hosts. Give host
+# "bert" another name, bertrand
+#cname=bertand,bert
+
+# For debugging purposes, log each DNS query as it passes through
+# dnsmasq.
+#log-queries
+
+# Log lots of extra information about DHCP transactions.
+#log-dhcp
+
+# Include a another lot of configuration options.
+#conf-file=/etc/dnsmasq.more.conf
+#conf-dir=/etc/dnsmasq.d
diff --git a/doc.html b/doc.html
new file mode 100644 (file)
index 0000000..0a73083
--- /dev/null
+++ b/doc.html
@@ -0,0 +1,121 @@
+<HTML>
+<HEAD>
+<TITLE> Dnsmasq - a DNS forwarder for NAT firewalls.</TITLE>
+<link rel="icon"
+      href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
+</HEAD>
+<BODY BGCOLOR="WHITE"> 
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr>
+<td align="left" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td>
+<td align="middle" valign="middle"><h1>Dnsmasq</h1></td>
+<td align="right" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td></tr>
+</table>
+
+Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP
+ server. It is designed to provide DNS and, optionally, DHCP, to a 
+ small network. It can serve the names of local machines which are 
+ not in the global DNS. The DHCP server integrates with the DNS 
+ server and allows machines with DHCP-allocated addresses
+ to appear in the DNS with names configured either in each host or
+ in a central configuration file. Dnsmasq supports static and dynamic 
+ DHCP leases and BOOTP/TFTP/PXE for network booting of diskless machines.
+<P>
+ Dnsmasq is targeted at home networks using NAT and 
+connected to the internet via a modem, cable-modem or ADSL
+connection but would be a good choice for any smallish network (up to
+1000 clients is known to work) where low
+resource use and ease of configuration are important. 
+<P>
+Supported platforms include Linux (with glibc and uclibc), *BSD,
+Solaris and Mac OS X.
+Dnsmasq is included in at least the following Linux distributions:
+Gentoo, Debian, Slackware, Suse, Fedora,
+Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, fli4l,
+CoyoteLinux, Endian Firewall and
+Clarkconnect. It is also available as FreeBSD, OpenBSD and NetBSD ports and is used in
+Linksys wireless routers (dd-wrt, openwrt and the stock firmware) and the m0n0wall project.
+<P>
+Dnsmasq provides the following features:
+<DIR>
+
+<LI> 
+The DNS configuration of machines behind the firewall is simple and
+doesn't depend on the details of the ISP's dns servers
+<LI>
+Clients which try to do DNS lookups while  a modem link to the
+internet is down will time out immediately.
+</LI>
+<LI>
+Dnsmasq will serve names from the /etc/hosts file on the firewall
+machine: If the names of local machines are there, then they can all
+be addressed without having to maintain /etc/hosts on each machine.
+</LI>
+<LI>
+The integrated DHCP server supports static and dynamic DHCP leases and
+multiple networks and IP ranges. It works across BOOTP relays and
+supports DHCP options including RFC3397 DNS search lists.
+Machines which are configured by DHCP have their names automatically 
+included in the DNS and the names can specified by each machine or
+centrally by associating a name with a MAC address in the dnsmasq
+config file.
+</LI>
+<LI>
+Dnsmasq caches internet addresses (A records and AAAA records) and address-to-name
+mappings (PTR records), reducing the load on upstream servers and
+improving performance (especially on modem connections). 
+</LI>
+<LI>
+Dnsmasq can be configured to automatically pick up the addresses of
+its upstream nameservers from ppp or dhcp configuration. It will
+automatically reload this information if it changes. This facility
+will be of particular interest to maintainers of Linux firewall
+distributions since it allows dns configuration to be made automatic.
+</LI>
+<LI>
+On IPv6-enabled boxes, dnsmasq can both talk to upstream servers via IPv6 
+and offer DNS service via IPv6. On dual-stack (IPv4 and IPv6) boxes it talks
+both protocols and can even act as IPv6-to-IPv4 or IPv4-to-IPv6 forwarder.
+</LI>
+<LI>
+Dnsmasq can be configured to send queries for certain domains to
+upstream servers handling only those domains. This makes integration
+with private DNS systems easy.
+</LI>
+<LI>
+Dnsmasq supports MX and SRV records and can be configured to return MX records
+for any or all local machines.
+</LI>
+</DIR>
+
+<H2>Download.</H2>
+
+<A HREF="http://www.thekelleys.org.uk/dnsmasq/"> Download</A> dnsmasq here. 
+The tarball includes this documentation, source, and manpage.
+There is also a <A HREF="CHANGELOG"> CHANGELOG</A> and a <A HREF="FAQ">FAQ</A>.
+Dnsmasq is part of the Debian distribution, it can be downloaded from 
+<A HREF="http://ftp.debian.org/debian/pool/main/d/dnsmasq/"> here</A> or installed using <TT>apt</TT>.
+
+<H2>Links.</H2>
+Damien Raude-Morvan has an article in French at <A HREF="http://www.drazzib.com/docs-dnsmasq.html">http://www.drazzib.com/docs-dnsmasq.html</A>
+There is a good article about dnsmasq at <A
+HREF="http://www.enterprisenetworkingplanet.com/netos/article.php/3377351">http://www.enterprisenetworkingplanet.com/netos/article.php/3377351</A>
+and another at <A
+HREF="http://www.linux.com/articles/149040">http://www.linux.com/articles/149040</A>
+and Ilya Evseev has an article in Russian about dnsmasq to be found at
+<A HREF="http://ilya-evseev.narod.ru/articles/dnsmasq">
+http://ilya-evseev.narod.ru/articles/dnsmasq</A>. Ismael Ull has an
+article about dnsmasq in Spanish at <A HREF="http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq">http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq</A>
+<H2>License.</H2>
+Dnsmasq is distributed under the GPL. See the file COPYING in the distribution 
+for details.
+
+<H2>Contact.</H2>
+There is a dnsmasq mailing list at <A
+HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
+http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
+first location for queries, bugreports, suggestions etc.
+Dnsmasq was written by Simon Kelley. You can contact me at <A
+HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
+</BODY>
+
diff --git a/logo/README b/logo/README
new file mode 100644 (file)
index 0000000..05a8250
--- /dev/null
@@ -0,0 +1,12 @@
+Dnsmasq logo, contributed by Justin Clift.
+
+The source format is Inkscape SVG vector format, which is scalable and
+easy to export to other formats. For convenience I've included a 56x31
+png export and a 16x16 ico suitable for use as a web favicon.
+
+Simon Kelley, 22/10/2010
+
+
+
+
diff --git a/logo/favicon.ico b/logo/favicon.ico
new file mode 100644 (file)
index 0000000..1c7e8f8
Binary files /dev/null and b/logo/favicon.ico differ
diff --git a/logo/icon.png b/logo/icon.png
new file mode 100644 (file)
index 0000000..cf48461
Binary files /dev/null and b/logo/icon.png differ
diff --git a/logo/icon.svg b/logo/icon.svg
new file mode 100644 (file)
index 0000000..a2f7521
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   x="0px"
+   y="0px"
+   width="56"
+   height="31"
+   viewBox="0 0 56 31"
+   enable-background="new 0 0 72.833 46.667"
+   xml:space="preserve"
+   id="svg2"
+   inkscape:version="0.47 r22583"
+   sodipodi:docname="dnsmasq_icon.svg"
+   inkscape:export-filename="/x/centos_home/jc/workspace/git_repos/libvirt-media/libvirt-media/png/dnsmasq_icon.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"><metadata
+   id="metadata27"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs25"><inkscape:perspective
+   sodipodi:type="inkscape:persp3d"
+   inkscape:vp_x="0 : 23.3335 : 1"
+   inkscape:vp_y="0 : 1000 : 0"
+   inkscape:vp_z="72.833 : 23.3335 : 1"
+   inkscape:persp3d-origin="36.4165 : 15.555667 : 1"
+   id="perspective4857" />
+       <filter
+   id="filter3802"
+   inkscape:label="filter1"
+   color-interpolation-filters="sRGB" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient4929"
+   gradientUnits="userSpaceOnUse"
+   x1="30.564501"
+   y1="-8.8144999"
+   x2="32.937"
+   y2="32.715599" />
+               <linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient5798"
+   gradientUnits="userSpaceOnUse"
+   x1="30.564501"
+   y1="-8.8144999"
+   x2="32.937"
+   y2="32.715599" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient5812"
+   gradientUnits="userSpaceOnUse"
+   x1="30.564501"
+   y1="-8.8144999"
+   x2="32.937"
+   y2="32.715599" /><filter
+   id="filter6262"
+   inkscape:label="Drop shadow"
+   width="1.5"
+   height="1.5"
+   x="-0.25"
+   y="-0.25"
+   color-interpolation-filters="sRGB"><feGaussianBlur
+     id="feGaussianBlur6264"
+     in="SourceAlpha"
+     stdDeviation="2.500000"
+     result="blur" /><feColorMatrix
+     id="feColorMatrix6266"
+     result="bluralpha"
+     type="matrix"
+     values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.500000 0 " /><feOffset
+     id="feOffset6268"
+     in="bluralpha"
+     dx="2.700000"
+     dy="2.600000"
+     result="offsetBlur" /><feMerge
+     id="feMerge6270"><feMergeNode
+       id="feMergeNode6272"
+       in="offsetBlur" /><feMergeNode
+       id="feMergeNode6274"
+       in="SourceGraphic" /></feMerge></filter></defs><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1568"
+   inkscape:window-height="1076"
+   id="namedview23"
+   showgrid="false"
+   inkscape:zoom="8"
+   inkscape:cx="31.966768"
+   inkscape:cy="21.211869"
+   inkscape:window-x="567"
+   inkscape:window-y="328"
+   inkscape:window-maximized="0"
+   inkscape:current-layer="layer1"
+   inkscape:showpageshadow="false"
+   showborder="true" />
+<g
+   inkscape:groupmode="layer"
+   id="layer1"
+   inkscape:label="dnsmasq"
+   style="display:inline"
+   transform="translate(5.2838057,-15.545371)"><g
+     id="g3790"
+     transform="matrix(0.8183832,0,0,0.8183832,65.304897,9.8747678)"
+     style="filter:url(#filter6262)"
+     inkscape:export-xdpi="90"
+     inkscape:export-ydpi="90"><g
+       transform="translate(-91.018462,1.0687099)"
+       id="g9">
+                       <path
+   style="fill:#6700ad"
+   inkscape:connector-curvature="0"
+   id="path11"
+   d="M 54.997,12.151 C 50.083,9.132 43.29,7.266 35.791,7.266 c -7.5,0 -14.29,1.866 -19.204,4.885 -4.915,3.016 -7.956,7.184 -7.956,11.789 0,4.604 3.041,8.772 7.956,11.788 4.914,3.02 11.704,-4.271 19.204,-4.271 7.499,0 14.292,7.291 19.206,4.271 4.914,-3.016 7.955,-7.185 7.955,-11.788 0,-4.606 -3.041,-8.773 -7.955,-11.789 z M 24.996,24.318 c -2.698,0 -4.885,-0.922 -4.885,-2.061 0,-1.14 2.187,-2.063 4.885,-2.063 2.697,0 4.885,0.924 4.885,2.063 0,1.139 -2.188,2.061 -4.885,2.061 z m 21.501,0.191 c -2.686,0 -4.861,-0.856 -4.861,-1.912 0,-1.054 2.176,-1.911 4.861,-1.911 2.685,0 4.863,0.857 4.863,1.911 0,1.056 -2.178,1.912 -4.863,1.912 z" />
+                       <path
+   style="fill:none;stroke:#ffb616;stroke-width:1.85353255"
+   inkscape:connector-curvature="0"
+   id="path13"
+   d="M 54.997,12.151 C 50.083,9.132 43.29,7.266 35.791,7.266 c -7.5,0 -14.29,1.866 -19.204,4.885 -4.915,3.016 -7.956,7.184 -7.956,11.789 0,4.604 3.041,8.772 7.956,11.788 4.914,3.02 11.704,-4.271 19.204,-4.271 7.499,0 14.292,7.291 19.206,4.271 4.914,-3.016 7.955,-7.185 7.955,-11.788 0,-4.606 -3.041,-8.773 -7.955,-11.789 z M 24.996,24.318 c -2.698,0 -4.885,-0.922 -4.885,-2.061 0,-1.14 2.187,-2.063 4.885,-2.063 2.697,0 4.885,0.924 4.885,2.063 0,1.139 -2.188,2.061 -4.885,2.061 z m 21.501,0.191 c -2.686,0 -4.861,-0.856 -4.861,-1.912 0,-1.054 2.176,-1.911 4.861,-1.911 2.685,0 4.863,0.857 4.863,1.911 0,1.056 -2.178,1.912 -4.863,1.912 z" />
+               </g><g
+       transform="translate(-91.018462,1.0687099)"
+       id="Layer_2">
+       <linearGradient
+   y2="32.715599"
+   x2="32.937"
+   y1="-8.8144999"
+   x1="30.564501"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_3_">
+               <stop
+   id="stop17"
+   style="stop-color:#FFFFFF;stop-opacity:0.73"
+   offset="0" />
+               <stop
+   id="stop19"
+   style="stop-color:#FFFFFF;stop-opacity:0"
+   offset="1" />
+       </linearGradient>
+       <path
+   inkscape:connector-curvature="0"
+   style="fill:url(#linearGradient5812)"
+   id="path21"
+   d="m 54.1,15.361 c -0.924,1.078 -2.782,1.265 -3.857,1.06 C 38,14.083 22.75,12.75 16.027,23.031 14.858,24.819 11.992,25.39 10.293,23.887 8.631,22.417 13.105,15.804 17.646,13.033 22.194,10.252 28.474,8.53 35.41,8.53 c 6.936,0 13.215,1.722 17.756,4.502 0.731,0.442 1.627,1.52 0.934,2.329 z" />
+</g></g></g></svg>
\ No newline at end of file
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
new file mode 100644 (file)
index 0000000..511f57f
--- /dev/null
@@ -0,0 +1,1507 @@
+.TH DNSMASQ 8
+.SH NAME
+dnsmasq \- A lightweight DHCP and caching DNS server.
+.SH SYNOPSIS
+.B dnsmasq
+.I [OPTION]...
+.SH "DESCRIPTION"
+.BR dnsmasq
+is a lightweight DNS, TFTP and DHCP server. It is intended to provide 
+coupled DNS and DHCP service to a LAN.
+.PP
+Dnsmasq accepts DNS queries and either answers them from a small, local,
+cache or forwards them to a real, recursive, DNS server. It loads the
+contents of /etc/hosts so that local hostnames
+which do not appear in the global DNS can be resolved and also answers
+DNS queries for DHCP configured hosts.
+.PP
+The dnsmasq DHCP server supports static address assignments and multiple
+networks. It automatically
+sends a sensible default set of DHCP options, and can be configured to
+send any desired set of DHCP options, including vendor-encapsulated
+options. It includes a secure, read-only,
+TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP.
+.PP
+Dnsmasq 
+supports IPv6 for DNS and TFTP, but not DHCP.
+.SH OPTIONS
+Note that in general missing parameters are allowed and switch off
+functions, for instance "--pid-file" disables writing a PID file. On
+BSD, unless the GNU getopt library is linked, the long form of the
+options does not work on the command line; it is still recognised in
+the configuration file.
+.TP
+.B --test
+Read and syntax check configuration file(s). Exit with code 0 if all
+is OK, or a non-zero code otherwise. Do not start up dnsmasq.
+.TP
+.B \-h, --no-hosts
+Don't read the hostnames in /etc/hosts.
+.TP
+.B \-H, --addn-hosts=<file>
+Additional hosts file. Read the specified file as well as /etc/hosts. If -h is given, read
+only the specified file. This option may be repeated for more than one
+additional hosts file. If a directory is given, then read all the files contained in that directory. 
+.TP
+.B \-E, --expand-hosts
+Add the domain to simple names (without a period) in /etc/hosts
+in the same way as for DHCP-derived names. Note that this does not
+apply to domain names in cnames, PTR records, TXT records etc.
+.TP
+.B \-T, --local-ttl=<time>
+When replying with information from /etc/hosts or the DHCP leases
+file dnsmasq by default sets the time-to-live field to zero, meaning
+that the requestor should not itself cache the information. This is
+the correct thing to do in almost all situations. This option allows a
+time-to-live (in seconds) to be given for these replies. This will
+reduce the load on the server at the expense of clients using stale
+data under some circumstances.
+.TP
+.B --neg-ttl=<time>
+Negative replies from upstream servers normally contain time-to-live
+information in SOA records which dnsmasq uses for caching. If the
+replies from upstream servers omit this information, dnsmasq does not
+cache the reply. This option gives a default value for time-to-live
+(in seconds) which dnsmasq uses to cache negative replies even in 
+the absence of an SOA record. 
+.TP
+.B --max-ttl=<time>
+Set a maximum TTL value that will be handed out to clients. The specified
+maximum TTL will be given to clients instead of the true TTL value if it is 
+lower. The true TTL value is however kept in the cache to avoid flooding 
+the upstream DNS servers.
+.TP
+.B \-k, --keep-in-foreground
+Do not go into the background at startup but otherwise run as
+normal. This is intended for use when dnsmasq is run under daemontools
+or launchd.
+.TP
+.B \-d, --no-daemon
+Debug mode: don't fork to the background, don't write a pid file,
+don't change user id, generate a complete cache dump on receipt on
+SIGUSR1, log to stderr as well as syslog, don't fork new processes
+to handle TCP queries.
+.TP
+.B \-q, --log-queries
+Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
+.TP
+.B \-8, --log-facility=<facility>
+Set the facility to which dnsmasq will send syslog entries, this
+defaults to DAEMON, and to LOCAL0 when debug mode is in operation. If
+the facility given contains at least one '/' character, it is taken to
+be a filename, and dnsmasq logs to the given file, instead of
+syslog. If the facility is '-' then dnsmasq logs to stderr.
+(Errors whilst reading configuration will still go to syslog,
+but all output from a successful startup, and all output whilst
+running, will go exclusively to the file.) When logging to a file,
+dnsmasq will close and reopen the file when it receives SIGUSR2. This 
+allows the log file to be rotated without stopping dnsmasq.
+.TP
+.B --log-async[=<lines>]
+Enable asynchronous logging and optionally set the limit on the
+number of lines
+which will be queued by dnsmasq when writing to the syslog is slow. 
+Dnsmasq can log asynchronously: this
+allows it to continue functioning without being blocked by syslog, and
+allows syslog to use dnsmasq for DNS queries without risking deadlock.
+If the queue of log-lines becomes full, dnsmasq will log the
+overflow, and the number of messages  lost. The default queue length is
+5, a sane value would be 5-25, and a maximum limit of 100 is imposed.
+.TP
+.B \-x, --pid-file=<path>
+Specify an alternate path for dnsmasq to record its process-id in. Normally /var/run/dnsmasq.pid.
+.TP
+.B \-u, --user=<username>
+Specify the userid to which dnsmasq will change after startup. Dnsmasq must normally be started as root, but it will drop root 
+privileges after startup by changing id to another user. Normally this user is "nobody" but that 
+can be over-ridden with this switch.
+.TP
+.B \-g, --group=<groupname> 
+Specify the group which dnsmasq will run
+as. The defaults to "dip", if available, to facilitate access to
+/etc/ppp/resolv.conf which is not normally world readable.
+.TP
+.B \-v, --version
+Print the version number.
+.TP
+.B \-p, --port=<port>
+Listen on <port> instead of the standard DNS port (53). Setting this
+to zero completely disables DNS function, leaving only DHCP and/or TFTP.
+.TP
+.B \-P, --edns-packet-max=<size>
+Specify the largest EDNS.0 UDP packet which is supported by the DNS
+forwarder. Defaults to 4096, which is the RFC5625-recommended size.
+.TP
+.B \-Q, --query-port=<query_port>
+Send outbound DNS queries from, and listen for their replies on, the
+specific UDP port <query_port> instead of using random ports. NOTE
+that using this option will make dnsmasq less secure against DNS
+spoofing attacks but it may be faster and use less resources.  Setting this option
+to zero makes dnsmasq use a single port allocated to it by the
+OS: this was the default behaviour in versions prior to 2.43. 
+.TP
+.B --min-port=<port>
+Do not use ports less than that given as source for outbound DNS
+queries. Dnsmasq picks random ports as source for outbound queries:
+when this option is given, the ports used will always to larger
+than that specified. Useful for systems behind firewalls. 
+.TP
+.B \-i, --interface=<interface name>
+Listen only on the specified interface(s). Dnsmasq automatically adds
+the loopback (local) interface to the list of interfaces to use when
+the
+.B \--interface
+option  is used. If no
+.B \--interface
+or
+.B \--listen-address
+options are given dnsmasq listens on all available interfaces except any
+given in
+.B \--except-interface
+options. IP alias interfaces (eg "eth1:0") cannot be used with
+.B --interface
+or
+.B --except-interface
+options, use --listen-address instead. 
+.TP
+.B \-I, --except-interface=<interface name>
+Do not listen on the specified interface. Note that the order of
+.B \--listen-address
+.B --interface
+and
+.B --except-interface
+options does not matter and that 
+.B --except-interface
+options always override the others.
+.TP 
+.B \-2, --no-dhcp-interface=<interface name>
+Do not provide DHCP or TFTP on the specified interface, but do provide DNS service.
+.TP
+.B \-a, --listen-address=<ipaddr>
+Listen on the given IP address(es). Both 
+.B \--interface
+and
+.B \--listen-address
+options may be given, in which case the set of both interfaces and
+addresses is used. Note that if no
+.B \--interface
+option is given, but 
+.B \--listen-address
+is, dnsmasq will not automatically listen on the loopback
+interface. To achieve this, its IP address, 127.0.0.1, must be
+explicitly given as a 
+.B \--listen-address
+option.
+.TP
+.B \-z, --bind-interfaces
+On systems which support it, dnsmasq binds the wildcard address,
+even when it is listening on only some interfaces. It then discards
+requests that it shouldn't reply to. This has the advantage of 
+working even when interfaces come and go and change address. This
+option forces dnsmasq to really bind only the interfaces it is
+listening on. About the only time when this is useful is when 
+running another nameserver (or another instance of dnsmasq) on the
+same machine. Setting this option also enables multiple instances of
+dnsmasq which provide DHCP service to run in the same machine.
+.TP
+.B \-y, --localise-queries
+Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was
+received. If a name in /etc/hosts has more than one address associated with
+it, and at least one of those addresses is on the same subnet as the
+interface to which the query was sent, then return only the
+address(es) on that subnet. This allows for a server  to have multiple
+addresses in /etc/hosts corresponding to each of its interfaces, and
+hosts will get the correct address based on which network they are
+attached to. Currently this facility is limited to IPv4.
+.TP
+.B \-b, --bogus-priv
+Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
+which are not found in /etc/hosts or the DHCP leases file are answered
+with "no such domain" rather than being forwarded upstream.
+.TP
+.B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>]
+Modify IPv4 addresses returned from upstream nameservers; old-ip is
+replaced by new-ip. If the optional mask is given then any address
+which matches the masked old-ip will be re-written. So, for instance
+.B --alias=1.2.3.0,6.7.8.0,255.255.255.0 
+will map 1.2.3.56 to 6.7.8.56 and 1.2.3.67 to 6.7.8.67. This is what
+Cisco PIX routers call "DNS doctoring". If the old IP is given as
+range, then only addresses in the range, rather than a whole subnet,
+are re-written. So 
+.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
+maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40
+.TP 
+.B \-B, --bogus-nxdomain=<ipaddr>
+Transform replies which contain the IP address given into "No such
+domain" replies. This is intended to counteract a devious move made by
+Verisign in September 2003 when they started returning the address of
+an advertising web page in response to queries for unregistered names,
+instead of the correct NXDOMAIN response. This option tells dnsmasq to
+fake the correct response when it sees this behaviour. As at Sept 2003
+the IP address being returned by Verisign is 64.94.110.11
+.TP
+.B \-f, --filterwin2k
+Later versions of windows make periodic DNS requests which don't get sensible answers from
+the public DNS and can cause problems by triggering dial-on-demand links. This flag turns on an option
+to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the 
+requested name has underscores, to catch LDAP requests.
+.TP
+.B \-r, --resolv-file=<file>
+Read the IP addresses of the upstream nameservers from <file>, instead of
+/etc/resolv.conf. For the format of this file see
+.BR resolv.conf (5) 
+the only lines relevant to dnsmasq are nameserver ones. Dnsmasq can
+be told to poll more than one resolv.conf file, the first file name  specified
+overrides the default, subsequent ones add to the list. This is only
+allowed when polling; the file with the currently latest modification
+time is the one used. 
+.TP
+.B \-R, --no-resolv
+Don't read /etc/resolv.conf. Get upstream servers only from the command
+line or the dnsmasq configuration file.
+.TP
+.B \-1, --enable-dbus
+Allow dnsmasq configuration to be updated via DBus method calls. The
+configuration which can be changed is upstream DNS servers (and
+corresponding domains) and cache clear. Requires that dnsmasq has
+been built with DBus support.
+.TP 
+.B \-o, --strict-order
+By default, dnsmasq will send queries to any of the upstream servers
+it knows about and tries to favour servers that are known to
+be up. Setting this flag forces dnsmasq to try each query with each
+server strictly in the order they appear in /etc/resolv.conf
+.TP
+.B --all-servers
+By default, when dnsmasq has more than one upstream server available,
+it will send queries to just one server. Setting this flag forces
+dnsmasq to send all queries to all available servers. The reply from
+the server which answers first will be returned to the original requestor.
+.TP
+.B --stop-dns-rebind
+Reject (and log) addresses from upstream nameservers which are in the
+private IP ranges. This blocks an attack where a browser behind a
+firewall is used to probe machines on the local network.
+.TP
+.B --rebind-localhost-ok
+Exempt 127.0.0.0/8 from rebinding checks. This address range is
+returned by realtime black hole servers, so blocking it may disable
+these services.
+.TP 
+.B  --rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/]
+Do not detect and block dns-rebind on queries to these domains. The
+argument may be either a single domain, or multiple domains surrounded
+by '/', like the --server syntax, eg. 
+.B  --rebind-domain-ok=/domain1/domain2/domain3/
+.TP
+.B \-n, --no-poll
+Don't poll /etc/resolv.conf for changes.
+.TP
+.B --clear-on-reload
+Whenever /etc/resolv.conf is re-read, clear the DNS cache.
+This is useful when new nameservers may have different
+data than that held in cache.
+.TP
+.B \-D, --domain-needed
+Tells dnsmasq to never forward queries for plain names, without dots
+or domain parts, to upstream nameservers. If the name is not known
+from /etc/hosts or DHCP then a "not found" answer is returned.
+.TP
+.B \-S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source-ip>|<interface>[#<port>]]
+Specify IP address of upstream servers directly. Setting this flag does
+not suppress reading of /etc/resolv.conf, use -R to do that. If one or
+more 
+optional domains are given, that server is used only for those domains
+and they are queried only using the specified server. This is
+intended for private nameservers: if you have a nameserver on your
+network which deals with names of the form
+xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving  the flag 
+.B -S /internal.thekelleys.org.uk/192.168.1.1 
+will send all queries for
+internal machines to that nameserver, everything else will go to the
+servers in /etc/resolv.conf. An empty domain specification,
+.B // 
+has the special meaning of "unqualified names only" ie names without any
+dots in them. A non-standard port may be specified as 
+part of the IP
+address using a # character.
+More than one -S flag is allowed, with
+repeated domain or ipaddr parts as required.
+
+More specific domains take precendence over less specific domains, so:
+.B --server=/google.com/1.2.3.4
+.B --server=/www.google.com/2.3.4.5
+will send queries for *.google.com to 1.2.3.4, except *www.google.com,
+which will go to 2.3.4.5
+
+The special server address '#' means, "use the standard servers", so
+.B --server=/google.com/1.2.3.4
+.B --server=/www.google.com/#
+will send queries for *.google.com to 1.2.3.4, except *www.google.com which will
+be forwarded as usual.
+
+Also permitted is a -S
+flag which gives a domain but no IP address; this tells dnsmasq that
+a domain is local and it may answer queries from /etc/hosts or DHCP
+but should never forward queries on that domain to any upstream
+servers.
+.B local
+is a synonym for
+.B server
+to make configuration files clearer in this case.
+
+The optional string after the @ character tells
+dnsmasq how to set the source of the queries to this
+nameserver. It should be an ip-address, which should belong to the machine on which
+dnsmasq is running otherwise this server line will be logged and then
+ignored, or an interface name. If an interface name is given, then
+queries to the server will be forced via that interface; if an
+ip-address is given then the source address of the queries will be set
+to that address.
+The query-port flag is ignored for any servers which have a
+source address specified but the port may be specified directly as
+part of the source address. Forcing queries to an interface is not
+implemented on all platforms supported by dnsmasq.
+.TP
+.B \-A, --address=/<domain>/[domain/]<ipaddr>
+Specify an IP address to return for any host in the given domains.
+Queries in the domains are never forwarded and always replied to
+with the specified IP address which may be IPv4 or IPv6. To give
+both IPv4 and IPv6 addresses for a domain, use repeated -A flags.
+Note that /etc/hosts and DHCP leases override this for individual
+names. A common use of this is to redirect the entire doubleclick.net
+domain to some friendly local web server to avoid banner ads. The
+domain specification works in the same was as for --server, with the
+additional facility that /#/ matches any domain. Thus
+--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
+answered from /etc/hosts or DHCP and not sent to an upstream
+nameserver by a more specific --server directive.
+.TP
+.B \-m, --mx-host=<mx name>[[,<hostname>],<preference>]
+Return an MX record named <mx name> pointing to the given hostname (if
+given), or
+the host specified in the --mx-target switch
+or, if that switch is not given, the host on which dnsmasq 
+is running. The default is useful for directing mail from systems on a LAN
+to a central server. The preference value is optional, and defaults to
+1 if not given. More than one MX record may be given for a host.
+.TP 
+.B \-t, --mx-target=<hostname>
+Specify the default target for the MX record returned by dnsmasq. See
+--mx-host.  If --mx-target is given, but not --mx-host, then dnsmasq
+returns a MX record containing the MX target for MX queries on the 
+hostname of the machine on which dnsmasq is running.
+.TP
+.B \-e, --selfmx
+Return an MX record pointing to itself for each local
+machine. Local machines are those in /etc/hosts or with DHCP leases.
+.TP 
+.B \-L, --localmx
+Return an MX record pointing to the host given by mx-target (or the
+machine on which dnsmasq is running) for each
+local machine. Local machines are those in /etc/hosts or with DHCP
+leases.
+.TP
+.B \-W, --srv-host=<_service>.<_prot>.[<domain>],[<target>[,<port>[,<priority>[,<weight>]]]]
+Return a SRV DNS record. See RFC2782 for details. If not supplied, the
+domain defaults to that given by
+.B --domain.
+The default for the target domain is empty, and the default for port
+is one and the defaults for 
+weight and priority are zero. Be careful if transposing data from BIND
+zone files: the port, weight and priority numbers are in a different
+order. More than one SRV record for a given service/domain is allowed,
+all that match are returned.
+.TP
+.B \-Y, --txt-record=<name>[[,<text>],<text>]
+Return a TXT DNS record. The value of TXT record is a set of strings,
+so  any number may be included, delimited by commas; use quotes to put
+commas into a string. Note that the maximum length of a single string
+is 255 characters, longer strings are split into 255 character chunks.
+.TP
+.B --ptr-record=<name>[,<target>]
+Return a PTR DNS record.
+.TP
+.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
+Return an NAPTR DNS record, as specified in RFC3403.
+.TP
+.B --cname=<cname>,<target>
+Return a CNAME record which indicates that <cname> is really
+<target>. There are significant limitations on the target; it must be a
+DNS name which is known to dnsmasq from /etc/hosts (or additional
+hosts files) or from DHCP. If the target does not satisfy this
+criteria, the whole cname is ignored. The cname must be unique, but it
+is permissable to have more than one cname pointing to the same target.
+.TP
+.B --interface-name=<name>,<interface>
+Return a DNS record associating the name with the primary address on
+the given interface. This flag specifies an A record for the given
+name in the same way as an /etc/hosts line, except that the address is
+not constant, but taken from the given interface. If the interface is
+down, not configured or non-existent, an empty record is returned. The
+matching PTR record is also created, mapping the interface address to
+the name. More than one name may be associated with an interface
+address by repeating the flag; in that case the first instance is used
+for the reverse address-to-name mapping.
+.TP
+.B --add-mac
+Add the MAC address of the requestor to DNS queries which are
+forwarded upstream. This may be used to DNS filtering by the upstream
+server. The MAC address can only be added if the requestor is on the same
+subnet as the dnsmasq server. Note that the mechanism used to achieve this (an EDNS0 option)
+is not yet standardised, so this should be considered
+experimental. Also note that exposing MAC addresses in this way may
+have security and privacy implications. 
+.TP
+.B \-c, --cache-size=<cachesize>
+Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
+.TP
+.B \-N, --no-negcache
+Disable negative caching. Negative caching allows dnsmasq to remember
+"no such domain" answers from upstream nameservers and answer
+identical queries without forwarding them again. 
+.TP
+.B \-0, --dns-forward-max=<queries>
+Set the maximum number of concurrent DNS queries. The default value is
+150, which should be fine for most setups. The only known situation
+where this needs to be increased is when using web-server log file
+resolvers, which can generate large numbers of concurrent queries.
+.TP
+.B --proxy-dnssec
+A resolver on a client machine can do DNSSEC validation in two ways: it
+can perform the cryptograhic operations on the reply it receives, or
+it can rely on the upstream recursive nameserver to do the validation
+and set a bit in the reply if it succeeds. Dnsmasq is not a DNSSEC
+validator, so it cannot perform the validation role of the recursive nameserver,
+but it can pass through the validation results from its own upstream
+nameservers. This option enables this behaviour. You should only do
+this if you trust all the configured upstream nameservers 
+.I and the network between you and them.
+If you use the first DNSSEC mode, validating resolvers in clients,
+this option is not required. Dnsmasq always returns all the data
+needed for a client to do validation itself. 
+.TP
+.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>,<end-addr>[,<netmask>[,<broadcast>]][,<lease time>]
+Enable the DHCP server. Addresses will be given out from the range
+<start-addr> to <end-addr> and from statically defined addresses given
+in 
+.B dhcp-host
+options. If the lease time is given, then leases
+will be given for that length of time. The lease time is in seconds,
+or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given,
+the default lease time is one hour. The
+minimum lease time is two minutes. This
+option may be repeated, with different addresses, to enable DHCP
+service to more than one network. For directly connected networks (ie,
+networks on which the machine running dnsmasq has an interface) the
+netmask is optional. It is, however, required for networks which
+receive DHCP service via a relay agent. The broadcast address is
+always optional. It is always
+allowed to have more than one dhcp-range in a single subnet. 
+
+The optional 
+.B set:<tag> 
+sets an alphanumeric label which marks this network so that
+dhcp options may be specified on a per-network basis. 
+When it is prefixed with 'tag:' instead, then its meaning changes from setting
+a tag to matching it. Only one tag may be set, but more than one tag may be matched.
+The end address may be replaced by the keyword 
+.B static
+which tells dnsmasq to enable DHCP for the network specified, but not
+to dynamically allocate IP addresses: only hosts which have static
+addresses given via 
+.B dhcp-host
+or from /etc/ethers will be served. The end address may be replaced by
+the keyword
+.B proxy
+in which case dnsmasq will provide proxy-DHCP on the specified
+subnet. (See 
+.B pxe-prompt
+and 
+.B pxe-service
+for details.)
+
+The interface:<interface name> section is not normally used. See the
+NOTES section for details of this.
+.TP
+.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
+Specify per host parameters for the DHCP server. This allows a machine
+with a particular hardware address to be always allocated the same
+hostname, IP address and lease time. A hostname specified like this
+overrides any supplied by the DHCP client on the machine. It is also
+allowable to ommit the hardware address and include the hostname, in
+which case the IP address and lease times will apply to any machine
+claiming that name. For example 
+.B --dhcp-host=00:20:e0:3b:13:af,wap,infinite 
+tells dnsmasq to give
+the machine with hardware address 00:20:e0:3b:13:af the name wap, and
+an infinite DHCP lease. 
+.B --dhcp-host=lap,192.168.0.199 
+tells
+dnsmasq to always allocate the machine lap the IP address
+192.168.0.199. 
+
+Addresses allocated like this are not constrained to be
+in the range given by the --dhcp-range option, but they must be in
+the same subnet as some valid dhcp-range.  For
+subnets which don't need a pool of dynamically allocated addresses,
+use the "static" keyword in the dhcp-range declaration.
+
+It is allowed to use client identifiers rather than
+hardware addresses to identify hosts by prefixing with 'id:'. Thus: 
+.B --dhcp-host=id:01:02:03:04,..... 
+refers to the host with client identifier 01:02:03:04. It is also
+allowed to specify the client ID as text, like this:
+.B --dhcp-host=id:clientidastext,..... 
+
+The special option id:* means "ignore any client-id 
+and use MAC addresses only." This is useful when a client presents a client-id sometimes 
+but not others.
+
+If a name appears in /etc/hosts, the associated address can be
+allocated to a DHCP lease, but only if a 
+.B --dhcp-host
+option specifying the name also exists. Only one hostname can be
+given in a 
+.B dhcp-host
+option, but aliases are possible by using CNAMEs. (See 
+.B --cname
+).
+
+The special keyword "ignore"
+tells dnsmasq to never offer a DHCP lease to a machine. The machine
+can be specified by hardware address, client ID or hostname, for
+instance
+.B --dhcp-host=00:20:e0:3b:13:af,ignore
+This is
+useful when there is another DHCP server on the network which should
+be used by some machines.
+
+The set:<tag> contruct sets the tag
+whenever this dhcp-host directive is in use. This can be used to 
+selectively send DHCP options just for this host. More than one tag
+can be set in a dhcp-host directive (but not in other places where
+"set:<tag>" is allowed). When a host matches any
+dhcp-host directive (or one implied by /etc/ethers) then the special
+tag "known" is set. This allows dnsmasq to be configured to
+ignore requests from unknown machines using
+.B --dhcp-ignore=tag:!known
+Ethernet addresses (but not client-ids) may have
+wildcard bytes, so for example 
+.B --dhcp-host=00:20:e0:3b:13:*,ignore 
+will cause dnsmasq to ignore a range of hardware addresses. Note that
+the "*" will need to be escaped or quoted on a command line, but not
+in the configuration file.
+
+Hardware addresses normally match any
+network (ARP) type, but it is possible to restrict them to a single
+ARP type by preceding them with the ARP-type (in HEX) and "-". so 
+.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4 
+will only match a
+Token-Ring hardware address, since the ARP-address type for token ring
+is 6. 
+
+As a special case, it is possible to include more than one
+hardware address. eg:
+.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2
+This allows an IP address to be associated with
+multiple hardware addresses, and gives dnsmasq permission to abandon a
+DHCP lease to one of the hardware addresses when another one asks for
+a lease. Beware that this is a dangerous thing to do, it will only
+work reliably if only one of the hardware addresses is active at any
+time and there is no way for dnsmasq to enforce this. It is, for instance,
+useful to allocate a stable IP address to a laptop which
+has both wired and wireless interfaces.
+.TP
+.B --dhcp-hostsfile=<path>
+Read DHCP host information from the specified file. If a directory
+is given, then read all the files contained in that directory. The file contains 
+information about one host per line. The format of a line is the same
+as text to the right of '=' in --dhcp-host. The advantage of storing DHCP host information
+in this file is that it can be changed without re-starting dnsmasq:
+the file will be re-read when dnsmasq receives SIGHUP.
+.TP
+.B --dhcp-optsfile=<path>
+Read DHCP option information from the specified file.  If a directory
+is given, then read all the files contained in that directory. The advantage of 
+using this option is the same as for --dhcp-hostsfile: the
+dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
+it is possible to encode the information in a
+.B --dhcp-boot
+flag as DHCP options, using the options names bootfile-name,
+server-ip-address and tftp-server. This allows these to be included
+in a dhcp-optsfile.
+.TP 
+.B \-Z, --read-ethers
+Read /etc/ethers for information about hosts for the DHCP server. The
+format of /etc/ethers is a hardware address, followed by either a
+hostname or dotted-quad IP address. When read by dnsmasq these lines
+have exactly the same effect as
+.B --dhcp-host
+options containing the same information. /etc/ethers is re-read when 
+dnsmasq receives SIGHUP.
+.TP
+.B \-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]]
+Specify different or extra options to DHCP clients. By default,
+dnsmasq sends some standard options to DHCP clients, the netmask and
+broadcast address are set to the same as the host running dnsmasq, and
+the DNS server and default route are set to the address of the machine
+running dnsmasq. If the domain name option has been set, that is sent.
+This configuration allows these defaults to be overridden,
+or other options specified. The option, to be sent may be given as a
+decimal number or as "option:<option-name>" The option numbers are
+specified in RFC2132 and subsequent RFCs. The set of option-names
+known by dnsmasq can be discovered by running "dnsmasq --help dhcp".
+For example, to set the default route option to 
+192.168.4.4, do 
+.B --dhcp-option=3,192.168.4.4 
+or
+.B --dhcp-option = option:router, 192.168.4.4
+and to set the time-server address to 192.168.0.4, do
+.B --dhcp-option = 42,192.168.0.4 
+or 
+.B --dhcp-option = option:ntp-server, 192.168.0.4
+The special address 0.0.0.0 is taken to mean "the address of the
+machine running dnsmasq". Data types allowed are comma separated
+dotted-quad IP addresses, a decimal number, colon-separated hex digits
+and a text string. If the optional tags are given then
+this option is only sent when all the tags are matched.
+
+Special processing is done on a text argument for option 119, to
+conform with RFC 3397. Text or dotted-quad IP addresses as arguments
+to option 120 are handled as per RFC 3361. Dotted-quad IP addresses 
+which are followed by a slash and then a netmask size are encoded as
+described in RFC 3442.
+
+Be careful: no checking is done that the correct type of data for the
+option number is sent, it is quite possible to
+persuade dnsmasq to generate illegal DHCP packets with injudicious use
+of this flag. When the value is a decimal number, dnsmasq must determine how 
+large the data item is. It does this by examining the option number and/or the
+value, but can be overridden by appending a single letter flag as follows:
+b = one byte, s = two bytes, i = four bytes. This is mainly useful with 
+encapsulated vendor class options (see below) where dnsmasq cannot
+determine data size from the  option number. Option data which
+consists solely of periods and digits will be interpreted by dnsmasq
+as an IP address, and inserted into an option as such. To force a
+literal string, use quotes. For instance when using option 66 to send
+a literal IP address as TFTP server name, it is necessary to do
+.B --dhcp-option=66,"1.2.3.4"
+
+Encapsulated Vendor-class options may also be specified using
+--dhcp-option: for instance 
+.B --dhcp-option=vendor:PXEClient,1,0.0.0.0 
+sends the encapsulated vendor
+class-specific option "mftp-address=0.0.0.0" to any client whose
+vendor-class matches "PXEClient". The vendor-class matching is
+substring based (see --dhcp-vendorclass for details). If a
+vendor-class option (number 60) is sent by dnsmasq, then that is used 
+for selecting encapsulated options in preference to any sent by the
+client. It is
+possible to omit the vendorclass completely;
+.B --dhcp-option=vendor:,1,0.0.0.0
+in which case the encapsulated option is always sent.
+
+Options may be encapsulated within other options: for instance
+.B --dhcp-option=encap:175, 190, "iscsi-client0"
+will send option 175, within which is the option 190. If multiple
+options are given which are encapsulated with the same option number
+then they will be correctly combined into one encapsulated option.
+encap: and vendor: are may not both be set in the same dhcp-option.
+
+The final variant on encapsulated options is "Vendor-Identifying
+Vendor Options" as specified by RFC3925. These are denoted like this: 
+.B --dhcp-option=vi-encap:2, 10, "text"
+The number in the vi-encap: section is the IANA enterprise number
+used to identify this option.
+
+The address 0.0.0.0 is not treated specially in
+encapsulated options.
+.TP
+.B --dhcp-option-force=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]]
+This works in exactly the same way as
+.B --dhcp-option
+except that the option will always be sent, even if the client does
+not ask for it in the parameter request list. This is sometimes
+needed, for example when sending options to PXELinux.
+.TP
+.B --dhcp-no-override
+Disable re-use of the DHCP servername and filename fields as extra
+option space. If it can, dnsmasq moves the boot server and filename
+information (from dhcp-boot) out of their dedicated fields into
+DHCP options. This make extra space available in the DHCP packet for
+options but can, rarely, confuse old or broken clients. This flag
+forces "simple and safe" behaviour to avoid problems in such a case.
+.TP
+.B \-U, --dhcp-vendorclass=set:<tag>,<vendor-class>
+Map from a vendor-class string to a tag. Most DHCP clients provide a 
+"vendor class" which represents, in some sense, the type of host. This option 
+maps vendor classes to tags, so that DHCP options may be selectively delivered
+to different classes of hosts. For example 
+.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
+will allow options to be set only for HP printers like so:
+.B --dhcp-option=tag:printers,3,192.168.4.4 
+The vendor-class string is
+substring matched against the vendor-class supplied by the client, to
+allow fuzzy matching. The set: prefix is optional but allowed for consistency.
+.TP
+.B \-j, --dhcp-userclass=set:<tag>,<user-class>
+Map from a user-class string to a tag (with substring
+matching, like vendor classes). Most DHCP clients provide a 
+"user class" which is configurable. This option
+maps user classes to tags, so that DHCP options may be selectively delivered
+to different classes of hosts. It is possible, for instance to use
+this to set a different printer server for hosts in the class
+"accounts" than for hosts in the class "engineering".
+.TP
+.B \-4, --dhcp-mac=set:<tag>,<MAC address>
+Map from a MAC address to a tag. The MAC address may include
+wildcards. For example
+.B --dhcp-mac=set:3com,01:34:23:*:*:*
+will set the tag "3com" for any host whose MAC address matches the pattern.
+.TP
+.B --dhcp-circuitid=set:<tag>,<circuit-id>, --dhcp-remoteid=set:<tag>,<remote-id>
+Map from RFC3046 relay agent options to tags. This data may
+be provided by DHCP relay agents. The circuit-id or remote-id is
+normally given as colon-separated hex, but is also allowed to be a
+simple string. If an exact match is achieved between the circuit or
+agent ID and one provided by a relay agent, the tag is set.
+.TP
+.B --dhcp-subscrid=set:<tag>,<subscriber-id>
+Map from RFC3993 subscriber-id relay agent options to tags.
+.TP
+.B --dhcp-proxy[=<ip addr>]......
+A normal DHCP relay agent is only used to forward the initial parts of
+a DHCP interaction to the DHCP server. Once a client is configured, it
+communicates directly with the server. This is undesirable if the
+relay agent is addding extra information to the DHCP packets, such as
+that used by
+.B dhcp-circuitid
+and
+.B dhcp-remoteid.
+A full relay implementation can use the RFC 5107 serverid-override
+option to force the DHCP server to use the relay as a full proxy, with all
+packets passing through it. This flag provides an alternative method
+of doing the same thing, for relays which don't support RFC
+5107. Given alone, it manipulates the server-id for all interactions
+via relays. If a list of IP addresses is given, only interactions via
+relays at those addresses are affected.
+.TP
+.B --dhcp-match=set:<tag>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>]
+Without a value, set the tag if the client sends a DHCP
+option of the given number or name. When a value is given, set the tag only if
+the option is sent and matches the value. The value may be of the form
+"01:ff:*:02" in which case the value must match (apart from widcards)
+but the option sent may have unmatched data past the end of the
+value. The value may also be of the same form as in 
+.B dhcp-option
+in which case the option sent is treated as an array, and one element
+must match, so
+
+--dhcp-match=set:efi-ia32,option:client-arch,6
+
+will set the tag "efi-ia32" if the the number 6 appears in the list of
+architectures sent by the client in option 93. (See RFC 4578 for
+details.)  If the value is a string, substring matching is used.
+
+The special form with vi-encap:<enterpise number> matches against
+vendor-identifying vendor classes for the specified enterprise. Please
+see RFC 3925 for more details of these rare and interesting beasts.
+.TP
+.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
+Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
+all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
+If no tag:<tag> appears set:<tag> tags are set unconditionally.
+Any number of set: and tag: forms may appear, in any order. 
+Tag-if lines ares executed in order, so if the tag in tag:<tag> is a
+tag set by another
+.B tag-if,
+the line which sets the tag must precede the one which tests it.
+.TP
+.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
+When all the given tags appear in the tag set ignore the host and do
+not allocate it a DHCP lease.
+.TP
+.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]]
+When all the given tags appear in the tag set, ignore any hostname
+provided by the host. Note that, unlike dhcp-ignore, it is permissible
+to supply no tags, in which case DHCP-client supplied hostnames
+are always ignored, and DHCP hosts are added to the DNS using only
+dhcp-host configuration in dnsmasq and the contents of /etc/hosts and
+/etc/ethers.
+.TP
+.B --dhcp-generate-names=tag:<tag>[,tag:<tag>]
+Generate a name for DHCP clients which do not otherwise have one,
+using the MAC address expressed in hex, seperated by dashes. Note that
+if a host provides a name, it will be used by preference to this,
+unless 
+.B --dhcp-ignore-names 
+is set.
+.TP
+.B --dhcp-broadcast[=tag:<tag>[,tag:<tag>]]
+When all the given tags appear in the tag set, always use broadcast to
+communicate with the host when it is unconfigured. It is permissible
+to supply no tags, in which case this is unconditional. Most DHCP clients which
+need broadcast replies set a flag in their requests so that this
+happens automatically, some old BOOTP clients do not.
+.TP
+.B \-M, --dhcp-boot=[tag:<tag>,]<filename>,[<servername>[,<server address>]]
+Set BOOTP options to be returned by the DHCP server. Server name and
+address are optional: if not provided, the name is left empty, and the
+address set to the address of the machine running dnsmasq. If dnsmasq
+is providing a TFTP service (see 
+.B --enable-tftp
+) then only the filename is required here to enable network booting.
+If the optional tag(s) are given,
+they must match for this configuration to be sent. 
+.TP
+.B --pxe-service=[tag:<tag>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>]
+Most uses of PXE boot-ROMS simply allow the PXE
+system to obtain an IP address and then download the file specified by
+.B dhcp-boot
+and execute it. However the PXE system is capable of more complex
+functions when supported by a suitable DHCP server.
+
+This specifies a boot option which may appear in a PXE boot menu. <CSA> is
+client system type, only services of the correct type will appear in a
+menu. The known types are x86PC, PC98, IA64_EFI, Alpha, Arc_x86,
+Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI and X86-64_EFI; an
+integer may be used for other types. The
+parameter after the menu text may be a file name, in which case dnsmasq acts as a
+boot server and directs the PXE client to download the file by TFTP,
+either from itself (
+.B enable-tftp 
+must be set for this to work) or another TFTP server if the final IP
+address is given.
+Note that the "layer"
+suffix (normally ".0") is supplied by PXE, and should not be added to
+the basename. If an integer boot service type, rather than a basename
+is given, then the PXE client will search for a
+suitable boot service for that type on the network. This search may be done
+by broadcast, or direct to a server if its IP address is provided.  
+If no boot service type or filename is provided (or a boot service type of 0 is specified)
+then the menu entry will abort the net boot procedure and
+continue booting from local media.
+.TP
+.B --pxe-prompt=[tag:<tag>,]<prompt>[,<timeout>]
+Setting this provides a prompt to be displayed after PXE boot. If the
+timeout is given then after the
+timeout has elapsed with no keyboard input, the first available menu
+option will be automatically executed. If the timeout is zero then the first available menu
+item will be executed immediately. If 
+.B pxe-prompt
+is ommitted the system will wait for user input if there are multiple
+items in the menu, but boot immediately if
+there is only one. See
+.B pxe-service 
+for details of menu items.
+
+Dnsmasq supports PXE "proxy-DHCP", in this case another DHCP server on
+the network is responsible for allocating IP addresses, and dnsmasq
+simply provides the information given in 
+.B pxe-prompt
+and
+.B pxe-service
+to allow netbooting. This mode is enabled using the
+.B proxy
+keyword in
+.B dhcp-range.
+.TP  
+.B \-X, --dhcp-lease-max=<number>
+Limits dnsmasq to the specified maximum number of DHCP leases. The
+default is 1000. This limit is to prevent DoS attacks from hosts which
+create thousands of leases and use lots of memory in the dnsmasq
+process.
+.TP
+.B \-K, --dhcp-authoritative
+Should be set when dnsmasq is definitely the only DHCP server on a network.
+It changes the behaviour from strict RFC compliance so that DHCP requests on
+unknown leases from unknown hosts are not ignored. This allows new hosts
+to get a lease without a tedious timeout under all circumstances. It also 
+allows dnsmasq to rebuild its lease database without each client needing to 
+reacquire a lease, if the database is lost.
+.TP
+.B --dhcp-alternate-port[=<server port>[,<client port>]]
+Change the ports used for DHCP from the default. If this option is
+given alone, without arguments, it changes the ports used for DHCP
+from 67 and 68 to 1067 and 1068. If a single argument is given, that
+port number is used for the server and the port number plus one used
+for the client. Finally, two port numbers allows arbitrary
+specification of both server and client ports for DHCP.
+.TP
+.B \-3, --bootp-dynamic[=<network-id>[,<network-id>]]
+Enable dynamic allocation of IP addresses to BOOTP clients. Use this
+with care, since each address allocated to a BOOTP client is leased
+forever, and therefore becomes permanently unavailable for re-use by
+other hosts. if this is given without tags, then it unconditionally
+enables dynamic allocation. With tags, only when the tags are all
+set. It may be repeated with different tag sets. 
+.TP
+.B \-5, --no-ping
+By default, the DHCP server will attempt to ensure that an address in
+not in use before allocating it to a host. It does this by sending an
+ICMP echo request (aka "ping") to the address in question. If it gets
+a reply, then the address must already be in use, and another is
+tried. This flag disables this check. Use with caution.
+.TP
+.B --log-dhcp
+Extra logging for DHCP: log all the options sent to DHCP clients and
+the tags used to determine them.
+.TP
+.B \-l, --dhcp-leasefile=<path>
+Use the specified file to store DHCP lease information.
+.TP 
+.B \-6 --dhcp-script=<path>
+Whenever a new DHCP lease is created, or an old one destroyed, the
+executable specified by this option is run.  <path>
+must be an absolute pathname, no PATH search occurs. 
+The arguments to the process
+are "add", "old" or "del", the MAC
+address of the host, the IP address, and the hostname,
+if known. "add" means a lease has been created, "del" means it has
+been destroyed, "old" is a notification of an existing lease when
+dnsmasq starts or a change to MAC address or hostname of an existing
+lease (also, lease length or expiry and client-id, if leasefile-ro is set).
+If the MAC address is from a network type other than ethernet,
+it will have the network type prepended, eg "06-01:23:45:67:89:ab" for
+token ring. The process is run as root (assuming that dnsmasq was originally run as
+root) even if dnsmasq is configured to change UID to an unprivileged user.
+
+The environment is inherited from the invoker of dnsmasq, with some or
+all of the following variables added.
+
+DNSMASQ_CLIENT_ID if the host provided a client-id.
+
+DNSMASQ_DOMAIN if the fully-qualified domain name of the host is
+known, this is set to the  domain part. (Note that the hostname passed
+to the script as an argument is never fully-qualified.)
+
+If the client provides vendor-class, hostname or user-class, 
+these are provided in DNSMASQ_VENDOR_CLASS
+DNSMASQ_SUPPLIED_HOSTNAME and 
+DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for
+"add" actions or "old" actions when a host resumes an existing lease,
+since these data are not held in dnsmasq's lease
+database.
+
+If dnsmasq was compiled with HAVE_BROKEN_RTC, then
+the length of the lease (in seconds) is stored in
+DNSMASQ_LEASE_LENGTH, otherwise the time of lease expiry is stored in
+DNSMASQ_LEASE_EXPIRES. The number of seconds until lease expiry is
+always stored in DNSMASQ_TIME_REMAINING. 
+
+If a lease used to have a hostname, which is
+removed, an "old" event is generated with the new state of the lease, 
+ie no name, and the former name is provided in the environment 
+variable DNSMASQ_OLD_HOSTNAME. 
+
+DNSMASQ_INTERFACE stores the name of
+the interface on which the request arrived; this is not set for "old"
+actions when dnsmasq restarts. 
+
+DNSMASQ_RELAY_ADDRESS is set if the client
+used a DHCP relay to contact dnsmasq and the IP address of the relay
+is known. 
+
+DNSMASQ_TAGS contains all the tags set during the
+DHCP transaction, separated by spaces.
+
+All file descriptors are
+closed except stdin, stdout and stderr which are open to /dev/null
+(except in debug mode).
+
+The script is not invoked concurrently: at most one instance
+of the script is ever running (dnsmasq waits for an instance of script to exit
+before running the next). Changes to the lease database are which
+require the script to be invoked are queued awaiting exit of a running instance.
+If this queueing allows multiple state changes occur to a single
+lease before the script can be run then 
+earlier states are discarded and the current state of that lease is
+reflected when the script finally runs. 
+
+At dnsmasq startup, the script will be invoked for
+all existing leases as they are read from the lease file. Expired
+leases will be called with "del" and others with "old". When dnsmasq
+receives a HUP signal, the script will be invoked for existing leases
+with an "old " event.
+.TP
+.B --dhcp-scriptuser
+Specify the user as which to run the lease-change script. This defaults to root, but can be changed to another user using this flag. 
+.TP 
+.B \-9, --leasefile-ro
+Completely suppress use of the lease database file. The file will not
+be created, read, or written. Change the way the lease-change
+script (if one is provided) is called, so that the lease database may
+be maintained in external storage by the script. In addition to the
+invocations  given in 
+.B  --dhcp-script
+the lease-change script is called once, at dnsmasq startup, with the
+single argument "init". When called like this the script should write
+the saved state of the lease database, in dnsmasq leasefile format, to
+stdout and exit with zero exit code. Setting this
+option also forces the leasechange script to be called on changes
+to the client-id and lease length and expiry time.
+.TP
+.B --bridge-interface=<interface>,<alias>[,<alias>]
+Treat DHCP request packets arriving at any of the <alias> interfaces
+as if they had arrived at <interface>. This option is necessary when
+using "old style" bridging on BSD platforms, since
+packets arrive at tap interfaces which don't have an IP address.
+.TP
+.B \-s, --domain=<domain>[,<address range>[,local]]
+Specifies DNS domains for the DHCP server. Domains may be be given 
+unconditionally (without the IP range) or for limited IP ranges. This has two effects;
+firstly it causes the DHCP server to return the domain to any hosts
+which request it, and secondly it sets the domain which it is legal
+for DHCP-configured hosts to claim. The intention is to constrain
+hostnames so that an untrusted host on the LAN cannot advertise 
+its name via dhcp as e.g. "microsoft.com" and capture traffic not 
+meant for it. If no domain suffix is specified, then any DHCP
+hostname with a domain part (ie with a period) will be disallowed 
+and logged. If suffix is specified, then hostnames with a domain 
+part are allowed, provided the domain part matches the suffix. In
+addition, when a suffix is set then hostnames without a domain
+part have the suffix added as an optional domain part. Eg on my network I can set 
+.B --domain=thekelleys.org.uk
+and have a machine whose DHCP hostname is "laptop". The IP address for that machine is available from 
+.B dnsmasq
+both as "laptop" and "laptop.thekelleys.org.uk". If the domain is
+given as "#" then the domain is read from the first "search" directive
+in /etc/resolv.conf (or equivalent).
+
+The address range can be of the form
+<ip address>,<ip address> or <ip address>/<netmask> or just a single
+<ip address>. See 
+.B --dhcp-fqdn
+which can change the behaviour of dnsmasq with domains.
+
+If the address range is given as ip-address/network-size, then a
+additional flag "local" may be supplied which has the effect of adding
+--local declarations for forward and reverse DNS queries. Eg.
+.B --domain=thekelleys.org.uk,192.168.0.0/24,local
+is identical to
+.B --domain=thekelleys.org.uk,192.168.0.0/24
+--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
+The network size must be 8, 16 or 24 for this to be legal.
+.TP
+.B --dhcp-fqdn
+In the default mode, dnsmasq inserts the unqualified names of
+DHCP clients into the DNS. For this reason, the names must be unique,
+even if two clients which have the same name are in different
+domains. If a second DHCP client appears which has the same name as an
+existing client, the name is transfered to the new client. If 
+.B --dhcp-fqdn
+is set, this behaviour changes: the unqualified name is no longer
+put in the DNS, only the qualified name. Two DHCP clients with the
+same name may both keep the name, provided that the domain part is
+different (ie the fully qualified names differ.) To ensure that all
+names have a domain part, there must be at least 
+.B --domain 
+without an address specified when 
+.B --dhcp-fqdn 
+is set.
+.TP
+.B --enable-tftp[=<interface>]
+Enable the TFTP server function. This is deliberately limited to that
+needed to net-boot a client. Only reading is allowed; the tsize and
+blksize extensions are supported (tsize is only supported in octet
+mode). See NOTES section for use of the interface argument.
+
+.TP
+.B --tftp-root=<directory>[,<interface>]
+Look for files to transfer using TFTP relative to the given
+directory. When this is set, TFTP paths which include ".." are
+rejected, to stop clients getting outside the specified root.
+Absolute paths (starting with /) are allowed, but they must be within
+the tftp-root. If the optional interface argument is given, the
+directory is only used for TFTP requests via that interface.
+.TP
+.B --tftp-unique-root
+Add the IP address of the TFTP client as a path component on the end
+of the TFTP-root (in standard dotted-quad format). Only valid if a
+tftp-root is set and the directory exists. For instance, if tftp-root is "/tftp" and client 
+1.2.3.4 requests file "myfile" then the effective path will be
+"/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
+.TP
+.B --tftp-secure
+Enable TFTP secure mode: without this, any file which is readable by
+the dnsmasq process under normal unix access-control rules is
+available via TFTP. When the --tftp-secure flag is given, only files
+owned by the user running the dnsmasq process are accessible. If
+dnsmasq is being run as root, different rules apply: --tftp-secure
+has no effect, but only files which have the world-readable bit set
+are accessible. It is not recommended to run dnsmasq as root with TFTP
+enabled, and certainly not without specifying --tftp-root. Doing so
+can expose any world-readable file on the server to any host on the net. 
+.TP
+.B --tftp-max=<connections>
+Set the maximum number of concurrent TFTP connections allowed. This
+defaults to 50. When serving a large number of TFTP connections,
+per-process file descriptor limits may be encountered. Dnsmasq needs
+one file descriptor for each concurrent TFTP connection and one
+file descriptor per unique file (plus a few others). So serving the
+same file simultaneously to n clients will use require about n + 10 file
+descriptors, serving different files simultaneously to n clients will
+require about (2*n) + 10 descriptors. If 
+.B --tftp-port-range
+is given, that can affect the number of concurrent connections.
+.TP
+.B --tftp-no-blocksize
+Stop the TFTP server from negotiating the "blocksize" option with a
+client. Some buggy clients request this option but then behave badly
+when it is granted.
+.TP
+.B --tftp-port-range=<start>,<end>
+A TFTP server listens on a well-known port (69) for connection initiation,
+but it also uses a dynamically-allocated port for each
+connection. Normally these are allocated by the OS, but this option
+specifies a range of ports for use by TFTP transfers. This can be
+useful when TFTP has to traverse a firewall. The start of the range
+cannot be lower than 1025 unless dnsmasq is running as root. The number
+of concurrent TFTP connections is limited by the size of the port range. 
+.TP  
+.B \-C, --conf-file=<file>
+Specify a different configuration file. The conf-file option is also allowed in
+configuration files, to include multiple configuration files. A
+filename of "-" causes dnsmasq to read configuration from stdin.
+.TP
+.B \-7, --conf-dir=<directory>[,<file-extension>......]
+Read all the files in the given directory as configuration
+files. If extension(s) are given, any files which end in those
+extensions are skipped. Any files whose names end in ~ or start with . or start and end
+with # are always skipped. This flag may be given on the command
+line or in a configuration file.
+.SH CONFIG FILE
+At startup, dnsmasq reads
+.I /etc/dnsmasq.conf,
+if it exists. (On
+FreeBSD, the file is 
+.I /usr/local/etc/dnsmasq.conf
+) (but see the 
+.B \-C
+and
+.B \-7
+options.) The format of this
+file consists of one option per line, exactly as the long options detailed 
+in the OPTIONS section but without the leading "--". Lines starting with # are comments and ignored. For
+options which may only be specified once, the configuration file overrides 
+the command line.  Quoting is allowed in a config file:
+between " quotes the special meanings of ,:. and # are removed and the
+following escapes are allowed: \\\\ \\" \\t \\e \\b \\r and \\n. The later 
+corresponding to tab, escape, backspace, return and newline.
+.SH NOTES
+When it receives a SIGHUP, 
+.B dnsmasq 
+clears its cache and then re-loads 
+.I /etc/hosts
+and 
+.I /etc/ethers 
+and any file given by --dhcp-hostsfile, --dhcp-optsfile or --addn-hosts.
+The dhcp lease change script is called for all
+existing DHCP leases. If 
+.B
+--no-poll
+is set SIGHUP also re-reads
+.I /etc/resolv.conf.
+SIGHUP
+does NOT re-read the configuration file.
+.PP
+When it receives a SIGUSR1,
+.B dnsmasq 
+writes statistics to the system log. It writes the cache size,
+the number of names which have had to removed from the cache before
+they expired in order to make room for new names and the total number
+of names that have been inserted into the cache. For each upstream
+server it gives the number of queries sent, and the number which
+resulted in an error. In 
+.B --no-daemon
+mode or when full logging is enabled (-q), a complete dump of the
+contents of the cache is made.
+.PP 
+When it receives SIGUSR2 and it is logging direct to a file (see
+.B --log-facility
+) 
+.B dnsmasq
+will close and reopen the log file. Note that during this operation,
+dnsmasq will not be running as root. When it first creates the logfile
+dnsmasq changes the ownership of the file to the non-root user it will run
+as. Logrotate should be configured to create a new log file with
+the ownership which matches the existing one before sending SIGUSR2.
+If TCP DNS queries are in progress, the old logfile will remain open in
+child processes which are handling TCP queries and may continue to be
+written. There is a limit of 150 seconds, after which all existing TCP
+processes will have expired: for this reason, it is not wise to
+configure logfile compression for logfiles which have just been
+rotated. Using logrotate, the required options are 
+.B create 
+and
+.B delaycompress.
+
+.PP
+Dnsmasq is a DNS query forwarder: it it not capable of recursively
+answering arbitrary queries starting from the root servers but
+forwards such queries to a fully recursive upstream DNS server which is
+typically provided by an ISP. By default, dnsmasq reads
+.I /etc/resolv.conf
+to discover the IP
+addresses of the upstream nameservers it should use, since the
+information is typically stored there. Unless
+.B --no-poll
+is used,
+.B dnsmasq
+checks the modification time of
+.I /etc/resolv.conf
+(or equivalent if 
+.B \--resolv-file 
+is used) and re-reads it if it changes. This allows the DNS servers to
+be set dynamically by PPP or DHCP since both protocols provide the
+information.
+Absence of
+.I /etc/resolv.conf
+is not an error
+since it may not have been created before a PPP connection exists. Dnsmasq 
+simply keeps checking in case
+.I /etc/resolv.conf 
+is created at any
+time. Dnsmasq can be told to parse more than one resolv.conf
+file. This is useful on a laptop, where both PPP and DHCP may be used:
+dnsmasq can be set to poll both 
+.I /etc/ppp/resolv.conf 
+and
+.I /etc/dhcpc/resolv.conf 
+and will use the contents of whichever changed
+last, giving automatic switching between DNS servers.
+.PP
+Upstream servers may also be specified on the command line or in
+the configuration file. These server specifications optionally take a
+domain name which tells dnsmasq to use that server only to find names
+in that particular domain.
+.PP
+In order to configure dnsmasq to act as cache for the host on which it is running, put "nameserver 127.0.0.1" in
+.I /etc/resolv.conf
+to force local processes to send queries to
+dnsmasq. Then either specify the upstream servers directly to dnsmasq
+using 
+.B \--server
+options or put their addresses real in another file, say
+.I /etc/resolv.dnsmasq
+and run dnsmasq with the 
+.B \-r /etc/resolv.dnsmasq
+option. This second technique allows for dynamic update of the server
+addresses by PPP or DHCP.
+.PP
+Addresses in /etc/hosts will "shadow" different addresses for the same
+names in the upstream DNS, so "mycompany.com 1.2.3.4" in /etc/hosts will ensure that
+queries for "mycompany.com" always return 1.2.3.4 even if queries in
+the upstream DNS would otherwise return a different address. There is
+one exception to this: if the upstream DNS contains a CNAME which
+points to a shadowed name, then looking up the CNAME through dnsmasq
+will result in the unshadowed address associated with the target of
+the CNAME. To work around this, add the CNAME to /etc/hosts so that
+the CNAME is shadowed too.
+
+.PP
+The tag system works as follows: For each DHCP request, dnsmasq
+collects a set of valid tags from active configuration lines which
+include set:<tag>, including one from the 
+.B dhcp-range
+used to allocate the address, one from any matching 
+.B dhcp-host
+(and "known" if a dhcp-host matches) 
+The tag "bootp" is set for BOOTP requests, and a tag whose name is the 
+name of the interface on which the request arrived is also set.
+
+Any configuration lines which includes one or more tag:<tag> contructs
+will only be valid if all that tags are matched in the set derived
+above. Typically this is dhcp-option.
+.B dhcp-option 
+which has tags will be used in preference  to an untagged 
+.B dhcp-option,
+provided that _all_ the tags match somewhere in the
+set collected as described above. The prefix '!' on a tag means 'not'
+so --dhcp=option=tag:!purple,3,1.2.3.4 sends the option when the
+tag purple is not in the set of valid tags. (If using this in a
+command line rather than a configuration file, be sure to escape !,
+which is a shell metacharacter)
+.PP
+Note that for 
+.B dhcp-range 
+both tag:<tag> and set:<tag> are allowed, to both select the range in
+use based on (eg) dhcp-host, and to affect the options sent, based on
+the range selected.
+
+This system evolved from an earlier, more limited one and for backward
+compatibility "net:" may be used instead of "tag:" and "set:" may be
+omitted. (Except in 
+.B dhcp-host,
+where "net:" may be used instead of "set:".) For the same reason, '#'
+may be used instead of '!' to indicate NOT.
+.PP 
+The DHCP server in dnsmasq will function as a BOOTP server also,
+provided that the MAC address and IP address for clients are given,
+either using 
+.B dhcp-host 
+configurations or in
+.I /etc/ethers
+, and a
+.B dhcp-range 
+configuration option is present to activate the DHCP server
+on a particular network. (Setting --bootp-dynamic removes the need for
+static address mappings.) The filename
+parameter in a BOOTP request is used as a tag,
+as is the tag "bootp", allowing some control over the options returned to
+different classes of hosts.
+
+.B dhcp-range
+may have an interface name supplied as
+"interface:<interface-name>". The semantics if this are as follows:
+For DHCP, if any other dhcp-range exists _without_ an interface name,
+then the interface name is ignored and and dnsmasq behaves as if the
+interface parts did not exist, otherwise DHCP is only provided to 
+interfaces mentioned in dhcp-range
+declarations. For DNS, if there are no
+.B --interface
+or 
+.B --listen-address
+flags, behaviour is unchanged by the interface part. If either of
+these flags are present, the interfaces mentioned in
+dhcp-ranges are added to the set which get DNS service.
+
+Similarly, 
+.B enable-tftp
+may take an interface name, which enables TFTP only for a particular
+interface, ignoring 
+.B --interface 
+or
+.B --listen-address
+flags. In addition 
+.B --tftp-secure
+and
+.B --tftp-unique-root
+and
+.B --tftp-no-blocksize
+are ignored for requests from such interfaces. (A 
+.B --tftp-root
+directive giving a root path and an interface should be 
+provided too.)
+
+These rules may seem odd at first sight, but  they
+allow a single line  of the form "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200"
+to be added to dnsmasq configuration which then supplies
+DHCP and DNS services to that interface, without affecting
+what services are supplied to other interfaces and irrespective of 
+the existance or lack of "interface=<interface>" 
+lines elsewhere in the dnsmasq configuration.
+"enable-tftp=virt0" and "tftp-root=<root>,virt0" do the same job for TFTP.
+ The idea is
+that such a line can be added automatically by libvirt
+or equivalent systems, without disturbing any manual
+configuration.
+
+.SH EXIT CODES
+.PP
+0 - Dnsmasq successfully forked into the background, or terminated
+normally if backgrounding is not enabled.
+.PP
+1 - A problem with configuration was detected.
+.PP
+2 - A problem with network access occurred (address in use, attempt
+to use privileged ports without permission).
+.PP
+3 - A problem occurred with a filesystem operation (missing
+file/directory, permissions).
+.PP
+4 - Memory allocation failure.
+.PP
+5 - Other miscellaneous problem.
+.PP
+11 or greater - a non zero return code was received from the
+lease-script process "init" call. The exit code from dnsmasq is the
+script's exit code with 10 added. 
+
+.SH LIMITS
+The default values for resource limits in dnsmasq are generally
+conservative, and appropriate for embedded router type devices with
+slow processors and limited memory. On more capable hardware, it is
+possible to increase the limits, and handle many more clients. The
+following applies to dnsmasq-2.37: earlier versions did not scale as well.
+.PP
+Dnsmasq is capable of handling DNS and DHCP for at least a thousand
+clients. The DHCP lease times should not be very short (less than one hour). The
+value of 
+.B --dns-forward-max 
+can be increased: start with it equal to
+the number of clients and increase if DNS seems slow. Note that DNS
+performance depends too on the performance of the upstream
+nameservers. The size of the DNS cache may be increased: the hard
+limit is 10000 names and the default (150) is very low. Sending
+SIGUSR1 to dnsmasq makes it log information which is useful for tuning
+the cache size. See the 
+.B NOTES
+section for details.
+
+.PP
+The built-in TFTP server is capable of many simultaneous file
+transfers: the absolute limit is related to the number of file-handles
+allowed to a process and the ability of the select() system call to
+cope with large numbers of file handles. If the limit is set too high
+using 
+.B --tftp-max
+it will be scaled down and the actual limit logged at
+start-up. Note that more transfers are possible when the same file is
+being sent than when each transfer sends a different file.
+
+.PP
+It is possible to use dnsmasq to block Web advertising by using a list
+of known banner-ad servers, all resolving to 127.0.0.1 or 0.0.0.0, in
+.B /etc/hosts 
+or an additional hosts file. The list can be very long, 
+dnsmasq has been tested successfully with one million names. That size
+file needs a 1GHz processor and about 60Mb of RAM.
+
+.SH INTERNATIONALISATION
+Dnsmasq can be compiled to support internationalisation. To do this,
+the make targets "all-i18n" and "install-i18n" should be used instead of
+the standard targets "all" and "install". When internationalisation
+is compiled in, dnsmasq will produce log messages in the local
+language and support internationalised domain names (IDN). Domain
+names in /etc/hosts, /etc/ethers and /etc/dnsmasq.conf which contain
+non-ASCII characters will be translated to the DNS-internal punycode
+representation. Note that
+dnsmasq determines both the language for messages and the assumed
+charset for configuration
+files from the LANG environment variable. This should be set to the system
+default value by the script which is responsible for starting
+dnsmasq. When editing the configuration files, be careful to do so
+using only the system-default locale and not user-specific one, since
+dnsmasq has no direct way of determining the charset in use, and must
+assume that it is the system default. 
+.SH FILES
+.IR /etc/dnsmasq.conf 
+
+.IR /usr/local/etc/dnsmasq.conf
+
+.IR /etc/resolv.conf
+.IR /var/run/dnsmasq/resolv.conf
+.IR /etc/ppp/resolv.conf
+.IR /etc/dhcpc/resolv.conf
+
+.IR /etc/hosts
+
+.IR /etc/ethers
+
+.IR /var/lib/misc/dnsmasq.leases 
+
+.IR /var/db/dnsmasq.leases
+
+.IR /var/run/dnsmasq.pid
+.SH SEE ALSO
+.BR hosts (5), 
+.BR resolver (5)
+.SH AUTHOR
+This manual page was written by Simon Kelley <simon@thekelleys.org.uk>.
+
+
diff --git a/man/es/dnsmasq.8 b/man/es/dnsmasq.8
new file mode 100644 (file)
index 0000000..65e4b72
--- /dev/null
@@ -0,0 +1,1517 @@
+.TH DNSMASQ 8
+.SH NOMBRE
+dnsmasq \- Un ligero servidor DHCP y DNS con caché.
+.SH SINOPSIS
+.B dnsmasq
+.I [OPCION]...
+.SH "DESCRIPCIÓN"
+.BR dnsmasq
+es un ligero servidor DNS, TFTP y DHCP. Su propósito es proveer servicios DNS
+y DHCP a una red de Ã¡rea local.
+.PP
+Dnsmasq acepta búsquedas DNS y las responde desde un pequeño
+caché local, o las reenvía hacia un servidor DNS real recursivo.
+Carga el contenido de /etc/hosts, de tal forma que nombres de
+hosts locales los cuales no aparecen en el DNS mundial puedan ser
+resueltos. También responde a búsquedas DNS para hosts configurados
+vía DHCP.
+.PP
+El servidor DHCP dnsmasq incluye soporte para asignación de direcciones
+estáticas y redes múltiples. Automáticamente envía un predeterminado sensible de
+opciones DHCP, y puede ser configurado para enviar cualquier opciones DHCP deseadas,
+incluyendo opciones encapsuladas por vendedores. Incluye un servidor seguro
+TFTP solo-lectura para permitir el inicio vía red/PXE de hosts DHCP. Tambíen
+incluye soporte para BOOTP.
+.PP
+Dnsmasq
+incluye soporte IPv6 para DNS, pero no para DHCP.
+.SH OPCIONES
+Nótese que en general parámetros ausentes son permitidos y deshabilitan
+funciones, por ejemplo "--pid-file=" deshabilita la escritura de un
+archivo PID. En BSD, a menos que la librería GNU getopt esté enlazada,
+la forma larga de las opciones no funciona en la línea de comandos,
+pero todavía es reconocida en el archivo de configuración.
+.TP
+.B --test
+Leer archivo(s) de configuración y revisar su sintaxis. Salir con código
+0 si todo está bien, o un código no-cero en cualquier otro caso. No
+iniciar dnsmasq.
+.TP
+.B \-h, --no-hosts
+No leer los nombres de hosts en /etc/hosts.
+.TP
+.B \-H, --addn-hosts=<archivo>
+Archivo de hosts adicional. Leer el archivo especificado adicionalmente
+a /etc/hosts. Si se brinda -h, leer solo el archivo especificado. Esta
+opción puede ser repetida para más de un archivo de hosts adicional. Si
+un directorio es brindado, entonces leer todos los archivos contenidos en
+ese directorio.
+.TP
+.B \-E, --expand-hosts
+Agregar el dominio a nombres sencillos (sin punto) en /etc/hosts de la
+misma manera que con nombres derivados de DHCP. Nótese que esto no
+aplica a nombres de dominio en cnames, expedientes PTR, TXT, etc.
+.TP
+.B \-T, --local-ttl=<tiempo>
+Al responder con información desde /etc/hosts o desde el archivo
+de arriendos DHCP, dnsmasq fija el tiempo de vida (TTL) a cero por
+predeterminado, significando que el remitente no debrá cachear
+la información por sí mismo. Esto es lo correcto a hacer en casi
+todas las situaciones. Esta opción permite que se especifique
+cierto tiempo de vida (en segundos) para estas respuestas. Esto
+reduce la carga sobre el servidor al costo de que los clientes
+usaran datos añejos bajo algunas circunstancias.
+.TP
+.B --neg-ttl=<tiempo>
+Respuestas negativas desde servidores upstream normalmente contienen
+información time-to-live (tiempo de vida) en expedientes SOA que
+dnsmasq usa para hacer caché. Si las respuestas de servidores upstream
+omiten esta información, dnsmasq no mete la respuesta en el caché.
+Esta opción brinda un valor predeterminado para el time-to-live que
+dnsmasq usa para meter respuestas negativas en el caché aún en la
+ausencia de un expediente SOA.
+.TP
+.B --max-ttl=<tiempo>
+Fijar un valor TTL (tiempo de vida) máximo que será entregado a
+clientes. El TTL máximo especificado será otorgado a clientes en vez
+del TTL verdadero si es menor. El valor TTL real es mantenido en el caché
+para prevenir la inundación de los servidores DNS upstream.
+.TP
+.B \-k, --keep-in-foreground
+No ir hacia el fondo al iniciar, pero aparte de eso ejecutar como
+normal. La intención de esto es para cuando dnsmasq es ejecutado
+bajo daemontools o launchd.
+.TP
+.B \-d, --no-daemon
+Modo debug: no hacer un fork hacia el fondo, no crear un archivo PID,
+no cambiar el ID del usuario, generar un cache dump completo al
+recibir un SIGUSR1, bitacorear a stderr al igual que a syslog, no
+forkear procesos nuevos para manejar búsquedas TCP.
+.TP
+.B \-q, --log-queries
+Bitacorear los resultados de búsquedas DNS manejadas por dnsmasq.
+Habilitar un dump de caché completo al recibir un SIGUSR1.
+.TP
+.B \-8, --log-facility=<facilidad>
+Fijar la facilidad a la cual dnsmasq deberá enviar mensajes syslog,
+esto es DAEMON por predeterminado, y LOCAL0 cuando el modo debug está
+en operación. Si la facilidad brindada contiene por lo menos un carácter
+"/", se trata como un nombre de archivo, y dnsmasq bitacoreará a dicho
+archivo, en vez de syslog. Si la facilidad es '-' entonces dnsmasq
+bitacorea a stderr. (Errores durante la lectura de la configuración
+irán a syslog todavía, pero todo output desde un inicio exitoso, y todo
+output mientras en ejecución, irá a este archivo exclusivamente.)
+Al bitacorear a un archivo, dnsmasq cerrará y reabrirá el archivo al
+recibir un SIGUSR2. Esto permite que el archivo de bitácora sea rotado
+sin detener a dnsmasq.
+.TP
+.B --log-async[=<líneas>]
+Habilitar bitacoréo asincrónico y opcionalmente fijar el límite de número
+de líneas que serán enviadas a la coleta por dnsmasq cuando syslog está
+lento. Dnsmasq puede bitacorear asincrónicamente: esto le permite continuar
+funcionando sin ser bloqueado por syslog, y permite a syslog usar dnsmasq
+para búsquedas DNS sin riesgo de tranque. Si la coleta de líneas de bitácora
+se llena, dnsmasq bitacoreará el desbordamiento, y el número de mensajes
+perdidos. El tamaño predeterminado de coleta es 5, un valor sano sería 5-25,
+y un límite de 100 es impuesto.
+.TP
+.B \-x, --pid-file=<path>
+Especificar un path alterno donde dnsmasq debe guardar su PID.
+Normalmente es /var/run/dnsmasq.pid.
+.TP
+.B \-u, --user=<usuario>
+Especificar el userid al cual dnsmasq debe cambiarse despues de iniciar.
+Dnsmasq normalmente debe ser iniciado como root, pero soltará los
+privilegios root despues del inicio, cambiando a otro usuario.
+Normalmente este usuario es "nobody", pero eso se puede cambiar
+con esta opción.
+.TP
+.B \-g, --group=<grupo> 
+Especificar el grupo como el cual dnsmasq correrá. El predeterminado
+es "dip", si está disponible, para facilitar el acceso a
+/etc/ppp/resolv.conf el cuál normálmente no es globalmente leíble.
+.TP
+.B \-v, --version
+Mostrar el número de versión.
+.TP
+.B \-p, --port=<puerto>
+Escuchar en el puerto <puerto> en vez del puerto estándar DNS (53).
+Fijar esto a cero deshabilita completamente la función DNS, dejando
+solo DHCP y/o TFTP.
+.TP
+.B \-P, --edns-packet-max=<tamaño>
+Especificar el paquete UDP EDNS.0 más grande que es soportado por
+el reenviador DNS. Por predeterminado es 4096, lo cual es el
+tamaño recomendado en RFC5625.
+.TP
+.B \-Q, --query-port=<puerto>
+Enviar búsquedas outbound desde, y escuchar por respuestas en,
+el puerto UDP <puerto> en vez de usar puertos aleatorios. Nótese
+que usar esta opción hace que dnsmasq sea menos seguro contra
+ataques de spoofing DNS, pero puede ser más rápido y usar menos
+recursos.
+Fijar esta opción a zero hace que dnsmasq use un solo puerto,
+asignado por el sistema operativo (esto era el comportamiento
+predeterminado en versiones anteriores a 2.43).
+.TP
+.B --min-port=<puerto>
+No usar puertos menores a <puerto> como remitentes para búsquedas
+DNS outbound. Dnsmasq escoje puertos aleatorios como remitentes
+para búsquedas DNS outbound. Cuando esta opción es brindada, los
+puertos usados siempre serán mayores que el especificado. Esto es
+útil para sistemas detras de firewalls.
+.TP
+.B \-i, --interface=<nombre de interface>
+Escuchar solo en las interfaces especificadas. Dnsmasq automáticamente
+agrega la interface loopback a la lista de interfaces para usar cuando
+la opción
+.B \--interface
+es usada. Si ninguna opción
+.B \--interface
+o
+.B \--listen-address
+es brindada, dnsmasq escucha en todas las interfaces disponibles excepto
+cualquiera fijada con opciones
+.B \--except-interface
+Interfaces IP alias (por ejemplo, "eth1:0") no pueden ser utilizadas con
+.B --interface
+o
+.B --except-interface
+, usar --listen-address en vez.
+.TP
+.B \-I, --except-interface=<nombre de interface>
+No escuchar en la interface especificada. Nótese que el orden de
+las opciones
+.B \--listen-address
+.B --interface
+y
+.B --except-interface
+no importa y las opciones
+.B --except-interface
+siempre invalidan a las otras.
+.TP 
+.B \-2, --no-dhcp-interface=<nombre de interface>
+No proveer DHCP ni TFTP en la interface especificada, pero sí
+proveer servicio DNS.
+.TP
+.B \-a, --listen-address=<dirección IP>
+Escuchar en la(s) dirección(es) IP especificada(s). Las opciones
+.B \--interface
+y
+.B \--listen-address
+ambas pueden ser brindadas, y en tal caso el juego de ambas
+direcciones IP y interfaces es usada. Nótese que si ninguna opción
+.B \--interface
+es brindada, pero sí se brinda la opción
+.B \--listen-address
+, entonces dnsmasq no escuchará automáticamente en la interface
+loopback. Para obtener esto, su dirección IP, 127.0.0.1, debe ser
+explícitamente brindada como una opción
+.B \--listen-address
+.TP
+.B \-z, --bind-interfaces
+En sistemas que inluyen el soporte, dnsmasq acopla la dirección
+de comodín, aún cuando está escuchando solamente en algunas
+interfaces. Entonces descarta búsquedas a las cuales no debe
+responder. Esto tiene la ventaja de funcionar aún cuando
+interfaces van y vienen y cambian direcciones. Esta opción forza
+a dnsmasq a acoplarse realmente solo a las interfaces en
+las cuales está escuchando. Casi la Ãºnica vez que esto es Ãºtil
+es cuando se está corriendo otro servidor DNS (o otra instancia
+de dnsmasq) en la misma máquina. Fijar esta opción tambien
+habilita multiples instancias de dnsmasq, las cuales proveen
+servicio DHCP en la misma máquina.
+.TP
+.B \-y, --localise-queries
+Retornar respuestas a búsquedas DNS desde /etc/hosts las cuales dependen
+de la interface donde entró la búsqueda. Si un nombre en /etc/hosts tiene
+mas de una dirección asociada con el, y por lo menos una de esas direcciones
+está en la misma subred de la interface donde fue enviada, entónces
+retornar solo las direcciones en esa subred. Esto permite a un servidor
+tener direcciones múltiples en /etc/hosts correspondientes a cada una de
+sus interfaces y cada host recibirá la respuesta adecuada
+dependiendo de cual red tengan adjunta. Por el momento, esta facilidad
+está limitada a IPv4.
+.TP
+.B \-b, --bogus-priv
+Búsquedas privadas reversas raras. Toda búsqueda reversa para rangos de IP
+privados (192.168.x.x, etc.) los cuales no se encuentren en
+/etc/hosts o en el archivo de arriendos DHCP es respondida con
+"dominio no existente" en vez de ser reenviada upstream.
+.TP
+.B \-V, --alias=[<IP viejo>]|[<IP inicio>-<IP final>],<IP nuevo>[,<máscara>]
+Modificar direcciones IPv4 retornadas desde servidores DNS upstream;
+<IP viejo> es remplazado con <IP nuevo>. Si la máscara opcional
+es brindada, entonces cualquier dirección que coincida con el
+<IP viejo> enmascarado será re-escrita. Así que, por ejemplo,
+.B --alias=1.2.3.0,6.7.8.0,255.255.255.0 trazará 1.2.3.56 a 6.7.8.56
+y 1.2.3.67 a 6.7.8.67. Esto es lo que
+ruteadores Cisco PIX llaman "DNS doctoring". Si la dirección vieja es
+brindada como un rango, entonces solo direcciones en ese rango, y no
+la subred entera, son re-escritas. De tal manera que
+.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
+relaciona 192.168.0.10->192.168.0.40 a 10.0.0.10->10.0.0.40
+.TP
+.B \-B, --bogus-nxdomain=<dirección IP>
+Transformar respuestas que contienen la dirección IP brindada a
+respuestas tipo "Dominio no existe". La intención de esto es actuar
+en contra de una movida desviada hecha por Verisign en septiembre
+del 2003, cuando comenzaron a retornar la dirección de un servidor
+de publicidad en respuesta a búsquedas por nombres no registrados,
+en vez de la correcta respuesta NXDOMAIN. Esta opción le dice a dnsmasq
+que debe forjear la respuesta correcta cuando ve este comportamiento.
+Para septiembre 2003 la dirección IP siendo retornada por Verisign
+es 64.94.110.11
+.TP
+.B \-f, --filterwin2k
+Algunas versiones de Windows hacen búsquedas DNS periódicas las cuales no
+reciben respuestas sensibles desde el DNS público y pueden causar problemas
+activando enlaces marcación-en-demanda. Esta opción filtra dichas búsquedas.
+Las búsquedas filtradas son para registros tipo SOA y SRV, al igual que
+tipo ANY donde el nombre pedido contiene _, para atrapar búsquedas LDAP.
+.TP
+.B \-r, --resolv-file=<archivo>
+Leer las direcciones IP de servidores DNS upstream desde <archivo>,
+en vez de /etc/resolv.conf. Para el formato de este archivo, ver
+.BR resolv.conf (5)
+Las Ãºnicas líneas relevantes a dnsmasq son las de servidores DNS. A
+dnsmasq se le puede decir que revise más de un archivo resolv.conf,
+el primer archivo especificado remplaza al predeterminado, y los
+subsiguientes son agregados a la lista. Esto es solo
+permitido al hacer polling; el archivo con la actual fecha
+de modificación más nueva es el que será usado.
+.TP
+.B \-R, --no-resolv
+No leer /etc/resolv.conf. Obtener los servidores DNS upstream solo
+desde la línea de comandos o desde el archivo de configuración de
+dnsmasq.
+.TP
+.B \-1, --enable-dbus
+Permitir que la configuración de dnsmasq sea actualizada vía llamadas
+de método DBus. La configuración que puede ser cambiada es servidores
+DNS upstream (y dominios correspondientes) y limpieza de caché. Esta
+opción requiere que dnsmasq haya sido compilado con soporte para DBus.
+.TP 
+.B \-o, --strict-order
+Por predeterminado, dnsmasq enviará búsquedas a cualquiera de los
+servidores upstream que conoce, y trata de favorecer servidores los
+cuales sabe que están activos. Fijar esta opción forza a dnsmasq a
+probar cada búsqueda con cada servidor estrictamente en el orden
+que aparecen en /etc/resolv.conf
+.TP
+.B --all-servers
+Por predeterminado, cuando dnsmasq tiene más de un servidor upstream
+disponible, enviará búsquedas a solo un servidor. Fijar esta opción
+forza a dnsmasq a enviar todas las búsquedas a todos los servidores
+disponibles. La respuesta del servidor que responda primero será
+devuelta al solicitante original.
+.TP
+.B --stop-dns-rebind
+Denegar (y bitacorear) direcciones de servidores upstream que están
+dentro de rangos IP privados. Esto bloquea un ataque donde un navegador
+detrás de un firewall es usado para analizar máquinas en la red local.
+.TP
+.B --rebind-localhost-ok
+Eximir a 127.0.0.0/8 de verificaciones de rebinding. Este rango de
+direcciones es retornado por servidores de tiempo real tipo hoyo
+negro, así que bloquearlo puede deshabilitar estos servicios.
+.TP
+.B  --rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/]
+No detectar y bloquear dns-rebind en búsquedas a estos dominios. El
+argumento puede ser o un dominio sencillo, o múltiples dominios
+rodeados por '/', como el syntax de --server, por ejemplo
+.B  --rebind-domain-ok=/dominio1/dominio2/dominio3/
+.TP
+.B \-n, --no-poll
+No revisar periodicamente a /etc/resolv.conf en busca de cambios.
+.TP
+.B --clear-on-reload
+Cuando sea que /etc/resolv.conf es re-leida, liberar el caché DNS.
+Esto es Ãºtil cuando servidores DNS nuevos puedan tener datos diferentes
+a los contenidos en el caché.
+.TP
+.B \-D, --domain-needed
+Le dice a dnsmasq que no debe reenviar búsquedas para nombres sencillos,
+sin puntos o partes de dominios, a servidores upstream. Si el nombre
+no se conoce desde /etc/hosts o desde DHCP entonces una respuesta
+"no encontrado" es devuelta.
+.TP
+.B \-S, --local, --server=[/[<dominio>]/[dominio/]][<dirección IP>[#<puerto>][@<IP de remitente>|<interface>[#<puerto>]]
+Especificar la dirección IP de servidores upstream directamente. Fijar
+esta opción no suprime la lectura de /etc/resolv.conf, use -R para
+hacer eso. Si uno a más dominios opcionales son brindados, ese servidor
+es usado solo para esos dominios y las búsquedas son hechas usando
+el servidor especificado solamente. La intención de esto es para el
+uso con servidores DNS privados: si usted tiene un servidor DNS en su
+red el cual lidea con nombres de la forma
+xxx.internal.thekelleys.org.uk en 192.168.1.1 entonces brindar la
+opción
+.B -S /internal.thekelleys.org.uk/192.168.1.1
+enviará todas las búsquedas de máquinas internas a ese servidor DNS,
+todas las demás búsquedas serán enviadas a los servidores en
+/etc/resolv.conf. Una especificación de dominio en blanco,
+.B //
+tiene el significado especial de "solo nombres no calificados", o
+sea nombres sin ningún punto en ellos. Un puerto no-estándar puede
+ser especificado como parte de la dirección IP usando el caracter
+#. Más de una opción -S es permitida, con partes de dominio o
+dirección IP repetidas como sea necesario.
+
+Dominios más específicos toman precedencia sobre los menos específicos,
+así que:
+.B --server=/google.com/1.2.3.4
+.B --server=/www.google.com/2.3.4.5
+enviará búsquedas por *.google.com hacia 1.2.3.4, excepto
+*www.google.com, el cual irá a 2.3.4.5.
+
+La dirección especial de servidor '#' significa "usar los servidores
+estándares", así que
+.B --server=/google.com/1.2.3.4
+.B --server=/www.google.com/#
+enviará búsquedas por *.google.com hacia 1.2.3.4, excepto
+*www.google.com, el cual será reenviado de manera usual.
+
+También se permite una opción -S la cual brinda un dominio pero
+ninguna dirección IP; esto le dice a dnsmasq que un dominio es local
+y puede responder a búsquedas desde /etc/hosts o DHCP pero nunca
+deberá reenviar búsquedas en ese dominio a ningún servidor upstream.
+.B local
+es un sinónimo de
+.B server
+para hacer los archivos de configuración mas claros en este caso.
+
+El string opcional despues del carácter @ le dice a dnsmasq como fijar
+el remitente de las búsquedas hacia este servidor DNS. Debe ser una
+dirección IP, la cual debe ser perteneciente a la máquina en la cual
+corre dnsmasq, de forma contraria esta línea de servidor será bitacoreada
+y después ignorada, o un nombre de interface. Si un nombre de interface
+es brindado, entonces búsquedas hacia el servidor serán forzadas vía esa
+interface; si una dirección IP es brindada, entonces la dirección de
+remitente de las búsquedas será fijada a esa dirección.
+La etiqueta query-port es ignorada para cualquier servidores que tengan
+una dirección remitente especificada, pero el puerto puede ser
+especificado directamente como parte de la dirección remitente. Forzar
+búsquedas a una interface no está implementado en todas las plataformas
+soportadas por dnsmasq.
+.TP
+.B \-A, --address=/<dominio>/[dominio/]<dirección IP>
+Especificar una dirección IP para retornar por cualquier host en
+los dominios brindados. Búsquedas en estos dominios nunca son
+reenviadas, y siempre son respondidas con la dirección IP
+especificada, la cual puede ser IPv4 o IPv6. Para brindar ambas
+direcciones IPv4 y IPv6 para un dominio, usar opciones -A repetidas.
+Nótese que /etc/hosts y arriendos DHCP invalidan esto para nombres
+individuales. Un uso común para esto es redireccionar el dominio
+doubleclick.net entero a algún servidor web local amigable para
+evitar banners de publicidad. La especificación funciona de la misma
+forma que con --server, con la facilidad adicional que /#/ coincide
+con cualquier dominio. De tal forma, --address=/#/1.2.3.4 siempre
+retornará 1.2.3.4 para cualquier búsqueda no respondida desde
+/etc/hosts o DHCP y que no haya sido enviada a un servidor DNS
+upstream por una directiva --server mas especifica.
+.TP
+.B \-m, --mx-host=<nombre mx>[[,<nombre de host>],<preferencia>]
+Retornar un record llamado <mx name> apuntando hacia el nombre de
+host brindado (opcionalmente), o el host especificado en la opción
+--mx-target, o si esa opción no es brindada, el host en el cual
+dnsmasq está corriendo. El predeterminado es Ãºtil para redireccionar
+correo de sistemas en la red local hacia un servidor central. La
+opción de preferencia es opcional, y su predeterminado es 1 si no
+es brindada. Más de un record MX puede ser brindado para un host.
+.TP 
+.B \-t, --mx-target=<nombre de host>
+Especificar el target predeterminado para el record MX devuelto
+por dnsmasq. Ver --mx-host. Si --mx-target es brindado, pero no
+--mx-host, entonces dnsmasq devuelve un record MX conteniendo
+el target MX para búsquedas MX en el nombre de host de la máquina donde
+dnsmasq está corriendo.
+.TP
+.B \-e, --selfmx
+Retornar un record MX apuntándose a sí mismo para cada máquina local.
+Máquinas locales son aquellas en /etc/hosts o con arriendos DHCP.
+.TP 
+.B \-L, --localmx
+Retornar un record MX apuntando al host brindado por mx-target (o
+la máquina donde dnsmasq está corriendo) para cada máquina local.
+Máquinas locales son aquellas en /etc/hosts o con arriendos DHCP.
+.TP
+.B \-W, --srv-host=<_servicio>.<_prot>.[<dominio>],[<target>[,<puerto>[,<prioridad>[,<peso>]]]]
+Retornar un record DNS SRV. Ver RFC2782 para detalles. Si no es
+brindada, el dominio se predetermina a el brindado por
+.B --domain.
+El predeterminado para el dominio target está vacío, el predeterminado
+para puerto es uno, y los predeterminados para peso y prioridad son cero.
+Tener cuidado al transponer data desde archivos de zona BIND: los
+números de puerto, peso, y prioridad están en un orden diferente. Más
+de un record SRV para un servicio/dominio es permitido, todos los que
+coincidan son retornados.
+.TP
+.B \-Y, --txt-record=<nombre>[[,<texto>],<texto>]
+Retornar un récord DNS TXT. El valor del récord TXT es una serie de
+strings, así que cualquier número puede ser incluido, dividido por
+comas.
+.TP
+.B --ptr-record=<nombre>[,<target>]
+Retornar un récord DNS PTR.
+.TP
+.B --naptr-record=<nombre>,<orden>,<preferencia>,<opciones>,<servicio>,<regexp>[,<remplazo>]
+Retornar un récord DNS NAPTR, como especificado en RFC3403.
+.TP
+.B --cname=<cname>,<target>
+Retornar un expediente CNAME que indica que <cname> es realmente <target>. Hay
+limitaciones significativas en el target. Debe ser un nombre DNS que le es conocido
+a dnsmasq desde /etc/hosts (o archivos hosts adicionales) o de DHCP. Si el target
+no satisface este criterio, el cname entero es ignorado. El cname debe ser Ãºnico,
+pero es permisible tener más de un cname indicando el mismo target.
+.TP
+.B --interface-name=<nombre>,<interface>
+Retornar un expediente DNS, asociando el nombre con la dirección primaria
+en la interface brindada. Esta opción especifica un expediente tipo A
+para el nombre brindado de la misma forma que una línea de /etc/hosts,
+excepto que la dirección no es constante y es en vez tomada de la
+interface brindada. Si la interface está deshabilitada, nó configurada,
+o nó existente, un récord vacío es devuelto. El récord PTR relevante
+tambien es creado, trazando la dirección de la interface a el nombre.
+Más de un nombre puede ser asociado con una dirección de interface,
+repitiendo la opción. En tal caso, la primera instancia es usada para
+la traza reversa dirección-a-nombre.
+.TP
+.B \-c, --cache-size=<tamaño de caché>
+Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres.
+Fijar el tamaño a cero deshabilita el caché.
+.TP
+.B \-N, --no-negcache
+Deshabilitar caché negativo. El caché negativo le permite a dnsmasq
+recordar resultados tipo "dominio no existe" desde servidores DNS
+upstream y responder búsquedas idénticas sin reenviarlas nuevamente.
+.TP
+.B \-0, --dns-forward-max=<búsquedas>
+Fijar el número máximo de búsquedas DNS simultáneas. El valor
+predeterminado es 150, lo cuál debería estar bien para la mayoría
+de casos. La Ãºnica situación conocida donde esto debe ser incrementado
+es al usar resolvedores de bitácoras de servidores web, los cuales pueden
+generar un número inmenso de búsquedas simultáneas.
+.TP
+.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<dirección-inicio>,<dirección-final>[,<netmask>[,<broadcast>]][,<tiempo de arriendo>]
+Habilitar el servidor DHCP. Direcciones serán distribuidas desde el
+rango <dirección-inicio> hasta <dirección-final> y desde direcciones definidas
+estáticamente en opciones
+.B dhcp-host
+Si el tiempo de arriendo es especificado, entonces arriendos serán
+otorgados por esa cantidad de tiempo. El tiempo de arriendo es en
+segundos, o minutos (por ejemplo, 45m), u horas (por ejemplo, 1h), o
+"infinite". Si no es brindada, el tiempo de arriendo predeterminado
+es de una hora. El tiempo de arriendo mínimo es de dos minutos.
+Esta opción puede ser repetida, con diferentes
+direcciones, para habilitar servicio DHCP en más de una red. Para
+redes conectadas diréctamente (en otras palabras, redes en las
+cuales la máquina corriendo dnsmasq tiene una interface) la
+máscara de subred es opcional. Pero, es requerida para redes que
+reciben servicio DHCP vía un agente de relay. La dirección de
+broadcast siempre es opcional. Siempre se permite tener más de
+un rango dhcp (dhcp-range) en una subred.
+
+El parámetro opcional
+.B set:<tag>
+fija una etiqueta alfanumérica la cual marca esta red de
+tal forma que opciones dhcp puedan ser especificadas en base a cada red.
+Cuando es prefijada con 'tag:' en vez, entonces el significado cambia
+de "fijar etiqueta" a "coincidir con etiqueta". Solo una etiqueta puede
+ser fijada, pero más de una puede ser revisada por coincidencias. La
+dirección final puede ser remplazada por la palabra clave
+.B static
+la cual le dice a dnsmasq que debe habilitar DHCP para la red
+especificada, pero no alocar dinámicamente direcciones IP:
+Solo hosts que tienen direcciones estáticas brindadas vía
+.B dhcp-host
+o desde /etc/ethers serán servidas. La dirección final puede ser
+remplazada por la palabra clave
+.B proxy
+caso en el cual dnsmasq proveerá proxy-DHCP en la subred especificada. (Ver
+.B pxe-prompt
+y
+.B pxe-service
+para detalles.)
+
+La sección interface:<interface name> no es normalmente usada. Ver la
+sección NOTAS para detalles sobre esto.
+.TP
+.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<tiempo_de_arriendo>][,ignorar]
+Especificar parámetros por host para el servidor DHCP. Esto permite
+que una máquina con una dirección de hardware particular sea siempre
+alocada el mismo nombre de host, dirección IP, y tiempo de arriendo.
+Un nombre de host especificado de esta manera toma presedencia
+sobre cualquiera suministrado por el cliente DHCP en la máquina.
+También se permite omitir la direccion de hardware y incluir el
+nombre de host; en tal caso la dirección IP y los tiempos de arriendo
+serán aplicables a cualquier máquina que reclame ese nombre.
+Por ejemplo:
+.B --dhcp-host=00:20:e0:3b:13:af,wap,infinite
+le dice a dnsmasq que debe darle a la máquina con dirección
+ethernet 00:20:e0:3b:13:af el nombre wap, y un arriendo DHCP infinito.
+.B --dhcp-host=lap,192.168.0.199
+le dice a dnsmasq que siempre debe alocarle a la maquina lap
+la dirección IP 192.168.0.199.
+
+Direcciones alocadas de esta manera no tienen que estar dentro
+del rango dado con la opción --dhcp-range, pero deben estar en la subred
+de un rango DHCP (dhcp-range) válido. Para subredes que no necesitan
+una collección de direcciones dinamicamente alocadas, usar la palabra
+clave "static" in la declaración dhcp-range.
+
+Es permitido usar identificadores de cliente en vez de direcciones de
+hardware para identificar hosts prefijando 'id:'. O sea que:
+.B --dhcp-host=id:01:02:03:04,.....
+se refiere al host con identificador de cliente 01:02:03:04.
+También se permite especificar el ID de cliente como texto, así:
+.B --dhcp-host=id:iddeclientecomotexto,.....
+
+La opción especial id:* significa "ignorar cualquier ID de cliente
+y usar solamente direcciones MAC." Esto es Ãºtil cuando un cliente
+presenta un ID de cliente algunas veces pero otras no.
+
+Si un nombre aparece en /etc/hosts, la dirección asociada puede
+ser alocada a un arriendo DHCP, pero solo si existe una opción
+.B --dhcp-host
+la cual especifica el nombre también. Solo un hostname puede ser
+brindado en una opción
+.B dhcp-host
+pero aliases son posibles por medio del uso de CNAMEs. (Ver
+.B --cname
+).
+
+La palabra clave "ignore"
+le dice a dnsmasq que no debe ofrecer jamás un arriendo DHCP a
+una máquina. La máquina puede ser especificada por dirección de
+hardware, ID de cliente, o nombre de host, por ejemplo:
+.B --dhcp-host=00:20:e0:3b:13:af,ignore
+Esto es Ãºtil cuando hay otro servidor DHCP en la red que debe ser
+usado por algúnas máquinas.
+
+El set:<tag> fija la etiqueta cuando sea que
+esta directiva dhcp-host está en uso. Esto puede ser usado para
+enviar selectivamente opciones DHCP a este host. Más de una etiqueta
+puede ser fijada en una directiva dhcp-host (pero no en otros lugares
+donde "set:<tag>" es permitido). Cuando un host coincide con 
+cualquier directiva dhcp-host (o una implicada por
+/etc/ethers) entonces la etiqueta especial "known" es
+fijada. Esto permite que dnsmasq sea configurado para ignorar
+pedidos desde máquinas desconocidas usando
+.B --dhcp-ignore=tag:!known
+Direcciones ethernet (pero no client-ids) pueden tener bytes
+comodínes, así que por ejemplo
+.B --dhcp-host=00:20:e0:3b:13:*,ignore
+causará que dnsmasq ignore un rango de direcciones ethernet. Nótese
+que el "*" necesitará ser escapado o escrito entre comillas en la
+línea de comandos, pero no en el archivo de configuración.
+
+Direcciones de hardware normalmente coinciden con cualquier
+tipo de red (ARP), pero es posible restringirlas a un tipo ARP
+singular precediendolo con el tipo ARP (en HEX) y "-". Así que
+.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4
+solo coincidiría con una dirección de hardware Token-Ring, dado que
+el tipo ARP para Token-Ring es 6.
+
+Como caso especial, es posible incluir más de una dirección de
+hardware. Ejemplo:
+.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2
+Esto permite que una dirección IP sea asociada con
+direcciones de hardware múltiples, y le brinda a dnsmasq permiso
+para abandonar un arriendo DHCP a una de las direcciones de hardware
+cuando otra pide un arriendo. Nótese que esto es algo peligroso,
+sólo funcionará dependiblemente si una de las direcciones de hardware
+está activa en cualquier momento y dnsmasq no tiene forma de enforzar
+esto. Pero es Ãºtil, por ejemplo, para alocar una dirección IP estable
+a una laptop que tiene interface alámbrica e inalámbrica.
+.TP
+.B --dhcp-hostsfile=<archivo>
+Leer información host DHCP desde el archivo especificado. El archivo contiene información de un host por línea. El formato de una línea es igual que texto hacia la derecha de '=' en --dhcp-host. La ventaja de almacenar información host DHCP en este archivo es que puede ser cambiada sin tener que reiniciar dnsmasq. El archivo será re-leído cuando dnsmasq recibe un SIGHUP.
+.TP
+.B --dhcp-optsfile=<archivo>
+Leer información sobre opciones DHCP desde el archivo especificado. La
+ventaja de usar esta opción es la misma que con --dhcp-hostsfile: el
+archivo dhcp-optsfile será re-leído cuando dnsmasq recibe un SIGHUP.
+Nótese que es posible colocar la información mediante
+.B --dhcp-boot
+como opciones DHCP, usando los nombres de opción bootfile-name,
+server-ip-address, y tftp-server. Esto permite que sean incluidas en
+un archivo dhcp-optsfile.
+.TP
+.B \-Z, --read-ethers
+Leer /etc/ethers en busca de información sobre hosts para el servidor
+DHCP. El formato de /etc/ethers es una dirección de hardware, seguida
+por ya sea un nombre de host o una dirección IP. Al ser leidas por
+dnsmasq, estas líneas tienen exáctamente el mismo efecto que opciones
+.B --dhcp-host
+que contienen la misma información. /etc/ethers es re-leída cuando
+dnsmasq recibe un SIGHUP.
+.TP
+.B \-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]]
+Especificar opciones diferentes o extra a clientes DHCP. Por
+predeterminado, dnsmasq envía algunas opciones estándar a clientes
+DHCP. La máscara de subred y dirección broadcast son fijadas igual
+a las del host que corre dnsmasq, y el servidor DNS y ruteador
+a la dirección de la máquina que corre dnsmasq. Si la opción de
+nombre de dominio ha sido fijada, es enviada. Esta opción permite
+que esos predeterminados sean sobrescritos, o que sean especificadas
+otras opciones. La opción a ser enviada puede ser brindada como un
+número decimal o como "option:<option-name>". Los números de opción
+están especificados en RFC2132 y RFCs subsiguientes. El juego de
+option-names conocido por dnsmasq puede ser descubierto ejecutando
+"dnsmasq --help dhcp". Por ejemplo, para fijar la ruta predeterminada a
+192.168.4.4, hágase un
+.B --dhcp-option=3,192.168.4.4
+o
+.B --dhcp-option=option:router, 192.168.4.4
+y para fijar la dirección de servidor de tiempo a 192.168.0.4,
+hágase un
+.B --dhcp-option=42,192.168.0.4
+o
+.B --dhcp-option=option:ntp-server, 192.168.0.4
+La dirección especial 0.0.0.0 es entendida que significa "la
+dirección de la máquina que corre dnsmasq". Tipos de data permitidos
+son direcciones IP de cuatro segmentos, un número decimal, dígitos hex
+separados por colones, y un string de texto. Si las etiquetas
+opcionales son brindadas, entonces esta opción es solo enviada cuando
+todas las etiquetas coinciden.
+
+Procesamiento especial es llevado a cabo en un argumento de texto para
+la opción 119, en conforme con RFC3397. Direcciones IP textuales o de
+cuatro segmentos como argumentos a la opción 120 son manejados mediante
+RFC3361. Direcciones IP de cuatro segmentos que son seguidas por un diagonal
+(slash) y después una máscara son codificados mediante RFC3442.
+
+Tener cuidado: niguna verificación es hecha sobre si el número de tipo
+correcto es enviado, y es muy posible persuadir a dnsmasq para que
+genere paquetes DHCP ilegales mediante uso inadecuado de esta opción.
+Cuando el valor es un número decimal, dnsmasq debe determinar qué tan
+grande es el objeto de data. Esto es hecho mediante una examinación del
+número de opción, y/o el valor, pero puede ser invalidado agregándole
+una opción de una sola letra de esta forma: b = un byte, s = dos bytes,
+i = cuatro bytes. Esto es principalmente Ãºtil con opciones encapsuladas
+tipo vendedor (ver abajo) donde dnsmasq no puede determinar el tamaño
+de data usando el número de opción. Data de opción la cual consiste
+solo de puntos y dígitos será interpretada por dnsmasq como una
+dirección IP, y será insertada dentro de una opción de esa manera.
+Para forzar un string literal, usar comillas. Por ejemplo, cuando se
+usa la opción 66 para enviar una IP literal como un nombre de servidor
+TFTP, es necesario hacer:
+.B --dhcp-option=66,"1.2.3.4"
+
+Opciones encapsuladas vendor-class también pueden ser especificadas usando
+--dhcp-option: por ejemplo
+.B --dhcp-option=vendor:PXEClient,1,0.0.0.0
+envía la opción específica de clase de vendedor "mftp-address=0.0.0.0" a
+cualquier cliente cuyo vendor-class
+coincida con "PXEClient". El revisado de coincidencias vendor-class está
+basado en substrings (ver --dhcp-vendorclass para detalles). Si una opción
+vendor-class (número 60) es enviada por dnsmasq, entonces es usada para
+seleccionar opciones encapsuladas en preferencia sobre cualquiera enviada
+por el cliente. Es posible omitir el vendorclass completamente;
+.B --dhcp-option=vendor:,1,0.0.0.0
+caso en el cuál la opción encapsulada siempre es enviada.
+Opciones pueden ser encapsuladas dentro de otras opciones, por ejemplo:
+.B --dhcp-option=encap:175, 190, "iscsi-client0"
+enviará opción 175, dentro de la cual está opción 190. Si múltiples
+opciones son brindadas que están encapsuladas con el mismo número de
+opción entonces serán correctamente combinadas en una opción encapsulada.
+encap: y vendor: no pueden ser fijadas ambas dentro de la misma opción dhcp-option.
+
+La variante final en opciones encapsuladas es "Vendor-Identifying Vendor Options"
+como especificado en RFC3925. Estos son denotados así:
+.B --dhcp-option=rfc3925-encap:2, 10, "text"
+El número en la sección rfc3925-encap: es el número enterprise usado
+para identificar esta opción.
+
+La dirección 0.0.0.0 no es tratada de forma especial en opciones encapsuladas.
+.TP
+.B --dhcp-option-force=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]]
+Esto funciona exáctamente de la misma forma que
+.B --dhcp-option
+excepto que la opción siempre será enviada, aún si el cliente no la pide en
+la lista de pedido de parámetros. Esto se necesita aveces, por ejemplo cuando
+enviando opciones a PXELinux.
+.TP
+.B --dhcp-no-override
+Deshabilitar la reutilización de los campos DHCP de nombre de servidor y
+archivo como espacio para opciones extra. Si puede, dnsmasq mueve la información
+del servidor boot y del nombre de archivo (de dhcp-boot) de sus campos dedicados
+hacia opciones DHCP. Esto crea espacio extra en el paquete DHCP para opciones,
+pero puede raramente confundir clientes viejos o defectuosos. Esta opción forza
+comportamiento "simple y sencillo" para prevenir problemas en tales casos.
+.TP
+.B \-U, --dhcp-vendorclass=set:<tag>,<vendor-class>
+Trazar desde un string vendor-class a una etiqueta. La mayoría de los
+clientes DHCP proveen una "vendor class" la cual representa, en cierto
+sentido, el tipo de host. Esta opción traza clases de vendedor a network
+ids, de tal forma que opciones DHCP pueden ser selectivamente entregadas
+a diferentes clases de hosts. Por ejemplo
+.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
+peritiría que opciones sean fijadas solo para impresoras HP así:
+.B --dhcp-option=tag:printers,3,192.168.4.4
+El string vendor-class es coordinado con el vendor-class proveido por
+el cliente, para permitir coincidencias borrosas. El prefijo set: es
+opcional, pero permitido por razones de consistencia.
+.TP
+.B \-j, --dhcp-userclass=set:<tag>,<user-class>
+Trazar desde un string user-class a una etiqueta (con coordinación
+substring, como con vendor-class). La mayoría de los clientes DHCP
+proveen un "user class" el cual es configurable. Esta opción traza
+clases user a network ids, de tal manera que opciones DHCP puedan
+ser selectivamente enviadas a diferentes tipos de hosts. Es posible,
+por ejemplo, usar esto para especificar una impresora diferente para
+hosts en la clase "cuentas" que para los de la clase "ingenieria".
+.TP
+.B \-4, --dhcp-mac=set:<tag>,<MAC address>
+Trazar desde una dirección MAC a una etiqueta. La dirección MAC
+puede incluir comodínes. Por ejemplo:
+.B --dhcp-mac=set:3com,01:34:23:*:*:*
+fijaría el tag "3com" a cualquier host el cual su MAC coincida con
+el patrón.
+.TP
+.B --dhcp-circuitid=<network-id>,<circuit-id>, --dhcp-remoteid=<network-id>,<remote-id>
+Trazar de opciones agente de relay RFC3046 a etiquetas. Estos
+datos pueden ser proveídos por agentes de relay DHCP. El circuit-id o
+remote-id es normlamente brindado como hex separado por doblepuntos, pero
+también se permite un string simple. Si se obtiene una coincidencia exacta
+entre el circuit o agent ID y uno proveído por un agente de relay,
+la etiqueta es fijada.
+.TP
+.B --dhcp-subscrid=set:<tag>,<subscriber-id>
+Trazar de opciones relay subscriber-id RFC3993 a etiquetas.
+.TP
+.B --dhcp-proxy[=<ip addr>]......
+Un agente de relay normal es usado solamente para reenviar las partes
+iniciales de una interacción DHCP con el servidor DHCP. Una vez que
+un cliente es configurado, se comunica diectamente con el servidor. Esto
+es indeseable si el agente de relay está agregando información extra a
+los paquetes DHCP, tal como usado por
+.B dhcp-circuitid
+y
+.B dhcp-remoteid.
+Una implementación relay completa puede usar la opción serverid-override
+RFC 5107 para obligar al servidor DHCP a usar el relay como un proxy
+completo, con todos los paquetes pasando a travez de el. Esta opción
+provee una manera alternativa de hacer la misma cosa, para relays que
+no tienen soporte RFC 5107. Brindada por si sola, manipula el server-id
+para todas las interacciones via relays. Si una lista de IPs es brindada,
+solo interacciones via relays en esas direcciones son afectadas.
+.TP
+.B --dhcp-match=set:<tag>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>]
+Sin un valor, fijar la etiqueta si el cliente envía una opción
+DHCP del número o valor brindado. Cuando un valor es brindado, fijar la
+etiqueta solo si la opción es enviada y coincide con el valor. El valor puede
+ser de la forma "01:ff:*:02", caso en el cual el valor debe coincidir (aparte
+de los comodines) pero la opción enviada puede tener data que no coincide despues
+del final del valor. El valor también puede ser de la misma forma que
+.B dhcp-option
+caso en el cual la opción enviada es tratada como un array, y un elemento debe
+coincidir, así que
+
+--dhcp-match=set:efi-ia32,option:client-arch,6
+
+fijará la etiqueta a "efi-ia32" si el número 6 aparece en la lista de
+architecturas enviada por los clientes en opción 93. (Ver RFC 4578 para
+detalles.) Si el valor es un string, coincidencia substring es usada.
+
+La forma especial con vi-encap:<enterpise number> busca coincidencia con
+clases de vendedor identificadoras para el enterprise especificado. Por
+favor ver RFC 3925 para mas detalles sobre estas bestias raras e interesantes.
+.TP
+.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
+Llevar a cabo operaciones boolean en etiquetas. Cualquier etiqueta
+que aparece como set:<tag> es fijada si todas las etiquetas que aparecen
+como tag:<tag> estan fijadas, (o desfijadas cuando tag:!<tag> es
+usado). Si ningún tag:<tag> aparece, etiquetas set:<tag> son fijadas
+incondicionalmente. Cualquier cantidad de formas set: y tag:
+pueden aparecer, en cualquier orden. Líneas tag-if son ejecutadas
+en orden, así que si la etiqueta en tag:<tag> es una etiqueta fijada
+por otra
+.B tag-if,
+la línea que fija la etiqueta debe preceder a la que comprueba.
+.TP
+.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
+Cuando todoas las etiquetas brindadas aparecen en el juego de etiquetas
+ignorar el host y no brindarle un arriendo DHCP.
+.TP
+.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]]
+Cuando todos las etiquetas brindadas aparecen en el juego de etiquetas, ignorar cualquier nombre de host proveido por el host. Nótese que,
+a diferencia de dhcp-ignore, es permisible no brindar ninguna etiqueta,
+y en tal caso nombres de host proveidos por clientes DHCP siempre son
+ignorados, y hosts DHCP son agregados al DNS usando solo la configuración
+dhcp-host en dnsmasq y el contenido de /etc/hosts y /etc/ethers.
+.TP
+.B --dhcp-generate-names=tag:<tag>[,tag:<tag>]
+Generar un nombre para clientes DHCP que de otra forma no tienen uno,
+usando la dirección MAC expresada en hex, separada por guiones. Nótese
+que si un host provee un nombre, será usado preferiblemente sobre este,
+a menos que
+.B --dhcp-ignore-names
+esté fijado.
+.TP
+.B --dhcp-broadcast[=tag:<tag>[,tag:<tag>]]
+Cuando todas las etiquetas aparecen en el juego de etiquetas, siempre
+usar broadcast para comunicar con el host cuando no está configurado.
+Es permisible omitir las etiquetas, caso en el cual esto es
+incondicional. La mayoría de clientes DHCP que necesitan
+respuestas broadcast fijan una opción en sus pedidos para que esto pase automaticamente, algunos clientes BOOTP viejos no lo hacen.
+.TP
+.B \-M, --dhcp-boot=[tag:<tag>,]<filename>,[<servername>[,<server address>]]
+Fijar opciones BOOTP que han de ser devueltas por el servidor DHCP. Nombre
+y dirección de servidor son opcionales: si no son brindadas, el nombre es
+dejado en blanco, y la dirección es fijada a la de la máquina que corre
+dnsmasq. Si dnsmasq está brindando servicio TFTP (ver
+.B --enable-tftp
+) entonces solo el nombre de archivo es requirido aquí para habilitar
+el inicio atravéz de una red. Si las opcionales etiquetas son brindadas,
+ellas deberán coincidir para que esta configuración sea enviada. Nótese
+que network-ids están prefijadas con "net:" para distinguirlas.
+.TP
+.B --pxe-service=[tag:<tag>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>]
+La mayoría de usos para boot-ROMS PXE simplemente permiten al sistema PXE
+obtener una dirección IP y entonces bajar el archivo especificado por
+.B dhcp-boot
+y ejecutarlo. Sin embargo, el sistema PXE es capaz de llevar
+a cabo funciones más complejas cuando están soportadas por un
+servidor DHCP adecuado.
+
+Esto especifica una opción boot que puede aparecer en un menú de boot
+PXE. <CSA> es tipo de sistema de cliente, solo servicios del tipo correcto
+aparecerán en un menú. Los tipos conocidos son x86PC, PC98, IA64_EFI,
+Alpha, Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI y X86-64_EFI;
+un número entero puede ser utilizado para otros tipos. El parámetro después
+del texto de menú puede ser un nombre de archivo, caso en el cuál dnsmasq
+actúa como un servidor boot y le ordena al cliente PXE bajar el archivo
+vía TFTP, ya sea de sí mismo (
+.B enable-tftp
+debe estar fijado para que esto funcione) o desde otro servidor TFTP si la
+dirección IP final es brindada.
+Nótese que el sufijo "layer" (normalmente ".0") es brindado por PXE, y
+no debe ser agregado al nombre base. Si un número entero es brindado en vez
+de un nombre base, entonces el cliente PXE buscará un servicio boot adecuado
+para ese tipo de red. Esta búsqueda puede ser hecha mediante broadcast,
+o directamente a un servidor si la dirección IP es brindada. Si ningún tipo
+de servicio boot o nombre de archivo es brindado (o un tipo de servicio boot
+de 0 es especificado), entonces la opción de menú abortará el proceso net boot
+y continuará desde el medio local.
+.TP
+.B --pxe-prompt=[tag:<tag>,]<prompt>[,<timeout>]
+Fijar esto hace que un aviso sea expuesto despues del boot PXE. Si el timeout
+es brindado, entonces despues que el timeout se haya vencido sin input del
+teclado, la primera opción del menú sera automaticamente ejecutada. Si el
+timeout es cero entonces la primera opción del menú sera automaticamente
+ejecutada. Si
+.B pxe-prompt
+es omitido, el sistema esperará para el input del usuario si hay múltiples
+artículos en el menú, pero hará boot imediatamente si hay solo uno. Ver
+.B pxe-service
+para detalles sobre artículos de menu.
+
+Dnsmasq tiene soporte para "proxy-DHCP" PXE, en este caso otro servidor
+DHCP en la red es responsable por asignar direcciones IP, y dnsmasq
+simplemente provee la dirección brindada en
+.B pxe-prompt
+y
+.B pxe-service
+para permitir boot a travez de la red. Este modo es habilitado usando
+la palabra clave
+.B proxy
+en
+.B dhcp-range.
+.TP
+.B \-X, --dhcp-lease-max=<número>
+Limita a dnsmasq a el número especificado de arriendos DHCP. El
+predeterminado es 1000. El limite es para prevenir ataques DoS desde
+hosts que crean cientos de arriendos y usan mucha de la memoria del
+proceso dnsmasq.
+.TP
+.B \-K, --dhcp-authoritative
+Esta opción debe ser fijada cuando dnsmasq es definitivamente el Ãºnico
+servidor DHCP en la red. Cambia el comportamiento de RFC de tal manera
+que pedidos desde hosts no conocidos no serán ignorados. Esto permite que
+hosts nuevos puedan conseguir un arriendo sin sin un timeout bajo toda
+circunstancia. También permite que dnsmasq reconstruya su base de datos
+de arriendos sin que cada cliente necesite readquirir un arriendo
+si la base de datos es perdida.
+.TP
+.B --dhcp-alternate-port[=<puerto de servidor>[,<puerto de cliente>]]
+Cambiar del predeterminado los puertos usados para DHCP. Si esta opción
+es brindada sola, sin argumentos, cambia los puertos usados para DHCP
+de 67 y 68 a 1067 y 1068. Si un solo argumento es brindado, ese puerto
+es usado para el servidor y el número de puerto mas uno es usado
+para el cliente. Finalmente, dos números permiten que se especifiquen
+ambos los puertos de servidor y cliente para DHCP.
+.TP
+.B \-3, --bootp-dynamic[=<network-id>[,<network-id>]]
+Habilitar alocación dinámica de direcciones IP a clientes BOOTP. Usar
+esto con cuidado, ya que cada dirección alocada a un cliente BOOTP
+es arrendada para siempre, y consecuentemente queda no-disponible
+para re-uso por otros hosts. Si esto es brindado sin etiquetas,
+entonces incondicionalmente habilita alocación dinámica. Con
+etiquetas, solo cuando todas las etiquetas están fijadas. Puede
+ser repetido con diferentes juegos de etiquetas.
+.TP
+.B \-5, --no-ping
+Por predetermindado, el servidor DHCP tratará de asegurarse que una
+dirección no esté en uso antes de alocarsela a un host. Hace esto
+enviando un echo ICMP (ping) a la dirección referente. Si recibe una
+respuesta, entonces la dirección debe estar siendo usada, y se repite
+la prueba con otra. Esta opción deshabilita esta prueba. Usar con
+cuidado.
+.TP
+.B --log-dhcp
+Bitacoréo extra para DHCP: Bitacorear todas las opciones enviadas a
+clientes DHCP y las etiquetas usadas para determinarlos.
+.TP
+.B \-l, --dhcp-leasefile=<path>
+Usar el archivo especificado para almacenar información de arriendos
+DHCP.
+.TP
+.B \-6 --dhcp-script=<path>
+Cuando un arriendo DHCP nuevo es creado, o uno viejo es
+destruido, el ejecutable especificado por esta opción es ejecutado.
+<path> debe ser un pathname absoluto, ninguna búsqueda PATH ocurre.
+Los argumentos para el binario son "add", "old", o "del", la dirección
+MAC del host, la dirección IP, y el hostname, si es
+conocido. "add" significa que un arriendo ha sido creado, "del" que
+ha sido destruido, y "old" es una notificación de un arriendo existente
+cuando dnsmasq inicia o un cambio a una MAC o nombre host de un arriendo
+existente (también, tiempo de arriendo o vencimiento y client-id, si
+leasefile-ro está fijado). Si la dirección MAC es de un tipo de red
+que no es ethernet, tendrá el tipo de red precolocado, por ejemplo
+"06-01:23:45:67:89:ab" para token ring. El proceso es ejecutado como root
+(asumiendo que dnsmasq fue originalmente ejecutado como root) aún si dnsmasq
+está configurado para cambiar su UID a un usuario sin privilegios.
+
+
+El ambiente es heredado del usuario que ha invocado a dnsmasq, con algunas
+o todas de las siguientes variables agregadas.
+
+DNSMASQ_CLIENT_ID si el host brindo un client-id.
+
+DNSMASQ_DOMAIN si el nombre de dominio completamente calificado del host
+es conocido, esto es fijado a la parte del dominio.
+
+Si el cliente brinda vendor-class, hostname o user-class, estos son
+brindados en las variables
+DNSMASQ_VENDOR_CLASS, DNSMASQ_SUPPLIED_HOSTNAME, y
+DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add"
+y "old" cuando un host reanuda un arriendo existente, dado a que estos
+datos no son almacenados en la base de datos de arriendos de dnsmasq.
+
+Si dnsmasq fue compilado con HAVE_BROKEN_RTC, entonces la duración del
+arriendo (en segundos) es almacenada en DNSMASQ_LEASE_LENGTH, de otra
+manera el tiempo de vencimiento es almacenado en DNSMASQ_LEASE_EXPIRES.
+El número de segundos faltante para el vencimiento del arriendo siempre
+es almacenado en DNSMASQ_TIME_REMAINING.
+
+Si un arriendo solía tener un nombre de host, el cual es removido, un
+evento "old" es generado con el nuevo estado del arriendo, (por ejemplo, sin
+nombre), y el nombre anterior es brindado en la variable de ambiente
+DNSMASQ_OLD_HOSTNAME.
+
+DNSMASQ_INTERFACE almacena el nombre de la interface
+en la cual llegó el pedido; esto no es fijado para acciones "viejas"
+cuando dnsmasq re-inicia.
+
+DNSMASQ_RELAY_ADDRESS es fijado si el cliente
+usó un relay DHCP para contactar a dnsmasq y la dirección IP del relay
+es conocida.
+
+DNSMASQ_TAGS contiene todas las etiquetas network-id fijadas
+durante la transacción DHCP, separadas por espacios.
+
+Todos los descriptores de archivo están cerrados
+excepto stdin, stdout, y stderr los cuales están abiertos a /dev/null
+(excepto en modo debug).
+
+Este guión no es invocado concurrentemente: máximo una instamcia del
+guión está corriendo a la vez (dnsmasq espera a que una instancia de
+guión haga exit antes de correr la siguiente). Cambios a la base de
+datos de arriendos que requieren que el guión sea invocado son puestos
+en cola esperando el exit de una instancia corriente. Si esta cola permite
+que cambios multiples de estado le ocurran a un arriendo individual antes
+de que el guión pueda ser ejecutado entonces estados anteriores son descartados
+y el estado actual del arriendo es reflejado cuando el guión finalmente corre.
+
+Al inicio de dnsmasq, el guión
+será invocado para todos los arriendos existentes mientras van siendo
+leídos desde el archivo de arriendos. Arriendos vencidos serán llamados
+con "del" y otros con "old". <path> debe ser un path absoluto, ninguna
+búsqueda PATH ocurre cuando arriendos dnsmasq serán llamados con "del"
+y otros con "old". Cuando dnsmasq recibe una señal HUP, el guión será
+invocado para arriendos existentes con un evento "old".
+.TP
+.B --dhcp-scriptuser
+Especificar el usuario como el cual se debe correr el archivo
+guión de cambio de arriendos. Este es root por predeterminado,
+pero puede ser cambiado a otro usuario mediante esta opción.
+.TP
+.B \-9, --leasefile-ro
+Suprimir completamente el uso del archivo de arriendos. El archivo no será
+creado, leído, ni escrito. Cambiar la manera en la cuál el archivo guión de
+cambio de arriendo (si es brindado) es llamado, de tal forma que la base de
+datos de arriendospueda ser mantenida en almacenaje externo por el archivo
+guión. Adicionálmente a las invocaciones brindadas en
+.B --dhcp-script
+el archivo de cambio de arriendos es llamado una vez, al inicio de dnsmasq,
+con el Ãºnico argumento "init". Cuando invocado de esta forma, el guión debería
+escribir el estado guardado de la base de datos de arriendos, en formato de
+archivo de arriendos dnsmasq, a stdout y hacer exit con código exit cero. Fijar
+esta opción también forza que el archivo de cambio de arriendos sea llamado
+cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
+.TP
+.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
+Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias>
+como si hubieran llegado a la interface <nombre de interface>. Esta opción
+es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que
+los paquetes llegan a interfaces tap que no tienen una dirección IP.
+.TP
+.B \-s, --domain=<dominio>[,<rango de IPs>]
+Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
+brindados incondicionalmente (sin el rango de IPs) o para rangos limitados. Esto
+tiene dos efectos: Primeramente, causa que el servidor DHCP le devuelva el
+dominio a cualquier host que lo pida. Segundamente, fija el dominio para el
+cual es legal para hosts configurados mediante DHCP reclamar. La intención es
+restringir nombres de host para que un host no-confiado en la LAN no
+pueda proclamar su nombre vía DHCP, como por ejemplo "microsoft.com" y
+capturar tráfico no destinado a ella. Si ningún sufijo de dominio es
+especificado, entonces cualquier nombre de host con una parte de dominio
+(o sea con un punto) será negada y bitacorada. Si un sufijo es especificado,
+entonces nombres de host con una parte de dominio son permitidos, con tal
+que la parte de dominio coincida con el sufijo. Adicionalmente, cuando
+un sufijo es fijado, entonces nombres de host sin parte de dominio tienen
+el sufijo agregado como una parte de dominio opcional. Por ejemplo, en
+mi red puedo fijar
+.B --domain=thekelleys.org.uk
+y tener una maquina cuyo nombre host DHCP es "laptop". La dirección IP
+de esa máquina es disponible desde
+.B dnsmasq
+como "laptop" y "laptop.thekelleys.org.uk". Si el dominio es brindado
+como "#" entonces el dominio es leido desde la primera directiva search
+en /etc/resolv.conf (o equivalente). El rango de direcciones puede ser
+<dirección IP>,<dirección IP> or <dirección IP>/<máscara de subred>. Ver
+.B --dhcp-fqdn el cual puede cambiar el comportamiento de dnsmasq con
+dominios.
+.TP
+.B --dhcp-fqdn
+En el modo predeterminado, dnsmasq pone los nombres no-calificados
+de clientes DHCP en el DNS. Por esta razón, los nombres deben ser Ãºnicos,
+aún si dos clientes que tienen el mismo nombre están en dominios
+diferentes. Si un segundo cliente DHCP aparece el cual tiene el mismo
+nombre que un cliente existente, el nombre es transferido al cliente nuevo. Si
+.B --dhcp-fqdn
+está fijado, este comportamiento cambia: El nombre no-calificado
+no es puesto en el DNS, solo el nombre calificado. Dos clientes DHCP con
+el mismo nombre pueden ambos quedarse con el nombre, con tal que la parte
+de dominio sea diferente (o sea que los nombres completamente calificados
+difieran). Para asegurar que todos los nombres tengan una parte de dominio,
+debe haber al menos
+.B --domain
+sin una dirección especificada cuando
+.B --dhcp-fqdn
+está fijado.
+.TP
+.B --enable-tftp[=<interface>]
+Habilitar la función de servidor TFTP. Esto está deliberadamente limitado
+a lo necesario para hacerle a un cliente un inicio vía red. Solo lectura es
+permitida; las extensiones tsize y blksize son soportadas (tsize solo es
+soportada en modo octeto). Ver sección de NOTAS para el uso de el argumento
+de interface.
+.TP
+.B --tftp-root=<directory>[,<interface>]
+Buscar, relativo al directorio brindado, archivos para transferir mediante el
+uso de TFTP. Cuando esta opción está fijada, paths TFTP que incluyen ".." son
+rechazados, para prevenir que clientes salgan de la raíz especificada. Paths
+absolutos (los que comienzan con "/") están permitidos, pero deben estar
+dentro del tftp-root. Si el argumento opcional de interface es brindado, el
+directorio es solo usado para pedidos TFTP vía esa interface.
+.TP
+.B --tftp-unique-root
+Agregar la dirección IP del cliente TFTP como un componente path del lado del
+TFTP-root (en formato estándar de cuatro puntos). Solo válido si un tftp-root
+está fijado y el directorio existe. Por ejemplo, si tftp-root es "/tftp" y el
+cliente 1.2.3.4 pide el archivo "miarchivo" entonces el path efectivo será
+"/tftp/1.2.3.4/miarchivo" si /tftp/1.2.3.4 existe o /tftp/miarchivo si no.
+.TP
+.B --tftp-secure
+Habilitar modo TFTP seguro: sin esto, cualquier archivo que es leíble por el
+proceso dnsmasq bajo reglas normales de control de acceso UNIX, está disponible
+vía TFTP. Cuando la opción --tftp-secure es fijada, solo archivos
+pertenecientes al usuario que corre el proceso dnsmasq están accesibles. Si
+dnsmasq está corriendo como root, reglas diferentes aplican: --tftp-secure no
+tiene ningún efecto, pero solo archivos que tienen el bit de lectura global
+fijados están accesibles. No se recomienda correr dnsmasq como root con TFTP
+habilitado, y mucho menos sin especificar --tftp-root, ya que se puede exponer
+cualquier archivo de lectura global en el servidor a cualquier host de la red.
+.TP
+.B --tftp-max=<conecciones>
+Fijar el número máximo permitido de conecciones TFTP simultáneas. Esto es 50
+por predeterminado. Al servir un número grande de conecciones TFTP, límites
+de descriptor de archivo por proceso pueden ser encontrados. Dnsmasq necesita
+un descriptor de archivo por cada coneccion TFTP concurrente, y por archivo
+único (mas algunos otros). De tal manera que servirle el mismo archivo
+simultáneo a n clientes requerirá el uso de n + 10 descriptores de archivo,
+y servirles archivos diferentes simultáneamente requerirá (2*n) + 10
+descriptores. Si
+.B --tftp-port-range
+es brindado, eso puede afectar el número de conexiones simultáneas.
+.TP
+.B --tftp-no-blocksize
+No permitir que el servidor negocie la opción "blocksize" con un cliente.
+Algunos clientes con errores piden esta opción pero se portán mal cuando se
+les brinda.
+.TP
+.B --tftp-port-range=<inicio>,<final>
+Un servidor TFTP escucha por inicios de conexión en un puerto bien conocido
+(69), pero tambien usa un puerto dinamicamente seleccionado para cada
+conexión. Normalmente estos son seleccionados por el sistema operativo,
+pero esta opción especifica un rango de puertos para ser usado por transferencias
+TFTP. Esto puede ser Ãºtil cuando TFTP tiene que pasar atraves de un firewall.
+El comienzo del rango no puede ser menor a 1025 a menos que dnsmasq esté corriendo
+como root. El número de conexiones simultáneas está limitado por el tamaño del
+rango de puertos.
+.TP
+.B \-C, --conf-file=<archivo>
+Especificar un archivo de configuración diferente. La opción conf-file
+también es permitida en archivos de configuración, para incluir múltiples
+archivos de configuración.
+.TP
+.B \-7, --conf-dir=<directorio>[,<file-extension>......]
+Leer todos los archivos dentro del directorio brindado como archivos
+de configuración. Si extensiones son brindadas, cualquier archivo que
+termine en esas extensiones son ignorados. Cualquier archivos cuyos nombres
+terminen con ~ o comienzen con . o comienzen y terminen con # siempre son
+ignorados. Esta opción puede ser brindada en la línea de comandos o en un
+archivo de configuración.
+.SH ARCHIVO DE CONFIGURACION
+Al inicio, dnsmasq lee
+.I /etc/dnsmasq.conf,
+si existe. (En FreeBSD, el archivo es
+.I /usr/local/etc/dnsmasq.conf
+) (pero ver las opciónes
+.B \-C
+y
+.B \-7
+porfavor.) El formato de este archivo consiste de una opción por línea,
+exáctamente como las opciones largas detalladas en la sección OPCIONES
+pero sin el "--" al frente. Líneas que comienzan con # son comentarios
+y son ignoradas. Para opciones que solo pueden ser especificadas una
+sola vez, el archivo de configuración invalida la línea de comandos.
+Las comillas son permitidas en el archivo de configuración: entre comillas
+tipo " los significados especiales de ,:. y # son eliminados y los
+siguientes escapes son permitidos: \\\\ \\" \\t \\e \\b \\r y \\n.
+Corresponden a tab, escape, backspace, return y newline.
+.SH NOTAS
+Al recibir un SIGHUP
+.B dnsmasq 
+libera su cache y entonces recarga
+.I /etc/hosts
+y
+.I /etc/ethers
+al igual que cualquier archivo brindado con --dhcp-hostsfile, --dhcp-optsfile,
+o --addn-hosts.
+El archivo guión de cambio de arriendos es llamado para todos los arriendos
+DHCP existentes. Si
+.B
+--no-poll
+está fijado entonces SIGHUP también re-lee
+.I /etc/resolv.conf.
+SIGHUP
+NO re-lee el archivo de configuración.
+.PP
+Al recibir un SIGUSR1,
+.B dnsmasq 
+escribe estadísticas a la bitácora del sistema. Escribe el tamaño
+del caché, el numero de nombres que han tenido que ser removidos del
+caché antes de que vencieran para hacer espacio para nombres nuevos, y el
+número total de nombres que han sido insertados en el caché. Para cada
+servidor upstream brinda el número de búsquedas enviadas, y el
+número que resultaron en error. En modo
+.B --no-daemon
+o cuando bitacoréo completo está habilitado (-q), una descarga completa de
+el contenido del caché es hecha.
+.PP
+Cuando recibe un SIGUSR2 y está bitacoreando diréctamente a un archivo (ver
+.B --log-facility
+)
+.B dnsmasq
+cerrará y reabrirá el archivo de bitácora. Nótese que durante esta
+operación, dnsmasq no estará corriendo como root. Al crear el archivo de
+bitácora, dnsmasq cambia el dueño del archivo a el usuario normal como
+el que correrá. Logrotate debe ser configurado para crear un archivo de
+bitácora nuevo con permisos iguales al existente, antes de enviar
+SIGUSR2. Si búsquedas DNS TCP están en progreso, el archivo de bitácora
+viejo se mantendrá abierto en procesos hijos que están manejando
+búsquedas TCP, y puede continuarse a escribirle. Hay un límite de 150
+segundos, después de lo cual todos los procesos TCP existentes se habrán
+vencido: por esta razón, no es sabio configurar compresión de archivos
+de bitácora para archivos que acaban de ser rotados. Con logrotate, las
+opciones requeridas son
+.B create
+y
+.B delaycompress.
+.PP
+Dnsmasq es un reenviador de búsquedas DNS: no puede responder búsquedas
+arbitrarias comenzando desde los servidores root pero reenvía dichas
+búsquedas a un servidor DNS recursivo, el cual es típicamente proveído
+por el proveedor de Internet. Por predeterminado, dnsmasq lee
+.I /etc/resolv.conf
+para descubir las direcciones IP de los servidores DNS upstream que
+debe usar, dado a que esta información es normalmente almacenada allí.
+Amenos que
+.B --no-poll
+sea usado,
+.B dnsmasq
+revisa el tiempo de modificación de
+.I /etc/resolv.conf
+(o equivalente si
+.B \--resolv-file 
+es usado) y lo re-lee si ha cambiado. Esto permite que servidores DNS séan
+fijados dinámicamente vía PPP o DHCP ya que ambos protocolos brindan esta
+información.
+La ausencia de
+.I /etc/resolv.conf
+no es un error ya que pudo haber sido creada antes de que una conexión PPP
+haya existido. Dnsmasq simplemente sigue revisando en caso de que
+.I /etc/resolv.conf 
+sea creado en algún momento. A dnsmasq se le puede decir que revise más
+de un archivo resolv.conf. Esto es Ãºtil en una laptop, donde ambos PPP y
+DHCP podrían estar siendo usados: dnsmasq puede ser fijado para revisar ambos
+.I /etc/ppp/resolv.conf 
+y
+.I /etc/dhcpc/resolv.conf 
+y usará el contenido del que haya cambiado mas recientemente,
+brindando así la habilidad de cambio automático entre servidores DNS.
+.PP
+Servidores upstream también pueden ser especificados en la línea de
+comandos o en el archivo de configuración. Estas especificaciones de
+servidor opcionalmente llevan un nombre de dominio el cual le dice a
+dnsmasq que debe usar ese servidor solo para encontrar nombres en ese
+dominio en particular.
+.PP
+Para configurar dnsmasq como caché para el host donde está
+corriendo, poner un "nameserver 127.0.0.1" en
+.I /etc/resolv.conf
+para así forzar procesos locales a enviar búsquedas a dnsmasq. Entonces,
+o especificar los servidores upstream diréctamente a dnsmasq usando opciones
+.B \--server
+o poniendo sus direcciones reales en otro archivo, digamos
+.I /etc/resolv.dnsmasq
+y correr dnsmasq con la opcion
+.B \-r /etc/resolv.dnsmasq
+Esta segunda técnica permite la actualización dinámica de las direcciones
+de servidor mediante PPP o DHCP.
+.PP
+Direcciones en /etc/hosts "harán sombra" a diferentes direcciones para
+los mismos nombres en servidores DNS upstream, así que
+"miempresa.com 1.2.3.4" en /etc/hosts se asegurará que las búsquedas
+por "miempresa.com" siempre retornarán 1.2.3.4 aún si búsquedas en el
+servidor DNS upstream devolverían una dirección diferente. Hay una
+excepción a esto: si el servidor DNS upstream contiene un CNAME que
+apunta a un nombre sombreado, entonces buscando el CNAME a travéz de
+dnsmasq resultará en que la dirección no-sombreada será asociada con
+el destino del CNAME. Para circumventar esto, agregar el CNAME a
+/etc/hosts de tal manera que el CNAME es sombreado también.
+
+.PP
+El sistema de etiquetas funciona de la siguiente manera: Para cada pedido
+DHCP, dnsmasq colecciona un juego de etiquetas válidas de líneas de
+configuración activas que incluyen set:<tag>, incluyendo una del
+.B dhcp-range
+usado para alocar la dirección, una de cualquier
+.B dhcp-host
+que coincida (y "known" si un dhcp-host coincide).
+La etiqueta "bootp" es fijada para pedidos BOOTP, y una etiqueta cuyo
+nombre es el nombre de la interface donde llegó el pedido tambien es
+fijada.
+
+Cualquier linea de configuración que incluya uno o mas
+construcciones tag:<tag> solo será válida si todas las etiquetas
+coinciden en el juego derivado arriba. Típicamente esto es dhcp-option.
+.B dhcp-option 
+que tenga etiquetas será usada en preferencia de una opción
+.B dhcp-option,
+sin etiqueta, con tal que _todas_ las etiquetas coincidan en alguna
+parte del juego coleccionado describido arriba. El prefijo '!' en una
+etiqueta significa "no" así que --dhcp=option=tag:!purple,3,1.2.3.4 envía
+la opción cuando la etiqueta "purple" no está en el juego
+de etiquetas válidas. (Si se está usando esto en una línea de comandos
+en vez de un archivo de configuración, asegurese de escapar !, el cual
+es un metacaracter de shell.)
+.PP
+Nótese que para
+.B dhcp-range
+ambos tag:<tag> y set:<tag> son permitidos, para seleccionar el rango
+en uso basado en (por ejemplo) dhcp-host, y para afectar las opciones
+enviadas, basadas en el rango seleccionado.
+
+Este sistema evolucionó de uno anterior mas limitado y para compatibildad
+reversa "net:" puede ser usada en vez de "tag:" y "set:" puede ser
+omitida. (Excepto en
+.B dhcp-host,
+donde "net:" puede ser usado en vez de "set:".) Por la misma razón, '#'
+puede ser usado en vez de '!' para indicar NO.
+.PP
+El servidor DHCP de dnsmasq funcionará como servidor BOOTP tambien,
+con tal que las direcciones MAC y IP de los clientes sean brindadas,
+ya sea usando configuraciones
+.B dhcp-host 
+o en
+.I /etc/ethers
+, y una configuración
+.B dhcp-range 
+esté presente para activar el servidor DHCP en una red particular.
+(Fijar --bootp-dynamic elimina la necesidad de trazados estáticos.) El
+parámetro de nombre de archivos en un pedido BOOTP es usado como
+una etiqueta, al igual que la etiqueta "bootp", permitiendo así algún
+control sobre las opciones devueltas a diferentes clases de hosts.
+
+.B dhcp-range
+puede tener un nombre de interface brindado como
+"interface:<interface-name>". La semántica de esto es así:
+Para DHCP, si cualquier otro dhcp-range existe _sin_ un nombre de
+interface, entonces el nombre de interface es ignorado y dnsmasq
+se comporta como si las partes de interface no existieran, de otra forma
+DHCP solo se provee a interfaces mencionadas en declaraciones
+dhcp-range. Para DNS, si no hay opciones
+.B --interface
+o
+.B --listen-address
+el comportamiento no se modifica por la parte de interface. Si cualquiera
+de estas opciones está presente, las interfaces mencionadas en dhcp-ranges
+son agregadas all juego que obtienen servicio DNS.
+
+Similarmente,
+.B enable-tftp
+puede tomar un nombre de interface, el cual habilita TFTP solo para una
+interface en particular, ignorando opciones
+.B --interface
+o
+.B --listen-address.
+Adicionalmente, 
+.B --tftp-secure
+y
+.B --tftp-unique-root
+y
+.B --tftp-no-blocksize
+son ignorados por pedidos desde dichas interfaces. (Una directiva
+.B --tftp-root
+brindando un path raíz y una interface debe ser brindada tambien.)
+
+Estas reglas pueden parecer raras a primera vista, pero permiten que
+una simple linea de la forma
+"dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" sea agregada a
+configuración dnsmasq, lo cual brinda servicios DHCP y DNS a esa interface,
+sin afectar los servicios en otras interfaces y irrespectivamente de
+la existencia o no de lineas "interface=<interface>" en alguna otra parte
+de la configuración dnsmasq.
+"enable-tftp=virt0" y "tftp-root=<root>,virt0" hacen el mismo trabajo
+para TFTP.
+La idea es que una linea así pueda ser agregada automaticamente
+por libvirt o sistemas equivalentes, sin estorbar alguna
+configuración manual.
+
+.SH CÓDIGOS EXIT
+.PP
+0 - Dnsmasq hizo fork hacia el fondo exitosamente, o terminó de manera
+normal si ir al fondo no está habilitado.
+.PP
+1 - Un problema con la configuración ha sido detectado.
+.PP
+2 - Un problema con acceso a redes ocurrió (dirección en uso, intento
+de usar puertos privilegiados sin permiso).
+.PP
+3 - Un problema con una operación de sistema de archivos ocurrió (archivo
+o directorio ausente, permisos).
+.PP
+4 - Falla de alocación de memoria.
+.PP
+5 - Otro problema misceláneo.
+.PP
+11 o mayor - un codigo de retorno no cero fué recibido del llamado "init"
+del proceso de archivo guión de arriendos. El código exit de dnsmasq es
+el código exit del archivo guión con 10 sumado.
+
+.SH LIMITES
+Los valores predeterminados para limites de recursos son generálmente
+conservadores, y apropiados para uso en dispositivos tipo enrutador
+encrustrado con procesadores lentos y poca memoria. En hardware más
+capáz, es posible incrementar los límites, y soportar muchos mas
+clientes. Lo siguiente se aplica a dnsmasq-2.37: versiones previas
+no escalaban tan bien.
+
+.PP
+Dnsmasq es capaz de soportar con DNS y DHCP a por lo menos mil (1,000)
+clientes. Los tiempos de arriendo no deben ser muy cortos (menos
+de una hora). El valor de
+.B --dns-forward-max
+puede ser aumentado: comienze con el equivalente a el número de clientes y
+auméntelo si parece lento el DNS. Nótese que el rendimiento DNS depende
+también de los servidores DNS upstream. El tamaño del caché DNS puede ser
+incrementado: el límite obligatorio es 10,000 nombres y el predeterminado
+(150) es muy bajo. El enviarle un SIGUSR1 a dnsmasq hace que bitacorée
+información que es Ãºtil para afinar el tamaño de caché. Ver la sección
+.B NOTAS
+para detalles.
+
+.PP
+El servidor TFTP incorporado es capáz de soportar varias transferencias
+simultáneas de archivos: el límite absoluto está relacionado con el número
+de file-handles permitidos a un proceso y la habilidad del system call
+select() a soportar números grandes de file-handles. Si el límite es fijado
+demasiado alto con
+.B --tftp-max
+será de-escalado y el límite real será bitacoreado al inicio. Nótese que más
+transferencias son posibles cuando el mismo archivo es enviado qué cuando
+cada transferencia envía un archivo diferente.
+
+.PP
+Es posible usar dnsmasq para negar publicidad Web usando una lista de
+servidores de banners bien conocidos, todos resolviendose a 127.0.0.1 o
+0.0.0.0 en
+.B /etc/hosts 
+o en un archivo hosts adicional. La lista puede ser muy larga. Dnsmasq ha sido
+probado exitósamente con un millón de nombres. Ese tamaño de archivo necesita
+un CPU de 1GHz y aproximadamente 60MB de RAM.
+
+.SH INTERNACIONALIZACION
+
+Dnsmasq puede ser compilado con soporte para internacionalización. Para hacer esto,
+los targets make "all-i18n" y "install-i18n" deberán ser usados en vez de
+los targets estándares "all" y "install". Cuando internacionalización es
+compilada, dnsmasq producirá mensajes de bitácora en el lenguaje local y soportará
+dominios internacionalizados (IDN). Nombres de dominio en /etc/hosts, /etc/ethers,
+y /etc/dnsmasq.conf que contienen carácteres no-ASCII serán traducidos a
+representación interna DNS punycode. Nótese que dnsmasq determina ambos el
+lenguaje para mensajes y el juego de carácteres asumido para archivos de configuración
+de la variable ambiental LANG. Esto debe estar fijado al valor predeterminado del sistema
+por el guión responsable de iniciar dnsmasq. Al editar archivos de configuración,
+tener cuidado de hacerlo usando solo el locale predeterminado del sistema y no
+uno especifico del usuario, dado a que dnsmasq no tiene ninguna manera directa de
+determinar el juego de caracteres en uso, y debe asumir que es el predeterminado
+del sistema.
+
+.SH ARCHIVOS
+.IR /etc/dnsmasq.conf 
+
+.IR /usr/local/etc/dnsmasq.conf
+
+.IR /etc/resolv.conf
+
+.IR /etc/hosts
+
+.IR /etc/ethers
+
+.IR /var/lib/misc/dnsmasq.leases 
+
+.IR /var/db/dnsmasq.leases
+
+.IR /var/run/dnsmasq.pid
+.SH VER TAMBIEN
+.BR hosts (5), 
+.BR resolver (5)
+.SH AUTOR
+Este manual fue escrito por Simon Kelley <simon@thekelleys.org.uk>.
+
+Traducido a español por Christopher Chatham <chrislinux@gmail.com>.
diff --git a/man/fr/dnsmasq.8 b/man/fr/dnsmasq.8
new file mode 100644 (file)
index 0000000..44c301b
--- /dev/null
@@ -0,0 +1,1695 @@
+.TH DNSMASQ 8
+.SH NAME
+Dnsmasq \- Un serveur DHCP et cache DNS poids-plume.
+.SH SYNOPSIS
+.B dnsmasq
+.I [OPTION]...
+.SH "DESCRIPTION"
+.BR dnsmasq
+est un serveur DHCP et DNS Ã  faible empreinte mémoire. Il offre Ã  la fois les
+services DNS et DHCP pour un réseau local (LAN).
+.PP
+Dnsmasq accepte les requêtes DNS et y réponds soit en utilisant un petit cache
+local, soit en effectuant une requête Ã  un serveur DNS récursif externe (par
+exemple celui de votre fournisseur d'accès internet). Il charge le contenu du
+fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS
+globaux soient tout de même résolus, et assure Ã©galement la résolution de nom
+pour les hôtes présents dans le service DHCP.
+.PP
+Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques et les
+réseaux multiples. Il envoie par défaut un jeu raisonnable de paramètres DHCP, et
+peut Ãªtre configuré pour envoyer n'importe quel option DHCP.
+Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
+le réseau/PXE de clients DHCP et supporte Ã©galement le protocole BOOTP.
+.PP
+Dnsmasq supporte IPv6 pour le DNS et TFTP mais pas pour le DHCP.
+.SH OPTIONS
+Notes : Il est possible d'utiliser des options sans leur donner de paramètre.
+Dans ce cas, la fonction correspondante sera désactivée. Par exemple
+.B --pid-file=
+(sans paramètre après le =) désactive l'écriture du fichier PID.
+Sur BSD, Ã  moins que le logiciel ne soit compilé avec la bibliothèque GNU
+getopt, la forme longue des options ne fonctionne pas en ligne de commande; Elle
+est toujours supportée dans le fichier de configuration.
+.TP
+.B --test
+Vérifie la syntaxe du ou des fichiers de configurations. Se termine avec le
+code de retour 0 si tout est OK, ou un code différent de 0 dans le cas
+contraire. Ne démarre pas Dnsmasq.
+.TP
+.B \-h, --no-hosts
+Ne pas charger les noms du fichier /etc/hosts.
+.TP
+.B \-H, --addn-hosts=<fichier>
+Fichiers d'hôtes additionnels. Lire le fichier spécifié en plus de /etc/hosts.
+Si 
+.B -h
+est spécifié, lire uniquement le fichier spécifié. Cette option peut Ãªtre
+répétée afin d'ajouter d'autres fichiers. Si un répertoire est donné, lis les
+fichiers contenus dans ce répertoire.
+.TP
+.B \-E, --expand-hosts
+Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le
+nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service
+DHCP. Notez que cela ne s'applique pas au nom de domaine dans les CNAME, les
+enregistrements PTR, TXT, etc...
+.TP
+.B \-T, --local-ttl=<durée>
+Lorsque Dnsmasq répond avec une information provenant du fichier /etc/hosts ou
+avec un bail DHCP, il donne un temps de vie (time-to-live) positionné Ã  zéro,
+afin d'indiquer Ã  la machine faisant la requête que celle-ci  ne doit pas Ãªtre
+mise dans un cache. Ceci est le comportement correct dans presque toutes les
+situations.
+Cette option permet de spécifier la valeur de time-to-live Ã  retourner (en
+secondes). Cela permet de réduire la charge sur le serveur, mais les clients
+risquent d'utiliser des données périmées dans certains cas.
+.TP
+.B --neg-ttl=<durée>
+Les réponses négatives provenant des serveurs amonts contiennent normalement
+une information de durée de vie (time-to-live) dans les enregistrements SOA,
+information dont dnsmasq se sert pour mettre la réponse en cache. Si la réponse
+du serveur amont omet cette information, dnsmasq ne cache pas la réponse. Cette
+option permet de doner une valeur de durée de vie par défaut (en secondes) que
+dnsmasq utilise pour mettre les réponses négatives dans son cache, même en
+l'absence d'enregistrement SOA.
+.TP
+.B --max-ttl=<durée>
+Définie la valeur de TTL maximum qui sera fournie aux clients. La valeur maximum
+de TTL spécifiée sera fournie aux clients en remplacement de la vraie valeur de TTL
+si cette dernière est supérieure. La valeur réelle de TTL est cependant conservée dans
+le cache afin d'éviter de saturer les serveurs DNS en amont.
+.TP
+.B \-k, --keep-in-foreground
+Ne pas aller en tâche de fond au lancement, mais en dehors de cela, fonctionner
+normalement. Ce mode est prévu pour les cas où Dnsmasq est lancé par daemontools
+ou launchd.
+.TP
+.B \-d, --no-daemon
+Mode debug (déverminage) : ne pas aller en tâche de fond, ne pas Ã©crire de
+fichier pid, ne pas changer d'identifiant utilisateur, générer un Ã©tat complet
+du cache lors de la réception d'un signal SIGUSR1, envoyer les logs sur la
+sortie standard d'erreur ("stderr") de même que dans le syslog, ne pas créer de
+processus fils pour traiter les requêtes TCP.
+.TP
+.B \-q, --log-queries
+Enregistrer les résultats des requêtes DNS traitées par Dnsmasq dans un fichier
+de traces ("logs"). Active la génération d'un Ã©tat complet du cache lors de la
+réception d'un signal SIGUSR1.
+.TP
+.B \-8, --log-facility=<facility>
+Définit la "facility" dans laquelle Dnsmasq enverra ses entrées syslog, par
+défaut DAEMON ou LOCAL0 si le mode debug est activé. Si la "facility" contient
+au moins un caractère "/", alors Dnsmasq considère qu'il s'agit d'un fichier et
+enverra les logs dans le fichier correspondant Ã  la place du syslog. Si la
+"facility" est '-', alors dnsmasq envoie les logs sur la sortie d'erreur
+standard stderr. (Les erreurs lors de la lecture de la configuration vont
+toujours vers le syslog, mais tous les messages postérieurs Ã  un démarrage
+réussi seront exclusivement envoyés vers le fichier de logs).
+Lorsque Dnsmasq est configuré pour envoyer
+ses traces vers un fichier, la réception d'un signal SIGUSR2 entraine la
+fermeture et réouverture du fichier. Cela permet la rotation de fichiers de
+traces sans nécessiter l'arrêt de Dnsmasq.
+.TP
+.B --log-async[=<lignes>]
+Permet l'envoi de traces de manière asynchrone, et de manière optionnelle, le
+nombre de lignes devant Ãªtre mises dans la file d'attente par Dnsmasq lorsque
+l'écriture vers le syslog est lente.
+Dnsmasq peut envoyer ses logs de manière asynchrone : cela lui permet de
+continuer Ã  fonctionner sans Ãªtre bloqué par le syslog, et permet Ã  syslog
+d'utiliser Dnsmasq pour les résolutions DNS sans risque d'interblocage.
+Si la file d'attente devient pleine, Dnsmasq loggera le dépassement de file et
+le nombre de messages perdus. La longueur par défaut de la file d'attente est de
+5 et une valeur saine sera comprise entre 5 et 25, avec une limite maximum
+imposée de 100.
+.TP
+.B \-x, --pid-file=<chemin>
+Spécifie un fichier dans lequel stocker le numéro de processus (pid). La valeur
+par défaut est /var/run/dnsmasq.pid.
+.TP
+.B \-u, --user=<nom d'utilisateur>
+Spécifie l'identité (nom d'utilisateur) prise par Dnsmasq après le démarrage.
+Dnsmasq doit normalement Ãªtre démarré en temps que root ("super-utilisateur"),
+mais abandonne ses privilèges après le démarrage en changeant d'identité.
+Normalement cet utilisateur est l'utilisateur nobody ("personne"), mais il est
+possible d'en définir un autre par le biais de ce paramètre.
+.TP
+.B \-g, --group=<nom de groupe> 
+Spécifie le groupe sous lequel Dnsmasq s'exécute. Par défaut, il s'agit du
+groupe "dip", afin de faciliter l'accès au fichier /etc/ppp/resolv.conf qui
+n'est en général pas en lecture par tout le monde.
+.TP
+.B \-v, --version
+Imprime le numéro de version.
+.TP
+.B \-p, --port=<port>
+Ecoute sur le port numéro <port> au lieu du port DNS standard (53). Paramétrer
+cette valeur Ã  zéro désactive complètement la fonction DNS pour ne laisser actif
+que le DHCP ou le TFTP.
+.TP
+.B \-P, --edns-packet-max=<taille>
+Spécifie la taille maximum de paquet UDP EDNS.0 supporté par le relai DNS. Le
+défaut est de 4096, qui est la valeur recommandée dans la RFC5625.
+.TP
+.B \-Q, --query-port=<numéro de port>
+Envoie et Ã©coute les requêtes DNS sortantes depuis le port UDP spécifié par
+<numéro de port>, et non sur un port aléatoire. NOTE : Cette option rends
+dnsmasq moins sûr contre les attaques par usurpation DNS ("DNS spoofing"), mais
+cela peut permettre d'utiliser moins de ressources et d'être plus rapide. Donner
+une valeur de zéro Ã  cette option restaure le comportement par défaut présent dans
+les versions de dnsmasq inférieures Ã  2.43 qui consiste Ã  n'allouer qu'un seul port
+alloué par le système d'exploitation.
+.TP
+.B --min-port=<port>
+Ne pas utiliser de port dont le numéro est inférieur Ã  la valeur donnée en paramètre
+pour les requêtes DNS sortantes. Dnsmasq choisis un port source aléatoire pour les
+requêtes sortantes : lorsque cette option est fournie, les ports utilisés seront toujours
+au dessus de la valeur spécifiée. Utile pour des systèmes derrière des dispositifs
+garde-barrières ("firewalls").
+.TP
+.B \-i, --interface=<nom d'interface>
+N'écouter que sur l'interface réseau spécifiée. Dnsmasq aujoute automatiquement
+l'interface locale ("loopback") Ã  la liste des interfaces lorsque l'option
+.B --interface
+est utilisée.
+Si aucune option
+.B --interface
+ou
+.B --listen-address
+n'est donnée, Dnsmasq Ã©coutera sur toutes les interfaces disponibles sauf
+celle(s) spécifiée(s) par l'option
+.B --except-interface.
+Les alias d'interfaces IP (e-g "eth1:0") ne peuvent Ãªtre utilisés ni avec
+.B --interface
+ni
+.B \--except-interface.
+Utiliser l'option 
+.B --listen-address
+à la place. 
+.TP
+.B \-I, --except-interface=<interface name>
+Ne pas Ã©couter sur l'interface spécifiée. Notez que l'ordre dans lesquelles les
+options
+.B \--listen-address
+,
+.B --interface
+et
+.B --except-interface
+sont fournies n'importe pas, et que l'option 
+.B --except-interface
+l'emporte toujours sur les autres.
+.TP 
+.B \-2, --no-dhcp-interface=<nom d'interface>
+Ne pas fournir de service DHCP sur l'interface spécifiée, mais fournir tout de
+même le service DNS.
+.TP
+.B \-a, --listen-address=<adresse IP>
+Ecouter sur la ou les adresse(s) IP spécifiée(s). Les options 
+.B \--interface
+et
+.B \--listen-address
+peuvent-être spécifiées simultanément, auquel cas un jeu d'interfaces et
+d'adresses seront utilisées. Notez que si
+aucune option
+.B \--interface
+n'est donnée alors qu'une option 
+.B \--listen-address
+l'est, Dnsmasq n'écoutera pas automatiquement sur l'interface locale
+("loopback"). Pour activer l'écoute sur l'interface locale, il est alors
+nécessaire de fournir explicitement son adresse IP, 127.0.0.1 via l'option
+.B \--listen-address.
+.TP
+.B \-z, --bind-interfaces
+Sur les systèmes qui le supporte, Dnsmasq s'associe avec l'interface joker
+("wildcard"), même lorsqu'il ne doit Ã©couter que sur certaines interfaces. Par
+la suite, il rejette les requêtes auxquelles il ne doit pas répondre. Cette
+situation présente l'avantage de fonctionner même lorsque les interfaces vont
+et viennent ou changent d'adresses. L'option 
+.B --bind-interfaces
+force Dnsmasq Ã  ne réellement s'associer qu'avec les interfaces sur lesquelles
+il doit Ã©couter. L'un des seuls cas où cette option est utile est celui où un
+autre serveur de nom (ou une autre instance de Dnsmasq) tourne sur la même
+machine. Utiliser cette option permet Ã©galement d'avoir plusieurs instances de
+Dnsmasq fournissant un service DHCP sur la même machine.
+.TP
+.B \-y, --localise-queries
+Retourne des réponses aux requêtes DNS dépendantes de l'interface sur laquelle
+la requête a Ã©té reçue, Ã  partir du fichier /etc/hosts. Si un nom dans
+/etc/hosts a plus d'une adresse associée avec lui, et qu'une des adresses au
+moins est dans le même sous-réseau que l'interface sur laquelle la requête a Ã©té
+reçue, alors ne retourne que la(les) adresse(s) du sous-réseau considéré. Cela
+permet d'avoir dans /etc/hosts un serveur avec de multiples adresses, une pour
+chacune de ses interfaces, et de fournir aux hôtes l'adresse correcte (basée sur
+le réseau auquel ils sont attachés). Cette possibilité est actuellement limitée
+à IPv4.
+.TP
+.B \-b, --bogus-priv
+Fausse résolution inverse pour les réseaux privés. Toutes les requêtes DNS
+inverses pour des adresses IP privées (ie 192.168.x.x, etc...) qui ne sont pas
+trouvées dans /etc/hosts ou dans le fichier de baux DHCP se voient retournées
+une réponse "pas de tel domaine" ("no such domain") au lieu d'être transmises
+aux serveurs de nom amont ("upstream server").
+.TP
+.B \-V, --alias=[<ancienne IP>]|[<IP de début>-<IP de fin>],<nouvelle IP>[,<masque>]
+Modifie les adresses IPv4 retournées par les serveurs de nom amont;
+<ancienne IP> est remplacée par <nouvelle IP>. Si le <masque> optionnel est
+fourni, alors toute adresse correspondant Ã  l'adresse <ancienne IP>/<masque>
+sera réécrite. Ainsi par exemple
+.B --alias=1.2.3.0,6.7.8.0,255.255.255.0 
+modifiera 1.2.3.56 en 6.7.8.56 et 1.2.3.67 en 6.7.8.67. 
+Cette fonctionnalité correspond Ã  ce que les routeurs Cisco PIX appellent
+"bidouillage DNS" ("DNS doctoring"). Si l'ancienne IP est donnée sous la forme
+d'une gamme d'adresses, alors seules les adresses dans cette gamme seront
+réecrites, et non le sous-réseau dans son ensemble. Ainsi,
+.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
+fait correspondre 192.168.0.10->192.168.0.40 Ã  10.0.0.10->10.0.0.40
+.TP 
+.B \-B, --bogus-nxdomain=<adresse IP>
+Transforme les réponses contenant l'adresse IP fournie en réponses "pas de tel
+domaine" ("no such domain"). Ceci a pour but de neutraliser la modification
+sournoise mise en place par Verisign en septembre 2003, lorsqu'ils ont commencé
+à retourner l'adresse d'un serveur web publicitaire en réponse aux requêtes pour
+les noms de domaines non enregistrés, au lieu de la réponse correcte "NXDOMAIN".
+Cette option demande Ã  Dnsmasq de retourner la réponse correcte lorsqu'il
+constate ce comportement. L'adresse retournée par Verisign en septembre 2003
+est 64.94.110.11.
+.TP
+.B \-f, --filterwin2k
+Les dernières versions de windows font des requêtes DNS périodiques auxquelles
+non seulement les serveurs DNS publics ne peuvent donner de réponse, mais qui,
+de surcroît, peuvent poser des problèmes en déclenchant des connexions
+intempestives pour des liens réseaux avec des connexions "à la demande". Fournir
+cette option active le filtrage des requêtes de ce type. Les requêtes bloquées
+sont les requêtes pour les entrées de type SOA ou SRV, ainsi que les requêtes de
+type ANY avec des noms possédant des caractères sous-lignés (requêtes pour des
+serveurs LDAP).
+.TP
+.B \-r, --resolv-file=<fichier>
+Lis les adresses des serveurs de nom amont dans le fichier de nom <fichier>,
+au lieu du fichier /etc/resolv.conf. Pour le format de ce fichier, voir dans le
+manuel pour
+.BR resolv.conf (5) 
+les entrées correspondant aux serveurs de noms (nameserver). Dnsmasq peut lire
+plusieurs fichiers de type resolv.conf, le premier fichier spécifié remplace le
+fichier par défaut, le contenu des suivants est rajouté dans la liste des
+fichiers Ã  consulter. Seul le fichier ayant la dernière date de modification
+sera chargé en mémoire.
+.TP
+.B \-R, --no-resolv
+Ne pas lire le contenu du fichier /etc/resolv.conf. N'obtenir l'adresse des
+serveurs de nom amont que depuis la ligne de commande ou le fichier de
+configuration de Dnsmasq.
+.TP
+.B \-1, --enable-dbus
+Autoriser la mise Ã  jour de la configuration de Dnsmasq par le biais d'appel de
+méthodes DBus. Il est possible par ce biais de mettre Ã  jour l'adresse de
+serveurs DNS amont (et les domaines correspondants) et de vider le cache. Cette
+option nécessite que Dnsmasq soit compilé avec le support DBus.
+.TP 
+.B \-o, --strict-order
+Par défaut, Dnsmasq envoie les requêtes Ã  n'importe lequel des serveurs amonts
+dont il a connaissance tout en essayant de favoriser les serveurs qu'il sait
+fonctionner. Cette option force Dnsmasq Ã  essayer d'interroger, pour chaque
+requête, les serveurs DNS dans leur ordre d'apparition dans le fichier
+/etc/resolv.conf.
+.TP
+.B --all-servers
+Par défaut, lorsque dnsmasq a plus d'un serveur amont disponible, il n'envoie
+les requêtes qu'à un seul serveur. Spécifier cette option force dnsmasq Ã 
+effectuer ses requêtes Ã  tous les serveurs disponibles. Le résultat renvoyé
+au client sera celui fournit par le premier serveur ayant répondu.
+.TP
+.B --stop-dns-rebind
+Rejete (et enregistre dans le journal d'activité) les adresses dans la gamme
+d'adresses IP privée (au sens RFC1918) qui pourraient Ãªtre renvoyées par les
+serveurs amonts suite Ã  une résolution de nom. Cela bloque les attaques cherchant
+à détourner de leur usage les logiciels de navigation web ('browser') en s'en
+servant pour découvrir les machines situées sur le réseau local.
+.TP
+.B --rebind-localhost-ok
+Exclue 127.0.0/8 des vérifications de réassociation DNS. Cette gamme d'adresses
+est retournée par les serveurs Realtime Blackhole (RBL, utilisés dans la
+lutte contre le spam), la bloquer peut entraîner des disfonctionnements de ces
+services.
+.TP 
+.B  --rebind-domain-ok=[<domaine>]|[[/<domaine>/[<domaine>/]
+Ne pas détecter ni bloquer les actions de type dns-rebind pour ces domaines.
+Cette option peut prendre comme valeur soit un nom de domaine soit plusieurs
+noms de domains entourés par des '/', selon une syntaxe similaire Ã  l'option
+--server, c-à-d :
+.B  --rebind-domain-ok=/domaine1/domaine2/domaine3/
+.TP
+.B \-n, --no-poll
+Ne pas vérifier régulièrement si le fichier /etc/resolv.conf a Ã©té modifié.
+.TP
+.B --clear-on-reload
+Lorsque le fichier /etc/resolv.conf est relu, vider le cache DNS.
+Cela est utile si les nouveaux serveurs sont susceptibles d'avoir des données
+différentes de celles stockées dans le cache.
+.TP
+.B \-D, --domain-needed
+Indique Ã  Dnsmasq de ne jamais transmettre en amont de requêtes pour des noms
+simples, ne comprenant donc ni points ni nom de domaine. Si un nom n'est pas
+dans /etc/hosts ou dans la liste des baux DHCP, alors une réponse de type
+"non trouvé" est renvoyée.
+.TP
+.B \-S, --local, --server=[/[<domaine>]/[domaine/]][<Adresse IP>[#<port>][@<Adresse IP source>|<interface>[#<port>]]]
+Spécifie directement l'adresse IP d'un serveur de nom amont. Cette option ne
+supprime pas la lecture du fichier /etc/resolv.conf : utiliser pour cela
+l'option
+.B -R .
+Si un ou plusieurs nom(s) de domaine(s) optionnel(s) sont fournis, ce
+serveur sera uniquement utilisé uniquement pour ce(s) domaine(s), et toute
+requête concernant ce(s) domaine(s) sera adressée uniquement Ã  ce serveur.
+Cette option est destinée aux serveurs de nom privés : si vous avez un serveur
+de nom sur votre réseau ayant pour adresse IP 192.168.1.1 et effectuant la
+résolution des noms de la forme xxx.internal.thekelleys.org.uk, alors
+.B -S /internal.thekelleys.org.uk/192.168.1.1 
+enverra toutes les requêtes pour les machines internes vers ce serveur de nom,
+alors que toutes les autres requêtes seront adressées aux serveurs indiqués dans
+le fichier /etc/resolv.conf. Une spécification de nom de domaine vide,
+.B // 
+possède le sens particulier de "pour les noms non qualifiés uniquement",
+c'est-à-dire les noms ne possédant pas de points. Un port non standard peut Ãªtre
+rajouté Ã  la suite des adresses IP en utilisant le caractère #. Plus d'une
+option
+.B -S
+est autorisée, en répétant les domaines et adresses IP comme requis.
+
+Le domaine le plus spécifique l'emporte sur le domaine le moins spécifique,
+ainsi :
+.B --server=/google.com/1.2.3.4
+.B --server=/www.google.com/2.3.4.5
+enverra les requêtes pour *.google.com Ã  1.2.3.4, Ã  l'exception des requêtes
+*www.google.com, qui seront envoyées Ã  2.3.4.5.
+
+L'adresse spéciale '#' signifie "utiliser les serveurs standards", ainsi
+.B --server=/google.com/1.2.3.4
+.B --server=/www.google.com/#
+enverra les requêtes pour *.google.com Ã  1.2.3.4, Ã  l'exception des requêtes
+pour *www.google.com qui seront envoyées comme d'habitude (c-à-d aux serveurs
+définis par défaut).
+
+Il est Ã©galement permis de donner une option
+.B -S
+avec un nom de domaine mais sans
+adresse IP; Cela informe Dnsmasq que le domaine est local et qu'il doit répondre
+aux requêtes le concernant depuis les entrées contenues dans le fichier
+/etc/hosts ou les baux DHCP, et ne doit en aucun cas transmettre les requêtes
+aux serveurs amonts.
+.B local
+est synonyme de
+.B server
+("serveur") afin de rendre plus claire l'utilisation de cette option pour cet
+usage particulier.
+
+La chaîne de caractères optionnelle suivant le caractère @ permet de définir
+la source que Dnsmasq doit utiliser pour les réponses Ã  ce
+serveur de nom. Il doit s'agir d'une des adresses IP appartenant Ã  la machine sur
+laquelle tourne Dnsmasq ou sinon la ligne sera ignorée et une erreur sera
+consignée dans le journal des Ã©vénements, ou alors d'un nom d'interface. Si un nom
+d'interface est donné, alors les requêtes vers le serveur de nom seront envoyées
+depuis cette interface; si une adresse ip est donnée, alors l'adresse source de
+la requête sera l'adresse en question. L'option query-port est ignorée pour tous
+les serveurs ayant une adresse source spécifiée, mais il est possible de la donner
+directement dans la spécification de l'adresse source. Forcer les requêtes Ã  Ãªtre
+émises depuis une interface spécifique n'est pas possible sur toutes les plateformes
+supportées par dnsmasq.
+.TP
+.B \-A, --address=/<domaine>/[domaine/]<adresse IP>
+Spécifie une adresse IP Ã  retourner pour toute requête pour les domaines fournis
+en option. Les requêtes pour ce(s) domaine(s) ne sont jamais transmises aux
+serveurs amonts et reçoivent comme réponse l'adresse IP spécifiée qui peut Ãªtre
+une adresse IPv4 ou IPv6. Pour donner Ã  la fois une adresse IPv4 et une adresse
+IPv6 pour un domaine, utiliser plusieurs options
+.B -A.
+Il faut noter que le
+contenu du fichier /etc/hosts et de celui des baux DHCP supplante ceci pour des
+noms individuels. Une utilisation courante de cette option est de rediriger la
+totalité du domaine doubleclick.net vers un serveur web local afin d'éviter les
+bannières publicitaires. La spécification de domaine fonctionne de la même façon
+que
+.B  --server,
+avec la caractéristique supplémentaire que
+.B /#/
+coïncide avec tout domaine. Ainsi,
+.B --address=/#/1.2.3.4
+retournera 1.2.3.4 pour toute requête
+n'ayant de réponse ni dans /etc/hosts, ni dans les baux DHCP, et n'étant pas
+transmise Ã  un serveur spécifique par le biais d'une directive
+.B --server.
+.TP
+.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préference>]
+Spécifie un enregistrement de type MX pour <nom de l'hôte> retournant le nom
+donné dans <nom du MX> (s'il est présent), ou sinon le nom spécifié dans
+l'option
+.B --mx-target
+si elle est présente. Sinon retourne le nom de la machine
+sur laquelle Dnsmasq tourne. La valeur par défaut (spécifiée dans l'option
+.B --mx-target
+) est utile dans un réseau local pour rediriger les courriers
+électroniques vers un serveur central. La valeur de préférence est optionnelle
+et vaut par défaut 1 si elle n'est pas spécifiée. Plus d'une entrée MX peut Ãªtre
+fournie pour un hôte donné.
+.TP 
+.B \-t, --mx-target=<nom d'hôte>
+Spécifie la réponse par défaut fournie par Dnsmasq pour les requêtes sur des
+enregistrements de type MX. Voir
+.B --mx-host.
+Si
+.B --mx-target
+est donné mais pas de
+.B --mx-host,
+alors Dnsmasq retourne comme réponse un enregistrement MX
+contenant le nom d'hôte spécifié dans l'option
+.B --mx-target
+pour toute requête
+concernant le MX de la machine sur laquelle tourne Dnsmasq.
+.TP
+.B \-e, --selfmx
+Définit, pour toutes les machines locales, un MX correspondant Ã  l'hôte
+considéré. Les machines locales sont celles définies dans le fichier /etc/hosts
+ou dans un bail DHCP.
+.TP 
+.B \-L, --localmx
+Définit, pour toutes les machines locales, un enregistrement MX pointant sur
+l'hôte spécifié par mx-target (ou la machine sur laquelle Dnsmasq tourne). Les
+machines locales sont celles définies dans le fichier /etc/hosts ou dans un bail
+DHCP.
+.TP
+.B \-W --srv-host=<_service>.<_protocole>.[<domaine>],[<cible>[,<port>[,<priorité>[,<poids>]]]]
+Spécifie un enregistrement DNS de type SRV. Voir la RFC2782 pour plus de
+détails. Si le champs <domaine> n'est pas fourni, prends par défaut la valeur
+fournie dans l'option
+.B --domain.
+La valeur par défaut pour le domaine est vide et le port par défaut est 1, alors
+que les poids et priorités par défaut sont 0. Attention lorsque vous transposez
+des valeurs issues d'une configuration BIND : les ports, poids et priorités sont
+dans un ordre différents. Pour un service/domaine donné, plus d'un
+enregistrement SRV est autorisé et tous les enregistrements qui coïncident sont
+retournés dans la réponse.
+.TP
+.B \-Y, --txt-record=<nom>[[,<texte>],<texte>]
+Définit un enregistrement DNS de type TXT. La valeur de l'enregistrement TXT est
+un ensemble de chaînes de caractères, donc un nombre variable de chaînes de
+caractères peuvent Ãªtre spécifiées, séparées par des virgules. Utilisez des
+guillemets pour mettre une virgule dans une chaîne de caractères. Notez que la
+longueur maximale pour une chaîne est de 255 caractères, les chaînes plus
+longues Ã©tant découpées en morceaux de 255 caractères de longs.
+.TP
+.B --ptr-record=<nom>[,<cible>]
+Définit un enregistrement DNS de type PTR.
+.TP
+.B --naptr-record=<nom>,<ordre>,<préférence>,<drapeaux>,<service>,<expr. régulière>[,<remplacement>]
+Retourne un enregistrement de type NAPTR, tel que spécifié dans le RFC3403.
+.TP
+.B --cname=<cname>,<cible>
+Retourne un enregistrement de type CNAME qui indique que <cname> est en
+réalité <cible>. Il existe des contraintes significatives sur la valeur
+de cible; il doit s'agir d'un nom DNS qui est connu de dnsmasq via /etc/hosts
+(ou un fichier hôtes additionnel) ou via DHCP. Si une cible ne satisfait
+pas ces critères, le CNAME est ignoré. Le CNAME doit Ãªtre unique, mais
+il est autorisé d'avoir plus d'un CNAME pointant vers la même cible.
+.TP
+.B --interface-name=<nom>,<interface>
+Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
+l'interface donnée en argument. Cette option spécifie un enregistrement de type
+A pour le nom donné en argument de la même façon que s'il Ã©tait défini par une
+ligne de /etc/hosts, sauf que l'adresse n'est pas constante mais dépendante de
+l'interface définie. Si l'interface est inactive, non existante ou non
+configurée, une réponse vide est fournie. Un enregistrement inverse (PTR) est
+également créé par cette option, associant l'adresse de l'interface avec le nom.
+Plus d'un nom peut Ãªtre associé Ã  une interface donnée en répétant cette option
+plusieurs fois; dans ce cas, l'enregistrement inverse pointe vers le nom fourni
+dans la première instance de cette option.
+.TP
+.B --add-mac
+Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises aux serveurs
+amonts. Cela peut Ãªtre utilisé dans un but de filtrage DNS par les serveurs
+amonts. L'adresse MAC peut uniquement Ãªtre ajoutée si le requêteur est sur le
+même sous-réseau que le serveur dnsmasq. Veuillez noter que le mécanisme
+utilisé pour effectuer cela (une option EDNS0) n'est pas encore standardisée,
+aussi cette fonctionalité doit Ãªtre considérée comme expérimentale. Notez
+également qu'exposer les adresses MAC de la sorte peut avoir des implications
+en termes de sécurité et de vie privée.
+.TP
+.B \-c, --cache-size=<taille>
+Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms.
+Définir une valeur de zéro désactive le cache.
+.TP
+.B \-N, --no-negcache
+Désactive le "cache négatif". Le "cache négatif" permet Ã  Dnsmasq de se souvenir
+des réponses de type "no such domain" fournies par les serveurs DNS en amont et
+de fournir les réponses sans avoir Ã  re-transmettre les requêtes aux serveurs
+amont.
+.TP
+.B \-0, --dns-forward-max=<nombre de requêtes>
+Définit le nombre maximum de requêtes DNS simultanées. La valeur par défaut est
+150, ce qui devrait Ãªtre suffisant dans la majorité des configurations. La seule
+situation identifiée dans laquelle cette valeur nécessite d'être augmentée est
+lorsqu'un serveur web a la résolution de nom activée pour l'enregistrement de
+son journal des requêtes, ce qui peut générer un nombre important de requêtes
+simultanées.
+.TP
+.B --proxy-dnssec
+Un resolveur sur une machine cliente peut effectuer la validation DNSSEC de
+deux façons : il peut effectuer lui-même les opérations de chiffrements sur
+la réponse reçue, ou il peut laisser le serveur récursif amont faire la
+validation et positionner un drapeau dans la réponse au cas où celle-ci est
+correcte. Dnsmasq n'est pas un validateur DNSSEC, aussi il ne peut effectuer
+la validation comme un serveur de nom récursif, cependant il peut retransmettre
+les résultats de validation de ses serveurs amonts. Cette option permet
+l'activation de cette fonctionalité. Vous ne devriez utiliser cela que si vous
+faites confiance aux serveurs amonts
+.I ainsi que le réseau entre vous et eux.
+Si vous utilisez le premier mode DNSSEC, la validation par le resolveur des
+clients, cette option n'est pas requise. Dnsmasq retourne toujours toutes les
+données nécessaires par un client pour effectuer la validation lui-même.
+.TP
+.B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label],]<adresse de début>,<adresse de fin>[,<masque de réseau>[,<broadcast>]][,<durée de bail>]
+Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
+<adresse de début> et <adresse de fin> et Ã  partir des adresses définies
+statiquement dans l'option
+.B dhcp-host.
+Si une durée de bail est donnée, alors les baux seront donnés pour cette
+durée. La durée de bail est donnée en secondes, en minutes (exemple : 45m),
+en heures (exemple : 1h) ou Ãªtre la chaine de caractère "infinite" pour une
+durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par défaut
+de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2
+minutes.
+Cette option peut Ãªtre répétée, avec différentes adresses,
+pour activer le service DHCP sur plus d'un réseau. Pour des réseaux directement
+connectés (c'est-à-dire des réseaux dans lesquels la machine sur laquelle tourne
+Dnsmasq possède une interface), le masque de réseau est optionnel. Il est par
+contre requis pour les réseaux pour lesquels le service DHCP se fait via un
+relais DHCP ("relay agent"). L'adresse de broadcast est toujours optionnelle.
+
+Il est toujours possible d'avoir plus d'une plage DHCP pour un même
+sous-réseau.
+L'identifiant de label optionnel
+.B set:<label>
+fournie une Ã©tiquette alphanumérique qui identifie ce réseau, afin de permettre
+la fourniture d'options DHCP spécifiques Ã  chaque réseau.
+Lorsque préfixé par 'tag:', la signification change, et au lieu de définir un
+label, il définit le label pour laquelle la règle s'applique. Un seul label peut-
+être défini mais plusieurs labels peuvent coïncider.
+
+L'adresse de fin peut Ãªtre remplacée par le mot-clef
+.B static
+("statique") qui indique Ã  Dnsmasq d'activer le service DHCP pour le réseau
+spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP : Seuls
+les hôtes possédant des adresses IP statiques fournies via 
+.B dhcp-host
+ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP.
+
+L'adresse de fin peut-être remplacée par le mot-clef
+.B proxy
+, auquel cas Dnsmasq fournira un service de DHCP proxy pour le sous-réseau
+spécifié. (voir
+.B pxe-prompt
+et
+.B pxe-service
+pour plus de détails).
+
+La section interface:<nom d'interface> n'est normalement pas utilisée. Se
+référer aux indications de la section NOTES pour plus de détail Ã  ce sujet.
+.TP
+.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
+Spécifie les paramètres DHCP relatifs Ã  un hôte. Cela permet Ã  une machine
+possédant une adresse matérielle spécifique de se voir toujours allouée les
+mêmes nom d'hôte, adresse IP et durée de bail. Un nom d'hôte spécifié comme
+ceci remplace le nom fourni par le client DHCP de la machine hôte. Il est
+également possible d'omettre l'adresse matérielle et d'inclure le nom d'hôte,
+auquel cas l'adresse IP et la durée de bail s'appliqueront Ã  toute machine se
+réclamant de ce nom. Par exemple
+.B --dhcp-host=00:20:e0:3b:13:af,wap,infinite 
+spécifie Ã  Dnsmasq de fournir Ã  la machine d'adresse matérielle
+00:20:e0:3b:13:af le nom, et un bail de durée indéterminée.
+
+.B --dhcp-host=lap,192.168.0.199 
+spécifie Ã  Dnsmasq d'allouer toujours Ã  la machine portant le nom lap
+l'adresse IP 192.168.0.199.
+
+Les adresses allouées de la sorte ne sont pas contraintes Ã  une plage d'adresse
+spécifiée par une option --dhcp-range, mais elles se trouver dans le même
+sous-réseau qu'une plage dhcp-range valide. Pour les sous-réseaux qui n'ont pas
+besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la
+déclaration de plage d'adresses dhcp-range.
+
+Il est possible
+d'utiliser des identifiants clients plutôt que des adresses matérielles pour
+identifier les hôtes, en préfixant par ceux-ci par 'id:'. Ainsi, 
+.B --dhcp-host=id:01:02:03:04,..... 
+réfère Ã  l'hôte d'identifiant 01:02:03:04. Il est Ã©galement possible de
+spécifier l'identifiant client sous la forme d'une chaîne de caractères, comme
+ceci :
+.B --dhcp-host=id:identifiantclientsousformedechaine,..... 
+
+L'option spéciale id:* signifie : "ignorer tout identifiant client et n'utiliser
+que l'adresse matérielle". Cela est utile lorsqu'un client présente un
+identifiant client mais pas les autres.
+
+Si un nom apparaît dans /etc/hosts, l'adresse associée peut Ãªtre allouée Ã  un
+bail DHCP mais seulement si une option
+.B --dhcp-host
+spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut-être donné dans
+une option
+.B dhcp-host
+, mais les alias sont possibles au travers de l'utilisation des CNAMEs. (Voir
+.B --cname
+).
+Le mot clef "ignore" ("ignorer") indique
+à Dnsmasq de ne jamais fournir de bail DHCP Ã  une machine. La machine peut Ãªtre
+spécifiée par son adresse matérielle, son identifiant client ou son nom d'hôte.
+Par exemple
+.B --dhcp-host=00:20:e0:3b:13:af,ignore
+Cela est utile lorsqu'un autre serveur DHCP sur le réseau doit Ãªtre utilisé par
+certaines machines.
+
+Le paramètre set:<identifiant réseau> permet de définir un
+identifiant de réseau lorsque l'option dhcp-host est utilisée. Cela peut servir
+à sélectionner des options DHCP juste pour cet hôte. Plus d'un label peut Ãªtre
+fourni dans une directive dhcp-host (et dans cette seule directive). Lorsqu'une
+machine coïncide avec une directive dhcp-host (ou une impliquée par
+/etc/ethers), alors le label réservé "known" ("connu") est associé. Cela permet Ã 
+Dnsmasq d'être configuré pour ignorer les requêtes issus de machines inconnue
+ par le biais de 
+.B --dhcp-ignore=tag:!known.
+
+Les adresses ethernet (mais pas les identifiants clients) peuvent Ãªtre définies
+avec des octets joker, ainsi par exemple
+.B --dhcp-host=00:20:e0:3b:13:*,ignore 
+demande Ã  Dnsmasq d'ignorer une gamme d'adresses matérielles. Il est  Ã  noter
+que "*" doit-être précédé d'un caractère d'échappement ou mis entre guillemets
+lorsque spécifié en option de ligne de commande, mais pas dans le fichier de
+configuration.
+
+Les adresses matérielles coïncident en principe avec n'importe
+quel type de réseau (ARP), mais il est possible de les limiter Ã  un seul type
+ARP en les précédant du type ARP (en Hexadécimal) et de "-". Ainsi
+.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4 
+coïncidera uniquement avec des adresses matérielles Token-Ring, puisque le type
+ARP pour une adresse Token-Ring est 6.
+
+Un cas spécial correspond Ã  l'inclusion d'une ou plusieurs adresses
+matérielles, c-à-d :
+.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2.
+Cela permet Ã  une adresse IP d'être associé Ã  plusieurs adresses
+matérielles, et donne Ã  dnsmasq la permission d'abandonner un bail DHCP
+attribué Ã  l'une de ces adresses lorsqu'une autre adresse dans la liste
+demande un bail. Ceci est une opération dangereuse qui ne fonctionnera
+de manière fiable que si une adresse matérielle est active Ã  un moment
+donné et dnsmasq n'a aucun moyen de s'assurer de cela. Cela est utile,
+par exemple, pour allouer une adresse IP stable Ã  un laptop qui
+aurait Ã  la fois une connexion filaire et sans-fil.
+.TP
+.B --dhcp-hostsfile=<chemin>
+Lis les informations d'hôtes DHCP dans le fichier spécifié. Si l'argument est
+un chemin vers un répertoire, lis tous les fichiers de ce répertoire. Le
+fichier contient des informations Ã  raison d'un hôte par ligne. Le format
+d'une ligne est la même que le texte fourni Ã  la droite sur caractère "=" dans
+l'option
+.B --dhcp-host.
+L'avantage de stocker les informations sur les hôtes DHCP dans ce fichier est
+que celles-ci peuvent Ãªtre modifiées sans recharger Dnsmasq; le fichier sera
+relu lorsque Dnsmasq reçoit un signal SIGHUP.
+.TP
+.B --dhcp-optsfile=<chemin>
+Lis les informations relatives aux options DHCP dans le fichier spécifié. Si
+l'argument est un chemin vers un répertoire, lis tous les fichiers de ce
+répertoire. L'intérêt d'utiliser cette option est le même que pour
+ --dhcp-hostsfile : le fichier spécifié sera rechargé Ã  la réception par
+dnsmasq d'un signal SIGHUP. Notez qu'il est possible d'encoder l'information
+via
+.B --dhcp-boot
+en utilisant les noms optionnels bootfile-name, server-ip-address et
+tftp-server. Ceci permet d'inclure ces options dans un fichier "dhcp-optsfile".DNSMASQ_SUPPLIED_HOSTNAME
+.TP
+.B \-Z, --read-ethers
+Lis les informations d'hôtes DHCP dans le fichier /etc/ethers. Le format de
+/etc/ethers est une adresse matérielle suivie, soit par un nom d'hôte, soit par
+une adresse IP sous la forme de 4 chiffres séparés par des points. Lorsque lu
+par Dnsmasq, ces lignes ont exactement le même effet que l'option
+.B --dhcp-host
+contenant les mêmes informations. /etc/ethers est relu Ã  la réception d'un
+signal SIGHUP par Dnsmasq.
+.TP
+.B \-O, --dhcp-option=[tag:<label>,[tag:<label>]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]]
+Spécifie des options différentes ou supplémentaires pour des clients DHCP. Par
+défaut, Dnsmasq envoie un ensemble standard d'options aux clients DHCP : le
+masque de réseau et l'adresse de broadcast sont les mêmes que pour l'hôte
+sur lequel tourne Dnsmasq, et le serveur DNS ainsi que la route par défaut
+prennent comme valeur l'adresse de la machine sur laquelle tourne Dnsmasq. Si
+une option de nom de domaine a Ã©té définie, son contenu est transmis. Cette
+option de configuration permet de changer toutes ces valeurs par défaut, ou de
+spécifier d'autres options. L'option DHCP Ã  transmettre peut Ãªtre fournie sous
+forme d'un nombre décimal ou sous la forme "option:<nom d'option>". Les nombres
+correspondants aux options sont définis dans la RFC2132 et suivants. Les noms
+d'options connus par Dnsmasq peuvent Ãªtre obtenus via "Dnsmasq --help dhcp".
+Par exemple, pour définir la route par défaut Ã  192.168.4.4, il est possible de
+faire
+.B --dhcp-option=3,192.168.4.4 
+ou
+.B --dhcp-option = option:router, 192.168.4.4
+ou encore, pour positionner l'adresse du serveur de temps Ã  192.168.0.4, on peut
+faire
+.B --dhcp-option = 42,192.168.0.4 
+ou 
+.B --dhcp-option = option:ntp-server, 192.168.0.4
+L'adresse 0.0.0.0 prends ici le sens "d'adresse de la machine sur laquelle
+tourne Dnsmasq". Les types de données autorisées sont des adresses IP sous la
+forme de 4 chiffres séparés par des points, un nombre décimal, une liste de
+caractères hexadécimaux séparés par des 2 points, ou une chaîne de caractères.
+Si des labels optionnels sont fournis, alors cette option n'est envoyée
+qu'aux réseaux dont tous les labels coïncident avec ceux de la requête.
+
+Un traitement spécial est effectué sur les chaînes de caractères fournies pour
+l'option 119, conformément Ã  la RFC 3397. Les chaînes de caractères ou les
+adresses IP sous forme de 4 chiffres séparés par des points donnés en arguments
+de l'option 120 sont traités conforméments Ã  la RFC 3361. Les adresses IP sous
+forme de 4 chiffres séparés par des points suivies par une barre montante "/",
+puis une taille de masque sont encodés conforméments Ã  la RFC 3442.
+
+Attention : aucun test n'étant fait pour vérifier que des données d'un type
+adéquat sont envoyées pour un numéro d'option donné, il est tout Ã  fait possible
+de persuader Dnsmasq de générer des paquets DHCP illégaux par une utilisation
+incorrecte de cette option. Lorsque la valeur est un nombre décimal, Dnsmasq
+doit déterminer la taille des données. Cela est fait en examinant le numéro de
+l'option et/ou la valeur, mais peut-être Ã©vité en rajoutant un suffixe d'une
+lettre comme suit :
+b = un octet, s = 2 octets, i = 4 octets. Cela sert essentiellement pour des
+options encapsulées de classes de vendeurs (voir plus bas), pour lesquelles 
+Dnsmasq ne peut déterminer la taille de la valeur. Les données d'options
+consistant uniquement de points et de décimaux sont interprétées par Dnsmasq
+comme des adresses IP, et envoyées comme telles. Pour forcer l'envoi sous forme
+de chaîne de caractère, il est nécessaire d'utiliser des guillemets doubles. Par
+exemple, l'utilisation de l'option 66 pour fournir une adresse IP sous la forme
+d'une chaîne de caractères comme nom de serveur TFTP, il est nécessaire de faire
+comme suit :
+.B --dhcp-option=66,"1.2.3.4"
+
+Les options encapsulées de classes de vendeurs peuvent-être aussi spécifiées en
+utilisant
+.B --dhcp-option
+: par exemple
+.B --dhcp-option=vendor:PXEClient,1,0.0.0.0
+envoie l'option encapsulée de classe de vendeur "mftp-address=0.0.0.0" Ã 
+n'importe quel client dont la classe de vendeur correspond Ã  "PXEClient". La
+correspondance pour les classes de vendeur s'effectue sur des sous-chaînes de
+caractères (voir
+.B --dhcp-vendorclass
+pour plus de détails). Si une option de
+classe de vendeur (numéro 60) est envoyée par Dnsmasq, alors cela est utilisé
+pour sélectionner les options encapsulées, de préférence Ã  toute option envoyée
+par le client. Il est possible d'omettre complètement une classe de vendeur :
+.B --dhcp-option=vendor:,1,0.0.0.0
+Dans ce cas l'option encapsulée est toujours envoyée.
+
+Les options peuvent-être encapsulées au sein d'autres options :
+par exemple
+.B --dhcp-option=encap:175, 190, "iscsi-client0"
+enverra l'option 175, au sein de laquelle se trouve l'option 190.
+Plusieurs options encapsulées avec le même numéro d'option seront correctement
+combinées au sein d'une seule option encapsulée. Il n'est pas possible de
+spécifier encap: et vendor: au sein d'une même option dhcp.
+
+La dernière variante pour les options encapsulées est "l'option de Vendeur
+identifiant le vendeur" ("Vendor-Identifying Vendor Options") telle que
+décrite dans le RFC3925. Celles-ci sont spécifiées comme suit :
+.B --dhcp-option=vi-encap:2, 10, "text"
+Le numéro dans la section vi-encap: est le numéro IANA de l'entreprise servant
+à identifier cette option.
+
+L'adresse 0.0.0.0 n'est pas traitée de manière particulière lorsque fournie dans
+une option encapsulée.
+.TP
+.B --dhcp-option-force=[tag:<label>,[tag:<label>]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]]
+Cela fonctionne exactement de la même façon que
+.B --dhcp-option
+sauf que cette option sera toujours envoyée, même si le client ne la demande pas
+dans la liste de paramêtres requis. Cela est parfois nécessaire, par exemple lors
+de la fourniture d'options Ã  PXELinux.
+.TP
+.B --dhcp-no-override
+Désactive la réutilisation des champs DHCP nom de serveur et nom de
+fichier comme espace supplémentaire pour les options. Si cela est
+possible, dnsmasq déplace les informations sur le serveur de démarrage
+et le nom de fichier (fournis par 'dhcp-boot') en dehors des champs
+dédiés Ã  cet usage dans les options DHCP. Cet espace supplémentaire est
+alors disponible dans le paquet DHCP pour d'autres options, mais peut, dans
+quelques rares cas, perturber des clients vieux ou défectueux. Cette
+option force le comportement Ã  l'utilisation des valeurs "simples et sûres"
+afin d'éviter des problèmes dans de tels cas.
+.TP
+.B \-U, --dhcp-vendorclass=set:<label>,<classe de vendeur>
+Associe une chaîne de classe de vendeur Ã  un label. La plupart
+des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui
+représente, d'une certaine façon, le type d'hôte. Cette option associe des
+classes de vendeur Ã  des labels, de telle sorte que des options DHCP peuvent-être
+fournie de manière sélective aux différentes classes d'hôtes. Par exemple,
+.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
+ou
+.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
+permet de n'allouer des options qu'aux imprimantes HP de la manière suivante :
+.B --dhcp-option=tag:printers,3,192.168.4.4
+La chaîne de caractères de la classe de vendeur founie en argument est cherchée
+en temps que sous-chaîne de caractères au sein de la classe de vendeur fournie
+par le client, de façon Ã  permettre la recherche d'un sous-ensemble de la chaîne
+de caractères ("fuzzy matching"). Le préfixe set: est optionnel mais autorisé
+afin de conserver une certaine homogénéité.
+.TP
+.B \-j, --dhcp-userclass=set:<label>,<classe utilisateur>
+Associe une chaîne de classe d'utilisateur Ã  un label (effectue la
+recherche sur des sous-chaînes, comme pour les classes de vendeur). La plupart
+des clients permettent de configurer une "classe d'utilisateur". Cette option
+associe une classe d'utilisateur Ã  un label, de telle manière qu'il soit
+possible de fournir des options DHCP spécifiques Ã  différentes classes d'hôtes.
+Il est possible, par exemple, d'utiliser ceci pour définir un serveur
+d'impression différent pour les hôtes de la classe "comptes" et ceux de la
+classe "ingénierie".
+.TP
+.B \-4, --dhcp-mac=set:<label>,<adresse MAC>
+Associe une adresse matérielle (MAC) Ã  un label. L'adresse
+matérielle peut inclure des jokers. Par exemple
+.B --dhcp-mac=set:3com,01:34:23:*:*:*
+permet de définir le label "3com" pour n'importe quel hôte dont l'adresse
+matérielle coïncide avec les critères définis.
+.TP
+.B --dhcp-circuitid=set:<label>,<identifiant de circuit>, --dhcp-remoteid=set:<label>,<identifiant distant>
+Associe des options de relais DHCP issus de la RFC3046 Ã  des labels.
+Cette information peut-être fournie par des relais DHCP. L'identifiant
+de circuit ou l'identifiant distant est normalement fourni sous la forme d'une
+chaîne de valeurs hexadécimales séparées par des ":", mais il est Ã©galement
+possible qu'elle le soit sous la forme d'une simple chaîne de caractères. Si
+l'identifiant de circuit ou d'agent correspond exactement Ã  celui fourni par le
+relais DHCP, alors le label est apposé.
+.TP
+.B --dhcp-subscrid=set:<label>,<identifiant d'abonné>
+Associe des options de relais DHCP issues de la RFC3993 Ã  des labels.
+.TP
+.B --dhcp-proxy[=<adresse ip>]......
+Un agent relai DHCP normal est uniquement utilisé pour faire suivre les
+éléments initiaux de l'interaction avec le serveur DHCP. Une fois que le
+client est configuré, il communique directement avec le serveur. Cela n'est pas
+souhaitable si le relais rajoute des informations supplémentaires aux paquets
+DHCP, telles que celles utilisées dans
+.B dhcp-circuitid
+et
+.B dhcp-remoteid.
+Une implémentation complète de relai peut utiliser l'option serverid-override
+de la RFC 5107 afin de forcer le serveur DHCP Ã  utiliser le relai en temps que
+proxy complet, de sorte que tous les paquets passent par le relai. Cette option
+permet d'obtenir le même résultat pour des relais ne supportant pas la RFC
+5107. Fournie seule, elle manipule la valeur de server-id pour toutes les
+interactions via des relais. Si une liste d'adresses IP est donnée, seules les
+interactions avec les relais dont l'adresse est dans la liste seront affectées.
+.TP
+.B --dhcp-match=set:<label>,<numéro d'option>|option:<nom d'option>|vi-encap:<entreprise>[,<valeur>]
+Si aucune valeur n'est spécifiée, associe le label si le client
+envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est
+fournie, positionne le label seulement dans le cas où l'option est fournie et
+correspond Ã  la valeur. La valeur peut-être de la forme "01:ff:*:02", auquel
+cas le début de l'option doit correspondre (en respectant les jokers). La
+valeur peut aussi Ãªtre de la même forme que dans
+.B dhcp-option
+, auquel cas l'option est traitée comme un tableau de valeur, et un des
+éléments doit correspondre, ainsi
+
+--dhcp-match=set:efi-ia32,option:client-arch,6
+
+spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste
+d'architectures envoyé par le client au sein de l'option 93. (se réferer
+au RFC 4578 pour plus de détails). Si la valeur est un chaine de caractères,
+celle-ci est recherchée (correspondance en temps que sous-chaîne).
+
+Pour la forme particulière vi-encap:<numéro d'entreprise>, la comparaison se
+fait avec les classes de vendeur "identifiant de vendeur" ("vendor-identifying
+vendor classes") pour l'entreprise dont le numéro est fourni en option.
+Veuillez vous réferer Ã  la RFC 3925 pour plus de détail.
+.TP
+.B --tag-if=set:<label>[,set:<label>[,tag:<label>[,tag:<label>]]]
+Effectue une opération booléenne sur les labels. Si tous les labels
+apparaissant dans la liste tag:<label> sont positionnés, alors tous les
+la de la liste "set:<labels>" sont positionnés (ou supprimés, dans le cas
+où "tag:!<label>" utilisé).
+Si aucun tag:<label> n'est spécifié, alors tous les labels fournis par
+set:<label> sont positionnés.
+N'importe quel nombre de set: ou tag: peuvent Ãªtre fournis, et l'ordre est sans
+importance.
+Les lignes tag-if sont executées dans l'ordre, ce qui fait que si un label dans
+tag:<label> est un label positionné par une rêgle
+.B tag-if,
+la ligne qui positionne le label doit précéder celle qui le teste.
+.TP
+.B \-J, --dhcp-ignore=tag:<label>[,tag:<label>]
+Lorsque tous les labels fournis dans l'option sont présents, ignorer l'hôte et
+ne pas donner de bail DHCP.
+.TP
+.B --dhcp-ignore-names[=tag:<label>[,tag:<label>]]
+Lorsque tous les labels fournis dans l'option sont présents, ignorer le
+nom de machine fourni par l'hôte. Il est Ã  noter que, Ã  la différence de
+l'option "dhcp-ignore", il est permis de ne pas fournir de label.
+Dans ce cas, les noms d'hôtes fournis par les clients DHCP seront toujours
+ignorés, et les noms d'hôtes seront ajoutés au DNS en utilisant uniquement la
+configuration dhcp-host de Dnsmasq, ainsi que le contenu des fichiers /etc/hosts
+et /etc/ethers.
+.TP
+.B --dhcp-generate-names=tag:<label>[,tag:<label>]
+Générer un nom pour les clients DHCP qui autrement n'en aurait pas, en
+utilisant l'adresse MAC sous sa forme hexadécimale, séparée par des tirets.
+Noter que si un hôte fourni un nom, celui-ci sera utilisé de préférence au nom
+autogénéré, Ã  moins que
+.B --dhcp-ignore-names 
+ne soit positionné.
+.TP
+.B --dhcp-broadcast=[tag:<label>[,tag:<label>]]
+Lorsque tous les labels fournis dans l'option sont présents, toujours utiliser
+le broadcast pour communiquer avec l'hôte lorsque celui-ci n'est
+pas configuré. Il est possible de ne spécifier aucun label, auquel cas cette
+option s'applique inconditionnellement. La plupart des clients DHCP nécessitant une réponse par le biais
+d'un broadcast activent une option dans leur requête, ce qui fait que cela
+se fait automatiquement, mais ce n'est pas la cas de certains vieux clients BOOTP.
+.TP
+.B \-M, --dhcp-boot=[tag:<label>,]<nom de fichier>,[<nom de serveur>[,<adresse de serveur>]]
+Spécifie les options BOOTP devant Ãªtre retournées par le serveur DHCP. Le nom de
+serveur ainsi que l'adresse sont optionnels : s'ils ne sont pas fournis, le nom
+est laissé vide et l'adresse fournie est celle de la machine sur laquelle
+s'exécute Dnsmasq. Si Dnsmasq founit un service TFTP (voir
+.B --enable-tftp
+), alors seul un nom de fichier est requis ici pour permettre un démarrage par
+le réseau.
+Si d'éventuels labels sont fournis, ils doivent coïncider avec
+ceux du client pour que cet Ã©lement de configuration lui soit envoyé.
+.TP
+.B --pxe-service=[tag:<label>,]<CSA>,<entrée de menu>[,<nom de fichier>|<type de service de démarrage>][,<adresse de serveur>]
+La plupart des ROMS de démarrage PXE ne permettent au système PXE que la simple
+obtention d'une adresse IP, le téléchargement du fichier spécifié dans
+.B dhcp-boot
+et son exécution. Cependant, le système PXE est capable de fonctions bien plus
+complexes pour peu que le serveur DHCP soit adapté.
+
+Ceci spécifie l'option de démarrage qui apparaitra dans un menu de démarrage
+PXE. <CSA> est le type du système client. Seuls des types de services valides
+apparaitront dans un menu. Les types connus sont x86PC, PC98, IA64_EFI, Alpha,
+Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI et X86-64_EFI;
+D'autres types peuvent-être spécifiés sous la forme d'une valeur entière. Le
+paramètre après le texte correspondant Ã  l'entrée dans le menu peut Ãªtre un nom
+de fichier, auquel cas Dnsmasq agit comme un serveur de démarrage et indique au
+client PXE qu'il faut télécharger ce fichier via TFTP, soit depuis ce serveur
+(l'option
+.B enable-tftp 
+doit Ãªtre spécifiée pour que cela marche), soit depuis un autre serveur TFTP
+si une adresse de serveur est fournie.
+Veuillez noter que le suffixe de "couche" (en principe ".0") est fourni par PXE
+et ne doit pas Ãªtre rajouté au nom de fichier. Si une valeur numérique entière
+est fournir pour le type de démarrage, en remplacement du nom de fichier, le
+client PXE devra chercher un service de démarrage de ce type sur le réseau.
+Cette recherche peut Ãªtre faite via broadcast ou directement auprès d'un
+serveur si son adresse IP est fournie dans l'option.
+Si aucun nom de fichier n'est donné ni aucune valeur de type de service de
+démarrage n'est fournie (ou qu'une valeur de 0 est donnée pour le type de
+service), alors l'entrée de menu provoque l'interruption du démarrage par
+le réseau et la poursuite du démarrage sur un média local.
+.TP
+.B --pxe-prompt=[tag:<label>,]<invite>[,<délai>]
+Cette option permet d'afficher une invite Ã  la suite du démarrage PXE. Si un
+délai est fourni, alors la première entrée du menu de démarrage sera
+automatiquement exécutée après ce délai. Si le délai vaut 0, alors la première
+entrée disponible sera exécutée immédiatement. Si
+.B pxe-prompt
+est omis, le système attendra un choix de l'utilisateur s'il existe plusieurs
+entrées dans le menu, ou démarrera immédiatement dans le cas où il n'y a qu'une
+seule entrée. Voir
+.B pxe-service 
+pour plus de détails sur les entrées de menu.
+
+Dnsmasq peut servir de "proxy-DHCP" PXE, dans le cas où un autre serveur DHCP
+sur le réseau est responsable de l'allocation des adresses IP, auquel cas
+Dnsmasq se contente de fournir les informations données dans les options
+.B pxe-prompt
+et
+.B pxe-service
+pour permettre le démarrage par le réseau. Ce mode est activé en utilisant le
+mot-clef
+.B proxy
+dans
+.B dhcp-range.
+.TP
+.B \-X, --dhcp-lease-max=<nombre>
+Limite Dnsmasq Ã  un maximum de <nombre> baux DHCP. Le défaut est de 1000. Cette
+limite permet d'éviter des attaques de déni de service ("DoS") par des hôtes
+créant des milliers de baux et utilisant beaucoup de mémoire dans le processus
+Dnsmasq.
+.TP
+.B \-K, --dhcp-authoritative
+Cette option doit Ãªtre donnée lorsque Dnsmasq est le seul serveur DHCP sur le
+réseau. Cela change le comportement par défaut qui est celui d'un strict respect
+des RFC, afin que les requêtes DHCP pour des baux inconnus par des hôtes
+inconnus ne soient pas ignorées. Cela permet Ã  de nouveaux hôtes d'obtenir des
+baux sans tenir compte de fastidieuses temporisations ("timeout"). Cela permet
+également Ã  Dnsmasq de reconstruire sa base de donnée contenant les baux sans
+que les clients n'aient besoin de redemander un bail, si celle-ci est perdue.
+.TP
+.B --dhcp-alternate-port[=<port serveur>[,<port client>]]
+Change les ports utilisés par défaut pour le DHCP. Si cette option est donnée
+toute seule sans arguments, alors change les ports utilisés pour le DHCP
+de 67 et 68 respectivement Ã  1067 et 1068. Si un seul argument est donné, ce
+numéro est utilisé pour le port serveur et ce numéro plus 1 est utilisé pour le
+port client. Enfin, en fournissant deux numéros de ports, il est possible de
+spécifier arbitrairement 2 ports Ã  la fois pour le serveur et pour le client DHCP.
+.TP
+.B \-3, --bootp-dynamic[=<identifiant de réseau>[,<identifiant de réseau>]]
+Permet l'allocation dynamique d'adresses IP Ã  des clients BOOTP. Utiliser cette
+option avec précaution, une adresse allouée Ã  un client BOOTP Ã©tant perpétuelle,
+et de fait n'est plus disponibles pour d'autres hôtes. Si aucun argument n'est
+donné, alors cette option permet une allocation dynamique dans tous les cas. Si
+des arguments sont spécifiés, alors l'allocation ne se fait que lorsque tous
+les identifiants coïncident. Il est possible de répeter cette option avec
+plusieurs jeux d'arguments.
+.TP
+.B \-5, --no-ping
+Par défaut, le serveur DHCP tente de s'assurer qu'une adresse n'est pas utilisée
+avant de l'allouer Ã  un hôte. Cela est fait en envoyant une requête ICMP de type
+"echo request" (aussi connue sous le nom de "ping") Ã  l'adresse en question. Si
+le serveur obtient une réponse, alors l'adresse doit déjà Ãªtre utilisée et une
+autre est essayée. Cette option permet de supprimer cette vérification. A
+utiliser avec précaution.
+.TP
+.B --log-dhcp
+Traces additionnelles pour le service DHCP : enregistre toutes les options
+envoyées aux clients DHCP et les labels utilisés pour la
+détermination de celles-ci.
+.TP
+.B \-l, --dhcp-leasefile=<chemin de fichier>
+Utilise le fichier dont le chemin est fourni pour stocker les informations de
+baux DHCP.
+.TP 
+.B \-6 --dhcp-script=<chemin de fichier>
+Lorsqu'un bail DHCP est créé, ou qu'un ancien est supprimé, le fichier dont le
+chemin  est spécifié est exécuté. Le <chemin de fichier> doit Ãªtre un chemin
+absolu, aucune recherche n'est effectuée via la variable d'environnement PATH.
+Les arguments fournis Ã  celui-ci sont soit
+"add" ("ajouter"), "old" ("ancien") ou "del" ("supprimer"), suivi de l'adresse
+MAC de l'hôte puis l'adresse IP et le nom d'hôte si celui-ci est
+connu."add" signifie qu'un bail a Ã©té créé, "del" signifie qu'il a Ã©té supprimé,
+"old" notifie que le bail existait au lancement de Dnsmasq, ou un changement
+d'adresse MAC ou de nom d'hôte pour un bail existant (ou, dans le cas où
+leasefile-ro est spécifié, un changement de durée de bail ou d'identifiant
+d'hôte). Si l'adresse Mac est d'un type de réseau autre qu'ethernet, il est
+nécessaire de la préceder du type de réseau, par exemple "06-01:23:45:67:89:ab"
+pour du token ring. Le processus est exécuté en temps que super-utilisateur 
+(si Dnsmasq a Ã©té lancé en temps que "root"), même si Dnsmasq est configuré 
+pour changer son UID pour celle d'un utilisateur non-privilégié.
+
+L'environnement est hérité de celui de l'invocation du processus Dnsmasq,
+auquel se rajoute quelques unes ou toutes les variables décrites ci-dessous :
+
+DNSMASQ_CLIENT_ID, si l'hôte a fourni un identifiant de client.
+
+DNSMASQ_DOMAIN si le nom de domaine pleinement qualifié de l'hôte est connu, la
+part relative au domaine y est stockée. (Notez que le nom d'hôte transmis comme
+argument au script n'est jamais pleinement qualifié).
+
+Si le client fournit une information de classe de vendeur, un nom d'hôte, ou
+des classes d'utilisateur, celles-ci sont fournies dans les
+variables DNSMASQ_VENDOR_CLASS et DNSMASQ_USER_CLASS0 Ã  DNSMASQ_USER_CLASSn
+et DNSMASQ_SUPPLIED_HOSTNAME respectivement, mais seulement pour les actions
+"add" et "old" lorsqu'un hôte reprend un bail existant, ces variables n'étant
+pas stockées dans la base de baux de Dnsmasq.
+
+Si Dnsmasq a Ã©té compilé avec l'option HAVE_BROKEN_RTC ("horloge RTC
+défectueuse"), alors la durée du bail (en secondes) est stockée dans la
+variable DNSMASQ_LEASE_LENGTH, sinon la date d'expiration du bail est toujours
+stocké dans la variable d'environnement DNSMASQ_LEASE_EXPIRES. Le nombre de
+secondes avant expiration est toujours stocké dans DNSMASQ_TIME_REMAINING.
+
+Si un bail Ã©tait associé Ã  un nom d'hôte et
+que celui-ci est supprimé, un Ã©vênement de type "old" est généré avec le
+nouveau statut du bail, c-à-d sans nom d'hôte, et le nom initial est fourni
+dans la variable d'environnement DNSMASQ_OLD_HOSTNAME.
+
+La variable DNSMASQ_INTERFACE contient le nom de l'interface sur laquelle la
+requête est arrivée; ceci n'est pas renseigné dans le cas des actions "old"
+ayant lieu après un redémarrage de dnsmasq.
+
+La variable DNSMASQ_RELAY_ADDRESS est renseignée si le client a utilisé un
+relai DHCP pour contacter Dnsmasq, si l'adresse IP du relai est connue.
+
+DNSMASQ_TAGS contient tous les labels fournis pendant la transaction DHCP,
+séparés par des espaces.
+
+Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui
+sont ouverts sur /dev/null (sauf en mode déverminage).
+
+Le script n'est pas lancé de manière concurrente : au plus une instance du
+script est executée Ã  la fois (dnsmasq attends qu'une instance de script se
+termine avant de lancer la suivante). Les changements dans la base des baux
+nécessitant le lancement du script sont placé en attente dans une queue jusqu'à
+terminaison d'une instance du script en cours. Si cette mise en queue fait que
+plusieurs changements d'états apparaissent pour un bail donné avant que le
+script puisse Ãªtre lancé, alors les Ã©tats les plus anciens sont supprimés et
+lorsque le script sera finalement lancé, ce sera avec l'état courant du bail.
+
+Au démarrage de Dnsmasq, le script sera invoqué pour chacun des baux existants
+dans le fichier des baux. Le script sera lancé avec l'action "del" pour les
+baux expirés, et "old" pour les autres. Lorsque Dnsmasq reçoit un signal HUP,
+le script sera invoqué avec une action "old" pour tous les baux existants.
+.TP 
+.B --dhcp-scriptuser
+Spécifie l'utilisateur sous lequel le script lease-change doit Ãªtre exécuté. La
+valeur par défaut correspond Ã  l'utilisateur root mais peut-être changée par le
+biais de cette option.
+.TP
+.B \-9, --leasefile-ro
+Supprimer complètement l'usage du fichier servant de base de donnée pour les
+baux DHCP. Le fichier ne sera ni créé, ni lu, ni Ã©crit. Change la façon dont le
+script de changement d'état de bail est lancé (si celui-ci est fourni par le
+biais de l'option
+.B --dhcp-script
+), de sorte que la base de données de baux puisse
+être complètement gérée par le script sur un stockage externe. En addition aux
+actions décrites dans 
+.B  --dhcp-script,
+le script de changement d'état de bail est appellé une fois, au lancement de
+Dnsmasq, avec pour seul argument "init". Lorsqu'appellé de la sorte, le script
+doit fournir l'état de la base de baux, dans le format de fichier de baux de
+Dnsmasq, sur sa sortie standard (stdout) et retourner un code de retour de 0.
+Positionner cette option provoque Ã©galement une invocation du script de
+changement d'état de bail Ã  chaque changement de l'identifiant de client, de
+longueur de bail ou de date d'expiration.
+.TP
+.B --bridge-interface=<interface>,<alias>[,<alias>]
+Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias>
+comme si elles arrivaient de l'interface <interface>. Cette option est
+nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme
+BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont
+pas d'adresse IP.
+.TP
+.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]]
+Spécifie le domaine du serveur DHCP. Le domaine peut Ãªtre donné de manière
+inconditionnelle (sans spécifier de gamme d'adresses IP) ou pour des gammes
+d'adresses IP limitées. Cela a deux effets; tout d'abord, le
+serveur DHCP retourne le domaine Ã  tous les hôtes le demandant, deuxièmement,
+cela spécifie le domaine valide pour les hôtes DHCP configurés. Le but de cela
+est de contraindre les noms d'hôte afin qu'aucun hôte sur le LAN ne puisse
+fournir via DHCP un nom tel que par exemple "microsoft.com" et capturer du
+trafic de manière illégitime. Si aucun nom de domaine n'est spécifié, alors
+les noms d'hôtes avec un nom de domaine (c-à-d un point dans le nom) seront
+interdits et enregistrés dans le journal (logs). Si un suffixe est fourni, alors
+les noms d'hôtes possédant un domaine sont autorisés, pour peu que le nom de
+domaine coïncide avec le nom fourni. De plus, si un suffixe est fourni, alors
+les noms d'hôtes ne possédant pas de nom de domain se voient rajouter le
+suffixe fourni dans l'option
+.B --domain.
+Ainsi, sur mon réseau, je peux configurer
+.B --domain=thekelleys.org.uk
+et avoir une machine dont le nom DHCP serait "laptop". L'adresse IP de cette
+machine sera disponible Ã  la fois pour "laptop" et "laptop.thekelleys.org.uk".
+Si la valeur fournie pour <domaine> est "#", alors le nom de domaine est
+positionné Ã  la première valeur de la directive "search" du fichier
+/etc/resolv.conf (ou Ã©quivalent).
+
+La gamme d'adresses peut Ãªtre de la forme
+<adresse ip>,<adresse ip> ou <adresse ip>/<masque de réseau> voire une simple
+<adresse ip>. Voir
+.B --dhcp-fqdn
+qui peut changer le comportement de dnsmasq relatif aux domaines.
+
+Si la gamme d'adresse est fournie sous la forme
+<adresse ip>/<taille de réseau>, alors le drapeau "local" peut-être rajouté
+qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et
+inverses. C-à-d
+.B --domain=thekelleys.org.uk,192.168.0.0/24,local
+est indentique Ã 
+.B --domain=thekelleys.org.uk,192.168.0.0/24
+--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
+La taille de réseau doit-être de 8, 16 ou 24 pour Ãªtre valide.
+.TP
+.B --dhcp-fqdn
+Dans le mode par défaut, dnsmasq insère les noms non-qualifiés des clients
+DHCP dans le DNS. Pour cette raison, les noms doivent Ãªtre uniques, même si
+deux clients ayant le même nom sont dans deux domaines différents. Si un
+deuxième client DHCP apparaît ayant le même nom qu'un client déjà existant,
+ce nom est transféré au nouveau client. Si
+.B --dhcp-fqdn
+est spécifié, ce comportement change : les noms non qualifiés ne sont plus
+rajoutés dans le DNS, seuls les noms qualifiés le sont. Deux clients DHCP
+avec le même nom peuvent tous les deux garder le nom, pour peu que la partie
+relative au domaine soit différente (c-à-d que les noms pleinements qualifiés
+diffèrent). Pour d'assurer que tous les noms ont une partie domaine, il doit-y
+avoir au moins un
+.B --domain
+sans gamme d'adresses de spécifié lorsque l'option
+.B --dhcp-fqdn 
+est configurée.
+.TP
+.B --enable-tftp[=<interface>]
+Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
+fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
+un accès en lecture est possible; les extensions tsize et blksize sont supportées
+(tsize est seulement supporté en mode octet). Voir dans la section NOTES les
+informations relatives Ã  la spécification de l'interface.
+.TP
+.B --tftp-root=<répertoire>[,<interface>]
+Les fichiers Ã  fournir dans les transferts TFTP seront cherchés en prenant le
+répertoire fourni comme racine. Lorsque cela est fourni, les chemins TFTP
+incluant ".." sont rejetés, afin d'éviter que les clients ne puissent sortir de
+la racine spécifiée. Les chemins absolus (commençant par "/") sont autorisés,
+mais ils doivent Ãªtre Ã  la racine TFTP fournie. Si l'option interface est
+spécifiée, le répertoire n'est utilisé que pour les requêtes TFTP reçues sur
+cette interface.
+.TP
+.B --tftp-unique-root
+Ajouter l'adresse IP du client TFTP en temps qu'élément de chemin, Ã  la suite
+de la racine tftp (adresse sous forme de 4 chiffres séparés par des points).
+Uniquement valable si une racine TFTP est spécifiée et si le répertoire
+correspond existe. Ainsi, si la valeur pour tftp-root est "/tftp" et que le
+client d'adresse IP 1.2.3.4 requiert le fichier "monfichier", alors le chemin
+effective résultant sera "/tftp/1.2.3.4/monfichier" si /tftp/1.2.3.4 existe, ou
+"/tftp/monfichier" dans le cas contraire.
+.TP
+.B --tftp-secure
+Active le mode TFTP sécurisé : sans cela, tout fichier lisible
+par Dnsmasq est disponible via TFTP (les règles de contrôle d'accès unix
+habituelles s'appliquent). Lorsque l'option
+.B --tftp-secure
+est spécifiée, seuls les fichiers possédés par l'utilisateur sous lequel tourne
+le processus Dnsmasq sont accessibles. Si Dnsmasq est exécuté en temps que
+super-utilisateur ("root"), des règles différentes s'appliquent :
+.B --tftp-secure
+n'a aucun effet, mais seuls les fichiers ayant un droit de lecture pour tout le
+monde sont accessibles. Il n'est pas recommandé d'exécuter Dnsmasq sous
+l'utilisateur "root" lorsque le service TFTP est activé, et il est formellement
+déconseillé de le faire sans fournir l'option
+.B --tftp-root.
+Sans cela, en effet, l'accès de tous les fichiers du serveur pour lequel le
+droit de lecture pour tout le monde est positionné ("world-readable") devient
+possible par n'importe quel hôte sur le réseau.
+.TP
+.B --tftp-max=<connexions>
+Définit le nombre maximum de connexions TFTP simultanées autorisées. La valeur
+par défaut est de 50. Lorsqu'un grand nombre de connexions TFTP est spécifié,
+il se peut que la limite de nombre de descripteurs de fichiers par processus
+soit atteinte. Dnsmasq nécessite quelques descripteurs de fichiers, ainsi qu'un
+descripteur de fichier pour chaque connexion TFTP simultanée et pour chacun des
+fichiers devant Ãªtre fournis. De fait, servir le même fichier Ã  n clients ne
+nécessitera qu'environ n + 10 descripteurs de fichiers, alors que fournir des
+fichiers tous différents Ã  n clients utilisera environ (2*n) + 10 descripteurs.
+Si elle est donnée, l'option 
+.B --tftp-port-range
+peut affecter le nombre maximum de connexions concurrentes.
+.TP
+.B --tftp-no-blocksize
+Empêche le serveur TFTP de négocier l'option "blocksize" (taille de bloc) avec
+les clients. Certains clients buggés spécifient cette option mais se comportent
+ensuite de manière incorrecte si celle-ci est accordée.
+.TP
+.B --tftp-port-range=<début>,<fin>
+Un serveur TFTP Ã©coute sur le port prédéfini 69 ("well-known port") pour
+l'initiation de la connexion, mais utilise Ã©galement un port dynamiquement
+alloué pour chaque connexion. Normalement, ces ports sont alloués par
+le système d'exploitation, mais cette option permet de spécifier une gamme
+de ports Ã  utiliser pour les transferts TFTP. Cela peut-être utile si
+TFTP doit traverser un dispositif garde-barrière ("firewall"). La valeur
+de début pour la plage de port ne peut-être inférieure Ã  1025 sauf si
+dnsmasq tourne en temps que super-utilisateur ("root"). Le nombre de
+connexions TFTP concurrentes est limitée par la taille de la gamme de
+ports ainsi spécifiée.
+.TP
+.B --tftp-port-range=<début>,<fin>
+Un serveur TFTP Ã©coute sur un numéro de port bien connu (69) pour l'initiation
+de la connexion, et alloue dynamiquement un port pour chaque connexion. Ces
+numéros de ports sont en principe alloués par le système d'exploitation, mais
+cette option permet de spécifier une gamme de ports Ã  utiliser pour les
+transferts TFTP. Cela peut-être utile lorsque ceux-ci doivent traverser un
+dispositif garde-barrière ("firewall"). Le début de la plage ne peut-être
+inférieur Ã  1024 Ã  moins que Dnsmasq ne fonctionne en temps que
+super-utilisateur ("root"). Le nombre maximal de connexions TFTP concurrentes
+est limitée par la taille de la plage de ports ainsi définie. 
+.TP
+.B \-C, --conf-file=<fichier>
+Spécifie un fichier de configuration différent. L'option "conf-file" est
+également autorisée dans des fichiers de configuration, ce qui permet
+l'inclusion de multiples fichiers de configuration. L'utilisation de "-" comme
+nom de fichier permet la lecture par dnsmasq de sa configuration sur l'entrée standard
+stdin.
+.TP
+.B \-7, --conf-dir=<répertoire>[,<extension de fichier>...]
+Lis tous les fichiers du répertoire spécifié et les traite comme des fichiers de
+configuration. Si des extensions sont données, tout fichier finissant par ces
+extensions seront ignorés. Tout fichier dont le nom se termine en ~ ou commence
+par ., ainsi que ceux commençant ou se terminant par # seront systématiquement
+ignorés.
+Cette option peut Ãªtre donnée en ligne de commande ou dans un fichier de
+configuration.
+.SH FICHIER DE CONFIGURATION
+Au démarrage, Dnsmasq lis
+.I /etc/dnsmasq.conf,
+si ce fichier existe. (Sur FreeBSD, ce fichier est
+.I /usr/local/etc/dnsmasq.conf
+) (voir cependant les options 
+.B \-C
+et
+.B \-7
+). Le format de ce fichier consiste en une option par ligne, exactement comme
+les options longues détaillées dans la section OPTIONS, mais sans Ãªtre précédées
+par "--". Les lignes commençant par # sont des commentaires et sont ignorées.
+Pour les options qui ne peuvent-être spécifiées qu'une seule fois, celle du
+fichier de configuration prends le pas sur celle fournie en ligne de commande.
+Il est possible d'utiliser des guillemets afin d'éviter que les ",",":","." et
+"#" ne soit interprêtés, et il est possible d'utiliser les séquences
+d'échappement suivantes : \\\\ \\" \\t \\e \\b \\r et \\n. Elles correspondent
+respectivement Ã  la barre oblique descendante ("anti-slash"), guillemets doubles,
+tabulation, caractère d'échappement ("escape"), suppression ("backspace"), retour ("return") et
+nouvelle ligne ("newline").
+.SH NOTES
+A la réception d'un signal SIGHUP,
+.B Dnsmasq
+vide son cache et recharge les fichiers
+.I /etc/hosts
+et
+.I /etc/ethers 
+ainsi que tout autre fichier spécifié par les options
+.B --dhcp-hostsfile
+,
+.B --dhcp-optsfile
+ou
+.B --addn-hosts.
+Le script de changement de bail est appellé pour chaque bail DHCP existant. Si
+l'option
+.B --no-poll
+est positionnée, alors le fichier
+.I /etc/resolv.conf
+est Ã©galement rechargé.
+SIGHUP ne provoque PAS de rechargement du fichier de configuration.
+.PP
+A la réception d'un signal SIGUSR1,
+.B Dnsmasq 
+écrit des statistiques dans les traces système. Les informations fournies sont :
+la taille du cache, le nombre de noms ayant Ã©té supprimés du cache avant
+expiration afin de faire de la place pour les nouveaux noms, ainsi que le nombre
+total d'entrées ayant Ã©té insérées dans le cache. Pour chaque serveur amont, il fournit
+le nomnbre de requêtes transmises ainsi que le nombre de requêtes ayant résulté par une
+erreur. Lorsque Dnsmasq a Ã©té lancé via
+.B --no-daemon
+ou lorsque la traçabilité maximale a Ã©té activée (
+.B -q
+), la totalité du contenu du
+cache est de surcroît fournie.
+.PP 
+A la réception d'un signal SIGUSR2 et lorsqu'il enregistre directement ses
+traces dans un fichier (voir
+.B --log-facility
+), alors 
+.B Dnsmasq
+ferme et re-rouvre le fichier de traces. Il faut noter que pendant cette
+opération Dnsmasq ne s'exécute pas en temps que "root". Lorsqu'il créé un
+fichier de traces pour la première fois, Dnsmasq change le propriétaire du
+fichier afin de le faire appartenir Ã  l'utilisateur non "root" sous lequel
+Dnsmasq s'exécute. Le logiciel de rotation de fichiers de trace logrotate doit
+être configuré pour créer un nouveau fichier avec un propriétaire identique au
+fichier existant avant d'envoyer le signal SIGUSR2. Si une requête DNS TCP est
+en cours, l'ancien fichier de traces reste ouvert dans le processus fils qui
+traite la requête TCP et il peut y Ãªtre Ã©crit. Il existe cependant une limite
+de 150 secondes après laquelle tous les processus traitant des requêtes TCP
+expirent : pour cette raison, il est préférable de ne pas configurer la
+compression des fichiers de traces venant juste de faire l'objet d'une rotation.
+Dans le cas de l'utilisation du logiciel logrotate, les options requises sont
+.B create 
+et
+.B delaycompress.
+
+.PP
+Dnsmasq est un logiciel de transmission de requêtes DNS : il n'est pas capable
+d'effectuer une résolution de nom récursive en partant des serveurs DNS racine,
+mais transmet de telles requêtes Ã  un serveur DNS amont capable de telles
+recherches récursives, ce qui est typiquement le cas d'un serveur DNS de FAI.
+Par défaut, Dnsmasq lis
+.I /etc/resolv.conf
+pour découvrir les adresses IP des serveurs DNS amonts Ã  utiliser, puisque cette
+information est en général stockée Ã  cet endroit. A moins que l'option
+.B --no-poll
+ne soit utilisée,
+.B Dnsmasq
+vérifie la date de modification du fichier
+.I /etc/resolv.conf
+(ou l'équivalent si 
+.B \--resolv-file 
+est utilisé), et le relis lorsqu'il change. Cela permet de définir les serveurs
+DNS amont de manière dynamique lorsque PPP ou DHCP sont utilisés, puisque ces
+protocoles fournissent cette information.
+L'absence du fichier
+.I /etc/resolv.conf
+ne conduit pas Ã  une erreur, puisqu'il peut très bien ne pas Ãªtre créé avant
+qu'une connexion PPP ne soit Ã©tablie. Dans ce cas, Dnsmasq vérifie régulièrement
+pour voir si un fichier
+.I /etc/resolv.conf 
+est créé. Dnsmasq peut Ãªtre configuré pour lire plus d'un fichier resolv.conf.
+Cela est utile sur un ordinateur portable où PPP et DHCP peuvent-être utilisés :
+Dnsmasq peut alors Ãªtre configuré pour lire Ã  la fois
+.I /etc/ppp/resolv.conf 
+et
+.I /etc/dhcpc/resolv.conf 
+et utilisera le contenu du fichier ayant changé en dernier, ce qui permet de
+passer automatiquement de serveurs DNS Ã  d'autres.
+.PP
+Les serveurs amonts peuvent aussi Ãªtre spécifiés sur la ligne de commande ou
+dans un fichier de configuration. Ces spécifications de serveurs peuvent
+éventuellement se voir adjoindre d'un nom de domaine qui précise Ã  Dnsmasq quel
+serveur utiliser pour trouver les noms d'un domaine donné.
+.PP
+Pour configurer Dnsmasq afin qu'il se comporte comme un cache pour la machine
+sur laquelle il tourne, mettre "nameserver 127.0.0.1" dans le fichier
+.I /etc/resolv.conf
+afin de forcer les processus locaux Ã  envoyer leurs requêtes Ã  Dnsmasq. Ensuite,
+spécifier les serveurs DNS amont soit en les fournissant directement Ã  Dnsmasq
+via l'option
+.B \--server
+ou alors en mettant leurs adresses dans un autre fichier, par exemple
+.I /etc/resolv.dnsmasq
+et en lançant Dnsmasq avec l'option
+.B \-r /etc/resolv.dnsmasq.
+Cette deuxième technique permet la mise-à-jour dynamique des addresses de
+serveurs DNS amont par le biais de PPP ou DHCP.
+.PP
+Les adresses dans /etc/hosts prennent le dessus sur celles fournies par le
+serveur DNS amont, ainsi "macompagnie.com 1.2.3.4" dans /etc/hosts assure que
+les requêtes pour "macompagnie.com" retourneront toujours 1.2.3.4, même si une
+requête au serveur DNS amont retournerait une adresse différente. Il y a une
+exception Ã  ceci : si le DNS amont contient un CNAME qui pointe vers un nom
+présent dans /etc/hosts, alors la recherche du CNAME via Dnsmasq fournira
+l'adresse DNS amont. Pour contourner cela, il suffit de mettre l'entrée
+correspondant au CNAME dans /etc/hosts.
+.PP
+le système de label fonctionne comme suit : pour chaque requête DHCP, dnsmasq
+associe un ensemble de labels obtenus Ã  partir des lignes de la configuration
+incluant set:<label>, y compris un pour la plage d'adresse (
+.B dhcp-range
+) utilisée pour allouer l'adresse, un pour chaque entrée
+.B dhcp-host
+associée (auquel est rajouté le mot-clef "known" si une entrée dhcp-host
+coïncide).
+
+Le label "bootp" est associé aux requêtes BOOTP, un label dont le nom est le
+nom de l'interface sur laquelle la requête est arrivée.
+
+Pour les lignes de configuration comportant des Ã©léments tag:<label>,
+seules seront valides celles pour lesquels tous les labels correspondants
+seront présents. C'est typiquement le cas des lignes dhcp-options.
+Un
+.B dhcp-option 
+possédant des labels sera utilisé de préférence Ã  un
+.B dhcp-option 
+sans label, pour peu que _tous_ les labels positionnés correspondent Ã  l'ensemble
+de labels décrit plus haut.
+Le préfixe '!' sur un label est un indicateur de négation, ainsi
+.B --dhcp=option=tag:!purple,3,1.2.3.4
+n'envoie l'option que lorsque le label "purple" n'est pas dans la liste de
+labels définis pour l'hôte considéré. (dans le cas de l'utilisation dans une
+ligne de commande au lieu d'un fichier de configuration, ne pas oublier
+d'échapper le caractère !, qui est un méta-caractère d'interpréteur de commande
+shell).
+.PP
+Veuillez noter que pour
+.B dhcp-range
+, les Ã©léments tag:<label> et set:<label> sont tous les deux autorisés
+pour sélectionner la plage Ã  utiliser selon, par exemple, le dhcp-host,
+et pour affecter l'option envoyée, sur la base de la plage sélectionnée.
+
+Ce système a Ã©volué d'un système plus ancien et aux possibilités plus limitées,
+et pour des raisons de compatibilité "net:" peut Ãªtre utilisé Ã  la place de
+"tag:" et "set:" peut-être omis (à l'exception de
+.B dhcp-host,
+où "net:" peut-être utilisé Ã  la place de "set:"). Pour les mêmes raisons, '#'
+peut-être utilisé Ã  la place de '!' pour indiquer la négation.
+.PP 
+Le serveur DHCP intégré dans Dnsmasq fonctionne Ã©galement en temps que serveur
+BOOTP, pour peu que l'adresse MAC et l'adresse IP des clients soient fournies,
+que ce soit par le biais de l'option 
+.B dhcp-host 
+ou dans le fichier
+.I /etc/ethers
+, et que l'option
+.B dhcp-range 
+soit présente afin d'activer le serveur DHCP pour un réseau donné (L'option
+.B --bootp-dynamic
+supprime la nécessité des associations statiques). Le paramètre
+"filename" (nom de fichier) de la requête BOOTP est utilisé comme label, ainsi
+que le label "bootp", permettant un certain contrôle sur les options retournées
+aux différentes classes d'hôtes.
+
+Il est possible de spécifier un nom d'interface Ã 
+.B dhcp-range
+sous la forme "interface:<nom d'interface>". La sémantique est comme suit :
+Pour le DHCP, s'il existe une autre valeur de dhcp-range pour laquelle
+_aucun_ nom d'interface n'est donné, alors le nom d'interface est ignoré
+et dnsmasq se comporte comme si la partie spécifiant l'interface n'existait
+pas, sinon le service DHCP n'est fourni qu'aux interfaces mentionnées dans
+les déclarations dhcp-range. Pour le DNS, si il n'y a pas d'option
+.B --interface
+ou
+.B --listen-address
+, alors le comportement n'est pas impacté par la spécification d'interface. Si
+l'une ou l'autre de ces options est présente, alors les interfaces mentionnées
+dans les plages d'adresses dhcp-range sont rajoutées Ã  la liste de celles
+où le service DNS est assuré.
+
+De manière similaire,
+.B enable-tftp
+peut prendre un nom d'interface, ce qui active le TFTP pour cette seule
+interface, en ignorant les options
+.B --interface 
+ou
+.B --listen-address
+De plus, 
+.B --tftp-secure
+, 
+.B --tftp-unique-root
+et
+.B --tftp-no-blocksize
+sont ignorées pour les requêtes sur de telles interfaces. (une directive
+.B --tftp-root
+donnant le chemin de la racine et une interface doit-être fournie).
+
+Ces règles peuvent paraître Ã©trange Ã  première vue, mais elles permettent
+d'ajouter Ã  la configuration de dnsmasq des lignes de configuration de la
+forme "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" afin de fournir
+un service DHCP et DNS sur cette interface, sans pour autant affecter les
+services fournis sur d'autres interfaces, malgré l'absence de paramètres
+"interface=<interface>" sur les autres lignes de configuration.
+"enable-tftp=virt0" et "tftp-root=<root>,virt0" effectuent la même chose pour
+TFTP.
+L'idée de tout cela est de permettre l'addition de telles lignes
+automatiquement par libvirt ou un système Ã©quivalent, sans perturbation
+d'une configuration manuelle existant par ailleurs.
+
+.SH CODES DE SORTIE
+.PP
+0 - Dnsmasq s'est correctement lancé en tâche de fond, ou alors s'est
+correctement terminé si le lancement en tâche de fond n'a pas Ã©té activé.
+.PP
+1 - Un problème de configuration a Ã©té détecté.
+.PP
+2 - Un problème est survenu avec un accès réseau (adresse déjà utilisée,
+tentative d'utiliser un port privilégié sans les permissions nécessaires).
+.PP
+3 - Un problème est survenu avec une opération sur un système de fichier
+(fichier ou répertoire manquant, permissions).
+.PP
+4 - Impossibilité d'allouer de la mémoire.
+.PP
+5 - Autre problème.
+.PP
+11 ou plus - un code de retour différent de 0 a Ã©té reçu lors de l'appel au
+processus "init" du script des bails. Le code de retour de Dnsmasq correspond
+au code de retour du script plus 10.
+
+.SH LIMITES
+Les valeurs par défaut pour les limites de ressources de Dnsmasq sont en général
+conservatrices et appropriées pour des utilisations embarquées sur des machines
+de type routeur ayant des processeurs lents et une mémoire limitée. Sur du
+matériel plus performant, il est possible d'augmenter les limites et de gérer
+plus de clients. Les remarques suivantes s'appliquent Ã  Dnsmasq version 2.37 et
+ultérieur : les versions précédentes ne montaient pas en charge aussi bien.
+.PP
+Dnsmasq est capable de gérer le DNS et DHCP pour au moins un millier de clients.
+Pour cela, la durée des bail ne doit pas Ãªtre très courte (moins d'une heure).
+La valeur de
+.B --dns-forward-max 
+peut-être augmentée : commencer par la rendre Ã©gale au nombre de clients et
+l'augmenter si le DNS semble lent. Noter que la performance du DNS dépends
+également de la performance des serveurs amonts. La taille du cache DNS peut-
+être augmentée : la limite en dur est de 10000 entrées et la valeur par défaut
+(150) est très basse. Envoyer un signal SIGUSR1 Ã  Dnsmasq le fait Ã©mettre des
+informations utiles pour paramétrer la taille de cache. Voir la section
+.B NOTES
+pour plus de détails.
+.PP
+Le serveur TFTP intégré est capable de plusieurs transferts de fichiers
+simultanés : La limite absolue est liée au nombre maximal de descripteurs de
+fichiers alloué Ã  un processus et Ã  la capacité de l'appel système select() Ã 
+gérer un grand nombre de HANDLE de fichier. Si la limite est fixée trop haut par
+le biais de
+.B --tftp-max
+elle sera réduite et la limite actuelle sera enregistrée au démarrage. Il faut
+noter que plus de transferts sont possible lorsque le même fichier est transmis
+au lieu d'avoir un fichier différent pour chaque transfert.
+
+.PP
+Il est possible d'utiliser Dnsmasq pour bloquer la publicité sur la toile
+en associant des serveurs de publicité bien connus Ã  l'adresse 127.0.0.1 ou
+0.0.0.0 par le biais du fichier
+.B /etc/hosts 
+ou d'un fichier d'hôte additionnel. Cette liste peut-être très longue, Dnsmasq
+ayant Ã©té testé avec succès avec un million de noms. Cette taille de fichier
+nécessite un processeur Ã  1 Ghz et environ 60 Mo de RAM.
+
+.SH INTERNATIONALISATION
+Dnsmasq peut Ãªtre compilé pour supporter l'internationalisation. Pour cela,
+les cibles "all-i18n" et "install-i18n" doivent Ãªtre données Ã  make, en lieu
+et place des cibles standards "all" et "install". Lorsque compilé avec le
+support de l'internationalisation, dnsmasq supporte les noms de domaines
+internationalisés ("internationalised domain names" ou IDN), et les messages de
+traces ("logs") sont Ã©crits dans la langue locale. Les noms de domaines dans
+/etc/hosts, /etc/ethers et /etc/dnsmasq.conf contenant des caractères
+non-ASCII seront transformés selon la représentation punycode interne
+aux DNS. Veuillez noter que dnsmasq détermine la langue pour les messages
+ainsi que le jeu de caractères susceptible d'être utilisé dans les fichiers
+de configuration Ã  partir de la variable d'environnement LANG. Ceci devrait
+être configuré Ã  la valeur par défaut du système par les scripts démarrant
+dnsmasq. Lorsque les fichiers de configuration sont Ã©dités, veuillez faire
+attention Ã  le faire en utilisant la valeur de locale par défaut du système
+et non une valeur spécifique Ã  l'utilisateur, puisque dnsmasq n'a aucun
+moyen de déterminer directement la valeur de jeu de caractère utilisé,
+et assume de ce fait qu'il s'agit de la valeur par défaut du système.
+
+.SH FICHIERS
+.IR /etc/dnsmasq.conf 
+
+.IR /usr/local/etc/dnsmasq.conf
+.IR /var/run/dnsmasq/resolv.conf
+.IR /etc/ppp/resolv.conf
+.IR /etc/dhcpc/resolv.conf
+
+.IR /etc/resolv.conf
+
+.IR /etc/hosts
+
+.IR /etc/ethers
+
+.IR /var/lib/misc/dnsmasq.leases 
+
+.IR /var/db/dnsmasq.leases
+
+.IR /var/run/dnsmasq.pid
+.SH VOIR AUSSI
+.BR hosts (5), 
+.BR resolver (5)
+.SH AUTEUR
+Cette page de manuel a Ã©té Ã©crite par Simon Kelley <simon@thekelleys.org.uk>.
+
+La traduction dans un français bancal a Ã©té commise par Gildas Le Nadan
+<3ntr0p13@gmail.com> : Toute révision/correction permettant de corriger
+orthographe ou grammaire mais surtout les Ã©ventuelles fautes de sens sera la
+bienvenue!
diff --git a/packaging/dnsmasq.spec b/packaging/dnsmasq.spec
new file mode 100644 (file)
index 0000000..2e8aad2
--- /dev/null
@@ -0,0 +1,33 @@
+Name:       dnsmasq
+Summary:    dnsmasq, DNS forwarder.
+Version:    2.57
+Release:    4
+Group:      TO_BE/FILLED_IN
+License:    TO BE FILLED IN
+Source0:    %{name}-%{version}.tar.gz
+BuildRequires: cmake
+BuildRequires: pkgconfig(dbus-1)
+
+%description
+Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP server.
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+%post
+mkdir -p /opt/var/lib/misc
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%files
+%{_bindir}/dnsmasq
+
+%changelog
+* Mon Apr 16 2012 Seungyoun Ju <sy39.ju@samsung.com> 2.57-4
+- "/opt/var/lib/misc" directory for lease file is created explicitly
diff --git a/po/de.po b/po/de.po
new file mode 100644 (file)
index 0000000..30ecb0e
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,1511 @@
+# German translations for dnsmasq package.
+#
+# This revised version is (C) Copyright by
+# Matthias Andree <matthias.andree@gmx.de>, 2010.
+# It is subject to the GNU General Public License v2,
+# or at your option, any later version.
+#
+# An older version of this file was originally put in the public domain by
+# Simon Kelley <simon@thekelleys.org.uk>, 2005.
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.53rc1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2010-05-24 16:29+0200\n"
+"Last-Translator: Matthias Andree <matthias.andree@gmx.de>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: cache.c:761
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr "Fehler beim Laden der Namen von %s: %s"
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "Fehlerhafte Adresse in %s Zeile %d"
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "Fehlerhafter Name in %s Zeile %d"
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "%s gelesen - %d Adressen"
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr "Cache geleert"
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr "%s ist ein CNAME, weise es der DHCP-Lease von %s nicht zu"
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr "Name %s wurde dem DHCP-Lease von %s nicht zugewiesen, da der Name in %s bereits mit Adresse %s existiert"
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr "Zeit %lu"
+
+#: cache.c:1040
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr "Cache Größe %d, %d/%d Cache-Einfügungen verwendeten nicht abgelaufene Cache-Einträge wieder."
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr "%u weitergeleitete Anfragen, %u lokal beantwortete Anfragen"
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr "Server %s#%d: %u Anfragen gesendet, %u erneut versucht oder fehlgeschlagen"
+
+#: util.c:57
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "Konnte den Zufallszahlengenerator nicht initialisieren: %s"
+
+#: util.c:189
+msgid "failed to allocate memory"
+msgstr "Konnte Speicher nicht belegen"
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr "Speicher nicht verfügbar"
+
+#: util.c:237
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr "Konnte Pipe nicht erzeugen: %s"
+
+#: util.c:245
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr "Konnte %d Bytes nicht belegen"
+
+# @Simon: not perfect but I cannot get nearer right now.
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr "unendlich"
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr "Lokale abzuhörende Adresse(n) angeben."
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "IP-Adresse für alle Hosts in angebenen Domänen festlegen."
+
+# FIXME: the English test is not to the point. Just use a shortened description
+# from the manpage instead. -- MA
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Für private Adressbereiche nach RFC1918 \"keine solche Domain\" liefern."
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Diese IP-Adresse als NXDOMAIN interpretieren (wehrt \"Suchhilfen\" ab)."
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Größe des Caches (Zahl der Einträge) festlegen (Voreinstellung: %s)."
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Konfigurationsdatei festlegen (Voreinstellung: %s)."
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "NICHT in den Hintergrund gehen: Betrieb im Debug-Modus"
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr "Anfragen ohne Domänen-Teil NICHT weiterschicken."
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Für lokale Einträge MX-Einträge liefern, die auf sich selbst zeigen."
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Erweitere einfache Namen in /etc/hosts mit der Domänen-Endung."
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "'unechte' DNS-Anfragen von Windows-Rechnern nicht weiterleiten"
+
+# @Simon: I'm a bit unsure about "spurious"
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "DHCP für angegebenen Bereich und Dauer einschalten"
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Nach dem Start in diese Benutzergruppe wechseln (Voreinstellung %s)."
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr "Adresse oder Hostnamen für einen angegebenen Computer setzen."
+
+#: option.c:258
+#, fuzzy
+msgid "Read DHCP host specs from file."
+msgstr "DHCP-Host-Angaben aus Datei lesen"
+
+#: option.c:259
+#, fuzzy
+msgid "Read DHCP option specs from file."
+msgstr "DHCP-Optionen aus Datei lesen"
+
+#: option.c:260
+#, fuzzy
+msgid "Evaluate conditional tag expression."
+msgstr "Auswertung eines Ausdrucks bedingter Marken"
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "%s-Datei NICHT laden."
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Hosts-Datei festlegen, die zusätzlich zu %s gelesen wird."
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr "Schnittstelle(n) zum Empfang festlegen."
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Schnittstelle(n) festlegen, die NICHT empfangen sollen."
+
+#: option.c:265
+msgid "Map DHCP user class to tag."
+msgstr "DHCP-Benutzerklasse auf Marke abbilden."
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr "RFC3046 \"circuit-id\" auf Marke abbilden."
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr "RFC3046 \"remote-id\" auf Marke abbilden."
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr "RFC3993 \"subscriber-id\" auf Marke abbilden."
+
+#: option.c:269
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Kein DHCP für Hosts mit gesetzter Marke verwenden."
+
+#: option.c:270
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Rundsendung für Hosts mit gesetzter Marke erzwingen."
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr "NICHT in den Hintergrund wechseln, NICHT im Debug-Modus laufen."
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr "Voraussetzen, dass wir der einzige DHCP-Server im lokalen Netz sind."
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Festlegen, wo DHCP-Leases gespeichert werden (Voreinstellung %s)."
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr "MX-Einträge für lokale Hosts liefern."
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr "Einen MX-Eintrag festlegen."
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr "BOOTP-Optionen für DHCP-Server festlegen."
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "%s-Datei NICHT abfragen, nur bei SIGHUP neu laden."
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr "Fehlerhafte Suchergebnisse NICHT zwischenspeichern."
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr "Namensserver streng in der in %s angegebenen Reihenfolge verwenden."
+
+#: option.c:280
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Optionen festlegen, die an DHCP-Klienten gesendet werden."
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr "DHCP-Option, die selbst ohne Klientenanfrage gesendet wird."
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Port zum Abhören der DNS-Anfragen festlegen (53 voreingestellt)."
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr "Maximale unterstützte UDP-Paketgröße für EDNS.0 (Voreinstellung %s)."
+
+#: option.c:284
+msgid "Log DNS queries."
+msgstr "DNS-Anfragen protokollieren."
+
+#: option.c:285
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Ausgehenden Port erzwingen für DNS-Anfragen an vorgelagerte Server."
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr "resolv.conf NICHT lesen."
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Pfad zu resolv.conf festlegen (%s voreingestellt)."
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Adresse(n) vorgelagerter Server festlegen, optional mit Domänen."
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr "Anfragen für angegebene Domänen niemals weiterleiten."
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Domäne festlegen, die für DHCP-Leases zugewiesen wird."
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr "Voreingestelltes Ziel für MX-Einträge festlegen."
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr "Gültigkeitsdauer für Antworten aus /etc/hosts festlegen."
+
+#: option.c:293
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
+
+#: option.c:294
+#, fuzzy
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Nach dem Start diese Benutzerrechte annehmen (%s voreingestellt)."
+
+#: option.c:296
+msgid "Map DHCP vendor class to tag."
+msgstr "DHCP-\"vendor class\" auf Marke abbilden."
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr "dnsmasq-Version und Urheberrecht anzeigen."
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "IPv4-Adressen von vorgelagerten Servern Ã¼bersetzen."
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr "SRV-Eintrag festlegen."
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr "Diese Hilfe anzeigen. Benutzen Sie --help dhcp für bekannte DHCP-Optionen."
+
+#: option.c:301
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Dateipfad für Prozesskennung (PID) festlegen (Voreinstellung: %s)."
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Höchstzahl der DHCP-Leases festlegen (%s voreingestellt)."
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr "DNS-Anfragen abhängig der Emfpangsschnittstelle beantworten."
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr "DNS-TXT-Eintrag festlegen."
+
+#: option.c:305
+msgid "Specify PTR DNS record."
+msgstr "DNS-PTR-Eintrag festlegen."
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr "Schnittstellennamen zur IPv4-Adresse des Interfaces auflösen."
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr "Nur an verwendete Schnittstellen binden."
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Statische DHCP-Host-Information aus %s lesen."
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "DBus-Schnittstelle zum Festlegen vorgelagerter Server usw. festlegen."
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "Auf dieser Schnittstelle kein DHCP anbieten, sondern nur DNS."
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Dynamische Adressbelegung für bootp einschalten."
+
+#: option.c:312
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "MAC-Adresse (mit Jokerzeichen) auf Netzmarke abbilden."
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr "DHCP-Anfragen von Alias-Schnittstellen für die Hauptschnittstelle beantworten."
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr "ICMP-Echo-Adressprüfung im DHCP-Server abschalten."
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr "Skript, das bei Erzeugung/Löschung einer DHCP-Lease laufen soll."
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr "Konfiguration aus allen Dateien in diesem Verzeichnis lesen."
+
+#: option.c:317
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Für diese Syslog-Anlage oder in Datei loggen (Voreinstellung DAEMON)."
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr "Keine Lease-Datei benützen."
+
+#: option.c:319
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Höchstzahl nebenläufiger DNS-Anfragen (%s voreingestellt)."
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr "DNS-Cache beim Neuladen von %s löschen."
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr "Von DHCP-Clients gelieferte Hostnamen ignorieren."
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr "Dateinamen und Server-Datenfehler für zusätzliche DHCP-Optionen NICHT wiederverwenden."
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr "Eingebauten Nur-Lese-TFTP-Server einschalten."
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr "Nur vom festgelegten Unterbaum Dateien per TFTP exportieren."
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr "IP-Adresse des Klienten an tftp-root anhängen."
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr "Zugriff nur auf Dateien gestatten, die dem dnsmasq aufrufenden Benutzer gehören."
+
+#: option.c:327
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Höchstzahl nebenläufiger TFTP-Ãœbertragungen (%s voreingestellt)."
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr "TFTP-Blockgrößen-Erweiterung abschalten."
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr "Bereich für vorübergehende Ports für TFTP-Ãœbertragungen."
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr "Erweiterte DHCP-Protokollierung."
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr "Asynchrone Protokollierung einschalten, opt. Warteschlangenlänge festlegen."
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr "DNS-Rebinding unterbinden, private IP-Bereiche bei der Auflösung ausfiltern."
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr "Auflösung zu 127.0.0.0/8 erlauben, für RBL-Server."
+
+#: option.c:334
+#, fuzzy
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr "DNS-Rebind-Schutz für diese Domäne sperren."
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr "DNS-Anfragen immer an alle Server weiterleiten."
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr "Marke setzen, wenn Klient eine entsprechende Option anfragt."
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr "Alternative Ports für DHCP verwenden."
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr "Lease-Änderungs-Skript mit den Rechten dieses Nutzers ausführen."
+
+#: option.c:339
+msgid "Specify NAPTR DNS record."
+msgstr "DNS-NAPTR-Eintrag festlegen."
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr "Niedrigsten verfügbaren Port für Ãœbertragung von DNS-Anfragen festlegen."
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr "Für DHCP-Klienten nur vollständig bestimmte Domänennamen benutzen."
+
+# FIXME: probably typo in original message. -- MA
+#: option.c:342
+#, fuzzy
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr "Für namenlose Klienten die Hostnamen MAC-basiert erzeugen."
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr "Diese DHCP-Relais als vollwertige Proxies verwenden."
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr "Alias für LOKALEN DNS-Namen festlegen."
+
+#: option.c:345
+msgid "Prompt to send to PXE clients."
+msgstr "Aufforderung, die an PXE-Klienten geschickt wird."
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr "Boot-Dienst für PXE-Menü."
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr "Konfigurationssyntax prüfen."
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+#: option.c:349
+#, fuzzy
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr "IPv4-Adressen von vorgelagerten Servern Ã¼bersetzen."
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Verwendung: dnsmasq [Optionen]\n"
+"\n"
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "Auf der Befehlszeile nur kurze Optionen verwenden!\n"
+
+#: option.c:642
+#, c-format
+msgid "Valid options are:\n"
+msgstr "Gültige Optionen sind:\n"
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr "Bekannte DHCP-Optionen:\n"
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr "Fehlerhafte DHCP-Option"
+
+#: option.c:860
+msgid "bad IP address"
+msgstr "Fehlerhafte IP-Adresse"
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr "Fehlerhafte Domäne in DHCP-Option"
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr "DHCP-Option zu lang"
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr "Unzulässige dhcp-match-Option"
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr "unzulässig wiederholte Markierung"
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr "unzulässig wiederholtes Schlüsselwort"
+
+#: option.c:1147 option.c:3030
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr "Kann auf Verzeichnis %s nicht zugreifen: %s"
+
+#: option.c:1178 tftp.c:460
+#, c-format
+msgid "cannot access %s: %s"
+msgstr "Kann auf %s nicht zugreifen: %s"
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr "unzulässige MX-Präferenz-Angabe"
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr "unzulässiger MX-Name"
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr "unzulässiges MX-Ziel"
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr "unter uClinux ist die Skriptausführung nicht möglich"
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr "Neuübersetzung mit HAVE_SCRIPT nötig, um Lease-Änderungs-Skripte auszuführen"
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr "unzulässiger Port"
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr "Schnittstellenbindung nicht unterstützt"
+
+#: option.c:1791
+msgid "bad port range"
+msgstr "unzulässiger Portbereich"
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr "unzulässige Brücken-Schnittstelle"
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr "unzulässiger DHCP-Bereich"
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr "nur eine Marke zulässig"
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr "inkonsistenter DHCP-Bereich"
+
+#: option.c:2019 option.c:2045
+msgid "bad hex constant"
+msgstr ""
+
+#: option.c:2107
+msgid "bad DHCP host name"
+msgstr "unzulässiger DHCP-Hostname"
+
+#: option.c:2188
+msgid "bad tag-if"
+msgstr "unzulässige bedingte Marke (tag-if)"
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr "unzulässige Portnummer"
+
+#: option.c:2529
+msgid "bad dhcp-proxy address"
+msgstr "Fehlerhafte DHCP-Proxy-Adresse"
+
+#: option.c:2569
+msgid "invalid alias range"
+msgstr "unzulässiger Alias-Bereich"
+
+#: option.c:2582
+msgid "bad interface name"
+msgstr "unzulässiger Schnittestellenname"
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr "unzulässiger CNAME"
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr "doppelter CNAME"
+
+#: option.c:2632
+msgid "bad PTR record"
+msgstr "unzulässiger PTR-Eintrag"
+
+#: option.c:2663
+msgid "bad NAPTR record"
+msgstr "unzulässiger NAPTR-Eintrag"
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr "unzulässiger TXT-Eintrag"
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr "unzulässiger SRV-Eintrag"
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr "unzulässiges SRV-Ziel"
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr "unzulässige Priorität"
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr "unzulässige Wichtung"
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr "unzulässige Option (prüfen Sie, ob dnsmasq mit DHCP/TFTP/DBus-Unterstützt Ã¼bersetzt wurde)"
+
+#: option.c:2849
+msgid "missing \""
+msgstr "fehlende \\\""
+
+#: option.c:2908
+msgid "bad option"
+msgstr "unzulässige Option"
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr "überschüssiger Parameter"
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr "fehler Parameter"
+
+#: option.c:2916
+msgid "error"
+msgstr "Fehler"
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s in Zeile %d von %%s"
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "kann %s nicht lesen: %s"
+
+#: option.c:3151 option.c:3187
+#, c-format
+msgid "read %s"
+msgstr "%s gelesen"
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr "Dnsmasq Version %s  %s\n"
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Ãœbersetzungs-Optionen %s\n"
+"\n"
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Für diese Software wird ABSOLUT KEINE GARANTIE gewährt.\n"
+
+# FIXME: this must be one long string! -- MA
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:3273
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:3284
+msgid "try --help"
+msgstr "versuchen Sie --help"
+
+#: option.c:3286
+msgid "try -w"
+msgstr "versuchen Sie -w"
+
+#: option.c:3289
+#, c-format
+msgid "bad command line options: %s"
+msgstr "unzulässige Optionen auf der Befehlszeile: %s"
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "kann Hostnamen nicht ermitteln: %s"
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "mit -n/--no-poll ist nur eine resolv.conf-Datei zulässig."
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "Um die Domäne zu lesen, muss genau eine resolv.conf-Datei verwendet werden."
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, c-format
+msgid "failed to read %s: %s"
+msgstr "konnte %s nicht lesen: %s"
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr "keine \"search\"-Anweisung in %s gefunden"
+
+#: option.c:3409
+#, fuzzy
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr "für --dhcp-fqdn muss eine Domäne vorausgewählt werden"
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr "Syntaxprüfung OK"
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "Namensserver %s hat eine rekursive Anfrage verweigert"
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s"
+
+#: network.c:171
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "unbekannte Schnittstelle %s in bridge-interface"
+
+#: network.c:380
+#, fuzzy, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr "Konnte Empfangs-Socket nicht erzeugen: %s"
+
+#: network.c:746
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "konnte nicht an Server-Socket für %s binden: %s"
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignoriere Namensserver %s - lokale Schnittstelle"
+
+#: network.c:794
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "ignoriere Namensserver %s - kann Socket nicht erzeugen/binden: %s"
+
+# FIXME: this isn't translatable - always provide full strings, do not assemble yourself! -- MA
+#: network.c:811
+msgid "unqualified"
+msgstr ""
+
+#: network.c:811
+msgid "names"
+msgstr ""
+
+#: network.c:813
+msgid "default"
+msgstr ""
+
+#: network.c:815
+msgid "domain"
+msgstr ""
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:820
+#, c-format
+msgid "using standard nameservers for %s %s"
+msgstr ""
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:825
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:148
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr "TFTP-Server nicht verfügbar, setzen Sie HAVE_TFTP in src/config.h"
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr "asynchrone Protokollierung unter Solaris nicht verfügbar"
+
+#: dnsmasq.c:158
+#, fuzzy
+msgid "asychronous logging is not available under Android"
+msgstr "asynchrone Protokollierung unter Solaris nicht verfügbar"
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "konnte Schnitstellenliste nicht beziehen: %s"
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr "unbekannte Schnittstelle %s"
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr "keine Schnittstelle mit Adresse %s"
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr "DBus-Fehler: %s"
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr "Unbekannter Benutzer oder Gruppe: %s"
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr "kann nicht ins Wurzelverzeichnis des Dateisystems wechseln: %s"
+
+# FIXME: this and the next would need commas after the version
+#: dnsmasq.c:455
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr "gestartet, Version %s, DNS abgeschaltet"
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "gestartet, Version %s, Cachegröße %d"
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr "Ãœbersetzungsoptionen: %s"
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr "DBus-Unterstützung eingeschaltet: mit Systembus verbunden"
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr "DBus-Unterstützung eingeschaltet: warte auf Systembus-Verbindung"
+
+#: dnsmasq.c:474
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "Warnung: konnte den Besitzer von %s nicht Ã¤ndern: %s"
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "Aktiviere --bind-interfaces wegen Einschränkungen des Betriebssystems"
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "Warnung: Schnittstelle %s existiert derzeit nicht"
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr "Warnung: Ignoriere \"resolv-file\", weil \"no-resolv\" aktiv ist"
+
+#: dnsmasq.c:491
+msgid "warning: no upstream servers configured"
+msgstr "Warnung: keine vorgelagerten (Upstream) Server konfiguriert"
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr "asynchrone Protokollierung eingeschaltet, Warteschlange fasst %d Nachrichten"
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr "DHCP, nur statische Leases auf %.0s%s, Lease-Zeit %s"
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr "DHCP, Proxy im Subnetz %.0s%s%.0s"
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, IP-Bereich %s - %s, Lease-Zeit %s "
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr "FIXME: this and the next few must be full strings to be translatable - do not assemble in code"
+
+#: dnsmasq.c:526
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr "Begrenze gleichzeitige TFTP-Ãœbertragungen auf maximal %d"
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr "Mit System-DBus verbunden"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr "kann nicht in den Hintergrund abspalten: %s"
+
+#: dnsmasq.c:778
+#, c-format
+msgid "failed to create helper: %s"
+msgstr "kann Helfer nicht erzeugen: %s"
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr "kann \"capabilities\" nicht setzen: %s"
+
+#: dnsmasq.c:785
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "Kann nicht Benutzerrechte %s annehmen: %s"
+
+#: dnsmasq.c:790
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "Kann nicht Gruppenrechte %s annehmen: %s"
+
+#: dnsmasq.c:793
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "kann die Prozessidentifikations-(PID)-Datei %s nicht Ã¶ffnen: %s"
+
+#: dnsmasq.c:796
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "kann %s nicht Ã¶ffnen: %s"
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr "Tochterprozess durch Signal %d zerstört"
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr "Tochterprozess beendete sich mit Status %d"
+
+#: dnsmasq.c:859
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr "konnte %s nicht ausführen: %s"
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr "beende nach Empfang von SIGTERM"
+
+#: dnsmasq.c:931
+#, c-format
+msgid "failed to access %s: %s"
+msgstr "konnte auf %s nicht zugreifen: %s"
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr "lese %s"
+
+#: dnsmasq.c:972
+#, c-format
+msgid "no servers found in %s, will retry"
+msgstr "keine Server in %s gefunden, werde es später neu versuchen"
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr "kann DHCP-Socket nicht erzeugen: %s"
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr "kann Optionen für DHCP-Socket nicht setzen: %s"
+
+#: dhcp.c:65
+#, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr "kann SO_REUSE{ADDR|PORT} für DHCP-Socket nicht aktivieren: %s"
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr "kann nicht an DHCP-Server-Socket binden: %s"
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "kann ICMP-Rohdaten-Socket nicht erzeugen: %s."
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr "DHCP-Paket ohne Adresse an Schnittstelle %s empfangen"
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr "DHCP-Bereich %s - %s passt nicht zur Netzmaske %s"
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "ungültige Zeile %2$d in Datei %1$s"
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr "ignoriere %s Zeile %d, doppelter Name oder doppelte IP-Adresse"
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "doppelte IP-Adresse %s in \"dhcp-config\"-Anweisung"
+
+#: dhcp.c:981
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "doppelte IP-Adresse %s in %s."
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr "%s hat mehr als eine Adresse in hosts-Datei, benutze %s für DHCP"
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr "doppelte IP-Adresse %s (%s) in \"dhcp-config\"-Anweisung"
+
+#: lease.c:67
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "kann Lease-Datei %s nicht Ã¶ffnen: %s"
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr "zu viele Leases gespeichert"
+
+#: lease.c:129
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "kann Lease-Start-Skript %s nicht ausführen: %s"
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr "Lease-Start-Skript beendete sich mit Code %s"
+
+# FIXME: This should be %u s also in English according to NIST and SI rules. -- MA
+#: lease.c:235
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "Konnte %s nicht schreiben: %s (Neuversuch in %u s)"
+
+# FIXME: this and the next few are not translatable. Please provide full
+# strings, do not programmatically assemble them.
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:331
+#, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr "%u verfügbare(s) DHCP-Subnetz: %s/%s"
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr "%u verfügbare(r) DHCP-Bereich: %s - %s"
+
+# FIXME: do not programmatically assemble strings - untranslatable
+#: rfc2131.c:363
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr "%u Klient stellt Name bereit: %s"
+
+#: rfc2131.c:700
+#, c-format
+msgid "%u vendor class: %s"
+msgstr "%u \"Vendor class\": %s"
+
+#: rfc2131.c:702
+#, c-format
+msgid "%u user class: %s"
+msgstr "%u Benutzerklasse: %s"
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr "PXE BIS nicht unterstützt"
+
+#: rfc2131.c:886
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "schalte statische DHCP-Adresse %s für %s ab"
+
+# FIXME: do not assemble
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr "benutze konfigurierte Adresse %s nicht, weil sie an %s verleast ist"
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr "benutze konfigurierte Adresse %s nicht, weil sie von Server/Relais verwendet wird"
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr "benutze konfigurierte Adresse %s nicht, weil sie zuvor abgelehnt wurde"
+
+# FIXME: do not assemble
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr "Gebe Lease von %2$s an %1$s auf"
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr "%u Marken: %s"
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr "%u Name der Bootdatei: %s"
+
+#: rfc2131.c:1732
+#, c-format
+msgid "%u server name: %s"
+msgstr "%u Servername: %s"
+
+#: rfc2131.c:1746
+#, c-format
+msgid "%u next server: %s"
+msgstr "%u nächster Server: %s"
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr "%u Antwort per Rundsendung"
+
+#: rfc2131.c:1812
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr "kann DHCP/BOOTP-Opition %d nicht setzen: kein Platz mehr im Paket"
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr "PXE-Menüeintrag zu groß"
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr "Ignoriere Domäne %s für DHCP-Hostnamen %s"
+
+#: rfc2131.c:2189
+#, c-format
+msgid "%u requested options: %s"
+msgstr "%u angeforderte Optionen: %s"
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr "Kann RFC3925-Option nicht senden: zu viele Optionen für Unternehmen Nr. %d"
+
+#: netlink.c:70
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "kann Netlink-Socket nicht erzeugen: %s"
+
+#: netlink.c:288
+#, c-format
+msgid "netlink returns error: %s"
+msgstr "Netlink liefert Fehler %s"
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr "Versuch, via DBus eine IPv6-Serveradresse zu setzen: keine IPv6-Unterstützung"
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr "vorgelagerte Server von DBus gesetzt"
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr "konnte Steuerungsprogramm für DBus-Nachrichten nicht anmelden"
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "konnte DHCP-BPF-Socket nicht einrichten: %s"
+
+#: bpf.c:245
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr "DHCP-Anfrage für nicht unterstützen Hardwaretyp (%d) auf %s empfangen"
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr "konnte keinen freien Port für TFTP bekommen"
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr "nicht unterstützte Anfrage von %s"
+
+#: tftp.c:406
+#, c-format
+msgid "file %s not found"
+msgstr "Datei %s nicht gefunden"
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr "Fehler %d %s von %s empfangen"
+
+#: tftp.c:554
+#, c-format
+msgid "failed sending %s to %s"
+msgstr "konnte %s nicht an %s senden"
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr "%s an %s verschickt"
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr "Ãœberlauf: %d Protokolleinträge verloren"
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr "Protokollierung fehlgeschlagen: %s"
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr "Start fehlgeschlagen"
+
+#~ msgid "only one dhcp-hostsfile allowed"
+#~ msgstr "nur eine DHCP-Hostdatei (dhcp-hostsfile) zulässig"
+
+#~ msgid "only one dhcp-optsfile allowed"
+#~ msgstr "nur eine DHCP-Optionsdatei (dhcp-optsfile) zulässig"
+
+#~ msgid "files nested too deep in %s"
+#~ msgstr "Dateien in %s zu tief verschachtelt"
+
+#~ msgid "TXT record string too long"
+#~ msgstr "TXT-Eintrag zu lang"
+
+#~ msgid "failed to set IPV6 options on listening socket: %s"
+#~ msgstr "konnte IPV6-Optionen auf Empfangs-Socket nicht einstellen: %s"
+
+#~ msgid "failed to bind listening socket for %s: %s"
+#~ msgstr "konnte Empfangs-Socket nicht an %s binden: %s"
+
+#~ msgid "failed to listen on socket: %s"
+#~ msgstr "konnte Socket nicht zum Empfang einrichten: %s"
+
+#~ msgid "failed to create TFTP socket: %s"
+#~ msgstr "konnte TFTP-Socket nicht erzeugen: %s"
diff --git a/po/es.po b/po/es.po
new file mode 100644 (file)
index 0000000..efdd24e
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,1575 @@
+# Spanish translations for dnsmasq package.
+# This file is put in the public domain.
+# Christopher Chatham <chrislinux@gmail.com>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.24\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2005-10-07 11:04+0100\n"
+"Last-Translator: Christopher Chatham <chrislinux@gmail.com>\n"
+"Language-Team: Spanish <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: cache.c:761
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "no se pudo cargar nombres desde %s: %s"
+
+#: cache.c:795 dhcp.c:865
+#, fuzzy, c-format
+msgid "bad address at %s line %d"
+msgstr "dirección errónea en %s línea %d"
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "nombre erróneo en %s línea %d"
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "direcciónes %s - %d leídas"
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr "el caché fue liberado"
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr "%s es un CNAME, no se le está dando al arriendo DHCP de %s"
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr "no otorgando nombre %s al arriendo DHCP de %s porque el nombre existe en %s con dirección %s"
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr "tiempo %lu"
+
+#: cache.c:1040
+#, fuzzy, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr "tamaño de caché %d, %d/%d inserciónes de caché reutilizaron objetos no vencidos."
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr "búsquedas reenviadas %u, búsquedas respondidas localmente %u"
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr "servidor %s#%d: búsquedas enviadas %u, reintentadas o fallidas %u"
+
+#: util.c:57
+#, fuzzy, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "no se pudo crear valor semilla para el generador de números aleatorios: %s"
+
+#: util.c:189
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "no se pudo asignar memoria"
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr "no se pudo adquirir memoria"
+
+#: util.c:237
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "no se puede crear pipe: %s"
+
+#: util.c:245
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "no se pudo asignar %d bytes"
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr "infinito"
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr "Especificar dirección(es) locales dónde escuchar."
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Retornar ipaddr (dirección IP) para todos los hosts en los dominios especificados."
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Falsificar búsquedas reversas para rangos de dirección privados RFC1918."
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Tratar ipaddr (dirección IP) como NXDOMAIN (derrota comodín Verisign)."
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Especificar tamaño de caché en cuanto a cantidad de objetos (%s por predeterminado)."
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Especificar archivo de configuración (%s por predeterminado)."
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "NO hacer un fork hacia el fondo: correr en modo debug."
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr "NO reenviar búsquedas sin parte de dominio."
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Retornar expedientes MX auto-señaladores para hosts locales."
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Expandir nombres simples en /etc/hosts con domain-suffix (sufijo de dominio)."
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "No reenviar pedidos DNS falsos desde máquinas Windows."
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Habilitar DHCP dentro del rango brindado con duración del arriendo."
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Cambiar a este grupo después del inicio (%s por predeterminado)."
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr "Fijar dirección o nombre de host para una máquina especificada."
+
+#: option.c:258
+#, fuzzy
+msgid "Read DHCP host specs from file."
+msgstr "Leer especificaciones DHCP de host desde archivo"
+
+#: option.c:259
+#, fuzzy
+msgid "Read DHCP option specs from file."
+msgstr "Leer opciones DHCP de host desde archivo"
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr "Evaluar expresión condicional de etiqueta."
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "NO cargar archivo %s."
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Especificar un archivo de hosts para ser leído adicionalmente a %s."
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr "Especificar interface(s) donde escuchar."
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Especificar interface(s) donde NO escuchar."
+
+#: option.c:265
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Trazar clase de usuario DHCP a etiqueta."
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr "Trazar circuit-id (identificación de circuito) RFC3046 a etiqueta."
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr "Trazar remote-id (identificación remota) RFC3046 a etiqueta."
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr "Trazar subscriber-id (identificación de suscritor) RFC3993 a etiqueta."
+
+#: option.c:269
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "No hacer DHCP para hosts con etiqueta fijada."
+
+#: option.c:270
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Forzar respuestas broadcast para hosts con etiqueta fijada."
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr "NO hacer un fork hacia el fondo, NO correr en modo debug."
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr "Asumir que somos el Ãºnico servidor DHCP en la red local."
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Especificar donde almacenar arriendos DHCP (%s por predeterminado)."
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr "Retornar expedientes MX para hosts locales."
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr "Especificar un expediente MX."
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Especificar opciones BOOTP a servidor DHCP."
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "NO revisar archivo %s periódicamente, recargar solo con SIGHUP."
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr "NO almacenar en caché resultados de búsquedas fallidas."
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr "Usar servidores DNS estrictamente en el Ã³rden brindado en %s."
+
+#: option.c:280
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Especificar opciones para ser enviadas a clientes DHCP."
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr "Opción DHCP enviada aún si el cliente no la pide."
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Especificar puerto donde escuchar por búsquedas DNS (53 por predeterminado)."
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr "Tamaño máximo de paquetes UDP soportado para EDNS.0 (%s por predeterminado)."
+
+#: option.c:284
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "Bitacorear búsquedas DNS."
+
+#: option.c:285
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Enforzar el puerto original para búsquedas DNS upstream."
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr "NO leer resolv.conf."
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Especificar el path hacia resolv.conf (%s por predeterminado)."
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Especificar dirección(es) de servidores upstream con dominios opcionales."
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr "Nunca reenviar búsquedas a dominios especificados."
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Especificar el dominio para ser asignado en arriendos DHCP."
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr "Especificar destino predeterminado en un expediente MX."
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr "Especificar tiempo de vida en segundos para respuestas desde /etc/hosts."
+
+#: option.c:293
+#, fuzzy
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Especificar tiempo de vida en segundos para caché negativo."
+
+#: option.c:294
+#, fuzzy
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr "Especificar tiempo de vida en segundos para respuestas desde /etc/hosts."
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Cambiar a este usuario despues del inicio (%s por predeterminado)."
+
+#: option.c:296
+#, fuzzy
+msgid "Map DHCP vendor class to tag."
+msgstr "Trazar clase de vendedor DHCP a etiqueta."
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr "Mostrar información sobre la versión y copyright de dnsmasq."
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Traducir direcciones IPv4 desde servidores upstream."
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr "Especificar un expediente SRV."
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr "Mostrar este mensaje. Usar --help dhcp para opciones DHCP conocidas."
+
+#: option.c:301
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Especificar path de archivo PID (%s por predeterminado)."
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Especificar número máximo de arriendos DHCP (%s por predeterminado)."
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr "Responder a búsquedas DNS en base a la interface a la cuál fueron enviadas."
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr "Especificar expediente DNS TXT."
+
+#: option.c:305
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Especificar expediente DNS PTR."
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr "Otorgar nombre DNS a dirección IPv4 de interface."
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr "Acoplar solo a interfaces en uso."
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Leer información sobre hosts DHCP estáticos desde %s."
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Habilitar la interface DBus para fijar servidores upstream, etc."
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "No proveer DHCP en esta interface, sólo proveer DNS."
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Habilitar alocación dinámica de direcciónes para BOOTP."
+
+#: option.c:312
+#, fuzzy
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Trazar dirección MAC (con comodínes) a opción fijada."
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr "Tratar pedidos DHCP en alias como si llegaran de la interface."
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr "Deshabilitar verificación de direcciónes para echo ICMP en el servidor DHCP."
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr "Archivo guión para ejecutar cuando se crea o destruye un arriendo DHCP."
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr "Leer configuración desde todos los archivos en este directorio."
+
+#: option.c:317
+#, fuzzy
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Bitacorear a esta facilidad syslog o archivo. (DAEMON por predeterminado)"
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr "No usar archivo de arriendos."
+
+#: option.c:319
+#, fuzzy, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Número máximo de búsquedas DNS simultáneas. (%s por predeterminado)"
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr "Liberar caché DNS al recargar %s."
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr "Ignorar nombres de host brindados por clientes DHCP."
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr "NO reutilizar campos de nombre de archivo y servidor para opciones DHCP extra."
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr "Habilitar servidor integrado TFTP solo-lectura."
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr "Exportar archivos vía TFTP solo del sub-árbol especificado."
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr "Agregar IP de cliente a tftp-root."
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr "Permitir acceso solo a archivos pertenecientes al usuario que corre dnsmasq."
+
+#: option.c:327
+#, fuzzy, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Número máximo de transferencias TFTP simultáneas (%s por predeterminado)."
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr "Deshabilitar la extensión TFTP blocksize (tamaño de bloque)."
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr "Rango de puertos efímeros para ser usados por transferencias TFTP."
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr "Bitacoreo extra para DHCP."
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr "Habilitar bitacoreo asincrónico; opcionalmente fijar tamaño de cola."
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr "Detener revinculación DNS. Filtrar rangos de IP privados al resolver."
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr "Permitir revinculación de 127.0.0.0/8, para servidores RBL."
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr "Inhibir protección de revinculación DNS en este dominio."
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr "Siempre realizar búsquedas DNS a todos los servidores."
+
+#: option.c:336
+#, fuzzy
+msgid "Set tag if client includes matching option in request."
+msgstr "Fijar etiqueta si cliente incluye opción coincidente en pedido."
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr "Usar puertos alternativos para DHCP."
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr "Correr archivo guión de cambio de arriendos como este usuario."
+
+#: option.c:339
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Especificar expediente DNS NAPTR."
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr "Especificar puerto más bajo disponible para transmisión de búsquedas DNS."
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr "Usar solo nombres de dominio completamente calificados para clientes DHCP."
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr "Generar hostnames basados en direcciones MAC para clientes sin nombre."
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr "Usar estos relays DHCP como proxies completos."
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr "Especificar nombre alias para nombre DNS LOCAL."
+
+#: option.c:345
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Aviso a ser enviado a clientes PXE."
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr "Servico boot para menú PXE."
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr "Revisar sintaxis de configuración."
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+#: option.c:349
+#, fuzzy
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr "Traducir direcciones IPv4 desde servidores upstream."
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Modo de uso: dnsmasq [opciones]\n"
+"\n"
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "Usar opciones cortas solo en la línea de comandos.\n"
+
+#: option.c:642
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "Opciones válidas son :\n"
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr "Opciones DHCP conocidas:\n"
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr "opción dhcp-option errónea"
+
+#: option.c:860
+#, fuzzy
+msgid "bad IP address"
+msgstr "dirección IP errónea"
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr "dominio erróneo en dhcp-option"
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr "opción dhcp-option demasiado larga"
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr "dhcp-match ilegal"
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr "opción repetida ilegal"
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr "palabra clave repetida ilegal"
+
+#: option.c:1147 option.c:3030
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "no se puede accesar directorio %s: %s"
+
+#: option.c:1178 tftp.c:460
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "no se puede accesar %s: %s"
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr "preferencia MX errónea"
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr "nombre MX erróneo"
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr "destino MX erróneo"
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr "no se pueden correr archivos guiónes bajo uClinux"
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr "recompilar con HAVE_SCRIPT definido para habilitar guiónes de cambio de arriendo"
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr "puerto erróneo"
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr "vinculación de interface no está soportado"
+
+#: option.c:1791
+#, fuzzy
+msgid "bad port range"
+msgstr "rango de puertos erróneo"
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr "opción bridge-interface (interface puente) errónea"
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr "opción dhcp-range (rango DHCP) errónea"
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr "solo una etiqueta permitida"
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr "rango DHCP inconsistente"
+
+#: option.c:2019 option.c:2045
+#, fuzzy
+msgid "bad hex constant"
+msgstr "opción dhcp-host errónea"
+
+#: option.c:2107
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "nombre de host DHCP erróneo"
+
+#: option.c:2188
+#, fuzzy
+msgid "bad tag-if"
+msgstr "destino MX erróneo"
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr "número de puerto inválido"
+
+#: option.c:2529
+#, fuzzy
+msgid "bad dhcp-proxy address"
+msgstr "dirección IP errónea"
+
+#: option.c:2569
+#, fuzzy
+msgid "invalid alias range"
+msgstr "rango alias inválido"
+
+#: option.c:2582
+#, fuzzy
+msgid "bad interface name"
+msgstr "nombre de interface erróneo"
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr "CNAME erróneo"
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr "CNAME duplicado"
+
+#: option.c:2632
+#, fuzzy
+msgid "bad PTR record"
+msgstr "expediente PTR erróneo"
+
+#: option.c:2663
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "expediente NAPTR erróneo"
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr "expediente TXT erróneo"
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr "expediente SRV erróneo"
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr "destino SRV erróneo"
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr "prioridad inválida"
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr "peso inválido"
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr "opción no soportada (verificar que dnsmasq fue compilado con soporte para DHCP/TFTP/DBus)"
+
+#: option.c:2849
+msgid "missing \""
+msgstr "falta \""
+
+#: option.c:2908
+msgid "bad option"
+msgstr "opción errónea"
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr "parámetro extraño"
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr "parámetro ausente"
+
+#: option.c:2916
+msgid "error"
+msgstr "error"
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s en línea %d de %%s"
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "no se puede leer %s: %s"
+
+#: option.c:3151 option.c:3187
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "leyendo %s"
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr "Dnsmasq versión %s  %s\n"
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Opciones de compilación %s\n"
+"\n"
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Este software viene SIN NINGUNA GARANTIA.\n"
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr "Dnsmasq es software libre, y usted está bienvenido a redistribuirlo\n"
+
+#: option.c:3273
+#, fuzzy, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr "bajo los términos de la GNU General Public License, versión 2 o 3.\n"
+
+#: option.c:3284
+msgid "try --help"
+msgstr "pruebe --help"
+
+#: option.c:3286
+msgid "try -w"
+msgstr "pruebe -w"
+
+#: option.c:3289
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "opciones de línea de comandos erróneas: %s"
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "no se puede obtener host-name (nombre de host): %s"
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "solo un archivo resolv.conf permitido en modo no-poll."
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "debe haber exáctamente un resolv.conf desde donde leer dominio."
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "no se pudo leer %s: %s"
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr "ninguna directiva de búsqueda encontrada en %s"
+
+#: option.c:3409
+#, fuzzy
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr "debe haber un dominio predeterminado cuando --dhcp-fqdn está fijado"
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr "revisión de sintaxis OK"
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "servidor DNS %s se reusó a hacer una búsqueda recursiva"
+
+#: forward.c:489
+#, fuzzy, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr "posible ataque de revinculación DNS detectado"
+
+#: network.c:171
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "interface desconocida %s en bridge-interface"
+
+#: network.c:380
+#, fuzzy, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr "no se pudo crear un socket escuchador: %s"
+
+#: network.c:746
+#, fuzzy, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "no se pudo acoplar socket escuchador para %s: %s"
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorando servidor DNS %s - interface local"
+
+#: network.c:794
+#, fuzzy, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "ignorando servidor DNS %s - no se puede crear/acoplar socket: %s"
+
+#: network.c:811
+msgid "unqualified"
+msgstr "no calificado"
+
+#: network.c:811
+msgid "names"
+msgstr "nombres"
+
+#: network.c:813
+msgid "default"
+msgstr "predeterminado"
+
+#: network.c:815
+msgid "domain"
+msgstr "dominio"
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "usando direcciones locales solo para %s %s"
+
+#: network.c:820
+#, fuzzy, c-format
+msgid "using standard nameservers for %s %s"
+msgstr "usando servidor DNS %s#%d para %s %s"
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "usando servidor DNS %s#%d para %s %s"
+
+#: network.c:825
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "usando servidor DNS %s#%d(vía %s)"
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "usando servidor DNS %s#%d"
+
+#: dnsmasq.c:148
+#, fuzzy
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr "servidor TFTP no disponible: fijar HAVE_TFTP en src/config.h"
+
+#: dnsmasq.c:153
+#, fuzzy
+msgid "asychronous logging is not available under Solaris"
+msgstr "bitacoreo asincrónico no está disponible bajo Solaris"
+
+#: dnsmasq.c:158
+#, fuzzy
+msgid "asychronous logging is not available under Android"
+msgstr "bitacoreo asincrónico no está disponible bajo Solaris"
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "no se pudo encontrar lista de interfaces: %s"
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr "interface desconocida %s"
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr "ninguna interface con dirección %s"
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr "error DBus: %s"
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus no disponible: fijar HAVE_DBUS en src/config.h"
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr "usuario o grupo desconocido: %s"
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr "no se puede cambiar directorio a raíz de sistema de archivos: %s"
+
+#: dnsmasq.c:455
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "iniciado, versión %s DNS deshabilitado"
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "iniciado, versión %s tamaño de caché %d"
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "iniciado, versión %s caché deshabilitado"
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr "opciones de compilación: %s"
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr "soporte DBus habilitado: conectado a bus de sistema"
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr "soporte DBus habilitado: conección a bus pendiente"
+
+#: dnsmasq.c:474
+#, fuzzy, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "advertencia: no se pudo cambiar dueño de %s: %s"
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "fijando opción --bind-interfaces debido a limitaciones de sistema operativo"
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "advertencia: interface %s no existe actuálmente"
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr "advertencia: ignorando opción resolv-file porque no-resolv está fijado"
+
+#: dnsmasq.c:491
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "advertencia: ningún servidor upstream configurado"
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr "bitacoreo asincrónico habilitado, límite de cola es %d mensajes"
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr "DHCP, arriendos estáticos solo en %.0s%s, tiempo de arriendo %s"
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr "DHCP, proxy en subred %.0s%s%.0s"
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, rango de IPs %s -- %s, tiempo de arriendo %s"
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr "root es "
+
+#: dnsmasq.c:526
+#, fuzzy
+msgid "enabled"
+msgstr "habilitado"
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr "modo seguro"
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr "limitando número máximo de transferencias TFTP simultáneas a %d"
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr "conectado a DBus de sistema"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr "no se puede hacer fork hacia el fondo: %s"
+
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "no se pudo crear ayudante: %s"
+
+#: dnsmasq.c:781
+#, fuzzy, c-format
+msgid "setting capabilities failed: %s"
+msgstr "configuración de capacidades ha fallado: %s"
+
+#: dnsmasq.c:785
+#, fuzzy, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "no se pudo cambiar user-id a %s: %s"
+
+#: dnsmasq.c:790
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "no se pudo cambiar group-id a %s: %s"
+
+#: dnsmasq.c:793
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "no se pudo abrir archivo PID %s: %s"
+
+#: dnsmasq.c:796
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "no se puede abrir %s: %s"
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr "proceso hijo eliminado por señal %d"
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr "proceso hijo hizo exit con estado %d"
+
+#: dnsmasq.c:859
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "no se pudo ejecutar %s: %s"
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr "saliendo al recibir SIGTERM"
+
+#: dnsmasq.c:931
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "no se pudo accesar %s: %s"
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr "leyendo %s"
+
+#: dnsmasq.c:972
+#, fuzzy, c-format
+msgid "no servers found in %s, will retry"
+msgstr "ningún servidor encontrado en %s, se reintentará"
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr "no se puede crear socket DHCP: %s"
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr "no se pudo fijar opciones en socket DHCP: %s"
+
+#: dhcp.c:65
+#, fuzzy, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr "no se pudo fijar SO_REUSE{ADDR|PORT} en socket DHCP: %s"
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr "no se pudo acoplar socket de servidor DHCP: %s"
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "no se puede crear socket crudo ICMP: %s."
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr "Paquete DHCP recibido en %s que no tiene dirección"
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr "rango DHCP %s -- %s no coincide con máscara de subred %s"
+
+#: dhcp.c:852
+#, fuzzy, c-format
+msgid "bad line at %s line %d"
+msgstr "línea errónea en %s línea %d"
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr "ignorando %s línea %d, nombre o dirección IP duplicada"
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "dirección IP duplicada %s en directiva dhcp-config."
+
+#: dhcp.c:981
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "dirección IP duplicada %s en %s."
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr "%s tiene más de una dirección en hostsfile, usando %s para DHCP"
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr "dirección IP duplicada %s (%s) en directiva dhcp-config"
+
+#: lease.c:67
+#, fuzzy, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "no se puede abrir o crear archivo de arriendos %s: %s"
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr "demasiados arriendos almacenados"
+
+#: lease.c:129
+#, fuzzy, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "no se puede ejecutar archivo guión lease-init %s: %s"
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr "archivo guión lease-init retornó exit code %s"
+
+#: lease.c:235
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "error al escribir %s: %s (reintentar en %us)"
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr "ningún rango de direcciónes disponible para pedido DHCP %s %s"
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr "con selector de subred"
+
+#: rfc2131.c:316
+msgid "via"
+msgstr "vía"
+
+#: rfc2131.c:331
+#, fuzzy, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr "%u Subred DHCP disponible: %s/%s"
+
+#: rfc2131.c:334
+#, fuzzy, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr "%u Rango DHCP disponible: %s -- %s"
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr "deshabilitado"
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr "ignorado"
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr "dirección en uso"
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr "ninguna dirección disponible"
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr "red equivocada"
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr "ninguna dirección configurada"
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr "no sobra ningún arriendo"
+
+#: rfc2131.c:545
+#, fuzzy, c-format
+msgid "%u client provides name: %s"
+msgstr "%u cliente provee nombre: %s"
+
+#: rfc2131.c:700
+#, fuzzy, c-format
+msgid "%u vendor class: %s"
+msgstr "%u Clase de vendedor: %s"
+
+#: rfc2131.c:702
+#, fuzzy, c-format
+msgid "%u user class: %s"
+msgstr "%u Clase de usuario: %s"
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr "no hay soporte para BIS PXE"
+
+#: rfc2131.c:886
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "deshabilitando dirección DHCP estática %s para %s"
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr "arriendo desconocido"
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr "no usando dirección configurada %s porque está arrendada a %s"
+
+#: rfc2131.c:949
+#, fuzzy, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr "no usando dirección configurada %s porque está en uso por el servidor o relay"
+
+#: rfc2131.c:952
+#, fuzzy, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr "no usando dirección configurada %s porque fué previamente denegada"
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr "ningún unique-id (identificación Ãºnica)"
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr "ID de servidor equivocada"
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr "dirección equivocada"
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr "arriendo no encontrado"
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr "dirección no disponible"
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr "arriendo estático disponible"
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr "dirección reservada"
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr "abandonando arriendo a %s de %s"
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr "%u etiquetas: %s"
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr "%u nombre de bootfile: %s"
+
+#: rfc2131.c:1732
+#, c-format
+msgid "%u server name: %s"
+msgstr "%u nombre de servidor: %s"
+
+#: rfc2131.c:1746
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "%u siguiente servidor: %s"
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr ""
+
+#: rfc2131.c:1812
+#, fuzzy, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr "no se puede enviar opción DHCP/BOOTP %d: no queda espacio en paquete"
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr "menú PXE demasiado grande"
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr "Ignorando dominio %s para nombre de host DHCP %s"
+
+#: rfc2131.c:2189
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "%u opciones solicitadas: %s"
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr "no se puede enviar opción RFC3925: demasiadas opciones para número enterprise %d"
+
+#: netlink.c:70
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "no se puede crear socket netlink: %s"
+
+#: netlink.c:288
+#, fuzzy, c-format
+msgid "netlink returns error: %s"
+msgstr "netlink retorna error: %s"
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr "intento de fijar dirección de servidor IPv6 vía DBus - no hay soporte IPv6"
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr "fijando servidores upstream desde DBus"
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr "no se pudo registrar un manejador de mensajes DBus"
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "no se puede crear socket BPF DHCP: %s"
+
+#: bpf.c:245
+#, fuzzy, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr "pedido DHCP por tipo de hardware no-soportado (%d) recibido en %s"
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr "incapaz de conseguir puerto libre para TFTP"
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr "pedido no-soportado desde %s"
+
+#: tftp.c:406
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "archivo %s no encontrado"
+
+#: tftp.c:522
+#, fuzzy, c-format
+msgid "error %d %s received from %s"
+msgstr "error TFTP %d %s recibido de %s"
+
+#: tftp.c:554
+#, fuzzy, c-format
+msgid "failed sending %s to %s"
+msgstr "TFTP no pudo enviar %s a %s"
+
+#: tftp.c:568
+#, fuzzy, c-format
+msgid "sent %s to %s"
+msgstr "TFTP envió %s a %s"
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr "desbordamiento: %d entradas de bitácora perdidas"
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr "bitácora falló: %s"
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr "el inicio ha FALLADO"
+
+#, fuzzy
+#~ msgid "only one dhcp-hostsfile allowed"
+#~ msgstr "solo un dhcp-hostsfile permitido"
+
+#, fuzzy
+#~ msgid "only one dhcp-optsfile allowed"
+#~ msgstr "solo un dhcp-optsfile permitido"
+
+#~ msgid "files nested too deep in %s"
+#~ msgstr "archivos jerarquizados demasiado profundo en %s"
+
+#~ msgid "TXT record string too long"
+#~ msgstr "expediente TXT demasiado largo"
+
+#~ msgid "failed to set IPV6 options on listening socket: %s"
+#~ msgstr "no se pudo fijar opciones IPv6 sobre socket escuchador: %s"
+
+#~ msgid "failed to bind listening socket for %s: %s"
+#~ msgstr "no se pudo acoplar socket escuchador para %s: %s"
+
+#~ msgid "failed to listen on socket: %s"
+#~ msgstr "no se pudo escuchar en socket: %s"
+
+#, fuzzy
+#~ msgid "failed to create TFTP socket: %s"
+#~ msgstr "no se pudo crear socket TFTP: %s"
+
+#~ msgid "DHCP packet: transaction-id is %u"
+#~ msgstr "paquete DHCP: transaction-id (identificación de transacción) es %u"
+
+#~ msgid "must set exactly one interface on broken systems without IP_RECVIF"
+#~ msgstr "debe fijarse exáctamente una interface en sistemas rotos sin IP_RECVIF"
+
+#, fuzzy
+#~ msgid "failed to load %s: %s"
+#~ msgstr "no se pudo cargar %s: %s"
+
+#~ msgid "bad name in %s"
+#~ msgstr "nombre erróneo en %s"
+
+#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part"
+#~ msgstr "Ignorando arriendo DHCP para %s porque tiene una parte ilegal de dominio"
+
+#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"
+#~ msgstr "integración dhcpd ISC no disponible: fijar HAVE_ISC_READER en src/config.h"
+
+#, fuzzy
+#~ msgid "illegal domain %s in dhcp-config directive."
+#~ msgstr "dominio ilegal %s en directiva dhcp-config."
+
+#~ msgid "illegal domain %s in %s."
+#~ msgstr "dominio ilegal %s en %s."
+
+#~ msgid "running as root"
+#~ msgstr "corriendo como root"
+
+#~ msgid "Read leases at startup, but never write the lease file."
+#~ msgstr "Leer arriendos al inicio, pero nunca escribir el archivo de arriendos."
+
+#, fuzzy
+#~ msgid "read %s - %d hosts"
+#~ msgstr "direcciónes %s - %d leídas"
+
+#~ msgid "Limit of %d leases exceeded."
+#~ msgstr "Límite de %d arriendos excedido."
+
+#~ msgid "domains"
+#~ msgstr "dominios"
+
+#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part"
+#~ msgstr "Ignorando nombre de host DHCP %s porque contiene una parte ilegal de dominio"
+
+#~ msgid "Display this message."
+#~ msgstr "Mostrar este mensaje."
+
+#~ msgid "failed to read %s: %m"
+#~ msgstr "no se pudo leer %s: %m"
+
+#~ msgid "failed to read %s:%m"
+#~ msgstr "no se pudo leer %s:%m"
diff --git a/po/fi.po b/po/fi.po
new file mode 100644 (file)
index 0000000..ccd0338
--- /dev/null
+++ b/po/fi.po
@@ -0,0 +1,1455 @@
+# Finnish translations for dnsmasq package.
+# This file is put in the public domain.
+# Simon Kelley <simon@thekelleys.org.uk>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.24\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2005-11-28 22:05+0000\n"
+"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
+"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: cache.c:761
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr ""
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr ""
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr ""
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr ""
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr ""
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr ""
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr ""
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1040
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr ""
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:57
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr ""
+
+#: util.c:189
+msgid "failed to allocate memory"
+msgstr ""
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr ""
+
+#: util.c:237
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr ""
+
+#: util.c:245
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr ""
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr ""
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr ""
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr ""
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr ""
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr ""
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr ""
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr ""
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr ""
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr ""
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr ""
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr ""
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr ""
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr ""
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr ""
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr ""
+
+#: option.c:258
+msgid "Read DHCP host specs from file."
+msgstr ""
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr ""
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr ""
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr ""
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr ""
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr ""
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr ""
+
+#: option.c:265
+msgid "Map DHCP user class to tag."
+msgstr ""
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:269
+msgid "Don't do DHCP for hosts with tag set."
+msgstr ""
+
+#: option.c:270
+msgid "Force broadcast replies for hosts with tag set."
+msgstr ""
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr ""
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr ""
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr ""
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr ""
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr ""
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr ""
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr ""
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr ""
+
+#: option.c:280
+msgid "Specify options to be sent to DHCP clients."
+msgstr ""
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr ""
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr ""
+
+#: option.c:284
+msgid "Log DNS queries."
+msgstr ""
+
+#: option.c:285
+msgid "Force the originating port for upstream DNS queries."
+msgstr ""
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr ""
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr ""
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr ""
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr ""
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr ""
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr ""
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr ""
+
+#: option.c:293
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr ""
+
+#: option.c:294
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr ""
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr ""
+
+#: option.c:296
+msgid "Map DHCP vendor class to tag."
+msgstr ""
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr ""
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr ""
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr ""
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:301
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr ""
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr ""
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr ""
+
+#: option.c:305
+msgid "Specify PTR DNS record."
+msgstr ""
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr ""
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr ""
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr ""
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr ""
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr ""
+
+#: option.c:312
+msgid "Map MAC address (with wildcards) to option set."
+msgstr ""
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:317
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr ""
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:319
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr ""
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:327
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr ""
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr ""
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr ""
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:339
+msgid "Specify NAPTR DNS record."
+msgstr ""
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr ""
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr ""
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:345
+msgid "Prompt to send to PXE clients."
+msgstr ""
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+#: option.c:349
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr ""
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr ""
+
+#: option.c:642
+#, c-format
+msgid "Valid options are:\n"
+msgstr ""
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr ""
+
+#: option.c:860
+msgid "bad IP address"
+msgstr ""
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr ""
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr ""
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1147 option.c:3030
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr ""
+
+#: option.c:1178 tftp.c:460
+#, c-format
+msgid "cannot access %s: %s"
+msgstr ""
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr ""
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr ""
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr ""
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr ""
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1791
+msgid "bad port range"
+msgstr ""
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr ""
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr ""
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr ""
+
+#: option.c:2019 option.c:2045
+msgid "bad hex constant"
+msgstr ""
+
+#: option.c:2107
+msgid "bad DHCP host name"
+msgstr ""
+
+#: option.c:2188
+msgid "bad tag-if"
+msgstr ""
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr ""
+
+#: option.c:2529
+msgid "bad dhcp-proxy address"
+msgstr ""
+
+#: option.c:2569
+msgid "invalid alias range"
+msgstr ""
+
+#: option.c:2582
+msgid "bad interface name"
+msgstr ""
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2632
+msgid "bad PTR record"
+msgstr ""
+
+#: option.c:2663
+msgid "bad NAPTR record"
+msgstr ""
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr ""
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr ""
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr ""
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr ""
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr ""
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2849
+msgid "missing \""
+msgstr ""
+
+#: option.c:2908
+msgid "bad option"
+msgstr ""
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr ""
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr ""
+
+#: option.c:2916
+msgid "error"
+msgstr ""
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr ""
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: option.c:3151 option.c:3187
+#, c-format
+msgid "read %s"
+msgstr ""
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr ""
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr ""
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:3273
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:3284
+msgid "try --help"
+msgstr ""
+
+#: option.c:3286
+msgid "try -w"
+msgstr ""
+
+#: option.c:3289
+#, c-format
+msgid "bad command line options: %s"
+msgstr ""
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr ""
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr ""
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr ""
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, c-format
+msgid "failed to read %s: %s"
+msgstr ""
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr ""
+
+#: option.c:3409
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr ""
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr ""
+
+#: network.c:171
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr ""
+
+#: network.c:380
+#, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr ""
+
+#: network.c:746
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr ""
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr ""
+
+#: network.c:794
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr ""
+
+#: network.c:811
+msgid "unqualified"
+msgstr ""
+
+#: network.c:811
+msgid "names"
+msgstr ""
+
+#: network.c:813
+msgid "default"
+msgstr ""
+
+#: network.c:815
+msgid "domain"
+msgstr ""
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:820
+#, c-format
+msgid "using standard nameservers for %s %s"
+msgstr ""
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:825
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:148
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:158
+msgid "asychronous logging is not available under Android"
+msgstr ""
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr ""
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr ""
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr ""
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr ""
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:455
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr ""
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr ""
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr ""
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr ""
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr ""
+
+#: dnsmasq.c:474
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr ""
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr ""
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr ""
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:491
+msgid "warning: no upstream servers configured"
+msgstr ""
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:526
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr ""
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, c-format
+msgid "failed to create helper: %s"
+msgstr ""
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:785
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:790
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:793
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr ""
+
+#: dnsmasq.c:796
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:859
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr ""
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr ""
+
+#: dnsmasq.c:931
+#, c-format
+msgid "failed to access %s: %s"
+msgstr ""
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr ""
+
+#: dnsmasq.c:972
+#, c-format
+msgid "no servers found in %s, will retry"
+msgstr ""
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:65
+#, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr ""
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr ""
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr ""
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr ""
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr ""
+
+#: dhcp.c:981
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr ""
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr ""
+
+#: lease.c:67
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr ""
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:129
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr ""
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:235
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr ""
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:331
+#, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:700
+#, c-format
+msgid "%u vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:702
+#, c-format
+msgid "%u user class: %s"
+msgstr ""
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:886
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr ""
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1732
+#, c-format
+msgid "%u server name: %s"
+msgstr ""
+
+#: rfc2131.c:1746
+#, c-format
+msgid "%u next server: %s"
+msgstr ""
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr ""
+
+#: rfc2131.c:1812
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2189
+#, c-format
+msgid "%u requested options: %s"
+msgstr ""
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr ""
+
+#: netlink.c:70
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr ""
+
+#: netlink.c:288
+#, c-format
+msgid "netlink returns error: %s"
+msgstr ""
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr ""
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr ""
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr ""
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr ""
+
+#: bpf.c:245
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr ""
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:406
+#, c-format
+msgid "file %s not found"
+msgstr ""
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:554
+#, c-format
+msgid "failed sending %s to %s"
+msgstr ""
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr ""
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr ""
diff --git a/po/fr.po b/po/fr.po
new file mode 100644 (file)
index 0000000..6863785
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,1571 @@
+# French translations for dnsmasq package.
+# This file is put in the public domain.
+# Lionel Tricon <lionel.tricon@free.fr>, 2005.
+# Translation completed by Gildas Le Nadan <3ntr0p13@gmail.com>
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.56\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2011-02-10 20:40+0100\n"
+"Last-Translator:  Gildas Le Nadan <3ntr0p13@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: cache.c:761
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr "Impossible de charger les noms Ã  partir de %s : %s"
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "mauvaise adresse dans %s ligne %d"
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "mauvais nom dans %s ligne %d"
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "lecture %s - %d adresses"
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr "cache vidé"
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr "%s est un CNAME, il ne sera pas donné au bail DHCP de %s"
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr "ne donne pas de nom %s au bail DHCP de %s parce-que le nom existe dans %s avec l'adresse %s"
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr "horodatage %lu"
+
+#: cache.c:1040
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr "taille de cache %d, %d/%d insertions dans le cache entrées non-expirées réutilisées"
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr "requêtes transmises %u, requêtes résolues localement %u"
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr "serveur %s#%d: requêtes envoyées %u, requêtes réessayées ou Ã©chouées %u"
+
+#: util.c:57
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "impossible d'initialiser le générateur de nombre aléatoire : %s"
+
+#: util.c:189
+msgid "failed to allocate memory"
+msgstr "impossible d'allouer la mémoire"
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr "impossible d'allouer de la mémoire"
+
+#: util.c:237
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr "Ne peut pas créer le tube %s : %s"
+
+#: util.c:245
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr "impossible d'allouer %d octets"
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr "illimité(e)"
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr "Spécifie la ou les adresse(s) locales où le démon doit se mettre Ã  l'écoute."
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Retourne les adresses IP pour toutes les machines présentes dans les domaines spécifiés"
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Traduction inverse truquée pour la plage d'adresse privée RFC1918"
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Traite l'adresse IP comme un domaine inexistant NXDOMAIN (contourne le systeme de redirection de Verisign)"
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Spécifie le nombre d'entrées que contiendra le cache (par défaut : %s)."
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Spécifie le nom du fichier de configuration (par défaut : %s)"
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "Ne passe pas en tâche de fond : démarre en mode debug"
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr "Ne retransmet pas les requêtes qui n'ont pas de domaine."
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Retourne les champs MX pour les machines locales."
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Etend les noms uniques des machines dans /etc/hosts avec le suffixe du domaine."
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Ne retransmet pas les fausses requêtes DNS en provenance des machines Windows."
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Autorise DHCP dans la plage d'adresses donnée sur la durée de validité du bail."
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "On change pour ce groupe après le démarrage (par défaut : %s)."
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr "On assigne une adresse ou un nom pour une machine spécifiée."
+
+#: option.c:258
+msgid "Read DHCP host specs from file."
+msgstr "Lecture des spécifications d'hôtes DHCP Ã  partir du fichier"
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr "Lecture des options DHCP Ã  partir du fichier"
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr "Expression d'évaluation conditionnelle d'étiquette"
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "Ne charge PAS le fichier %s."
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Spécifie un nom de fichier hosts Ã  lire en complément de %s"
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr "Spécifie la ou les interface(s) où le démon doit se mettre Ã  l'écoute."
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Spécifie la ou les interface(s) que le démon ne doit PAS traiter."
+
+#
+#: option.c:265
+msgid "Map DHCP user class to tag."
+msgstr "Associe les classes d'utilisateurs ('user class') DHCP aux options."
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr "Associe les identifiants de circuits RFC3046 ('circuit-id') aux options"
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr "Associe les identifiants distants RFC3046 ('remote-id') aux options"
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr "Associe les identifiants de souscripteurs RFC3993 ('subscriber-id') aux options"
+
+#
+#: option.c:269
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Ne pas autoriser DHCP pour les machines Ã©numerées dans les options."
+
+#
+#: option.c:270
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Forcer les réponses par 'broadcast' pour les machines Ã©numerées dans les options."
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr "Ne passe pas en tâche de fond, ne pas s'exécuter en mode debug."
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr "On considère que l'on est le seul serveur DHCP sur le réseau local."
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Spécifie où il faut sauvegarder les baux DHCP (par défaut : %s)."
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr "Retourne les champs MX pour les machines locales."
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr "Spécifie un champ MX."
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Spécifie les options BOOTP pour le serveur DHCP."
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "Ne pas scruter le fichier %s, ne recharger les modifications que sur réception du signal SIGHUP."
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr "Ne place pas en cache le résultat des requêtes qui ont Ã©chouées."
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr "Utilise les serveurs de noms dans l'ordre donné dans %s."
+
+#
+#: option.c:280
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Options supplémentaires Ã  associer aux clients DHCP."
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr "Option DHCP envoyée même si le client de la demande pas."
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Spécifie le port où il faut Ã©couter les requêtes DNS (par défaut : 53)."
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr "Taille maximale des paquets UDP supportés pour EDNS.0 (par défaut : %s)."
+
+#
+#: option.c:284
+msgid "Log DNS queries."
+msgstr "Enregistre les requêtes DNS dans un journal d'activité."
+
+#
+#: option.c:285
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Force le port d'origine pour les requêtes vers les serveurs amonts."
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr "Ne pas lire le fichier resolv.conf."
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Spécifie le chemin pour le fichier resolv.conf (par défaut : %s)."
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Spécifie la ou les adresses des serveurs amonts avec des domaines optionels."
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr "Ne jamais retransmettre les requêtes pour les domaines spécifiés."
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Spécifie le domaine qui doit etre assigné aux baux DHCP."
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr "Spécifie la cible par défaut dans un champ MX."
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts."
+
+#
+#: option.c:293
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts."
+
+#: option.c:294
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr "Spécifie, en secondes, la valeur maximum de TTL Ã  renvoyer aux clients."
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Change pour cet utilisateur après le démarrage (par défaut : %s)."
+
+#
+#: option.c:296
+msgid "Map DHCP vendor class to tag."
+msgstr "Associe les classes de fournisseurs ('vendor class') DHCP aux options."
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr "Affiche la version de Dnsmasq et les informations liées au copyright."
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Traduit les adresses IPV4 des serveurs amonts."
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr "Spécifie un champ SRV."
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr "Afficher ce message. Utiliser --help dhcp pour obtenir la liste des options DHCP connues."
+
+#: option.c:301
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Spécifie un chemin pour le fichier PID (par défaut : %s)."
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Spécifie le nombre maximum de baux DHCP (par défaut : %s)."
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr "Repond aux requêtes DNS en se basant sur l'interface ou a Ã©té envoyée la requête."
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr "Spécifie un champ DNS TXT"
+
+#
+#: option.c:305
+msgid "Specify PTR DNS record."
+msgstr "Spécifie un champ DNS PTR"
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr "Donne le nom DNS pour l'adresse IPv4 de l'interface."
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr "Association uniquement aux interfaces réseau actuellement actives."
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Lecture des informations de DHCP statique Ã  partir de %s."
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Autorise l'interface DBus pour la configuration des serveurs amonts, etc."
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "Ne pas assurer de fonction DHCP sur cette interface, mais seulement la fonction DNS."
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Autorise l'allocation dynamique d'adresse pour bootp."
+
+#
+#: option.c:312
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Associe l'adresse MAC (avec les jokers) aux options."
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr "Traiter les requêtes DHCP sur les alias comme arrivant de l'interface."
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr "Supprime la vérification d'adresse sur le serveur au moyen de paquets ICMP echo"
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr "Script Ã  exécuter lors de la création ou destruction de bail DHCP."
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr "Lecture de la configuration dans tous les fichiers de ce répertoire."
+
+#
+#: option.c:317
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Enregistrer les journaux d'activité dans cette facilité syslog. (défaut : DAEMON)"
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr "Ne pas utiliser de fichier de baux."
+
+#: option.c:319
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Spécifie le nombre maximum de requêtes DHCP concurrentes (par défaut : %s)."
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr "Vider le cache DNS lors du rechargement de %s."
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr "Ignorer les noms d'hôtes fournis par les clients DHCP"
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr "Ne pas réutiliser les champs nom de fichier et serveur dans les options DHCP supplémentaires."
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr "Activer le server TFTP intégré (fonctionnant en lecture seulement)"
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr "N'exporter par TFTP que les fichiers de l'arborescence de fichier spécifiée"
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr "Ajouter les adresses IP clientes Ã  la racine tftp ('tftp-root')."
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr "Accès aux seuls fichiers appartenants Ã  l'utilisateur sous lequel tourne dnsmasq"
+
+#: option.c:327
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Spécifie le nombre maximum de transfert TFTP concurrents (défaut : %s)."
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr "Désactivation de l'extension TFTP Â« taille de bloc Â»"
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr "Gamme de ports dans laquelle seront choisis les ports temporaires utilisés dans les transferts TFTP."
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr "Traces supplémentaires pour le DHCP."
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr "Active l'écriture de traces en mode asynchrone. Peut prendre en option la valeur de la longueur de la queue."
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr "Stopper la réassociation DNS ('DNS rebinding'). Filtre les gammes d'adresses IP privées lors de la résolution."
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr "Autorise la réassociation de 127.0.0/8, pour les serveurs RBL (Realtime Blackhole List)"
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr "Désactive la protection contre les réassociation DNS pour ce domaine"
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr "Toujours effectuer les requêtes DNS Ã  tous les serveurs."
+
+#
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr "Spécifie le label si le client inclus l'option dans la requête."
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr "Utiliser des ports alternatifs pour le DHCP."
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr "Lancer le script 'lease-change' avec cet utilisateur."
+
+#
+#: option.c:339
+msgid "Specify NAPTR DNS record."
+msgstr "Spécifie un champ DNS NAPTR."
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr "Définie le plus petit port utilisé pour la transmission d'une requête DNS."
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr "Utilise seulement les noms de domaine pleinement qualifiés pour les clients DHCP."
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr "Génère les noms d'hôtes Ã  partir de l'adresse MAC pour les clients sans nom."
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr "Utilise ces relais DHCP en temps que proxy complets."
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr "Spécifie un alias pour un nom DNS local."
+
+#
+#: option.c:345
+msgid "Prompt to send to PXE clients."
+msgstr "Invite Ã  envoyer aux clients PXE."
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr "Service de démarrage pour menu PXE."
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr "vérification de la syntaxe de la configuration."
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr "Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises"
+
+#: option.c:349
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr "Transmet les résultats de validation DNSSEC des serveurs amonts"
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Usage : dnsmasq [options]\n"
+"\n"
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "Utilisez les options courtes uniquement sur la ligne de commande.\n"
+
+#: option.c:642
+#, c-format
+msgid "Valid options are:\n"
+msgstr "Les options valides sont :\n"
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr "Options DHCP connues :\n"
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr "mauvaise valeur de 'dhcp-option'"
+
+#
+#: option.c:860
+msgid "bad IP address"
+msgstr "mauvaise adresse IP"
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr "mauvais domaine dans dhcp-option"
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr "dhcp-option trop long"
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr "valeur illégale pour 'dhcp-match'"
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr "Une option ne pouvant Ãªtre spécifié qu'une seule fois Ã  Ã©té donnée plusieurs fois"
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr "Mot-clef ne pouvant Ãªtre répété"
+
+#: option.c:1147 option.c:3030
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr "Ne peut pas lire le répertoire %s : %s"
+
+#: option.c:1178 tftp.c:460
+#, c-format
+msgid "cannot access %s: %s"
+msgstr "Ne peut pas lire %s : %s"
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr "préference MX incorrecte"
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr "nom MX incorrect"
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr "valeur MX cible incorrecte"
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr "ne peut exécuter de script sous uClinux"
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr "pour permettre l'exécution de scripts au changement de bail (lease-change), recompiler en définissant HAVE_SCRIPT"
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr "numéro de port incorrect"
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr "association d'interface non supportée"
+
+#
+#: option.c:1791
+msgid "bad port range"
+msgstr "gamme de ports incorrecte"
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr "interface-pont incorrecte"
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr "plage d'adresses DHCP (dhcp-range) incorrecte"
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr "une seule Ã©tiquette est autorisée"
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr "plage d'adresses DHCP incohérente"
+
+#: option.c:2019 option.c:2045
+msgid "bad hex constant"
+msgstr "mauvaise constante hexadecimale"
+
+#
+#: option.c:2107
+msgid "bad DHCP host name"
+msgstr "nom d'hôte DHCP incorrect"
+
+#: option.c:2188
+msgid "bad tag-if"
+msgstr "mauvaise Ã©tiquette tag-if"
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr "numéro de port invalide"
+
+#
+#: option.c:2529
+msgid "bad dhcp-proxy address"
+msgstr "adresse dhcp-proxy incorrecte"
+
+#
+#: option.c:2569
+msgid "invalid alias range"
+msgstr "poids invalide"
+
+#
+#: option.c:2582
+msgid "bad interface name"
+msgstr "nom d'interface invalide"
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr "mauvais CNAME"
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr "ce CNAME existe déja"
+
+#
+#: option.c:2632
+msgid "bad PTR record"
+msgstr "mauvais champ PTR"
+
+#
+#: option.c:2663
+msgid "bad NAPTR record"
+msgstr "mauvais champ NAPTR"
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr "champ TXT invalide"
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr "champ SRV invalide"
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr "cible SRV invalide"
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr "priorité invalide"
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr "poids invalide"
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr "option non supportée (vérifier que Dnsmasq a Ã©té compilé avec le support DHCP/TFTP/DBus)"
+
+#: option.c:2849
+msgid "missing \""
+msgstr "il manque \""
+
+#: option.c:2908
+msgid "bad option"
+msgstr "mauvaise option"
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr "paramètre en trop"
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr "paramètre manquant"
+
+#: option.c:2916
+msgid "error"
+msgstr "erreur"
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s Ã  la ligne %d de %%s"
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "Ne peut pas lire %s : %s"
+
+#: option.c:3151 option.c:3187
+#, c-format
+msgid "read %s"
+msgstr "Lecture de %s"
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr "la ligne de commande contient des Ã©léments indésirables ou incompréhensibles"
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr "Version de Dnsmasq %s  %s\n"
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Options Ã  la compilation %s\n"
+"\n"
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Ce logiciel est fourni sans AUCUNE GARANTIE.\n"
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr "Dnsmasq est un logiciel libre, il vous est permis de le redistribuer\n"
+
+#: option.c:3273
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr "sous les termes de la licence GPL (GNU General Public License), version 2 ou 3.\n"
+
+#: option.c:3284
+msgid "try --help"
+msgstr "essayez avec --help"
+
+#: option.c:3286
+msgid "try -w"
+msgstr "essayez avec -w"
+
+#: option.c:3289
+#, c-format
+msgid "bad command line options: %s"
+msgstr "mauvaises options en ligne de commande : %s."
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "ne peut pas obtenir le nom de la machine : %s"
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "seul un fichier resolv.conf est autorisé dans le mode no-poll"
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "un fichier resolv.conf (et un seul) est nécessaire pour y récuperer le nom de domaine."
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, c-format
+msgid "failed to read %s: %s"
+msgstr "impossible de lire %s : %s"
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr "pas de directive de recherche trouvée dans %s"
+
+#: option.c:3409
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr "un domaine par défaut doit Ãªtre spécifié lorsque l'option --dhcp-fqdn est utilisée"
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr "vérification de syntaxe OK"
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "le serveur de nom %s a refusé de faire une recherche récursive"
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr "détection d'une possible attaque de type DNS-rebind: %s"
+
+#: network.c:171
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "interface %s inconnue spécifiée comme interface de pont"
+
+#: network.c:380
+#, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr "impossible de créer une socket d'écoute pour %s : %s"
+
+#: network.c:746
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "impossible de lier la socket de serveur pour %s : %s"
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignore le serveur de nom %s - interface locale"
+
+#: network.c:794
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "ignore le serveur de nom %s - ne peut construire/lier la socket : %m"
+
+#: network.c:811
+msgid "unqualified"
+msgstr "non-qualifié(e)"
+
+#: network.c:811
+msgid "names"
+msgstr "noms"
+
+#: network.c:813
+msgid "default"
+msgstr "défaut"
+
+#: network.c:815
+msgid "domain"
+msgstr "domaine"
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "utilise les adresses locales seulement pour %s %s"
+
+#: network.c:820
+#, c-format
+msgid "using standard nameservers for %s %s"
+msgstr "utilisation des serveurs de nom standards pour %s %s"
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "utilise le serveur de nom %s#%d pour %s %s"
+
+#: network.c:825
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "utilise le serveur de nom %s#%d (via %s)"
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "utilise le serveur de nom %s#%d"
+
+#
+#: dnsmasq.c:148
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr "TFTP n'est pas disponible : activez HAVE_TFTP dans src/config.h"
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr "l'écriture de traces en mode asynchrone n'est pas disponible sous Solaris."
+
+#: dnsmasq.c:158
+#, fuzzy
+msgid "asychronous logging is not available under Android"
+msgstr "l'écriture de traces en mode asynchrone n'est pas disponible sous Solaris."
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "impossible de trouver la liste des interfaces : %s"
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr "interface %s inconnue"
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr "pas d'interface avec l'adresse %s"
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr "Erreur DBus : %s"
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus n'est pas disponible : activez HAVE_DBUS dans src/config.h"
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr "utilisateur ou groupe inconnu : %s"
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr "Ne peut effectuer un 'chdir' Ã  la racine du système de fichier : %s"
+
+#: dnsmasq.c:455
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr "démarrage avec le DNS désactivé (version %s)"
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "demarré, version %s (taille de cache %d)"
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "démarrage avec le cache désactivé (version %s)"
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr "options Ã  la compilation : %s"
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr "Support DBus autorisé : connecté au bus système"
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr "Support DBus autorisé : connexion au bus en attente"
+
+#: dnsmasq.c:474
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "Impossible de changer pour l'utilisateur %s : %s"
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "active l'option --bind-interfaces Ã  cause de limitations dans le système d'exploitation"
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "attention : l'interface %s n'existe pas actuellement"
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr "attention : l'option Â« resolv-file Â» sera ignorée car Â« no-resolv Â» a Ã©té spécifié"
+
+#
+#: dnsmasq.c:491
+msgid "warning: no upstream servers configured"
+msgstr "attention : aucun serveur amont n'est configuré"
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr "mode asynchrone d'écriture de traces, la taille maximum de la queue est de %d messages."
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr "baux statiques DHCP seulement sur %.0s%s, durée de validité de bail %s"
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr "DHCP, proxy sur le sous-réseau %.0s%s%.0s"
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, plage d'adresses %s -- %s, durée de bail %s"
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr "root est"
+
+#
+#: dnsmasq.c:526
+msgid "enabled"
+msgstr "activé"
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr "mode sécurisé"
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr "le nombre maximum de transferts TFTP simultanés sera restreint Ã  %d"
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr "connecté au systeme DBus"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr "Ne peut se lancer en tâche de fond : %s"
+
+#: dnsmasq.c:778
+#, c-format
+msgid "failed to create helper: %s"
+msgstr "impossible de créer le 'helper' : %s"
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr "impossible de configurer la capacité %s"
+
+#: dnsmasq.c:785
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "Impossible de changer l'identifiant utilisateur pour %s : %s"
+
+#: dnsmasq.c:790
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "Impossible de changer l'identifiant de groupe pour %s : %s"
+
+#: dnsmasq.c:793
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "impossible de lire le fichier de PID %s : %s"
+
+#: dnsmasq.c:796
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "Ne peut pas lire %s : %s"
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr "Le processus fils a Ã©té terminé par le signal %d"
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr "Le processus fils s'est terminé avec le statut %d"
+
+#: dnsmasq.c:859
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr "impossible d'exécuter Ã  %s : %s"
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr "sortie sur réception du signal SIGTERM"
+
+#: dnsmasq.c:931
+#, c-format
+msgid "failed to access %s: %s"
+msgstr "impossible d'accéder Ã  %s : %s"
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr "Lecture de %s"
+
+#: dnsmasq.c:972
+#, c-format
+msgid "no servers found in %s, will retry"
+msgstr "aucun serveur trouvé dans %s, va réessayer"
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr "ne peut créer la socket DHCP: %s"
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr "impossible d'appliquer les options sur la socket DHCP : %s"
+
+#: dhcp.c:65
+#, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr "impossible de déclarer SO_REUSE{ADDR|PORT} sur la socket DHCP : %s"
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr "impossible de lier la socket serveur DHCP : %s"
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "ne peut créer de socket en mode raw pour ICMP : %s."
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr "Paquet DHCP reçu sur %s qui n'a pas d'adresse"
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr "La plage d'adresses DHCP %s -- %s n'est pas cohérente avec le masque de réseau %s"
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "mauvaise ligne dans %s ligne %d"
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr "ignore %s Ã  la ligne %d : duplication de nom ou d'adresse IP"
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "adresse IP %s dupliquée dans la directive dhcp-config."
+
+#: dhcp.c:981
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "adresse IP %s dupliquée dans %s."
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr "%s a plus d'une adresse dans le fichier d'hôte, utilisation de %s pour le DHCP."
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr "adresse IP %s (%s) dupliquée dans la directive dhcp-config."
+
+#: lease.c:67
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "ne peut ouvrir ou créer le fichiers de baux %s : %s"
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr "beaucoup trop de baux enregistrés"
+
+#: lease.c:129
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "Ne peut pas exécuter le script lease-init %s : %s"
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr "le script lease-init a retourné le code %s"
+
+#: lease.c:235
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "impossible de lire %s : %s (prochain essai dans %us)"
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr "pas de plage d'adresse disponible pour la requête DHCP %s %s"
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr "avec sélecteur de sous-reseau"
+
+#: rfc2131.c:316
+msgid "via"
+msgstr "par l'intermédiaire de"
+
+#: rfc2131.c:331
+#, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr "%u sous-réseaux DHCP disponibles : %s/%s"
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr "%u la gamme DHCP disponible est : %s -- %s"
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr "désactivé"
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr "ignoré"
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr "adresse déjà utilisée"
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr "pas d'adresse disponible"
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr "mauvais réseau"
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr "pas d'adresse configurée"
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr "plus aucun bail disponible"
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr "le client %u fourni le nom : %s"
+
+#: rfc2131.c:700
+#, c-format
+msgid "%u vendor class: %s"
+msgstr "%u Classe de vendeur ('Vendor Class') : %s"
+
+#: rfc2131.c:702
+#, c-format
+msgid "%u user class: %s"
+msgstr "%u Classe d'utilisateur : %s"
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr "Service PXE BIS (Boot Integrity Services) non supporté"
+
+#: rfc2131.c:886
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "désactive l'adresse statique DHCP %s pour %s"
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr "bail inconnu"
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr "L'adresse statique %s ne sera pas utilisée car un bail est déjà attribué Ã  %s"
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr "L'adresse statique %s ne sera pas utilisée car elle est utilisée par le serveur ou un relai"
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr "L'adresse statique %s ne sera pas utilisée car elle a préalablement Ã©té refusée"
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr "pas d'identifiant unique"
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr "mauvais identifiant de serveur"
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr "mauvaise adresse"
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr "bail non trouvé"
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr "adresse non disponible"
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr "bail statique disponible"
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr "adresse reservée"
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr "abandon du bail de %s pour %s"
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr "%u options: %s"
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr "%u nom de fichier 'bootfile' : %s"
+
+#: rfc2131.c:1732
+#, c-format
+msgid "%u server name: %s"
+msgstr "%u nom du serveur : %s"
+
+#: rfc2131.c:1746
+#, c-format
+msgid "%u next server: %s"
+msgstr "%u serveur suivant : %s"
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr "%u réponse broadcast"
+
+#: rfc2131.c:1812
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr "Impossible d'envoyer l'option DHCP/BOOTP %d : pas assez d'espace dans le paquet"
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr "menu PXE trop grand"
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr "Le domaine %s est ignoré pour l'hôte DHCP %s"
+
+#: rfc2131.c:2189
+#, c-format
+msgid "%u requested options: %s"
+msgstr "%u options demandées : %s"
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr "ne peux envoyer l'option RFC3925 : trop d'options pour le numéro d'entreprise %d"
+
+#: netlink.c:70
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "ne peux lier une socket netlink : %s"
+
+#: netlink.c:288
+#, c-format
+msgid "netlink returns error: %s"
+msgstr "Erreur netlink : %s"
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr "tentative de lier une adresse serveur IPV6 via DBus - pas de support IPV6"
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr "configuration des serveurs amonts Ã  partir de DBus"
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr "ne peut enregistrer une routine de traitement des messages DBus"
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "impossible de créer une socket BPF pour DHCP : %s"
+
+#: bpf.c:245
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr "requête DHCP pour un type de matériel non supporté (%d) reçue sur %s"
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr "impossible d'obtenir un port libre pour TFTP"
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr "requête de %s non supportée"
+
+#: tftp.c:406
+#, c-format
+msgid "file %s not found"
+msgstr "fichier %s non trouvé"
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr "erreur %d %s reçu de %s"
+
+#: tftp.c:554
+#, c-format
+msgid "failed sending %s to %s"
+msgstr "impossible d'envoyer %s Ã  %s"
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr "envoyé %s Ã  %s"
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr "débordement : %d traces perdues"
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr "trace perdue : %s"
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr "IMPOSSIBLE de démarrer"
+
+#
+#~ msgid "only one dhcp-hostsfile allowed"
+#~ msgstr "une seule valeur est autorisée pour 'dhcp-hostsfile'"
+
+#
+#~ msgid "only one dhcp-optsfile allowed"
+#~ msgstr "une seule valeur est autorisée pour 'dhcp-optsfile'"
+
+#~ msgid "files nested too deep in %s"
+#~ msgstr "trop de niveaux de récursion pour les fichiers dans %s"
+
+#~ msgid "TXT record string too long"
+#~ msgstr "chaîne du champ TXT trop longue"
+
+#~ msgid "failed to set IPV6 options on listening socket: %s"
+#~ msgstr "impossible d'activer les options IPV6 sur la socket de lecture : %s"
+
+#~ msgid "failed to bind listening socket for %s: %s"
+#~ msgstr "impossible de lier la socket de lecture pour %s : %s"
+
+#~ msgid "failed to listen on socket: %s"
+#~ msgstr "impossible de lire sur la socket : %s"
+
+#~ msgid "failed to create TFTP socket: %s"
+#~ msgstr "impossible de créer une socket TFTP : %s"
+
+#~ msgid "DHCP packet: transaction-id is %u"
+#~ msgstr "paquet DHCP : l'identifiant de transaction ('transaction-id') est %u"
+
+#~ msgid "failed to read %s:%s"
+#~ msgstr "impossible de lire %s : %s"
+
+#~ msgid "must set exactly one interface on broken systems without IP_RECVIF"
+#~ msgstr "Une interface et une seule doit Ãªtre déclarée sur les systèmes sans IP_RECVIF"
+
+#
+#~ msgid "failed to load %s: %s"
+#~ msgstr "impossible de charger %s : %m"
+
+#~ msgid "bad name in %s"
+#~ msgstr "mauvais nom dans %s"
+
+#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part"
+#~ msgstr "On ignore le bail DHCP pour %s car il possède un nom de domaine illégal"
+
+#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"
+#~ msgstr "L'intégration DHCP ISC n'est pas disponible : activez HAVE_ISC_READER dans src/config.h"
+
+#
+#~ msgid "illegal domain %s in dhcp-config directive."
+#~ msgstr "domaine %s dupliqué dans la directive dhcp-config."
+
+#~ msgid "illegal domain %s in %s."
+#~ msgstr "domaine %s illégal dans %s."
+
+#~ msgid "running as root"
+#~ msgstr "executé en temps que root"
+
+#~ msgid "Read leases at startup, but never write the lease file."
+#~ msgstr "Lecture des baux au démarrage, mais aucune Ã©criture de fichier de baux"
+
+#
+#~ msgid "read %s - %d hosts"
+#~ msgstr "lecture %s - %d hôtes"
+
+#~ msgid "domains"
+#~ msgstr "domaines"
+
+#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part"
+#~ msgstr "Le nom de machine DHCP %s sera ignoré parce qu'il possède un nom de domaine illégal"
+
+#~ msgid "Display this message."
+#~ msgstr "Affiche ce message."
+
+#~ msgid "failed to read %s: %m"
+#~ msgstr "impossible de lire %s : %m"
+
+#~ msgid "failed to read %s:%m"
+#~ msgstr "impossible de lire %s : %m"
+
+#
+#~ msgid "cannot send encapsulated option %d: no space left in wrapper"
+#~ msgstr "Impossible d'envoyer l'option DHCP %d : pas assez d'espace dans le paquet"
+
+#~ msgid "More than one vendor class matches, using %s"
+#~ msgstr "Plusieurs classes de fournisseurs correspondent, %s sera utilisé"
diff --git a/po/id.po b/po/id.po
new file mode 100644 (file)
index 0000000..749da19
--- /dev/null
+++ b/po/id.po
@@ -0,0 +1,1799 @@
+# Indonesian translations for dnsmasq package.
+# This file is put in the public domain.
+# Salman AS <sas@salman.or.id>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.24\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2005-10-07 11:45+0100\n"
+"Last-Translator: Salman AS <sas@salman.or.id>\n"
+"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# OK
+#: cache.c:761
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: cache.c:795 dhcp.c:865
+#, fuzzy, c-format
+msgid "bad address at %s line %d"
+msgstr "kesalahan nama pada %s baris %d"
+
+# OK
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "kesalahan nama pada %s baris %d"
+
+# OK
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "membaca %s - %d alamat"
+
+# OK
+#: cache.c:899
+msgid "cleared cache"
+msgstr "cache telah dihapus"
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr ""
+
+# OK
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr "tidak memberikan nama %s kepada lease DHCP %s karena nama telah ada dalam %sdengan alamat %s"
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+# OK
+#: cache.c:1040
+#, fuzzy, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr "ukuran cache %d, %d/%d penyisipan cache menimpa cache yang belum kadaluwarsa"
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+# OK
+#: util.c:57
+#, fuzzy, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "gagal mendengarkan di socket: %s"
+
+# OK
+#: util.c:189
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "gagal memuat %S: %m"
+
+# OK
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr "tidak bisa mendapatkan memory"
+
+# OK
+#: util.c:237
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+# OK
+#: util.c:245
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "gagal memuat %S: %m"
+
+# OK
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr "tak terbatas"
+
+# OK
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr "Tentukan alamat lokal untuk mendengarkan."
+
+# OK
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Menghasilkan ipaddr untuk semua host dalam domain yang dipilih."
+
+# OK
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Fake pencarian balik untuk alamat private sesuai dengan RFC1918."
+
+# OK
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Perlakukan ipaddr sebagai NXDOMAIN (mengalahkan wildcard Verisign)."
+
+# OK
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Tentukan ukuran cache, dalam jumlah isian (default %s)."
+
+# OK
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Tentukan file konfigurasi (default %s)."
+
+# OK
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "JANGAN berjalan di background: berjalan dalam modus debug."
+
+# OK
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr "JANGAN teruskan permintaan tanpa bagian domain."
+
+# OK
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Mengembalikan record MX untuk diri sendiri host-host lokal."
+
+# OK
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Melengkapi nama-nama di /etc/hosts dengan akhiran domain."
+
+# OK
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Jangan meneruskan permintaan DNS spurious dari host-host Windows."
+
+# OK
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Bolehkan DHCP dalam jangkauan yang diberikan dengan durasi lease."
+
+# OK
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Ubah ke group ini setelah mulai (default %s)."
+
+# OK
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr "Setel alamat atau nama host untuk mesin yang disebutkan."
+
+# OK
+#: option.c:258
+#, fuzzy
+msgid "Read DHCP host specs from file."
+msgstr "nama MX salah"
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr ""
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr ""
+
+# OK
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "JANGAN muat file %s."
+
+# OK
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Sebutkan sebuah file hosts yang harus dibaca sebagai tambahan untuk %s."
+
+# OK
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr "Sebutkan antarmuka untuk mendengarkan."
+
+# OK
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Sebutkan antarmuka untuk TIDAK mendengarkan."
+
+# OK
+#: option.c:265
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Petakan kelas user DHCP ke setelan yang dipilih."
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+# OK
+#: option.c:269
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih."
+
+# OK
+#: option.c:270
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih."
+
+# OK
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr "JANGAN berjalan di background, jangan berjalan dalam modus debug."
+
+# OK
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr "Berpikir bahwa kita satu-satunya DHCP server dalam jaringan."
+
+# OK
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Sebutkan lokasi untuk menyimpan lease DHCP (default %s)."
+
+# OK
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr "Kembalikan rekord MX untuk host-host lokal."
+
+# OK
+#: option.c:275
+msgid "Specify an MX record."
+msgstr "Sebutkan sebuah rekord MX."
+
+# OK
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Sebutkan pilihan-pilihan BOOTP untuk DHCP server."
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "Jangan kumpulkan file %s, muat kembali saat SIGHUP."
+
+# OK
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr "JANGAN menyimpan hasil pencarian yang gagal."
+
+# OK
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr "Gunakan secara ketat namaserver yang disebutkan sesuai urutan di %s."
+
+# OK
+#: option.c:280
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP."
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+# OK
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Sebutkan port untuk mendengarkan permintaan DNS (default port 53)."
+
+# OK
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr "Ukuran maksimum paket UDP yang didukung untuk EDNS.0 (default %s)."
+
+# OK
+#: option.c:284
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "Permintaan log."
+
+# OK
+#: option.c:285
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Paksa port asal untuk permintaan ke atas."
+
+# OK
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr "JANGAN baca resolv.conf."
+
+# OK
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Sebutkan path ke resolv.conf (default %s)."
+
+# OK
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Sebutkan alamat-alamat server di atas, boleh dilengkapi dengan nama domain."
+
+# OK
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr "JANGAN pernah meneruskan permintaan ke domain yang disebutkan."
+
+# OK
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Sebutkan domain yang digunakan dalam lease DHCP."
+
+# OK
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr "Sebutkan tujuan default dalam rekord MX."
+
+# OK
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
+
+# OK
+#: option.c:293
+#, fuzzy
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
+
+# OK
+#: option.c:294
+#, fuzzy
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts."
+
+# OK
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Ubah ke user ini setelah mulai. (default %s)."
+
+# OK
+#: option.c:296
+#, fuzzy
+msgid "Map DHCP vendor class to tag."
+msgstr "Memetakan kelas vendor DHCP ke daftar pilihan."
+
+# OK
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr "Menampilkan versi dan informasi hak cipta dnsmasq."
+
+# OK
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Terjemahkan alamat-alamat IPv4 dari server-server di atas."
+
+# OK
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr "Sebutkan rekord SRV."
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+# OK
+#: option.c:301
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Sebutkan path file PID. (default %s)."
+
+# OK
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
+
+# OK
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr "Jawab permintaan DNS berdasarkan antarmuka dimana permintaan dikirimkan."
+
+# OK
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr "Sebutkan rekord TXT DNS."
+
+# OK
+#: option.c:305
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Sebutkan rekord TXT DNS."
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+# OK
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr "Hanya kaitkan ke antarmuka yang sedang digunakan saja."
+
+# OK
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Baca informasi statik host DHCP dari %s."
+
+# OK
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Mungkinkan antar muka DBus untuk menyetel server-server di atas, dsb."
+
+# OK
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "JANGAN menyediakan DHCP pada antarmuka ini, hanya menyediakan DNS."
+
+# OK
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Mungkinkan alokasi alamat dinamis untuk bootp."
+
+# OK
+#: option.c:312
+#, fuzzy
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Memetakan kelas vendor DHCP ke daftar pilihan."
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+# OK
+#: option.c:317
+#, fuzzy
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Ubah ke user ini setelah mulai. (default %s)."
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr ""
+
+# OK
+#: option.c:319
+#, fuzzy, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+# OK
+#: option.c:327
+#, fuzzy, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr ""
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr ""
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr ""
+
+# OK
+#: option.c:339
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Sebutkan rekord TXT DNS."
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr ""
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr ""
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+# OK
+#: option.c:345
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP."
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+# OK
+#: option.c:349
+#, fuzzy
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr "Terjemahkan alamat-alamat IPv4 dari server-server di atas."
+
+# OK
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Penggunaan: dnsmasq [pilihan]\n"
+"\n"
+
+# OK
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "Gunakan pilihan pendek saja pada perintah baris.\n"
+
+# OK
+#: option.c:642
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "Pilihan yang boleh adalah:\n"
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+# OK
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr "dhcp-option salah"
+
+# OK
+#: option.c:860
+#, fuzzy
+msgid "bad IP address"
+msgstr "membaca %s - %d alamat"
+
+# OK
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr "domain dalam dhcp-option salah"
+
+# OK
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr "dhcp-option terlalu panjang"
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr ""
+
+# OK
+#: option.c:1147 option.c:3030
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+# OK
+#: option.c:1178 tftp.c:460
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+# OK
+#: option.c:1265
+msgid "bad MX preference"
+msgstr "kesukaan MX salah"
+
+# OK
+#: option.c:1270
+msgid "bad MX name"
+msgstr "nama MX salah"
+
+# OK
+#: option.c:1284
+msgid "bad MX target"
+msgstr "target MX salah"
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+# OK
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr "port salah"
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr ""
+
+# OK
+#: option.c:1791
+#, fuzzy
+msgid "bad port range"
+msgstr "port salah"
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr ""
+
+# OK
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr "dhcp-range salah"
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr ""
+
+# OK
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr "jangkauan DHCP tidak konsisten"
+
+# OK
+#: option.c:2019 option.c:2045
+#, fuzzy
+msgid "bad hex constant"
+msgstr "dhcp-host salah"
+
+# OK
+#: option.c:2107
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "nama MX salah"
+
+# OK
+#: option.c:2188
+#, fuzzy
+msgid "bad tag-if"
+msgstr "target MX salah"
+
+# OK
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr "nomor port tidak benar"
+
+# OK
+#: option.c:2529
+#, fuzzy
+msgid "bad dhcp-proxy address"
+msgstr "membaca %s - %d alamat"
+
+# OK
+#: option.c:2569
+#, fuzzy
+msgid "invalid alias range"
+msgstr "weight tidak benar"
+
+# OK
+#: option.c:2582
+#, fuzzy
+msgid "bad interface name"
+msgstr "nama MX salah"
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr ""
+
+# OK
+#: option.c:2632
+#, fuzzy
+msgid "bad PTR record"
+msgstr "rekord SRV salah"
+
+# OK
+#: option.c:2663
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "rekord SRV salah"
+
+# OK
+#: option.c:2695
+msgid "bad TXT record"
+msgstr "rekord TXT salah"
+
+# OK
+#: option.c:2738
+msgid "bad SRV record"
+msgstr "rekord SRV salah"
+
+# OK
+#: option.c:2745
+msgid "bad SRV target"
+msgstr "target SRV salah"
+
+# OK
+#: option.c:2759
+msgid "invalid priority"
+msgstr "prioritas tidak benar"
+
+# OK
+#: option.c:2766
+msgid "invalid weight"
+msgstr "weight tidak benar"
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+# OK
+#: option.c:2849
+msgid "missing \""
+msgstr "kurang \""
+
+# OK
+#: option.c:2908
+msgid "bad option"
+msgstr "pilihan salah"
+
+# OK
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr "parameter berlebihan"
+
+# OK
+#: option.c:2912
+msgid "missing parameter"
+msgstr "parameter kurang"
+
+# OK
+#: option.c:2916
+msgid "error"
+msgstr "kesalahan"
+
+# OK
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s pada baris %d dari %%s"
+
+# OK
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+# OK
+#: option.c:3151 option.c:3187
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "membaca %s"
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+# OK
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr "Dnsmasq versi %s  %s\n"
+
+# OK
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Pilihan-pilihan saat kompilasi %s\n"
+"\n"
+
+# OK
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Perangkat lunak ini tersedia TANPA JAMINAN SEDIKITPUN.\n"
+
+# OK
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr "Dnsdmasq adalah perangkat lunak bebas, dan Anda dipersilahkan untuk membagikannya\n"
+
+# OK
+#: option.c:3273
+#, fuzzy, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr "dengan aturan GNU General Public License, versi 2.\n"
+
+#: option.c:3284
+msgid "try --help"
+msgstr ""
+
+#: option.c:3286
+msgid "try -w"
+msgstr ""
+
+# OK
+#: option.c:3289
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "pilihan baris perintah salah: %s."
+
+# OK
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "tidak bisa mendapatkan host-name: %s"
+
+# OK
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "hanya satu file resolv.conf yang diperbolehkan dalam modus no-poll."
+
+# OK
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "harus mempunyai tepat satu resolv.conf untuk mendapatkan nama domain."
+
+# OK
+#: option.c:3371 network.c:848 dhcp.c:814
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "gagal membaca %s: %s"
+
+# OK
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr "tidak ditemukan direktif search di %s"
+
+#: option.c:3409
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr ""
+
+# OK
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "nameserver %s menolak melakukan resolusi rekursif"
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr ""
+
+# OK
+#: network.c:171
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "antarmuka tidak dikenal %s"
+
+# OK
+#: network.c:380
+#, fuzzy, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr "gagal membuat socket: %s "
+
+#: network.c:746
+#, fuzzy, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "gagal mem-bind socket untuk mendengarkan %s: %s"
+
+# OK
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "mengabaikan nameserver %s - antarmuka lokal"
+
+# OK
+#: network.c:794
+#, fuzzy, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "mengabaikan nameserver %s - tak dapat membuat/mem-bind socket: %s"
+
+# OK
+#: network.c:811
+msgid "unqualified"
+msgstr "tidak memenuhi syarat"
+
+#: network.c:811
+msgid "names"
+msgstr ""
+
+#: network.c:813
+msgid "default"
+msgstr ""
+
+# OK
+#: network.c:815
+msgid "domain"
+msgstr "domain"
+
+# OK
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "menggunakan alamat lokal saja untuk %s %s"
+
+# OK
+#: network.c:820
+#, fuzzy, c-format
+msgid "using standard nameservers for %s %s"
+msgstr "menggunakan nameserver %s#%d untuk %s %s"
+
+# OK
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "menggunakan nameserver %s#%d untuk %s %s"
+
+# OK
+#: network.c:825
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "menggunakan nameserver %s#%d"
+
+# OK
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "menggunakan nameserver %s#%d"
+
+# OK
+#: dnsmasq.c:148
+#, fuzzy
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:158
+msgid "asychronous logging is not available under Android"
+msgstr ""
+
+# OK
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "gagal mendapatkan daftar antarmuka: %s"
+
+# OK
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr "antarmuka tidak dikenal %s"
+
+# OK
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr "tidak ada antarmuka dengan alamat %s"
+
+# OK
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr "DBus error: %s"
+
+# OK
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:455
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "dimulai, cache versi %s di disable"
+
+# OK
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "dimulai, versi %s ukuran cache %d"
+
+# OK
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "dimulai, cache versi %s di disable"
+
+# OK
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr "pilihan-pilihan saat kompilasi: %s"
+
+# OK
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr "dukungan DBus dimungkinkan: terkoneksi pada bus sistem"
+
+# OK
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr "dukungan DBus dimungkinkan: koneksi bus ditunda"
+
+# OK
+#: dnsmasq.c:474
+#, fuzzy, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "setelan opsi --bind-interfaces disebabkan keterbatasan OS"
+
+# OK
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "peringatan: antarmuka %s tidak ada"
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+# OK
+#: dnsmasq.c:491
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "menyetel server-server di atas dengan DBus"
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+# OK
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr "DHCP, lease static pada %.0s%s, waktu lease %s"
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, jangkaun IP %s -- %s, waktu lease %s"
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr ""
+
+# OK
+#: dnsmasq.c:526
+#, fuzzy
+msgid "enabled"
+msgstr "di disable"
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+# OK
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr "terhubung ke sistem DBus"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "gagal membaca %s: %s"
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:785
+#, fuzzy, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: dnsmasq.c:790
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: dnsmasq.c:793
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "gagal membaca %s: %s"
+
+# OK
+#: dnsmasq.c:796
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "tidak bisa membuka %s:%s"
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+# OK
+#: dnsmasq.c:859
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "gagal mengakses %s: %s"
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr "keluar karena menerima SIGTERM"
+
+# OK
+#: dnsmasq.c:931
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "gagal mengakses %s: %s"
+
+# OK
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr "membaca %s"
+
+# OK
+#: dnsmasq.c:972
+#, fuzzy, c-format
+msgid "no servers found in %s, will retry"
+msgstr "tidak ditemukan direktif search di %s"
+
+# OK
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr "tidak bisa membuat socket DHCP: %s"
+
+# OK
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr "gagal menyetel opsi pada socket DHCP: %s"
+
+# OK
+#: dhcp.c:65
+#, fuzzy, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr "gagal menyetel SO_REUSEADDR pada socket DHCP: %s"
+
+# OK
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr "gagal mem-bind socket server DHCP: %s"
+
+# OK
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "tidak dapat membuat socket ICMP raw: %s"
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+# OK
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr "jangkauan DHCP %s -- %s tidak konsisten dengan netmask %s"
+
+# OK
+#: dhcp.c:852
+#, fuzzy, c-format
+msgid "bad line at %s line %d"
+msgstr "kesalahan nama pada %s baris %d"
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+# OK
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "alamat IP kembar %s dalam direktif dhcp-config"
+
+# OK
+#: dhcp.c:981
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "alamat IP kembar %s dalam direktif dhcp-config"
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+# OK
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr "alamat IP kembar %s (%s) dalam direktif dhcp-config"
+
+# OK
+#: lease.c:67
+#, fuzzy, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "tidak dapat membuka atau membuat file lease: %s"
+
+# OK
+#: lease.c:93
+msgid "too many stored leases"
+msgstr "terlalu banyak lease yang disimpan"
+
+# OK
+#: lease.c:129
+#, fuzzy, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+# OK
+#: lease.c:235
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "gagal membaca %s: %s"
+
+# OK
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s"
+
+# OK
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr "dengan pemilih subnet"
+
+# OK
+#: rfc2131.c:316
+msgid "via"
+msgstr "lewat"
+
+# OK
+#: rfc2131.c:331
+#, fuzzy, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s"
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr ""
+
+# OK
+#: rfc2131.c:363
+msgid "disabled"
+msgstr "di disable"
+
+# OK
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr "diabaikan"
+
+# OK
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr "alamat telah digunakan"
+
+# OK
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr "tak ada alamat yang tersedia"
+
+# OK
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr "jaringan yang salah"
+
+# OK
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr "tak ada alamat yang disetel"
+
+# OK
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr "tak ada lease yang tersisa"
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+# OK
+#: rfc2131.c:700
+#, fuzzy, c-format
+msgid "%u vendor class: %s"
+msgstr "DBus error: %s"
+
+# OK
+#: rfc2131.c:702
+#, fuzzy, c-format
+msgid "%u user class: %s"
+msgstr "DBus error: %s"
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr ""
+
+# OK
+#: rfc2131.c:886
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "men-disable alamat statik DHCP %s"
+
+# OK
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr "lease tidak diketahui"
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr ""
+
+# OK
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr "alamat salah"
+
+# OK
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr "lease tak ditemukan"
+
+# OK
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr "alamat tak tersedia"
+
+# OK
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr "lease statik tak tersedia"
+
+# OK
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr "alamat telah dipesan"
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+# OK
+#: rfc2131.c:1732
+#, fuzzy, c-format
+msgid "%u server name: %s"
+msgstr "DBus error: %s"
+
+# OK
+#: rfc2131.c:1746
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "DBus error: %s"
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr ""
+
+#: rfc2131.c:1812
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+# OK
+#: rfc2131.c:2189
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "pilihan-pilihan saat kompilasi: %s"
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr ""
+
+# OK
+#: netlink.c:70
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "tidak bisa mem-bind netlink socket: %s"
+
+# OK
+#: netlink.c:288
+#, fuzzy, c-format
+msgid "netlink returns error: %s"
+msgstr "DBus error: %s"
+
+# OK
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr "mencoba menyetel sebuah alamat IPv6 server lewat DBus - tidak ada dukungan untuk IPv6"
+
+# OK
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr "menyetel server-server di atas dengan DBus"
+
+# OK
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr "tidak bisa mendaftar sebuah DBus message handler"
+
+# OK
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "tidak dapat membuat socket DHCP BPF: %s"
+
+# OK
+#: bpf.c:245
+#, fuzzy, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr "permintaan DHCP untuk tipe hardware yang tidak didukung (%d) diterima pada %s"
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+# OK
+#: tftp.c:406
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "lease tak ditemukan"
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr ""
+
+# OK
+#: tftp.c:554
+#, fuzzy, c-format
+msgid "failed sending %s to %s"
+msgstr "gagal membaca %s: %s"
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr ""
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+# OK
+#: log.c:462
+msgid "FAILED to start up"
+msgstr "GAGAL untuk memulai"
+
+# OK
+#~ msgid "TXT record string too long"
+#~ msgstr "string rekord TXT terlalu panjang"
+
+# OK
+#~ msgid "failed to set IPV6 options on listening socket: %s"
+#~ msgstr "gagal menyetel IPV6 pada socket: %s"
+
+#~ msgid "failed to bind listening socket for %s: %s"
+#~ msgstr "gagal mem-bind socket untuk mendengarkan %s: %s"
+
+# OK
+#~ msgid "failed to listen on socket: %s"
+#~ msgstr "gagal mendengarkan di socket: %s"
+
+# OK
+#, fuzzy
+#~ msgid "failed to create TFTP socket: %s"
+#~ msgstr "gagal membuat socket: %s "
+
+# OK
+#~ msgid "must set exactly one interface on broken systems without IP_RECVIF"
+#~ msgstr "harus menyetel satu antarmuka saja pada sistem yang tidak benar dengan IP_RECVIF"
+
+# OK
+#, fuzzy
+#~ msgid "failed to load %s: %s"
+#~ msgstr "gagal memuat %S: %s"
+
+# OK
+#~ msgid "bad name in %s"
+#~ msgstr "kesalahan nama di %s"
+
+# OK
+#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part"
+#~ msgstr "Mengabaikan lease DHCP untuk %s sebab terdapat bagian domain yang tidak sah"
+
+# OK
+#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"
+#~ msgstr "Integrasi dengan dhcpd ISC tidak tersedia: atur HAVE_ISC_READER dalam src/config.h"
+
+# OK
+#, fuzzy
+#~ msgid "illegal domain %s in dhcp-config directive."
+#~ msgstr "alamat IP kembar %s dalam direktif dhcp-config"
+
+# OK
+#~ msgid "running as root"
+#~ msgstr "berjalan menggunakan root"
+
+# OK
+#, fuzzy
+#~ msgid "read %s - %d hosts"
+#~ msgstr "membaca %s - %d alamat"
+
+# OK
+#~ msgid "domains"
+#~ msgstr "domain-domain"
+
+# OK
+#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part"
+#~ msgstr "Mengabaikan nama host DHCP %s sebab memiliki bagian domain yang tidak sah"
+
+# OK
+#~ msgid "Display this message."
+#~ msgstr "Menampilkan pesan ini."
+
+# OK
+#~ msgid "failed to read %s: %m"
+#~ msgstr "gagal membaca %s: %m"
+
+# OK
+#~ msgid "failed to read %s:%m"
+#~ msgstr "gagal membaca %s:%m"
+
+# OK
+#~ msgid "More than one vendor class matches, using %s"
+#~ msgstr "Lebih dari satu kelas vendor yang sesuai, menggunakan %s"
+
+# OK
+#~ msgid "forwarding table overflow: check for server loops."
+#~ msgstr "meneruskan tabel overflow: memeriksa apakah terjadi loop server."
+
+# OK
+#~ msgid "nested includes not allowed"
+#~ msgstr "includes bersarang tidak diijinkan"
+
+# OK
+#~ msgid "DHCP, %s will be written every %s"
+#~ msgstr "DHCP, %s akan ditulis setiap %s"
+
+# OK
+#~ msgid "cannot create DHCP packet socket: %s. Is CONFIG_PACKET enabled in your kernel?"
+#~ msgstr "tidak dapat membuat socket packet DHCP: %s. Apakah CONFIG_PACKET dimungkinkan pada kernel?"
diff --git a/po/it.po b/po/it.po
new file mode 100644 (file)
index 0000000..0b42ef1
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,1455 @@
+# Italian translations for dnsmasq package.
+# This file is put in the public domain.
+# Simon Kelley <simon@thekelleys.org.uk>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.32\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2006-05-22 11:09+0100\n"
+"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: cache.c:761
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr ""
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr ""
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr ""
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr ""
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr ""
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr ""
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr ""
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1040
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr ""
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:57
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr ""
+
+#: util.c:189
+msgid "failed to allocate memory"
+msgstr ""
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr ""
+
+#: util.c:237
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr ""
+
+#: util.c:245
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr ""
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr ""
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr ""
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr ""
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr ""
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr ""
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr ""
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr ""
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr ""
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr ""
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr ""
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr ""
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr ""
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr ""
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr ""
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr ""
+
+#: option.c:258
+msgid "Read DHCP host specs from file."
+msgstr ""
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr ""
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr ""
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr ""
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr ""
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr ""
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr ""
+
+#: option.c:265
+msgid "Map DHCP user class to tag."
+msgstr ""
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:269
+msgid "Don't do DHCP for hosts with tag set."
+msgstr ""
+
+#: option.c:270
+msgid "Force broadcast replies for hosts with tag set."
+msgstr ""
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr ""
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr ""
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr ""
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr ""
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr ""
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr ""
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr ""
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr ""
+
+#: option.c:280
+msgid "Specify options to be sent to DHCP clients."
+msgstr ""
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr ""
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr ""
+
+#: option.c:284
+msgid "Log DNS queries."
+msgstr ""
+
+#: option.c:285
+msgid "Force the originating port for upstream DNS queries."
+msgstr ""
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr ""
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr ""
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr ""
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr ""
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr ""
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr ""
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr ""
+
+#: option.c:293
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr ""
+
+#: option.c:294
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr ""
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr ""
+
+#: option.c:296
+msgid "Map DHCP vendor class to tag."
+msgstr ""
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr ""
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr ""
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr ""
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:301
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr ""
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr ""
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr ""
+
+#: option.c:305
+msgid "Specify PTR DNS record."
+msgstr ""
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr ""
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr ""
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr ""
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr ""
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr ""
+
+#: option.c:312
+msgid "Map MAC address (with wildcards) to option set."
+msgstr ""
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:317
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr ""
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:319
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr ""
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:327
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr ""
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr ""
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr ""
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:339
+msgid "Specify NAPTR DNS record."
+msgstr ""
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr ""
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr ""
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:345
+msgid "Prompt to send to PXE clients."
+msgstr ""
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+#: option.c:349
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr ""
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr ""
+
+#: option.c:642
+#, c-format
+msgid "Valid options are:\n"
+msgstr ""
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr ""
+
+#: option.c:860
+msgid "bad IP address"
+msgstr ""
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr ""
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr ""
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1147 option.c:3030
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr ""
+
+#: option.c:1178 tftp.c:460
+#, c-format
+msgid "cannot access %s: %s"
+msgstr ""
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr ""
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr ""
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr ""
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr ""
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1791
+msgid "bad port range"
+msgstr ""
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr ""
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr ""
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr ""
+
+#: option.c:2019 option.c:2045
+msgid "bad hex constant"
+msgstr ""
+
+#: option.c:2107
+msgid "bad DHCP host name"
+msgstr ""
+
+#: option.c:2188
+msgid "bad tag-if"
+msgstr ""
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr ""
+
+#: option.c:2529
+msgid "bad dhcp-proxy address"
+msgstr ""
+
+#: option.c:2569
+msgid "invalid alias range"
+msgstr ""
+
+#: option.c:2582
+msgid "bad interface name"
+msgstr ""
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2632
+msgid "bad PTR record"
+msgstr ""
+
+#: option.c:2663
+msgid "bad NAPTR record"
+msgstr ""
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr ""
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr ""
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr ""
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr ""
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr ""
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2849
+msgid "missing \""
+msgstr ""
+
+#: option.c:2908
+msgid "bad option"
+msgstr ""
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr ""
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr ""
+
+#: option.c:2916
+msgid "error"
+msgstr ""
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr ""
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: option.c:3151 option.c:3187
+#, c-format
+msgid "read %s"
+msgstr ""
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr ""
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr ""
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:3273
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:3284
+msgid "try --help"
+msgstr ""
+
+#: option.c:3286
+msgid "try -w"
+msgstr ""
+
+#: option.c:3289
+#, c-format
+msgid "bad command line options: %s"
+msgstr ""
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr ""
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr ""
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr ""
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, c-format
+msgid "failed to read %s: %s"
+msgstr ""
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr ""
+
+#: option.c:3409
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr ""
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr ""
+
+#: network.c:171
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr ""
+
+#: network.c:380
+#, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr ""
+
+#: network.c:746
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr ""
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr ""
+
+#: network.c:794
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr ""
+
+#: network.c:811
+msgid "unqualified"
+msgstr ""
+
+#: network.c:811
+msgid "names"
+msgstr ""
+
+#: network.c:813
+msgid "default"
+msgstr ""
+
+#: network.c:815
+msgid "domain"
+msgstr ""
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:820
+#, c-format
+msgid "using standard nameservers for %s %s"
+msgstr ""
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:825
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:148
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:158
+msgid "asychronous logging is not available under Android"
+msgstr ""
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr ""
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr ""
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr ""
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr ""
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:455
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr ""
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr ""
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr ""
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr ""
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr ""
+
+#: dnsmasq.c:474
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr ""
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr ""
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr ""
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:491
+msgid "warning: no upstream servers configured"
+msgstr ""
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:526
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr ""
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, c-format
+msgid "failed to create helper: %s"
+msgstr ""
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:785
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:790
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:793
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr ""
+
+#: dnsmasq.c:796
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:859
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr ""
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr ""
+
+#: dnsmasq.c:931
+#, c-format
+msgid "failed to access %s: %s"
+msgstr ""
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr ""
+
+#: dnsmasq.c:972
+#, c-format
+msgid "no servers found in %s, will retry"
+msgstr ""
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:65
+#, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr ""
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr ""
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr ""
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr ""
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr ""
+
+#: dhcp.c:981
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr ""
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr ""
+
+#: lease.c:67
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr ""
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:129
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr ""
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:235
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr ""
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:331
+#, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:700
+#, c-format
+msgid "%u vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:702
+#, c-format
+msgid "%u user class: %s"
+msgstr ""
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:886
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr ""
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1732
+#, c-format
+msgid "%u server name: %s"
+msgstr ""
+
+#: rfc2131.c:1746
+#, c-format
+msgid "%u next server: %s"
+msgstr ""
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr ""
+
+#: rfc2131.c:1812
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2189
+#, c-format
+msgid "%u requested options: %s"
+msgstr ""
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr ""
+
+#: netlink.c:70
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr ""
+
+#: netlink.c:288
+#, c-format
+msgid "netlink returns error: %s"
+msgstr ""
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr ""
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr ""
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr ""
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr ""
+
+#: bpf.c:245
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr ""
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:406
+#, c-format
+msgid "file %s not found"
+msgstr ""
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:554
+#, c-format
+msgid "failed sending %s to %s"
+msgstr ""
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr ""
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr ""
diff --git a/po/no.po b/po/no.po
new file mode 100644 (file)
index 0000000..78382cf
--- /dev/null
+++ b/po/no.po
@@ -0,0 +1,1571 @@
+# Norwegian translations for dnsmasq package.
+# This file is put in the public domain.
+# Simon Kelley <simon@thekelleys.org.uk>, 2006.
+#
+# Current translator: Jan Erik Askildt <jeaskildt@gmail.com>, 2006
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.25\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2006-01-11 17:39+0000\n"
+"Last-Translator: Jan Erik Askildt <jeaskildt@gmail.com>\n"
+"Language-Team: Norwegian <i18n-nb@lister.ping.uio.no>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: cache.c:761
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "feilet Ã¥ laste navn fra %s: %s"
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "dÃ¥rlig adresse ved %s linje %d"
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "dÃ¥rlig navn ved %s linje %d"
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "les %s - %d adresser"
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr "mellomlager tømt"
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr ""
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr "gir ikke navnet %s til DHCP leien for %s fordi navnet eksisterer i %s med adressen %s"
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1040
+#, fuzzy, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr "mellomlager størrelse %d, %d/%d mellomlager innsettinger re-bruker mellomlager plasser som ikke er utløpt"
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:57
+#, fuzzy, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "feilet Ã¥ lytte pÃ¥ socket: %s"
+
+#: util.c:189
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "feilet Ã¥ laste %d bytes"
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr "kunne ikke fÃ¥ minne"
+
+#: util.c:237
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: util.c:245
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "feilet Ã¥ laste %d bytes"
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr "uendelig"
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr "Spesifiser lokal(e) adresse(r) Ã¥ lytte pÃ¥."
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Returner ipaddr for alle verter i det spesifiserte domenet."
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Forfalsk revers oppslag for RFC1918 private adresse omrÃ¥der."
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Behandle ipaddr som NXDOMAIN (omgÃ¥r Verisign wildcard)."
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Spesifiser størrelsen pÃ¥ mellomlager plassene (standard er %s)."
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Spesifiser konfigurasjonsfil (standard er %s)."
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "IKKE legg (fork) som bakgrunnsprosess: kjør i debug modus."
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr "IKKE videresend oppslag som mangler domene del."
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Returner selv-pekende MX post for lokale verter."
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Utvid enkle navn i /etc/hosts med domene-suffiks."
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Ikke videresend falske/uekte DNS forespørsler fra Windows verter."
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Aktiver DHCP i det gitte omrÃ¥det med leie varighet"
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Skift til denne gruppen etter oppstart (standard er %s)."
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr "Sett adresse eller vertsnavn for en spesifikk maskin."
+
+#: option.c:258
+#, fuzzy
+msgid "Read DHCP host specs from file."
+msgstr "dÃ¥rlig MX navn"
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr ""
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr ""
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "IKKE last %s filen."
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Spesifiser en verts (hosts) fil som skal leses i tilleg til %s."
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr "Spesifiser nettverkskort det skal lyttes pÃ¥."
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Spesifiser nettverkskort det IKKE skal lyttes pÃ¥."
+
+#: option.c:265
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Map DHCP bruker klasse til opsjon sett."
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:269
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Ikke utfør DHCP for klienter i opsjon sett."
+
+#: option.c:270
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Ikke utfør DHCP for klienter i opsjon sett."
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr "IKKE last (fork) som bakgrunnsprosess, IKKE kjør i debug modus."
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr "Anta at vi er den eneste DHCP tjeneren pÃ¥ det lokale nettverket."
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Spesifiser hvor DHCP leiene skal lagres (standard er %s)."
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr "Returner MX records for lokale verter."
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr "Spesifiser en MX post."
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Spesifiser BOOTP opsjoner til DHCP tjener."
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "IKKE spør (poll) %s fil, les pÃ¥ nytt kun ved SIGHUP"
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr "IKKE mellomlagre søkeresultater som feiler."
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr "Bruk navnetjenere kun som bestemt i rekkefølgen gitt i %s."
+
+#: option.c:280
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene."
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Spesifiser lytteport for DNS oppslag (standard er 53)."
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr "Maksimal støttet UDP pakkestørrelse for EDNS.0 (standard er %s)."
+
+#: option.c:284
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "Logg oppslag."
+
+#: option.c:285
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Tving bruk av opprinnelig port for oppstrøms oppslag."
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr "IKKE les resolv.conf."
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Spesifiser stien til resolv.conf (standard er %s)."
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Spesifiser adressen(e) til oppstrøms tjenere med valgfrie domener."
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr "Aldri videresend oppslag til spesifiserte domener."
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Spesifiser domenet som skal tildeles i DHCP leien."
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr "Spesifiser default mÃ¥l i en MX post."
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
+
+#: option.c:293
+#, fuzzy
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
+
+#: option.c:294
+#, fuzzy
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts."
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Skift til denne bruker etter oppstart (standard er %s)."
+
+#: option.c:296
+#, fuzzy
+msgid "Map DHCP vendor class to tag."
+msgstr "Map DHCP produsent klasse til opsjon sett."
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr "Vis dnsmasq versjon og copyright informasjon."
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Oversett IPv4 adresser fra oppstrøms tjenere."
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr "Spesifiser en SRV post."
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:301
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Spesifiser stien til PID fil. (standard er %s)."
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr "Svar DNS oppslag basert pÃ¥ nettverkskortet oppslaget ble sendt til."
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr "Spesifiser TXT DNS post."
+
+#: option.c:305
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Spesifiser TXT DNS post."
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr "Bind kun til nettverkskort som er i bruk."
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Les DHCP statisk vert informasjon fra %s."
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Aktiver DBus interface for Ã¥ sette oppstrøms tjenere, osv."
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "Ikke lever DHCP pÃ¥ dette nettverkskortet, kun lever DNS."
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Aktiver dynamisk adresse allokering for bootp."
+
+#: option.c:312
+#, fuzzy
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Map DHCP produsent klasse til opsjon sett."
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:317
+#, fuzzy
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Skift til denne bruker etter oppstart (standard er %s)."
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:319
+#, fuzzy, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:327
+#, fuzzy, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr ""
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr ""
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:339
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Spesifiser TXT DNS post."
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr ""
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr ""
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:345
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene."
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+#: option.c:349
+#, fuzzy
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr "Oversett IPv4 adresser fra oppstrøms tjenere."
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Bruk: dnsmasq [opsjoner]\n"
+"\n"
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "Bruk korte opsjoner kun pÃ¥ kommandolinjen.\n"
+
+#: option.c:642
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "Gyldige opsjoner er :\n"
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr "dÃ¥rlig dhcp-opsjon"
+
+#: option.c:860
+#, fuzzy
+msgid "bad IP address"
+msgstr "les %s - %d adresser"
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr "dÃ¥rlig domene i dhcp-opsjon"
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr "dhcp-opsjon for lang"
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1147 option.c:3030
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: option.c:1178 tftp.c:460
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr "dÃ¥rlig MX preferanse"
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr "dÃ¥rlig MX navn"
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr "dÃ¥rlig MX mÃ¥l"
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr "dÃ¥rlig port"
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1791
+#, fuzzy
+msgid "bad port range"
+msgstr "dÃ¥rlig port"
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr "dÃ¥rlig dhcp-omrÃ¥de"
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr ""
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr "ikke konsistent DHCP omrÃ¥de"
+
+#: option.c:2019 option.c:2045
+#, fuzzy
+msgid "bad hex constant"
+msgstr "dÃ¥rlig dhcp-vert"
+
+#: option.c:2107
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "dÃ¥rlig MX navn"
+
+#: option.c:2188
+#, fuzzy
+msgid "bad tag-if"
+msgstr "dÃ¥rlig MX mÃ¥l"
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr "ugyldig portnummer"
+
+#: option.c:2529
+#, fuzzy
+msgid "bad dhcp-proxy address"
+msgstr "les %s - %d adresser"
+
+#: option.c:2569
+#, fuzzy
+msgid "invalid alias range"
+msgstr "ugyldig vekt"
+
+#: option.c:2582
+#, fuzzy
+msgid "bad interface name"
+msgstr "dÃ¥rlig MX navn"
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2632
+#, fuzzy
+msgid "bad PTR record"
+msgstr "dÃ¥rlig SRV post"
+
+#: option.c:2663
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "dÃ¥rlig SRV post"
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr "dÃ¥rlig TXT post"
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr "dÃ¥rlig SRV post"
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr "dÃ¥rlig SRV mÃ¥l"
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr "ugyldig prioritet"
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr "ugyldig vekt"
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2849
+msgid "missing \""
+msgstr "mangler \""
+
+#: option.c:2908
+msgid "bad option"
+msgstr "dÃ¥rlig opsjon"
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr "overflødig parameter"
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr "mangler parameter"
+
+#: option.c:2916
+msgid "error"
+msgstr "feil"
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s pÃ¥ linje %d av %%s"
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: option.c:3151 option.c:3187
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "leser %s"
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr "Dnsmasq versjon %s %s\n"
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Kompileringsopsjoner %s\n"
+"\n"
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Denne programvaren kommer med ABSOLUTT INGEN GARANTI.\n"
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr "DNsmasq er fri programvare, du er velkommen til Ã¥ redistribuere den\n"
+
+#: option.c:3273
+#, fuzzy, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr "under vilkÃ¥rene gitt i GNU General Public License, versjon 2.\n"
+
+#: option.c:3284
+msgid "try --help"
+msgstr ""
+
+#: option.c:3286
+msgid "try -w"
+msgstr ""
+
+#: option.c:3289
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "dÃ¥rlige kommandlinje opsjoner: %s."
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "klarer ikke Ã¥ fÃ¥ vertsnavn: %s"
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "kun en resolv.conf fil tillat i no-poll modus."
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "mÃ¥ ha nøyaktig en resolv.conf Ã¥ lese domene fra."
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "feilet Ã¥ lese %s: %s"
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr "intet søke direktiv funnet i %s"
+
+#: option.c:3409
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "navnetjener %s nektet Ã¥ gjøre et rekursivt oppslag"
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr ""
+
+#: network.c:171
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "ukjent tilknytning (interface) %s"
+
+#: network.c:380
+#, fuzzy, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr "feilet Ã¥ lage lytte socket: %s"
+
+#: network.c:746
+#, fuzzy, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "feilet Ã¥ binde lytte socket for %s: %s"
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorerer navnetjener %s - lokal tilknytning"
+
+#: network.c:794
+#, fuzzy, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "ignorerer navnetjener %s - kan ikke lage/dinde socket: %s"
+
+#: network.c:811
+msgid "unqualified"
+msgstr "ikke kvalifisert"
+
+#: network.c:811
+msgid "names"
+msgstr ""
+
+#: network.c:813
+msgid "default"
+msgstr ""
+
+#: network.c:815
+msgid "domain"
+msgstr "domene"
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "benytter lokale adresser kun for %s %s"
+
+#: network.c:820
+#, fuzzy, c-format
+msgid "using standard nameservers for %s %s"
+msgstr "benytter navnetjener %s#%d for %s %s"
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "benytter navnetjener %s#%d for %s %s"
+
+#: network.c:825
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "benytter navnetjener %s#%d"
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "benytter navnetjener %s#%d"
+
+#: dnsmasq.c:148
+#, fuzzy
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:158
+msgid "asychronous logging is not available under Android"
+msgstr ""
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "feilet Ã¥ finne liste av tilknytninger (interfaces): %s"
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr "ukjent tilknytning (interface) %s"
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr "ingen tilknytning (interface) med adresse %s"
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr "DBus feil: %s"
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:455
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "startet, versjon %s mellomlager deaktivert"
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "startet, versjon %s mellomlager størrelse %d"
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "startet, versjon %s mellomlager deaktivert"
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr "kompilerings opsjoner: %s"
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr "DBus støtte aktivert: koblet til system buss"
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr "DBus støtte aktivert: avventer buss tilkobling"
+
+#: dnsmasq.c:474
+#, fuzzy, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "feilet Ã¥ laste navn fra %s: %s"
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "setter --bind-interfaces opsjon pÃ¥ grunn av OS begrensninger"
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "advarsel: nettverkskort %s eksisterer ikke for tiden"
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:491
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "setter oppstrøms tjener fra DBus"
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr "DHCP, statisk leie kun pÃ¥ %.0s%s, leie tid %s"
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, IP omrÃ¥de %s -- %s, leie tid %s"
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:526
+#, fuzzy
+msgid "enabled"
+msgstr "deaktivert"
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr "tilkoblet til system DBus"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "feilet Ã¥ lese %s: %s"
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:785
+#, fuzzy, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "feilet Ã¥ laste navn fra %s: %s"
+
+#: dnsmasq.c:790
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "feilet Ã¥ laste navn fra %s: %s"
+
+#: dnsmasq.c:793
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "feilet Ã¥ lese %s: %s"
+
+#: dnsmasq.c:796
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "kan ikke Ã¥pne %s:%s"
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:859
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "feilet Ã¥ fÃ¥ tilgang til %s: %s"
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr "avslutter etter mottak av SIGTERM"
+
+#: dnsmasq.c:931
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "feilet Ã¥ fÃ¥ tilgang til %s: %s"
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr "leser %s"
+
+#: dnsmasq.c:972
+#, fuzzy, c-format
+msgid "no servers found in %s, will retry"
+msgstr "intet søke direktiv funnet i %s"
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr "kan ikke lage DHCP socket: %s"
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr "feilet Ã¥ sette opsjoner pÃ¥ DHCP socket: %s"
+
+#: dhcp.c:65
+#, fuzzy, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr "feilet Ã¥ sette SO_REUSEADDR pÃ¥ DHCP socket: %s"
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr "feilet Ã¥ binde DHCP tjener socket: %s"
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "kan ikke lage ICMP raw socket: %s"
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr "DHCP omrÃ¥de %s -- %s er ikke konsistent med nettmaske %s"
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "dÃ¥rlig linje ved %s linje %d"
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "dubliserte IP adresser i %s dhcp-config direktiv."
+
+#: dhcp.c:981
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "dubliserte IP adresser i %s dhcp-config direktiv."
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr "dubliserte IP adresser i %s (%s) i dhcp-config direktiv"
+
+#: lease.c:67
+#, fuzzy, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "kan ikke Ã¥pne eller lage leie fil: %s"
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr "for mange lagrede leier"
+
+#: lease.c:129
+#, fuzzy, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:235
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "feilet Ã¥ lese %s: %s"
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr "ingen adresse omrÃ¥de tilgjengelig for DHCP krav %s %s"
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr "med subnet velger"
+
+#: rfc2131.c:316
+msgid "via"
+msgstr "via"
+
+#: rfc2131.c:331
+#, fuzzy, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr "ingen adresse omrÃ¥de tilgjengelig for DHCP krav %s %s"
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr "deaktivert"
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr "oversett"
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr "adresse i bruk"
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr "ingen adresse tilgjengelig"
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr "galt nettverk"
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr "ingen adresse konfigurert"
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr "ingen leier igjen"
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:700
+#, fuzzy, c-format
+msgid "%u vendor class: %s"
+msgstr "DBus feil: %s"
+
+#: rfc2131.c:702
+#, fuzzy, c-format
+msgid "%u user class: %s"
+msgstr "DBus feil: %s"
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:886
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "deaktiverer DHCP statisk adresse %s"
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr "ukjent leie"
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr "gal adresse"
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr "leie ikke funnet"
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr "adresse ikke tilgjengelig"
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr "statisk leie tilgjengelig"
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr "adresse reservert"
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1732
+#, fuzzy, c-format
+msgid "%u server name: %s"
+msgstr "DBus feil: %s"
+
+#: rfc2131.c:1746
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "DBus feil: %s"
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr ""
+
+#: rfc2131.c:1812
+#, fuzzy, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr "kan ikke sende DHCP opsjon %d: ikke mer plass i pakken"
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2189
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "kompilerings opsjoner: %s"
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr ""
+
+#: netlink.c:70
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "kan ikke binde netlink socket: %s"
+
+#: netlink.c:288
+#, fuzzy, c-format
+msgid "netlink returns error: %s"
+msgstr "DBus feil: %s"
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr "forsøk pÃ¥ Ã¥ sette en IPv6 tjener adresse via DBus - ingen IPv6 støtte"
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr "setter oppstrøms tjener fra DBus"
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr "kunne ikke registrere en DBus meldingshÃ¥ndterer"
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "kan ikke lage DHCP BPF socket: %s"
+
+#: bpf.c:245
+#, fuzzy, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr "DHCP krav for ikke støttet maskinvare type (%d) mottatt pÃ¥ %s"
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:406
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "leie ikke funnet"
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:554
+#, fuzzy, c-format
+msgid "failed sending %s to %s"
+msgstr "feilet Ã¥ lese %s: %s"
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr ""
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr "FEILET Ã¥ starte opp"
+
+#~ msgid "TXT record string too long"
+#~ msgstr "TXT post streng for lang"
+
+#~ msgid "failed to set IPV6 options on listening socket: %s"
+#~ msgstr "feilet Ã¥ sette IPv6 opsjoner pÃ¥ lytte socket: %s"
+
+#~ msgid "failed to bind listening socket for %s: %s"
+#~ msgstr "feilet Ã¥ binde lytte socket for %s: %s"
+
+#~ msgid "failed to listen on socket: %s"
+#~ msgstr "feilet Ã¥ lytte pÃ¥ socket: %s"
+
+#, fuzzy
+#~ msgid "failed to create TFTP socket: %s"
+#~ msgstr "feilet Ã¥ lage lytte socket: %s"
+
+#~ msgid "must set exactly one interface on broken systems without IP_RECVIF"
+#~ msgstr "mÃ¥ sette nøyaktig et interface pÃ¥ Ã¸delagte systemer uten IP_RECVIF"
+
+#, fuzzy
+#~ msgid "failed to load %s: %s"
+#~ msgstr "feilet Ã¥ laste %s: %s"
+
+#~ msgid "bad name in %s"
+#~ msgstr "dÃ¥rlig navn i %s"
+
+#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part"
+#~ msgstr "Ignorerer DHCP leie for %s siden den har en ulovlig domene del"
+
+#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"
+#~ msgstr "ISC dhcpf integrasjon ikke tilgjengelig: sett HAVE_ISC_READER i src/config.h"
+
+#, fuzzy
+#~ msgid "illegal domain %s in dhcp-config directive."
+#~ msgstr "dubliserte IP adresser i %s dhcp-config direktiv."
+
+#~ msgid "running as root"
+#~ msgstr "kjører som rot (root)"
+
+#, fuzzy
+#~ msgid "read %s - %d hosts"
+#~ msgstr "les %s - %d adresser"
+
+#~ msgid "domains"
+#~ msgstr "domener"
+
+#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part"
+#~ msgstr "Ignorerer DHCP verts navn %s pÃ¥ grunn av ulovlig domene del"
+
+#~ msgid "Display this message."
+#~ msgstr "Vis denne meldingen."
+
+#~ msgid "failed to read %s: %m"
+#~ msgstr "feilet Ã¥ lese %s: %m"
+
+#~ msgid "failed to read %s:%m"
+#~ msgstr "feilet Ã¥ lese %s:%m"
+
+#, fuzzy
+#~ msgid "cannot send encapsulated option %d: no space left in wrapper"
+#~ msgstr "kan ikke sende DHCP opsjon %d: ikke mer plass i pakken"
+
+#~ msgid "More than one vendor class matches, using %s"
+#~ msgstr "Mer enn en produsent klasse som passer, bruker %s"
+
+#~ msgid "forwarding table overflow: check for server loops."
+#~ msgstr "fremsendelse (forwarding) tabell overflyt: sjekk etter tjener løkker."
+
+#~ msgid "nested includes not allowed"
+#~ msgstr "nøstede inkluderinger er ikke tillatt"
+
+#~ msgid "DHCP, %s will be written every %s"
+#~ msgstr "DHCP, %s vil bli skrevet hver %s"
+
+#~ msgid "cannot create DHCP packet socket: %s. Is CONFIG_PACKET enabled in your kernel?"
+#~ msgstr "kan ikke lage DHCP pakke socket: %s. Er CONFIG_PACKET aktivert i din kjerne?"
+
+#~ msgid "Cannot use RTnetlink socket, falling back to ioctl API"
+#~ msgstr "Kan ikke benytte RTnetlink socket, faller tilbake til ioctl API"
diff --git a/po/pl.po b/po/pl.po
new file mode 100644 (file)
index 0000000..945df01
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,1490 @@
+# translation of pl.po to polski
+# Polish translations for dnsmasq package.
+# This file is put in the public domain.
+#
+# Tomasz Sochañski <nerdhero@gmail.com>, 2005.
+# Jan Psota <jasiu@belsznica.pl>, 2008, 2009, 2010.
+# Jan Psota <jasiupsota@gmail.com>, 2010, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: pl\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-10 20:57+0100\n"
+"PO-Revision-Date: 2011-01-16 23:56+0100\n"
+"Last-Translator: Jan Psota <jasiupsota@gmail.com>\n"
+"Language-Team: Polish <>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Lokalize 1.1\n"
+"X-Language: pl_PL\n"
+
+#: cache.c:761
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr "nie potrafiê wczytaæ nazw z %s: %s"
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "b³êdny adres w pliku %s, w linii %d"
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "b³êdna nazwa w pliku %s, w linii %d"
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "wczyta³em %s - %d adresów"
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr "wyczyszczono pamiêæ podrêczn±"
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr "%s to nazwa CNAME, nie przypisujê jej dzier¿awie DHCP %s"
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr "nazwa %s nie zosta³a nadana dzier¿awie DHCP %s,poniewa¿ nazwa istnieje w %s i ma ju¿ adres %s"
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr "czas %lu"
+
+#: cache.c:1040
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr "wielko¶æ pamiêci podrêcznej: %d; %d z %d miejsc aktualnych wpisów u¿yto ponownie."
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr "%u zapytañ przes³anych dalej, %u odpowiedzi udzielonych samodzielnie"
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr "serwer %s#%d: %u zapytañ wys³anych, %u ponowionych lub nieudanych"
+
+#: util.c:57
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "brak mo¿liwo¶ci u¿ycia generatora liczb losowych: %s"
+
+#: util.c:189
+msgid "failed to allocate memory"
+msgstr "nie uda³o siê przydzieliæ pamiêci"
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr "nie mo¿na dostaæ pamiêci"
+
+#: util.c:237
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr "b³±d podczas próby utworzenia potoku: %s"
+
+#: util.c:245
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr "niemo¿liwo¶æ przydzielenia %d bajtów pamiêci"
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr "nieskoñczona"
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr "Wskazanie adresów, na których nale¿y nas³uchiwaæ."
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Zwracanie adresu IP dla wszystkich hostów we wskazanych domenach."
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Wy³±czenie przekazywania zapytañ odwrotnych dla prywatnych zakresów IP."
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Traktowanie adresu IP jako NXDOMAIN (uniewa¿nia ,,Verisign wildcard'')."
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Wskazanie wielko¶ci pamiêci podrêcznej (domy¶lnie: %s miejsc)."
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Wskazanie pliku konfiguracyjnego (domy¶lnie: %s)."
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "NIE twórz procesu potomnego w tle: dzia³anie w trybie debugowania."
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr "Wy³±czenie przekazywania zapytañ bez podanej czê¶ci domenowej."
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Zwracanie samowskazuj±cego rekordu MX dla lokalnych hostów."
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Rozwijanie prostych nazw z /etc/hosts przyrostkiem domenowym."
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Wy³±czenie przekazywania pozornych zapytañ DNS z komputerów dzia³aj±cych pod Windows."
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "W³±czenie serwera DHCP dla wskazanego zakresu adresów."
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Po uruchomieniu zmiana grupy procesu na podan± (domy¶lnie: %s)."
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr "Ustawienie adresu lub nazwy dla wskazanego komputera."
+
+#: option.c:258
+msgid "Read DHCP host specs from file."
+msgstr "Wskazanie pliku z warto¶ciami 'dhcp-host='."
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr "Wskazanie pliku z warto¶ciami 'dhcp-option='."
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr "Warunkowe ustawianie znaczników."
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "NIE wczytywanie pliku %s."
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Wskazanie dodatkowego pliku 'hosts' oprócz %s."
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr "Interfejsy, na których nas³uchiwaæ."
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Interfejsy, na których NIE nas³uchiwaæ."
+
+#: option.c:265
+msgid "Map DHCP user class to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od klasy u¿ytkownika DHCP."
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru obwodu (w rozumieniu RFC3046)."
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru agenta (w rozumieniu RFC3046)."
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru subskrybenta (w rozumieniu RFC3993)."
+
+#: option.c:269
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Wy³±czenie DHCP dla hostów z okre¶lonym znacznikiem."
+
+#: option.c:270
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Wymuszenie odpowiedzi w trybie rozg³oszeniowym dla hostów z okre¶lonym znacznikiem."
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr "NIE twórz procesu potomnego w tle i NIE w³±czaj trybu debugowania."
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr "Zak³adanie, Â¿e jeste¶my jedynym serwerem DHCP w sieci lokalnej."
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "¦cie¿ka przechowywania pliku dzier¿aw DHCP (domy¶lnie: %s)."
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr "W³±czenie zwracania rekordu MX dla hostów lokalnych."
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr "Specyfikacja rekordu MX."
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Okre¶lenie opcji BOOTP serwera DHCP."
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "Wy³±czenie obserwowania pliku %s; ponowne odczytywanie tylko po odebraniu sygna³u SIGHUP."
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr "Wy³±czenie przechowywania w pamiêci podrêcznej wyników nieudanych wyszukiwañ."
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr "Odpytywanie serwerów nazw w kolejno¶ci ich wyst±pienia w %s."
+
+#: option.c:280
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Specyfikacja opcji wysy³anej do klientów DHCP."
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr "Opcja DHCP wysy³ana nawet je¿eli klient o ni± nie prosi."
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Wskazanie portu do nas³uchiwania zapytañ DNS (domy¶lnie: 53)."
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr "Maksymalna obs³ugiwana wielko¶æ pakietu EDNS.0 (domy¶lnie: %s)."
+
+#: option.c:284
+msgid "Log DNS queries."
+msgstr "W³±czenie spisywania zapytañ DNS do logu."
+
+#: option.c:285
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Wymuszenie u¿ycia wskazanego portu UDP do odpytywania nadrzêdnych serwerów DNS i odbierania od nich odpowiedzi."
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr "Wy³±czenie czytania pliku resolv.conf."
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Wskazanie po³o¿enia pliku resolv.conf (domy¶lnie: %s)."
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Wskazywanie adresów serwerów nazw, opcjonalnie z przypisaniem do domeny."
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr "Wy³±czenie przekazywania zapytañ do wskazanych domen."
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Wskazanie domeny dla serwera DHCP."
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr "Okre¶lenie domy¶lnego celu w rekordzie MX."
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr "Okre¶lenie (w sekundach) czasu wa¿no¶ci odpowiedzi udzielonych na podstawie /etc/hosts (domy¶lnie 0)."
+
+#: option.c:293
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Okre¶lenie (w sekundach) czasu wa¿no¶ci negatywnych odpowiedzi."
+
+#: option.c:294
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr "Ograniczenie maksymalnego czasu wa¿no¶ci odpowiedzi (TTL) podawanego klientom [w sekundach]."
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Zmiana u¿ytkownika procesu na wskazanego (po uruchomieniu, domy¶lnie: %s)."
+
+#: option.c:296
+msgid "Map DHCP vendor class to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od typu klienta DHCP."
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr "Wydrukowanie informacji o programie i ochronie praw autorskich."
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "T³umaczenie adresów IPv4 z serwerów nadrzêdnych."
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr "Okre¶lenie rekordu SRV."
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr "Wy¶wietla ten komunikat. U¿yj '--help dhcp' chc±c przejrzeæ listê opcji DHCP (dhcp-option=xxx,...)."
+
+#: option.c:301
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Okre¶lenie Â¶cie¿ki do pliku PID (domy¶lnie: %s)."
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Maksymalna liczba dzier¿aw DHCP (domy¶lnie: %s)."
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr "Uzale¿nienie odpowiedzi DNS od interfejsu, na którym odebrano zapytanie (wygodne dla serwerów kilku podsieci z ró¿nymi adresami w /etc/hosts)."
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr "Specyfikacja rekordu DNS TXT."
+
+#: option.c:305
+msgid "Specify PTR DNS record."
+msgstr "Specyfikacja rekordu DNS PTR."
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr "Zwraca nazwê domenow± powi±zan± z adresem interfejsu sieciowego."
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr "Nas³uchiwanie tylko na wykorzystywanych interfejsach (umo¿liwia uruchomienie osobnych serwerów dla ró¿nych kart)."
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Wczytanie przyporz±dkowañ adresów z %s."
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "W³±czenie u¿ywania interfejsu DBus do informowania o zmianach konfiguracji."
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "Uruchomienie na wskazanym interfejsie tylko DNS-a, bez us³ug DHCP i TFTP."
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr "W³±czenie dynamicznego przydzielania adresów dla klientów BOOTP."
+
+#: option.c:312
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od adresu MAC (mo¿na u¿ywaæ uogólnieñ: *)."
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr "Traktowanie Â¿Â±dañ DHCP odebranych na interfejsach alias, ..., jako odebranych na iface."
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr "Pominiêcie sprawdzania za pomoc± ICMP niezajêto¶ci adresu przed jego wydzier¿awieniem."
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr "Wskazanie skryptu uruchamianego w przypadku wydzier¿awienia adresu lub wyga¶niêcia dzier¿awy."
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr "Wczytanie wszystkich plików ze wskazanego katalogu jako konfiguracyjnych."
+
+#: option.c:317
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Wskazanie kana³u syslog-a do którego maj± trafiaæ komunikaty (domy¶lnie: DAEMON)"
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr "Nieu¿ywanie bazy dzier¿aw."
+
+#: option.c:319
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Maksymalna liczba jednocze¶nie obs³ugiwanych zapytañ DNS (domy¶lnie: %s)"
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr "Czyszczenie pamiêci podrêcznej serwera nazw w przypadku ponownego odczytu %s."
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr "Nie zwracanie uwagi na nazwê podawan± przez klienta w przypadku dopasowania wszystkich wymienionych znaczników."
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr "Wy³±czenie oszczêdzania miejsca w pakiecie DHCP przez przesuwanie pól servername i filename do opcji DHCP. Wymusza prostszy tryb budowy pakietu rozwi±zuj±c problemy z nieprzystosowanymi klientami DHCP."
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr "W³±czenie wbudowanego serwera TFTP (tylko do wysy³ania)."
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr "Ograniczenie dzia³ania serwera TFTP do wskazanego katalogu i podkatalogów. Nazwy z .. s± odrzucane, / odnosi siê do wskazanego katalogu."
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr "Doklejanie adresu IP klienta do g³ównego katalogu TFTP. Je¿eli wynikowy katalog nie istnieje, nadal wykorzystuje siê tftp-root."
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr "Ograniczenie dostêpu do plików przez TFTP do tych, których w³a¶cicielem jest u¿ytkownik uruchamiaj±cy dnsmasq-a."
+
+#: option.c:327
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Maksymalna liczba jednocze¶nie obs³ugiwanych po³±czeñ TFTP (domy¶lnie %s)."
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr "Wy³±czenie mo¿liwo¶ci negocjowania wielko¶ci bloku dla przesy³ów przez TFTP."
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr "Wskazanie zakresu portów do u¿ytku TFTP."
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr "W³±czenie spisywania w logu operacji DHCP."
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr "W³±czenie asynchronicznego zapisywania do logu z ewentualnym wskazaniem d³ugo¶ci kolejki."
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr "Odfiltrowywanie adresów wskazuj±cych na komputery w sieciach wewnêtrznych spo¶ród odpowiedzi od zewnêtrznych serwerów DNS."
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr "Zezwolenie na przekazywanie odpowiedzi w klasie 127.0.0.0/8. Dla serwerów RBL."
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr "Dezaktywacja zabezpieczenia przed atakami DNS-rebind dla wskazanych domen."
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr "Jednoczesne odpytywanie wszystkich serwerów nadrzêdnych; klientowi przekazywana jest pierwsza odpowied¼."
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr "Ustawienie znacznika je¿eli w Â¿Â±daniu DHCP pojawi siê wskazana opcja, ewentualnie o konkretnej warto¶ci."
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr "U¿ycie alternatywnych portów dla us³ugi DHCP."
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr "Uruchamianie skryptu dhcp-script jako wskazany u¿ytkownik."
+
+#: option.c:339
+msgid "Specify NAPTR DNS record."
+msgstr "Specyfikacja rekordu DNS NAPTR."
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr "Ustawienie dolnej granicy numerów portów do przesy³ania zapytañ DNS."
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr "Przechowywanie w serwerze DNS dnsmasq-a tylko w pe³ni kwalifikowanych nazw zg³aszanych przez klientów DHCP."
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr "Generowanie nazw na podstawie MAC-adresów dla klientów bez nazwy."
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr "Traktowanie wskazanych serwerów po¶rednicz±cych DHCP jako dzia³aj±cych w trybie \"pe³nomocnika\" (full-proxy)."
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr "Wskazanie synonimu nazwy komputera lokalnego - znanego z /etc/hosts albo z DHCP."
+
+#: option.c:345
+msgid "Prompt to send to PXE clients."
+msgstr "Zg³oszenie wysy³ane klientom PXE."
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr "Sk³adnik menu PXE (--> man)."
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr "Sprawdzenie sk³adni."
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr "Za³±czanie MAC-adresu komputera pytaj±cego w przekazywanych dalej zapytaniach DNS."
+
+#: option.c:349
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr "Przekazywanie wyników weryfikacji DNSSEC z serwerów nadrzêdnych."
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"U¿ycie: dnsmasq [opcje]\n"
+"\n"
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "W tym systemie w linii poleceñ mo¿na u¿ywaæ wy³±cznie jednoliterowych opcji.\n"
+
+#: option.c:642
+#, c-format
+msgid "Valid options are:\n"
+msgstr "Dostêpne opcje:\n"
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr "Znane opcje DHCP:\n"
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr "b³±d w dhcp-option"
+
+#: option.c:860
+msgid "bad IP address"
+msgstr "z³y adres IP"
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr "nieprawid³owa nazwa domeny w dhcp-option"
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr "zbyt d³uga dhcp-option (>255 znaków)"
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr "niedopuszczalne dhcp-match"
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr "wielokrotne u¿ycie opcji niedozwolone (pojawi³a siê wcze¶niej w linii poleceñ)"
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr "wielokrotne u¿ycie opcji niedozwolone (pojawi³a siê wsze¶niej w pliku konfiguracyjnym)"
+
+#: option.c:1147 option.c:3030
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr "brak dostêpu do katalogu %s: %s"
+
+#: option.c:1178 tftp.c:460
+#, c-format
+msgid "cannot access %s: %s"
+msgstr "brak dostêpu do %s: %s"
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr "nieprawid³owa warto¶æ preferencji MX"
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr "nieprawid³owa nazwa MX"
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr "nieprawid³owa warto¶æ celu MX"
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr "w uClinuksie nie ma mo¿liwo¶ci uruchamiania skryptów"
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr "¿eby mieæ mo¿liwo¶æ u¿ywania skryptów wywo³ywanych przy zmianie dzier¿awy, przekompiluj dnsmasq-a z w³±czon± flag± HAVE_SCRIPT"
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr "nieprawid³owy numer portu"
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr "nie ma mo¿liwo¶ci dowi±zywania do interfejsu"
+
+#: option.c:1791
+msgid "bad port range"
+msgstr "nieprawid³owy zakres numerów portów"
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr "nieprawid³owa nazwa urz±dzenia w bridge-interface"
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr "nieprawid³owy zakres dhcp-range"
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr "mo¿na wskazaæ tylko jeden znacznik sieci"
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr "niespójny zakres adresów DHCP"
+
+#: option.c:2019 option.c:2045
+msgid "bad hex constant"
+msgstr "zapis niezgodny z formatem szesnastkowym"
+
+#: option.c:2107
+msgid "bad DHCP host name"
+msgstr "niedopuszczalna nazwa komputera w dhcp-host"
+
+#: option.c:2188
+msgid "bad tag-if"
+msgstr "nieprawid³owa sk³adnia 'tag-if'"
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr "nieprawid³owy numer portu"
+
+#: option.c:2529
+msgid "bad dhcp-proxy address"
+msgstr "z³y adres dhcp-proxy"
+
+#: option.c:2569
+msgid "invalid alias range"
+msgstr "nieprawid³owy zakres adresów w --alias"
+
+#: option.c:2582
+msgid "bad interface name"
+msgstr "nieprawid³owa nazwa interfejsu"
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr "z³a CNAME"
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr "powtórzona CNAME"
+
+#: option.c:2632
+msgid "bad PTR record"
+msgstr "nieprawid³owy zapis rekordu PTR"
+
+#: option.c:2663
+msgid "bad NAPTR record"
+msgstr "nieprawid³owy zapis rekordu NAPTR"
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr "nieprawid³owy zapis rekordu TXT"
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr "nieprawid³owy zapis rekordu SRV"
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr "nieprawid³owa warto¶æ celu SRV"
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr "nieprawid³owy priorytet"
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr "nieprawid³owa waga"
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr "nieobs³ugiwana opcja (sprawd¼, czy obs³uga DHCP/TFTP/DBus zosta³a wkompilowana)"
+
+#: option.c:2849
+msgid "missing \""
+msgstr "brakuje \""
+
+#: option.c:2908
+msgid "bad option"
+msgstr "nieprawid³owa opcja"
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr "nadwy¿kowy parametr"
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr "brak parametru"
+
+#: option.c:2916
+msgid "error"
+msgstr "b³±d"
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s w linii %d pliku %%s"
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "b³±d odczytu z pliku %s: %s"
+
+#: option.c:3151 option.c:3187
+#, c-format
+msgid "read %s"
+msgstr "przeczyta³em %s"
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr "jakie¶ Â¶mieci w linii poleceñ"
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr "Dnsmasq, wersja %s  %s\n"
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Wkompilowane opcje %s\n"
+"\n"
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Autor nie daje Â¯ADNYCH GWARANCJI egzekwowalnych prawnie.\n"
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr "Dnsmasq jest wolnym oprogramowaniem, mo¿esz go rozprowadzaæ\n"
+
+#: option.c:3273
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr "na warunkach okre¶lonych w GNU General Public Licence, w wersji 2 lub 3.\n"
+
+#: option.c:3284
+msgid "try --help"
+msgstr "spróbuj: --help"
+
+#: option.c:3286
+msgid "try -w"
+msgstr "spróbuj: -w"
+
+#: option.c:3289
+#, c-format
+msgid "bad command line options: %s"
+msgstr "nieprawid³owa opcja w linii poleceñ %s"
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "nie mo¿na pobraæ nazwy hosta: %s"
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "w trybie no-poll mo¿na wskazaæ najwy¿ej jeden plik resolv.conf."
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "musisz mieæ dok³adnie jeden plik resolv.conf do odczytu domen."
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, c-format
+msgid "failed to read %s: %s"
+msgstr "nie uda³o siê odczytaæ %s: %s"
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr "brak wytycznych wyszukiwania w %s"
+
+#: option.c:3409
+#, fuzzy
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr "w przypadku u¿ywania --dhcp-fqdn trzeba wskazaæ domy¶ln± domenê"
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr "sk³adnia sprawdzona, jest prawid³owa"
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "serwer nazw %s odmawia wykonania zapytania rekurencyjnego"
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr "prawdopodobnie wykryto atak DNS-rebind: %s"
+
+#: network.c:171
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "nieznany interfejs %s w bridge-u"
+
+#: network.c:380
+#, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr "nie uda³o siê otworzyæ gniazda %s: %s"
+
+#: network.c:746
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "b³±d przy przyznawaniu nazwy gniazdu serwera %s: %s"
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorowanie serwera nazw %s - interfejs lokalny"
+
+#: network.c:794
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "ignorowanie serwera nazw %s - nie mo¿na utworzyæ/dowi±zaæ gniazda: %s"
+
+#: network.c:811
+msgid "unqualified"
+msgstr "niekwalifikowane(-a)"
+
+#: network.c:811
+msgid "names"
+msgstr "nazwy"
+
+#: network.c:813
+msgid "default"
+msgstr "domy¶lne"
+
+#: network.c:815
+msgid "domain"
+msgstr "domeny"
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "u¿ywam adresów lokalnych tylko dla %s %s"
+
+#: network.c:820
+#, c-format
+msgid "using standard nameservers for %s %s"
+msgstr "u¿ywam standardowych serwerów nazw dla %s %s"
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "u¿ywam serwera nazw %s#%d dla %s %s"
+
+#: network.c:825
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "u¿ywam serwera nazw %s#%d (przez %s)"
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "u¿ywam serwera nazw %s#%d"
+
+#: dnsmasq.c:148
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr "Serwer TFTP nie zosta³ wkompilowany -- ustaw HAVE_TFTP w src/config.h"
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr "zapis do logów w trybie asynchronicznym nie jest dostêpny w Solarisie"
+
+#: dnsmasq.c:158
+#, fuzzy
+msgid "asychronous logging is not available under Android"
+msgstr "zapis do logów w trybie asynchronicznym nie jest dostêpny w Solarisie"
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "b³±d podczas tworzenia listy interfejsów sieciowych: %s"
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr "nieznany interfejs %s"
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr "brak interfejsu z adresem %s"
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr "b³±d DBus: %s"
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "Obs³uga DBus nie zosta³a wkompilowana -- ustaw HAVE_DBUS w src/config.h"
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr "nieznany u¿ytkownik lub grupa: %s"
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr "nie potrafiê wej¶æ do g³ównego katalogu: %s"
+
+#: dnsmasq.c:455
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr "uruchomiony, wersja %s, DNS wy³±czony"
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "uruchomiony, wersja %s, %d miejsc w pamiêci podrêcznej"
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "uruchomiony, wersja %s, pamiêæ podrêczna wy³±czona"
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr "opcje kompilacji: %s"
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr "obs³uga DBus w³±czona, pod³±czono do serwera DBus"
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr "obs³uga DBus w³±czona, trwa pod³±czanie do serwera DBus"
+
+#: dnsmasq.c:474
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "UWAGA! Nie uda³o siê zmieniæ u¿ytkownika pliku %s: %s"
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "ustawiam --bind-interfaces z powodu ograniczeñ systemu operacyjnego"
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "uwaga: interfejs %s nie jest w³±czony"
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr "uwaga: ignorujê opcjê resolv-file, poniewa¿ wybrano tryb no-resolv"
+
+#: dnsmasq.c:491
+msgid "warning: no upstream servers configured"
+msgstr "uwaga: nie wskazano nadrzêdnych serwerów DNS"
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr "w³±czono asynchroniczny tryb zapisu do logów z kolejk± na %d komunikatów"
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr "DHCP: tylko statyczne dzier¿awy na %.0s%s, czas dzier¿awy %s"
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr "DHCP: po¶rednik na podsieci %.0s%s%.0s"
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP: zakres IP %s -- %s, czas dzier¿awy %s"
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr "z g³ównym katalogiem w "
+
+#: dnsmasq.c:526
+msgid "enabled"
+msgstr "w³±czony"
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr "w trybie bezpiecznym"
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr "ograniczam ilo¶æ jednoczesnych przes³añ TFTP do %d"
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr "pod³±czono do DBus-a"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr "nie potrafiê prze³±czyæ siê do pracy w tle: %s"
+
+#: dnsmasq.c:778
+#, c-format
+msgid "failed to create helper: %s"
+msgstr "nie uda³o siê utworzyæ procesu pomocniczego: %s"
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr "nie powiod³o siê ustawianie ograniczeñ (capabilities): %s"
+
+#: dnsmasq.c:785
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "nie uda³o siê zmieniæ u¿ytkownika procesu na %s: %s"
+
+#: dnsmasq.c:790
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "nie uda³o siê zmieniæ grupy procesu na %s: %s"
+
+#: dnsmasq.c:793
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "nie uda³o siê otworzyæ pliku z PID-em %s: %s"
+
+#: dnsmasq.c:796
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "nie mo¿na otworzyæ %s: %s"
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr "proces potomny zabity sygna³em %d"
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr "proces potomny zakoñczy³ siê z kodem powrotu %d"
+
+#: dnsmasq.c:859
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr "nie uda³o siê uruchomiæ %s: %s"
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr "zakoñczy³em dzia³anie z powodu odebrania SIGTERM"
+
+#: dnsmasq.c:931
+#, c-format
+msgid "failed to access %s: %s"
+msgstr "brak dostêpu do %s: %s"
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr "czytanie %s"
+
+#: dnsmasq.c:972
+#, c-format
+msgid "no servers found in %s, will retry"
+msgstr "w %s nie znalaz³em serwerów, spróbujê ponownie pó¼niej"
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr "nie uda³o siê utworzyæ gniazda dla DHCP: %s"
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr "b³±d podczas ustawiania opcji gniazda DHCP: %s"
+
+#: dhcp.c:65
+#, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr "nie uda³o siê ustawiæ SO_REUSE{ADDR|PORT} gniazda DHCP: %s"
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr "b³±d przy przyznawaniu nazwy gniazdu serwera DHCP: %s"
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "nie uda³o siê utworzyæ surowego gniazda ICMP: %s."
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr "¿±danie DHCP odebrano na interfejsie %s, który nie ma adresu"
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr "zakres adresów DHCP %s -- %s jest niespójny z mask± sieci %s"
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "z³a zawarto¶æ pliku %s, w linii %d"
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr "w %s pomijam liniê %d -- powtórzona nazwa lub adres IP"
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "powtórzony adres IP (%s) w parametrze dhcp-config"
+
+#: dhcp.c:981
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "powtórzony adres IP (%s) w pliku %s"
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr "do komputera o nazwie %s pasuje wiêcej ni¿ jeden adres, w odpowiedzi DHCP wysy³am %s"
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr "powtórzenie adresu IP %s (%s) w opcji dhcp-config"
+
+#: lease.c:67
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "nie potrafiê otworzyæ albo utworzyæ pliku dzier¿aw %s: %s"
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr "zbyt du¿a ilo¶æ zapisanych dzier¿aw"
+
+#: lease.c:129
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "nie potrafiê uruchomiæ skryptu %s: %s"
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr "skrypt zakoñczy³ siê z kodem powrotu %s"
+
+#: lease.c:235
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "b³±d zapisu do %s: %s (spróbujê ponownie za %us)"
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr "nie zdefiniowano zakresu adresów odpowiedniego dla Â¿Â±dania %s %s"
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr "z wyborem podsieci"
+
+#: rfc2131.c:316
+msgid "via"
+msgstr "przez"
+
+#: rfc2131.c:331
+#, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr "%u dostêpna podsieæ DHCP: %s/%s"
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr "%u dostêpny zakres adresów DHCP: %s -- %s"
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr "wy³±czony(a)"
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr "ignorujê"
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr "adres jest w u¿yciu"
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr "brak dostêpnego adresu"
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr "nieprawid³owa sieæ"
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr "brak skonfigurowanego adresu"
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr "brak wolnych dzier¿aw"
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr "klient %u przedstawia siê jako %s"
+
+#: rfc2131.c:700
+#, c-format
+msgid "%u vendor class: %s"
+msgstr "%u klasa dostawcy: %s"
+
+#: rfc2131.c:702
+#, c-format
+msgid "%u user class: %s"
+msgstr "%u klasa u¿ytkownika: %s"
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr "PXE BIS nie jest obs³ugiwane"
+
+#: rfc2131.c:886
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "wy³±czam statyczne przypisanie adresu %s dla %s"
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr "nieznana dzier¿awa"
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr "nie proponujê zak³adanego w konfiguracji adresu %s, bo jest on ju¿ wydzier¿awiony komputerowi %s"
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr "nie proponujê zak³adanego w konfiguracji adresu %s, bo u¿ywa go który¶ z serwerów"
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr "nie proponujê zak³adanego w konfiguracji adresu %s, bo ju¿ poprzednio zosta³ odrzucony"
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr "brak unikalnego id"
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr "nieprawid³owy identyfikator serwera (server-ID)"
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr "b³êdny adres"
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr "dzier¿awa nieznaleziona"
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr "adres niedostêpny"
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr "dostêpna statyczna dzier¿awa"
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr "adres zarezerwowany"
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr "porzucam przypisanie do %s nazwy %s"
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr "%u cechy: %s"
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr "%u nazwa pliku bootowania: %s"
+
+#: rfc2131.c:1732
+#, c-format
+msgid "%u server name: %s"
+msgstr "%u nazwa serwera: %s"
+
+#: rfc2131.c:1746
+#, c-format
+msgid "%u next server: %s"
+msgstr "%u nastêpny serwer: %s"
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr "%u odpowied¼ rozg³oszeniowa"
+
+#: rfc2131.c:1812
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr "nie mam mo¿liwo¶ci wys³ania opcji %d DHCP/BOOTP: niedostateczna ilo¶æ miejsca w pakiecie"
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr "menu PXE zbyt du¿e"
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr "Nie uwzglêdniam czê¶ci domenowej (%s) dla komputera %s"
+
+#: rfc2131.c:2189
+#, c-format
+msgid "%u requested options: %s"
+msgstr "%u za¿±dano: %s"
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr "nie mogê wys³aæ opcji RFC3925: za d³ugi Â³añcuch opcji przy numerze %d"
+
+#: netlink.c:70
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "nie potrafiê utworzyæ po³±czenia netlink %s"
+
+#: netlink.c:288
+#, c-format
+msgid "netlink returns error: %s"
+msgstr "wyst±pi³ b³±d w po³±czeniu netlink %s"
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr "próba ustawienia adresu IPv6 serwera przez DBus, ale brak obs³ugi IPv6"
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr "ustawiam adresy serwerów nadrzêdnych na podstawie informacji odebranych z DBus"
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr "nie mo¿na zarejestrowaæ uchwytu DBus"
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "nie potrafiê utworzyæ gniazda DHCP BPF: %s"
+
+#: bpf.c:245
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr "¿±danie DHCP od urz±dzenia nieobs³ugiwanego typu (%d) odebrano na %s"
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr "brak wolnego portu dla us³ugi TFTP"
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr "nieobs³ugiwane Â¿Â±danie od komputera %s"
+
+#: tftp.c:406
+#, c-format
+msgid "file %s not found"
+msgstr "plik %s nie zosta³ znaleziony"
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr "b³±d %d %s odebrano od %s"
+
+#: tftp.c:554
+#, c-format
+msgid "failed sending %s to %s"
+msgstr "b³±d wysy³ania pliku %s do komputera %s"
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr "plik %s przes³ano do %s"
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr "przepe³nienie: stracono %d wpisów do logów"
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr "nie uda³o siê zapisaæ komunikatów do %s"
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr "B£¡D: nie uda³o siê uruchomiæ dnsmasq-a"
+
+#~ msgid "only one dhcp-hostsfile allowed"
+#~ msgstr "mo¿na wskazaæ tylko jeden plik dhcp-hostsfile"
+
+#~ msgid "only one dhcp-optsfile allowed"
+#~ msgstr "mo¿na wskazaæ tylko jeden plik dhcp-optsfile"
+
+#~ msgid "files nested too deep in %s"
+#~ msgstr "zbyt du¿e zag³êbienie plików w %s"
+
+#~ msgid "TXT record string too long"
+#~ msgstr "zbyt d³ugi rekord TXT"
+
+#~ msgid "failed to set IPV6 options on listening socket: %s"
+#~ msgstr "b³±d ustawiania opcji IPV6 na nas³uchuj±cym gnie¼dzie: %s"
+
+#~ msgid "failed to bind listening socket for %s: %s"
+#~ msgstr "b³±d przy przyznawaniu nazwy gniazdu %s: %s"
+
+#~ msgid "failed to listen on socket: %s"
+#~ msgstr "b³±d przy w³±czaniu nas³uchu na gnie¼dzie: %s"
+
+#~ msgid "failed to create TFTP socket: %s"
+#~ msgstr "nie powiod³o siê otwieranie gniazda dla us³ugi TFTP: %s"
diff --git a/po/pt_BR.po b/po/pt_BR.po
new file mode 100644 (file)
index 0000000..5fe209e
--- /dev/null
@@ -0,0 +1,1455 @@
+# Portuguese translations for dnsmasq package.
+# This file is put in the public domain.
+# Simon Kelley <simon@thekelleys.org.uk>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.26\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2006-01-16 20:42+0000\n"
+"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
+"Language-Team: Portuguese <ldp-br@bazar.conectiva.com.br>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: cache.c:761
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr ""
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr ""
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr ""
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr ""
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr ""
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr ""
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr ""
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1040
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr ""
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:57
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr ""
+
+#: util.c:189
+msgid "failed to allocate memory"
+msgstr ""
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr ""
+
+#: util.c:237
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr ""
+
+#: util.c:245
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr ""
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr ""
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr ""
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr ""
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr ""
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr ""
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr ""
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr ""
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr ""
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr ""
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr ""
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr ""
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr ""
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr ""
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr ""
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr ""
+
+#: option.c:258
+msgid "Read DHCP host specs from file."
+msgstr ""
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr ""
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr ""
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr ""
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr ""
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr ""
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr ""
+
+#: option.c:265
+msgid "Map DHCP user class to tag."
+msgstr ""
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:269
+msgid "Don't do DHCP for hosts with tag set."
+msgstr ""
+
+#: option.c:270
+msgid "Force broadcast replies for hosts with tag set."
+msgstr ""
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr ""
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr ""
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr ""
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr ""
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr ""
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr ""
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr ""
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr ""
+
+#: option.c:280
+msgid "Specify options to be sent to DHCP clients."
+msgstr ""
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr ""
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr ""
+
+#: option.c:284
+msgid "Log DNS queries."
+msgstr ""
+
+#: option.c:285
+msgid "Force the originating port for upstream DNS queries."
+msgstr ""
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr ""
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr ""
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr ""
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr ""
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr ""
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr ""
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr ""
+
+#: option.c:293
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr ""
+
+#: option.c:294
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr ""
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr ""
+
+#: option.c:296
+msgid "Map DHCP vendor class to tag."
+msgstr ""
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr ""
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr ""
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr ""
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:301
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr ""
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr ""
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr ""
+
+#: option.c:305
+msgid "Specify PTR DNS record."
+msgstr ""
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr ""
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr ""
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr ""
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr ""
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr ""
+
+#: option.c:312
+msgid "Map MAC address (with wildcards) to option set."
+msgstr ""
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:317
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr ""
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:319
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr ""
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:327
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr ""
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr ""
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr ""
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:339
+msgid "Specify NAPTR DNS record."
+msgstr ""
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr ""
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr ""
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:345
+msgid "Prompt to send to PXE clients."
+msgstr ""
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+#: option.c:349
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr ""
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr ""
+
+#: option.c:642
+#, c-format
+msgid "Valid options are:\n"
+msgstr ""
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr ""
+
+#: option.c:860
+msgid "bad IP address"
+msgstr ""
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr ""
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr ""
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1147 option.c:3030
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr ""
+
+#: option.c:1178 tftp.c:460
+#, c-format
+msgid "cannot access %s: %s"
+msgstr ""
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr ""
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr ""
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr ""
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr ""
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1791
+msgid "bad port range"
+msgstr ""
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr ""
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr ""
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr ""
+
+#: option.c:2019 option.c:2045
+msgid "bad hex constant"
+msgstr ""
+
+#: option.c:2107
+msgid "bad DHCP host name"
+msgstr ""
+
+#: option.c:2188
+msgid "bad tag-if"
+msgstr ""
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr ""
+
+#: option.c:2529
+msgid "bad dhcp-proxy address"
+msgstr ""
+
+#: option.c:2569
+msgid "invalid alias range"
+msgstr ""
+
+#: option.c:2582
+msgid "bad interface name"
+msgstr ""
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2632
+msgid "bad PTR record"
+msgstr ""
+
+#: option.c:2663
+msgid "bad NAPTR record"
+msgstr ""
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr ""
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr ""
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr ""
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr ""
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr ""
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2849
+msgid "missing \""
+msgstr ""
+
+#: option.c:2908
+msgid "bad option"
+msgstr ""
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr ""
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr ""
+
+#: option.c:2916
+msgid "error"
+msgstr ""
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr ""
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: option.c:3151 option.c:3187
+#, c-format
+msgid "read %s"
+msgstr ""
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr ""
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr ""
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:3273
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:3284
+msgid "try --help"
+msgstr ""
+
+#: option.c:3286
+msgid "try -w"
+msgstr ""
+
+#: option.c:3289
+#, c-format
+msgid "bad command line options: %s"
+msgstr ""
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr ""
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr ""
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr ""
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, c-format
+msgid "failed to read %s: %s"
+msgstr ""
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr ""
+
+#: option.c:3409
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr ""
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr ""
+
+#: network.c:171
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr ""
+
+#: network.c:380
+#, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr ""
+
+#: network.c:746
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr ""
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr ""
+
+#: network.c:794
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr ""
+
+#: network.c:811
+msgid "unqualified"
+msgstr ""
+
+#: network.c:811
+msgid "names"
+msgstr ""
+
+#: network.c:813
+msgid "default"
+msgstr ""
+
+#: network.c:815
+msgid "domain"
+msgstr ""
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:820
+#, c-format
+msgid "using standard nameservers for %s %s"
+msgstr ""
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:825
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:148
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:158
+msgid "asychronous logging is not available under Android"
+msgstr ""
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr ""
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr ""
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr ""
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr ""
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:455
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr ""
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr ""
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr ""
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr ""
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr ""
+
+#: dnsmasq.c:474
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr ""
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr ""
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr ""
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:491
+msgid "warning: no upstream servers configured"
+msgstr ""
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:526
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr ""
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, c-format
+msgid "failed to create helper: %s"
+msgstr ""
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:785
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:790
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:793
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr ""
+
+#: dnsmasq.c:796
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:859
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr ""
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr ""
+
+#: dnsmasq.c:931
+#, c-format
+msgid "failed to access %s: %s"
+msgstr ""
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr ""
+
+#: dnsmasq.c:972
+#, c-format
+msgid "no servers found in %s, will retry"
+msgstr ""
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:65
+#, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr ""
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr ""
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr ""
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr ""
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr ""
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr ""
+
+#: dhcp.c:981
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr ""
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr ""
+
+#: lease.c:67
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr ""
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:129
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr ""
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:235
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr ""
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:316
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:331
+#, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:700
+#, c-format
+msgid "%u vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:702
+#, c-format
+msgid "%u user class: %s"
+msgstr ""
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:886
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr ""
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1732
+#, c-format
+msgid "%u server name: %s"
+msgstr ""
+
+#: rfc2131.c:1746
+#, c-format
+msgid "%u next server: %s"
+msgstr ""
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr ""
+
+#: rfc2131.c:1812
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2189
+#, c-format
+msgid "%u requested options: %s"
+msgstr ""
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr ""
+
+#: netlink.c:70
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr ""
+
+#: netlink.c:288
+#, c-format
+msgid "netlink returns error: %s"
+msgstr ""
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr ""
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr ""
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr ""
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr ""
+
+#: bpf.c:245
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr ""
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:406
+#, c-format
+msgid "file %s not found"
+msgstr ""
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:554
+#, c-format
+msgid "failed sending %s to %s"
+msgstr ""
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr ""
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr ""
diff --git a/po/ro.po b/po/ro.po
new file mode 100644 (file)
index 0000000..094da79
--- /dev/null
+++ b/po/ro.po
@@ -0,0 +1,1566 @@
+# Romanian translations for dnsmasq package.
+# This file is put in the public domain.
+# Simon Kelley <simon@thekelleys.org.uk>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dnsmasq 2.24\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2005-11-22 16:46+0000\n"
+"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n"
+"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# for compatibility purposes the letters Ã¢, Äƒ, ÅŸ, Å£ and Ã® can be written as their look-alike correspondent.
+#: cache.c:761
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "încărcarea numelor din %s: %s a eÅŸuat"
+
+#: cache.c:795 dhcp.c:865
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "adresă greÅŸită Ã®n %s, linia %d"
+
+#: cache.c:853 dhcp.c:881
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "nume greÅŸit Ã®n %s linia %d"
+
+#: cache.c:860 dhcp.c:956
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "citesc %s - %d adrese"
+
+#: cache.c:899
+msgid "cleared cache"
+msgstr "memoria temporară a fost ÅŸtearsă"
+
+#: cache.c:960
+#, c-format
+msgid "%s is a CNAME, not giving it to the DHCP lease of %s"
+msgstr ""
+
+#: cache.c:966
+#, c-format
+msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s"
+msgstr "nu pot da numele %s Ã®mprumutului de adresă DHCP a lui %s deoarece numeleexistă Ã®n %s cu adresa %s"
+
+#: cache.c:1039
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1040
+#, fuzzy, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr "cantitate de memorie temporară %d, %d/%d stocări temporare aureutilizat locaÅ£ii neexpirate."
+
+#: cache.c:1042
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1068
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:57
+#, fuzzy, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "ascultarea pe socket a eÅŸuat: %s"
+
+#: util.c:189
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "nu pot Ã®ncărca %d bytes"
+
+#: util.c:227 option.c:573
+msgid "could not get memory"
+msgstr "nu am putut aloca memorie"
+
+#: util.c:237
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "nu pot citi %s: %s"
+
+#: util.c:245
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "nu pot Ã®ncărca %d bytes"
+
+#: util.c:350
+#, c-format
+msgid "infinite"
+msgstr "infinit"
+
+#: option.c:244
+msgid "Specify local address(es) to listen on."
+msgstr "SpecificaÅ£i adresele locale deservite."
+
+#: option.c:245
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "AfiÅŸează adresele IP ale maÅŸinilor Ã®n domeniul dat."
+
+#: option.c:246
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Simulează căutări după adresă pentru domenii de adresă private (RFC1918)."
+
+#: option.c:247
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Interpretează adresa IP ca NXDOMAIN (împotriva manipulărilor Verisign)"
+
+#: option.c:248
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Specifică mărimea Ã®nregistrărilor temporare (implicit e %s)."
+
+#: option.c:249
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Specifică fiÅŸier de configurare (implicit e %s)."
+
+#: option.c:250
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "NU porneÅŸte Ã®n fundal: rulează Ã®n modul depanare."
+
+#: option.c:251
+msgid "Do NOT forward queries with no domain part."
+msgstr "NU Ã®nainta cererile ce nu conÅ£in domeniu DNS."
+
+#: option.c:252
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Răspunde cu Ã®nregistrări MX spre el Ã®nsuÅŸi pentru maÅŸini locale."
+
+#: option.c:253
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Adaugă numelor simple din /etc/hosts numele domeniului ca sufix."
+
+#: option.c:254
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Nu inainta cereri DNS defecte provenite de la maÅŸini Windows."
+
+#: option.c:255
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Activează DHCP Ã®n domeniul dat cu durată limitată de Ã®mprumut."
+
+#: option.c:256
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Rulează sub acest grup după pornire (implicit e %s)."
+
+#: option.c:257
+msgid "Set address or hostname for a specified machine."
+msgstr "Schimbă adresa sau numele maÅŸinii specificate."
+
+#: option.c:258
+#, fuzzy
+msgid "Read DHCP host specs from file."
+msgstr "nume MX invalid"
+
+#: option.c:259
+msgid "Read DHCP option specs from file."
+msgstr ""
+
+#: option.c:260
+msgid "Evaluate conditional tag expression."
+msgstr ""
+
+#: option.c:261
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "Nu Ã®ncarcă fiÅŸierul %s."
+
+#: option.c:262
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Specifică spre citire un fiÅŸier hosts adiÅ£ional la %s."
+
+#: option.c:263
+msgid "Specify interface(s) to listen on."
+msgstr "Specifică interfeÅ£ele deservite."
+
+#: option.c:264
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Specifică interfeÅ£ele NE-deservite."
+
+#: option.c:265
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Leagă clasa de utilizator DHCP cu grup de opÅ£iuni."
+
+#: option.c:266
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:267
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:268
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:269
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Nu furniza DHCP maÅŸinilor din grupul de opÅ£iuni."
+
+#: option.c:270
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Nu furniza DHCP maÅŸinilor din grupul de opÅ£iuni."
+
+#: option.c:271
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr "NU porneÅŸte Ã®n fundal, NU rulează Ã®n modul depanare."
+
+#: option.c:272
+msgid "Assume we are the only DHCP server on the local network."
+msgstr "Presupune că suntem singurul server DHCP din reÅ£eaua locală."
+
+#: option.c:273
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Specifică fiÅŸierul de stocare a Ã®mprumuturilor DHCP (implicit e %s)."
+
+#: option.c:274
+msgid "Return MX records for local hosts."
+msgstr "Răspunde cu Ã®ntregistrări MX pentru maÅŸini locale."
+
+#: option.c:275
+msgid "Specify an MX record."
+msgstr "Specifică o Ã®nregistrare MX."
+
+#: option.c:276
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Specifică opÅ£iuni BOOTP serverului DHCP."
+
+#: option.c:277
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "Nu Ã®ncărca fiÅŸierul %s, citeÅŸte-l doar la SIGHUP."
+
+#: option.c:278
+msgid "Do NOT cache failed search results."
+msgstr "NU memora rezultatele de căutare DNS eÅŸuatată."
+
+#: option.c:279
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr "FoloseÅŸte servere DNS strict Ã®n ordinea dată Ã®n %s."
+
+#: option.c:280
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Configurează opÅ£iuni Ã®n plusce trebuie trimise clienÅ£ilor DHCP."
+
+#: option.c:281
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:282
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Specifică numărul portului pentru cereri DNS (implicit e 53)."
+
+#: option.c:283
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr "Marimea maximă a pachetului UDP pentru EDNS.0 (implicit e %s)."
+
+#: option.c:284
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "ÃŽnregistrează tranzacÅ£iile."
+
+#: option.c:285
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "ForÅ£ează acest port pentru datele ce pleacă."
+
+#: option.c:286
+msgid "Do NOT read resolv.conf."
+msgstr "NU citi fiÅŸierul resolv.conf"
+
+#: option.c:287
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Specifică calea către resolv.conf (implicit e %s)."
+
+#: option.c:288
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Specifică adresele server(elor) superioare cu domenii opÅ£ionale."
+
+#: option.c:289
+msgid "Never forward queries to specified domains."
+msgstr "Nu Ã®naintează cererile spre domeniile specificate."
+
+#: option.c:290
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Specifică domeniul de transmis prin DHCP."
+
+#: option.c:291
+msgid "Specify default target in an MX record."
+msgstr "Specifică o Å£intă Ã®ntr-o Ã®nregistrare MX."
+
+#: option.c:292
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr "Specifică TTL Ã®n secunde pentru răspunsurile din /etc/hosts."
+
+#: option.c:293
+#, fuzzy
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Specifică TTL Ã®n secunde pentru răspunsurile din /etc/hosts."
+
+#: option.c:294
+#, fuzzy
+msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
+msgstr "Specifică TTL Ã®n secunde pentru răspunsurile din /etc/hosts."
+
+#: option.c:295
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)."
+
+#: option.c:296
+#, fuzzy
+msgid "Map DHCP vendor class to tag."
+msgstr "Trimite opÅ£iuni DHCP Ã®n funcÅ£ie de marca plăcii de reÅ£ea."
+
+#: option.c:297
+msgid "Display dnsmasq version and copyright information."
+msgstr "AfiÅŸează versiunea dnsmasq ÅŸi drepturile de autor."
+
+#: option.c:298
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Traduce adresele IPv4 de la serverele DNS superioare."
+
+#: option.c:299
+msgid "Specify a SRV record."
+msgstr "Specifică o Ã®nregistrare SRV."
+
+#: option.c:300
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:301
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Specifică o cale pentru fiÅŸierul PID. (implicit %s)."
+
+#: option.c:302
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Specifică numărul maxim de Ã®mprumuturi DHCP (implicit %s)."
+
+#: option.c:303
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr "Răspunde cererilor DNS Ã®n funcÅ£ie de interfaÅ£a pe care a venit cererea."
+
+#: option.c:304
+msgid "Specify TXT DNS record."
+msgstr "Specifică o Ã®nregistrare TXT."
+
+#: option.c:305
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Specifică o Ã®nregistrare TXT."
+
+#: option.c:306
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:307
+msgid "Bind only to interfaces in use."
+msgstr "Ascultă doar pe interfeÅ£ele active."
+
+#: option.c:308
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "CiteÅŸte informaÅ£ii DHCP statice despre maÅŸină din %s."
+
+#: option.c:309
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Activeaza interfaÅ£a DBus pentru configurarea serverelor superioare."
+
+#: option.c:310
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "Nu activează DHCP ci doar DNS pe această interfaţă."
+
+#: option.c:311
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Activează alocarea dinamică a adreselor pentru BOOTP."
+
+#: option.c:312
+#, fuzzy
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Trimite opÅ£iuni DHCP Ã®n funcÅ£ie de marca plăcii de reÅ£ea."
+
+#: option.c:313
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:314
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:315
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:316
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:317
+#, fuzzy
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)."
+
+#: option.c:318
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:319
+#, fuzzy, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Specifică numărul maxim de Ã®mprumuturi DHCP (implicit %s)."
+
+#: option.c:320
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:321
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:323
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:324
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:325
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:326
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:327
+#, fuzzy, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Specifică numărul maxim de Ã®mprumuturi DHCP (implicit %s)."
+
+#: option.c:328
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:329
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:330
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:331
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:332
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:333
+msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
+msgstr ""
+
+#: option.c:334
+msgid "Inhibit DNS-rebind protection on this domain."
+msgstr ""
+
+#: option.c:335
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:336
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:337
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:338
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:339
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Specifică o Ã®nregistrare TXT."
+
+#: option.c:340
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:341
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:342
+msgid "Generate hostnames based on MAC address for nameless clients."
+msgstr ""
+
+#: option.c:343
+msgid "Use these DHCP relays as full proxies."
+msgstr ""
+
+#: option.c:344
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:345
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Configurează opÅ£iuni Ã®n plusce trebuie trimise clienÅ£ilor DHCP."
+
+#: option.c:346
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:347
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:348
+msgid "Add requestor's MAC address to forwarded DNS queries"
+msgstr ""
+
+#: option.c:349
+#, fuzzy
+msgid "Proxy DNSSEC validation results from upstream nameservers"
+msgstr "Traduce adresele IPv4 de la serverele DNS superioare."
+
+#: option.c:638
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Utilizare: dnsmasq [opÅ£iuni]\n"
+"\n"
+
+#: option.c:640
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "FolosiÅ£i opÅ£iunile prescurtate doar Ã®n linie de comandă.\n"
+
+#: option.c:642
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "OpÅ£iunile valide sunt:\n"
+
+#: option.c:683
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:798
+msgid "bad dhcp-option"
+msgstr "dhcp-option invalid"
+
+#: option.c:860
+#, fuzzy
+msgid "bad IP address"
+msgstr "citesc %s - %d adrese"
+
+#: option.c:968
+msgid "bad domain in dhcp-option"
+msgstr "domeniu DNS invalid Ã®n declaraÅ£ia dhcp-option"
+
+#: option.c:1034
+msgid "dhcp-option too long"
+msgstr "declararea dhcp-option este prea lungă"
+
+#: option.c:1043
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:1087
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1095
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1147 option.c:3030
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: option.c:1178 tftp.c:460
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: option.c:1207
+msgid "setting log facility is not possible under Android"
+msgstr ""
+
+#: option.c:1216
+msgid "bad log facility"
+msgstr ""
+
+#: option.c:1265
+msgid "bad MX preference"
+msgstr "preferinţă MX invalidă"
+
+#: option.c:1270
+msgid "bad MX name"
+msgstr "nume MX invalid"
+
+#: option.c:1284
+msgid "bad MX target"
+msgstr "Å£intă MX invalidă"
+
+#: option.c:1294
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1296
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1597 option.c:1601
+msgid "bad port"
+msgstr "port invalid"
+
+#: option.c:1620 option.c:1645
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1791
+#, fuzzy
+msgid "bad port range"
+msgstr "port invalid"
+
+#: option.c:1808
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1850
+msgid "bad dhcp-range"
+msgstr "dhcp-range invalid"
+
+#: option.c:1878
+msgid "only one tag allowed"
+msgstr ""
+
+#: option.c:1925
+msgid "inconsistent DHCP range"
+msgstr "domeniu DHCP inconsistent"
+
+#: option.c:2019 option.c:2045
+#, fuzzy
+msgid "bad hex constant"
+msgstr "dhcp-host invalid"
+
+#: option.c:2107
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "nume MX invalid"
+
+#: option.c:2188
+#, fuzzy
+msgid "bad tag-if"
+msgstr "Å£intă MX invalidă"
+
+#: option.c:2467 option.c:2752
+msgid "invalid port number"
+msgstr "număr de port invalid"
+
+#: option.c:2529
+#, fuzzy
+msgid "bad dhcp-proxy address"
+msgstr "citesc %s - %d adrese"
+
+#: option.c:2569
+#, fuzzy
+msgid "invalid alias range"
+msgstr "pondere invalidă"
+
+#: option.c:2582
+#, fuzzy
+msgid "bad interface name"
+msgstr "nume MX invalid"
+
+#: option.c:2607
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2612
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2632
+#, fuzzy
+msgid "bad PTR record"
+msgstr "înregistrare SRV invalidă"
+
+#: option.c:2663
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "înregistrare SRV invalidă"
+
+#: option.c:2695
+msgid "bad TXT record"
+msgstr "înregistrare TXT invalidă"
+
+#: option.c:2738
+msgid "bad SRV record"
+msgstr "înregistrare SRV invalidă"
+
+#: option.c:2745
+msgid "bad SRV target"
+msgstr "Å£intă SRV invalidă"
+
+#: option.c:2759
+msgid "invalid priority"
+msgstr "prioritate invalidă"
+
+#: option.c:2766
+msgid "invalid weight"
+msgstr "pondere invalidă"
+
+#: option.c:2785
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2849
+msgid "missing \""
+msgstr "lipseÅŸte \""
+
+#: option.c:2908
+msgid "bad option"
+msgstr "opÅ£iune invalidă"
+
+#: option.c:2910
+msgid "extraneous parameter"
+msgstr "parametru nerecunoscut"
+
+#: option.c:2912
+msgid "missing parameter"
+msgstr "parametru lipsa"
+
+#: option.c:2916
+msgid "error"
+msgstr "eroare"
+
+#: option.c:2921
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s la linia %d din %%s"
+
+#: option.c:2985 tftp.c:624
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: option.c:3151 option.c:3187
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "citesc %s"
+
+#: option.c:3239
+msgid "junk found in command line"
+msgstr ""
+
+#: option.c:3269
+#, c-format
+msgid "Dnsmasq version %s  %s\n"
+msgstr "dnsmasq versiunea %s  %s\n"
+
+#: option.c:3270
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"OpÅ£iuni cu care a fost compilat %s\n"
+"\n"
+
+#: option.c:3271
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Acest program vine FÄ‚RÄ‚ NICI O GARANÅ¢IE.\n"
+
+#: option.c:3272
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr "Dnsmasq este un program gratuit, sunteÅ£i invitaÅ£i să-l redistribuiÅ£i\n"
+
+#: option.c:3273
+#, fuzzy, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr "în termenii LicenÅ£ei publice generale GNU, versiunea 2.\n"
+
+#: option.c:3284
+msgid "try --help"
+msgstr ""
+
+#: option.c:3286
+msgid "try -w"
+msgstr ""
+
+#: option.c:3289
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "opÅ£iuni Ã®n linie de comandă invalide: %s."
+
+#: option.c:3330
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "nu pot citi numele maÅŸinii: %s"
+
+#: option.c:3358
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "se permite un singur fiÅŸier resolv.conf Ã®n modul no-poll"
+
+#: option.c:3368
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "am nevoie de un singur resolv.conf din care să citesc numele domeniului."
+
+#: option.c:3371 network.c:848 dhcp.c:814
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: option.c:3388
+#, c-format
+msgid "no search directive found in %s"
+msgstr "nu s-a găsit nici un criteriu de căutare Ã®n %s"
+
+#: option.c:3409
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:3413
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:461
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "serverul DNS %s refuză interogările recursive"
+
+#: forward.c:489
+#, c-format
+msgid "possible DNS-rebind attack detected: %s"
+msgstr ""
+
+#: network.c:171
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "interfaţă necunoscută %s"
+
+#: network.c:380
+#, fuzzy, c-format
+msgid "failed to create listening socket for %s: %s"
+msgstr "creearea socket-ului de ascultare a eÅŸuat: %s"
+
+#: network.c:746
+#, fuzzy, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "activarea socket-ului de ascultare pentru %s a eÅŸuat: %s"
+
+#: network.c:783
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorăm serverul DNS %s - interfaţă locală"
+
+#: network.c:794
+#, fuzzy, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "ignorăm serverul DNS %s - nu pot creea/activa socket-ul: %s"
+
+#: network.c:811
+msgid "unqualified"
+msgstr "invalid"
+
+#: network.c:811
+msgid "names"
+msgstr ""
+
+#: network.c:813
+msgid "default"
+msgstr ""
+
+#: network.c:815
+msgid "domain"
+msgstr "domeniu"
+
+#: network.c:818
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "folosim adresele locale doar pentru %S %s"
+
+#: network.c:820
+#, fuzzy, c-format
+msgid "using standard nameservers for %s %s"
+msgstr "folosim serverul DNS %s#%d pentru %s %s"
+
+#: network.c:822
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "folosim serverul DNS %s#%d pentru %s %s"
+
+#: network.c:825
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "folosim serverul DNS %s#%d"
+
+#: network.c:827
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "folosim serverul DNS %s#%d"
+
+#: dnsmasq.c:148
+#, fuzzy
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr "DBus nu este disponibil: puneÅ£i HAVE_DBUS in src/config.h"
+
+#: dnsmasq.c:153
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:158
+msgid "asychronous logging is not available under Android"
+msgstr ""
+
+#: dnsmasq.c:177
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "enumerarea interfeÅ£elor a eÅŸuat: %s"
+
+#: dnsmasq.c:185
+#, c-format
+msgid "unknown interface %s"
+msgstr "interfaţă necunoscută %s"
+
+#: dnsmasq.c:191
+#, c-format
+msgid "no interface with address %s"
+msgstr "nu exista interfaţă pentru adresa %s"
+
+#: dnsmasq.c:207 dnsmasq.c:678
+#, c-format
+msgid "DBus error: %s"
+msgstr "eroare DBus: %s"
+
+#: dnsmasq.c:210
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus nu este disponibil: puneÅ£i HAVE_DBUS in src/config.h"
+
+#: dnsmasq.c:236
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:291
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:455
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "am pornit, versiunea %s memorie temporară dezactivată"
+
+#: dnsmasq.c:457
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "am ponit, versiunea %s memorie temporară %d"
+
+#: dnsmasq.c:459
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "am pornit, versiunea %s memorie temporară dezactivată"
+
+#: dnsmasq.c:461
+#, c-format
+msgid "compile time options: %s"
+msgstr "compilat cu opÅ£iunile: %s"
+
+#: dnsmasq.c:467
+msgid "DBus support enabled: connected to system bus"
+msgstr "suportul DBus activ: sunt conectat la magistrala sistem"
+
+#: dnsmasq.c:469
+msgid "DBus support enabled: bus connection pending"
+msgstr "suportul DBus activ: aÅŸtept conexiunea la magistrală"
+
+# for compatibility purposes the letters Ã¢, Äƒ, ÅŸ, Å£ and Ã® can be written as their look-alike correspondent.
+#: dnsmasq.c:474
+#, fuzzy, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "încărcarea numelor din %s: %s a eÅŸuat"
+
+#: dnsmasq.c:478
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "specific opÅ£iunea --bind-interfaces din cauza limitărilor SO"
+
+#: dnsmasq.c:483
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "atenÅ£ie: interfaÅ£a %s nu există momentan"
+
+#: dnsmasq.c:488
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:491
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "configurăm serverele superioare prin Dbus"
+
+#: dnsmasq.c:495
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:508
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr "DHCP, Ã®mprumuturi statice doar către  %.0s%s, timpul reînoirii %s"
+
+#: dnsmasq.c:510
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:511
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, domeniu IP %s -- %s, timpul reînoirii %s"
+
+#: dnsmasq.c:526
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:526
+#, fuzzy
+msgid "enabled"
+msgstr "dezactivat"
+
+#: dnsmasq.c:528
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:554
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:680
+msgid "connected to system DBus"
+msgstr "magistrala sistem Dbus conectată"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "nu pot citi %s: %s"
+
+#: dnsmasq.c:781
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+# for compatibility purposes the letters Ã¢, Äƒ, ÅŸ, Å£ and Ã® can be written as their look-alike correspondent.
+#: dnsmasq.c:785
+#, fuzzy, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "încărcarea numelor din %s: %s a eÅŸuat"
+
+# for compatibility purposes the letters Ã¢, Äƒ, ÅŸ, Å£ and Ã® can be written as their look-alike correspondent.
+#: dnsmasq.c:790
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "încărcarea numelor din %s: %s a eÅŸuat"
+
+#: dnsmasq.c:793
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: dnsmasq.c:796
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "nu pot deschide %s:%s"
+
+#: dnsmasq.c:851
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:855
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:859
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "accesarea serverului %s a eÅŸuat: %s"
+
+#: dnsmasq.c:903
+msgid "exiting on receipt of SIGTERM"
+msgstr "am primit SIGTERM, am terminat"
+
+#: dnsmasq.c:931
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "accesarea serverului %s a eÅŸuat: %s"
+
+#: dnsmasq.c:961
+#, c-format
+msgid "reading %s"
+msgstr "citesc %s"
+
+#: dnsmasq.c:972
+#, fuzzy, c-format
+msgid "no servers found in %s, will retry"
+msgstr "nu s-a găsit nici un criteriu de căutare Ã®n %s"
+
+#: dhcp.c:40
+#, c-format
+msgid "cannot create DHCP socket: %s"
+msgstr "nu pot creea socket DHCP: %s"
+
+#: dhcp.c:52
+#, c-format
+msgid "failed to set options on DHCP socket: %s"
+msgstr "configurarea opÅ£iunilor socketului DHCP a eÅŸuat: %s"
+
+#: dhcp.c:65
+#, fuzzy, c-format
+msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"
+msgstr "configurarea SO_REUSEADDR pe socket-ul DHCP a eÅŸuat: %s"
+
+#: dhcp.c:77
+#, c-format
+msgid "failed to bind DHCP server socket: %s"
+msgstr "activarea socket-ului server-ului DHCP a eÅŸuat: %s"
+
+#: dhcp.c:103
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "nu pot creea socket ICMP raw: %s."
+
+#: dhcp.c:281
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:445
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr "domeniu DHCP %s -- %s nu este consistent cu masca de reÅ£ea %s"
+
+#: dhcp.c:852
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "linie invalidă Ã®n %s rândul %d"
+
+#: dhcp.c:895
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:978
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "adresă IP duplicat %s Ã®n declaraÅ£ia dhcp-config."
+
+#: dhcp.c:981
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "adresă IP duplicat %s Ã®n declaraÅ£ia dhcp-config."
+
+#: dhcp.c:1024
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:1029
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr "adresă IP duplicat %s (%s) Ã®n declaraÅ£ia dhcp-config."
+
+#: lease.c:67
+#, fuzzy, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "nu pot creea sau deschide fiÅŸierul cu Ã®mprumuturi: %s"
+
+#: lease.c:93
+msgid "too many stored leases"
+msgstr "prea multe Ã®mprumuturi stocate"
+
+#: lease.c:129
+#, fuzzy, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: lease.c:135
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:235
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "nu pot citi %s: %s"
+
+#: rfc2131.c:315
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s"
+
+#: rfc2131.c:316
+msgid "with subnet selector"
+msgstr "cu selectorul de subreÅ£ea"
+
+#: rfc2131.c:316
+msgid "via"
+msgstr "prin"
+
+#: rfc2131.c:331
+#, fuzzy, c-format
+msgid "%u available DHCP subnet: %s/%s"
+msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s"
+
+#: rfc2131.c:334
+#, c-format
+msgid "%u available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:363
+msgid "disabled"
+msgstr "dezactivat"
+
+#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288
+msgid "ignored"
+msgstr "ignorat"
+
+#: rfc2131.c:419 rfc2131.c:1135
+msgid "address in use"
+msgstr "adresa este folosită"
+
+#: rfc2131.c:433 rfc2131.c:970
+msgid "no address available"
+msgstr "nici o adresă disponibilă"
+
+#: rfc2131.c:440 rfc2131.c:1098
+msgid "wrong network"
+msgstr "reÅ£ea greÅŸită"
+
+#: rfc2131.c:454
+msgid "no address configured"
+msgstr "adresă lipsă"
+
+#: rfc2131.c:460 rfc2131.c:1148
+msgid "no leases left"
+msgstr "nu mai am de unde să Ã®mprumut"
+
+#: rfc2131.c:545
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:700
+#, fuzzy, c-format
+msgid "%u vendor class: %s"
+msgstr "eroare DBus: %s"
+
+#: rfc2131.c:702
+#, fuzzy, c-format
+msgid "%u user class: %s"
+msgstr "eroare DBus: %s"
+
+#: rfc2131.c:761
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:886
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "dezactivăm adresele DHCP statice %s"
+
+#: rfc2131.c:907
+msgid "unknown lease"
+msgstr "împrumut necunoscut"
+
+#: rfc2131.c:939
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:949
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:952
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:968 rfc2131.c:1141
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1037
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1055
+msgid "wrong address"
+msgstr "adresă greÅŸită"
+
+#: rfc2131.c:1073
+msgid "lease not found"
+msgstr "împrumutul nu a fost găsit"
+
+#: rfc2131.c:1106
+msgid "address not available"
+msgstr "adresă indisponibilă"
+
+#: rfc2131.c:1117
+msgid "static lease available"
+msgstr "împrumut static este disponibil"
+
+#: rfc2131.c:1121
+msgid "address reserved"
+msgstr "adresă rezervată"
+
+#: rfc2131.c:1129
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1710
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1723
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1732
+#, fuzzy, c-format
+msgid "%u server name: %s"
+msgstr "eroare DBus: %s"
+
+#: rfc2131.c:1746
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "eroare DBus: %s"
+
+#: rfc2131.c:1749
+#, c-format
+msgid "%u broadcast response"
+msgstr ""
+
+#: rfc2131.c:1812
+#, fuzzy, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr "nu pot trimite opÅ£iunea DHCP %d: nu mai este loc Ã®n pachet"
+
+#: rfc2131.c:2058
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2171
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2189
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "compilat cu opÅ£iunile: %s"
+
+#: rfc2131.c:2456
+#, c-format
+msgid "cannot send RFC3925 option: too many options for enterprise number %d"
+msgstr ""
+
+#: netlink.c:70
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "nu pot să activez socket-ul netlink: %s"
+
+#: netlink.c:288
+#, fuzzy, c-format
+msgid "netlink returns error: %s"
+msgstr "eroare DBus: %s"
+
+#: dbus.c:150
+msgid "attempt to set an IPv6 server address via DBus - no IPv6 support"
+msgstr "incerc să configurez un server IPv6 prin Dbus - nu este suport IPv6"
+
+#: dbus.c:286
+msgid "setting upstream servers from DBus"
+msgstr "configurăm serverele superioare prin Dbus"
+
+#: dbus.c:324
+msgid "could not register a DBus message handler"
+msgstr "nu pot activa o interfaţă de mesaje DBus"
+
+#: bpf.c:217
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "nu pot creea socket DHCP BPF: %s"
+
+#: bpf.c:245
+#, fuzzy, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr "cerere DHCP pentru dispozitiv nesuportat (%d) recepÅ£ionată prin %s"
+
+#: tftp.c:281
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:296
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:406
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "împrumutul nu a fost găsit"
+
+#: tftp.c:522
+#, c-format
+msgid "error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:554
+#, fuzzy, c-format
+msgid "failed sending %s to %s"
+msgstr "nu pot citi %s: %s"
+
+#: tftp.c:568
+#, c-format
+msgid "sent %s to %s"
+msgstr ""
+
+#: log.c:177
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:254
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:462
+msgid "FAILED to start up"
+msgstr "pornirea A EÅžUAT"
+
+#~ msgid "TXT record string too long"
+#~ msgstr "ÅŸirul de caractere pentru Ã®nregistrarea TXT este prea lung"
+
+#~ msgid "failed to set IPV6 options on listening socket: %s"
+#~ msgstr "configurarea opÅ£iunilor IPv6 a eÅŸuat pe socket-ul de ascultare: %s"
+
+#~ msgid "failed to bind listening socket for %s: %s"
+#~ msgstr "activarea socket-ului de ascultare pentru %s a eÅŸuat: %s"
+
+#~ msgid "failed to listen on socket: %s"
+#~ msgstr "ascultarea pe socket a eÅŸuat: %s"
+
+#, fuzzy
+#~ msgid "failed to create TFTP socket: %s"
+#~ msgstr "creearea socket-ului de ascultare a eÅŸuat: %s"
+
+#~ msgid "must set exactly one interface on broken systems without IP_RECVIF"
+#~ msgstr "trebuie specificată exact o singură interfaţă pe sistemele defectece nu au IP_RECVIF"
+
+#, fuzzy
+#~ msgid "failed to load %s: %s"
+#~ msgstr "nu pot Ã®ncărca %s: %s"
+
+#~ msgid "bad name in %s"
+#~ msgstr "nume invalid Ã®n %s"
+
+#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part"
+#~ msgstr "ÃŽmprumutul DHCP pentru %s va fi ignorat deoarece are domeniu invalid"
+
+#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"
+#~ msgstr "Integrarea cu ISC dhcpd nu este disponibilă:puneÅ£i HAVE_ISC_HEADER Ã®n src/config.h"
+
+#, fuzzy
+#~ msgid "illegal domain %s in dhcp-config directive."
+#~ msgstr "adresă IP duplicat %s Ã®n declaraÅ£ia dhcp-config."
+
+#~ msgid "running as root"
+#~ msgstr "rulez ca root"
+
+#, fuzzy
+#~ msgid "read %s - %d hosts"
+#~ msgstr "citesc %s - %d adrese"
+
+#~ msgid "domains"
+#~ msgstr "domenii"
+
+#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part"
+#~ msgstr "Ignor numele DHCP al maÅŸinii %s deoarece are domeniu DNS ilegal"
+
+#~ msgid "Display this message."
+#~ msgstr "AfiÅŸează acest mesaj."
+
+#~ msgid "failed to read %s:%m"
+#~ msgstr "citirea %s:%n a eÅŸuat"
+
+#, fuzzy
+#~ msgid "cannot send encapsulated option %d: no space left in wrapper"
+#~ msgstr "nu pot trimite opÅ£iunea DHCP %d: nu mai este loc Ã®n pachet"
+
+#~ msgid "More than one vendor class matches, using %s"
+#~ msgstr "Se potrivesc mai multe clase de mărci de interfeÅ£e, folosim %s"
+
+#~ msgid "forwarding table overflow: check for server loops."
+#~ msgstr "depăşire de memorie Ã®n tabela cu Ã®naintări DNS: verificaÅ£i de bucle."
+
+#~ msgid "nested includes not allowed"
+#~ msgstr "incluziunile locale nu sunt permise"
+
+#~ msgid "DHCP, %s will be written every %s"
+#~ msgstr "DHCP, %s va fi rescris odată la fiecare %s"
+
+#~ msgid "cannot create DHCP packet socket: %s. Is CONFIG_PACKET enabled in your kernel?"
+#~ msgstr "nu pot creea socket DHCP packet: %s. AveÅ£i activată Ã®n nucleulsistemului opÅ£iunea CONFIG_PACKET ?"
diff --git a/setup.html b/setup.html
new file mode 100644 (file)
index 0000000..1183f3b
--- /dev/null
@@ -0,0 +1,231 @@
+<HTML>
+<HEAD>
+<TITLE> Configuring Dnsmasq.</TITLE>
+</HEAD>
+<BODY BGCOLOR="WHITE"> 
+<H1 ALIGN=center>Dnsmasq setup</H1> 
+<H2>Installation.</H2>
+To compile and install dnsmasq, the following command (as root) is enough.
+
+<PRE>
+make install
+</PRE>
+
+You might want to edit config.h. Dnsmasq has
+been run on (at least) Linux, uCLinux, AIX 4.1.5, FreeBSD 4.4 OpenBSD and Tru64 4.x 
+
+Dnsmasq is normally  run on a firewall machine (the machine with the
+modem or other connection to your ISP.) but it can run on any machine
+with access to the ISPs nameservers.
+
+Put the binary in <TT>/usr/local/sbin/dnsmasq</TT> (running <TT>make install</TT>  will do this) and arrange for it
+to be started at boot time.
+
+Note that dnsmasq needs to run as root, since it binds privileged ports. It will drop root privileges after start-up. Dnsmasq
+logs problems using the syslog facility as a daemon. It logs debugging
+information to local0
+<P>
+<H2>Configuration.</H2>
+Configuration for dnsmasq is pretty simple in almost all cases. The
+program has collected a fair few options as it has developed but most of them
+are not needed most of the time. A machine which already has a DNS
+configuration (ie one or more external nameservers in <TT>/etc/resolv.conf</TT>
+and any local hosts in <TT>/etc/hosts</TT>) can be turned into a nameserver
+simply by running dnsmasq, with no options or configuration at
+all. Set the IP address of the machine running dnsmasq as the DNS
+server in all the other machines on your network, and you're done.
+<P>
+With a few option flags, it is possible to make dnsmasq do more clever
+tricks. Options for dnsmasq can be set either on the command line
+when starting dnsmasq, or in its configuration file, <TT>/etc/dnsmasq.conf</TT>.
+
+<h2>Making the nameserver machine use dnsmasq.</h2>
+In the simple configuration described above, processes local to the
+machine will not use dnsmasq, since they get their information about
+which nameservers to use from /etc/resolv.conf, which is set to the
+upstream nameservers. To fix this, simply replace the nameserver in
+<TT>/etc/resolv.conf</TT> with the local address 127.0.0.1 and give the
+address(es) of the upstream nameserver(s) to dnsmasq directly. You can
+do this using either the <TT>server</TT> option, or by putting them into
+another file, and telling  dnsmasq about its location with 
+the <TT>resolv-file</TT> option. 
+
+<h2>Automatic nameserver configuration.</h2>
+The two protocols most used for automatic IP network configuration
+(PPP and DHCP) can determine the IP addresses for nameservers automatically.
+The daemons can be made to write out a file in the resolv.conf format with the
+nameservers in which is perfect for dnsmasq to use. When the
+nameservers change, for instance on dialling into a new ISP using PPP,
+dnsmasq will automatically re-read this file and begin using the new
+nameserver(s) completely transparently.
+
+<h3>Automatic DNS server configuration with PPP.</h3>
+Later versions of pppd have an option "usepeerdns" which instructs it to write a file containing
+the address(es) of the DNS severs in <TT>/etc/ppp/resolv.conf</TT>. Configure dnsmasq
+as above with "nameserver 127.0.0.1" in <TT>/etc/resolv.conf</TT> and run dnsmasq 
+with to option <TT>resolv-file=/etc/ppp/resolv.conf</TT>.
+<P>
+On Redhat (at least versions 7.1, 7.2 and 7.3) you can set pppd
+options by adding "PPPOPTIONS=usepeerdns" to
+<TT>/etc/sysconfig/network-scripts/ifcfg-ippp0</TT>.  In the same file, make sure
+that "PEERDNS=no" to stop RedHat's network initscripts from copying
+<TT>/etc/ppp/resolv.conf</TT> into <TT>/etc/resolv.conf</TT>.<BR>
+
+On SuSE (at least version 8.1, and 8.2) you should use YaST to activate
+<TT>[x] Modify DNS when connected</TT> then stop SuSEs network initscripts 
+from copying <TT>/etc/ppp/resolv.conf</TT> into <TT>/etc/resolv.conf</TT> 
+by modifying MODIFY_RESOLV_CONF_DYNAMICALLY="no" in <TT>/etc/sysconfig/network/config</TT>.
+
+<h3>Automatic DNS server configuration with DHCP.</h3>
+You need to get your DHCP client to write the addresse(s) of the DNS
+servers to a file other than <TT>/etc/resolv.conf</TT>. For dhcpcd, the
+<TT>dhcpcd.exe</TT> script gets run with the addresses of the nameserver(s) in
+the shell variable <TT>$DNS</TT>. The following bit of shell script
+uses that to write a file suitable for dnsmasq. 
+<PRE>
+
+echo -n >|/etc/dhcpc/resolv.conf
+dnsservs=${DNS//,/ }
+for serv in $dnsservs; do
+    echo "nameserver $serv" >>/etc/dhcpc/resolv.conf
+done
+
+</PRE>
+Remember to give dhcpcd the <TT>-R</TT> flag to stop it overwriting 
+<TT>/etc/resolv.conf</TT>.
+
+<P>
+For other DHCP clients it should be possible to achieve the same effect.
+
+<h3> DHCP and PPP.</h3>
+On a laptop which may potentially connect via a modem and PPP or
+ethernet and DHCP it is possible to combine both of the above
+configurations. Running dnsmasq with the flags
+<TT>resolv-file=/etc/ppp/resolv.conf resolv-file=/etc/dhcpc/resolv.conf</TT>  
+makes it poll <B>both</B> files and use whichever was updated
+last. The result is automatic switching between DNS servers.
+</H3>
+
+<H2> Integration with DHCP.</H2>
+Dnsmasq reads <TT>/etc/hosts</TT> so that the names of local machines are
+available in DNS. This is fine when you give all your local machines
+static IP addresses which can go in <TT>/etc/hosts</TT>, but it doesn't work 
+when local machines are configured via DHCP, since the IP address
+allocated to machine is not fixed. Dnsmasq comes with an integrated
+DHCP daemon to solve this problem.
+<P>
+The dnsmasq DHCP daemon allocates addresses to hosts on the network and tries
+to determine their names. If it succeeds it add the name and address
+pair to the DNS. There are basically two ways to associate a name with
+a DHCP-configured machine; either the machine knows its name which it
+gets a DHCP lease, or dnsmasq gives it a name, based on the MAC
+address of its ethernet card. For the former to work, a machine needs to know its name when it
+requests a DHCP lease. For dhcpcd, the -h option specifies this. The
+names may be anything as far as DHCP is concerned, but dnsmasq adds
+some limitations. By default the names must no have a domain part, ie
+they must just be a alphanumeric name, without any dots.  This is a
+security feature to stop a machine on your network telling DHCP that
+its name is "www.microsoft.com" and thereby grabbing traffic which
+shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
+if the <TT>domain-suffix</TT> option is set, the domain part must match the
+suffix.
+<P>
+As an aside, make sure not to tell DHCP to set the hostname when it
+obtains a lease (in dhcpcd that's the -H flag.)
+This is not reliable since the DHCP server gets the
+hostname from DNS which in this case is dnsmasq. There is a race
+condition because the host's name in the DNS may change as a
+result of it getting a DHCP lease, but this does not propagate before
+the name is looked up. The net effect may be that the host believes it
+is called something different to its name in the DNS. To be safe, set
+the hostname on a machine locally, and pass the same name to DHCP when
+requesting a lease.
+<P>
+<H2>Setting up a mailhub.</H2>
+If you generate mail on the machines attached to your private network, you may
+ be interested in the MX record feature of dnsmasq. This allows you to have all
+ the machines on your network use your firewall or another machine as a "smarthost" and 
+deliver mail to it. The details of how to set this up are highly dependent on
+your mailer, system and distribution. The only thing that's relevant to dnsmasq is that the mailer 
+needs to be able to interrogate the DNS and find an MX record for your mailhub.
+<P>
+By giving dnsmasq the <TT>mx-host</TT> option
+you instruct dnsmasq to serve an MX record for the specified address. 
+By default the MX record 
+points to the machine on which dnsmasq is running, so mail delivered to that
+name will get sent to the mailer on your firewall machine. You can
+have the MX record point to another machine by using the <TT>mx-target</TT>
+option.
+<P>
+In some cases it's useful for all local machines to see an MX record
+pointing at themselves: this allows mailers which insist on an MX record and
+don't fall back to A records to deliver mail within the
+machine. These MX records are enabled using the <TT>selfmx</TT> option.
+
+<H2>Using special servers.</H2>
+Dnsmasq has the ability to direct DNS queries for certain domains to
+specific upstream nameservers. This feature was added for use with
+VPNs but it is fully general. The scenario is this: you have a
+standard internet connection via an ISP, and dnsmasq is configured to
+forward queries to the ISP's nameservers, then you make a VPN
+connection into your companies network, giving access to hosts inside
+the company firewall. You have access, but since many of the internal hosts
+aren't visible on the public internet, your company doesn't publish 
+them to the public DNS and you can't get their IP address from the ISP
+nameservers. The solution is to use the companies nameserver for
+private domains within the company, and dnsmasq allows this. Assuming
+that internal company machines are all in the domain internal.myco.com
+and the companies nameserver is at 192.168.10.1 then the option
+<TT>server=/internal.myco.com/192.168.10.1</TT> will direct all
+queries in the internal domain to the correct nameserver. You can
+specify more than one domain in each server option. If there is
+more than one nameserver just include as many
+<TT>server</TT> options as is needed to specify them all.  
+
+<H2>Local domains.</H2>
+Sometimes people have local domains which they do not want forwarded
+to upstream servers. This is accomodated by using server options
+without the server IP address. To make things clearer <TT>local</TT>
+is a synonym for <TT>server</TT>. For example the option
+<TT>local=/localnet/</TT> ensures that any domain name query which ends in
+<TT>.localnet</TT> will be answered if possible from
+<TT>/etc/hosts</TT> or DHCP, but never sent to an upstream server.
+
+<H2>Defeating wildcards in top level domains.</H2>
+In September 2003 Verisign installed a wildcard record in the .com and
+.net top level domains. The effect of this is that queries for
+unregistered .com and .net names now return the address of Verisign's
+sitefinder service, rather than a "no such domain" response. To
+restore the correct behaviour, you can tell dnsmasq the address of the
+sitefinder host and have it substitute an NXDOMAIN reply when it sees
+that address. The sitefinder address is currently  64.94.110.11, so
+giving the option <TT>bogus-nxdomain=64.94.110.11</TT> will enable
+this facility for Verisign. If other TLDs do that same thing you can
+add the correct addresses for them too. See the dnsmasq FAQ for more
+details on the <TT>bogus-nxdomain</TT> option.
+<H2>Other configuration details.</H2>
+By default dnsmasq offers DNS service on all the configured interfaces
+of a host. It's likely that you don't (for instance) want to offer a
+DNS service to the world via an interface connected to ADSL or
+cable-modem so dnsmasq allows you to specify which interfaces it will
+listen on. Use either the <TT>interface</TT> or <TT>address</TT> options to do this.
+<P>
+The <TT>filterwin2k</TT> option makes dnsmasq ignore certain DNS requests which
+are made by Windows boxen every few minutes. The requests generally
+don't get sensible answers in the global DNS and cause trouble by
+triggering dial-on-demand internet links.
+<P>
+Sending SIGHUP to the dnsmasq process will cause it to empty its cache and 
+then re-load <TT>/etc/hosts</TT> and <TT>/etc/resolv.conf</TT>.
+<P> Sending SIGUSR1 (killall -10 dnsmasq) to the dnsmasq process will
+cause to to write cache usage statisticss to the log, typically
+<TT>/var/log/syslog</TT> or <TT>/var/log/messages</TT>.
+<P> The <TT>log-queries</TT> option tells dnsmasq to verbosely log the queries
+it is handling and causes SIGUSR1 to trigger a complete dump of the
+contents of the cache to the syslog.
+
+<P>For a complete listing of options please take a look at the manpage
+dnsmasq(8).
diff --git a/src/bpf.c b/src/bpf.c
new file mode 100644 (file)
index 0000000..9a77426
--- /dev/null
+++ b/src/bpf.c
@@ -0,0 +1,321 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
+
+static struct iovec ifconf = {
+  .iov_base = NULL,
+  .iov_len = 0
+};
+
+static struct iovec ifreq = {
+  .iov_base = NULL,
+  .iov_len = 0
+};
+
+#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
+
+#include <sys/sysctl.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/if_ether.h>
+
+int arp_enumerate(void *parm, int (*callback)())
+{
+  int mib[6];
+  size_t needed;
+  char *next;
+  struct rt_msghdr *rtm;
+  struct sockaddr_inarp *sin2;
+  struct sockaddr_dl *sdl;
+  int rc;
+  
+  mib[0] = CTL_NET;
+  mib[1] = PF_ROUTE;
+  mib[2] = 0;
+  mib[3] = AF_INET;
+  mib[4] = NET_RT_FLAGS;
+#ifdef RTF_LLINFO
+  mib[5] = RTF_LLINFO;
+#else
+  mib[5] = 0;
+#endif 
+  if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1 || needed == 0)
+    return 0;
+
+  while (1) 
+    {
+      if (!expand_buf(&ifconf, needed))
+       return 0;
+      if ((rc = sysctl(mib, 6, ifconf.iov_base, &needed, NULL, 0)) == 0 ||
+         errno != ENOMEM)
+       break;
+      needed += needed / 8;
+    }
+  if (rc == -1)
+    return 0;
+  
+  for (next = ifconf.iov_base ; next < (char *)ifconf.iov_base + needed; next += rtm->rtm_msglen)
+    {
+      rtm = (struct rt_msghdr *)next;
+      sin2 = (struct sockaddr_inarp *)(rtm + 1);
+      sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
+      if (!(*callback)(AF_INET, &sin2->sin_addr, LLADDR(sdl), sdl->sdl_alen, parm))
+       return 0;
+    }
+
+  return 1;
+}
+
+#endif
+
+
+int iface_enumerate(int family, void *parm, int (*callback)())
+{
+  char *ptr;
+  struct ifreq *ifr;
+  struct ifconf ifc;
+  int fd, errsav, ret = 0;
+  int lastlen = 0;
+  size_t len = 0;
+  
+  if (family == AF_UNSPEC)
+#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
+    return  arp_enumerate(parm, callback);
+#else
+  return 0; /* need code for Solaris and MacOS*/
+#endif
+
+  if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
+    return 0;
+  
+  while(1)
+    {
+      len += 10*sizeof(struct ifreq);
+      
+      if (!expand_buf(&ifconf, len))
+       goto err;
+      
+      ifc.ifc_len = len;
+      ifc.ifc_buf = ifconf.iov_base;
+      
+      if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
+       {
+         if (errno != EINVAL || lastlen != 0)
+           goto err;
+       }
+      else
+       {
+         if (ifc.ifc_len == lastlen)
+           break; /* got a big enough buffer now */
+         lastlen = ifc.ifc_len;
+       }
+    }
+  
+  for (ptr = ifc.ifc_buf; ptr < (char *)(ifc.ifc_buf + ifc.ifc_len); ptr += len)
+    {
+      /* subsequent entries may not be aligned, so copy into
+        an aligned buffer to avoid nasty complaints about 
+        unaligned accesses. */
+
+      len = sizeof(struct ifreq);
+      
+#ifdef HAVE_SOCKADDR_SA_LEN
+      ifr = (struct ifreq *)ptr;
+      if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru))
+       len = ifr->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
+#endif
+      
+      if (!expand_buf(&ifreq, len))
+       goto err;
+
+      ifr = (struct ifreq *)ifreq.iov_base;
+      memcpy(ifr, ptr, len);
+           
+      if (ifr->ifr_addr.sa_family == family)
+       {
+         if (family == AF_INET)
+           {
+             struct in_addr addr, netmask, broadcast;
+             broadcast.s_addr = 0;
+             addr = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
+             if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1)
+               continue;
+             netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
+             if (ioctl(fd, SIOCGIFBRDADDR, ifr) != -1)
+               broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr; 
+             if (!((*callback)(addr, 
+                               (int)if_nametoindex(ifr->ifr_name),
+                               netmask, broadcast, 
+                               parm)))
+               goto err;
+           }
+#ifdef HAVE_IPV6
+         else if (family == AF_INET6)
+           {
+             struct in6_addr *addr = &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr;
+             /* voodoo to clear interface field in address */
+             if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
+               {
+                 addr->s6_addr[2] = 0;
+                 addr->s6_addr[3] = 0;
+               }
+             if (!((*callback)(addr,
+                               (int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id,
+                               (int)if_nametoindex(ifr->ifr_name),
+                               parm)))
+               goto err;
+           }
+#endif
+       }
+    }
+  
+  ret = 1;
+
+ err:
+  errsav = errno;
+  close(fd);  
+  errno = errsav;
+
+  return ret;
+}
+#endif
+
+
+#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
+#include <net/bpf.h>
+
+void init_bpf(void)
+{
+  int i = 0;
+
+  while (1) 
+    {
+      /* useful size which happens to be sufficient */
+      if (expand_buf(&ifreq, sizeof(struct ifreq)))
+       {
+         sprintf(ifreq.iov_base, "/dev/bpf%d", i++);
+         if ((daemon->dhcp_raw_fd = open(ifreq.iov_base, O_RDWR, 0)) != -1)
+           return;
+       }
+      if (errno != EBUSY)
+       die(_("cannot create DHCP BPF socket: %s"), NULL, EC_BADNET);
+    }       
+}
+
+void send_via_bpf(struct dhcp_packet *mess, size_t len,
+                 struct in_addr iface_addr, struct ifreq *ifr)
+{
+   /* Hairy stuff, packet either has to go to the
+      net broadcast or the destination can't reply to ARP yet,
+      but we do know the physical address. 
+      Build the packet by steam, and send directly, bypassing
+      the kernel IP stack */
+  
+  struct ether_header ether; 
+  struct ip ip;
+  struct udphdr {
+    u16 uh_sport;               /* source port */
+    u16 uh_dport;               /* destination port */
+    u16 uh_ulen;                /* udp length */
+    u16 uh_sum;                 /* udp checksum */
+  } udp;
+  
+  u32 i, sum;
+  struct iovec iov[4];
+
+  /* Only know how to do ethernet on *BSD */
+  if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN)
+    {
+      my_syslog(MS_DHCP | LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"), 
+               mess->htype, ifr->ifr_name);
+      return;
+    }
+   
+  ifr->ifr_addr.sa_family = AF_LINK;
+  if (ioctl(daemon->dhcpfd, SIOCGIFADDR, ifr) < 0)
+    return;
+  
+  memcpy(ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
+  ether.ether_type = htons(ETHERTYPE_IP);
+  
+  if (ntohs(mess->flags) & 0x8000)
+    {
+      memset(ether.ether_dhost, 255,  ETHER_ADDR_LEN);
+      ip.ip_dst.s_addr = INADDR_BROADCAST;
+    }
+  else
+    {
+      memcpy(ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN); 
+      ip.ip_dst.s_addr = mess->yiaddr.s_addr;
+    }
+  
+  ip.ip_p = IPPROTO_UDP;
+  ip.ip_src.s_addr = iface_addr.s_addr;
+  ip.ip_len = htons(sizeof(struct ip) + 
+                   sizeof(struct udphdr) +
+                   len) ;
+  ip.ip_hl = sizeof(struct ip) / 4;
+  ip.ip_v = IPVERSION;
+  ip.ip_tos = 0;
+  ip.ip_id = htons(0);
+  ip.ip_off = htons(0x4000); /* don't fragment */
+  ip.ip_ttl = IPDEFTTL;
+  ip.ip_sum = 0;
+  for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
+    sum += ((u16 *)&ip)[i];
+  while (sum>>16)
+    sum = (sum & 0xffff) + (sum >> 16);  
+  ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
+  
+  udp.uh_sport = htons(daemon->dhcp_server_port);
+  udp.uh_dport = htons(daemon->dhcp_client_port);
+  if (len & 1)
+    ((char *)mess)[len] = 0; /* for checksum, in case length is odd. */
+  udp.uh_sum = 0;
+  udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len);
+  sum += htons(IPPROTO_UDP);
+  sum += ip.ip_src.s_addr & 0xffff;
+  sum += (ip.ip_src.s_addr >> 16) & 0xffff;
+  sum += ip.ip_dst.s_addr & 0xffff;
+  sum += (ip.ip_dst.s_addr >> 16) & 0xffff;
+  for (i = 0; i < sizeof(struct udphdr)/2; i++)
+    sum += ((u16 *)&udp)[i];
+  for (i = 0; i < (len + 1) / 2; i++)
+    sum += ((u16 *)mess)[i];
+  while (sum>>16)
+    sum = (sum & 0xffff) + (sum >> 16);
+  udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
+  
+  ioctl(daemon->dhcp_raw_fd, BIOCSETIF, ifr);
+  
+  iov[0].iov_base = &ether;
+  iov[0].iov_len = sizeof(ether);
+  iov[1].iov_base = &ip;
+  iov[1].iov_len = sizeof(ip);
+  iov[2].iov_base = &udp;
+  iov[2].iov_len = sizeof(udp);
+  iov[3].iov_base = mess;
+  iov[3].iov_len = len;
+
+  while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
+}
+
+#endif
+
+
diff --git a/src/cache.c b/src/cache.c
new file mode 100644 (file)
index 0000000..77c1972
--- /dev/null
@@ -0,0 +1,1226 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
+#ifdef HAVE_DHCP
+static struct crec *dhcp_spare = NULL;
+#endif
+static struct crec *new_chain = NULL;
+static int cache_inserted = 0, cache_live_freed = 0, insert_error;
+static union bigname *big_free = NULL;
+static int bignames_left, hash_size;
+static int uid = 0;
+static char *addrbuff = NULL;
+
+/* type->string mapping: this is also used by the name-hash function as a mixing table. */
+static const struct {
+  unsigned int type;
+  const char * const name;
+} typestr[] = {
+  { 1,   "A" },
+  { 2,   "NS" },
+  { 5,   "CNAME" },
+  { 6,   "SOA" },
+  { 10,  "NULL" },
+  { 11,  "WKS" },
+  { 12,  "PTR" },
+  { 13,  "HINFO" },    
+  { 15,  "MX" },
+  { 16,  "TXT" },
+  { 22,  "NSAP" },
+  { 23,  "NSAP_PTR" },
+  { 24,  "SIG" },
+  { 25,  "KEY" },
+  { 28,  "AAAA" },
+  { 33,  "SRV" },
+  { 35,  "NAPTR" },
+  { 36,  "KX" },
+  { 37,  "CERT" },
+  { 38,  "A6" },
+  { 39,  "DNAME" },
+  { 41,  "OPT" },
+  { 48,  "DNSKEY" },
+  { 249, "TKEY" },
+  { 250, "TSIG" },
+  { 251, "IXFR" },
+  { 252, "AXFR" },
+  { 253, "MAILB" },
+  { 254, "MAILA" },
+  { 255, "ANY" }
+};
+
+static void cache_free(struct crec *crecp);
+static void cache_unlink(struct crec *crecp);
+static void cache_link(struct crec *crecp);
+static void rehash(int size);
+static void cache_hash(struct crec *crecp);
+
+void cache_init(void)
+{
+  struct crec *crecp;
+  int i;
+
+  if (option_bool(OPT_LOG))
+    addrbuff = safe_malloc(ADDRSTRLEN);
+  
+  bignames_left = daemon->cachesize/10;
+  
+  if (daemon->cachesize > 0)
+    {
+      crecp = safe_malloc(daemon->cachesize*sizeof(struct crec));
+      
+      for (i=0; i < daemon->cachesize; i++, crecp++)
+       {
+         cache_link(crecp);
+         crecp->flags = 0;
+         crecp->uid = uid++;
+       }
+    }
+  
+  /* create initial hash table*/
+  rehash(daemon->cachesize);
+}
+
+/* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
+   but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
+   will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
+   expand the table. */
+static void rehash(int size)
+{
+  struct crec **new, **old, *p, *tmp;
+  int i, new_size, old_size;
+
+  /* hash_size is a power of two. */
+  for (new_size = 64; new_size < size/10; new_size = new_size << 1);
+  
+  /* must succeed in getting first instance, failure later is non-fatal */
+  if (!hash_table)
+    new = safe_malloc(new_size * sizeof(struct crec *));
+  else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec *))))
+    return;
+
+  for(i = 0; i < new_size; i++)
+    new[i] = NULL;
+
+  old = hash_table;
+  old_size = hash_size;
+  hash_table = new;
+  hash_size = new_size;
+  
+  if (old)
+    {
+      for (i = 0; i < old_size; i++)
+       for (p = old[i]; p ; p = tmp)
+         {
+           tmp = p->hash_next;
+           cache_hash(p);
+         }
+      free(old);
+    }
+}
+  
+static struct crec **hash_bucket(char *name)
+{
+  unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */
+  const unsigned char *mix_tab = (const unsigned char*)typestr; 
+
+  while((c = (unsigned char) *name++))
+    {
+      /* don't use tolower and friends here - they may be messed up by LOCALE */
+      if (c >= 'A' && c <= 'Z')
+       c += 'a' - 'A';
+      val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c);
+    } 
+  
+  /* hash_size is a power of two */
+  return hash_table + ((val ^ (val >> 16)) & (hash_size - 1));
+}
+
+static void cache_hash(struct crec *crecp)
+{
+  /* maintain an invariant that all entries with F_REVERSE set
+     are at the start of the hash-chain  and all non-reverse
+     immortal entries are at the end of the hash-chain.
+     This allows reverse searches and garbage collection to be optimised */
+
+  struct crec **up = hash_bucket(cache_get_name(crecp));
+
+  if (!(crecp->flags & F_REVERSE))
+    {
+      while (*up && ((*up)->flags & F_REVERSE))
+       up = &((*up)->hash_next); 
+      
+      if (crecp->flags & F_IMMORTAL)
+       while (*up && !((*up)->flags & F_IMMORTAL))
+         up = &((*up)->hash_next);
+    }
+  crecp->hash_next = *up;
+  *up = crecp;
+}
+static void cache_free(struct crec *crecp)
+{
+  crecp->flags &= ~F_FORWARD;
+  crecp->flags &= ~F_REVERSE;
+  crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
+  
+  if (cache_tail)
+    cache_tail->next = crecp;
+  else
+    cache_head = crecp;
+  crecp->prev = cache_tail;
+  crecp->next = NULL;
+  cache_tail = crecp;
+  
+  /* retrieve big name for further use. */
+  if (crecp->flags & F_BIGNAME)
+    {
+      crecp->name.bname->next = big_free;
+      big_free = crecp->name.bname;
+      crecp->flags &= ~F_BIGNAME;
+    }
+}    
+
+/* insert a new cache entry at the head of the list (youngest entry) */
+static void cache_link(struct crec *crecp)
+{
+  if (cache_head) /* check needed for init code */
+    cache_head->prev = crecp;
+  crecp->next = cache_head;
+  crecp->prev = NULL;
+  cache_head = crecp;
+  if (!cache_tail)
+    cache_tail = crecp;
+}
+
+/* remove an arbitrary cache entry for promotion */ 
+static void cache_unlink (struct crec *crecp)
+{
+  if (crecp->prev)
+    crecp->prev->next = crecp->next;
+  else
+    cache_head = crecp->next;
+
+  if (crecp->next)
+    crecp->next->prev = crecp->prev;
+  else
+    cache_tail = crecp->prev;
+}
+
+char *cache_get_name(struct crec *crecp)
+{
+  if (crecp->flags & F_BIGNAME)
+    return crecp->name.bname->name;
+  else if (crecp->flags & F_NAMEP) 
+    return crecp->name.namep;
+  
+  return crecp->name.sname;
+}
+
+static int is_outdated_cname_pointer(struct crec *crecp)
+{
+  if (!(crecp->flags & F_CNAME))
+    return 0;
+  
+  if (crecp->addr.cname.cache && crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
+    return 0;
+  
+  return 1;
+}
+
+static int is_expired(time_t now, struct crec *crecp)
+{
+  if (crecp->flags & F_IMMORTAL)
+    return 0;
+
+  if (difftime(now, crecp->ttd) < 0)
+    return 0;
+  
+  return 1;
+}
+
+static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
+{
+  /* Scan and remove old entries.
+     If (flags & F_FORWARD) then remove any forward entries for name and any expired
+     entries but only in the same hash bucket as name.
+     If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
+     entries in the whole cache.
+     If (flags == 0) remove any expired entries in the whole cache. 
+
+     In the flags & F_FORWARD case, the return code is valid, and returns zero if the
+     name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
+
+     We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
+     so that when we hit an entry which isn't reverse and is immortal, we're done. */
+  struct crec *crecp, **up;
+  
+  if (flags & F_FORWARD)
+    {
+      for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
+       if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
+         { 
+           *up = crecp->hash_next;
+           if (!(crecp->flags & (F_HOSTS | F_DHCP)))
+             {
+               cache_unlink(crecp);
+               cache_free(crecp);
+             }
+         } 
+       else if ((crecp->flags & F_FORWARD) && 
+                ((flags & crecp->flags & (F_IPV4 | F_IPV6)) || ((crecp->flags | flags) & F_CNAME)) &&
+                hostname_isequal(cache_get_name(crecp), name))
+         {
+           if (crecp->flags & (F_HOSTS | F_DHCP))
+             return 0;
+           *up = crecp->hash_next;
+           cache_unlink(crecp);
+           cache_free(crecp);
+         }
+       else
+         up = &crecp->hash_next;
+    }
+  else
+    {
+      int i;
+#ifdef HAVE_IPV6
+      int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
+#else
+      int addrlen = INADDRSZ;
+#endif 
+      for (i = 0; i < hash_size; i++)
+       for (crecp = hash_table[i], up = &hash_table[i]; 
+            crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
+            crecp = crecp->hash_next)
+         if (is_expired(now, crecp))
+           {
+             *up = crecp->hash_next;
+             if (!(crecp->flags & (F_HOSTS | F_DHCP)))
+               { 
+                 cache_unlink(crecp);
+                 cache_free(crecp);
+               }
+           }
+         else if (!(crecp->flags & (F_HOSTS | F_DHCP)) &&
+                  (flags & crecp->flags & F_REVERSE) && 
+                  (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
+                  memcmp(&crecp->addr.addr, addr, addrlen) == 0)
+           {
+             *up = crecp->hash_next;
+             cache_unlink(crecp);
+             cache_free(crecp);
+           }
+         else
+           up = &crecp->hash_next;
+    }
+  
+  return 1;
+}
+
+/* Note: The normal calling sequence is
+   cache_start_insert
+   cache_insert * n
+   cache_end_insert
+
+   but an abort can cause the cache_end_insert to be missed 
+   in which can the next cache_start_insert cleans things up. */
+
+void cache_start_insert(void)
+{
+  /* Free any entries which didn't get committed during the last
+     insert due to error.
+  */
+  while (new_chain)
+    {
+      struct crec *tmp = new_chain->next;
+      cache_free(new_chain);
+      new_chain = tmp;
+    }
+  new_chain = NULL;
+  insert_error = 0;
+}
+struct crec *cache_insert(char *name, struct all_addr *addr, 
+                         time_t now,  unsigned long ttl, unsigned short flags)
+{
+  struct crec *new;
+  union bigname *big_name = NULL;
+  int freed_all = flags & F_REVERSE;
+  int free_avail = 0;
+
+  log_query(flags | F_UPSTREAM, name, addr, NULL);
+
+  /* if previous insertion failed give up now. */
+  if (insert_error)
+    return NULL;
+
+  /* First remove any expired entries and entries for the name/address we
+     are currently inserting. Fail is we attempt to delete a name from
+     /etc/hosts or DHCP. */
+  if (!cache_scan_free(name, addr, now, flags))
+    {
+      insert_error = 1;
+      return NULL;
+    }
+  
+  /* Now get a cache entry from the end of the LRU list */
+  while (1) {
+    if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
+      {
+       insert_error = 1;
+       return NULL;
+      }
+    
+    /* End of LRU list is still in use: if we didn't scan all the hash
+       chains for expired entries do that now. If we already tried that
+       then it's time to start spilling things. */
+    
+    if (new->flags & (F_FORWARD | F_REVERSE))
+      { 
+       /* If free_avail set, we believe that an entry has been freed.
+          Bugs have been known to make this not true, resulting in
+          a tight loop here. If that happens, abandon the
+          insert. Once in this state, all inserts will probably fail. */
+       if (free_avail)
+         {
+           insert_error = 1;
+           return NULL;
+         }
+               
+       if (freed_all)
+         {
+           free_avail = 1; /* Must be free space now. */
+           cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags);
+           cache_live_freed++;
+         }
+       else
+         {
+           cache_scan_free(NULL, NULL, now, 0);
+           freed_all = 1;
+         }
+       continue;
+      }
+    /* Check if we need to and can allocate extra memory for a long name.
+       If that fails, give up now. */
+    if (name && (strlen(name) > SMALLDNAME-1))
+      {
+       if (big_free)
+         { 
+           big_name = big_free;
+           big_free = big_free->next;
+         }
+       else if (!bignames_left ||
+                !(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
+         {
+           insert_error = 1;
+           return NULL;
+         }
+       else
+         bignames_left--;
+       
+      }
+
+    /* Got the rest: finally grab entry. */
+    cache_unlink(new);
+    break;
+  }
+  
+  new->flags = flags;
+  if (big_name)
+    {
+      new->name.bname = big_name;
+      new->flags |= F_BIGNAME;
+    }
+
+  if (name)
+    strcpy(cache_get_name(new), name);
+  else
+    *cache_get_name(new) = 0;
+
+  if (addr)
+    new->addr.addr = *addr;
+  else
+    new->addr.cname.cache = NULL;
+  
+  new->ttd = now + (time_t)ttl;
+  new->next = new_chain;
+  new_chain = new;
+
+  return new;
+}
+
+/* after end of insertion, commit the new entries */
+void cache_end_insert(void)
+{
+  if (insert_error)
+    return;
+  
+  while (new_chain)
+    { 
+      struct crec *tmp = new_chain->next;
+      /* drop CNAMEs which didn't find a target. */
+      if (is_outdated_cname_pointer(new_chain))
+       cache_free(new_chain);
+      else
+       {
+         cache_hash(new_chain);
+         cache_link(new_chain);
+         cache_inserted++;
+       }
+      new_chain = tmp;
+    }
+  new_chain = NULL;
+}
+
+struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned short prot)
+{
+  struct crec *ans;
+
+  if (crecp) /* iterating */
+    ans = crecp->next;
+  else
+    {
+      /* first search, look for relevant entries and push to top of list
+        also free anything which has expired */
+      struct crec *next, **up, **insert = NULL, **chainp = &ans;
+      unsigned short ins_flags = 0;
+      
+      for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
+       {
+         next = crecp->hash_next;
+         
+         if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
+           {
+             if ((crecp->flags & F_FORWARD) && 
+                 (crecp->flags & prot) &&
+                 hostname_isequal(cache_get_name(crecp), name))
+               {
+                 if (crecp->flags & (F_HOSTS | F_DHCP))
+                   {
+                     *chainp = crecp;
+                     chainp = &crecp->next;
+                   }
+                 else
+                   {
+                     cache_unlink(crecp);
+                     cache_link(crecp);
+                   }
+                     
+                 /* Move all but the first entry up the hash chain
+                    this implements round-robin. 
+                    Make sure that re-ordering doesn't break the hash-chain
+                    order invariants. 
+                 */
+                 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
+                   {
+                     *up = crecp->hash_next;
+                     crecp->hash_next = *insert;
+                     *insert = crecp;
+                     insert = &crecp->hash_next;
+                   }
+                 else
+                   {
+                     if (!insert)
+                       {
+                         insert = up;
+                         ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
+                       }
+                     up = &crecp->hash_next; 
+                   }
+               }
+             else
+               /* case : not expired, incorrect entry. */
+               up = &crecp->hash_next; 
+           }
+         else
+           {
+             /* expired entry, free it */
+             *up = crecp->hash_next;
+             if (!(crecp->flags & (F_HOSTS | F_DHCP)))
+               { 
+                 cache_unlink(crecp);
+                 cache_free(crecp);
+               }
+           }
+       }
+         
+      *chainp = cache_head;
+    }
+
+  if (ans && 
+      (ans->flags & F_FORWARD) &&
+      (ans->flags & prot) &&
+      hostname_isequal(cache_get_name(ans), name))
+    return ans;
+  
+  return NULL;
+}
+
+struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, 
+                               time_t now, unsigned short prot)
+{
+  struct crec *ans;
+#ifdef HAVE_IPV6
+  int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
+#else
+  int addrlen = INADDRSZ;
+#endif
+  
+  if (crecp) /* iterating */
+    ans = crecp->next;
+  else
+    {  
+      /* first search, look for relevant entries and push to top of list
+        also free anything which has expired. All the reverse entries are at the
+        start of the hash chain, so we can give up when we find the first 
+        non-REVERSE one.  */
+       int i;
+       struct crec **up, **chainp = &ans;
+       
+       for (i=0; i<hash_size; i++)
+        for (crecp = hash_table[i], up = &hash_table[i]; 
+             crecp && (crecp->flags & F_REVERSE);
+             crecp = crecp->hash_next)
+          if (!is_expired(now, crecp))
+            {      
+              if ((crecp->flags & prot) &&
+                  memcmp(&crecp->addr.addr, addr, addrlen) == 0)
+                {          
+                  if (crecp->flags & (F_HOSTS | F_DHCP))
+                    {
+                      *chainp = crecp;
+                      chainp = &crecp->next;
+                    }
+                  else
+                    {
+                      cache_unlink(crecp);
+                      cache_link(crecp);
+                    }
+                }
+              up = &crecp->hash_next;
+            }
+          else
+            {
+              *up = crecp->hash_next;
+              if (!(crecp->flags & (F_HOSTS | F_DHCP)))
+                {
+                  cache_unlink(crecp);
+                  cache_free(crecp);
+                }
+            }
+       
+       *chainp = cache_head;
+    }
+  
+  if (ans && 
+      (ans->flags & F_REVERSE) &&
+      (ans->flags & prot) &&
+      memcmp(&ans->addr.addr, addr, addrlen) == 0)
+    return ans;
+  
+  return NULL;
+}
+
+static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen, 
+                           unsigned short flags, int index, int addr_dup)
+{
+  struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6));
+  int i, nameexists = 0;
+  struct cname *a;
+
+  /* Remove duplicates in hosts files. */
+  if (lookup && (lookup->flags & F_HOSTS))
+    {
+      nameexists = 1;
+      if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
+       {
+         free(cache);
+         return;
+       }
+    }
+  
+  /* Ensure there is only one address -> name mapping (first one trumps) 
+     We do this by steam here, first we see if the address is the same as
+     the last one we saw, which eliminates most in the case of an ad-block 
+     file with thousands of entries for the same address.
+     Then we search and bail at the first matching address that came from
+     a HOSTS file. Since the first host entry gets reverse, we know 
+     then that it must exist without searching exhaustively for it. */
+  
+  if (addr_dup)
+    flags &= ~F_REVERSE;
+  else
+    for (i=0; i<hash_size; i++)
+      {
+       for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next)
+         if ((lookup->flags & F_HOSTS) && 
+             (lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
+             memcmp(&lookup->addr.addr, addr, addrlen) == 0)
+           {
+             flags &= ~F_REVERSE;
+             break;
+           }
+       if (lookup)
+         break;
+      }
+  
+  cache->flags = flags;
+  cache->uid = index;
+  memcpy(&cache->addr.addr, addr, addrlen);
+  cache_hash(cache);
+  
+  /* don't need to do alias stuff for second and subsequent addresses. */
+  if (!nameexists)
+    for (a = daemon->cnames; a; a = a->next)
+      if (hostname_isequal(cache->name.sname, a->target) &&
+         (lookup = whine_malloc(sizeof(struct crec))))
+       {
+         lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
+         lookup->name.namep = a->alias;
+         lookup->addr.cname.cache = cache;
+         lookup->addr.cname.uid = index;
+         cache_hash(lookup);
+       }
+}
+
+static int eatspace(FILE *f)
+{
+  int c, nl = 0;
+
+  while (1)
+    {
+      if ((c = getc(f)) == '#')
+       while (c != '\n' && c != EOF)
+         c = getc(f);
+      
+      if (c == EOF)
+       return 1;
+
+      if (!isspace(c))
+       {
+         ungetc(c, f);
+         return nl;
+       }
+
+      if (c == '\n')
+       nl = 1;
+    }
+}
+        
+static int gettok(FILE *f, char *token)
+{
+  int c, count = 0;
+  while (1)
+    {
+      if ((c = getc(f)) == EOF)
+       return (count == 0) ? EOF : 1;
+
+      if (isspace(c) || c == '#')
+       {
+         ungetc(c, f);
+         return eatspace(f);
+       }
+      
+      if (count < (MAXDNAME - 1))
+       {
+         token[count++] = c;
+         token[count] = 0;
+       }
+    }
+}
+
+static int read_hostsfile(char *filename, int index, int cache_size)
+{  
+  FILE *f = fopen(filename, "r");
+  char *token = daemon->namebuff, *domain_suffix = NULL;
+  int addr_count = 0, name_count = cache_size, lineno = 0;
+  unsigned short flags = 0, saved_flags = 0;
+  struct all_addr addr, saved_addr;
+  int atnl, addrlen = 0, addr_dup;
+
+  if (!f)
+    {
+      my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
+      return 0;
+    }
+  
+  eatspace(f);
+  
+  while ((atnl = gettok(f, token)) != EOF)
+    {
+      addr_dup = 0;
+      lineno++;
+      
+#ifdef HAVE_IPV6      
+      if (inet_pton(AF_INET, token, &addr) > 0)
+       {
+         flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
+         addrlen = INADDRSZ;
+         domain_suffix = get_domain(addr.addr.addr4);
+       }
+      else if (inet_pton(AF_INET6, token, &addr) > 0)
+       {
+         flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
+         addrlen = IN6ADDRSZ;
+         domain_suffix = daemon->domain_suffix;
+       }
+#else 
+      if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
+       {
+         flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
+         addrlen = INADDRSZ;
+         domain_suffix = get_domain(addr.addr.addr4);
+       }
+#endif
+      else
+       {
+         my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno); 
+         while (atnl == 0)
+           atnl = gettok(f, token);
+         continue;
+       }
+      
+      if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0)
+       addr_dup = 1;
+      else
+       {
+         saved_flags = flags;
+         saved_addr = addr;
+       }
+      
+      addr_count++;
+      
+      /* rehash every 1000 names. */
+      if ((name_count - cache_size) > 1000)
+       {
+         rehash(name_count);
+         cache_size = name_count;
+       } 
+      
+      while (atnl == 0)
+       {
+         struct crec *cache;
+         int fqdn, nomem;
+         char *canon;
+         
+         if ((atnl = gettok(f, token)) == EOF)
+           break;
+
+         fqdn = !!strchr(token, '.');
+
+         if ((canon = canonicalise(token, &nomem)))
+           {
+             /* If set, add a version of the name with a default domain appended */
+             if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn && 
+                 (cache = whine_malloc(sizeof(struct crec) + 
+                                       strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
+               {
+                 strcpy(cache->name.sname, canon);
+                 strcat(cache->name.sname, ".");
+                 strcat(cache->name.sname, domain_suffix);
+                 add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
+                 addr_dup = 1;
+                 name_count++;
+               }
+             if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
+               {
+                 strcpy(cache->name.sname, canon);
+                 add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
+                 name_count++;
+               }
+             free(canon);
+             
+           }
+         else if (!nomem)
+           my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno); 
+       }
+    } 
+
+  fclose(f);
+  rehash(name_count);
+  
+  my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
+  
+  return name_count;
+}
+           
+void cache_reload(void)
+{
+  struct crec *cache, **up, *tmp;
+  int i, total_size = daemon->cachesize;
+  struct hostsfile *ah;
+
+  cache_inserted = cache_live_freed = 0;
+  
+  for (i=0; i<hash_size; i++)
+    for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
+      {
+       tmp = cache->hash_next;
+       if (cache->flags & F_HOSTS)
+         {
+           *up = cache->hash_next;
+           free(cache);
+         }
+       else if (!(cache->flags & F_DHCP))
+         {
+           *up = cache->hash_next;
+           if (cache->flags & F_BIGNAME)
+             {
+               cache->name.bname->next = big_free;
+               big_free = cache->name.bname;
+             }
+           cache->flags = 0;
+         }
+       else
+         up = &cache->hash_next;
+      }
+  
+  if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
+    {
+      if (daemon->cachesize > 0)
+       my_syslog(LOG_INFO, _("cleared cache"));
+      return;
+    }
+
+  if (!option_bool(OPT_NO_HOSTS))
+    total_size = read_hostsfile(HOSTSFILE, 0, total_size);
+          
+  daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
+  for (ah = daemon->addn_hosts; ah; ah = ah->next)
+    if (!(ah->flags & AH_INACTIVE))
+      total_size = read_hostsfile(ah->fname, ah->index, total_size);
+} 
+
+char *get_domain(struct in_addr addr)
+{
+  struct cond_domain *c;
+
+  for (c = daemon->cond_domain; c; c = c->next)
+    if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
+        ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
+      return c->domain;
+
+  return daemon->domain_suffix;
+}
+
+#ifdef HAVE_DHCP
+void cache_unhash_dhcp(void)
+{
+  struct crec *cache, **up;
+  int i;
+
+  for (i=0; i<hash_size; i++)
+    for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
+      if (cache->flags & F_DHCP)
+       {
+         *up = cache->hash_next;
+         cache->next = dhcp_spare;
+         dhcp_spare = cache;
+       }
+      else
+       up = &cache->hash_next;
+}
+
+void cache_add_dhcp_entry(char *host_name, 
+                         struct in_addr *host_address, time_t ttd) 
+{
+  struct crec *crec = NULL, *aliasc;
+  unsigned short flags =  F_NAMEP | F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE;
+  int in_hosts = 0;
+  struct cname *a;
+  
+  while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME)))
+    {
+      /* check all addresses associated with name */
+      if (crec->flags & F_HOSTS)
+       {
+         /* if in hosts, don't need DHCP record */
+         in_hosts = 1;
+         
+         if (crec->flags & F_CNAME)
+           my_syslog(MS_DHCP | LOG_WARNING, 
+                     _("%s is a CNAME, not giving it to the DHCP lease of %s"),
+                     host_name, inet_ntoa(*host_address));
+         else if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
+           {
+             strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
+             my_syslog(MS_DHCP | LOG_WARNING, 
+                       _("not giving name %s to the DHCP lease of %s because "
+                         "the name exists in %s with address %s"), 
+                       host_name, inet_ntoa(*host_address),
+                       record_source(crec->uid), daemon->namebuff);
+           }     
+       }
+      else if (!(crec->flags & F_DHCP))
+       {
+         cache_scan_free(host_name, NULL, 0, crec->flags & (F_IPV4 | F_CNAME | F_FORWARD));
+         /* scan_free deletes all addresses associated with name */
+         break;
+       }
+    }
+  
+   if (in_hosts)
+    return;
+
+   if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, F_IPV4)))
+     {
+       if (crec->flags & F_NEG)
+        cache_scan_free(NULL, (struct all_addr *)host_address, 0, F_IPV4 | F_REVERSE);
+       else
+        /* avoid multiple reverse mappings */
+        flags &= ~F_REVERSE;
+     }
+   
+   if ((crec = dhcp_spare))
+    dhcp_spare = dhcp_spare->next;
+  else /* need new one */
+    crec = whine_malloc(sizeof(struct crec));
+  
+  if (crec) /* malloc may fail */
+    {
+      crec->flags = flags;
+      if (ttd == 0)
+       crec->flags |= F_IMMORTAL;
+      else
+       crec->ttd = ttd;
+      crec->addr.addr.addr.addr4 = *host_address;
+      crec->name.namep = host_name;
+      crec->uid = uid++;
+      cache_hash(crec);
+
+      for (a = daemon->cnames; a; a = a->next)
+       if (hostname_isequal(host_name, a->target))
+         {
+           if ((aliasc = dhcp_spare))
+             dhcp_spare = dhcp_spare->next;
+           else /* need new one */
+             aliasc = whine_malloc(sizeof(struct crec));
+           
+           if (aliasc)
+             {
+               aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
+               if (ttd == 0)
+                 aliasc->flags |= F_IMMORTAL;
+               else
+                 aliasc->ttd = ttd;
+               aliasc->name.namep = a->alias;
+               aliasc->addr.cname.cache = crec;
+               aliasc->addr.cname.uid = crec->uid;
+               cache_hash(aliasc);
+             }
+         }
+    }
+}
+#endif
+
+
+void dump_cache(time_t now)
+{
+  struct server *serv, *serv1;
+
+  my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
+  my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."), 
+           daemon->cachesize, cache_live_freed, cache_inserted);
+  my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"), 
+           daemon->queries_forwarded, daemon->local_answer);
+
+  if (!addrbuff && !(addrbuff = whine_malloc(ADDRSTRLEN)))
+    return;
+
+  /* sum counts from different records for same server */
+  for (serv = daemon->servers; serv; serv = serv->next)
+    serv->flags &= ~SERV_COUNTED;
+  
+  for (serv = daemon->servers; serv; serv = serv->next)
+    if (!(serv->flags & 
+         (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
+      {
+       int port;
+       unsigned int queries = 0, failed_queries = 0;
+       for (serv1 = serv; serv1; serv1 = serv1->next)
+         if (!(serv1->flags & 
+               (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) && 
+             sockaddr_isequal(&serv->addr, &serv1->addr))
+           {
+             serv1->flags |= SERV_COUNTED;
+             queries += serv1->queries;
+             failed_queries += serv1->failed_queries;
+           }
+       port = prettyprint_addr(&serv->addr, addrbuff);
+       my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), addrbuff, port, queries, failed_queries);
+      }
+  
+  if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
+    {
+      struct crec *cache ;
+      int i;
+      my_syslog(LOG_INFO, "Host                                     Address                        Flags     Expires");
+    
+      for (i=0; i<hash_size; i++)
+       for (cache = hash_table[i]; cache; cache = cache->hash_next)
+         {
+           char *a, *p = daemon->namebuff;
+           p += sprintf(p, "%-40.40s ", cache_get_name(cache));
+           if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD))
+             a = ""; 
+           else if (cache->flags & F_CNAME) 
+             {
+               a = "";
+               if (!is_outdated_cname_pointer(cache))
+                 a = cache_get_name(cache->addr.cname.cache);
+             }
+#ifdef HAVE_IPV6
+           else 
+             { 
+               a = addrbuff;
+               if (cache->flags & F_IPV4)
+                 inet_ntop(AF_INET, &cache->addr.addr, addrbuff, ADDRSTRLEN);
+               else if (cache->flags & F_IPV6)
+                 inet_ntop(AF_INET6, &cache->addr.addr, addrbuff, ADDRSTRLEN);
+             }
+#else
+            else 
+             a = inet_ntoa(cache->addr.addr.addr.addr4);
+#endif
+           p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s%s  ", a, 
+                        cache->flags & F_IPV4 ? "4" : "",
+                        cache->flags & F_IPV6 ? "6" : "",
+                        cache->flags & F_CNAME ? "C" : "",
+                        cache->flags & F_FORWARD ? "F" : " ",
+                        cache->flags & F_REVERSE ? "R" : " ",
+                        cache->flags & F_IMMORTAL ? "I" : " ",
+                        cache->flags & F_DHCP ? "D" : " ",
+                        cache->flags & F_NEG ? "N" : " ",
+                        cache->flags & F_NXDOMAIN ? "X" : " ",
+                        cache->flags & F_HOSTS ? "H" : " ");
+#ifdef HAVE_BROKEN_RTC
+           p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
+#else
+           p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
+           /* ctime includes trailing \n - eat it */
+           *(p-1) = 0;
+#endif
+           my_syslog(LOG_INFO, daemon->namebuff);
+         }
+    }
+}
+
+char *record_source(int index)
+{
+  struct hostsfile *ah;
+
+  if (index == 0)
+    return HOSTSFILE;
+
+  for (ah = daemon->addn_hosts; ah; ah = ah->next)
+    if (ah->index == index)
+      return ah->fname;
+  
+  return "<unknown>";
+}
+
+void querystr(char *str, unsigned short type)
+{
+  unsigned int i;
+  
+  sprintf(str, "query[type=%d]", type); 
+  for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
+    if (typestr[i].type == type)
+      sprintf(str,"query[%s]", typestr[i].name);
+}
+
+void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
+{
+  char *source, *dest = addrbuff;
+  char *verb = "is";
+  
+  if (!option_bool(OPT_LOG))
+    return;
+
+  if (addr)
+    {
+#ifdef HAVE_IPV6
+      inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
+               addr, addrbuff, ADDRSTRLEN);
+#else
+      strncpy(addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);  
+#endif
+    }
+
+  if (flags & F_REVERSE)
+    {
+      dest = name;
+      name = addrbuff;
+    }
+  
+  if (flags & F_NEG)
+    {
+      if (flags & F_NXDOMAIN)
+       {
+         if (flags & F_IPV4)
+           dest = "NXDOMAIN-IPv4";
+         else if (flags & F_IPV6)
+           dest = "NXDOMAIN-IPv6";
+         else
+           dest = "NXDOMAIN";
+       }
+      else
+       {      
+         if (flags & F_IPV4)
+           dest = "NODATA-IPv4";
+         else if (flags & F_IPV6)
+           dest = "NODATA-IPv6";
+         else
+           dest = "NODATA";
+       }
+    }
+  else if (flags & F_CNAME)
+    dest = "<CNAME>";
+  else if (flags & F_RRNAME)
+    dest = arg;
+    
+  if (flags & F_CONFIG)
+    source = "config";
+  else if (flags & F_DHCP)
+    source = "DHCP";
+  else if (flags & F_HOSTS)
+    source = arg;
+  else if (flags & F_UPSTREAM)
+    source = "reply";
+  else if (flags & F_SERVER)
+    {
+      source = "forwarded";
+      verb = "to";
+    }
+  else if (flags & F_QUERY)
+    {
+      source = arg;
+      verb = "from";
+    }
+  else
+    source = "cached";
+  
+  if (strlen(name) == 0)
+    name = ".";
+
+  my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
+}
+
diff --git a/src/config.h b/src/config.h
new file mode 100644 (file)
index 0000000..0039c3e
--- /dev/null
@@ -0,0 +1,280 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define VERSION "2.57"
+
+#define FTABSIZ 150 /* max number of outstanding requests (default) */
+#define MAX_PROCS 20 /* max no children for TCP requests */
+#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
+#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
+#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
+#define FORWARD_TEST 50 /* try all servers every 50 queries */
+#define FORWARD_TIME 20 /* or 20 seconds */
+#define RANDOM_SOCKS 64 /* max simultaneous random ports */
+#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
+#define CACHESIZ 150 /* default cache size */
+#define MAXLEASES 1000 /* maximum number of DHCP leases */
+#define PING_WAIT 3 /* wait for ping address-in-use test */
+#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
+#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
+#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
+#define SMALLDNAME 40 /* most domain names are smaller than this */
+#define HOSTSFILE "/etc/hosts"
+#define ETHERSFILE "/etc/ethers"
+#ifdef __uClinux__
+#  define RESOLVFILE "/etc/config/resolv.conf"
+#else
+#  define RESOLVFILE "/etc/resolv.conf"
+#endif
+#define RUNFILE "/var/run/dnsmasq.pid"
+
+#ifndef LEASEFILE
+#   if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
+#      define LEASEFILE "/var/db/dnsmasq.leases"
+#   elif defined(__sun__) || defined (__sun)
+#      define LEASEFILE "/var/cache/dnsmasq.leases"
+#   elif defined(__ANDROID__)
+#      define LEASEFILE "/data/misc/dhcp/dnsmasq.leases"
+#   else
+#      define LEASEFILE "/var/lib/misc/dnsmasq.leases"
+#   endif
+#endif
+
+#ifndef CONFFILE
+#   if defined(__FreeBSD__)
+#      define CONFFILE "/usr/local/etc/dnsmasq.conf"
+#   else
+#      define CONFFILE "/etc/dnsmasq.conf"
+#   endif
+#endif
+
+#define DEFLEASE 3600 /* default lease time, 1 hour */
+#define CHUSER "nobody"
+#define CHGRP "dip"
+#define NAMESERVER_PORT 53
+#define DHCP_SERVER_PORT 67
+#define DHCP_CLIENT_PORT 68
+#define DHCP_SERVER_ALTPORT 1067
+#define DHCP_CLIENT_ALTPORT 1068
+#define PXE_PORT 4011
+#define TFTP_PORT 69
+#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
+#define LOG_MAX 5 /* log-queue length */
+#define RANDFILE "/dev/urandom"
+#define DAD_WAIT 20 /* retry binding IPv6 sockets for this long */
+#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
+
+/* DBUS interface specifics */
+#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
+#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
+
+/* Follows system specific switches. If you run on a 
+   new system, you may want to edit these. 
+   May replace this with Autoconf one day. 
+
+HAVE_LINUX_NETWORK
+HAVE_BSD_NETWORK
+HAVE_SOLARIS_NETWORK
+   define exactly one of these to alter interaction with kernel networking.
+
+HAVE_BROKEN_RTC
+   define this on embedded systems which don't have an RTC
+   which keeps time over reboots. Causes dnsmasq to use uptime
+   for timing, and keep lease lengths rather than expiry times
+   in its leases file. This also make dnsmasq "flash disk friendly".
+   Normally, dnsmasq tries very hard to keep the on-disk leases file
+   up-to-date: rewriting it after every renewal.  When HAVE_BROKEN_RTC 
+   is in effect, the lease file is only written when a new lease is 
+   created, or an old one destroyed. (Because those are the only times 
+   it changes.) This vastly reduces the number of file writes, and makes
+   it viable to keep the lease file on a flash filesystem.
+   NOTE: when enabling or disabling this, be sure to delete any old
+   leases file, otherwise dnsmasq may get very confused.
+
+HAVE_TFTP
+   define this to get dnsmasq's built-in TFTP server.
+
+HAVE_DHCP
+   define this to get dnsmasq's DHCP server.
+
+HAVE_SCRIPT
+   define this to get the ability to call scripts on lease-change
+
+HAVE_GETOPT_LONG
+   define this if you have GNU libc or GNU getopt. 
+
+HAVE_ARC4RANDOM
+   define this if you have arc4random() to get better security from DNS spoofs
+   by using really random ids (OpenBSD) 
+
+HAVE_SOCKADDR_SA_LEN
+   define this if struct sockaddr has sa_len field (*BSD) 
+
+HAVE_DBUS
+   define this if you want to link against libdbus, and have dnsmasq
+   support some methods to allow (re)configuration of the upstream DNS 
+   servers via DBus.
+
+HAVE_IDN
+   define this if you want international domain name support.
+   NOTE: for backwards compatibility, IDN support is automatically 
+         included when internationalisation support is built, using the 
+        *-i18n makefile targets, even if HAVE_IDN is not explicitly set.
+
+NOTES:
+   For Linux you should define 
+      HAVE_LINUX_NETWORK
+      HAVE_GETOPT_LONG
+  you should NOT define 
+      HAVE_ARC4RANDOM
+      HAVE_SOCKADDR_SA_LEN
+
+   For *BSD systems you should define 
+     HAVE_BSD_NETWORK
+     HAVE_SOCKADDR_SA_LEN
+   and you MAY define  
+     HAVE_ARC4RANDOM - OpenBSD and FreeBSD and NetBSD version 2.0 or later
+     HAVE_GETOPT_LONG - NetBSD, later FreeBSD 
+                       (FreeBSD and OpenBSD only if you link GNU getopt) 
+
+*/
+
+/* platform independent options- uncomment to enable */
+#define HAVE_DHCP
+#define HAVE_TFTP
+#define HAVE_SCRIPT
+/* #define HAVE_BROKEN_RTC */
+#define HAVE_DBUS
+/* #define HAVE_IDN */
+
+/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */
+#ifdef NO_TFTP
+#undef HAVE_TFTP
+#endif
+
+/* Allow DHCP to be disabled with COPTS=-DNO_DHCP */
+#ifdef NO_DHCP
+#undef HAVE_DHCP
+#endif
+
+/* Allow scripts to be disabled with COPTS=-DNO_SCRIPT */
+#ifdef NO_SCRIPT
+#undef HAVE_SCRIPT
+#endif
+
+
+
+/* platform dependent options. */
+
+/* Must preceed __linux__ since uClinux defines __linux__ too. */
+#if defined(__uClinux__)
+#define HAVE_LINUX_NETWORK
+#define HAVE_GETOPT_LONG
+#undef HAVE_ARC4RANDOM
+#undef HAVE_SOCKADDR_SA_LEN
+/* Never use fork() on uClinux. Note that this is subtly different from the
+   --keep-in-foreground option, since it also  suppresses forking new 
+   processes for TCP connections and disables the call-a-script on leasechange
+   system. It's intended for use on MMU-less kernels. */
+#define NO_FORK
+
+#elif defined(__UCLIBC__)
+#define HAVE_LINUX_NETWORK
+#if defined(__UCLIBC_HAS_GNU_GETOPT__) || \
+   ((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
+#    define HAVE_GETOPT_LONG
+#endif
+#undef HAVE_ARC4RANDOM
+#undef HAVE_SOCKADDR_SA_LEN
+#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
+#  define NO_FORK
+#endif
+#if defined(__UCLIBC_HAS_IPV6__)
+#  ifndef IPV6_V6ONLY
+#    define IPV6_V6ONLY 26
+#  endif
+#endif
+
+/* This is for glibc 2.x */
+#elif defined(__linux__)
+#define HAVE_LINUX_NETWORK
+#define HAVE_GETOPT_LONG
+#undef HAVE_ARC4RANDOM
+#undef HAVE_SOCKADDR_SA_LEN
+
+#elif defined(__FreeBSD__) || \
+      defined(__OpenBSD__) || \
+      defined(__DragonFly__) || \
+      defined(__FreeBSD_kernel__)
+#define HAVE_BSD_NETWORK
+/* Later verions of FreeBSD have getopt_long() */
+#if defined(optional_argument) && defined(required_argument)
+#   define HAVE_GETOPT_LONG
+#endif
+#if !defined(__FreeBSD_kernel__)
+#   define HAVE_ARC4RANDOM
+#endif
+#define HAVE_SOCKADDR_SA_LEN
+
+#elif defined(__APPLE__)
+#define HAVE_BSD_NETWORK
+#define HAVE_GETOPT_LONG
+#define HAVE_ARC4RANDOM
+#define HAVE_SOCKADDR_SA_LEN
+/* Define before sys/socket.h is included so we get socklen_t */
+#define _BSD_SOCKLEN_T_
+#elif defined(__NetBSD__)
+#define HAVE_BSD_NETWORK
+#define HAVE_GETOPT_LONG
+#undef HAVE_ARC4RANDOM
+#define HAVE_SOCKADDR_SA_LEN
+
+#elif defined(__sun) || defined(__sun__)
+#define HAVE_SOLARIS_NETWORK
+#define HAVE_GETOPT_LONG
+#undef HAVE_ARC4RANDOM
+#undef HAVE_SOCKADDR_SA_LEN
+#define ETHER_ADDR_LEN 6 
+#endif
+
+/* Decide if we're going to support IPv6 */
+/* IPv6 can be forced off with "make COPTS=-DNO_IPV6" */
+/* We assume that systems which don't have IPv6
+   headers don't have ntop and pton either */
+
+#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) && !defined(NO_IPV6)
+#  define HAVE_IPV6
+#  define ADDRSTRLEN INET6_ADDRSTRLEN
+#  if defined(SOL_IPV6)
+#    define IPV6_LEVEL SOL_IPV6
+#  else
+#    define IPV6_LEVEL IPPROTO_IPV6
+#  endif
+#elif defined(INET_ADDRSTRLEN)
+#  undef HAVE_IPV6
+#  define ADDRSTRLEN INET_ADDRSTRLEN
+#else
+#  undef HAVE_IPV6
+#  define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
+#endif
+
+/* Can't do scripts without fork */
+#ifdef NOFORK
+#  undef HAVE_SCRIPT
+#endif
+
diff --git a/src/dbus.c b/src/dbus.c
new file mode 100644 (file)
index 0000000..5cb43fb
--- /dev/null
@@ -0,0 +1,440 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_DBUS
+
+#include <dbus/dbus.h>
+
+const char* introspection_xml =
+"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
+"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
+"<node name=\"" DNSMASQ_PATH "\">\n"
+"  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+"    <method name=\"Introspect\">\n"
+"      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
+"    </method>\n"
+"  </interface>\n"
+"  <interface name=\"" DNSMASQ_SERVICE "\">\n"
+"    <method name=\"ClearCache\">\n"
+"    </method>\n"
+"    <method name=\"GetVersion\">\n"
+"      <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
+"    </method>\n"
+"    <method name=\"SetServers\">\n"
+"      <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
+"    </method>\n"
+"    <signal name=\"DhcpLeaseAdded\">\n"
+"      <arg name=\"ipaddr\" type=\"s\"/>\n"
+"      <arg name=\"hwaddr\" type=\"s\"/>\n"
+"      <arg name=\"hostname\" type=\"s\"/>\n"
+"    </signal>\n"
+"    <signal name=\"DhcpLeaseDeleted\">\n"
+"      <arg name=\"ipaddr\" type=\"s\"/>\n"
+"      <arg name=\"hwaddr\" type=\"s\"/>\n"
+"      <arg name=\"hostname\" type=\"s\"/>\n"
+"    </signal>\n"
+"    <signal name=\"DhcpLeaseUpdated\">\n"
+"      <arg name=\"ipaddr\" type=\"s\"/>\n"
+"      <arg name=\"hwaddr\" type=\"s\"/>\n"
+"      <arg name=\"hostname\" type=\"s\"/>\n"
+"    </signal>\n"
+"  </interface>\n"
+"</node>\n";
+
+struct watch {
+  DBusWatch *watch;      
+  struct watch *next;
+};
+
+
+static dbus_bool_t add_watch(DBusWatch *watch, void *data)
+{
+  struct watch *w;
+
+  for (w = daemon->watches; w; w = w->next)
+    if (w->watch == watch)
+      return TRUE;
+
+  if (!(w = whine_malloc(sizeof(struct watch))))
+    return FALSE;
+
+  w->watch = watch;
+  w->next = daemon->watches;
+  daemon->watches = w;
+
+  w = data; /* no warning */
+  return TRUE;
+}
+
+static void remove_watch(DBusWatch *watch, void *data)
+{
+  struct watch **up, *w;  
+  
+  for (up = &(daemon->watches), w = daemon->watches; w; w = w->next)
+    if (w->watch == watch)
+      {
+        *up = w->next;
+        free(w);
+      }
+    else
+      up = &(w->next);
+
+  w = data; /* no warning */
+}
+
+static void dbus_read_servers(DBusMessage *message)
+{
+  struct server *serv, *tmp, **up;
+  DBusMessageIter iter;
+  union  mysockaddr addr, source_addr;
+  char *domain;
+  
+  dbus_message_iter_init(message, &iter);
+  
+  /* mark everything from DBUS */
+  for (serv = daemon->servers; serv; serv = serv->next)
+    if (serv->flags & SERV_FROM_DBUS)
+      serv->flags |= SERV_MARK;
+  
+  while (1)
+    {
+      int skip = 0;
+
+      if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32)
+       {
+         u32 a;
+         
+         dbus_message_iter_get_basic(&iter, &a);
+         dbus_message_iter_next (&iter);
+         
+#ifdef HAVE_SOCKADDR_SA_LEN
+         source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
+#endif
+         addr.in.sin_addr.s_addr = ntohl(a);
+         source_addr.in.sin_family = addr.in.sin_family = AF_INET;
+         addr.in.sin_port = htons(NAMESERVER_PORT);
+         source_addr.in.sin_addr.s_addr = INADDR_ANY;
+         source_addr.in.sin_port = htons(daemon->query_port);
+       }
+      else if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_BYTE)
+       {
+         unsigned char p[sizeof(struct in6_addr)];
+         unsigned int i;
+
+         skip = 1;
+
+         for(i = 0; i < sizeof(struct in6_addr); i++)
+           {
+             dbus_message_iter_get_basic(&iter, &p[i]);
+             dbus_message_iter_next (&iter);
+             if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
+               break;
+           }
+
+#ifndef HAVE_IPV6
+         my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
+#else
+         if (i == sizeof(struct in6_addr)-1)
+           {
+             memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
+#ifdef HAVE_SOCKADDR_SA_LEN
+              source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+              source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
+              addr.in6.sin6_port = htons(NAMESERVER_PORT);
+              source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
+             source_addr.in6.sin6_scope_id = addr.in6.sin6_scope_id = 0;
+              source_addr.in6.sin6_addr = in6addr_any;
+              source_addr.in6.sin6_port = htons(daemon->query_port);
+             skip = 0;
+           }
+#endif
+       }
+      else
+       /* At the end */
+       break;
+      
+      do {
+       if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
+         {
+           dbus_message_iter_get_basic(&iter, &domain);
+           dbus_message_iter_next (&iter);
+         }
+       else
+         domain = NULL;
+       
+       if (!skip)
+         {
+           /* See if this is already there, and unmark */
+           for (serv = daemon->servers; serv; serv = serv->next)
+             if ((serv->flags & SERV_FROM_DBUS) &&
+                 (serv->flags & SERV_MARK))
+               {
+                 if (!(serv->flags & SERV_HAS_DOMAIN) && !domain)
+                   {
+                     serv->flags &= ~SERV_MARK;
+                     break;
+                   }
+                 if ((serv->flags & SERV_HAS_DOMAIN) && 
+                     domain &&
+                     hostname_isequal(domain, serv->domain))
+                   {
+                     serv->flags &= ~SERV_MARK;
+                     break;
+                   }
+               }
+           
+           if (!serv && (serv = whine_malloc(sizeof (struct server))))
+             {
+               /* Not found, create a new one. */
+               memset(serv, 0, sizeof(struct server));
+               
+               if (domain)
+                 serv->domain = whine_malloc(strlen(domain)+1);
+               
+               if (domain && !serv->domain)
+                 {
+                   free(serv);
+                   serv = NULL;
+                 }
+               else
+                 {
+                   serv->next = daemon->servers;
+                   daemon->servers = serv;
+                   serv->flags = SERV_FROM_DBUS;
+                   if (domain)
+                     {
+                       strcpy(serv->domain, domain);
+                       serv->flags |= SERV_HAS_DOMAIN;
+                     }
+                 }
+             }
+
+           if (serv)
+             {
+               if (source_addr.in.sin_family == AF_INET &&
+                   addr.in.sin_addr.s_addr == 0 &&
+                   serv->domain)
+                 serv->flags |= SERV_NO_ADDR;
+               else
+                 {
+                   serv->flags &= ~SERV_NO_ADDR;
+                   serv->addr = addr;
+                   serv->source_addr = source_addr;
+                 }
+             }
+         }
+       } while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
+    }
+  
+  /* unlink and free anything still marked. */
+  for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) 
+    {
+      tmp = serv->next;
+      if (serv->flags & SERV_MARK)
+       {
+         server_gone(serv);
+         *up = serv->next;
+         free(serv);
+       }
+      else 
+       up = &serv->next;
+    }
+
+}
+
+DBusHandlerResult message_handler(DBusConnection *connection, 
+                                 DBusMessage *message, 
+                                 void *user_data)
+{
+  char *method = (char *)dbus_message_get_member(message);
+   
+  if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
+    {
+      DBusMessage *reply = dbus_message_new_method_return(message);
+
+      dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
+      dbus_connection_send (connection, reply, NULL);
+      dbus_message_unref (reply);
+    }
+  else if (strcmp(method, "GetVersion") == 0)
+    {
+      char *v = VERSION;
+      DBusMessage *reply = dbus_message_new_method_return(message);
+      
+      dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
+      dbus_connection_send (connection, reply, NULL);
+      dbus_message_unref (reply);
+    }
+  else if (strcmp(method, "SetServers") == 0)
+    {
+      my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
+      dbus_read_servers(message);
+      check_servers();
+    }
+  else if (strcmp(method, "ClearCache") == 0)
+    clear_cache_and_reload(dnsmasq_time());
+  else
+    return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+  
+  method = user_data; /* no warning */
+
+  return (DBUS_HANDLER_RESULT_HANDLED);
+}
+
+/* returns NULL or error message, may fail silently if dbus daemon not yet up. */
+char *dbus_init(void)
+{
+  DBusConnection *connection = NULL;
+  DBusObjectPathVTable dnsmasq_vtable = {NULL, &message_handler, NULL, NULL, NULL, NULL };
+  DBusError dbus_error;
+  DBusMessage *message;
+
+  dbus_error_init (&dbus_error);
+  if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
+    return NULL;
+    
+  dbus_connection_set_exit_on_disconnect(connection, FALSE);
+  dbus_connection_set_watch_functions(connection, add_watch, remove_watch, 
+                                     NULL, NULL, NULL);
+  dbus_error_init (&dbus_error);
+  dbus_bus_request_name (connection, DNSMASQ_SERVICE, 0, &dbus_error);
+  if (dbus_error_is_set (&dbus_error))
+    return (char *)dbus_error.message;
+  
+  if (!dbus_connection_register_object_path(connection,  DNSMASQ_PATH, 
+                                           &dnsmasq_vtable, NULL))
+    return _("could not register a DBus message handler");
+  
+  daemon->dbus = connection; 
+  
+  if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up")))
+    {
+      dbus_connection_send(connection, message, NULL);
+      dbus_message_unref(message);
+    }
+
+  return NULL;
+}
+
+void set_dbus_listeners(int *maxfdp,
+                       fd_set *rset, fd_set *wset, fd_set *eset)
+{
+  struct watch *w;
+  
+  for (w = daemon->watches; w; w = w->next)
+    if (dbus_watch_get_enabled(w->watch))
+      {
+       unsigned int flags = dbus_watch_get_flags(w->watch);
+       int fd = dbus_watch_get_unix_fd(w->watch);
+       
+       bump_maxfd(fd, maxfdp);
+       
+       if (flags & DBUS_WATCH_READABLE)
+         FD_SET(fd, rset);
+       
+       if (flags & DBUS_WATCH_WRITABLE)
+         FD_SET(fd, wset);
+       
+       FD_SET(fd, eset);
+      }
+}
+
+void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
+{
+  DBusConnection *connection = (DBusConnection *)daemon->dbus;
+  struct watch *w;
+
+  for (w = daemon->watches; w; w = w->next)
+    if (dbus_watch_get_enabled(w->watch))
+      {
+       unsigned int flags = 0;
+       int fd = dbus_watch_get_unix_fd(w->watch);
+       
+       if (FD_ISSET(fd, rset))
+         flags |= DBUS_WATCH_READABLE;
+       
+       if (FD_ISSET(fd, wset))
+         flags |= DBUS_WATCH_WRITABLE;
+       
+       if (FD_ISSET(fd, eset))
+         flags |= DBUS_WATCH_ERROR;
+
+       if (flags != 0)
+         dbus_watch_handle(w->watch, flags);
+      }
+
+  if (connection)
+    {
+      dbus_connection_ref (connection);
+      while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS);
+      dbus_connection_unref (connection);
+    }
+}
+
+#ifdef HAVE_DHCP
+void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
+{
+  DBusConnection *connection = (DBusConnection *)daemon->dbus;
+  DBusMessage* message = NULL;
+  DBusMessageIter args;
+  char *action_str, *addr, *mac = daemon->namebuff;
+  unsigned char *p;
+  int i;
+
+  if (!connection)
+    return;
+  
+  if (!hostname)
+    hostname = "";
+  
+  p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
+                     lease->hwaddr, lease->clid_len, lease->clid, &i);
+  print_mac(mac, p, i);
+  
+  if (action == ACTION_DEL)
+    action_str = "DhcpLeaseDeleted";
+  else if (action == ACTION_ADD)
+    action_str = "DhcpLeaseAdded";
+  else if (action == ACTION_OLD)
+    action_str = "DhcpLeaseUpdated";
+  else if (action == ACTION_CONNECT)
+    action_str = "DhcpConnected";
+  else
+    return;
+
+  addr = inet_ntoa(lease->addr);
+
+  if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
+    return;
+  
+  dbus_message_iter_init_append(message, &args);
+
+  if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &addr) &&
+      dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &mac) &&
+      dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &hostname))
+    dbus_connection_send(connection, message, NULL);
+  
+  dbus_message_unref(message);
+}
+#endif
+
+#endif
diff --git a/src/dhcp.c b/src/dhcp.c
new file mode 100644 (file)
index 0000000..29ddf24
--- /dev/null
@@ -0,0 +1,1094 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_DHCP
+
+struct iface_param {
+  struct in_addr relay, primary;
+  struct dhcp_context *current;
+  int ind;
+};
+
+static int complete_context(struct in_addr local, int if_index, 
+                           struct in_addr netmask, struct in_addr broadcast, void *vparam);
+
+static int make_fd(int port)
+{
+  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  struct sockaddr_in saddr;
+  int oneopt = 1;
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+  int mtu = IP_PMTUDISC_DONT;
+#endif
+
+  if (fd == -1)
+    die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
+  
+  if (!fix_fd(fd) ||
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+      setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 ||
+#endif
+#if defined(HAVE_LINUX_NETWORK)
+      setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
+#else
+      setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
+#endif
+      setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)  
+    die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
+  
+  /* When bind-interfaces is set, there might be more than one dnmsasq
+     instance binding port 67. That's OK if they serve different networks.
+     Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
+  if (option_bool(OPT_NOWILD))
+    {
+#ifdef SO_REUSEPORT
+      int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
+#else
+      int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
+#endif
+      if (rc == -1)
+       die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
+    }
+  
+  memset(&saddr, 0, sizeof(saddr));
+  saddr.sin_family = AF_INET;
+  saddr.sin_port = htons(port);
+  saddr.sin_addr.s_addr = INADDR_ANY;
+#ifdef HAVE_SOCKADDR_SA_LEN
+  saddr.sin_len = sizeof(struct sockaddr_in);
+#endif
+
+  if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
+    die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);
+
+  return fd;
+}
+
+void dhcp_init(void)
+{
+#if defined(HAVE_BSD_NETWORK)
+  int oneopt = 1;
+#endif
+
+  daemon->dhcpfd = make_fd(daemon->dhcp_server_port);
+  if (daemon->enable_pxe)
+    daemon->pxefd = make_fd(PXE_PORT);
+  else
+    daemon->pxefd = -1;
+
+#if defined(HAVE_BSD_NETWORK)
+  /* When we're not using capabilities, we need to do this here before
+     we drop root. Also, set buffer size small, to avoid wasting
+     kernel buffers */
+  
+  if (option_bool(OPT_NO_PING))
+    daemon->dhcp_icmp_fd = -1;
+  else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
+          setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
+    die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET);
+  
+  /* Make BPF raw send socket */
+  init_bpf();
+#endif
+  
+  check_dhcp_hosts(1);
+    
+  daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet); 
+  daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
+}
+  
+void dhcp_packet(time_t now, int pxe_fd)
+{
+  int fd = pxe_fd ? daemon->pxefd : daemon->dhcpfd;
+  struct dhcp_packet *mess;
+  struct dhcp_context *context;
+  struct iname *tmp;
+  struct ifreq ifr;
+  struct msghdr msg;
+  struct sockaddr_in dest;
+  struct cmsghdr *cmptr;
+  struct iovec iov;
+  ssize_t sz; 
+  int iface_index = 0, unicast_dest = 0, is_inform = 0;
+  struct in_addr iface_addr, *addrp = NULL;
+  struct iface_param parm;
+#ifdef HAVE_LINUX_NETWORK
+  struct arpreq arp_req;
+#endif
+  
+  union {
+    struct cmsghdr align; /* this ensures alignment */
+#if defined(HAVE_LINUX_NETWORK)
+    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
+#elif defined(HAVE_SOLARIS_NETWORK)
+    char control[CMSG_SPACE(sizeof(unsigned int))];
+#elif defined(HAVE_BSD_NETWORK) 
+    char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
+#endif
+  } control_u;
+  
+  msg.msg_control = NULL;
+  msg.msg_controllen = 0;
+  msg.msg_name = NULL;
+  msg.msg_namelen = 0;
+  msg.msg_iov = &daemon->dhcp_packet;
+  msg.msg_iovlen = 1;
+  
+  while (1)
+    {
+      msg.msg_flags = 0;
+      while ((sz = recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
+      
+      if (sz == -1)
+       return;
+      
+      if (!(msg.msg_flags & MSG_TRUNC))
+       break;
+
+      /* Very new Linux kernels return the actual size needed, 
+        older ones always return truncated size */
+      if ((size_t)sz == daemon->dhcp_packet.iov_len)
+       {
+         if (!expand_buf(&daemon->dhcp_packet, sz + 100))
+           return;
+       }
+      else
+       {
+         expand_buf(&daemon->dhcp_packet, sz);
+         break;
+       }
+    }
+  
+  /* expand_buf may have moved buffer */
+  mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
+  msg.msg_controllen = sizeof(control_u);
+  msg.msg_control = control_u.control;
+  msg.msg_flags = 0;
+  msg.msg_name = &dest;
+  msg.msg_namelen = sizeof(dest);
+
+  while ((sz = recvmsg(fd, &msg, 0)) == -1 && errno == EINTR);
+  if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
+    return;
+  
+#if defined (HAVE_LINUX_NETWORK)
+  if (msg.msg_controllen >= sizeof(struct cmsghdr))
+    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+      if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
+       {
+         union {
+           unsigned char *c;
+           struct in_pktinfo *p;
+         } p;
+         p.c = CMSG_DATA(cmptr);
+         iface_index = p.p->ipi_ifindex;
+         if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
+           unicast_dest = 1;
+       }
+
+#elif defined(HAVE_BSD_NETWORK) 
+  if (msg.msg_controllen >= sizeof(struct cmsghdr))
+    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+      if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+        {
+         union {
+            unsigned char *c;
+            struct sockaddr_dl *s;
+          } p;
+         p.c = CMSG_DATA(cmptr);
+         iface_index = p.s->sdl_index;
+       }
+  
+#elif defined(HAVE_SOLARIS_NETWORK) 
+  if (msg.msg_controllen >= sizeof(struct cmsghdr))
+    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+      if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+       {
+         union {
+           unsigned char *c;
+           unsigned int *i;
+         } p;
+         p.c = CMSG_DATA(cmptr);
+         iface_index = *(p.i);
+       }
+#endif
+       
+  if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
+    return;
+
+#ifdef HAVE_LINUX_NETWORK
+  /* ARP fiddling uses original interface even if we pretend to use a different one. */
+  strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
+#endif 
+
+#ifdef MSG_BCAST
+  /* OpenBSD tells us when a packet was broadcast */
+  if (!(msg.msg_flags & MSG_BCAST))
+    unicast_dest = 1;
+#endif
+
+  ifr.ifr_addr.sa_family = AF_INET;
+  if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
+    {
+      addrp = &iface_addr;
+      iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+    }
+
+  if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index))
+    return;
+  
+  for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+    if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
+      return;
+
+  /* weird libvirt-inspired access control */
+  for (context = daemon->dhcp; context; context = context->next)
+    if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
+      break;
+
+  if (!context)
+    return;
+  
+  /* unlinked contexts are marked by context->current == context */
+  for (context = daemon->dhcp; context; context = context->next)
+    context->current = context;
+  
+  parm.relay = mess->giaddr;
+  parm.primary = iface_addr;
+  parm.current = NULL;
+  parm.ind = iface_index;
+
+    /* interface may have been changed by alias in iface_check, make sure it gets priority in case
+       there is more than one address on the interface in the same subnet */
+  if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
+    {
+      my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
+      return;
+    }
+  else
+    {
+      iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+      if (ioctl(daemon->dhcpfd, SIOCGIFNETMASK, &ifr) != -1)
+       {
+         struct in_addr netmask =  ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+         if (ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) != -1)
+           {
+             struct in_addr broadcast =  ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+             complete_context(iface_addr, iface_index, netmask, broadcast, &parm);
+           }
+       }
+    } 
+
+  if (!iface_enumerate(AF_INET, &parm, complete_context))
+    return;
+  lease_prune(NULL, now); /* lose any expired leases */
+  iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, 
+                          now, unicast_dest, &is_inform, pxe_fd);
+  lease_update_file(now);
+  lease_update_dns();
+    
+  if (iov.iov_len == 0)
+    return;
+  
+  msg.msg_name = &dest;
+  msg.msg_namelen = sizeof(dest);
+  msg.msg_control = NULL;
+  msg.msg_controllen = 0;
+  msg.msg_iov = &iov;
+  iov.iov_base = daemon->dhcp_packet.iov_base;
+  
+  /* packet buffer may have moved */
+  mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
+  
+#ifdef HAVE_SOCKADDR_SA_LEN
+  dest.sin_len = sizeof(struct sockaddr_in);
+#endif
+     
+  if (pxe_fd)
+    { 
+      if (mess->ciaddr.s_addr != 0)
+       dest.sin_addr = mess->ciaddr;
+    }
+  else if (mess->giaddr.s_addr)
+    {
+      /* Send to BOOTP relay  */
+      dest.sin_port = htons(daemon->dhcp_server_port);
+      dest.sin_addr = mess->giaddr; 
+    }
+  else if (mess->ciaddr.s_addr)
+    {
+      /* If the client's idea of its own address tallys with
+        the source address in the request packet, we believe the
+        source port too, and send back to that.  If we're replying 
+        to a DHCPINFORM, trust the source address always. */
+      if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
+         dest.sin_port == 0 || dest.sin_addr.s_addr == 0)
+       {
+         dest.sin_port = htons(daemon->dhcp_client_port); 
+         dest.sin_addr = mess->ciaddr;
+       }
+    } 
+#if defined(HAVE_LINUX_NETWORK)
+  else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
+          mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
+    {
+      /* broadcast to 255.255.255.255 (or mac address invalid) */
+      struct in_pktinfo *pkt;
+      msg.msg_control = control_u.control;
+      msg.msg_controllen = sizeof(control_u);
+      cmptr = CMSG_FIRSTHDR(&msg);
+      pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
+      pkt->ipi_ifindex = iface_index;
+      pkt->ipi_spec_dst.s_addr = 0;
+      msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+      cmptr->cmsg_level = SOL_IP;
+      cmptr->cmsg_type = IP_PKTINFO;  
+      dest.sin_addr.s_addr = INADDR_BROADCAST;
+      dest.sin_port = htons(daemon->dhcp_client_port);
+    }
+  else
+    {
+      /* unicast to unconfigured client. Inject mac address direct into ARP cache. 
+        struct sockaddr limits size to 14 bytes. */
+      dest.sin_addr = mess->yiaddr;
+      dest.sin_port = htons(daemon->dhcp_client_port);
+      memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
+      arp_req.arp_ha.sa_family = mess->htype;
+      memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
+      /* interface name already copied in */
+      arp_req.arp_flags = ATF_COM;
+      ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
+    }
+#elif defined(HAVE_SOLARIS_NETWORK)
+  else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
+    {
+      /* broadcast to 255.255.255.255 (or mac address invalid) */
+      dest.sin_addr.s_addr = INADDR_BROADCAST;
+      dest.sin_port = htons(daemon->dhcp_client_port);
+      /* note that we don't specify the interface here: that's done by the
+        IP_BOUND_IF sockopt lower down. */
+    }
+  else
+    {
+      /* unicast to unconfigured client. Inject mac address direct into ARP cache. 
+        Note that this only works for ethernet on solaris, because we use SIOCSARP
+        and not SIOCSXARP, which would be perfect, except that it returns ENXIO 
+        mysteriously. Bah. Fall back to broadcast for other net types. */
+      struct arpreq req;
+      dest.sin_addr = mess->yiaddr;
+      dest.sin_port = htons(daemon->dhcp_client_port);
+      *((struct sockaddr_in *)&req.arp_pa) = dest;
+      req.arp_ha.sa_family = AF_UNSPEC;
+      memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
+      req.arp_flags = ATF_COM;
+      ioctl(daemon->dhcpfd, SIOCSARP, &req);
+    }
+#elif defined(HAVE_BSD_NETWORK)
+  else 
+    {
+      send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
+      return;
+    }
+#endif
+   
+#ifdef HAVE_SOLARIS_NETWORK
+  setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
+#endif
+  
+  while(sendmsg(fd, &msg, 0) == -1 && retry_send());
+}
+/* This is a complex routine: it gets called with each (address,netmask,broadcast) triple 
+   of each interface (and any relay address) and does the  following things:
+
+   1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
+   2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
+   3) Fills in local (this host) and router (this host or relay) addresses.
+   4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
+
+   Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
+
+static int complete_context(struct in_addr local, int if_index, 
+                           struct in_addr netmask, struct in_addr broadcast, void *vparam)
+{
+  struct dhcp_context *context;
+  struct iface_param *param = vparam;
+  
+  for (context = daemon->dhcp; context; context = context->next)
+    {
+      if (!(context->flags & CONTEXT_NETMASK) &&
+         (is_same_net(local, context->start, netmask) ||
+          is_same_net(local, context->end, netmask)))
+      { 
+       if (context->netmask.s_addr != netmask.s_addr &&
+           !(is_same_net(local, context->start, netmask) &&
+             is_same_net(local, context->end, netmask)))
+         {
+           strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
+           strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
+           my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
+                     daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
+         }     
+       context->netmask = netmask;
+      }
+      
+      if (context->netmask.s_addr)
+       {
+         if (is_same_net(local, context->start, context->netmask) &&
+             is_same_net(local, context->end, context->netmask))
+           {
+             /* link it onto the current chain if we've not seen it before */
+             if (if_index == param->ind && context->current == context)
+               {
+                 context->router = local;
+                 context->local = local;
+                 context->current = param->current;
+                 param->current = context;
+               }
+             
+             if (!(context->flags & CONTEXT_BRDCAST))
+               {
+                 if (is_same_net(broadcast, context->start, context->netmask))
+                   context->broadcast = broadcast;
+                 else 
+                   context->broadcast.s_addr  = context->start.s_addr | ~context->netmask.s_addr;
+               }
+           }   
+         else if (param->relay.s_addr && is_same_net(param->relay, context->start, context->netmask))
+           {
+             context->router = param->relay;
+             context->local = param->primary;
+             /* fill in missing broadcast addresses for relayed ranges */
+             if (!(context->flags & CONTEXT_BRDCAST))
+               context->broadcast.s_addr  = context->start.s_addr | ~context->netmask.s_addr;
+           }
+
+       }
+    }
+
+  return 1;
+}
+         
+struct dhcp_context *address_available(struct dhcp_context *context, 
+                                      struct in_addr taddr,
+                                      struct dhcp_netid *netids)
+{
+  /* Check is an address is OK for this network, check all
+     possible ranges. Make sure that the address isn't in use
+     by the server itself. */
+  
+  unsigned int start, end, addr = ntohl(taddr.s_addr);
+  struct dhcp_context *tmp;
+
+  for (tmp = context; tmp; tmp = tmp->current)
+    if (taddr.s_addr == context->router.s_addr)
+      return NULL;
+  
+  for (tmp = context; tmp; tmp = tmp->current)
+    {
+      start = ntohl(tmp->start.s_addr);
+      end = ntohl(tmp->end.s_addr);
+
+      if (!(tmp->flags & CONTEXT_STATIC) &&
+         addr >= start &&
+         addr <= end &&
+         match_netid(tmp->filter, netids, 1))
+       return tmp;
+    }
+
+  return NULL;
+}
+
+struct dhcp_context *narrow_context(struct dhcp_context *context, 
+                                   struct in_addr taddr,
+                                   struct dhcp_netid *netids)
+{
+  /* We start of with a set of possible contexts, all on the current physical interface.
+     These are chained on ->current.
+     Here we have an address, and return the actual context correponding to that
+     address. Note that none may fit, if the address came a dhcp-host and is outside
+     any dhcp-range. In that case we return a static range if possible, or failing that,
+     any context on the correct subnet. (If there's more than one, this is a dodgy 
+     configuration: maybe there should be a warning.) */
+  
+  struct dhcp_context *tmp;
+
+  if (!(tmp = address_available(context, taddr, netids)))
+    {
+      for (tmp = context; tmp; tmp = tmp->current)
+       if (match_netid(tmp->filter, netids, 1) &&
+           is_same_net(taddr, tmp->start, tmp->netmask) && 
+           (tmp->flags & CONTEXT_STATIC))
+         break;
+      
+      if (!tmp)
+       for (tmp = context; tmp; tmp = tmp->current)
+         if (match_netid(tmp->filter, netids, 1) &&
+             is_same_net(taddr, tmp->start, tmp->netmask))
+           break;
+    }
+  
+  /* Only one context allowed now */
+  if (tmp)
+    tmp->current = NULL;
+  
+  return tmp;
+}
+
+struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
+{
+  struct dhcp_config *config;
+  
+  for (config = configs; config; config = config->next)
+    if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
+      return config;
+
+  return NULL;
+}
+
+/* Is every member of check matched by a member of pool? 
+   If tagnotneeded, untagged is OK */
+int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded)
+{
+  struct dhcp_netid *tmp1;
+  
+  if (!check && !tagnotneeded)
+    return 0;
+
+  for (; check; check = check->next)
+    {
+      /* '#' for not is for backwards compat. */
+      if (check->net[0] != '!' && check->net[0] != '#')
+       {
+         for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
+           if (strcmp(check->net, tmp1->net) == 0)
+             break;
+         if (!tmp1)
+           return 0;
+       }
+      else
+       for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
+         if (strcmp((check->net)+1, tmp1->net) == 0)
+           return 0;
+    }
+  return 1;
+}
+
+struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
+{
+  struct tag_if *exprs;
+  struct dhcp_netid_list *list;
+
+  for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
+    if (match_netid(exprs->tag, tags, 1))
+      for (list = exprs->set; list; list = list->next)
+       {
+         list->list->next = tags;
+         tags = list->list;
+       }
+
+  return tags;
+}
+
+int address_allocate(struct dhcp_context *context,
+                    struct in_addr *addrp, unsigned char *hwaddr, int hw_len, 
+                    struct dhcp_netid *netids, time_t now)   
+{
+  /* Find a free address: exclude anything in use and anything allocated to
+     a particular hwaddr/clientid/hostname in our configuration.
+     Try to return from contexts which match netids first. */
+
+  struct in_addr start, addr;
+  struct dhcp_context *c, *d;
+  int i, pass;
+  unsigned int j; 
+
+  /* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good
+     dispersal even with similarly-valued "strings". */ 
+  for (j = 0, i = 0; i < hw_len; i++)
+    j += hwaddr[i] + (j << 6) + (j << 16) - j;
+  
+  for (pass = 0; pass <= 1; pass++)
+    for (c = context; c; c = c->current)
+      if (c->flags & CONTEXT_STATIC)
+       continue;
+      else if (!match_netid(c->filter, netids, pass))
+       continue;
+      else
+       {
+         /* pick a seed based on hwaddr then iterate until we find a free address. */
+         start.s_addr = addr.s_addr = 
+           htonl(ntohl(c->start.s_addr) + 
+                 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
+         
+         do {
+           /* eliminate addresses in use by the server. */
+           for (d = context; d; d = d->current)
+             if (addr.s_addr == d->router.s_addr)
+               break;
+
+           /* Addresses which end in .255 and .0 are broken in Windows even when using 
+              supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
+              then 192.168.0.255 is a valid IP address, but not for Windows as it's
+              in the class C range. See  KB281579. We therefore don't allocate these 
+              addresses to avoid hard-to-diagnose problems. Thanks Bill. */        
+           if (!d &&
+               !lease_find_by_addr(addr) && 
+               !config_find_by_address(daemon->dhcp_conf, addr) &&
+               (!IN_CLASSC(ntohl(addr.s_addr)) || 
+                ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
+             {
+               struct ping_result *r, *victim = NULL;
+               int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
+                                             ((float)PING_WAIT)));
+               
+               *addrp = addr;
+
+               if (option_bool(OPT_NO_PING))
+                 return 1;
+               
+               /* check if we failed to ping addr sometime in the last
+                  PING_CACHE_TIME seconds. If so, assume the same situation still exists.
+                  This avoids problems when a stupid client bangs
+                  on us repeatedly. As a final check, if we did more
+                  than 60% of the possible ping checks in the last 
+                  PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
+               for (count = 0, r = daemon->ping_results; r; r = r->next)
+                 if (difftime(now, r->time) >  (float)PING_CACHE_TIME)
+                   victim = r; /* old record */
+                 else if (++count == max || r->addr.s_addr == addr.s_addr)
+                   return 1;
+                   
+               if (icmp_ping(addr))
+                 /* address in use: perturb address selection so that we are
+                    less likely to try this address again. */
+                 c->addr_epoch++;
+               else
+                 {
+                   /* at this point victim may hold an expired record */
+                   if (!victim)
+                     {
+                       if ((victim = whine_malloc(sizeof(struct ping_result))))
+                         {
+                           victim->next = daemon->ping_results;
+                           daemon->ping_results = victim;
+                         }
+                     }
+                   
+                   /* record that this address is OK for 30s 
+                      without more ping checks */
+                   if (victim)
+                     {
+                       victim->addr = addr;
+                       victim->time = now;
+                     }
+                   return 1;
+                 }
+             }
+
+           addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
+           
+           if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
+             addr = c->start;
+           
+         } while (addr.s_addr != start.s_addr);
+       }
+  return 0;
+}
+
+static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config)
+{
+  if (!context) /* called via find_config() from lease_update_from_configs() */
+    return 1; 
+  if (!(config->flags & CONFIG_ADDR))
+    return 1;
+  for (; context; context = context->current)
+    if (is_same_net(config->addr, context->start, context->netmask))
+      return 1;
+  
+  return 0;
+}
+
+int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
+{
+  struct hwaddr_config *conf_addr;
+  
+  for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
+    if (conf_addr->wildcard_mask == 0 &&
+       conf_addr->hwaddr_len == len &&
+       (conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
+       memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
+      return 1;
+  
+  return 0;
+}
+
+struct dhcp_config *find_config(struct dhcp_config *configs,
+                               struct dhcp_context *context,
+                               unsigned char *clid, int clid_len,
+                               unsigned char *hwaddr, int hw_len, 
+                               int hw_type, char *hostname)
+{
+  int count, new;
+  struct dhcp_config *config, *candidate; 
+  struct hwaddr_config *conf_addr;
+
+  if (clid)
+    for (config = configs; config; config = config->next)
+      if (config->flags & CONFIG_CLID)
+       {
+         if (config->clid_len == clid_len && 
+             memcmp(config->clid, clid, clid_len) == 0 &&
+             is_addr_in_context(context, config))
+           return config;
+         
+         /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
+            cope with that here */
+         if (*clid == 0 && config->clid_len == clid_len-1  &&
+             memcmp(config->clid, clid+1, clid_len-1) == 0 &&
+             is_addr_in_context(context, config))
+           return config;
+       }
+  
+
+  for (config = configs; config; config = config->next)
+    if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
+       is_addr_in_context(context, config))
+      return config;
+  
+  if (hostname && context)
+    for (config = configs; config; config = config->next)
+      if ((config->flags & CONFIG_NAME) && 
+         hostname_isequal(config->hostname, hostname) &&
+         is_addr_in_context(context, config))
+       return config;
+
+  /* use match with fewest wildcast octets */
+  for (candidate = NULL, count = 0, config = configs; config; config = config->next)
+    if (is_addr_in_context(context, config))
+      for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
+       if (conf_addr->wildcard_mask != 0 &&
+           conf_addr->hwaddr_len == hw_len &&  
+           (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
+           (new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
+         {
+           count = new;
+           candidate = config;
+         }
+
+  return candidate;
+}
+
+void dhcp_read_ethers(void)
+{
+  FILE *f = fopen(ETHERSFILE, "r");
+  unsigned int flags;
+  char *buff = daemon->namebuff;
+  char *ip, *cp;
+  struct in_addr addr;
+  unsigned char hwaddr[ETHER_ADDR_LEN];
+  struct dhcp_config **up, *tmp;
+  struct dhcp_config *config;
+  int count = 0, lineno = 0;
+
+  addr.s_addr = 0; /* eliminate warning */
+  
+  if (!f)
+    {
+      my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
+      return;
+    }
+
+  /* This can be called again on SIGHUP, so remove entries created last time round. */
+  for (up = &daemon->dhcp_conf, config = daemon->dhcp_conf; config; config = tmp)
+    {
+      tmp = config->next;
+      if (config->flags & CONFIG_FROM_ETHERS)
+       {
+         *up = tmp;
+         /* cannot have a clid */
+         if (config->flags & CONFIG_NAME)
+           free(config->hostname);
+         free(config->hwaddr);
+         free(config);
+       }
+      else
+       up = &config->next;
+    }
+
+  while (fgets(buff, MAXDNAME, f))
+    {
+      char *host = NULL;
+      
+      lineno++;
+      
+      while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
+       buff[strlen(buff)-1] = 0;
+      
+      if ((*buff == '#') || (*buff == '+') || (*buff == 0))
+       continue;
+      
+      for (ip = buff; *ip && !isspace((int)*ip); ip++);
+      for(; *ip && isspace((int)*ip); ip++)
+       *ip = 0;
+      if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
+       {
+         my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno); 
+         continue;
+       }
+      
+      /* check for name or dotted-quad */
+      for (cp = ip; *cp; cp++)
+       if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
+         break;
+      
+      if (!*cp)
+       {
+         if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
+           {
+             my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno); 
+             continue;
+           }
+
+         flags = CONFIG_ADDR;
+         
+         for (config = daemon->dhcp_conf; config; config = config->next)
+           if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
+             break;
+       }
+      else 
+       {
+         int nomem;
+         if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
+           {
+             if (!nomem)
+               my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno); 
+             free(host);
+             continue;
+           }
+             
+         flags = CONFIG_NAME;
+
+         for (config = daemon->dhcp_conf; config; config = config->next)
+           if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
+             break;
+       }
+
+      if (config && (config->flags & CONFIG_FROM_ETHERS))
+       {
+         my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno); 
+         continue;
+       }
+       
+      if (!config)
+       { 
+         for (config = daemon->dhcp_conf; config; config = config->next)
+           {
+             struct hwaddr_config *conf_addr = config->hwaddr;
+             if (conf_addr && 
+                 conf_addr->next == NULL && 
+                 conf_addr->wildcard_mask == 0 &&
+                 conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
+                 (conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
+                 memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
+               break;
+           }
+         
+         if (!config)
+           {
+             if (!(config = whine_malloc(sizeof(struct dhcp_config))))
+               continue;
+             config->flags = CONFIG_FROM_ETHERS;
+             config->hwaddr = NULL;
+             config->domain = NULL;
+             config->netid = NULL;
+             config->next = daemon->dhcp_conf;
+             daemon->dhcp_conf = config;
+           }
+         
+         config->flags |= flags;
+         
+         if (flags & CONFIG_NAME)
+           {
+             config->hostname = host;
+             host = NULL;
+           }
+         
+         if (flags & CONFIG_ADDR)
+           config->addr = addr;
+       }
+      
+      config->flags |= CONFIG_NOCLID;
+      if (!config->hwaddr)
+       config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
+      if (config->hwaddr)
+       {
+         memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
+         config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
+         config->hwaddr->hwaddr_type = ARPHRD_ETHER;
+         config->hwaddr->wildcard_mask = 0;
+         config->hwaddr->next = NULL;
+       }
+      count++;
+      
+      free(host);
+
+    }
+  
+  fclose(f);
+
+  my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
+}
+
+void check_dhcp_hosts(int fatal)
+{
+  /* If the same IP appears in more than one host config, then DISCOVER
+     for one of the hosts will get the address, but REQUEST will be NAKed,
+     since the address is reserved by the other one -> protocol loop. 
+     Also check that FQDNs match the domain we are using. */
+  
+  struct dhcp_config *configs, *cp;
+  for (configs = daemon->dhcp_conf; configs; configs = configs->next)
+    {
+      char *domain;
+
+      if ((configs->flags & DHOPT_BANK) || fatal)
+       {
+        for (cp = configs->next; cp; cp = cp->next)
+          if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
+            {
+              if (fatal)
+                die(_("duplicate IP address %s in dhcp-config directive."), 
+                    inet_ntoa(cp->addr), EC_BADCONF);
+              else
+                my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."), 
+                          inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
+              configs->flags &= ~CONFIG_ADDR;
+            }
+        
+        /* split off domain part */
+        if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
+          configs->domain = domain;
+       }
+    }
+}
+
+void dhcp_update_configs(struct dhcp_config *configs)
+{
+  /* Some people like to keep all static IP addresses in /etc/hosts.
+     This goes through /etc/hosts and sets static addresses for any DHCP config
+     records which don't have an address and whose name matches. 
+     We take care to maintain the invariant that any IP address can appear
+     in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP, 
+     restore the status-quo ante first. */
+  
+  struct dhcp_config *config;
+  struct crec *crec;
+
+  for (config = configs; config; config = config->next)
+    if (config->flags & CONFIG_ADDR_HOSTS)
+      config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
+  
+  
+  if (daemon->port != 0)
+    for (config = configs; config; config = config->next)
+      if (!(config->flags & CONFIG_ADDR) &&
+         (config->flags & CONFIG_NAME) && 
+         (crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
+         (crec->flags & F_HOSTS))
+       {
+         if (cache_find_by_name(crec, config->hostname, 0, F_IPV4))
+           {
+             /* use primary (first) address */
+             while (crec && !(crec->flags & F_REVERSE))
+               crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4);
+             if (!crec)
+               continue; /* should be never */
+             my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"), 
+                       config->hostname, inet_ntoa(crec->addr.addr.addr.addr4));
+           }
+
+         if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
+           my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"), 
+                     inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
+         else 
+           {
+             config->addr = crec->addr.addr.addr.addr4;
+             config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
+           }
+       }
+}
+
+/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
+   for this address. If it has a domain part, that must match the set domain and
+   it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
+   so check here that the domain name is legal as a hostname. 
+   NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */
+char *host_from_dns(struct in_addr addr)
+{
+  struct crec *lookup;
+
+  if (daemon->port == 0)
+    return NULL; /* DNS disabled. */
+  
+  lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
+
+  if (lookup && (lookup->flags & F_HOSTS))
+    {
+      char *dot, *hostname = cache_get_name(lookup);
+      dot = strchr(hostname, '.');
+      
+      if (dot && strlen(dot+1) != 0)
+       {
+         char *d2 = get_domain(addr);
+         if (!d2 || !hostname_isequal(dot+1, d2))
+           return NULL; /* wrong domain */
+       }
+
+      if (!legal_hostname(hostname))
+       return NULL;
+      
+      strncpy(daemon->dhcp_buff, hostname, 256);
+      daemon->dhcp_buff[255] = 0;
+      strip_hostname(daemon->dhcp_buff);
+
+      return daemon->dhcp_buff;
+    }
+  
+  return NULL;
+}
+
+/* return domain or NULL if none. */
+char *strip_hostname(char *hostname)
+{
+  char *dot = strchr(hostname, '.');
+  if (!dot)
+    return NULL;
+  
+  *dot = 0; /* truncate */
+  if (strlen(dot+1) != 0)
+    return dot+1;
+  
+  return NULL;
+}
+
+#endif
+
diff --git a/src/dhcp_protocol.h b/src/dhcp_protocol.h
new file mode 100644 (file)
index 0000000..e09cad8
--- /dev/null
@@ -0,0 +1,91 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define BOOTREQUEST              1
+#define BOOTREPLY                2
+#define DHCP_COOKIE              0x63825363
+
+/* The Linux in-kernel DHCP client silently ignores any packet 
+   smaller than this. Sigh...........   */
+#define MIN_PACKETSZ             300
+
+#define OPTION_PAD               0
+#define OPTION_NETMASK           1
+#define OPTION_ROUTER            3
+#define OPTION_DNSSERVER         6
+#define OPTION_HOSTNAME          12
+#define OPTION_DOMAINNAME        15
+#define OPTION_BROADCAST         28
+#define OPTION_VENDOR_CLASS_OPT  43
+#define OPTION_REQUESTED_IP      50 
+#define OPTION_LEASE_TIME        51
+#define OPTION_OVERLOAD          52
+#define OPTION_MESSAGE_TYPE      53
+#define OPTION_SERVER_IDENTIFIER 54
+#define OPTION_REQUESTED_OPTIONS 55
+#define OPTION_MESSAGE           56
+#define OPTION_MAXMESSAGE        57
+#define OPTION_T1                58
+#define OPTION_T2                59
+#define OPTION_VENDOR_ID         60
+#define OPTION_CLIENT_ID         61
+#define OPTION_SNAME             66
+#define OPTION_FILENAME          67
+#define OPTION_USER_CLASS        77
+#define OPTION_CLIENT_FQDN       81
+#define OPTION_AGENT_ID          82
+#define OPTION_ARCH              93
+#define OPTION_PXE_UUID          97
+#define OPTION_SUBNET_SELECT     118
+#define OPTION_DOMAIN_SEARCH     119
+#define OPTION_SIP_SERVER        120
+#define OPTION_VENDOR_IDENT      124
+#define OPTION_VENDOR_IDENT_OPT  125
+#define OPTION_END               255
+
+#define SUBOPT_CIRCUIT_ID        1
+#define SUBOPT_REMOTE_ID         2
+#define SUBOPT_SUBNET_SELECT     5     /* RFC 3527 */
+#define SUBOPT_SUBSCR_ID         6     /* RFC 3393 */
+#define SUBOPT_SERVER_OR         11    /* RFC 5107 */
+
+#define SUBOPT_PXE_BOOT_ITEM     71    /* PXE standard */
+#define SUBOPT_PXE_DISCOVERY     6
+#define SUBOPT_PXE_SERVERS       8
+#define SUBOPT_PXE_MENU          9
+#define SUBOPT_PXE_MENU_PROMPT   10
+
+#define DHCPDISCOVER             1
+#define DHCPOFFER                2
+#define DHCPREQUEST              3
+#define DHCPDECLINE              4
+#define DHCPACK                  5
+#define DHCPNAK                  6
+#define DHCPRELEASE              7
+#define DHCPINFORM               8
+
+#define BRDBAND_FORUM_IANA       3561 /* Broadband forum IANA enterprise */
+
+#define DHCP_CHADDR_MAX 16
+
+struct dhcp_packet {
+  u8 op, htype, hlen, hops;
+  u32 xid;
+  u16 secs, flags;
+  struct in_addr ciaddr, yiaddr, siaddr, giaddr;
+  u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
+  u8 options[312];
+};
diff --git a/src/dns_protocol.h b/src/dns_protocol.h
new file mode 100644 (file)
index 0000000..bc18e79
--- /dev/null
@@ -0,0 +1,111 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define IN6ADDRSZ       16
+#define INADDRSZ        4
+
+#define PACKETSZ       512             /* maximum packet size */
+#define MAXDNAME       1025            /* maximum presentation domain name */
+#define RRFIXEDSZ      10              /* #/bytes of fixed data in r record */
+#define MAXLABEL        63              /* maximum length of domain label */
+
+#define NOERROR                0               /* no error */
+#define FORMERR                1               /* format error */
+#define SERVFAIL       2               /* server failure */
+#define NXDOMAIN       3               /* non existent domain */
+#define NOTIMP         4               /* not implemented */
+#define REFUSED                5               /* query refused */
+
+#define QUERY           0               /* opcode */
+
+#define C_IN            1               /* the arpa internet */
+#define C_CHAOS         3               /* for chaos net (MIT) */
+#define C_ANY           255             /* wildcard match */
+
+#define T_A            1
+#define T_NS            2               
+#define T_CNAME                5
+#define T_SOA          6
+#define T_PTR          12
+#define T_MX           15
+#define T_TXT          16
+#define T_SIG          24
+#define T_AAAA         28
+#define T_SRV          33
+#define T_NAPTR                35
+#define T_OPT          41
+#define        T_TKEY          249             
+#define        T_TSIG          250
+#define T_MAILB                253     
+#define T_ANY          255
+
+struct dns_header {
+  u16 id;
+  u8  hb3,hb4;
+  u16 qdcount,ancount,nscount,arcount;
+} ;
+
+#define HB3_QR       0x80
+#define HB3_OPCODE   0x78
+#define HB3_AA       0x04
+#define HB3_TC       0x02
+#define HB3_RD       0x01
+
+#define HB4_RA       0x80
+#define HB4_AD       0x20
+#define HB4_CD       0x10
+#define HB4_RCODE    0x0f
+
+#define OPCODE(x)          (((x)->hb3 & HB3_OPCODE) >> 3)
+#define RCODE(x)           ((x)->hb4 & HB4_RCODE)
+#define SET_RCODE(x, code) (x)->hb4 = ((x)->hb4 & ~HB4_RCODE) | code
+  
+#define GETSHORT(s, cp) { \
+       unsigned char *t_cp = (unsigned char *)(cp); \
+       (s) = ((u16)t_cp[0] << 8) \
+           | ((u16)t_cp[1]) \
+           ; \
+       (cp) += 2; \
+}
+
+#define GETLONG(l, cp) { \
+       unsigned char *t_cp = (unsigned char *)(cp); \
+       (l) = ((u32)t_cp[0] << 24) \
+           | ((u32)t_cp[1] << 16) \
+           | ((u32)t_cp[2] << 8) \
+           | ((u32)t_cp[3]) \
+           ; \
+       (cp) += 4; \
+}
+
+#define PUTSHORT(s, cp) { \
+       u16 t_s = (u16)(s); \
+       unsigned char *t_cp = (unsigned char *)(cp); \
+       *t_cp++ = t_s >> 8; \
+       *t_cp   = t_s; \
+       (cp) += 2; \
+}
+
+#define PUTLONG(l, cp) { \
+       u32 t_l = (u32)(l); \
+       unsigned char *t_cp = (unsigned char *)(cp); \
+       *t_cp++ = t_l >> 24; \
+       *t_cp++ = t_l >> 16; \
+       *t_cp++ = t_l >> 8; \
+       *t_cp   = t_l; \
+       (cp) += 4; \
+}
+
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
new file mode 100644 (file)
index 0000000..827b0dc
--- /dev/null
@@ -0,0 +1,1325 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+struct daemon *daemon;
+
+static char *compile_opts = 
+#ifndef HAVE_IPV6
+"no-"
+#endif
+"IPv6 "
+#ifndef HAVE_GETOPT_LONG
+"no-"
+#endif
+"GNU-getopt "
+#ifdef HAVE_BROKEN_RTC
+"no-RTC "
+#endif
+#ifdef NO_FORK
+"no-MMU "
+#endif
+#ifndef HAVE_DBUS
+"no-"
+#endif
+"DBus "
+#ifndef LOCALEDIR
+"no-"
+#endif
+"I18N "
+#ifndef HAVE_DHCP
+"no-"
+#endif
+"DHCP "
+#if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT)
+"no-scripts "
+#endif
+#ifndef HAVE_TFTP
+"no-"
+#endif
+"TFTP "
+#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
+"no-"
+#endif 
+"IDN";
+
+
+static volatile pid_t pid = 0;
+static volatile int pipewrite;
+
+static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
+static void check_dns_listeners(fd_set *set, time_t now);
+static void sig_handler(int sig);
+static void async_event(int pipe, time_t now);
+static void fatal_event(struct event_desc *ev);
+
+int main (int argc, char **argv)
+{
+  int bind_fallback = 0;
+  time_t now;
+  struct sigaction sigact;
+  struct iname *if_tmp;
+  int piperead, pipefd[2], err_pipe[2];
+  struct passwd *ent_pw = NULL;
+#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
+  uid_t script_uid = 0;
+  gid_t script_gid = 0;
+#endif
+  struct group *gp = NULL;
+  long i, max_fd = sysconf(_SC_OPEN_MAX);
+  char *baduser = NULL;
+  int log_err;
+#if defined(HAVE_LINUX_NETWORK)
+  cap_user_header_t hdr = NULL;
+  cap_user_data_t data = NULL;
+#endif 
+
+#ifdef LOCALEDIR
+  setlocale(LC_ALL, "");
+  bindtextdomain("dnsmasq", LOCALEDIR); 
+  textdomain("dnsmasq");
+#endif
+
+  sigact.sa_handler = sig_handler;
+  sigact.sa_flags = 0;
+  sigemptyset(&sigact.sa_mask);
+  sigaction(SIGUSR1, &sigact, NULL);
+  sigaction(SIGUSR2, &sigact, NULL);
+  sigaction(SIGHUP, &sigact, NULL);
+  sigaction(SIGTERM, &sigact, NULL);
+  sigaction(SIGALRM, &sigact, NULL);
+  sigaction(SIGCHLD, &sigact, NULL);
+
+  /* ignore SIGPIPE */
+  sigact.sa_handler = SIG_IGN;
+  sigaction(SIGPIPE, &sigact, NULL);
+
+  umask(022); /* known umask, create leases and pid files as 0644 */
+
+  read_opts(argc, argv, compile_opts);
+    
+  if (daemon->edns_pktsz < PACKETSZ)
+    daemon->edns_pktsz = PACKETSZ;
+  daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ? 
+    daemon->edns_pktsz : DNSMASQ_PACKETSZ;
+  daemon->packet = safe_malloc(daemon->packet_buff_sz);
+
+#ifdef HAVE_DHCP
+  if (!daemon->lease_file)
+    {
+      if (daemon->dhcp)
+       daemon->lease_file = LEASEFILE;
+    }
+#endif
+  
+  /* Close any file descriptors we inherited apart from std{in|out|err} */
+  for (i = 0; i < max_fd; i++)
+    if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
+      close(i);
+
+#ifdef HAVE_LINUX_NETWORK
+  netlink_init();
+#elif !(defined(IP_RECVDSTADDR) && \
+       defined(IP_RECVIF) && \
+       defined(IP_SENDSRCADDR))
+  if (!option_bool(OPT_NOWILD))
+    {
+      bind_fallback = 1;
+      set_option_bool(OPT_NOWILD);
+    }
+#endif
+
+#ifndef HAVE_TFTP
+  if (daemon->tftp_unlimited || daemon->tftp_interfaces)
+    die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
+#endif
+
+#ifdef HAVE_SOLARIS_NETWORK
+  if (daemon->max_logs != 0)
+    die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
+#endif
+  
+#ifdef __ANDROID__
+  if (daemon->max_logs != 0)
+    die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
+#endif
+
+  rand_init();
+  
+  now = dnsmasq_time();
+  
+#ifdef HAVE_DHCP
+  if (daemon->dhcp)
+    {
+      /* Note that order matters here, we must call lease_init before
+        creating any file descriptors which shouldn't be leaked
+        to the lease-script init process. */
+      lease_init(now);
+      dhcp_init();
+    }
+#endif
+
+  if (!enumerate_interfaces())
+    die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
+    
+  if (option_bool(OPT_NOWILD)) 
+    {
+      daemon->listeners = create_bound_listeners();
+
+      for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
+       if (if_tmp->name && !if_tmp->used)
+         die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
+  
+      for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
+       if (!if_tmp->used)
+         {
+           prettyprint_addr(&if_tmp->addr, daemon->namebuff);
+           die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
+         }
+    }
+  else 
+    daemon->listeners = create_wildcard_listeners();
+  
+  if (daemon->port != 0)
+    cache_init();
+    
+  if (option_bool(OPT_DBUS))
+#ifdef HAVE_DBUS
+    {
+      char *err;
+      daemon->dbus = NULL;
+      daemon->watches = NULL;
+      if ((err = dbus_init()))
+       die(_("DBus error: %s"), err, EC_MISC);
+    }
+#else
+  die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
+#endif
+  
+  if (daemon->port != 0)
+    pre_allocate_sfds();
+
+#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
+  /* Note getpwnam returns static storage */
+  if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser)
+    {
+      if ((ent_pw = getpwnam(daemon->scriptuser)))
+       {
+         script_uid = ent_pw->pw_uid;
+         script_gid = ent_pw->pw_gid;
+        }
+      else
+       baduser = daemon->scriptuser;
+    }
+#endif
+  
+  if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
+    baduser = daemon->username;
+  else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
+    baduser = daemon->groupname;
+
+  if (baduser)
+    die(_("unknown user or group: %s"), baduser, EC_BADCONF);
+   
+  /* implement group defaults, "dip" if available, or group associated with uid */
+  if (!daemon->group_set && !gp)
+    {
+      if (!(gp = getgrnam(CHGRP)) && ent_pw)
+       gp = getgrgid(ent_pw->pw_gid);
+      
+      /* for error message */
+      if (gp)
+       daemon->groupname = gp->gr_name; 
+    }
+
+#if defined(HAVE_LINUX_NETWORK)
+  /* determine capability API version here, while we can still
+     call safe_malloc */
+  if (ent_pw && ent_pw->pw_uid != 0)
+    {
+      int capsize = 1; /* for header version 1 */
+      hdr = safe_malloc(sizeof(*hdr));
+
+      /* find version supported by kernel */
+      memset(hdr, 0, sizeof(*hdr));
+      capget(hdr, NULL);
+      
+      if (hdr->version != LINUX_CAPABILITY_VERSION_1)
+       {
+         /* if unknown version, use largest supported version (3) */
+         if (hdr->version != LINUX_CAPABILITY_VERSION_2)
+           hdr->version = LINUX_CAPABILITY_VERSION_3;
+         capsize = 2;
+       }
+      
+      data = safe_malloc(sizeof(*data) * capsize);
+      memset(data, 0, sizeof(*data) * capsize);
+    }
+#endif
+
+  /* Use a pipe to carry signals and other events back to the event loop 
+     in a race-free manner and another to carry errors to daemon-invoking process */
+  safe_pipe(pipefd, 1);
+  
+  piperead = pipefd[0];
+  pipewrite = pipefd[1];
+  /* prime the pipe to load stuff first time. */
+  send_event(pipewrite, EVENT_RELOAD, 0); 
+
+  err_pipe[1] = -1;
+  
+  if (!option_bool(OPT_DEBUG))   
+    {
+      /* The following code "daemonizes" the process. 
+        See Stevens section 12.4 */
+      
+      if (chdir("/") != 0)
+       die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC); 
+
+#ifndef NO_FORK      
+      if (!option_bool(OPT_NO_FORK))
+       {
+         pid_t pid;
+         
+         /* pipe to carry errors back to original process.
+            When startup is complete we close this and the process terminates. */
+         safe_pipe(err_pipe, 0);
+         
+         if ((pid = fork()) == -1)
+           /* fd == -1 since we've not forked, never returns. */
+           send_event(-1, EVENT_FORK_ERR, errno);
+          
+         if (pid != 0)
+           {
+             struct event_desc ev;
+             
+             /* close our copy of write-end */
+             close(err_pipe[1]);
+             
+             /* check for errors after the fork */
+             if (read_write(err_pipe[0], (unsigned char *)&ev, sizeof(ev), 1))
+               fatal_event(&ev);
+             
+             _exit(EC_GOOD);
+           } 
+         
+         close(err_pipe[0]);
+
+         /* NO calls to die() from here on. */
+         
+         setsid();
+        
+         if ((pid = fork()) == -1)
+           send_event(err_pipe[1], EVENT_FORK_ERR, errno);
+        
+         if (pid != 0)
+           _exit(0);
+       }
+#endif
+            
+      /* write pidfile _after_ forking ! */
+      if (daemon->runfile)
+       {
+         FILE *pidfile;
+         
+         /* only complain if started as root */
+         if ((pidfile = fopen(daemon->runfile, "w")))
+           {
+             fprintf(pidfile, "%d\n", (int) getpid());
+             fclose(pidfile);
+           }
+         else if (getuid() == 0)
+           {
+             send_event(err_pipe[1], EVENT_PIDFILE, errno);
+             _exit(0);
+           }
+       }
+    }
+  
+   log_err = log_start(ent_pw, err_pipe[1]);
+
+   if (!option_bool(OPT_DEBUG)) 
+     {       
+       /* open  stdout etc to /dev/null */
+       int nullfd = open("/dev/null", O_RDWR);
+       dup2(nullfd, STDOUT_FILENO);
+       dup2(nullfd, STDERR_FILENO);
+       dup2(nullfd, STDIN_FILENO);
+       close(nullfd);
+     }
+   
+   /* if we are to run scripts, we need to fork a helper before dropping root. */
+  daemon->helperfd = -1;
+#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT) 
+  if (daemon->dhcp && daemon->lease_change_command)
+    daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
+#endif
+
+  if (!option_bool(OPT_DEBUG) && getuid() == 0)   
+    {
+      int bad_capabilities = 0;
+      gid_t dummy;
+      
+      /* remove all supplimentary groups */
+      if (gp && 
+         (setgroups(0, &dummy) == -1 ||
+          setgid(gp->gr_gid) == -1))
+       {
+         send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
+         _exit(0);
+       }
+  
+      if (ent_pw && ent_pw->pw_uid != 0)
+       {     
+#if defined(HAVE_LINUX_NETWORK)
+         /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
+            CAP_NET_RAW (for icmp) if we're doing dhcp */
+         data->effective = data->permitted = data->inheritable =
+           (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
+         
+         /* Tell kernel to not clear capabilities when dropping root */
+         if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
+           bad_capabilities = errno;
+                         
+#elif defined(HAVE_SOLARIS_NETWORK)
+         /* http://developers.sun.com/solaris/articles/program_privileges.html */
+         priv_set_t *priv_set;
+         
+         if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
+             priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
+             priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
+           bad_capabilities = errno;
+
+         if (priv_set && bad_capabilities == 0)
+           {
+             priv_inverse(priv_set);
+         
+             if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
+               bad_capabilities = errno;
+           }
+
+         if (priv_set)
+           priv_freeset(priv_set);
+
+#endif    
+
+         if (bad_capabilities != 0)
+           {
+             send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities);
+             _exit(0);
+           }
+         
+         /* finally drop root */
+         if (setuid(ent_pw->pw_uid) == -1)
+           {
+             send_event(err_pipe[1], EVENT_USER_ERR, errno);
+             _exit(0);
+           }     
+
+#ifdef HAVE_LINUX_NETWORK
+         data->effective = data->permitted = 
+           (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
+         data->inheritable = 0;
+         
+         /* lose the setuid and setgid capbilities */
+         if (capset(hdr, data) == -1)
+           {
+             send_event(err_pipe[1], EVENT_CAP_ERR, errno);
+             _exit(0);
+           }
+#endif
+         
+       }
+    }
+  
+#ifdef HAVE_LINUX_NETWORK
+  if (option_bool(OPT_DEBUG)) 
+    prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+#endif
+
+  if (daemon->port == 0)
+    my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
+  else if (daemon->cachesize != 0)
+    my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
+  else
+    my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
+  
+  my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
+  
+#ifdef HAVE_DBUS
+  if (option_bool(OPT_DBUS))
+    {
+      if (daemon->dbus)
+       my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
+      else
+       my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
+    }
+#endif
+
+  if (log_err != 0)
+    my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), 
+             daemon->log_file, strerror(log_err));
+
+  if (bind_fallback)
+    my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
+  
+  if (!option_bool(OPT_NOWILD)) 
+    for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
+      if (if_tmp->name && !if_tmp->used)
+       my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
+   
+  if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
+    {
+      if (daemon->resolv_files && !daemon->resolv_files->is_default)
+       my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
+      daemon->resolv_files = NULL;
+      if (!daemon->servers)
+       my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
+    } 
+
+  if (daemon->max_logs != 0)
+    my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
+
+#ifdef HAVE_DHCP
+  if (daemon->dhcp)
+    {
+      struct dhcp_context *dhcp_tmp;
+      
+      for (dhcp_tmp = daemon->dhcp; dhcp_tmp; dhcp_tmp = dhcp_tmp->next)
+       {
+         prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
+         strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
+         my_syslog(MS_DHCP | LOG_INFO, 
+                   (dhcp_tmp->flags & CONTEXT_STATIC) ? 
+                   _("DHCP, static leases only on %.0s%s, lease time %s") :
+                   (dhcp_tmp->flags & CONTEXT_PROXY) ?
+                   _("DHCP, proxy on subnet %.0s%s%.0s") :
+                   _("DHCP, IP range %s -- %s, lease time %s"),
+                   daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
+       }
+    }
+#endif
+
+#ifdef HAVE_TFTP
+  if (daemon->tftp_unlimited || daemon->tftp_interfaces)
+    {
+#ifdef FD_SETSIZE
+      if (FD_SETSIZE < (unsigned)max_fd)
+       max_fd = FD_SETSIZE;
+#endif
+
+      my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s", 
+               daemon->tftp_prefix ? _("root is ") : _("enabled"),
+               daemon->tftp_prefix ? daemon->tftp_prefix: "",
+               option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
+      
+      /* This is a guess, it assumes that for small limits, 
+        disjoint files might be served, but for large limits, 
+        a single file will be sent to may clients (the file only needs
+        one fd). */
+
+      max_fd -= 30; /* use other than TFTP */
+      
+      if (max_fd < 0)
+       max_fd = 5;
+      else if (max_fd < 100)
+       max_fd = max_fd/2;
+      else
+       max_fd = max_fd - 20;
+      
+      /* if we have to use a limited range of ports, 
+        that will limit the number of transfers */
+      if (daemon->start_tftp_port != 0 &&
+         daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
+       max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
+
+      if (daemon->tftp_max > max_fd)
+       {
+         daemon->tftp_max = max_fd;
+         my_syslog(MS_TFTP | LOG_WARNING, 
+                   _("restricting maximum simultaneous TFTP transfers to %d"), 
+                   daemon->tftp_max);
+       }
+    }
+#endif
+
+  /* finished start-up - release original process */
+  if (err_pipe[1] != -1)
+    close(err_pipe[1]);
+  
+  if (daemon->port != 0)
+    check_servers();
+  
+  pid = getpid();
+  
+  while (1)
+    {
+      int maxfd = -1;
+      struct timeval t, *tp = NULL;
+      fd_set rset, wset, eset;
+      
+      FD_ZERO(&rset);
+      FD_ZERO(&wset);
+      FD_ZERO(&eset);
+      
+      /* if we are out of resources, find how long we have to wait
+        for some to come free, we'll loop around then and restart
+        listening for queries */
+      if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0)
+       {
+         t.tv_usec = 0;
+         tp = &t;
+       }
+
+      /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
+      if (daemon->tftp_trans ||
+         (option_bool(OPT_DBUS) && !daemon->dbus))
+       {
+         t.tv_sec = 0;
+         t.tv_usec = 250000;
+         tp = &t;
+       }
+
+#ifdef HAVE_DBUS
+      set_dbus_listeners(&maxfd, &rset, &wset, &eset);
+#endif 
+  
+#ifdef HAVE_DHCP
+      if (daemon->dhcp)
+       {
+         FD_SET(daemon->dhcpfd, &rset);
+         bump_maxfd(daemon->dhcpfd, &maxfd);
+         if (daemon->pxefd != -1)
+           {
+             FD_SET(daemon->pxefd, &rset);
+             bump_maxfd(daemon->pxefd, &maxfd);
+           }
+       }
+#endif
+
+#ifdef HAVE_LINUX_NETWORK
+      FD_SET(daemon->netlinkfd, &rset);
+      bump_maxfd(daemon->netlinkfd, &maxfd);
+#endif
+      
+      FD_SET(piperead, &rset);
+      bump_maxfd(piperead, &maxfd);
+
+#ifdef HAVE_DHCP
+#  ifdef HAVE_SCRIPT
+      while (helper_buf_empty() && do_script_run(now));
+
+      if (!helper_buf_empty())
+       {
+         FD_SET(daemon->helperfd, &wset);
+         bump_maxfd(daemon->helperfd, &maxfd);
+       }
+#  else
+      /* need this for other side-effects */
+      while (do_script_run(now));
+#  endif
+#endif
+   
+      /* must do this just before select(), when we know no
+        more calls to my_syslog() can occur */
+      set_log_writer(&wset, &maxfd);
+      
+      if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
+       {
+         /* otherwise undefined after error */
+         FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
+       }
+
+      now = dnsmasq_time();
+
+      check_log_writer(&wset);
+
+#ifdef HAVE_LINUX_NETWORK
+      if (FD_ISSET(daemon->netlinkfd, &rset))
+       netlink_multicast();
+#endif
+
+      /* Check for changes to resolv files once per second max. */
+      /* Don't go silent for long periods if the clock goes backwards. */
+      if (daemon->last_resolv == 0 || 
+         difftime(now, daemon->last_resolv) > 1.0 || 
+         difftime(now, daemon->last_resolv) < -1.0)
+       {
+         /* poll_resolv doesn't need to reload first time through, since 
+            that's queued anyway. */
+
+         poll_resolv(0, daemon->last_resolv != 0, now);          
+         daemon->last_resolv = now;
+       }
+      
+      if (FD_ISSET(piperead, &rset))
+       async_event(piperead, now);
+      
+#ifdef HAVE_DBUS
+      /* if we didn't create a DBus connection, retry now. */ 
+     if (option_bool(OPT_DBUS) && !daemon->dbus)
+       {
+         char *err;
+         if ((err = dbus_init()))
+           my_syslog(LOG_WARNING, _("DBus error: %s"), err);
+         if (daemon->dbus)
+           my_syslog(LOG_INFO, _("connected to system DBus"));
+       }
+      check_dbus_listeners(&rset, &wset, &eset);
+#endif
+      
+      check_dns_listeners(&rset, now);
+
+#ifdef HAVE_TFTP
+      check_tftp_listeners(&rset, now);
+#endif      
+
+#ifdef HAVE_DHCP
+      if (daemon->dhcp)
+       {
+         if (FD_ISSET(daemon->dhcpfd, &rset))
+           dhcp_packet(now, 0);
+         if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset))
+           dhcp_packet(now, 1);
+       }
+
+#  ifdef HAVE_SCRIPT
+      if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
+       helper_write();
+#  endif
+#endif
+
+    }
+}
+
+static void sig_handler(int sig)
+{
+  if (pid == 0)
+    {
+      /* ignore anything other than TERM during startup
+        and in helper proc. (helper ignore TERM too) */
+      if (sig == SIGTERM)
+       exit(EC_MISC);
+    }
+  else if (pid != getpid())
+    {
+      /* alarm is used to kill TCP children after a fixed time. */
+      if (sig == SIGALRM)
+       _exit(0);
+    }
+  else
+    {
+      /* master process */
+      int event, errsave = errno;
+      
+      if (sig == SIGHUP)
+       event = EVENT_RELOAD;
+      else if (sig == SIGCHLD)
+       event = EVENT_CHILD;
+      else if (sig == SIGALRM)
+       event = EVENT_ALARM;
+      else if (sig == SIGTERM)
+       event = EVENT_TERM;
+      else if (sig == SIGUSR1)
+       event = EVENT_DUMP;
+      else if (sig == SIGUSR2)
+       event = EVENT_REOPEN;
+      else
+       return;
+
+      send_event(pipewrite, event, 0); 
+      errno = errsave;
+    }
+}
+
+void send_event(int fd, int event, int data)
+{
+  struct event_desc ev;
+  
+  ev.event = event;
+  ev.data = data;
+  
+  /* error pipe, debug mode. */
+  if (fd == -1)
+    fatal_event(&ev);
+  else
+    /* pipe is non-blocking and struct event_desc is smaller than
+       PIPE_BUF, so this either fails or writes everything */
+    while (write(fd, &ev, sizeof(ev)) == -1 && errno == EINTR);
+}
+
+static void fatal_event(struct event_desc *ev)
+{
+  errno = ev->data;
+  
+  switch (ev->event)
+    {
+    case EVENT_DIE:
+      exit(0);
+
+    case EVENT_FORK_ERR:
+      die(_("cannot fork into background: %s"), NULL, EC_MISC);
+  
+    case EVENT_PIPE_ERR:
+      die(_("failed to create helper: %s"), NULL, EC_MISC);
+  
+    case EVENT_CAP_ERR:
+      die(_("setting capabilities failed: %s"), NULL, EC_MISC);
+
+    case EVENT_USER_ERR:
+    case EVENT_HUSER_ERR:
+      die(_("failed to change user-id to %s: %s"), 
+         ev->event == EVENT_USER_ERR ? daemon->username : daemon->scriptuser,
+         EC_MISC);
+
+    case EVENT_GROUP_ERR:
+      die(_("failed to change group-id to %s: %s"), daemon->groupname, EC_MISC);
+      
+    case EVENT_PIDFILE:
+      die(_("failed to open pidfile %s: %s"), daemon->runfile, EC_FILE);
+
+    case EVENT_LOG_ERR:
+      die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
+    }
+}      
+      
+static void async_event(int pipe, time_t now)
+{
+  pid_t p;
+  struct event_desc ev;
+  int i;
+
+  if (read_write(pipe, (unsigned char *)&ev, sizeof(ev), 1))
+    switch (ev.event)
+      {
+      case EVENT_RELOAD:
+       clear_cache_and_reload(now);
+       if (daemon->port != 0 && daemon->resolv_files && option_bool(OPT_NO_POLL))
+         {
+           reload_servers(daemon->resolv_files->name);
+           check_servers();
+         }
+#ifdef HAVE_DHCP
+       rerun_scripts();
+#endif
+       break;
+       
+      case EVENT_DUMP:
+       if (daemon->port != 0)
+         dump_cache(now);
+       break;
+       
+      case EVENT_ALARM:
+#ifdef HAVE_DHCP
+       if (daemon->dhcp)
+         {
+           lease_prune(NULL, now);
+           lease_update_file(now);
+         }
+#endif
+       break;
+               
+      case EVENT_CHILD:
+       /* See Stevens 5.10 */
+       while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
+         if (p == -1)
+           {
+             if (errno != EINTR)
+               break;
+           }      
+         else 
+           for (i = 0 ; i < MAX_PROCS; i++)
+             if (daemon->tcp_pids[i] == p)
+               daemon->tcp_pids[i] = 0;
+       break;
+       
+      case EVENT_KILLED:
+       my_syslog(LOG_WARNING, _("child process killed by signal %d"), ev.data);
+       break;
+
+      case EVENT_EXITED:
+       my_syslog(LOG_WARNING, _("child process exited with status %d"), ev.data);
+       break;
+
+      case EVENT_EXEC_ERR:
+       my_syslog(LOG_ERR, _("failed to execute %s: %s"), 
+                 daemon->lease_change_command, strerror(ev.data));
+       break;
+
+       /* necessary for fatal errors in helper */
+      case EVENT_HUSER_ERR:
+      case EVENT_DIE:
+       fatal_event(&ev);
+       break;
+
+      case EVENT_REOPEN:
+       /* Note: this may leave TCP-handling processes with the old file still open.
+          Since any such process will die in CHILD_LIFETIME or probably much sooner,
+          we leave them logging to the old file. */
+       if (daemon->log_file != NULL)
+         log_reopen(daemon->log_file);
+       break;
+       
+      case EVENT_TERM:
+       /* Knock all our children on the head. */
+       for (i = 0; i < MAX_PROCS; i++)
+         if (daemon->tcp_pids[i] != 0)
+           kill(daemon->tcp_pids[i], SIGALRM);
+       
+#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
+       /* handle pending lease transitions */
+       if (daemon->helperfd != -1)
+         {
+           /* block in writes until all done */
+           if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
+             fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK); 
+           do {
+             helper_write();
+           } while (!helper_buf_empty() || do_script_run(now));
+           close(daemon->helperfd);
+         }
+#endif
+       
+       if (daemon->lease_stream)
+         fclose(daemon->lease_stream);
+
+       if (daemon->runfile)
+         unlink(daemon->runfile);
+       
+       my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
+       flush_log();
+       exit(EC_GOOD);
+      }
+}
+
+void poll_resolv(int force, int do_reload, time_t now)
+{
+  struct resolvc *res, *latest;
+  struct stat statbuf;
+  time_t last_change = 0;
+  /* There may be more than one possible file. 
+     Go through and find the one which changed _last_.
+     Warn of any which can't be read. */
+
+  if (daemon->port == 0 || option_bool(OPT_NO_POLL))
+    return;
+  
+  for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
+    if (stat(res->name, &statbuf) == -1)
+      {
+       if (force)
+         {
+           res->mtime = 0; 
+           continue;
+         }
+
+       if (!res->logged)
+         my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
+       res->logged = 1;
+       
+       if (res->mtime != 0)
+         { 
+           /* existing file evaporated, force selection of the latest
+              file even if its mtime hasn't changed since we last looked */
+           poll_resolv(1, do_reload, now);
+           return;
+         }
+      }
+    else
+      {
+       res->logged = 0;
+       if (force || (statbuf.st_mtime != res->mtime))
+          {
+            res->mtime = statbuf.st_mtime;
+           if (difftime(statbuf.st_mtime, last_change) > 0.0)
+             {
+               last_change = statbuf.st_mtime;
+               latest = res;
+             }
+         }
+      }
+  
+  if (latest)
+    {
+      static int warned = 0;
+      if (reload_servers(latest->name))
+       {
+         my_syslog(LOG_INFO, _("reading %s"), latest->name);
+         warned = 0;
+         check_servers();
+         if (option_bool(OPT_RELOAD) && do_reload)
+           clear_cache_and_reload(now);
+       }
+      else 
+       {
+         latest->mtime = 0;
+         if (!warned)
+           {
+             my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
+             warned = 1;
+           }
+       }
+    }
+}       
+
+void clear_cache_and_reload(time_t now)
+{
+  if (daemon->port != 0)
+    cache_reload();
+  
+#ifdef HAVE_DHCP
+  if (daemon->dhcp)
+    {
+      if (option_bool(OPT_ETHERS))
+       dhcp_read_ethers();
+      reread_dhcp();
+      dhcp_update_configs(daemon->dhcp_conf);
+      check_dhcp_hosts(0);
+      lease_update_from_configs(); 
+      lease_update_file(now); 
+      lease_update_dns();
+    }
+#endif
+}
+
+static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
+{
+  struct serverfd *serverfdp;
+  struct listener *listener;
+  int wait = 0, i;
+  
+#ifdef HAVE_TFTP
+  int  tftp = 0;
+  struct tftp_transfer *transfer;
+  for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
+    {
+      tftp++;
+      FD_SET(transfer->sockfd, set);
+      bump_maxfd(transfer->sockfd, maxfdp);
+    }
+#endif
+  
+  /* will we be able to get memory? */
+  if (daemon->port != 0)
+    get_new_frec(now, &wait);
+  
+  for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
+    {
+      FD_SET(serverfdp->fd, set);
+      bump_maxfd(serverfdp->fd, maxfdp);
+    }
+
+  if (daemon->port != 0 && !daemon->osport)
+    for (i = 0; i < RANDOM_SOCKS; i++)
+      if (daemon->randomsocks[i].refcount != 0)
+       {
+         FD_SET(daemon->randomsocks[i].fd, set);
+         bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
+       }
+  
+  for (listener = daemon->listeners; listener; listener = listener->next)
+    {
+      /* only listen for queries if we have resources */
+      if (listener->fd != -1 && wait == 0)
+       {
+         FD_SET(listener->fd, set);
+         bump_maxfd(listener->fd, maxfdp);
+       }
+
+      /* death of a child goes through the select loop, so
+        we don't need to explicitly arrange to wake up here */
+      if  (listener->tcpfd != -1)
+       for (i = 0; i < MAX_PROCS; i++)
+         if (daemon->tcp_pids[i] == 0)
+           {
+             FD_SET(listener->tcpfd, set);
+             bump_maxfd(listener->tcpfd, maxfdp);
+             break;
+           }
+
+#ifdef HAVE_TFTP
+      if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
+       {
+         FD_SET(listener->tftpfd, set);
+         bump_maxfd(listener->tftpfd, maxfdp);
+       }
+#endif
+
+    }
+  
+  return wait;
+}
+
+static void check_dns_listeners(fd_set *set, time_t now)
+{
+  struct serverfd *serverfdp;
+  struct listener *listener;
+  int i;
+
+  for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
+    if (FD_ISSET(serverfdp->fd, set))
+      reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
+  
+  if (daemon->port != 0 && !daemon->osport)
+    for (i = 0; i < RANDOM_SOCKS; i++)
+      if (daemon->randomsocks[i].refcount != 0 && 
+         FD_ISSET(daemon->randomsocks[i].fd, set))
+       reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
+  
+  for (listener = daemon->listeners; listener; listener = listener->next)
+    {
+      if (listener->fd != -1 && FD_ISSET(listener->fd, set))
+       receive_query(listener, now); 
+      
+#ifdef HAVE_TFTP     
+      if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
+       tftp_request(listener, now);
+#endif
+
+      if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
+       {
+         int confd;
+         struct irec *iface = NULL;
+         pid_t p;
+         
+         while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
+         
+         if (confd == -1)
+           continue;
+         
+         if (option_bool(OPT_NOWILD))
+           iface = listener->iface;
+         else
+           {
+             union mysockaddr tcp_addr;
+             socklen_t tcp_len = sizeof(union mysockaddr);
+             /* Check for allowed interfaces when binding the wildcard address:
+                we do this by looking for an interface with the same address as 
+                the local address of the TCP connection, then looking to see if that's
+                an allowed interface. As a side effect, we get the netmask of the
+                interface too, for localisation. */
+             
+             /* interface may be new since startup */
+             if (enumerate_interfaces() &&
+                 getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
+               for (iface = daemon->interfaces; iface; iface = iface->next)
+                 if (sockaddr_isequal(&iface->addr, &tcp_addr))
+                   break;
+           }
+         
+         if (!iface)
+           {
+             shutdown(confd, SHUT_RDWR);
+             close(confd);
+           }
+#ifndef NO_FORK
+         else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
+           {
+             if (p != -1)
+               {
+                 int i;
+                 for (i = 0; i < MAX_PROCS; i++)
+                   if (daemon->tcp_pids[i] == 0)
+                     {
+                       daemon->tcp_pids[i] = p;
+                       break;
+                     }
+               }
+             close(confd);
+           }
+#endif
+         else
+           {
+             unsigned char *buff;
+             struct server *s; 
+             int flags;
+             struct in_addr dst_addr_4;
+             
+             dst_addr_4.s_addr = 0;
+             
+#ifndef NO_FORK
+             /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
+                terminate the process. */
+             if (!option_bool(OPT_DEBUG))
+               alarm(CHILD_LIFETIME);
+#endif
+
+             /* start with no upstream connections. */
+             for (s = daemon->servers; s; s = s->next)
+                s->tcpfd = -1; 
+             
+             /* The connected socket inherits non-blocking
+                attribute from the listening socket. 
+                Reset that here. */
+             if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
+               fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
+             
+             if (listener->family == AF_INET)
+               dst_addr_4 = iface->addr.in.sin_addr;
+             
+             buff = tcp_request(confd, now, dst_addr_4, iface->netmask);
+              
+             shutdown(confd, SHUT_RDWR);
+             close(confd);
+             
+             if (buff)
+               free(buff);
+             
+             for (s = daemon->servers; s; s = s->next)
+               if (s->tcpfd != -1)
+                 {
+                   shutdown(s->tcpfd, SHUT_RDWR);
+                   close(s->tcpfd);
+                 }
+#ifndef NO_FORK                   
+             if (!option_bool(OPT_DEBUG))
+               {
+                 flush_log();
+                 _exit(0);
+               }
+#endif
+           }
+       }
+    }
+}
+
+#ifdef HAVE_DHCP
+int make_icmp_sock(void)
+{
+  int fd;
+  int zeroopt = 0;
+
+  if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
+    {
+      if (!fix_fd(fd) ||
+         setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
+       {
+         close(fd);
+         fd = -1;
+       }
+    }
+
+  return fd;
+}
+
+int icmp_ping(struct in_addr addr)
+{
+  /* Try and get an ICMP echo from a machine. */
+
+  /* Note that whilst in the three second wait, we check for 
+     (and service) events on the DNS and TFTP  sockets, (so doing that
+     better not use any resources our caller has in use...)
+     but we remain deaf to signals or further DHCP packets. */
+
+  int fd;
+  struct sockaddr_in saddr;
+  struct { 
+    struct ip ip;
+    struct icmp icmp;
+  } packet;
+  unsigned short id = rand16();
+  unsigned int i, j;
+  int gotreply = 0;
+  time_t start, now;
+
+#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
+  if ((fd = make_icmp_sock()) == -1)
+    return 0;
+#else
+  int opt = 2000;
+  fd = daemon->dhcp_icmp_fd;
+  setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
+#endif
+
+  saddr.sin_family = AF_INET;
+  saddr.sin_port = 0;
+  saddr.sin_addr = addr;
+#ifdef HAVE_SOCKADDR_SA_LEN
+  saddr.sin_len = sizeof(struct sockaddr_in);
+#endif
+  
+  memset(&packet.icmp, 0, sizeof(packet.icmp));
+  packet.icmp.icmp_type = ICMP_ECHO;
+  packet.icmp.icmp_id = id;
+  for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
+    j += ((u16 *)&packet.icmp)[i];
+  while (j>>16)
+    j = (j & 0xffff) + (j >> 16);  
+  packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
+  
+  while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0, 
+               (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
+        retry_send());
+  
+  for (now = start = dnsmasq_time(); 
+       difftime(now, start) < (float)PING_WAIT;)
+    {
+      struct timeval tv;
+      fd_set rset, wset;
+      struct sockaddr_in faddr;
+      int maxfd = fd; 
+      socklen_t len = sizeof(faddr);
+      
+      tv.tv_usec = 250000;
+      tv.tv_sec = 0; 
+      
+      FD_ZERO(&rset);
+      FD_ZERO(&wset);
+      FD_SET(fd, &rset);
+      set_dns_listeners(now, &rset, &maxfd);
+      set_log_writer(&wset, &maxfd);
+
+      if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0)
+       {
+         FD_ZERO(&rset);
+         FD_ZERO(&wset);
+       }
+
+      now = dnsmasq_time();
+
+      check_log_writer(&wset);
+      check_dns_listeners(&rset, now);
+
+#ifdef HAVE_TFTP
+      check_tftp_listeners(&rset, now);
+#endif
+
+      if (FD_ISSET(fd, &rset) &&
+         recvfrom(fd, &packet, sizeof(packet), 0,
+                  (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
+         saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
+         packet.icmp.icmp_type == ICMP_ECHOREPLY &&
+         packet.icmp.icmp_seq == 0 &&
+         packet.icmp.icmp_id == id)
+       {
+         gotreply = 1;
+         break;
+       }
+    }
+  
+#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
+  close(fd);
+#else
+  opt = 1;
+  setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
+#endif
+
+  return gotreply;
+}
+#endif
+
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
new file mode 100644 (file)
index 0000000..66c602e
--- /dev/null
@@ -0,0 +1,941 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define COPYRIGHT "Copyright (c) 2000-2011 Simon Kelley" 
+
+#ifndef NO_LARGEFILE
+/* Ensure we can use files >2GB (log files may grow this big) */
+#  define _LARGEFILE_SOURCE 1
+#  define _FILE_OFFSET_BITS 64
+#endif
+
+/* Get linux C library versions and define _GNU_SOURCE for kFreeBSD. */
+#if defined(__linux__) || defined(__GLIBC__)
+#  ifndef __ANDROID__
+#      define _GNU_SOURCE
+#  endif
+#  include <features.h> 
+#endif
+
+/* Need these defined early */
+#if defined(__sun) || defined(__sun__)
+#  define _XPG4_2
+#  define __EXTENSIONS__
+#endif
+
+/* get these before config.h  for IPv6 stuff... */
+#include <sys/types.h> 
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/* and this. */
+#include <getopt.h>
+
+#include "config.h"
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#include "dns_protocol.h"
+#include "dhcp_protocol.h"
+
+#define gettext_noop(S) (S)
+#ifndef LOCALEDIR
+#  define _(S) (S)
+#else
+#  include <libintl.h>
+#  include <locale.h>   
+#  define _(S) gettext(S)
+#endif
+
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#if defined(HAVE_SOLARIS_NETWORK)
+#  include <sys/sockio.h>
+#endif
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <limits.h>
+#include <net/if.h>
+#if defined(HAVE_SOLARIS_NETWORK) && !defined(ifr_mtu)
+/* Some solaris net/if./h omit this. */
+#  define ifr_mtu  ifr_ifru.ifru_metric
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stddef.h>
+#include <time.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdarg.h>
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) || defined (__sun) || defined (__ANDROID__)
+#  include <netinet/if_ether.h>
+#else
+#  include <net/ethernet.h>
+#endif
+#include <net/if_arp.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <sys/uio.h>
+#include <syslog.h>
+#include <dirent.h>
+#ifndef HAVE_LINUX_NETWORK
+#  include <net/if_dl.h>
+#endif
+
+#if defined(HAVE_LINUX_NETWORK)
+#include <linux/capability.h>
+/* There doesn't seem to be a universally-available 
+   userpace header for these. */
+extern int capset(cap_user_header_t header, cap_user_data_t data);
+extern int capget(cap_user_header_t header, cap_user_data_t data);
+#define LINUX_CAPABILITY_VERSION_1  0x19980330
+#define LINUX_CAPABILITY_VERSION_2  0x20071026
+#define LINUX_CAPABILITY_VERSION_3  0x20080522
+
+#include <sys/prctl.h>
+#elif defined(HAVE_SOLARIS_NETWORK)
+#include <priv.h>
+#endif
+
+/* daemon is function in the C library.... */
+#define daemon dnsmasq_daemon
+
+/* Async event queue */
+struct event_desc {
+  int event, data;
+};
+
+#define EVENT_RELOAD    1
+#define EVENT_DUMP      2
+#define EVENT_ALARM     3
+#define EVENT_TERM      4
+#define EVENT_CHILD     5
+#define EVENT_REOPEN    6
+#define EVENT_EXITED    7
+#define EVENT_KILLED    8
+#define EVENT_EXEC_ERR  9
+#define EVENT_PIPE_ERR  10
+#define EVENT_USER_ERR  11
+#define EVENT_CAP_ERR   12
+#define EVENT_PIDFILE   13
+#define EVENT_HUSER_ERR 14
+#define EVENT_GROUP_ERR 15
+#define EVENT_DIE       16
+#define EVENT_LOG_ERR   17
+#define EVENT_FORK_ERR  18
+
+/* Exit codes. */
+#define EC_GOOD        0
+#define EC_BADCONF     1
+#define EC_BADNET      2
+#define EC_FILE        3
+#define EC_NOMEM       4
+#define EC_MISC        5
+#define EC_INIT_OFFSET 10
+
+/* Min buffer size: we check after adding each record, so there must be 
+   memory for the largest packet, and the largest record so the
+   min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
+   This might be increased is EDNS packet size if greater than the minimum.
+*/
+#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
+
+/* Trust the compiler dead-code eliminator.... */
+#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
+
+#define OPT_BOGUSPRIV      0
+#define OPT_FILTER         1
+#define OPT_LOG            2
+#define OPT_SELFMX         3
+#define OPT_NO_HOSTS       4
+#define OPT_NO_POLL        5
+#define OPT_DEBUG          6
+#define OPT_ORDER          7
+#define OPT_NO_RESOLV      8
+#define OPT_EXPAND         9
+#define OPT_LOCALMX        10
+#define OPT_NO_NEG         11
+#define OPT_NODOTS_LOCAL   12
+#define OPT_NOWILD         13
+#define OPT_ETHERS         14
+#define OPT_RESOLV_DOMAIN  15
+#define OPT_NO_FORK        16
+#define OPT_AUTHORITATIVE  17
+#define OPT_LOCALISE       18
+#define OPT_DBUS           19
+#define OPT_DHCP_FQDN      20
+#define OPT_NO_PING        21
+#define OPT_LEASE_RO       22
+#define OPT_ALL_SERVERS    23
+#define OPT_RELOAD         24
+#define OPT_LOCAL_REBIND   25  
+#define OPT_TFTP_SECURE    26
+#define OPT_TFTP_NOBLOCK   27
+#define OPT_LOG_OPTS       28
+#define OPT_TFTP_APREF     29
+#define OPT_NO_OVERRIDE    30
+#define OPT_NO_REBIND      31
+#define OPT_ADD_MAC        32
+#define OPT_DNSSEC         33
+#define OPT_LAST           34
+
+/* extra flags for my_syslog, we use a couple of facilities since they are known 
+   not to occupy the same bits as priorities, no matter how syslog.h is set up. */
+#define MS_TFTP LOG_USER
+#define MS_DHCP LOG_DAEMON 
+
+struct all_addr {
+  union {
+    struct in_addr addr4;
+#ifdef HAVE_IPV6
+    struct in6_addr addr6;
+#endif
+  } addr;
+};
+
+struct bogus_addr {
+  struct in_addr addr;
+  struct bogus_addr *next;
+};
+
+/* dns doctor param */
+struct doctor {
+  struct in_addr in, end, out, mask;
+  struct doctor *next;
+};
+
+struct mx_srv_record {
+  char *name, *target;
+  int issrv, srvport, priority, weight;
+  unsigned int offset;
+  struct mx_srv_record *next;
+};
+
+struct naptr {
+  char *name, *replace, *regexp, *services, *flags;
+  unsigned int order, pref;
+  struct naptr *next;
+};
+
+struct txt_record {
+  char *name;
+  unsigned char *txt;
+  unsigned short class, len;
+  struct txt_record *next;
+};
+
+struct ptr_record {
+  char *name, *ptr;
+  struct ptr_record *next;
+};
+
+struct cname {
+  char *alias, *target;
+  struct cname *next;
+};
+
+struct interface_name {
+  char *name; /* domain name */
+  char *intr; /* interface name */
+  struct interface_name *next;
+};
+
+union bigname {
+  char name[MAXDNAME];
+  union bigname *next; /* freelist */
+};
+
+struct crec { 
+  struct crec *next, *prev, *hash_next;
+  time_t ttd; /* time to die */
+  int uid; 
+  union {
+    struct all_addr addr;
+    struct {
+      struct crec *cache;
+      int uid;
+    } cname;
+  } addr;
+  unsigned short flags;
+  union {
+    char sname[SMALLDNAME];
+    union bigname *bname;
+    char *namep;
+  } name;
+};
+
+#define F_IMMORTAL  (1u<<0)
+#define F_NAMEP     (1u<<1)
+#define F_REVERSE   (1u<<2)
+#define F_FORWARD   (1u<<3)
+#define F_DHCP      (1u<<4)
+#define F_NEG       (1u<<5)       
+#define F_HOSTS     (1u<<6)
+#define F_IPV4      (1u<<7)
+#define F_IPV6      (1u<<8)
+#define F_BIGNAME   (1u<<9)
+#define F_NXDOMAIN  (1u<<10)
+#define F_CNAME     (1u<<11)
+#define F_NOERR     (1u<<12)
+#define F_CONFIG    (1u<<13)
+/* below here are only valid as args to log_query: cache
+   entries are limited to 16 bits */
+#define F_UPSTREAM  (1u<<16)
+#define F_RRNAME    (1u<<17)
+#define F_SERVER    (1u<<18)
+#define F_QUERY     (1u<<19)
+#define F_NSRR      (1u<<20)
+
+
+/* struct sockaddr is not large enough to hold any address,
+   and specifically not big enough to hold an IPv6 address.
+   Blech. Roll our own. */
+union mysockaddr {
+  struct sockaddr sa;
+  struct sockaddr_in in;
+#if defined(HAVE_IPV6)
+  struct sockaddr_in6 in6;
+#endif
+};
+
+#define SERV_FROM_RESOLV       1  /* 1 for servers from resolv, 0 for command line. */
+#define SERV_NO_ADDR           2  /* no server, this domain is local only */
+#define SERV_LITERAL_ADDRESS   4  /* addr is the answer, not the server */ 
+#define SERV_HAS_DOMAIN        8  /* server for one domain only */
+#define SERV_HAS_SOURCE       16  /* source address defined */
+#define SERV_FOR_NODOTS       32  /* server for names with no domain part only */
+#define SERV_WARNED_RECURSIVE 64  /* avoid warning spam */
+#define SERV_FROM_DBUS       128  /* 1 if source is DBus */
+#define SERV_MARK            256  /* for mark-and-delete */
+#define SERV_TYPE    (SERV_HAS_DOMAIN | SERV_FOR_NODOTS)
+#define SERV_COUNTED         512  /* workspace for log code */
+#define SERV_USE_RESOLV     1024  /* forward this domain in the normal way */
+#define SERV_NO_REBIND      2048  /* inhibit dns-rebind protection */
+
+struct serverfd {
+  int fd;
+  union mysockaddr source_addr;
+  char interface[IF_NAMESIZE+1];
+  struct serverfd *next;
+};
+
+struct randfd {
+  int fd;
+  unsigned short refcount, family;
+};
+  
+struct server {
+  union mysockaddr addr, source_addr;
+  char interface[IF_NAMESIZE+1];
+  struct serverfd *sfd; 
+  char *domain; /* set if this server only handles a domain. */ 
+  int flags, tcpfd;
+  unsigned int queries, failed_queries;
+  struct server *next; 
+};
+
+struct irec {
+  union mysockaddr addr;
+  struct in_addr netmask; /* only valid for IPv4 */
+  int tftp_ok, mtu;
+  char *name;
+  struct irec *next;
+};
+
+struct listener {
+  int fd, tcpfd, tftpfd, family;
+  struct irec *iface; /* only valid for non-wildcard */
+  struct listener *next;
+};
+
+/* interface and address parms from command line. */
+struct iname {
+  char *name;
+  union mysockaddr addr;
+  int isloop, used;
+  struct iname *next;
+};
+
+/* resolv-file parms from command-line */
+struct resolvc {
+  struct resolvc *next;
+  int is_default, logged;
+  time_t mtime;
+  char *name;
+};
+
+/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */
+#define AH_DIR      1
+#define AH_INACTIVE 2
+struct hostsfile {
+  struct hostsfile *next;
+  int flags;
+  char *fname;
+  int index; /* matches to cache entries for logging */
+};
+
+#define FREC_NOREBIND           1
+#define FREC_CHECKING_DISABLED  2
+
+struct frec {
+  union mysockaddr source;
+  struct all_addr dest;
+  struct server *sentto; /* NULL means free */
+  struct randfd *rfd4;
+#ifdef HAVE_IPV6
+  struct randfd *rfd6;
+#endif
+  unsigned int iface;
+  unsigned short orig_id, new_id;
+  int fd, forwardall, flags;
+  unsigned int crc;
+  time_t time;
+  struct frec *next;
+};
+
+/* actions in the daemon->helper RPC */
+#define ACTION_DEL           1
+#define ACTION_OLD_HOSTNAME  2
+#define ACTION_OLD           3
+#define ACTION_ADD           4
+#define ACTION_CONNECT      5
+
+struct dhcp_lease {
+  int clid_len;          /* length of client identifier */
+  unsigned char *clid;   /* clientid */
+  char *hostname, *fqdn; /* name from client-hostname option or config */
+  char *old_hostname;    /* hostname before it moved to another lease */
+  char auth_name;        /* hostname came from config, not from client */
+  char new;              /* newly created */
+  char changed;          /* modified */
+  char aux_changed;      /* CLID or expiry changed */
+  time_t expires;        /* lease expiry */
+#ifdef HAVE_BROKEN_RTC
+  unsigned int length;
+#endif
+  int hwaddr_len, hwaddr_type;
+  unsigned char hwaddr[DHCP_CHADDR_MAX]; 
+  struct in_addr addr, override, giaddr;
+  unsigned char *extradata;
+  unsigned int extradata_len, extradata_size;
+  int last_interface;
+  struct dhcp_lease *next;
+};
+
+struct dhcp_netid {
+  char *net;
+  struct dhcp_netid *next;
+};
+
+struct dhcp_netid_list {
+  struct dhcp_netid *list;
+  struct dhcp_netid_list *next;
+};
+
+struct tag_if {
+  struct dhcp_netid_list *set;
+  struct dhcp_netid *tag;
+  struct tag_if *next;
+};
+
+struct hwaddr_config {
+  int hwaddr_len, hwaddr_type;
+  unsigned char hwaddr[DHCP_CHADDR_MAX];
+  unsigned int wildcard_mask;
+  struct hwaddr_config *next;
+};
+
+struct dhcp_config {
+  unsigned int flags;
+  int clid_len;          /* length of client identifier */
+  unsigned char *clid;   /* clientid */
+  char *hostname, *domain;
+  struct dhcp_netid_list *netid;
+  struct in_addr addr;
+  time_t decline_time;
+  unsigned int lease_time;
+  struct hwaddr_config *hwaddr;
+  struct dhcp_config *next;
+};
+
+#define CONFIG_DISABLE           1
+#define CONFIG_CLID              2
+#define CONFIG_TIME              8
+#define CONFIG_NAME             16
+#define CONFIG_ADDR             32
+#define CONFIG_NOCLID          128
+#define CONFIG_FROM_ETHERS     256    /* entry created by /etc/ethers */
+#define CONFIG_ADDR_HOSTS      512    /* address added by from /etc/hosts */
+#define CONFIG_DECLINED       1024    /* address declined by client */
+#define CONFIG_BANK           2048    /* from dhcp hosts file */
+
+struct dhcp_opt {
+  int opt, len, flags;
+  union {
+    int encap;
+    unsigned int wildcard_mask;
+    unsigned char *vendor_class;
+  } u;
+  unsigned char *val;
+  struct dhcp_netid *netid;
+  struct dhcp_opt *next;
+};
+
+#define DHOPT_ADDR               1
+#define DHOPT_STRING             2
+#define DHOPT_ENCAPSULATE        4
+#define DHOPT_ENCAP_MATCH        8
+#define DHOPT_FORCE             16
+#define DHOPT_BANK              32
+#define DHOPT_ENCAP_DONE        64
+#define DHOPT_MATCH            128
+#define DHOPT_VENDOR           256
+#define DHOPT_HEX              512
+#define DHOPT_VENDOR_MATCH    1024
+#define DHOPT_RFC3925         2048
+
+struct dhcp_boot {
+  char *file, *sname;
+  struct in_addr next_server;
+  struct dhcp_netid *netid;
+  struct dhcp_boot *next;
+};
+
+struct pxe_service {
+  unsigned short CSA, type; 
+  char *menu, *basename;
+  struct in_addr server;
+  struct dhcp_netid *netid;
+  struct pxe_service *next;
+};
+
+#define MATCH_VENDOR     1
+#define MATCH_USER       2
+#define MATCH_CIRCUIT    3
+#define MATCH_REMOTE     4
+#define MATCH_SUBSCRIBER 5
+
+/* vendorclass, userclass, remote-id or cicuit-id */
+struct dhcp_vendor {
+  int len, match_type, option;
+  char *data;
+  struct dhcp_netid netid;
+  struct dhcp_vendor *next;
+};
+
+struct dhcp_mac {
+  unsigned int mask;
+  int hwaddr_len, hwaddr_type;
+  unsigned char hwaddr[DHCP_CHADDR_MAX];
+  struct dhcp_netid netid;
+  struct dhcp_mac *next;
+};
+
+struct dhcp_bridge {
+  char iface[IF_NAMESIZE];
+  struct dhcp_bridge *alias, *next;
+};
+
+struct cond_domain {
+  char *domain;
+  struct in_addr start, end;
+  struct cond_domain *next;
+};
+
+struct dhcp_context {
+  unsigned int lease_time, addr_epoch;
+  struct in_addr netmask, broadcast;
+  struct in_addr local, router;
+  struct in_addr start, end; /* range of available addresses */
+  int flags;
+  char *interface;
+  struct dhcp_netid netid, *filter;
+  struct dhcp_context *next, *current;
+};
+
+#define CONTEXT_STATIC    1
+#define CONTEXT_NETMASK   2
+#define CONTEXT_BRDCAST   4
+#define CONTEXT_PROXY     8
+
+struct ping_result {
+  struct in_addr addr;
+  time_t time;
+  struct ping_result *next;
+};
+
+struct tftp_file {
+  int refcount, fd;
+  off_t size;
+  dev_t dev;
+  ino_t inode;
+  char filename[];
+};
+
+struct tftp_transfer {
+  int sockfd;
+  time_t timeout;
+  int backoff;
+  unsigned int block, blocksize, expansion;
+  off_t offset;
+  union mysockaddr peer;
+  char opt_blocksize, opt_transize, netascii, carrylf;
+  struct tftp_file *file;
+  struct tftp_transfer *next;
+};
+
+struct addr_list {
+  struct in_addr addr;
+  struct addr_list *next;
+};
+
+struct interface_list {
+  char *interface;
+  struct interface_list *next;
+};
+
+struct tftp_prefix {
+  char *interface;
+  char *prefix;
+  struct tftp_prefix *next;
+};
+
+
+extern struct daemon {
+  /* datastuctures representing the command-line and 
+     config file arguments. All set (including defaults)
+     in option.c */
+
+  unsigned int options, options2;
+  struct resolvc default_resolv, *resolv_files;
+  time_t last_resolv;
+  struct mx_srv_record *mxnames;
+  struct naptr *naptr;
+  struct txt_record *txt;
+  struct ptr_record *ptr;
+  struct cname *cnames;
+  struct interface_name *int_names;
+  char *mxtarget;
+  char *lease_file; 
+  char *username, *groupname, *scriptuser;
+  int group_set, osport;
+  char *domain_suffix;
+  struct cond_domain *cond_domain;
+  char *runfile; 
+  char *lease_change_command;
+  struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
+  struct bogus_addr *bogus_addr;
+  struct server *servers;
+  int log_fac; /* log facility */
+  char *log_file; /* optional log file */
+  int max_logs;  /* queue limit */
+  int cachesize, ftabsize;
+  int port, query_port, min_port;
+  unsigned long local_ttl, neg_ttl, max_ttl;
+  struct hostsfile *addn_hosts;
+  struct dhcp_context *dhcp;
+  struct dhcp_config *dhcp_conf;
+  struct dhcp_opt *dhcp_opts, *dhcp_match;
+  struct dhcp_vendor *dhcp_vendors;
+  struct dhcp_mac *dhcp_macs;
+  struct dhcp_boot *boot_config;
+  struct pxe_service *pxe_services;
+  struct tag_if *tag_if; 
+  struct addr_list *override_relays;
+  int override;
+  int enable_pxe;
+  struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names; 
+  struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
+  struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
+  int dhcp_max, tftp_max;
+  int dhcp_server_port, dhcp_client_port;
+  int start_tftp_port, end_tftp_port; 
+  unsigned int min_leasetime;
+  struct doctor *doctors;
+  unsigned short edns_pktsz;
+  char *tftp_prefix; 
+  struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
+  struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
+  int tftp_unlimited;
+
+  /* globally used stuff for DNS */
+  char *packet; /* packet buffer */
+  int packet_buff_sz; /* size of above */
+  char *namebuff; /* MAXDNAME size buffer */
+  unsigned int local_answer, queries_forwarded;
+  struct frec *frec_list;
+  struct serverfd *sfds;
+  struct irec *interfaces;
+  struct listener *listeners;
+  struct server *last_server;
+  time_t forwardtime;
+  int forwardcount;
+  struct server *srv_save; /* Used for resend on DoD */
+  size_t packet_len;       /*      "        "        */
+  struct randfd *rfd_save; /*      "        "        */
+  pid_t tcp_pids[MAX_PROCS];
+  struct randfd randomsocks[RANDOM_SOCKS];
+  int v6pktinfo; 
+
+  /* DHCP state */
+  int dhcpfd, helperfd, pxefd; 
+#if defined(HAVE_LINUX_NETWORK)
+  int netlinkfd;
+#elif defined(HAVE_BSD_NETWORK)
+  int dhcp_raw_fd, dhcp_icmp_fd;
+#endif
+  struct iovec dhcp_packet;
+  char *dhcp_buff, *dhcp_buff2, *dhcp_buff3;
+  struct ping_result *ping_results;
+  FILE *lease_stream;
+  struct dhcp_bridge *bridges;
+
+  /* DBus stuff */
+  /* void * here to avoid depending on dbus headers outside dbus.c */
+  void *dbus;
+#ifdef HAVE_DBUS
+  struct watch *watches;
+#endif
+
+  /* TFTP stuff */
+  struct tftp_transfer *tftp_trans;
+
+} *daemon;
+
+/* cache.c */
+void cache_init(void);
+void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg); 
+char *record_source(int index);
+void querystr(char *str, unsigned short type);
+struct crec *cache_find_by_addr(struct crec *crecp,
+                               struct all_addr *addr, time_t now, 
+                               unsigned short prot);
+struct crec *cache_find_by_name(struct crec *crecp, 
+                               char *name, time_t now, unsigned short  prot);
+void cache_end_insert(void);
+void cache_start_insert(void);
+struct crec *cache_insert(char *name, struct all_addr *addr,
+                         time_t now, unsigned long ttl, unsigned short flags);
+void cache_reload(void);
+void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd);
+void cache_unhash_dhcp(void);
+void dump_cache(time_t now);
+char *cache_get_name(struct crec *crecp);
+char *get_domain(struct in_addr addr);
+
+/* rfc1035.c */
+unsigned int extract_request(struct dns_header *header, size_t qlen, 
+                              char *name, unsigned short *typep);
+size_t setup_reply(struct dns_header *header, size_t  qlen,
+                  struct all_addr *addrp, unsigned int flags,
+                  unsigned long local_ttl);
+int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, 
+                     time_t now, int is_sign, int checkrebind, int checking_disabled);
+size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
+                  struct in_addr local_addr, struct in_addr local_netmask, time_t now);
+int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, 
+                            struct bogus_addr *addr, time_t now);
+unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
+                                size_t *len, unsigned char **p, int *is_sign);
+int check_for_local_domain(char *name, time_t now);
+unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
+size_t resize_packet(struct dns_header *header, size_t plen, 
+                 unsigned char *pheader, size_t hlen);
+size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
+
+/* util.c */
+void rand_init(void);
+unsigned short rand16(void);
+int legal_hostname(char *c);
+char *canonicalise(char *s, int *nomem);
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
+void *safe_malloc(size_t size);
+void safe_pipe(int *fd, int read_noblock);
+void *whine_malloc(size_t size);
+int sa_len(union mysockaddr *addr);
+int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
+int hostname_isequal(char *a, char *b);
+time_t dnsmasq_time(void);
+int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
+int retry_send(void);
+void prettyprint_time(char *buf, unsigned int t);
+int prettyprint_addr(union mysockaddr *addr, char *buf);
+int parse_hex(char *in, unsigned char *out, int maxlen, 
+             unsigned int *wildcard_mask, int *mac_type);
+int memcmp_masked(unsigned char *a, unsigned char *b, int len, 
+                 unsigned int mask);
+int expand_buf(struct iovec *iov, size_t size);
+char *print_mac(char *buff, unsigned char *mac, int len);
+void bump_maxfd(int fd, int *max);
+int read_write(int fd, unsigned char *packet, int size, int rw);
+
+/* log.c */
+void die(char *message, char *arg1, int exit_code);
+int log_start(struct passwd *ent_pw, int errfd);
+int log_reopen(char *log_file);
+void my_syslog(int priority, const char *format, ...);
+void set_log_writer(fd_set *set, int *maxfdp);
+void check_log_writer(fd_set *set);
+void flush_log(void);
+
+/* option.c */
+void read_opts (int argc, char **argv, char *compile_opts);
+char *option_string(unsigned char opt, int *is_ip, int *is_name);
+void reread_dhcp(void);
+void set_option_bool(unsigned int opt);
+struct hostsfile *expand_filelist(struct hostsfile *list);
+
+/* forward.c */
+void reply_query(int fd, int family, time_t now);
+void receive_query(struct listener *listen, time_t now);
+unsigned char *tcp_request(int confd, time_t now,
+                          struct in_addr local_addr, struct in_addr netmask);
+void server_gone(struct server *server);
+struct frec *get_new_frec(time_t now, int *wait);
+
+/* network.c */
+int indextoname(int fd, int index, char *name);
+int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
+int random_sock(int family);
+void pre_allocate_sfds(void);
+int reload_servers(char *fname);
+void check_servers(void);
+int enumerate_interfaces();
+struct listener *create_wildcard_listeners(void);
+struct listener *create_bound_listeners(void);
+int iface_check(int family, struct all_addr *addr, char *name, int *indexp);
+int fix_fd(int fd);
+struct in_addr get_ifaddr(char *intr);
+
+/* dhcp.c */
+#ifdef HAVE_DHCP
+void dhcp_init(void);
+void dhcp_packet(time_t now, int pxe_fd);
+struct dhcp_context *address_available(struct dhcp_context *context, 
+                                      struct in_addr addr,
+                                      struct dhcp_netid *netids);
+struct dhcp_context *narrow_context(struct dhcp_context *context, 
+                                   struct in_addr taddr,
+                                   struct dhcp_netid *netids);
+int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
+int address_allocate(struct dhcp_context *context,
+                    struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
+                    struct dhcp_netid *netids, time_t now);
+struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
+int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
+struct dhcp_config *find_config(struct dhcp_config *configs,
+                               struct dhcp_context *context,
+                               unsigned char *clid, int clid_len,
+                               unsigned char *hwaddr, int hw_len, 
+                               int hw_type, char *hostname);
+void dhcp_update_configs(struct dhcp_config *configs);
+void dhcp_read_ethers(void);
+void check_dhcp_hosts(int fatal);
+struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
+char *strip_hostname(char *hostname);
+char *host_from_dns(struct in_addr addr);
+char *get_domain(struct in_addr addr);
+#endif
+
+/* lease.c */
+#ifdef HAVE_DHCP
+void lease_update_file(time_t now);
+void lease_update_dns();
+void lease_init(time_t now);
+struct dhcp_lease *lease_allocate(struct in_addr addr);
+void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
+                     unsigned char *clid, int hw_len, int hw_type, int clid_len);
+void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth);
+void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
+void lease_set_interface(struct dhcp_lease *lease, int interface);
+struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,  
+                                       unsigned char *clid, int clid_len);
+struct dhcp_lease *lease_find_by_addr(struct in_addr addr);
+void lease_prune(struct dhcp_lease *target, time_t now);
+void lease_update_from_configs(void);
+int do_script_run(time_t now);
+void rerun_scripts(void);
+#endif
+
+/* rfc2131.c */
+#ifdef HAVE_DHCP
+size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
+                 size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe_fd);
+unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, 
+                              int clid_len, unsigned char *clid, int *len_out);
+#endif
+
+/* dnsmasq.c */
+#ifdef HAVE_DHCP
+int make_icmp_sock(void);
+int icmp_ping(struct in_addr addr);
+#endif
+void send_event(int fd, int event, int data);
+void clear_cache_and_reload(time_t now);
+void poll_resolv(int force, int do_reload, time_t now);
+
+/* netlink.c */
+#ifdef HAVE_LINUX_NETWORK
+void netlink_init(void);
+void netlink_multicast(void);
+#endif
+
+/* bpf.c */
+#ifdef HAVE_BSD_NETWORK
+void init_bpf(void);
+void send_via_bpf(struct dhcp_packet *mess, size_t len,
+                 struct in_addr iface_addr, struct ifreq *ifr);
+#endif
+
+/* bpf.c or netlink.c */
+int iface_enumerate(int family, void *parm, int (callback)());
+
+/* dbus.c */
+#ifdef HAVE_DBUS
+char *dbus_init(void);
+void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
+void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
+#  ifdef HAVE_DHCP
+void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
+#  endif
+#endif
+
+/* helper.c */
+#if defined(HAVE_DHCP) && !defined(NO_FORK)
+int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
+void helper_write(void);
+void queue_script(int action, struct dhcp_lease *lease, 
+                 char *hostname, time_t now);
+int helper_buf_empty(void);
+#endif
+
+/* tftp.c */
+#ifdef HAVE_TFTP
+void tftp_request(struct listener *listen, time_t now);
+void check_tftp_listeners(fd_set *rset, time_t now);
+#endif
diff --git a/src/forward.c b/src/forward.c
new file mode 100644 (file)
index 0000000..92bc6b0
--- /dev/null
@@ -0,0 +1,1182 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+static struct frec *lookup_frec(unsigned short id, unsigned int crc);
+static struct frec *lookup_frec_by_sender(unsigned short id,
+                                         union mysockaddr *addr,
+                                         unsigned int crc);
+static unsigned short get_id(unsigned int crc);
+static void free_frec(struct frec *f);
+static struct randfd *allocate_rfd(int family);
+
+/* Send a UDP packet with its source address set as "source" 
+   unless nowild is true, when we just send it with the kernel default */
+static void send_from(int fd, int nowild, char *packet, size_t len, 
+                     union mysockaddr *to, struct all_addr *source,
+                     unsigned int iface)
+{
+  struct msghdr msg;
+  struct iovec iov[1]; 
+  union {
+    struct cmsghdr align; /* this ensures alignment */
+#if defined(HAVE_LINUX_NETWORK)
+    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
+#elif defined(IP_SENDSRCADDR)
+    char control[CMSG_SPACE(sizeof(struct in_addr))];
+#endif
+#ifdef HAVE_IPV6
+    char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+#endif
+  } control_u;
+  
+  iov[0].iov_base = packet;
+  iov[0].iov_len = len;
+
+  msg.msg_control = NULL;
+  msg.msg_controllen = 0;
+  msg.msg_flags = 0;
+  msg.msg_name = to;
+  msg.msg_namelen = sa_len(to);
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 1;
+  
+  if (!nowild)
+    {
+      struct cmsghdr *cmptr;
+      msg.msg_control = &control_u;
+      msg.msg_controllen = sizeof(control_u);
+      cmptr = CMSG_FIRSTHDR(&msg);
+
+      if (to->sa.sa_family == AF_INET)
+       {
+#if defined(HAVE_LINUX_NETWORK)
+         struct in_pktinfo p;
+         p.ipi_ifindex = 0;
+         p.ipi_spec_dst = source->addr.addr4;
+         memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
+         msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+         cmptr->cmsg_level = SOL_IP;
+         cmptr->cmsg_type = IP_PKTINFO;
+#elif defined(IP_SENDSRCADDR)
+         memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
+         msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+         cmptr->cmsg_level = IPPROTO_IP;
+         cmptr->cmsg_type = IP_SENDSRCADDR;
+#endif
+       }
+      else
+#ifdef HAVE_IPV6
+       {
+         struct in6_pktinfo p;
+         p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
+         p.ipi6_addr = source->addr.addr6;
+         memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
+         msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+         cmptr->cmsg_type = daemon->v6pktinfo;
+         cmptr->cmsg_level = IPV6_LEVEL;
+       }
+#else
+      iface = 0; /* eliminate warning */
+#endif
+    }
+  
+ retry:
+  if (sendmsg(fd, &msg, 0) == -1)
+    {
+      /* certain Linux kernels seem to object to setting the source address in the IPv6 stack
+        by returning EINVAL from sendmsg. In that case, try again without setting the
+        source address, since it will nearly alway be correct anyway.  IPv6 stinks. */
+      if (errno == EINVAL && msg.msg_controllen)
+       {
+         msg.msg_controllen = 0;
+         goto retry;
+       }
+      if (retry_send())
+       goto retry;
+    }
+}
+          
+static unsigned int search_servers(time_t now, struct all_addr **addrpp, 
+                                    unsigned int qtype, char *qdomain, int *type, char **domain, int *norebind)
+                             
+{
+  /* If the query ends in the domain in one of our servers, set
+     domain to point to that name. We find the largest match to allow both
+     domain.org and sub.domain.org to exist. */
+  
+  unsigned int namelen = strlen(qdomain);
+  unsigned int matchlen = 0;
+  struct server *serv;
+  unsigned int flags = 0;
+  
+  for (serv = daemon->servers; serv; serv=serv->next)
+    /* domain matches take priority over NODOTS matches */
+    if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
+      {
+       unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; 
+       *type = SERV_FOR_NODOTS;
+       if (serv->flags & SERV_NO_ADDR)
+         flags = F_NXDOMAIN;
+       else if (serv->flags & SERV_LITERAL_ADDRESS) 
+         { 
+           if (sflag & qtype)
+             {
+               flags = sflag;
+               if (serv->addr.sa.sa_family == AF_INET) 
+                 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
+#ifdef HAVE_IPV6
+               else
+                 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
+#endif 
+             }
+           else if (!flags || (flags & F_NXDOMAIN))
+             flags = F_NOERR;
+         } 
+      }
+    else if (serv->flags & SERV_HAS_DOMAIN)
+      {
+       unsigned int domainlen = strlen(serv->domain);
+       char *matchstart = qdomain + namelen - domainlen;
+       if (namelen >= domainlen &&
+           hostname_isequal(matchstart, serv->domain) &&
+           (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
+         {
+           if (serv->flags & SERV_NO_REBIND)   
+             *norebind = 1;
+           else
+             {
+               unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
+               /* implement priority rules for --address and --server for same domain.
+                  --address wins if the address is for the correct AF
+                  --server wins otherwise. */
+               if (domainlen != 0 && domainlen == matchlen)
+                 {
+                   if ((serv->flags & SERV_LITERAL_ADDRESS))
+                     {
+                       if (!(sflag & qtype) && flags == 0)
+                         continue;
+                     }
+                   else
+                     {
+                       if (flags & (F_IPV4 | F_IPV6))
+                         continue;
+                     }
+                 }
+               
+               if (domainlen >= matchlen)
+                 {
+                   *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND);
+                   *domain = serv->domain;
+                   matchlen = domainlen;
+                   if (serv->flags & SERV_NO_ADDR)
+                     flags = F_NXDOMAIN;
+                   else if (serv->flags & SERV_LITERAL_ADDRESS)
+                     {
+                       if (sflag & qtype)
+                         {
+                           flags = sflag;
+                           if (serv->addr.sa.sa_family == AF_INET) 
+                             *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
+#ifdef HAVE_IPV6
+                           else
+                             *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
+#endif
+                         }
+                       else if (!flags || (flags & F_NXDOMAIN))
+                         flags = F_NOERR;
+                     }
+                   else
+                     flags = 0;
+                 } 
+             }
+         }
+      }
+  
+  if (flags == 0 && !(qtype & F_NSRR) && 
+      option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
+    /* don't forward simple names, make exception for NS queries and empty name. */
+    flags = F_NXDOMAIN;
+  
+  if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
+    flags = F_NOERR;
+
+  if (flags)
+    {
+      int logflags = 0;
+      
+      if (flags == F_NXDOMAIN || flags == F_NOERR)
+       logflags = F_NEG | qtype;
+  
+      log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
+    }
+  else if ((*type) & SERV_USE_RESOLV)
+    {
+      *type = 0; /* use normal servers for this domain */
+      *domain = NULL;
+    }
+  return  flags;
+}
+
+static int forward_query(int udpfd, union mysockaddr *udpaddr,
+                        struct all_addr *dst_addr, unsigned int dst_iface,
+                        struct dns_header *header, size_t plen, time_t now, struct frec *forward)
+{
+  char *domain = NULL;
+  int type = 0, norebind = 0;
+  struct all_addr *addrp = NULL;
+  unsigned int crc = questions_crc(header, plen, daemon->namebuff);
+  unsigned int flags = 0;
+  unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
+  struct server *start = NULL;
+    
+  /* RFC 4035: sect 4.6 para 2 */
+  header->hb4 &= ~HB4_AD;
+  
+  /* may be no servers available. */
+  if (!daemon->servers)
+    forward = NULL;
+  else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
+    {
+      /* retry on existing query, send to all available servers  */
+      domain = forward->sentto->domain;
+      forward->sentto->failed_queries++;
+      if (!option_bool(OPT_ORDER))
+       {
+         forward->forwardall = 1;
+         daemon->last_server = NULL;
+       }
+      type = forward->sentto->flags & SERV_TYPE;
+      if (!(start = forward->sentto->next))
+       start = daemon->servers; /* at end of list, recycle */
+      header->id = htons(forward->new_id);
+    }
+  else 
+    {
+      if (gotname)
+       flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
+      
+      if (!flags && !(forward = get_new_frec(now, NULL)))
+       /* table full - server failure. */
+       flags = F_NEG;
+      
+      if (forward)
+       {
+         forward->source = *udpaddr;
+         forward->dest = *dst_addr;
+         forward->iface = dst_iface;
+         forward->orig_id = ntohs(header->id);
+         forward->new_id = get_id(crc);
+         forward->fd = udpfd;
+         forward->crc = crc;
+         forward->forwardall = 0;
+         if (norebind)
+           forward->flags |= FREC_NOREBIND;
+         if (header->hb4 & HB4_CD)
+           forward->flags |= FREC_CHECKING_DISABLED;
+
+         header->id = htons(forward->new_id);
+         
+         /* In strict_order mode, always try servers in the order 
+            specified in resolv.conf, if a domain is given 
+            always try all the available servers,
+            otherwise, use the one last known to work. */
+         
+         if (type == 0)
+           {
+             if (option_bool(OPT_ORDER))
+               start = daemon->servers;
+             else if (!(start = daemon->last_server) ||
+                      daemon->forwardcount++ > FORWARD_TEST ||
+                      difftime(now, daemon->forwardtime) > FORWARD_TIME)
+               {
+                 start = daemon->servers;
+                 forward->forwardall = 1;
+                 daemon->forwardcount = 0;
+                 daemon->forwardtime = now;
+               }
+           }
+         else
+           {
+             start = daemon->servers;
+             if (!option_bool(OPT_ORDER))
+               forward->forwardall = 1;
+           }
+       }
+    }
+
+  /* check for send errors here (no route to host) 
+     if we fail to send to all nameservers, send back an error
+     packet straight away (helps modem users when offline)  */
+  
+  if (!flags && forward)
+    {
+      struct server *firstsentto = start;
+      int forwarded = 0;
+      
+      if (udpaddr && option_bool(OPT_ADD_MAC))
+       plen = add_mac(header, plen, ((char *) header) + PACKETSZ, udpaddr);
+      
+      while (1)
+       { 
+         /* only send to servers dealing with our domain.
+            domain may be NULL, in which case server->domain 
+            must be NULL also. */
+         
+         if (type == (start->flags & SERV_TYPE) &&
+             (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
+             !(start->flags & SERV_LITERAL_ADDRESS))
+           {
+             int fd;
+
+             /* find server socket to use, may need to get random one. */
+             if (start->sfd)
+               fd = start->sfd->fd;
+             else 
+               {
+#ifdef HAVE_IPV6
+                 if (start->addr.sa.sa_family == AF_INET6)
+                   {
+                     if (!forward->rfd6 &&
+                         !(forward->rfd6 = allocate_rfd(AF_INET6)))
+                       break;
+                     daemon->rfd_save = forward->rfd6;
+                     fd = forward->rfd6->fd;
+                   }
+                 else
+#endif
+                   {
+                     if (!forward->rfd4 &&
+                         !(forward->rfd4 = allocate_rfd(AF_INET)))
+                       break;
+                     daemon->rfd_save = forward->rfd4;
+                     fd = forward->rfd4->fd;
+                   }
+               }
+             
+             if (sendto(fd, (char *)header, plen, 0,
+                        &start->addr.sa,
+                        sa_len(&start->addr)) == -1)
+               {
+                 if (retry_send())
+                   continue;
+               }
+             else
+               {
+                 /* Keep info in case we want to re-send this packet */
+                 daemon->srv_save = start;
+                 daemon->packet_len = plen;
+                 
+                 if (!gotname)
+                   strcpy(daemon->namebuff, "query");
+                 if (start->addr.sa.sa_family == AF_INET)
+                   log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 
+                             (struct all_addr *)&start->addr.in.sin_addr, NULL); 
+#ifdef HAVE_IPV6
+                 else
+                   log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 
+                             (struct all_addr *)&start->addr.in6.sin6_addr, NULL);
+#endif 
+                 start->queries++;
+                 forwarded = 1;
+                 forward->sentto = start;
+                 if (!forward->forwardall) 
+                   break;
+                 forward->forwardall++;
+               }
+           } 
+         
+         if (!(start = start->next))
+           start = daemon->servers;
+         
+         if (start == firstsentto)
+           break;
+       }
+      
+      if (forwarded)
+       return 1;
+      
+      /* could not send on, prepare to return */ 
+      header->id = htons(forward->orig_id);
+      free_frec(forward); /* cancel */
+    }    
+  
+  /* could not send on, return empty answer or address if known for whole domain */
+  if (udpfd != -1)
+    {
+      plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
+      send_from(udpfd, option_bool(OPT_NOWILD), (char *)header, plen, udpaddr, dst_addr, dst_iface);
+    }
+
+  return 0;
+}
+
+static size_t process_reply(struct dns_header *header, time_t now, 
+                           struct server *server, size_t n, int check_rebind, int checking_disabled)
+{
+  unsigned char *pheader, *sizep;
+  int munged = 0, is_sign;
+  size_t plen; 
+
+  /* If upstream is advertising a larger UDP packet size
+     than we allow, trim it so that we don't get overlarge
+     requests for the client. We can't do this for signed packets. */
+
+  if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
+    {
+      unsigned short udpsz;
+      unsigned char *psave = sizep;
+      
+      GETSHORT(udpsz, sizep);
+      if (udpsz > daemon->edns_pktsz)
+       PUTSHORT(daemon->edns_pktsz, psave);
+    }
+
+  /* RFC 4035 sect 4.6 para 3 */
+  if (!is_sign && !option_bool(OPT_DNSSEC))
+     header->hb4 &= ~HB4_AD;
+
+  if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
+    return n;
+  
+  /* Complain loudly if the upstream server is non-recursive. */
+  if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR && ntohs(header->ancount) == 0 &&
+      server && !(server->flags & SERV_WARNED_RECURSIVE))
+    {
+      prettyprint_addr(&server->addr, daemon->namebuff);
+      my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
+      if (!option_bool(OPT_LOG))
+       server->flags |= SERV_WARNED_RECURSIVE;
+    }  
+    
+  if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
+      check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
+    {
+      munged = 1;
+      SET_RCODE(header, NXDOMAIN);
+      header->hb3 &= ~HB3_AA;
+    }
+  else 
+    {
+      if (RCODE(header) == NXDOMAIN && 
+         extract_request(header, n, daemon->namebuff, NULL) &&
+         check_for_local_domain(daemon->namebuff, now))
+       {
+         /* if we forwarded a query for a locally known name (because it was for 
+            an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
+            since we know that the domain exists, even if upstream doesn't */
+         munged = 1;
+         header->hb3 |= HB3_AA;
+         SET_RCODE(header, NOERROR);
+       }
+      
+      if (extract_addresses(header, n, daemon->namebuff, now, is_sign, check_rebind, checking_disabled))
+       {
+         my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
+         munged = 1;
+       }
+    }
+  
+  /* do this after extract_addresses. Ensure NODATA reply and remove
+     nameserver info. */
+  
+  if (munged)
+    {
+      header->ancount = htons(0);
+      header->nscount = htons(0);
+      header->arcount = htons(0);
+    }
+  
+  /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
+     sections of the packet. Find the new length here and put back pseudoheader
+     if it was removed. */
+  return resize_packet(header, n, pheader, plen);
+}
+
+/* sets new last_server */
+void reply_query(int fd, int family, time_t now)
+{
+  /* packet from peer server, extract data for cache, and send to
+     original requester */
+  struct dns_header *header;
+  union mysockaddr serveraddr;
+  struct frec *forward;
+  socklen_t addrlen = sizeof(serveraddr);
+  ssize_t n = recvfrom(fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
+  size_t nn;
+  struct server *server;
+  
+  /* packet buffer overwritten */
+  daemon->srv_save = NULL;
+  
+  /* Determine the address of the server replying  so that we can mark that as good */
+  serveraddr.sa.sa_family = family;
+#ifdef HAVE_IPV6
+  if (serveraddr.sa.sa_family == AF_INET6)
+    serveraddr.in6.sin6_flowinfo = 0;
+#endif
+  
+  /* spoof check: answer must come from known server, */
+  for (server = daemon->servers; server; server = server->next)
+    if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
+       sockaddr_isequal(&server->addr, &serveraddr))
+      break;
+   
+  header = (struct dns_header *)daemon->packet;
+  
+  if (!server ||
+      n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) ||
+      !(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff))))
+    return;
+   
+  server = forward->sentto;
+  
+  if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
+      !option_bool(OPT_ORDER) &&
+      forward->forwardall == 0)
+    /* for broken servers, attempt to send to another one. */
+    {
+      unsigned char *pheader;
+      size_t plen;
+      int is_sign;
+      
+      /* recreate query from reply */
+      pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
+      if (!is_sign)
+       {
+         header->ancount = htons(0);
+         header->nscount = htons(0);
+         header->arcount = htons(0);
+         if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
+           {
+             header->hb3 &= ~(HB3_QR | HB3_TC);
+             forward_query(-1, NULL, NULL, 0, header, nn, now, forward);
+             return;
+           }
+       }
+    }   
+  
+  if ((forward->sentto->flags & SERV_TYPE) == 0)
+    {
+      if (RCODE(header) == SERVFAIL || RCODE(header) == REFUSED)
+       server = NULL;
+      else
+       {
+         struct server *last_server;
+         
+         /* find good server by address if possible, otherwise assume the last one we sent to */ 
+         for (last_server = daemon->servers; last_server; last_server = last_server->next)
+           if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
+               sockaddr_isequal(&last_server->addr, &serveraddr))
+             {
+               server = last_server;
+               break;
+             }
+       } 
+      if (!option_bool(OPT_ALL_SERVERS))
+       daemon->last_server = server;
+    }
+  
+  /* If the answer is an error, keep the forward record in place in case
+     we get a good reply from another server. Kill it when we've
+     had replies from all to avoid filling the forwarding table when
+     everything is broken */
+  if (forward->forwardall == 0 || --forward->forwardall == 1 || 
+      (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
+    {
+      int check_rebind = !(forward->flags & FREC_NOREBIND);
+
+      if (!option_bool(OPT_NO_REBIND))
+       check_rebind = 0;
+      
+      if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, forward->flags & FREC_CHECKING_DISABLED)))
+       {
+         header->id = htons(forward->orig_id);
+         header->hb4 |= HB4_RA; /* recursion if available */
+         send_from(forward->fd, option_bool(OPT_NOWILD), daemon->packet, nn, 
+                   &forward->source, &forward->dest, forward->iface);
+       }
+      free_frec(forward); /* cancel */
+    }
+}
+
+
+void receive_query(struct listener *listen, time_t now)
+{
+  struct dns_header *header = (struct dns_header *)daemon->packet;
+  union mysockaddr source_addr;
+  unsigned short type;
+  struct all_addr dst_addr;
+  struct in_addr netmask, dst_addr_4;
+  size_t m;
+  ssize_t n;
+  int if_index = 0;
+  struct iovec iov[1];
+  struct msghdr msg;
+  struct cmsghdr *cmptr;
+  union {
+    struct cmsghdr align; /* this ensures alignment */
+#ifdef HAVE_IPV6
+    char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+#endif
+#if defined(HAVE_LINUX_NETWORK)
+    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
+#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
+    char control[CMSG_SPACE(sizeof(struct in_addr)) +
+                CMSG_SPACE(sizeof(unsigned int))];
+#elif defined(IP_RECVDSTADDR)
+    char control[CMSG_SPACE(sizeof(struct in_addr)) +
+                CMSG_SPACE(sizeof(struct sockaddr_dl))];
+#endif
+  } control_u;
+  
+  /* packet buffer overwritten */
+  daemon->srv_save = NULL;
+  
+  if (listen->family == AF_INET && option_bool(OPT_NOWILD))
+    {
+      dst_addr_4 = listen->iface->addr.in.sin_addr;
+      netmask = listen->iface->netmask;
+    }
+  else
+    {
+      dst_addr_4.s_addr = 0;
+      netmask.s_addr = 0;
+    }
+
+  iov[0].iov_base = daemon->packet;
+  iov[0].iov_len = daemon->edns_pktsz;
+    
+  msg.msg_control = control_u.control;
+  msg.msg_controllen = sizeof(control_u);
+  msg.msg_flags = 0;
+  msg.msg_name = &source_addr;
+  msg.msg_namelen = sizeof(source_addr);
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 1;
+  
+  if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
+    return;
+  
+  if (n < (int)sizeof(struct dns_header) || 
+      (msg.msg_flags & MSG_TRUNC) ||
+      (header->hb3 & HB3_QR))
+    return;
+  
+  source_addr.sa.sa_family = listen->family;
+#ifdef HAVE_IPV6
+  if (listen->family == AF_INET6)
+    source_addr.in6.sin6_flowinfo = 0;
+#endif
+
+  if (!option_bool(OPT_NOWILD))
+    {
+      struct ifreq ifr;
+
+      if (msg.msg_controllen < sizeof(struct cmsghdr))
+       return;
+
+#if defined(HAVE_LINUX_NETWORK)
+      if (listen->family == AF_INET)
+       for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+         if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
+           {
+             union {
+               unsigned char *c;
+               struct in_pktinfo *p;
+             } p;
+             p.c = CMSG_DATA(cmptr);
+             dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
+             if_index = p.p->ipi_ifindex;
+           }
+#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+      if (listen->family == AF_INET)
+       {
+         for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+           {
+             union {
+               unsigned char *c;
+               unsigned int *i;
+               struct in_addr *a;
+#ifndef HAVE_SOLARIS_NETWORK
+               struct sockaddr_dl *s;
+#endif
+             } p;
+              p.c = CMSG_DATA(cmptr);
+              if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
+                dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
+              else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+#ifdef HAVE_SOLARIS_NETWORK
+                if_index = *(p.i);
+#else
+                if_index = p.s->sdl_index;
+#endif
+           }
+       }
+#endif
+      
+#ifdef HAVE_IPV6
+      if (listen->family == AF_INET6)
+       {
+         for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+           if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == daemon->v6pktinfo)
+             {
+               union {
+                 unsigned char *c;
+                 struct in6_pktinfo *p;
+               } p;
+               p.c = CMSG_DATA(cmptr);
+                 
+               dst_addr.addr.addr6 = p.p->ipi6_addr;
+               if_index = p.p->ipi6_ifindex;
+             }
+       }
+#endif
+      
+      /* enforce available interface configuration */
+      
+      if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
+         !iface_check(listen->family, &dst_addr, ifr.ifr_name, &if_index))
+       return;
+      
+      if (listen->family == AF_INET &&
+         option_bool(OPT_LOCALISE) &&
+         ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1)
+       return;
+      
+      netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+    }
+  
+  if (extract_request(header, (size_t)n, daemon->namebuff, &type))
+    {
+      char types[20];
+
+      querystr(types, type);
+
+      if (listen->family == AF_INET) 
+       log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
+                 (struct all_addr *)&source_addr.in.sin_addr, types);
+#ifdef HAVE_IPV6
+      else
+       log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
+                 (struct all_addr *)&source_addr.in6.sin6_addr, types);
+#endif
+    }
+
+  m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, 
+                     dst_addr_4, netmask, now);
+  if (m >= 1)
+    {
+      send_from(listen->fd, option_bool(OPT_NOWILD), (char *)header, 
+               m, &source_addr, &dst_addr, if_index);
+      daemon->local_answer++;
+    }
+  else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
+                        header, (size_t)n, now, NULL))
+    daemon->queries_forwarded++;
+  else
+    daemon->local_answer++;
+}
+
+/* The daemon forks before calling this: it should deal with one connection,
+   blocking as neccessary, and then return. Note, need to be a bit careful
+   about resources for debug mode, when the fork is suppressed: that's
+   done by the caller. */
+unsigned char *tcp_request(int confd, time_t now,
+                          struct in_addr local_addr, struct in_addr netmask)
+{
+  size_t size = 0;
+  int norebind = 0;
+  int checking_disabled;
+  size_t m;
+  unsigned short qtype, gotname;
+  unsigned char c1, c2;
+  /* Max TCP packet + slop */
+  unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ);
+  struct dns_header *header;
+  struct server *last_server;
+  
+  while (1)
+    {
+      if (!packet ||
+         !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
+         !(size = c1 << 8 | c2) ||
+         !read_write(confd, packet, size, 1))
+               return packet; 
+  
+      if (size < (int)sizeof(struct dns_header))
+       continue;
+      
+      header = (struct dns_header *)packet;
+
+      /* save state of "cd" flag in query */
+      checking_disabled = header->hb4 & HB4_CD;
+       
+      /* RFC 4035: sect 4.6 para 2 */
+      header->hb4 &= ~HB4_AD;
+      
+      if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
+       {
+         union mysockaddr peer_addr;
+         socklen_t peer_len = sizeof(union mysockaddr);
+         
+         if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1)
+           {
+             char types[20];
+
+             querystr(types, qtype);
+
+             if (peer_addr.sa.sa_family == AF_INET) 
+               log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
+                         (struct all_addr *)&peer_addr.in.sin_addr, types);
+#ifdef HAVE_IPV6
+             else
+               log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
+                         (struct all_addr *)&peer_addr.in6.sin6_addr, types);
+#endif
+           }
+       }
+      
+      /* m > 0 if answered from cache */
+      m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, 
+                        local_addr, netmask, now);
+
+      /* Do this by steam now we're not in the select() loop */
+      check_log_writer(NULL); 
+      
+      if (m == 0)
+       {
+         unsigned int flags = 0;
+         struct all_addr *addrp = NULL;
+         int type = 0;
+         char *domain = NULL;
+          
+         if (option_bool(OPT_ADD_MAC))
+           {
+             union mysockaddr peer_addr;
+             socklen_t peer_len = sizeof(union mysockaddr);
+             
+             if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1)
+               size = add_mac(header, size, ((char *) header) + 65536, &peer_addr);
+           }
+      
+         if (gotname)
+           flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
+         
+         if (type != 0  || option_bool(OPT_ORDER) || !daemon->last_server)
+           last_server = daemon->servers;
+         else
+           last_server = daemon->last_server;
+      
+         if (!flags && last_server)
+           {
+             struct server *firstsendto = NULL;
+             unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
+
+             /* Loop round available servers until we succeed in connecting to one.
+                Note that this code subtley ensures that consecutive queries on this connection
+                which can go to the same server, do so. */
+             while (1) 
+               {
+                 if (!firstsendto)
+                   firstsendto = last_server;
+                 else
+                   {
+                     if (!(last_server = last_server->next))
+                       last_server = daemon->servers;
+                     
+                     if (last_server == firstsendto)
+                       break;
+                   }
+             
+                 /* server for wrong domain */
+                 if (type != (last_server->flags & SERV_TYPE) ||
+                     (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
+                   continue;
+                 
+                 if ((last_server->tcpfd == -1) &&
+                     (last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 &&
+                     (!local_bind(last_server->tcpfd,  &last_server->source_addr, last_server->interface, 1) ||
+                      connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
+                   {
+                     close(last_server->tcpfd);
+                     last_server->tcpfd = -1;
+                   }
+                 
+                 if (last_server->tcpfd == -1) 
+                   continue;
+
+                 c1 = size >> 8;
+                 c2 = size;
+                 
+                 if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
+                     !read_write(last_server->tcpfd, &c2, 1, 0) ||
+                     !read_write(last_server->tcpfd, packet, size, 0) ||
+                     !read_write(last_server->tcpfd, &c1, 1, 1) ||
+                     !read_write(last_server->tcpfd, &c2, 1, 1))
+                   {
+                     close(last_server->tcpfd);
+                     last_server->tcpfd = -1;
+                     continue;
+                   } 
+                 
+                 m = (c1 << 8) | c2;
+                 if (!read_write(last_server->tcpfd, packet, m, 1))
+                   return packet;
+                 
+                 if (!gotname)
+                   strcpy(daemon->namebuff, "query");
+                 if (last_server->addr.sa.sa_family == AF_INET)
+                   log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 
+                             (struct all_addr *)&last_server->addr.in.sin_addr, NULL); 
+#ifdef HAVE_IPV6
+                 else
+                   log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 
+                             (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
+#endif 
+                 
+                 /* There's no point in updating the cache, since this process will exit and
+                    lose the information after a few queries. We make this call for the alias and 
+                    bogus-nxdomain side-effects. */
+                 /* If the crc of the question section doesn't match the crc we sent, then
+                    someone might be attempting to insert bogus values into the cache by 
+                    sending replies containing questions and bogus answers. */
+                 if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff))
+                   m = process_reply(header, now, last_server, (unsigned int)m, 
+                                     option_bool(OPT_NO_REBIND) && !norebind, checking_disabled);
+                 
+                 break;
+               }
+           }
+         
+         /* In case of local answer or no connections made. */
+         if (m == 0)
+           m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
+       }
+
+      check_log_writer(NULL);
+      
+      c1 = m>>8;
+      c2 = m;
+      if (!read_write(confd, &c1, 1, 0) ||
+         !read_write(confd, &c2, 1, 0) || 
+         !read_write(confd, packet, m, 0))
+       return packet;
+    }
+}
+
+static struct frec *allocate_frec(time_t now)
+{
+  struct frec *f;
+  
+  if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
+    {
+      f->next = daemon->frec_list;
+      f->time = now;
+      f->sentto = NULL;
+      f->rfd4 = NULL;
+      f->flags = 0;
+#ifdef HAVE_IPV6
+      f->rfd6 = NULL;
+#endif
+      daemon->frec_list = f;
+    }
+
+  return f;
+}
+
+static struct randfd *allocate_rfd(int family)
+{
+  static int finger = 0;
+  int i;
+
+  /* limit the number of sockets we have open to avoid starvation of 
+     (eg) TFTP. Once we have a reasonable number, randomness should be OK */
+
+  for (i = 0; i < RANDOM_SOCKS; i++)
+    if (daemon->randomsocks[i].refcount == 0)
+      {
+       if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
+         break;
+      
+       daemon->randomsocks[i].refcount = 1;
+       daemon->randomsocks[i].family = family;
+       return &daemon->randomsocks[i];
+      }
+
+  /* No free ones or cannot get new socket, grab an existing one */
+  for (i = 0; i < RANDOM_SOCKS; i++)
+    {
+      int j = (i+finger) % RANDOM_SOCKS;
+      if (daemon->randomsocks[j].refcount != 0 &&
+         daemon->randomsocks[j].family == family && 
+         daemon->randomsocks[j].refcount != 0xffff)
+       {
+         finger = j;
+         daemon->randomsocks[j].refcount++;
+         return &daemon->randomsocks[j];
+       }
+    }
+
+  return NULL; /* doom */
+}
+
+static void free_frec(struct frec *f)
+{
+  if (f->rfd4 && --(f->rfd4->refcount) == 0)
+    close(f->rfd4->fd);
+    
+  f->rfd4 = NULL;
+  f->sentto = NULL;
+  f->flags = 0;
+  
+#ifdef HAVE_IPV6
+  if (f->rfd6 && --(f->rfd6->refcount) == 0)
+    close(f->rfd6->fd);
+    
+  f->rfd6 = NULL;
+#endif
+}
+
+/* if wait==NULL return a free or older than TIMEOUT record.
+   else return *wait zero if one available, or *wait is delay to
+   when the oldest in-use record will expire. Impose an absolute
+   limit of 4*TIMEOUT before we wipe things (for random sockets) */
+struct frec *get_new_frec(time_t now, int *wait)
+{
+  struct frec *f, *oldest, *target;
+  int count;
+  
+  if (wait)
+    *wait = 0;
+
+  for (f = daemon->frec_list, oldest = NULL, target =  NULL, count = 0; f; f = f->next, count++)
+    if (!f->sentto)
+      target = f;
+    else 
+      {
+       if (difftime(now, f->time) >= 4*TIMEOUT)
+         {
+           free_frec(f);
+           target = f;
+         }
+       
+       if (!oldest || difftime(f->time, oldest->time) <= 0)
+         oldest = f;
+      }
+
+  if (target)
+    {
+      target->time = now;
+      return target;
+    }
+  
+  /* can't find empty one, use oldest if there is one
+     and it's older than timeout */
+  if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
+    { 
+      /* keep stuff for twice timeout if we can by allocating a new
+        record instead */
+      if (difftime(now, oldest->time) < 2*TIMEOUT && 
+         count <= daemon->ftabsize &&
+         (f = allocate_frec(now)))
+       return f;
+
+      if (!wait)
+       {
+         free_frec(oldest);
+         oldest->time = now;
+       }
+      return oldest;
+    }
+  
+  /* none available, calculate time 'till oldest record expires */
+  if (count > daemon->ftabsize)
+    {
+      if (oldest && wait)
+       *wait = oldest->time + (time_t)TIMEOUT - now;
+      return NULL;
+    }
+  
+  if (!(f = allocate_frec(now)) && wait)
+    /* wait one second on malloc failure */
+    *wait = 1;
+
+  return f; /* OK if malloc fails and this is NULL */
+}
+/* crc is all-ones if not known. */
+static struct frec *lookup_frec(unsigned short id, unsigned int crc)
+{
+  struct frec *f;
+
+  for(f = daemon->frec_list; f; f = f->next)
+    if (f->sentto && f->new_id == id && 
+       (f->crc == crc || crc == 0xffffffff))
+      return f;
+      
+  return NULL;
+}
+
+static struct frec *lookup_frec_by_sender(unsigned short id,
+                                         union mysockaddr *addr,
+                                         unsigned int crc)
+{
+  struct frec *f;
+  
+  for(f = daemon->frec_list; f; f = f->next)
+    if (f->sentto &&
+       f->orig_id == id && 
+       f->crc == crc &&
+       sockaddr_isequal(&f->source, addr))
+      return f;
+   
+  return NULL;
+}
+
+/* A server record is going away, remove references to it */
+void server_gone(struct server *server)
+{
+  struct frec *f;
+  
+  for (f = daemon->frec_list; f; f = f->next)
+    if (f->sentto && f->sentto == server)
+      free_frec(f);
+  
+  if (daemon->last_server == server)
+    daemon->last_server = NULL;
+
+  if (daemon->srv_save == server)
+    daemon->srv_save = NULL;
+}
+
+/* return unique random ids. */
+static unsigned short get_id(unsigned int crc)
+{
+  unsigned short ret = 0;
+  
+  do 
+    ret = rand16();
+  while (lookup_frec(ret, crc));
+  
+  return ret;
+}
+
+
+
+
+
diff --git a/src/helper.c b/src/helper.c
new file mode 100644 (file)
index 0000000..93f99f0
--- /dev/null
@@ -0,0 +1,410 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+/* This file has code to fork a helper process which recieves data via a pipe 
+   shared with the main process and which is responsible for calling a script when
+   DHCP leases change.
+
+   The helper process is forked before the main process drops root, so it retains root 
+   privs to pass on to the script. For this reason it tries to be paranoid about 
+   data received from the main process, in case that has been compromised. We don't
+   want the helper to give an attacker root. In particular, the script to be run is
+   not settable via the pipe, once the fork has taken place it is not alterable by the 
+   main process.
+*/
+
+#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
+
+static void my_setenv(const char *name, const char *value, int *error);
+static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end,  char *env, int *err);
+
+struct script_data
+{
+  unsigned char action, hwaddr_len, hwaddr_type;
+  unsigned char clid_len, hostname_len, ed_len;
+  struct in_addr addr, giaddr;
+  unsigned int remaining_time;
+#ifdef HAVE_BROKEN_RTC
+  unsigned int length;
+#else
+  time_t expires;
+#endif
+  unsigned char hwaddr[DHCP_CHADDR_MAX];
+  char interface[IF_NAMESIZE];
+};
+
+static struct script_data *buf = NULL;
+static size_t bytes_in_buf = 0, buf_size = 0;
+
+int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
+{
+  pid_t pid;
+  int i, pipefd[2];
+  struct sigaction sigact;
+
+  /* create the pipe through which the main program sends us commands,
+     then fork our process. */
+  if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
+    {
+      send_event(err_fd, EVENT_PIPE_ERR, errno);
+      _exit(0);
+    }
+
+  if (pid != 0)
+    {
+      close(pipefd[0]); /* close reader side */
+      return pipefd[1];
+    }
+
+  /* ignore SIGTERM, so that we can clean up when the main process gets hit
+     and SIGALRM so that we can use sleep() */
+  sigact.sa_handler = SIG_IGN;
+  sigact.sa_flags = 0;
+  sigemptyset(&sigact.sa_mask);
+  sigaction(SIGTERM, &sigact, NULL);
+  sigaction(SIGALRM, &sigact, NULL);
+
+  if (!option_bool(OPT_DEBUG) && uid != 0)
+    {
+      gid_t dummy;
+      if (setgroups(0, &dummy) == -1 || 
+         setgid(gid) == -1 || 
+         setuid(uid) == -1)
+       {
+         if (option_bool(OPT_NO_FORK))
+           /* send error to daemon process if no-fork */
+           send_event(event_fd, EVENT_HUSER_ERR, errno);
+         else
+           {
+             /* kill daemon */
+             send_event(event_fd, EVENT_DIE, 0);
+             /* return error */
+             send_event(err_fd, EVENT_HUSER_ERR, errno);
+           }
+         _exit(0);
+       }
+    }
+
+  /* close all the sockets etc, we don't need them here. This closes err_fd, so that
+     main process can return. */
+  for (max_fd--; max_fd >= 0; max_fd--)
+    if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && 
+       max_fd != STDIN_FILENO && max_fd != pipefd[0] && max_fd != event_fd)
+      close(max_fd);
+  
+  /* loop here */
+  while(1)
+    {
+      struct script_data data;
+      char *p, *action_str, *hostname = NULL;
+      unsigned char *buf = (unsigned char *)daemon->namebuff;
+      unsigned char *end, *alloc_buff = NULL;
+      int err = 0;
+
+      /* we read zero bytes when pipe closed: this is our signal to exit */ 
+      if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1))
+       _exit(0);
+      
+      if (data.action == ACTION_DEL)
+       action_str = "del";
+      else if (data.action == ACTION_ADD)
+       action_str = "add";
+      else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME)
+       action_str = "old";
+      else
+       continue;
+       
+      /* stringify MAC into dhcp_buff */
+      p = daemon->dhcp_buff;
+      if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0) 
+        p += sprintf(p, "%.2x-", data.hwaddr_type);
+      for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++)
+        {
+          p += sprintf(p, "%.2x", data.hwaddr[i]);
+          if (i != data.hwaddr_len - 1)
+            p += sprintf(p, ":");
+        }
+      
+      /* and CLID into packet, avoid overwrite from bad data */
+      if ((data.clid_len > daemon->packet_buff_sz) || !read_write(pipefd[0], buf, data.clid_len, 1))
+       continue;
+      for (p = daemon->packet, i = 0; i < data.clid_len; i++)
+       {
+         p += sprintf(p, "%.2x", buf[i]);
+         if (i != data.clid_len - 1) 
+           p += sprintf(p, ":");
+       }
+      
+      /* and expiry or length into dhcp_buff2 */
+#ifdef HAVE_BROKEN_RTC
+      sprintf(daemon->dhcp_buff2, "%u", data.length);
+#else
+      sprintf(daemon->dhcp_buff2, "%lu", (unsigned long)data.expires);
+#endif
+      
+      /* supplied data may just exceed normal buffer (unlikely) */
+      if ((data.hostname_len + data.ed_len) > daemon->packet_buff_sz && 
+         !(alloc_buff = buf = malloc(data.hostname_len + data.ed_len)))
+       continue;
+      
+      if (!read_write(pipefd[0], buf, 
+                     data.hostname_len + data.ed_len, 1))
+       continue;
+      
+      /* possible fork errors are all temporary resource problems */
+      while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
+       sleep(2);
+
+      free(alloc_buff);
+      
+      if (pid == -1)
+       continue;
+         
+      /* wait for child to complete */
+      if (pid != 0)
+       {
+         /* reap our children's children, if necessary */
+         while (1)
+           {
+             int status;
+             pid_t rc = wait(&status);
+             
+             if (rc == pid)
+               {
+                 /* On error send event back to main process for logging */
+                 if (WIFSIGNALED(status))
+                   send_event(event_fd, EVENT_KILLED, WTERMSIG(status));
+                 else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
+                   send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status));
+                 break;
+               }
+             
+             if (rc == -1 && errno != EINTR)
+               break;
+           }
+         
+         continue;
+       }
+      
+      if (data.clid_len != 0)
+       my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err);
+
+      if (strlen(data.interface) != 0)
+       my_setenv("DNSMASQ_INTERFACE", data.interface, &err);
+            
+#ifdef HAVE_BROKEN_RTC
+      my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err);
+#else
+      my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); 
+#endif
+      
+      if (data.hostname_len != 0)
+       {
+         char *dot;
+         hostname = (char *)buf;
+         hostname[data.hostname_len - 1] = 0;
+         if (!legal_hostname(hostname))
+           hostname = NULL;
+         else if ((dot = strchr(hostname, '.')))
+           {
+             my_setenv("DNSMASQ_DOMAIN", dot+1, &err);
+             *dot = 0;
+           } 
+         buf += data.hostname_len;
+       }
+
+      end = buf + data.ed_len;
+      buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);
+      buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err);
+      buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err);
+      buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err);   
+      buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err);
+      buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
+      
+      for (i = 0; buf; i++)
+       {
+         sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i);
+         buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
+       }
+      
+      if (data.giaddr.s_addr != 0)
+       my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err); 
+
+      if (data.action != ACTION_DEL)
+       {
+         sprintf(daemon->dhcp_buff2, "%u", data.remaining_time);
+         my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
+       }
+
+      if (data.action == ACTION_OLD_HOSTNAME && hostname)
+       {
+         my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);
+         hostname = NULL;
+       }
+
+      /* we need to have the event_fd around if exec fails */
+      if ((i = fcntl(event_fd, F_GETFD)) != -1)
+       fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
+      close(pipefd[0]);
+
+      p =  strrchr(daemon->lease_change_command, '/');
+      if (err == 0)
+       {
+         execl(daemon->lease_change_command, 
+               p ? p+1 : daemon->lease_change_command,
+               action_str, daemon->dhcp_buff, inet_ntoa(data.addr), hostname, (char*)NULL);
+         err = errno;
+       }
+      /* failed, send event so the main process logs the problem */
+      send_event(event_fd, EVENT_EXEC_ERR, err);
+      _exit(0); 
+    }
+}
+
+static void my_setenv(const char *name, const char *value, int *error)
+{
+  if (*error == 0 && setenv(name, value, 1) != 0)
+    *error = errno;
+}
+static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end,  char *env, int *err)
+{
+  unsigned char *next;
+
+  if (!buf || (buf == end))
+    return NULL;
+
+  for (next = buf; *next != 0; next++)
+    if (next == end)
+      return NULL;
+  
+  if (next != buf)
+    {
+      char *p;
+      /* No "=" in value */
+      if ((p = strchr((char *)buf, '=')))
+       *p = 0;
+      my_setenv(env, (char *)buf, err);
+    }
+
+  return next + 1;
+}
+
+/* pack up lease data into a buffer */    
+void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now)
+{
+  unsigned char *p;
+  size_t size;
+  unsigned int hostname_len = 0, clid_len = 0, ed_len = 0;
+  
+  /* no script */
+  if (daemon->helperfd == -1)
+    return;
+
+  if (lease->extradata)
+    ed_len = lease->extradata_len;
+  if (lease->clid)
+    clid_len = lease->clid_len;
+  if (hostname)
+    hostname_len = strlen(hostname) + 1;
+
+  size = sizeof(struct script_data) +  clid_len + ed_len + hostname_len;
+
+  if (size > buf_size)
+    {
+      struct script_data *new;
+      
+      /* start with reasonable size, will almost never need extending. */
+      if (size < sizeof(struct script_data) + 200)
+       size = sizeof(struct script_data) + 200;
+
+      if (!(new = whine_malloc(size)))
+       return;
+      if (buf)
+       free(buf);
+      buf = new;
+      buf_size = size;
+    }
+
+  buf->action = action;
+  buf->hwaddr_len = lease->hwaddr_len;
+  buf->hwaddr_type = lease->hwaddr_type;
+  buf->clid_len = clid_len;
+  buf->ed_len = ed_len;
+  buf->hostname_len = hostname_len;
+  buf->addr = lease->addr;
+  buf->giaddr = lease->giaddr;
+  memcpy(buf->hwaddr, lease->hwaddr, lease->hwaddr_len);
+  if (!indextoname(daemon->dhcpfd, lease->last_interface, buf->interface))
+    buf->interface[0] = 0;
+  
+#ifdef HAVE_BROKEN_RTC 
+  buf->length = lease->length;
+#else
+  buf->expires = lease->expires;
+#endif
+  buf->remaining_time = (unsigned int)difftime(lease->expires, now);
+
+  p = (unsigned char *)(buf+1);
+  if (clid_len != 0)
+    {
+      memcpy(p, lease->clid, clid_len);
+      p += clid_len;
+    }
+  if (hostname_len != 0)
+    {
+      memcpy(p, hostname, hostname_len);
+      p += hostname_len;
+    }
+  if (ed_len != 0)
+    {
+      memcpy(p, lease->extradata, ed_len);
+      p += ed_len;
+    }
+  bytes_in_buf = p - (unsigned char *)buf;
+}
+
+int helper_buf_empty(void)
+{
+  return bytes_in_buf == 0;
+}
+
+void helper_write(void)
+{
+  ssize_t rc;
+
+  if (bytes_in_buf == 0)
+    return;
+  
+  if ((rc = write(daemon->helperfd, buf, bytes_in_buf)) != -1)
+    {
+      if (bytes_in_buf != (size_t)rc)
+       memmove(buf, buf + rc, bytes_in_buf - rc); 
+      bytes_in_buf -= rc;
+    }
+  else
+    {
+      if (errno == EAGAIN || errno == EINTR)
+       return;
+      bytes_in_buf = 0;
+    }
+}
+
+#endif
+
+
diff --git a/src/lease.c b/src/lease.c
new file mode 100644 (file)
index 0000000..cfa7543
--- /dev/null
@@ -0,0 +1,615 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_DHCP
+
+static struct dhcp_lease *leases = NULL, *old_leases = NULL;
+static int dns_dirty, file_dirty, leases_left;
+
+void lease_init(time_t now)
+{
+  unsigned long ei;
+  struct in_addr addr;
+  struct dhcp_lease *lease;
+  int clid_len, hw_len, hw_type;
+  FILE *leasestream;
+  
+  /* These each hold a DHCP option max size 255
+     and get a terminating zero added */
+  daemon->dhcp_buff = safe_malloc(256);
+  daemon->dhcp_buff2 = safe_malloc(256); 
+  daemon->dhcp_buff3 = safe_malloc(256);
+  leases_left = daemon->dhcp_max;
+
+  if (option_bool(OPT_LEASE_RO))
+    {
+      /* run "<lease_change_script> init" once to get the
+        initial state of the database. If leasefile-ro is
+        set without a script, we just do without any 
+        lease database. */
+#ifdef HAVE_SCRIPT
+      if (daemon->lease_change_command)
+       {
+         strcpy(daemon->dhcp_buff, daemon->lease_change_command);
+         strcat(daemon->dhcp_buff, " init");
+         leasestream = popen(daemon->dhcp_buff, "r");
+       }
+      else
+#endif
+       {
+          file_dirty = dns_dirty = 0;
+          return;
+        }
+
+    }
+  else
+    {
+      /* NOTE: need a+ mode to create file if it doesn't exist */
+      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
+      
+      if (!leasestream)
+       die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
+      
+      /* a+ mode leaves pointer at end. */
+      rewind(leasestream);
+    }
+  
+  /* client-id max length is 255 which is 255*2 digits + 254 colons 
+     borrow DNS packet buffer which is always larger than 1000 bytes */
+  if (leasestream)
+    while (fscanf(leasestream, "%lu %255s %16s %255s %764s",
+                 &ei, daemon->dhcp_buff2, daemon->namebuff, 
+                 daemon->dhcp_buff, daemon->packet) == 5)
+      {
+       hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
+       /* For backwards compatibility, no explict MAC address type means ether. */
+       if (hw_type == 0 && hw_len != 0)
+         hw_type = ARPHRD_ETHER;
+       
+       addr.s_addr = inet_addr(daemon->namebuff);
+       
+       /* decode hex in place */
+       clid_len = 0;
+       if (strcmp(daemon->packet, "*") != 0)
+         clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
+       
+       if (!(lease = lease_allocate(addr)))
+         die (_("too many stored leases"), NULL, EC_MISC);
+               
+#ifdef HAVE_BROKEN_RTC
+       if (ei != 0)
+         lease->expires = (time_t)ei + now;
+       else
+         lease->expires = (time_t)0;
+       lease->length = ei;
+#else
+       /* strictly time_t is opaque, but this hack should work on all sane systems,
+          even when sizeof(time_t) == 8 */
+       lease->expires = (time_t)ei;
+#endif
+       
+       lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
+       
+       if (strcmp(daemon->dhcp_buff, "*") !=  0)
+         lease_set_hostname(lease, daemon->dhcp_buff, 0);
+
+       /* set these correctly: the "old" events are generated later from
+          the startup synthesised SIGHUP. */
+       lease->new = lease->changed = 0;
+      }
+  
+#ifdef HAVE_SCRIPT
+  if (!daemon->lease_stream)
+    {
+      int rc = 0;
+
+      /* shell returns 127 for "command not found", 126 for bad permissions. */
+      if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
+       {
+         if (WEXITSTATUS(rc) == 127)
+           errno = ENOENT;
+         else if (WEXITSTATUS(rc) == 126)
+           errno = EACCES;
+         die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
+       }
+      
+      if (WEXITSTATUS(rc) != 0)
+       {
+         sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
+         die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
+       }
+    }
+#endif
+
+  /* Some leases may have expired */
+  file_dirty = 0;
+  lease_prune(NULL, now);
+  dns_dirty = 1;
+}
+
+void lease_update_from_configs(void)
+{
+  /* changes to the config may change current leases. */
+  
+  struct dhcp_lease *lease;
+  struct dhcp_config *config;
+  char *name;
+
+  for (lease = leases; lease; lease = lease->next)
+    if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, 
+                             lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && 
+       (config->flags & CONFIG_NAME) &&
+       (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
+      lease_set_hostname(lease, config->hostname, 1);
+    else if ((name = host_from_dns(lease->addr)))
+      lease_set_hostname(lease, name, 1); /* updates auth flag only */
+}
+
+static void ourprintf(int *errp, char *format, ...)
+{
+  va_list ap;
+  
+  va_start(ap, format);
+  if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0)
+    *errp = errno;
+  va_end(ap);
+}
+
+void lease_update_file(time_t now)
+{
+  struct dhcp_lease *lease;
+  time_t next_event;
+  int i, err = 0;
+
+  if (file_dirty != 0 && daemon->lease_stream)
+    {
+      errno = 0;
+      rewind(daemon->lease_stream);
+      if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0)
+       err = errno;
+      
+      for (lease = leases; lease; lease = lease->next)
+       {
+#ifdef HAVE_BROKEN_RTC
+         ourprintf(&err, "%u ", lease->length);
+#else
+         ourprintf(&err, "%lu ", (unsigned long)lease->expires);
+#endif
+         if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) 
+           ourprintf(&err, "%.2x-", lease->hwaddr_type);
+         for (i = 0; i < lease->hwaddr_len; i++)
+           {
+             ourprintf(&err, "%.2x", lease->hwaddr[i]);
+             if (i != lease->hwaddr_len - 1)
+               ourprintf(&err, ":");
+           }
+
+         ourprintf(&err, " %s ", inet_ntoa(lease->addr));
+         ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*");
+                 
+         if (lease->clid && lease->clid_len != 0)
+           {
+             for (i = 0; i < lease->clid_len - 1; i++)
+               ourprintf(&err, "%.2x:", lease->clid[i]);
+             ourprintf(&err, "%.2x\n", lease->clid[i]);
+           }
+         else
+           ourprintf(&err, "*\n");       
+       }
+      
+      if (fflush(daemon->lease_stream) != 0 ||
+         fsync(fileno(daemon->lease_stream)) < 0)
+       err = errno;
+      
+      if (!err)
+       file_dirty = 0;
+    }
+  
+  /* Set alarm for when the first lease expires + slop. */
+  for (next_event = 0, lease = leases; lease; lease = lease->next)
+    if (lease->expires != 0 &&
+       (next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0))
+      next_event = lease->expires + 10;
+   
+  if (err)
+    {
+      if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
+       next_event = LEASE_RETRY + now;
+      
+      my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"), 
+               daemon->lease_file, strerror(err),
+               (unsigned int)difftime(next_event, now));
+    }
+
+  if (next_event != 0)
+    alarm((unsigned)difftime(next_event, now)); 
+}
+
+void lease_update_dns(void)
+{
+  struct dhcp_lease *lease;
+  
+  if (daemon->port != 0 && dns_dirty)
+    {
+      cache_unhash_dhcp();
+      
+      for (lease = leases; lease; lease = lease->next)
+       {
+         if (lease->fqdn)
+           cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
+            
+         if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
+           cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
+       }
+      
+      dns_dirty = 0;
+    }
+}
+
+void lease_prune(struct dhcp_lease *target, time_t now)
+{
+  struct dhcp_lease *lease, *tmp, **up;
+
+  for (lease = leases, up = &leases; lease; lease = tmp)
+    {
+      tmp = lease->next;
+      if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target)
+       {
+         file_dirty = 1;
+         if (lease->hostname)
+           dns_dirty = 1;
+         
+         *up = lease->next; /* unlink */
+         
+         /* Put on old_leases list 'till we
+            can run the script */
+         lease->next = old_leases;
+         old_leases = lease;
+         
+         leases_left++;
+       }
+      else
+       up = &lease->next;
+    }
+} 
+       
+  
+struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
+                                       unsigned char *clid, int clid_len)
+{
+  struct dhcp_lease *lease;
+
+  if (clid)
+    for (lease = leases; lease; lease = lease->next)
+      if (lease->clid && clid_len == lease->clid_len &&
+         memcmp(clid, lease->clid, clid_len) == 0)
+       return lease;
+  
+  for (lease = leases; lease; lease = lease->next)     
+    if ((!lease->clid || !clid) && 
+       hw_len != 0 && 
+       lease->hwaddr_len == hw_len &&
+       lease->hwaddr_type == hw_type &&
+       memcmp(hwaddr, lease->hwaddr, hw_len) == 0)
+      return lease;
+  
+  return NULL;
+}
+
+struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
+{
+  struct dhcp_lease *lease;
+
+  for (lease = leases; lease; lease = lease->next)
+    if (lease->addr.s_addr == addr.s_addr)
+      return lease;
+  
+  return NULL;
+}
+
+
+struct dhcp_lease *lease_allocate(struct in_addr addr)
+{
+  struct dhcp_lease *lease;
+  if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease))))
+    return NULL;
+
+  memset(lease, 0, sizeof(struct dhcp_lease));
+  lease->new = 1;
+  lease->addr = addr;
+  lease->hwaddr_len = 256; /* illegal value */
+  lease->expires = 1;
+#ifdef HAVE_BROKEN_RTC
+  lease->length = 0xffffffff; /* illegal value */
+#endif
+  lease->next = leases;
+  leases = lease;
+  
+  file_dirty = 1;
+  leases_left--;
+
+  return lease;
+}
+
+void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
+{
+  time_t exp = now + (time_t)len;
+  
+  if (len == 0xffffffff)
+    {
+      exp = 0;
+      len = 0;
+    }
+  
+  if (exp != lease->expires)
+    {
+      dns_dirty = 1;
+      lease->expires = exp;
+#ifndef HAVE_BROKEN_RTC
+      lease->aux_changed = file_dirty = 1;
+#endif
+    }
+  
+#ifdef HAVE_BROKEN_RTC
+  if (len != lease->length)
+    {
+      lease->length = len;
+      lease->aux_changed = file_dirty = 1; 
+    }
+#endif
+} 
+
+void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
+                     unsigned char *clid, int hw_len, int hw_type, int clid_len)
+{
+  if (hw_len != lease->hwaddr_len ||
+      hw_type != lease->hwaddr_type || 
+      (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
+    {
+      memcpy(lease->hwaddr, hwaddr, hw_len);
+      lease->hwaddr_len = hw_len;
+      lease->hwaddr_type = hw_type;
+      lease->changed = file_dirty = 1; /* run script on change */
+    }
+
+  /* only update clid when one is available, stops packets
+     without a clid removing the record. Lease init uses
+     clid_len == 0 for no clid. */
+  if (clid_len != 0 && clid)
+    {
+      if (!lease->clid)
+       lease->clid_len = 0;
+
+      if (lease->clid_len != clid_len)
+       {
+         lease->aux_changed = file_dirty = 1;
+         free(lease->clid);
+         if (!(lease->clid = whine_malloc(clid_len)))
+           return;
+       }
+      else if (memcmp(lease->clid, clid, clid_len) != 0)
+       lease->aux_changed = file_dirty = 1;
+         
+      lease->clid_len = clid_len;
+      memcpy(lease->clid, clid, clid_len);
+    }
+
+}
+
+static void kill_name(struct dhcp_lease *lease)
+{
+  /* run script to say we lost our old name */
+  
+  /* this shouldn't happen unless updates are very quick and the
+     script very slow, we just avoid a memory leak if it does. */
+  free(lease->old_hostname);
+  
+  /* If we know the fqdn, pass that. The helper will derive the
+     unqualified name from it, free the unqulaified name here. */
+
+  if (lease->fqdn)
+    {
+      lease->old_hostname = lease->fqdn;
+      free(lease->hostname);
+    }
+  else
+    lease->old_hostname = lease->hostname;
+
+  lease->hostname = lease->fqdn = NULL;
+}
+
+void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth)
+{
+  struct dhcp_lease *lease_tmp;
+  char *new_name = NULL, *new_fqdn = NULL;
+  
+  if (lease->hostname && name && hostname_isequal(lease->hostname, name))
+    {
+      lease->auth_name = auth;
+      return;
+    }
+  
+  if (!name && !lease->hostname)
+    return;
+
+  /* If a machine turns up on a new net without dropping the old lease,
+     or two machines claim the same name, then we end up with two interfaces with
+     the same name. Check for that here and remove the name from the old lease.
+     Don't allow a name from the client to override a name from dnsmasq config. */
+  
+  if (name)
+    {
+      if ((new_name = whine_malloc(strlen(name) + 1)))
+       {
+         char *suffix = get_domain(lease->addr);
+         strcpy(new_name, name);
+         if (suffix && (new_fqdn = whine_malloc(strlen(new_name) + strlen(suffix) + 2)))
+           {
+             strcpy(new_fqdn, name);
+             strcat(new_fqdn, ".");
+             strcat(new_fqdn, suffix);
+           }
+       }
+         
+      /* Depending on mode, we check either unqualified name or FQDN. */
+      for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next)
+       {
+         if (option_bool(OPT_DHCP_FQDN))
+           {
+             if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn) )
+               continue;
+           }
+         else
+           {
+             if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) )
+               continue; 
+           }
+         
+         if (lease_tmp->auth_name && !auth)
+           {
+             free(new_name);
+             free(new_fqdn);
+             return;
+           }
+       
+         kill_name(lease_tmp);
+         break;
+       }
+    }
+
+  if (lease->hostname)
+    kill_name(lease);
+
+  lease->hostname = new_name;
+  lease->fqdn = new_fqdn;
+  lease->auth_name = auth;
+  
+  file_dirty = 1;
+  dns_dirty = 1; 
+  lease->changed = 1; /* run script on change */
+}
+
+void lease_set_interface(struct dhcp_lease *lease, int interface)
+{
+  if (lease->last_interface == interface)
+    return;
+
+  lease->last_interface = interface;
+  lease->changed = 1;
+}
+
+void rerun_scripts(void)
+{
+  struct dhcp_lease *lease;
+  
+  for (lease = leases; lease; lease = lease->next)
+    lease->changed = 1;
+}
+
+/* deleted leases get transferred to the old_leases list.
+   remove them here, after calling the lease change
+   script. Also run the lease change script on new/modified leases.
+
+   Return zero if nothing to do. */
+int do_script_run(time_t now)
+{
+  struct dhcp_lease *lease;
+
+#ifdef HAVE_DBUS
+  /* If we're going to be sending DBus signals, but the connection is not yet up,
+     delay everything until it is. */
+  if (option_bool(OPT_DBUS) && !daemon->dbus)
+    return 0;
+#endif
+
+  if (old_leases)
+    {
+      lease = old_leases;
+                  
+      /* If the lease still has an old_hostname, do the "old" action on that first */
+      if (lease->old_hostname)
+       {
+#ifdef HAVE_SCRIPT
+         queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
+#endif
+         free(lease->old_hostname);
+         lease->old_hostname = NULL;
+         return 1;
+       }
+      else 
+       {
+         kill_name(lease);
+#ifdef HAVE_SCRIPT
+         queue_script(ACTION_DEL, lease, lease->old_hostname, now);
+#endif
+#ifdef HAVE_DBUS
+         emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname);
+#endif
+         old_leases = lease->next;
+         
+         free(lease->old_hostname); 
+         free(lease->clid);
+         free(lease->extradata);
+         free(lease);
+           
+         return 1; 
+       }
+    }
+  
+  /* make sure we announce the loss of a hostname before its new location. */
+  for (lease = leases; lease; lease = lease->next)
+    if (lease->old_hostname)
+      {        
+#ifdef HAVE_SCRIPT
+       queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
+#endif
+       free(lease->old_hostname);
+       lease->old_hostname = NULL;
+       return 1;
+      }
+  
+  for (lease = leases; lease; lease = lease->next)
+    if (lease->new || lease->changed || 
+       (lease->aux_changed && option_bool(OPT_LEASE_RO)))
+      {
+#ifdef HAVE_SCRIPT
+       queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, 
+                    lease->fqdn ? lease->fqdn : lease->hostname, now);
+#endif
+#ifdef HAVE_DBUS
+       emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease,
+                        lease->fqdn ? lease->fqdn : lease->hostname);
+#endif
+       lease->new = lease->changed = lease->aux_changed = 0;
+       
+       /* this is used for the "add" call, then junked, since they're not in the database */
+       free(lease->extradata);
+       lease->extradata = NULL;
+       
+       return 1;
+      }
+
+  return 0; /* nothing to do */
+}
+
+#endif
+         
+
+      
+
diff --git a/src/log.c b/src/log.c
new file mode 100644 (file)
index 0000000..baaae7c
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,466 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef __ANDROID__
+#  include <android/log.h>
+#endif
+
+/* Implement logging to /dev/log asynchronously. If syslogd is 
+   making DNS lookups through dnsmasq, and dnsmasq blocks awaiting
+   syslogd, then the two daemons can deadlock. We get around this
+   by not blocking when talking to syslog, instead we queue up to 
+   MAX_LOGS messages. If more are queued, they will be dropped,
+   and the drop event itself logged. */
+
+/* The "wire" protocol for logging is defined in RFC 3164 */
+
+/* From RFC 3164 */
+#define MAX_MESSAGE 1024
+
+/* defaults in case we die() before we log_start() */
+static int log_fac = LOG_DAEMON;
+static int log_stderr = 0;
+static int echo_stderr = 0;
+static int log_fd = -1;
+static int log_to_file = 0;
+static int entries_alloced = 0;
+static int entries_lost = 0;
+static int connection_good = 1;
+static int max_logs = 0;
+static int connection_type = SOCK_DGRAM;
+
+struct log_entry {
+  int offset, length;
+  pid_t pid; /* to avoid duplicates over a fork */
+  struct log_entry *next;
+  char payload[MAX_MESSAGE];
+};
+
+static struct log_entry *entries = NULL;
+static struct log_entry *free_entries = NULL;
+
+
+int log_start(struct passwd *ent_pw, int errfd)
+{
+  int ret = 0;
+
+  echo_stderr = option_bool(OPT_DEBUG);
+
+  if (daemon->log_fac != -1)
+    log_fac = daemon->log_fac;
+#ifdef LOG_LOCAL0
+  else if (option_bool(OPT_DEBUG))
+    log_fac = LOG_LOCAL0;
+#endif
+
+  if (daemon->log_file)
+    { 
+      log_to_file = 1;
+      daemon->max_logs = 0;
+      if (strcmp(daemon->log_file, "-") == 0)
+       {
+         log_stderr = 1;
+         echo_stderr = 0;
+         log_fd = dup(STDERR_FILENO);
+       }
+    }
+  
+  max_logs = daemon->max_logs;
+
+  if (!log_reopen(daemon->log_file))
+    {
+      send_event(errfd, EVENT_LOG_ERR, errno);
+      _exit(0);
+    }
+
+  /* if queuing is inhibited, make sure we allocate
+     the one required buffer now. */
+  if (max_logs == 0)
+    {  
+      free_entries = safe_malloc(sizeof(struct log_entry));
+      free_entries->next = NULL;
+      entries_alloced = 1;
+    }
+
+  /* If we're running as root and going to change uid later,
+     change the ownership here so that the file is always owned by
+     the dnsmasq user. Then logrotate can just copy the owner.
+     Failure of the chown call is OK, (for instance when started as non-root) */
+  if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0 && 
+      fchown(log_fd, ent_pw->pw_uid, -1) != 0)
+    ret = errno;
+
+  return ret;
+}
+
+int log_reopen(char *log_file)
+{
+  if (!log_stderr)
+    {      
+      if (log_fd != -1)
+       close(log_fd);
+      
+      /* NOTE: umask is set to 022 by the time this gets called */
+      
+      if (log_file)
+       log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);      
+      else
+       {
+#if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__)
+         /* Solaris logging is "different", /dev/log is not unix-domain socket.
+            Just leave log_fd == -1 and use the vsyslog call for everything.... */
+#   define _PATH_LOG ""  /* dummy */
+         return 1;
+#else
+         int flags;
+         log_fd = socket(AF_UNIX, connection_type, 0);
+         
+         /* if max_logs is zero, leave the socket blocking */
+         if (log_fd != -1 && max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1)
+           fcntl(log_fd, F_SETFL, flags | O_NONBLOCK);
+#endif
+       }
+    }
+  
+  return log_fd != -1;
+}
+
+static void free_entry(void)
+{
+  struct log_entry *tmp = entries;
+  entries = tmp->next;
+  tmp->next = free_entries;
+  free_entries = tmp;
+}      
+
+static void log_write(void)
+{
+  ssize_t rc;
+   
+  while (entries)
+    {
+      /* Avoid duplicates over a fork() */
+      if (entries->pid != getpid())
+       {
+         free_entry();
+         continue;
+       }
+
+      connection_good = 1;
+
+      if ((rc = write(log_fd, entries->payload + entries->offset, entries->length)) != -1)
+       {
+         entries->length -= rc;
+         entries->offset += rc;
+         if (entries->length == 0)
+           {
+             free_entry();
+             if (entries_lost != 0)
+               {
+                 int e = entries_lost;
+                 entries_lost = 0; /* avoid wild recursion */
+                 my_syslog(LOG_WARNING, _("overflow: %d log entries lost"), e);
+               }         
+           }
+         continue;
+       }
+      
+      if (errno == EINTR)
+       continue;
+
+      if (errno == EAGAIN)
+       return; /* syslogd busy, go again when select() or poll() says so */
+      
+      if (errno == ENOBUFS)
+       {
+         connection_good = 0;
+         return;
+       }
+
+      /* errors handling after this assumes sockets */ 
+      if (!log_to_file)
+       {
+         /* Once a stream socket hits EPIPE, we have to close and re-open
+            (we ignore SIGPIPE) */
+         if (errno == EPIPE)
+           {
+             if (log_reopen(NULL))
+               continue;
+           }
+         else if (errno == ECONNREFUSED || 
+                  errno == ENOTCONN || 
+                  errno == EDESTADDRREQ || 
+                  errno == ECONNRESET)
+           {
+             /* socket went (syslogd down?), try and reconnect. If we fail,
+                stop trying until the next call to my_syslog() 
+                ECONNREFUSED -> connection went down
+                ENOTCONN -> nobody listening
+                (ECONNRESET, EDESTADDRREQ are *BSD equivalents) */
+             
+             struct sockaddr_un logaddr;
+             
+#ifdef HAVE_SOCKADDR_SA_LEN
+             logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1; 
+#endif
+             logaddr.sun_family = AF_UNIX;
+             strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
+             
+             /* Got connection back? try again. */
+             if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1)
+               continue;
+             
+             /* errors from connect which mean we should keep trying */
+             if (errno == ENOENT || 
+                 errno == EALREADY || 
+                 errno == ECONNREFUSED ||
+                 errno == EISCONN || 
+                 errno == EINTR ||
+                 errno == EAGAIN)
+               {
+                 /* try again on next syslog() call */
+                 connection_good = 0;
+                 return;
+               }
+             
+             /* try the other sort of socket... */
+             if (errno == EPROTOTYPE)
+               {
+                 connection_type = connection_type == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM;
+                 if (log_reopen(NULL))
+                   continue;
+               }
+           }
+       }
+
+      /* give up - fall back to syslog() - this handles out-of-space
+        when logging to a file, for instance. */
+      log_fd = -1;
+      my_syslog(LOG_CRIT, _("log failed: %s"), strerror(errno));
+      return;
+    }
+}
+
+/* priority is one of LOG_DEBUG, LOG_INFO, LOG_NOTICE, etc. See sys/syslog.h.
+   OR'd to priority can be MS_TFTP, MS_DHCP, ... to be able to do log separation between
+   DNS, DHCP and TFTP services.
+*/
+void my_syslog(int priority, const char *format, ...)
+{
+  va_list ap;
+  struct log_entry *entry;
+  time_t time_now;
+  char *p;
+  size_t len;
+  pid_t pid = getpid();
+  char *func = "";
+
+  if ((LOG_FACMASK & priority) == MS_TFTP)
+    func = "-tftp";
+  else if ((LOG_FACMASK & priority) == MS_DHCP)
+    func = "-dhcp";
+      
+#ifdef LOG_PRI
+  priority = LOG_PRI(priority);
+#else
+  /* Solaris doesn't have LOG_PRI */
+  priority &= LOG_PRIMASK;
+#endif
+
+  if (echo_stderr) 
+    {
+      fprintf(stderr, "dnsmasq%s: ", func);
+      va_start(ap, format);
+      vfprintf(stderr, format, ap);
+      va_end(ap);
+      fputc('\n', stderr);
+    }
+
+  if (log_fd == -1)
+    {
+#ifdef __ANDROID__
+      /* do android-specific logging. 
+        log_fd is always -1 on Android except when logging to a file. */
+      int alog_lvl;
+      
+      if (priority <= LOG_ERR)
+       alog_lvl = ANDROID_LOG_ERROR;
+      else if (priority == LOG_WARNING)
+       alog_lvl = ANDROID_LOG_WARN;
+      else if (priority <= LOG_INFO)
+       alog_lvl = ANDROID_LOG_INFO;
+      else
+       alog_lvl = ANDROID_LOG_DEBUG;
+
+      va_start(ap, format);
+      __android_log_vprint(alog_lvl, "dnsmasq", format, ap);
+      va_end(ap);
+#else
+      /* fall-back to syslog if we die during startup or 
+        fail during running (always on Solaris). */
+      static int isopen = 0;
+
+      if (!isopen)
+       {
+         openlog("dnsmasq", LOG_PID, log_fac);
+         isopen = 1;
+       }
+      va_start(ap, format);  
+      vsyslog(priority, format, ap);
+      va_end(ap);
+#endif
+
+      return;
+    }
+  
+  if ((entry = free_entries))
+    free_entries = entry->next;
+  else if (entries_alloced < max_logs && (entry = malloc(sizeof(struct log_entry))))
+    entries_alloced++;
+  
+  if (!entry)
+    entries_lost++;
+  else
+    {
+      /* add to end of list, consumed from the start */
+      entry->next = NULL;
+      if (!entries)
+       entries = entry;
+      else
+       {
+         struct log_entry *tmp;
+         for (tmp = entries; tmp->next; tmp = tmp->next);
+         tmp->next = entry;
+       }
+      
+      time(&time_now);
+      p = entry->payload;
+      if (!log_to_file)
+       p += sprintf(p, "<%d>", priority | log_fac);
+
+      /* Omit timestamp for default daemontools situation */
+      if (!log_stderr || !option_bool(OPT_NO_FORK)) 
+       p += sprintf(p, "%.15s ", ctime(&time_now) + 4);
+      
+      p += sprintf(p, "dnsmasq%s[%d]: ", func, (int)pid);
+        
+      len = p - entry->payload;
+      va_start(ap, format);  
+      len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */
+      va_end(ap);
+      entry->length = len > MAX_MESSAGE ? MAX_MESSAGE : len;
+      entry->offset = 0;
+      entry->pid = pid;
+
+      /* replace terminator with \n */
+      if (log_to_file)
+       entry->payload[entry->length - 1] = '\n';
+    }
+  
+  /* almost always, logging won't block, so try and write this now,
+     to save collecting too many log messages during a select loop. */
+  log_write();
+  
+  /* Since we're doing things asynchronously, a cache-dump, for instance,
+     can now generate log lines very fast. With a small buffer (desirable),
+     that means it can overflow the log-buffer very quickly,
+     so that the cache dump becomes mainly a count of how many lines 
+     overflowed. To avoid this, we delay here, the delay is controlled 
+     by queue-occupancy, and grows exponentially. The delay is limited to (2^8)ms.
+     The scaling stuff ensures that when the queue is bigger than 8, the delay
+     only occurs for the last 8 entries. Once the queue is full, we stop delaying
+     to preserve performance.
+  */
+
+  if (entries && max_logs != 0)
+    {
+      int d;
+      
+      for (d = 0,entry = entries; entry; entry = entry->next, d++);
+      
+      if (d == max_logs)
+       d = 0;
+      else if (max_logs > 8)
+       d -= max_logs - 8;
+
+      if (d > 0)
+       {
+         struct timespec waiter;
+         waiter.tv_sec = 0;
+         waiter.tv_nsec = 1000000 << (d - 1); /* 1 ms */
+         nanosleep(&waiter, NULL);
+      
+         /* Have another go now */
+         log_write();
+       }
+    } 
+}
+
+void set_log_writer(fd_set *set, int *maxfdp)
+{
+  if (entries && log_fd != -1 && connection_good)
+    {
+      FD_SET(log_fd, set);
+      bump_maxfd(log_fd, maxfdp);
+    }
+}
+
+void check_log_writer(fd_set *set)
+{
+  if (log_fd != -1 && (!set || FD_ISSET(log_fd, set)))
+    log_write();
+}
+
+void flush_log(void)
+{
+  /* write until queue empty, but don't loop forever if there's
+   no connection to the syslog in existance */
+  while (log_fd != -1)
+    {
+      struct timespec waiter;
+      log_write();
+      if (!entries || !connection_good)
+       {
+         close(log_fd);        
+         break;
+       }
+      waiter.tv_sec = 0;
+      waiter.tv_nsec = 1000000; /* 1 ms */
+      nanosleep(&waiter, NULL);
+    }
+}
+
+void die(char *message, char *arg1, int exit_code)
+{
+  char *errmess = strerror(errno);
+  
+  if (!arg1)
+    arg1 = errmess;
+
+  if (!log_stderr)
+    {
+      echo_stderr = 1; /* print as well as log when we die.... */
+      fputc('\n', stderr); /* prettyfy  startup-script message */
+    }
+  my_syslog(LOG_CRIT, message, arg1, errmess);
+  echo_stderr = 0;
+  my_syslog(LOG_CRIT, _("FAILED to start up"));
+  flush_log();
+  
+  exit(exit_code);
+}
diff --git a/src/netlink.c b/src/netlink.c
new file mode 100644 (file)
index 0000000..f6da7db
--- /dev/null
@@ -0,0 +1,326 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_LINUX_NETWORK
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+/* linux 2.6.19 buggers up the headers, patch it up here. */ 
+#ifndef IFA_RTA
+#  define IFA_RTA(r)  \
+       ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+
+#  include <linux/if_addr.h>
+#endif
+
+#ifndef NDA_RTA
+#  define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) 
+#endif 
+
+static struct iovec iov;
+static u32 netlink_pid;
+
+static void nl_err(struct nlmsghdr *h);
+static void nl_routechange(struct nlmsghdr *h);
+
+void netlink_init(void)
+{
+  struct sockaddr_nl addr;
+  socklen_t slen = sizeof(addr);
+
+  addr.nl_family = AF_NETLINK;
+  addr.nl_pad = 0;
+  addr.nl_pid = 0; /* autobind */
+#ifdef HAVE_IPV6
+  addr.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
+#else
+  addr.nl_groups = RTMGRP_IPV4_ROUTE;
+#endif
+  
+  /* May not be able to have permission to set multicast groups don't die in that case */
+  if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1)
+    {
+      if (bind(daemon->netlinkfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+       {
+         addr.nl_groups = 0;
+         if (errno != EPERM || bind(daemon->netlinkfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+           daemon->netlinkfd = -1;
+       }
+    }
+  
+  if (daemon->netlinkfd == -1 || 
+      getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == 1)
+    die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
+   
+  /* save pid assigned by bind() and retrieved by getsockname() */ 
+  netlink_pid = addr.nl_pid;
+  
+  iov.iov_len = 100;
+  iov.iov_base = safe_malloc(iov.iov_len);
+}
+
+static ssize_t netlink_recv(void)
+{
+  struct msghdr msg;
+  struct sockaddr_nl nladdr;
+  ssize_t rc;
+
+  while (1)
+    {
+      msg.msg_control = NULL;
+      msg.msg_controllen = 0;
+      msg.msg_name = &nladdr;
+      msg.msg_namelen = sizeof(nladdr);
+      msg.msg_iov = &iov;
+      msg.msg_iovlen = 1;
+      msg.msg_flags = 0;
+      
+      while ((rc = recvmsg(daemon->netlinkfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
+      
+      /* make buffer big enough */
+      if (rc != -1 && (msg.msg_flags & MSG_TRUNC))
+       {
+         /* Very new Linux kernels return the actual size needed, older ones always return truncated size */
+         if ((size_t)rc == iov.iov_len)
+           {
+             if (expand_buf(&iov, rc + 100))
+               continue;
+           }
+         else
+           expand_buf(&iov, rc);
+       }
+
+      /* read it for real */
+      msg.msg_flags = 0;
+      while ((rc = recvmsg(daemon->netlinkfd, &msg, 0)) == -1 && errno == EINTR);
+      
+      /* Make sure this is from the kernel */
+      if (rc == -1 || nladdr.nl_pid == 0)
+       break;
+    }
+      
+  /* discard stuff which is truncated at this point (expand_buf() may fail) */
+  if (msg.msg_flags & MSG_TRUNC)
+    {
+      rc = -1;
+      errno = ENOMEM;
+    }
+  
+  return rc;
+}
+  
+
+/* family = AF_UNSPEC finds ARP table entries. */
+int iface_enumerate(int family, void *parm, int (*callback)())
+{
+  struct sockaddr_nl addr;
+  struct nlmsghdr *h;
+  ssize_t len;
+  static unsigned int seq = 0;
+
+  struct {
+    struct nlmsghdr nlh;
+    struct rtgenmsg g; 
+  } req;
+
+  addr.nl_family = AF_NETLINK;
+  addr.nl_pad = 0;
+  addr.nl_groups = 0;
+  addr.nl_pid = 0; /* address to kernel */
+
+ again:
+  req.nlh.nlmsg_len = sizeof(req);
+  req.nlh.nlmsg_type = family == AF_UNSPEC ? RTM_GETNEIGH : RTM_GETADDR;
+  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK; 
+  req.nlh.nlmsg_pid = 0;
+  req.nlh.nlmsg_seq = ++seq;
+  req.g.rtgen_family = family; 
+
+  /* Don't block in recvfrom if send fails */
+  while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, 
+                     (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
+  
+  if (len == -1)
+    return 0;
+    
+  while (1)
+    {
+      if ((len = netlink_recv()) == -1)
+       {
+         if (errno == ENOBUFS)
+           {
+             sleep(1);
+             goto again;
+           }
+         return 0;
+       }
+
+      for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
+       if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid)
+         nl_routechange(h); /* May be multicast arriving async */
+       else if (h->nlmsg_type == NLMSG_ERROR)
+         nl_err(h);
+       else if (h->nlmsg_type == NLMSG_DONE)
+         return 1;
+       else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC)
+         {
+           struct ifaddrmsg *ifa = NLMSG_DATA(h);  
+           struct rtattr *rta = IFA_RTA(ifa);
+           unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
+           
+           if (ifa->ifa_family == family)
+             {
+               if (ifa->ifa_family == AF_INET)
+                 {
+                   struct in_addr netmask, addr, broadcast;
+                   
+                   netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
+                   addr.s_addr = 0;
+                   broadcast.s_addr = 0;
+                   
+                   while (RTA_OK(rta, len1))
+                     {
+                       if (rta->rta_type == IFA_LOCAL)
+                         addr = *((struct in_addr *)(rta+1));
+                       else if (rta->rta_type == IFA_BROADCAST)
+                         broadcast = *((struct in_addr *)(rta+1));
+                       
+                       rta = RTA_NEXT(rta, len1);
+                     }
+                   
+                   if (addr.s_addr)
+                     if (!((*callback)(addr, ifa->ifa_index, netmask, broadcast, parm)))
+                       return 0;
+                 }
+#ifdef HAVE_IPV6
+               else if (ifa->ifa_family == AF_INET6)
+                 {
+                   struct in6_addr *addrp = NULL;
+                   while (RTA_OK(rta, len1))
+                     {
+                       if (rta->rta_type == IFA_ADDRESS)
+                         addrp = ((struct in6_addr *)(rta+1)); 
+                       
+                       rta = RTA_NEXT(rta, len1);
+                     }
+                   
+                   if (addrp)
+                     if (!((*callback)(addrp, ifa->ifa_index, ifa->ifa_index, parm)))
+                       return 0;
+                 }
+#endif
+             }
+         }
+       else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC)
+         {
+           struct ndmsg *neigh = NLMSG_DATA(h);  
+           struct rtattr *rta = NDA_RTA(neigh);
+           unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*neigh));
+           size_t maclen = 0;
+           char *inaddr = NULL, *mac = NULL;
+           
+           while (RTA_OK(rta, len1))
+             {
+               if (rta->rta_type == NDA_DST)
+                 inaddr = (char *)(rta+1);
+               else if (rta->rta_type == NDA_LLADDR)
+                 {
+                   maclen = rta->rta_len - sizeof(struct rtattr);
+                   mac = (char *)(rta+1);
+                 }
+               
+               rta = RTA_NEXT(rta, len1);
+             }
+
+           if (inaddr && mac)
+             if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
+               return 0;
+         }     
+    }
+}
+
+void netlink_multicast(void)
+{
+  ssize_t len;
+  struct nlmsghdr *h;
+  int flags;
+  
+  /* don't risk blocking reading netlink messages here. */
+  if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
+      fcntl(daemon->netlinkfd, F_SETFL, flags | O_NONBLOCK) == -1) 
+    return;
+  
+  if ((len = netlink_recv()) != -1)
+    {
+      for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
+       if (h->nlmsg_type == NLMSG_ERROR)
+         nl_err(h);
+       else
+         nl_routechange(h);
+    }
+
+  /* restore non-blocking status */
+  fcntl(daemon->netlinkfd, F_SETFL, flags); 
+}
+
+static void nl_err(struct nlmsghdr *h)
+{
+  struct nlmsgerr *err = NLMSG_DATA(h);
+  
+  if (err->error != 0)
+    my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
+}
+
+/* We arrange to receive netlink multicast messages whenever the network route is added.
+   If this happens and we still have a DNS packet in the buffer, we re-send it.
+   This helps on DoD links, where frequently the packet which triggers dialling is
+   a DNS query, which then gets lost. By re-sending, we can avoid the lookup
+   failing. Note that we only accept these messages from the kernel (pid == 0) */ 
+static void nl_routechange(struct nlmsghdr *h)
+{
+  if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
+    {
+      struct rtmsg *rtm = NLMSG_DATA(h);
+      int fd;
+
+      if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK)
+       return;
+
+      /* Force re-reading resolv file right now, for luck. */
+      daemon->last_resolv = 0;
+      
+      if (daemon->srv_save)
+       {
+         if (daemon->srv_save->sfd)
+           fd = daemon->srv_save->sfd->fd;
+         else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
+           fd = daemon->rfd_save->fd;
+         else
+           return;
+         
+         while(sendto(fd, daemon->packet, daemon->packet_len, 0,
+                      &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send()); 
+       }
+    }
+}
+
+#endif
+
+      
diff --git a/src/network.c b/src/network.c
new file mode 100644 (file)
index 0000000..7b2e905
--- /dev/null
@@ -0,0 +1,973 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_LINUX_NETWORK
+
+int indextoname(int fd, int index, char *name)
+{
+  struct ifreq ifr;
+  
+  if (index == 0)
+    return 0;
+
+  ifr.ifr_ifindex = index;
+  if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
+    return 0;
+
+  strncpy(name, ifr.ifr_name, IF_NAMESIZE);
+
+  return 1;
+}
+
+
+#elif defined(HAVE_SOLARIS_NETWORK)
+
+#include <zone.h>
+#include <alloca.h>
+#ifndef LIFC_UNDER_IPMP
+#  define LIFC_UNDER_IPMP 0
+#endif
+
+int indextoname(int fd, int index, char *name)
+{
+  int64_t lifc_flags;
+  struct lifnum lifn;
+  int numifs, bufsize, i;
+  struct lifconf lifc;
+  struct lifreq *lifrp;
+  
+  if (index == 0)
+    return 0;
+  
+  if (getzoneid() == GLOBAL_ZONEID) 
+    {
+      if (!if_indextoname(index, name))
+       return 0;
+      return 1;
+    }
+  
+  lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
+  lifn.lifn_family = AF_UNSPEC;
+  lifn.lifn_flags = lifc_flags;
+  if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0) 
+    return 0;
+  
+  numifs = lifn.lifn_count;
+  bufsize = numifs * sizeof(struct lifreq);
+  
+  lifc.lifc_family = AF_UNSPEC;
+  lifc.lifc_flags = lifc_flags;
+  lifc.lifc_len = bufsize;
+  lifc.lifc_buf = alloca(bufsize);
+  
+  if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)  
+    return 0;
+  
+  lifrp = lifc.lifc_req;
+  for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++) 
+    {
+      struct lifreq lifr;
+      strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
+      if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0) 
+       return 0;
+      
+      if (lifr.lifr_index == index) {
+       strncpy(name, lifr.lifr_name, IF_NAMESIZE);
+       return 1;
+      }
+    }
+  return 0;
+}
+
+
+#else
+
+int indextoname(int fd, int index, char *name)
+{ 
+  if (index == 0 || !if_indextoname(index, name))
+    return 0;
+
+  return 1;
+}
+
+#endif
+
+int iface_check(int family, struct all_addr *addr, char *name, int *indexp)
+{
+  struct iname *tmp;
+  int ret = 1;
+
+  /* Note: have to check all and not bail out early, so that we set the
+     "used" flags. */
+  
+  if (daemon->if_names || (addr && daemon->if_addrs))
+    {
+#ifdef HAVE_DHCP
+      struct dhcp_context *range;
+#endif
+
+      ret = 0;
+
+#ifdef HAVE_DHCP
+      for (range = daemon->dhcp; range; range = range->next)
+       if (range->interface && strcmp(range->interface, name) == 0)
+         ret = 1;
+#endif
+
+      for (tmp = daemon->if_names; tmp; tmp = tmp->next)
+       if (tmp->name && (strcmp(tmp->name, name) == 0))
+         ret = tmp->used = 1;
+               
+      for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
+       if (addr && tmp->addr.sa.sa_family == family)
+         {
+           if (family == AF_INET &&
+               tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
+             ret = tmp->used = 1;
+#ifdef HAVE_IPV6
+           else if (family == AF_INET6 &&
+                    IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, 
+                                       &addr->addr.addr6))
+             ret = tmp->used = 1;
+#endif
+         }          
+    }
+  
+  for (tmp = daemon->if_except; tmp; tmp = tmp->next)
+    if (tmp->name && (strcmp(tmp->name, name) == 0))
+      ret = 0;
+  
+  if (indexp)
+    {
+      /* One form of bridging on BSD has the property that packets
+        can be recieved on bridge interfaces which do not have an IP address.
+        We allow these to be treated as aliases of another interface which does have
+        an IP address with --dhcp-bridge=interface,alias,alias */
+      struct dhcp_bridge *bridge, *alias;
+      for (bridge = daemon->bridges; bridge; bridge = bridge->next)
+       {
+         for (alias = bridge->alias; alias; alias = alias->next)
+           if (strncmp(name, alias->iface, IF_NAMESIZE) == 0)
+             {
+               int newindex;
+               
+               if (!(newindex = if_nametoindex(bridge->iface)))
+                 {
+                   my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), name);
+                   return 0;
+                 }
+               else 
+                 {
+                   *indexp = newindex;
+                   strncpy(name,  bridge->iface, IF_NAMESIZE);
+                   break;
+                 }
+             }
+         if (alias)
+           break;
+       }
+    }
+  
+  return ret; 
+}
+      
+static int iface_allowed(struct irec **irecp, int if_index, 
+                        union mysockaddr *addr, struct in_addr netmask) 
+{
+  struct irec *iface;
+  int fd, mtu = 0, loopback;
+  struct ifreq ifr;
+  int tftp_ok = daemon->tftp_unlimited;
+#ifdef HAVE_DHCP
+  struct iname *tmp;
+#endif
+  struct interface_list *ir = NULL;
+
+  /* check whether the interface IP has been added already 
+     we call this routine multiple times. */
+  for (iface = *irecp; iface; iface = iface->next) 
+    if (sockaddr_isequal(&iface->addr, addr))
+      return 1;
+  
+  if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
+      !indextoname(fd, if_index, ifr.ifr_name) ||
+      ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
+    {
+      if (fd != -1)
+       {
+         int errsave = errno;
+         close(fd);
+         errno = errsave;
+       }
+      return 0;
+    }
+   
+  loopback = ifr.ifr_flags & IFF_LOOPBACK;
+
+  if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
+    mtu = ifr.ifr_mtu;
+  
+  close(fd);
+  
+  /* If we are restricting the set of interfaces to use, make
+     sure that loopback interfaces are in that set. */
+  if (daemon->if_names && loopback)
+    {
+      struct iname *lo;
+      for (lo = daemon->if_names; lo; lo = lo->next)
+       if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
+         {
+           lo->isloop = 1;
+           break;
+         }
+      
+      if (!lo && 
+         (lo = whine_malloc(sizeof(struct iname))) &&
+         (lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
+       {
+         strcpy(lo->name, ifr.ifr_name);
+         lo->isloop = lo->used = 1;
+         lo->next = daemon->if_names;
+         daemon->if_names = lo;
+       }
+    }
+  
+#ifdef HAVE_TFTP
+  /* implement wierd TFTP service rules */
+  for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
+    if (strcmp(ir->interface, ifr.ifr_name) == 0)
+      {
+       tftp_ok = 1;
+       break;
+      }
+#endif
+  
+  if (!ir)
+    {
+      if (addr->sa.sa_family == AF_INET &&
+         !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL))
+       return 1;
+      
+#ifdef HAVE_DHCP
+      for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+       if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
+         tftp_ok = 0;
+#endif
+      
+#ifdef HAVE_IPV6
+      if (addr->sa.sa_family == AF_INET6 &&
+         !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL))
+       return 1;
+#endif
+    }
+
+  /* add to list */
+  if ((iface = whine_malloc(sizeof(struct irec))))
+    {
+      iface->addr = *addr;
+      iface->netmask = netmask;
+      iface->tftp_ok = tftp_ok;
+      iface->mtu = mtu;
+      if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
+       strcpy(iface->name, ifr.ifr_name);
+      iface->next = *irecp;
+      *irecp = iface;
+      return 1;
+    }
+  
+  errno = ENOMEM; 
+  return 0;
+}
+
+#ifdef HAVE_IPV6
+static int iface_allowed_v6(struct in6_addr *local, 
+                           int scope, int if_index, void *vparam)
+{
+  union mysockaddr addr;
+  struct in_addr netmask; /* dummy */
+  
+  netmask.s_addr = 0;
+  
+  memset(&addr, 0, sizeof(addr));
+#ifdef HAVE_SOCKADDR_SA_LEN
+  addr.in6.sin6_len = sizeof(addr.in6);
+#endif
+  addr.in6.sin6_family = AF_INET6;
+  addr.in6.sin6_addr = *local;
+  addr.in6.sin6_port = htons(daemon->port);
+  addr.in6.sin6_scope_id = scope;
+  
+  return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
+}
+#endif
+
+static int iface_allowed_v4(struct in_addr local, int if_index, 
+                           struct in_addr netmask, struct in_addr broadcast, void *vparam)
+{
+  union mysockaddr addr;
+
+  memset(&addr, 0, sizeof(addr));
+#ifdef HAVE_SOCKADDR_SA_LEN
+  addr.in.sin_len = sizeof(addr.in);
+#endif
+  addr.in.sin_family = AF_INET;
+  addr.in.sin_addr = broadcast; /* warning */
+  addr.in.sin_addr = local;
+  addr.in.sin_port = htons(daemon->port);
+
+  return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
+}
+   
+int enumerate_interfaces(void)
+{
+#ifdef HAVE_IPV6
+  if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6))
+    return 0; 
+#endif
+
+  return iface_enumerate(AF_INET, &daemon->interfaces, iface_allowed_v4); 
+}
+
+/* set NONBLOCK bit on fd: See Stevens 16.6 */
+int fix_fd(int fd)
+{
+  int flags;
+
+  if ((flags = fcntl(fd, F_GETFL)) == -1 ||
+      fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
+    return 0;
+  
+  return 1;
+}
+
+static int make_sock(union mysockaddr *addr, int type)
+{
+  int family = addr->sa.sa_family;
+  int fd, rc, opt = 1;
+#ifdef HAVE_IPV6
+  static int dad_count = 0;
+#endif
+  
+  if ((fd = socket(family, type, 0)) == -1)
+    {
+      int port;
+
+      /* No error if the kernel just doesn't support this IP flavour */
+      if (errno == EPROTONOSUPPORT ||
+         errno == EAFNOSUPPORT ||
+         errno == EINVAL)
+       return -1;
+      
+    err:
+      port = prettyprint_addr(addr, daemon->namebuff);
+      if (!option_bool(OPT_NOWILD))
+       sprintf(daemon->namebuff, "port %d", port);
+      die(_("failed to create listening socket for %s: %s"), 
+         daemon->namebuff, EC_BADNET);
+    }  
+
+  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
+    goto err;
+  
+#ifdef HAVE_IPV6
+  if (family == AF_INET6 && setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
+    goto err;
+#endif
+  
+  while (1)
+    {
+      if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) != -1)
+       break;
+      
+#ifdef HAVE_IPV6
+      /* An interface may have an IPv6 address which is still undergoing DAD. 
+        If so, the bind will fail until the DAD completes, so we try over 20 seconds
+        before failing. */
+      if (family == AF_INET6 && 
+         (errno == ENODEV || errno == EADDRNOTAVAIL) && 
+         dad_count++ < DAD_WAIT)
+       {
+         sleep(1);
+         continue;
+       }
+#endif
+      break;
+    }
+  
+  if (rc == -1)
+    goto err;
+  
+  if (type == SOCK_STREAM)
+    {
+      if (listen(fd, 5) == -1)
+       goto err;
+    }
+  else if (!option_bool(OPT_NOWILD))
+    {
+      if (family == AF_INET)
+       {
+#if defined(HAVE_LINUX_NETWORK) 
+         if (setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
+           goto err;
+#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+         if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
+             setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
+           goto err;
+#endif
+       }
+#ifdef HAVE_IPV6
+      else
+       {
+         /* The API changed around Linux 2.6.14 but the old ABI is still supported:
+            handle all combinations of headers and kernel.
+            OpenWrt note that this fixes the problem addressed by your very broken patch. */
+         daemon->v6pktinfo = IPV6_PKTINFO;
+         
+#  ifdef IPV6_RECVPKTINFO
+#    ifdef IPV6_2292PKTINFO
+         if (setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1)
+           {
+             if (errno == ENOPROTOOPT && setsockopt(fd, IPV6_LEVEL, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
+               daemon->v6pktinfo = IPV6_2292PKTINFO;
+             else
+               goto err;
+           }
+#    else
+         if (setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1)
+           goto err;
+#    endif 
+#  else
+         if (setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1)
+           goto err;
+#  endif
+       }
+#endif
+    }
+
+  return fd;
+}
+      
+static struct listener *create_listeners(union mysockaddr *addr, int do_tftp)
+{
+  struct listener *l = NULL;
+  int fd = -1, tcpfd = -1, tftpfd = -1;
+
+  if (daemon->port != 0)
+    {
+      fd = make_sock(addr, SOCK_DGRAM);
+      tcpfd = make_sock(addr, SOCK_STREAM);
+    }
+  
+#ifdef HAVE_TFTP
+  if (do_tftp)
+    {
+      if (addr->sa.sa_family == AF_INET)
+       {
+         /* port must be restored to DNS port for TCP code */
+         short save = addr->in.sin_port;
+         addr->in.sin_port = htons(TFTP_PORT);
+         tftpfd = make_sock(addr, SOCK_DGRAM);
+         addr->in.sin_port = save;
+       }
+#  ifdef HAVE_IPV6
+      else
+       {
+         short save = addr->in6.sin6_port;
+         addr->in6.sin6_port = htons(TFTP_PORT);
+         tftpfd = make_sock(addr, SOCK_DGRAM);
+         addr->in6.sin6_port = save;
+       }  
+#  endif
+    }
+#endif
+
+  if (fd != -1 || tcpfd != -1 || tftpfd != -1)
+    {
+      l = safe_malloc(sizeof(struct listener));
+      l->next = NULL;
+      l->family = addr->sa.sa_family;
+      l->fd = fd;
+      l->tcpfd = tcpfd;
+      l->tftpfd = tftpfd;
+    }
+
+  return l;
+}
+
+struct listener *create_wildcard_listeners(void)
+{
+  union mysockaddr addr;
+  struct listener *l;
+  int tftp_enabled = daemon->tftp_unlimited || daemon->tftp_interfaces; 
+
+  memset(&addr, 0, sizeof(addr));
+#ifdef HAVE_SOCKADDR_SA_LEN
+  addr.in.sin_len = sizeof(addr.in);
+#endif
+  addr.in.sin_family = AF_INET;
+  addr.in.sin_addr.s_addr = INADDR_ANY;
+  addr.in.sin_port = htons(daemon->port);
+
+  l = create_listeners(&addr, tftp_enabled);
+
+#ifdef HAVE_IPV6
+  memset(&addr, 0, sizeof(addr));
+#  ifdef HAVE_SOCKADDR_SA_LEN
+  addr.in6.sin6_len = sizeof(addr.in6);
+#  endif
+  addr.in6.sin6_family = AF_INET6;
+  addr.in6.sin6_addr = in6addr_any;
+  addr.in6.sin6_port = htons(daemon->port);
+  
+  if (l) 
+    l->next = create_listeners(&addr, tftp_enabled);
+  else 
+    l = create_listeners(&addr, tftp_enabled);
+#endif
+
+  return l;
+}
+
+struct listener *create_bound_listeners(void)
+{
+  struct listener *new, *listeners = NULL;
+  struct irec *iface;
+
+  for (iface = daemon->interfaces; iface; iface = iface->next)
+    if ((new = create_listeners(&iface->addr, iface->tftp_ok)))
+      {
+       new->iface = iface;
+       new->next = listeners;
+       listeners = new;
+      }
+  
+  return listeners;
+}
+
+
+/* return a UDP socket bound to a random port, have to cope with straying into
+   occupied port nos and reserved ones. */
+int random_sock(int family)
+{
+  int fd;
+
+  if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
+    {
+      union mysockaddr addr;
+      unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
+      int tries = ports_avail < 30 ? 3 * ports_avail : 100;
+
+      memset(&addr, 0, sizeof(addr));
+      addr.sa.sa_family = family;
+
+      /* don't loop forever if all ports in use. */
+
+      if (fix_fd(fd))
+       while(tries--)
+         {
+           unsigned short port = rand16();
+           
+           if (daemon->min_port != 0)
+             port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
+           
+           if (family == AF_INET) 
+             {
+               addr.in.sin_addr.s_addr = INADDR_ANY;
+               addr.in.sin_port = port;
+#ifdef HAVE_SOCKADDR_SA_LEN
+               addr.in.sin_len = sizeof(struct sockaddr_in);
+#endif
+             }
+#ifdef HAVE_IPV6
+           else
+             {
+               addr.in6.sin6_addr = in6addr_any; 
+               addr.in6.sin6_port = port;
+#ifdef HAVE_SOCKADDR_SA_LEN
+               addr.in6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+             }
+#endif
+           
+           if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
+             return fd;
+           
+           if (errno != EADDRINUSE && errno != EACCES)
+             break;
+         }
+
+      close(fd);
+    }
+
+  return -1; 
+}
+  
+
+int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
+{
+  union mysockaddr addr_copy = *addr;
+
+  /* cannot set source _port_ for TCP connections. */
+  if (is_tcp)
+    {
+      if (addr_copy.sa.sa_family == AF_INET)
+       addr_copy.in.sin_port = 0;
+#ifdef HAVE_IPV6
+      else
+       addr_copy.in6.sin6_port = 0;
+#endif
+    }
+  
+  if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
+    return 0;
+    
+#if defined(SO_BINDTODEVICE)
+  if (intname[0] != 0 &&
+      setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
+    return 0;
+#endif
+
+  return 1;
+}
+
+static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
+{
+  struct serverfd *sfd;
+  int errsave;
+
+  /* when using random ports, servers which would otherwise use
+     the INADDR_ANY/port0 socket have sfd set to NULL */
+  if (!daemon->osport && intname[0] == 0)
+    {
+      errno = 0;
+      
+      if (addr->sa.sa_family == AF_INET &&
+         addr->in.sin_addr.s_addr == INADDR_ANY &&
+         addr->in.sin_port == htons(0)) 
+       return NULL;
+
+#ifdef HAVE_IPV6
+      if (addr->sa.sa_family == AF_INET6 &&
+         memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
+         addr->in6.sin6_port == htons(0)) 
+       return NULL;
+#endif
+    }
+      
+  /* may have a suitable one already */
+  for (sfd = daemon->sfds; sfd; sfd = sfd->next )
+    if (sockaddr_isequal(&sfd->source_addr, addr) &&
+       strcmp(intname, sfd->interface) == 0)
+      return sfd;
+  
+  /* need to make a new one. */
+  errno = ENOMEM; /* in case malloc fails. */
+  if (!(sfd = whine_malloc(sizeof(struct serverfd))))
+    return NULL;
+  
+  if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
+    {
+      free(sfd);
+      return NULL;
+    }
+  
+  if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
+    { 
+      errsave = errno; /* save error from bind. */
+      close(sfd->fd);
+      free(sfd);
+      errno = errsave;
+      return NULL;
+    }
+    
+  strcpy(sfd->interface, intname); 
+  sfd->source_addr = *addr;
+  sfd->next = daemon->sfds;
+  daemon->sfds = sfd;
+  return sfd; 
+}
+
+/* create upstream sockets during startup, before root is dropped which may be needed
+   this allows query_port to be a low port and interface binding */
+void pre_allocate_sfds(void)
+{
+  struct server *srv;
+  
+  if (daemon->query_port != 0)
+    {
+      union  mysockaddr addr;
+      memset(&addr, 0, sizeof(addr));
+      addr.in.sin_family = AF_INET;
+      addr.in.sin_addr.s_addr = INADDR_ANY;
+      addr.in.sin_port = htons(daemon->query_port);
+#ifdef HAVE_SOCKADDR_SA_LEN
+      addr.in.sin_len = sizeof(struct sockaddr_in);
+#endif
+      allocate_sfd(&addr, "");
+#ifdef HAVE_IPV6
+      memset(&addr, 0, sizeof(addr));
+      addr.in6.sin6_family = AF_INET6;
+      addr.in6.sin6_addr = in6addr_any;
+      addr.in6.sin6_port = htons(daemon->query_port);
+#ifdef HAVE_SOCKADDR_SA_LEN
+      addr.in6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+      allocate_sfd(&addr, "");
+#endif
+    }
+  
+  for (srv = daemon->servers; srv; srv = srv->next)
+    if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
+       !allocate_sfd(&srv->source_addr, srv->interface) &&
+       errno != 0 &&
+       option_bool(OPT_NOWILD))
+      {
+       prettyprint_addr(&srv->source_addr, daemon->namebuff);
+       if (srv->interface[0] != 0)
+         {
+           strcat(daemon->namebuff, " ");
+           strcat(daemon->namebuff, srv->interface);
+         }
+       die(_("failed to bind server socket for %s: %s"),
+           daemon->namebuff, EC_BADNET);
+      }  
+}
+
+
+void check_servers(void)
+{
+  struct irec *iface;
+  struct server *new, *tmp, *ret = NULL;
+  int port = 0;
+
+  /* interface may be new since startup */
+  if (!option_bool(OPT_NOWILD))
+    enumerate_interfaces();
+  
+  for (new = daemon->servers; new; new = tmp)
+    {
+      tmp = new->next;
+      
+      if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
+       {
+         port = prettyprint_addr(&new->addr, daemon->namebuff);
+
+         /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
+         if (new->addr.sa.sa_family == AF_INET &&
+             new->addr.in.sin_addr.s_addr == 0)
+           {
+             free(new);
+             continue;
+           }
+
+         for (iface = daemon->interfaces; iface; iface = iface->next)
+           if (sockaddr_isequal(&new->addr, &iface->addr))
+             break;
+         if (iface)
+           {
+             my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
+             free(new);
+             continue;
+           }
+         
+         /* Do we need a socket set? */
+         if (!new->sfd && 
+             !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
+             errno != 0)
+           {
+             my_syslog(LOG_WARNING, 
+                       _("ignoring nameserver %s - cannot make/bind socket: %s"),
+                       daemon->namebuff, strerror(errno));
+             free(new);
+             continue;
+           }
+       }
+      
+      /* reverse order - gets it right. */
+      new->next = ret;
+      ret = new;
+      
+      if (!(new->flags & SERV_NO_REBIND))
+       {
+         if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
+           {
+             char *s1, *s2;
+             if (!(new->flags & SERV_HAS_DOMAIN))
+               s1 = _("unqualified"), s2 = _("names");
+             else if (strlen(new->domain) == 0)
+               s1 = _("default"), s2 = "";
+             else
+               s1 = _("domain"), s2 = new->domain;
+             
+             if (new->flags & SERV_NO_ADDR)
+               my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
+             else if (new->flags & SERV_USE_RESOLV)
+               my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
+             else if (!(new->flags & SERV_LITERAL_ADDRESS))
+               my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
+           }
+         else if (new->interface[0] != 0)
+           my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface); 
+         else
+           my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 
+       }
+    }
+  
+  daemon->servers = ret;
+}
+
+/* Return zero if no servers found, in that case we keep polling.
+   This is a protection against an update-time/write race on resolv.conf */
+int reload_servers(char *fname)
+{
+  FILE *f;
+  char *line;
+  struct server *old_servers = NULL;
+  struct server *new_servers = NULL;
+  struct server *serv;
+  int gotone = 0;
+
+  /* buff happens to be MAXDNAME long... */
+  if (!(f = fopen(fname, "r")))
+    {
+      my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
+      return 0;
+    }
+  
+  /* move old servers to free list - we can reuse the memory 
+     and not risk malloc if there are the same or fewer new servers. 
+     Servers which were specced on the command line go to the new list. */
+  for (serv = daemon->servers; serv;)
+    {
+      struct server *tmp = serv->next;
+      if (serv->flags & SERV_FROM_RESOLV)
+       {
+         serv->next = old_servers;
+         old_servers = serv; 
+         /* forward table rules reference servers, so have to blow them away */
+         server_gone(serv);
+       }
+      else
+       {
+         serv->next = new_servers;
+         new_servers = serv;
+       }
+      serv = tmp;
+    }
+  
+  while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
+    {
+      union mysockaddr addr, source_addr;
+      char *token = strtok(line, " \t\n\r");
+      
+      if (!token)
+       continue;
+      if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
+       continue;
+      if (!(token = strtok(NULL, " \t\n\r")))
+       continue;
+      
+      memset(&addr, 0, sizeof(addr));
+      memset(&source_addr, 0, sizeof(source_addr));
+      
+      if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
+       {
+#ifdef HAVE_SOCKADDR_SA_LEN
+         source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
+#endif
+         source_addr.in.sin_family = addr.in.sin_family = AF_INET;
+         addr.in.sin_port = htons(NAMESERVER_PORT);
+         source_addr.in.sin_addr.s_addr = INADDR_ANY;
+         source_addr.in.sin_port = htons(daemon->query_port);
+       }
+#ifdef HAVE_IPV6
+      else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
+       {
+#ifdef HAVE_SOCKADDR_SA_LEN
+         source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
+#endif
+         source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
+         addr.in6.sin6_port = htons(NAMESERVER_PORT);
+         source_addr.in6.sin6_addr = in6addr_any;
+         source_addr.in6.sin6_port = htons(daemon->query_port);
+       }
+#endif /* IPV6 */
+      else
+       continue;
+      
+      if (old_servers)
+       {
+         serv = old_servers;
+         old_servers = old_servers->next;
+       }
+      else if (!(serv = whine_malloc(sizeof (struct server))))
+       continue;
+      
+      /* this list is reverse ordered: 
+        it gets reversed again in check_servers */
+      serv->next = new_servers;
+      new_servers = serv;
+      serv->addr = addr;
+      serv->source_addr = source_addr;
+      serv->domain = NULL;
+      serv->interface[0] = 0;
+      serv->sfd = NULL;
+      serv->flags = SERV_FROM_RESOLV;
+      serv->queries = serv->failed_queries = 0;
+      gotone = 1;
+    }
+  
+  /* Free any memory not used. */
+  while (old_servers)
+    {
+      struct server *tmp = old_servers->next;
+      free(old_servers);
+      old_servers = tmp;
+    }
+
+  daemon->servers = new_servers;
+  fclose(f);
+
+  return gotone;
+}
+
+
+/* Use an IPv4 listener socket for ioctling */
+struct in_addr get_ifaddr(char *intr)
+{
+  struct listener *l;
+  struct ifreq ifr;
+  struct sockaddr_in ret;
+  
+  ret.sin_addr.s_addr = -1;
+
+  for (l = daemon->listeners; 
+       l && (l->family != AF_INET || l->fd == -1);
+       l = l->next);
+  
+  strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
+  ifr.ifr_addr.sa_family = AF_INET;
+  
+  if (l &&  ioctl(l->fd, SIOCGIFADDR, &ifr) != -1)
+    memcpy(&ret, &ifr.ifr_addr, sizeof(ret)); 
+  
+  return ret.sin_addr;
+}
+
+
+
diff --git a/src/option.c b/src/option.c
new file mode 100644 (file)
index 0000000..4cee0a2
--- /dev/null
@@ -0,0 +1,3416 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* define this to get facilitynames */
+#define SYSLOG_NAMES
+#include "dnsmasq.h"
+#include <setjmp.h>
+
+static volatile int mem_recover = 0;
+static jmp_buf mem_jmp;
+static void one_file(char *file, int hard_opt);
+
+/* Solaris headers don't have facility names. */
+#ifdef HAVE_SOLARIS_NETWORK
+static const struct {
+  char *c_name;
+  unsigned int c_val;
+}  facilitynames[] = {
+  { "kern",   LOG_KERN },
+  { "user",   LOG_USER },
+  { "mail",   LOG_MAIL },
+  { "daemon", LOG_DAEMON },
+  { "auth",   LOG_AUTH },
+  { "syslog", LOG_SYSLOG },
+  { "lpr",    LOG_LPR },
+  { "news",   LOG_NEWS },
+  { "uucp",   LOG_UUCP },
+  { "audit",  LOG_AUDIT },
+  { "cron",   LOG_CRON },
+  { "local0", LOG_LOCAL0 },
+  { "local1", LOG_LOCAL1 },
+  { "local2", LOG_LOCAL2 },
+  { "local3", LOG_LOCAL3 },
+  { "local4", LOG_LOCAL4 },
+  { "local5", LOG_LOCAL5 },
+  { "local6", LOG_LOCAL6 },
+  { "local7", LOG_LOCAL7 },
+  { NULL, 0 }
+};
+#endif
+
+#ifndef HAVE_GETOPT_LONG
+struct myoption {
+  const char *name;
+  int has_arg;
+  int *flag;
+  int val;
+};
+#endif
+
+#define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:"
+
+/* options which don't have a one-char version */
+#define LOPT_RELOAD    256
+#define LOPT_NO_NAMES  257
+#define LOPT_TFTP      258
+#define LOPT_SECURE    259
+#define LOPT_PREFIX    260
+#define LOPT_PTR       261
+#define LOPT_BRIDGE    262
+#define LOPT_TFTP_MAX  263
+#define LOPT_FORCE     264
+#define LOPT_NOBLOCK   265
+#define LOPT_LOG_OPTS  266
+#define LOPT_MAX_LOGS  267
+#define LOPT_CIRCUIT   268
+#define LOPT_REMOTE    269
+#define LOPT_SUBSCR    270
+#define LOPT_INTNAME   271
+#define LOPT_BANK      272
+#define LOPT_DHCP_HOST 273
+#define LOPT_APREF     274
+#define LOPT_OVERRIDE  275
+#define LOPT_TFTPPORTS 276
+#define LOPT_REBIND    277
+#define LOPT_NOLAST    278
+#define LOPT_OPTS      279
+#define LOPT_DHCP_OPTS 280
+#define LOPT_MATCH     281
+#define LOPT_BROADCAST 282
+#define LOPT_NEGTTL    283
+#define LOPT_ALTPORT   284
+#define LOPT_SCRIPTUSR 285
+#define LOPT_LOCAL     286
+#define LOPT_NAPTR     287
+#define LOPT_MINPORT   288
+#define LOPT_DHCP_FQDN 289
+#define LOPT_CNAME     290
+#define LOPT_PXE_PROMT 291
+#define LOPT_PXE_SERV  292
+#define LOPT_TEST      293
+#define LOPT_TAG_IF    294
+#define LOPT_PROXY     295
+#define LOPT_GEN_NAMES 296
+#define LOPT_MAXTTL    297
+#define LOPT_NO_REBIND 298
+#define LOPT_LOC_REBND 299
+#define LOPT_ADD_MAC   300
+#define LOPT_DNSSEC    301
+
+#ifdef HAVE_GETOPT_LONG
+static const struct option opts[] =  
+#else
+static const struct myoption opts[] = 
+#endif
+  { 
+    { "version", 0, 0, 'v' },
+    { "no-hosts", 0, 0, 'h' },
+    { "no-poll", 0, 0, 'n' },
+    { "help", 0, 0, 'w' },
+    { "no-daemon", 0, 0, 'd' },
+    { "log-queries", 0, 0, 'q' },
+    { "user", 2, 0, 'u' },
+    { "group", 2, 0, 'g' },
+    { "resolv-file", 2, 0, 'r' },
+    { "mx-host", 1, 0, 'm' },
+    { "mx-target", 1, 0, 't' },
+    { "cache-size", 2, 0, 'c' },
+    { "port", 1, 0, 'p' },
+    { "dhcp-leasefile", 2, 0, 'l' },
+    { "dhcp-lease", 1, 0, 'l' },
+    { "dhcp-host", 1, 0, 'G' },
+    { "dhcp-range", 1, 0, 'F' },
+    { "dhcp-option", 1, 0, 'O' },
+    { "dhcp-boot", 1, 0, 'M' },
+    { "domain", 1, 0, 's' },
+    { "domain-suffix", 1, 0, 's' },
+    { "interface", 1, 0, 'i' },
+    { "listen-address", 1, 0, 'a' },
+    { "bogus-priv", 0, 0, 'b' },
+    { "bogus-nxdomain", 1, 0, 'B' },
+    { "selfmx", 0, 0, 'e' },
+    { "filterwin2k", 0, 0, 'f' },
+    { "pid-file", 2, 0, 'x' },
+    { "strict-order", 0, 0, 'o' },
+    { "server", 1, 0, 'S' },
+    { "local", 1, 0, LOPT_LOCAL },
+    { "address", 1, 0, 'A' },
+    { "conf-file", 2, 0, 'C' },
+    { "no-resolv", 0, 0, 'R' },
+    { "expand-hosts", 0, 0, 'E' },
+    { "localmx", 0, 0, 'L' },
+    { "local-ttl", 1, 0, 'T' },
+    { "no-negcache", 0, 0, 'N' },
+    { "addn-hosts", 1, 0, 'H' },
+    { "query-port", 1, 0, 'Q' },
+    { "except-interface", 1, 0, 'I' },
+    { "no-dhcp-interface", 1, 0, '2' },
+    { "domain-needed", 0, 0, 'D' },
+    { "dhcp-lease-max", 1, 0, 'X' },
+    { "bind-interfaces", 0, 0, 'z' },
+    { "read-ethers", 0, 0, 'Z' },
+    { "alias", 1, 0, 'V' },
+    { "dhcp-vendorclass", 1, 0, 'U' },
+    { "dhcp-userclass", 1, 0, 'j' },
+    { "dhcp-ignore", 1, 0, 'J' },
+    { "edns-packet-max", 1, 0, 'P' },
+    { "keep-in-foreground", 0, 0, 'k' },
+    { "dhcp-authoritative", 0, 0, 'K' },
+    { "srv-host", 1, 0, 'W' },
+    { "localise-queries", 0, 0, 'y' },
+    { "txt-record", 1, 0, 'Y' },
+    { "enable-dbus", 0, 0, '1' },
+    { "bootp-dynamic", 2, 0, '3' },
+    { "dhcp-mac", 1, 0, '4' },
+    { "no-ping", 0, 0, '5' },
+    { "dhcp-script", 1, 0, '6' },
+    { "conf-dir", 1, 0, '7' },
+    { "log-facility", 1, 0 ,'8' },
+    { "leasefile-ro", 0, 0, '9' },
+    { "dns-forward-max", 1, 0, '0' },
+    { "clear-on-reload", 0, 0, LOPT_RELOAD },
+    { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
+    { "enable-tftp", 2, 0, LOPT_TFTP },
+    { "tftp-secure", 0, 0, LOPT_SECURE },
+    { "tftp-unique-root", 0, 0, LOPT_APREF },
+    { "tftp-root", 1, 0, LOPT_PREFIX },
+    { "tftp-max", 1, 0, LOPT_TFTP_MAX },
+    { "ptr-record", 1, 0, LOPT_PTR },
+    { "naptr-record", 1, 0, LOPT_NAPTR },
+    { "bridge-interface", 1, 0 , LOPT_BRIDGE },
+    { "dhcp-option-force", 1, 0, LOPT_FORCE },
+    { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK },
+    { "log-dhcp", 0, 0, LOPT_LOG_OPTS },
+    { "log-async", 2, 0, LOPT_MAX_LOGS },
+    { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
+    { "dhcp-remoteid", 1, 0, LOPT_REMOTE },
+    { "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
+    { "interface-name", 1, 0, LOPT_INTNAME },
+    { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
+    { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
+    { "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
+    { "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
+    { "stop-dns-rebind", 0, 0, LOPT_REBIND },
+    { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
+    { "all-servers", 0, 0, LOPT_NOLAST }, 
+    { "dhcp-match", 1, 0, LOPT_MATCH }, 
+    { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
+    { "neg-ttl", 1, 0, LOPT_NEGTTL },
+    { "max-ttl", 1, 0, LOPT_MAXTTL },
+    { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
+    { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
+    { "min-port", 1, 0, LOPT_MINPORT },
+    { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
+    { "cname", 1, 0, LOPT_CNAME },
+    { "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
+    { "pxe-service", 1, 0, LOPT_PXE_SERV },
+    { "test", 0, 0, LOPT_TEST },
+    { "tag-if", 1, 0, LOPT_TAG_IF },
+    { "dhcp-proxy", 2, 0, LOPT_PROXY },
+    { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
+    { "rebind-localhost-ok", 0, 0,  LOPT_LOC_REBND },
+    { "add-mac", 0, 0, LOPT_ADD_MAC },
+    { "proxy-dnssec", 0, 0, LOPT_DNSSEC },
+    { NULL, 0, 0, 0 }
+  };
+
+
+#define ARG_DUP       OPT_LAST
+#define ARG_ONE       OPT_LAST + 1
+#define ARG_USED_CL   OPT_LAST + 2
+#define ARG_USED_FILE OPT_LAST + 3
+
+static struct {
+  int opt;
+  unsigned int rept;
+  char * const flagdesc;
+  char * const desc;
+  char * const arg;
+} usage[] = {
+  { 'a', ARG_DUP, "ipaddr",  gettext_noop("Specify local address(es) to listen on."), NULL },
+  { 'A', ARG_DUP, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL },
+  { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL },
+  { 'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL }, 
+  { 'c', ARG_ONE, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" },
+  { 'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE },
+  { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL },
+  { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL }, 
+  { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
+  { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
+  { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
+  { 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
+  { 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
+  { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
+  { LOPT_DHCP_HOST, ARG_DUP, "<filename>", gettext_noop("Read DHCP host specs from file."), NULL },
+  { LOPT_DHCP_OPTS, ARG_DUP, "<filename>", gettext_noop("Read DHCP option specs from file."), NULL },
+  { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
+  { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
+  { 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
+  { 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL },
+  { 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
+  { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
+  { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
+  { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
+  { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
+  { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
+  { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL }, 
+  { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
+  { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
+  { 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
+  { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL },
+  { 'm', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL },
+  { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
+  { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE }, 
+  { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
+  { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
+  { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
+  { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
+  { 'p', ARG_ONE, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL },
+  { 'P', ARG_ONE, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
+  { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL },
+  { 'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
+  { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
+  { 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, 
+  { 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
+  { LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL },
+  { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL },
+  { 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
+  { 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
+  { LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
+  { LOPT_MAXTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
+  { 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER }, 
+  { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
+  { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
+  { 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
+  { 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL },
+  { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
+  { 'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
+  { 'X', ARG_ONE, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
+  { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
+  { 'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL },
+  { LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL },
+  { LOPT_INTNAME, ARG_DUP, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL },
+  { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
+  { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
+  { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
+  { '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
+  { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
+  { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
+  { LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
+  { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
+  { '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
+  { '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL },
+  { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
+  { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
+  { '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" }, 
+  { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
+  { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
+  { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
+  { LOPT_TFTP, ARG_DUP, "[=<interface>]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
+  { LOPT_PREFIX, ARG_ONE, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
+  { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
+  { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
+  { LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
+  { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
+  { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
+  { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
+  { LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
+  { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
+  { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
+  { LOPT_NO_REBIND, ARG_DUP, "/domain/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
+  { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
+  { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
+  { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
+  { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
+  { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
+  { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
+  { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
+  { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
+  { LOPT_PROXY, ARG_DUP, "[=<ip_address>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
+  { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
+  { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
+  { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
+  { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
+  { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries"), NULL },
+  { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers"), NULL },
+  { 0, 0, NULL, NULL, NULL }
+}; 
+
+#ifdef HAVE_DHCP
+#define OT_ADDR_LIST 0x80
+#define OT_RFC1035_NAME 0x40
+#define OT_INTERNAL 0x20
+#define OT_NAME 0x10
+
+
+static const struct {
+  char *name;
+  unsigned char val, size;
+} opttab[] = {
+  { "netmask", 1, OT_ADDR_LIST },
+  { "time-offset", 2, 4 },
+  { "router", 3, OT_ADDR_LIST  },
+  { "dns-server", 6, OT_ADDR_LIST },
+  { "log-server", 7, OT_ADDR_LIST },
+  { "lpr-server", 9, OT_ADDR_LIST },
+  { "hostname", 12, OT_INTERNAL | OT_NAME },
+  { "boot-file-size", 13, 2 },
+  { "domain-name", 15, OT_NAME },
+  { "swap-server", 16, OT_ADDR_LIST },
+  { "root-path", 17, OT_NAME },
+  { "extension-path", 18, OT_NAME },
+  { "ip-forward-enable", 19, 1 },
+  { "non-local-source-routing", 20, 1 },
+  { "policy-filter", 21, OT_ADDR_LIST },
+  { "max-datagram-reassembly", 22, 2 },
+  { "default-ttl", 23, 1 },
+  { "mtu", 26, 2 },
+  { "all-subnets-local", 27, 1 },
+  { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
+  { "router-discovery", 31, 1 },
+  { "router-solicitation", 32, OT_ADDR_LIST },
+  { "static-route", 33, OT_ADDR_LIST },
+  { "trailer-encapsulation", 34, 1 },
+  { "arp-timeout", 35, 4 },
+  { "ethernet-encap", 36, 1 },
+  { "tcp-ttl", 37, 1 },
+  { "tcp-keepalive", 38, 4 },
+  { "nis-domain", 40, OT_NAME },
+  { "nis-server", 41, OT_ADDR_LIST },
+  { "ntp-server", 42, OT_ADDR_LIST },
+  { "vendor-encap", 43, OT_INTERNAL },
+  { "netbios-ns", 44, OT_ADDR_LIST },
+  { "netbios-dd", 45, OT_ADDR_LIST },
+  { "netbios-nodetype", 46, 1 },
+  { "netbios-scope", 47, 0 },
+  { "x-windows-fs", 48, OT_ADDR_LIST },
+  { "x-windows-dm", 49, OT_ADDR_LIST },
+  { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
+  { "lease-time", 51, OT_INTERNAL },
+  { "option-overload", 52, OT_INTERNAL },
+  { "message-type", 53, OT_INTERNAL, },
+  { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
+  { "parameter-request", 55, OT_INTERNAL },
+  { "message", 56, OT_INTERNAL },
+  { "max-message-size", 57, OT_INTERNAL },
+  { "T1", 58, OT_INTERNAL },
+  { "T2", 59, OT_INTERNAL },
+  { "vendor-class", 60, 0 },
+  { "client-id", 61,OT_INTERNAL },
+  { "nis+-domain", 64, OT_NAME },
+  { "nis+-server", 65, OT_ADDR_LIST },
+  { "tftp-server", 66, OT_NAME },
+  { "bootfile-name", 67, OT_NAME },
+  { "mobile-ip-home", 68, OT_ADDR_LIST }, 
+  { "smtp-server", 69, OT_ADDR_LIST }, 
+  { "pop3-server", 70, OT_ADDR_LIST }, 
+  { "nntp-server", 71, OT_ADDR_LIST }, 
+  { "irc-server", 74, OT_ADDR_LIST }, 
+  { "user-class", 77, 0 },
+  { "FQDN", 81, OT_INTERNAL },
+  { "agent-id", 82, OT_INTERNAL },
+  { "client-arch", 93, 2 },
+  { "client-interface-id", 94, 0 },
+  { "client-machine-id", 97, 0 },
+  { "subnet-select", 118, OT_INTERNAL },
+  { "domain-search", 119, OT_RFC1035_NAME },
+  { "sip-server", 120, 0 },
+  { "classless-static-route", 121, 0 },
+  { "vendor-id-encap", 125, 0 },
+  { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
+  { NULL, 0, 0 }
+};
+
+char *option_string(unsigned char opt, int *is_ip, int *is_name)
+{
+  int i;
+
+  for (i = 0; opttab[i].name; i++)
+    if (opttab[i].val == opt)
+      {
+       if (is_ip)
+         *is_ip = !!(opttab[i].size & OT_ADDR_LIST);
+       if (is_name)
+         *is_name = !!(opttab[i].size & OT_NAME);
+       return opttab[i].name;
+      }
+
+  return NULL;
+}
+
+#endif
+
+/* We hide metacharaters in quoted strings by mapping them into the ASCII control
+   character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
+   following sequence so that they map to themselves: it is therefore possible to call
+   unhide_metas repeatedly on string without breaking things.
+   The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a 
+   couple of other places. 
+   Note that space is included here so that
+   --dhcp-option=3, string
+   has five characters, whilst
+   --dhcp-option=3," string"
+   has six.
+*/
+
+static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,.";
+
+static char hide_meta(char c)
+{
+  unsigned int i;
+
+  for (i = 0; i < (sizeof(meta) - 1); i++)
+    if (c == meta[i])
+      return (char)i;
+  
+  return c;
+}
+
+static char unhide_meta(char cr)
+{ 
+  unsigned int c = cr;
+  
+  if (c < (sizeof(meta) - 1))
+    cr = meta[c];
+  
+  return cr;
+}
+
+static void unhide_metas(char *cp)
+{
+  if (cp)
+    for(; *cp; cp++)
+      *cp = unhide_meta(*cp);
+}
+
+static void *opt_malloc(size_t size)
+{
+  void *ret;
+
+  if (mem_recover)
+    {
+      ret = whine_malloc(size);
+      if (!ret)
+       longjmp(mem_jmp, 1);
+    }
+  else
+    ret = safe_malloc(size);
+  
+  return ret;
+}
+
+static char *opt_string_alloc(char *cp)
+{
+  char *ret = NULL;
+  
+  if (cp && strlen(cp) != 0)
+    {
+      ret = opt_malloc(strlen(cp)+1);
+      strcpy(ret, cp); 
+      
+      /* restore hidden metachars */
+      unhide_metas(ret);
+    }
+    
+  return ret;
+}
+
+
+/* find next comma, split string with zero and eliminate spaces.
+   return start of string following comma */
+
+static char *split_chr(char *s, char c)
+{
+  char *comma, *p;
+
+  if (!s || !(comma = strchr(s, c)))
+    return NULL;
+  
+  p = comma;
+  *comma = ' ';
+  
+  for (; *comma == ' '; comma++);
+  for (; (p >= s) && *p == ' '; p--)
+    *p = 0;
+    
+  return comma;
+}
+
+static char *split(char *s)
+{
+  return split_chr(s, ',');
+}
+
+static char *canonicalise_opt(char *s)
+{
+  char *ret;
+  int nomem;
+
+  if (!s)
+    return 0;
+
+  unhide_metas(s);
+  if (!(ret = canonicalise(s, &nomem)) && nomem)
+    {
+      if (mem_recover)
+       longjmp(mem_jmp, 1);
+      else
+       die(_("could not get memory"), NULL, EC_NOMEM);
+    }
+
+  return ret;
+}
+
+static int atoi_check(char *a, int *res)
+{
+  char *p;
+
+  if (!a)
+    return 0;
+
+  unhide_metas(a);
+  
+  for (p = a; *p; p++)
+     if (*p < '0' || *p > '9')
+       return 0;
+
+  *res = atoi(a);
+  return 1;
+}
+
+static int atoi_check16(char *a, int *res)
+{
+  if (!(atoi_check(a, res)) ||
+      *res < 0 ||
+      *res > 0xffff)
+    return 0;
+
+  return 1;
+}
+       
+static void add_txt(char *name, char *txt)
+{
+  size_t len = strlen(txt);
+  struct txt_record *r = opt_malloc(sizeof(struct txt_record));
+  
+  r->name = opt_string_alloc(name);
+  r->next = daemon->txt;
+  daemon->txt = r;
+  r->class = C_CHAOS;
+  r->txt = opt_malloc(len+1);
+  r->len = len+1;
+  *(r->txt) = len;
+  memcpy((r->txt)+1, txt, len);
+}
+
+static void do_usage(void)
+{
+  char buff[100];
+  int i, j;
+
+  struct {
+    char handle;
+    int val;
+  } tab[] = {
+    { '$', CACHESIZ },
+    { '*', EDNS_PKTSZ },
+    { '&', MAXLEASES },
+    { '!', FTABSIZ },
+    { '#', TFTP_MAX_CONNECTIONS },
+    { '\0', 0 }
+  };
+
+  printf(_("Usage: dnsmasq [options]\n\n"));
+#ifndef HAVE_GETOPT_LONG
+  printf(_("Use short options only on the command line.\n"));
+#endif
+  printf(_("Valid options are:\n"));
+  
+  for (i = 0; usage[i].opt != 0; i++)
+    {
+      char *desc = usage[i].flagdesc; 
+      char *eq = "=";
+      
+      if (!desc || *desc == '[')
+       eq = "";
+      
+      if (!desc)
+       desc = "";
+
+      for ( j = 0; opts[j].name; j++)
+       if (opts[j].val == usage[i].opt)
+         break;
+      if (usage[i].opt < 256)
+       sprintf(buff, "-%c, ", usage[i].opt);
+      else
+       sprintf(buff, "    ");
+      
+      sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
+      printf("%-40.40s", buff);
+            
+      if (usage[i].arg)
+       {
+         strcpy(buff, usage[i].arg);
+         for (j = 0; tab[j].handle; j++)
+           if (tab[j].handle == *(usage[i].arg))
+             sprintf(buff, "%d", tab[j].val);
+       }
+      printf(_(usage[i].desc), buff);
+      printf("\n");
+    }
+}
+
+#ifdef HAVE_DHCP
+static void display_opts(void)
+{
+  int i;
+  
+  printf(_("Known DHCP options:\n"));
+  
+  for (i = 0; opttab[i].name; i++)
+    if (!(opttab[i].size & OT_INTERNAL))
+      printf("%3d %s\n", opttab[i].val, opttab[i].name);
+}
+
+static int is_tag_prefix(char *arg)
+{
+  if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
+    return 1;
+  
+  return 0;
+}
+
+static char *set_prefix(char *arg)
+{
+   if (strstr(arg, "set:") == arg)
+     return arg+4;
+   
+   return arg;
+}
+
+/* This is too insanely large to keep in-line in the switch */
+static char *parse_dhcp_opt(char *arg, int flags)
+{
+  struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
+  char lenchar = 0, *cp;
+  int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots;
+  char *comma = NULL, *problem = NULL;
+  struct dhcp_netid *np = NULL;
+  unsigned char opt_len = 0;
+
+  new->len = 0;
+  new->flags = flags;
+  new->netid = NULL;
+  new->val = NULL;
+  new->opt = 0;
+  
+  while (arg)
+    {
+      comma = split(arg);      
+
+      for (cp = arg; *cp; cp++)
+       if (*cp < '0' || *cp > '9')
+         break;
+      
+      if (!*cp)
+       {
+         new->opt = atoi(arg);
+         opt_len = 0;
+         break;
+       }
+      
+      if (strstr(arg, "option:") == arg)
+       {
+         for (i = 0; opttab[i].name; i++)
+           if (!(opttab[i].size & OT_INTERNAL) &&
+               strcasecmp(opttab[i].name, arg+7) == 0)
+             {
+               new->opt = opttab[i].val;
+               opt_len = opttab[i].size;
+               break;
+             }
+         /* option:<optname> must follow tag and vendor string. */
+         break;
+       }
+      else if (strstr(arg, "vendor:") == arg)
+       {
+         new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
+         new->flags |= DHOPT_VENDOR;
+       }
+      else if (strstr(arg, "encap:") == arg)
+       {
+         new->u.encap = atoi(arg+6);
+         new->flags |= DHOPT_ENCAPSULATE;
+       }
+      else if (strstr(arg, "vi-encap:") == arg)
+       {
+         new->u.encap = atoi(arg+9);
+         new->flags |= DHOPT_RFC3925;
+         if (flags == DHOPT_MATCH)
+           {
+             new->opt = 1; /* avoid error below */
+             break;
+           }
+       }
+      else
+       {
+         new->netid = opt_malloc(sizeof (struct dhcp_netid));
+         /* allow optional "net:" or "tag:" for consistency */
+         if (is_tag_prefix(arg))
+           new->netid->net = opt_string_alloc(arg+4);
+         else
+           new->netid->net = opt_string_alloc(set_prefix(arg));
+         new->netid->next = np;
+         np = new->netid;
+       }
+      
+      arg = comma; 
+    }
+  
+  if (opt_len == 0 &&
+      !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925)))
+    for (i = 0; opttab[i].name; i++)
+      if (new->opt == opttab[i].val)
+       {
+         opt_len = opttab[i].size;
+         if (opt_len & OT_INTERNAL)
+           opt_len = 0;
+         break;
+       }
+
+  /* option may be missing with rfc3925 match */
+  if (new->opt == 0)
+    problem = _("bad dhcp-option");
+  else if (comma)
+    {
+      /* characterise the value */
+      char c;
+      int found_dig = 0;
+      is_addr = is_hex = is_dec = is_string = 1;
+      addrs = digs = 1;
+      dots = 0;
+      for (cp = comma; (c = *cp); cp++)
+       if (c == ',')
+         {
+           addrs++;
+           is_dec = is_hex = 0;
+         }
+       else if (c == ':')
+         {
+           digs++;
+           is_dec = is_addr = 0;
+         }
+       else if (c == '/') 
+         {
+           is_dec = is_hex = 0;
+           if (cp == comma) /* leading / means a pathname */
+             is_addr = 0;
+         } 
+       else if (c == '.')      
+         {
+           is_dec = is_hex = 0;
+           dots++;
+         }
+       else if (c == '-')
+         is_hex = is_addr = 0;
+       else if (c == ' ')
+         is_dec = is_hex = 0;
+       else if (!(c >='0' && c <= '9'))
+         {
+           is_addr = 0;
+           if (cp[1] == 0 && is_dec &&
+               (c == 'b' || c == 's' || c == 'i'))
+             {
+               lenchar = c;
+               *cp = 0;
+             }
+           else
+             is_dec = 0;
+           if (!((c >='A' && c <= 'F') ||
+                 (c >='a' && c <= 'f') || 
+                 (c == '*' && (flags & DHOPT_MATCH))))
+             is_hex = 0;
+         }
+       else
+         found_dig = 1;
+     
+      if (!found_dig)
+       is_dec = is_addr = 0;
+      
+      /* We know that some options take addresses */
+      if (opt_len & OT_ADDR_LIST)
+       {
+         is_string = is_dec = is_hex = 0;
+         if (!is_addr || dots == 0)
+           problem = _("bad IP address");
+       }
+      /* or names */
+      else if (opt_len & (OT_NAME | OT_RFC1035_NAME))
+       is_addr = is_dec = is_hex = 0;
+         
+      if (is_hex && digs > 1)
+       {
+         new->len = digs;
+         new->val = opt_malloc(new->len);
+         parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL);
+         new->flags |= DHOPT_HEX;
+       }
+      else if (is_dec)
+       {
+         int i, val = atoi(comma);
+         /* assume numeric arg is 1 byte except for
+            options where it is known otherwise.
+            For vendor class option, we have to hack. */
+         if (opt_len != 0)
+           new->len = opt_len;
+         else if (val & 0xffff0000)
+           new->len = 4;
+         else if (val & 0xff00)
+           new->len = 2;
+         else
+           new->len = 1;
+
+         if (lenchar == 'b')
+           new->len = 1;
+         else if (lenchar == 's')
+           new->len = 2;
+         else if (lenchar == 'i')
+           new->len = 4;
+         
+         new->val = opt_malloc(new->len);
+         for (i=0; i<new->len; i++)
+           new->val[i] = val>>((new->len - i - 1)*8);
+       }
+      else if (is_addr)        
+       {
+         struct in_addr in;
+         unsigned char *op;
+         char *slash;
+         /* max length of address/subnet descriptor is five bytes,
+            add one for the option 120 enc byte too */
+         new->val = op = opt_malloc((5 * addrs) + 1);
+         new->flags |= DHOPT_ADDR;
+
+         if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) && 
+             new->opt == OPTION_SIP_SERVER)
+           {
+             *(op++) = 1; /* RFC 3361 "enc byte" */
+             new->flags &= ~DHOPT_ADDR;
+           }
+         while (addrs--) 
+           {
+             cp = comma;
+             comma = split(cp);
+             slash = split_chr(cp, '/');
+             in.s_addr = inet_addr(cp);
+             if (!slash)
+               {
+                 memcpy(op, &in, INADDRSZ);
+                 op += INADDRSZ;
+               }
+             else
+               {
+                 unsigned char *p = (unsigned char *)&in;
+                 int netsize = atoi(slash);
+                 *op++ = netsize;
+                 if (netsize > 0)
+                   *op++ = *p++;
+                 if (netsize > 8)
+                   *op++ = *p++;
+                 if (netsize > 16)
+                   *op++ = *p++;
+                 if (netsize > 24)
+                   *op++ = *p++;
+                 new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */
+               } 
+           }
+         new->len = op - new->val;
+       }
+      else if (is_string)
+       {
+         /* text arg */
+         if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) &&
+             !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
+           {
+             /* dns search, RFC 3397, or SIP, RFC 3361 */
+             unsigned char *q, *r, *tail;
+             unsigned char *p, *m = NULL, *newp;
+             size_t newlen, len = 0;
+             int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1;
+             
+             arg = comma;
+             comma = split(arg);
+             
+             while (arg && *arg)
+               {
+                 char *in, *dom = NULL;
+                 size_t domlen = 1;
+                 /* Allow "." as an empty domain */
+                 if (strcmp (arg, ".") != 0)
+                   {
+                     if (!(dom = canonicalise_opt(arg)))
+                       {
+                         problem = _("bad domain in dhcp-option");
+                         break;
+                       }
+                     domlen = strlen(dom) + 2;
+                   }
+                     
+                 newp = opt_malloc(len + domlen + header_size);
+                 if (m)
+                   {
+                     memcpy(newp, m, header_size + len);
+                     free(m);
+                   }
+                 m = newp;
+                 p = m + header_size;
+                 q = p + len;
+                 
+                 /* add string on the end in RFC1035 format */
+                 for (in = dom; in && *in;) 
+                   {
+                     unsigned char *cp = q++;
+                     int j;
+                     for (j = 0; *in && (*in != '.'); in++, j++)
+                       *q++ = *in;
+                     *cp = j;
+                     if (*in)
+                       in++;
+                   }
+                 *q++ = 0;
+                 free(dom);
+                 
+                 /* Now tail-compress using earlier names. */
+                 newlen = q - p;
+                 for (tail = p + len; *tail; tail += (*tail) + 1)
+                   for (r = p; r - p < (int)len; r += (*r) + 1)
+                     if (strcmp((char *)r, (char *)tail) == 0)
+                       {
+                         PUTSHORT((r - p) | 0xc000, tail); 
+                         newlen = tail - p;
+                         goto end;
+                       }
+               end:
+                 len = newlen;
+                 
+                 arg = comma;
+                 comma = split(arg);
+               }
+      
+             /* RFC 3361, enc byte is zero for names */
+             if (new->opt == OPTION_SIP_SERVER)
+               m[0] = 0;
+             new->len = (int) len + header_size;
+             new->val = m;
+           }
+         else
+           {
+             new->len = strlen(comma);
+             /* keep terminating zero on string */
+             new->val = (unsigned char *)opt_string_alloc(comma);
+             new->flags |= DHOPT_STRING;
+           }
+       }
+    }
+
+  if ((new->len > 255) || 
+      (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) ||
+      (new->len > 250 && (new->flags & DHOPT_RFC3925)))
+    problem = _("dhcp-option too long");
+  
+  if (!problem)
+    {
+      if (flags == DHOPT_MATCH)
+       {
+         if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) ||
+             !new->netid ||
+             new->netid->next)
+           problem = _("illegal dhcp-match");
+         else
+           {
+             new->next = daemon->dhcp_match;
+             daemon->dhcp_match = new;
+           }
+       }
+      else     
+       {
+         new->next = daemon->dhcp_opts;
+         daemon->dhcp_opts = new;
+       }
+    }
+
+  return problem;
+}
+
+#endif
+
+void set_option_bool(unsigned int opt)
+{
+  if (opt < 32)
+    daemon->options |= 1u << opt;
+  else
+    daemon->options2 |= 1u << (opt - 32);
+}
+
+static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
+{      
+  int i;
+  char *comma, *problem = NULL;;
+
+  if (option == '?')
+    return gen_prob;
+  
+  for (i=0; usage[i].opt != 0; i++)
+    if (usage[i].opt == option)
+      {
+        int rept = usage[i].rept;
+        
+        if (command_line)
+          {
+            /* command line */
+            if (rept == ARG_USED_CL)
+              return _("illegal repeated flag");
+            if (rept == ARG_ONE)
+              usage[i].rept = ARG_USED_CL;
+          }
+        else
+          {
+            /* allow file to override command line */
+            if (rept == ARG_USED_FILE)
+              return _("illegal repeated keyword");
+            if (rept == ARG_USED_CL || rept == ARG_ONE)
+              usage[i].rept = ARG_USED_FILE;
+          }
+
+        if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL) 
+          {
+            set_option_bool(rept);
+            return NULL;
+          }
+       
+        break;
+      }
+  
+  switch (option)
+    { 
+    case 'C': /* --conf-file */
+      {
+       char *file = opt_string_alloc(arg);
+       if (file)
+         {
+           one_file(file, 0);
+           free(file);
+         }
+       break;
+      }
+
+    case '7': /* --conf-dir */       
+      {
+       DIR *dir_stream;
+       struct dirent *ent;
+       char *directory, *path;
+       struct list {
+         char *suffix;
+         struct list *next;
+       } *ignore_suffix = NULL, *li;
+       
+       comma = split(arg);
+       if (!(directory = opt_string_alloc(arg)))
+         break;
+       
+       for (arg = comma; arg; arg = comma) 
+         {
+           comma = split(arg);
+           li = opt_malloc(sizeof(struct list));
+           li->next = ignore_suffix;
+           ignore_suffix = li;
+           /* Have to copy: buffer is overwritten */
+           li->suffix = opt_string_alloc(arg);
+         };
+       
+       if (!(dir_stream = opendir(directory)))
+         die(_("cannot access directory %s: %s"), directory, EC_FILE);
+       
+       while ((ent = readdir(dir_stream)))
+         {
+           size_t len = strlen(ent->d_name);
+           struct stat buf;
+           
+           /* ignore emacs backups and dotfiles */
+           if (len == 0 ||
+               ent->d_name[len - 1] == '~' ||
+               (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') ||
+               ent->d_name[0] == '.')
+             continue;
+
+           for (li = ignore_suffix; li; li = li->next)
+             {
+               /* check for proscribed suffices */
+               size_t ls = strlen(li->suffix);
+               if (len > ls &&
+                   strcmp(li->suffix, &ent->d_name[len - ls]) == 0)
+                 break;
+             }
+           if (li)
+             continue;
+           
+           path = opt_malloc(strlen(directory) + len + 2);
+           strcpy(path, directory);
+           strcat(path, "/");
+           strcat(path, ent->d_name);
+
+           if (stat(path, &buf) == -1)
+             die(_("cannot access %s: %s"), path, EC_FILE);
+           /* only reg files allowed. */
+           if (!S_ISREG(buf.st_mode))
+             continue;
+           
+           /* files must be readable */
+           one_file(path, 0);
+           free(path);
+         }
+     
+       closedir(dir_stream);
+       free(directory);
+       for(; ignore_suffix; ignore_suffix = li)
+         {
+           li = ignore_suffix->next;
+           free(ignore_suffix->suffix);
+           free(ignore_suffix);
+         }
+             
+       break;
+      }
+
+    case '8': /* --log-facility */
+      /* may be a filename */
+      if (strchr(arg, '/') || strcmp (arg, "-") == 0)
+       daemon->log_file = opt_string_alloc(arg);
+      else
+       {         
+#ifdef __ANDROID__
+         problem = _("setting log facility is not possible under Android");
+#else
+         for (i = 0; facilitynames[i].c_name; i++)
+           if (hostname_isequal((char *)facilitynames[i].c_name, arg))
+             break;
+         
+         if (facilitynames[i].c_name)
+           daemon->log_fac = facilitynames[i].c_val;
+         else
+           problem = _("bad log facility");
+#endif
+       }
+      break;
+      
+    case 'x': /* --pid-file */
+      daemon->runfile = opt_string_alloc(arg);
+      break;
+
+    case 'r': /* --resolv-file */
+      {
+       char *name = opt_string_alloc(arg);
+       struct resolvc *new, *list = daemon->resolv_files;
+       
+       if (list && list->is_default)
+         {
+           /* replace default resolv file - possibly with nothing */
+           if (name)
+             {
+               list->is_default = 0;
+               list->name = name;
+             }
+           else
+             list = NULL;
+         }
+       else if (name)
+         {
+           new = opt_malloc(sizeof(struct resolvc));
+           new->next = list;
+           new->name = name;
+           new->is_default = 0;
+           new->mtime = 0;
+           new->logged = 0;
+           list = new;
+         }
+       daemon->resolv_files = list;
+       break;
+      }
+      
+    case 'm':  /* --mx-host */
+      {
+       int pref = 1;
+       struct mx_srv_record *new;
+       char *name, *target = NULL;
+
+       if ((comma = split(arg)))
+         {
+           char *prefstr;
+           if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref))
+             problem = _("bad MX preference");
+         }
+       
+       if (!(name = canonicalise_opt(arg)) || 
+           (comma && !(target = canonicalise_opt(comma))))
+         problem = _("bad MX name");
+       
+       new = opt_malloc(sizeof(struct mx_srv_record));
+       new->next = daemon->mxnames;
+       daemon->mxnames = new;
+       new->issrv = 0;
+       new->name = name;
+       new->target = target; /* may be NULL */
+       new->weight = pref;
+       break;
+      }
+      
+    case 't': /*  --mx-target */
+      if (!(daemon->mxtarget = canonicalise_opt(arg)))
+       problem = _("bad MX target");
+      break;
+
+#ifdef HAVE_DHCP      
+    case 'l':  /* --dhcp-leasefile */
+      daemon->lease_file = opt_string_alloc(arg);
+      break;
+      
+    case '6': /* --dhcp-script */
+#  if defined(NO_FORK)
+      problem = _("cannot run scripts under uClinux");
+#  elif !defined(HAVE_SCRIPT)
+      problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts");
+#  else
+      daemon->lease_change_command = opt_string_alloc(arg);
+#  endif
+      break;
+#endif
+
+    case LOPT_DHCP_HOST: /* --dhcp-hostfile */
+    case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
+    case 'H': /* --addn-hosts */
+      {
+       struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
+       static int hosts_index = 1;
+       new->fname = opt_string_alloc(arg);
+       new->index = hosts_index++;
+       new->flags = 0;
+       if (option == 'H')
+         {
+           new->next = daemon->addn_hosts;
+           daemon->addn_hosts = new;
+         }
+       else if (option == LOPT_DHCP_HOST)
+         {
+           new->next = daemon->dhcp_hosts_file;
+           daemon->dhcp_hosts_file = new;
+         }
+       else if (option ==  LOPT_DHCP_OPTS)
+         {
+           new->next = daemon->dhcp_opts_file;
+           daemon->dhcp_opts_file = new;
+         }       
+       break;
+      }
+      
+    case 's': /* --domain */
+      if (strcmp (arg, "#") == 0)
+       set_option_bool(OPT_RESOLV_DOMAIN);
+      else
+       {
+         char *d;
+         comma = split(arg);
+         if (!(d = canonicalise_opt(arg)))
+           option = '?';
+         else
+           {
+             if (comma)
+               {
+                 struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
+                 char *netpart;
+
+                 unhide_metas(comma);
+                 if ((netpart = split_chr(comma, '/')))
+                   {
+                     int msize, mask;
+                     arg = split(netpart);
+                     if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
+                         !atoi_check(netpart, &msize))
+                       option = '?';
+                     else
+                       {
+                         mask = (1 << (32 - msize)) - 1;
+                         new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
+                         new->end.s_addr = new->start.s_addr | htonl(mask);
+                         if (arg)
+                           {
+                             /* generate the equivalent of
+                                local=/<domain>/
+                                local=/xxx.yyy.zzz.in-addr.arpa/ */
+
+                             if (strcmp(arg, "local") != 0 || 
+                                 (msize != 8 && msize != 16 && msize != 24))
+                               option = '?';
+                             else
+                               {
+                                 struct server *serv = opt_malloc(sizeof(struct server));
+                                 in_addr_t a = ntohl(new->start.s_addr) >> 8;
+                                 char *p;
+
+                                 memset(serv, 0, sizeof(struct server));
+                                 serv->domain = d;
+                                 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
+                                 serv->next = daemon->servers;
+                                 daemon->servers = serv;
+
+                                 serv = opt_malloc(sizeof(struct server));
+                                 memset(serv, 0, sizeof(struct server));
+                                 p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
+                                 
+                                 if (msize == 24)
+                                   p += sprintf(p, "%d.", a & 0xff);
+                                 a = a >> 8;
+                                 if (msize != 8)
+                                   p += sprintf(p, "%d.", a & 0xff);
+                                 a = a >> 8;
+                                 p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
+
+                                 serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
+                                 serv->next = daemon->servers;
+                                 daemon->servers = serv;
+                               }
+                           }
+                       }
+                   }
+                 else if ((arg = split(comma)))
+                   {
+                     if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
+                         (new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1)
+                       option = '?';
+                   }
+                 else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1)
+                   option = '?';
+
+                 new->domain = d;
+                 new->next = daemon->cond_domain;
+                 daemon->cond_domain = new;
+               }
+             else
+               daemon->domain_suffix = d;
+           }
+       }
+      break;
+      
+    case 'u':  /* --user */
+      daemon->username = opt_string_alloc(arg);
+      break;
+      
+    case 'g':  /* --group */
+      daemon->groupname = opt_string_alloc(arg);
+      daemon->group_set = 1;
+      break;
+
+#ifdef HAVE_DHCP
+    case LOPT_SCRIPTUSR: /* --scriptuser */
+      daemon->scriptuser = opt_string_alloc(arg);
+      break;
+#endif
+      
+    case 'i':  /* --interface */
+      do {
+       struct iname *new = opt_malloc(sizeof(struct iname));
+       comma = split(arg);
+       new->next = daemon->if_names;
+       daemon->if_names = new;
+       /* new->name may be NULL if someone does
+          "interface=" to disable all interfaces except loop. */
+       new->name = opt_string_alloc(arg);
+       new->isloop = new->used = 0;
+       arg = comma;
+      } while (arg);
+      break;
+      
+    case 'I':  /* --except-interface */
+    case '2':  /* --no-dhcp-interface */
+      do {
+       struct iname *new = opt_malloc(sizeof(struct iname));
+       comma = split(arg);
+       new->name = opt_string_alloc(arg);
+       if (option == 'I')
+         {
+           new->next = daemon->if_except;
+           daemon->if_except = new;
+         }
+       else
+         {
+           new->next = daemon->dhcp_except;
+           daemon->dhcp_except = new;
+         }
+       arg = comma;
+      } while (arg);
+      break;
+      
+    case 'B':  /* --bogus-nxdomain */
+      {
+       struct in_addr addr;
+       unhide_metas(arg);
+       if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
+         {
+           struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
+           baddr->next = daemon->bogus_addr;
+           daemon->bogus_addr = baddr;
+           baddr->addr = addr;
+         }
+       else
+         option = '?'; /* error */
+       break;  
+      }
+      
+    case 'a':  /* --listen-address */
+      do {
+       struct iname *new = opt_malloc(sizeof(struct iname));
+       comma = split(arg);
+       unhide_metas(arg);
+       new->next = daemon->if_addrs;
+       if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
+         {
+           new->addr.sa.sa_family = AF_INET;
+#ifdef HAVE_SOCKADDR_SA_LEN
+           new->addr.in.sin_len = sizeof(new->addr.in);
+#endif
+         }
+#ifdef HAVE_IPV6
+       else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
+         {
+           new->addr.sa.sa_family = AF_INET6;
+           new->addr.in6.sin6_flowinfo = 0;
+           new->addr.in6.sin6_scope_id = 0;
+#ifdef HAVE_SOCKADDR_SA_LEN
+           new->addr.in6.sin6_len = sizeof(new->addr.in6);
+#endif
+         }
+#endif
+       else
+         {
+           option = '?'; /* error */
+           break;
+         }
+       
+       daemon->if_addrs = new;
+       arg = comma;
+      } while (arg);
+      break;
+      
+    case 'S':            /*  --server */
+    case LOPT_LOCAL:     /*  --local */
+    case 'A':            /*  --address */
+    case LOPT_NO_REBIND: /*  --rebind-domain-ok */
+      {
+       struct server *serv, *newlist = NULL;
+       
+       unhide_metas(arg);
+       
+       if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
+         {
+           int rebind = !(*arg == '/');
+           char *end = NULL;
+           if (!rebind)
+             arg++;
+           while (rebind || (end = split_chr(arg, '/')))
+             {
+               char *domain = NULL;
+               /* elide leading dots - they are implied in the search algorithm */
+               while (*arg == '.') arg++;
+               /* # matches everything and becomes a zero length domain string */
+               if (strcmp(arg, "#") == 0)
+                 domain = "";
+               else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
+                 option = '?';
+               serv = opt_malloc(sizeof(struct server));
+               memset(serv, 0, sizeof(struct server));
+               serv->next = newlist;
+               newlist = serv;
+               serv->domain = domain;
+               serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
+               arg = end;
+               if (rebind)
+                 break;
+             }
+           if (!newlist)
+             {
+               option = '?';
+               break;
+             }
+           
+         }
+       else
+         {
+           newlist = opt_malloc(sizeof(struct server));
+           memset(newlist, 0, sizeof(struct server));
+         }
+       
+       if (option == 'A')
+         {
+           newlist->flags |= SERV_LITERAL_ADDRESS;
+           if (!(newlist->flags & SERV_TYPE))
+             option = '?';
+         }
+       else if (option == LOPT_NO_REBIND)
+         newlist->flags |= SERV_NO_REBIND;
+       
+       if (!arg || !*arg)
+         {
+           if (!(newlist->flags & SERV_NO_REBIND))
+             newlist->flags |= SERV_NO_ADDR; /* no server */
+           if (newlist->flags & SERV_LITERAL_ADDRESS)
+             option = '?';
+         }
+
+       else if (strcmp(arg, "#") == 0)
+         {
+           newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
+           if (newlist->flags & SERV_LITERAL_ADDRESS)
+             option = '?';
+         }
+       else
+         {
+           int source_port = 0, serv_port = NAMESERVER_PORT;
+           char *portno, *source;
+           
+           if ((source = split_chr(arg, '@')) && /* is there a source. */
+               (portno = split_chr(source, '#')) &&
+               !atoi_check16(portno, &source_port))
+             problem = _("bad port");
+                   
+           if ((portno = split_chr(arg, '#')) && /* is there a port no. */
+               !atoi_check16(portno, &serv_port))
+             problem = _("bad port");
+           
+           if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
+             {
+               newlist->addr.in.sin_port = htons(serv_port);   
+               newlist->source_addr.in.sin_port = htons(source_port); 
+               newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET;
+#ifdef HAVE_SOCKADDR_SA_LEN
+               newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in);
+#endif
+               if (source)
+                 {
+                   newlist->flags |= SERV_HAS_SOURCE;
+                   if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
+                     {
+#if defined(SO_BINDTODEVICE)
+                       newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
+                       strncpy(newlist->interface, source, IF_NAMESIZE - 1);
+#else
+                       problem = _("interface binding not supported");
+#endif
+                     }
+                 }
+               else
+                 newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY;
+             }
+#ifdef HAVE_IPV6
+           else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0)
+             {
+               newlist->addr.in6.sin6_port = htons(serv_port);
+               newlist->source_addr.in6.sin6_port = htons(source_port);
+               newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6;
+#ifdef HAVE_SOCKADDR_SA_LEN
+               newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6);
+#endif
+               if (source)
+                 {
+                    newlist->flags |= SERV_HAS_SOURCE;
+                    if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0)
+                     {
+#if defined(SO_BINDTODEVICE)
+                       newlist->source_addr.in6.sin6_addr = in6addr_any; 
+                       strncpy(newlist->interface, source, IF_NAMESIZE - 1);
+#else
+                       problem = _("interface binding not supported");
+#endif
+                     }
+                 }
+               else
+                 newlist->source_addr.in6.sin6_addr = in6addr_any; 
+             }
+#endif
+           else
+             option = '?'; /* error */
+           
+         }
+       
+       serv = newlist;
+       while (serv->next)
+         {
+           serv->next->flags = serv->flags;
+           serv->next->addr = serv->addr;
+           serv->next->source_addr = serv->source_addr;
+           serv = serv->next;
+         }
+       serv->next = daemon->servers;
+       daemon->servers = newlist;
+       break;
+      }
+      
+    case 'c':  /* --cache-size */
+      {
+       int size;
+       
+       if (!atoi_check(arg, &size))
+         option = '?';
+       else
+         {
+           /* zero is OK, and means no caching. */
+           
+           if (size < 0)
+             size = 0;
+           else if (size > 10000)
+             size = 10000;
+           
+           daemon->cachesize = size;
+         }
+       break;
+      }
+      
+    case 'p':  /* --port */
+      if (!atoi_check16(arg, &daemon->port))
+       option = '?';
+      break;
+    
+    case LOPT_MINPORT:  /* --min-port */
+      if (!atoi_check16(arg, &daemon->min_port))
+       option = '?';
+      break;
+
+    case '0':  /* --dns-forward-max */
+      if (!atoi_check(arg, &daemon->ftabsize))
+       option = '?';
+      break;  
+    
+    case LOPT_MAX_LOGS:  /* --log-async */
+      daemon->max_logs = LOG_MAX; /* default */
+      if (arg && !atoi_check(arg, &daemon->max_logs))
+       option = '?';
+      else if (daemon->max_logs > 100)
+       daemon->max_logs = 100;
+      break;  
+
+    case 'P': /* --edns-packet-max */
+      {
+       int i;
+       if (!atoi_check(arg, &i))
+         option = '?';
+       daemon->edns_pktsz = (unsigned short)i; 
+       break;
+      }
+      
+    case 'Q':  /* --query-port */
+      if (!atoi_check16(arg, &daemon->query_port))
+       option = '?';
+      /* if explicitly set to zero, use single OS ephemeral port
+        and disable random ports */
+      if (daemon->query_port == 0)
+       daemon->osport = 1;
+      break;
+      
+    case 'T':         /* --local-ttl */
+    case LOPT_NEGTTL: /* --neg-ttl */
+    case LOPT_MAXTTL: /* --max-ttl */
+      {
+       int ttl;
+       if (!atoi_check(arg, &ttl))
+         option = '?';
+       else if (option == LOPT_NEGTTL)
+         daemon->neg_ttl = (unsigned long)ttl;
+       else if (option == LOPT_MAXTTL)
+         daemon->max_ttl = (unsigned long)ttl;
+       else
+         daemon->local_ttl = (unsigned long)ttl;
+       break;
+      }
+      
+#ifdef HAVE_DHCP
+    case 'X': /* --dhcp-lease-max */
+      if (!atoi_check(arg, &daemon->dhcp_max))
+       option = '?';
+      break;
+#endif
+      
+#ifdef HAVE_TFTP
+    case LOPT_TFTP:  /* --enable-tftp */
+      if (arg)
+       {
+         struct interface_list *new = opt_malloc(sizeof(struct interface_list));
+         new->interface = opt_string_alloc(arg);
+         new->next = daemon->tftp_interfaces;
+         daemon->tftp_interfaces = new;
+       }
+      else
+       daemon->tftp_unlimited = 1;
+      break;
+
+    case LOPT_TFTP_MAX:  /*  --tftp-max */
+      if (!atoi_check(arg, &daemon->tftp_max))
+       option = '?';
+      break;  
+
+    case LOPT_PREFIX: /* --tftp-prefix */
+      comma = split(arg);
+      if (comma)
+       {
+         struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
+         new->interface = opt_string_alloc(comma);
+         new->prefix = opt_string_alloc(arg);
+         new->next = daemon->if_prefix;
+         daemon->if_prefix = new;
+       }
+      else
+       daemon->tftp_prefix = opt_string_alloc(arg);
+      break;
+
+    case LOPT_TFTPPORTS: /* --tftp-port-range */
+      if (!(comma = split(arg)) || 
+         !atoi_check16(arg, &daemon->start_tftp_port) ||
+         !atoi_check16(comma, &daemon->end_tftp_port))
+       problem = _("bad port range");
+      
+      if (daemon->start_tftp_port > daemon->end_tftp_port)
+       {
+         int tmp = daemon->start_tftp_port;
+         daemon->start_tftp_port = daemon->end_tftp_port;
+         daemon->end_tftp_port = tmp;
+       } 
+      
+      break;
+#endif
+             
+    case LOPT_BRIDGE:   /* --bridge-interface */
+      {
+       struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge));
+       if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 )
+         {
+           problem = _("bad bridge-interface");
+           break;
+         }
+       
+       strcpy(new->iface, arg);
+       new->alias = NULL;
+       new->next = daemon->bridges;
+       daemon->bridges = new;
+
+       do {
+         arg = comma;
+         comma = split(arg);
+         if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1)
+           {
+             struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge)); 
+             b->next = new->alias;
+             new->alias = b;
+             strcpy(b->iface, arg);
+           }
+       } while (comma);
+       
+       break;
+      }
+
+#ifdef HAVE_DHCP
+    case 'F':  /* --dhcp-range */
+      {
+       int k, leasepos = 2;
+       char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL };
+       struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
+       
+       new->next = daemon->dhcp;
+       new->lease_time = DEFLEASE;
+       new->addr_epoch = 0;
+       new->netmask.s_addr = 0;
+       new->broadcast.s_addr = 0;
+       new->router.s_addr = 0;
+       new->netid.net = NULL;
+       new->filter = NULL;
+       new->flags = 0;
+       new->interface = NULL;
+
+       gen_prob = _("bad dhcp-range");
+       
+       if (!arg)
+         {
+           option = '?';
+           break;
+         }
+       
+       while(1)
+         {
+           for (cp = arg; *cp; cp++)
+             if (!(*cp == ' ' || *cp == '.' ||  (*cp >='0' && *cp <= '9')))
+               break;
+           
+           if (*cp != ',' && (comma = split(arg)))
+             {
+               if (strstr(arg, "interface:") == arg)
+                 new->interface = opt_string_alloc(arg+10);
+               else if (is_tag_prefix(arg))
+                 {
+                   struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
+                   tt->net = opt_string_alloc(arg+4);
+                   tt->next = new->filter;
+                   new->filter = tt;
+                 }
+               else
+                 {
+                   if (new->netid.net)
+                     problem = _("only one tag allowed");
+                   else if (strstr(arg, "set:") == arg)
+                     new->netid.net = opt_string_alloc(arg+4);
+                   else
+                     new->netid.net = opt_string_alloc(arg);
+                 }
+               arg = comma;
+             }
+           else
+             {
+               a[0] = arg;
+               break;
+             }
+         }
+       
+       for (k = 1; k < 5; k++)
+         if (!(a[k] = split(a[k-1])))
+           break;
+       
+       if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
+         option = '?';
+       else if (strcmp(a[1], "static") == 0)
+         {
+           new->end = new->start;
+           new->flags |= CONTEXT_STATIC;
+         }
+       else if (strcmp(a[1], "proxy") == 0)
+         {
+           new->end = new->start;
+           new->flags |= CONTEXT_PROXY;
+         }
+       else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
+         option = '?';
+       
+       if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
+         {
+           struct in_addr tmp = new->start;
+           new->start = new->end;
+           new->end = tmp;
+         }
+       
+       if (option != '?' && k >= 3 && strchr(a[2], '.') &&  
+           ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
+         {
+           new->flags |= CONTEXT_NETMASK;
+           leasepos = 3;
+           if (!is_same_net(new->start, new->end, new->netmask))
+             problem = _("inconsistent DHCP range");
+         }
+       daemon->dhcp = new;
+       
+       if (k >= 4 && strchr(a[3], '.') &&  
+           ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
+         {
+           new->flags |= CONTEXT_BRDCAST;
+           leasepos = 4;
+         }
+       
+       if (k >= leasepos+1)
+         {
+           if (strcmp(a[leasepos], "infinite") == 0)
+             new->lease_time = 0xffffffff;
+           else
+             {
+               int fac = 1;
+               if (strlen(a[leasepos]) > 0)
+                 {
+                   switch (a[leasepos][strlen(a[leasepos]) - 1])
+                     {
+                     case 'd':
+                     case 'D':
+                       fac *= 24;
+                       /* fall though */
+                     case 'h':
+                     case 'H':
+                       fac *= 60;
+                       /* fall through */
+                     case 'm':
+                     case 'M':
+                       fac *= 60;
+                       /* fall through */
+                     case 's':
+                     case 'S':
+                       a[leasepos][strlen(a[leasepos]) - 1] = 0;
+                     }
+                   
+                   new->lease_time = atoi(a[leasepos]) * fac;
+                   /* Leases of a minute or less confuse
+                      some clients, notably Apple's */
+                   if (new->lease_time < 120)
+                     new->lease_time = 120;
+                 }
+             }
+         }
+       break;
+      }
+
+    case LOPT_BANK:
+    case 'G':  /* --dhcp-host */
+      {
+       int j, k = 0;
+       char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
+       struct dhcp_config *new;
+       struct in_addr in;
+       
+       new = opt_malloc(sizeof(struct dhcp_config));
+       
+       new->next = daemon->dhcp_conf;
+       new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
+       new->hwaddr = NULL;
+       new->netid = NULL;
+
+       if ((a[0] = arg))
+         for (k = 1; k < 6; k++)
+           if (!(a[k] = split(a[k-1])))
+             break;
+       
+       for (j = 0; j < k; j++)
+         if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
+           {
+             char *arg = a[j];
+             
+             if ((arg[0] == 'i' || arg[0] == 'I') &&
+                 (arg[1] == 'd' || arg[1] == 'D') &&
+                 arg[2] == ':')
+               {
+                 if (arg[3] == '*')
+                   new->flags |= CONFIG_NOCLID;
+                 else
+                   {
+                     int len;
+                     arg += 3; /* dump id: */
+                     if (strchr(arg, ':'))
+                       len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
+                     else
+                       {
+                         unhide_metas(arg);
+                         len = (int) strlen(arg);
+                       }
+
+                     if (len == -1)
+                       problem = _("bad hex constant");
+                     else if ((new->clid = opt_malloc(len)))
+                       {
+                         new->flags |= CONFIG_CLID;
+                         new->clid_len = len;
+                         memcpy(new->clid, arg, len);
+                       }
+                   }
+               }
+             /* dhcp-host has strange backwards-compat needs. */
+             else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
+               {
+                 struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
+                 struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
+                 newtag->net = opt_malloc(strlen(arg + 4) + 1);
+                 newlist->next = new->netid;
+                 new->netid = newlist;
+                 newlist->list = newtag;
+                 strcpy(newtag->net, arg+4);
+                 unhide_metas(newtag->net);
+               }
+             else 
+               {
+                 struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
+                 if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX, 
+                                                    &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
+                   problem = _("bad hex constant");
+                 else
+                   {
+                     
+                     newhw->next = new->hwaddr;
+                     new->hwaddr = newhw;
+                   }               
+               }
+           }
+         else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
+           {
+             new->addr = in;
+             new->flags |= CONFIG_ADDR;
+           }
+         else
+           {
+             char *cp, *lastp = NULL, last = 0;
+             int fac = 1;
+             
+             if (strlen(a[j]) > 1)
+               {
+                 lastp = a[j] + strlen(a[j]) - 1;
+                 last = *lastp;
+                 switch (last)
+                   {
+                   case 'd':
+                   case 'D':
+                     fac *= 24;
+                     /* fall through */
+                   case 'h':
+                   case 'H':
+                     fac *= 60;
+                     /* fall through */
+                   case 'm':
+                   case 'M':
+                     fac *= 60;
+                     /* fall through */
+                   case 's':
+                   case 'S':
+                     *lastp = 0;
+                   }
+               }
+             
+             for (cp = a[j]; *cp; cp++)
+               if (!isdigit((unsigned char)*cp) && *cp != ' ')
+                 break;
+             
+             if (*cp)
+               {
+                 if (lastp)
+                   *lastp = last;
+                 if (strcmp(a[j], "infinite") == 0)
+                   {
+                     new->lease_time = 0xffffffff;
+                     new->flags |= CONFIG_TIME;
+                   }
+                 else if (strcmp(a[j], "ignore") == 0)
+                   new->flags |= CONFIG_DISABLE;
+                 else
+                   {
+                     if (!(new->hostname = canonicalise_opt(a[j])) ||
+                         !legal_hostname(new->hostname))
+                       problem = _("bad DHCP host name");
+                     else
+                       new->flags |= CONFIG_NAME;
+                     new->domain = NULL;                       
+                   }
+               }
+             else
+               {
+                 new->lease_time = atoi(a[j]) * fac; 
+                 /* Leases of a minute or less confuse
+                    some clients, notably Apple's */
+                 if (new->lease_time < 120)
+                   new->lease_time = 120;
+                 new->flags |= CONFIG_TIME;
+               }
+           }
+       
+       daemon->dhcp_conf = new;
+       break;
+      }
+
+    case LOPT_TAG_IF:  /* --tag-if */
+      {
+       struct tag_if *new = opt_malloc(sizeof(struct tag_if));
+               
+       new->tag = NULL;
+       new->set = NULL;
+       new->next = NULL;
+       
+       /* preserve order */
+       if (!daemon->tag_if)
+         daemon->tag_if = new;
+       else
+         {
+           struct tag_if *tmp;
+           for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
+           tmp->next = new;
+         }
+
+       while (arg)
+         {
+           size_t len;
+
+           comma = split(arg);
+           len = strlen(arg);
+
+           if (len < 5)
+             {
+               new->set = NULL;
+               break;
+             }
+           else
+             {
+               struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
+               newtag->net = opt_malloc(len - 3);
+               strcpy(newtag->net, arg+4);
+               unhide_metas(newtag->net);
+
+               if (strstr(arg, "set:") == arg)
+                 {
+                   struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
+                   newlist->next = new->set;
+                   new->set = newlist;
+                   newlist->list = newtag;
+                 }
+               else if (strstr(arg, "tag:") == arg)
+                 {
+                   newtag->next = new->tag;
+                   new->tag = newtag;
+                 }
+               else 
+                 {
+                   new->set = NULL;
+                   break;
+                 }
+             }
+           
+           arg = comma;
+         }
+
+       if (!new->set)
+         problem = _("bad tag-if");
+         
+       break;
+      }
+
+      
+    case 'O':           /* --dhcp-option */
+    case LOPT_FORCE:    /* --dhcp-option-force */
+    case LOPT_OPTS:
+    case LOPT_MATCH:    /* --dhcp-match */
+      problem = parse_dhcp_opt(arg, 
+                              option == LOPT_FORCE ? DHOPT_FORCE : 
+                              (option == LOPT_MATCH ? DHOPT_MATCH :
+                              (option == LOPT_OPTS ? DHOPT_BANK : 0)));
+      break;
+      
+    case 'M': /* --dhcp-boot */
+      {
+       struct dhcp_netid *id = NULL;
+       while (is_tag_prefix(arg))
+         {
+           struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
+           newid->next = id;
+           id = newid;
+           comma = split(arg);
+           newid->net = opt_string_alloc(arg+4);
+           arg = comma;
+         };
+       
+       if (!arg)
+         option = '?';
+       else 
+         {
+           char *dhcp_file, *dhcp_sname = NULL;
+           struct in_addr dhcp_next_server;
+           comma = split(arg);
+           dhcp_file = opt_string_alloc(arg);
+           dhcp_next_server.s_addr = 0;
+           if (comma)
+             {
+               arg = comma;
+               comma = split(arg);
+               dhcp_sname = opt_string_alloc(arg);
+               if (comma)
+                 {
+                   unhide_metas(comma);
+                   if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
+                     option = '?';
+                 }
+             }
+           if (option != '?')
+             {
+               struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot));
+               new->file = dhcp_file;
+               new->sname = dhcp_sname;
+               new->next_server = dhcp_next_server;
+               new->netid = id;
+               new->next = daemon->boot_config;
+               daemon->boot_config = new;
+             }
+         }
+       
+       break;
+      }
+
+    case LOPT_PXE_PROMT:  /* --pxe-prompt */
+       {
+        struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
+        int timeout;
+
+        new->netid = NULL;
+        new->opt = 10; /* PXE_MENU_PROMPT */
+
+        while (is_tag_prefix(arg))
+         {
+            struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
+            comma = split(arg);
+            nn->next = new->netid;
+            new->netid = nn;
+            nn->net = opt_string_alloc(arg+4);
+            arg = comma;
+          }
+        
+        if (!arg)
+          option = '?';
+        else
+          {
+            comma = split(arg);
+            unhide_metas(arg);
+            new->len = strlen(arg) + 1;
+            new->val = opt_malloc(new->len);
+            memcpy(new->val + 1, arg, new->len - 1);
+            
+            new->u.vendor_class = (unsigned char *)"PXEClient";
+            new->flags = DHOPT_VENDOR;
+            
+            if (comma && atoi_check(comma, &timeout))
+              *(new->val) = timeout;
+            else
+              *(new->val) = 255;
+
+            new->next = daemon->dhcp_opts;
+            daemon->dhcp_opts = new;
+            daemon->enable_pxe = 1;
+          }
+        
+        break;
+       }
+       
+    case LOPT_PXE_SERV:  /* --pxe-service */
+       {
+        struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
+        char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
+                        "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };  
+        static int boottype = 32768;
+        
+        new->netid = NULL;
+        new->server.s_addr = 0;
+
+        while (is_tag_prefix(arg))
+          {
+            struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
+            comma = split(arg);
+            nn->next = new->netid;
+            new->netid = nn;
+            nn->net = opt_string_alloc(arg+4);
+            arg = comma;
+          }
+       
+        if (arg && (comma = split(arg)))
+          {
+            for (i = 0; CSA[i]; i++)
+              if (strcasecmp(CSA[i], arg) == 0)
+                break;
+            
+            if (CSA[i] || atoi_check(arg, &i))
+              {
+                arg = comma;
+                comma = split(arg);
+                
+                new->CSA = i;
+                new->menu = opt_string_alloc(arg);
+                
+                if (!comma)
+                  {
+                    new->type = 0; /* local boot */
+                    new->basename = NULL;
+                  }
+                else
+                  {
+                    arg = comma;
+                    comma = split(arg);
+                    if (atoi_check(arg, &i))
+                      {
+                        new->type = i;
+                        new->basename = NULL;
+                      }
+                    else
+                      {
+                        new->type = boottype++;
+                        new->basename = opt_string_alloc(arg);
+                      }
+                    
+                    if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1)
+                      option = '?';
+                  }
+
+                /* Order matters */
+                new->next = NULL;
+                if (!daemon->pxe_services)
+                  daemon->pxe_services = new; 
+                else
+                  {
+                    struct pxe_service *s;
+                    for (s = daemon->pxe_services; s->next; s = s->next);
+                    s->next = new;
+                  }
+                
+                daemon->enable_pxe = 1;
+                break;
+               
+              }
+          }
+        
+        option = '?';
+        break;
+       }
+        
+    case '4':  /* --dhcp-mac */
+      {
+       if (!(comma = split(arg)))
+         option = '?';
+       else
+         {
+           struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
+           new->netid.net = opt_string_alloc(set_prefix(arg));
+           unhide_metas(comma);
+           new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
+           if (new->hwaddr_len == -1)
+             option = '?';
+           else
+             {
+               new->next = daemon->dhcp_macs;
+               daemon->dhcp_macs = new;
+             }
+         }
+      }
+      break;
+      
+    case 'U':           /* --dhcp-vendorclass */
+    case 'j':           /* --dhcp-userclass */
+    case LOPT_CIRCUIT:  /* --dhcp-circuitid */
+    case LOPT_REMOTE:   /* --dhcp-remoteid */
+    case LOPT_SUBSCR:   /* --dhcp-subscrid */
+      {
+       if (!(comma = split(arg)))
+         option = '?';
+       else
+         {
+           unsigned char *p;
+           int dig = 0;
+           struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
+           new->netid.net = opt_string_alloc(set_prefix(arg));
+           /* check for hex string - must digits may include : must not have nothing else, 
+              only allowed for agent-options. */
+           for (p = (unsigned char *)comma; *p; p++)
+             if (isxdigit(*p))
+               dig = 1;
+             else if (*p != ':')
+               break;
+           unhide_metas(comma);
+           if (option == 'U' || option == 'j' || *p || !dig)
+             {
+               new->len = strlen(comma);  
+               new->data = opt_malloc(new->len);
+               memcpy(new->data, comma, new->len);
+             }
+           else
+             {
+               new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL);
+               new->data = opt_malloc(new->len);
+               memcpy(new->data, comma, new->len);
+             }
+
+           switch (option)
+             {
+             case 'j':
+               new->match_type = MATCH_USER;
+               break;
+             case 'U':
+               new->match_type = MATCH_VENDOR;
+               break; 
+             case LOPT_CIRCUIT:
+               new->match_type = MATCH_CIRCUIT;
+               break;
+             case LOPT_REMOTE:
+               new->match_type = MATCH_REMOTE;
+               break;
+             case LOPT_SUBSCR:
+               new->match_type = MATCH_SUBSCRIBER;
+               break;
+             }
+           new->next = daemon->dhcp_vendors;
+           daemon->dhcp_vendors = new;
+         }
+       break;
+      }
+      
+    case LOPT_ALTPORT:   /* --dhcp-alternate-port */
+      if (!arg)
+       {
+         daemon->dhcp_server_port = DHCP_SERVER_ALTPORT;
+         daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT;
+       }
+      else
+       {
+         comma = split(arg);
+         if (!atoi_check16(arg, &daemon->dhcp_server_port) || 
+             (comma && !atoi_check16(comma, &daemon->dhcp_client_port)))
+           problem = _("invalid port number");
+         if (!comma)
+           daemon->dhcp_client_port = daemon->dhcp_server_port+1; 
+       }
+      break;
+
+    case 'J':            /* --dhcp-ignore */
+    case LOPT_NO_NAMES:  /* --dhcp-ignore-names */
+    case LOPT_BROADCAST: /* --dhcp-broadcast */
+    case '3':            /* --bootp-dynamic */
+    case LOPT_GEN_NAMES: /* --dhcp-generate-names */
+      {
+       struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
+       struct dhcp_netid *list = NULL;
+       if (option == 'J')
+         {
+           new->next = daemon->dhcp_ignore;
+           daemon->dhcp_ignore = new;
+         }
+       else if (option == LOPT_BROADCAST)
+         {
+           new->next = daemon->force_broadcast;
+           daemon->force_broadcast = new;
+         }
+       else if (option == '3')
+         {
+           new->next = daemon->bootp_dynamic;
+           daemon->bootp_dynamic = new;
+         }
+       else if (option == LOPT_GEN_NAMES)
+         {
+           new->next = daemon->dhcp_gen_names;
+           daemon->dhcp_gen_names = new;
+         }
+       else
+         {
+           new->next = daemon->dhcp_ignore_names;
+           daemon->dhcp_ignore_names = new;
+         }
+       
+       while (arg) {
+         struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid));
+         comma = split(arg);
+         member->next = list;
+         list = member;
+         if (is_tag_prefix(arg))
+           member->net = opt_string_alloc(arg+4);
+         else
+           member->net = opt_string_alloc(arg);
+         arg = comma;
+       }
+       
+       new->list = list;
+       break;
+      }
+
+    case LOPT_PROXY: /* --dhcp-proxy */
+      daemon->override = 1;
+      while (arg) {
+       struct addr_list *new = opt_malloc(sizeof(struct addr_list));
+       comma = split(arg);
+       if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
+         problem = _("bad dhcp-proxy address");
+       new->next = daemon->override_relays;
+       daemon->override_relays = new;
+       arg = comma;
+      }
+      break;
+#endif
+      
+    case 'V':  /* --alias */
+      {
+       char *dash, *a[3] = { NULL, NULL, NULL };
+       int k = 0;
+       struct doctor *new = opt_malloc(sizeof(struct doctor));
+       new->next = daemon->doctors;
+       daemon->doctors = new;
+       new->mask.s_addr = 0xffffffff;
+       new->end.s_addr = 0;
+
+       if ((a[0] = arg))
+         for (k = 1; k < 3; k++)
+           {
+             if (!(a[k] = split(a[k-1])))
+               break;
+             unhide_metas(a[k]);
+           }
+       
+       dash = split_chr(a[0], '-');
+
+       if ((k < 2) || 
+           ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
+           ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
+         option = '?';
+       
+       if (k == 3)
+         new->mask.s_addr = inet_addr(a[2]);
+       
+       if (dash && 
+           ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
+            !is_same_net(new->in, new->end, new->mask) ||
+            ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
+         problem = _("invalid alias range");
+       
+       break;
+      }
+      
+    case LOPT_INTNAME:  /* --interface-name */
+      {
+       struct interface_name *new, **up;
+       char *domain = NULL;
+
+       comma = split(arg);
+       
+       if (!comma || !(domain = canonicalise_opt(arg)))
+         problem = _("bad interface name");
+       
+       new = opt_malloc(sizeof(struct interface_name));
+       new->next = NULL;
+       /* Add to the end of the list, so that first name
+          of an interface is used for PTR lookups. */
+       for (up = &daemon->int_names; *up; up = &((*up)->next));
+       *up = new;
+       new->name = domain;
+       new->intr = opt_string_alloc(comma);
+       break;
+      }
+      
+    case LOPT_CNAME: /* --cname */
+      {
+       struct cname *new;
+       
+       if (!(comma = split(arg)))
+         option = '?';
+       else
+         {
+           char *alias = canonicalise_opt(arg);
+           char *target = canonicalise_opt(comma);
+           
+           if (!alias || !target)
+             problem = _("bad CNAME");
+           else
+             {
+               for (new = daemon->cnames; new; new = new->next)
+                 if (hostname_isequal(new->alias, arg))
+                   problem = _("duplicate CNAME");
+               new = opt_malloc(sizeof(struct cname));
+               new->next = daemon->cnames;
+               daemon->cnames = new;
+               new->alias = alias;
+               new->target = target;
+             }
+         }
+       break;
+      }
+
+    case LOPT_PTR:  /* --ptr-record */
+      {
+       struct ptr_record *new;
+       char *dom, *target = NULL;
+
+       comma = split(arg);
+       
+       if (!(dom = canonicalise_opt(arg)) ||
+           (comma && !(target = canonicalise_opt(comma))))
+         problem = _("bad PTR record");
+       else
+         {
+           new = opt_malloc(sizeof(struct ptr_record));
+           new->next = daemon->ptr;
+           daemon->ptr = new;
+           new->name = dom;
+           new->ptr = target;
+         }
+       break;
+      }
+
+    case LOPT_NAPTR: /* --naptr-record */
+      {
+       char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+       int k = 0;
+       struct naptr *new;
+       int order, pref;
+       char *name, *replace = NULL;
+
+       if ((a[0] = arg))
+         for (k = 1; k < 7; k++)
+           if (!(a[k] = split(a[k-1])))
+             break;
+       
+       
+       if (k < 6 || 
+           !(name = canonicalise_opt(a[0])) ||
+           !atoi_check16(a[1], &order) || 
+           !atoi_check16(a[2], &pref) ||
+           (k == 7 && !(replace = canonicalise_opt(a[6]))))
+         problem = _("bad NAPTR record");
+       else
+         {
+           new = opt_malloc(sizeof(struct naptr));
+           new->next = daemon->naptr;
+           daemon->naptr = new;
+           new->name = name;
+           new->flags = opt_string_alloc(a[3]);
+           new->services = opt_string_alloc(a[4]);
+           new->regexp = opt_string_alloc(a[5]);
+           new->replace = replace;
+           new->order = order;
+           new->pref = pref;
+         }
+       break;
+      }
+       
+    case 'Y':  /* --txt-record */
+      {
+       struct txt_record *new;
+       unsigned char *p, *cnt;
+       size_t len;
+
+       comma = split(arg);
+               
+       new = opt_malloc(sizeof(struct txt_record));
+       new->next = daemon->txt;
+       daemon->txt = new;
+       new->class = C_IN;
+       
+       if (!(new->name = canonicalise_opt(arg)))
+         {
+           problem = _("bad TXT record");
+           break;
+         }
+
+       len = comma ? strlen(comma) : 0;
+       len += (len/255) + 1; /* room for extra counts */
+       new->txt = p = opt_malloc(len);
+
+       cnt = p++;
+       *cnt = 0;
+       
+       while (comma && *comma)
+         {
+           unsigned char c = (unsigned char)*comma++;
+
+           if (c == ',' || *cnt == 255)
+             {
+               if (c != ',')
+                 comma--;
+               cnt = p++;
+               *cnt = 0;
+             }
+           else
+             {
+               *p++ = unhide_meta(c);
+               (*cnt)++;
+             }
+         }
+
+       new->len = p - new->txt;
+
+       break;
+      }
+      
+    case 'W':  /* --srv-host */
+      {
+       int port = 1, priority = 0, weight = 0;
+       char *name, *target = NULL;
+       struct mx_srv_record *new;
+       
+       comma = split(arg);
+       
+       if (!(name = canonicalise_opt(arg)))
+         problem = _("bad SRV record");
+         
+       if (comma)
+         {
+           arg = comma;
+           comma = split(arg);
+           if (!(target = canonicalise_opt(arg))
+)            problem = _("bad SRV target");
+               
+           if (comma)
+             {
+               arg = comma;
+               comma = split(arg);
+               if (!atoi_check16(arg, &port))
+                 problem = _("invalid port number");
+               
+               if (comma)
+                 {
+                   arg = comma;
+                   comma = split(arg);
+                   if (!atoi_check16(arg, &priority))
+                     problem = _("invalid priority");
+                       
+                   if (comma)
+                     {
+                       arg = comma;
+                       comma = split(arg);
+                       if (!atoi_check16(arg, &weight))
+                         problem = _("invalid weight");
+                     }
+                 }
+             }
+         }
+       
+       new = opt_malloc(sizeof(struct mx_srv_record));
+       new->next = daemon->mxnames;
+       daemon->mxnames = new;
+       new->issrv = 1;
+       new->name = name;
+       new->target = target;
+       new->srvport = port;
+       new->priority = priority;
+       new->weight = weight;
+       break;
+      }
+      
+    default:
+      return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
+
+    }
+
+  if (problem)
+    return problem;
+  
+  if (option == '?')
+    return gen_prob;
+
+  return NULL;
+}
+
+static void read_file(char *file, FILE *f, int hard_opt)       
+{
+  volatile int lineno = 0;
+  char *buff = daemon->namebuff;
+  
+  while (fgets(buff, MAXDNAME, f))
+    {
+      int white, i, option; ;
+      char *errmess, *p, *arg, *start;
+      size_t len;
+
+      /* Memory allocation failure longjmps here if mem_recover == 1 */ 
+      if (hard_opt)
+       {
+         if (setjmp(mem_jmp))
+           continue;
+         mem_recover = 1;
+       }
+      
+      lineno++;
+      errmess = NULL;
+      
+      /* Implement quotes, inside quotes we allow \\ \" \n and \t 
+        metacharacters get hidden also strip comments */
+      for (white = 1, p = buff; *p; p++)
+       {
+         if (*p == '"')
+           {
+             memmove(p, p+1, strlen(p+1)+1);
+
+             for(; *p && *p != '"'; p++)
+               {
+                 if (*p == '\\' && strchr("\"tnebr\\", p[1]))
+                   {
+                     if (p[1] == 't')
+                       p[1] = '\t';
+                     else if (p[1] == 'n')
+                       p[1] = '\n';
+                     else if (p[1] == 'b')
+                       p[1] = '\b';
+                     else if (p[1] == 'r')
+                       p[1] = '\r';
+                     else if (p[1] == 'e') /* escape */
+                       p[1] = '\033';
+                     memmove(p, p+1, strlen(p+1)+1);
+                   }
+                 *p = hide_meta(*p);
+               }
+
+             if (*p == 0) 
+               {
+                 errmess = _("missing \"");
+                 goto oops; 
+               }
+
+             memmove(p, p+1, strlen(p+1)+1);
+           }
+
+         if (isspace(*p))
+           {
+             *p = ' ';
+             white = 1;
+           }
+         else 
+           {
+             if (white && *p == '#')
+               { 
+                 *p = 0;
+                 break;
+               }
+             white = 0;
+           } 
+       }
+
+      
+      /* strip leading spaces */
+      for (start = buff; *start && *start == ' '; start++);
+      
+      /* strip trailing spaces */
+      for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
+      
+      if (len == 0)
+       continue; 
+      else
+       start[len] = 0;
+      
+      if (hard_opt != 0)
+       arg = start;
+      else if ((p=strchr(start, '=')))
+       {
+         /* allow spaces around "=" */
+         for (arg = p+1; *arg == ' '; arg++);
+         for (; p >= start && (*p == ' ' || *p == '='); p--)
+           *p = 0;
+       }
+      else
+       arg = NULL;
+
+      if (hard_opt != 0)
+       option = hard_opt;
+      else
+       {
+         for (option = 0, i = 0; opts[i].name; i++) 
+           if (strcmp(opts[i].name, start) == 0)
+             {
+               option = opts[i].val;
+               break;
+             }
+         
+         if (!option)
+           errmess = _("bad option");
+         else if (opts[i].has_arg == 0 && arg)
+           errmess = _("extraneous parameter");
+         else if (opts[i].has_arg == 1 && !arg)
+           errmess = _("missing parameter");
+       }
+         
+      if (!errmess)
+       errmess = one_opt(option, arg, _("error"), 0);
+      
+      if (errmess)
+       {
+       oops:
+         sprintf(buff, _("%s at line %d of %%s"), errmess, lineno);
+         if (hard_opt != 0)
+           my_syslog(LOG_ERR, buff, file);
+         else
+           die(buff, file, EC_BADCONF);
+       }
+    }
+
+  mem_recover = 0;
+  fclose(f);
+}
+
+static void one_file(char *file, int hard_opt)
+{
+  FILE *f;
+  int nofile_ok = 0;
+  static int read_stdin = 0;
+  static struct fileread {
+    dev_t dev;
+    ino_t ino;
+    struct fileread *next;
+  } *filesread = NULL;
+  
+  if (hard_opt == '7')
+    {
+      /* default conf-file reading */
+      hard_opt = 0;
+      nofile_ok = 1;
+    }
+
+  if (hard_opt == 0 && strcmp(file, "-") == 0)
+    {
+      if (read_stdin == 1)
+       return;
+      read_stdin = 1;
+      file = "stdin";
+      f = stdin;
+    }
+  else
+    {
+      /* ignore repeated files. */
+      struct stat statbuf;
+    
+      if (hard_opt == 0 && stat(file, &statbuf) == 0)
+       {
+         struct fileread *r;
+         
+         for (r = filesread; r; r = r->next)
+           if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino)
+             return;
+         
+         r = safe_malloc(sizeof(struct fileread));
+         r->next = filesread;
+         filesread = r;
+         r->dev = statbuf.st_dev;
+         r->ino = statbuf.st_ino;
+       }
+      
+      if (!(f = fopen(file, "r")))
+       {   
+         if (errno == ENOENT && nofile_ok)
+           return; /* No conffile, all done. */
+         else
+           {
+             char *str = _("cannot read %s: %s");
+             if (hard_opt != 0)
+               {
+                 my_syslog(LOG_ERR, str, file, strerror(errno));
+                 return;
+               }
+             else
+               die(str, file, EC_FILE);
+           }
+       } 
+    }
+  
+  read_file(file, f, hard_opt);
+}
+
+/* expand any name which is a directory */
+struct hostsfile *expand_filelist(struct hostsfile *list)
+{
+  int i;
+  struct hostsfile *ah;
+
+  for (i = 0, ah = list; ah; ah = ah->next)
+    {
+      if (i <= ah->index)
+       i = ah->index + 1;
+
+      if (ah->flags & AH_DIR)
+       ah->flags |= AH_INACTIVE;
+      else
+       ah->flags &= ~AH_INACTIVE;
+    }
+
+  for (ah = list; ah; ah = ah->next)
+    if (!(ah->flags & AH_INACTIVE))
+      {
+       struct stat buf;
+       if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
+         {
+           DIR *dir_stream;
+           struct dirent *ent;
+           
+           /* don't read this as a file */
+           ah->flags |= AH_INACTIVE;
+
+           if (!(dir_stream = opendir(ah->fname)))
+             my_syslog(LOG_ERR, _("cannot access directory %s: %s"), 
+                       ah->fname, strerror(errno));
+           else
+             {
+               while ((ent = readdir(dir_stream)))
+                 {
+                   size_t lendir = strlen(ah->fname);
+                   size_t lenfile = strlen(ent->d_name);
+                   struct hostsfile *ah1;
+                   char *path;
+                   
+                   /* ignore emacs backups and dotfiles */
+                   if (lenfile == 0 || 
+                       ent->d_name[lenfile - 1] == '~' ||
+                       (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
+                       ent->d_name[0] == '.')
+                     continue;
+                   
+                   /* see if we have an existing record.
+                      dir is ah->fname 
+                      file is ent->d_name
+                      path to match is ah1->fname */
+                   
+                   for (ah1 = list; ah1; ah1 = ah1->next)
+                     {
+                       if (lendir < strlen(ah1->fname) &&
+                           strstr(ah1->fname, ah->fname) == ah1->fname &&
+                           ah1->fname[lendir] == '/' &&
+                           strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
+                         {
+                           ah1->flags &= ~AH_INACTIVE;
+                           break;
+                         }
+                     }
+                   
+                   /* make new record */
+                   if (!ah1)
+                     {
+                       if (!(ah1 = whine_malloc(sizeof(struct hostsfile))))
+                         continue;
+                       
+                       if (!(path = whine_malloc(lendir + lenfile + 2)))
+                         {
+                           free(ah1);
+                           continue;
+                         }
+                       
+                       strcpy(path, ah->fname);
+                       strcat(path, "/");
+                       strcat(path, ent->d_name);
+                       ah1->fname = path;
+                       ah1->index = i++;
+                       ah1->flags = AH_DIR;
+                       ah1->next = list;
+                       list = ah1;
+                     }
+                   
+                   /* inactivate record if not regular file */
+                   if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
+                     ah1->flags |= AH_INACTIVE; 
+                   
+                 }
+               closedir(dir_stream);
+             }
+         }
+      }
+  
+  return list;
+}
+
+
+#ifdef HAVE_DHCP
+void reread_dhcp(void)
+{
+  struct hostsfile *hf;
+
+  if (daemon->dhcp_hosts_file)
+    {
+      struct dhcp_config *configs, *cp, **up;
+  
+      /* remove existing... */
+      for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
+       {
+         cp = configs->next;
+         
+         if (configs->flags & CONFIG_BANK)
+           {
+             struct hwaddr_config *mac, *tmp;
+             struct dhcp_netid_list *list, *tmplist;
+             
+             for (mac = configs->hwaddr; mac; mac = tmp)
+               {
+                 tmp = mac->next;
+                 free(mac);
+               }
+
+             if (configs->flags & CONFIG_CLID)
+               free(configs->clid);
+
+             for (list = configs->netid; list; list = tmplist)
+               {
+                 free(list->list);
+                 tmplist = list->next;
+                 free(list);
+               }
+             
+             if (configs->flags & CONFIG_NAME)
+               free(configs->hostname);
+             
+             *up = configs->next;
+             free(configs);
+           }
+         else
+           up = &configs->next;
+       }
+      
+      daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file);
+      for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
+        if (!(hf->flags & AH_INACTIVE))
+          {
+            one_file(hf->fname, LOPT_BANK);  
+            my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
+          }
+    }
+
+  if (daemon->dhcp_opts_file)
+    {
+      struct dhcp_opt *opts, *cp, **up;
+      struct dhcp_netid *id, *next;
+
+      for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
+       {
+         cp = opts->next;
+         
+         if (opts->flags & DHOPT_BANK)
+           {
+             if ((opts->flags & DHOPT_VENDOR))
+               free(opts->u.vendor_class);
+             free(opts->val);
+             for (id = opts->netid; id; id = next)
+               {
+                 next = id->next;
+                 free(id->net);
+                 free(id);
+               }
+             *up = opts->next;
+             free(opts);
+           }
+         else
+           up = &opts->next;
+       }
+      
+      daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
+      for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
+       if (!(hf->flags & AH_INACTIVE))
+         {
+           one_file(hf->fname, LOPT_OPTS);  
+           my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
+         }
+    }
+}
+#endif
+    
+void read_opts(int argc, char **argv, char *compile_opts)
+{
+  char *buff = opt_malloc(MAXDNAME);
+  int option, conffile_opt = '7', testmode = 0;
+  char *errmess, *arg, *conffile = CONFFILE;
+      
+  opterr = 0;
+
+  daemon = opt_malloc(sizeof(struct daemon));
+  memset(daemon, 0, sizeof(struct daemon));
+  daemon->namebuff = buff;
+
+  /* Set defaults - everything else is zero or NULL */
+  daemon->cachesize = CACHESIZ;
+  daemon->ftabsize = FTABSIZ;
+  daemon->port = NAMESERVER_PORT;
+  daemon->dhcp_client_port = DHCP_CLIENT_PORT;
+  daemon->dhcp_server_port = DHCP_SERVER_PORT;
+  daemon->default_resolv.is_default = 1;
+  daemon->default_resolv.name = RESOLVFILE;
+  daemon->resolv_files = &daemon->default_resolv;
+  daemon->username = CHUSER;
+  daemon->runfile =  RUNFILE;
+  daemon->dhcp_max = MAXLEASES;
+  daemon->tftp_max = TFTP_MAX_CONNECTIONS;
+  daemon->edns_pktsz = EDNS_PKTSZ;
+  daemon->log_fac = -1;
+  add_txt("version.bind", "dnsmasq-" VERSION );
+  add_txt("authors.bind", "Simon Kelley");
+  add_txt("copyright.bind", COPYRIGHT);
+
+  while (1) 
+    {
+#ifdef HAVE_GETOPT_LONG
+      option = getopt_long(argc, argv, OPTSTRING, opts, NULL);
+#else
+      option = getopt(argc, argv, OPTSTRING);
+#endif
+      
+      if (option == -1)
+       {
+         for (; optind < argc; optind++)
+           {
+             unsigned char *c = (unsigned char *)argv[optind];
+             for (; *c != 0; c++)
+               if (!isspace(*c))
+                 die(_("junk found in command line"), NULL, EC_BADCONF);
+           }
+         break;
+       }
+
+      /* Copy optarg so that argv doesn't get changed */
+      if (optarg)
+       {
+         strncpy(buff, optarg, MAXDNAME);
+         buff[MAXDNAME-1] = 0;
+         arg = buff;
+       }
+      else
+       arg = NULL;
+      
+      /* command-line only stuff */
+      if (option == LOPT_TEST)
+       testmode = 1;
+      else if (option == 'w')
+       {
+         if (argc != 3 ||  strcmp(argv[2], "dhcp") != 0)
+           do_usage();
+#ifdef HAVE_DHCP
+         else
+           display_opts();
+#endif
+         exit(0);
+       }
+      else if (option == 'v')
+       {
+         printf(_("Dnsmasq version %s  %s\n"), VERSION, COPYRIGHT);
+         printf(_("Compile time options %s\n\n"), compile_opts); 
+         printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n"));
+         printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n"));
+         printf(_("under the terms of the GNU General Public License, version 2 or 3.\n"));
+          exit(0);
+        }
+      else if (option == 'C')
+       {
+         conffile_opt = 0; /* file must exist */
+         conffile = opt_string_alloc(arg);
+       }
+      else
+       {
+#ifdef HAVE_GETOPT_LONG
+         errmess = one_opt(option, arg, _("try --help"), 1);
+#else 
+         errmess = one_opt(option, arg, _("try -w"), 1); 
+#endif  
+         if (errmess)
+           die(_("bad command line options: %s"), errmess, EC_BADCONF);
+       }
+    }
+
+  if (conffile)
+    one_file(conffile, conffile_opt);
+
+  /* port might not be known when the address is parsed - fill in here */
+  if (daemon->servers)
+    {
+      struct server *tmp;
+      for (tmp = daemon->servers; tmp; tmp = tmp->next)
+       if (!(tmp->flags & SERV_HAS_SOURCE))
+         {
+           if (tmp->source_addr.sa.sa_family == AF_INET)
+             tmp->source_addr.in.sin_port = htons(daemon->query_port);
+#ifdef HAVE_IPV6
+           else if (tmp->source_addr.sa.sa_family == AF_INET6)
+             tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
+#endif 
+         } 
+    }
+  
+  if (daemon->if_addrs)
+    {  
+      struct iname *tmp;
+      for(tmp = daemon->if_addrs; tmp; tmp = tmp->next)
+       if (tmp->addr.sa.sa_family == AF_INET)
+         tmp->addr.in.sin_port = htons(daemon->port);
+#ifdef HAVE_IPV6
+       else if (tmp->addr.sa.sa_family == AF_INET6)
+         tmp->addr.in6.sin6_port = htons(daemon->port);
+#endif /* IPv6 */
+    }
+                     
+  /* only one of these need be specified: the other defaults to the host-name */
+  if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
+    {
+      struct mx_srv_record *mx;
+      
+      if (gethostname(buff, MAXDNAME) == -1)
+       die(_("cannot get host-name: %s"), NULL, EC_MISC);
+      
+      for (mx = daemon->mxnames; mx; mx = mx->next)
+       if (!mx->issrv && hostname_isequal(mx->name, buff))
+         break;
+      
+      if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx)
+       {
+         mx = opt_malloc(sizeof(struct mx_srv_record));
+         mx->next = daemon->mxnames;
+         mx->issrv = 0;
+         mx->target = NULL;
+         mx->name = opt_string_alloc(buff);
+         daemon->mxnames = mx;
+       }
+      
+      if (!daemon->mxtarget)
+       daemon->mxtarget = opt_string_alloc(buff);
+
+      for (mx = daemon->mxnames; mx; mx = mx->next)
+       if (!mx->issrv && !mx->target)
+         mx->target = daemon->mxtarget;
+    }
+
+  if (!option_bool(OPT_NO_RESOLV) &&
+      daemon->resolv_files && 
+      daemon->resolv_files->next && 
+      option_bool(OPT_NO_POLL))
+    die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
+  
+  if (option_bool(OPT_RESOLV_DOMAIN))
+    {
+      char *line;
+      FILE *f;
+
+      if (option_bool(OPT_NO_RESOLV) ||
+         !daemon->resolv_files || 
+         (daemon->resolv_files)->next)
+       die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF);
+      
+      if (!(f = fopen((daemon->resolv_files)->name, "r")))
+       die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE);
+      
+      while ((line = fgets(buff, MAXDNAME, f)))
+       {
+         char *token = strtok(line, " \t\n\r");
+         
+         if (!token || strcmp(token, "search") != 0)
+           continue;
+         
+         if ((token = strtok(NULL, " \t\n\r")) &&  
+             (daemon->domain_suffix = canonicalise_opt(token)))
+           break;
+       }
+
+      fclose(f);
+
+      if (!daemon->domain_suffix)
+       die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC);
+    }
+
+  if (daemon->domain_suffix)
+    {
+       /* add domain for any srv record without one. */
+      struct mx_srv_record *srv;
+      
+      for (srv = daemon->mxnames; srv; srv = srv->next)
+       if (srv->issrv &&
+           strchr(srv->name, '.') && 
+           strchr(srv->name, '.') == strrchr(srv->name, '.'))
+         {
+           strcpy(buff, srv->name);
+           strcat(buff, ".");
+           strcat(buff, daemon->domain_suffix);
+           free(srv->name);
+           srv->name = opt_string_alloc(buff);
+         }
+    }
+  else if (option_bool(OPT_DHCP_FQDN))
+    die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF);
+
+  if (testmode)
+    {
+      fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK"));
+      exit(0);
+    }
+}  
diff --git a/src/rfc1035.c b/src/rfc1035.c
new file mode 100644 (file)
index 0000000..889c1f0
--- /dev/null
@@ -0,0 +1,1815 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+static int add_resource_record(struct dns_header *header, char *limit, int *truncp, 
+                              unsigned int nameoffset, unsigned char **pp, 
+                              unsigned long ttl, unsigned int *offset, unsigned short type, 
+                              unsigned short class, char *format, ...);
+
+#define CHECK_LEN(header, pp, plen, len) \
+    ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
+
+#define ADD_RDLEN(header, pp, plen, len) \
+    (!CHECK_LEN(header, pp, plen, len) ? 0 : (long)((pp) += (len)), 1)
+
+static int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, 
+                       char *name, int isExtract, int extrabytes)
+{
+  unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
+  unsigned int j, l, hops = 0;
+  int retvalue = 1;
+  
+  if (isExtract)
+    *cp = 0;
+
+  while (1)
+    { 
+      unsigned int label_type;
+
+      if (!CHECK_LEN(header, p, plen, 1))
+       return 0;
+      
+      if ((l = *p++) == 0) 
+       /* end marker */
+       {
+         /* check that there are the correct no of bytes after the name */
+         if (!CHECK_LEN(header, p, plen, extrabytes))
+           return 0;
+         
+         if (isExtract)
+           {
+             if (cp != (unsigned char *)name)
+               cp--;
+             *cp = 0; /* terminate: lose final period */
+           }
+         else if (*cp != 0)
+           retvalue = 2;
+         
+         if (p1) /* we jumped via compression */
+           *pp = p1;
+         else
+           *pp = p;
+         
+         return retvalue;
+       }
+
+      label_type = l & 0xc0;
+      
+      if (label_type == 0xc0) /* pointer */
+       { 
+         if (!CHECK_LEN(header, p, plen, 1))
+           return 0;
+             
+         /* get offset */
+         l = (l&0x3f) << 8;
+         l |= *p++;
+         
+         if (!p1) /* first jump, save location to go back to */
+           p1 = p;
+             
+         hops++; /* break malicious infinite loops */
+         if (hops > 255)
+           return 0;
+         
+         p = l + (unsigned char *)header;
+       }
+      else if (label_type == 0x80)
+       return 0; /* reserved */
+      else if (label_type == 0x40)
+       { /* ELT */
+         unsigned int count, digs;
+         
+         if ((l & 0x3f) != 1)
+           return 0; /* we only understand bitstrings */
+
+         if (!isExtract)
+           return 0; /* Cannot compare bitsrings */
+         
+         count = *p++;
+         if (count == 0)
+           count = 256;
+         digs = ((count-1)>>2)+1;
+         
+         /* output is \[x<hex>/siz]. which is digs+9 chars */
+         if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
+           return 0;
+         if (!CHECK_LEN(header, p, plen, (count-1)>>3))
+           return 0;
+
+         *cp++ = '\\';
+         *cp++ = '[';
+         *cp++ = 'x';
+         for (j=0; j<digs; j++)
+           {
+             unsigned int dig;
+             if (j%2 == 0)
+               dig = *p >> 4;
+             else
+               dig = *p++ & 0x0f;
+             
+             *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10;
+           } 
+         cp += sprintf((char *)cp, "/%d]", count);
+         /* do this here to overwrite the zero char from sprintf */
+         *cp++ = '.';
+       }
+      else 
+       { /* label_type = 0 -> label. */
+         if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
+           return 0;
+         if (!CHECK_LEN(header, p, plen, l))
+           return 0;
+         
+         for(j=0; j<l; j++, p++)
+           if (isExtract)
+             {
+               unsigned char c = *p;
+               if (isascii(c) && !iscntrl(c) && c != '.')
+                 *cp++ = *p;
+               else
+                 return 0;
+             }
+           else 
+             {
+               unsigned char c1 = *cp, c2 = *p;
+               
+               if (c1 == 0)
+                 retvalue = 2;
+               else 
+                 {
+                   cp++;
+                   if (c1 >= 'A' && c1 <= 'Z')
+                     c1 += 'a' - 'A';
+                   if (c2 >= 'A' && c2 <= 'Z')
+                     c2 += 'a' - 'A';
+                   
+                   if (c1 != c2)
+                     retvalue =  2;
+                 }
+             }
+         
+         if (isExtract)
+           *cp++ = '.';
+         else if (*cp != 0 && *cp++ != '.')
+           retvalue = 2;
+       }
+    }
+}
+/* Max size of input string (for IPv6) is 75 chars.) */
+#define MAXARPANAME 75
+static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
+{
+  int j;
+  char name[MAXARPANAME+1], *cp1;
+  unsigned char *addr = (unsigned char *)addrp;
+  char *lastchunk = NULL, *penchunk = NULL;
+  
+  if (strlen(namein) > MAXARPANAME)
+    return 0;
+
+  memset(addrp, 0, sizeof(struct all_addr));
+
+  /* turn name into a series of asciiz strings */
+  /* j counts no of labels */
+  for(j = 1,cp1 = name; *namein; cp1++, namein++)
+    if (*namein == '.')
+      {
+       penchunk = lastchunk;
+        lastchunk = cp1 + 1;
+       *cp1 = 0;
+       j++;
+      }
+    else
+      *cp1 = *namein;
+  
+  *cp1 = 0;
+
+  if (j<3)
+    return 0;
+
+  if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr"))
+    {
+      /* IP v4 */
+      /* address arives as a name of the form
+        www.xxx.yyy.zzz.in-addr.arpa
+        some of the low order address octets might be missing
+        and should be set to zero. */
+      for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
+       {
+         /* check for digits only (weeds out things like
+            50.0/24.67.28.64.in-addr.arpa which are used 
+            as CNAME targets according to RFC 2317 */
+         char *cp;
+         for (cp = cp1; *cp; cp++)
+           if (!isdigit((unsigned char)*cp))
+             return 0;
+         
+         addr[3] = addr[2];
+         addr[2] = addr[1];
+         addr[1] = addr[0];
+         addr[0] = atoi(cp1);
+       }
+
+      return F_IPV4;
+    }
+#ifdef HAVE_IPV6
+  else if (hostname_isequal(penchunk, "ip6") && 
+          (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa")))
+    {
+      /* IP v6:
+         Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
+        or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
+      
+        Note that most of these the various reprentations are obsolete and 
+        left-over from the many DNS-for-IPv6 wars. We support all the formats
+        that we can since there is no reason not to.
+      */
+
+      if (*name == '\\' && *(name+1) == '[' && 
+         (*(name+2) == 'x' || *(name+2) == 'X'))
+       {         
+         for (j = 0, cp1 = name+3; *cp1 && isxdigit((unsigned char) *cp1) && j < 32; cp1++, j++)
+           {
+             char xdig[2];
+             xdig[0] = *cp1;
+             xdig[1] = 0;
+             if (j%2)
+               addr[j/2] |= strtol(xdig, NULL, 16);
+             else
+               addr[j/2] = strtol(xdig, NULL, 16) << 4;
+           }
+         
+         if (*cp1 == '/' && j == 32)
+           return F_IPV6;
+       }
+      else
+       {
+         for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
+           {
+             if (*(cp1+1) || !isxdigit((unsigned char)*cp1))
+               return 0;
+             
+             for (j = sizeof(struct all_addr)-1; j>0; j--)
+               addr[j] = (addr[j] >> 4) | (addr[j-1] << 4);
+             addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4);
+           }
+         
+         return F_IPV6;
+       }
+    }
+#endif
+  
+  return 0;
+}
+
+static unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes)
+{
+  while(1)
+    {
+      unsigned int label_type;
+      
+      if (!CHECK_LEN(header, ansp, plen, 1))
+       return NULL;
+      
+      label_type = (*ansp) & 0xc0;
+
+      if (label_type == 0xc0)
+       {
+         /* pointer for compression. */
+         ansp += 2;    
+         break;
+       }
+      else if (label_type == 0x80)
+       return NULL; /* reserved */
+      else if (label_type == 0x40)
+       {
+         /* Extended label type */
+         unsigned int count;
+         
+         if (!CHECK_LEN(header, ansp, plen, 2))
+           return NULL;
+         
+         if (((*ansp++) & 0x3f) != 1)
+           return NULL; /* we only understand bitstrings */
+         
+         count = *(ansp++); /* Bits in bitstring */
+         
+         if (count == 0) /* count == 0 means 256 bits */
+           ansp += 32;
+         else
+           ansp += ((count-1)>>3)+1;
+       }
+      else
+       { /* label type == 0 Bottom six bits is length */
+         unsigned int len = (*ansp++) & 0x3f;
+         
+         if (!ADD_RDLEN(header, ansp, plen, len))
+           return NULL;
+
+         if (len == 0)
+           break; /* zero length label marks the end. */
+       }
+    }
+
+  if (!CHECK_LEN(header, ansp, plen, extrabytes))
+    return NULL;
+  
+  return ansp;
+}
+
+static unsigned char *skip_questions(struct dns_header *header, size_t plen)
+{
+  int q;
+  unsigned char *ansp = (unsigned char *)(header+1);
+
+  for (q = ntohs(header->qdcount); q != 0; q--)
+    {
+      if (!(ansp = skip_name(ansp, header, plen, 4)))
+       return NULL;
+      ansp += 4; /* class and type */
+    }
+  
+  return ansp;
+}
+
+static unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen)
+{
+  int i, rdlen;
+  
+  for (i = 0; i < count; i++)
+    {
+      if (!(ansp = skip_name(ansp, header, plen, 10)))
+       return NULL; 
+      ansp += 8; /* type, class, TTL */
+      GETSHORT(rdlen, ansp);
+      if (!ADD_RDLEN(header, ansp, plen, rdlen))
+       return NULL;
+    }
+
+  return ansp;
+}
+
+/* CRC the question section. This is used to safely detect query 
+   retransmision and to detect answers to questions we didn't ask, which 
+   might be poisoning attacks. Note that we decode the name rather 
+   than CRC the raw bytes, since replies might be compressed differently. 
+   We ignore case in the names for the same reason. Return all-ones
+   if there is not question section. */
+unsigned int questions_crc(struct dns_header *header, size_t plen, char *name)
+{
+  int q;
+  unsigned int crc = 0xffffffff;
+  unsigned char *p1, *p = (unsigned char *)(header+1);
+
+  for (q = ntohs(header->qdcount); q != 0; q--) 
+    {
+      if (!extract_name(header, plen, &p, name, 1, 4))
+       return crc; /* bad packet */
+      
+      for (p1 = (unsigned char *)name; *p1; p1++)
+       {
+         int i = 8;
+         char c = *p1;
+
+         if (c >= 'A' && c <= 'Z')
+           c += 'a' - 'A';
+
+         crc ^= c << 24;
+         while (i--)
+           crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
+       }
+      
+      /* CRC the class and type as well */
+      for (p1 = p; p1 < p+4; p1++)
+       {
+         int i = 8;
+         crc ^= *p1 << 24;
+         while (i--)
+           crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
+       }
+
+      p += 4;
+      if (!CHECK_LEN(header, p, plen, 0))
+       return crc; /* bad packet */
+    }
+
+  return crc;
+}
+
+
+size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *pheader, size_t hlen)
+{
+  unsigned char *ansp = skip_questions(header, plen);
+    
+  /* if packet is malformed, just return as-is. */
+  if (!ansp)
+    return plen;
+  
+  if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
+                           header, plen)))
+    return plen;
+    
+  /* restore pseudoheader */
+  if (pheader && ntohs(header->arcount) == 0)
+    {
+      /* must use memmove, may overlap */
+      memmove(ansp, pheader, hlen);
+      header->arcount = htons(1);
+      ansp += hlen;
+    }
+
+  return ansp - (unsigned char *)header;
+}
+
+unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t  *len, unsigned char **p, int *is_sign)
+{
+  /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 
+     also return length of pseudoheader in *len and pointer to the UDP size in *p
+     Finally, check to see if a packet is signed. If it is we cannot change a single bit before
+     forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
+  
+  int i, arcount = ntohs(header->arcount);
+  unsigned char *ansp = (unsigned char *)(header+1);
+  unsigned short rdlen, type, class;
+  unsigned char *ret = NULL;
+
+  if (is_sign)
+    {
+      *is_sign = 0;
+
+      if (OPCODE(header) == QUERY)
+       {
+         for (i = ntohs(header->qdcount); i != 0; i--)
+           {
+             if (!(ansp = skip_name(ansp, header, plen, 4)))
+               return NULL;
+             
+             GETSHORT(type, ansp); 
+             GETSHORT(class, ansp);
+             
+             if (class == C_IN && type == T_TKEY)
+               *is_sign = 1;
+           }
+       }
+    }
+  else
+    {
+      if (!(ansp = skip_questions(header, plen)))
+       return NULL;
+    }
+    
+  if (arcount == 0)
+    return NULL;
+  
+  if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
+    return NULL; 
+  
+  for (i = 0; i < arcount; i++)
+    {
+      unsigned char *save, *start = ansp;
+      if (!(ansp = skip_name(ansp, header, plen, 10)))
+       return NULL; 
+
+      GETSHORT(type, ansp);
+      save = ansp;
+      GETSHORT(class, ansp);
+      ansp += 4; /* TTL */
+      GETSHORT(rdlen, ansp);
+      if (!ADD_RDLEN(header, ansp, plen, rdlen))
+       return NULL;
+      if (type == T_OPT)
+       {
+         if (len)
+           *len = ansp - start;
+         if (p)
+           *p = save;
+         ret = start;
+       }
+      else if (is_sign && 
+              i == arcount - 1 && 
+              class == C_ANY && 
+              (type == T_SIG || type == T_TSIG))
+       *is_sign = 1;
+    }
+  
+  return ret;
+}
+
+struct macparm {
+  unsigned char *limit;
+  struct dns_header *header;
+  size_t plen;
+  union mysockaddr *l3;
+};
+
+static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
+{
+  struct macparm *parm = parmv;
+  int match = 0;
+  unsigned short rdlen;
+  struct dns_header *header = parm->header;
+  unsigned char *lenp, *datap, *p;
+  
+  if (family == parm->l3->sa.sa_family)
+    {
+      if (family == AF_INET && memcmp (&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
+       match = 1;
+#ifdef HAVE_IPV6
+      else
+       if (family == AF_INET6 && memcmp (&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
+         match = 1;
+#endif
+    }
+  if (!match)
+    return 1; /* continue */
+  
+  if (ntohs(header->arcount) == 0)
+    {
+      /* We are adding the pseudoheader */
+      if (!(p = skip_questions(header, parm->plen)) ||
+         !(p = skip_section(p, 
+                            ntohs(header->ancount) + ntohs(header->nscount), 
+                            header, parm->plen)))
+       return 0;
+      *p++ = 0; /* empty name */
+      PUTSHORT(T_OPT, p);
+      PUTSHORT(PACKETSZ, p); /* max packet length - is 512 suitable default for non-EDNS0 resolvers? */
+      PUTLONG(0, p);    /* extended RCODE */
+      lenp = p;
+      PUTSHORT(0, p);    /* RDLEN */
+      rdlen = 0;
+      if (((ssize_t)maclen) > (parm->limit - (p + 4)))
+       return 0; /* Too big */
+      header->arcount = htons(1);
+      datap = p;
+    }
+  else
+    {
+      int i, is_sign;
+      unsigned short code, len;
+      
+      if (ntohs(header->arcount) != 1 ||
+         !(p = find_pseudoheader(header, parm->plen, NULL, NULL, &is_sign)) ||
+         is_sign ||
+         (!(p = skip_name(p, header, parm->plen, 10))))
+       return 0;
+      
+      p += 8; /* skip UDP length and RCODE */
+      
+      lenp = p;
+      GETSHORT(rdlen, p);
+      if (!CHECK_LEN(header, p, parm->plen, rdlen))
+       return 0; /* bad packet */
+      datap = p;
+
+      /* check if option already there */
+      for (i = 0; i + 4 < rdlen; i += len + 4)
+       {
+         GETSHORT(code, p);
+         GETSHORT(len, p);
+         if (code == EDNS0_OPTION_MAC)
+           return 0;
+         p += len;
+       }
+      
+      if (((ssize_t)maclen) > (parm->limit - (p + 4)))
+       return 0; /* Too big */
+    }
+  
+  PUTSHORT(EDNS0_OPTION_MAC, p);
+  PUTSHORT(maclen, p);
+  memcpy(p, mac, maclen);
+  p += maclen;  
+
+  PUTSHORT(p - datap, lenp);
+  parm->plen = p - (unsigned char *)header;
+  
+  return 0; /* done */
+}            
+     
+
+size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3)
+{
+  struct macparm parm;
+     
+/* Must have an existing pseudoheader as the only ar-record, 
+   or have no ar-records. Must also not be signed */
+   
+  if (ntohs(header->arcount) > 1)
+    return plen;
+
+  parm.header = header;
+  parm.limit = (unsigned char *)limit;
+  parm.plen = plen;
+  parm.l3 = l3;
+
+  iface_enumerate(AF_UNSPEC, &parm, filter_mac);
+  
+  return parm.plen; 
+}
+
+    
+/* is addr in the non-globally-routed IP space? */ 
+static int private_net(struct in_addr addr, int ban_localhost) 
+{
+  in_addr_t ip_addr = ntohl(addr.s_addr);
+
+  return
+    (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost)  /* 127.0.0.0/8    (loopback) */ || 
+    ((ip_addr & 0xFFFF0000) == 0xC0A80000)  /* 192.168.0.0/16 (private)  */ ||
+    ((ip_addr & 0xFF000000) == 0x0A000000)  /* 10.0.0.0/8     (private)  */ ||
+    ((ip_addr & 0xFFF00000) == 0xAC100000)  /* 172.16.0.0/12  (private)  */ ||
+    ((ip_addr & 0xFFFF0000) == 0xA9FE0000)  /* 169.254.0.0/16 (zeroconf) */ ;
+}
+
+static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name)
+{
+  int i, qtype, qclass, rdlen;
+  unsigned long ttl;
+
+  for (i = count; i != 0; i--)
+    {
+      if (name && option_bool(OPT_LOG))
+       {
+         if (!extract_name(header, qlen, &p, name, 1, 10))
+           return 0;
+       }
+      else if (!(p = skip_name(p, header, qlen, 10)))
+       return 0; /* bad packet */
+      
+      GETSHORT(qtype, p); 
+      GETSHORT(qclass, p);
+      GETLONG(ttl, p);
+      GETSHORT(rdlen, p);
+      
+      if (qclass == C_IN && qtype == T_A)
+       {
+         struct doctor *doctor;
+         struct in_addr addr;
+         
+         if (!CHECK_LEN(header, p, qlen, INADDRSZ))
+           return 0;
+         
+         /* alignment */
+         memcpy(&addr, p, INADDRSZ);
+         
+         for (doctor = daemon->doctors; doctor; doctor = doctor->next)
+           {
+             if (doctor->end.s_addr == 0)
+               {
+                 if (!is_same_net(doctor->in, addr, doctor->mask))
+                   continue;
+               }
+             else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) || 
+                      ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
+               continue;
+             
+             addr.s_addr &= ~doctor->mask.s_addr;
+             addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
+             /* Since we munged the data, the server it came from is no longer authoritative */
+             header->hb3 &= ~HB3_AA;
+             memcpy(p, &addr, INADDRSZ);
+             break;
+           }
+       }
+      else if (qtype == T_TXT && name && option_bool(OPT_LOG))
+       {
+         unsigned char *p1 = p;
+         if (!CHECK_LEN(header, p1, qlen, rdlen))
+           return 0;
+         while ((p1 - p) < rdlen)
+           {
+             unsigned int i, len = *p1;
+             unsigned char *p2 = p1;
+             /* make counted string zero-term  and sanitise */
+             for (i = 0; i < len; i++)
+               if (isprint(*(p2+1)))
+                 {
+                   *p2 = *(p2+1);
+                   p2++;
+                 }
+             *p2 = 0;
+             my_syslog(LOG_INFO, "reply %s is %s", name, p1);
+             /* restore */
+             memmove(p1 + 1, p1, len);
+             *p1 = len;
+             p1 += len+1;
+           }
+       }                 
+      
+      if (!ADD_RDLEN(header, p, qlen, rdlen))
+        return 0; /* bad packet */
+    }
+  
+  return p; 
+}
+
+static int find_soa(struct dns_header *header, size_t qlen, char *name)
+{
+  unsigned char *p;
+  int qtype, qclass, rdlen;
+  unsigned long ttl, minttl = ULONG_MAX;
+  int i, found_soa = 0;
+  
+  /* first move to NS section and find TTL from any SOA section */
+  if (!(p = skip_questions(header, qlen)) ||
+      !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name)))
+    return 0;  /* bad packet */
+  
+  for (i = ntohs(header->nscount); i != 0; i--)
+    {
+      if (!(p = skip_name(p, header, qlen, 10)))
+       return 0; /* bad packet */
+      
+      GETSHORT(qtype, p); 
+      GETSHORT(qclass, p);
+      GETLONG(ttl, p);
+      GETSHORT(rdlen, p);
+      
+      if ((qclass == C_IN) && (qtype == T_SOA))
+       {
+         found_soa = 1;
+         if (ttl < minttl)
+           minttl = ttl;
+
+         /* MNAME */
+         if (!(p = skip_name(p, header, qlen, 0)))
+           return 0;
+         /* RNAME */
+         if (!(p = skip_name(p, header, qlen, 20)))
+           return 0;
+         p += 16; /* SERIAL REFRESH RETRY EXPIRE */
+         
+         GETLONG(ttl, p); /* minTTL */
+         if (ttl < minttl)
+           minttl = ttl;
+       }
+      else if (!ADD_RDLEN(header, p, qlen, rdlen))
+       return 0; /* bad packet */
+    }
+  
+  /* rewrite addresses in additioal section too */
+  if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL))
+    return 0;
+  
+  if (!found_soa)
+    minttl = daemon->neg_ttl;
+
+  return minttl;
+}
+
+/* Note that the following code can create CNAME chains that don't point to a real record,
+   either because of lack of memory, or lack of SOA records.  These are treated by the cache code as 
+   expired and cleaned out that way. 
+   Return 1 if we reject an address because it look like part of dns-rebinding attack. */
+int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now, 
+                     int is_sign, int check_rebind, int checking_disabled)
+{
+  unsigned char *p, *p1, *endrr, *namep;
+  int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
+  unsigned long ttl = 0;
+  struct all_addr addr;
+
+  cache_start_insert();
+
+  /* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
+  if (daemon->doctors || option_bool(OPT_LOG))
+    {
+      searched_soa = 1;
+      ttl = find_soa(header, qlen, name);
+    }
+  
+  /* go through the questions. */
+  p = (unsigned char *)(header+1);
+  
+  for (i = ntohs(header->qdcount); i != 0; i--)
+    {
+      int found = 0, cname_count = 5;
+      struct crec *cpp = NULL;
+      int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
+      unsigned long cttl = ULONG_MAX, attl;
+      
+      namep = p;
+      if (!extract_name(header, qlen, &p, name, 1, 4))
+       return 0; /* bad packet */
+           
+      GETSHORT(qtype, p); 
+      GETSHORT(qclass, p);
+      
+      if (qclass != C_IN)
+       continue;
+
+      /* PTRs: we chase CNAMEs here, since we have no way to 
+        represent them in the cache. */
+      if (qtype == T_PTR)
+       { 
+         int name_encoding = in_arpa_name_2_addr(name, &addr);
+         
+         if (!name_encoding)
+           continue;
+
+         if (!(flags & F_NXDOMAIN))
+           {
+           cname_loop:
+             if (!(p1 = skip_questions(header, qlen)))
+               return 0;
+             
+             for (j = ntohs(header->ancount); j != 0; j--) 
+               {
+                 unsigned char *tmp = namep;
+                 /* the loop body overwrites the original name, so get it back here. */
+                 if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
+                     !(res = extract_name(header, qlen, &p1, name, 0, 10)))
+                   return 0; /* bad packet */
+                 
+                 GETSHORT(aqtype, p1); 
+                 GETSHORT(aqclass, p1);
+                 GETLONG(attl, p1);
+                 if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
+                   {
+                     (p1) -= 4;
+                     PUTLONG(daemon->max_ttl, p1);
+                   }
+                 GETSHORT(ardlen, p1);
+                 endrr = p1+ardlen;
+                 
+                 /* TTL of record is minimum of CNAMES and PTR */
+                 if (attl < cttl)
+                   cttl = attl;
+
+                 if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
+                   {
+                     if (!extract_name(header, qlen, &p1, name, 1, 0))
+                       return 0;
+                     
+                     if (aqtype == T_CNAME)
+                       {
+                         if (!cname_count--)
+                           return 0; /* looped CNAMES */
+                         goto cname_loop;
+                       }
+                     
+                     cache_insert(name, &addr, now, cttl, name_encoding | F_REVERSE);
+                     found = 1; 
+                   }
+                 
+                 p1 = endrr;
+                 if (!CHECK_LEN(header, p1, qlen, 0))
+                   return 0; /* bad packet */
+               }
+           }
+         
+          if (!found && !option_bool(OPT_NO_NEG))
+           {
+             if (!searched_soa)
+               {
+                 searched_soa = 1;
+                 ttl = find_soa(header, qlen, NULL);
+               }
+             if (ttl)
+               cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags); 
+           }
+       }
+      else
+       {
+         /* everything other than PTR */
+         struct crec *newc;
+         int addrlen;
+
+         if (qtype == T_A)
+           {
+             addrlen = INADDRSZ;
+             flags |= F_IPV4;
+           }
+#ifdef HAVE_IPV6
+         else if (qtype == T_AAAA)
+           {
+             addrlen = IN6ADDRSZ;
+             flags |= F_IPV6;
+           }
+#endif
+         else 
+           continue;
+           
+         if (!(flags & F_NXDOMAIN))
+           {
+           cname_loop1:
+             if (!(p1 = skip_questions(header, qlen)))
+               return 0;
+             
+             for (j = ntohs(header->ancount); j != 0; j--) 
+               {
+                 if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
+                   return 0; /* bad packet */
+                 
+                 GETSHORT(aqtype, p1); 
+                 GETSHORT(aqclass, p1);
+                 GETLONG(attl, p1);
+                 if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
+                   {
+                     (p1) -= 4;
+                     PUTLONG(daemon->max_ttl, p1);
+                   }
+                 GETSHORT(ardlen, p1);
+                 endrr = p1+ardlen;
+                 
+                 if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
+                   {
+                     if (aqtype == T_CNAME)
+                       {
+                         if (!cname_count--)
+                           return 0; /* looped CNAMES */
+                         newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
+                         if (newc && cpp)
+                           {
+                             cpp->addr.cname.cache = newc;
+                             cpp->addr.cname.uid = newc->uid;
+                           }
+
+                         cpp = newc;
+                         if (attl < cttl)
+                           cttl = attl;
+                         
+                         if (!extract_name(header, qlen, &p1, name, 1, 0))
+                           return 0;
+                         goto cname_loop1;
+                       }
+                     else
+                       {
+                         found = 1;
+                         
+                         /* copy address into aligned storage */
+                         if (!CHECK_LEN(header, p1, qlen, addrlen))
+                           return 0; /* bad packet */
+                         memcpy(&addr, p1, addrlen);
+                         
+                         /* check for returned address in private space */
+                         if (check_rebind &&
+                             (flags & F_IPV4) &&
+                             private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
+                           return 1;
+                         
+                         newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
+                         if (newc && cpp)
+                           {
+                             cpp->addr.cname.cache = newc;
+                             cpp->addr.cname.uid = newc->uid;
+                           }
+                         cpp = NULL;
+                       }
+                   }
+                 
+                 p1 = endrr;
+                 if (!CHECK_LEN(header, p1, qlen, 0))
+                   return 0; /* bad packet */
+               }
+           }
+         
+         if (!found && !option_bool(OPT_NO_NEG))
+           {
+             if (!searched_soa)
+               {
+                 searched_soa = 1;
+                 ttl = find_soa(header, qlen, NULL);
+               }
+             /* If there's no SOA to get the TTL from, but there is a CNAME 
+                pointing at this, inherit its TTL */
+             if (ttl || cpp)
+               {
+                 newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags);    
+                 if (newc && cpp)
+                   {
+                     cpp->addr.cname.cache = newc;
+                     cpp->addr.cname.uid = newc->uid;
+                   }
+               }
+           }
+       }
+    }
+  
+  /* Don't put stuff from a truncated packet into the cache,
+     also don't cache replies where DNSSEC validation was turned off, either
+     the upstream server told us so, or the original query specified it. */
+  if (!(header->hb3 & HB3_TC) && !(header->hb4 & HB4_CD) && !checking_disabled)
+    cache_end_insert();
+
+  return 0;
+}
+
+/* If the packet holds exactly one query
+   return F_IPV4 or F_IPV6  and leave the name from the query in name */
+
+unsigned int extract_request(struct dns_header *header, size_t qlen, char *name, unsigned short *typep)
+{
+  unsigned char *p = (unsigned char *)(header+1);
+  int qtype, qclass;
+
+  if (typep)
+    *typep = 0;
+
+  if (ntohs(header->qdcount) != 1 || OPCODE(header) != QUERY)
+    return 0; /* must be exactly one query. */
+  
+  if (!extract_name(header, qlen, &p, name, 1, 4))
+    return 0; /* bad packet */
+   
+  GETSHORT(qtype, p); 
+  GETSHORT(qclass, p);
+
+  if (typep)
+    *typep = qtype;
+
+  if (qclass == C_IN)
+    {
+      if (qtype == T_A)
+       return F_IPV4;
+      if (qtype == T_AAAA)
+       return F_IPV6;
+      if (qtype == T_ANY)
+       return  F_IPV4 | F_IPV6;
+      if (qtype == T_NS || qtype == T_SOA)
+       return F_QUERY | F_NSRR;
+    }
+  
+  return F_QUERY;
+}
+
+
+size_t setup_reply(struct dns_header *header, size_t qlen,
+               struct all_addr *addrp, unsigned int flags, unsigned long ttl)
+{
+  unsigned char *p = skip_questions(header, qlen);
+  
+  /* clear authoritative and truncated flags, set QR flag */
+  header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
+  /* set RA flag */
+  header->hb4 |= HB4_RA;
+
+  header->nscount = htons(0);
+  header->arcount = htons(0);
+  header->ancount = htons(0); /* no answers unless changed below */
+  if (flags == F_NEG)
+    SET_RCODE(header, SERVFAIL); /* couldn't get memory */
+  else if (flags == F_NOERR)
+    SET_RCODE(header, NOERROR); /* empty domain */
+  else if (flags == F_NXDOMAIN)
+    SET_RCODE(header, NXDOMAIN);
+  else if (p && flags == F_IPV4)
+    { /* we know the address */
+      SET_RCODE(header, NOERROR);
+      header->ancount = htons(1);
+      header->hb3 |= HB3_AA;
+      add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
+    }
+#ifdef HAVE_IPV6
+  else if (p && flags == F_IPV6)
+    {
+      SET_RCODE(header, NOERROR);
+      header->ancount = htons(1);
+      header->hb3 |= HB3_AA;
+      add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp);
+    }
+#endif
+  else /* nowhere to forward to */
+    SET_RCODE(header, REFUSED);
+  return p - (unsigned char *)header;
+}
+
+/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
+int check_for_local_domain(char *name, time_t now)
+{
+  struct crec *crecp;
+  struct mx_srv_record *mx;
+  struct txt_record *txt;
+  struct interface_name *intr;
+  struct ptr_record *ptr;
+  
+  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)) &&
+      (crecp->flags & (F_HOSTS | F_DHCP)))
+    return 1;
+  
+  for (mx = daemon->mxnames; mx; mx = mx->next)
+    if (hostname_isequal(name, mx->name))
+      return 1;
+
+  for (txt = daemon->txt; txt; txt = txt->next)
+    if (hostname_isequal(name, txt->name))
+      return 1;
+
+  for (intr = daemon->int_names; intr; intr = intr->next)
+    if (hostname_isequal(name, intr->name))
+      return 1;
+
+  for (ptr = daemon->ptr; ptr; ptr = ptr->next)
+    if (hostname_isequal(name, ptr->name))
+      return 1;
+  return 0;
+}
+
+/* Is the packet a reply with the answer address equal to addr?
+   If so mung is into an NXDOMAIN reply and also put that information
+   in the cache. */
+int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, 
+                            struct bogus_addr *baddr, time_t now)
+{
+  unsigned char *p;
+  int i, qtype, qclass, rdlen;
+  unsigned long ttl;
+  struct bogus_addr *baddrp;
+
+  /* skip over questions */
+  if (!(p = skip_questions(header, qlen)))
+    return 0; /* bad packet */
+
+  for (i = ntohs(header->ancount); i != 0; i--)
+    {
+      if (!extract_name(header, qlen, &p, name, 1, 10))
+       return 0; /* bad packet */
+  
+      GETSHORT(qtype, p); 
+      GETSHORT(qclass, p);
+      GETLONG(ttl, p);
+      GETSHORT(rdlen, p);
+      
+      if (qclass == C_IN && qtype == T_A)
+       {
+         if (!CHECK_LEN(header, p, qlen, INADDRSZ))
+           return 0;
+         
+         for (baddrp = baddr; baddrp; baddrp = baddrp->next)
+           if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
+             {
+               /* Found a bogus address. Insert that info here, since there no SOA record
+                  to get the ttl from in the normal processing */
+               cache_start_insert();
+               cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
+               cache_end_insert();
+               
+               return 1;
+             }
+       }
+      
+      if (!ADD_RDLEN(header, p, qlen, rdlen))
+       return 0;
+    }
+  
+  return 0;
+}
+
+static int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp, 
+                              unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...)
+{
+  va_list ap;
+  unsigned char *sav, *p = *pp;
+  int j;
+  unsigned short usval;
+  long lval;
+  char *sval;
+
+  if (truncp && *truncp)
+    return 0;
+
+  PUTSHORT(nameoffset | 0xc000, p);
+  PUTSHORT(type, p);
+  PUTSHORT(class, p);
+  PUTLONG(ttl, p);      /* TTL */
+
+  sav = p;              /* Save pointer to RDLength field */
+  PUTSHORT(0, p);       /* Placeholder RDLength */
+
+  va_start(ap, format);   /* make ap point to 1st unamed argument */
+  
+  for (; *format; format++)
+    switch (*format)
+      {
+#ifdef HAVE_IPV6
+      case '6':
+       sval = va_arg(ap, char *); 
+       memcpy(p, sval, IN6ADDRSZ);
+       p += IN6ADDRSZ;
+       break;
+#endif
+       
+      case '4':
+       sval = va_arg(ap, char *); 
+       memcpy(p, sval, INADDRSZ);
+       p += INADDRSZ;
+       break;
+       
+      case 's':
+       usval = va_arg(ap, int);
+       PUTSHORT(usval, p);
+       break;
+       
+      case 'l':
+       lval = va_arg(ap, long);
+       PUTLONG(lval, p);
+       break;
+       
+      case 'd':
+       /* get domain-name answer arg and store it in RDATA field */
+       if (offset)
+         *offset = p - (unsigned char *)header;
+       p = do_rfc1035_name(p, va_arg(ap, char *));
+       *p++ = 0;
+       break;
+       
+      case 't':
+       usval = va_arg(ap, int);
+       sval = va_arg(ap, char *);
+       memcpy(p, sval, usval);
+       p += usval;
+       break;
+
+      case 'z':
+       sval = va_arg(ap, char *);
+       usval = sval ? strlen(sval) : 0;
+       if (usval > 255)
+         usval = 255;
+       *p++ = (unsigned char)usval;
+       memcpy(p, sval, usval);
+       p += usval;
+       break;
+      }
+
+  va_end(ap);  /* clean up variable argument pointer */
+  
+  j = p - sav - 2;
+  PUTSHORT(j, sav);     /* Now, store real RDLength */
+  
+  /* check for overflow of buffer */
+  if (limit && ((unsigned char *)limit - p) < 0)
+    {
+      if (truncp)
+       *truncp = 1;
+      return 0;
+    }
+  
+  *pp = p;
+  return 1;
+}
+
+static unsigned long crec_ttl(struct crec *crecp, time_t now)
+{
+  /* Return 0 ttl for DHCP entries, which might change
+     before the lease expires. */
+
+  if  (crecp->flags & (F_IMMORTAL | F_DHCP))
+    return daemon->local_ttl;
+  
+  /* Return the Max TTL value if it is lower then the actual TTL */
+  if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
+    return crecp->ttd - now;
+  else
+    return daemon->max_ttl;
+}
+  
+
+/* return zero if we can't answer from cache, or packet size if we can */
+size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
+                     struct in_addr local_addr, struct in_addr local_netmask, time_t now) 
+{
+  char *name = daemon->namebuff;
+  unsigned char *p, *ansp, *pheader;
+  int qtype, qclass;
+  struct all_addr addr;
+  unsigned int nameoffset;
+  unsigned short flag;
+  int q, ans, anscount = 0, addncount = 0;
+  int dryrun = 0, sec_reqd = 0;
+  int is_sign;
+  struct crec *crecp;
+  int nxdomain = 0, auth = 1, trunc = 0;
+  struct mx_srv_record *rec;
+  /* If there is an RFC2671 pseudoheader then it will be overwritten by
+     partial replies, so we have to do a dry run to see if we can answer
+     the query. We check to see if the do bit is set, if so we always
+     forward rather than answering from the cache, which doesn't include
+     security information. */
+
+  if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
+    { 
+      unsigned short udpsz, ext_rcode, flags;
+      unsigned char *psave = pheader;
+
+      GETSHORT(udpsz, pheader);
+      GETSHORT(ext_rcode, pheader);
+      GETSHORT(flags, pheader);
+      
+      sec_reqd = flags & 0x8000; /* do bit */ 
+
+      /* If our client is advertising a larger UDP packet size
+        than we allow, trim it so that we don't get an overlarge
+        response from upstream */
+
+      if (!is_sign && (udpsz > daemon->edns_pktsz))
+       PUTSHORT(daemon->edns_pktsz, psave); 
+
+      dryrun = 1;
+    }
+
+  if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
+    return 0;
+  
+  for (rec = daemon->mxnames; rec; rec = rec->next)
+    rec->offset = 0;
+  
+ rerun:
+  /* determine end of question section (we put answers there) */
+  if (!(ansp = skip_questions(header, qlen)))
+    return 0; /* bad packet */
+   
+  /* now process each question, answers go in RRs after the question */
+  p = (unsigned char *)(header+1);
+
+  for (q = ntohs(header->qdcount); q != 0; q--)
+    {
+      /* save pointer to name for copying into answers */
+      nameoffset = p - (unsigned char *)header;
+
+      /* now extract name as .-concatenated string into name */
+      if (!extract_name(header, qlen, &p, name, 1, 4))
+       return 0; /* bad packet */
+            
+      GETSHORT(qtype, p); 
+      GETSHORT(qclass, p);
+
+      ans = 0; /* have we answered this question */
+      
+      if (qtype == T_TXT || qtype == T_ANY)
+       {
+         struct txt_record *t;
+         for(t = daemon->txt; t ; t = t->next)
+           {
+             if (t->class == qclass && hostname_isequal(name, t->name))
+               {
+                 ans = 1;
+                 if (!dryrun)
+                   {
+                     log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
+                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                             daemon->local_ttl, NULL,
+                                             T_TXT, t->class, "t", t->len, t->txt))
+                       anscount++;
+
+                   }
+               }
+           }
+       }
+
+      if (qclass == C_IN)
+       {
+         if (qtype == T_PTR || qtype == T_ANY)
+           {
+             /* see if it's w.z.y.z.in-addr.arpa format */
+             int is_arpa = in_arpa_name_2_addr(name, &addr);
+             struct ptr_record *ptr;
+             struct interface_name* intr = NULL;
+
+             for (ptr = daemon->ptr; ptr; ptr = ptr->next)
+               if (hostname_isequal(name, ptr->name))
+                 break;
+
+             if (is_arpa == F_IPV4)
+               for (intr = daemon->int_names; intr; intr = intr->next)
+                 {
+                   if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
+                     break;
+                   else
+                     while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
+                       intr = intr->next;
+                 }
+             
+             if (intr)
+               {
+                 ans = 1;
+                 if (!dryrun)
+                   {
+                     log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
+                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                             daemon->local_ttl, NULL,
+                                             T_PTR, C_IN, "d", intr->name))
+                       anscount++;
+                   }
+               }
+             else if (ptr)
+               {
+                 ans = 1;
+                 if (!dryrun)
+                   {
+                     log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
+                     for (ptr = daemon->ptr; ptr; ptr = ptr->next)
+                       if (hostname_isequal(name, ptr->name) &&
+                           add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                               daemon->local_ttl, NULL,
+                                               T_PTR, C_IN, "d", ptr->ptr))
+                         anscount++;
+                        
+                   }
+               }
+             else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
+               do 
+                 { 
+                   /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
+                   if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
+                     continue;
+                   
+                   if (crecp->flags & F_NEG)
+                     {
+                       ans = 1;
+                       auth = 0;
+                       if (crecp->flags & F_NXDOMAIN)
+                         nxdomain = 1;
+                       if (!dryrun)
+                         log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
+                     }
+                   else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
+                     {
+                       ans = 1;
+                       if (!(crecp->flags & (F_HOSTS | F_DHCP)))
+                         auth = 0;
+                       if (!dryrun)
+                         {
+                           log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, 
+                                     record_source(crecp->uid));
+                           
+                           if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                                   crec_ttl(crecp, now), NULL,
+                                                   T_PTR, C_IN, "d", cache_get_name(crecp)))
+                             anscount++;
+                         }
+                     }
+                 } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
+             else if (is_arpa == F_IPV4 && 
+                      option_bool(OPT_BOGUSPRIV) && 
+                      private_net(addr.addr.addr4, 1))
+               {
+                 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
+                 ans = 1;
+                 nxdomain = 1;
+                 if (!dryrun)
+                   log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, 
+                             name, &addr, NULL);
+               }
+           }
+           
+         for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
+           {
+             unsigned short type = T_A;
+             
+             if (flag == F_IPV6)
+#ifdef HAVE_IPV6
+               type = T_AAAA;
+#else
+               break;
+#endif
+             
+             if (qtype != type && qtype != T_ANY)
+               continue;
+             
+             /* Check for "A for A"  queries; be rather conservative 
+                about what looks like dotted-quad.  */
+             if (qtype == T_A)
+               {
+                 char *cp;
+                 unsigned int i, a;
+                 int x;
+
+                 for (cp = name, i = 0, a = 0; *cp; i++)
+                   {
+                     if (!isdigit((unsigned char)*cp) || (x = strtol(cp, &cp, 10)) > 255) 
+                       {
+                         i = 5;
+                         break;
+                       }
+                     
+                     a = (a << 8) + x;
+                     
+                     if (*cp == '.') 
+                       cp++;
+                   }
+                 
+                 if (i == 4)
+                   {
+                     ans = 1;
+                     if (!dryrun)
+                       {
+                         addr.addr.addr4.s_addr = htonl(a);
+                         log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
+                         if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                                 daemon->local_ttl, NULL, type, C_IN, "4", &addr))
+                           anscount++;
+                       }
+                     continue;
+                   }
+               }
+
+             /* interface name stuff */
+             if (qtype == T_A)
+               {
+                 struct interface_name *intr;
+
+                 for (intr = daemon->int_names; intr; intr = intr->next)
+                   if (hostname_isequal(name, intr->name))
+                     break;
+                 
+                 if (intr)
+                   {
+                     ans = 1;
+                     if (!dryrun)
+                       {
+                         if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
+                           log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
+                         else
+                           {
+                             log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
+                             if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                                     daemon->local_ttl, NULL, type, C_IN, "4", &addr))
+                               anscount++;
+                           }
+                       }
+                     continue;
+                   }
+               }
+
+           cname_restart:
+             if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME)))
+               {
+                 int localise = 0;
+                 
+                 /* See if a putative address is on the network from which we recieved
+                    the query, is so we'll filter other answers. */
+                 if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && flag == F_IPV4)
+                   {
+                     struct crec *save = crecp;
+                     do {
+                       if ((crecp->flags & F_HOSTS) &&
+                           is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
+                         {
+                           localise = 1;
+                           break;
+                         } 
+                       } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
+                     crecp = save;
+                   }
+                         
+                 do
+                   { 
+                     /* don't answer wildcard queries with data not from /etc/hosts
+                        or DHCP leases */
+                     if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
+                       break;
+                     
+                     if (crecp->flags & F_CNAME)
+                       {
+                         if (!dryrun)
+                           {
+                             log_query(crecp->flags, name, NULL, record_source(crecp->uid));
+                             if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                                     crec_ttl(crecp, now), &nameoffset,
+                                                     T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
+                               anscount++;
+                           }
+                         
+                         strcpy(name, cache_get_name(crecp->addr.cname.cache));
+                         goto cname_restart;
+                       }
+                     
+                     if (crecp->flags & F_NEG)
+                       {
+                         ans = 1;
+                         auth = 0;
+                         if (crecp->flags & F_NXDOMAIN)
+                           nxdomain = 1;
+                         if (!dryrun)
+                           log_query(crecp->flags, name, NULL, NULL);
+                       }
+                     else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
+                       {
+                         /* If we are returning local answers depending on network,
+                            filter here. */
+                         if (localise && 
+                             (crecp->flags & F_HOSTS) &&
+                             !is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
+                           continue;
+       
+                         if (!(crecp->flags & (F_HOSTS | F_DHCP)))
+                           auth = 0;
+                         
+                         ans = 1;
+                         if (!dryrun)
+                           {
+                             log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
+                                       record_source(crecp->uid));
+                             
+                             if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                                     crec_ttl(crecp, now), NULL, type, C_IN, 
+                                                     type == T_A ? "4" : "6", &crecp->addr))
+                               anscount++;
+                           }
+                       }
+                   } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
+               }
+           }
+         
+         if (qtype == T_MX || qtype == T_ANY)
+           {
+             int found = 0;
+             for (rec = daemon->mxnames; rec; rec = rec->next)
+               if (!rec->issrv && hostname_isequal(name, rec->name))
+                 {
+                 ans = found = 1;
+                 if (!dryrun)
+                   {
+                     unsigned int offset;
+                     log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
+                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
+                                             &offset, T_MX, C_IN, "sd", rec->weight, rec->target))
+                       {
+                         anscount++;
+                         if (rec->target)
+                           rec->offset = offset;
+                       }
+                   }
+                 }
+             
+             if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && 
+                 cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP))
+               { 
+                 ans = 1;
+                 if (!dryrun)
+                   {
+                     log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
+                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL, 
+                                             T_MX, C_IN, "sd", 1, 
+                                             option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
+                       anscount++;
+                   }
+               }
+           }
+                 
+         if (qtype == T_SRV || qtype == T_ANY)
+           {
+             int found = 0;
+             struct mx_srv_record *move = NULL, **up = &daemon->mxnames;
+
+             for (rec = daemon->mxnames; rec; rec = rec->next)
+               if (rec->issrv && hostname_isequal(name, rec->name))
+                 {
+                   found = ans = 1;
+                   if (!dryrun)
+                     {
+                       unsigned int offset;
+                       log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
+                       if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 
+                                               &offset, T_SRV, C_IN, "sssd", 
+                                               rec->priority, rec->weight, rec->srvport, rec->target))
+                         {
+                           anscount++;
+                           if (rec->target)
+                             rec->offset = offset;
+                         }
+                     }
+                   
+                   /* unlink first SRV record found */
+                   if (!move)
+                     {
+                       move = rec;
+                       *up = rec->next;
+                     }
+                   else
+                     up = &rec->next;      
+                 }
+               else
+                 up = &rec->next;
+
+             /* put first SRV record back at the end. */
+             if (move)
+               {
+                 *up = move;
+                 move->next = NULL;
+               }
+             
+             if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
+               {
+                 ans = 1;
+                 if (!dryrun)
+                   log_query(F_CONFIG | F_NEG, name, NULL, NULL);
+               }
+           }
+
+         if (qtype == T_NAPTR || qtype == T_ANY)
+           {
+             struct naptr *na;
+             for (na = daemon->naptr; na; na = na->next)
+               if (hostname_isequal(name, na->name))
+                 {
+                   ans = 1;
+                   if (!dryrun)
+                     {
+                       log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
+                       if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 
+                                               NULL, T_NAPTR, C_IN, "sszzzd", 
+                                               na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
+                         anscount++;
+                     }
+                 }
+           }
+         
+         if (qtype == T_MAILB)
+           ans = 1, nxdomain = 1;
+
+         if (qtype == T_SOA && option_bool(OPT_FILTER))
+           {
+             ans = 1; 
+             if (!dryrun)
+               log_query(F_CONFIG | F_NEG, name, &addr, NULL);
+           }
+       }
+
+      if (!ans)
+       return 0; /* failed to answer a question */
+    }
+  
+  if (dryrun)
+    {
+      dryrun = 0;
+      goto rerun;
+    }
+  
+  /* create an additional data section, for stuff in SRV and MX record replies. */
+  for (rec = daemon->mxnames; rec; rec = rec->next)
+    if (rec->offset != 0)
+      {
+       /* squash dupes */
+       struct mx_srv_record *tmp;
+       for (tmp = rec->next; tmp; tmp = tmp->next)
+         if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target))
+           tmp->offset = 0;
+       
+       crecp = NULL;
+       while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
+         {
+#ifdef HAVE_IPV6
+           int type =  crecp->flags & F_IPV4 ? T_A : T_AAAA;
+#else
+           int type = T_A;
+#endif
+           if (crecp->flags & F_NEG)
+             continue;
+
+           if (add_resource_record(header, limit, NULL, rec->offset, &ansp, 
+                                   crec_ttl(crecp, now), NULL, type, C_IN, 
+                                   crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
+             addncount++;
+         }
+      }
+  
+  /* done all questions, set up header and return length of result */
+  /* clear authoritative and truncated flags, set QR flag */
+  header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
+  /* set RA flag */
+  header->hb4 |= HB4_RA;
+   
+  /* authoritive - only hosts and DHCP derived names. */
+  if (auth)
+    header->hb3 |= HB3_AA;
+  
+  /* truncation */
+  if (trunc)
+    header->hb3 |= HB3_TC;
+
+  if (anscount == 0 && nxdomain)
+    SET_RCODE(header, NXDOMAIN);
+  else
+    SET_RCODE(header, NOERROR); /* no error */
+  header->ancount = htons(anscount);
+  header->nscount = htons(0);
+  header->arcount = htons(addncount);
+  return ansp - (unsigned char *)header;
+}
+
+
+
+
+
diff --git a/src/rfc2131.c b/src/rfc2131.c
new file mode 100644 (file)
index 0000000..9218765
--- /dev/null
@@ -0,0 +1,2512 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_DHCP
+
+#define have_config(config, mask) ((config) && ((config)->flags & (mask))) 
+#define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
+#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
+
+#ifdef HAVE_SCRIPT
+static void add_extradata_data(struct dhcp_lease *lease, unsigned char *data, size_t len, int delim);
+static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt);
+#endif
+
+static int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
+static int sanitise(unsigned char *opt, char *buf);
+static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
+static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
+static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
+static void option_put_string(struct dhcp_packet *mess, unsigned char *end, 
+                             int opt, char *string, int null_term);
+static struct in_addr option_addr(unsigned char *opt);
+static struct in_addr option_addr_arr(unsigned char *opt, int offset);
+static unsigned int option_uint(unsigned char *opt, int i, int size);
+static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
+                      int mac_len, char *interface, char *string, u32 xid);
+static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
+static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
+static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid,
+                              unsigned char *agent_id, unsigned char *real_end);
+static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
+static void do_options(struct dhcp_context *context,
+                      struct dhcp_packet *mess,
+                      unsigned char *real_end, 
+                      unsigned char *req_options,
+                      char *hostname, 
+                      char *domain, char *config_domain,
+                      struct dhcp_netid *netid,
+                      struct in_addr subnet_addr,
+                      unsigned char fqdn_flags,
+                      int null_term, int pxearch,
+                      unsigned char *uuid,
+                      int vendor_class_len);
+
+
+static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); 
+static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
+static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
+static int prune_vendor_opts(struct dhcp_netid *netid);
+static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local);
+struct dhcp_boot *find_boot(struct dhcp_netid *netid);
+
+  
+size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
+                 size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe)
+{
+  unsigned char *opt, *clid = NULL;
+  struct dhcp_lease *ltmp, *lease = NULL;
+  struct dhcp_vendor *vendor;
+  struct dhcp_mac *mac;
+  struct dhcp_netid_list *id_list;
+  int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1;
+  struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
+  unsigned char *end = (unsigned char *)(mess + 1); 
+  unsigned char *real_end = (unsigned char *)(mess + 1); 
+  char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
+  int hostname_auth = 0, borken_opt = 0;
+  unsigned char *req_options = NULL;
+  char *message = NULL;
+  unsigned int time;
+  struct dhcp_config *config;
+  struct dhcp_netid *netid, *tagif_netid;
+  struct in_addr subnet_addr, fallback, override;
+  unsigned short fuzz = 0;
+  unsigned int mess_type = 0;
+  unsigned char fqdn_flags = 0;
+  unsigned char *agent_id = NULL, *uuid = NULL;
+  unsigned char *emac = NULL;
+  int vendor_class_len = 0, emac_len = 0;
+  struct dhcp_netid known_id, iface_id, cpewan_id;
+  struct dhcp_opt *o;
+  unsigned char pxe_uuid[17];
+  unsigned char *oui = NULL, *serial = NULL, *class = NULL;
+
+  static time_t old_time = 0;
+
+  subnet_addr.s_addr = override.s_addr = 0;
+
+  /* set tag with name == interface */
+  iface_id.net = iface_name;
+  iface_id.next = NULL;
+  netid = &iface_id; 
+  
+  if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
+    return 0;
+   
+  if (mess->htype == 0 && mess->hlen != 0)
+    return 0;
+
+  /* check for DHCP rather than BOOTP */
+  if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
+    {
+      u32 cookie = htonl(DHCP_COOKIE);
+      
+      /* only insist on a cookie for DHCP. */
+      if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
+       return 0;
+      
+      mess_type = option_uint(opt, 0, 1);
+      
+      /* two things to note here: expand_buf may move the packet,
+        so reassign mess from daemon->packet. Also, the size
+        sent includes the IP and UDP headers, hence the magic "-28" */
+      if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
+       {
+         size_t size = (size_t)option_uint(opt, 0, 2) - 28;
+         
+         if (size > DHCP_PACKET_MAX)
+           size = DHCP_PACKET_MAX;
+         else if (size < sizeof(struct dhcp_packet))
+           size = sizeof(struct dhcp_packet);
+         
+         if (expand_buf(&daemon->dhcp_packet, size))
+           {
+             mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
+             real_end = end = ((unsigned char *)mess) + size;
+           }
+       }
+
+      /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
+        it can affect the context-determination code. */
+      if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
+       mess->ciaddr.s_addr = 0;
+
+      /* search for device identity from CPEWAN devices, we pass this through to the script */
+      if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5)))
+       {
+         unsigned  int elen, offset, len = option_len(opt);
+         
+         for (offset = 0; offset < (len - 5); offset += elen + 5)
+           {
+             elen = option_uint(opt, offset + 4 , 1);
+             if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
+               {
+                 unsigned char *x = option_ptr(opt, offset + 5);
+                 unsigned char *y = option_ptr(opt, offset + elen + 5);
+                 oui = option_find1(x, y, 1, 1);
+                 serial = option_find1(x, y, 2, 1);
+                 class = option_find1(x, y, 3, 1);
+                 
+                 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing 
+                    the gateway id back. Note that the device class is optional */
+                 if (oui && serial)
+                   {
+                     cpewan_id.net = "cpewan-id";
+                     cpewan_id.next = netid;
+                     netid = &cpewan_id;
+                   }
+                 break;
+               }
+           }
+       }
+      
+      if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
+       {
+         /* Any agent-id needs to be copied back out, verbatim, as the last option
+            in the packet. Here, we shift it to the very end of the buffer, if it doesn't
+            get overwritten, then it will be shuffled back at the end of processing.
+            Note that the incoming options must not be overwritten here, so there has to 
+            be enough free space at the end of the packet to copy the option. */
+         unsigned char *sopt;
+         unsigned int total = option_len(opt) + 2;
+         unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
+         if (last_opt && last_opt < end - total)
+           {
+             end -= total;
+             agent_id = end;
+             memcpy(agent_id, opt, total);
+           }
+
+         /* look for RFC3527 Link selection sub-option */
+         if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
+           subnet_addr = option_addr(sopt);
+
+         /* look for RFC5107 server-identifier-override */
+         if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
+           override = option_addr(sopt);
+         
+         /* if a circuit-id or remote-is option is provided, exact-match to options. */ 
+         for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
+           {
+             int search;
+             
+             if (vendor->match_type == MATCH_CIRCUIT)
+               search = SUBOPT_CIRCUIT_ID;
+             else if (vendor->match_type == MATCH_REMOTE)
+               search = SUBOPT_REMOTE_ID;
+             else if (vendor->match_type == MATCH_SUBSCRIBER)
+               search = SUBOPT_SUBSCR_ID;
+             else 
+               continue;
+
+             if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
+                 vendor->len == option_len(sopt) &&
+                 memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
+               {
+                 vendor->netid.next = netid;
+                 netid = &vendor->netid;
+               } 
+           }
+       }
+
+      /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
+      if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
+       subnet_addr = option_addr(opt);
+      
+      /* If there is no client identifier option, use the hardware address */
+      if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
+       {
+         clid_len = option_len(opt);
+         clid = option_ptr(opt, 0);
+       }
+
+      /* do we have a lease in store? */
+      lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
+
+      /* If this request is missing a clid, but we've seen one before, 
+        use it again for option matching etc. */
+      if (lease && !clid && lease->clid)
+       {
+         clid_len = lease->clid_len;
+         clid = lease->clid;
+       }
+
+      /* find mac to use for logging and hashing */
+      emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
+    }
+  
+  for (mac = daemon->dhcp_macs; mac; mac = mac->next)
+    if (mac->hwaddr_len == mess->hlen &&
+       (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
+       memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
+      {
+       mac->netid.next = netid;
+       netid = &mac->netid;
+      }
+  
+  /* Determine network for this packet. Our caller will have already linked all the 
+     contexts which match the addresses of the receiving interface but if the 
+     machine has an address already, or came via a relay, or we have a subnet selector, 
+     we search again. If we don't have have a giaddr or explicit subnet selector, 
+     use the ciaddr. This is necessary because a  machine which got a lease via a 
+     relay won't use the relay to renew. If matching a ciaddr fails but we have a context 
+     from the physical network, continue using that to allow correct DHCPNAK generation later. */
+  if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
+    {
+      struct dhcp_context *context_tmp, *context_new = NULL;
+      struct in_addr addr;
+      int force = 0;
+      
+      if (subnet_addr.s_addr)
+       {
+         addr = subnet_addr;
+         force = 1;
+       }
+      else if (mess->giaddr.s_addr)
+       {
+         addr = mess->giaddr;
+         force = 1;
+       }
+      else
+       {
+         /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
+         addr = mess->ciaddr;
+         for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
+           if (context_tmp->netmask.s_addr && 
+               is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
+               is_same_net(addr, context_tmp->end, context_tmp->netmask))
+             {
+               context_new = context;
+               break;
+             }
+       } 
+               
+      if (!context_new)
+       for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
+         if (context_tmp->netmask.s_addr  && 
+             is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
+             is_same_net(addr, context_tmp->end, context_tmp->netmask))
+           {
+             context_tmp->current = context_new;
+             context_new = context_tmp;
+           }
+      
+      if (context_new || force)
+       context = context_new;
+      
+    }
+  
+  if (!context)
+    {
+      my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"), 
+               subnet_addr.s_addr ? _("with subnet selector") : _("via"),
+               subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
+      return 0;
+    }
+
+  /* keep _a_ local address available. */
+  fallback = context->local;
+  
+  if (option_bool(OPT_LOG_OPTS))
+    {
+      struct dhcp_context *context_tmp;
+      for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
+       {
+         strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
+         if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
+           my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
+                     ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
+         else
+           my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"), 
+                     ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
+       }
+    }
+
+  mess->op = BOOTREPLY;
+  
+  config = find_config(daemon->dhcp_conf, context, clid, clid_len, 
+                      mess->chaddr, mess->hlen, mess->htype, NULL);
+
+  /* set "known" tag for known hosts */
+  if (config)
+    {
+      known_id.net = "known";
+      known_id.next = netid;
+      netid = &known_id;
+    }
+  
+  if (mess_type == 0 && !pxe)
+    {
+      /* BOOTP request */
+      struct dhcp_netid id, bootp_id;
+      struct in_addr *logaddr = NULL;
+
+      /* must have a MAC addr for bootp */
+      if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
+       return 0;
+      
+      if (have_config(config, CONFIG_DISABLE))
+       message = _("disabled");
+
+      end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
+            
+      if (have_config(config, CONFIG_NAME))
+       {
+         hostname = config->hostname;
+         domain = config->domain;
+       }
+
+      if (config)
+       {
+         struct dhcp_netid_list *list;
+
+         for (list = config->netid; list; list = list->next)
+           {
+             list->list->next = netid;
+             netid = list->list;
+           }
+       }
+
+      /* Match incoming filename field as a netid. */
+      if (mess->file[0])
+       {
+         memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
+         daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
+         id.net = (char *)daemon->dhcp_buff2;
+         id.next = netid;
+         netid = &id;
+       }
+
+      /* Add "bootp" as a tag to allow different options, address ranges etc
+        for BOOTP clients */
+      bootp_id.net = "bootp";
+      bootp_id.next = netid;
+      netid = &bootp_id;
+      
+      tagif_netid = run_tag_if(netid);
+
+      for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
+       if (match_netid(id_list->list, tagif_netid, 0))
+         message = _("ignored");
+      
+      if (!message)
+       {
+         int nailed = 0;
+
+         if (have_config(config, CONFIG_ADDR))
+           {
+             nailed = 1;
+             logaddr = &config->addr;
+             mess->yiaddr = config->addr;
+             if ((lease = lease_find_by_addr(config->addr)) &&
+                 (lease->hwaddr_len != mess->hlen ||
+                  lease->hwaddr_type != mess->htype ||
+                  memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
+               message = _("address in use");
+           }
+         else
+           {
+             if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
+                 !address_available(context, lease->addr, tagif_netid))
+               {
+                  if (lease)
+                    {
+                      /* lease exists, wrong network. */
+                      lease_prune(lease, now);
+                      lease = NULL;
+                    }
+                  if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
+                    message = _("no address available");
+               }
+             else
+               mess->yiaddr = lease->addr;
+           }
+         
+         if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
+           message = _("wrong network");
+         else if (context->netid.net)
+           {
+             context->netid.next = netid;
+             netid = &context->netid; 
+             tagif_netid = run_tag_if(netid);
+           }
+           
+         if (!message && !nailed)
+           {
+             for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
+               if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
+                 break;
+             if (!id_list)
+               message = _("no address configured");
+           }
+
+         if (!message && 
+             !lease && 
+             (!(lease = lease_allocate(mess->yiaddr))))
+           message = _("no leases left");
+         
+         if (!message)
+           {
+             logaddr = &mess->yiaddr;
+               
+             lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
+             if (hostname)
+               lease_set_hostname(lease, hostname, 1); 
+             /* infinite lease unless nailed in dhcp-host line. */
+             lease_set_expires(lease,  
+                               have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff, 
+                               now); 
+             lease_set_interface(lease, int_index);
+             
+             clear_packet(mess, end);
+             do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr), 
+                        domain, tagif_netid, subnet_addr, 0, 0, 0, NULL, 0);
+           }
+       }
+      
+      log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);
+      
+      return message ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
+    }
+      
+  if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
+    {
+      /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
+      int len = option_len(opt);
+      char *pq = daemon->dhcp_buff;
+      unsigned char *pp, *op = option_ptr(opt, 0);
+      
+      fqdn_flags = *op;
+      len -= 3;
+      op += 3;
+      pp = op;
+      
+      /* Always force update, since the client has no way to do it itself. */
+      if (!(fqdn_flags & 0x01))
+       fqdn_flags |= 0x02;
+      
+      fqdn_flags &= ~0x08;
+      fqdn_flags |= 0x01;
+      
+      if (fqdn_flags & 0x04)
+       while (*op != 0 && ((op + (*op) + 1) - pp) < len)
+         {
+           memcpy(pq, op+1, *op);
+           pq += *op;
+           op += (*op)+1;
+           *(pq++) = '.';
+         }
+      else
+       {
+         memcpy(pq, op, len);
+         if (len > 0 && op[len-1] == 0)
+           borken_opt = 1;
+         pq += len + 1;
+       }
+      
+      if (pq != daemon->dhcp_buff)
+       pq--;
+      
+      *pq = 0;
+      
+      if (legal_hostname(daemon->dhcp_buff))
+       offer_hostname = client_hostname = daemon->dhcp_buff;
+    }
+  else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
+    {
+      int len = option_len(opt);
+      memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
+      /* Microsoft clients are broken, and need zero-terminated strings
+        in options. We detect this state here, and do the same in
+        any options we send */
+      if (len > 0 && daemon->dhcp_buff[len-1] == 0)
+       borken_opt = 1;
+      else
+       daemon->dhcp_buff[len] = 0;
+      if (legal_hostname(daemon->dhcp_buff))
+       client_hostname = daemon->dhcp_buff;
+    }
+
+  if (client_hostname && option_bool(OPT_LOG_OPTS))
+    my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
+  
+  if (have_config(config, CONFIG_NAME))
+    {
+      hostname = config->hostname;
+      domain = config->domain;
+      hostname_auth = 1;
+      /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
+      if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
+        offer_hostname = hostname;
+    }
+  else if (client_hostname)
+    {
+      domain = strip_hostname(client_hostname);
+      
+      if (strlen(client_hostname) != 0)
+       {
+         hostname = client_hostname;
+         if (!config)
+           {
+             /* Search again now we have a hostname. 
+                Only accept configs without CLID and HWADDR here, (they won't match)
+                to avoid impersonation by name. */
+             struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
+                                                   mess->chaddr, mess->hlen, 
+                                                   mess->htype, hostname);
+             if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
+               {
+                 config = new;
+                 /* set "known" tag for known hosts */
+                 known_id.net = "known";
+                 known_id.next = netid;
+                 netid = &known_id;
+               }
+           }
+       }
+    }
+  
+  if (config)
+    {
+      struct dhcp_netid_list *list;
+      
+      for (list = config->netid; list; list = list->next)
+       {
+         list->list->next = netid;
+         netid = list->list;
+       }
+    }
+  
+  /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
+     Otherwise assume the option is an array, and look for a matching element. 
+     If no data given, existance of the option is enough. This code handles 
+     rfc3925 V-I classes too. */
+  for (o = daemon->dhcp_match; o; o = o->next)
+    {
+      unsigned int len, elen, match = 0;
+      size_t offset, o2;
+
+      if (o->flags & DHOPT_RFC3925)
+       {
+         if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
+           continue;
+         
+         for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
+           {
+             len = option_uint(opt, offset + 4 , 1);
+             /* Need to take care that bad data can't run us off the end of the packet */
+             if ((offset + len + 5 <= (option_len(opt))) &&
+                 (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
+               for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
+                 { 
+                   elen = option_uint(opt, o2, 1);
+                   if ((o2 + elen + 1 <= option_len(opt)) &&
+                       (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
+                     break;
+                 }
+             if (match) 
+               break;
+           }     
+       }
+      else
+       {
+         if (!(opt = option_find(mess, sz, o->opt, 1)))
+           continue;
+         
+         match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
+       } 
+
+      if (match)
+       {
+         o->netid->next = netid;
+         netid = o->netid;
+       }
+    }
+       
+  /* user-class options are, according to RFC3004, supposed to contain
+     a set of counted strings. Here we check that this is so (by seeing
+     if the counts are consistent with the overall option length) and if
+     so zero the counts so that we don't get spurious matches between 
+     the vendor string and the counts. If the lengths don't add up, we
+     assume that the option is a single string and non RFC3004 compliant 
+     and just do the substring match. dhclient provides these broken options.
+     The code, later, which sends user-class data to the lease-change script
+     relies on the transformation done here.
+  */
+
+  if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
+    {
+      unsigned char *ucp = option_ptr(opt, 0);
+      int tmp, j;
+      for (j = 0; j < option_len(opt); j += ucp[j] + 1);
+      if (j == option_len(opt))
+       for (j = 0; j < option_len(opt); j = tmp)
+         {
+           tmp = j + ucp[j] + 1;
+           ucp[j] = 0;
+         }
+    }
+    
+  for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
+    {
+      int mopt;
+      
+      if (vendor->match_type == MATCH_VENDOR)
+       mopt = OPTION_VENDOR_ID;
+      else if (vendor->match_type == MATCH_USER)
+       mopt = OPTION_USER_CLASS; 
+      else
+       continue;
+
+      if ((opt = option_find(mess, sz, mopt, 1)))
+       {
+         int i;
+         for (i = 0; i <= (option_len(opt) - vendor->len); i++)
+           if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
+             {
+               vendor->netid.next = netid;
+               netid = &vendor->netid;
+               break;
+             }
+       }
+    }
+
+  /* mark vendor-encapsulated options which match the client-supplied vendor class,
+     save client-supplied vendor class */
+  if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
+    {
+      memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
+      vendor_class_len = option_len(opt);
+    }
+  match_vendor_opts(opt, daemon->dhcp_opts);
+  
+  if (option_bool(OPT_LOG_OPTS))
+    {
+      if (sanitise(opt, daemon->namebuff))
+       my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
+      if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
+       my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
+    }
+
+  tagif_netid = run_tag_if(netid);
+
+  /* if all the netids in the ignore list are present, ignore this client */
+  for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
+    if (match_netid(id_list->list, tagif_netid, 0))
+      ignore = 1;
+
+  /* If configured, we can override the server-id to be the address of the relay, 
+     so that all traffic goes via the relay and can pick up agent-id info. This can be
+     configured for all relays, or by address. */
+  if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
+    {
+      if (!daemon->override_relays)
+       override = mess->giaddr;
+      else
+       {
+         struct addr_list *l;
+         for (l = daemon->override_relays; l; l = l->next)
+           if (l->addr.s_addr == mess->giaddr.s_addr)
+             break;
+         if (l)
+           override = mess->giaddr;
+       }
+    }
+
+  /* Can have setting to ignore the client ID for a particular MAC address or hostname */
+  if (have_config(config, CONFIG_NOCLID))
+    clid = NULL;
+          
+  /* Check if client is PXE client. */
+  if (daemon->enable_pxe && 
+      (opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) && 
+      strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
+    {
+      if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
+       {
+         memcpy(pxe_uuid, option_ptr(opt, 0), 17);
+         uuid = pxe_uuid;
+       }
+
+      /* Check if this is really a PXE bootserver request, and handle specially if so. */
+      if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
+         (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
+         (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
+       {
+         struct pxe_service *service;
+         int type = option_uint(opt, 0, 2);
+         int layer = option_uint(opt, 2, 2);
+         unsigned char save71[4];
+         struct dhcp_opt opt71;
+
+         if (ignore)
+           return 0;
+
+         if (layer & 0x8000)
+           {
+             my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
+             return 0;
+           }
+
+         memcpy(save71, option_ptr(opt, 0), 4);
+         
+         for (service = daemon->pxe_services; service; service = service->next)
+           if (service->type == type)
+             break;
+         
+         if (!service || !service->basename)
+           return 0;
+         
+         clear_packet(mess, end);
+         
+         mess->yiaddr = mess->ciaddr;
+         mess->ciaddr.s_addr = 0;
+         if (service->server.s_addr != 0)
+           mess->siaddr = service->server; 
+         else
+           mess->siaddr = context->local; 
+         
+         snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
+         option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
+         option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
+         pxe_misc(mess, end, uuid);
+         
+         prune_vendor_opts(tagif_netid);
+         opt71.val = save71;
+         opt71.opt = SUBOPT_PXE_BOOT_ITEM;
+         opt71.len = 4;
+         opt71.flags = DHOPT_VENDOR_MATCH;
+         opt71.netid = NULL;
+         opt71.next = daemon->dhcp_opts;
+         do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
+         
+         log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid);
+         return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);         
+       }
+      
+      if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
+       {
+         pxearch = option_uint(opt, 0, 2);
+
+         /* proxy DHCP here. */
+         if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
+           {
+             struct dhcp_context *tmp;
+             
+             for (tmp = context; tmp; tmp = tmp->current)
+               if ((tmp->flags & CONTEXT_PROXY) &&
+                   match_netid(tmp->filter, tagif_netid, 1))
+                 break;
+             
+             if (tmp)
+               {
+                 struct dhcp_boot *boot = find_boot(tagif_netid);
+               
+                 mess->yiaddr.s_addr = 0;
+                 if  (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
+                   {
+                     mess->ciaddr.s_addr = 0;
+                     mess->flags |= htons(0x8000); /* broadcast */
+                   }
+                 
+                 clear_packet(mess, end);
+                 
+                 /* Provide the bootfile here, for gPXE, and in case we have no menu items
+                    and set discovery_control = 8 */
+                 if (boot)
+                   {
+                     if (boot->next_server.s_addr)
+                       mess->siaddr = boot->next_server;
+                     
+                     if (boot->file)
+                       strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
+                   }
+                 
+                 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, 
+                            mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
+                 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
+                 pxe_misc(mess, end, uuid);
+                 prune_vendor_opts(tagif_netid);
+                 do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
+                 
+                 log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", mess->xid);
+                 return ignore ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end);    
+               }
+           }
+       }
+    }
+
+  /* if we're just a proxy server, go no further */
+  if ((context->flags & CONTEXT_PROXY) || pxe)
+    return 0;
+  
+  if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
+    {
+      req_options = (unsigned char *)daemon->dhcp_buff2;
+      memcpy(req_options, option_ptr(opt, 0), option_len(opt));
+      req_options[option_len(opt)] = OPTION_END;
+    }
+  
+  switch (mess_type)
+    {
+    case DHCPDECLINE:
+      if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
+         option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
+       return 0;
+      
+      /* sanitise any message. Paranoid? Moi? */
+      sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
+      
+      if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
+       return 0;
+      
+      log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff, mess->xid);
+      
+      if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
+       lease_prune(lease, now);
+      
+      if (have_config(config, CONFIG_ADDR) && 
+         config->addr.s_addr == option_addr(opt).s_addr)
+       {
+         prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
+         my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"), 
+                   inet_ntoa(config->addr), daemon->dhcp_buff);
+         config->flags |= CONFIG_DECLINED;
+         config->decline_time = now;
+       }
+      else
+       /* make sure this host gets a different address next time. */
+       for (; context; context = context->current)
+         context->addr_epoch++;
+      
+      return 0;
+
+    case DHCPRELEASE:
+      if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
+         !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
+         option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
+       return 0;
+      
+      if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
+       lease_prune(lease, now);
+      else
+       message = _("unknown lease");
+
+      log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
+       
+      return 0;
+      
+    case DHCPDISCOVER:
+      if (ignore || have_config(config, CONFIG_DISABLE))
+       {
+         message = _("ignored");
+         opt = NULL;
+       }
+      else 
+       {
+         struct in_addr addr, conf;
+         
+         addr.s_addr = conf.s_addr = 0;
+
+         if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))      
+           addr = option_addr(opt);
+         
+         if (have_config(config, CONFIG_ADDR))
+           {
+             char *addrs = inet_ntoa(config->addr);
+             
+             if ((ltmp = lease_find_by_addr(config->addr)) && 
+                 ltmp != lease &&
+                 !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
+               {
+                 int len;
+                 unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
+                                                      ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
+                 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
+                           addrs, print_mac(daemon->namebuff, mac, len));
+               }
+             else
+               {
+                 struct dhcp_context *tmp;
+                 for (tmp = context; tmp; tmp = tmp->current)
+                   if (context->router.s_addr == config->addr.s_addr)
+                     break;
+                 if (tmp)
+                   my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
+                 else if (have_config(config, CONFIG_DECLINED) &&
+                          difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
+                   my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
+                 else
+                   conf = config->addr;
+               }
+           }
+         
+         if (conf.s_addr)
+           mess->yiaddr = conf;
+         else if (lease && 
+                  address_available(context, lease->addr, tagif_netid) && 
+                  !config_find_by_address(daemon->dhcp_conf, lease->addr))
+           mess->yiaddr = lease->addr;
+         else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) && 
+                  !config_find_by_address(daemon->dhcp_conf, addr))
+           mess->yiaddr = addr;
+         else if (emac_len == 0)
+           message = _("no unique-id");
+         else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
+           message = _("no address available");      
+       }
+      
+      log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid); 
+
+      if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
+       return 0;
+
+      log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
+
+      if (context->netid.net)
+       {
+         context->netid.next = netid;
+         netid = &context->netid;
+         tagif_netid = run_tag_if(netid);
+       }
+       
+      time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
+      clear_packet(mess, end);
+      option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
+      option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
+      option_put(mess, end, OPTION_LEASE_TIME, 4, time);
+      /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
+      if (time != 0xffffffff)
+       {
+         option_put(mess, end, OPTION_T1, 4, (time/2));
+         option_put(mess, end, OPTION_T2, 4, (time*7)/8);
+       }
+      do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr), 
+                domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
+      
+      return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
+      
+    case DHCPREQUEST:
+      if (ignore || have_config(config, CONFIG_DISABLE))
+       return 0;
+      if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
+       {
+         /* SELECTING  or INIT_REBOOT */
+         mess->yiaddr = option_addr(opt);
+         
+         /* send vendor and user class info for new or recreated lease */
+         do_classes = 1;
+         
+         if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
+           {
+             /* SELECTING */
+             selecting = 1;
+             
+             if (override.s_addr != 0)
+               {
+                 if (option_addr(opt).s_addr != override.s_addr)
+                   return 0;
+               }
+             else 
+               {
+                 for (; context; context = context->current)
+                   if (context->local.s_addr == option_addr(opt).s_addr)
+                     break;
+                 
+                 if (!context)
+                   {
+                     /* In auth mode, a REQUEST sent to the wrong server
+                        should be faulted, so that the client establishes 
+                        communication with us, otherwise, silently ignore. */
+                     if (!option_bool(OPT_AUTHORITATIVE))
+                       return 0;
+                     message = _("wrong server-ID");
+                   }
+               }
+
+             /* If a lease exists for this host and another address, squash it. */
+             if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
+               {
+                 lease_prune(lease, now);
+                 lease = NULL;
+               }
+           }
+         else
+           {
+             /* INIT-REBOOT */
+             if (!lease && !option_bool(OPT_AUTHORITATIVE))
+               return 0;
+             
+             if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
+               message = _("wrong address");
+           }
+       }
+      else
+       {
+         /* RENEWING or REBINDING */ 
+         /* Check existing lease for this address.
+            We allow it to be missing if dhcp-authoritative mode
+            as long as we can allocate the lease now - checked below.
+            This makes for a smooth recovery from a lost lease DB */
+         if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
+             (!lease && !option_bool(OPT_AUTHORITATIVE)))
+           {
+             /* A client rebinding will broadcast the request, so we may see it even 
+                if the lease is held by another server. Just ignore it in that case. 
+                If the request is unicast to us, then somethings wrong, NAK */
+             if (!unicast_dest)
+               return 0;
+             message = _("lease not found");
+             /* ensure we broadcast NAK */
+             unicast_dest = 0;
+           }
+
+         /* desynchronise renewals */
+         fuzz = rand16();
+         mess->yiaddr = mess->ciaddr;
+       }
+      
+      log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
+      if (!message)
+       {
+         struct dhcp_config *addr_config;
+         struct dhcp_context *tmp = NULL;
+         
+         if (have_config(config, CONFIG_ADDR))
+           for (tmp = context; tmp; tmp = tmp->current)
+             if (context->router.s_addr == config->addr.s_addr)
+               break;
+         
+         if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
+           {
+             /* If a machine moves networks whilst it has a lease, we catch that here. */
+             message = _("wrong network");
+             /* ensure we broadcast NAK */
+             unicast_dest = 0;
+           }
+         
+         /* Check for renewal of a lease which is outside the allowed range. */
+         else if (!address_available(context, mess->yiaddr, tagif_netid) &&
+                  (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
+           message = _("address not available");
+         
+         /* Check if a new static address has been configured. Be very sure that
+            when the client does DISCOVER, it will get the static address, otherwise
+            an endless protocol loop will ensue. */
+         else if (!tmp && !selecting &&
+                  have_config(config, CONFIG_ADDR) && 
+                  (!have_config(config, CONFIG_DECLINED) ||
+                   difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
+                  config->addr.s_addr != mess->yiaddr.s_addr &&
+                  (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
+           message = _("static lease available");
+
+         /* Check to see if the address is reserved as a static address for another host */
+         else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
+           message = _("address reserved");
+
+         else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
+           {
+             /* If a host is configured with more than one MAC address, it's OK to 'nix 
+                a lease from one of it's MACs to give the address to another. */
+             if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
+               {
+                 my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
+                           print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len), 
+                           inet_ntoa(ltmp->addr));
+                 lease = ltmp;
+               }
+             else
+               message = _("address in use");
+           }
+
+         if (!message)
+           {
+             if (emac_len == 0)
+               message = _("no unique-id");
+             
+             else if (!lease)
+               {            
+                 if ((lease = lease_allocate(mess->yiaddr)))
+                   do_classes = 1;
+                 else
+                   message = _("no leases left");
+               }
+           }
+       }
+
+      if (message)
+       {
+         log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, message, mess->xid);
+         
+         mess->yiaddr.s_addr = 0;
+         clear_packet(mess, end);
+         option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
+         option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
+         option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
+         /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on 
+            a distant subnet which unicast a REQ to us won't work. */
+         if (!unicast_dest || mess->giaddr.s_addr != 0 || 
+             mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
+           {
+             mess->flags |= htons(0x8000); /* broadcast */
+             mess->ciaddr.s_addr = 0;
+           }
+       }
+      else
+       {
+         if (context->netid.net)
+           {
+             context->netid.next = netid;
+             netid = &context->netid;
+             tagif_netid = run_tag_if(netid);
+           }
+         
+#ifdef HAVE_SCRIPT
+         if (do_classes && daemon->lease_change_command)
+           {
+             struct dhcp_netid *n;
+             
+             if (mess->giaddr.s_addr)
+               lease->giaddr = mess->giaddr;
+             
+             lease->changed = 1;
+             free(lease->extradata);
+             lease->extradata = NULL;
+             lease->extradata_size = lease->extradata_len = 0;
+             
+             add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
+             add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
+             add_extradata_opt(lease, oui);
+             add_extradata_opt(lease, serial);
+             add_extradata_opt(lease, class);
+             
+             /* space-concat tag set */
+             if (!tagif_netid)
+               add_extradata_opt(lease, NULL);
+             else
+               for (n = tagif_netid; n; n = n->next)
+                 add_extradata_data(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0); 
+             
+             if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
+               {
+                 int len = option_len(opt);
+                 unsigned char *ucp = option_ptr(opt, 0);
+                 /* If the user-class option started as counted strings, the first byte will be zero. */
+                 if (len != 0 && ucp[0] == 0)
+                   ucp++, len--;
+                 add_extradata_data(lease, ucp, len, 0);
+               }
+           }
+#endif
+         
+         if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
+           {
+             domain = get_domain(mess->yiaddr);
+             hostname = client_hostname;
+             hostname_auth = 1;
+           }
+         
+         time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
+         lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len);
+         
+         /* if all the netids in the ignore_name list are present, ignore client-supplied name */
+         if (!hostname_auth)
+           {
+             for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
+               if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
+                 break;
+             if (id_list)
+               hostname = NULL;
+           }
+         
+         /* Last ditch, if configured, generate hostname from mac address */
+         if (!hostname && emac_len != 0)
+           {
+             for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
+               if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
+                 break;
+             if (id_list)
+               {
+                 int i;
+
+                 hostname = daemon->dhcp_buff;
+                 /* buffer is 256 bytes, 3 bytes per octet */
+                 for (i = 0; (i < emac_len) && (i < 80); i++)
+                   hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
+                 hostname = daemon->dhcp_buff;
+               }
+           }
+
+         if (hostname)
+           lease_set_hostname(lease, hostname, hostname_auth);
+         
+         lease_set_expires(lease, time, now);
+         lease_set_interface(lease, int_index);
+
+         if (override.s_addr != 0)
+           lease->override = override;
+         else
+           override = lease->override;
+
+         log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, mess->xid);  
+         if (difftime(now, old_time) > 7)
+               emit_dbus_signal(ACTION_CONNECT, lease, hostname);
+         old_time = now;
+         
+         clear_packet(mess, end);
+         option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
+         option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
+         option_put(mess, end, OPTION_LEASE_TIME, 4, time);
+         if (time != 0xffffffff)
+           {
+             while (fuzz > (time/16))
+               fuzz = fuzz/2; 
+             option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
+             option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
+           }
+         do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr), 
+                    domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
+       }
+
+      return dhcp_packet_size(mess, tagif_netid, agent_id, real_end); 
+      
+    case DHCPINFORM:
+      if (ignore || have_config(config, CONFIG_DISABLE))
+       message = _("ignored");
+      
+      log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid);
+     
+      if (message || mess->ciaddr.s_addr == 0)
+       return 0;
+
+      /* For DHCPINFORM only, cope without a valid context */
+      context = narrow_context(context, mess->ciaddr, tagif_netid);
+      
+      /* Find a least based on IP address if we didn't
+        get one from MAC address/client-d */
+      if (!lease &&
+         (lease = lease_find_by_addr(mess->ciaddr)) && 
+         lease->hostname)
+       hostname = lease->hostname;
+      
+      if (!hostname && (hostname = host_from_dns(mess->ciaddr)))
+       domain = get_domain(mess->ciaddr);
+
+      log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid);
+      
+      if (context && context->netid.net)
+       {
+         context->netid.next = netid;
+         netid = &context->netid;
+         tagif_netid = run_tag_if(netid);
+       }
+      
+      if (lease)
+       {
+         if (override.s_addr != 0)
+           lease->override = override;
+         else
+           override = lease->override;
+       }
+
+      clear_packet(mess, end);
+      option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
+      option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
+      
+      if (lease)
+       {
+         if (lease->expires == 0)
+           time = 0xffffffff;
+         else
+           time = (unsigned int)difftime(lease->expires, now);
+         option_put(mess, end, OPTION_LEASE_TIME, 4, time);
+         lease_set_interface(lease, int_index);
+       }
+
+      do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
+                domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
+      
+      *is_inform = 1; /* handle reply differently */
+      return dhcp_packet_size(mess, tagif_netid, agent_id, real_end); 
+    }
+  
+  return 0;
+}
+
+static int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
+{
+  int i;
+  
+  if (o->len > len)
+    return 0;
+  
+  if (o->len == 0)
+    return 1;
+     
+  if (o->flags & DHOPT_HEX)
+    { 
+      if (memcmp_masked(o->val, p, o->len, o->u.wildcard_mask))
+       return 1;
+    }
+  else 
+    for (i = 0; i <= (len - o->len); ) 
+      {
+       if (memcmp(o->val, p + i, o->len) == 0)
+         return 1;
+           
+       if (o->flags & DHOPT_STRING)
+         i++;
+       else
+         i += o->len;
+      }
+  
+  return 0;
+}
+      
+
+/* find a good value to use as MAC address for logging and address-allocation hashing.
+   This is normally just the chaddr field from the DHCP packet,
+   but eg Firewire will have hlen == 0 and use the client-id instead. 
+   This could be anything, but will normally be EUI64 for Firewire.
+   We assume that if the first byte of the client-id equals the htype byte
+   then the client-id is using the usual encoding and use the rest of the 
+   client-id: if not we can use the whole client-id. This should give
+   sane MAC address logs. */
+unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, 
+                                     int clid_len, unsigned char *clid, int *len_out)
+{
+  if (hwlen == 0 && clid && clid_len > 3)
+    {
+      if (clid[0]  == hwtype)
+       {
+         *len_out = clid_len - 1 ;
+         return clid + 1;
+       }
+
+#if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
+      if (clid[0] ==  ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
+       {
+         *len_out = clid_len - 1 ;
+         return clid + 1;
+       }
+#endif
+      
+      *len_out = clid_len;
+      return clid;
+    }
+  
+  *len_out = hwlen;
+  return hwaddr;
+}
+
+static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
+{
+  unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
+  
+  if (opt)
+    { 
+      unsigned int req_time = option_uint(opt, 0, 4);
+      if (req_time < 120 )
+       req_time = 120; /* sanity */
+      if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
+       time = req_time;
+    }
+
+  return time;
+}
+
+static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
+{
+  if (override.s_addr != 0)
+    return override;
+  else if (context)
+    return context->local;
+  else
+    return fallback;
+}
+
+static int sanitise(unsigned char *opt, char *buf)
+{
+  char *p;
+  int i;
+  
+  *buf = 0;
+  
+  if (!opt)
+    return 0;
+
+  p = option_ptr(opt, 0);
+
+  for (i = option_len(opt); i > 0; i--)
+    {
+      char c = *p++;
+      if (isprint((int)c))
+       *buf++ = c;
+    }
+  *buf = 0; /* add terminator */
+  
+  return 1;
+}
+
+#ifdef HAVE_SCRIPT
+static void add_extradata_data(struct dhcp_lease *lease, unsigned char *data, size_t len, int delim)
+{
+  if ((lease->extradata_size - lease->extradata_len) < (len + 1))
+    {
+      size_t newsz = lease->extradata_len + len + 100;
+      unsigned char *new = whine_malloc(newsz);
+  
+      if (!new)
+       return;
+      
+      if (lease->extradata)
+       {
+         memcpy(new, lease->extradata, lease->extradata_len);
+         free(lease->extradata);
+       }
+
+      lease->extradata = new;
+      lease->extradata_size = newsz;
+    }
+
+  if (len != 0)
+    memcpy(lease->extradata + lease->extradata_len, data, len);
+  lease->extradata[lease->extradata_len + len] = delim;
+  lease->extradata_len += len + 1; 
+}
+
+static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
+{
+  if (!opt)
+    add_extradata_data(lease, NULL, 0, 0);
+  else
+    {
+      size_t i, len = option_len(opt);
+      unsigned char *ucp = option_ptr(opt, 0);
+      
+      /* check for embeded NULLs */
+      for (i = 0; i < len; i++)
+       if (ucp[i] == 0)
+         {
+           len = i;
+           break;
+         }
+
+      add_extradata_data(lease, ucp, len, 0);
+    }
+}
+#endif
+
+static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
+                      int mac_len, char *interface, char *string, u32 xid)
+{
+  struct in_addr a;
+  /* addr may be misaligned */
+  if (addr)
+    memcpy(&a, addr, sizeof(a));
+  
+  print_mac(daemon->namebuff, ext_mac, mac_len);
+  
+  if(option_bool(OPT_LOG_OPTS))
+     my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s",
+              ntohl(xid), 
+              type,
+              interface, 
+              addr ? inet_ntoa(a) : "",
+              addr ? " " : "",
+              daemon->namebuff,
+              string ? string : "");
+  else
+    my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s",
+             type,
+             interface, 
+             addr ? inet_ntoa(a) : "",
+             addr ? " " : "",
+             daemon->namebuff,
+             string ? string : "");
+}
+
+static void log_options(unsigned char *start, u32 xid)
+{
+  while (*start != OPTION_END)
+    {
+      int is_ip, is_name, i;
+      char *text = option_string(start[0], &is_ip, &is_name);
+      unsigned char trunc = option_len(start);
+      
+      if (is_ip)
+       for (daemon->namebuff[0]= 0, i = 0; i <= trunc - INADDRSZ; i += INADDRSZ) 
+         {
+           if (i != 0)
+             strncat(daemon->namebuff, ", ", 256 - strlen(daemon->namebuff));
+           strncat(daemon->namebuff, inet_ntoa(option_addr_arr(start, i)), 256 - strlen(daemon->namebuff));
+         }
+      else if (!is_name || !sanitise(start, daemon->namebuff))
+       {
+         if (trunc > 13)
+           trunc = 13;
+         print_mac(daemon->namebuff, option_ptr(start, 0), trunc);
+       }
+      
+      my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d%s%s%s%s%s", 
+               ntohl(xid), option_len(start), start[0],
+               text ? ":" : "", text ? text : "",
+               trunc == 0 ? "" : "  ",
+               trunc == 0 ? "" : daemon->namebuff,
+               trunc == option_len(start) ? "" : "...");
+      start += start[1] + 2;
+    }
+}
+
+static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
+{
+  while (1) 
+    {
+      if (p > end)
+       return NULL;
+      else if (*p == OPTION_END)
+       return opt == OPTION_END ? p : NULL;
+      else if (*p == OPTION_PAD)
+       p++;
+      else 
+       { 
+         int opt_len;
+         if (p > end - 2)
+           return NULL; /* malformed packet */
+         opt_len = option_len(p);
+         if (p > end - (2 + opt_len))
+           return NULL; /* malformed packet */
+         if (*p == opt && opt_len >= minsize)
+           return p;
+         p += opt_len + 2;
+       }
+    }
+}
+static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
+{
+  unsigned char *ret, *overload;
+  
+  /* skip over DHCP cookie; */
+  if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
+    return ret;
+
+  /* look for overload option. */
+  if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
+    return NULL;
+  
+  /* Can we look in filename area ? */
+  if ((overload[2] & 1) &&
+      (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
+    return ret;
+
+  /* finally try sname area */
+  if ((overload[2] & 2) &&
+      (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
+    return ret;
+
+  return NULL;
+}
+
+static struct in_addr option_addr_arr(unsigned char *opt, int offset)
+{
+  /* this worries about unaligned data in the option. */
+  /* struct in_addr is network byte order */
+  struct in_addr ret;
+
+  memcpy(&ret, option_ptr(opt, offset), INADDRSZ);
+
+  return ret;
+}
+
+static struct in_addr option_addr(unsigned char *opt)
+{
+  return option_addr_arr(opt, 0);
+}
+
+static unsigned int option_uint(unsigned char *opt, int offset, int size)
+{
+  /* this worries about unaligned data and byte order */
+  unsigned int ret = 0;
+  int i;
+  unsigned char *p = option_ptr(opt, offset);
+  
+  for (i = 0; i < size; i++)
+    ret = (ret << 8) | *p++;
+
+  return ret;
+}
+
+static unsigned char *dhcp_skip_opts(unsigned char *start)
+{
+  while (*start != 0)
+    start += start[1] + 2;
+  return start;
+}
+
+/* only for use when building packet: doesn't check for bad data. */ 
+static unsigned char *find_overload(struct dhcp_packet *mess)
+{
+  unsigned char *p = &mess->options[0] + sizeof(u32);
+  
+  while (*p != 0)
+    {
+      if (*p == OPTION_OVERLOAD)
+       return p;
+      p += p[1] + 2;
+    }
+  return NULL;
+}
+
+static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid,
+                              unsigned char *agent_id, unsigned char *real_end)
+{
+  unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
+  unsigned char *overload;
+  size_t ret;
+  struct dhcp_netid_list *id_list;
+  struct dhcp_netid *n;
+
+  /* move agent_id back down to the end of the packet */
+  if (agent_id)
+    {
+      memmove(p, agent_id, real_end - agent_id);
+      p += real_end - agent_id;
+      memset(p, 0, real_end - p); /* in case of overlap */
+    }
+  
+  /* We do logging too */
+  if (netid && option_bool(OPT_LOG_OPTS))
+    {
+      char *s = daemon->namebuff;
+      for (*s = 0; netid; netid = netid->next)
+       {
+         /* kill dupes. */
+         for (n = netid->next; n; n = n->next)
+           if (strcmp(netid->net, n->net) == 0)
+             break;
+         
+         if (!n)
+           {
+             strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
+             if (netid->next)
+               strncat (s, ", ", (MAXDNAME-1) - strlen(s));
+           }
+       }
+      my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), s);
+    } 
+   
+  /* add END options to the regions. */
+  overload = find_overload(mess);
+  
+  if (overload && (option_uint(overload, 0, 1) & 1))
+    {
+      *dhcp_skip_opts(mess->file) = OPTION_END;
+      if (option_bool(OPT_LOG_OPTS))
+       log_options(mess->file, mess->xid);
+    }
+  else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
+    my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
+  
+  if (overload && (option_uint(overload, 0, 1) & 2))
+    {
+      *dhcp_skip_opts(mess->sname) = OPTION_END;
+      if (option_bool(OPT_LOG_OPTS))
+       log_options(mess->sname, mess->xid);
+    }
+  else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
+    my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
+
+
+  *p++ = OPTION_END;
+  
+  for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
+    if ((!id_list->list) || match_netid(id_list->list, netid, 0))
+      break;
+  if (id_list)
+    mess->flags |= htons(0x8000); /* force broadcast */
+  
+  if (option_bool(OPT_LOG_OPTS))
+    {
+      if (mess->siaddr.s_addr != 0)
+       my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
+      
+      if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
+       my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
+      
+      log_options(&mess->options[0] + sizeof(u32), mess->xid);
+    } 
+  
+  ret = (size_t)(p - (unsigned char *)mess);
+  
+  if (ret < MIN_PACKETSZ)
+    ret = MIN_PACKETSZ;
+  
+  return ret;
+}
+
+static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
+{
+  unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
+  
+  if (p + len + 3 >= end)
+    /* not enough space in options area, try and use overload, if poss */
+    {
+      unsigned char *overload;
+      
+      if (!(overload = find_overload(mess)) &&
+         (mess->file[0] == 0 || mess->sname[0] == 0))
+       {
+         /* attempt to overload fname and sname areas, we've reserved space for the
+            overflow option previuously. */
+         overload = p;
+         *(p++) = OPTION_OVERLOAD;
+         *(p++) = 1;
+       }
+      
+      p = NULL;
+      
+      /* using filename field ? */
+      if (overload)
+       {
+         if (mess->file[0] == 0)
+           overload[2] |= 1;
+         
+         if (overload[2] & 1)
+           {
+             p = dhcp_skip_opts(mess->file);
+             if (p + len + 3 >= mess->file + sizeof(mess->file))
+               p = NULL;
+           }
+         
+         if (!p)
+           {
+             /* try to bring sname into play (it may be already) */
+             if (mess->sname[0] == 0)
+               overload[2] |= 2;
+             
+             if (overload[2] & 2)
+               {
+                 p = dhcp_skip_opts(mess->sname);
+                 if (p + len + 3 >= mess->sname + sizeof(mess->file))
+                   p = NULL;
+               }
+           }
+       }
+      
+      if (!p)
+       my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
+    }
+  if (p)
+    {
+      *(p++) = opt;
+      *(p++) = len;
+    }
+
+  return p;
+}
+             
+static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
+{
+  int i;
+  unsigned char *p = free_space(mess, end, opt, len);
+  
+  if (p) 
+    for (i = 0; i < len; i++)
+      *(p++) = val >> (8 * (len - (i + 1)));
+}
+
+static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt, 
+                             char *string, int null_term)
+{
+  unsigned char *p;
+  size_t len = strlen(string);
+
+  if (null_term && len != 255)
+    len++;
+
+  if ((p = free_space(mess, end, opt, len)))
+    memcpy(p, string, len);
+}
+
+/* return length, note this only does the data part */
+static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
+{
+  int len = opt->len;
+  
+  if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
+    len++;
+
+  if (p && len != 0)
+    {
+      if (context && (opt->flags & DHOPT_ADDR))
+       {
+         int j;
+         struct in_addr *a = (struct in_addr *)opt->val;
+         for (j = 0; j < opt->len; j+=INADDRSZ, a++)
+           {
+             /* zero means "self" (but not in vendorclass options.) */
+             if (a->s_addr == 0)
+               memcpy(p, &context->local, INADDRSZ);
+             else
+               memcpy(p, a, INADDRSZ);
+             p += INADDRSZ;
+           }
+       }
+      else
+       memcpy(p, opt->val, len);
+    }  
+  return len;
+}
+
+static int in_list(unsigned char *list, int opt)
+{
+  int i;
+
+   /* If no requested options, send everything, not nothing. */
+  if (!list)
+    return 1;
+  
+  for (i = 0; list[i] != OPTION_END; i++)
+    if (opt == list[i])
+      return 1;
+
+  return 0;
+}
+
+static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *opts, int opt)
+{
+  struct dhcp_opt *tmp;  
+  for (tmp = opts; tmp; tmp = tmp->next)
+    if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
+      if (match_netid(tmp->netid, netid, 0))
+       return tmp;
+
+  /* No match, look for one without a netid */
+  for (tmp = opts; tmp; tmp = tmp->next)
+    if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
+      if (match_netid(tmp->netid, netid, 1))
+       return tmp;
+                     
+  return NULL;
+}
+
+/* mark vendor-encapsulated options which match the client-supplied  or
+   config-supplied vendor class */
+static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
+{
+  for (; dopt; dopt = dopt->next)
+    {
+      dopt->flags &= ~DHOPT_VENDOR_MATCH;
+      if (opt && (dopt->flags & DHOPT_VENDOR))
+       {
+         int i, len = 0;
+         if (dopt->u.vendor_class)
+           len = strlen((char *)dopt->u.vendor_class);
+         for (i = 0; i <= (option_len(opt) - len); i++)
+           if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
+             {
+               dopt->flags |= DHOPT_VENDOR_MATCH;
+               break;
+             }
+       }
+    }
+}
+
+static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,  
+                        struct dhcp_packet *mess, unsigned char *end, int null_term)
+{
+  int len, enc_len, ret = 0;
+  struct dhcp_opt *start;
+  unsigned char *p;
+    
+  /* find size in advance */
+  for (enc_len = 0, start = opt; opt; opt = opt->next)
+    if (opt->flags & flag)
+      {
+       int new = do_opt(opt, NULL, NULL, null_term) + 2;
+       ret  = 1;
+       if (enc_len + new <= 255)
+         enc_len += new;
+       else
+         {
+           p = free_space(mess, end, encap, enc_len);
+           for (; start && start != opt; start = start->next)
+             if (p && (start->flags & flag))
+               {
+                 len = do_opt(start, p + 2, NULL, null_term);
+                 *(p++) = start->opt;
+                 *(p++) = len;
+                 p += len;
+               }
+           enc_len = new;
+           start = opt;
+         }
+      }
+  
+  if (enc_len != 0 &&
+      (p = free_space(mess, end, encap, enc_len + 1)))
+    {
+      for (; start; start = start->next)
+       if (start->flags & flag)
+         {
+           len = do_opt(start, p + 2, NULL, null_term);
+           *(p++) = start->opt;
+           *(p++) = len;
+           p += len;
+         }
+      *p = OPTION_END;
+    }
+
+  return ret;
+}
+
+static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
+{
+  unsigned char *p;
+
+  option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0);
+  if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
+    memcpy(p, uuid, 17);
+}
+
+static int prune_vendor_opts(struct dhcp_netid *netid)
+{
+  int force = 0;
+  struct dhcp_opt *opt;
+
+  /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
+  for (opt = daemon->dhcp_opts; opt; opt = opt->next)
+    if (opt->flags & DHOPT_VENDOR_MATCH)
+      {
+       if (!match_netid(opt->netid, netid, 1))
+         opt->flags &= ~DHOPT_VENDOR_MATCH;
+       else if (opt->flags & DHOPT_FORCE)
+         force = 1;
+      }
+  return force;
+}
+
+static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local)
+{
+#define NUM_OPTS 4  
+
+  unsigned  char *p, *q;
+  struct pxe_service *service;
+  static struct dhcp_opt *o, *ret;
+  int i, j = NUM_OPTS - 1;
+  struct in_addr boot_server;
+  
+  /* We pass back references to these, hence they are declared static */
+  static unsigned char discovery_control;
+  static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' }; 
+  static struct dhcp_opt *fake_opts = NULL;
+  
+  /* Disable multicast, since we don't support it, and broadcast
+     unless we need it */
+  discovery_control = 3;
+  
+  ret = daemon->dhcp_opts;
+  
+  if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
+    return ret;
+
+  for (i = 0; i < NUM_OPTS; i++)
+    {
+      fake_opts[i].flags = DHOPT_VENDOR_MATCH;
+      fake_opts[i].netid = NULL;
+      fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
+    }
+  
+  /* create the data for the PXE_MENU and PXE_SERVERS options. */
+  p = (unsigned char *)daemon->dhcp_buff;
+  q = (unsigned char *)daemon->dhcp_buff3;
+
+  for (i = 0, service = daemon->pxe_services; service; service = service->next)
+    if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
+      {
+       size_t len = strlen(service->menu);
+       /* opt 43 max size is 255. encapsulated option has type and length
+          bytes, so its max size is 253. */
+       if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
+         {
+           *(p++) = service->type >> 8;
+           *(p++) = service->type;
+           *(p++) = len;
+           memcpy(p, service->menu, len);
+           p += len;
+           i++;
+         }
+       else
+         {
+         toobig:
+           my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
+           return daemon->dhcp_opts;
+         }
+       
+       boot_server = service->basename ? local : service->server;
+
+       if (boot_server.s_addr != 0)
+         {
+           if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
+             goto toobig;
+           
+           /* Boot service with known address - give it */
+           *(q++) = service->type >> 8;
+           *(q++) = service->type;
+           *(q++) = 1;
+           /* dest misaligned */
+           memcpy(q, &boot_server.s_addr, INADDRSZ);
+           q += INADDRSZ;
+         }
+       else if (service->type != 0)
+         /* We don't know the server for a service type, so we'll
+            allow the client to broadcast for it */
+         discovery_control = 2;
+      }
+
+  /* if no prompt, wait forever if there's a choice */
+  fake_prompt[0] = (i > 1) ? 255 : 0;
+  
+  if (i == 0)
+    discovery_control = 8; /* no menu - just use use mess->filename */
+  else
+    {
+      ret = &fake_opts[j--];
+      ret->len = p - (unsigned char *)daemon->dhcp_buff;
+      ret->val = (unsigned char *)daemon->dhcp_buff;
+      ret->opt = SUBOPT_PXE_MENU;
+
+      if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
+       {
+         ret = &fake_opts[j--]; 
+         ret->len = q - (unsigned char *)daemon->dhcp_buff3;
+         ret->val = (unsigned char *)daemon->dhcp_buff3;
+         ret->opt = SUBOPT_PXE_SERVERS;
+       }
+    }
+
+  for (o = daemon->dhcp_opts; o; o = o->next)
+    if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
+      break;
+  
+  if (!o)
+    {
+      ret = &fake_opts[j--]; 
+      ret->len = sizeof(fake_prompt);
+      ret->val = fake_prompt;
+      ret->opt = SUBOPT_PXE_MENU_PROMPT;
+    }
+  
+  ret = &fake_opts[j--]; 
+  ret->len = 1;
+  ret->opt = SUBOPT_PXE_DISCOVERY;
+  ret->val= &discovery_control;
+  return ret;
+}
+  
+static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
+{
+  memset(mess->sname, 0, sizeof(mess->sname));
+  memset(mess->file, 0, sizeof(mess->file));
+  memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
+  mess->siaddr.s_addr = 0;
+}
+
+struct dhcp_boot *find_boot(struct dhcp_netid *netid)
+{
+  struct dhcp_boot *boot;
+
+  /* decide which dhcp-boot option we're using */
+  for (boot = daemon->boot_config; boot; boot = boot->next)
+    if (match_netid(boot->netid, netid, 0))
+      break;
+  if (!boot)
+    /* No match, look for one without a netid */
+    for (boot = daemon->boot_config; boot; boot = boot->next)
+      if (match_netid(boot->netid, netid, 1))
+       break;
+
+  return boot;
+}
+
+static void do_options(struct dhcp_context *context,
+                      struct dhcp_packet *mess,
+                      unsigned char *end, 
+                      unsigned char *req_options,
+                      char *hostname, 
+                      char *domain, char *config_domain,
+                      struct dhcp_netid *netid,
+                      struct in_addr subnet_addr,
+                      unsigned char fqdn_flags,
+                      int null_term, int pxe_arch,
+                      unsigned char *uuid,
+                      int vendor_class_len)
+{
+  struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
+  struct dhcp_boot *boot;
+  unsigned char *p;
+  int i, len, force_encap = 0;
+  unsigned char f0 = 0, s0 = 0;
+  int done_file = 0, done_server = 0;
+  int done_vendor_class = 0;
+
+  if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
+    my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, hostname);
+  
+  /* logging */
+  if (option_bool(OPT_LOG_OPTS) && req_options)
+    {
+      char *q = daemon->namebuff;
+      for (i = 0; req_options[i] != OPTION_END; i++)
+       {
+         char *s = option_string(req_options[i], NULL, NULL);
+         q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
+                       "%d%s%s%s", 
+                       req_options[i],
+                       s ? ":" : "",
+                       s ? s : "", 
+                       req_options[i+1] == OPTION_END ? "" : ", ");
+         if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
+           {
+             q = daemon->namebuff;
+             my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
+           }
+       }
+    }
+      
+  if (context)
+    mess->siaddr = context->local;
+  
+  /* See if we can send the boot stuff as options.
+     To do this we need a requested option list, BOOTP
+     and very old DHCP clients won't have this, we also 
+     provide an manual option to disable it.
+     Some PXE ROMs have bugs (surprise!) and need zero-terminated 
+     names, so we always send those.  */
+  if ((boot = find_boot(netid)))
+    {
+      if (boot->sname)
+       {         
+         if (!option_bool(OPT_NO_OVERRIDE) &&
+             req_options && 
+             in_list(req_options, OPTION_SNAME))
+           option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
+         else
+           strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
+       }
+      
+      if (boot->file)
+       {
+         if (!option_bool(OPT_NO_OVERRIDE) &&
+             req_options && 
+             in_list(req_options, OPTION_FILENAME))
+           option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
+         else
+           strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
+       }
+      
+      if (boot->next_server.s_addr)
+       mess->siaddr = boot->next_server;
+    }
+  else
+    /* Use the values of the relevant options if no dhcp-boot given and
+       they're not explicitly asked for as options. OPTION_END is used
+       as an internal way to specify siaddr without using dhcp-boot, for use in
+       dhcp-optsfile. */
+    {
+      if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
+         (opt = option_find2(netid, config_opts, OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
+       {
+         strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
+         done_file = 1;
+       }
+      
+      if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
+         (opt = option_find2(netid, config_opts, OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
+       {
+         strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
+         done_server = 1;
+       }
+      
+      if ((opt = option_find2(netid, config_opts, OPTION_END)))
+       mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;     
+    }
+        
+  /* We don't want to do option-overload for BOOTP, so make the file and sname
+     fields look like they are in use, even when they aren't. This gets restored
+     at the end of this function. */
+
+  if (!req_options || option_bool(OPT_NO_OVERRIDE))
+    {
+      f0 = mess->file[0];
+      mess->file[0] = 1;
+      s0 = mess->sname[0];
+      mess->sname[0] = 1;
+    }
+      
+  /* At this point, if mess->sname or mess->file are zeroed, they are available
+     for option overload, reserve space for the overload option. */
+  if (mess->file[0] == 0 || mess->sname[0] == 0)
+    end -= 3;
+
+  /* rfc3011 says this doesn't need to be in the requested options list. */
+  if (subnet_addr.s_addr)
+    option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
+  
+  /* replies to DHCPINFORM may not have a valid context */
+  if (context)
+    {
+      if (!option_find2(netid, config_opts, OPTION_NETMASK))
+       option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
+  
+      /* May not have a "guessed" broadcast address if we got no packets via a relay
+        from this net yet (ie just unicast renewals after a restart */
+      if (context->broadcast.s_addr &&
+         !option_find2(netid, config_opts, OPTION_BROADCAST))
+       option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
+      
+      /* Same comments as broadcast apply, and also may not be able to get a sensible
+        default when using subnet select.  User must configure by steam in that case. */
+      if (context->router.s_addr &&
+         in_list(req_options, OPTION_ROUTER) &&
+         !option_find2(netid, config_opts, OPTION_ROUTER))
+       option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
+      
+      if (in_list(req_options, OPTION_DNSSERVER) &&
+         !option_find2(netid, config_opts, OPTION_DNSSERVER))
+       option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
+    }
+
+  if (domain && in_list(req_options, OPTION_DOMAINNAME) && 
+      !option_find2(netid, config_opts, OPTION_DOMAINNAME))
+    option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
+  /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
+  if (hostname)
+    {
+      if (in_list(req_options, OPTION_HOSTNAME) &&
+         !option_find2(netid, config_opts, OPTION_HOSTNAME))
+       option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
+      
+      if (fqdn_flags != 0)
+       {
+         len = strlen(hostname) + 3;
+         
+         if (fqdn_flags & 0x04)
+           len += 2;
+         else if (null_term)
+           len++;
+
+         if (domain)
+           len += strlen(domain) + 1;
+         
+         if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
+           {
+             *(p++) = fqdn_flags;
+             *(p++) = 255;
+             *(p++) = 255;
+
+             if (fqdn_flags & 0x04)
+               {
+                 p = do_rfc1035_name(p, hostname);
+                 if (domain)
+                   p = do_rfc1035_name(p, domain);
+                 *p++ = 0;
+               }
+             else
+               {
+                 memcpy(p, hostname, strlen(hostname));
+                 p += strlen(hostname);
+                 if (domain)
+                   {
+                     *(p++) = '.';
+                     memcpy(p, domain, strlen(domain));
+                     p += strlen(domain);
+                   }
+                 if (null_term)
+                   *(p++) = 0;
+               }
+           }
+       }
+    }      
+
+  for (opt = config_opts; opt; opt = opt->next)
+    {
+      int optno = opt->opt;
+
+      /* was it asked for, or are we sending it anyway? */
+      if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
+       continue;
+      
+      /* prohibit some used-internally options */
+      if (optno == OPTION_CLIENT_FQDN ||
+         optno == OPTION_MAXMESSAGE ||
+         optno == OPTION_OVERLOAD ||
+         optno == OPTION_PAD ||
+         optno == OPTION_END)
+       continue;
+
+      if (optno == OPTION_SNAME && done_server)
+       continue;
+
+      if (optno == OPTION_FILENAME && done_file)
+       continue;
+      
+      /* netids match and not encapsulated? */
+      if (opt != option_find2(netid, config_opts, optno))
+       continue;
+      
+      /* For the options we have default values on
+        dhc-option=<optionno> means "don't include this option"
+        not "include a zero-length option" */
+      if (opt->len == 0 && 
+         (optno == OPTION_NETMASK ||
+          optno == OPTION_BROADCAST ||
+          optno == OPTION_ROUTER ||
+          optno == OPTION_DNSSERVER || 
+          optno == OPTION_DOMAINNAME ||
+          optno == OPTION_HOSTNAME))
+       continue;
+
+      /* vendor-class comes from elsewhere for PXE */
+      if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
+       continue;
+      
+      /* always force null-term for filename and servername - buggy PXE again. */
+      len = do_opt(opt, NULL, context, 
+                  (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
+
+      if ((p = free_space(mess, end, optno, len)))
+       {
+         do_opt(opt, p, context, 
+                (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
+         
+         /* If we send a vendor-id, revisit which vendor-ops we consider 
+            it appropriate to send. */
+         if (optno == OPTION_VENDOR_ID)
+           {
+             match_vendor_opts(p - 2, config_opts);
+             done_vendor_class = 1;
+           }
+       }  
+    }
+
+  /* Now send options to be encapsulated in arbitrary options, 
+     eg dhcp-option=encap:172,17,.......
+     Also hand vendor-identifying vendor-encapsulated options,
+     dhcp-option = rfc3925-encap:13,17,.......
+     The may be more that one "outer" to do, so group
+     all the options which match each outer in turn. */
+  for (opt = config_opts; opt; opt = opt->next)
+    opt->flags &= ~DHOPT_ENCAP_DONE;
+  
+  for (opt = config_opts; opt; opt = opt->next)
+    {
+      int flags;
+      
+      if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
+       {
+         int found = 0;
+         struct dhcp_opt *o;
+
+         if (opt->flags & DHOPT_ENCAP_DONE)
+           continue;
+
+         for (len = 0, o = config_opts; o; o = o->next)
+           {
+             int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
+
+             o->flags &= ~DHOPT_ENCAP_MATCH;
+             
+             if (!(o->flags & flags) || opt->u.encap != o->u.encap)
+               continue;
+             
+             o->flags |= DHOPT_ENCAP_DONE;
+             if (match_netid(o->netid, netid, 1) &&
+                 ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
+               {
+                 o->flags |= DHOPT_ENCAP_MATCH;
+                 found = 1;
+                 len += do_opt(o, NULL, NULL, 0) + 2;
+               }
+           } 
+         
+         if (found)
+           { 
+             if (flags & DHOPT_ENCAPSULATE)
+               do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
+             else if (len > 250)
+               my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
+             else if ((p = free_space(mess, end,  OPTION_VENDOR_IDENT_OPT, len + 5)))
+               {
+                 int swap_ent = htonl(opt->u.encap);
+                 memcpy(p, &swap_ent, 4);
+                 p += 4;
+                 *(p++) = len;
+                 for (o = config_opts; o; o = o->next)
+                   if (o->flags & DHOPT_ENCAP_MATCH)
+                     {
+                       len = do_opt(o, p + 2, NULL, 0);
+                       *(p++) = o->opt;
+                       *(p++) = len;
+                       p += len;
+                     }     
+               }
+           }
+       }
+    }      
+
+  force_encap = prune_vendor_opts(netid);
+  
+  if (context && pxe_arch != -1)
+    {
+      pxe_misc(mess, end, uuid);
+      config_opts = pxe_opts(pxe_arch, netid, context->local);
+    }
+
+  if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
+      do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) && 
+      pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
+      (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
+    /* If we send vendor encapsulated options, and haven't already sent option 60,
+       echo back the value we got from the client. */
+    memcpy(p, daemon->dhcp_buff3, vendor_class_len);       
+   
+   /* restore BOOTP anti-overload hack */
+  if (!req_options || option_bool(OPT_NO_OVERRIDE))
+    {
+      mess->file[0] = f0;
+      mess->sname[0] = s0;
+    }
+}
+
+#endif
+  
+
+  
+  
+
+
+  
diff --git a/src/tftp.c b/src/tftp.c
new file mode 100644 (file)
index 0000000..789c444
--- /dev/null
@@ -0,0 +1,711 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+     
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_TFTP
+
+static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special);
+static void free_transfer(struct tftp_transfer *transfer);
+static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
+static ssize_t tftp_err_oops(char *packet, char *file);
+static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
+static char *next(char **p, char *end);
+
+#define OP_RRQ  1
+#define OP_WRQ  2
+#define OP_DATA 3
+#define OP_ACK  4
+#define OP_ERR  5
+#define OP_OACK 6
+
+#define ERR_NOTDEF 0
+#define ERR_FNF    1
+#define ERR_PERM   2
+#define ERR_FULL   3
+#define ERR_ILL    4
+
+void tftp_request(struct listener *listen, time_t now)
+{
+  ssize_t len;
+  char *packet = daemon->packet;
+  char *filename, *mode, *p, *end, *opt;
+  union mysockaddr addr, peer;
+  struct msghdr msg;
+  struct iovec iov;
+  struct ifreq ifr;
+  int is_err = 1, if_index = 0, mtu = 0, special = 0;
+#ifdef HAVE_DHCP
+  struct iname *tmp;
+#endif
+  struct tftp_transfer *transfer;
+  int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+  int mtuflag = IP_PMTUDISC_DONT;
+#endif
+  char namebuff[IF_NAMESIZE];
+  char pretty_addr[ADDRSTRLEN];
+  char *name;
+  char *prefix = daemon->tftp_prefix;
+  struct tftp_prefix *pref;
+  struct interface_list *ir;
+
+  union {
+    struct cmsghdr align; /* this ensures alignment */
+#ifdef HAVE_IPV6
+    char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+#endif
+#if defined(HAVE_LINUX_NETWORK)
+    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
+#elif defined(HAVE_SOLARIS_NETWORK)
+    char control[CMSG_SPACE(sizeof(unsigned int))];
+#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+    char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
+#endif
+  } control_u; 
+
+  msg.msg_controllen = sizeof(control_u);
+  msg.msg_control = control_u.control;
+  msg.msg_flags = 0;
+  msg.msg_name = &peer;
+  msg.msg_namelen = sizeof(peer);
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+
+  iov.iov_base = packet;
+  iov.iov_len = daemon->packet_buff_sz;
+
+  /* we overwrote the buffer... */
+  daemon->srv_save = NULL;
+
+  if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
+    return;
+  
+  if (option_bool(OPT_NOWILD))
+    {
+      addr = listen->iface->addr;
+      mtu = listen->iface->mtu;
+      name = listen->iface->name;
+    }
+  else
+    {
+      struct cmsghdr *cmptr;
+      int check;
+      struct interface_list *ir;
+
+      if (msg.msg_controllen < sizeof(struct cmsghdr))
+        return;
+      
+      addr.sa.sa_family = listen->family;
+      
+#if defined(HAVE_LINUX_NETWORK)
+      if (listen->family == AF_INET)
+       for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+         if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
+           {
+             union {
+               unsigned char *c;
+               struct in_pktinfo *p;
+             } p;
+             p.c = CMSG_DATA(cmptr);
+             addr.in.sin_addr = p.p->ipi_spec_dst;
+             if_index = p.p->ipi_ifindex;
+           }
+      
+#elif defined(HAVE_SOLARIS_NETWORK)
+      if (listen->family == AF_INET)
+       for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+         {
+           union {
+             unsigned char *c;
+             struct in_addr *a;
+             unsigned int *i;
+           } p;
+           p.c = CMSG_DATA(cmptr);
+           if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
+           addr.in.sin_addr = *(p.a);
+           else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+           if_index = *(p.i);
+         }
+      
+#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+      if (listen->family == AF_INET)
+       for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+         {
+           union {
+             unsigned char *c;
+             struct in_addr *a;
+             struct sockaddr_dl *s;
+           } p;
+           p.c = CMSG_DATA(cmptr);
+           if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
+             addr.in.sin_addr = *(p.a);
+           else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+             if_index = p.s->sdl_index;
+         }
+         
+#endif
+
+#ifdef HAVE_IPV6
+      if (listen->family == AF_INET6)
+        {
+          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+            if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == daemon->v6pktinfo)
+              {
+                union {
+                  unsigned char *c;
+                  struct in6_pktinfo *p;
+                } p;
+                p.c = CMSG_DATA(cmptr);
+                  
+                addr.in6.sin6_addr = p.p->ipi6_addr;
+                if_index = p.p->ipi6_ifindex;
+              }
+        }
+#endif
+      
+      if (!indextoname(listen->tftpfd, if_index, namebuff))
+       return;
+
+      name = namebuff;
+
+#ifdef HAVE_IPV6
+      if (listen->family == AF_INET6)
+       check = iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name, &if_index);
+      else
+#endif
+        check = iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name, &if_index);
+
+      /* wierd TFTP service override */
+      for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
+       if (strcmp(ir->interface, name) == 0)
+         break;
+       
+      if (!ir)
+       {
+         if (!daemon->tftp_unlimited || !check)
+           return;
+         
+#ifdef HAVE_DHCP      
+         /* allowed interfaces are the same as for DHCP */
+         for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+           if (tmp->name && (strcmp(tmp->name, name) == 0))
+             return;
+#endif
+       }
+
+      strncpy(ifr.ifr_name, name, IF_NAMESIZE);
+      if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
+       mtu = ifr.ifr_mtu;      
+    }
+  
+  /* check for per-interface prefix */ 
+  for (pref = daemon->if_prefix; pref; pref = pref->next)
+    if (strcmp(pref->interface, name) == 0)
+      prefix = pref->prefix;
+
+  /* wierd TFTP interfaces disable special options. */
+  for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
+    if (strcmp(ir->interface, name) == 0)
+      special = 1;
+
+#ifdef HAVE_SOCKADDR_SA_LEN
+  addr.sa.sa_len = sa_len(&addr);
+#endif
+
+  if (listen->family == AF_INET)
+    addr.in.sin_port = htons(port);
+#ifdef HAVE_IPV6
+  else
+    {
+      addr.in6.sin6_port = htons(port);
+      addr.in6.sin6_flowinfo = 0;
+    }
+#endif
+
+  if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
+    return;
+  
+  if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1)
+    {
+      free(transfer);
+      return;
+    }
+  
+  transfer->peer = peer;
+  transfer->timeout = now + 2;
+  transfer->backoff = 1;
+  transfer->block = 1;
+  transfer->blocksize = 512;
+  transfer->offset = 0;
+  transfer->file = NULL;
+  transfer->opt_blocksize = transfer->opt_transize = 0;
+  transfer->netascii = transfer->carrylf = 0;
+  prettyprint_addr(&peer, pretty_addr);
+  
+  /* if we have a nailed-down range, iterate until we find a free one. */
+  while (1)
+    {
+      if (bind(transfer->sockfd, &addr.sa, sizeof(addr)) == -1 ||
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+         setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
+#endif
+         !fix_fd(transfer->sockfd))
+       {
+         if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
+           {
+             if (++port <= daemon->end_tftp_port)
+               { 
+                 if (listen->family == AF_INET)
+                   addr.in.sin_port = htons(port);
+#ifdef HAVE_IPV6
+                 else
+                    addr.in6.sin6_port = htons(port);
+#endif
+                 continue;
+               }
+             my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
+           }
+         free_transfer(transfer);
+         return;
+       }
+      break;
+    }
+  
+  p = packet + 2;
+  end = packet + len;
+
+  if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
+      !(filename = next(&p, end)) ||
+      !(mode = next(&p, end)) ||
+      (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
+    len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), pretty_addr);
+  else
+    {
+      if (strcasecmp(mode, "netascii") == 0)
+       transfer->netascii = 1;
+      
+      while ((opt = next(&p, end)))
+       {
+         if (strcasecmp(opt, "blksize") == 0)
+           {
+             if ((opt = next(&p, end)) &&
+                 (special || !option_bool(OPT_TFTP_NOBLOCK)))
+               {
+                 transfer->blocksize = atoi(opt);
+                 if (transfer->blocksize < 1)
+                   transfer->blocksize = 1;
+                 if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
+                   transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
+                 /* 32 bytes for IP, UDP and TFTP headers */
+                 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
+                   transfer->blocksize = (unsigned)mtu - 32;
+                 transfer->opt_blocksize = 1;
+                 transfer->block = 0;
+               }
+           }
+         else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
+           {
+             transfer->opt_transize = 1;
+             transfer->block = 0;
+           }
+       }
+
+      /* cope with backslashes from windows boxen. */
+      while ((p = strchr(filename, '\\')))
+       *p = '/';
+
+      strcpy(daemon->namebuff, "/");
+      if (prefix)
+       {
+         if (prefix[0] == '/')
+           daemon->namebuff[0] = 0;
+         strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
+         if (prefix[strlen(prefix)-1] != '/')
+           strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
+
+         if (!special && option_bool(OPT_TFTP_APREF))
+           {
+             size_t oldlen = strlen(daemon->namebuff);
+             struct stat statbuf;
+             
+             strncat(daemon->namebuff, pretty_addr, (MAXDNAME-1) - strlen(daemon->namebuff));
+             strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
+             
+             /* remove unique-directory if it doesn't exist */
+             if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
+               daemon->namebuff[oldlen] = 0;
+           }
+               
+         /* Absolute pathnames OK if they match prefix */
+         if (filename[0] == '/')
+           {
+             if (strstr(filename, daemon->namebuff) == filename)
+               daemon->namebuff[0] = 0;
+             else
+               filename++;
+           }
+       }
+      else if (filename[0] == '/')
+       daemon->namebuff[0] = 0;
+      strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
+
+      /* check permissions and open file */
+      if ((transfer->file = check_tftp_fileperm(&len, prefix, special)))
+       {
+         if ((len = get_block(packet, transfer)) == -1)
+           len = tftp_err_oops(packet, daemon->namebuff);
+         else
+           is_err = 0;
+       }
+    }
+  
+  while (sendto(transfer->sockfd, packet, len, 0, 
+               (struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR);
+  
+  if (is_err)
+    free_transfer(transfer);
+  else
+    {
+      transfer->next = daemon->tftp_trans;
+      daemon->tftp_trans = transfer;
+    }
+}
+static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special)
+{
+  char *packet = daemon->packet, *namebuff = daemon->namebuff;
+  struct tftp_file *file;
+  struct tftp_transfer *t;
+  uid_t uid = geteuid();
+  struct stat statbuf;
+  int fd = -1;
+
+  /* trick to ban moving out of the subtree */
+  if (prefix && strstr(namebuff, "/../"))
+    goto perm;
+  
+  if ((fd = open(namebuff, O_RDONLY)) == -1)
+    {
+      if (errno == ENOENT)
+       {
+         *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
+         return NULL;
+       }
+      else if (errno == EACCES)
+       goto perm;
+      else
+       goto oops;
+    }
+  
+  /* stat the file descriptor to avoid stat->open races */
+  if (fstat(fd, &statbuf) == -1)
+    goto oops;
+  
+  /* running as root, must be world-readable */
+  if (uid == 0)
+    {
+      if (!(statbuf.st_mode & S_IROTH))
+       goto perm;
+    }
+  /* in secure mode, must be owned by user running dnsmasq */
+  else if (!special && option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
+    goto perm;
+      
+  /* If we're doing many tranfers from the same file, only 
+     open it once this saves lots of file descriptors 
+     when mass-booting a big cluster, for instance. 
+     Be conservative and only share when inode and name match
+     this keeps error messages sane. */
+  for (t = daemon->tftp_trans; t; t = t->next)
+    if (t->file->dev == statbuf.st_dev && 
+       t->file->inode == statbuf.st_ino &&
+       strcmp(t->file->filename, namebuff) == 0)
+      {
+       close(fd);
+       t->file->refcount++;
+       return t->file;
+      }
+  
+  if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
+    {
+      errno = ENOMEM;
+      goto oops;
+    }
+
+  file->fd = fd;
+  file->size = statbuf.st_size;
+  file->dev = statbuf.st_dev;
+  file->inode = statbuf.st_ino;
+  file->refcount = 1;
+  strcpy(file->filename, namebuff);
+  return file;
+  
+ perm:
+  errno = EACCES;
+  *len =  tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
+  if (fd != -1)
+    close(fd);
+  return NULL;
+
+ oops:
+  *len =  tftp_err_oops(packet, namebuff);
+  if (fd != -1)
+    close(fd);
+  return NULL;
+}
+
+void check_tftp_listeners(fd_set *rset, time_t now)
+{
+  struct tftp_transfer *transfer, *tmp, **up;
+  ssize_t len;
+  char pretty_addr[ADDRSTRLEN];
+  
+  struct ack {
+    unsigned short op, block;
+  } *mess = (struct ack *)daemon->packet;
+  
+  /* Check for activity on any existing transfers */
+  for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
+    {
+      tmp = transfer->next;
+      
+      if (FD_ISSET(transfer->sockfd, rset))
+       {
+         /* we overwrote the buffer... */
+         daemon->srv_save = NULL;
+          
+         prettyprint_addr(&transfer->peer, pretty_addr);
+         
+         if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
+           {
+             if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block) 
+               {
+                 /* Got ack, ensure we take the (re)transmit path */
+                 transfer->timeout = now;
+                 transfer->backoff = 0;
+                 if (transfer->block++ != 0)
+                   transfer->offset += transfer->blocksize - transfer->expansion;
+               }
+             else if (ntohs(mess->op) == OP_ERR)
+               {
+                 char *p = daemon->packet + sizeof(struct ack);
+                 char *end = daemon->packet + len;
+                 char *err = next(&p, end);
+                 
+                 /* Sanitise error message */
+                 if (!err)
+                   err = "";
+                 else
+                   {
+                     unsigned char *q, *r;
+                     for (q = r = (unsigned char *)err; *r; r++)
+                       if (isprint(*r))
+                         *(q++) = *r;
+                     *q = 0;
+                   }
+
+                 my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
+                           (int)ntohs(mess->block), err, 
+                           pretty_addr);       
+                 
+                 /* Got err, ensure we take abort */
+                 transfer->timeout = now;
+                 transfer->backoff = 100;
+               }
+           }
+       }
+      
+      if (difftime(now, transfer->timeout) >= 0.0)
+       {
+         int endcon = 0;
+
+         /* timeout, retransmit */
+         transfer->timeout += 1 + (1<<transfer->backoff);
+                 
+         /* we overwrote the buffer... */
+         daemon->srv_save = NULL;
+        
+         if ((len = get_block(daemon->packet, transfer)) == -1)
+           {
+             len = tftp_err_oops(daemon->packet, transfer->file->filename);
+             endcon = 1;
+           }
+         else if (++transfer->backoff > 5)
+           {
+             /* don't complain about timeout when we're awaiting the last
+                ACK, some clients never send it */
+             if (len != 0)
+               {
+                 my_syslog(MS_TFTP | LOG_ERR, _("failed sending %s to %s"), 
+                           transfer->file->filename, pretty_addr);
+                 len = 0;
+                 endcon = 1;
+               }
+           }
+         
+         if (len != 0)
+           while(sendto(transfer->sockfd, daemon->packet, len, 0, 
+                        (struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR);
+         
+         if (endcon || len == 0)
+           {
+             if (!endcon)
+               my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, pretty_addr);
+             /* unlink */
+             *up = tmp;
+             free_transfer(transfer);
+             continue;
+           }
+       }
+
+      up = &transfer->next;
+    }    
+}
+
+static void free_transfer(struct tftp_transfer *transfer)
+{
+  close(transfer->sockfd);
+  if (transfer->file && (--transfer->file->refcount) == 0)
+    {
+      close(transfer->file->fd);
+      free(transfer->file);
+    }
+  free(transfer);
+}
+
+static char *next(char **p, char *end)
+{
+  char *ret = *p;
+  size_t len;
+
+  if (*(end-1) != 0 || 
+      *p == end ||
+      (len = strlen(ret)) == 0)
+    return NULL;
+
+  *p += len + 1;
+  return ret;
+}
+
+static ssize_t tftp_err(int err, char *packet, char *message, char *file)
+{
+  struct errmess {
+    unsigned short op, err;
+    char message[];
+  } *mess = (struct errmess *)packet;
+  ssize_t ret = 4;
+  char *errstr = strerror(errno);
+  mess->op = htons(OP_ERR);
+  mess->err = htons(err);
+  ret += (snprintf(mess->message, 500,  message, file, errstr) + 1);
+  my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
+  
+  return  ret;
+}
+
+static ssize_t tftp_err_oops(char *packet, char *file)
+{
+  return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file);
+}
+
+/* return -1 for error, zero for done. */
+static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
+{
+  if (transfer->block == 0)
+    {
+      /* send OACK */
+      char *p;
+      struct oackmess {
+       unsigned short op;
+       char data[];
+      } *mess = (struct oackmess *)packet;
+      
+      p = mess->data;
+      mess->op = htons(OP_OACK);
+      if (transfer->opt_blocksize)
+       {
+         p += (sprintf(p, "blksize") + 1);
+         p += (sprintf(p, "%d", transfer->blocksize) + 1);
+       }
+      if (transfer->opt_transize)
+       {
+         p += (sprintf(p,"tsize") + 1);
+         p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
+       }
+
+      return p - packet;
+    }
+  else
+    {
+      /* send data packet */
+      struct datamess {
+       unsigned short op, block;
+       unsigned char data[];
+      } *mess = (struct datamess *)packet;
+      
+      size_t size = transfer->file->size - transfer->offset; 
+      
+      if (transfer->offset > transfer->file->size)
+       return 0; /* finished */
+      
+      if (size > transfer->blocksize)
+       size = transfer->blocksize;
+      
+      mess->op = htons(OP_DATA);
+      mess->block = htons((unsigned short)(transfer->block));
+      
+      if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
+         !read_write(transfer->file->fd, mess->data, size, 1))
+       return -1;
+      
+      transfer->expansion = 0;
+      
+      /* Map '\n' to CR-LF in netascii mode */
+      if (transfer->netascii)
+       {
+         size_t i;
+         int newcarrylf;
+
+         for (i = 0, newcarrylf = 0; i < size; i++)
+           if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
+             {
+               if (size == transfer->blocksize)
+                 {
+                   transfer->expansion++;
+                   if (i == size - 1)
+                     newcarrylf = 1; /* don't expand LF again if it moves to the next block */
+                 }
+               else
+                 size++; /* room in this block */
+             
+               /* make space and insert CR */
+               memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
+               mess->data[i] = '\r';
+               
+               i++;
+             }
+         transfer->carrylf = newcarrylf;
+         
+       }
+
+      return size + 4;
+    }
+}
+
+#endif
diff --git a/src/util.c b/src/util.c
new file mode 100644 (file)
index 0000000..e64f1a6
--- /dev/null
@@ -0,0 +1,516 @@
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+      
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* The SURF random number generator was taken from djbdns-1.05, by 
+   Daniel J Bernstein, which is public domain. */
+
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_BROKEN_RTC
+#include <sys/times.h>
+#endif
+
+#if defined(LOCALEDIR) || defined(HAVE_IDN)
+#include <idna.h>
+#endif
+
+#ifdef HAVE_ARC4RANDOM
+void rand_init(void)
+{
+  return;
+}
+
+unsigned short rand16(void)
+{
+   return (unsigned short) (arc4random() >> 15);
+}
+
+#else
+
+/* SURF random number generator */
+
+static u32 seed[32];
+static u32 in[12];
+static u32 out[8];
+
+void rand_init()
+{
+  int fd = open(RANDFILE, O_RDONLY);
+  
+  if (fd == -1 ||
+      !read_write(fd, (unsigned char *)&seed, sizeof(seed), 1) ||
+      !read_write(fd, (unsigned char *)&in, sizeof(in), 1))
+    die(_("failed to seed the random number generator: %s"), NULL, EC_MISC);
+  
+  close(fd);
+}
+
+#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
+#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
+
+static void surf(void)
+{
+  u32 t[12]; u32 x; u32 sum = 0;
+  int r; int i; int loop;
+
+  for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
+  for (i = 0;i < 8;++i) out[i] = seed[24 + i];
+  x = t[11];
+  for (loop = 0;loop < 2;++loop) {
+    for (r = 0;r < 16;++r) {
+      sum += 0x9e3779b9;
+      MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
+      MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
+      MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
+    }
+    for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
+  }
+}
+
+unsigned short rand16(void)
+{
+  static int outleft = 0;
+
+  if (!outleft) {
+    if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
+    surf();
+    outleft = 8;
+  }
+
+  return (unsigned short) out[--outleft];
+}
+
+#endif
+
+static int check_name(char *in)
+{
+  /* remove trailing . 
+     also fail empty string and label > 63 chars */
+  size_t dotgap = 0, l = strlen(in);
+  char c;
+  int nowhite = 0;
+  
+  if (l == 0 || l > MAXDNAME) return 0;
+  
+  if (in[l-1] == '.')
+    {
+      if (l == 1) return 0;
+      in[l-1] = 0;
+    }
+  
+  for (; (c = *in); in++)
+    {
+      if (c == '.')
+       dotgap = 0;
+      else if (++dotgap > MAXLABEL)
+       return 0;
+      else if (isascii((unsigned char)c) && iscntrl((unsigned char)c)) 
+       /* iscntrl only gives expected results for ascii */
+       return 0;
+#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
+      else if (!isascii((unsigned char)c))
+       return 0;
+#endif
+      else if (c != ' ')
+       nowhite = 1;
+    }
+
+  if (!nowhite)
+    return 0;
+
+  return 1;
+}
+
+/* Hostnames have a more limited valid charset than domain names
+   so check for legal char a-z A-Z 0-9 - _ 
+   Note that this may receive a FQDN, so only check the first label 
+   for the tighter criteria. */
+int legal_hostname(char *name)
+{
+  char c;
+
+  if (!check_name(name))
+    return 0;
+
+  for (; (c = *name); name++)
+    /* check for legal char a-z A-Z 0-9 - _ . */
+    {
+      if ((c >= 'A' && c <= 'Z') ||
+         (c >= 'a' && c <= 'z') ||
+         (c >= '0' && c <= '9') ||
+         c == '-' || c == '_')
+       continue;
+      
+      /* end of hostname part */
+      if (c == '.')
+       return 1;
+      
+      return 0;
+    }
+  
+  return 1;
+}
+  
+char *canonicalise(char *in, int *nomem)
+{
+  char *ret = NULL;
+#if defined(LOCALEDIR) || defined(HAVE_IDN)
+  int rc;
+#endif
+
+  if (nomem)
+    *nomem = 0;
+  
+  if (!check_name(in))
+    return NULL;
+  
+#if defined(LOCALEDIR) || defined(HAVE_IDN)
+  if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
+    {
+      if (ret)
+       free(ret);
+
+      if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
+       {
+         my_syslog(LOG_ERR, _("failed to allocate memory"));
+         *nomem = 1;
+       }
+    
+      return NULL;
+    }
+#else
+  if ((ret = whine_malloc(strlen(in)+1)))
+    strcpy(ret, in);
+  else if (nomem)
+    *nomem = 1;    
+#endif
+
+  return ret;
+}
+
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
+{
+  int j;
+  
+  while (sval && *sval)
+    {
+      unsigned char *cp = p++;
+      for (j = 0; *sval && (*sval != '.'); sval++, j++)
+       *p++ = *sval;
+      *cp  = j;
+      if (*sval)
+       sval++;
+    }
+  return p;
+}
+
+/* for use during startup */
+void *safe_malloc(size_t size)
+{
+  void *ret = malloc(size);
+  
+  if (!ret)
+    die(_("could not get memory"), NULL, EC_NOMEM);
+     
+  return ret;
+}    
+
+void safe_pipe(int *fd, int read_noblock)
+{
+  if (pipe(fd) == -1 || 
+      !fix_fd(fd[1]) ||
+      (read_noblock && !fix_fd(fd[0])))
+    die(_("cannot create pipe: %s"), NULL, EC_MISC);
+}
+
+void *whine_malloc(size_t size)
+{
+  void *ret = malloc(size);
+
+  if (!ret)
+    my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
+
+  return ret;
+}
+
+int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
+{
+  if (s1->sa.sa_family == s2->sa.sa_family)
+    { 
+      if (s1->sa.sa_family == AF_INET &&
+         s1->in.sin_port == s2->in.sin_port &&
+         s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
+       return 1;
+#ifdef HAVE_IPV6      
+      if (s1->sa.sa_family == AF_INET6 &&
+         s1->in6.sin6_port == s2->in6.sin6_port &&
+         IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
+       return 1;
+#endif
+    }
+  return 0;
+}
+
+int sa_len(union mysockaddr *addr)
+{
+#ifdef HAVE_SOCKADDR_SA_LEN
+  return addr->sa.sa_len;
+#else
+#ifdef HAVE_IPV6
+  if (addr->sa.sa_family == AF_INET6)
+    return sizeof(addr->in6);
+  else
+#endif
+    return sizeof(addr->in); 
+#endif
+}
+
+/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
+int hostname_isequal(char *a, char *b)
+{
+  unsigned int c1, c2;
+  
+  do {
+    c1 = (unsigned char) *a++;
+    c2 = (unsigned char) *b++;
+    
+    if (c1 >= 'A' && c1 <= 'Z')
+      c1 += 'a' - 'A';
+    if (c2 >= 'A' && c2 <= 'Z')
+      c2 += 'a' - 'A';
+    
+    if (c1 != c2)
+      return 0;
+  } while (c1);
+  
+  return 1;
+}
+    
+time_t dnsmasq_time(void)
+{
+#ifdef HAVE_BROKEN_RTC
+  struct tms dummy;
+  static long tps = 0;
+
+  if (tps == 0)
+    tps = sysconf(_SC_CLK_TCK);
+
+  return (time_t)(times(&dummy)/tps);
+#else
+  return time(NULL);
+#endif
+}
+
+int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
+{
+  return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
+} 
+
+/* returns port number from address */
+int prettyprint_addr(union mysockaddr *addr, char *buf)
+{
+  int port = 0;
+  
+#ifdef HAVE_IPV6
+  if (addr->sa.sa_family == AF_INET)
+    {
+      inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
+      port = ntohs(addr->in.sin_port);
+    }
+  else if (addr->sa.sa_family == AF_INET6)
+    {
+      inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN);
+      port = ntohs(addr->in6.sin6_port);
+    }
+#else
+  strcpy(buf, inet_ntoa(addr->in.sin_addr));
+  port = ntohs(addr->in.sin_port); 
+#endif
+  
+  return port;
+}
+
+void prettyprint_time(char *buf, unsigned int t)
+{
+  if (t == 0xffffffff)
+    sprintf(buf, _("infinite"));
+  else
+    {
+      unsigned int x, p = 0;
+       if ((x = t/86400))
+       p += sprintf(&buf[p], "%dd", x);
+       if ((x = (t/3600)%24))
+       p += sprintf(&buf[p], "%dh", x);
+      if ((x = (t/60)%60))
+       p += sprintf(&buf[p], "%dm", x);
+      if ((x = t%60))
+       p += sprintf(&buf[p], "%ds", x);
+    }
+}
+
+
+/* in may equal out, when maxlen may be -1 (No max len). 
+   Return -1 for extraneous no-hex chars found. */
+int parse_hex(char *in, unsigned char *out, int maxlen, 
+             unsigned int *wildcard_mask, int *mac_type)
+{
+  int mask = 0, i = 0;
+  char *r;
+    
+  if (mac_type)
+    *mac_type = 0;
+  
+  while (maxlen == -1 || i < maxlen)
+    {
+      for (r = in; *r != 0 && *r != ':' && *r != '-'; r++)
+       if (*r != '*' && !isxdigit((unsigned char)*r))
+         return -1;
+      
+      if (*r == 0)
+       maxlen = i;
+      
+      if (r != in )
+       {
+         if (*r == '-' && i == 0 && mac_type)
+          {
+             *r = 0;
+             *mac_type = strtol(in, NULL, 16);
+             mac_type = NULL;
+          }
+         else
+           {
+             *r = 0;
+             mask = mask << 1;
+             if (strcmp(in, "*") == 0)
+               mask |= 1;
+             else
+               out[i] = strtol(in, NULL, 16);
+             i++;
+           }
+       }
+      in = r+1;
+    }
+  
+  if (wildcard_mask)
+    *wildcard_mask = mask;
+
+  return i;
+}
+
+/* return 0 for no match, or (no matched octets) + 1 */
+int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
+{
+  int i, count;
+  for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1)
+    if (!(mask & 1))
+      {
+       if (a[i] == b[i])
+         count++;
+       else
+         return 0;
+      }
+  return count;
+}
+
+/* _note_ may copy buffer */
+int expand_buf(struct iovec *iov, size_t size)
+{
+  void *new;
+
+  if (size <= (size_t)iov->iov_len)
+    return 1;
+
+  if (!(new = whine_malloc(size)))
+    {
+      errno = ENOMEM;
+      return 0;
+    }
+
+  if (iov->iov_base)
+    {
+      memcpy(new, iov->iov_base, iov->iov_len);
+      free(iov->iov_base);
+    }
+
+  iov->iov_base = new;
+  iov->iov_len = size;
+
+  return 1;
+}
+
+char *print_mac(char *buff, unsigned char *mac, int len)
+{
+  char *p = buff;
+  int i;
+   
+  if (len == 0)
+    sprintf(p, "<null>");
+  else
+    for (i = 0; i < len; i++)
+      p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
+  
+  return buff;
+}
+
+void bump_maxfd(int fd, int *max)
+{
+  if (fd > *max)
+    *max = fd;
+}
+
+int retry_send(void)
+{
+   struct timespec waiter;
+   if (errno == EAGAIN)
+     {
+       waiter.tv_sec = 0;
+       waiter.tv_nsec = 10000;
+       nanosleep(&waiter, NULL);
+       return 1;
+     }
+   
+   if (errno == EINTR)
+     return 1;
+
+   return 0;
+}
+
+int read_write(int fd, unsigned char *packet, int size, int rw)
+{
+  ssize_t n, done;
+  
+  for (done = 0; done < size; done += n)
+    {
+    retry:
+      if (rw)
+        n = read(fd, &packet[done], (size_t)(size - done));
+      else
+        n = write(fd, &packet[done], (size_t)(size - done));
+
+      if (n == 0)
+        return 0;
+      else if (n == -1)
+        {
+          if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
+            goto retry;
+          else
+            return 0;
+        }
+    }
+  return 1;
+}
+