summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xCHANGELOG438
-rwxr-xr-xCHANGELOG.archive2509
-rwxr-xr-xCOPYING340
-rwxr-xr-xCOPYING-v3674
-rwxr-xr-xFAQ471
-rwxr-xr-xMakefile78
-rwxr-xr-xbld/Makefile17
-rwxr-xr-xbld/install-man9
-rwxr-xr-xbld/install-mo9
-rwxr-xr-xbld/pkg-wrapper11
-rwxr-xr-xcontrib/Solaris10/README28
-rwxr-xr-xcontrib/Solaris10/dnsmasq.xml65
-rwxr-xr-xcontrib/Suse/README6
-rwxr-xr-xcontrib/Suse/README.susefirewall27
-rwxr-xr-xcontrib/Suse/dnsmasq-SuSE.patch23
-rwxr-xr-xcontrib/Suse/dnsmasq-suse.spec111
-rwxr-xr-xcontrib/Suse/rc.dnsmasq-suse79
-rwxr-xr-xcontrib/dns-loc/README12
-rwxr-xr-xcontrib/dns-loc/dnsmasq2-loc-rfc1876.patch522
-rwxr-xr-xcontrib/dnslist/dhcp.css57
-rwxr-xr-xcontrib/dnslist/dnslist.pl608
-rwxr-xr-xcontrib/dnslist/dnslist.tt232
-rwxr-xr-xcontrib/dnsmasq_MacOSX/DNSmasq22
-rwxr-xr-xcontrib/dnsmasq_MacOSX/README.rtf42
-rwxr-xr-xcontrib/dnsmasq_MacOSX/StartupParameters.plist18
-rwxr-xr-xcontrib/dynamic-dnsmasq/dynamic-dnsmasq.pl249
-rwxr-xr-xcontrib/lease-access/README20
-rwxr-xr-xcontrib/lease-access/lease.access.patch578
-rwxr-xr-xcontrib/openvpn/README44
-rwxr-xr-xcontrib/openvpn/dhclient-enter-hooks30
-rwxr-xr-xcontrib/openvpn/dnsmasq.patch61
-rwxr-xr-xcontrib/port-forward/dnsmasq-portforward68
-rwxr-xr-xcontrib/port-forward/portforward28
-rwxr-xr-xcontrib/slackware-dnsmasq/dnsmasq.SlackBuild56
-rwxr-xr-xcontrib/slackware-dnsmasq/dnsmasq.leasedir.diff.gzbin0 -> 435 bytes
-rwxr-xr-xcontrib/slackware-dnsmasq/doinst.sh.gzbin0 -> 302 bytes
-rwxr-xr-xcontrib/slackware-dnsmasq/rc.dnsmasq.gzbin0 -> 265 bytes
-rwxr-xr-xcontrib/slackware-dnsmasq/slack-desc19
-rwxr-xr-xcontrib/try-all-ns/README19
-rwxr-xr-xcontrib/try-all-ns/README-2.4711
-rwxr-xr-xcontrib/try-all-ns/dnsmasq-2.35-try-all-ns.patch61
-rwxr-xr-xcontrib/try-all-ns/dnsmasq-2.47_no_nxdomain_until_end.patch17
-rwxr-xr-xcontrib/webmin/README54
-rwxr-xr-xcontrib/webmin/dnsmasq.wbmbin0 -> 174080 bytes
-rwxr-xr-xcontrib/wrt/Makefile6
-rwxr-xr-xcontrib/wrt/README81
-rwxr-xr-xcontrib/wrt/dhcp_lease_time.c214
-rwxr-xr-xcontrib/wrt/dhcp_release.c331
-rwxr-xr-xcontrib/wrt/lease_update.sh54
-rwxr-xr-xdbus/DBus-interface131
-rwxr-xr-xdbus/dnsmasq.conf14
-rwxr-xr-xdnsmasq.conf.example540
-rwxr-xr-xdoc.html113
-rwxr-xr-xman/dnsmasq.81290
-rwxr-xr-xman/es/dnsmasq.81310
-rwxr-xr-xman/fr/dnsmasq.81449
-rwxr-xr-xpo/de.po1462
-rwxr-xr-xpo/es.po1500
-rwxr-xr-xpo/fi.po1411
-rwxr-xr-xpo/fr.po1504
-rwxr-xr-xpo/id.po1727
-rwxr-xr-xpo/it.po1411
-rwxr-xr-xpo/no.po1508
-rwxr-xr-xpo/pl.po1420
-rwxr-xr-xpo/pt_BR.po1411
-rwxr-xr-xpo/ro.po1503
-rwxr-xr-xsetup.html231
-rwxr-xr-xsrc/bpf.c254
-rwxr-xr-xsrc/cache.c1317
-rwxr-xr-xsrc/config.h293
-rwxr-xr-xsrc/dbus.c436
-rwxr-xr-xsrc/dhcp.c1002
-rwxr-xr-xsrc/dnsmasq.c1287
-rwxr-xr-xsrc/dnsmasq.h885
-rwxr-xr-xsrc/forward.c1094
-rwxr-xr-xsrc/helper.c428
-rwxr-xr-xsrc/lease.c622
-rwxr-xr-xsrc/log.c419
-rwxr-xr-xsrc/netlink.c303
-rwxr-xr-xsrc/network.c874
-rwxr-xr-xsrc/option.c2990
-rwxr-xr-xsrc/rfc1035.c1604
-rwxr-xr-xsrc/rfc2131.c2332
-rwxr-xr-xsrc/tftp.c600
-rwxr-xr-xsrc/util.c514
85 files changed, 45398 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100755
index 0000000..89209d5
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,438 @@
+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 100755
index 0000000..c9973cc
--- /dev/null
+++ b/CHANGELOG.archive
@@ -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/COPYING b/COPYING
new file mode 100755
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.
+
+ 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) 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 100755
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING-v3
@@ -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 100755
index 0000000..b51c31e
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,471 @@
+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.68.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 Suse?
+
+A: Dnsmasq is in Suse itself, and the latest releases are also
+ available at ftp://ftp.suse.com/pub/people/ug/
+
+
+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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..3d07c24
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,78 @@
+# dnsmasq is Copyright (c) 2000-2009 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
+
+SRC = src
+PO = po
+MAN = man
+
+PKG_CONFIG = pkg-config
+INSTALL = install
+MSGMERGE = msgmerge
+MSGFMT = msgfmt
+XGETTEXT = xgettext
+
+#################################################################
+
+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`
+SUNOS_LIBS= `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi`
+
+all : dnsmasq
+
+dnsmasq :
+ @cd $(SRC) && $(MAKE) \
+ DNSMASQ_CFLAGS="$(DNSMASQ_CFLAGS)" \
+ DNSMASQ_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS)" \
+ -f ../bld/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)\"' \
+ DNSMASQ_CFLAGS="$(DNSMASQ_CFLAGS) `$(PKG_CONFIG) --cflags libidn`" \
+ DNSMASQ_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS) `$(PKG_CONFIG) --libs libidn`" \
+ -f ../bld/Makefile dnsmasq
+ @cd $(PO); for f in *.po; do \
+ cd ../$(SRC) && $(MAKE) \
+ MSGMERGE=$(MSGMERGE) MSGFMT=$(MSGFMT) XGETTEXT=$(XGETTEXT) \
+ -f ../bld/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) XGETTEXT=$(XGETTEXT) -f ../bld/Makefile dnsmasq.pot
+ @cd $(PO); for f in *.po; do \
+ echo -n msgmerge $$f && $(MSGMERGE) --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \
+ done
+
+
diff --git a/bld/Makefile b/bld/Makefile
new file mode 100755
index 0000000..53dab34
--- /dev/null
+++ b/bld/Makefile
@@ -0,0 +1,17 @@
+CFLAGS = -Wall -W -O2
+
+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
+
+.c.o:
+ $(CC) $(CFLAGS) $(COPTS) $(I18N) $(DNSMASQ_CFLAGS) $(RPM_OPT_FLAGS) -c $<
+
+dnsmasq : $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(DNSMASQ_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 -
diff --git a/bld/install-man b/bld/install-man
new file mode 100755
index 0000000..f4cf3dc
--- /dev/null
+++ b/bld/install-man
@@ -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
index 0000000..d11fa9f
--- /dev/null
+++ b/bld/install-mo
@@ -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
index 0000000..4f3b76b
--- /dev/null
+++ b/bld/pkg-wrapper
@@ -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/Solaris10/README b/contrib/Solaris10/README
new file mode 100755
index 0000000..a035875
--- /dev/null
+++ b/contrib/Solaris10/README
@@ -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/dnsmasq.xml b/contrib/Solaris10/dnsmasq.xml
new file mode 100755
index 0000000..7da0253
--- /dev/null
+++ b/contrib/Solaris10/dnsmasq.xml
@@ -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 100755
index 0000000..3fdc186
--- /dev/null
+++ b/contrib/Suse/README
@@ -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 100755
index 0000000..2f19ca6
--- /dev/null
+++ b/contrib/Suse/README.susefirewall
@@ -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 100755
index 0000000..626245f
--- /dev/null
+++ b/contrib/Suse/dnsmasq-SuSE.patch
@@ -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 100755
index 0000000..ff8ba8f
--- /dev/null
+++ b/contrib/Suse/dnsmasq-suse.spec
@@ -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 100755
index 0000000..71f4c72
--- /dev/null
+++ b/contrib/Suse/rc.dnsmasq-suse
@@ -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 100755
index 0000000..6f43a8d
--- /dev/null
+++ b/contrib/dns-loc/README
@@ -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 100755
index 0000000..d950321
--- /dev/null
+++ b/contrib/dns-loc/dnsmasq2-loc-rfc1876.patch
@@ -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 100755
index 0000000..79cea39
--- /dev/null
+++ b/contrib/dnslist/dhcp.css
@@ -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
index 0000000..7ce2720
--- /dev/null
+++ b/contrib/dnslist/dnslist.pl
@@ -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 100755
index 0000000..1998e5f
--- /dev/null
+++ b/contrib/dnslist/dnslist.tt2
@@ -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/DNSmasq b/contrib/dnsmasq_MacOSX/DNSmasq
new file mode 100755
index 0000000..6b62118
--- /dev/null
+++ b/contrib/dnsmasq_MacOSX/DNSmasq
@@ -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/README.rtf b/contrib/dnsmasq_MacOSX/README.rtf
new file mode 100755
index 0000000..da48411
--- /dev/null
+++ b/contrib/dnsmasq_MacOSX/README.rtf
@@ -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/StartupParameters.plist b/contrib/dnsmasq_MacOSX/StartupParameters.plist
new file mode 100755
index 0000000..454bda0
--- /dev/null
+++ b/contrib/dnsmasq_MacOSX/StartupParameters.plist
@@ -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
index 0000000..3c4a1f1
--- /dev/null
+++ b/contrib/dynamic-dnsmasq/dynamic-dnsmasq.pl
@@ -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 100755
index 0000000..fc66bdf
--- /dev/null
+++ b/contrib/lease-access/README
@@ -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 100755
index 0000000..ad76e25
--- /dev/null
+++ b/contrib/lease-access/lease.access.patch
@@ -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 100755
index 0000000..dd99600
--- /dev/null
+++ b/contrib/openvpn/README
@@ -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 100755
index 0000000..cb78e2a
--- /dev/null
+++ b/contrib/openvpn/dhclient-enter-hooks
@@ -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 100755
index 0000000..5c11881
--- /dev/null
+++ b/contrib/openvpn/dnsmasq.patch
@@ -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
index 0000000..f9bb857
--- /dev/null
+++ b/contrib/port-forward/dnsmasq-portforward
@@ -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 100755
index 0000000..1a97c3a
--- /dev/null
+++ b/contrib/port-forward/portforward
@@ -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
index 0000000..c5ba083
--- /dev/null
+++ b/contrib/slackware-dnsmasq/dnsmasq.SlackBuild
@@ -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 100755
index 0000000..22fc32b
--- /dev/null
+++ b/contrib/slackware-dnsmasq/dnsmasq.leasedir.diff.gz
Binary files differ
diff --git a/contrib/slackware-dnsmasq/doinst.sh.gz b/contrib/slackware-dnsmasq/doinst.sh.gz
new file mode 100755
index 0000000..3b44227
--- /dev/null
+++ b/contrib/slackware-dnsmasq/doinst.sh.gz
Binary files differ
diff --git a/contrib/slackware-dnsmasq/rc.dnsmasq.gz b/contrib/slackware-dnsmasq/rc.dnsmasq.gz
new file mode 100755
index 0000000..a86abbb
--- /dev/null
+++ b/contrib/slackware-dnsmasq/rc.dnsmasq.gz
Binary files differ
diff --git a/contrib/slackware-dnsmasq/slack-desc b/contrib/slackware-dnsmasq/slack-desc
new file mode 100755
index 0000000..0a0c577
--- /dev/null
+++ b/contrib/slackware-dnsmasq/slack-desc
@@ -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/try-all-ns/README b/contrib/try-all-ns/README
new file mode 100755
index 0000000..224d554
--- /dev/null
+++ b/contrib/try-all-ns/README
@@ -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 100755
index 0000000..3ebec65
--- /dev/null
+++ b/contrib/try-all-ns/README-2.47
@@ -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 100755
index 0000000..ec3f3e0
--- /dev/null
+++ b/contrib/try-all-ns/dnsmasq-2.35-try-all-ns.patch
@@ -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 100755
index 0000000..7586003
--- /dev/null
+++ b/contrib/try-all-ns/dnsmasq-2.47_no_nxdomain_until_end.patch
@@ -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 100755
index 0000000..8a8f937
--- /dev/null
+++ b/contrib/webmin/README
@@ -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 100755
index 0000000..7307e23
--- /dev/null
+++ b/contrib/webmin/dnsmasq.wbm
Binary files differ
diff --git a/contrib/wrt/Makefile b/contrib/wrt/Makefile
new file mode 100755
index 0000000..68e8d32
--- /dev/null
+++ b/contrib/wrt/Makefile
@@ -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 100755
index 0000000..862046f
--- /dev/null
+++ b/contrib/wrt/README
@@ -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 100755
index 0000000..2866bb5
--- /dev/null
+++ b/contrib/wrt/dhcp_lease_time.c
@@ -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 100755
index 0000000..c66d3a0
--- /dev/null
+++ b/contrib/wrt/dhcp_release.c
@@ -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
index 0000000..46509b3
--- /dev/null
+++ b/contrib/wrt/lease_update.sh
@@ -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 100755
index 0000000..8d578ca
--- /dev/null
+++ b/dbus/DBus-interface
@@ -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 100755
index 0000000..82b1c76
--- /dev/null
+++ b/dbus/dnsmasq.conf
@@ -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/dnsmasq.conf.example b/dnsmasq.conf.example
new file mode 100755
index 0000000..ac9ef7a
--- /dev/null
+++ b/dnsmasq.conf.example
@@ -0,0 +1,540 @@
+# 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)
+# uneccessarily. If you have a dial-on-demand link they also stop
+# these requests from bringing up the link uneccessarily.
+
+# 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 doubleclick.net to a local
+# webserver.
+#address=/doubleclick.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 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 with a network-id, so that
+# some DHCP options may be set only for this network.
+#dhcp-range=red,192.168.0.50,192.168.0.150
+
+# 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 permissble to give name,adddress 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,net:red
+
+# Send extra options which are tagged as "red" to
+# any machine with ethernet address starting 11:22:33:
+#dhcp-host=11:22:33:*:*:*,net:red
+
+# Ignore any clients which are specified in dhcp-host lines
+# or /etc/ethers. Equivalent to ISC "deny unkown-clients".
+# This relies on the special "known" tag which is set when
+# a host is matched.
+#dhcp-ignore=#known
+
+# Send extra options which are tagged as "red" to any machine whose
+# DHCP vendorclass string includes the substring "Linux"
+#dhcp-vendorclass=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=red,accounts
+
+# Send extra options which are tagged as "red" to any machine whose
+# MAC address matches the pattern.
+#dhcp-mac=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 net: part must precede the option: part.
+#dhcp-option = net: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=gpxe,175 # gPXE sends a 175 option.
+#dhcp-boot=net:#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", 0
+
+# 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 availble 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 slighest 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/index.pl?/sw/dhcp/authoritative.php
+#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 289
+#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 289 (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 100755
index 0000000..18a4b24
--- /dev/null
+++ b/doc.html
@@ -0,0 +1,113 @@
+<HTML>
+<HEAD>
+<TITLE> Dnsmasq - a DNS forwarder for NAT firewalls.</TITLE>
+</HEAD>
+<BODY BGCOLOR="WHITE">
+<H1 ALIGN=center>Dnsmasq</H1>
+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/man/dnsmasq.8 b/man/dnsmasq.8
new file mode 100755
index 0000000..a5eac63
--- /dev/null
+++ b/man/dnsmasq.8
@@ -0,0 +1,1290 @@
+.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, 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 \-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. (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 1280, which is the RFC2671-recommended maximum
+for ethernet.
+.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 \-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.
+
+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, split by commas.
+.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 \-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 \-F, --dhcp-range=[[net:]network-id,]<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
+network-id is a alphanumeric label which marks this network so that
+dhcp options may be specified on a per-network basis.
+When it is prefixed with 'net:' 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.)
+.TP
+.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,net:<netid>][,<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 on the
+network being served by the DHCP server. 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. 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 net:<network-id> sets the network-id tag
+whenever this dhcp-host directive is in use. This can be used to
+selectively send DHCP options just for this host. When a host matches any
+dhcp-host directive (or one implied by /etc/ethers) then the special
+network-id tag "known" is set. This allows dnsmasq to be configured to
+ignore requests from unknown machines using
+.B --dhcp-ignore=#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=<file>
+Read DHCP host information from the specified file. 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=<file>
+Read DHCP option information from the specified file. 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=[<network-id>,[<network-id>,]][encap:<opt>,][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 network-ids are given then
+this option is only sent when all the network-ids 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 address 0.0.0.0 is not treated specially in
+encapsulated options.
+.TP
+.B --dhcp-option-force=[<network-id>,[<network-id>,]][encap:<opt>,][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=<network-id>,<vendor-class>
+Map from a vendor-class string to a network id 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=printers,Hewlett-Packard JetDirect
+will allow options to be set only for HP printers like so:
+.B --dhcp-option=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.
+.TP
+.B \-j, --dhcp-userclass=<network-id>,<user-class>
+Map from a user-class string to a network id 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=<network-id>,<MAC address>
+Map from a MAC address to a network-id tag. The MAC address may include
+wildcards. For example
+.B --dhcp-mac=3com,01:34:23:*:*:*
+will set the tag "3com" for any host whose MAC address matches the pattern.
+.TP
+.B --dhcp-circuitid=<network-id>,<circuit-id>, --dhcp-remoteid=<network-id>,<remote-id>
+Map from RFC3046 relay agent options to network-id 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 network-id tag is set.
+.TP
+.B --dhcp-subscrid=<network-id>,<subscriber-id>
+Map from RFC3993 subscriber-id relay agent options to network-id tags.
+.TP
+.B --dhcp-match=<network-id>,<option number>|option:<option name>[,<value>]
+Without a value, set the network-id 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=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.
+.TP
+.B \-J, --dhcp-ignore=<network-id>[,<network-id>]
+When all the given network-ids match the set of network-ids derived
+from the net, host, vendor and user classes, ignore the host and do
+not allocate it a DHCP lease.
+.TP
+.B --dhcp-ignore-names[=<network-id>[,<network-id>]]
+When all the given network-ids match the set of network-ids derived
+from the net, host, vendor and user classes, ignore any hostname
+provided by the host. Note that, unlike dhcp-ignore, it is permissible
+to supply no netid 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-broadcast=<network-id>[,<network-id>]
+When all the given network-ids match the set of network-ids derived
+from the net, host, vendor and user classes, always use broadcast to
+communicate with the host when it is unconfigured. 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=[net:<network-id>,]<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 network-id(s) are given,
+they must match for this configuration to be sent. Note that
+network-ids are prefixed by "net:" to distinguish them.
+.TP
+.B --pxe-service=[net:<network-id>,]<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 multicast or broadcast, or direct to a server if its IP address is provided. A boot service
+type of 0 is special, and will abort the net boot procedure and
+continue booting from local media.
+.TP
+.B --pxe-prompt=[net:<network-id>,]<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 150. 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 netid 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. 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, and if the
+host provided a client-id, this is stored in the environment variable
+DNSMASQ_CLIENT_ID. If the fully-qualified domain name of the host is
+known, the domain part is stored in DNSMASQ_DOMAIN.
+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.
+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: if subsequent lease
+changes occur, the script is not invoked again until any existing
+invocation exits. 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". <path>
+must be an absolute pathname, no PATH search occurs. 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>]
+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.
+.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
+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).
+.TP
+.B --tftp-root=<directory>
+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.
+.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.
+.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 network-id system works as follows: For each DHCP request, dnsmasq
+collects a set of valid network-id tags, 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" for BOOTP requests, a tag whose name is the
+name if the interface on which the request arrived,
+and possibly many from matching vendor classes and user
+classes sent by the DHCP client. Any
+.B dhcp-option
+which has network-id 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=#purple,3,1.2.3.4 sends the option when the
+network-id tag purple is not in the set of valid tags.
+.PP
+If the network-id in a
+.B dhcp-range
+is prefixed with 'net:' then its meaning changes from setting a
+tag to matching it. Thus if there is more than dhcp-range on a subnet,
+and one is tagged with a network-id which is set (for instance
+from a vendorclass option) then hosts which set the netid tag will be
+allocated addresses in the tagged range.
+.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 matched against netids in
+.B dhcp-option
+configurations, as is the tag "bootp", allowing some control over the options returned to
+different classes of hosts.
+
+.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. Clearly to do this the value of
+.B --dhcp-lease-max
+must be increased,
+and 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 /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 100755
index 0000000..7197212
--- /dev/null
+++ b/man/es/dnsmasq.8
@@ -0,0 +1,1310 @@
+.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.
+.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 en el caché aún en la ausencia de
+un expediente SOA.
+.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. (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 1280, lo cual es el
+máximo recomendado en RFC2671 para ethernet.
+.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 \-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.
+
+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=[[net:]network-id,]<dirección-inicio>,<dirección-final>[[,<máscara>],<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
+network-id es 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 'net:' 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.)
+.TP
+.B \-G, --dhcp-host=[<dirección de hardware>][,id:<client_id>|*][,net:<netid>][,<dirección IP>][,<nombre de host>][,<tiempo de arriendo>][,ignore]
+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 red siendo servida por el servidor DHCP. Se
+permite usar identificadores de clientes 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. 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 net:<network-id> fija la etiqueta network-id cuando sea que
+esta directiva dhcp-host está en uso. Esto puede ser usado para
+enviar selectivamente opciones DHCP a este host. Cuando un host
+coincide con cualquier directiva dhcp-host (o una implicada por
+/etc/ethers) entonces la etiqueta network-id especial "known" es
+fijada. Esto permite que dnsmasq sea configurado para ignorar
+pedidos desde máquinas desconocidas usando
+.B --dhcp-ignore=#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.
+.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=[<network-id>,[<network-id>,]][encap:<opt>,][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 network-ids
+opcionales son brindadas, entonces esta opción es solo enviada cuando
+todas las network-ids 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 dirección 0.0.0.0 no es tratada de forma especial en opciones encapsuladas.
+.TP
+.B --dhcp-option-force=[<network-id>,[<network-id>,]][encap:<opt>,][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=<network-id>,<vendor-class>
+Trazar desde un string vendor-class a un network id. 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=printers,Hewlett-Packard JetDirect
+peritiría que opciones sean fijadas solo para impresoras HP así:
+.B --dhcp-option=printers,3,192.168.4.4
+El string vendor-class es coordinado con el vendor-class proveido por
+el cliente, para permitir coincidencias borrosas.
+.TP
+.B \-j, --dhcp-userclass=<network-id>,<user-class>
+Trazar desde un string user-class a un network id (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=<network-id>,<dirección MAC>
+Trazar desde una dirección MAC a una network id. La dirección MAC
+puede incluir comodínes. Por ejemplo:
+.B --dhcp-mac=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 opciones network-id. 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,
+network-id es fijado.
+.TP
+.B --dhcp-subscrid=<network-id>,<subscriber-id>
+Trazar de opciones relay subscriber-id RFC3993 a opciones network-id.
+.TP
+.B --dhcp-match=<network-id>,<option number>|option:<option name>[,<value>]
+Sin un valor, fijar la etiqueta network-id 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=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.
+.B \-J, --dhcp-ignore=<network-id>[,<network-id>]
+Cuando todos los network ids brindados coincidan con el juego de
+network ids derivados de las clases net, host, y vendor, ignorar
+el host y no brindarle un arriendo DHCP.
+.TP
+.B --dhcp-ignore-names[=<network-id>[,<network-id>]]
+Cuando todos los network-ids brindados coinciden con el juego de
+network-ids derivado de la red, host, classes de vendedor y usuario,
+ignorar cualquier nombre de host proveido por el host. Nótese que,
+a diferencia de dhcp-ignore, es permisible no brindar ningún tag netid,
+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-broadcast=<network-id>[,<network-id>]
+Cuando todos los network-ids brindados coinciden con el juego de network-ids
+derivados de la red, host, clases de vendedor y usuarios, siempre usar
+broadcast para comunicarse con el host cuando está sin configurar. 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=[net:<network-id>,]<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 network-ids 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=[net:<network-id>,]<CSA>,<texto de menú>,<nombre base>|<tipo de servicio boot>[,<dirección de servidor>]
+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 multicast o
+broadcast, o directamente a un servidor si la dirección IP es brindada. Un
+tipo de servicio boot de 0 es especial, y abortará el proceso boot de red
+y continuará desde medio local.
+.TP
+.B --pxe-prompt=[net:<network-id>,]<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 150. 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 netid 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.
+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, y si el
+host brindó un client-id, es almacenado en la variable de ambiente
+DNSMASQ_CLIENT_ID. Si el dominio completamente calificado del host
+es conocido, la parte de dominio es almacenada en DNSMASQ_DOMAIN. Si
+el cliente brinda información de clase de vendedoro usuario,
+estos son brindados en las variables DNSMASQ_VENDOR_CLASS y
+DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add"
+y "old" cuando un host resume 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.
+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: si cambios de arriendos
+subsiguientes ocurren, el guión no es invocado otra vez hasta que
+cualquier invocación existente haga exit. 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 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
+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).
+.TP
+.B --tftp-root=<directorio>
+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.
+.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>
+Leer todos los archivos dentro del directorio brindado como archivos
+de configuración. Archivos cuyos nombres terminen con ~ o comienzen
+con . o comienzen y terminen con # 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 network-id funciona de la siguiente manera: Para cada pedido
+DHCP, dnsmasq colecciona un juego de etiquetas network-id válidas,
+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"
+para pedidos BOOTP, una etiqueta cuyo nombre es el nombre de la
+interface donde llegó el pedido, y posiblemente muchas de clases
+de vendedor y usuario que coincidan que hayan sido enviadas por
+el cliente DHCP. Cualquier opción
+.B dhcp-option
+que tenga etiquetas network-id 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=#purple,3,1.2.3.4 envía
+la opción cuando la etiqueta network-id "purple" no está en el juego
+de etiquetas válidas.
+.PP
+Si el network-id en un
+.B dhcp-range
+es prefijado con "net:", entonces su significado cambia de "fijar
+etiqueta" a "coincidir con etiqueta". O sea que si hay más de un
+dhcp-range en en una subred, y uno tiene una etiqueta network-id la
+cual está fijada (por ejemplo una opción de clase de vendedor) entonces
+hosts que fijen la etiqueta network-id serán alocados direcciones en
+el rango etiquetado.
+.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 revisado para
+ver si coincide con algún network-id en configuraciónes
+.B dhcp-option
+al igual que la etiqueta "bootp", permitiendo así algún control sobre
+las opciones devueltas a diferentes clases de hosts.
+
+.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. Por supuesto que para lograr esto debe aumentarse el valor de
+.B --dhcp-lease-max
+, y 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 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 100755
index 0000000..92ec024
--- /dev/null
+++ b/man/fr/dnsmasq.8
@@ -0,0 +1,1449 @@
+.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 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 \-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. (Les
+erreurs lors de la lecture de la configuration vont toujours vers le syslog,
+mais tous les messages postérieures à 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 1280, qui est la valeur maximale
+recommandée pour ethernet dans la RFC2671.
+.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 \-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.
+
+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.
+.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 \-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 \-F, --dhcp-range=[[net:]identifiant de réseau,]<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 réseau optionnel est un label alphanumérique qui permet de
+marquer ce réseau afin de fournir des options DHCP spécifiques à chaque réseau.
+Lorsque préfixé par 'net:', la signification change est 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).
+.TP
+.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,net:<identifiant de réseau>][,<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 92.168.0.199. Les adresses allouées comme ceci ne sont pas
+contraintes dans une plage d'adresse spécifiée par une option --dhcp-range, mais
+elles doivent être sur un réseau servi par le serveur DHCP. 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. 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 net:<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. Lorsqu'une machine coïncide
+avec une directive dhcp-host (ou une impliquée par /etc/ethers), alors
+l'identifiant réseau 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=#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=<fichier>
+Lis les informations d'hôtes DHCP dans le fichier spécifié. 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=<fichier>
+Lis les informations relatives aux options DHCP dans le fichier spécifié.
+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=[<identifiant_de_réseau>,[<identifiant_de_réseau>,]][encap:<option>,][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 identifiants de réseaux sont fournis, alors cette option n'est envoyée
+qu'aux réseaux dont tous les identifiants coïncident.
+
+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.
+
+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=[<identifiant de réseau>,[<identifiant de réseau>,]][encap:<option>,][vendor:[<classe de vendeur>],]<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=<identifiant de réseau>,<classe de vendeur>
+Associe une chaîne de classe de vendeur à un indentifiant de réseau. 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=printers,Hewlett-Packard JetDirect
+permet de n'allouer des options qu'aux imprimantes HP de la manière suivante :
+.B --dhcp-option=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").
+.TP
+.B \-j, --dhcp-userclass=<identifiant de réseau>,<classe utilisateur>
+Associe une chaîne de classe d'utilisateur à un identifiant réseau (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=<identifiant de réseau>,<adresse MAC>
+Associe une adresse matérielle (MAC) à un identifiant réseau. L'adresse
+matérielle peut inclure des jokers. Par exemple
+.B --dhcp-mac=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=<identifiant de réseau>,<identifiant de circuit>, --dhcp-remoteid=<identifiant de réseau>,<identifiant distant>
+Associe des options de relais DHCP issus de la RFC3046 à des identifiants de
+réseau. 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 l'identifiant de réseau est positionné.
+.TP
+.B --dhcp-subscrid=<identifiant de réseau>,<identifiant d'abonné>
+Associe des options de relais DHCP issues de la RFC3993 à des identifiants de
+réseau.
+.TP
+.B --dhcp-match=<identifiant de réseau>,<numéro d'option>|option:<nom d'option>[,<valeur>]
+Si aucune valeur n'est spécifiée, associe l'identifiant de réseau 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=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).
+.TP
+.B \-J, --dhcp-ignore=<identifiant de réseau>[,<identifiant de réseau>]
+Lorsque tous les identifiants de réseau fournis coïncident avec la liste
+d'identifiants réseau dérivée des classes de réseau, hôte, vendeur et
+utilisateur, ignorer l'hôte et ne pas donner de bail DHCP.
+.TP
+.B --dhcp-ignore-names[=<identifiant de réseau>[,<identifiant de réseau>]]
+Lorsque tous les identifiant de réseau coïncident avec la liste d'identifiants
+réseau dérivées des classes de réseau, hôte, vendeur et utilisateur, 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 d'identifiant réseau.
+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-broadcast=<identifiant de réseau>[,<identifiant de réseau>]
+Lorsque tous les identifiants de réseaux fournis correspondent à ceux
+obtenus à partir des classes de réseau, d'hôte ou d'utilisateur, force
+l'utilisation du broadcast pour communiquer avec l'hôte lorsque celui-ci n'est
+pas configuré. 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=[net:<identifiant de réseau>,]<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 identifiants de réseau sont fournis, ils doivent coïncider avec
+ceux du client pour que cet élement de configuration lui soit envoyé. Il est à
+noter que les identifiants de réseau doivent-être préfixés par "net:".
+.TP
+.B --pxe-service=[net:<identifiant de réseau>,]<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 multicast ou broadcast, ou directement
+auprès d'un serveur si son adresse IP est fournie dans l'option. Un service de
+démarrage de type 0 est spécial et provoquera une interruption du démarrage par
+le réseau ainsi que la poursuite du démarrage sur un média local.
+.TP
+.B --pxe-prompt=[net:<identifiant de réseau>,]<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 150. 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 identifiants de réseaux 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é. 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, et
+si l'hôte fournit un identifiant de client, celui-ci est stocké dans la
+variable d'environnement DNSMASQ_CLIENT_ID. Si un nom de domaine pleinement
+qualifié (FQDN) est connu pour l'hôte, la part relative au domaine est stockée
+dans DNSMASQ_DOMAIN. Si le client fournit une information de classe de vendeur,
+de classe d'utilisateur ou un nom d'hôte, celles-ci sont positionnées 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.
+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 : si un autre changement de
+bail intervient, le script ne sera relancé que lorsque l'exécution actuelle sera
+terminée.
+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. <chemin de fichier> doit être un chemin
+absolu (c'est-à-dire partant de la racine "/"), aucune recherche n'aura lieu
+dans les répertoires de la variable d'environnement PATH. 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>]
+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.
+.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
+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).
+.TP
+.B --tftp-root=<répertoire>
+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.
+.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.
+.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
+les identifiants de réseau fonctionnent comme suit : Dnsmasq associe à chaque
+requête DHCP un ensemble d'identifiants de réseau; un pour la plage d'adresse
+DHCP (
+.B dhcp-range
+) utilisée pour allouer l'adresse, un identifiant pour chaque entrée
+.B dhcp-host
+associée (il ajoute "known" lorsqu'une entrée dhcp-host coïncide), l'étiquette
+"bootp" pour les requêtes BOOTP, un identifiant dont le nom est le nom de
+l'interface sur laquelle la requête est arrivée, et éventuellement un
+identifiant pour chaque classe de vendeur ou d'utilisateur
+fournie par le client DHCP dans sa requête. Les options DHCP (
+.B dhcp-option
+) ayant un identifiant de réseau seront utilisés de préférence à celles
+sans identifiants de réseau, pour peu que
+.I tous
+les labels correspondent.
+Le préfixe '#' sur un label est un indicateur de négation, ainsi
+.B --dhcp=option=#purple,3,1.2.3.4
+envoie l'option lorsque le label "purple" n'est pas dans la liste de labels
+valides pour l'hôte considéré.
+.PP
+Si l'identifiant de réseau dans la plage d'adresses DHCP (
+.B dhcp-range
+) est préfixé par 'net:', alors sa signification change : au lieu d'associer un
+label à la plage spécifiée, cela indique un label de réseau devant être spécifié
+par le client DHCP. Ainsi, s'il y a plus d'une plage d'adresses DHCP sur un
+sous-réseau, et que l'une est préfixée par un identifiant de réseau (par exemple
+l'un spécifié dans une option de classe de vendeur), alors un hôte ayant
+l'identifiant de réseau en question positionné se verra allouer une adresse dans
+la plage d'adresses DHCP préfixée.
+.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 comparé avec les
+identifiants de réseaux des options
+.B dhcp-option
+ainsi que le label "bootp", ce qui permet de contrôler les options retournées
+aux différentes classes d'hôtes.
+
+.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.
+Evidement, pour cela la valeur de
+.B --dhcp-lease-max
+doit être augmentée et la durée des baux 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 FICHIERS
+.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 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/po/de.po b/po/de.po
new file mode 100755
index 0000000..6e1c440
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,1462 @@
+# German 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-09-27 09:37+0100\n"
+"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\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:764
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr ""
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr ""
+
+# @Simon: Here I need an example to understand it :)
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr ""
+
+# @Simon: Here I need an example to understand it :)
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "lese %s - %d Adressen"
+
+# @Simon: 'lese' is present, is that ok? If it should be past, it would be
+# @Simon: "gelesen: %s - %d Adressen" - note the colon, it's a must, then.
+#: cache.c:902
+msgid "cleared cache"
+msgstr "Cache geleert"
+
+#: cache.c:933 option.c:1055
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr ""
+
+# @Simon: "Cache geleert" is literally "Cache emptied" but I think other translations could be misleading
+# @Simon: (I don't know a good german replacement for "Cache" but AFAIK "Cache" is common in german)
+#: cache.c:1052
+#, 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 nicht dem DHCP 'Mieter' von %s zugewiesen, da der Name in %smit der Adresse %s bereits existiert"
+
+#: cache.c:1129
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+# @Simon: "Mieter" is rather 'logder, renter, tenant, lessee' but I couldn't find anything that fits better.
+# @Simon: So I thought I put it in ''-marks :)
+#: cache.c:1130
+#, fuzzy, 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:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1155
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:59
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr ""
+
+#: util.c:191
+msgid "failed to allocate memory"
+msgstr ""
+
+# @Simon: "re-used" = "wiederverwenden", but in such a case it must be split apart to "verwendet ... wieder"
+# @Simon: "unexpired" = "nicht abgelaufen" (expired=abgelaufen) -- altogether it sounds complicated in german,
+# @Simon: I would prefer to use "noch gültige" = "still valid", would that fit to the sense? Then it would be:
+# @Simon: msgstr "Cache Größe %d, %d/%d Cache-Einfügungen verwendeten noch gültige Cache-Einträge wieder."
+# @Simon: btw, what is the "%d/%d"-part?
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr "Speicher nicht verfügbar"
+
+#: util.c:239
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr ""
+
+#: util.c:247
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr ""
+
+# @Simon: not perfect but I cannot get nearer right now.
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr "unendlich"
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr "Lokale abzuhörende Adresse(n) angeben."
+
+# @Simon: Quite literal translation, sounds not too polite in german.
+# @Simon: How about: "Bitte die lokalen abzuhörende Adresse(n) angeben."
+# @Simon: = "Please specify the local address(es) to listen on."
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Rückkehr-IP-Adresse für alle Geräte in angebenen Domänen"
+
+# @Simon: I hope "Return ipaddr" is similar to "Return-ipaddr" and not "Return the ipaddr ... !"
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "'Gefälschte' Rückwärts-Ergebnisse für private Adressbereiche nach RFC1918"
+
+# @Simon: I'm a bit unsure about the meaning of "Fake" here, and the best word for "lookup" is "Nachsehen"
+# @Simon: (that is "looking-for") but I think that cannot be used. "Ergebnisse" = "results", is that near enough?
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Behandle IP-Adr als NXDOMAIN (wehrt Verisign-Platzhalter ab)."
+
+# @Simon: or "Behandle IP-Adr als NXDOMAIN (gegen Verisign-Platzhalter)."
+# @Simon: "gegen" = "against", I believe that might be clumsy in english but it is fine in german.
+# @Simon: Just by chance I know what this is for - it is merely against verisign's use of wildcard
+# @Simon: entries (that lead to their own servers), right. Therefore, how about:
+# @Simon: "Behandle IP-Adr als NXDOMAIN (gegen Verisigns Platzhalter-Gebrauch)."
+# @Simon: = "Treat ipaddr as NXDOMAIN (defeats Verisigns wildcard usage)." ?
+# @Simon: But the explanatory(?) effect is only a very tiny bit better, I believe - what do U think?
+#: option.c:232
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr "Angabe der Größe des Caches in Einträgen (Voreinstellung: %s)."
+
+#: option.c:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Angabe der Konfigurationsdatei (Voreinstellung: %s)."
+
+#: option.c:234
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "NICHT in den Hintergrund gehen: Betrieb im Debug-Modus"
+
+# @Simon: = "DO NOT go into the background: Operation in debug-mode"
+# @Simon: I know it sounds a bit clumsy in english, but "fork" would be hard to understand
+# @Simon: and then I get a problem between "go" and "run" - so...
+# @Simon: "Debug-mode" = "Fehlersuch-Modus", literally, but I think "Debug-Modus" is better :)
+#: option.c:235
+msgid "Do NOT forward queries with no domain part."
+msgstr "Anfragen ohne Domänen-Teil NICHT weiterschicken"
+
+# @Simon: "weiterschicken" is rather "pass on" (I hope) but that's the best I found.
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Rückgabe auf sich selbst zeigender MX-Einträge für lokale Geräte"
+
+# @Simon: "self-pointing" is a bit difficult, the meaning is clear but takes 3-4 words to express it in german.
+# @Simon: "Geräte" is about "hard-devices". There is a word for "host" (it is "Wirt") but it would be misleading.
+# @Simon: My online dict suggest "Rechner" (= Computer), but I think "hard-devices" is better because it's more general.
+#: option.c:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Erweitere einfache Namen in /etc/hosts mit der Domänen-Endung"
+
+#: option.c:238
+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:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr ""
+
+#: option.c:240
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr ""
+
+#: option.c:241
+msgid "Set address or hostname for a specified machine."
+msgstr ""
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr ""
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr ""
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr ""
+
+#: option.c:245
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr ""
+
+#: option.c:246
+msgid "Specify interface(s) to listen on."
+msgstr ""
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr ""
+
+#: option.c:248
+msgid "Map DHCP user class to tag."
+msgstr ""
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:252
+msgid "Don't do DHCP for hosts with tag set."
+msgstr ""
+
+#: option.c:253
+msgid "Force broadcast replies for hosts with tag set."
+msgstr ""
+
+#: option.c:254
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr ""
+
+#: option.c:255
+msgid "Assume we are the only DHCP server on the local network."
+msgstr ""
+
+#: option.c:256
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:257
+msgid "Return MX records for local hosts."
+msgstr ""
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr ""
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr ""
+
+#: option.c:260
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr ""
+
+#: option.c:261
+msgid "Do NOT cache failed search results."
+msgstr ""
+
+#: option.c:262
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr ""
+
+#: option.c:263
+msgid "Specify options to be sent to DHCP clients."
+msgstr ""
+
+#: option.c:264
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:265
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr ""
+
+#: option.c:266
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr ""
+
+#: option.c:267
+msgid "Log DNS queries."
+msgstr ""
+
+#: option.c:268
+msgid "Force the originating port for upstream DNS queries."
+msgstr ""
+
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr ""
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr ""
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr ""
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr ""
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr ""
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr ""
+
+#: option.c:275
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr ""
+
+#: option.c:276
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr ""
+
+#: option.c:277
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr ""
+
+#: option.c:278
+msgid "Map DHCP vendor class to tag."
+msgstr ""
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr ""
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr ""
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr ""
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:283
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Angabe der Konfigurationsdatei (Voreinstellung: %s)."
+
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:285
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr ""
+
+#: option.c:286
+msgid "Specify TXT DNS record."
+msgstr ""
+
+#: option.c:287
+msgid "Specify PTR DNS record."
+msgstr ""
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr ""
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr ""
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr ""
+
+#: option.c:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr ""
+
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr ""
+
+#: option.c:294
+msgid "Map MAC address (with wildcards) to option set."
+msgstr ""
+
+#: option.c:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:296
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:297
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:298
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:299
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr ""
+
+#: option.c:300
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:301
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr ""
+
+#: option.c:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:304
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:305
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:308
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:309
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr ""
+
+#: option.c:310
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:316
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:319
+msgid "Specify NAPTR DNS record."
+msgstr ""
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:323
+msgid "Prompt to send to PXE clients."
+msgstr ""
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+
+#: option.c:615
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr ""
+
+#: option.c:617
+#, c-format
+msgid "Valid options are:\n"
+msgstr ""
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr ""
+
+# @Simon: Here I need an example to understand it :)
+#: option.c:792
+#, fuzzy
+msgid "bad IP address"
+msgstr "lese %s - %d Adressen"
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr ""
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr ""
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1086 tftp.c:359
+#, c-format
+msgid "cannot access %s: %s"
+msgstr ""
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr ""
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr ""
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr ""
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr ""
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr ""
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr ""
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1611
+msgid "bad port range"
+msgstr ""
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr ""
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr ""
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr ""
+
+#: option.c:1912
+msgid "bad DHCP host name"
+msgstr ""
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr ""
+
+#: option.c:2284
+msgid "invalid alias range"
+msgstr ""
+
+#: option.c:2297
+msgid "bad interface name"
+msgstr ""
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2347
+msgid "bad PTR record"
+msgstr ""
+
+#: option.c:2378
+msgid "bad NAPTR record"
+msgstr ""
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr ""
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr ""
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr ""
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr ""
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr ""
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr ""
+
+#: option.c:2514
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr ""
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: option.c:2626
+msgid "missing \""
+msgstr ""
+
+#: option.c:2673
+msgid "bad option"
+msgstr ""
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr ""
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr ""
+
+#: option.c:2685
+msgid "error"
+msgstr ""
+
+# @Simon: "Speicher nicht verfügbar" = "memory not available"
+# @Simon: "could not get memory" = "konnte keinen Speicher bekommen" or "konnte Speicher nicht bekommen"
+# @Simon: ("keinen Speicher" = "no memory", "... nicht bekommen" = "... not get")
+# @Simon: both would be correct - but would sound rather clumsy in german
+# @Simon: how about "Nicht genügend Speicher verfügbar" = "Not enough memory available" ?
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s in Zeile %d von %%s"
+
+#: option.c:2740 option.c:2771
+#, c-format
+msgid "read %s"
+msgstr ""
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr ""
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr ""
+
+#: option.c:2846
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:2847
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:2858
+msgid "try --help"
+msgstr ""
+
+#: option.c:2860
+msgid "try -w"
+msgstr ""
+
+#: option.c:2863
+#, c-format
+msgid "bad command line options: %s"
+msgstr ""
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr ""
+
+#: option.c:2932
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr ""
+
+#: option.c:2942
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr ""
+
+#: option.c:2945 network.c:754 dhcp.c:734
+#, c-format
+msgid "failed to read %s: %s"
+msgstr ""
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr ""
+
+#: option.c:2983
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:2987
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr ""
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr ""
+
+#: network.c:73
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr ""
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr ""
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr ""
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr ""
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr ""
+
+#: network.c:467
+#, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr ""
+
+#: network.c:661
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr ""
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr ""
+
+#: network.c:705
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr ""
+
+#: network.c:720
+msgid "unqualified"
+msgstr ""
+
+#: network.c:720
+msgid "names"
+msgstr ""
+
+#: network.c:722
+msgid "default"
+msgstr ""
+
+#: network.c:724
+msgid "domain"
+msgstr ""
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:732
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:146
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:151
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr ""
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr ""
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr ""
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr ""
+
+#: dnsmasq.c:204
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:448
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr ""
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr ""
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr ""
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr ""
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr ""
+
+#: dnsmasq.c:467
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr ""
+
+#: dnsmasq.c:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr ""
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr ""
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:484
+msgid "warning: no upstream servers configured"
+msgstr ""
+
+#: dnsmasq.c:488
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:501
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr ""
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:760
+#, c-format
+msgid "failed to create helper: %s"
+msgstr ""
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:767
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:772
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:775
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:841
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr ""
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr ""
+
+#: dnsmasq.c:903
+#, c-format
+msgid "failed to access %s: %s"
+msgstr ""
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr ""
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr ""
+
+#: dhcp.c:226
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:385
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr ""
+
+#: dhcp.c:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr ""
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr ""
+
+#: dhcp.c:900
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr ""
+
+#: dhcp.c:943
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:948
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr ""
+
+#: lease.c:66
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr ""
+
+#: lease.c:92
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:128
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr ""
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:234
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr ""
+
+#: rfc2131.c:336
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr ""
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:853
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr ""
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:906
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:916
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:919
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1605
+#, c-format
+msgid "%u server name: %s"
+msgstr ""
+
+#: rfc2131.c:1613
+#, c-format
+msgid "%u next server: %s"
+msgstr ""
+
+#: rfc2131.c:1680
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:1919
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2052
+#, c-format
+msgid "%u requested options: %s"
+msgstr ""
+
+#: netlink.c:66
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr ""
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr ""
+
+#: bpf.c:178
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr ""
+
+#: tftp.c:179
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr ""
+
+#: tftp.c:305
+#, c-format
+msgid "file %s not found"
+msgstr ""
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:447
+#, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr ""
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+# @Simon: I would like to have an example :) - instead of "von" it would be possible to use "aus",
+# @Simon: both translate to "of" and nothing else, but depending on the sense one could be better
+# @Simon: than the other.
+#: log.c:415
+msgid "FAILED to start up"
+msgstr "Start gescheitert"
+
+# @Simon: Here I need an example to understand it :)
+#, fuzzy
+#~ msgid "read %s - %d hosts"
+#~ msgstr "lese %s - %d Adressen"
diff --git a/po/es.po b/po/es.po
new file mode 100755
index 0000000..201e171
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,1500 @@
+# 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:764
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "no se pudo cargar nombres desde %s: %s"
+
+#: cache.c:798 dhcp.c:785
+#, fuzzy, c-format
+msgid "bad address at %s line %d"
+msgstr "dirección errónea en %s línea %d"
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "nombre erróneo en %s línea %d"
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "direcciónes %s - %d leídas"
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr "el caché fue liberado"
+
+#: cache.c:933 option.c:1055
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "no se puede accesar directorio %s: %s"
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr "tiempo %lu"
+
+#: cache.c:1130
+#, 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:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr "búsquedas reenviadas %u, búsquedas respondidas localmente %u"
+
+#: cache.c:1155
+#, 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:59
+#, 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:191
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "no se pudo alocar %d bytes"
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr "no se pudo adquirir memoria"
+
+#: util.c:239
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "no se puede crear pipe: %s"
+
+#: util.c:247
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "no se pudo alocar %d bytes"
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr "infinito"
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr "Especificar dirección(es) locales dónde escuchar."
+
+#: option.c:229
+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:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Falsificar búsquedas reversas para rangos de dirección privados RFC1918."
+
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Tratar ipaddr (dirección IP) como NXDOMAIN (derrota comodín Verisign)."
+
+#: option.c:232
+#, 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:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Especificar archivo de configuración (%s por predeterminado)."
+
+#: option.c:234
+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:235
+msgid "Do NOT forward queries with no domain part."
+msgstr "NO reenviar búsquedas sin parte de dominio."
+
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Retornar expedientes MX auto-señaladores para hosts locales."
+
+#: option.c:237
+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:238
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "No reenviar pedidos DNS falsos desde máquinas Windows."
+
+#: option.c:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Habilitar DHCP dentro del rango brindado con duración del arriendo."
+
+#: option.c:240
+#, 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:241
+msgid "Set address or hostname for a specified machine."
+msgstr "Fijar dirección o nombre de host para una máquina especificada."
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr "Leer especificaciones DHCP de host desde archivo"
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr "Leer opciones DHCP de host desde archivo"
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "NO cargar archivo %s."
+
+#: option.c:245
+#, 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:246
+msgid "Specify interface(s) to listen on."
+msgstr "Especificar interface(s) donde escuchar."
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Especificar interface(s) donde NO escuchar."
+
+#: option.c:248
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Trazar clase de usuario DHCP a etiqueta."
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr "Trazar circuit-id (identificación de circuito) RFC3046 a etiqueta."
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr "Trazar remote-id (identificación remota) RFC3046 a etiqueta."
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr "Trazar subscriber-id (identificación de suscritor) RFC3993 a etiqueta."
+
+#: option.c:252
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "No hacer DHCP para hosts con etiqueta fijada."
+
+#: option.c:253
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Forzar respuestas broadcast para hosts con etiqueta fijada."
+
+#: option.c:254
+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:255
+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:256
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Especificar donde almacenar arriendos DHCP (%s por predeterminado)."
+
+#: option.c:257
+msgid "Return MX records for local hosts."
+msgstr "Retornar expedientes MX para hosts locales."
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr "Especificar un expediente MX."
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Especificar opciones BOOTP a servidor DHCP."
+
+#: option.c:260
+#, 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:261
+msgid "Do NOT cache failed search results."
+msgstr "NO almacenar en caché resultados de búsquedas fallidas."
+
+#: option.c:262
+#, 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:263
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Especificar opciones para ser enviadas a clientes DHCP."
+
+#: option.c:264
+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:265
+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:266
+#, 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:267
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "Bitacorear búsquedas DNS."
+
+#: option.c:268
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Enforzar el puerto original para búsquedas DNS upstream."
+
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr "NO leer resolv.conf."
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Especificar el path hacia resolv.conf (%s por predeterminado)."
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Especificar dirección(es) de servidores upstream con dominios opcionales."
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr "Nunca reenviar búsquedas a dominios especificados."
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Especificar el dominio para ser asignado en arriendos DHCP."
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr "Especificar destino predeterminado en un expediente MX."
+
+#: option.c:275
+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:276
+#, fuzzy
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Especificar tiempo de vida en segundos para caché negativo."
+
+#: option.c:277
+#, 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:278
+#, fuzzy
+msgid "Map DHCP vendor class to tag."
+msgstr "Trazar clase de vendedor DHCP a etiqueta."
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr "Mostrar información sobre la versión y copyright de dnsmasq."
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Traducir direcciones IPv4 desde servidores upstream."
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr "Especificar un expediente SRV."
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr "Mostrar este mensaje. Usar --help dhcp para opciones DHCP conocidas."
+
+#: option.c:283
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Especificar path de archivo PID (%s por predeterminado)."
+
+#: option.c:284
+#, 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:285
+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:286
+msgid "Specify TXT DNS record."
+msgstr "Especificar expediente DNS TXT."
+
+#: option.c:287
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Especificar expediente DNS PTR."
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr "Otorgar nombre DNS a dirección IPv4 de interface."
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr "Acoplar solo a interfaces en uso."
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Leer información sobre hosts DHCP estáticos desde %s."
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Habilitar la interface DBus para fijar servidores upstream, etc."
+
+#: option.c:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "No proveer DHCP en esta interface, sólo proveer DNS."
+
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Habilitar alocación dinámica de direcciónes para BOOTP."
+
+#: option.c:294
+#, fuzzy
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Trazar dirección MAC (con comodínes) a opción fijada."
+
+#: option.c:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr "Tratar pedidos DHCP en alias como si llegaran de la interface."
+
+#: option.c:296
+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:297
+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:298
+msgid "Read configuration from all the files in this directory."
+msgstr "Leer configuración desde todos los archivos en este directorio."
+
+#: option.c:299
+#, 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:300
+msgid "Do not use leasefile."
+msgstr "No usar archivo de arriendos."
+
+#: option.c:301
+#, 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:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr "Liberar caché DNS al recargar %s."
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr "Ignorar nombres de host brindados por clientes DHCP."
+
+#: option.c:304
+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:305
+msgid "Enable integrated read-only TFTP server."
+msgstr "Habilitar servidor integrado TFTP solo-lectura."
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr "Exportar archivos vía TFTP solo del sub-árbol especificado."
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr "Agregar IP de cliente a tftp-root."
+
+#: option.c:308
+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:309
+#, 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:310
+msgid "Disable the TFTP blocksize extension."
+msgstr "Deshabilitar la extensión TFTP blocksize (tamaño de bloque)."
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr "Rango de puertos efímeros para ser usados por transferencias TFTP."
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr "Bitacoreo extra para DHCP."
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr "Habilitar bitacoreo asincrónico; opcionalmente fijar tamaño de cola."
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr "Detener revinculación DNS. Filtrar rangos de IP privados al resolver."
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr "Siempre realizar búsquedas DNS a todos los servidores."
+
+#: option.c:316
+#, fuzzy
+msgid "Set tag if client includes matching option in request."
+msgstr "Fijar etiqueta si cliente incluye opción coincidente en pedido."
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr "Usar puertos alternativos para DHCP."
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr "Correr archivo guión de cambio de arriendos como este usuario."
+
+#: option.c:319
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Especificar expediente DNS NAPTR."
+
+#: option.c:320
+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:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr "Usar solo nombres de dominio completamente calificados para clientes DHCP."
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr "Especificar nombre alias para nombre DNS LOCAL."
+
+#: option.c:323
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Aviso a ser enviado a clientes PXE."
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr "Servico boot para menú PXE."
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr "Revisar sintaxis de configuración."
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Modo de uso: dnsmasq [opciones]\n"
+"\n"
+
+#: option.c:615
+#, 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:617
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "Opciones válidas son :\n"
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr "Opciones DHCP conocidas:\n"
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr "opción dhcp-option errónea"
+
+#: option.c:792
+#, fuzzy
+msgid "bad IP address"
+msgstr "dirección IP errónea"
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr "dominio erróneo en dhcp-option"
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr "opción dhcp-option demasiado larga"
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr "dhcp-match ilegal"
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr "opción repetida ilegal"
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr "palabra clave repetida ilegal"
+
+#: option.c:1086 tftp.c:359
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "no se puede accesar %s: %s"
+
+#: option.c:1131
+#, fuzzy
+msgid "only one dhcp-hostsfile allowed"
+msgstr "solo un dhcp-hostsfile permitido"
+
+#: option.c:1138
+#, fuzzy
+msgid "only one dhcp-optsfile allowed"
+msgstr "solo un dhcp-optsfile permitido"
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr "preferencia MX errónea"
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr "nombre MX erróneo"
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr "destino MX erróneo"
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr "no se pueden correr archivos guiónes bajo uClinux"
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr "puerto erróneo"
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr "vinculación de interface no está soportado"
+
+#: option.c:1611
+#, fuzzy
+msgid "bad port range"
+msgstr "rango de puertos erróneo"
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr "opción bridge-interface (interface puente) errónea"
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr "opción dhcp-range (rango DHCP) errónea"
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr "solo una etiqueta netid permitida"
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr "rango DHCP inconsistente"
+
+#: option.c:1912
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "nombre de host DHCP erróneo"
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr "número de puerto inválido"
+
+#: option.c:2284
+#, fuzzy
+msgid "invalid alias range"
+msgstr "rango alias inválido"
+
+#: option.c:2297
+#, fuzzy
+msgid "bad interface name"
+msgstr "nombre de interface erróneo"
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr "CNAME duplicado"
+
+#: option.c:2347
+#, fuzzy
+msgid "bad PTR record"
+msgstr "expediente PTR erróneo"
+
+#: option.c:2378
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "expediente NAPTR erróneo"
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr "expediente TXT demasiado largo"
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr "expediente TXT erróneo"
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr "expediente SRV erróneo"
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr "destino SRV erróneo"
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr "prioridad inválida"
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr "peso inválido"
+
+#: option.c:2514
+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:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr "archivos jerarquizados demasiado profundo en %s"
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "no se puede leer %s: %s"
+
+#: option.c:2626
+msgid "missing \""
+msgstr "falta \""
+
+#: option.c:2673
+msgid "bad option"
+msgstr "opción errónea"
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr "parámetro extraño"
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr "parámetro ausente"
+
+#: option.c:2685
+msgid "error"
+msgstr "error"
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s en línea %d de %%s"
+
+#: option.c:2740 option.c:2771
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "leyendo %s"
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr "Dnsmasq versión %s %s\n"
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Opciones de compilación %s\n"
+"\n"
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Este software viene SIN NINGUNA GARANTIA.\n"
+
+#: option.c:2846
+#, 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:2847
+#, 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:2858
+msgid "try --help"
+msgstr "pruebe --help"
+
+#: option.c:2860
+msgid "try -w"
+msgstr "pruebe -w"
+
+#: option.c:2863
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "opciones de línea de comandos erróneas: %s"
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "no se puede obtener host-name (nombre de host): %s"
+
+#: option.c:2932
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "solo un archivo resolv.conf permitido en modo no-poll."
+
+#: option.c:2942
+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:2945 network.c:754 dhcp.c:734
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "no se pudo leer %s: %s"
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr "ninguna directiva de búsqueda encontrada en %s"
+
+#: option.c:2983
+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:2987
+msgid "syntax check OK"
+msgstr "revisión de sintaxis OK"
+
+#: forward.c:409
+#, 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:437
+msgid "possible DNS-rebind attack detected"
+msgstr "posible ataque de revinculación DNS detectado"
+
+#: network.c:73
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "interface desconocida %s en bridge-interface"
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr "no se pudo crear un socket escuchador: %s"
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr "no se pudo fijar opciones IPv6 sobre socket escuchador: %s"
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr "no se pudo acoplar socket escuchador para %s: %s"
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr "no se pudo escuchar en socket: %s"
+
+#: network.c:467
+#, fuzzy, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr "no se pudo crear socket TFTP: %s"
+
+#: network.c:661
+#, fuzzy, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "no se pudo acoplar socket escuchador para %s: %s"
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorando servidor DNS %s - interface local"
+
+#: network.c:705
+#, 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:720
+msgid "unqualified"
+msgstr "no calificado"
+
+#: network.c:720
+msgid "names"
+msgstr "nombres"
+
+#: network.c:722
+msgid "default"
+msgstr "predeterminado"
+
+#: network.c:724
+msgid "domain"
+msgstr "dominio"
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "usando direcciones locales solo para %s %s"
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "usando servidor DNS %s#%d para %s %s"
+
+#: network.c:732
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "usando servidor DNS %s#%d(vía %s)"
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "usando servidor DNS %s#%d"
+
+#: dnsmasq.c:146
+#, 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:151
+#, fuzzy
+msgid "asychronous logging is not available under Solaris"
+msgstr "bitacoreo asincrónico no está disponible bajo Solaris"
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "no se pudo encontrar lista de interfaces: %s"
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr "interface desconocida %s"
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr "ninguna interface con dirección %s"
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr "error DBus: %s"
+
+#: dnsmasq.c:204
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus no disponible: fijar HAVE_DBUS en src/config.h"
+
+#: dnsmasq.c:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr "usuario o grupo desconocido: %s"
+
+#: dnsmasq.c:287
+#, 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:448
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "iniciado, versión %s DNS deshabilitado"
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "iniciado, versión %s tamaño de caché %d"
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "iniciado, versión %s caché deshabilitado"
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr "opciones de compilación: %s"
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr "soporte DBus habilitado: conectado a bus de sistema"
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr "soporte DBus habilitado: conección a bus pendiente"
+
+#: dnsmasq.c:467
+#, 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:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "fijando opción --bind-interfaces debido a limitaciones de sistema operativo"
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "advertencia: interface %s no existe actuálmente"
+
+#: dnsmasq.c:481
+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:484
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "advertencia: ningún servidor upstream configurado"
+
+#: dnsmasq.c:488
+#, 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:501
+#, 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:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr "DHCP, proxy en subred %.0s%s%.0s"
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, rango de IPs %s -- %s, tiempo de arriendo %s"
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr "root es "
+
+#: dnsmasq.c:519
+#, fuzzy
+msgid "enabled"
+msgstr "habilitado"
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr "modo seguro"
+
+#: dnsmasq.c:547
+#, 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:667
+msgid "connected to system DBus"
+msgstr "conectado a DBus de sistema"
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr "no se puede hacer fork hacia el fondo: %s"
+
+#: dnsmasq.c:760
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "no se pudo crear ayudante: %s"
+
+#: dnsmasq.c:763
+#, fuzzy, c-format
+msgid "setting capabilities failed: %s"
+msgstr "configuración de capacidades ha fallado: %s"
+
+#: dnsmasq.c:767
+#, fuzzy, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "no se pudo cambiar user-id a %s: %s"
+
+#: dnsmasq.c:772
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "no se pudo cambiar group-id a %s: %s"
+
+#: dnsmasq.c:775
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "no se pudo abrir archivo PID %s: %s"
+
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "no se puede abrir %s: %s"
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr "proceso hijo eliminado por señal %d"
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr "proceso hijo hizo exit con estado %d"
+
+#: dnsmasq.c:841
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "no se pudo ejecutar %s: %s"
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr "saliendo al recibir SIGTERM"
+
+#: dnsmasq.c:903
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "no se pudo accesar %s: %s"
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr "leyendo %s"
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "no se puede crear socket crudo ICMP: %s."
+
+#: dhcp.c:226
+#, 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:385
+#, 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:772
+#, fuzzy, c-format
+msgid "bad line at %s line %d"
+msgstr "línea errónea en %s línea %d"
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "dirección IP duplicada %s en directiva dhcp-config."
+
+#: dhcp.c:900
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "dirección IP duplicada %s en %s."
+
+#: dhcp.c:943
+#, 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:948
+#, 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:66
+#, 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:92
+msgid "too many stored leases"
+msgstr "demasiados arriendos almacenados"
+
+#: lease.c:128
+#, 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:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr "archivo guión lease-init retornó exit code %s"
+
+#: lease.c:234
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "error al escribir %s: %s (reintentar en %us)"
+
+#: rfc2131.c:336
+#, 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:337
+msgid "with subnet selector"
+msgstr "con selector de subred"
+
+#: rfc2131.c:337
+msgid "via"
+msgstr "vía"
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr "%u Subred DHCP disponible: %s/%s"
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr "%u Rango DHCP disponible: %s -- %s"
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr "deshabilitado"
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr "ignorado"
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr "dirección en uso"
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr "ninguna dirección disponible"
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr "red equivocada"
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr "ninguna dirección configurada"
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr "no sobra ningún arriendo"
+
+#: rfc2131.c:558
+#, fuzzy, c-format
+msgid "%u client provides name: %s"
+msgstr "%u cliente provee nombre: %s"
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr "%u Clase de vendedor: %s"
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr "%u Clase de usuario: %s"
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr "no hay soporte para BIS PXE"
+
+#: rfc2131.c:853
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "deshabilitando dirección DHCP estática %s para %s"
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr "arriendo desconocido"
+
+#: rfc2131.c:906
+#, 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:916
+#, 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:919
+#, 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:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr "ningún unique-id (identificación única)"
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr "ID de servidor equivocada"
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr "dirección equivocada"
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr "arriendo no encontrado"
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr "dirección no disponible"
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr "arriendo estático disponible"
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr "dirección reservada"
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr "abandonando arriendo a %s de %s"
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr "%u etiquetas: %s"
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr "%u nombre de bootfile: %s"
+
+#: rfc2131.c:1605
+#, c-format
+msgid "%u server name: %s"
+msgstr "%u nombre de servidor: %s"
+
+#: rfc2131.c:1613
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "%u siguiente servidor: %s"
+
+#: rfc2131.c:1680
+#, 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:1919
+msgid "PXE menu too large"
+msgstr "menú PXE demasiado grande"
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr "Ignorando dominio %s para nombre de host DHCP %s"
+
+#: rfc2131.c:2052
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "%u opciones solicitadas: %s"
+
+#: netlink.c:66
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "no se puede crear socket netlink: %s"
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "no se puede crear socket BPF DHCP: %s"
+
+#: bpf.c:178
+#, 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:179
+msgid "unable to get free port for TFTP"
+msgstr "incapaz de conseguir puerto libre para TFTP"
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr "pedido no-soportado desde %s"
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr "TFTP envió %s a %s"
+
+#: tftp.c:305
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "archivo %s no encontrado"
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr "error TFTP %d %s recibido de %s"
+
+#: tftp.c:447
+#, fuzzy, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr "TFTP no pudo enviar %s a %s"
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr "desbordamiento: %d entradas de bitácora perdidas"
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr "bitácora falló: %s"
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr "el inicio ha FALLADO"
+
+#~ 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 "bad dhcp-host"
+#~ msgstr "opción dhcp-host errónea"
+
+#~ 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 100755
index 0000000..a0a6fbd
--- /dev/null
+++ b/po/fi.po
@@ -0,0 +1,1411 @@
+# 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:764
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr ""
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr ""
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr ""
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr ""
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr ""
+
+#: cache.c:933 option.c:1055
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr ""
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1130
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr ""
+
+#: cache.c:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1155
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:59
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr ""
+
+#: util.c:191
+msgid "failed to allocate memory"
+msgstr ""
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr ""
+
+#: util.c:239
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr ""
+
+#: util.c:247
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr ""
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr ""
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr ""
+
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr ""
+
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr ""
+
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr ""
+
+#: option.c:232
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr ""
+
+#: option.c:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr ""
+
+#: option.c:234
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr ""
+
+#: option.c:235
+msgid "Do NOT forward queries with no domain part."
+msgstr ""
+
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr ""
+
+#: option.c:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr ""
+
+#: option.c:238
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr ""
+
+#: option.c:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr ""
+
+#: option.c:240
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr ""
+
+#: option.c:241
+msgid "Set address or hostname for a specified machine."
+msgstr ""
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr ""
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr ""
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr ""
+
+#: option.c:245
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr ""
+
+#: option.c:246
+msgid "Specify interface(s) to listen on."
+msgstr ""
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr ""
+
+#: option.c:248
+msgid "Map DHCP user class to tag."
+msgstr ""
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:252
+msgid "Don't do DHCP for hosts with tag set."
+msgstr ""
+
+#: option.c:253
+msgid "Force broadcast replies for hosts with tag set."
+msgstr ""
+
+#: option.c:254
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr ""
+
+#: option.c:255
+msgid "Assume we are the only DHCP server on the local network."
+msgstr ""
+
+#: option.c:256
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:257
+msgid "Return MX records for local hosts."
+msgstr ""
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr ""
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr ""
+
+#: option.c:260
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr ""
+
+#: option.c:261
+msgid "Do NOT cache failed search results."
+msgstr ""
+
+#: option.c:262
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr ""
+
+#: option.c:263
+msgid "Specify options to be sent to DHCP clients."
+msgstr ""
+
+#: option.c:264
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:265
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr ""
+
+#: option.c:266
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr ""
+
+#: option.c:267
+msgid "Log DNS queries."
+msgstr ""
+
+#: option.c:268
+msgid "Force the originating port for upstream DNS queries."
+msgstr ""
+
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr ""
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr ""
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr ""
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr ""
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr ""
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr ""
+
+#: option.c:275
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr ""
+
+#: option.c:276
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr ""
+
+#: option.c:277
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr ""
+
+#: option.c:278
+msgid "Map DHCP vendor class to tag."
+msgstr ""
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr ""
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr ""
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr ""
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:283
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr ""
+
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:285
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr ""
+
+#: option.c:286
+msgid "Specify TXT DNS record."
+msgstr ""
+
+#: option.c:287
+msgid "Specify PTR DNS record."
+msgstr ""
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr ""
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr ""
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr ""
+
+#: option.c:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr ""
+
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr ""
+
+#: option.c:294
+msgid "Map MAC address (with wildcards) to option set."
+msgstr ""
+
+#: option.c:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:296
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:297
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:298
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:299
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr ""
+
+#: option.c:300
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:301
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr ""
+
+#: option.c:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:304
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:305
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:308
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:309
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr ""
+
+#: option.c:310
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:316
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:319
+msgid "Specify NAPTR DNS record."
+msgstr ""
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:323
+msgid "Prompt to send to PXE clients."
+msgstr ""
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+
+#: option.c:615
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr ""
+
+#: option.c:617
+#, c-format
+msgid "Valid options are:\n"
+msgstr ""
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr ""
+
+#: option.c:792
+msgid "bad IP address"
+msgstr ""
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr ""
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr ""
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1086 tftp.c:359
+#, c-format
+msgid "cannot access %s: %s"
+msgstr ""
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr ""
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr ""
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr ""
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr ""
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr ""
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr ""
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1611
+msgid "bad port range"
+msgstr ""
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr ""
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr ""
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr ""
+
+#: option.c:1912
+msgid "bad DHCP host name"
+msgstr ""
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr ""
+
+#: option.c:2284
+msgid "invalid alias range"
+msgstr ""
+
+#: option.c:2297
+msgid "bad interface name"
+msgstr ""
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2347
+msgid "bad PTR record"
+msgstr ""
+
+#: option.c:2378
+msgid "bad NAPTR record"
+msgstr ""
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr ""
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr ""
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr ""
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr ""
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr ""
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr ""
+
+#: option.c:2514
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr ""
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: option.c:2626
+msgid "missing \""
+msgstr ""
+
+#: option.c:2673
+msgid "bad option"
+msgstr ""
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr ""
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr ""
+
+#: option.c:2685
+msgid "error"
+msgstr ""
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr ""
+
+#: option.c:2740 option.c:2771
+#, c-format
+msgid "read %s"
+msgstr ""
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr ""
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr ""
+
+#: option.c:2846
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:2847
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:2858
+msgid "try --help"
+msgstr ""
+
+#: option.c:2860
+msgid "try -w"
+msgstr ""
+
+#: option.c:2863
+#, c-format
+msgid "bad command line options: %s"
+msgstr ""
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr ""
+
+#: option.c:2932
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr ""
+
+#: option.c:2942
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr ""
+
+#: option.c:2945 network.c:754 dhcp.c:734
+#, c-format
+msgid "failed to read %s: %s"
+msgstr ""
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr ""
+
+#: option.c:2983
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:2987
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr ""
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr ""
+
+#: network.c:73
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr ""
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr ""
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr ""
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr ""
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr ""
+
+#: network.c:467
+#, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr ""
+
+#: network.c:661
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr ""
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr ""
+
+#: network.c:705
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr ""
+
+#: network.c:720
+msgid "unqualified"
+msgstr ""
+
+#: network.c:720
+msgid "names"
+msgstr ""
+
+#: network.c:722
+msgid "default"
+msgstr ""
+
+#: network.c:724
+msgid "domain"
+msgstr ""
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:732
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:146
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:151
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr ""
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr ""
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr ""
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr ""
+
+#: dnsmasq.c:204
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:448
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr ""
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr ""
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr ""
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr ""
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr ""
+
+#: dnsmasq.c:467
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr ""
+
+#: dnsmasq.c:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr ""
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr ""
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:484
+msgid "warning: no upstream servers configured"
+msgstr ""
+
+#: dnsmasq.c:488
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:501
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr ""
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:760
+#, c-format
+msgid "failed to create helper: %s"
+msgstr ""
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:767
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:772
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:775
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:841
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr ""
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr ""
+
+#: dnsmasq.c:903
+#, c-format
+msgid "failed to access %s: %s"
+msgstr ""
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr ""
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr ""
+
+#: dhcp.c:226
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:385
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr ""
+
+#: dhcp.c:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr ""
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr ""
+
+#: dhcp.c:900
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr ""
+
+#: dhcp.c:943
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:948
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr ""
+
+#: lease.c:66
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr ""
+
+#: lease.c:92
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:128
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr ""
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:234
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr ""
+
+#: rfc2131.c:336
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr ""
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:853
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr ""
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:906
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:916
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:919
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1605
+#, c-format
+msgid "%u server name: %s"
+msgstr ""
+
+#: rfc2131.c:1613
+#, c-format
+msgid "%u next server: %s"
+msgstr ""
+
+#: rfc2131.c:1680
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:1919
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2052
+#, c-format
+msgid "%u requested options: %s"
+msgstr ""
+
+#: netlink.c:66
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr ""
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr ""
+
+#: bpf.c:178
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr ""
+
+#: tftp.c:179
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr ""
+
+#: tftp.c:305
+#, c-format
+msgid "file %s not found"
+msgstr ""
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:447
+#, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr ""
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr ""
diff --git a/po/fr.po b/po/fr.po
new file mode 100755
index 0000000..c9f2f9f
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,1504 @@
+# 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.51\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-18 12:24+0100\n"
+"PO-Revision-Date: 2009-09-30 10:22+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:764
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr "Impossible de charger les noms à partir de %s : %s"
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "mauvaise adresse dans %s ligne %d"
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "mauvais nom dans %s ligne %d"
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "lecture %s - %d adresses"
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr "cache vidé"
+
+#: cache.c:933 option.c:1055
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr "Ne peut pas lire le répertoire %s : %s"
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr "horodatage %lu"
+
+#: cache.c:1130
+#, 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:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr "requêtes transmises %u, requêtes résolues localement %u"
+
+#: cache.c:1155
+#, 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:59
+#, 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:191
+msgid "failed to allocate memory"
+msgstr "impossible d'allouer la mémoire"
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr "impossible d'allouer de la mémoire"
+
+#: util.c:239
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr "Ne peut pas créer le tube %s : %s"
+
+#: util.c:247
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr "impossible d'allouer %d octets"
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr "illimité(e)"
+
+#: option.c:228
+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:229
+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:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Traduction inverse truquée pour la plage d'adresse privée RFC1918"
+
+#: option.c:231
+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:232
+#, 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:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Spécifie le nom du fichier de configuration (par défaut : %s)"
+
+#: option.c:234
+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:235
+msgid "Do NOT forward queries with no domain part."
+msgstr "Ne retransmet pas les requêtes qui n'ont pas de domaine."
+
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Retourne les champs MX pour les machines locales."
+
+#: option.c:237
+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:238
+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:239
+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:240
+#, 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:241
+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:242
+msgid "Read DHCP host specs from file"
+msgstr "Lecture des spécifications d'hôtes DHCP à partir du fichier"
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr "Lecture des options DHCP à partir du fichier"
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "Ne charge PAS le fichier %s."
+
+#: option.c:245
+#, 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:246
+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:247
+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:248
+msgid "Map DHCP user class to tag."
+msgstr "Associe les classes d'utilisateurs ('user class') DHCP aux options."
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr "Associe les identifiants de circuits RFC3046 ('circuit-id') aux options"
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr "Associe les identifiants distants RFC3046 ('remote-id') aux options"
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr "Associe les identifiants de souscripteurs RFC3993 ('subscriber-id') aux options"
+
+#
+#: option.c:252
+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:253
+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:254
+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:255
+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:256
+#, 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:257
+msgid "Return MX records for local hosts."
+msgstr "Retourne les champs MX pour les machines locales."
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr "Spécifie un champ MX."
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Spécifie les options BOOTP pour le serveur DHCP."
+
+#: option.c:260
+#, 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:261
+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:262
+#, 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:263
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Options supplémentaires à associer aux clients DHCP."
+
+#: option.c:264
+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:265
+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:266
+#, 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:267
+msgid "Log DNS queries."
+msgstr "Enregistre les requêtes DNS dans un journal d'activité."
+
+#
+#: option.c:268
+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:269
+msgid "Do NOT read resolv.conf."
+msgstr "Ne pas lire le fichier resolv.conf."
+
+#: option.c:270
+#, 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:271
+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:272
+msgid "Never forward queries to specified domains."
+msgstr "Ne jamais retransmettre les requêtes pour les domaines spécifiés."
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Spécifie le domaine qui doit etre assigné aux baux DHCP."
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr "Spécifie la cible par défaut dans un champ MX."
+
+#: option.c:275
+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:276
+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:277
+#, 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:278
+msgid "Map DHCP vendor class to tag."
+msgstr "Associe les classes de fournisseurs ('vendor class') DHCP aux options."
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr "Affiche la version de Dnsmasq et les informations liées au copyright."
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Traduit les adresses IPV4 des serveurs amonts."
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr " Spécifie un champ SRV."
+
+#: option.c:282
+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:283
+#, 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:284
+#, 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:285
+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:286
+msgid "Specify TXT DNS record."
+msgstr "Spécifie un champ DNS TXT"
+
+#
+#: option.c:287
+msgid "Specify PTR DNS record."
+msgstr "Spécifie un champ DNS PTR"
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr "Donne le nom DNS pour l'adresse IPv4 de l'interface."
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr "Association uniquement aux interfaces réseau actuellement actives."
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Lecture des informations de DHCP statique à partir de %s."
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Autorise l'interface DBus pour la configuration des serveurs amonts, etc."
+
+#: option.c:292
+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:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Autorise l'allocation dynamique d'adresse pour bootp."
+
+#
+#: option.c:294
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Associe l'adresse MAC (avec les jokers) aux options."
+
+#: option.c:295
+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:296
+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:297
+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:298
+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:299
+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:300
+msgid "Do not use leasefile."
+msgstr "Ne pas utiliser de fichier de baux."
+
+#: option.c:301
+#, 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:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr "Vider le cache DNS lors du rechargement de %s."
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr "Ignorer les noms d'hôtes fournis par les clients DHCP"
+
+#: option.c:304
+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:305
+msgid "Enable integrated read-only TFTP server."
+msgstr "Activer le server TFTP intégré (fonctionnant en lecture seulement)"
+
+#: option.c:306
+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:307
+msgid "Add client IP address to tftp-root."
+msgstr "Ajouter les adresses IP clientes à la racine tftp ('tftp-root')."
+
+#: option.c:308
+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:309
+#, 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:310
+msgid "Disable the TFTP blocksize extension."
+msgstr "Désactivation de l'extension TFTP « taille de bloc »"
+
+#: option.c:311
+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:312
+msgid "Extra logging for DHCP."
+msgstr "Traces supplémentaires pour le DHCP."
+
+#: option.c:313
+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:314
+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:315
+msgid "Always perform DNS queries to all servers."
+msgstr "Toujours effectuer les requêtes DNS à tous les serveurs."
+
+#
+#: option.c:316
+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:317
+msgid "Use alternative ports for DHCP."
+msgstr "Utiliser des ports alternatifs pour le DHCP."
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr "Lancer le script 'lease-change' avec cet utilisateur."
+
+#
+#: option.c:319
+msgid "Specify NAPTR DNS record."
+msgstr "Spécifie un champ DNS NAPTR."
+
+#: option.c:320
+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:321
+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:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr "Spécifie un alias pour un nom DNS local."
+
+#
+#: option.c:323
+msgid "Prompt to send to PXE clients."
+msgstr "Invite à envoyer aux clients PXE."
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr "Service de démarrage pour menu PXE"
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr "vérification de la syntaxe de la configuration"
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Usage : dnsmasq [options]\n"
+"\n"
+
+#: option.c:615
+#, 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:617
+#, c-format
+msgid "Valid options are:\n"
+msgstr "Les options valides sont :\n"
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr "Options DHCP connues :\n"
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr "mauvaise valeur de 'dhcp-option'"
+
+#
+#: option.c:792
+msgid "bad IP address"
+msgstr "mauvaise adresse IP"
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr "mauvais domaine dans dhcp-option"
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr "dhcp-option trop long"
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr "valeur illégale pour 'dhcp-match'"
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr "Une option ne pouvant être spécifié qu'une seule fois à été donnée plusieurs fois."
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr "Mot-clef ne pouvant être répété"
+
+#: option.c:1086 tftp.c:359
+#, c-format
+msgid "cannot access %s: %s"
+msgstr "Ne peut pas lire %s : %s"
+
+#
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr "une seule valeur est autorisée pour 'dhcp-hostsfile'"
+
+#
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr "une seule valeur est autorisée pour 'dhcp-optsfile'"
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr "Mauvaise préference MX"
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr "mauvais nom MX"
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr "mauvaise cible MX"
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr "ne peut exécuter de script sous uClinux"
+
+#: option.c:1214
+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:1442 option.c:1446
+msgid "bad port"
+msgstr "mauvais port"
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr "association d'interface non supportée"
+
+#
+#: option.c:1611
+msgid "bad port range"
+msgstr "mauvaise gamme de ports"
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr "mauvaise interface-pont"
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr "mauvaise plage d'adresses DHCP (dhcp-range)"
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr "une seule étiquette netid est autorisée"
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr "plage d'adresses DHCP incohérente"
+
+#
+#: option.c:1912
+msgid "bad DHCP host name"
+msgstr "mauvais nom d'hôte DHCP"
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr "numéro de port invalide"
+
+#
+#: option.c:2284
+msgid "invalid alias range"
+msgstr "poids invalide"
+
+#
+#: option.c:2297
+msgid "bad interface name"
+msgstr "mauvais nom d'interface"
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr "mauvais CNAME"
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr "ce CNAME existe déja"
+
+#
+#: option.c:2347
+msgid "bad PTR record"
+msgstr "mauvais champ PTR"
+
+#
+#: option.c:2378
+msgid "bad NAPTR record"
+msgstr "mauvais champ NAPTR"
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr "chaîne du champ TXT trop longue"
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr "mauvais champ TXT"
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr "mauvais champ SRV"
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr "mauvaise cible SRV"
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr "priorité invalide"
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr "poids invalide"
+
+#: option.c:2514
+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:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr "trop de niveaux de récursion pour les fichiers dans %s"
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "Ne peut pas lire %s : %s"
+
+#: option.c:2626
+msgid "missing \""
+msgstr "il manque \""
+
+#: option.c:2673
+msgid "bad option"
+msgstr "mauvaise option"
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr "paramètre en trop"
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr "paramètre manquant"
+
+#: option.c:2685
+msgid "error"
+msgstr "erreur"
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s à la ligne %d de %%s"
+
+#: option.c:2740 option.c:2771
+#, c-format
+msgid "read %s"
+msgstr "Lecture de %s"
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr "Version de Dnsmasq %s %s\n"
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Options à la compilation %s\n"
+"\n"
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Ce logiciel est fourni sans AUCUNE GARANTIE.\n"
+
+#: option.c:2846
+#, 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:2847
+#, 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:2858
+msgid "try --help"
+msgstr "essayez avec --help"
+
+#: option.c:2860
+msgid "try -w"
+msgstr "essayez avec -w"
+
+#: option.c:2863
+#, c-format
+msgid "bad command line options: %s"
+msgstr "mauvaises options en ligne de commande : %s."
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "ne peut pas obtenir le nom de la machine : %s"
+
+#: option.c:2932
+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:2942
+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:2945 network.c:754 dhcp.c:734
+#, c-format
+msgid "failed to read %s: %s"
+msgstr "impossible de lire %s : %s"
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr "pas de directive de recherche trouvée dans %s"
+
+#: option.c:2983
+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:2987
+msgid "syntax check OK"
+msgstr "vérification de syntaxe OK"
+
+#: forward.c:409
+#, 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:437
+msgid "possible DNS-rebind attack detected"
+msgstr "détection d'une possible attaque de type DNS-rebind"
+
+#: network.c:73
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "interface %s inconnue spécifiée comme interface de pont"
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr "impossible de créer une socket de lecture : %s"
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr "impossible d'activer les options IPV6 sur la socket de lecture : %s"
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr "impossible de lier la socket de lecture pour %s : %s"
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr "impossible de lire sur la socket : %s"
+
+#: network.c:467
+#, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr "impossible de créer une socket TFTP : %s"
+
+#: network.c:661
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "impossible de lier la socket de serveur pour %s : %s"
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignore le serveur de nom %s - interface locale"
+
+#: network.c:705
+#, 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:720
+msgid "unqualified"
+msgstr "non-qualifié(e)"
+
+#: network.c:720
+msgid "names"
+msgstr "noms"
+
+#: network.c:722
+msgid "default"
+msgstr "défaut"
+
+#: network.c:724
+msgid "domain"
+msgstr "domaine"
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "utilise les adresses locales seulement pour %s %s"
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "utilise le serveur de nom %s#%d pour %s %s"
+
+#: network.c:732
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "utilise le serveur de nom %s#%d (via %s)"
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "utilise le serveur de nom %s#%d"
+
+#
+#: dnsmasq.c:146
+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:151
+msgid "asychronous logging is not available under Solaris"
+msgstr "l'écriture de traces en mode asynchrone n'est pas disponible sous Solaris."
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "impossible de trouver la liste des interfaces : %s"
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr "interface %s inconnue"
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr "pas d'interface avec l'adresse %s"
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr "Erreur DBus : %s"
+
+#: dnsmasq.c:204
+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:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr "utilisateur ou groupe inconnu : %s"
+
+#: dnsmasq.c:287
+#, 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:448
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr "démarrage avec le DNS désactivé (version %s)"
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "demarré, version %s (taille de cache %d)"
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "démarrage avec le cache désactivé (version %s)"
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr "options à la compilation : %s"
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr "Support DBus autorisé : connecté au bus système"
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr "Support DBus autorisé : connexion au bus en attente"
+
+#: dnsmasq.c:467
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "Impossible de changer pour l'utilisateur %s : %s"
+
+#: dnsmasq.c:471
+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:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "attention : l'interface %s n'existe pas actuellement"
+
+#: dnsmasq.c:481
+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:484
+msgid "warning: no upstream servers configured"
+msgstr "attention : aucun serveur amont n'est configuré"
+
+#: dnsmasq.c:488
+#, 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:501
+#, 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:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr "DHCP, proxy sur le sous-réseau %.0s%s%.0s"
+
+#: dnsmasq.c:504
+#, 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:519
+msgid "root is "
+msgstr "root est"
+
+#
+#: dnsmasq.c:519
+msgid "enabled"
+msgstr "activé"
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr "mode sécurisé"
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr "le nombre maximum de transferts TFTP simultanés sera restreint à %d"
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr "connecté au systeme DBus"
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr "Ne peut se lancer en tâche de fond : %s"
+
+#: dnsmasq.c:760
+#, c-format
+msgid "failed to create helper: %s"
+msgstr "impossible de créer le 'helper' : %s"
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr "impossible de configurer la capacité %s"
+
+#: dnsmasq.c:767
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "Impossible de changer l'identifiant utilisateur pour %s : %s"
+
+#: dnsmasq.c:772
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "Impossible de changer l'identifiant de groupe pour %s : %s"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "impossible de lire le fichier de PID %s : %s"
+
+#: dnsmasq.c:778
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "Ne peut pas lire %s : %s"
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr "Le processus fils a été terminé par le signal %d"
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr "Le processus fils s'est terminé avec le statut %d"
+
+#: dnsmasq.c:841
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr "impossible d'exécuter à %s : %s"
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr "sortie sur réception du signal SIGTERM"
+
+#: dnsmasq.c:903
+#, c-format
+msgid "failed to access %s: %s"
+msgstr "impossible d'accéder à %s : %s"
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr "Lecture de %s"
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "ne peut créer de socket en mode raw pour ICMP : %s."
+
+#: dhcp.c:226
+#, 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:385
+#, 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:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "mauvaise ligne dans %s ligne %d"
+
+#: dhcp.c:815
+#, 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:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "adresse IP %s dupliquée dans la directive dhcp-config."
+
+#: dhcp.c:900
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "adresse IP %s dupliquée dans %s."
+
+#: dhcp.c:943
+#, 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:948
+#, 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:66
+#, 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:92
+msgid "too many stored leases"
+msgstr "beaucoup trop de baux enregistrés"
+
+#: lease.c:128
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "Ne peut pas exécuter le script lease-init %s : %s"
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr "le script lease-init a retourné le code %s"
+
+#: lease.c:234
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "impossible de lire %s : %s (prochain essai dans %us)"
+
+#: rfc2131.c:336
+#, 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:337
+msgid "with subnet selector"
+msgstr "avec sélecteur de sous-reseau"
+
+#: rfc2131.c:337
+msgid "via"
+msgstr "par l'intermédiaire de"
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr "%u sous-réseaux DHCP disponibles : %s/%s"
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr "%u la gamme DHCP disponible est : %s -- %s"
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr "désactivé"
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr "ignoré"
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr "adresse déjà utilisée"
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr "pas d'adresse disponible"
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr "mauvais réseau"
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr "pas d'adresse configurée"
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr "plus aucun bail disponible"
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr "le client %u fourni le nom : %s"
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr "%u Classe de vendeur ('Vendor Class') : %s"
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr "%u Classe d'utilisateur : %s"
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr "Service PXE BIS (Boot Integrity Services) non supporté"
+
+#: rfc2131.c:853
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "désactive l'adresse statique DHCP %s pour %s"
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr "bail inconnu"
+
+#: rfc2131.c:906
+#, 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:916
+#, 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:919
+#, 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:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr "pas d'identifiant unique"
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr "mauvais identifiant de serveur"
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr "mauvaise adresse"
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr "bail non trouvé"
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr "adresse non disponible"
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr "bail statique disponible"
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr "adresse reservée"
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr "abandon du bail de %s pour %s"
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr "%u options: %s"
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr "%u nom de fichier 'bootfile' : %s"
+
+#: rfc2131.c:1605
+#, c-format
+msgid "%u server name: %s"
+msgstr "%u nom du serveur : %s"
+
+#: rfc2131.c:1613
+#, c-format
+msgid "%u next server: %s"
+msgstr "%u serveur suivant : %s"
+
+#: rfc2131.c:1680
+#, 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:1919
+msgid "PXE menu too large"
+msgstr "menu PXE trop grand"
+
+#: rfc2131.c:2034
+#, 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:2052
+#, c-format
+msgid "%u requested options: %s"
+msgstr "%u options demandées : %s"
+
+#: netlink.c:66
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "ne peux lier une socket netlink : %s"
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "impossible de créer une socket BPF pour DHCP : %s"
+
+#: bpf.c:178
+#, 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:179
+msgid "unable to get free port for TFTP"
+msgstr "impossible d'obtenir un port libre pour TFTP"
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr "requête de %s non supportée"
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr "TFTP envoyé %s à %s"
+
+#: tftp.c:305
+#, c-format
+msgid "file %s not found"
+msgstr "fichier %s non trouvé"
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr "TFTP erreur %d %s reçu de %s"
+
+#: tftp.c:447
+#, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr "TFTP : impossible d'envoyer %s à %s"
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr "débordement : %d traces perdues"
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr "trace perdue : %s"
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr "IMPOSSIBLE de démarrer"
+
+#~ 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 "bad dhcp-host"
+#~ msgstr "mauvais dhcp-host"
+
+#~ 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 100755
index 0000000..a5ff6e8
--- /dev/null
+++ b/po/id.po
@@ -0,0 +1,1727 @@
+# 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:764
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: cache.c:798 dhcp.c:785
+#, fuzzy, c-format
+msgid "bad address at %s line %d"
+msgstr "kesalahan nama pada %s baris %d"
+
+# OK
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "kesalahan nama pada %s baris %d"
+
+# OK
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "membaca %s - %d alamat"
+
+# OK
+#: cache.c:902
+msgid "cleared cache"
+msgstr "cache telah dihapus"
+
+# OK
+#: cache.c:933 option.c:1055
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+# OK
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+# OK
+#: cache.c:1130
+#, 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:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1155
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+# OK
+#: util.c:59
+#, fuzzy, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "gagal mendengarkan di socket: %s"
+
+# OK
+#: util.c:191
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "gagal memuat %S: %m"
+
+# OK
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr "tidak bisa mendapatkan memory"
+
+# OK
+#: util.c:239
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+# OK
+#: util.c:247
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "gagal memuat %S: %m"
+
+# OK
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr "tak terbatas"
+
+# OK
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr "Tentukan alamat lokal untuk mendengarkan."
+
+# OK
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Menghasilkan ipaddr untuk semua host dalam domain yang dipilih."
+
+# OK
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Fake pencarian balik untuk alamat private sesuai dengan RFC1918."
+
+# OK
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Perlakukan ipaddr sebagai NXDOMAIN (mengalahkan wildcard Verisign)."
+
+# OK
+#: option.c:232
+#, 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:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Tentukan file konfigurasi (default %s)."
+
+# OK
+#: option.c:234
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "JANGAN berjalan di background: berjalan dalam modus debug."
+
+# OK
+#: option.c:235
+msgid "Do NOT forward queries with no domain part."
+msgstr "JANGAN teruskan permintaan tanpa bagian domain."
+
+# OK
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Mengembalikan record MX untuk diri sendiri host-host lokal."
+
+# OK
+#: option.c:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Melengkapi nama-nama di /etc/hosts dengan akhiran domain."
+
+# OK
+#: option.c:238
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Jangan meneruskan permintaan DNS spurious dari host-host Windows."
+
+# OK
+#: option.c:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Bolehkan DHCP dalam jangkauan yang diberikan dengan durasi lease."
+
+# OK
+#: option.c:240
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Ubah ke group ini setelah mulai (default %s)."
+
+# OK
+#: option.c:241
+msgid "Set address or hostname for a specified machine."
+msgstr "Setel alamat atau nama host untuk mesin yang disebutkan."
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr ""
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr ""
+
+# OK
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "JANGAN muat file %s."
+
+# OK
+#: option.c:245
+#, 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:246
+msgid "Specify interface(s) to listen on."
+msgstr "Sebutkan antarmuka untuk mendengarkan."
+
+# OK
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Sebutkan antarmuka untuk TIDAK mendengarkan."
+
+# OK
+#: option.c:248
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Petakan kelas user DHCP ke setelan yang dipilih."
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+# OK
+#: option.c:252
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih."
+
+# OK
+#: option.c:253
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih."
+
+# OK
+#: option.c:254
+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:255
+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:256
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Sebutkan lokasi untuk menyimpan lease DHCP (default %s)."
+
+# OK
+#: option.c:257
+msgid "Return MX records for local hosts."
+msgstr "Kembalikan rekord MX untuk host-host lokal."
+
+# OK
+#: option.c:258
+msgid "Specify an MX record."
+msgstr "Sebutkan sebuah rekord MX."
+
+# OK
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Sebutkan pilihan-pilihan BOOTP untuk DHCP server."
+
+#: option.c:260
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "Jangan kumpulkan file %s, muat kembali saat SIGHUP."
+
+# OK
+#: option.c:261
+msgid "Do NOT cache failed search results."
+msgstr "JANGAN menyimpan hasil pencarian yang gagal."
+
+# OK
+#: option.c:262
+#, 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:263
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP."
+
+#: option.c:264
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+# OK
+#: option.c:265
+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:266
+#, 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:267
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "Permintaan log."
+
+# OK
+#: option.c:268
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Paksa port asal untuk permintaan ke atas."
+
+# OK
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr "JANGAN baca resolv.conf."
+
+# OK
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Sebutkan path ke resolv.conf (default %s)."
+
+# OK
+#: option.c:271
+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:272
+msgid "Never forward queries to specified domains."
+msgstr "JANGAN pernah meneruskan permintaan ke domain yang disebutkan."
+
+# OK
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Sebutkan domain yang digunakan dalam lease DHCP."
+
+# OK
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr "Sebutkan tujuan default dalam rekord MX."
+
+# OK
+#: option.c:275
+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:276
+#, 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:277
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Ubah ke user ini setelah mulai. (default %s)."
+
+# OK
+#: option.c:278
+#, fuzzy
+msgid "Map DHCP vendor class to tag."
+msgstr "Memetakan kelas vendor DHCP ke daftar pilihan."
+
+# OK
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr "Menampilkan versi dan informasi hak cipta dnsmasq."
+
+# OK
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Terjemahkan alamat-alamat IPv4 dari server-server di atas."
+
+# OK
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr "Sebutkan rekord SRV."
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+# OK
+#: option.c:283
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Sebutkan path file PID. (default %s)."
+
+# OK
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
+
+# OK
+#: option.c:285
+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:286
+msgid "Specify TXT DNS record."
+msgstr "Sebutkan rekord TXT DNS."
+
+# OK
+#: option.c:287
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Sebutkan rekord TXT DNS."
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+# OK
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr "Hanya kaitkan ke antarmuka yang sedang digunakan saja."
+
+# OK
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Baca informasi statik host DHCP dari %s."
+
+# OK
+#: option.c:291
+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:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "JANGAN menyediakan DHCP pada antarmuka ini, hanya menyediakan DNS."
+
+# OK
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Mungkinkan alokasi alamat dinamis untuk bootp."
+
+# OK
+#: option.c:294
+#, fuzzy
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Memetakan kelas vendor DHCP ke daftar pilihan."
+
+#: option.c:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:296
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:297
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:298
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+# OK
+#: option.c:299
+#, fuzzy
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Ubah ke user ini setelah mulai. (default %s)."
+
+#: option.c:300
+msgid "Do not use leasefile."
+msgstr ""
+
+# OK
+#: option.c:301
+#, fuzzy, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
+
+#: option.c:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:304
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:305
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:308
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+# OK
+#: option.c:309
+#, fuzzy, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)."
+
+#: option.c:310
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:316
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr ""
+
+# OK
+#: option.c:319
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Sebutkan rekord TXT DNS."
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+# OK
+#: option.c:323
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP."
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr ""
+
+# OK
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Penggunaan: dnsmasq [pilihan]\n"
+"\n"
+
+# OK
+#: option.c:615
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "Gunakan pilihan pendek saja pada perintah baris.\n"
+
+# OK
+#: option.c:617
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "Pilihan yang boleh adalah:\n"
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+# OK
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr "dhcp-option salah"
+
+# OK
+#: option.c:792
+#, fuzzy
+msgid "bad IP address"
+msgstr "membaca %s - %d alamat"
+
+# OK
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr "domain dalam dhcp-option salah"
+
+# OK
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr "dhcp-option terlalu panjang"
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr ""
+
+# OK
+#: option.c:1086 tftp.c:359
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr ""
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr ""
+
+# OK
+#: option.c:1183
+msgid "bad MX preference"
+msgstr "kesukaan MX salah"
+
+# OK
+#: option.c:1188
+msgid "bad MX name"
+msgstr "nama MX salah"
+
+# OK
+#: option.c:1202
+msgid "bad MX target"
+msgstr "target MX salah"
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+# OK
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr "port salah"
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr ""
+
+# OK
+#: option.c:1611
+#, fuzzy
+msgid "bad port range"
+msgstr "port salah"
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr ""
+
+# OK
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr "dhcp-range salah"
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr ""
+
+# OK
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr "jangkauan DHCP tidak konsisten"
+
+# OK
+#: option.c:1912
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "nama MX salah"
+
+# OK
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr "nomor port tidak benar"
+
+# OK
+#: option.c:2284
+#, fuzzy
+msgid "invalid alias range"
+msgstr "weight tidak benar"
+
+# OK
+#: option.c:2297
+#, fuzzy
+msgid "bad interface name"
+msgstr "nama MX salah"
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr ""
+
+# OK
+#: option.c:2347
+#, fuzzy
+msgid "bad PTR record"
+msgstr "rekord SRV salah"
+
+# OK
+#: option.c:2378
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "rekord SRV salah"
+
+# OK
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr "string rekord TXT terlalu panjang"
+
+# OK
+#: option.c:2451
+msgid "bad TXT record"
+msgstr "rekord TXT salah"
+
+# OK
+#: option.c:2467
+msgid "bad SRV record"
+msgstr "rekord SRV salah"
+
+# OK
+#: option.c:2474
+msgid "bad SRV target"
+msgstr "target SRV salah"
+
+# OK
+#: option.c:2488
+msgid "invalid priority"
+msgstr "prioritas tidak benar"
+
+# OK
+#: option.c:2495
+msgid "invalid weight"
+msgstr "weight tidak benar"
+
+#: option.c:2514
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr ""
+
+# OK
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+# OK
+#: option.c:2626
+msgid "missing \""
+msgstr "kurang \""
+
+# OK
+#: option.c:2673
+msgid "bad option"
+msgstr "pilihan salah"
+
+# OK
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr "parameter berlebihan"
+
+# OK
+#: option.c:2677
+msgid "missing parameter"
+msgstr "parameter kurang"
+
+# OK
+#: option.c:2685
+msgid "error"
+msgstr "kesalahan"
+
+# OK
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s pada baris %d dari %%s"
+
+# OK
+#: option.c:2740 option.c:2771
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "membaca %s"
+
+# OK
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr "Dnsmasq versi %s %s\n"
+
+# OK
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Pilihan-pilihan saat kompilasi %s\n"
+"\n"
+
+# OK
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Perangkat lunak ini tersedia TANPA JAMINAN SEDIKITPUN.\n"
+
+# OK
+#: option.c:2846
+#, 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:2847
+#, 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:2858
+msgid "try --help"
+msgstr ""
+
+#: option.c:2860
+msgid "try -w"
+msgstr ""
+
+# OK
+#: option.c:2863
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "pilihan baris perintah salah: %s."
+
+# OK
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "tidak bisa mendapatkan host-name: %s"
+
+# OK
+#: option.c:2932
+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:2942
+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:2945 network.c:754 dhcp.c:734
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "gagal membaca %s: %s"
+
+# OK
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr "tidak ditemukan direktif search di %s"
+
+#: option.c:2983
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:2987
+msgid "syntax check OK"
+msgstr ""
+
+# OK
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "nameserver %s menolak melakukan resolusi rekursif"
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr ""
+
+# OK
+#: network.c:73
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "antarmuka tidak dikenal %s"
+
+# OK
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr "gagal membuat socket: %s "
+
+# OK
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr "gagal menyetel IPV6 pada socket: %s"
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr "gagal mem-bind socket untuk mendengarkan %s: %s"
+
+# OK
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr "gagal mendengarkan di socket: %s"
+
+# OK
+#: network.c:467
+#, fuzzy, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr "gagal membuat socket: %s "
+
+#: network.c:661
+#, fuzzy, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "gagal mem-bind socket untuk mendengarkan %s: %s"
+
+# OK
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "mengabaikan nameserver %s - antarmuka lokal"
+
+# OK
+#: network.c:705
+#, 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:720
+msgid "unqualified"
+msgstr "tidak memenuhi syarat"
+
+#: network.c:720
+msgid "names"
+msgstr ""
+
+#: network.c:722
+msgid "default"
+msgstr ""
+
+# OK
+#: network.c:724
+msgid "domain"
+msgstr "domain"
+
+# OK
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "menggunakan alamat lokal saja untuk %s %s"
+
+# OK
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "menggunakan nameserver %s#%d untuk %s %s"
+
+# OK
+#: network.c:732
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "menggunakan nameserver %s#%d"
+
+# OK
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "menggunakan nameserver %s#%d"
+
+# OK
+#: dnsmasq.c:146
+#, 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:151
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+# OK
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "gagal mendapatkan daftar antarmuka: %s"
+
+# OK
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr "antarmuka tidak dikenal %s"
+
+# OK
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr "tidak ada antarmuka dengan alamat %s"
+
+# OK
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr "DBus error: %s"
+
+# OK
+#: dnsmasq.c:204
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h"
+
+#: dnsmasq.c:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:448
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "dimulai, cache versi %s di disable"
+
+# OK
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "dimulai, versi %s ukuran cache %d"
+
+# OK
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "dimulai, cache versi %s di disable"
+
+# OK
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr "pilihan-pilihan saat kompilasi: %s"
+
+# OK
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr "dukungan DBus dimungkinkan: terkoneksi pada bus sistem"
+
+# OK
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr "dukungan DBus dimungkinkan: koneksi bus ditunda"
+
+# OK
+#: dnsmasq.c:467
+#, fuzzy, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: dnsmasq.c:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "setelan opsi --bind-interfaces disebabkan keterbatasan OS"
+
+# OK
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "peringatan: antarmuka %s tidak ada"
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+# OK
+#: dnsmasq.c:484
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "menyetel server-server di atas dengan DBus"
+
+#: dnsmasq.c:488
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+# OK
+#: dnsmasq.c:501
+#, 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:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, jangkaun IP %s -- %s, waktu lease %s"
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr ""
+
+# OK
+#: dnsmasq.c:519
+#, fuzzy
+msgid "enabled"
+msgstr "di disable"
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+# OK
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr "terhubung ke sistem DBus"
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:760
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "gagal membaca %s: %s"
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+# OK
+#: dnsmasq.c:767
+#, fuzzy, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: dnsmasq.c:772
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "gagal memuat nama-nama dari %s: %s"
+
+# OK
+#: dnsmasq.c:775
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "gagal membaca %s: %s"
+
+# OK
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "tidak bisa membuka %s:%s"
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+# OK
+#: dnsmasq.c:841
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "gagal mengakses %s: %s"
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr "keluar karena menerima SIGTERM"
+
+# OK
+#: dnsmasq.c:903
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "gagal mengakses %s: %s"
+
+# OK
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr "membaca %s"
+
+# OK
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "tidak dapat membuat socket ICMP raw: %s"
+
+#: dhcp.c:226
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+# OK
+#: dhcp.c:385
+#, 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:772
+#, fuzzy, c-format
+msgid "bad line at %s line %d"
+msgstr "kesalahan nama pada %s baris %d"
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+# OK
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "alamat IP kembar %s dalam direktif dhcp-config"
+
+# OK
+#: dhcp.c:900
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "alamat IP kembar %s dalam direktif dhcp-config"
+
+#: dhcp.c:943
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+# OK
+#: dhcp.c:948
+#, 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:66
+#, fuzzy, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "tidak dapat membuka atau membuat file lease: %s"
+
+# OK
+#: lease.c:92
+msgid "too many stored leases"
+msgstr "terlalu banyak lease yang disimpan"
+
+# OK
+#: lease.c:128
+#, fuzzy, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "tidak bisa membaca %s: %s"
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+# OK
+#: lease.c:234
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "gagal membaca %s: %s"
+
+# OK
+#: rfc2131.c:336
+#, 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:337
+msgid "with subnet selector"
+msgstr "dengan pemilih subnet"
+
+# OK
+#: rfc2131.c:337
+msgid "via"
+msgstr "lewat"
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr ""
+
+# OK
+#: rfc2131.c:384
+msgid "disabled"
+msgstr "di disable"
+
+# OK
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr "diabaikan"
+
+# OK
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr "alamat telah digunakan"
+
+# OK
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr "tak ada alamat yang tersedia"
+
+# OK
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr "jaringan yang salah"
+
+# OK
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr "tak ada alamat yang disetel"
+
+# OK
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr "tak ada lease yang tersisa"
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr ""
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr ""
+
+# OK
+#: rfc2131.c:853
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "men-disable alamat statik DHCP %s"
+
+# OK
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr "lease tidak diketahui"
+
+#: rfc2131.c:906
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:916
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:919
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr ""
+
+# OK
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr "alamat salah"
+
+# OK
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr "lease tak ditemukan"
+
+# OK
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr "alamat tak tersedia"
+
+# OK
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr "lease statik tak tersedia"
+
+# OK
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr "alamat telah dipesan"
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+# OK
+#: rfc2131.c:1605
+#, fuzzy, c-format
+msgid "%u server name: %s"
+msgstr "DBus error: %s"
+
+# OK
+#: rfc2131.c:1613
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "DBus error: %s"
+
+#: rfc2131.c:1680
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:1919
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+# OK
+#: rfc2131.c:2052
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "pilihan-pilihan saat kompilasi: %s"
+
+# OK
+#: netlink.c:66
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "tidak bisa mem-bind netlink socket: %s"
+
+# OK
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "tidak dapat membuat socket DHCP BPF: %s"
+
+# OK
+#: bpf.c:178
+#, 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:179
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr ""
+
+# OK
+#: tftp.c:305
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "lease tak ditemukan"
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr ""
+
+# OK
+#: tftp.c:447
+#, fuzzy, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr "gagal membaca %s: %s"
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+# OK
+#: log.c:415
+msgid "FAILED to start up"
+msgstr "GAGAL untuk memulai"
+
+# 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 "bad dhcp-host"
+#~ msgstr "dhcp-host salah"
+
+# 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 100755
index 0000000..37a8c4b
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,1411 @@
+# 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:764
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr ""
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr ""
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr ""
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr ""
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr ""
+
+#: cache.c:933 option.c:1055
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr ""
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1130
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr ""
+
+#: cache.c:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1155
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:59
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr ""
+
+#: util.c:191
+msgid "failed to allocate memory"
+msgstr ""
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr ""
+
+#: util.c:239
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr ""
+
+#: util.c:247
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr ""
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr ""
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr ""
+
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr ""
+
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr ""
+
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr ""
+
+#: option.c:232
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr ""
+
+#: option.c:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr ""
+
+#: option.c:234
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr ""
+
+#: option.c:235
+msgid "Do NOT forward queries with no domain part."
+msgstr ""
+
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr ""
+
+#: option.c:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr ""
+
+#: option.c:238
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr ""
+
+#: option.c:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr ""
+
+#: option.c:240
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr ""
+
+#: option.c:241
+msgid "Set address or hostname for a specified machine."
+msgstr ""
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr ""
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr ""
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr ""
+
+#: option.c:245
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr ""
+
+#: option.c:246
+msgid "Specify interface(s) to listen on."
+msgstr ""
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr ""
+
+#: option.c:248
+msgid "Map DHCP user class to tag."
+msgstr ""
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:252
+msgid "Don't do DHCP for hosts with tag set."
+msgstr ""
+
+#: option.c:253
+msgid "Force broadcast replies for hosts with tag set."
+msgstr ""
+
+#: option.c:254
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr ""
+
+#: option.c:255
+msgid "Assume we are the only DHCP server on the local network."
+msgstr ""
+
+#: option.c:256
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:257
+msgid "Return MX records for local hosts."
+msgstr ""
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr ""
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr ""
+
+#: option.c:260
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr ""
+
+#: option.c:261
+msgid "Do NOT cache failed search results."
+msgstr ""
+
+#: option.c:262
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr ""
+
+#: option.c:263
+msgid "Specify options to be sent to DHCP clients."
+msgstr ""
+
+#: option.c:264
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:265
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr ""
+
+#: option.c:266
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr ""
+
+#: option.c:267
+msgid "Log DNS queries."
+msgstr ""
+
+#: option.c:268
+msgid "Force the originating port for upstream DNS queries."
+msgstr ""
+
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr ""
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr ""
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr ""
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr ""
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr ""
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr ""
+
+#: option.c:275
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr ""
+
+#: option.c:276
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr ""
+
+#: option.c:277
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr ""
+
+#: option.c:278
+msgid "Map DHCP vendor class to tag."
+msgstr ""
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr ""
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr ""
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr ""
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:283
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr ""
+
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:285
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr ""
+
+#: option.c:286
+msgid "Specify TXT DNS record."
+msgstr ""
+
+#: option.c:287
+msgid "Specify PTR DNS record."
+msgstr ""
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr ""
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr ""
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr ""
+
+#: option.c:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr ""
+
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr ""
+
+#: option.c:294
+msgid "Map MAC address (with wildcards) to option set."
+msgstr ""
+
+#: option.c:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:296
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:297
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:298
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:299
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr ""
+
+#: option.c:300
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:301
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr ""
+
+#: option.c:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:304
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:305
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:308
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:309
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr ""
+
+#: option.c:310
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:316
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:319
+msgid "Specify NAPTR DNS record."
+msgstr ""
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:323
+msgid "Prompt to send to PXE clients."
+msgstr ""
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+
+#: option.c:615
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr ""
+
+#: option.c:617
+#, c-format
+msgid "Valid options are:\n"
+msgstr ""
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr ""
+
+#: option.c:792
+msgid "bad IP address"
+msgstr ""
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr ""
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr ""
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1086 tftp.c:359
+#, c-format
+msgid "cannot access %s: %s"
+msgstr ""
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr ""
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr ""
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr ""
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr ""
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr ""
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr ""
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1611
+msgid "bad port range"
+msgstr ""
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr ""
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr ""
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr ""
+
+#: option.c:1912
+msgid "bad DHCP host name"
+msgstr ""
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr ""
+
+#: option.c:2284
+msgid "invalid alias range"
+msgstr ""
+
+#: option.c:2297
+msgid "bad interface name"
+msgstr ""
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2347
+msgid "bad PTR record"
+msgstr ""
+
+#: option.c:2378
+msgid "bad NAPTR record"
+msgstr ""
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr ""
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr ""
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr ""
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr ""
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr ""
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr ""
+
+#: option.c:2514
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr ""
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: option.c:2626
+msgid "missing \""
+msgstr ""
+
+#: option.c:2673
+msgid "bad option"
+msgstr ""
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr ""
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr ""
+
+#: option.c:2685
+msgid "error"
+msgstr ""
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr ""
+
+#: option.c:2740 option.c:2771
+#, c-format
+msgid "read %s"
+msgstr ""
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr ""
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr ""
+
+#: option.c:2846
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:2847
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:2858
+msgid "try --help"
+msgstr ""
+
+#: option.c:2860
+msgid "try -w"
+msgstr ""
+
+#: option.c:2863
+#, c-format
+msgid "bad command line options: %s"
+msgstr ""
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr ""
+
+#: option.c:2932
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr ""
+
+#: option.c:2942
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr ""
+
+#: option.c:2945 network.c:754 dhcp.c:734
+#, c-format
+msgid "failed to read %s: %s"
+msgstr ""
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr ""
+
+#: option.c:2983
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:2987
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr ""
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr ""
+
+#: network.c:73
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr ""
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr ""
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr ""
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr ""
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr ""
+
+#: network.c:467
+#, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr ""
+
+#: network.c:661
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr ""
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr ""
+
+#: network.c:705
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr ""
+
+#: network.c:720
+msgid "unqualified"
+msgstr ""
+
+#: network.c:720
+msgid "names"
+msgstr ""
+
+#: network.c:722
+msgid "default"
+msgstr ""
+
+#: network.c:724
+msgid "domain"
+msgstr ""
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:732
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:146
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:151
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr ""
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr ""
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr ""
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr ""
+
+#: dnsmasq.c:204
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:448
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr ""
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr ""
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr ""
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr ""
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr ""
+
+#: dnsmasq.c:467
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr ""
+
+#: dnsmasq.c:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr ""
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr ""
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:484
+msgid "warning: no upstream servers configured"
+msgstr ""
+
+#: dnsmasq.c:488
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:501
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr ""
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:760
+#, c-format
+msgid "failed to create helper: %s"
+msgstr ""
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:767
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:772
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:775
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:841
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr ""
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr ""
+
+#: dnsmasq.c:903
+#, c-format
+msgid "failed to access %s: %s"
+msgstr ""
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr ""
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr ""
+
+#: dhcp.c:226
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:385
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr ""
+
+#: dhcp.c:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr ""
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr ""
+
+#: dhcp.c:900
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr ""
+
+#: dhcp.c:943
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:948
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr ""
+
+#: lease.c:66
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr ""
+
+#: lease.c:92
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:128
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr ""
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:234
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr ""
+
+#: rfc2131.c:336
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr ""
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:853
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr ""
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:906
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:916
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:919
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1605
+#, c-format
+msgid "%u server name: %s"
+msgstr ""
+
+#: rfc2131.c:1613
+#, c-format
+msgid "%u next server: %s"
+msgstr ""
+
+#: rfc2131.c:1680
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:1919
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2052
+#, c-format
+msgid "%u requested options: %s"
+msgstr ""
+
+#: netlink.c:66
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr ""
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr ""
+
+#: bpf.c:178
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr ""
+
+#: tftp.c:179
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr ""
+
+#: tftp.c:305
+#, c-format
+msgid "file %s not found"
+msgstr ""
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:447
+#, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr ""
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr ""
diff --git a/po/no.po b/po/no.po
new file mode 100755
index 0000000..f70e56b
--- /dev/null
+++ b/po/no.po
@@ -0,0 +1,1508 @@
+# 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:764
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "feilet å laste navn fra %s: %s"
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "dårlig adresse ved %s linje %d"
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "dårlig navn ved %s linje %d"
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "les %s - %d adresser"
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr "mellomlager tømt"
+
+#: cache.c:933 option.c:1055
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1130
+#, 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:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1155
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:59
+#, fuzzy, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "feilet å lytte på socket: %s"
+
+#: util.c:191
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "feilet å laste %d bytes"
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr "kunne ikke få minne"
+
+#: util.c:239
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: util.c:247
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "feilet å laste %d bytes"
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr "uendelig"
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr "Spesifiser lokal(e) adresse(r) å lytte på."
+
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Returner ipaddr for alle verter i det spesifiserte domenet."
+
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Forfalsk revers oppslag for RFC1918 private adresse områder."
+
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Behandle ipaddr som NXDOMAIN (omgår Verisign wildcard)."
+
+#: option.c:232
+#, 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:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Spesifiser konfigurasjonsfil (standard er %s)."
+
+#: option.c:234
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "IKKE legg (fork) som bakgrunnsprosess: kjør i debug modus."
+
+#: option.c:235
+msgid "Do NOT forward queries with no domain part."
+msgstr "IKKE videresend oppslag som mangler domene del."
+
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Returner selv-pekende MX post for lokale verter."
+
+#: option.c:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Utvid enkle navn i /etc/hosts med domene-suffiks."
+
+#: option.c:238
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Ikke videresend falske/uekte DNS forespørsler fra Windows verter."
+
+#: option.c:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Aktiver DHCP i det gitte området med leie varighet"
+
+#: option.c:240
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Skift til denne gruppen etter oppstart (standard er %s)."
+
+#: option.c:241
+msgid "Set address or hostname for a specified machine."
+msgstr "Sett adresse eller vertsnavn for en spesifikk maskin."
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr ""
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr ""
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "IKKE last %s filen."
+
+#: option.c:245
+#, 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:246
+msgid "Specify interface(s) to listen on."
+msgstr "Spesifiser nettverkskort det skal lyttes på."
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Spesifiser nettverkskort det IKKE skal lyttes på."
+
+#: option.c:248
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Map DHCP bruker klasse til opsjon sett."
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:252
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Ikke utfør DHCP for klienter i opsjon sett."
+
+#: option.c:253
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Ikke utfør DHCP for klienter i opsjon sett."
+
+#: option.c:254
+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:255
+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:256
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr "Spesifiser hvor DHCP leiene skal lagres (standard er %s)."
+
+#: option.c:257
+msgid "Return MX records for local hosts."
+msgstr "Returner MX records for lokale verter."
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr "Spesifiser en MX post."
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Spesifiser BOOTP opsjoner til DHCP tjener."
+
+#: option.c:260
+#, 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:261
+msgid "Do NOT cache failed search results."
+msgstr "IKKE mellomlagre søkeresultater som feiler."
+
+#: option.c:262
+#, 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:263
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene."
+
+#: option.c:264
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:265
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr "Spesifiser lytteport for DNS oppslag (standard er 53)."
+
+#: option.c:266
+#, 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:267
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "Logg oppslag."
+
+#: option.c:268
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Tving bruk av opprinnelig port for oppstrøms oppslag."
+
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr "IKKE les resolv.conf."
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Spesifiser stien til resolv.conf (standard er %s)."
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Spesifiser adressen(e) til oppstrøms tjenere med valgfrie domener."
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr "Aldri videresend oppslag til spesifiserte domener."
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Spesifiser domenet som skal tildeles i DHCP leien."
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr "Spesifiser default mål i en MX post."
+
+#: option.c:275
+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:276
+#, 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:277
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Skift til denne bruker etter oppstart (standard er %s)."
+
+#: option.c:278
+#, fuzzy
+msgid "Map DHCP vendor class to tag."
+msgstr "Map DHCP produsent klasse til opsjon sett."
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr "Vis dnsmasq versjon og copyright informasjon."
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Oversett IPv4 adresser fra oppstrøms tjenere."
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr "Spesifiser en SRV post."
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:283
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Spesifiser stien til PID fil. (standard er %s)."
+
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
+
+#: option.c:285
+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:286
+msgid "Specify TXT DNS record."
+msgstr "Spesifiser TXT DNS post."
+
+#: option.c:287
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Spesifiser TXT DNS post."
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr "Bind kun til nettverkskort som er i bruk."
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Les DHCP statisk vert informasjon fra %s."
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Aktiver DBus interface for å sette oppstrøms tjenere, osv."
+
+#: option.c:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "Ikke lever DHCP på dette nettverkskortet, kun lever DNS."
+
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Aktiver dynamisk adresse allokering for bootp."
+
+#: option.c:294
+#, fuzzy
+msgid "Map MAC address (with wildcards) to option set."
+msgstr "Map DHCP produsent klasse til opsjon sett."
+
+#: option.c:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:296
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:297
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:298
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:299
+#, fuzzy
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Skift til denne bruker etter oppstart (standard er %s)."
+
+#: option.c:300
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:301
+#, fuzzy, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
+
+#: option.c:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:304
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:305
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:308
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:309
+#, fuzzy, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)"
+
+#: option.c:310
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:316
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:319
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Spesifiser TXT DNS post."
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:323
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene."
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Bruk: dnsmasq [opsjoner]\n"
+"\n"
+
+#: option.c:615
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr "Bruk korte opsjoner kun på kommandolinjen.\n"
+
+#: option.c:617
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "Gyldige opsjoner er :\n"
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr "dårlig dhcp-opsjon"
+
+#: option.c:792
+#, fuzzy
+msgid "bad IP address"
+msgstr "les %s - %d adresser"
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr "dårlig domene i dhcp-opsjon"
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr "dhcp-opsjon for lang"
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1086 tftp.c:359
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr ""
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr ""
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr "dårlig MX preferanse"
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr "dårlig MX navn"
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr "dårlig MX mål"
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr "dårlig port"
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1611
+#, fuzzy
+msgid "bad port range"
+msgstr "dårlig port"
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr "dårlig dhcp-område"
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr ""
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr "ikke konsistent DHCP område"
+
+#: option.c:1912
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "dårlig MX navn"
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr "ugyldig portnummer"
+
+#: option.c:2284
+#, fuzzy
+msgid "invalid alias range"
+msgstr "ugyldig vekt"
+
+#: option.c:2297
+#, fuzzy
+msgid "bad interface name"
+msgstr "dårlig MX navn"
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2347
+#, fuzzy
+msgid "bad PTR record"
+msgstr "dårlig SRV post"
+
+#: option.c:2378
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "dårlig SRV post"
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr "TXT post streng for lang"
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr "dårlig TXT post"
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr "dårlig SRV post"
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr "dårlig SRV mål"
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr "ugyldig prioritet"
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr "ugyldig vekt"
+
+#: option.c:2514
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr ""
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: option.c:2626
+msgid "missing \""
+msgstr "mangler \""
+
+#: option.c:2673
+msgid "bad option"
+msgstr "dårlig opsjon"
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr "overflødig parameter"
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr "mangler parameter"
+
+#: option.c:2685
+msgid "error"
+msgstr "feil"
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s på linje %d av %%s"
+
+#: option.c:2740 option.c:2771
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "leser %s"
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr "Dnsmasq versjon %s %s\n"
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Kompileringsopsjoner %s\n"
+"\n"
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Denne programvaren kommer med ABSOLUTT INGEN GARANTI.\n"
+
+#: option.c:2846
+#, 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:2847
+#, 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:2858
+msgid "try --help"
+msgstr ""
+
+#: option.c:2860
+msgid "try -w"
+msgstr ""
+
+#: option.c:2863
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "dårlige kommandlinje opsjoner: %s."
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "klarer ikke å få vertsnavn: %s"
+
+#: option.c:2932
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr "kun en resolv.conf fil tillat i no-poll modus."
+
+#: option.c:2942
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr "må ha nøyaktig en resolv.conf å lese domene fra."
+
+#: option.c:2945 network.c:754 dhcp.c:734
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "feilet å lese %s: %s"
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr "intet søke direktiv funnet i %s"
+
+#: option.c:2983
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:2987
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "navnetjener %s nektet å gjøre et rekursivt oppslag"
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr ""
+
+#: network.c:73
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "ukjent tilknytning (interface) %s"
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr "feilet å lage lytte socket: %s"
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr "feilet å sette IPv6 opsjoner på lytte socket: %s"
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr "feilet å binde lytte socket for %s: %s"
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr "feilet å lytte på socket: %s"
+
+#: network.c:467
+#, fuzzy, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr "feilet å lage lytte socket: %s"
+
+#: network.c:661
+#, fuzzy, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "feilet å binde lytte socket for %s: %s"
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorerer navnetjener %s - lokal tilknytning"
+
+#: network.c:705
+#, fuzzy, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr "ignorerer navnetjener %s - kan ikke lage/dinde socket: %s"
+
+#: network.c:720
+msgid "unqualified"
+msgstr "ikke kvalifisert"
+
+#: network.c:720
+msgid "names"
+msgstr ""
+
+#: network.c:722
+msgid "default"
+msgstr ""
+
+#: network.c:724
+msgid "domain"
+msgstr "domene"
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "benytter lokale adresser kun for %s %s"
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "benytter navnetjener %s#%d for %s %s"
+
+#: network.c:732
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "benytter navnetjener %s#%d"
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "benytter navnetjener %s#%d"
+
+#: dnsmasq.c:146
+#, 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:151
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "feilet å finne liste av tilknytninger (interfaces): %s"
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr "ukjent tilknytning (interface) %s"
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr "ingen tilknytning (interface) med adresse %s"
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr "DBus feil: %s"
+
+#: dnsmasq.c:204
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h"
+
+#: dnsmasq.c:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:448
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "startet, versjon %s mellomlager deaktivert"
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "startet, versjon %s mellomlager størrelse %d"
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "startet, versjon %s mellomlager deaktivert"
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr "kompilerings opsjoner: %s"
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr "DBus støtte aktivert: koblet til system buss"
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr "DBus støtte aktivert: avventer buss tilkobling"
+
+#: dnsmasq.c:467
+#, fuzzy, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "feilet å laste navn fra %s: %s"
+
+#: dnsmasq.c:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "setter --bind-interfaces opsjon på grunn av OS begrensninger"
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "advarsel: nettverkskort %s eksisterer ikke for tiden"
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:484
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "setter oppstrøms tjener fra DBus"
+
+#: dnsmasq.c:488
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:501
+#, 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:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, IP område %s -- %s, leie tid %s"
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:519
+#, fuzzy
+msgid "enabled"
+msgstr "deaktivert"
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr "tilkoblet til system DBus"
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:760
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "feilet å lese %s: %s"
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:767
+#, fuzzy, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr "feilet å laste navn fra %s: %s"
+
+#: dnsmasq.c:772
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "feilet å laste navn fra %s: %s"
+
+#: dnsmasq.c:775
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "feilet å lese %s: %s"
+
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "kan ikke åpne %s:%s"
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:841
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "feilet å få tilgang til %s: %s"
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr "avslutter etter mottak av SIGTERM"
+
+#: dnsmasq.c:903
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "feilet å få tilgang til %s: %s"
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr "leser %s"
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "kan ikke lage ICMP raw socket: %s"
+
+#: dhcp.c:226
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:385
+#, 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:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "dårlig linje ved %s linje %d"
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "dubliserte IP adresser i %s dhcp-config direktiv."
+
+#: dhcp.c:900
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "dubliserte IP adresser i %s dhcp-config direktiv."
+
+#: dhcp.c:943
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:948
+#, 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:66
+#, fuzzy, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "kan ikke åpne eller lage leie fil: %s"
+
+#: lease.c:92
+msgid "too many stored leases"
+msgstr "for mange lagrede leier"
+
+#: lease.c:128
+#, fuzzy, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "kan ikke lese %s: %s"
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:234
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "feilet å lese %s: %s"
+
+#: rfc2131.c:336
+#, 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:337
+msgid "with subnet selector"
+msgstr "med subnet velger"
+
+#: rfc2131.c:337
+msgid "via"
+msgstr "via"
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr "deaktivert"
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr "oversett"
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr "adresse i bruk"
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr "ingen adresse tilgjengelig"
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr "galt nettverk"
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr "ingen adresse konfigurert"
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr "ingen leier igjen"
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr ""
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:853
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "deaktiverer DHCP statisk adresse %s"
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr "ukjent leie"
+
+#: rfc2131.c:906
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:916
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:919
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr "gal adresse"
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr "leie ikke funnet"
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr "adresse ikke tilgjengelig"
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr "statisk leie tilgjengelig"
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr "adresse reservert"
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1605
+#, fuzzy, c-format
+msgid "%u server name: %s"
+msgstr "DBus feil: %s"
+
+#: rfc2131.c:1613
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "DBus feil: %s"
+
+#: rfc2131.c:1680
+#, 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:1919
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2052
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "kompilerings opsjoner: %s"
+
+#: netlink.c:66
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "kan ikke binde netlink socket: %s"
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "kan ikke lage DHCP BPF socket: %s"
+
+#: bpf.c:178
+#, 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:179
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr ""
+
+#: tftp.c:305
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "leie ikke funnet"
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:447
+#, fuzzy, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr "feilet å lese %s: %s"
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr "FEILET å starte opp"
+
+#~ 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 "bad dhcp-host"
+#~ msgstr "dårlig dhcp-vert"
+
+#~ 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 100755
index 0000000..accaa60
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,1420 @@
+# 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.
+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: 2009-10-02 20:30+0200\n"
+"Last-Translator: Jan Psota <jasiu@belsznica.pl>\n"
+"Language-Team: Polish <kde-i18n-doc@kde.org>\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.0\n"
+"X-Language: pl_PL\n"
+
+#: cache.c:764
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr "nie potrafiê wczytaæ nazw z %s: %s"
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "b³êdny adres w pliku %s, w linii %d"
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "b³êdna nazwa w pliku %s, w linii %d"
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "wczyta³em %s - %d adresów"
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr "wyczyszczono pamiêæ podrêczn±"
+
+#: cache.c:933 option.c:1055
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr "brak dostêpu do katalogu %s: %s"
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr "czas %lu"
+
+#: cache.c:1130
+#, 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:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr "%u zapytañ przes³anych dalej, %u odpowiedzi udzielonych samodzielnie"
+
+#: cache.c:1155
+#, 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:59
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "brak mo¿liwo¶ci u¿ycia generatora liczb losowych: %s"
+
+#: util.c:191
+msgid "failed to allocate memory"
+msgstr "nie uda³o siê przydzieliæ pamiêci"
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr "nie mo¿na dostaæ pamiêci"
+
+#: util.c:239
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr "b³±d podczas próby utworzenia potoku: %s"
+
+#: util.c:247
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr "niemo¿liwo¶æ przydzielenia %d bajtów pamiêci"
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr "nieskoñczona"
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr "Wskazanie adresów, na których nale¿y nas³uchiwaæ."
+
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Zwracanie adresu IP dla wszystkich hostów we wskazanych domenach."
+
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Wy³±czenie przekazywania zapytañ odwrotnych dla prywatnych zakresów IP."
+
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Traktowanie adresu IP jako NXDOMAIN (uniewa¿nia ,,Verisign wildcard'')."
+
+#: option.c:232
+#, 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:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Wskazanie pliku konfiguracyjnego (domy¶lnie: %s)."
+
+#: option.c:234
+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:235
+msgid "Do NOT forward queries with no domain part."
+msgstr "Wy³±czenie przekazywania zapytañ bez podanej czê¶ci domenowej."
+
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr "Zwracanie samowskazuj±cego rekordu MX dla lokalnych hostów."
+
+#: option.c:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Rozwijanie prostych nazw z /etc/hosts przyrostkiem domenowym."
+
+#: option.c:238
+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:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "W³±czenie serwera DHCP dla wskazanego zakresu adresów."
+
+#: option.c:240
+#, 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:241
+msgid "Set address or hostname for a specified machine."
+msgstr "Ustawienie adresu lub nazwy dla wskazanego komputera."
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr "Wczytanie z podanego pliku opisu maszyn na potrzeby DHCP."
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr "Wczytanie z podanego pliku warto¶ci opcji DHCP."
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "Nie wczytywanie pliku %s."
+
+#: option.c:245
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr "Wskazanie dodatkowego pliku 'hosts' oprócz %s."
+
+#: option.c:246
+msgid "Specify interface(s) to listen on."
+msgstr "Interfejsy, na których nas³uchiwaæ."
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Interfejsy, na których NIE nas³uchiwaæ."
+
+#: option.c:248
+msgid "Map DHCP user class to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od klasy u¿ytkownika DHCP."
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru obwodu (w rozumieniu RFC3046)."
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru agenta (w rozumieniu RFC3046)."
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru subskrybenta (w rozumieniu RFC3993)."
+
+#: option.c:252
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Wy³±czenie DHCP dla hostów z okre¶lonym znacznikiem."
+
+#: option.c:253
+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:254
+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:255
+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:256
+#, 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:257
+msgid "Return MX records for local hosts."
+msgstr "W³±czenie zwracania rekordu MX dla hostów lokalnych."
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr "Specyfikacja rekordu MX."
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Okre¶lenie opcji BOOTP serwera DHCP."
+
+#: option.c:260
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr "Wy³±czenie obserwacji pliku %s, ponowne odczytywanie tylko po odebraniu sygna³u SIGHUP."
+
+#: option.c:261
+msgid "Do NOT cache failed search results."
+msgstr "Wy³±czenie przechowywania w pamiêci podrêcznej wyników nieudanych wyszukiwañ."
+
+#: option.c:262
+#, 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:263
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Specyfikacja opcji wysy³anej do klientów DHCP."
+
+#: option.c:264
+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:265
+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:266
+#, 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:267
+msgid "Log DNS queries."
+msgstr "W³±czenie spisywania zapytañ DNS do logu."
+
+#: option.c:268
+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:269
+msgid "Do NOT read resolv.conf."
+msgstr "Wy³±czenie czytania pliku resolv.conf."
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Wskazanie po³o¿enia pliku resolv.conf (domy¶lnie: %s)."
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Wskazywanie adresów serwerów nazw, opcjonalnie z przypisaniem do domeny."
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr "Wy³±czenie przekazywania zapytañ do wskazanych domen."
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Wskazanie domeny dla serwera DHCP."
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr "Okre¶lenie domy¶lnego celu w rekordzie MX."
+
+#: option.c:275
+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:276
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Okre¶lenie (w sekundach) czasu wa¿no¶ci negatywnych odpowiedzi."
+
+#: option.c:277
+#, 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:278
+msgid "Map DHCP vendor class to tag."
+msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od typu klienta DHCP."
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr "Wydrukowanie informacji o programie i ochronie praw autorskich."
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "T³umaczenie adresów IPv4 z serwerów nadrzêdnych."
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr "Okre¶lenie rekordu SRV."
+
+#: option.c:282
+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:283
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Okre¶lenie ¶cie¿ki do pliku PID (domy¶lnie: %s)."
+
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Maksymalna liczba dzier¿aw DHCP (domy¶lnie: %s)."
+
+#: option.c:285
+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:286
+msgid "Specify TXT DNS record."
+msgstr "Specyfikacja rekordu DNS TXT."
+
+#: option.c:287
+msgid "Specify PTR DNS record."
+msgstr "Specyfikacja rekordu DNS PTR."
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr "Zwraca nazwê domenow± powi±zan± z adresem interfejsu sieciowego."
+
+#: option.c:289
+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:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Wczytanie przyporz±dkowañ adresów z %s."
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "W³±czenie u¿ywania interfejsu DBus do informowania o zmianach konfiguracji."
+
+#: option.c:292
+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:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr "W³±czenie dynamicznego przydzielania adresów dla klientów BOOTP."
+
+#: option.c:294
+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:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr "Traktowanie ¿±dañ DHCP odebranych na interfejsach alias, ..., jako odebranych na iface."
+
+#: option.c:296
+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:297
+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:298
+msgid "Read configuration from all the files in this directory."
+msgstr "Wczytanie wszystkich plików ze wskazanego katalogu jako konfiguracyjnych."
+
+#: option.c:299
+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:300
+msgid "Do not use leasefile."
+msgstr "Nieu¿ywanie bazy dzier¿aw."
+
+#: option.c:301
+#, 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:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr "Czyszczenie pamiêci podrêcznej serwera nazw w przypadku ponownego odczytu %s."
+
+#: option.c:303
+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:304
+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:305
+msgid "Enable integrated read-only TFTP server."
+msgstr "W³±czenie wbudowanego serwera TFTP (tylko do wysy³ania)."
+
+#: option.c:306
+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:307
+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:308
+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:309
+#, 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:310
+msgid "Disable the TFTP blocksize extension."
+msgstr "Wy³±czenie mo¿liwo¶ci negocjowania wielko¶ci bloku dla przesy³ów przez TFTP."
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr "Wskazanie zakresu portów do u¿ytku TFTP."
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr "W³±czenie spisywania w logu operacji DHCP."
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr "W³±czenie asynchronicznego zapisywania do logu z ewentualnym wskazaniem d³ugo¶ci kolejki."
+
+#: option.c:314
+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:315
+msgid "Always perform DNS queries to all servers."
+msgstr "Jednoczesne odpytywanie wszystkich serwerów nadrzêdnych; klientowi przekazywana jest pierwsza odpowied¼."
+
+#: option.c:316
+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:317
+msgid "Use alternative ports for DHCP."
+msgstr "U¿ycie alternatywnych portów dla us³ugi DHCP."
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr "Uruchamianie skryptu dhcp-script jako wskazany u¿ytkownik."
+
+#: option.c:319
+msgid "Specify NAPTR DNS record."
+msgstr "Specyfikacja rekordu DNS NAPTR."
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr "Ustawienie dolnej granicy numerów portów do przesy³ania zapytañ DNS."
+
+#: option.c:321
+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:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr "Wskazanie synonimu nazwy komputera lokalnego - znanego z /etc/hosts albo z DHCP."
+
+#: option.c:323
+msgid "Prompt to send to PXE clients."
+msgstr "Zg³oszenie wysy³ane klientom PXE."
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr "Sk³adnik menu PXE (--> man)."
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr "Sprawd¼ sk³adniê."
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"U¿ycie: dnsmasq [opcje]\n"
+"\n"
+
+#: option.c:615
+#, 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:617
+#, c-format
+msgid "Valid options are:\n"
+msgstr "Dostêpne opcje:\n"
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr "Znane opcje DHCP:\n"
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr "b³±d w dhcp-option"
+
+#: option.c:792
+msgid "bad IP address"
+msgstr "z³y adres IP"
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr "nieprawid³owa nazwa domeny w dhcp-option"
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr "zbyt d³uga dhcp-option (>255 znaków)"
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr "niedopuszczalne dhcp-match"
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr "wielokrotne u¿ycie opcji niedozwolone (pojawi³a siê wcze¶niej w linii poleceñ)"
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr "wielokrotne u¿ycie opcji niedozwolone (pojawi³a siê wsze¶niej w pliku konfiguracyjnym)"
+
+#: option.c:1086 tftp.c:359
+#, c-format
+msgid "cannot access %s: %s"
+msgstr "brak dostêpu do %s: %s"
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr "mo¿na wskazaæ tylko jeden plik dhcp-hostsfile"
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr "mo¿na wskazaæ tylko jeden plik dhcp-optsfile"
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr "nieprawid³owa warto¶æ preferencji MX"
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr "nieprawid³owa nazwa MX"
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr "nieprawid³owa warto¶æ celu MX"
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr "w uClinuksie nie ma mo¿liwo¶ci uruchamiania skryptów"
+
+#: option.c:1214
+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:1442 option.c:1446
+msgid "bad port"
+msgstr "nieprawid³owy numer portu"
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr "nie ma mo¿liwo¶ci dowi±zywania do interfejsu"
+
+#: option.c:1611
+msgid "bad port range"
+msgstr "nieprawid³owy zakres numerów portów"
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr "nieprawid³owa nazwa urz±dzenia w bridge-interface"
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr "nieprawid³owy zakres dhcp-range"
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr "mo¿na wskazaæ tylko jeden znacznik sieci"
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr "niespójny zakres adresów DHCP"
+
+#: option.c:1912
+msgid "bad DHCP host name"
+msgstr "niedopuszczalna nazwa komputera w dhcp-host"
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr "nieprawid³owy numer portu"
+
+#: option.c:2284
+msgid "invalid alias range"
+msgstr "nieprawid³owy zakres adresów w --alias"
+
+#: option.c:2297
+msgid "bad interface name"
+msgstr "nieprawid³owa nazwa interfejsu"
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr "z³a CNAME"
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr "powtórzona CNAME"
+
+#: option.c:2347
+msgid "bad PTR record"
+msgstr "nieprawid³owy zapis rekordu PTR"
+
+#: option.c:2378
+msgid "bad NAPTR record"
+msgstr "nieprawid³owy zapis rekordu NAPTR"
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr "zbyt d³ugi rekord TXT"
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr "nieprawid³owy zapis rekordu TXT"
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr "nieprawid³owy zapis rekordu SRV"
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr "nieprawid³owa warto¶æ celu SRV"
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr "nieprawid³owy priorytet"
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr "nieprawid³owa waga"
+
+#: option.c:2514
+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:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr "zbyt du¿e zag³êbienie plików w %s"
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "b³±d odczytu z pliku %s: %s"
+
+#: option.c:2626
+msgid "missing \""
+msgstr "brakuje \""
+
+#: option.c:2673
+msgid "bad option"
+msgstr "nieprawid³owa opcja"
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr "nadwy¿kowy parametr"
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr "brak parametru"
+
+#: option.c:2685
+msgid "error"
+msgstr "b³±d"
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s w linii %d pliku %%s"
+
+#: option.c:2740 option.c:2771
+#, c-format
+msgid "read %s"
+msgstr "przeczyta³em %s"
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr "Dnsmasq, wersja %s %s\n"
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Wkompilowane opcje %s\n"
+"\n"
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Autor nie daje ¯ADNYCH GWARANCJI egzekwowalnych prawnie.\n"
+
+#: option.c:2846
+#, 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:2847
+#, 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:2858
+msgid "try --help"
+msgstr "spróbuj: --help"
+
+#: option.c:2860
+msgid "try -w"
+msgstr "spróbuj: -w"
+
+#: option.c:2863
+#, c-format
+msgid "bad command line options: %s"
+msgstr "nieprawid³owa opcja w linii poleceñ %s"
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "nie mo¿na pobraæ nazwy hosta: %s"
+
+#: option.c:2932
+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:2942
+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:2945 network.c:754 dhcp.c:734
+#, c-format
+msgid "failed to read %s: %s"
+msgstr "nie uda³o siê odczytaæ %s: %s"
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr "brak wytycznych wyszukiwania w %s"
+
+#: option.c:2983
+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:2987
+msgid "syntax check OK"
+msgstr "sk³adnia sprawdzona, jest prawid³owa"
+
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "serwer nazw %s odmawia wykonania zapytania rekurencyjnego"
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr "prawdopodobnie wykryto atak DNS-rebind"
+
+#: network.c:73
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "nieznany interfejs %s w bridge-u"
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr "b³±d podczas tworzenia gniazda: %s"
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr "b³±d ustawiania opcji IPV6 na nas³uchuj±cym gnie¼dzie: %s"
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr "b³±d przy przyznawaniu nazwy gniazdu %s: %s"
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr "b³±d przy w³±czaniu nas³uchu na gnie¼dzie: %s"
+
+#: network.c:467
+#, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr "nie powiod³o siê otwieranie gniazda dla us³ugi TFTP: %s"
+
+#: network.c:661
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr "b³±d przy przyznawaniu nazwy gniazdu serwera %s: %s"
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorowanie serwera nazw %s - interfejs lokalny"
+
+#: network.c:705
+#, 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:720
+msgid "unqualified"
+msgstr "niekwalifikowane(-a)"
+
+#: network.c:720
+msgid "names"
+msgstr "nazwy"
+
+#: network.c:722
+msgid "default"
+msgstr "domy¶lne"
+
+#: network.c:724
+msgid "domain"
+msgstr "domeny"
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "u¿ywam adresów lokalnych tylko dla %s %s"
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "u¿ywam serwera nazw %s#%d dla %s %s"
+
+#: network.c:732
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "u¿ywam serwera nazw %s#%d (przez %s)"
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "u¿ywam serwera nazw %s#%d"
+
+#: dnsmasq.c:146
+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:151
+msgid "asychronous logging is not available under Solaris"
+msgstr "zapis do logów w trybie asynchronicznym nie jest dostêpny w Solarisie"
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "b³±d podczas tworzenia listy interfejsów sieciowych: %s"
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr "nieznany interfejs %s"
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr "brak interfejsu z adresem %s"
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr "b³±d DBus: %s"
+
+#: dnsmasq.c:204
+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:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr "nieznany u¿ytkownik lub grupa: %s"
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr "nie potrafiê wej¶æ do g³ównego katalogu: %s"
+
+#: dnsmasq.c:448
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr "uruchomiony, wersja %s, DNS wy³±czony"
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "uruchomiony, wersja %s, %d miejsc w pamiêci podrêcznej"
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "uruchomiony, wersja %s, pamiêæ podrêczna wy³±czona"
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr "opcje kompilacji: %s"
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr "obs³uga DBus w³±czona, pod³±czono do serwera DBus"
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr "obs³uga DBus w³±czona, trwa pod³±czanie do serwera DBus"
+
+#: dnsmasq.c:467
+#, 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:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "ustawiam --bind-interfaces z powodu ograniczeñ systemu operacyjnego"
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "uwaga: interfejs %s nie jest w³±czony"
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr "uwaga: ignorujê opcjê resolv-file, poniewa¿ wybrano tryb no-resolv"
+
+#: dnsmasq.c:484
+msgid "warning: no upstream servers configured"
+msgstr "uwaga: nie wskazano nadrzêdnych serwerów DNS"
+
+#: dnsmasq.c:488
+#, 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:501
+#, 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:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr "DHCP: po¶rednik na podsieci %.0s%s%.0s"
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP: zakres IP %s -- %s, czas dzier¿awy %s"
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr "z g³ównym katalogiem w "
+
+#: dnsmasq.c:519
+msgid "enabled"
+msgstr "w³±czony"
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr "w trybie bezpiecznym"
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr "ograniczam ilo¶æ jednoczesnych przes³añ TFTP do %d"
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr "pod³±czono do DBus-a"
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr "nie potrafiê prze³±czyæ siê do pracy w tle: %s"
+
+#: dnsmasq.c:760
+#, c-format
+msgid "failed to create helper: %s"
+msgstr "nie uda³o siê utworzyæ procesu pomocniczego: %s"
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr "nie powiod³o siê ustawianie ograniczeñ (capabilities): %s"
+
+#: dnsmasq.c:767
+#, 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:772
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "nie uda³o siê zmieniæ grupy procesu na %s: %s"
+
+#: dnsmasq.c:775
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "nie uda³o siê otworzyæ pliku z PID-em %s: %s"
+
+#: dnsmasq.c:778
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "nie mo¿na otworzyæ %s: %s"
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr "proces potomny zabity sygna³em %d"
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr "proces potomny zakoñczy³ siê z kodem powrotu %d"
+
+#: dnsmasq.c:841
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr "nie uda³o siê uruchomiæ %s: %s"
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr "zakoñczy³em dzia³anie z powodu odebrania SIGTERM"
+
+#: dnsmasq.c:903
+#, c-format
+msgid "failed to access %s: %s"
+msgstr "brak dostêpu do %s: %s"
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr "czytanie %s"
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "nie uda³o siê utworzyæ surowego gniazda ICMP: %s."
+
+#: dhcp.c:226
+#, 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:385
+#, 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:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "z³a zawarto¶æ pliku %s, w linii %d"
+
+#: dhcp.c:815
+#, 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:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "powtórzony adres IP (%s) w parametrze dhcp-config"
+
+#: dhcp.c:900
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "powtórzony adres IP (%s) w pliku %s"
+
+#: dhcp.c:943
+#, 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:948
+#, 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:66
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr "nie potrafiê otworzyæ albo utworzyæ pliku dzier¿aw %s: %s"
+
+#: lease.c:92
+msgid "too many stored leases"
+msgstr "zbyt du¿a ilo¶æ zapisanych dzier¿aw"
+
+#: lease.c:128
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "nie potrafiê uruchomiæ skryptu %s: %s"
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr "skrypt zakoñczy³ siê z kodem powrotu %s"
+
+#: lease.c:234
+#, 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:336
+#, 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:337
+msgid "with subnet selector"
+msgstr "z wyborem podsieci"
+
+#: rfc2131.c:337
+msgid "via"
+msgstr "przez"
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr "%u Dostêpna podsieæ DHCP: %s/%s"
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr "%u zakres adresów na u¿ytek DHCP: %s -- %s"
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr "wy³±czony(a)"
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr "ignorujê"
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr "adres jest w u¿yciu"
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr "brak dostêpnego adresu"
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr "nieprawid³owa sieæ"
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr "brak skonfigurowanego adresu"
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr "brak wolnych dzier¿aw"
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr "klient %u przedstawia siê jako %s"
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr "%u klasa klienta: %s"
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr "%u Klasa u¿ytkownika: %s"
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr "PXE BIS nie jest obs³ugiwane"
+
+#: rfc2131.c:853
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "wy³±czam statyczne przypisanie adresu %s dla %s"
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr "nieznana dzier¿awa"
+
+#: rfc2131.c:906
+#, 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:916
+#, 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:919
+#, 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:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr "brak unikalnego id"
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr "nieprawid³owy identyfikator serwera (server-ID)"
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr "b³êdny adres"
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr "dzier¿awa nieznaleziona"
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr "adres niedostêpny"
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr "dostêpna statyczna dzier¿awa"
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr "adres zarezerwowany"
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr "porzucam przypisanie do %s nazwy %s"
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr "%u cechy: %s"
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr "%u nazwa pliku bootowania: %s"
+
+#: rfc2131.c:1605
+#, c-format
+msgid "%u server name: %s"
+msgstr "%u nazwa serwera: %s"
+
+#: rfc2131.c:1613
+#, c-format
+msgid "%u next server: %s"
+msgstr "%u nastêpny serwer: %s"
+
+#: rfc2131.c:1680
+#, 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:1919
+msgid "PXE menu too large"
+msgstr "menu PXE zbyt du¿e"
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr "Nie uwzglêdniam czê¶ci domenowej (%s) dla komputera %s"
+
+#: rfc2131.c:2052
+#, c-format
+msgid "%u requested options: %s"
+msgstr "%u wskazane opcje: %s"
+
+#: netlink.c:66
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "nie potrafiê utworzyæ po³±czenia netlink %s"
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "nie potrafiê utworzyæ gniazda DHCP BPF: %s"
+
+#: bpf.c:178
+#, 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:179
+msgid "unable to get free port for TFTP"
+msgstr "brak wolnego portu dla us³ugi TFTP"
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr "nieobs³ugiwane ¿±danie od komputera %s"
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr "plik %s przes³ano za pomoc± TFTP do %s"
+
+#: tftp.c:305
+#, c-format
+msgid "file %s not found"
+msgstr "plik %s nie zosta³ znaleziony"
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr "b³±d TFTP: %d bajtów odebrano (%s) z %s"
+
+#: tftp.c:447
+#, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr "b³±d wysy³ania przez TFTP pliku %s do komputera %s"
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr "przepe³nienie: stracono %d wpisów do logów"
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr "nie uda³o siê zapisaæ komunikatów do %s"
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr "B£¡D: nie uda³o siê uruchomiæ dnsmasq-a"
+
diff --git a/po/pt_BR.po b/po/pt_BR.po
new file mode 100755
index 0000000..89b8133
--- /dev/null
+++ b/po/pt_BR.po
@@ -0,0 +1,1411 @@
+# 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:764
+#, c-format
+msgid "failed to load names from %s: %s"
+msgstr ""
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr ""
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr ""
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr ""
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr ""
+
+#: cache.c:933 option.c:1055
+#, c-format
+msgid "cannot access directory %s: %s"
+msgstr ""
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1130
+#, c-format
+msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries."
+msgstr ""
+
+#: cache.c:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1155
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:59
+#, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr ""
+
+#: util.c:191
+msgid "failed to allocate memory"
+msgstr ""
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr ""
+
+#: util.c:239
+#, c-format
+msgid "cannot create pipe: %s"
+msgstr ""
+
+#: util.c:247
+#, c-format
+msgid "failed to allocate %d bytes"
+msgstr ""
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr ""
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr ""
+
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr ""
+
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr ""
+
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr ""
+
+#: option.c:232
+#, c-format
+msgid "Specify the size of the cache in entries (defaults to %s)."
+msgstr ""
+
+#: option.c:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr ""
+
+#: option.c:234
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr ""
+
+#: option.c:235
+msgid "Do NOT forward queries with no domain part."
+msgstr ""
+
+#: option.c:236
+msgid "Return self-pointing MX records for local hosts."
+msgstr ""
+
+#: option.c:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr ""
+
+#: option.c:238
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr ""
+
+#: option.c:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr ""
+
+#: option.c:240
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr ""
+
+#: option.c:241
+msgid "Set address or hostname for a specified machine."
+msgstr ""
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr ""
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr ""
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr ""
+
+#: option.c:245
+#, c-format
+msgid "Specify a hosts file to be read in addition to %s."
+msgstr ""
+
+#: option.c:246
+msgid "Specify interface(s) to listen on."
+msgstr ""
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr ""
+
+#: option.c:248
+msgid "Map DHCP user class to tag."
+msgstr ""
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:252
+msgid "Don't do DHCP for hosts with tag set."
+msgstr ""
+
+#: option.c:253
+msgid "Force broadcast replies for hosts with tag set."
+msgstr ""
+
+#: option.c:254
+msgid "Do NOT fork into the background, do NOT run in debug mode."
+msgstr ""
+
+#: option.c:255
+msgid "Assume we are the only DHCP server on the local network."
+msgstr ""
+
+#: option.c:256
+#, c-format
+msgid "Specify where to store DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:257
+msgid "Return MX records for local hosts."
+msgstr ""
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr ""
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr ""
+
+#: option.c:260
+#, c-format
+msgid "Do NOT poll %s file, reload only on SIGHUP."
+msgstr ""
+
+#: option.c:261
+msgid "Do NOT cache failed search results."
+msgstr ""
+
+#: option.c:262
+#, c-format
+msgid "Use nameservers strictly in the order given in %s."
+msgstr ""
+
+#: option.c:263
+msgid "Specify options to be sent to DHCP clients."
+msgstr ""
+
+#: option.c:264
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:265
+msgid "Specify port to listen for DNS requests on (defaults to 53)."
+msgstr ""
+
+#: option.c:266
+#, c-format
+msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)."
+msgstr ""
+
+#: option.c:267
+msgid "Log DNS queries."
+msgstr ""
+
+#: option.c:268
+msgid "Force the originating port for upstream DNS queries."
+msgstr ""
+
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr ""
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr ""
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr ""
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr ""
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr ""
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr ""
+
+#: option.c:275
+msgid "Specify time-to-live in seconds for replies from /etc/hosts."
+msgstr ""
+
+#: option.c:276
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr ""
+
+#: option.c:277
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr ""
+
+#: option.c:278
+msgid "Map DHCP vendor class to tag."
+msgstr ""
+
+#: option.c:279
+msgid "Display dnsmasq version and copyright information."
+msgstr ""
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr ""
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr ""
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:283
+#, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr ""
+
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr ""
+
+#: option.c:285
+msgid "Answer DNS queries based on the interface a query was sent to."
+msgstr ""
+
+#: option.c:286
+msgid "Specify TXT DNS record."
+msgstr ""
+
+#: option.c:287
+msgid "Specify PTR DNS record."
+msgstr ""
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr ""
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr ""
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr ""
+
+#: option.c:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr ""
+
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr ""
+
+#: option.c:294
+msgid "Map MAC address (with wildcards) to option set."
+msgstr ""
+
+#: option.c:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:296
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:297
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:298
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:299
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr ""
+
+#: option.c:300
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:301
+#, c-format
+msgid "Maximum number of concurrent DNS queries. (defaults to %s)"
+msgstr ""
+
+#: option.c:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:304
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:305
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:308
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:309
+#, c-format
+msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)."
+msgstr ""
+
+#: option.c:310
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:316
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:319
+msgid "Specify NAPTR DNS record."
+msgstr ""
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:323
+msgid "Prompt to send to PXE clients."
+msgstr ""
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+
+#: option.c:615
+#, c-format
+msgid "Use short options only on the command line.\n"
+msgstr ""
+
+#: option.c:617
+#, c-format
+msgid "Valid options are:\n"
+msgstr ""
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr ""
+
+#: option.c:792
+msgid "bad IP address"
+msgstr ""
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr ""
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr ""
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1086 tftp.c:359
+#, c-format
+msgid "cannot access %s: %s"
+msgstr ""
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr ""
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr ""
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr ""
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr ""
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr ""
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr ""
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1611
+msgid "bad port range"
+msgstr ""
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr ""
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr ""
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr ""
+
+#: option.c:1912
+msgid "bad DHCP host name"
+msgstr ""
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr ""
+
+#: option.c:2284
+msgid "invalid alias range"
+msgstr ""
+
+#: option.c:2297
+msgid "bad interface name"
+msgstr ""
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2347
+msgid "bad PTR record"
+msgstr ""
+
+#: option.c:2378
+msgid "bad NAPTR record"
+msgstr ""
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr ""
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr ""
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr ""
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr ""
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr ""
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr ""
+
+#: option.c:2514
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr ""
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: option.c:2626
+msgid "missing \""
+msgstr ""
+
+#: option.c:2673
+msgid "bad option"
+msgstr ""
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr ""
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr ""
+
+#: option.c:2685
+msgid "error"
+msgstr ""
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr ""
+
+#: option.c:2740 option.c:2771
+#, c-format
+msgid "read %s"
+msgstr ""
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr ""
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr ""
+
+#: option.c:2846
+#, c-format
+msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
+msgstr ""
+
+#: option.c:2847
+#, c-format
+msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
+msgstr ""
+
+#: option.c:2858
+msgid "try --help"
+msgstr ""
+
+#: option.c:2860
+msgid "try -w"
+msgstr ""
+
+#: option.c:2863
+#, c-format
+msgid "bad command line options: %s"
+msgstr ""
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr ""
+
+#: option.c:2932
+msgid "only one resolv.conf file allowed in no-poll mode."
+msgstr ""
+
+#: option.c:2942
+msgid "must have exactly one resolv.conf to read domain from."
+msgstr ""
+
+#: option.c:2945 network.c:754 dhcp.c:734
+#, c-format
+msgid "failed to read %s: %s"
+msgstr ""
+
+#: option.c:2962
+#, c-format
+msgid "no search directive found in %s"
+msgstr ""
+
+#: option.c:2983
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:2987
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr ""
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr ""
+
+#: network.c:73
+#, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr ""
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr ""
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr ""
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr ""
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr ""
+
+#: network.c:467
+#, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr ""
+
+#: network.c:661
+#, c-format
+msgid "failed to bind server socket for %s: %s"
+msgstr ""
+
+#: network.c:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr ""
+
+#: network.c:705
+#, c-format
+msgid "ignoring nameserver %s - cannot make/bind socket: %s"
+msgstr ""
+
+#: network.c:720
+msgid "unqualified"
+msgstr ""
+
+#: network.c:720
+msgid "names"
+msgstr ""
+
+#: network.c:722
+msgid "default"
+msgstr ""
+
+#: network.c:724
+msgid "domain"
+msgstr ""
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr ""
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr ""
+
+#: network.c:732
+#, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr ""
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr ""
+
+#: dnsmasq.c:146
+msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:151
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr ""
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr ""
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr ""
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr ""
+
+#: dnsmasq.c:204
+msgid "DBus not available: set HAVE_DBUS in src/config.h"
+msgstr ""
+
+#: dnsmasq.c:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:448
+#, c-format
+msgid "started, version %s DNS disabled"
+msgstr ""
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr ""
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr ""
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr ""
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr ""
+
+#: dnsmasq.c:462
+msgid "DBus support enabled: bus connection pending"
+msgstr ""
+
+#: dnsmasq.c:467
+#, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr ""
+
+#: dnsmasq.c:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr ""
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr ""
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:484
+msgid "warning: no upstream servers configured"
+msgstr ""
+
+#: dnsmasq.c:488
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:501
+#, c-format
+msgid "DHCP, static leases only on %.0s%s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:519
+msgid "enabled"
+msgstr ""
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr ""
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:760
+#, c-format
+msgid "failed to create helper: %s"
+msgstr ""
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+#: dnsmasq.c:767
+#, c-format
+msgid "failed to change user-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:772
+#, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr ""
+
+#: dnsmasq.c:775
+#, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr ""
+
+#: dnsmasq.c:778
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:841
+#, c-format
+msgid "failed to execute %s: %s"
+msgstr ""
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr ""
+
+#: dnsmasq.c:903
+#, c-format
+msgid "failed to access %s: %s"
+msgstr ""
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr ""
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr ""
+
+#: dhcp.c:226
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:385
+#, c-format
+msgid "DHCP range %s -- %s is not consistent with netmask %s"
+msgstr ""
+
+#: dhcp.c:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr ""
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr ""
+
+#: dhcp.c:900
+#, c-format
+msgid "duplicate IP address %s in %s."
+msgstr ""
+
+#: dhcp.c:943
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:948
+#, c-format
+msgid "duplicate IP address %s (%s) in dhcp-config directive"
+msgstr ""
+
+#: lease.c:66
+#, c-format
+msgid "cannot open or create lease file %s: %s"
+msgstr ""
+
+#: lease.c:92
+msgid "too many stored leases"
+msgstr ""
+
+#: lease.c:128
+#, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr ""
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:234
+#, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr ""
+
+#: rfc2131.c:336
+#, c-format
+msgid "no address range available for DHCP request %s %s"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "with subnet selector"
+msgstr ""
+
+#: rfc2131.c:337
+msgid "via"
+msgstr ""
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr ""
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr ""
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr ""
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr ""
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr ""
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr ""
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr ""
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr ""
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:853
+#, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr ""
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr ""
+
+#: rfc2131.c:906
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:916
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:919
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr ""
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr ""
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr ""
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr ""
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr ""
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1605
+#, c-format
+msgid "%u server name: %s"
+msgstr ""
+
+#: rfc2131.c:1613
+#, c-format
+msgid "%u next server: %s"
+msgstr ""
+
+#: rfc2131.c:1680
+#, c-format
+msgid "cannot send DHCP/BOOTP option %d: no space left in packet"
+msgstr ""
+
+#: rfc2131.c:1919
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2052
+#, c-format
+msgid "%u requested options: %s"
+msgstr ""
+
+#: netlink.c:66
+#, c-format
+msgid "cannot create netlink socket: %s"
+msgstr ""
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr ""
+
+#: bpf.c:178
+#, c-format
+msgid "DHCP request for unsupported hardware type (%d) received on %s"
+msgstr ""
+
+#: tftp.c:179
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr ""
+
+#: tftp.c:305
+#, c-format
+msgid "file %s not found"
+msgstr ""
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:447
+#, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr ""
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr ""
diff --git a/po/ro.po b/po/ro.po
new file mode 100755
index 0000000..f6c2492
--- /dev/null
+++ b/po/ro.po
@@ -0,0 +1,1503 @@
+# 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:764
+#, fuzzy, c-format
+msgid "failed to load names from %s: %s"
+msgstr "încărcarea numelor din %s: %s a eşuat"
+
+#: cache.c:798 dhcp.c:785
+#, c-format
+msgid "bad address at %s line %d"
+msgstr "adresă greşită în %s, linia %d"
+
+#: cache.c:856 dhcp.c:801
+#, c-format
+msgid "bad name at %s line %d"
+msgstr "nume greşit în %s linia %d"
+
+#: cache.c:863 dhcp.c:875
+#, c-format
+msgid "read %s - %d addresses"
+msgstr "citesc %s - %d adrese"
+
+#: cache.c:902
+msgid "cleared cache"
+msgstr "memoria temporară a fost ştearsă"
+
+#: cache.c:933 option.c:1055
+#, fuzzy, c-format
+msgid "cannot access directory %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: cache.c:1052
+#, 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:1129
+#, c-format
+msgid "time %lu"
+msgstr ""
+
+#: cache.c:1130
+#, 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:1132
+#, c-format
+msgid "queries forwarded %u, queries answered locally %u"
+msgstr ""
+
+#: cache.c:1155
+#, c-format
+msgid "server %s#%d: queries sent %u, retried or failed %u"
+msgstr ""
+
+#: util.c:59
+#, fuzzy, c-format
+msgid "failed to seed the random number generator: %s"
+msgstr "ascultarea pe socket a eÅŸuat: %s"
+
+#: util.c:191
+#, fuzzy
+msgid "failed to allocate memory"
+msgstr "nu pot încărca %d bytes"
+
+#: util.c:229 option.c:548
+msgid "could not get memory"
+msgstr "nu am putut aloca memorie"
+
+#: util.c:239
+#, fuzzy, c-format
+msgid "cannot create pipe: %s"
+msgstr "nu pot citi %s: %s"
+
+#: util.c:247
+#, fuzzy, c-format
+msgid "failed to allocate %d bytes"
+msgstr "nu pot încărca %d bytes"
+
+#: util.c:352
+#, c-format
+msgid "infinite"
+msgstr "infinit"
+
+#: option.c:228
+msgid "Specify local address(es) to listen on."
+msgstr "Specificaţi adresele locale deservite."
+
+#: option.c:229
+msgid "Return ipaddr for all hosts in specified domains."
+msgstr "Afişează adresele IP ale maşinilor în domeniul dat."
+
+#: option.c:230
+msgid "Fake reverse lookups for RFC1918 private address ranges."
+msgstr "Simulează căutări după adresă pentru domenii de adresă private (RFC1918)."
+
+#: option.c:231
+msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."
+msgstr "Interpretează adresa IP ca NXDOMAIN (împotriva manipulărilor Verisign)"
+
+#: option.c:232
+#, 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:233
+#, c-format
+msgid "Specify configuration file (defaults to %s)."
+msgstr "Specifică fişier de configurare (implicit e %s)."
+
+#: option.c:234
+msgid "Do NOT fork into the background: run in debug mode."
+msgstr "NU porneşte în fundal: rulează în modul depanare."
+
+#: option.c:235
+msgid "Do NOT forward queries with no domain part."
+msgstr "NU înainta cererile ce nu conţin domeniu DNS."
+
+#: option.c:236
+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:237
+msgid "Expand simple names in /etc/hosts with domain-suffix."
+msgstr "Adaugă numelor simple din /etc/hosts numele domeniului ca sufix."
+
+#: option.c:238
+msgid "Don't forward spurious DNS requests from Windows hosts."
+msgstr "Nu inainta cereri DNS defecte provenite de la maÅŸini Windows."
+
+#: option.c:239
+msgid "Enable DHCP in the range given with lease duration."
+msgstr "Activează DHCP în domeniul dat cu durată limitată de împrumut."
+
+#: option.c:240
+#, c-format
+msgid "Change to this group after startup (defaults to %s)."
+msgstr "Rulează sub acest grup după pornire (implicit e %s)."
+
+#: option.c:241
+msgid "Set address or hostname for a specified machine."
+msgstr "Schimbă adresa sau numele maşinii specificate."
+
+#: option.c:242
+msgid "Read DHCP host specs from file"
+msgstr ""
+
+#: option.c:243
+msgid "Read DHCP option specs from file"
+msgstr ""
+
+#: option.c:244
+#, c-format
+msgid "Do NOT load %s file."
+msgstr "Nu încarcă fişierul %s."
+
+#: option.c:245
+#, 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:246
+msgid "Specify interface(s) to listen on."
+msgstr "Specifică interfeţele deservite."
+
+#: option.c:247
+msgid "Specify interface(s) NOT to listen on."
+msgstr "Specifică interfeţele NE-deservite."
+
+#: option.c:248
+#, fuzzy
+msgid "Map DHCP user class to tag."
+msgstr "Leagă clasa de utilizator DHCP cu grup de opţiuni."
+
+#: option.c:249
+msgid "Map RFC3046 circuit-id to tag."
+msgstr ""
+
+#: option.c:250
+msgid "Map RFC3046 remote-id to tag."
+msgstr ""
+
+#: option.c:251
+msgid "Map RFC3993 subscriber-id to tag."
+msgstr ""
+
+#: option.c:252
+#, fuzzy
+msgid "Don't do DHCP for hosts with tag set."
+msgstr "Nu furniza DHCP maşinilor din grupul de opţiuni."
+
+#: option.c:253
+#, fuzzy
+msgid "Force broadcast replies for hosts with tag set."
+msgstr "Nu furniza DHCP maşinilor din grupul de opţiuni."
+
+#: option.c:254
+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:255
+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:256
+#, 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:257
+msgid "Return MX records for local hosts."
+msgstr "Răspunde cu întregistrări MX pentru maşini locale."
+
+#: option.c:258
+msgid "Specify an MX record."
+msgstr "Specifică o înregistrare MX."
+
+#: option.c:259
+msgid "Specify BOOTP options to DHCP server."
+msgstr "Specifică opţiuni BOOTP serverului DHCP."
+
+#: option.c:260
+#, 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:261
+msgid "Do NOT cache failed search results."
+msgstr "NU memora rezultatele de căutare DNS eşuatată."
+
+#: option.c:262
+#, 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:263
+#, fuzzy
+msgid "Specify options to be sent to DHCP clients."
+msgstr "Configurează opţiuni în plusce trebuie trimise clienţilor DHCP."
+
+#: option.c:264
+msgid "DHCP option sent even if the client does not request it."
+msgstr ""
+
+#: option.c:265
+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:266
+#, 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:267
+#, fuzzy
+msgid "Log DNS queries."
+msgstr "Înregistrează tranzacţiile."
+
+#: option.c:268
+#, fuzzy
+msgid "Force the originating port for upstream DNS queries."
+msgstr "Forţează acest port pentru datele ce pleacă."
+
+#: option.c:269
+msgid "Do NOT read resolv.conf."
+msgstr "NU citi fiÅŸierul resolv.conf"
+
+#: option.c:270
+#, c-format
+msgid "Specify path to resolv.conf (defaults to %s)."
+msgstr "Specifică calea către resolv.conf (implicit e %s)."
+
+#: option.c:271
+msgid "Specify address(es) of upstream servers with optional domains."
+msgstr "Specifică adresele server(elor) superioare cu domenii opţionale."
+
+#: option.c:272
+msgid "Never forward queries to specified domains."
+msgstr "Nu înaintează cererile spre domeniile specificate."
+
+#: option.c:273
+msgid "Specify the domain to be assigned in DHCP leases."
+msgstr "Specifică domeniul de transmis prin DHCP."
+
+#: option.c:274
+msgid "Specify default target in an MX record."
+msgstr "Specifică o ţintă într-o înregistrare MX."
+
+#: option.c:275
+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:276
+#, fuzzy
+msgid "Specify time-to-live in seconds for negative caching."
+msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts."
+
+#: option.c:277
+#, c-format
+msgid "Change to this user after startup. (defaults to %s)."
+msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)."
+
+#: option.c:278
+#, 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:279
+msgid "Display dnsmasq version and copyright information."
+msgstr "Afişează versiunea dnsmasq şi drepturile de autor."
+
+#: option.c:280
+msgid "Translate IPv4 addresses from upstream servers."
+msgstr "Traduce adresele IPv4 de la serverele DNS superioare."
+
+#: option.c:281
+msgid "Specify a SRV record."
+msgstr "Specifică o înregistrare SRV."
+
+#: option.c:282
+msgid "Display this message. Use --help dhcp for known DHCP options."
+msgstr ""
+
+#: option.c:283
+#, fuzzy, c-format
+msgid "Specify path of PID file (defaults to %s)."
+msgstr "Specifică o cale pentru fişierul PID. (implicit %s)."
+
+#: option.c:284
+#, c-format
+msgid "Specify maximum number of DHCP leases (defaults to %s)."
+msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)."
+
+#: option.c:285
+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:286
+msgid "Specify TXT DNS record."
+msgstr "Specifică o înregistrare TXT."
+
+#: option.c:287
+#, fuzzy
+msgid "Specify PTR DNS record."
+msgstr "Specifică o înregistrare TXT."
+
+#: option.c:288
+msgid "Give DNS name to IPv4 address of interface."
+msgstr ""
+
+#: option.c:289
+msgid "Bind only to interfaces in use."
+msgstr "Ascultă doar pe interfeţele active."
+
+#: option.c:290
+#, c-format
+msgid "Read DHCP static host information from %s."
+msgstr "Citeşte informaţii DHCP statice despre maşină din %s."
+
+#: option.c:291
+msgid "Enable the DBus interface for setting upstream servers, etc."
+msgstr "Activeaza interfaţa DBus pentru configurarea serverelor superioare."
+
+#: option.c:292
+msgid "Do not provide DHCP on this interface, only provide DNS."
+msgstr "Nu activează DHCP ci doar DNS pe această interfaţă."
+
+#: option.c:293
+msgid "Enable dynamic address allocation for bootp."
+msgstr "Activează alocarea dinamică a adreselor pentru BOOTP."
+
+#: option.c:294
+#, 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:295
+msgid "Treat DHCP requests on aliases as arriving from interface."
+msgstr ""
+
+#: option.c:296
+msgid "Disable ICMP echo address checking in the DHCP server."
+msgstr ""
+
+#: option.c:297
+msgid "Script to run on DHCP lease creation and destruction."
+msgstr ""
+
+#: option.c:298
+msgid "Read configuration from all the files in this directory."
+msgstr ""
+
+#: option.c:299
+#, fuzzy
+msgid "Log to this syslog facility or file. (defaults to DAEMON)"
+msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)."
+
+#: option.c:300
+msgid "Do not use leasefile."
+msgstr ""
+
+#: option.c:301
+#, 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:302
+#, c-format
+msgid "Clear DNS cache when reloading %s."
+msgstr ""
+
+#: option.c:303
+msgid "Ignore hostnames provided by DHCP clients."
+msgstr ""
+
+#: option.c:304
+msgid "Do NOT reuse filename and server fields for extra DHCP options."
+msgstr ""
+
+#: option.c:305
+msgid "Enable integrated read-only TFTP server."
+msgstr ""
+
+#: option.c:306
+msgid "Export files by TFTP only from the specified subtree."
+msgstr ""
+
+#: option.c:307
+msgid "Add client IP address to tftp-root."
+msgstr ""
+
+#: option.c:308
+msgid "Allow access only to files owned by the user running dnsmasq."
+msgstr ""
+
+#: option.c:309
+#, 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:310
+msgid "Disable the TFTP blocksize extension."
+msgstr ""
+
+#: option.c:311
+msgid "Ephemeral port range for use by TFTP transfers."
+msgstr ""
+
+#: option.c:312
+msgid "Extra logging for DHCP."
+msgstr ""
+
+#: option.c:313
+msgid "Enable async. logging; optionally set queue length."
+msgstr ""
+
+#: option.c:314
+msgid "Stop DNS rebinding. Filter private IP ranges when resolving."
+msgstr ""
+
+#: option.c:315
+msgid "Always perform DNS queries to all servers."
+msgstr ""
+
+#: option.c:316
+msgid "Set tag if client includes matching option in request."
+msgstr ""
+
+#: option.c:317
+msgid "Use alternative ports for DHCP."
+msgstr ""
+
+#: option.c:318
+msgid "Run lease-change script as this user."
+msgstr ""
+
+#: option.c:319
+#, fuzzy
+msgid "Specify NAPTR DNS record."
+msgstr "Specifică o înregistrare TXT."
+
+#: option.c:320
+msgid "Specify lowest port available for DNS query transmission."
+msgstr ""
+
+#: option.c:321
+msgid "Use only fully qualified domain names for DHCP clients."
+msgstr ""
+
+#: option.c:322
+msgid "Specify alias name for LOCAL DNS name."
+msgstr ""
+
+#: option.c:323
+#, fuzzy
+msgid "Prompt to send to PXE clients."
+msgstr "Configurează opţiuni în plusce trebuie trimise clienţilor DHCP."
+
+#: option.c:324
+msgid "Boot service for PXE menu."
+msgstr ""
+
+#: option.c:325
+msgid "Check configuration syntax."
+msgstr ""
+
+#: option.c:613
+#, c-format
+msgid ""
+"Usage: dnsmasq [options]\n"
+"\n"
+msgstr ""
+"Utilizare: dnsmasq [opţiuni]\n"
+"\n"
+
+#: option.c:615
+#, 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:617
+#, fuzzy, c-format
+msgid "Valid options are:\n"
+msgstr "Opţiunile valide sunt:\n"
+
+#: option.c:658
+#, c-format
+msgid "Known DHCP options:\n"
+msgstr ""
+
+#: option.c:735
+msgid "bad dhcp-option"
+msgstr "dhcp-option invalid"
+
+#: option.c:792
+#, fuzzy
+msgid "bad IP address"
+msgstr "citesc %s - %d adrese"
+
+#: option.c:891
+msgid "bad domain in dhcp-option"
+msgstr "domeniu DNS invalid în declaraţia dhcp-option"
+
+#: option.c:950
+msgid "dhcp-option too long"
+msgstr "declararea dhcp-option este prea lungă"
+
+#: option.c:959
+msgid "illegal dhcp-match"
+msgstr ""
+
+#: option.c:995
+msgid "illegal repeated flag"
+msgstr ""
+
+#: option.c:1003
+msgid "illegal repeated keyword"
+msgstr ""
+
+#: option.c:1086 tftp.c:359
+#, fuzzy, c-format
+msgid "cannot access %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: option.c:1131
+msgid "only one dhcp-hostsfile allowed"
+msgstr ""
+
+#: option.c:1138
+msgid "only one dhcp-optsfile allowed"
+msgstr ""
+
+#: option.c:1183
+msgid "bad MX preference"
+msgstr "preferinţă MX invalidă"
+
+#: option.c:1188
+msgid "bad MX name"
+msgstr "nume MX invalid"
+
+#: option.c:1202
+msgid "bad MX target"
+msgstr "ţintă MX invalidă"
+
+#: option.c:1212
+msgid "cannot run scripts under uClinux"
+msgstr ""
+
+#: option.c:1214
+msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
+msgstr ""
+
+#: option.c:1442 option.c:1446
+msgid "bad port"
+msgstr "port invalid"
+
+#: option.c:1465 option.c:1490
+msgid "interface binding not supported"
+msgstr ""
+
+#: option.c:1611
+#, fuzzy
+msgid "bad port range"
+msgstr "port invalid"
+
+#: option.c:1628
+msgid "bad bridge-interface"
+msgstr ""
+
+#: option.c:1669
+msgid "bad dhcp-range"
+msgstr "dhcp-range invalid"
+
+#: option.c:1695
+msgid "only one netid tag allowed"
+msgstr ""
+
+#: option.c:1740
+msgid "inconsistent DHCP range"
+msgstr "domeniu DHCP inconsistent"
+
+#: option.c:1912
+#, fuzzy
+msgid "bad DHCP host name"
+msgstr "nume MX invalid"
+
+#: option.c:2201 option.c:2481
+msgid "invalid port number"
+msgstr "număr de port invalid"
+
+#: option.c:2284
+#, fuzzy
+msgid "invalid alias range"
+msgstr "pondere invalidă"
+
+#: option.c:2297
+#, fuzzy
+msgid "bad interface name"
+msgstr "nume MX invalid"
+
+#: option.c:2322
+msgid "bad CNAME"
+msgstr ""
+
+#: option.c:2327
+msgid "duplicate CNAME"
+msgstr ""
+
+#: option.c:2347
+#, fuzzy
+msgid "bad PTR record"
+msgstr "înregistrare SRV invalidă"
+
+#: option.c:2378
+#, fuzzy
+msgid "bad NAPTR record"
+msgstr "înregistrare SRV invalidă"
+
+#: option.c:2403
+msgid "TXT record string too long"
+msgstr "şirul de caractere pentru înregistrarea TXT este prea lung"
+
+#: option.c:2451
+msgid "bad TXT record"
+msgstr "înregistrare TXT invalidă"
+
+#: option.c:2467
+msgid "bad SRV record"
+msgstr "înregistrare SRV invalidă"
+
+#: option.c:2474
+msgid "bad SRV target"
+msgstr "ţintă SRV invalidă"
+
+#: option.c:2488
+msgid "invalid priority"
+msgstr "prioritate invalidă"
+
+#: option.c:2495
+msgid "invalid weight"
+msgstr "pondere invalidă"
+
+#: option.c:2514
+msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"
+msgstr ""
+
+#: option.c:2557
+#, c-format
+msgid "files nested too deep in %s"
+msgstr ""
+
+#: option.c:2565 tftp.c:513
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: option.c:2626
+msgid "missing \""
+msgstr "lipseÅŸte \""
+
+#: option.c:2673
+msgid "bad option"
+msgstr "opţiune invalidă"
+
+#: option.c:2675
+msgid "extraneous parameter"
+msgstr "parametru nerecunoscut"
+
+#: option.c:2677
+msgid "missing parameter"
+msgstr "parametru lipsa"
+
+#: option.c:2685
+msgid "error"
+msgstr "eroare"
+
+#: option.c:2691
+#, c-format
+msgid "%s at line %d of %%s"
+msgstr "%s la linia %d din %%s"
+
+#: option.c:2740 option.c:2771
+#, fuzzy, c-format
+msgid "read %s"
+msgstr "citesc %s"
+
+#: option.c:2843
+#, c-format
+msgid "Dnsmasq version %s %s\n"
+msgstr "dnsmasq versiunea %s %s\n"
+
+#: option.c:2844
+#, c-format
+msgid ""
+"Compile time options %s\n"
+"\n"
+msgstr ""
+"Opţiuni cu care a fost compilat %s\n"
+"\n"
+
+#: option.c:2845
+#, c-format
+msgid "This software comes with ABSOLUTELY NO WARRANTY.\n"
+msgstr "Acest program vine FÄ‚RÄ‚ NICI O GARANÅ¢IE.\n"
+
+#: option.c:2846
+#, 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:2847
+#, 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:2858
+msgid "try --help"
+msgstr ""
+
+#: option.c:2860
+msgid "try -w"
+msgstr ""
+
+#: option.c:2863
+#, fuzzy, c-format
+msgid "bad command line options: %s"
+msgstr "opţiuni în linie de comandă invalide: %s."
+
+#: option.c:2904
+#, c-format
+msgid "cannot get host-name: %s"
+msgstr "nu pot citi numele maÅŸinii: %s"
+
+#: option.c:2932
+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:2942
+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:2945 network.c:754 dhcp.c:734
+#, fuzzy, c-format
+msgid "failed to read %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: option.c:2962
+#, 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:2983
+msgid "there must be a default domain when --dhcp-fqdn is set"
+msgstr ""
+
+#: option.c:2987
+msgid "syntax check OK"
+msgstr ""
+
+#: forward.c:409
+#, c-format
+msgid "nameserver %s refused to do a recursive query"
+msgstr "serverul DNS %s refuză interogările recursive"
+
+#: forward.c:437
+msgid "possible DNS-rebind attack detected"
+msgstr ""
+
+#: network.c:73
+#, fuzzy, c-format
+msgid "unknown interface %s in bridge-interface"
+msgstr "interfaţă necunoscută %s"
+
+#: network.c:417 dnsmasq.c:189
+#, c-format
+msgid "failed to create listening socket: %s"
+msgstr "creearea socket-ului de ascultare a eÅŸuat: %s"
+
+#: network.c:424
+#, c-format
+msgid "failed to set IPV6 options on listening socket: %s"
+msgstr "configurarea opţiunilor IPv6 a eşuat pe socket-ul de ascultare: %s"
+
+#: network.c:450
+#, c-format
+msgid "failed to bind listening socket for %s: %s"
+msgstr "activarea socket-ului de ascultare pentru %s a eÅŸuat: %s"
+
+#: network.c:455
+#, c-format
+msgid "failed to listen on socket: %s"
+msgstr "ascultarea pe socket a eÅŸuat: %s"
+
+#: network.c:467
+#, fuzzy, c-format
+msgid "failed to create TFTP socket: %s"
+msgstr "creearea socket-ului de ascultare a eÅŸuat: %s"
+
+#: network.c:661
+#, 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:694
+#, c-format
+msgid "ignoring nameserver %s - local interface"
+msgstr "ignorăm serverul DNS %s - interfaţă locală"
+
+#: network.c:705
+#, 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:720
+msgid "unqualified"
+msgstr "invalid"
+
+#: network.c:720
+msgid "names"
+msgstr ""
+
+#: network.c:722
+msgid "default"
+msgstr ""
+
+#: network.c:724
+msgid "domain"
+msgstr "domeniu"
+
+#: network.c:727
+#, c-format
+msgid "using local addresses only for %s %s"
+msgstr "folosim adresele locale doar pentru %S %s"
+
+#: network.c:729
+#, c-format
+msgid "using nameserver %s#%d for %s %s"
+msgstr "folosim serverul DNS %s#%d pentru %s %s"
+
+#: network.c:732
+#, fuzzy, c-format
+msgid "using nameserver %s#%d(via %s)"
+msgstr "folosim serverul DNS %s#%d"
+
+#: network.c:734
+#, c-format
+msgid "using nameserver %s#%d"
+msgstr "folosim serverul DNS %s#%d"
+
+#: dnsmasq.c:146
+#, 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:151
+msgid "asychronous logging is not available under Solaris"
+msgstr ""
+
+#: dnsmasq.c:170
+#, c-format
+msgid "failed to find list of interfaces: %s"
+msgstr "enumerarea interfeţelor a eşuat: %s"
+
+#: dnsmasq.c:178
+#, c-format
+msgid "unknown interface %s"
+msgstr "interfaţă necunoscută %s"
+
+#: dnsmasq.c:184
+#, c-format
+msgid "no interface with address %s"
+msgstr "nu exista interfaţă pentru adresa %s"
+
+#: dnsmasq.c:201 dnsmasq.c:665
+#, c-format
+msgid "DBus error: %s"
+msgstr "eroare DBus: %s"
+
+#: dnsmasq.c:204
+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:230
+#, c-format
+msgid "unknown user or group: %s"
+msgstr ""
+
+#: dnsmasq.c:287
+#, c-format
+msgid "cannot chdir to filesystem root: %s"
+msgstr ""
+
+#: dnsmasq.c:448
+#, fuzzy, c-format
+msgid "started, version %s DNS disabled"
+msgstr "am pornit, versiunea %s memorie temporară dezactivată"
+
+#: dnsmasq.c:450
+#, c-format
+msgid "started, version %s cachesize %d"
+msgstr "am ponit, versiunea %s memorie temporară %d"
+
+#: dnsmasq.c:452
+#, c-format
+msgid "started, version %s cache disabled"
+msgstr "am pornit, versiunea %s memorie temporară dezactivată"
+
+#: dnsmasq.c:454
+#, c-format
+msgid "compile time options: %s"
+msgstr "compilat cu opţiunile: %s"
+
+#: dnsmasq.c:460
+msgid "DBus support enabled: connected to system bus"
+msgstr "suportul DBus activ: sunt conectat la magistrala sistem"
+
+#: dnsmasq.c:462
+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:467
+#, fuzzy, c-format
+msgid "warning: failed to change owner of %s: %s"
+msgstr "încărcarea numelor din %s: %s a eşuat"
+
+#: dnsmasq.c:471
+msgid "setting --bind-interfaces option because of OS limitations"
+msgstr "specific opţiunea --bind-interfaces din cauza limitărilor SO"
+
+#: dnsmasq.c:476
+#, c-format
+msgid "warning: interface %s does not currently exist"
+msgstr "atenţie: interfaţa %s nu există momentan"
+
+#: dnsmasq.c:481
+msgid "warning: ignoring resolv-file flag because no-resolv is set"
+msgstr ""
+
+#: dnsmasq.c:484
+#, fuzzy
+msgid "warning: no upstream servers configured"
+msgstr "configurăm serverele superioare prin Dbus"
+
+#: dnsmasq.c:488
+#, c-format
+msgid "asynchronous logging enabled, queue limit is %d messages"
+msgstr ""
+
+#: dnsmasq.c:501
+#, 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:503
+#, c-format
+msgid "DHCP, proxy on subnet %.0s%s%.0s"
+msgstr ""
+
+#: dnsmasq.c:504
+#, c-format
+msgid "DHCP, IP range %s -- %s, lease time %s"
+msgstr "DHCP, domeniu IP %s -- %s, timpul reînoirii %s"
+
+#: dnsmasq.c:519
+msgid "root is "
+msgstr ""
+
+#: dnsmasq.c:519
+#, fuzzy
+msgid "enabled"
+msgstr "dezactivat"
+
+#: dnsmasq.c:521
+msgid "secure mode"
+msgstr ""
+
+#: dnsmasq.c:547
+#, c-format
+msgid "restricting maximum simultaneous TFTP transfers to %d"
+msgstr ""
+
+#: dnsmasq.c:667
+msgid "connected to system DBus"
+msgstr "magistrala sistem Dbus conectată"
+
+#: dnsmasq.c:757
+#, c-format
+msgid "cannot fork into background: %s"
+msgstr ""
+
+#: dnsmasq.c:760
+#, fuzzy, c-format
+msgid "failed to create helper: %s"
+msgstr "nu pot citi %s: %s"
+
+#: dnsmasq.c:763
+#, c-format
+msgid "setting capabilities failed: %s"
+msgstr ""
+
+# for compatibility purposes the letters â, ă, ş, ţ and î can be written as their look-alike correspondent.
+#: dnsmasq.c:767
+#, 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:772
+#, fuzzy, c-format
+msgid "failed to change group-id to %s: %s"
+msgstr "încărcarea numelor din %s: %s a eşuat"
+
+#: dnsmasq.c:775
+#, fuzzy, c-format
+msgid "failed to open pidfile %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: dnsmasq.c:778
+#, fuzzy, c-format
+msgid "cannot open %s: %s"
+msgstr "nu pot deschide %s:%s"
+
+#: dnsmasq.c:833
+#, c-format
+msgid "child process killed by signal %d"
+msgstr ""
+
+#: dnsmasq.c:837
+#, c-format
+msgid "child process exited with status %d"
+msgstr ""
+
+#: dnsmasq.c:841
+#, fuzzy, c-format
+msgid "failed to execute %s: %s"
+msgstr "accesarea serverului %s a eÅŸuat: %s"
+
+#: dnsmasq.c:885
+msgid "exiting on receipt of SIGTERM"
+msgstr "am primit SIGTERM, am terminat"
+
+#: dnsmasq.c:903
+#, fuzzy, c-format
+msgid "failed to access %s: %s"
+msgstr "accesarea serverului %s a eÅŸuat: %s"
+
+#: dnsmasq.c:925
+#, c-format
+msgid "reading %s"
+msgstr "citesc %s"
+
+#: dnsmasq.c:936
+#, 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:90
+#, c-format
+msgid "cannot create ICMP raw socket: %s."
+msgstr "nu pot creea socket ICMP raw: %s."
+
+#: dhcp.c:226
+#, c-format
+msgid "DHCP packet received on %s which has no address"
+msgstr ""
+
+#: dhcp.c:385
+#, 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:772
+#, c-format
+msgid "bad line at %s line %d"
+msgstr "linie invalidă în %s rândul %d"
+
+#: dhcp.c:815
+#, c-format
+msgid "ignoring %s line %d, duplicate name or IP address"
+msgstr ""
+
+#: dhcp.c:897
+#, c-format
+msgid "duplicate IP address %s in dhcp-config directive."
+msgstr "adresă IP duplicat %s în declaraţia dhcp-config."
+
+#: dhcp.c:900
+#, fuzzy, c-format
+msgid "duplicate IP address %s in %s."
+msgstr "adresă IP duplicat %s în declaraţia dhcp-config."
+
+#: dhcp.c:943
+#, c-format
+msgid "%s has more than one address in hostsfile, using %s for DHCP"
+msgstr ""
+
+#: dhcp.c:948
+#, 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:66
+#, 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:92
+msgid "too many stored leases"
+msgstr "prea multe împrumuturi stocate"
+
+#: lease.c:128
+#, fuzzy, c-format
+msgid "cannot run lease-init script %s: %s"
+msgstr "nu pot citi %s: %s"
+
+#: lease.c:134
+#, c-format
+msgid "lease-init script returned exit code %s"
+msgstr ""
+
+#: lease.c:234
+#, fuzzy, c-format
+msgid "failed to write %s: %s (retry in %us)"
+msgstr "nu pot citi %s: %s"
+
+#: rfc2131.c:336
+#, 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:337
+msgid "with subnet selector"
+msgstr "cu selectorul de subreţea"
+
+#: rfc2131.c:337
+msgid "via"
+msgstr "prin"
+
+#: rfc2131.c:352
+#, c-format
+msgid "%u Available DHCP subnet: %s/%s"
+msgstr ""
+
+#: rfc2131.c:355
+#, c-format
+msgid "%u Available DHCP range: %s -- %s"
+msgstr ""
+
+#: rfc2131.c:384
+msgid "disabled"
+msgstr "dezactivat"
+
+#: rfc2131.c:418 rfc2131.c:883 rfc2131.c:1242
+msgid "ignored"
+msgstr "ignorat"
+
+#: rfc2131.c:433 rfc2131.c:1100
+msgid "address in use"
+msgstr "adresa este folosită"
+
+#: rfc2131.c:447 rfc2131.c:937
+msgid "no address available"
+msgstr "nici o adresă disponibilă"
+
+#: rfc2131.c:454 rfc2131.c:1063
+msgid "wrong network"
+msgstr "reţea greşită"
+
+#: rfc2131.c:467
+msgid "no address configured"
+msgstr "adresă lipsă"
+
+#: rfc2131.c:473 rfc2131.c:1113
+msgid "no leases left"
+msgstr "nu mai am de unde să împrumut"
+
+#: rfc2131.c:558
+#, c-format
+msgid "%u client provides name: %s"
+msgstr ""
+
+#: rfc2131.c:696
+#, c-format
+msgid "%u Vendor class: %s"
+msgstr ""
+
+#: rfc2131.c:698
+#, c-format
+msgid "%u User class: %s"
+msgstr ""
+
+#: rfc2131.c:737
+msgid "PXE BIS not supported"
+msgstr ""
+
+#: rfc2131.c:853
+#, fuzzy, c-format
+msgid "disabling DHCP static address %s for %s"
+msgstr "dezactivăm adresele DHCP statice %s"
+
+#: rfc2131.c:874
+msgid "unknown lease"
+msgstr "împrumut necunoscut"
+
+#: rfc2131.c:906
+#, c-format
+msgid "not using configured address %s because it is leased to %s"
+msgstr ""
+
+#: rfc2131.c:916
+#, c-format
+msgid "not using configured address %s because it is in use by the server or relay"
+msgstr ""
+
+#: rfc2131.c:919
+#, c-format
+msgid "not using configured address %s because it was previously declined"
+msgstr ""
+
+#: rfc2131.c:935 rfc2131.c:1106
+msgid "no unique-id"
+msgstr ""
+
+#: rfc2131.c:1003
+msgid "wrong server-ID"
+msgstr ""
+
+#: rfc2131.c:1022
+msgid "wrong address"
+msgstr "adresă greşită"
+
+#: rfc2131.c:1039
+msgid "lease not found"
+msgstr "împrumutul nu a fost găsit"
+
+#: rfc2131.c:1071
+msgid "address not available"
+msgstr "adresă indisponibilă"
+
+#: rfc2131.c:1082
+msgid "static lease available"
+msgstr "împrumut static este disponibil"
+
+#: rfc2131.c:1086
+msgid "address reserved"
+msgstr "adresă rezervată"
+
+#: rfc2131.c:1094
+#, c-format
+msgid "abandoning lease to %s of %s"
+msgstr ""
+
+#: rfc2131.c:1583
+#, c-format
+msgid "%u tags: %s"
+msgstr ""
+
+#: rfc2131.c:1596
+#, c-format
+msgid "%u bootfile name: %s"
+msgstr ""
+
+#: rfc2131.c:1605
+#, fuzzy, c-format
+msgid "%u server name: %s"
+msgstr "eroare DBus: %s"
+
+#: rfc2131.c:1613
+#, fuzzy, c-format
+msgid "%u next server: %s"
+msgstr "eroare DBus: %s"
+
+#: rfc2131.c:1680
+#, 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:1919
+msgid "PXE menu too large"
+msgstr ""
+
+#: rfc2131.c:2034
+#, c-format
+msgid "Ignoring domain %s for DHCP host name %s"
+msgstr ""
+
+#: rfc2131.c:2052
+#, fuzzy, c-format
+msgid "%u requested options: %s"
+msgstr "compilat cu opţiunile: %s"
+
+#: netlink.c:66
+#, fuzzy, c-format
+msgid "cannot create netlink socket: %s"
+msgstr "nu pot să activez socket-ul netlink: %s"
+
+#: netlink.c:265
+#, 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:150
+#, c-format
+msgid "cannot create DHCP BPF socket: %s"
+msgstr "nu pot creea socket DHCP BPF: %s"
+
+#: bpf.c:178
+#, 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:179
+msgid "unable to get free port for TFTP"
+msgstr ""
+
+#: tftp.c:194
+#, c-format
+msgid "unsupported request from %s"
+msgstr ""
+
+#: tftp.c:282
+#, c-format
+msgid "TFTP sent %s to %s"
+msgstr ""
+
+#: tftp.c:305
+#, fuzzy, c-format
+msgid "file %s not found"
+msgstr "împrumutul nu a fost găsit"
+
+#: tftp.c:416
+#, c-format
+msgid "TFTP error %d %s received from %s"
+msgstr ""
+
+#: tftp.c:447
+#, fuzzy, c-format
+msgid "TFTP failed sending %s to %s"
+msgstr "nu pot citi %s: %s"
+
+#: log.c:169
+#, c-format
+msgid "overflow: %d log entries lost"
+msgstr ""
+
+#: log.c:246
+#, c-format
+msgid "log failed: %s"
+msgstr ""
+
+#: log.c:415
+msgid "FAILED to start up"
+msgstr "pornirea A EÅžUAT"
+
+#~ 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 "bad dhcp-host"
+#~ msgstr "dhcp-host invalid"
+
+#~ 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 100755
index 0000000..1183f3b
--- /dev/null
+++ b/setup.html
@@ -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 100755
index 0000000..abde78c
--- /dev/null
+++ b/src/bpf.c
@@ -0,0 +1,254 @@
+/* dnsmasq is Copyright (c) 2000-2009 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
+};
+
+int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
+{
+ char *ptr;
+ struct ifreq *ifr;
+ struct ifconf ifc;
+ int fd, errsav, ret = 0;
+ int lastlen = 0;
+ size_t len = 0;
+
+ 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 == AF_INET && ipv4_callback)
+ {
+ 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 (!((*ipv4_callback)(addr,
+ (int)if_nametoindex(ifr->ifr_name),
+ netmask, broadcast,
+ parm)))
+ goto err;
+ }
+#ifdef HAVE_IPV6
+ else if (ifr->ifr_addr.sa_family == AF_INET6 && ipv6_callback)
+ {
+ struct in6_addr *addr = &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr;
+ /* voodoo to clear interface field in address */
+ if (!(daemon->options & OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
+ {
+ addr->s6_addr[2] = 0;
+ addr->s6_addr[3] = 0;
+ }
+ if (!((*ipv6_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 100755
index 0000000..d641ae7
--- /dev/null
+++ b/src/cache.c
@@ -0,0 +1,1317 @@
+/* dnsmasq is Copyright (c) 2000-2009 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 (daemon->options & 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_DHCP | F_CONFIG))
+ 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);
+
+ /* CONFIG bit means something else when stored in cache entries */
+ flags &= ~F_CONFIG;
+
+ /* 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;
+ int 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_CONFIG | 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 ((daemon->options & 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 ((daemon->options & OPT_NO_HOSTS) && !daemon->addn_hosts)
+ {
+ if (daemon->cachesize > 0)
+ my_syslog(LOG_INFO, _("cleared cache"));
+ return;
+ }
+
+ if (!(daemon->options & OPT_NO_HOSTS))
+ total_size = read_hostsfile(HOSTSFILE, 0, total_size);
+
+ for (i = 0, ah = daemon->addn_hosts; 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 = daemon->addn_hosts; 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 = daemon->addn_hosts; 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 = daemon->addn_hosts;
+ daemon->addn_hosts = 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);
+ }
+ }
+ }
+
+ 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_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 (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
+ {
+ strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
+ my_syslog(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);
+ return;
+ }
+ else
+ /* if in hosts, don't need DHCP record */
+ in_hosts = 1;
+ }
+ 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_CONFIG | 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)))
+ {
+ 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)) && 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 ((daemon->options & (OPT_DEBUG | OPT_LOG)))
+ {
+ struct crec *cache ;
+ int i;
+ my_syslog(LOG_DEBUG, "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_DEBUG, 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 short flags, char *name, struct all_addr *addr, char *arg)
+{
+ char *source, *dest = addrbuff;
+ char *verb = "is";
+
+ if (!(daemon->options & 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)
+ {
+ /* nasty abuse of NXDOMAIN and CNAME flags */
+ if (flags & F_NXDOMAIN)
+ dest = arg;
+ else
+ dest = "<CNAME>";
+ }
+
+ 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_DEBUG, "%s %s %s %s", source, name, verb, dest);
+}
+
diff --git a/src/config.h b/src/config.h
new file mode 100755
index 0000000..d5d3b15
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,293 @@
+/* dnsmasq is Copyright (c) 2000-2009 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.51"
+
+#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 1280 /* default max EDNS.0 UDP packet from RFC2671 */
+#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
+#define FORWARD_TEST 50 /* try all servers every 50 queries */
+#define FORWARD_TIME 10 /* or 10 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 150 /* 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"
+# 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 DHCP_SERVER_PORT 67
+#define DHCP_CLIENT_PORT 68
+#define DHCP_SERVER_ALTPORT 1067
+#define DHCP_CLIENT_ALTPORT 1068
+#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 */
+
+/* DBUS interface specifics */
+#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
+#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
+
+/* A small collection of RR-types which are missing on some platforms */
+
+#ifndef T_SIG
+# define T_SIG 24
+#endif
+
+#ifndef T_SRV
+# define T_SRV 33
+#endif
+
+#ifndef T_OPT
+# define T_OPT 41
+#endif
+
+#ifndef T_TKEY
+# define T_TKEY 249
+#endif
+
+#ifndef T_TSIG
+# define T_TSIG 250
+#endif
+
+
+/* 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
+ define some methods to allow (re)configuration of the upstream DNS
+ servers via DBus.
+
+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 */
+
+/* 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
+#undef 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 _XPG4_2
+#define __EXTENSIONS__
+#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 100755
index 0000000..841f924
--- /dev/null
+++ b/src/dbus.c
@@ -0,0 +1,436 @@
+/* dnsmasq is Copyright (c) 2000-2009 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);
+ }
+}
+
+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
+ 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
diff --git a/src/dhcp.c b/src/dhcp.c
new file mode 100755
index 0000000..335fc04
--- /dev/null
+++ b/src/dhcp.c
@@ -0,0 +1,1002 @@
+/* dnsmasq is Copyright (c) 2000-2009 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);
+
+void dhcp_init(void)
+{
+ 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 (daemon->options & 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(daemon->dhcp_server_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);
+
+ daemon->dhcpfd = fd;
+
+#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 (daemon->options & 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)
+{
+ 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;
+
+ 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(daemon->dhcpfd, &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(daemon->dhcpfd, &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)
+ {
+ iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
+ if (((struct in_pktinfo *)CMSG_DATA(cmptr))->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)
+ iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->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)
+ iface_index = *((unsigned int *)CMSG_DATA(cmptr));
+
+#endif
+
+ if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
+ return;
+
+#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;
+
+ /* interface may have been changed by alias in iface_check */
+ if (!addrp)
+ {
+ 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;
+ }
+
+ /* 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;
+
+ 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,
+ now, unicast_dest, &is_inform);
+ 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 (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. */
+ 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 = mess->htype;
+ memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
+ strncpy(req.arp_dev, ifr.ifr_name, 16);
+ req.arp_flags = ATF_COM;
+ ioctl(daemon->dhcpfd, SIOCSARP, &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(daemon->dhcpfd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
+#endif
+
+ while(sendmsg(daemon->dhcpfd, &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 (is_same_net(taddr, tmp->start, tmp->netmask) &&
+ (tmp->flags & CONTEXT_STATIC))
+ break;
+
+ if (!tmp)
+ for (tmp = context; tmp; tmp = tmp->current)
+ if (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)
+ {
+ if (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;
+}
+
+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 */
+ for (j = 0, i = 0; i < hw_len; i++)
+ j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
+
+ 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 (daemon->options & 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->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. */
+char *host_from_dns(struct in_addr addr)
+{
+ struct crec *lookup;
+ char *hostname = NULL;
+ char *d1, *d2;
+
+ 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))
+ {
+ hostname = daemon->dhcp_buff;
+ strncpy(hostname, cache_get_name(lookup), 256);
+ hostname[255] = 0;
+ d1 = strip_hostname(hostname);
+ d2 = get_domain(addr);
+ if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2))))
+ hostname = NULL;
+ }
+
+ return hostname;
+}
+
+/* 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/dnsmasq.c b/src/dnsmasq.c
new file mode 100755
index 0000000..48e3ecf
--- /dev/null
+++ b/src/dnsmasq.c
@@ -0,0 +1,1287 @@
+/* dnsmasq is Copyright (c) 2000-2009 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";
+
+
+
+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);
+static void poll_resolv(void);
+
+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 (!(daemon->options & OPT_NOWILD))
+ {
+ bind_fallback = 1;
+ daemon->options |= OPT_NOWILD;
+ }
+#endif
+
+#ifndef HAVE_TFTP
+ if (daemon->options & OPT_TFTP)
+ 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
+
+ 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 (daemon->options & 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 if ((daemon->port != 0 || (daemon->options & OPT_TFTP)) &&
+ !(daemon->listeners = create_wildcard_listeners()))
+ die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
+
+ if (daemon->port != 0)
+ cache_init();
+
+ if (daemon->options & 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 (!(daemon->options & OPT_DEBUG))
+ {
+ int nullfd;
+
+ /* 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 (!(daemon->options & 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);
+ }
+ }
+
+ /* open stdout etc to /dev/null */
+ nullfd = open("/dev/null", O_RDWR);
+ dup2(nullfd, STDOUT_FILENO);
+ dup2(nullfd, STDERR_FILENO);
+ dup2(nullfd, STDIN_FILENO);
+ close(nullfd);
+ }
+
+ log_err = log_start(ent_pw, err_pipe[1]);
+
+ /* 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 (!(daemon->options & 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) == -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 (daemon->options & OPT_DEBUG)
+ prctl(PR_SET_DUMPABLE, 1);
+#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 (daemon->options & 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 (!(daemon->options & 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 && (daemon->options & 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->options & OPT_TFTP)
+ {
+#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: "",
+ daemon->options & 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 ||
+ ((daemon->options & 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);
+ }
+#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);
+
+ /* 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)
+ {
+ daemon->last_resolv = now;
+
+ if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL))
+ poll_resolv();
+ }
+
+ if (FD_ISSET(piperead, &rset))
+ async_event(piperead, now);
+
+#ifdef HAVE_LINUX_NETWORK
+ if (FD_ISSET(daemon->netlinkfd, &rset))
+ netlink_multicast();
+#endif
+
+#ifdef HAVE_DBUS
+ /* if we didn't create a DBus connection, retry now. */
+ if ((daemon->options & 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 && FD_ISSET(daemon->dhcpfd, &rset))
+ dhcp_packet(now);
+
+# 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 && (daemon->options & 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);
+ }
+}
+
+static void poll_resolv()
+{
+ 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. */
+ for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
+ if (stat(res->name, &statbuf) == -1)
+ {
+ if (!res->logged)
+ my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
+ res->logged = 1;
+ }
+ else
+ {
+ res->logged = 0;
+ if (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 (daemon->options & OPT_RELOAD)
+ cache_reload();
+ }
+ 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 (daemon->options & 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 (daemon->options & 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 (!(daemon->options & 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;
+
+ /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
+ terminate the process. */
+ if (!(daemon->options & OPT_DEBUG))
+ alarm(CHILD_LIFETIME);
+
+ /* 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 (!(daemon->options & 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 100755
index 0000000..e84ea85
--- /dev/null
+++ b/src/dnsmasq.h
@@ -0,0 +1,885 @@
+/* dnsmasq is Copyright (c) 2000-2009 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-2009 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. */
+#ifdef __linux__
+# define _GNU_SOURCE
+# include <features.h>
+#endif
+
+/* get these before config.h for IPv6 stuff... */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifdef __APPLE__
+# include <nameser.h>
+# include <arpa/nameser_compat.h>
+#else
+# include <arpa/nameser.h>
+#endif
+
+/* and this. */
+#include <getopt.h>
+
+#include "config.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>
+#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)
+# 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
+
+#define OPT_BOGUSPRIV (1u<<0)
+#define OPT_FILTER (1u<<1)
+#define OPT_LOG (1u<<2)
+#define OPT_SELFMX (1u<<3)
+#define OPT_NO_HOSTS (1u<<4)
+#define OPT_NO_POLL (1u<<5)
+#define OPT_DEBUG (1u<<6)
+#define OPT_ORDER (1u<<7)
+#define OPT_NO_RESOLV (1u<<8)
+#define OPT_EXPAND (1u<<9)
+#define OPT_LOCALMX (1u<<10)
+#define OPT_NO_NEG (1u<<11)
+#define OPT_NODOTS_LOCAL (1u<<12)
+#define OPT_NOWILD (1u<<13)
+#define OPT_ETHERS (1u<<14)
+#define OPT_RESOLV_DOMAIN (1u<<15)
+#define OPT_NO_FORK (1u<<16)
+#define OPT_AUTHORITATIVE (1u<<17)
+#define OPT_LOCALISE (1u<<18)
+#define OPT_DBUS (1u<<19)
+#define OPT_DHCP_FQDN (1u<<20)
+#define OPT_NO_PING (1u<<21)
+#define OPT_LEASE_RO (1u<<22)
+#define OPT_ALL_SERVERS (1u<<23)
+#define OPT_RELOAD (1u<<24)
+#define OPT_TFTP (1u<<25)
+#define OPT_TFTP_SECURE (1u<<26)
+#define OPT_TFTP_NOBLOCK (1u<<27)
+#define OPT_LOG_OPTS (1u<<28)
+#define OPT_TFTP_APREF (1u<<29)
+#define OPT_NO_OVERRIDE (1u<<30)
+#define OPT_NO_REBIND (1u<<31)
+
+/* 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, *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 1
+#define F_CONFIG 2
+#define F_REVERSE 4
+#define F_FORWARD 8
+#define F_DHCP 16
+#define F_NEG 32
+#define F_HOSTS 64
+#define F_IPV4 128
+#define F_IPV6 256
+#define F_BIGNAME 512
+#define F_UPSTREAM 1024
+#define F_SERVER 2048
+#define F_NXDOMAIN 4096
+#define F_QUERY 8192
+#define F_CNAME 16384
+#define F_NOERR 32768
+
+/* 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 */
+
+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 dhcp_ok, mtu;
+ 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 */
+#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 */
+};
+
+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;
+ 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 DHCP_CHADDR_MAX 16
+
+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 *vendorclass, *userclass, *supplied_hostname;
+ unsigned int vendorclass_len, userclass_len, supplied_hostname_len;
+ 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 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 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_NETID 64
+#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
+
+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;
+ 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
+
+
+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];
+ u8 options[312];
+};
+
+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;
+ struct sockaddr_in peer;
+ char opt_blocksize, opt_transize, netascii, carrylf;
+ struct tftp_file *file;
+ struct tftp_transfer *next;
+};
+
+extern struct daemon {
+ /* datastuctures representing the command-line and
+ config file arguments. All set (including defaults)
+ in option.c */
+
+ unsigned int options;
+ 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;
+ 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;
+ int enable_pxe;
+ struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
+ char *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;
+
+ /* 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];
+
+ /* DHCP state */
+ int dhcpfd, helperfd;
+#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;
+ 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 short 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 short extract_request(HEADER *header, size_t qlen,
+ char *name, unsigned short *typep);
+size_t setup_reply(HEADER *header, size_t qlen,
+ struct all_addr *addrp, unsigned short flags,
+ unsigned long local_ttl);
+int extract_addresses(HEADER *header, size_t qlen, char *namebuff, time_t now);
+size_t answer_request(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(HEADER *header, size_t qlen, char *name,
+ struct bogus_addr *addr, time_t now);
+unsigned char *find_pseudoheader(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(HEADER *header, size_t plen, char *buff);
+size_t resize_packet(HEADER *header, size_t plen,
+ unsigned char *pheader, size_t hlen);
+
+/* 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);
+
+/* 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);
+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);
+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);
+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);
+
+/* 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(void *parm, int (*ipv4_callback)(), int (*ipv6_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);
+void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
+#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 100755
index 0000000..40cda1c
--- /dev/null
+++ b/src/forward.c
@@ -0,0 +1,1094 @@
+/* dnsmasq is Copyright (c) 2000-2009 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(int force, unsigned short force_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 *pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
+ pkt->ipi_ifindex = 0;
+ pkt->ipi_spec_dst = source->addr.addr4;
+ 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)
+ struct in_addr *a = (struct in_addr *)CMSG_DATA(cmptr);
+ *a = 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 *pkt = (struct in6_pktinfo *)CMSG_DATA(cmptr);
+ pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
+ pkt->ipi6_addr = source->addr.addr6;
+ msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ cmptr->cmsg_type = IPV6_PKTINFO;
+ 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 short search_servers(time_t now, struct all_addr **addrpp,
+ unsigned short qtype, char *qdomain, int *type, char **domain)
+
+{
+ /* 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 short 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 short 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 >= matchlen &&
+ (domainlen == 0 || namelen == domainlen || *(serv->domain) == '.' || *(matchstart-1) == '.' ))
+ {
+ unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
+ *type = SERV_HAS_DOMAIN;
+ *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;
+ }
+ }
+ }
+
+ if (flags == 0 && !(qtype & F_BIGNAME) &&
+ (daemon->options & 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);
+ }
+
+ return flags;
+}
+
+static int forward_query(int udpfd, union mysockaddr *udpaddr,
+ struct all_addr *dst_addr, unsigned int dst_iface,
+ HEADER *header, size_t plen, time_t now, struct frec *forward)
+{
+ char *domain = NULL;
+ int type = 0;
+ struct all_addr *addrp = NULL;
+ unsigned int crc = questions_crc(header, plen, daemon->namebuff);
+ unsigned short flags = 0;
+ unsigned short gotname = extract_request(header, plen, daemon->namebuff, NULL);
+ struct server *start = NULL;
+
+ /* 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 (!(daemon->options & 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);
+
+ if (!flags && !(forward = get_new_frec(now, NULL)))
+ /* table full - server failure. */
+ flags = F_NEG;
+
+ if (forward)
+ {
+ /* force unchanging id for signed packets */
+ int is_sign;
+ find_pseudoheader(header, plen, NULL, NULL, &is_sign);
+
+ forward->source = *udpaddr;
+ forward->dest = *dst_addr;
+ forward->iface = dst_iface;
+ forward->orig_id = ntohs(header->id);
+ forward->new_id = get_id(is_sign, forward->orig_id, crc);
+ forward->fd = udpfd;
+ forward->crc = crc;
+ forward->forwardall = 0;
+ header->id = htons(forward->new_id);
+
+ /* In strict_order mode, or when using domain specific servers
+ always try servers in the order specified in resolv.conf,
+ otherwise, use the one last known to work. */
+
+ if (type != 0 || (daemon->options & 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;
+ }
+ }
+ }
+
+ /* 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;
+
+ 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, daemon->options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr, dst_iface);
+ }
+
+ return 0;
+}
+
+static size_t process_reply(HEADER *header, time_t now,
+ struct server *server, size_t n)
+{
+ 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);
+ }
+
+ if (header->opcode != QUERY || (header->rcode != NOERROR && header->rcode != NXDOMAIN))
+ return n;
+
+ /* Complain loudly if the upstream server is non-recursive. */
+ if (!header->ra && header->rcode == 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 (!(daemon->options & OPT_LOG))
+ server->flags |= SERV_WARNED_RECURSIVE;
+ }
+
+ if (daemon->bogus_addr && header->rcode != NXDOMAIN &&
+ check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
+ {
+ munged = 1;
+ header->rcode = NXDOMAIN;
+ header->aa = 0;
+ }
+ else
+ {
+ if (header->rcode == 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->aa = 1;
+ header->rcode = NOERROR;
+ }
+
+ if (extract_addresses(header, n, daemon->namebuff, now))
+ {
+ my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected"));
+ 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 */
+ 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 = (HEADER *)daemon->packet;
+
+ if (!server ||
+ n < (int)sizeof(HEADER) || !header->qr ||
+ !(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff))))
+ return;
+
+ server = forward->sentto;
+
+ if ((header->rcode == SERVFAIL || header->rcode == REFUSED) &&
+ !(daemon->options & 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->qr = 0;
+ header->tc = 0;
+ forward_query(-1, NULL, NULL, 0, header, nn, now, forward);
+ return;
+ }
+ }
+ }
+
+ if ((forward->sentto->flags & SERV_TYPE) == 0)
+ {
+ if (header->rcode == SERVFAIL || header->rcode == 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 (!(daemon->options & 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 ||
+ (header->rcode != REFUSED && header->rcode != SERVFAIL))
+ {
+ if ((nn = process_reply(header, now, server, (size_t)n)))
+ {
+ header->id = htons(forward->orig_id);
+ header->ra = 1; /* recursion if available */
+ send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn,
+ &forward->source, &forward->dest, forward->iface);
+ }
+ free_frec(forward); /* cancel */
+ }
+}
+
+
+void receive_query(struct listener *listen, time_t now)
+{
+ HEADER *header = (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 && (daemon->options & 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(HEADER) ||
+ (msg.msg_flags & MSG_TRUNC) ||
+ header->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 (!(daemon->options & 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)
+ {
+ dst_addr_4 = dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
+ if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->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))
+ if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
+ dst_addr_4 = dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
+ else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+#ifdef HAVE_SOLARIS_NETWORK
+ if_index = *((unsigned int *)CMSG_DATA(cmptr));
+#else
+ if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->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 == IPV6_PKTINFO)
+ {
+ dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
+ if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->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 &&
+ (daemon->options & 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, daemon->options & 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)
+{
+ int size = 0;
+ size_t m;
+ unsigned short qtype, gotname;
+ unsigned char c1, c2;
+ /* Max TCP packet + slop */
+ unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ);
+ 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(HEADER))
+ continue;
+
+ header = (HEADER *)packet;
+
+ 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 short flags = 0;
+ struct all_addr *addrp = NULL;
+ int type = 0;
+ char *domain = NULL;
+
+ if (gotname)
+ flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain);
+
+ if (type != 0 || (daemon->options & 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);
+
+ 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;
+#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;
+
+#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.
+ For signed packets we can't change the ID without breaking the
+ signing, so we keep the same one. In this case force is set, and this
+ routine degenerates into killing any conflicting forward record. */
+static unsigned short get_id(int force, unsigned short force_id, unsigned int crc)
+{
+ unsigned short ret = 0;
+
+ if (force)
+ {
+ struct frec *f = lookup_frec(force_id, crc);
+ if (f)
+ free_frec(f); /* free */
+ ret = force_id;
+ }
+ else do
+ ret = rand16();
+ while (lookup_frec(ret, crc));
+
+ return ret;
+}
+
+
+
+
+
diff --git a/src/helper.c b/src/helper.c
new file mode 100755
index 0000000..b992e78
--- /dev/null
+++ b/src/helper.c
@@ -0,0 +1,428 @@
+/* dnsmasq is Copyright (c) 2000-2009 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);
+
+struct script_data
+{
+ unsigned char action, hwaddr_len, hwaddr_type;
+ unsigned char clid_len, hostname_len, uclass_len, vclass_len, shost_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 (!(daemon->options & OPT_DEBUG) && uid != 0)
+ {
+ gid_t dummy;
+ if (setgroups(0, &dummy) == -1 ||
+ setgid(gid) == -1 ||
+ setuid(uid) == -1)
+ {
+ if (daemon->options & 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;
+ 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 */
+ if (!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
+
+ if (!read_write(pipefd[0], buf,
+ data.hostname_len + data.uclass_len + data.vclass_len + data.shost_len, 1))
+ continue;
+
+ /* possible fork errors are all temporary resource problems */
+ while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
+ sleep(2);
+
+ 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.vclass_len != 0)
+ {
+ buf[data.vclass_len - 1] = 0; /* don't trust zero-term */
+ /* cannot have = chars in env - truncate if found . */
+ if ((p = strchr((char *)buf, '=')))
+ *p = 0;
+ my_setenv("DNSMASQ_VENDOR_CLASS", (char *)buf, &err);
+ buf += data.vclass_len;
+ }
+
+ if (data.uclass_len != 0)
+ {
+ unsigned char *end = buf + data.uclass_len;
+ buf[data.uclass_len - 1] = 0; /* don't trust zero-term */
+
+ for (i = 0; buf < end;)
+ {
+ size_t len = strlen((char *)buf) + 1;
+ if ((p = strchr((char *)buf, '=')))
+ *p = 0;
+ if (strlen((char *)buf) != 0)
+ {
+ sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i++);
+ my_setenv(daemon->dhcp_buff2, (char *)buf, &err);
+ }
+ buf += len;
+ }
+ }
+
+ if (data.shost_len != 0)
+ {
+ buf[data.shost_len - 1] = 0; /* don't trust zero-term */
+ /* cannot have = chars in env - truncate if found . */
+ if ((p = strchr((char *)buf, '=')))
+ *p = 0;
+ my_setenv("DNSMASQ_SUPPLIED_HOSTNAME", (char *)buf, &err);
+ buf += data.shost_len;
+ }
+
+ if (data.giaddr.s_addr != 0)
+ my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
+
+ sprintf(daemon->dhcp_buff2, "%u ", data.remaining_time);
+ my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
+
+ 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;
+ }
+ }
+
+ 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;
+}
+
+/* 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, vclass_len = 0;
+ unsigned int uclass_len = 0, shost_len = 0;
+
+ /* no script */
+ if (daemon->helperfd == -1)
+ return;
+
+ if (lease->vendorclass)
+ vclass_len = lease->vendorclass_len;
+ if (lease->userclass)
+ uclass_len = lease->userclass_len;
+ if (lease->supplied_hostname)
+ shost_len = lease->supplied_hostname_len;
+ if (lease->clid)
+ clid_len = lease->clid_len;
+ if (hostname)
+ hostname_len = strlen(hostname) + 1;
+
+ size = sizeof(struct script_data) + clid_len + vclass_len + uclass_len + shost_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->vclass_len = vclass_len;
+ buf->uclass_len = uclass_len;
+ buf->shost_len = shost_len;
+ buf->hostname_len = hostname_len;
+ buf->addr = lease->addr;
+ buf->giaddr = lease->giaddr;
+ memcpy(buf->hwaddr, lease->hwaddr, lease->hwaddr_len);
+ buf->interface[0] = 0;
+#ifdef HAVE_LINUX_NETWORK
+ if (lease->last_interface != 0)
+ {
+ struct ifreq ifr;
+ ifr.ifr_ifindex = lease->last_interface;
+ if (ioctl(daemon->dhcpfd, SIOCGIFNAME, &ifr) != -1)
+ strncpy(buf->interface, ifr.ifr_name, IF_NAMESIZE);
+ }
+#else
+ if (lease->last_interface != 0)
+ if_indextoname(lease->last_interface, buf->interface);
+#endif
+
+#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 (vclass_len != 0)
+ {
+ memcpy(p, lease->vendorclass, vclass_len);
+ p += vclass_len;
+ }
+ if (uclass_len != 0)
+ {
+ memcpy(p, lease->userclass, uclass_len);
+ p += uclass_len;
+ }
+ if (shost_len != 0)
+ {
+ memcpy(p, lease->supplied_hostname, shost_len);
+ p += shost_len;
+ }
+ if (hostname_len != 0)
+ {
+ memcpy(p, hostname, hostname_len);
+ p += hostname_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 100755
index 0000000..c021d15
--- /dev/null
+++ b/src/lease.c
@@ -0,0 +1,622 @@
+/* dnsmasq is Copyright (c) 2000-2009 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 two 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);
+
+ leases_left = daemon->dhcp_max;
+
+ if (daemon->options & 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 (!(daemon->options & 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 (daemon->options & 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 ((daemon->options & 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->vendorclass);
+ free(lease->userclass);
+ free(lease->supplied_hostname);
+ 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 && (daemon->options & 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;
+
+ /* these are used for the "add" call, then junked, since they're not in the database */
+ free(lease->vendorclass);
+ lease->vendorclass = NULL;
+
+ free(lease->userclass);
+ lease->userclass = NULL;
+
+ free(lease->supplied_hostname);
+ lease->supplied_hostname = NULL;
+
+ return 1;
+ }
+
+ return 0; /* nothing to do */
+}
+
+#endif
+
+
+
+
diff --git a/src/log.c b/src/log.c
new file mode 100755
index 0000000..7ec491d
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,419 @@
+/* dnsmasq is Copyright (c) 2000-2009 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"
+
+/* 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 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;
+
+ log_stderr = !!(daemon->options & OPT_DEBUG);
+
+ if (daemon->log_fac != -1)
+ log_fac = daemon->log_fac;
+#ifdef LOG_LOCAL0
+ else if (daemon->options & OPT_DEBUG)
+ log_fac = LOG_LOCAL0;
+#endif
+
+ if (daemon->log_file)
+ {
+ log_to_file = 1;
+ daemon->max_logs = 0;
+ }
+
+ 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 && 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_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);
+ return log_fd != -1;
+ }
+ else
+#ifdef HAVE_SOLARIS_NETWORK
+ /* 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 */
+ log_fd = -1;
+#else
+ {
+ int flags;
+ log_fd = socket(AF_UNIX, connection_type, 0);
+
+ if (log_fd == -1)
+ return 0;
+
+ /* if max_logs is zero, leave the socket blocking */
+ if (max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1)
+ fcntl(log_fd, F_SETFL, flags | O_NONBLOCK);
+ }
+#endif
+
+ return 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";
+
+ priority = LOG_PRI(priority);
+
+ if (log_stderr)
+ {
+ fprintf(stderr, "dnsmasq%s: ", func);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ }
+
+ if (log_fd == -1)
+ {
+ /* fall-back to syslog if we die during startup or fail during running. */
+ 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);
+ 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);
+
+ p += sprintf(p, "%.15s dnsmasq%s[%d]: ", ctime(&time_now) + 4, 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)
+{
+ /* block until queue empty */
+ if (log_fd != -1)
+ {
+ int flags;
+ if ((flags = fcntl(log_fd, F_GETFL)) != -1)
+ fcntl(log_fd, F_SETFL, flags & ~O_NONBLOCK);
+ log_write();
+ close(log_fd);
+ }
+}
+
+void die(char *message, char *arg1, int exit_code)
+{
+ char *errmess = strerror(errno);
+
+ if (!arg1)
+ arg1 = errmess;
+
+ log_stderr = 1; /* print as well as log when we die.... */
+ fputc('\n', stderr); /* prettyfy startup-script message */
+ my_syslog(LOG_CRIT, message, arg1, errmess);
+
+ log_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 100755
index 0000000..77c4385
--- /dev/null
+++ b/src/netlink.c
@@ -0,0 +1,303 @@
+/* dnsmasq is Copyright (c) 2000-2009 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
+
+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;
+}
+
+int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
+{
+ struct sockaddr_nl addr;
+ struct nlmsghdr *h;
+ ssize_t len;
+ static unsigned int seq = 0;
+ int family = AF_INET;
+
+ 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 = 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)
+ {
+#ifdef HAVE_IPV6
+ if (family == AF_INET && ipv6_callback)
+ {
+ family = AF_INET6;
+ goto again;
+ }
+#endif
+ return 1;
+ }
+ else if (h->nlmsg_type == RTM_NEWADDR)
+ {
+ 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 == 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 && ipv4_callback)
+ if (!((*ipv4_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 && ipv6_callback)
+ if (!((*ipv6_callback)(addrp, ifa->ifa_index, ifa->ifa_index, parm)))
+ return 0;
+ }
+#endif
+ }
+ }
+}
+
+
+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 100755
index 0000000..68113fb
--- /dev/null
+++ b/src/network.c
@@ -0,0 +1,874 @@
+/* dnsmasq is Copyright (c) 2000-2009 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;
+}
+
+#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 (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;
+ }
+ }
+
+ if (daemon->if_names || (addr && daemon->if_addrs))
+ {
+ ret = 0;
+
+ 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;
+
+ 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 dhcp_ok = 1;
+ struct iname *tmp;
+
+ /* 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;
+ }
+ }
+
+ if (addr->sa.sa_family == AF_INET &&
+ !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL))
+ return 1;
+
+ for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+ if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
+ dhcp_ok = 0;
+
+#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->dhcp_ok = dhcp_ok;
+ iface->mtu = mtu;
+ 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
+ return iface_enumerate(&daemon->interfaces, iface_allowed_v4, iface_allowed_v6);
+#else
+ return iface_enumerate(&daemon->interfaces, iface_allowed_v4, NULL);
+#endif
+}
+
+/* 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;
+}
+
+#if defined(HAVE_IPV6)
+static int create_ipv6_listener(struct listener **link, int port)
+{
+ union mysockaddr addr;
+ int tcpfd, fd;
+ struct listener *l;
+ int opt = 1;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.in6.sin6_family = AF_INET6;
+ addr.in6.sin6_addr = in6addr_any;
+ addr.in6.sin6_port = htons(port);
+#ifdef HAVE_SOCKADDR_SA_LEN
+ addr.in6.sin6_len = sizeof(addr.in6);
+#endif
+
+ /* No error of the kernel doesn't support IPv6 */
+ if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
+ return (errno == EPROTONOSUPPORT ||
+ errno == EAFNOSUPPORT ||
+ errno == EINVAL);
+
+ if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
+ return 0;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
+ setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
+ setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
+ setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
+ !fix_fd(fd) ||
+ !fix_fd(tcpfd) ||
+#ifdef IPV6_RECVPKTINFO
+ setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
+#else
+ setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
+#endif
+ bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
+ listen(tcpfd, 5) == -1 ||
+ bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
+ return 0;
+
+ l = safe_malloc(sizeof(struct listener));
+ l->fd = fd;
+ l->tcpfd = tcpfd;
+ l->tftpfd = -1;
+ l->family = AF_INET6;
+ l->next = NULL;
+ *link = l;
+
+ return 1;
+}
+#endif
+
+struct listener *create_wildcard_listeners(void)
+{
+ union mysockaddr addr;
+ int opt = 1;
+ struct listener *l, *l6 = NULL;
+ int tcpfd = -1, fd = -1, tftpfd = -1;
+
+ 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->port);
+#ifdef HAVE_SOCKADDR_SA_LEN
+ addr.in.sin_len = sizeof(struct sockaddr_in);
+#endif
+
+ if (daemon->port != 0)
+ {
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
+ (tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ return NULL;
+
+ if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
+ bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
+ listen(tcpfd, 5) == -1 ||
+ !fix_fd(tcpfd) ||
+#ifdef HAVE_IPV6
+ !create_ipv6_listener(&l6, daemon->port) ||
+#endif
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
+ !fix_fd(fd) ||
+#if defined(HAVE_LINUX_NETWORK)
+ setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
+#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+ setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
+ setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
+#endif
+ bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
+ return NULL;
+ }
+
+#ifdef HAVE_TFTP
+ if (daemon->options & OPT_TFTP)
+ {
+ addr.in.sin_port = htons(TFTP_PORT);
+ if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ return NULL;
+
+ if (!fix_fd(tftpfd) ||
+#if defined(HAVE_LINUX_NETWORK)
+ setsockopt(tftpfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
+#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+ setsockopt(tftpfd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
+ setsockopt(tftpfd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
+#endif
+ bind(tftpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
+ return NULL;
+ }
+#endif
+
+ l = safe_malloc(sizeof(struct listener));
+ l->family = AF_INET;
+ l->fd = fd;
+ l->tcpfd = tcpfd;
+ l->tftpfd = tftpfd;
+ l->next = l6;
+
+ return l;
+}
+
+struct listener *create_bound_listeners(void)
+{
+ struct listener *listeners = NULL;
+ struct irec *iface;
+ int rc, opt = 1;
+#ifdef HAVE_IPV6
+ static int dad_count = 0;
+#endif
+
+ for (iface = daemon->interfaces; iface; iface = iface->next)
+ {
+ struct listener *new = safe_malloc(sizeof(struct listener));
+ new->family = iface->addr.sa.sa_family;
+ new->iface = iface;
+ new->next = listeners;
+ new->tftpfd = -1;
+ new->tcpfd = -1;
+ new->fd = -1;
+ listeners = new;
+
+ if (daemon->port != 0)
+ {
+ if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
+ (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
+ setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
+ setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
+ !fix_fd(new->tcpfd) ||
+ !fix_fd(new->fd))
+ die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
+
+#ifdef HAVE_IPV6
+ if (iface->addr.sa.sa_family == AF_INET6)
+ {
+ if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
+ setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
+ die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);
+ }
+#endif
+
+ while(1)
+ {
+ if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->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 (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) &&
+ dad_count++ < DAD_WAIT)
+ {
+ sleep(1);
+ continue;
+ }
+#endif
+ break;
+ }
+
+ if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
+ {
+ prettyprint_addr(&iface->addr, daemon->namebuff);
+ die(_("failed to bind listening socket for %s: %s"),
+ daemon->namebuff, EC_BADNET);
+ }
+
+ if (listen(new->tcpfd, 5) == -1)
+ die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
+ }
+
+#ifdef HAVE_TFTP
+ if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
+ {
+ short save = iface->addr.in.sin_port;
+ iface->addr.in.sin_port = htons(TFTP_PORT);
+ if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
+ setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
+ !fix_fd(new->tftpfd) ||
+ bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
+ die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET);
+ iface->addr.in.sin_port = save;
+ }
+#endif
+
+ }
+
+ 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, strlen(intname)) == -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)) &&
+ !allocate_sfd(&srv->source_addr, srv->interface) &&
+ errno != 0 &&
+ (daemon->options & OPT_NOWILD))
+ {
+ prettyprint_addr(&srv->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;
+
+ for (new = daemon->servers; new; new = tmp)
+ {
+ tmp = new->next;
+
+ if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
+ {
+ 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_HAS_DOMAIN | SERV_FOR_NODOTS))
+ {
+ 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_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;
+
+ for (l = daemon->listeners; l && l->family != AF_INET; 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)
+ ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = -1;
+
+ return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+}
+
+
+
diff --git a/src/option.c b/src/option.c
new file mode 100755
index 0000000..abea37e
--- /dev/null
+++ b/src/option.c
@@ -0,0 +1,2990 @@
+/* dnsmasq is Copyright (c) 2000-2009 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 nest, 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
+
+#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", 0, 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 },
+ { "all-servers", 0, 0, LOPT_NOLAST },
+ { "dhcp-match", 1, 0, LOPT_MATCH },
+ { "dhcp-broadcast", 1, 0, LOPT_BROADCAST },
+ { "neg-ttl", 1, 0, LOPT_NEGTTL },
+ { "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 },
+ { NULL, 0, 0, 0 }
+ };
+
+/* These must have more the one '1' bit */
+#define ARG_DUP 3
+#define ARG_ONE 5
+#define ARG_USED_CL 7
+#define ARG_USED_FILE 9
+
+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_ONE, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL },
+ { LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file"), 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, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
+ { LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
+ { LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
+ { LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
+ { 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
+ { LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]", 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 },
+ { 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
+ { 'U', ARG_DUP, "<id>,<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, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
+ { '4', ARG_DUP, "<id>,<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, "[=<id>[,<id>]]", 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, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
+ { LOPT_PREFIX, ARG_ONE, "<directory>", 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_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
+ { LOPT_MATCH, ARG_DUP, "<netid>,<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_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 },
+ { 0, 0, NULL, NULL, NULL }
+};
+
+#ifdef HAVE_DHCP
+/* makes options which take a list of addresses */
+#define OT_ADDR_LIST 0x80
+/* DHCP-internal options, for logging. not valid in config file */
+#define OT_INTERNAL 0x40
+#define OT_NAME 0x20
+
+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, 0 },
+ { "extension-path", 18, 0 },
+ { "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, 0 },
+ { "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, 0 },
+ { "nis+-server", 65, OT_ADDR_LIST },
+ { "tftp-server", 66, 0 },
+ { "bootfile-name", 67, 0 },
+ { "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, 0 },
+ { "sip-server", 120, 0 },
+ { "classless-static-route", 121, 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 (; isspace((int)*comma); comma++);
+
+ for (; (p >= s) && isspace((int)*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("%-36.36s", 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);
+}
+
+/* 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
+ {
+ new->netid = opt_malloc(sizeof (struct dhcp_netid));
+ /* allow optional "net:" for consistency */
+ if (strstr(arg, "net:") == arg)
+ new->netid->net = opt_string_alloc(arg+4);
+ else
+ new->netid->net = opt_string_alloc(arg);
+ new->netid->next = np;
+ np = new->netid;
+ }
+
+ arg = comma;
+ }
+
+ if (new->opt == 0)
+ problem = _("bad dhcp-option");
+ else if (comma)
+ {
+ /* characterise the value */
+ char c;
+ 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;
+ }
+
+ /* 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");
+ }
+
+ 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) && new->opt == 120)
+ {
+ *(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 == 119 || new->opt == 120) && !(new->flags & DHOPT_ENCAPSULATE))
+ {
+ /* 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 == 119) ? 0 : 1;
+
+ arg = comma;
+ comma = split(arg);
+
+ while (arg && *arg)
+ {
+ char *dom;
+ if (!(dom = arg = canonicalise_opt(arg)))
+ {
+ problem = _("bad domain in dhcp-option");
+ break;
+ }
+
+ newp = opt_malloc(len + strlen(arg) + 2 + header_size);
+ if (m)
+ memcpy(newp, m, header_size + len);
+ m = newp;
+ p = m + header_size;
+ q = p + len;
+
+ /* add string on the end in RFC1035 format */
+ while (*arg)
+ {
+ unsigned char *cp = q++;
+ int j;
+ for (j = 0; *arg && (*arg != '.'); arg++, j++)
+ *q++ = *arg;
+ *cp = j;
+ if (*arg)
+ arg++;
+ }
+ *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 == 120)
+ 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))))
+ 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
+
+static char *one_opt(int option, char *arg, char *gen_prob, int nest)
+{
+ 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 (nest == 0)
+ {
+ /* 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)
+ {
+ daemon->options |= rept;
+ return NULL;
+ }
+
+ break;
+ }
+
+ switch (option)
+ {
+ case 'C': /* --conf-file */
+ {
+ char *file = opt_string_alloc(arg);
+ if (file)
+ {
+ one_file(file, nest, 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;
+
+ /* dir is one level, so files must be readable */
+ one_file(path, nest + 1, 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, '/'))
+ daemon->log_file = opt_string_alloc(arg);
+ 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";
+ }
+ break;
+
+ case 'x': /* --pid-file */
+ daemon->runfile = opt_string_alloc(arg);
+ break;
+
+ case LOPT_DHCP_HOST: /* --dhcp-hostfile */
+ if (daemon->dhcp_hosts_file)
+ problem = _("only one dhcp-hostsfile allowed");
+ else
+ daemon->dhcp_hosts_file = opt_string_alloc(arg);
+ break;
+
+ case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
+ if (daemon->dhcp_opts_file)
+ problem = _("only one dhcp-optsfile allowed");
+ else
+ daemon->dhcp_opts_file = 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 '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;
+ new->next = daemon->addn_hosts;
+ daemon->addn_hosts = new;
+ break;
+ }
+
+ case 's': /* --domain */
+ if (strcmp (arg, "#") == 0)
+ daemon->options |= 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));
+ unhide_metas(comma);
+ if ((arg = split_chr(comma, '/')))
+ {
+ int mask;
+ if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 ||
+ !atoi_check(arg, &mask))
+ option = '?';
+ else
+ {
+ mask = (1 << (32 - mask)) - 1;
+ new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
+ new->end.s_addr = new->start.s_addr | htonl(mask);
+ }
+ }
+ 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 */
+ {
+ struct server *serv, *newlist = NULL;
+
+ unhide_metas(arg);
+
+ if (arg && *arg == '/')
+ {
+ char *end;
+ arg++;
+ while ((end = split_chr(arg, '/')))
+ {
+ char *domain = NULL;
+ /* # 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 (!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 = '?';
+ }
+
+ if (!arg || !*arg)
+ {
+ newlist->flags |= SERV_NO_ADDR; /* no server */
+ 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);
+#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);
+#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 */
+ {
+ int ttl;
+ if (!atoi_check(arg, &ttl))
+ option = '?';
+ else if (option == LOPT_NEGTTL)
+ daemon->neg_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_MAX: /* --tftp-max */
+ if (!atoi_check(arg, &daemon->tftp_max))
+ option = '?';
+ break;
+
+ case LOPT_PREFIX: /* --tftp-prefix */
+ 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)))
+ {
+ problem = _("bad bridge-interface");
+ break;
+ }
+
+ strncpy(new->iface, arg, IF_NAMESIZE);
+ new->alias = NULL;
+ new->next = daemon->bridges;
+ daemon->bridges = new;
+
+ do {
+ arg = comma;
+ comma = split(arg);
+ if (strlen(arg) != 0)
+ {
+ struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge));
+ b->next = new->alias;
+ new->alias = b;
+ strncpy(b->iface, arg, IF_NAMESIZE);
+ }
+ } 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;
+
+ 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, "net:") == 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 netid tag allowed");
+ 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;
+
+ 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 ((new->clid = opt_malloc(len)))
+ {
+ new->flags |= CONFIG_CLID;
+ new->clid_len = len;
+ memcpy(new->clid, arg, len);
+ }
+ }
+ }
+ else if (strstr(arg, "net:") == arg)
+ {
+ int len = strlen(arg + 4) + 1;
+ if ((new->netid.net = opt_malloc(len)))
+ {
+ new->flags |= CONFIG_NETID;
+ strcpy(new->netid.net, arg+4);
+ unhide_metas(new->netid.net);
+ }
+ }
+ else
+ {
+ struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
+ newhw->next = new->hwaddr;
+ new->hwaddr = newhw;
+ newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
+ &newhw->wildcard_mask, &newhw->hwaddr_type);
+ }
+ }
+ 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((int)*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 '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 (arg && strstr(arg, "net:") == 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 (arg && strstr(arg, "net:") == 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 (arg && strstr(arg, "net:") == 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)
+ {
+ 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));
+ if (strstr(arg, "net:") == arg)
+ new->netid.net = opt_string_alloc(arg+4);
+ else
+ new->netid.net = opt_string_alloc(arg);
+ unhide_metas(comma);
+ new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
+ 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
+ {
+ char *p;
+ int dig = 0;
+ struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
+ if (strstr(arg, "net:") == arg)
+ new->netid.net = opt_string_alloc(arg+4);
+ else
+ new->netid.net = opt_string_alloc(arg);
+ /* check for hex string - must digits may include : must not have nothing else,
+ only allowed for agent-options. */
+ for (p = comma; *p; p++)
+ if (isxdigit((int)*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 */
+ {
+ 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
+ {
+ 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 (strstr(arg, "net:") == arg)
+ member->net = opt_string_alloc(arg+4);
+ else
+ member->net = opt_string_alloc(arg);
+ arg = comma;
+ }
+
+ new->list = list;
+ 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, *q;
+
+ if ((comma = split(arg)))
+ comma--;
+
+ gen_prob = _("TXT record string too long");
+
+ if ((q = (unsigned char *)comma))
+ while (1)
+ {
+ size_t len;
+ if ((p = (unsigned char *)strchr((char*)q+1, ',')))
+ {
+ if ((len = p - q - 1) > 255)
+ option = '?';
+ *q = len;
+ for (q = q+1; q < p; q++)
+ *q = unhide_meta(*q);
+ }
+ else
+ {
+ if ((len = strlen((char *)q+1)) > 255)
+ option = '?';
+ *q = len;
+ for (q = q+1; *q; q++)
+ *q = unhide_meta(*q);
+ break;
+ }
+ }
+
+ new = opt_malloc(sizeof(struct txt_record));
+ new->next = daemon->txt;
+ daemon->txt = new;
+ new->class = C_IN;
+ if (comma)
+ {
+ new->len = q - ((unsigned char *)comma);
+ new->txt = opt_malloc(new->len);
+ memcpy(new->txt, comma, new->len);
+ }
+ else
+ {
+ static char empty[] = "";
+ new->len = 1;
+ new->txt = empty;
+ }
+
+ /* ensure arg is terminated */
+ if (comma)
+ *comma = 0;
+
+ if (!(new->name = canonicalise_opt(arg)))
+ {
+ problem = _("bad TXT record");
+ break;
+ }
+
+ 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 one_file(char *file, int nest, int hard_opt)
+{
+ volatile int lineno = 0;
+ int i, option;
+ FILE *f;
+ char *p, *arg, *start, *buff = daemon->namebuff;
+ static struct fileread {
+ dev_t dev;
+ ino_t ino;
+ struct fileread *next;
+ } *filesread = NULL;
+ struct stat statbuf;
+
+ /* ignore repeated files. */
+ 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 (nest > 20)
+ die(_("files nested too deep in %s"), file, EC_BADCONF);
+
+ if (!(f = fopen(file, "r")))
+ {
+ if (errno == ENOENT && nest == 0)
+ 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);
+ }
+ }
+
+ while (fgets(buff, MAXDNAME, f))
+ {
+ int white;
+ unsigned int lastquote;
+ char *errmess;
+
+ /* 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, lastquote = 0, 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 == '"')
+ {
+ memmove(p, p+1, strlen(p+1)+1);
+ lastquote = p - buff;
+ }
+ else
+ {
+ errmess = _("missing \"");
+ goto oops;
+ }
+ }
+
+ if (white && *p == '#')
+ {
+ *p = 0;
+ break;
+ }
+ white = isspace((int)unhide_meta(*p));
+ }
+
+ /* fgets gets end of line char too. */
+ while (strlen(buff) > lastquote && isspace((int)unhide_meta(buff[strlen(buff)-1])))
+ buff[strlen(buff)-1] = 0;
+
+ if (*buff == 0)
+ continue;
+
+ if (hard_opt != 0)
+ arg = buff;
+ else if ((p=strchr(buff, '=')))
+ {
+ /* allow spaces around "=" */
+ arg = p+1;
+ for (; p >= buff && (isspace((int)*p) || *p == '='); p--)
+ *p = 0;
+ }
+ else
+ arg = NULL;
+
+ if (hard_opt != 0)
+ option = hard_opt;
+ else
+ {
+ /* skip leading space */
+ for (start = buff; *start && isspace((int)*start); start++);
+
+ 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)
+ {
+ if (arg)
+ for (; isspace((int)*arg); arg++);
+
+ errmess = one_opt(option, arg, _("error"), nest + 1);
+ }
+
+ 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 = 1;
+ fclose(f);
+}
+
+#ifdef HAVE_DHCP
+void reread_dhcp(void)
+{
+ 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;
+
+ for (mac = configs->hwaddr; mac; mac = tmp)
+ {
+ tmp = mac->next;
+ free(mac);
+ }
+ if (configs->flags & CONFIG_CLID)
+ free(configs->clid);
+ if (configs->flags & CONFIG_NETID)
+ free(configs->netid.net);
+ if (configs->flags & CONFIG_NAME)
+ free(configs->hostname);
+
+
+ *up = configs->next;
+ free(configs);
+ }
+ else
+ up = &configs->next;
+ }
+
+ one_file(daemon->dhcp_hosts_file, 1, LOPT_BANK);
+ my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_hosts_file);
+ }
+
+ 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;
+ }
+
+ one_file(daemon->dhcp_opts_file, 1, LOPT_OPTS);
+ my_syslog(MS_DHCP | LOG_INFO, _("read %s"), daemon->dhcp_opts_file);
+ }
+}
+#endif
+
+void read_opts(int argc, char **argv, char *compile_opts)
+{
+ char *buff = opt_malloc(MAXDNAME);
+ int option, nest = 0, 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)
+ 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_string_alloc(arg);
+ nest++;
+ }
+ else
+ {
+#ifdef HAVE_GETOPT_LONG
+ errmess = one_opt(option, arg, _("try --help"), 0);
+#else
+ errmess = one_opt(option, arg, _("try -w"), 0);
+#endif
+ if (errmess)
+ die(_("bad command line options: %s"), errmess, EC_BADCONF);
+ }
+ }
+
+ if (conffile)
+ one_file(conffile, nest, 0);
+
+ /* 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 ((daemon->options & 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 || (daemon->options & 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 (!(daemon->options & OPT_NO_RESOLV) &&
+ daemon->resolv_files &&
+ daemon->resolv_files->next &&
+ (daemon->options & OPT_NO_POLL))
+ die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF);
+
+ if (daemon->options & OPT_RESOLV_DOMAIN)
+ {
+ char *line;
+ FILE *f;
+
+ if ((daemon->options & 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 (daemon->options & 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 100755
index 0000000..ca5ceba
--- /dev/null
+++ b/src/rfc1035.c
@@ -0,0 +1,1604 @@
+/* dnsmasq is Copyright (c) 2000-2009 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(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(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((int)*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((int) *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((int)*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, 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(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, 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(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(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(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 (header->opcode == 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;
+}
+
+
+/* is addr in the non-globally-routed IP space? */
+static int private_net(struct in_addr addr)
+{
+ in_addr_t ip_addr = ntohl(addr.s_addr);
+
+ return
+ ((ip_addr & 0xFF000000) == 0x7F000000) /* 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, HEADER *header, size_t qlen)
+{
+ int i, qtype, qclass, rdlen;
+ unsigned long ttl;
+
+ for (i = count; 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_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->aa = 0;
+ memcpy(p, &addr, INADDRSZ);
+ break;
+ }
+ }
+
+ if (!ADD_RDLEN(header, p, qlen, rdlen))
+ return 0; /* bad packet */
+ }
+
+ return p;
+}
+
+static int find_soa(HEADER *header, size_t qlen)
+{
+ 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)))
+ 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))
+ 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 parct of dns-rebinding attack. */
+int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
+{
+ 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 side-effects, so don't call it lazily if there are any. */
+ if (daemon->doctors)
+ {
+ searched_soa = 1;
+ ttl = find_soa(header, qlen);
+ }
+
+ /* 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 = header->rcode == 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);
+ 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 && !(daemon->options & OPT_NO_NEG))
+ {
+ if (!searched_soa)
+ {
+ searched_soa = 1;
+ ttl = find_soa(header, qlen);
+ }
+ 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);
+ 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 ((daemon->options & OPT_NO_REBIND) &&
+ (flags & F_IPV4) &&
+ private_net(addr.addr.addr4))
+ 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 && !(daemon->options & OPT_NO_NEG))
+ {
+ if (!searched_soa)
+ {
+ searched_soa = 1;
+ ttl = find_soa(header, qlen);
+ }
+ /* 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, but do everything else */
+ if (!header->tc)
+ 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.
+ Abuse F_BIGNAME to indicate an NS query - yuck. */
+
+unsigned short extract_request(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 || header->opcode != 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_BIGNAME;
+ }
+
+ return F_QUERY;
+}
+
+
+size_t setup_reply(HEADER *header, size_t qlen,
+ struct all_addr *addrp, unsigned short flags, unsigned long ttl)
+{
+ unsigned char *p = skip_questions(header, qlen);
+
+ header->qr = 1; /* response */
+ header->aa = 0; /* authoritive */
+ header->ra = 1; /* recursion if available */
+ header->tc = 0; /* not truncated */
+ header->nscount = htons(0);
+ header->arcount = htons(0);
+ header->ancount = htons(0); /* no answers unless changed below */
+ if (flags == F_NEG)
+ header->rcode = SERVFAIL; /* couldn't get memory */
+ else if (flags == F_NOERR)
+ header->rcode = NOERROR; /* empty domain */
+ else if (flags == F_NXDOMAIN)
+ header->rcode = NXDOMAIN;
+ else if (p && flags == F_IPV4)
+ { /* we know the address */
+ header->rcode = NOERROR;
+ header->ancount = htons(1);
+ header->aa = 1;
+ add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_A, C_IN, "4", addrp);
+ }
+#ifdef HAVE_IPV6
+ else if (p && flags == F_IPV6)
+ {
+ header->rcode = NOERROR;
+ header->ancount = htons(1);
+ header->aa = 1;
+ add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp);
+ }
+#endif
+ else /* nowhere to forward to */
+ header->rcode = 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(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(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 crecp->ttd - now;
+}
+
+
+/* return zero if we can't answer from cache, or packet size if we can */
+size_t answer_request(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 || header->opcode != 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_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, 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_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, 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 &&
+ (daemon->options & OPT_BOGUSPRIV) &&
+ private_net(addr.addr.addr4))
+ {
+ /* 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 */
+ if (qtype == T_A && (addr.addr.addr4.s_addr = inet_addr(name)) != (in_addr_t) -1)
+ {
+ ans = 1;
+ if (!dryrun)
+ {
+ 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 && (daemon->options & 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_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, 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 && (daemon->options & (OPT_SELFMX | OPT_LOCALMX)) &&
+ cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP))
+ {
+ ans = 1;
+ if (!dryrun)
+ {
+ log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>");
+ if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
+ T_MX, C_IN, "sd", 1,
+ (daemon->options & OPT_SELFMX) ? name : daemon->mxtarget))
+ anscount++;
+ }
+ }
+ }
+
+ if (qtype == T_SRV || qtype == T_ANY)
+ {
+ int found = 0;
+
+ 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_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, 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;
+ }
+ }
+ }
+
+ if (!found && (daemon->options & 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_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, 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 && (daemon->options & 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 */
+ header->qr = 1; /* response */
+ header->aa = auth; /* authoritive - only hosts and DHCP derived names. */
+ header->ra = 1; /* recursion if available */
+ header->tc = trunc; /* truncation */
+ if (anscount == 0 && nxdomain)
+ header->rcode = NXDOMAIN;
+ else
+ header->rcode = 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 100755
index 0000000..1ec1bcf
--- /dev/null
+++ b/src/rfc2131.c
@@ -0,0 +1,2332 @@
+/* dnsmasq is Copyright (c) 2000-2009 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 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_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 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)]))
+
+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);
+
+
+static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
+static void 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 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)
+{
+ 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;
+ 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 emac_len = 0;
+ struct dhcp_netid known_id, iface_id;
+ struct dhcp_opt *o;
+ unsigned char pxe_uuid[17];
+
+ 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)))
+ {
+ mess_type = option_uint(opt, 0, 1);
+
+ /* only insist on a cookie for DHCP. */
+ if (*((u32 *)&mess->options) != htonl(DHCP_COOKIE))
+ return 0;
+
+ /* 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;
+
+ 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;
+ break;
+ }
+ }
+ }
+
+ /* 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 (daemon->options & 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)
+ {
+ /* 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 (have_config(config, CONFIG_NETID))
+ {
+ config->netid.next = netid;
+ netid = &config->netid;
+ }
+
+ /* 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;
+
+ for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
+ if (match_netid(id_list->list, 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, netid))
+ {
+ if (lease)
+ {
+ /* lease exists, wrong network. */
+ lease_prune(lease, now);
+ lease = NULL;
+ }
+ if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, 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;
+ }
+
+ 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, 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, netid, subnet_addr, 0, 0, 0, NULL);
+ }
+ }
+
+ log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);
+
+ return message ? 0 : dhcp_packet_size(mess, 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 && daemon->options & 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 (have_config(config, CONFIG_NETID))
+ {
+ config->netid.next = netid;
+ netid = &config->netid;
+ }
+
+ /* 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. */
+ for (o = daemon->dhcp_match; o; o = o->next)
+ {
+ int i, matched = 0;
+
+ if (!(opt = option_find(mess, sz, o->opt, 1)) ||
+ o->len > option_len(opt))
+ continue;
+
+ if (o->len == 0)
+ matched = 1;
+ else if (o->flags & DHOPT_HEX)
+ {
+ if (memcmp_masked(o->val, option_ptr(opt, 0), o->len, o->u.wildcard_mask))
+ matched = 1;
+ }
+ else
+ for (i = 0; i <= (option_len(opt) - o->len); )
+ {
+ if (memcmp(o->val, option_ptr(opt, i), o->len) == 0)
+ {
+ matched = 1;
+ break;
+ }
+
+ if (o->flags & DHOPT_STRING)
+ i++;
+ else
+ i += o->len;
+ }
+
+ if (matched)
+ {
+ 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 */
+ match_vendor_opts(option_find(mess, sz, OPTION_VENDOR_ID, 1), daemon->dhcp_opts);
+
+ if (daemon->options & OPT_LOG_OPTS)
+ {
+ if (sanitise(option_find(mess, sz, OPTION_VENDOR_ID, 1), 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);
+ }
+
+ /* 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, netid, 0))
+ ignore = 1;
+
+ /* 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(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, netid, agent_id, real_end);
+ }
+
+ if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
+ {
+ pxearch = option_uint(opt, 0, 2);
+
+ /* proxy DHCP here. The DHCPREQUEST stuff is for gPXE */
+ if ((mess_type == DHCPDISCOVER || mess_type == DHCPREQUEST) &&
+ (context->flags & CONTEXT_PROXY))
+ {
+ struct dhcp_boot *boot = find_boot(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(netid);
+ do_encap_opts(pxe_opts(pxearch, netid), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
+
+ log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy" : "proxy-ignored", mess->xid);
+ return ignore ? 0 : dhcp_packet_size(mess, netid, agent_id, real_end);
+ }
+ }
+ }
+
+ /* if we're just a proxy server, go no further */
+ if (context->flags & CONTEXT_PROXY)
+ 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, 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, netid) &&
+ !config_find_by_address(daemon->dhcp_conf, lease->addr))
+ mess->yiaddr = lease->addr;
+ else if (opt && address_available(context, addr, 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, 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, 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;
+ }
+
+ 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, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
+
+ return dhcp_packet_size(mess, 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 (!(daemon->options & 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 && !(daemon->options & OPT_AUTHORITATIVE))
+ return 0;
+
+ if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
+ {
+ message = _("wrong address");
+ /* avoid loops when client brain-dead */
+ lease_prune(lease, now);
+ lease = NULL;
+ }
+ }
+ }
+ 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 && !(daemon->options & OPT_AUTHORITATIVE)))
+ {
+ 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, 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, 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 (do_classes)
+ {
+ if (mess->giaddr.s_addr)
+ lease->giaddr = mess->giaddr;
+
+ lease->changed = 1;
+ /* copy user-class and vendor class into new lease, for the script */
+ 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--;
+ free(lease->userclass);
+ if ((lease->userclass = whine_malloc(len+1)))
+ {
+ memcpy(lease->userclass, ucp, len);
+ lease->userclass[len] = 0;
+ lease->userclass_len = len+1;
+ }
+ }
+ if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
+ {
+ int len = option_len(opt);
+ unsigned char *ucp = option_ptr(opt, 0);
+ free(lease->vendorclass);
+ if ((lease->vendorclass = whine_malloc(len+1)))
+ {
+ memcpy(lease->vendorclass, ucp, len);
+ lease->vendorclass[len] = 0;
+ lease->vendorclass_len = len+1;
+ }
+ }
+ if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
+ {
+ int len = option_len(opt);
+ unsigned char *ucp = option_ptr(opt, 0);
+ free(lease->supplied_hostname);
+ if ((lease->supplied_hostname = whine_malloc(len+1)))
+ {
+ memcpy(lease->supplied_hostname, ucp, len);
+ lease->supplied_hostname[len] = 0;
+ lease->supplied_hostname_len = len+1;
+ }
+ }
+ }
+
+ if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
+ {
+ hostname = client_hostname;
+ hostname_auth = 1;
+ }
+
+ if (context->netid.net)
+ {
+ context->netid.next = netid;
+ netid = &context->netid;
+ }
+
+ 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, netid, 0))
+ break;
+ if (id_list)
+ hostname = NULL;
+ }
+ 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);
+
+ 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, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
+ }
+
+ return dhcp_packet_size(mess, 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, 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);
+
+ 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;
+ }
+
+ 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, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
+
+ *is_inform = 1; /* handle reply differently */
+ return dhcp_packet_size(mess, netid, agent_id, real_end);
+ }
+
+ 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;
+}
+
+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(daemon->options & 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 && (daemon->options & 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 (daemon->options & OPT_LOG_OPTS)
+ log_options(mess->file, mess->xid);
+ }
+ else if ((daemon->options & 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 (daemon->options & OPT_LOG_OPTS)
+ log_options(mess->sname, mess->xid);
+ }
+ else if ((daemon->options & 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;
+
+ if (daemon->options & 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));
+
+ log_options(&mess->options[0] + sizeof(u32), mess->xid);
+ }
+
+ for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
+ if (match_netid(id_list->list, netid, 0))
+ mess->flags |= htons(0x8000); /* force broadcast */
+
+ 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)))
+ if (match_netid(tmp->netid, netid, netid ? 0 : 1))
+ return tmp;
+
+ return netid ? option_find2(NULL, opts, opt) : 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 void 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;
+ 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;
+ 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;
+ }
+}
+
+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)
+{
+#define NUM_OPTS 4
+
+ unsigned char *p, *q;
+ struct pxe_service *service;
+ static struct dhcp_opt *o, *ret;
+ int i, j = NUM_OPTS - 1;
+
+ /* 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;
+
+ /* We are found by broadcast, so disable multicast. It gets switched on again
+ if we point to other servers and don't give a unicast address. Note that
+ we don't provide our own address for services we are the boot server for because unicast
+ discovery is to port 4011 and we don't listen there. If you are using proxy DHCP
+ and DHCP relays, the relay will need to forward to the proxy too. */
+ discovery_control = 2;
+
+ 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_buff2;
+
+ 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;
+ }
+
+ if (!service->basename)
+ {
+ if (service->server.s_addr != 0)
+ {
+ if (q - (unsigned char *)daemon->dhcp_buff2 + 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, &service->server.s_addr, INADDRSZ);
+ q += INADDRSZ;
+ }
+ else if (service->type != 0)
+ /* We're not supplying a server, so let the client multicast.
+ type zero is "local boot" so no need for M/C on that. */
+ discovery_control = 0;
+ }
+ }
+
+ /* 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_buff2 != 0)
+ {
+ ret = &fake_opts[j--];
+ ret->len = q - (unsigned char *)daemon->dhcp_buff2;
+ ret->val = (unsigned char *)daemon->dhcp_buff2;
+ 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;
+ }
+
+ if (discovery_control != 0)
+ {
+ 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)
+{
+ 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;
+
+ 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 ((daemon->options & 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 (!(daemon->options & 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 (!(daemon->options & 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)) && mess->file[0] == 0 &&
+ (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 || (daemon->options & 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);
+ }
+ }
+
+ /* Now send options to be encapsulated in arbitrary options,
+ eg dhcp-option=encap:172,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)
+ if ((opt->flags & (DHOPT_ENCAPSULATE | DHOPT_ENCAP_DONE)) == DHOPT_ENCAPSULATE)
+ {
+ struct dhcp_opt *o;
+ int found = 0;
+
+ for (o = config_opts; o; o = o->next)
+ {
+ o->flags &= ~DHOPT_ENCAP_MATCH;
+ if ((o->flags & DHOPT_ENCAPSULATE) && opt->u.encap == o->u.encap)
+ {
+ o->flags |= DHOPT_ENCAP_DONE;
+ if (match_netid(o->netid, netid, 1) &&
+ (o->flags & DHOPT_FORCE || in_list(req_options, o->u.encap)))
+ {
+ o->flags |= DHOPT_ENCAP_MATCH;
+ found = 1;
+ }
+ }
+ }
+
+ if (found)
+ do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
+ }
+
+ /* Must precede pxe_opts, since it overwrites req_options */
+ force_encap = prune_vendor_opts(netid);
+ if (in_list(req_options, OPTION_VENDOR_CLASS_OPT))
+ force_encap = 1;
+
+ if (pxe_arch != -1)
+ {
+ pxe_misc(mess, end, uuid);
+ config_opts = pxe_opts(pxe_arch, netid);
+ }
+
+ if (force_encap)
+ do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term);
+
+ /* restore BOOTP anti-overload hack */
+ if (!req_options || (daemon->options & 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 100755
index 0000000..c1ddb19
--- /dev/null
+++ b/src/tftp.c
@@ -0,0 +1,600 @@
+/* dnsmasq is Copyright (c) 2000-2009 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);
+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;
+ struct sockaddr_in addr, peer;
+ struct msghdr msg;
+ struct iovec iov;
+ struct ifreq ifr;
+ int is_err = 1, if_index = 0, mtu = 0;
+ struct iname *tmp;
+ 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
+
+ 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(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 (daemon->options & OPT_NOWILD)
+ {
+ addr = listen->iface->addr.in;
+ mtu = listen->iface->mtu;
+ }
+ else
+ {
+ char name[IF_NAMESIZE];
+ struct cmsghdr *cmptr;
+
+ addr.sin_addr.s_addr = 0;
+
+#if defined(HAVE_LINUX_NETWORK)
+ for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+ if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
+ {
+ addr.sin_addr = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
+ if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
+ }
+
+#elif defined(HAVE_SOLARIS_NETWORK)
+ for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+ if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
+ addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
+ else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+ if_index = *((unsigned int *)CMSG_DATA(cmptr));
+
+
+#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
+ for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+ if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
+ addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
+ else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
+ if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
+
+#endif
+
+ if (!indextoname(listen->tftpfd, if_index, name) ||
+ addr.sin_addr.s_addr == 0 ||
+ !iface_check(AF_INET, (struct all_addr *)&addr.sin_addr, name, &if_index))
+ return;
+
+ /* 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;
+
+ strncpy(name, ifr.ifr_name, IF_NAMESIZE);
+ if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
+ mtu = ifr.ifr_mtu;
+ }
+
+ addr.sin_port = htons(port);
+ addr.sin_family = AF_INET;
+#ifdef HAVE_SOCKADDR_SA_LEN
+ addr.sin_len = sizeof(addr);
+#endif
+
+ if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
+ return;
+
+ if ((transfer->sockfd = socket(AF_INET, 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;
+
+ /* if we have a nailed-down range, iterate until we find a free one. */
+ while (1)
+ {
+ if (bind(transfer->sockfd, (struct sockaddr *)&addr, 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)
+ {
+ addr.sin_port = htons(port);
+ 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"), inet_ntoa(peer.sin_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)) &&
+ !(daemon->options & 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 (daemon->tftp_prefix)
+ {
+ if (daemon->tftp_prefix[0] == '/')
+ daemon->namebuff[0] = 0;
+ strncat(daemon->namebuff, daemon->tftp_prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
+ if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/')
+ strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
+
+ if (daemon->options & OPT_TFTP_APREF)
+ {
+ size_t oldlen = strlen(daemon->namebuff);
+ struct stat statbuf;
+
+ strncat(daemon->namebuff, inet_ntoa(peer.sin_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)))
+ {
+ 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
+ {
+ my_syslog(MS_TFTP | LOG_INFO, _("TFTP sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr));
+ transfer->next = daemon->tftp_trans;
+ daemon->tftp_trans = transfer;
+ }
+}
+
+static struct tftp_file *check_tftp_fileperm(ssize_t *len)
+{
+ 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 (daemon->tftp_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 ((daemon->options & 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;
+
+ 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;
+
+ 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
+ {
+ char *q, *r;
+ for (q = r = err; *r; r++)
+ if (isprint((int)*r))
+ *(q++) = *r;
+ *q = 0;
+ }
+ my_syslog(MS_TFTP | LOG_ERR, _("TFTP error %d %s received from %s"),
+ (int)ntohs(mess->block), err,
+ inet_ntoa(transfer->peer.sin_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, _("TFTP failed sending %s to %s"),
+ transfer->file->filename, inet_ntoa(transfer->peer.sin_addr));
+ len = 0;
+ }
+
+ 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)
+ {
+ /* 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, "TFTP %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 100755
index 0000000..ce77f05
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,514 @@
+/* dnsmasq is Copyright (c) 2000-2009 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
+
+#ifdef LOCALEDIR
+#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 */
+
+typedef unsigned int uint32;
+
+static uint32 seed[32];
+static uint32 in[12];
+static uint32 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)
+{
+ uint32 t[12]; uint32 x; uint32 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(c) && iscntrl(c))
+ /* iscntrl only gives expected results for ascii */
+ return 0;
+#ifndef LOCALEDIR
+ else if (!isascii(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;
+#ifdef LOCALEDIR
+ int rc;
+#endif
+
+ if (nomem)
+ *nomem = 0;
+
+ if (!check_name(in))
+ return NULL;
+
+#ifdef LOCALEDIR
+ 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). */
+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 == 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;
+}
+