diff options
108 files changed, 49350 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..ba187a6 --- /dev/null +++ b/Android.mk @@ -0,0 +1,3 @@ +ifneq ($(TARGET_SIMULATOR),true) +include $(call all-subdir-makefiles) +endif diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..fb15e3d --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,873 @@ +version 2.57 + Add patches to allow build under Android. + + Provide our own header for the DNS protocol, rather than + relying on arpa/nameser.h. This has proved more or less + defective over the years and the final straw is that it's + effectively empty on Android. + + Fix regression in 2.56 which caused hex constants in + configuration to be rejected if they contain the '*' + wildcard. + + Correct wrong casts of arguments to ctype.h functions, + isdigit(), isxdigit() etc. Thanks to Matthias Andree for + spotting this. + + Allow build with IDN support independently from i18n. + IDN support continues to be included automatically + when i18n is included. + 'make COPTS=-DHAVE_IDN' is the magic incantation. + + Modify check on extraneous command line junk (added in + 2.56) so that it doesn't complain about extra _empty_ + arguments. Otherwise this breaks libvirt. + + +version 2.56 + Add a patch to allow dnsmasq to get interface names right in a + Solaris zone. Thanks to Dj Padzensky for this. + + Improve data-type parsing heuristics so that + --dhcp-option=option:domain-search,. + treats the value as a string and not an IP address. + Thanks to Clemens Fischer for spotting that. + + Add IPv6 support to the TFTP server. Many thanks to Jan + 'RedBully' Seiffert for the patches. + + Log DNS queries at level LOG_INFO, rather then + LOG_DEBUG. This makes things consistent with DHCP + logging. Thanks to Adam Pribyl for spotting the problem. + + Ensure that dnsmasq terminates cleanly when using + --syslog-async even if it cannot make a connection to the + syslogd. + + Add --add-mac option. This is to support currently + experimental DNS filtering facilities. Thanks to Benjamin + Petrin for the orignal patch. + + Fix bug which meant that tags were ignored in dhcp-range + configuration specifying PXE-proxy service. Thanks to + Cristiano Cumer for spotting this. + + Raise an error if there is extra junk, not part of an + option, on the command line. + + Flag a couple of log messages in cache.c as coming from + the DHCP subsystem. Thanks to Olaf Westrik for the patch. + + Omit timestamps from logs when a) logging to stderr and + b) --keep-in-forground is set. The logging facility on the + other end of stderr can be assumned to supply them. Thanks + to John Hallam for the patch. + + Don't complain about strings longer than 255 characters in + --txt-record, just split the long strings into 255 + character chunks instead. + + Fix crash on double-free. This bug can only happen when + dhcp-script is in use and then only in rare circumstances + triggered by high DHCP transaction rate and a slow + script. Thanks to Ferenc Wagner for finding the problem. + + Only log that a file has been sent by TFTP after the + transfer has completed succesfully. + + A good suggestion from Ferenc Wagner: extend + the --domain option to allow this sort of thing: + --domain=thekelleys.org.uk,192.168.0.0/24,local + which automatically creates + --local=/thekelleys.org.uk/ + --local=/0.168.192.in-addr.arpa/ + + Tighten up syntax checking of hex contants in the config + file. Thanks to Fred Damen for spotting this. + + Add dnsmasq logo/icon, contributed by Justin Swift. Many + thanks for that. + + Never cache DNS replies which have the 'cd' bit set, or + which result from queries forwarded with the 'cd' bit + set. The 'cd' bit instructs a DNSSEC validating server + upstream to ignore signature failures and return replies + anyway. Without this change it's possible to pollute the + dnsmasq cache with bad data by making a query with the + 'cd' bit set and subsequent queries would return this data + without its being marked as suspect. Thanks to Anders + Kaseorg for pointing out this problem. + + Add --proxy-dnssec flag, for compliance with RFC + 4035. Dnsmasq will now clear the 'ad' bit in answers returned + from upstream validating nameservers unless this option is + set. + + Allow a filename of "-" for --conf-file to read + stdin. Suggestion from Timothy Redaelli. + + Rotate the order of SRV records in replies, to provide + round-robin load balancing when all the priorities are + equal. Thanks to Peter McKinney for the suggestion. + + Edit + contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist + so that it doesn't log all queries to a file by + default. Thanks again to Peter McKinney. + + By default, setting an IPv4 address for a domain but not + an IPv6 address causes dnsmasq to return + an NODATA reply for IPv6 (or vice-versa). So + --address=/google.com/1.2.3.4 stops IPv6 queries for + *google.com from being forwarded. Make it possible to + override this behaviour by defining the sematics if the + same domain appears in both --server and --address. + In that case, the --address has priority for the address + family in which is appears, but the --server has priority + of the address family which doesn't appear in --adddress + So: + --address=/google.com/1.2.3.4 + --server=/google.com/# + will return 1.2.3.4 for IPv4 queries for *.google.com but + forward IPv6 queries to the normal upstream nameserver. + Similarly when setting an IPv6 address + only this will allow forwarding of IPv4 queries. Thanks to + William for pointing out the need for this. + + Allow more than one --dhcp-optsfile and --dhcp-hostsfile + and make them understand directories as arguments in the + same way as --addn-hosts. Suggestion from John Hanks. + + Ignore rebinding requests for leases we don't know + about. Rebind is broadcast, so we might get to overhear a + request meant for another DHCP server. NAKing this is + wrong. Thanks to Brad D'Hondt for assistance with this. + + Fix cosmetic bug which produced strange output when + dumping cache statistics with some configurations. Thanks + to Fedor Kozhevnikov for spotting this. + + +version 2.55 + Fix crash when /etc/ethers is in use. Thanks to + Gianluigi Tiesi for finding this. + + Fix crash in netlink_multicast(). Thanks to Arno Wald for + finding this one. + + Allow the empty domain "." in dhcp domain-search (119) + options. + + +version 2.54 + There is no version 2.54 to avoid confusion with 2.53, + which incorrectly identifies itself as 2.54. + + +version 2.53 + Fix failure to compile on Debian/kFreeBSD. Thanks to + Axel Beckert and Petr Salinger. + + Fix code to avoid scary strict-aliasing warnings + generated by gcc 4.4. + + Added FAQ entry warning about DHCP failures with Vista + when firewalls block 255.255.255.255. + + Fixed bug which caused bad things to happen if a + resolv.conf file which exists is subsequently removed. + Thanks to Nikolai Saoukh for the patch. + + Rationalised the DHCP tag system. Every configuration item + which can set a tag does so by adding "set:<tag>" and + every configuration item which is conditional on a tag is + made so by "tag:<tag>". The NOT operator changes to '!', + which is a bit more intuitive too. Dhcp-host directives + can set more than one tag now. The old '#' NOT, + "net:" prefix and no-prefixes are still honoured, so + no existing config file needs to be changed, but + the documentation and new-style config files should be + much less confusing. + + Added --tag-if to allow boolean operations on tags. + This allows complicated logic to be clearer and more + general. A great suggestion from Richard Voigt. + + Add broadcast/unicast information to DHCP logging. + + Allow --dhcp-broadcast to be unconditional. + + Fixed incorrect behaviour with NOT <tag> conditionals in + dhcp-options. Thanks to Max Turkewitz for assistance + finding this. + + If we send vendor-class encapsulated options based on the + vendor-class supplied by the client, and no explicit + vendor-class option is given, echo back the vendor-class + from the client. + + Fix bug which stopped dnsmasq from matching both a + circuitid and a remoteid. Thanks to Ignacio Bravo for + finding this. + + Add --dhcp-proxy, which makes it possible to configure + dnsmasq to use a DHCP relay agent as a full proxy, with + all DHCP messages passing through the proxy. This is + useful if the relay adds extra information to the packets + it forwards, but cannot be configured with the RFC 5107 + server-override option. + + Added interface:<iface name> part to dhcp-range. The + semantics of this are very odd at first sight, but it + allows a single line of the form + dhcp-range=interface:virt0,192.168.0.4,192.168.0.200 + to be added to dnsmasq configuration which then supplies + DHCP and DNS services to that interface, without affecting + what services are supplied to other interfaces and + irrespective of the existance or lack of + interface=<interface> + lines elsewhere in the dnsmasq configuration. The idea is + that such a line can be added automatically by libvirt + or equivalent systems, without disturbing any manual + configuration. + + Similarly to the above, allow --enable-tftp=<interface> + + Allow a TFTP root to be set separately for requests via + different interfaces, --tftp-root=<path>,<interface> + + Correctly handle and log clashes between CNAMES and + DNS names being given to DHCP leases. This fixes a bug + which caused nonsense IP addresses to be logged. Thanks to + Sergei Zhirikov for finding and analysing the problem. + + Tweak flush_log so as to avoid leaving the log + file in non-blocking mode. O_NONBLOCK is a property of the + file, not the process/descriptor. + + Fix contrib/Solaris10/create_package + (/usr/man -> /usr/share/man) Thanks to Vita Batrla. + + Fix a problem where, if a client got a lease, then went + to another subnet and got another lease, then moved back, + it couldn't resume the old lease, but would instead get + a new address. Thanks to Leonardo Rodrigues for spotting + this and testing the fix. + + Fix weird bug which sometimes omitted certain characters + from the start of quoted strings in dhcp-options. Thanks + to Dayton Turner for spotting the problem. + + Add facility to redirect some domains to the standard + upstream servers: this allows something like + --server=/google.com/1.2.3.4 --server=/www.google.com/# + which will send queries for *.google.com to 1.2.3.4, + except *www.google.com which will be forwarded as usual. + Thanks to AJ Weber for prompting this addition. + + Improve the hash-algorithm used to generate IP addresses + from MAC addresses during initial DHCP address + allocation. This improves performance when large numbers + of hosts with similar MAC addresses all try and get an IP + address at the same time. Thanks to Paul Smith for his + work on this. + + Tweak DHCP code so that --bridge-interface can be used to + select which IP alias of an interface should be used for + DHCP purposes on Linux. If eth0 has an alias eth0:dhcp + then adding --bridge-interface=eth0:dhcp,eth0 will use + the address of eth0:dhcp to determine the correct subnet + for DHCP address allocation. Thanks to Pawel Golaszewski + for prompting this and Eric Cooper for further testing. + + Add --dhcp-generate-names. Suggestion by Ferenc Wagner. + + Tweak DNS server selection algorithm when there is more + than one server available for a domain, eg. + --server=/mydomain/1.1.1.1 + --server=/mydomain/2.2.2.2 + Thanks to Alberto Cuesta-Canada for spotting a weakness + here. + + Add --max-ttl. Thanks to Fredrik Ringertz for the patch. + + Allow --log-facility=- to force all logging to + stderr. Suggestion from Clemens Fischer. + + Fix regression which caused configuration like + --address=/.domain.com/1.2.3.4 to be rejected. The dot to the + left of the domain has been implied and not required for a + long time, but it should be accepted for backward + compatibility. Thanks to Andrew Burcin for spotting this. + + Add --rebind-domain-ok and --rebind-localhost-ok. + Suggestion from Clemens Fischer. + + Log replies to queries of type TXT, when --log-queries + is set. + + Fix compiler warnings when compiled with -DNO_DHCP. Thanks + to Shantanu Gadgil for the patch. + + Updated French translation. Thanks to Gildas Le Nadan. + + Updated Polish translation. Thanks to Jan Psota. + + Updated German translation. Thanks to Matthias Andree. + + Added contrib/static-arp, thanks to Darren Hoo. + + Fix corruption of the domain when a name from /etc/hosts + overrides one supplied by a DHCP client. Thanks to Fedor + Kozhevnikov for spotting the problem. + + Updated Spanish translation. Thanks to Chris Chatham. + + +version 2.52 + Work around a Linux kernel bug which insists that the + length of the option passed to setsockopt must be at least + sizeof(int) bytes, even if we're calling SO_BINDTODEVICE + and the device name is "lo". Note that this is fixed + in kernel 2.6.31, but the workaround is harmless and + allows earlier kernels to be used. Also fix dnsmasq + bug which reported the wrong address when this failed. + Thanks to Fedor for finding this. + + The API for IPv6 PKTINFO changed around Linux kernel + 2.6.14. Workaround the case where dnsmasq is compiled + against newer headers, but then run on an old kernel: + necessary for some *WRT distros. + + Re-read the set of network interfaces when re-loading + /etc/resolv.conf if --bind-interfaces is not set. This + handles the case that loopback interfaces do not exist + when dnsmasq is first started. + + Tweak the PXE code to support port 4011. This should + reduce broadcasts and make things more reliable when other + servers are around. It also improves inter-operability + with certain clients. + + Make a pxe-service configuration with no filename or boot + service type legal: this does a local boot. eg. + pxe-service=x86PC, "Local boot" + + Be more conservative in detecting "A for A" + queries. Dnsmasq checks if the name in a type=A query looks + like a dotted-quad IP address and answers the query itself + if so, rather than forwarding it. Previously dnsmasq + relied in the library function inet_addr() to convert + addresses, and that will accept some things which are + confusing in this context, like 1.2.3 or even just + 1234. Now we only do A for A processing for four decimal + numbers delimited by dots. + + A couple of tweaks to fix compilation on Solaris. Thanks + to Joel Macklow for help with this. + + Another Solaris compilation tweak, needed for Solaris + 2009.06. Thanks to Lee Essen for that. + + Added extract packaging stuff from Lee Essen to + contrib/Solaris10. + + Increased the default limit on number of leases to 1000 + (from 150). This is mainly a defence against DoS attacks, + and for the average "one for two class C networks" + installation, IP address exhaustion does that just as + well. Making the limit greater than the number of IP + addresses available in such an installation removes a + surprise which otherwise can catch people out. + + Removed extraneous trailing space in the value of the + DNSMASQ_TIME_REMAINING DNSMASQ_LEASE_LENGTH and + DNSMASQ_LEASE_EXPIRES environment variables. Thanks to + Gildas Le Nadan for spotting this. + + Provide the network-id tags for a DHCP transaction to + the lease-change script in the environment variable + DNSMASQ_TAGS. A good suggestion from Gildas Le Nadan. + + Add support for RFC3925 "Vendor-Identifying Vendor + Options". The syntax looks like this: + --dhcp-option=vi-encap:<enterprise number>, ......... + + Add support to --dhcp-match to allow matching against + RFC3925 "Vendor-Identifying Vendor Classes". The syntax + looks like this: + --dhcp-match=tag,vi-encap<enterprise number>, <value> + + Add some application specific code to assist in + implementing the Broadband forum TR069 CPE-WAN + specification. The details are in contrib/CPE-WAN/README + + Increase the default DNS packet size limit to 4096, as + recommended by RFC5625 section 4.4.3. This can be + reconfigured using --edns-packet-max if needed. Thanks to + Francis Dupont for pointing this out. + + Rewrite query-ids even for TSIG signed packets, since + this is allowed by RFC5625 section 4.5. + + Use getopt_long by default on OS X. It has been supported + since version 10.3.0. Thanks to Arek Dreyer for spotting + this. + + Added up-to-date startup configuration for MacOSX/launchd + in contrib/MacOSX-launchd. Thanks to Arek Dreyer for + providing this. + + Fix link error when including Dbus but excluding DHCP. + Thanks to Oschtan for the bug report. + + Updated French translation. Thanks to Gildas Le Nadan. + + Updated Polish translation. Thanks to Jan Psota. + + Updated Spanish translation. Thanks to Chris Chatham. + + Fixed confusion about domains, when looking up DHCP hosts + in /etc/hosts. This could cause spurious "Ignoring + domain..." messages. Thanks to Fedor Kozhevnikov for + finding and analysing the problem. + + +version 2.51 + Add support for internationalised DNS. Non-ASCII characters + in domain names found in /etc/hosts, /etc/ethers and + /etc/dnsmasq.conf will be correctly handled by translation to + punycode, as specified in RFC3490. This function is only + available if dnsmasq is compiled with internationalisation + support, and adds a dependency on GNU libidn. Without i18n + support, dnsmasq continues to be compilable with just + standard tools. Thanks to Yves Dorfsman for the + suggestion. + + Add two more environment variables for lease-change scripts: + First, DNSMASQ_SUPPLIED_HOSTNAME; this is set to the hostname + supplied by a client, even if the actual hostname used is + over-ridden by dhcp-host or dhcp-ignore-names directives. + Also DNSMASQ_RELAY_ADDRESS which gives the address of + a DHCP relay, if used. + Suggestions from Michael Rack. + + Fix regression which broke echo of relay-agent + options. Thanks to Michael Rack for spotting this. + + Don't treat option 67 as being interchangeable with + dhcp-boot parameters if it's specified as + dhcp-option-force. + + Make the code to call scripts on lease-change compile-time + optional. It can be switched off by editing src/config.h + or building with "make COPTS=-DNO_SCRIPT". + + Make the TFTP server cope with filenames from Windows/DOS + which use '\' as pathname separator. Thanks to Ralf for + the patch. + + Updated Polish translation. Thanks to Jan Psota. + + Warn if an IP address is duplicated in /etc/ethers. Thanks + to Felix Schwarz for pointing this out. + + Teach --conf-dir to take an option list of file suffices + which will be ignored when scanning the directory. Useful + for backup files etc. Thanks to Helmut Hullen for the + suggestion. + + Add new DHCP option named tftpserver-address, which + corresponds to the third argument of dhcp-boot. This + allows the complete functionality of dhcp-boot to be + replicated with dhcp-option. Useful when using + dhcp-optsfile. + + Test which upstream nameserver to use every 10 seconds + or 50 queries and not just when a query times out and + is retried. This should improve performance when there + is a slow nameserver in the list. Thanks to Joe for the + suggestion. + + Don't do any PXE processing, even for clients with the + correct vendorclass, unless at least one pxe-prompt or + pxe-service option is given. This stops dnsmasq + interfering with proxy PXE subsystems when it is just + the DHCP server. Thanks to Spencer Clark for spotting this. + + Limit the blocksize used for TFTP transfers to a value + which avoids packet fragmentation, based on the MTU of the + local interface. Many netboot ROMs can't cope with + fragmented packets. + + Honour dhcp-ignore configuration for PXE and proxy-PXE + requests. Thanks to Niels Basjes for the bug report. + + Updated French translation. Thanks to Gildas Le Nadan. + + +version 2.50 + Fix security problem which allowed any host permitted to + do TFTP to possibly compromise dnsmasq by remote buffer + overflow when TFTP enabled. Thanks to Core Security + Technologies and Iván Arce, Pablo Hernán Jorge, Alejandro + Pablo Rodriguez, MartÃn Coco, Alberto Soliño Testa and + Pablo Annetta. This problem has Bugtraq id: 36121 + and CVE: 2009-2957 + + Fix a problem which allowed a malicious TFTP client to + crash dnsmasq. Thanks to Steve Grubb at Red Hat for + spotting this. This problem has Bugtraq id: 36120 and + CVE: 2009-2958 + + +version 2.49 + Fix regression in 2.48 which disables the lease-change + script. Thanks to Jose Luis Duran for spotting this. + + Log TFTP "file not found" errors. These were not logged, + since a normal PXELinux boot generates many of them, but + the lack of the messages seems to be more confusing than + routinely seeing them when there is no real error. + + Update Spanish translation. Thanks to Chris Chatham. + + +version 2.48 + Archived the extensive, backwards, changelog to + CHANGELOG.archive. The current changelog now runs from + version 2.43 and runs conventionally. + + Fixed bug which broke binding of servers to physical + interfaces when interface names were longer than four + characters. Thanks to MURASE Katsunori for the patch. + + Fixed netlink code to check that messages come from the + correct source, and not another userspace process. Thanks + to Steve Grubb for the patch. + + Maintainability drive: removed bug and missing feature + workarounds for some old platforms. Solaris 9, OpenBSD + older than 4.1, Glibc older than 2.2, Linux 2.2.x and + DBus older than 1.1.x are no longer supported. + + Don't read included configuration files more than once: + allows complex configuration structures without problems. + + Mark log messages from the various subsystems in dnsmasq: + messages from the DHCP subsystem now have the ident string + "dnsmasq-dhcp" and messages from TFTP have ident + "dnsmasq-tftp". Thanks to Olaf Westrik for the patch. + + Fix possible infinite DHCP protocol loop when an IP + address nailed to a hostname (not a MAC address) and a + host sometimes provides the name, sometimes not. + + Allow --addn-hosts to take a directory: all the files + in the directory are read. Thanks to Phil Cornelius for + the suggestion. + + Support --bridge-interface on all platforms, not just BSD. + + Added support for advanced PXE functions. It's now + possible to define a prompt and menu options which will + be displayed when a client PXE boots. It's also possible to + hand-off booting to other boot servers. Proxy-DHCP, where + dnsmasq just supplies the PXE information and another DHCP + server does address allocation, is also allowed. See the + --pxe-prompt and --pxe-service keywords. Thanks to + Alkis Georgopoulos for the suggestion and Guilherme Moro + and Michael Brown for assistance. + + Improvements to DHCP logging. Thanks to Tom Metro for + useful suggestions. + + Add ability to build dnsmasq without DHCP support. To do + this, edit src/config.h or build with + "make COPTS=-DNO_DHCP". Thanks to Mahavir Jain for the patch. + + Added --test command-line switch - syntax check + configuration files only. + + Updated French translation. Thanks to Gildas Le Nadan. + + +version 2.47 + Updated French translation. Thanks to Gildas Le Nadan. + + Fixed interface enumeration code to work on NetBSD + 5.0. Thanks to Roy Marples for the patch. + + Updated config.h to use the same location for the lease + file on NetBSD as the other *BSD variants. Also allow + LEASEFILE and CONFFILE symbols to be overriden in CFLAGS. + + Handle duplicate address detection on IPv6 more + intelligently. In IPv6, an interface can have an address + which is not usable, because it is still undergoing DAD + (such addresses are marked "tentative"). Attempting to + bind to an address in this state returns an error, + EADDRNOTAVAIL. Previously, on getting such an error, + dnsmasq would silently abandon the address, and never + listen on it. Now, it retries once per second for 20 + seconds before generating a fatal error. 20 seconds should + be long enough for any DAD process to complete, but can be + adjusted in src/config.h if necessary. Thanks to Martin + Krafft for the bug report. + + Add DBus introspection. Patch from Jeremy Laine. + + Update Dbus configuration file. Patch from Colin Walters. + Fix for this bug: + http://bugs.freedesktop.org/show_bug.cgi?id=18961 + + Support arbitrarily encapsulated DHCP options, suggestion + and initial patch from Samium Gromoff. This is useful for + (eg) gPXE, which expect all its private options to be + encapsulated inside a single option 175. So, eg, + + dhcp-option = encap:175, 190, "iscsi-client0" + dhcp-option = encap:175, 191, "iscsi-client0-secret" + + will provide iSCSI parameters to gPXE. + + Enhance --dhcp-match to allow testing of the contents of a + client-sent option, as well as its presence. This + application in mind for this is RFC 4578 + client-architecture specifiers, but it's generally useful. + Joey Korkames suggested the enhancement. + + Move from using the IP_XMIT_IF ioctl to IP_BOUND_IF on + OpenSolaris. Thanks to Bastian Machek for the heads-up. + + No longer complain about blank lines in + /etc/ethers. Thanks to Jon Nelson for the patch. + + Fix binding of servers to physical devices, eg + --server=/domain/1.2.3.4@eth0 which was broken from 2.43 + onwards unless --query-port=0 set. Thanks to Peter Naulls + for the bug report. + + Reply to DHCPINFORM requests even when the supplied ciaddr + doesn't fall in any dhcp-range. In this case it's not + possible to supply a complete configuration, but + individually-configured options (eg PAC) may be useful. + + Allow the source address of an alias to be a range: + --alias=192.168.0.0,10.0.0.0,255.255.255.0 maps the whole + subnet 192.168.0.0->192.168.0.255 to 10.0.0.0->10.0.0.255, + as before. + --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0 + maps only the 192.168.0.10->192.168.0.40 region. Thanks to + Ib Uhrskov for the suggestion. + + Don't dynamically allocate DHCP addresses which may break + Windows. Addresses which end in .255 or .0 are broken in + Windows even when using supernetting. + --dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0 means + 192.168.0.255 is a valid IP address, but not for Windows. + See Microsoft KB281579. We therefore no longer allocate + these addresses to avoid hard-to-diagnose problems. + + Update Polish translation. Thanks to Jan Psota. + + Delete the PID-file when dnsmasq shuts down. Note that by + this time, dnsmasq is normally not running as root, so + this will fail if the PID-file is stored in a root-owned + directory; such failure is silently ignored. To take + advantage of this feature, the PID-file must be stored in a + directory owned and write-able by the user running + dnsmasq. + + +version 2.46 + Allow --bootp-dynamic to take a netid tag, so that it may + be selectively enabled. Thanks to Olaf Westrik for the + suggestion. + + Remove ISC-leasefile reading code. This has been + deprecated for a long time, and last time I removed it, it + ended up going back by request of one user. This time, + it's gone for good; otherwise it would need to be + re-worked to support multiple domains (see below). + + Support DHCP clients in multiple DNS domains. This is a + long-standing request. Clients are assigned to a domain + based in their IP address. + + Add --dhcp-fqdn flag, which changes behaviour if DNS names + assigned to DHCP clients. When this is set, there must be + a domain associated with each client, and only + fully-qualified domain names are added to the DNS. The + advantage is that the only the FQDN needs to be unique, + so that two or more DHCP clients can share a hostname, as + long as they are in different domains. + + Set environment variable DNSMASQ_DOMAIN when invoking + lease-change script. This may be useful information to + have now that it's variable. + + Tighten up data-checking code for DNS packet + handling. Thanks to Steve Dodd who found certain illegal + packets which could crash dnsmasq. No memory overwrite was + possible, so this is not a security issue beyond the DoS + potential. + + Update example config dhcp option 47, the previous + suggestion generated an illegal, zero-length, + option. Thanks to Matthias Andree for finding this. + + Rewrite hosts-file reading code to remove the limit of + 1024 characters per line. John C Meuser found this. + + Create a net-id tag with the name of the interface on + which the DHCP request was received. + + Fixed minor memory leak in DBus code, thanks to Jeremy + Laine for the patch. + + Emit DBus signals as the DHCP lease database + changes. Thanks to Jeremy Laine for the patch. + + Allow for more that one MAC address in a dhcp-host + line. This configuration tells dnsmasq that it's OK to + abandon a DHCP lease of the fixed address to one MAC + address, if another MAC address in the dhcp-host statement + asks for an address. This is useful to give a fixed + address to a host which has two network interfaces + (say, a laptop with wired and wireless interfaces.) + It's very important to ensure that only one interface + at a time is up, since dnsmasq abandons the first lease + and re-uses the address before the leased time has + elapsed. John Gray suggested this. + + Tweak the response to a DHCP request packet with a wrong + server-id when --dhcp-authoritative is set; dnsmasq now + returns a DHCPNAK, rather than silently ignoring the + packet. Thanks to Chris Marget for spotting this + improvement. + + Add --cname option. This provides a limited alias + function, usable for DHCP names. Thanks to AJ Weber for + suggestions on this. + + Updated contrib/webmin with latest version from Neil + Fisher. + + Updated Polish translation. Thanks to Jan Psota. + + Correct the text names for DHCP options 64 and 65 to be + "nis+-domain" and "nis+-servers". + + Updated Spanish translation. Thanks to Chris Chatham. + + Force re-reading of /etc/resolv.conf when an "interface + up" event occurs. + + +version 2.45 + Fix total DNS failure in release 2.44 unless --min-port + specified. Thanks to Steven Barth and Grant Coady for + bugreport. Also reject out-of-range port spec, which could + break things too: suggestion from Gilles Espinasse. + + +version 2.44 + Fix crash when unknown client attempts to renew a DHCP + lease, problem introduced in version 2.43. Thanks to + Carlos Carvalho for help chasing this down. + + Fix potential crash when a host which doesn't have a lease + does DHCPINFORM. Again introduced in 2.43. This bug has + never been reported in the wild. + + Fix crash in netlink code introduced in 2.43. Thanks to + Jean Wolter for finding this. + + Change implementation of min_port to work even if min-port + is large. + + Patch to enable compilation of latest Mac OS X. Thanks to + David Gilman. + + Update Spanish translation. Thanks to Christopher Chatham. + + +version 2.43 + Updated Polish translation. Thanks to Jan Psota. + + Flag errors when configuration options are repeated + illegally. + + Further tweaks for GNU/kFreeBSD + + Add --no-wrap to msgmerge call - provides nicer .po file + format. + + Honour lease-time spec in dhcp-host lines even for + BOOTP. The user is assumed to known what they are doing in + this case. (Hosts without the time spec still get infinite + leases for BOOTP, over-riding the default in the + dhcp-range.) Thanks to Peter Katzmann for uncovering this. + + Fix problem matching relay-agent ids. Thanks to Michael + Rack for the bug report. + + Add --naptr-record option. Suggestion from Johan + Bergquist. + + Implement RFC 5107 server-id-override DHCP relay agent + option. + + Apply patches from Stefan Kruger for compilation on + Solaris 10 under Sun studio. + + Yet more tweaking of Linux capability code, to suppress + pointless wingeing from kernel 2.6.25 and above. + + Improve error checking during startup. Previously, some + errors which occurred during startup would be worked + around, with dnsmasq still starting up. Some were logged, + some silent. Now, they all cause a fatal error and dnsmasq + terminates with a non-zero exit code. The errors are those + associated with changing uid and gid, setting process + capabilities and writing the pidfile. Thanks to Uwe + Gansert and the Suse security team for pointing out + this improvement, and Bill Reimers for good implementation + suggestions. + + Provide NO_LARGEFILE compile option to switch off largefile + support when compiling against versions of uclibc which + don't support it. Thanks to Stephane Billiart for the patch. + + Implement random source ports for interactions with + upstream nameservers. New spoofing attacks have been found + against nameservers which do not do this, though it is not + clear if dnsmasq is vulnerable, since to doesn't implement + recursion. By default dnsmasq will now use a different + source port (and socket) for each query it sends + upstream. This behaviour can suppressed using the + --query-port option, and the old default behaviour + restored using --query-port=0. Explicit source-port + specifications in --server configs are still honoured. + + Replace the random number generator, for better + security. On most BSD systems, dnsmasq uses the + arc4random() RNG, which is secure, but on other platforms, + it relied on the C-library RNG, which may be + guessable and therefore allow spoofing. This release + replaces the libc RNG with the SURF RNG, from Daniel + J. Berstein's DJBDNS package. + + Don't attempt to change user or group or set capabilities + if dnsmasq is run as a non-root user. Without this, the + change from soft to hard errors when these fail causes + problems for non-root daemons listening on high + ports. Thanks to Patrick McLean for spotting this. + + Updated French translation. Thanks to Gildas Le Nadan. + + +version 2.42 + The changelog for version 2.42 and earlier is + available in CHANGELOG.archive. diff --git a/CHANGELOG.archive b/CHANGELOG.archive new file mode 100644 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/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..25e9554 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(dnsmasq C) + +SET(SRCS src/bpf.c + src/cache.c + src/dbus.c + src/dhcp.c + src/dnsmasq.c + src/forward.c + src/helper.c + src/lease.c + src/log.c + src/netlink.c + src/network.c + src/option.c + src/rfc1035.c + src/rfc2131.c + src/tftp.c + src/util.c + ) + +SET(VENDOR "samsung") +SET(PACKAGE ${PROJECT_NAME}) +SET(PKGNAME ${PACKAGE}) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(BINDIR "${PREFIX}/bin") + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +#INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED dbus-1) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") + +ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"") +ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"") +ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +#IF("${ARCH}" STREQUAL "arm") +# ADD_DEFINITIONS("-D_MMICHECK_ARM_CODE_") +#ENDIF("${ARCH}" STREQUAL "arm") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR}) @@ -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 100644 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>. @@ -0,0 +1,482 @@ +Q: Why does dnsmasq open UDP ports >1024 as well as port 53. + Is this a security problem/trojan/backdoor? + +A: The high ports that dnsmasq opens are for replies from the upstream + nameserver(s). Queries from dnsmasq to upstream nameservers are sent + from these ports and replies received to them. The reason for doing this is + that most firewall setups block incoming packets _to_ port 53, in order + to stop DNS queries from the outside world. If dnsmasq sent its queries + from port 53 the replies would be _to_ port 53 and get blocked. + + This is not a security hole since dnsmasq will only accept replies to that + port: queries are dropped. The replies must be to oustanding queries + which dnsmasq has forwarded, otherwise they are dropped too. + + Addendum: dnsmasq now has the option "query-port" (-Q), which allows + you to specify the UDP port to be used for this purpose. If not + specified, the operating system will select an available port number + just as it did before. + + Second addendum: following the discovery of a security flaw in the + DNS protocol, dnsmasq from version 2.43 has changed behavior. It + now uses a new, randomly selected, port for each query. The old + default behaviour (use one port allocated by the OS) is available by + setting --query-port=0, and setting the query port to a positive + value is still works. You should think hard and know what you are + doing before using either of these options. + +Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify + that? + +A: Update: from version 2.10, it does. There are a few limitations: + data obtained via TCP is not cached, and source-address + or query-port specifications are ignored for TCP. + +Q: When I send SIGUSR1 to dump the contents of the cache, some entries have + no IP address and are for names like mymachine.mydomain.com.mydomain.com. + What are these? + +A: They are negative entries: that's what the N flag means. Dnsmasq asked + an upstream nameserver to resolve that address and it replied "doesn't + exist, and won't exist for <n> hours" so dnsmasq saved that information so + that if _it_ gets asked the same question it can answer directly without + having to go back to the upstream server again. The strange repeated domains + result from the way resolvers search short names. See "man resolv.conf" for + details. + + +Q: Will dnsmasq compile/run on non-Linux systems? + +A: Yes, there is explicit support for *BSD and MacOS X and Solaris. + There are start-up scripts for MacOS X Tiger and Panther + in /contrib. Dnsmasq will link with uclibc to provide small + binaries suitable for use in embedded systems such as + routers. (There's special code to support machines with flash + filesystems and no battery-backed RTC.) + If you encounter make errors with *BSD, try installing gmake from + ports and building dnsmasq with "make MAKE=gmake" + For other systems, try altering the settings in config.h. + +Q: My company's nameserver knows about some names which aren't in the + public DNS. Even though I put it first in /etc/resolv.conf, it + dosen't work: dnsmasq seems not to use the nameservers in the order + given. What am I doing wrong? + +A: By default, dnsmasq treats all the nameservers it knows about as + equal: it picks the one to use using an algorithm designed to avoid + nameservers which aren't responding. To make dnsmasq use the + servers in order, give it the -o flag. If you want some queries + sent to a special server, think about using the -S flag to give the + IP address of that server, and telling dnsmasq exactly which + domains to use the server for. + +Q: OK, I've got queries to a private nameserver working, now how about + reverse queries for a range of IP addresses? + +A: Use the standard DNS convention of <reversed address>.in-addr.arpa. + For instance to send reverse queries on the range 192.168.0.0 to + 192.168.0.255 to a nameserver at 10.0.0.1 do + server=/0.168.192.in-addr.arpa/10.0.0.1 + Note that the "bogus-priv" option take priority over this option, + so the above will not work when the bogus-priv option is set. + +Q: Dnsmasq fails to start with an error like this: "dnsmasq: bind + failed: Cannot assign requested address". What's the problem? + +A: This has been seen when a system is bringing up a PPP interface at + boot time: by the time dnsmasq start the interface has been + created, but not brought up and assigned an address. The easiest + solution is to use --interface flags to specify which interfaces + dnsmasq should listen on. Since you are unlikely to want dnsmasq to + listen on a PPP interface and offer DNS service to the world, the + problem is solved. + +Q: I'm running on BSD and dnsmasq won't accept long options on the + command line. + +A: Dnsmasq when built on some BSD systems doesn't use GNU getopt by + default. You can either just use the single-letter options or + change config.h and the Makefile to use getopt-long. Note that + options in /etc/dnsmasq.conf must always be the long form, + on all platforms. + +Q: Names on the internet are working fine, but looking up local names + from /etc/hosts or DHCP doesn't seem to work. + +A: Resolver code sometime does strange things when given names without + any dots in. Win2k and WinXP may not use the DNS at all and just + try and look up the name using WINS. On unix look at "options ndots:" + in "man resolv.conf" for details on this topic. Testing lookups + using "nslookup" or "dig" will work, but then attempting to run + "ping" will get a lookup failure, appending a dot to the end of the + hostname will fix things. (ie "ping myhost" fails, but "ping + myhost." works. The solution is to make sure that all your hosts + have a domain set ("domain" in resolv.conf, or set a domain in + your DHCP server, see below fr Windows XP and Mac OS X). + Any domain will do, but "localnet" is traditional. Now when you + resolve "myhost" the resolver will attempt to look up + "myhost.localnet" so you need to have dnsmasq reply to that name. + The way to do that is to include the domain in each name on + /etc/hosts and/or to use the --expand-hosts and --domain options. + +Q: How do I set the DNS domain in Windows XP or MacOS X (ref: previous + question)? + +A: for XP, Control Panel > Network Connections > { Connection to gateway / + DNS } > Properties > { Highlight TCP/IP } > Properties > Advanced > + DNS Tab > DNS suffix for this connection: + +A: for OS X, System Preferences > Network > {Connection to gateway / DNS } > + Search domains: + +Q: Can I get dnsmasq to save the contents of its cache to disk when + I shut my machine down and re-load when it starts again? + +A: No, that facility is not provided. Very few names in the DNS have + their time-to-live set for longer than a few hours so most of the + cache entries would have expired after a shutdown. For longer-lived + names it's much cheaper to just reload them from the upstream + server. Note that dnsmasq is not shut down between PPP sessions so + go off-line and then on-line again will not lose the contents of + the cache. + +Q: Who are Verisign, what do they have to do with the bogus-nxdomain + option in dnsmasq and why should I wory about it? + +A: [note: this was written in September 2003, things may well change.] + Versign run the .com and .net top-level-domains. They have just + changed the configuration of their servers so that unknown .com and + .net domains, instead of returning an error code NXDOMAIN, (no such + domain) return the address of a host at Versign which runs a web + server showing a search page. Most right-thinking people regard + this new behaviour as broken :-). You can test to see if you are + suffering Versign brokeness by run a command like + + host jlsdajkdalld.com + + If you get "jlsdajkdalld.com" does not exist, then all is fine, if + host returns an IP address, then the DNS is broken. (Try a few + different unlikely domains, just in case you picked a wierd one + which really _is_ registered.) + + Assuming that your DNS is broken, and you want to fix it, simply + note the IP address being returned and pass it to dnsmasq using the + --bogus-nxdomain flag. Dnsmasq will check for results returning + that address and substitute an NXDOMAIN instead. + + As of writing, the IP address in question for the .com and .net + domains is is 64.94.110.11. Various other, less prominent, + registries pull the same stunt; there is a list of them all, and + the addresses to block, at http://winware.org/bogus-domains.txt + +Q: This new DHCP server is well and good, but it doesn't work for me. + What's the problem? + +A: There are a couple of configuration gotchas which have been + encountered by people moving from the ISC dhcpd to the dnsmasq + integrated DHCP daemon. Both are related to differences in + in the way the two daemons bypass the IP stack to do "ground up" + IP configuration and can lead to the dnsmasq daemon failing + whilst the ISC one works. + + The first thing to check is the broadcast address set for the + ethernet interface. This is normally the adddress on the connected + network with all ones in the host part. For instance if the + address of the ethernet interface is 192.168.55.7 and the netmask + is 255.255.255.0 then the broadcast address should be + 192.168.55.255. Having a broadcast address which is not on the + network to which the interface is connected kills things stone + dead. + + The second potential problem relates to firewall rules: since the ISC + daemon in some configurations bypasses the kernel firewall rules + entirely, the ability to run the ISC daemon does not indicate + that the current configuration is OK for the dnsmasq daemon. + For the dnsmasq daemon to operate it's vital that UDP packets to + and from ports 67 and 68 and broadcast packets with source + address 0.0.0.0 and destination address 255.255.255.255 are not + dropped by iptables/ipchains. + +Q: I'm running Debian, and my machines get an address fine with DHCP, + but their names are not appearing in the DNS. + +A: By default, none of the DHCP clients send the host-name when asking + for a lease. For most of the clients, you can set the host-name to + send with the "hostname" keyword in /etc/network/interfaces. (See + "man interfaces" for details.) That doesn't work for dhclient, were + you have to add something like "send host-name daisy" to + /etc/dhclient.conf [Update: the lastest dhcpcd packages _do_ send + the hostname by default. + +Q: I'm network booting my machines, and trying to give them static + DHCP-assigned addresses. The machine gets its correct address + whilst booting, but then the OS starts and it seems to get + allocated a different address. + +A: What is happening is this: The boot process sends a DHCP + request and gets allocated the static address corresponding to its + MAC address. The boot loader does not send a client-id. Then the OS + starts and repeats the DHCP process, but it it does send a + client-id. Dnsmasq cannot assume that the two requests are from the + same machine (since the client ID's don't match) and even though + the MAC address has a static allocation, that address is still in + use by the first incarnation of the machine (the one from the boot, + without a client ID.) dnsmasq therefore has to give the machine a + dynamic address from its pool. There are three ways to solve this: + (1) persuade your DHCP client not to send a client ID, or (2) set up + the static assignment to the client ID, not the MAC address. The + default client-id will be 01:<MAC address>, so change the dhcp-host + line from "dhcp-host=11:22:33:44:55:66,1.2.3.4" to + "dhcp-host=id:01:11:22:33:44:55:66,1.2.3.4" or (3) tell dnsmasq to + ignore client IDs for a particular MAC address, like this: + dhcp-host=11:22:33:44:55:66,id:* + +Q: What network types are supported by the DHCP server? + +A: Ethernet (and 802.11 wireless) are supported on all platforms. On + Linux all network types (including FireWire) are supported. + +Q: What is this strange "bind-interface" option? + +A: The DNS spec says that the reply to a DNS query must come from the + same address it was sent to. The traditional way to write an UDP + server to do this is to find all of the addresses belonging to the + machine (ie all the interfaces on the machine) and then create a + socket for each interface which is bound to the address of the + interface. Then when a packet is sent to address A, it is received + on the socket bound to address A and when the reply is also sent + via that socket, the source address is set to A by the kernel and + everything works. This is the how dnsmasq works when + "bind-interfaces" is set, with the obvious extension that is misses + out creating sockets for some interfaces depending on the + --interface, --address and --except-interface flags. The + disadvantage of this approach is that it breaks if interfaces don't + exist or are not configured when the daemon starts and does the + socket creation step. In a hotplug-aware world this is a real + problem. + + The alternative approach is to have only one socket, which is bound + to the correct port and the wildcard IP address (0.0.0.0). That + socket will receive _all_ packets sent to port 53, no matter what + destination address they have. This solves the problem of + interfaces which are created or reconfigured after daemon + start-up. To make this work is more complicated because of the + "reply source address" problem. When a UDP packet is sent by a + socket bound to 0.0.0.0 its source address will be set to the + address of one of the machine's interfaces, but which one is not + determined and can vary depending on the OS being run. To get round + this it is neccessary to use a scary advanced API to determine the + address to which a query was sent, and force that to be the source + address in the reply. For IPv4 this stuff in non-portable and quite + often not even available (It's different between FreeBSD 5.x and + Linux, for instance, and FreeBSD 4.x, Linux 2.0.x and OpenBSD don't + have it at all.) Hence "bind-interfaces" has to always be available + as a fall back. For IPv6 the API is standard and universally + available. + + It could be argued that if the --interface or --address flags are + used then binding interfaces is more appropriate, but using + wildcard binding means that dnsmasq will quite happily start up + after being told to use interfaces which don't exist, but which are + created later. Wildcard binding breaks the scenario when dnsmasq is + listening on one interface and another server (most probably BIND) + is listening on another. It's not possible for BIND to bind to an + (address,port) pair when dnsmasq has bound (wildcard,port), hence + the ability to explicitly turn off wildcard binding. + +Q: Why doesn't Kerberos work/why can't I get sensible answers to + queries for SRV records. + +A: Probably because you have the "filterwin2k" option set. Note that + it was on by default in example configuration files included in + versions before 2.12, so you might have it set on without + realising. + +Q: Can I get email notification when a new version of dnsmasq is + released? + +A: Yes, new releases of dnsmasq are always announced through + freshmeat.net, and they allow you to subcribe to email alerts when + new versions of particular projects are released. New releases are + also announced in the dnsmasq-discuss mailing list, subscribe at + http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss + +Q: What does the dhcp-authoritative option do? + +A: See http://www.isc.org/index.pl?/sw/dhcp/authoritative.php - that's + for the ISC daemon, but the same applies to dnsmasq. + +Q: Why does my Gentoo box pause for a minute before getting a new + lease? + +A: Because when a Gentoo box shuts down, it releases its lease with + the server but remembers it on the client; this seems to be a + Gentoo-specific patch to dhcpcd. On restart it tries to renew + a lease which is long gone, as far as dnsmasq is concerned, and + dnsmasq ignores it until is times out and restarts the process. + To fix this, set the dhcp-authoritative flag in dnsmasq. + +Q: My laptop has two network interfaces, a wired one and a wireless + one. I never use both interfaces at the same time, and I'd like the + same IP and configuration to be used irrespective of which + interface is in use. How can I do that? + +A: By default, the identity of a machine is determined by using the + MAC address, which is associated with interface hardware. Once an + IP is bound to the MAC address of one interface, it cannot be + associated with another MAC address until after the DHCP lease + expires. The solution to this is to use a client-id as the machine + identity rather than the MAC address. If you arrange for the same + client-id to sent when either interface is in use, the DHCP server + will recognise the same machine, and use the same address. The + method for setting the client-id varies with DHCP client software, + dhcpcd uses the "-I" flag. Windows uses a registry setting, + see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm +Addendum: + From version 2.46, dnsmasq has a solution to this which doesn't + involve setting client-IDs. It's possible to put more than one MAC + address in a --dhcp-host configuration. This tells dnsmasq that it + should use the specified IP for any of the specified MAC addresses, + and furthermore it gives dnsmasq permission to sumarily abandon a + lease to one of the MAC addresses if another one comes along. Note + that this will work fine only as longer as only one interface is + up at any time. There is no way for dnsmasq to enforce this + constraint: if you configure multiple MAC addresses and violate + this rule, bad things will happen. + +Q: Can dnsmasq do DHCP on IP-alias interfaces? + +A: Yes, from version-2.21. The support is only available running under + Linux, on a kernel which provides the RT-netlink facility. All 2.4 + and 2.6 kernels provide RT-netlink and it's an option in 2.2 + kernels. + + If a physical interface has more than one IP address or aliases + with extra IP addresses, then any dhcp-ranges corresponding to + these addresses can be used for address allocation. So if an + interface has addresses 192.168.1.0/24 and 192.168.2.0/24 and there + are DHCP ranges 192.168.1.100-192.168.1.200 and + 192.168.2.100-192.168.2.200 then both ranges would be used for host + connected to the physical interface. A more typical use might be to + have one of the address-ranges as static-only, and have known + hosts allocated addresses on that subnet using dhcp-host options, + while anonymous hosts go on the other. + + +Q: Dnsmasq sometimes logs "nameserver xxx.xxx.xxx.xxx refused + to do a recursive query" and DNS stops working. What's going on? + +A: Probably the nameserver is an authoritative nameserver for a + particular domain, but is not configured to answer general DNS + queries for an arbitrary domain. It is not suitable for use by + dnsmasq as an upstream server and should be removed from the + configuration. Note that if you have more than one upstream + nameserver configured dnsmasq will load-balance across them and + it may be some time before dnsmasq gets around to using a + particular nameserver. This means that a particular configuration + may work for sometime with a broken upstream nameserver + configuration. + + +Q: Does the dnsmasq DHCP server probe addresses before allocating + them, as recommended in RFC2131? + +A: Yes, dynmaically allocated IP addresses are checked by sending an + ICMP echo request (ping). If a reply is received, then dnsmasq + assumes that the address is in use, and attempts to allocate an + different address. The wait for a reply is between two and three + seconds. Because the DHCP server is not re-entrant, it cannot serve + other DHCP requests during this time. To avoid dropping requests, + the address probe may be skipped when dnsmasq is under heavy load. + + +Q: I'm using dnsmasq on a machine with the Firestarter firewall, and + DHCP doesn't work. What's the problem? + +A: This a variant on the iptables problem. Explicit details on how to + proceed can be found at + http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2005q3/000431.html + + +Q: I'm using dnsmasq on a machine with the shorewall firewall, and + DHCP doesn't work. What's the problem? + +A: This a variant on the iptables problem. Explicit details on how to + proceed can be found at + http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2007q4/001764.html + + +Q: Dnsmasq fails to start up with a message about capabilities. + Why did that happen and what can do to fix it? + +A: Change your kernel configuration: either deselect CONFIG_SECURITY + _or_ select CONFIG_SECURITY_CAPABILITIES. Alternatively, you can + remove the need to set capabilities by running dnsmasq as root. + + +Q: Where can I get .rpms Suitable for openSUSE/SLES? + +A: Dnsmasq is in openSUSE itself, and the latest releases are also + available at http://download.opensuse.org/repositories/network/ + + +Q: Can I run dnsmasq in a Linux vserver? + +A: Yes, as a DNS server, dnsmasq will just work in a vserver. + To use dnsmasq's DHCP function you need to give the vserver + extra system capabilities. Please note that doing so will lesser + the overall security of your system. The capabilities + required are NET_ADMIN and NET_RAW. NET_ADMIN is essential, NET_RAW + is required to do an ICMP "ping" check on newly allocated + addresses. If you don't need this check, you can disable it with + --no-ping and omit the NET_RAW capability. + Adding the capabilities is done by adding them, one per line, to + either /etc/vservers/<vservername>/ccapabilities for a 2.4 kernel or + /etc/vservers/<vservername>/bcapabilities for a 2.6 kernel (please + refer to the vserver documentation for more information). + + +Q: What's the problem with syslog and dnsmasq? + +A: In almost all cases: none. If you have the normal arrangement with + local daemons logging to a local syslog, which then writes to disk, + then there's never a problem. If you use network logging, then + there's a potential problem with deadlock: the syslog daemon will + do DNS lookups so that it can log the source of log messages, + these lookups will (depending on exact configuration) go through + dnsmasq, which also sends log messages. With bad timing, you can + arrive at a situation where syslog is waiting for dnsmasq, and + dnsmasq is waiting for syslog; they will both wait forever. This + problem is fixed from dnsmasq-2.39, which introduces asynchronous + logging: dnsmasq no longer waits for syslog and the deadlock is + broken. There is a remaining problem in 2.39, where "log-queries" + is in use. In this case most DNS queries generate two log lines, if + these go to a syslog which is doing a DNS lookup for each log line, + then those queries will in turn generate two more log lines, and a + chain reaction runaway will occur. To avoid this, use syslog-ng + and turn on syslog-ng's dns-cache function. + + +Q: DHCP doesn't work with windows Vista, but everything else is fine. + +A: The DHCP client on windows Vista (and possibly later versions) + demands that the DHCP server send replies as broadcasts. Most other + clients don't do this. The broadcasts are send to + 255.255.255.255. A badly configured firewall which blocks such + packets will show exactly these symptoms (Vista fails, others + work). + + + + + + + + + + + + + + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..16c69e4 --- /dev/null +++ b/Makefile @@ -0,0 +1,99 @@ +# dnsmasq is Copyright (c) 2000-2011 Simon Kelley +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 dated June, 1991, or +# (at your option) version 3 dated 29 June, 2007. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +PREFIX = /usr/local +BINDIR = ${PREFIX}/sbin +MANDIR = ${PREFIX}/share/man +LOCALEDIR = ${PREFIX}/share/locale + +PKG_CONFIG = pkg-config +INSTALL = install +MSGMERGE = msgmerge +MSGFMT = msgfmt +XGETTEXT = xgettext + +CFLAGS = -Wall -W -O2 + +################################################################# + +SRC = src +PO = po +MAN = man + +DNSMASQ_CFLAGS=`echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1` +DNSMASQ_LIBS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1` +IDN_CFLAGS=`echo $(COPTS) | ../bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn` +IDN_LIBS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn` +SUNOS_LIBS= `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi` + +OBJS = cache.o rfc1035.o util.o option.o forward.o network.o \ + dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ + helper.o tftp.o log.o + +all : + @cd $(SRC) && $(MAKE) \ + BUILD_CFLAGS="$(DNSMASQ_CFLAGS) $(IDN_CFLAGS)" \ + BUILD_LIBS="$(DNSMASQ_LIBS) $(IDN_LIBS) $(SUNOS_LIBS)" \ + -f ../Makefile dnsmasq + +clean : + rm -f *~ $(SRC)/*.mo contrib/*/*~ */*~ $(SRC)/*.pot + rm -f $(SRC)/*.o $(SRC)/dnsmasq.a $(SRC)/dnsmasq core */core + +install : all install-common + +install-common : + $(INSTALL) -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8 + $(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8 + $(INSTALL) -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR) + +all-i18n : + @cd $(SRC) && $(MAKE) \ + I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \ + BUILD_CFLAGS="$(DNSMASQ_CFLAGS) `$(PKG_CONFIG) --cflags libidn`" \ + BUILD_LIBS="$(DNSMASQ_LIBS) $(SUNOS_LIBS) `$(PKG_CONFIG) --libs libidn`" \ + -f ../Makefile dnsmasq + @cd $(PO); for f in *.po; do \ + cd ../$(SRC) && $(MAKE) \ + -f ../Makefile $${f%.po}.mo; \ + done + +install-i18n : all-i18n install-common + cd $(SRC); ../bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL) + cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL) + +merge : + @cd $(SRC) && $(MAKE) -f ../Makefile dnsmasq.pot + @cd $(PO); for f in *.po; do \ + echo -n msgmerge $$f && $(MSGMERGE) --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \ + done + + +# rules below are targets in recusive makes with cwd=$(SRC) + +.c.o: + $(CC) $(CFLAGS) $(COPTS) $(I18N) $(BUILD_CFLAGS) $(RPM_OPT_FLAGS) -c $< + +dnsmasq : $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(BUILD_LIBS) $(LIBS) + +dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h + $(XGETTEXT) -d dnsmasq --foreign-user --omit-header --keyword=_ -o $@ -i $(OBJS:.o=.c) + +%.mo : ../po/%.po dnsmasq.pot + $(MSGMERGE) -o - ../po/$*.po dnsmasq.pot | $(MSGFMT) -o $*.mo - + + +.PHONY : all clean install install-common all-i18n install-i18n merge diff --git a/bld/Android.mk b/bld/Android.mk new file mode 100644 index 0000000..373a783 --- /dev/null +++ b/bld/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH := external/dnsmasq/src + +######################### + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \ + forward.c helper.c lease.c log.c \ + netlink.c network.c option.c rfc1035.c \ + rfc2131.c tftp.c util.c + +LOCAL_MODULE := dnsmasq + +LOCAL_C_INCLUDES := external/dnsmasq/src + +LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT +LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils + +include $(BUILD_EXECUTABLE) diff --git a/bld/install-man b/bld/install-man new file mode 100755 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/CPE-WAN/README b/contrib/CPE-WAN/README new file mode 100644 index 0000000..4d56347 --- /dev/null +++ b/contrib/CPE-WAN/README @@ -0,0 +1,36 @@ +Dnsmasq from version 2.52 has a couple of rather application-specific +features designed to allow for implementation of the DHCP part of CPE +WAN management protocol. + +http://www.broadband-forum.org/technical/download/TR-069_Amendment-2.pdf +http://en.wikipedia.org/wiki/TR-069 + +The relevant sections are F.2.1 "Gateway Requirements" and F.2.5 "DHCP +Vendor Options". + +First, dnsmasq checks for DHCP requests which contain an option-125 +vendor-class option which in turn holds a vendor section for IANA +enterprise number 3561 which contains sub-options codes 1 and 2. If +this is present then the network-tag "cpewan-id" is set. +This allows dnsmasq to be configured to reply with the correct +GatewayManufacturerOUI, GatewaySerialNumber and GatewayProductClass like this: + +dhcp-option=cpewan-id,vi-encap:3561,4,"<GatewayManufacturerOUI>" +dhcp-option=cpewan-id,vi-encap:3561,5,"<SerialNumber>" +dhcp-option=cpewan-id,vi-encap:3561,6,"<ProductClass>" + +Second, the received sub-options 1, 2, and 3 are passed to the DHCP +lease-change script as the environment variables DNSMASQ_CPEWAN_OUI, +DNSMASQ_CPEWAN_SERIAL, and DNSMASQ_CPEWAN_CLASS respectively. This allows +the script to be used to maintain a ManageableDevice table as +specified in F.2.1. Note that this data is not retained in dnsmasq's +internal DHCP lease database, so it is not available on every call to +the script (this is the same as some other data such as vendor and +user classes). It will however be available for at least the "add" +call, and should be stored then against the IP address as primary +key for future use. + + +This feature was added to dnsmasq under sponsorship from Ericsson. + + diff --git a/contrib/MacOSX-launchd/launchd-README.txt b/contrib/MacOSX-launchd/launchd-README.txt new file mode 100644 index 0000000..4783221 --- /dev/null +++ b/contrib/MacOSX-launchd/launchd-README.txt @@ -0,0 +1,38 @@ +This is a launchd item for Mac OS X and Mac OS X Server. +For more information about launchd, the +"System wide and per-user daemon/agent manager", see the launchd +man page, or the wikipedia page: http://en.wikipedia.org/wiki/Launchd + +This launchd item uses the following flags: +--keep-in-foreground - this is crucial for use with launchd +--log-queries - this is optional and you can remove it +--log-facility=/var/log/dnsmasq.log - again optional instead of system.log + +To use this launchd item for dnsmasq: + +If you don't already have a folder /Library/LaunchDaemons, then create one: +sudo mkdir /Library/LaunchDaemons +sudo chown root:admin /Library/LaunchDaemons +sudo chmod 775 /Library/LaunchDaemons + +Copy uk.org.thekelleys.dnsmasq.plist there and then set ownership/permissions: +sudo cp uk.org.thekelleys.dnsmasq.plist /Library/LaunchDaemons/ +sudo chown root:admin /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist +sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist + +Optionally, edit your dnsmasq configuration file to your liking. + +To start the launchd job, which starts dnsmaq, reboot or use the command: +sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist + +To stop the launchd job, which stops dnsmasq, use the command: +sudo launchctl unload /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist + +If you want to permanently stop the launchd job, so it doesn't start the job even after a reboot, use the following command: +sudo launchctl unload -w /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist + +If you make a change to the configuration file, you should relaunch dnsmasq; +to do this unload and then load again: + +sudo launchctl unload /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist +sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist diff --git a/contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist b/contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist new file mode 100644 index 0000000..87725b1 --- /dev/null +++ b/contrib/MacOSX-launchd/uk.org.thekelleys.dnsmasq.plist @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Label</key> + <string>uk.org.thekelleys.dnsmasq</string> + <key>ProgramArguments</key> + <array> + <string>/usr/local/sbin/dnsmasq</string> + <string>--keep-in-foreground</string> + </array> + <key>RunAtLoad</key> + <true/> +</dict> +</plist> diff --git a/contrib/Solaris10/README b/contrib/Solaris10/README new file mode 100644 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/README-sparc b/contrib/Solaris10/README-sparc new file mode 100644 index 0000000..327b65c --- /dev/null +++ b/contrib/Solaris10/README-sparc @@ -0,0 +1,8 @@ +Hi Simon, + +I just wanted to let you know that I have built a Solaris .pkg install package of your dnsmasq utility for people to use. Feel free to point them in my direction if you have people who want this sort of thing. + +http://ejesconsulting.wordpress.com/2010/05/12/gnu-dnsmasq-for-opensolaris-sparc/ + +Thanks +-evan diff --git a/contrib/Solaris10/README.create_package b/contrib/Solaris10/README.create_package new file mode 100644 index 0000000..676899a --- /dev/null +++ b/contrib/Solaris10/README.create_package @@ -0,0 +1,25 @@ +Ok, script attached ... seems to be working ok for me, +tried to install and remove a few times. It does the +right thing with the smf when installing, you can then +simply enable the service. Upon removal it cleans up the +files but won't clean up the services (I think until +a reboot) ... I've only started looking at the new +packages stuff in the last day or two, so I could be +missing something, but I can't find any way to force + a proper cleanup. + +It requires that you have a writable repository setup +as per the docs on the opensolaris website and it will +create a dnsmasq package (package name is a variable +in the script). The script takes a version number for +the package and assumes that it's in the contrib/Solaris10 +directory, it then works out the base tree directory +from $0. + +i.e. $ contrib/Solaris10/create_package 2.52-1 +or $ cd contrib/Solaris10; ./create_package 2.52-1 + +It's a bit more complex than it could be because I +prefer putting the daemon in /usr/sbin and the config +in /etc, so the script will actually create a new +version of the existing contrib dnsmasq.xml. diff --git a/contrib/Solaris10/create_package b/contrib/Solaris10/create_package new file mode 100644 index 0000000..acfa2a1 --- /dev/null +++ b/contrib/Solaris10/create_package @@ -0,0 +1,87 @@ +#!/bin/sh + +# +# For our package, and for the SMF script, we need to define where we +# want things to go... +# +BIN_DIR="/usr/sbin" +CONF_DIR="/etc" +MAN_DIR="/usr/share/man/man8" + +PACKAGE_NAME="dnsmasq" + +# +# Since we know we are in the contrib directory we can work out where +# the rest of the tree is... +# +BASEDIR="`dirname $0`/../.." + +# +# We need a version number to use for the package creation... +# +if [ $# != 1 ]; then + echo "Usage: $0 <package_version_number>" >&2 + exit 1 +fi +VERSION="$1" + +# +# First thing we do is fix-up the smf file to use the paths we prefer... +# +if [ ! -f "${BASEDIR}/contrib/Solaris10/dnsmasq.xml" ]; then + echo "$0: unable to find contrib/Solaris10/dnsmasq.xml" >&2 + exit 1 +fi + +echo "Fixing up smf file ... \c" +cat "${BASEDIR}/contrib/Solaris10/dnsmasq.xml" | \ + sed -e "s%/usr/local/etc%${CONF_DIR}%" \ + -e "s%/usr/local/sbin%${BIN_DIR}%" \ + -e "s%/usr/local/man%${MAN_DIR}%" > ${BASEDIR}/contrib/Solaris10/dnsmasq-pkg.xml +echo "done." + +echo "Creating packaging file ... \c" +cat <<EOF >${BASEDIR}/contrib/Solaris10/dnsmasq_package.inc +# +# header +# +set name=pkg.name value="dnsmasq" +set name=pkg.description value="dnsmasq daemon - dns, dhcp, tftp etc" +set name=pkg.detailed_url value="http://www.thekelleys.org.uk/dnsmasq/doc.html" +set name=info.maintainer value="TBD (tbd@tbd.com)" +set name=info.upstream value="dnsmasq-discuss@lists.thekelleys.org.uk" +set name=info.upstream_url value="http://www.thekelleys.org.uk/dnsmasq/doc.html" +# +# dependencies ... none? +# + +# +# directories +# +dir mode=0755 owner=root group=bin path=${BIN_DIR}/ +dir mode=0755 owner=root group=sys path=${CONF_DIR}/ +dir mode=0755 owner=root group=sys path=${MAN_DIR}/ +dir mode=0755 owner=root group=sys path=/var/ +dir mode=0755 owner=root group=sys path=/var/svc +dir mode=0755 owner=root group=sys path=/var/svc/manifest +dir mode=0755 owner=root group=sys path=/var/svc/manifest/network + +# +# files +# +file ${BASEDIR}/src/dnsmasq mode=0555 owner=root group=bin path=${BIN_DIR}/dnsmasq +file ${BASEDIR}/man/dnsmasq.8 mode=0555 owner=root group=bin path=${MAN_DIR}/dnsmasq.8 +file ${BASEDIR}/dnsmasq.conf.example mode=0644 owner=root group=sys path=${CONF_DIR}/dnsmasq.conf preserve=strawberry +file ${BASEDIR}/contrib/Solaris10/dnsmasq-pkg.xml mode=0644 owner=root group=sys path=/var/svc/manifest/network/dnsmasq.xml restart_fmri=svc:/system/manifest-import:default + +EOF +echo "done." + +echo "Creating package..." +eval `pkgsend open ${PACKAGE_NAME}@${VERSION}` +pkgsend include ${BASEDIR}/contrib/Solaris10/dnsmasq_package.inc +if [ "$?" = 0 ]; then + pkgsend close +else + echo "Errors" +fi diff --git a/contrib/Solaris10/dnsmasq.xml b/contrib/Solaris10/dnsmasq.xml new file mode 100644 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 100644 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 100644 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 100644 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 100644 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 100644 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 100644 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 100644 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 100644 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 100644 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-pre10.4/DNSmasq b/contrib/dnsmasq_MacOSX-pre10.4/DNSmasq new file mode 100755 index 0000000..6b62118 --- /dev/null +++ b/contrib/dnsmasq_MacOSX-pre10.4/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-pre10.4/README.rtf b/contrib/dnsmasq_MacOSX-pre10.4/README.rtf new file mode 100644 index 0000000..da48411 --- /dev/null +++ b/contrib/dnsmasq_MacOSX-pre10.4/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-pre10.4/StartupParameters.plist b/contrib/dnsmasq_MacOSX-pre10.4/StartupParameters.plist new file mode 100644 index 0000000..454bda0 --- /dev/null +++ b/contrib/dnsmasq_MacOSX-pre10.4/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 100644 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 100644 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 100644 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 100644 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 100644 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 100644 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 Binary files differnew file mode 100644 index 0000000..22fc32b --- /dev/null +++ b/contrib/slackware-dnsmasq/dnsmasq.leasedir.diff.gz diff --git a/contrib/slackware-dnsmasq/doinst.sh.gz b/contrib/slackware-dnsmasq/doinst.sh.gz Binary files differnew file mode 100644 index 0000000..3b44227 --- /dev/null +++ b/contrib/slackware-dnsmasq/doinst.sh.gz diff --git a/contrib/slackware-dnsmasq/rc.dnsmasq.gz b/contrib/slackware-dnsmasq/rc.dnsmasq.gz Binary files differnew file mode 100644 index 0000000..a86abbb --- /dev/null +++ b/contrib/slackware-dnsmasq/rc.dnsmasq.gz diff --git a/contrib/slackware-dnsmasq/slack-desc b/contrib/slackware-dnsmasq/slack-desc new file mode 100644 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/static-arp/static-arp b/contrib/static-arp/static-arp new file mode 100644 index 0000000..82115b7 --- /dev/null +++ b/contrib/static-arp/static-arp @@ -0,0 +1,35 @@ +#!/bin/sh + +# Contributed by Darren Hoo <darren.hoo@gmail.com> + +# If you use dnsmasq as DHCP server on a router, you may have +# met with attackers trying ARP Poison Routing (APR) on your +# local area network. This script will setup a 'permanent' entry +# in the router's ARP table upon each DHCP transaction so as to +# make the attacker's efforts less successful. + +# Usage: +# edit /etc/dnsmasq.conf and specify the path of this script +# to dhcp-script, for example: +# dhcp-script=/usr/sbin/static-arp + +# if $1 is add or old, update the static arp table entry. +# if $1 is del, then delete the entry from the table +# if $1 is init which is called by dnsmasq at startup, it's ignored + +ARP=/usr/sbin/arp + +# Arguments. +# $1 is action (add, del, old) +# $2 is MAC +# $3 is address +# $4 is hostname (optional, may be unset) + +if [ ${1} = del ] ; then + ${ARP} -d $3 +fi + +if [ ${1} = old ] || [ ${1} = add ] ; then + ${ARP} -s $3 $2 +fi + diff --git a/contrib/try-all-ns/README b/contrib/try-all-ns/README new file mode 100644 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 100644 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 100644 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 100644 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 100644 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 Binary files differnew file mode 100644 index 0000000..7307e23 --- /dev/null +++ b/contrib/webmin/dnsmasq.wbm diff --git a/contrib/wrt/Makefile b/contrib/wrt/Makefile new file mode 100644 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 100644 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 100644 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 100644 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 100644 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 100644 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/debian/changelog b/debian/changelog new file mode 100644 index 0000000..2cbf56b --- /dev/null +++ b/debian/changelog @@ -0,0 +1,23 @@ +dnsmasq (2.57-slp2+3) unstable; urgency=low + + * Enable dbus feature + * Git: 165.213.180.234:/slp/pkgs/d/dnsmasq + * Tag: dnsmasq_2.57-slp2+3 + + -- Byeongho Shim <bh.shim@samsung.com> Mon, 07 Nov 2011 21:26:30 +0900 + +dnsmasq (2.57-slp2+2) unstable; urgency=low + + * Change the section on control file + * Git: 165.213.180.234:/slp/pkgs/d/dnsmasq + * Tag: dnsmasq_2.57-slp2+2 + + -- Byeongho Shim <bh.shim@samsung.com> Tue, 30 Aug 2011 09:59:52 +0900 + +dnsmasq (2.57-slp2+1) unstable; urgency=low + + * Initial Release. + * Git: 165.213.180.234:/slp/pkgs/d/dnsmasq + * Tag: dnsmasq_2.57-slp2+1 + + -- Byeongho Shim <bh.shim@samsung.com> Tue, 16 Aug 2011 16:43:13 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..edba10b --- /dev/null +++ b/debian/control @@ -0,0 +1,20 @@ +Source: dnsmasq +Section: base +Priority: extra +Maintainer: Seungyoun Ju <sy39.ju@samsung.com>, Hocheol Seo <hocheol.seo@samsung.com> +Build-Depends: debhelper (>= 5), libdbus-1-dev +Standards-Version: 3.7.2 + +Package: dnsmasq +Section: base +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Dnsmasq is a lightweight, easy to configure DNS forwarder + and DHCP server. + +Package: dnsmasq-dbg +Section: debug +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, dnsmasq (= ${Source-Version}) +Description: Dnsmasq is a lightweight, easy to configure DNS forwarder + and DHCP server. diff --git a/debian/dnsmasq.install.in b/debian/dnsmasq.install.in new file mode 100644 index 0000000..7346c45 --- /dev/null +++ b/debian/dnsmasq.install.in @@ -0,0 +1 @@ +@PREFIX@/bin/* diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..be777c3 --- /dev/null +++ b/debian/rules @@ -0,0 +1,118 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +CFLAGS ?= -Wall -g +CXXFLAGS ?= -Wall -g +LDFLAGS ?= +PREFIX ?= /usr +DATADIR ?= /opt + +CFLAGS += -fPIE +CXXFLAGS += -fPIE + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 + CXXFLAGS += -O0 +else + CFLAGS += -O2 + CXXFLAGS += -O2 +endif + +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--hash-style=both -Wl,--as-needed -pie + +CMAKE_BUILD_DIR ?= $(CURDIR)/cmake_build_tmp + +configure: configure-stamp +configure-stamp: + dh_testdir + mkdir -p $(CMAKE_BUILD_DIR) && cd $(CMAKE_BUILD_DIR) && \ + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake .. -DCMAKE_INSTALL_PREFIX=$(PREFIX) + + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + cd $(CMAKE_BUILD_DIR) && $(MAKE) + + #docbook-to-man debian/wavplayer.sgml > wavplayer.1 + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + rm -rf $(CMAKE_BUILD_DIR) + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/wavplayer. + cd $(CMAKE_BUILD_DIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot +# dh_installchangelogs +# dh_installdocs +# dh_installexamples + dh_install --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo +# dh_installman + dh_link + dh_strip --dbg-package=dnsmasq-dbg + dh_compress + dh_fixperms +# dh_perl + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example new file mode 100644 index 0000000..719dcff --- /dev/null +++ b/dnsmasq.conf.example @@ -0,0 +1,553 @@ +# Configuration file for dnsmasq. +# +# Format is one option per line, legal options are the same +# as the long options legal on the command line. See +# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details. + +# The following two options make you a better netizen, since they +# tell dnsmasq to filter out queries which the public DNS cannot +# answer, and which load the servers (especially the root servers) +# unnecessarily. If you have a dial-on-demand link they also stop +# these requests from bringing up the link unnecessarily. + +# Never forward plain names (without a dot or domain part) +#domain-needed +# Never forward addresses in the non-routed address spaces. +#bogus-priv + + +# Uncomment this to filter useless windows-originated DNS requests +# which can trigger dial-on-demand links needlessly. +# Note that (amongst other things) this blocks all SRV requests, +# so don't use it if you use eg Kerberos, SIP, XMMP or Google-talk. +# This option only affects forwarding, SRV records originating for +# dnsmasq (via srv-host= lines) are not suppressed by it. +#filterwin2k + +# Change this line if you want dns to get its upstream servers from +# somewhere other that /etc/resolv.conf +#resolv-file= + +# By default, dnsmasq will send queries to any of the upstream +# servers it knows about and tries to favour servers to are known +# to be up. Uncommenting this forces dnsmasq to try each query +# with each server strictly in the order they appear in +# /etc/resolv.conf +#strict-order + +# If you don't want dnsmasq to read /etc/resolv.conf or any other +# file, getting its servers from this file instead (see below), then +# uncomment this. +#no-resolv + +# If you don't want dnsmasq to poll /etc/resolv.conf or other resolv +# files for changes and re-read them then uncomment this. +#no-poll + +# Add other name servers here, with domain specs if they are for +# non-public domains. +#server=/localnet/192.168.0.1 + +# Example of routing PTR queries to nameservers: this will send all +# address->name queries for 192.168.3/24 to nameserver 10.1.2.3 +#server=/3.168.192.in-addr.arpa/10.1.2.3 + +# Add local-only domains here, queries in these domains are answered +# from /etc/hosts or DHCP only. +#local=/localnet/ + +# Add domains which you want to force to an IP address here. +# The example below send any host in double-click.net to a local +# web-server. +#address=/double-click.net/127.0.0.1 + +# --address (and --server) work with IPv6 addresses too. +#address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83 + +# You can control how dnsmasq talks to a server: this forces +# queries to 10.1.2.3 to be routed via eth1 +# server=10.1.2.3@eth1 + +# and this sets the source (ie local) address used to talk to +# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that +# IP on the machine, obviously). +# server=10.1.2.3@192.168.1.1#55 + +# If you want dnsmasq to change uid and gid to something other +# than the default, edit the following lines. +#user= +#group= + +# If you want dnsmasq to listen for DHCP and DNS requests only on +# specified interfaces (and the loopback) give the name of the +# interface (eg eth0) here. +# Repeat the line for more than one interface. +#interface= +# Or you can specify which interface _not_ to listen on +#except-interface= +# Or which to listen on by address (remember to include 127.0.0.1 if +# you use this.) +#listen-address= +# If you want dnsmasq to provide only DNS service on an interface, +# configure it as shown above, and then use the following line to +# disable DHCP and TFTP on it. +#no-dhcp-interface= + +# On systems which support it, dnsmasq binds the wildcard address, +# even when it is listening on only some interfaces. It then discards +# requests that it shouldn't reply to. This has the advantage of +# working even when interfaces come and go and change address. If you +# want dnsmasq to really bind only the interfaces it is listening on, +# uncomment this option. About the only time you may need this is when +# running another nameserver on the same machine. +#bind-interfaces + +# If you don't want dnsmasq to read /etc/hosts, uncomment the +# following line. +#no-hosts +# or if you want it to read another file, as well as /etc/hosts, use +# this. +#addn-hosts=/etc/banner_add_hosts + +# Set this (and domain: see below) if you want to have a domain +# automatically added to simple names in a hosts-file. +#expand-hosts + +# Set the domain for dnsmasq. this is optional, but if it is set, it +# does the following things. +# 1) Allows DHCP hosts to have fully qualified domain names, as long +# as the domain part matches this setting. +# 2) Sets the "domain" DHCP option thereby potentially setting the +# domain of all systems configured by DHCP +# 3) Provides the domain part for "expand-hosts" +#domain=thekelleys.org.uk + +# Set a different domain for a particular subnet +#domain=wireless.thekelleys.org.uk,192.168.2.0/24 + +# Same idea, but range rather then subnet +#domain=reserved.thekelleys.org.uk,192.68.3.100,192.168.3.200 + +# Uncomment this to enable the integrated DHCP server, you need +# to supply the range of addresses available for lease and optionally +# a lease time. If you have more than one network, you will need to +# repeat this for each network on which you want to supply DHCP +# service. +#dhcp-range=192.168.0.50,192.168.0.150,12h + +# This is an example of a DHCP range where the netmask is given. This +# is needed for networks we reach the dnsmasq DHCP server via a relay +# agent. If you don't know what a DHCP relay agent is, you probably +# don't need to worry about this. +#dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h + +# This is an example of a DHCP range which sets a tag, so that +# some DHCP options may be set only for this network. +#dhcp-range=set:red,192.168.0.50,192.168.0.150 + +# Use this DHCP range only when the tag "green" is set. +#dhcp-range=tag:green,192.168.0.50,192.168.0.150,12h + +# Specify a subnet which can't be used for dynamic address allocation, +# is available for hosts with matching --dhcp-host lines. Note that +# dhcp-host declarations will be ignored unless there is a dhcp-range +# of some type for the subnet in question. +# In this case the netmask is implied (it comes from the network +# configuration on the machine running dnsmasq) it is possible to give +# an explicit netmask instead. +#dhcp-range=192.168.0.0,static + +# Supply parameters for specified hosts using DHCP. There are lots +# of valid alternatives, so we will give examples of each. Note that +# IP addresses DO NOT have to be in the range given above, they just +# need to be on the same network. The order of the parameters in these +# do not matter, it's permissible to give name, address and MAC in any +# order. + +# Always allocate the host with Ethernet address 11:22:33:44:55:66 +# The IP address 192.168.0.60 +#dhcp-host=11:22:33:44:55:66,192.168.0.60 + +# Always set the name of the host with hardware address +# 11:22:33:44:55:66 to be "fred" +#dhcp-host=11:22:33:44:55:66,fred + +# Always give the host with Ethernet address 11:22:33:44:55:66 +# the name fred and IP address 192.168.0.60 and lease time 45 minutes +#dhcp-host=11:22:33:44:55:66,fred,192.168.0.60,45m + +# Give a host with Ethernet address 11:22:33:44:55:66 or +# 12:34:56:78:90:12 the IP address 192.168.0.60. Dnsmasq will assume +# that these two Ethernet interfaces will never be in use at the same +# time, and give the IP address to the second, even if it is already +# in use by the first. Useful for laptops with wired and wireless +# addresses. +#dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.60 + +# Give the machine which says its name is "bert" IP address +# 192.168.0.70 and an infinite lease +#dhcp-host=bert,192.168.0.70,infinite + +# Always give the host with client identifier 01:02:02:04 +# the IP address 192.168.0.60 +#dhcp-host=id:01:02:02:04,192.168.0.60 + +# Always give the host with client identifier "marjorie" +# the IP address 192.168.0.60 +#dhcp-host=id:marjorie,192.168.0.60 + +# Enable the address given for "judge" in /etc/hosts +# to be given to a machine presenting the name "judge" when +# it asks for a DHCP lease. +#dhcp-host=judge + +# Never offer DHCP service to a machine whose Ethernet +# address is 11:22:33:44:55:66 +#dhcp-host=11:22:33:44:55:66,ignore + +# Ignore any client-id presented by the machine with Ethernet +# address 11:22:33:44:55:66. This is useful to prevent a machine +# being treated differently when running under different OS's or +# between PXE boot and OS boot. +#dhcp-host=11:22:33:44:55:66,id:* + +# Send extra options which are tagged as "red" to +# the machine with Ethernet address 11:22:33:44:55:66 +#dhcp-host=11:22:33:44:55:66,set:red + +# Send extra options which are tagged as "red" to +# any machine with Ethernet address starting 11:22:33: +#dhcp-host=11:22:33:*:*:*,set:red + +# Ignore any clients which are specified in dhcp-host lines +# or /etc/ethers. Equivalent to ISC "deny unknown-clients". +# This relies on the special "known" tag which is set when +# a host is matched. +#dhcp-ignore=tag:!known + +# Send extra options which are tagged as "red" to any machine whose +# DHCP vendorclass string includes the substring "Linux" +#dhcp-vendorclass=set:red,Linux + +# Send extra options which are tagged as "red" to any machine one +# of whose DHCP userclass strings includes the substring "accounts" +#dhcp-userclass=set:red,accounts + +# Send extra options which are tagged as "red" to any machine whose +# MAC address matches the pattern. +#dhcp-mac=set:red,00:60:8C:*:*:* + +# If this line is uncommented, dnsmasq will read /etc/ethers and act +# on the ethernet-address/IP pairs found there just as if they had +# been given as --dhcp-host options. Useful if you keep +# MAC-address/host mappings there for other purposes. +#read-ethers + +# Send options to hosts which ask for a DHCP lease. +# See RFC 2132 for details of available options. +# Common options can be given to dnsmasq by name: +# run "dnsmasq --help dhcp" to get a list. +# Note that all the common settings, such as netmask and +# broadcast address, DNS server and default route, are given +# sane defaults by dnsmasq. You very likely will not need +# any dhcp-options. If you use Windows clients and Samba, there +# are some options which are recommended, they are detailed at the +# end of this section. + +# Override the default route supplied by dnsmasq, which assumes the +# router is the same machine as the one running dnsmasq. +#dhcp-option=3,1.2.3.4 + +# Do the same thing, but using the option name +#dhcp-option=option:router,1.2.3.4 + +# Override the default route supplied by dnsmasq and send no default +# route at all. Note that this only works for the options sent by +# default (1, 3, 6, 12, 28) the same line will send a zero-length option +# for all other option numbers. +#dhcp-option=3 + +# Set the NTP time server addresses to 192.168.0.4 and 10.10.0.5 +#dhcp-option=option:ntp-server,192.168.0.4,10.10.0.5 + +# Set the NTP time server address to be the same machine as +# is running dnsmasq +#dhcp-option=42,0.0.0.0 + +# Set the NIS domain name to "welly" +#dhcp-option=40,welly + +# Set the default time-to-live to 50 +#dhcp-option=23,50 + +# Set the "all subnets are local" flag +#dhcp-option=27,1 + +# Send the etherboot magic flag and then etherboot options (a string). +#dhcp-option=128,e4:45:74:68:00:00 +#dhcp-option=129,NIC=eepro100 + +# Specify an option which will only be sent to the "red" network +# (see dhcp-range for the declaration of the "red" network) +# Note that the tag: part must precede the option: part. +#dhcp-option = tag:red, option:ntp-server, 192.168.1.1 + +# The following DHCP options set up dnsmasq in the same way as is specified +# for the ISC dhcpcd in +# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt +# adapted for a typical dnsmasq installation where the host running +# dnsmasq is also the host running samba. +# you may want to uncomment some or all of them if you use +# Windows clients and Samba. +#dhcp-option=19,0 # option ip-forwarding off +#dhcp-option=44,0.0.0.0 # set netbios-over-TCP/IP nameserver(s) aka WINS server(s) +#dhcp-option=45,0.0.0.0 # netbios datagram distribution server +#dhcp-option=46,8 # netbios node type + +# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client +# probably doesn't support this...... +#dhcp-option=option:domain-search,eng.apple.com,marketing.apple.com + +# Send RFC-3442 classless static routes (note the netmask encoding) +#dhcp-option=121,192.168.1.0/24,1.2.3.4,10.0.0.0/8,5.6.7.8 + +# Send vendor-class specific options encapsulated in DHCP option 43. +# The meaning of the options is defined by the vendor-class so +# options are sent only when the client supplied vendor class +# matches the class given here. (A substring match is OK, so "MSFT" +# matches "MSFT" and "MSFT 5.0"). This example sets the +# mtftp address to 0.0.0.0 for PXEClients. +#dhcp-option=vendor:PXEClient,1,0.0.0.0 + +# Send microsoft-specific option to tell windows to release the DHCP lease +# when it shuts down. Note the "i" flag, to tell dnsmasq to send the +# value as a four-byte integer - that's what microsoft wants. See +# http://technet2.microsoft.com/WindowsServer/en/library/a70f1bb7-d2d4-49f0-96d6-4b7414ecfaae1033.mspx?mfr=true +#dhcp-option=vendor:MSFT,2,1i + +# Send the Encapsulated-vendor-class ID needed by some configurations of +# Etherboot to allow is to recognise the DHCP server. +#dhcp-option=vendor:Etherboot,60,"Etherboot" + +# Send options to PXELinux. Note that we need to send the options even +# though they don't appear in the parameter request list, so we need +# to use dhcp-option-force here. +# See http://syslinux.zytor.com/pxe.php#special for details. +# Magic number - needed before anything else is recognised +#dhcp-option-force=208,f1:00:74:7e +# Configuration file name +#dhcp-option-force=209,configs/common +# Path prefix +#dhcp-option-force=210,/tftpboot/pxelinux/files/ +# Reboot time. (Note 'i' to send 32-bit value) +#dhcp-option-force=211,30i + +# Set the boot filename for netboot/PXE. You will only need +# this is you want to boot machines over the network and you will need +# a TFTP server; either dnsmasq's built in TFTP server or an +# external one. (See below for how to enable the TFTP server.) +#dhcp-boot=pxelinux.0 + +# Boot for Etherboot gPXE. The idea is to send two different +# filenames, the first loads gPXE, and the second tells gPXE what to +# load. The dhcp-match sets the gpxe tag for requests from gPXE. +#dhcp-match=set:gpxe,175 # gPXE sends a 175 option. +#dhcp-boot=tag:!gpxe,undionly.kpxe +#dhcp-boot=mybootimage + +# Encapsulated options for Etherboot gPXE. All the options are +# encapsulated within option 175 +#dhcp-option=encap:175, 1, 5b # priority code +#dhcp-option=encap:175, 176, 1b # no-proxydhcp +#dhcp-option=encap:175, 177, string # bus-id +#dhcp-option=encap:175, 189, 1b # BIOS drive code +#dhcp-option=encap:175, 190, user # iSCSI username +#dhcp-option=encap:175, 191, pass # iSCSI password + +# Test for the architecture of a netboot client. PXE clients are +# supposed to send their architecture as option 93. (See RFC 4578) +#dhcp-match=peecees, option:client-arch, 0 #x86-32 +#dhcp-match=itanics, option:client-arch, 2 #IA64 +#dhcp-match=hammers, option:client-arch, 6 #x86-64 +#dhcp-match=mactels, option:client-arch, 7 #EFI x86-64 + +# Do real PXE, rather than just booting a single file, this is an +# alternative to dhcp-boot. +#pxe-prompt="What system shall I netboot?" +# or with timeout before first available action is taken: +#pxe-prompt="Press F8 for menu.", 60 + +# Available boot services. for PXE. +#pxe-service=x86PC, "Boot from local disk" + +# Loads <tftp-root>/pxelinux.0 from dnsmasq TFTP server. +#pxe-service=x86PC, "Install Linux", pxelinux + +# Loads <tftp-root>/pxelinux.0 from TFTP server at 1.2.3.4. +# Beware this fails on old PXE ROMS. +#pxe-service=x86PC, "Install Linux", pxelinux, 1.2.3.4 + +# Use bootserver on network, found my multicast or broadcast. +#pxe-service=x86PC, "Install windows from RIS server", 1 + +# Use bootserver at a known IP address. +#pxe-service=x86PC, "Install windows from RIS server", 1, 1.2.3.4 + +# If you have multicast-FTP available, +# information for that can be passed in a similar way using options 1 +# to 5. See page 19 of +# http://download.intel.com/design/archives/wfm/downloads/pxespec.pdf + + +# Enable dnsmasq's built-in TFTP server +#enable-tftp + +# Set the root directory for files available via FTP. +#tftp-root=/var/ftpd + +# Make the TFTP server more secure: with this set, only files owned by +# the user dnsmasq is running as will be send over the net. +#tftp-secure + +# This option stops dnsmasq from negotiating a larger blocksize for TFTP +# transfers. It will slow things down, but may rescue some broken TFTP +# clients. +#tftp-no-blocksize + +# Set the boot file name only when the "red" tag is set. +#dhcp-boot=net:red,pxelinux.red-net + +# An example of dhcp-boot with an external TFTP server: the name and IP +# address of the server are given after the filename. +# Can fail with old PXE ROMS. Overridden by --pxe-service. +#dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3 + +# Set the limit on DHCP leases, the default is 150 +#dhcp-lease-max=150 + +# The DHCP server needs somewhere on disk to keep its lease database. +# This defaults to a sane location, but if you want to change it, use +# the line below. +#dhcp-leasefile=/var/lib/misc/dnsmasq.leases + +# Set the DHCP server to authoritative mode. In this mode it will barge in +# and take over the lease for any client which broadcasts on the network, +# whether it has a record of the lease or not. This avoids long timeouts +# when a machine wakes up on a new network. DO NOT enable this if there's +# the slightest chance that you might end up accidentally configuring a DHCP +# server for your campus/company accidentally. The ISC server uses +# the same option, and this URL provides more information: +# http://www.isc.org/files/auth.html +#dhcp-authoritative + +# Run an executable when a DHCP lease is created or destroyed. +# The arguments sent to the script are "add" or "del", +# then the MAC address, the IP address and finally the hostname +# if there is one. +#dhcp-script=/bin/echo + +# Set the cachesize here. +#cache-size=150 + +# If you want to disable negative caching, uncomment this. +#no-negcache + +# Normally responses which come form /etc/hosts and the DHCP lease +# file have Time-To-Live set as zero, which conventionally means +# do not cache further. If you are happy to trade lower load on the +# server for potentially stale date, you can set a time-to-live (in +# seconds) here. +#local-ttl= + +# If you want dnsmasq to detect attempts by Verisign to send queries +# to unregistered .com and .net hosts to its sitefinder service and +# have dnsmasq instead return the correct NXDOMAIN response, uncomment +# this line. You can add similar lines to do the same for other +# registries which have implemented wildcard A records. +#bogus-nxdomain=64.94.110.11 + +# If you want to fix up DNS results from upstream servers, use the +# alias option. This only works for IPv4. +# This alias makes a result of 1.2.3.4 appear as 5.6.7.8 +#alias=1.2.3.4,5.6.7.8 +# and this maps 1.2.3.x to 5.6.7.x +#alias=1.2.3.0,5.6.7.0,255.255.255.0 +# and this maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40 +#alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0 + +# Change these lines if you want dnsmasq to serve MX records. + +# Return an MX record named "maildomain.com" with target +# servermachine.com and preference 50 +#mx-host=maildomain.com,servermachine.com,50 + +# Set the default target for MX records created using the localmx option. +#mx-target=servermachine.com + +# Return an MX record pointing to the mx-target for all local +# machines. +#localmx + +# Return an MX record pointing to itself for all local machines. +#selfmx + +# Change the following lines if you want dnsmasq to serve SRV +# records. These are useful if you want to serve ldap requests for +# Active Directory and other windows-originated DNS requests. +# See RFC 2782. +# You may add multiple srv-host lines. +# The fields are <name>,<target>,<port>,<priority>,<weight> +# If the domain part if missing from the name (so that is just has the +# service and protocol sections) then the domain given by the domain= +# config option is used. (Note that expand-hosts does not need to be +# set for this to work.) + +# A SRV record sending LDAP for the example.com domain to +# ldapserver.example.com port 389 +#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389 + +# A SRV record sending LDAP for the example.com domain to +# ldapserver.example.com port 389 (using domain=) +#domain=example.com +#srv-host=_ldap._tcp,ldapserver.example.com,389 + +# Two SRV records for LDAP, each with different priorities +#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,1 +#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,2 + +# A SRV record indicating that there is no LDAP server for the domain +# example.com +#srv-host=_ldap._tcp.example.com + +# The following line shows how to make dnsmasq serve an arbitrary PTR +# record. This is useful for DNS-SD. (Note that the +# domain-name expansion done for SRV records _does_not +# occur for PTR records.) +#ptr-record=_http._tcp.dns-sd-services,"New Employee Page._http._tcp.dns-sd-services" + +# Change the following lines to enable dnsmasq to serve TXT records. +# These are used for things like SPF and zeroconf. (Note that the +# domain-name expansion done for SRV records _does_not +# occur for TXT records.) + +#Example SPF. +#txt-record=example.com,"v=spf1 a -all" + +#Example zeroconf +#txt-record=_http._tcp.example.com,name=value,paper=A4 + +# Provide an alias for a "local" DNS name. Note that this _only_ works +# for targets which are names from DHCP or /etc/hosts. Give host +# "bert" another name, bertrand +#cname=bertand,bert + +# For debugging purposes, log each DNS query as it passes through +# dnsmasq. +#log-queries + +# Log lots of extra information about DHCP transactions. +#log-dhcp + +# Include a another lot of configuration options. +#conf-file=/etc/dnsmasq.more.conf +#conf-dir=/etc/dnsmasq.d diff --git a/dnsmasq.manifest b/dnsmasq.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/dnsmasq.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_"/> + </request> +</manifest> diff --git a/doc.html b/doc.html new file mode 100644 index 0000000..0a73083 --- /dev/null +++ b/doc.html @@ -0,0 +1,121 @@ +<HTML> +<HEAD> +<TITLE> Dnsmasq - a DNS forwarder for NAT firewalls.</TITLE> +<link rel="icon" + href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico"> +</HEAD> +<BODY BGCOLOR="WHITE"> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tr> +<td align="left" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td> +<td align="middle" valign="middle"><h1>Dnsmasq</h1></td> +<td align="right" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td></tr> +</table> + +Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP + server. It is designed to provide DNS and, optionally, DHCP, to a + small network. It can serve the names of local machines which are + not in the global DNS. The DHCP server integrates with the DNS + server and allows machines with DHCP-allocated addresses + to appear in the DNS with names configured either in each host or + in a central configuration file. Dnsmasq supports static and dynamic + DHCP leases and BOOTP/TFTP/PXE for network booting of diskless machines. +<P> + Dnsmasq is targeted at home networks using NAT and +connected to the internet via a modem, cable-modem or ADSL +connection but would be a good choice for any smallish network (up to +1000 clients is known to work) where low +resource use and ease of configuration are important. +<P> +Supported platforms include Linux (with glibc and uclibc), *BSD, +Solaris and Mac OS X. +Dnsmasq is included in at least the following Linux distributions: +Gentoo, Debian, Slackware, Suse, Fedora, +Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, fli4l, +CoyoteLinux, Endian Firewall and +Clarkconnect. It is also available as FreeBSD, OpenBSD and NetBSD ports and is used in +Linksys wireless routers (dd-wrt, openwrt and the stock firmware) and the m0n0wall project. +<P> +Dnsmasq provides the following features: +<DIR> + +<LI> +The DNS configuration of machines behind the firewall is simple and +doesn't depend on the details of the ISP's dns servers +<LI> +Clients which try to do DNS lookups while a modem link to the +internet is down will time out immediately. +</LI> +<LI> +Dnsmasq will serve names from the /etc/hosts file on the firewall +machine: If the names of local machines are there, then they can all +be addressed without having to maintain /etc/hosts on each machine. +</LI> +<LI> +The integrated DHCP server supports static and dynamic DHCP leases and +multiple networks and IP ranges. It works across BOOTP relays and +supports DHCP options including RFC3397 DNS search lists. +Machines which are configured by DHCP have their names automatically +included in the DNS and the names can specified by each machine or +centrally by associating a name with a MAC address in the dnsmasq +config file. +</LI> +<LI> +Dnsmasq caches internet addresses (A records and AAAA records) and address-to-name +mappings (PTR records), reducing the load on upstream servers and +improving performance (especially on modem connections). +</LI> +<LI> +Dnsmasq can be configured to automatically pick up the addresses of +its upstream nameservers from ppp or dhcp configuration. It will +automatically reload this information if it changes. This facility +will be of particular interest to maintainers of Linux firewall +distributions since it allows dns configuration to be made automatic. +</LI> +<LI> +On IPv6-enabled boxes, dnsmasq can both talk to upstream servers via IPv6 +and offer DNS service via IPv6. On dual-stack (IPv4 and IPv6) boxes it talks +both protocols and can even act as IPv6-to-IPv4 or IPv4-to-IPv6 forwarder. +</LI> +<LI> +Dnsmasq can be configured to send queries for certain domains to +upstream servers handling only those domains. This makes integration +with private DNS systems easy. +</LI> +<LI> +Dnsmasq supports MX and SRV records and can be configured to return MX records +for any or all local machines. +</LI> +</DIR> + +<H2>Download.</H2> + +<A HREF="http://www.thekelleys.org.uk/dnsmasq/"> Download</A> dnsmasq here. +The tarball includes this documentation, source, and manpage. +There is also a <A HREF="CHANGELOG"> CHANGELOG</A> and a <A HREF="FAQ">FAQ</A>. +Dnsmasq is part of the Debian distribution, it can be downloaded from +<A HREF="http://ftp.debian.org/debian/pool/main/d/dnsmasq/"> here</A> or installed using <TT>apt</TT>. + +<H2>Links.</H2> +Damien Raude-Morvan has an article in French at <A HREF="http://www.drazzib.com/docs-dnsmasq.html">http://www.drazzib.com/docs-dnsmasq.html</A> +There is a good article about dnsmasq at <A +HREF="http://www.enterprisenetworkingplanet.com/netos/article.php/3377351">http://www.enterprisenetworkingplanet.com/netos/article.php/3377351</A> +and another at <A +HREF="http://www.linux.com/articles/149040">http://www.linux.com/articles/149040</A> +and Ilya Evseev has an article in Russian about dnsmasq to be found at +<A HREF="http://ilya-evseev.narod.ru/articles/dnsmasq"> +http://ilya-evseev.narod.ru/articles/dnsmasq</A>. Ismael Ull has an +article about dnsmasq in Spanish at <A HREF="http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq">http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq</A> +<H2>License.</H2> +Dnsmasq is distributed under the GPL. See the file COPYING in the distribution +for details. + +<H2>Contact.</H2> +There is a dnsmasq mailing list at <A +HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss"> +http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the +first location for queries, bugreports, suggestions etc. +Dnsmasq was written by Simon Kelley. You can contact me at <A +HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>. +</BODY> + diff --git a/logo/README b/logo/README new file mode 100644 index 0000000..05a8250 --- /dev/null +++ b/logo/README @@ -0,0 +1,12 @@ +Dnsmasq logo, contributed by Justin Clift. + +The source format is Inkscape SVG vector format, which is scalable and +easy to export to other formats. For convenience I've included a 56x31 +png export and a 16x16 ico suitable for use as a web favicon. + +Simon Kelley, 22/10/2010 + + + + + diff --git a/logo/favicon.ico b/logo/favicon.ico Binary files differnew file mode 100644 index 0000000..1c7e8f8 --- /dev/null +++ b/logo/favicon.ico diff --git a/logo/icon.png b/logo/icon.png Binary files differnew file mode 100644 index 0000000..cf48461 --- /dev/null +++ b/logo/icon.png diff --git a/logo/icon.svg b/logo/icon.svg new file mode 100644 index 0000000..a2f7521 --- /dev/null +++ b/logo/icon.svg @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + x="0px" + y="0px" + width="56" + height="31" + viewBox="0 0 56 31" + enable-background="new 0 0 72.833 46.667" + xml:space="preserve" + id="svg2" + inkscape:version="0.47 r22583" + sodipodi:docname="dnsmasq_icon.svg" + inkscape:export-filename="/x/centos_home/jc/workspace/git_repos/libvirt-media/libvirt-media/png/dnsmasq_icon.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"><metadata + id="metadata27"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs25"><inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 23.3335 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="72.833 : 23.3335 : 1" + inkscape:persp3d-origin="36.4165 : 15.555667 : 1" + id="perspective4857" /> + <filter + id="filter3802" + inkscape:label="filter1" + color-interpolation-filters="sRGB" /><linearGradient + inkscape:collect="always" + xlink:href="#SVGID_3_" + id="linearGradient4929" + gradientUnits="userSpaceOnUse" + x1="30.564501" + y1="-8.8144999" + x2="32.937" + y2="32.715599" /> + <linearGradient + inkscape:collect="always" + xlink:href="#SVGID_3_" + id="linearGradient5798" + gradientUnits="userSpaceOnUse" + x1="30.564501" + y1="-8.8144999" + x2="32.937" + y2="32.715599" /><linearGradient + inkscape:collect="always" + xlink:href="#SVGID_3_" + id="linearGradient5812" + gradientUnits="userSpaceOnUse" + x1="30.564501" + y1="-8.8144999" + x2="32.937" + y2="32.715599" /><filter + id="filter6262" + inkscape:label="Drop shadow" + width="1.5" + height="1.5" + x="-0.25" + y="-0.25" + color-interpolation-filters="sRGB"><feGaussianBlur + id="feGaussianBlur6264" + in="SourceAlpha" + stdDeviation="2.500000" + result="blur" /><feColorMatrix + id="feColorMatrix6266" + result="bluralpha" + type="matrix" + values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.500000 0 " /><feOffset + id="feOffset6268" + in="bluralpha" + dx="2.700000" + dy="2.600000" + result="offsetBlur" /><feMerge + id="feMerge6270"><feMergeNode + id="feMergeNode6272" + in="offsetBlur" /><feMergeNode + id="feMergeNode6274" + in="SourceGraphic" /></feMerge></filter></defs><sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1568" + inkscape:window-height="1076" + id="namedview23" + showgrid="false" + inkscape:zoom="8" + inkscape:cx="31.966768" + inkscape:cy="21.211869" + inkscape:window-x="567" + inkscape:window-y="328" + inkscape:window-maximized="0" + inkscape:current-layer="layer1" + inkscape:showpageshadow="false" + showborder="true" /> +<g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="dnsmasq" + style="display:inline" + transform="translate(5.2838057,-15.545371)"><g + id="g3790" + transform="matrix(0.8183832,0,0,0.8183832,65.304897,9.8747678)" + style="filter:url(#filter6262)" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"><g + transform="translate(-91.018462,1.0687099)" + id="g9"> + <path + style="fill:#6700ad" + inkscape:connector-curvature="0" + id="path11" + d="M 54.997,12.151 C 50.083,9.132 43.29,7.266 35.791,7.266 c -7.5,0 -14.29,1.866 -19.204,4.885 -4.915,3.016 -7.956,7.184 -7.956,11.789 0,4.604 3.041,8.772 7.956,11.788 4.914,3.02 11.704,-4.271 19.204,-4.271 7.499,0 14.292,7.291 19.206,4.271 4.914,-3.016 7.955,-7.185 7.955,-11.788 0,-4.606 -3.041,-8.773 -7.955,-11.789 z M 24.996,24.318 c -2.698,0 -4.885,-0.922 -4.885,-2.061 0,-1.14 2.187,-2.063 4.885,-2.063 2.697,0 4.885,0.924 4.885,2.063 0,1.139 -2.188,2.061 -4.885,2.061 z m 21.501,0.191 c -2.686,0 -4.861,-0.856 -4.861,-1.912 0,-1.054 2.176,-1.911 4.861,-1.911 2.685,0 4.863,0.857 4.863,1.911 0,1.056 -2.178,1.912 -4.863,1.912 z" /> + <path + style="fill:none;stroke:#ffb616;stroke-width:1.85353255" + inkscape:connector-curvature="0" + id="path13" + d="M 54.997,12.151 C 50.083,9.132 43.29,7.266 35.791,7.266 c -7.5,0 -14.29,1.866 -19.204,4.885 -4.915,3.016 -7.956,7.184 -7.956,11.789 0,4.604 3.041,8.772 7.956,11.788 4.914,3.02 11.704,-4.271 19.204,-4.271 7.499,0 14.292,7.291 19.206,4.271 4.914,-3.016 7.955,-7.185 7.955,-11.788 0,-4.606 -3.041,-8.773 -7.955,-11.789 z M 24.996,24.318 c -2.698,0 -4.885,-0.922 -4.885,-2.061 0,-1.14 2.187,-2.063 4.885,-2.063 2.697,0 4.885,0.924 4.885,2.063 0,1.139 -2.188,2.061 -4.885,2.061 z m 21.501,0.191 c -2.686,0 -4.861,-0.856 -4.861,-1.912 0,-1.054 2.176,-1.911 4.861,-1.911 2.685,0 4.863,0.857 4.863,1.911 0,1.056 -2.178,1.912 -4.863,1.912 z" /> + </g><g + transform="translate(-91.018462,1.0687099)" + id="Layer_2"> + <linearGradient + y2="32.715599" + x2="32.937" + y1="-8.8144999" + x1="30.564501" + gradientUnits="userSpaceOnUse" + id="SVGID_3_"> + <stop + id="stop17" + style="stop-color:#FFFFFF;stop-opacity:0.73" + offset="0" /> + <stop + id="stop19" + style="stop-color:#FFFFFF;stop-opacity:0" + offset="1" /> + </linearGradient> + <path + inkscape:connector-curvature="0" + style="fill:url(#linearGradient5812)" + id="path21" + d="m 54.1,15.361 c -0.924,1.078 -2.782,1.265 -3.857,1.06 C 38,14.083 22.75,12.75 16.027,23.031 14.858,24.819 11.992,25.39 10.293,23.887 8.631,22.417 13.105,15.804 17.646,13.033 22.194,10.252 28.474,8.53 35.41,8.53 c 6.936,0 13.215,1.722 17.756,4.502 0.731,0.442 1.627,1.52 0.934,2.329 z" /> +</g></g></g></svg>
\ No newline at end of file diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 new file mode 100644 index 0000000..511f57f --- /dev/null +++ b/man/dnsmasq.8 @@ -0,0 +1,1507 @@ +.TH DNSMASQ 8 +.SH NAME +dnsmasq \- A lightweight DHCP and caching DNS server. +.SH SYNOPSIS +.B dnsmasq +.I [OPTION]... +.SH "DESCRIPTION" +.BR dnsmasq +is a lightweight DNS, TFTP and DHCP server. It is intended to provide +coupled DNS and DHCP service to a LAN. +.PP +Dnsmasq accepts DNS queries and either answers them from a small, local, +cache or forwards them to a real, recursive, DNS server. It loads the +contents of /etc/hosts so that local hostnames +which do not appear in the global DNS can be resolved and also answers +DNS queries for DHCP configured hosts. +.PP +The dnsmasq DHCP server supports static address assignments and multiple +networks. It automatically +sends a sensible default set of DHCP options, and can be configured to +send any desired set of DHCP options, including vendor-encapsulated +options. It includes a secure, read-only, +TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP. +.PP +Dnsmasq +supports IPv6 for DNS and TFTP, but not DHCP. +.SH OPTIONS +Note that in general missing parameters are allowed and switch off +functions, for instance "--pid-file" disables writing a PID file. On +BSD, unless the GNU getopt library is linked, the long form of the +options does not work on the command line; it is still recognised in +the configuration file. +.TP +.B --test +Read and syntax check configuration file(s). Exit with code 0 if all +is OK, or a non-zero code otherwise. Do not start up dnsmasq. +.TP +.B \-h, --no-hosts +Don't read the hostnames in /etc/hosts. +.TP +.B \-H, --addn-hosts=<file> +Additional hosts file. Read the specified file as well as /etc/hosts. If -h is given, read +only the specified file. This option may be repeated for more than one +additional hosts file. If a directory is given, then read all the files contained in that directory. +.TP +.B \-E, --expand-hosts +Add the domain to simple names (without a period) in /etc/hosts +in the same way as for DHCP-derived names. Note that this does not +apply to domain names in cnames, PTR records, TXT records etc. +.TP +.B \-T, --local-ttl=<time> +When replying with information from /etc/hosts or the DHCP leases +file dnsmasq by default sets the time-to-live field to zero, meaning +that the requestor should not itself cache the information. This is +the correct thing to do in almost all situations. This option allows a +time-to-live (in seconds) to be given for these replies. This will +reduce the load on the server at the expense of clients using stale +data under some circumstances. +.TP +.B --neg-ttl=<time> +Negative replies from upstream servers normally contain time-to-live +information in SOA records which dnsmasq uses for caching. If the +replies from upstream servers omit this information, dnsmasq does not +cache the reply. This option gives a default value for time-to-live +(in seconds) which dnsmasq uses to cache negative replies even in +the absence of an SOA record. +.TP +.B --max-ttl=<time> +Set a maximum TTL value that will be handed out to clients. The specified +maximum TTL will be given to clients instead of the true TTL value if it is +lower. The true TTL value is however kept in the cache to avoid flooding +the upstream DNS servers. +.TP +.B \-k, --keep-in-foreground +Do not go into the background at startup but otherwise run as +normal. This is intended for use when dnsmasq is run under daemontools +or launchd. +.TP +.B \-d, --no-daemon +Debug mode: don't fork to the background, don't write a pid file, +don't change user id, generate a complete cache dump on receipt on +SIGUSR1, log to stderr as well as syslog, don't fork new processes +to handle TCP queries. +.TP +.B \-q, --log-queries +Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. +.TP +.B \-8, --log-facility=<facility> +Set the facility to which dnsmasq will send syslog entries, this +defaults to DAEMON, and to LOCAL0 when debug mode is in operation. If +the facility given contains at least one '/' character, it is taken to +be a filename, and dnsmasq logs to the given file, instead of +syslog. If the facility is '-' then dnsmasq logs to stderr. +(Errors whilst reading configuration will still go to syslog, +but all output from a successful startup, and all output whilst +running, will go exclusively to the file.) When logging to a file, +dnsmasq will close and reopen the file when it receives SIGUSR2. This +allows the log file to be rotated without stopping dnsmasq. +.TP +.B --log-async[=<lines>] +Enable asynchronous logging and optionally set the limit on the +number of lines +which will be queued by dnsmasq when writing to the syslog is slow. +Dnsmasq can log asynchronously: this +allows it to continue functioning without being blocked by syslog, and +allows syslog to use dnsmasq for DNS queries without risking deadlock. +If the queue of log-lines becomes full, dnsmasq will log the +overflow, and the number of messages lost. The default queue length is +5, a sane value would be 5-25, and a maximum limit of 100 is imposed. +.TP +.B \-x, --pid-file=<path> +Specify an alternate path for dnsmasq to record its process-id in. Normally /var/run/dnsmasq.pid. +.TP +.B \-u, --user=<username> +Specify the userid to which dnsmasq will change after startup. Dnsmasq must normally be started as root, but it will drop root +privileges after startup by changing id to another user. Normally this user is "nobody" but that +can be over-ridden with this switch. +.TP +.B \-g, --group=<groupname> +Specify the group which dnsmasq will run +as. The defaults to "dip", if available, to facilitate access to +/etc/ppp/resolv.conf which is not normally world readable. +.TP +.B \-v, --version +Print the version number. +.TP +.B \-p, --port=<port> +Listen on <port> instead of the standard DNS port (53). Setting this +to zero completely disables DNS function, leaving only DHCP and/or TFTP. +.TP +.B \-P, --edns-packet-max=<size> +Specify the largest EDNS.0 UDP packet which is supported by the DNS +forwarder. Defaults to 4096, which is the RFC5625-recommended size. +.TP +.B \-Q, --query-port=<query_port> +Send outbound DNS queries from, and listen for their replies on, the +specific UDP port <query_port> instead of using random ports. NOTE +that using this option will make dnsmasq less secure against DNS +spoofing attacks but it may be faster and use less resources. Setting this option +to zero makes dnsmasq use a single port allocated to it by the +OS: this was the default behaviour in versions prior to 2.43. +.TP +.B --min-port=<port> +Do not use ports less than that given as source for outbound DNS +queries. Dnsmasq picks random ports as source for outbound queries: +when this option is given, the ports used will always to larger +than that specified. Useful for systems behind firewalls. +.TP +.B \-i, --interface=<interface name> +Listen only on the specified interface(s). Dnsmasq automatically adds +the loopback (local) interface to the list of interfaces to use when +the +.B \--interface +option is used. If no +.B \--interface +or +.B \--listen-address +options are given dnsmasq listens on all available interfaces except any +given in +.B \--except-interface +options. IP alias interfaces (eg "eth1:0") cannot be used with +.B --interface +or +.B --except-interface +options, use --listen-address instead. +.TP +.B \-I, --except-interface=<interface name> +Do not listen on the specified interface. Note that the order of +.B \--listen-address +.B --interface +and +.B --except-interface +options does not matter and that +.B --except-interface +options always override the others. +.TP +.B \-2, --no-dhcp-interface=<interface name> +Do not provide DHCP or TFTP on the specified interface, but do provide DNS service. +.TP +.B \-a, --listen-address=<ipaddr> +Listen on the given IP address(es). Both +.B \--interface +and +.B \--listen-address +options may be given, in which case the set of both interfaces and +addresses is used. Note that if no +.B \--interface +option is given, but +.B \--listen-address +is, dnsmasq will not automatically listen on the loopback +interface. To achieve this, its IP address, 127.0.0.1, must be +explicitly given as a +.B \--listen-address +option. +.TP +.B \-z, --bind-interfaces +On systems which support it, dnsmasq binds the wildcard address, +even when it is listening on only some interfaces. It then discards +requests that it shouldn't reply to. This has the advantage of +working even when interfaces come and go and change address. This +option forces dnsmasq to really bind only the interfaces it is +listening on. About the only time when this is useful is when +running another nameserver (or another instance of dnsmasq) on the +same machine. Setting this option also enables multiple instances of +dnsmasq which provide DHCP service to run in the same machine. +.TP +.B \-y, --localise-queries +Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was +received. If a name in /etc/hosts has more than one address associated with +it, and at least one of those addresses is on the same subnet as the +interface to which the query was sent, then return only the +address(es) on that subnet. This allows for a server to have multiple +addresses in /etc/hosts corresponding to each of its interfaces, and +hosts will get the correct address based on which network they are +attached to. Currently this facility is limited to IPv4. +.TP +.B \-b, --bogus-priv +Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc) +which are not found in /etc/hosts or the DHCP leases file are answered +with "no such domain" rather than being forwarded upstream. +.TP +.B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>] +Modify IPv4 addresses returned from upstream nameservers; old-ip is +replaced by new-ip. If the optional mask is given then any address +which matches the masked old-ip will be re-written. So, for instance +.B --alias=1.2.3.0,6.7.8.0,255.255.255.0 +will map 1.2.3.56 to 6.7.8.56 and 1.2.3.67 to 6.7.8.67. This is what +Cisco PIX routers call "DNS doctoring". If the old IP is given as +range, then only addresses in the range, rather than a whole subnet, +are re-written. So +.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0 +maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40 +.TP +.B \-B, --bogus-nxdomain=<ipaddr> +Transform replies which contain the IP address given into "No such +domain" replies. This is intended to counteract a devious move made by +Verisign in September 2003 when they started returning the address of +an advertising web page in response to queries for unregistered names, +instead of the correct NXDOMAIN response. This option tells dnsmasq to +fake the correct response when it sees this behaviour. As at Sept 2003 +the IP address being returned by Verisign is 64.94.110.11 +.TP +.B \-f, --filterwin2k +Later versions of windows make periodic DNS requests which don't get sensible answers from +the public DNS and can cause problems by triggering dial-on-demand links. This flag turns on an option +to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the +requested name has underscores, to catch LDAP requests. +.TP +.B \-r, --resolv-file=<file> +Read the IP addresses of the upstream nameservers from <file>, instead of +/etc/resolv.conf. For the format of this file see +.BR resolv.conf (5) +the only lines relevant to dnsmasq are nameserver ones. Dnsmasq can +be told to poll more than one resolv.conf file, the first file name specified +overrides the default, subsequent ones add to the list. This is only +allowed when polling; the file with the currently latest modification +time is the one used. +.TP +.B \-R, --no-resolv +Don't read /etc/resolv.conf. Get upstream servers only from the command +line or the dnsmasq configuration file. +.TP +.B \-1, --enable-dbus +Allow dnsmasq configuration to be updated via DBus method calls. The +configuration which can be changed is upstream DNS servers (and +corresponding domains) and cache clear. Requires that dnsmasq has +been built with DBus support. +.TP +.B \-o, --strict-order +By default, dnsmasq will send queries to any of the upstream servers +it knows about and tries to favour servers that are known to +be up. Setting this flag forces dnsmasq to try each query with each +server strictly in the order they appear in /etc/resolv.conf +.TP +.B --all-servers +By default, when dnsmasq has more than one upstream server available, +it will send queries to just one server. Setting this flag forces +dnsmasq to send all queries to all available servers. The reply from +the server which answers first will be returned to the original requestor. +.TP +.B --stop-dns-rebind +Reject (and log) addresses from upstream nameservers which are in the +private IP ranges. This blocks an attack where a browser behind a +firewall is used to probe machines on the local network. +.TP +.B --rebind-localhost-ok +Exempt 127.0.0.0/8 from rebinding checks. This address range is +returned by realtime black hole servers, so blocking it may disable +these services. +.TP +.B --rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/] +Do not detect and block dns-rebind on queries to these domains. The +argument may be either a single domain, or multiple domains surrounded +by '/', like the --server syntax, eg. +.B --rebind-domain-ok=/domain1/domain2/domain3/ +.TP +.B \-n, --no-poll +Don't poll /etc/resolv.conf for changes. +.TP +.B --clear-on-reload +Whenever /etc/resolv.conf is re-read, clear the DNS cache. +This is useful when new nameservers may have different +data than that held in cache. +.TP +.B \-D, --domain-needed +Tells dnsmasq to never forward queries for plain names, without dots +or domain parts, to upstream nameservers. If the name is not known +from /etc/hosts or DHCP then a "not found" answer is returned. +.TP +.B \-S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source-ip>|<interface>[#<port>]] +Specify IP address of upstream servers directly. Setting this flag does +not suppress reading of /etc/resolv.conf, use -R to do that. If one or +more +optional domains are given, that server is used only for those domains +and they are queried only using the specified server. This is +intended for private nameservers: if you have a nameserver on your +network which deals with names of the form +xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving the flag +.B -S /internal.thekelleys.org.uk/192.168.1.1 +will send all queries for +internal machines to that nameserver, everything else will go to the +servers in /etc/resolv.conf. An empty domain specification, +.B // +has the special meaning of "unqualified names only" ie names without any +dots in them. A non-standard port may be specified as +part of the IP +address using a # character. +More than one -S flag is allowed, with +repeated domain or ipaddr parts as required. + +More specific domains take precendence over less specific domains, so: +.B --server=/google.com/1.2.3.4 +.B --server=/www.google.com/2.3.4.5 +will send queries for *.google.com to 1.2.3.4, except *www.google.com, +which will go to 2.3.4.5 + +The special server address '#' means, "use the standard servers", so +.B --server=/google.com/1.2.3.4 +.B --server=/www.google.com/# +will send queries for *.google.com to 1.2.3.4, except *www.google.com which will +be forwarded as usual. + +Also permitted is a -S +flag which gives a domain but no IP address; this tells dnsmasq that +a domain is local and it may answer queries from /etc/hosts or DHCP +but should never forward queries on that domain to any upstream +servers. +.B local +is a synonym for +.B server +to make configuration files clearer in this case. + +The optional string after the @ character tells +dnsmasq how to set the source of the queries to this +nameserver. It should be an ip-address, which should belong to the machine on which +dnsmasq is running otherwise this server line will be logged and then +ignored, or an interface name. If an interface name is given, then +queries to the server will be forced via that interface; if an +ip-address is given then the source address of the queries will be set +to that address. +The query-port flag is ignored for any servers which have a +source address specified but the port may be specified directly as +part of the source address. Forcing queries to an interface is not +implemented on all platforms supported by dnsmasq. +.TP +.B \-A, --address=/<domain>/[domain/]<ipaddr> +Specify an IP address to return for any host in the given domains. +Queries in the domains are never forwarded and always replied to +with the specified IP address which may be IPv4 or IPv6. To give +both IPv4 and IPv6 addresses for a domain, use repeated -A flags. +Note that /etc/hosts and DHCP leases override this for individual +names. A common use of this is to redirect the entire doubleclick.net +domain to some friendly local web server to avoid banner ads. The +domain specification works in the same was as for --server, with the +additional facility that /#/ matches any domain. Thus +--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not +answered from /etc/hosts or DHCP and not sent to an upstream +nameserver by a more specific --server directive. +.TP +.B \-m, --mx-host=<mx name>[[,<hostname>],<preference>] +Return an MX record named <mx name> pointing to the given hostname (if +given), or +the host specified in the --mx-target switch +or, if that switch is not given, the host on which dnsmasq +is running. The default is useful for directing mail from systems on a LAN +to a central server. The preference value is optional, and defaults to +1 if not given. More than one MX record may be given for a host. +.TP +.B \-t, --mx-target=<hostname> +Specify the default target for the MX record returned by dnsmasq. See +--mx-host. If --mx-target is given, but not --mx-host, then dnsmasq +returns a MX record containing the MX target for MX queries on the +hostname of the machine on which dnsmasq is running. +.TP +.B \-e, --selfmx +Return an MX record pointing to itself for each local +machine. Local machines are those in /etc/hosts or with DHCP leases. +.TP +.B \-L, --localmx +Return an MX record pointing to the host given by mx-target (or the +machine on which dnsmasq is running) for each +local machine. Local machines are those in /etc/hosts or with DHCP +leases. +.TP +.B \-W, --srv-host=<_service>.<_prot>.[<domain>],[<target>[,<port>[,<priority>[,<weight>]]]] +Return a SRV DNS record. See RFC2782 for details. If not supplied, the +domain defaults to that given by +.B --domain. +The default for the target domain is empty, and the default for port +is one and the defaults for +weight and priority are zero. Be careful if transposing data from BIND +zone files: the port, weight and priority numbers are in a different +order. More than one SRV record for a given service/domain is allowed, +all that match are returned. +.TP +.B \-Y, --txt-record=<name>[[,<text>],<text>] +Return a TXT DNS record. The value of TXT record is a set of strings, +so any number may be included, delimited by commas; use quotes to put +commas into a string. Note that the maximum length of a single string +is 255 characters, longer strings are split into 255 character chunks. +.TP +.B --ptr-record=<name>[,<target>] +Return a PTR DNS record. +.TP +.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>] +Return an NAPTR DNS record, as specified in RFC3403. +.TP +.B --cname=<cname>,<target> +Return a CNAME record which indicates that <cname> is really +<target>. There are significant limitations on the target; it must be a +DNS name which is known to dnsmasq from /etc/hosts (or additional +hosts files) or from DHCP. If the target does not satisfy this +criteria, the whole cname is ignored. The cname must be unique, but it +is permissable to have more than one cname pointing to the same target. +.TP +.B --interface-name=<name>,<interface> +Return a DNS record associating the name with the primary address on +the given interface. This flag specifies an A record for the given +name in the same way as an /etc/hosts line, except that the address is +not constant, but taken from the given interface. If the interface is +down, not configured or non-existent, an empty record is returned. The +matching PTR record is also created, mapping the interface address to +the name. More than one name may be associated with an interface +address by repeating the flag; in that case the first instance is used +for the reverse address-to-name mapping. +.TP +.B --add-mac +Add the MAC address of the requestor to DNS queries which are +forwarded upstream. This may be used to DNS filtering by the upstream +server. The MAC address can only be added if the requestor is on the same +subnet as the dnsmasq server. Note that the mechanism used to achieve this (an EDNS0 option) +is not yet standardised, so this should be considered +experimental. Also note that exposing MAC addresses in this way may +have security and privacy implications. +.TP +.B \-c, --cache-size=<cachesize> +Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching. +.TP +.B \-N, --no-negcache +Disable negative caching. Negative caching allows dnsmasq to remember +"no such domain" answers from upstream nameservers and answer +identical queries without forwarding them again. +.TP +.B \-0, --dns-forward-max=<queries> +Set the maximum number of concurrent DNS queries. The default value is +150, which should be fine for most setups. The only known situation +where this needs to be increased is when using web-server log file +resolvers, which can generate large numbers of concurrent queries. +.TP +.B --proxy-dnssec +A resolver on a client machine can do DNSSEC validation in two ways: it +can perform the cryptograhic operations on the reply it receives, or +it can rely on the upstream recursive nameserver to do the validation +and set a bit in the reply if it succeeds. Dnsmasq is not a DNSSEC +validator, so it cannot perform the validation role of the recursive nameserver, +but it can pass through the validation results from its own upstream +nameservers. This option enables this behaviour. You should only do +this if you trust all the configured upstream nameservers +.I and the network between you and them. +If you use the first DNSSEC mode, validating resolvers in clients, +this option is not required. Dnsmasq always returns all the data +needed for a client to do validation itself. +.TP +.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>,<end-addr>[,<netmask>[,<broadcast>]][,<lease time>] +Enable the DHCP server. Addresses will be given out from the range +<start-addr> to <end-addr> and from statically defined addresses given +in +.B dhcp-host +options. If the lease time is given, then leases +will be given for that length of time. The lease time is in seconds, +or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given, +the default lease time is one hour. The +minimum lease time is two minutes. This +option may be repeated, with different addresses, to enable DHCP +service to more than one network. For directly connected networks (ie, +networks on which the machine running dnsmasq has an interface) the +netmask is optional. It is, however, required for networks which +receive DHCP service via a relay agent. The broadcast address is +always optional. It is always +allowed to have more than one dhcp-range in a single subnet. + +The optional +.B set:<tag> +sets an alphanumeric label which marks this network so that +dhcp options may be specified on a per-network basis. +When it is prefixed with 'tag:' instead, then its meaning changes from setting +a tag to matching it. Only one tag may be set, but more than one tag may be matched. +The end address may be replaced by the keyword +.B static +which tells dnsmasq to enable DHCP for the network specified, but not +to dynamically allocate IP addresses: only hosts which have static +addresses given via +.B dhcp-host +or from /etc/ethers will be served. The end address may be replaced by +the keyword +.B proxy +in which case dnsmasq will provide proxy-DHCP on the specified +subnet. (See +.B pxe-prompt +and +.B pxe-service +for details.) + +The interface:<interface name> section is not normally used. See the +NOTES section for details of this. +.TP +.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore] +Specify per host parameters for the DHCP server. This allows a machine +with a particular hardware address to be always allocated the same +hostname, IP address and lease time. A hostname specified like this +overrides any supplied by the DHCP client on the machine. It is also +allowable to ommit the hardware address and include the hostname, in +which case the IP address and lease times will apply to any machine +claiming that name. For example +.B --dhcp-host=00:20:e0:3b:13:af,wap,infinite +tells dnsmasq to give +the machine with hardware address 00:20:e0:3b:13:af the name wap, and +an infinite DHCP lease. +.B --dhcp-host=lap,192.168.0.199 +tells +dnsmasq to always allocate the machine lap the IP address +192.168.0.199. + +Addresses allocated like this are not constrained to be +in the range given by the --dhcp-range option, but they must be in +the same subnet as some valid dhcp-range. For +subnets which don't need a pool of dynamically allocated addresses, +use the "static" keyword in the dhcp-range declaration. + +It is allowed to use client identifiers rather than +hardware addresses to identify hosts by prefixing with 'id:'. Thus: +.B --dhcp-host=id:01:02:03:04,..... +refers to the host with client identifier 01:02:03:04. It is also +allowed to specify the client ID as text, like this: +.B --dhcp-host=id:clientidastext,..... + +The special option id:* means "ignore any client-id +and use MAC addresses only." This is useful when a client presents a client-id sometimes +but not others. + +If a name appears in /etc/hosts, the associated address can be +allocated to a DHCP lease, but only if a +.B --dhcp-host +option specifying the name also exists. Only one hostname can be +given in a +.B dhcp-host +option, but aliases are possible by using CNAMEs. (See +.B --cname +). + +The special keyword "ignore" +tells dnsmasq to never offer a DHCP lease to a machine. The machine +can be specified by hardware address, client ID or hostname, for +instance +.B --dhcp-host=00:20:e0:3b:13:af,ignore +This is +useful when there is another DHCP server on the network which should +be used by some machines. + +The set:<tag> contruct sets the tag +whenever this dhcp-host directive is in use. This can be used to +selectively send DHCP options just for this host. More than one tag +can be set in a dhcp-host directive (but not in other places where +"set:<tag>" is allowed). When a host matches any +dhcp-host directive (or one implied by /etc/ethers) then the special +tag "known" is set. This allows dnsmasq to be configured to +ignore requests from unknown machines using +.B --dhcp-ignore=tag:!known +Ethernet addresses (but not client-ids) may have +wildcard bytes, so for example +.B --dhcp-host=00:20:e0:3b:13:*,ignore +will cause dnsmasq to ignore a range of hardware addresses. Note that +the "*" will need to be escaped or quoted on a command line, but not +in the configuration file. + +Hardware addresses normally match any +network (ARP) type, but it is possible to restrict them to a single +ARP type by preceding them with the ARP-type (in HEX) and "-". so +.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4 +will only match a +Token-Ring hardware address, since the ARP-address type for token ring +is 6. + +As a special case, it is possible to include more than one +hardware address. eg: +.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2 +This allows an IP address to be associated with +multiple hardware addresses, and gives dnsmasq permission to abandon a +DHCP lease to one of the hardware addresses when another one asks for +a lease. Beware that this is a dangerous thing to do, it will only +work reliably if only one of the hardware addresses is active at any +time and there is no way for dnsmasq to enforce this. It is, for instance, +useful to allocate a stable IP address to a laptop which +has both wired and wireless interfaces. +.TP +.B --dhcp-hostsfile=<path> +Read DHCP host information from the specified file. If a directory +is given, then read all the files contained in that directory. The file contains +information about one host per line. The format of a line is the same +as text to the right of '=' in --dhcp-host. The advantage of storing DHCP host information +in this file is that it can be changed without re-starting dnsmasq: +the file will be re-read when dnsmasq receives SIGHUP. +.TP +.B --dhcp-optsfile=<path> +Read DHCP option information from the specified file. If a directory +is given, then read all the files contained in that directory. The advantage of +using this option is the same as for --dhcp-hostsfile: the +dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that +it is possible to encode the information in a +.B --dhcp-boot +flag as DHCP options, using the options names bootfile-name, +server-ip-address and tftp-server. This allows these to be included +in a dhcp-optsfile. +.TP +.B \-Z, --read-ethers +Read /etc/ethers for information about hosts for the DHCP server. The +format of /etc/ethers is a hardware address, followed by either a +hostname or dotted-quad IP address. When read by dnsmasq these lines +have exactly the same effect as +.B --dhcp-host +options containing the same information. /etc/ethers is re-read when +dnsmasq receives SIGHUP. +.TP +.B \-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]] +Specify different or extra options to DHCP clients. By default, +dnsmasq sends some standard options to DHCP clients, the netmask and +broadcast address are set to the same as the host running dnsmasq, and +the DNS server and default route are set to the address of the machine +running dnsmasq. If the domain name option has been set, that is sent. +This configuration allows these defaults to be overridden, +or other options specified. The option, to be sent may be given as a +decimal number or as "option:<option-name>" The option numbers are +specified in RFC2132 and subsequent RFCs. The set of option-names +known by dnsmasq can be discovered by running "dnsmasq --help dhcp". +For example, to set the default route option to +192.168.4.4, do +.B --dhcp-option=3,192.168.4.4 +or +.B --dhcp-option = option:router, 192.168.4.4 +and to set the time-server address to 192.168.0.4, do +.B --dhcp-option = 42,192.168.0.4 +or +.B --dhcp-option = option:ntp-server, 192.168.0.4 +The special address 0.0.0.0 is taken to mean "the address of the +machine running dnsmasq". Data types allowed are comma separated +dotted-quad IP addresses, a decimal number, colon-separated hex digits +and a text string. If the optional tags are given then +this option is only sent when all the tags are matched. + +Special processing is done on a text argument for option 119, to +conform with RFC 3397. Text or dotted-quad IP addresses as arguments +to option 120 are handled as per RFC 3361. Dotted-quad IP addresses +which are followed by a slash and then a netmask size are encoded as +described in RFC 3442. + +Be careful: no checking is done that the correct type of data for the +option number is sent, it is quite possible to +persuade dnsmasq to generate illegal DHCP packets with injudicious use +of this flag. When the value is a decimal number, dnsmasq must determine how +large the data item is. It does this by examining the option number and/or the +value, but can be overridden by appending a single letter flag as follows: +b = one byte, s = two bytes, i = four bytes. This is mainly useful with +encapsulated vendor class options (see below) where dnsmasq cannot +determine data size from the option number. Option data which +consists solely of periods and digits will be interpreted by dnsmasq +as an IP address, and inserted into an option as such. To force a +literal string, use quotes. For instance when using option 66 to send +a literal IP address as TFTP server name, it is necessary to do +.B --dhcp-option=66,"1.2.3.4" + +Encapsulated Vendor-class options may also be specified using +--dhcp-option: for instance +.B --dhcp-option=vendor:PXEClient,1,0.0.0.0 +sends the encapsulated vendor +class-specific option "mftp-address=0.0.0.0" to any client whose +vendor-class matches "PXEClient". The vendor-class matching is +substring based (see --dhcp-vendorclass for details). If a +vendor-class option (number 60) is sent by dnsmasq, then that is used +for selecting encapsulated options in preference to any sent by the +client. It is +possible to omit the vendorclass completely; +.B --dhcp-option=vendor:,1,0.0.0.0 +in which case the encapsulated option is always sent. + +Options may be encapsulated within other options: for instance +.B --dhcp-option=encap:175, 190, "iscsi-client0" +will send option 175, within which is the option 190. If multiple +options are given which are encapsulated with the same option number +then they will be correctly combined into one encapsulated option. +encap: and vendor: are may not both be set in the same dhcp-option. + +The final variant on encapsulated options is "Vendor-Identifying +Vendor Options" as specified by RFC3925. These are denoted like this: +.B --dhcp-option=vi-encap:2, 10, "text" +The number in the vi-encap: section is the IANA enterprise number +used to identify this option. + +The address 0.0.0.0 is not treated specially in +encapsulated options. +.TP +.B --dhcp-option-force=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]] +This works in exactly the same way as +.B --dhcp-option +except that the option will always be sent, even if the client does +not ask for it in the parameter request list. This is sometimes +needed, for example when sending options to PXELinux. +.TP +.B --dhcp-no-override +Disable re-use of the DHCP servername and filename fields as extra +option space. If it can, dnsmasq moves the boot server and filename +information (from dhcp-boot) out of their dedicated fields into +DHCP options. This make extra space available in the DHCP packet for +options but can, rarely, confuse old or broken clients. This flag +forces "simple and safe" behaviour to avoid problems in such a case. +.TP +.B \-U, --dhcp-vendorclass=set:<tag>,<vendor-class> +Map from a vendor-class string to a tag. Most DHCP clients provide a +"vendor class" which represents, in some sense, the type of host. This option +maps vendor classes to tags, so that DHCP options may be selectively delivered +to different classes of hosts. For example +.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect +will allow options to be set only for HP printers like so: +.B --dhcp-option=tag:printers,3,192.168.4.4 +The vendor-class string is +substring matched against the vendor-class supplied by the client, to +allow fuzzy matching. The set: prefix is optional but allowed for consistency. +.TP +.B \-j, --dhcp-userclass=set:<tag>,<user-class> +Map from a user-class string to a tag (with substring +matching, like vendor classes). Most DHCP clients provide a +"user class" which is configurable. This option +maps user classes to tags, so that DHCP options may be selectively delivered +to different classes of hosts. It is possible, for instance to use +this to set a different printer server for hosts in the class +"accounts" than for hosts in the class "engineering". +.TP +.B \-4, --dhcp-mac=set:<tag>,<MAC address> +Map from a MAC address to a tag. The MAC address may include +wildcards. For example +.B --dhcp-mac=set:3com,01:34:23:*:*:* +will set the tag "3com" for any host whose MAC address matches the pattern. +.TP +.B --dhcp-circuitid=set:<tag>,<circuit-id>, --dhcp-remoteid=set:<tag>,<remote-id> +Map from RFC3046 relay agent options to tags. This data may +be provided by DHCP relay agents. The circuit-id or remote-id is +normally given as colon-separated hex, but is also allowed to be a +simple string. If an exact match is achieved between the circuit or +agent ID and one provided by a relay agent, the tag is set. +.TP +.B --dhcp-subscrid=set:<tag>,<subscriber-id> +Map from RFC3993 subscriber-id relay agent options to tags. +.TP +.B --dhcp-proxy[=<ip addr>]...... +A normal DHCP relay agent is only used to forward the initial parts of +a DHCP interaction to the DHCP server. Once a client is configured, it +communicates directly with the server. This is undesirable if the +relay agent is addding extra information to the DHCP packets, such as +that used by +.B dhcp-circuitid +and +.B dhcp-remoteid. +A full relay implementation can use the RFC 5107 serverid-override +option to force the DHCP server to use the relay as a full proxy, with all +packets passing through it. This flag provides an alternative method +of doing the same thing, for relays which don't support RFC +5107. Given alone, it manipulates the server-id for all interactions +via relays. If a list of IP addresses is given, only interactions via +relays at those addresses are affected. +.TP +.B --dhcp-match=set:<tag>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>] +Without a value, set the tag if the client sends a DHCP +option of the given number or name. When a value is given, set the tag only if +the option is sent and matches the value. The value may be of the form +"01:ff:*:02" in which case the value must match (apart from widcards) +but the option sent may have unmatched data past the end of the +value. The value may also be of the same form as in +.B dhcp-option +in which case the option sent is treated as an array, and one element +must match, so + +--dhcp-match=set:efi-ia32,option:client-arch,6 + +will set the tag "efi-ia32" if the the number 6 appears in the list of +architectures sent by the client in option 93. (See RFC 4578 for +details.) If the value is a string, substring matching is used. + +The special form with vi-encap:<enterpise number> matches against +vendor-identifying vendor classes for the specified enterprise. Please +see RFC 3925 for more details of these rare and interesting beasts. +.TP +.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]] +Perform boolean operations on tags. Any tag appearing as set:<tag> is set if +all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used) +If no tag:<tag> appears set:<tag> tags are set unconditionally. +Any number of set: and tag: forms may appear, in any order. +Tag-if lines ares executed in order, so if the tag in tag:<tag> is a +tag set by another +.B tag-if, +the line which sets the tag must precede the one which tests it. +.TP +.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>] +When all the given tags appear in the tag set ignore the host and do +not allocate it a DHCP lease. +.TP +.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]] +When all the given tags appear in the tag set, ignore any hostname +provided by the host. Note that, unlike dhcp-ignore, it is permissible +to supply no tags, in which case DHCP-client supplied hostnames +are always ignored, and DHCP hosts are added to the DNS using only +dhcp-host configuration in dnsmasq and the contents of /etc/hosts and +/etc/ethers. +.TP +.B --dhcp-generate-names=tag:<tag>[,tag:<tag>] +Generate a name for DHCP clients which do not otherwise have one, +using the MAC address expressed in hex, seperated by dashes. Note that +if a host provides a name, it will be used by preference to this, +unless +.B --dhcp-ignore-names +is set. +.TP +.B --dhcp-broadcast[=tag:<tag>[,tag:<tag>]] +When all the given tags appear in the tag set, always use broadcast to +communicate with the host when it is unconfigured. It is permissible +to supply no tags, in which case this is unconditional. Most DHCP clients which +need broadcast replies set a flag in their requests so that this +happens automatically, some old BOOTP clients do not. +.TP +.B \-M, --dhcp-boot=[tag:<tag>,]<filename>,[<servername>[,<server address>]] +Set BOOTP options to be returned by the DHCP server. Server name and +address are optional: if not provided, the name is left empty, and the +address set to the address of the machine running dnsmasq. If dnsmasq +is providing a TFTP service (see +.B --enable-tftp +) then only the filename is required here to enable network booting. +If the optional tag(s) are given, +they must match for this configuration to be sent. +.TP +.B --pxe-service=[tag:<tag>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>] +Most uses of PXE boot-ROMS simply allow the PXE +system to obtain an IP address and then download the file specified by +.B dhcp-boot +and execute it. However the PXE system is capable of more complex +functions when supported by a suitable DHCP server. + +This specifies a boot option which may appear in a PXE boot menu. <CSA> is +client system type, only services of the correct type will appear in a +menu. The known types are x86PC, PC98, IA64_EFI, Alpha, Arc_x86, +Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI and X86-64_EFI; an +integer may be used for other types. The +parameter after the menu text may be a file name, in which case dnsmasq acts as a +boot server and directs the PXE client to download the file by TFTP, +either from itself ( +.B enable-tftp +must be set for this to work) or another TFTP server if the final IP +address is given. +Note that the "layer" +suffix (normally ".0") is supplied by PXE, and should not be added to +the basename. If an integer boot service type, rather than a basename +is given, then the PXE client will search for a +suitable boot service for that type on the network. This search may be done +by broadcast, or direct to a server if its IP address is provided. +If no boot service type or filename is provided (or a boot service type of 0 is specified) +then the menu entry will abort the net boot procedure and +continue booting from local media. +.TP +.B --pxe-prompt=[tag:<tag>,]<prompt>[,<timeout>] +Setting this provides a prompt to be displayed after PXE boot. If the +timeout is given then after the +timeout has elapsed with no keyboard input, the first available menu +option will be automatically executed. If the timeout is zero then the first available menu +item will be executed immediately. If +.B pxe-prompt +is ommitted the system will wait for user input if there are multiple +items in the menu, but boot immediately if +there is only one. See +.B pxe-service +for details of menu items. + +Dnsmasq supports PXE "proxy-DHCP", in this case another DHCP server on +the network is responsible for allocating IP addresses, and dnsmasq +simply provides the information given in +.B pxe-prompt +and +.B pxe-service +to allow netbooting. This mode is enabled using the +.B proxy +keyword in +.B dhcp-range. +.TP +.B \-X, --dhcp-lease-max=<number> +Limits dnsmasq to the specified maximum number of DHCP leases. The +default is 1000. This limit is to prevent DoS attacks from hosts which +create thousands of leases and use lots of memory in the dnsmasq +process. +.TP +.B \-K, --dhcp-authoritative +Should be set when dnsmasq is definitely the only DHCP server on a network. +It changes the behaviour from strict RFC compliance so that DHCP requests on +unknown leases from unknown hosts are not ignored. This allows new hosts +to get a lease without a tedious timeout under all circumstances. It also +allows dnsmasq to rebuild its lease database without each client needing to +reacquire a lease, if the database is lost. +.TP +.B --dhcp-alternate-port[=<server port>[,<client port>]] +Change the ports used for DHCP from the default. If this option is +given alone, without arguments, it changes the ports used for DHCP +from 67 and 68 to 1067 and 1068. If a single argument is given, that +port number is used for the server and the port number plus one used +for the client. Finally, two port numbers allows arbitrary +specification of both server and client ports for DHCP. +.TP +.B \-3, --bootp-dynamic[=<network-id>[,<network-id>]] +Enable dynamic allocation of IP addresses to BOOTP clients. Use this +with care, since each address allocated to a BOOTP client is leased +forever, and therefore becomes permanently unavailable for re-use by +other hosts. if this is given without tags, then it unconditionally +enables dynamic allocation. With tags, only when the tags are all +set. It may be repeated with different tag sets. +.TP +.B \-5, --no-ping +By default, the DHCP server will attempt to ensure that an address in +not in use before allocating it to a host. It does this by sending an +ICMP echo request (aka "ping") to the address in question. If it gets +a reply, then the address must already be in use, and another is +tried. This flag disables this check. Use with caution. +.TP +.B --log-dhcp +Extra logging for DHCP: log all the options sent to DHCP clients and +the tags used to determine them. +.TP +.B \-l, --dhcp-leasefile=<path> +Use the specified file to store DHCP lease information. +.TP +.B \-6 --dhcp-script=<path> +Whenever a new DHCP lease is created, or an old one destroyed, the +executable specified by this option is run. <path> +must be an absolute pathname, no PATH search occurs. +The arguments to the process +are "add", "old" or "del", the MAC +address of the host, the IP address, and the hostname, +if known. "add" means a lease has been created, "del" means it has +been destroyed, "old" is a notification of an existing lease when +dnsmasq starts or a change to MAC address or hostname of an existing +lease (also, lease length or expiry and client-id, if leasefile-ro is set). +If the MAC address is from a network type other than ethernet, +it will have the network type prepended, eg "06-01:23:45:67:89:ab" for +token ring. The process is run as root (assuming that dnsmasq was originally run as +root) even if dnsmasq is configured to change UID to an unprivileged user. + +The environment is inherited from the invoker of dnsmasq, with some or +all of the following variables added. + +DNSMASQ_CLIENT_ID if the host provided a client-id. + +DNSMASQ_DOMAIN if the fully-qualified domain name of the host is +known, this is set to the domain part. (Note that the hostname passed +to the script as an argument is never fully-qualified.) + +If the client provides vendor-class, hostname or user-class, +these are provided in DNSMASQ_VENDOR_CLASS +DNSMASQ_SUPPLIED_HOSTNAME and +DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for +"add" actions or "old" actions when a host resumes an existing lease, +since these data are not held in dnsmasq's lease +database. + +If dnsmasq was compiled with HAVE_BROKEN_RTC, then +the length of the lease (in seconds) is stored in +DNSMASQ_LEASE_LENGTH, otherwise the time of lease expiry is stored in +DNSMASQ_LEASE_EXPIRES. The number of seconds until lease expiry is +always stored in DNSMASQ_TIME_REMAINING. + +If a lease used to have a hostname, which is +removed, an "old" event is generated with the new state of the lease, +ie no name, and the former name is provided in the environment +variable DNSMASQ_OLD_HOSTNAME. + +DNSMASQ_INTERFACE stores the name of +the interface on which the request arrived; this is not set for "old" +actions when dnsmasq restarts. + +DNSMASQ_RELAY_ADDRESS is set if the client +used a DHCP relay to contact dnsmasq and the IP address of the relay +is known. + +DNSMASQ_TAGS contains all the tags set during the +DHCP transaction, separated by spaces. + +All file descriptors are +closed except stdin, stdout and stderr which are open to /dev/null +(except in debug mode). + +The script is not invoked concurrently: at most one instance +of the script is ever running (dnsmasq waits for an instance of script to exit +before running the next). Changes to the lease database are which +require the script to be invoked are queued awaiting exit of a running instance. +If this queueing allows multiple state changes occur to a single +lease before the script can be run then +earlier states are discarded and the current state of that lease is +reflected when the script finally runs. + +At dnsmasq startup, the script will be invoked for +all existing leases as they are read from the lease file. Expired +leases will be called with "del" and others with "old". When dnsmasq +receives a HUP signal, the script will be invoked for existing leases +with an "old " event. +.TP +.B --dhcp-scriptuser +Specify the user as which to run the lease-change script. This defaults to root, but can be changed to another user using this flag. +.TP +.B \-9, --leasefile-ro +Completely suppress use of the lease database file. The file will not +be created, read, or written. Change the way the lease-change +script (if one is provided) is called, so that the lease database may +be maintained in external storage by the script. In addition to the +invocations given in +.B --dhcp-script +the lease-change script is called once, at dnsmasq startup, with the +single argument "init". When called like this the script should write +the saved state of the lease database, in dnsmasq leasefile format, to +stdout and exit with zero exit code. Setting this +option also forces the leasechange script to be called on changes +to the client-id and lease length and expiry time. +.TP +.B --bridge-interface=<interface>,<alias>[,<alias>] +Treat DHCP request packets arriving at any of the <alias> interfaces +as if they had arrived at <interface>. This option is necessary when +using "old style" bridging on BSD platforms, since +packets arrive at tap interfaces which don't have an IP address. +.TP +.B \-s, --domain=<domain>[,<address range>[,local]] +Specifies DNS domains for the DHCP server. Domains may be be given +unconditionally (without the IP range) or for limited IP ranges. This has two effects; +firstly it causes the DHCP server to return the domain to any hosts +which request it, and secondly it sets the domain which it is legal +for DHCP-configured hosts to claim. The intention is to constrain +hostnames so that an untrusted host on the LAN cannot advertise +its name via dhcp as e.g. "microsoft.com" and capture traffic not +meant for it. If no domain suffix is specified, then any DHCP +hostname with a domain part (ie with a period) will be disallowed +and logged. If suffix is specified, then hostnames with a domain +part are allowed, provided the domain part matches the suffix. In +addition, when a suffix is set then hostnames without a domain +part have the suffix added as an optional domain part. Eg on my network I can set +.B --domain=thekelleys.org.uk +and have a machine whose DHCP hostname is "laptop". The IP address for that machine is available from +.B dnsmasq +both as "laptop" and "laptop.thekelleys.org.uk". If the domain is +given as "#" then the domain is read from the first "search" directive +in /etc/resolv.conf (or equivalent). + +The address range can be of the form +<ip address>,<ip address> or <ip address>/<netmask> or just a single +<ip address>. See +.B --dhcp-fqdn +which can change the behaviour of dnsmasq with domains. + +If the address range is given as ip-address/network-size, then a +additional flag "local" may be supplied which has the effect of adding +--local declarations for forward and reverse DNS queries. Eg. +.B --domain=thekelleys.org.uk,192.168.0.0/24,local +is identical to +.B --domain=thekelleys.org.uk,192.168.0.0/24 +--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/ +The network size must be 8, 16 or 24 for this to be legal. +.TP +.B --dhcp-fqdn +In the default mode, dnsmasq inserts the unqualified names of +DHCP clients into the DNS. For this reason, the names must be unique, +even if two clients which have the same name are in different +domains. If a second DHCP client appears which has the same name as an +existing client, the name is transfered to the new client. If +.B --dhcp-fqdn +is set, this behaviour changes: the unqualified name is no longer +put in the DNS, only the qualified name. Two DHCP clients with the +same name may both keep the name, provided that the domain part is +different (ie the fully qualified names differ.) To ensure that all +names have a domain part, there must be at least +.B --domain +without an address specified when +.B --dhcp-fqdn +is set. +.TP +.B --enable-tftp[=<interface>] +Enable the TFTP server function. This is deliberately limited to that +needed to net-boot a client. Only reading is allowed; the tsize and +blksize extensions are supported (tsize is only supported in octet +mode). See NOTES section for use of the interface argument. + +.TP +.B --tftp-root=<directory>[,<interface>] +Look for files to transfer using TFTP relative to the given +directory. When this is set, TFTP paths which include ".." are +rejected, to stop clients getting outside the specified root. +Absolute paths (starting with /) are allowed, but they must be within +the tftp-root. If the optional interface argument is given, the +directory is only used for TFTP requests via that interface. +.TP +.B --tftp-unique-root +Add the IP address of the TFTP client as a path component on the end +of the TFTP-root (in standard dotted-quad format). Only valid if a +tftp-root is set and the directory exists. For instance, if tftp-root is "/tftp" and client +1.2.3.4 requests file "myfile" then the effective path will be +"/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise. +.TP +.B --tftp-secure +Enable TFTP secure mode: without this, any file which is readable by +the dnsmasq process under normal unix access-control rules is +available via TFTP. When the --tftp-secure flag is given, only files +owned by the user running the dnsmasq process are accessible. If +dnsmasq is being run as root, different rules apply: --tftp-secure +has no effect, but only files which have the world-readable bit set +are accessible. It is not recommended to run dnsmasq as root with TFTP +enabled, and certainly not without specifying --tftp-root. Doing so +can expose any world-readable file on the server to any host on the net. +.TP +.B --tftp-max=<connections> +Set the maximum number of concurrent TFTP connections allowed. This +defaults to 50. When serving a large number of TFTP connections, +per-process file descriptor limits may be encountered. Dnsmasq needs +one file descriptor for each concurrent TFTP connection and one +file descriptor per unique file (plus a few others). So serving the +same file simultaneously to n clients will use require about n + 10 file +descriptors, serving different files simultaneously to n clients will +require about (2*n) + 10 descriptors. If +.B --tftp-port-range +is given, that can affect the number of concurrent connections. +.TP +.B --tftp-no-blocksize +Stop the TFTP server from negotiating the "blocksize" option with a +client. Some buggy clients request this option but then behave badly +when it is granted. +.TP +.B --tftp-port-range=<start>,<end> +A TFTP server listens on a well-known port (69) for connection initiation, +but it also uses a dynamically-allocated port for each +connection. Normally these are allocated by the OS, but this option +specifies a range of ports for use by TFTP transfers. This can be +useful when TFTP has to traverse a firewall. The start of the range +cannot be lower than 1025 unless dnsmasq is running as root. The number +of concurrent TFTP connections is limited by the size of the port range. +.TP +.B \-C, --conf-file=<file> +Specify a different configuration file. The conf-file option is also allowed in +configuration files, to include multiple configuration files. A +filename of "-" causes dnsmasq to read configuration from stdin. +.TP +.B \-7, --conf-dir=<directory>[,<file-extension>......] +Read all the files in the given directory as configuration +files. If extension(s) are given, any files which end in those +extensions are skipped. Any files whose names end in ~ or start with . or start and end +with # are always skipped. This flag may be given on the command +line or in a configuration file. +.SH CONFIG FILE +At startup, dnsmasq reads +.I /etc/dnsmasq.conf, +if it exists. (On +FreeBSD, the file is +.I /usr/local/etc/dnsmasq.conf +) (but see the +.B \-C +and +.B \-7 +options.) The format of this +file consists of one option per line, exactly as the long options detailed +in the OPTIONS section but without the leading "--". Lines starting with # are comments and ignored. For +options which may only be specified once, the configuration file overrides +the command line. Quoting is allowed in a config file: +between " quotes the special meanings of ,:. and # are removed and the +following escapes are allowed: \\\\ \\" \\t \\e \\b \\r and \\n. The later +corresponding to tab, escape, backspace, return and newline. +.SH NOTES +When it receives a SIGHUP, +.B dnsmasq +clears its cache and then re-loads +.I /etc/hosts +and +.I /etc/ethers +and any file given by --dhcp-hostsfile, --dhcp-optsfile or --addn-hosts. +The dhcp lease change script is called for all +existing DHCP leases. If +.B +--no-poll +is set SIGHUP also re-reads +.I /etc/resolv.conf. +SIGHUP +does NOT re-read the configuration file. +.PP +When it receives a SIGUSR1, +.B dnsmasq +writes statistics to the system log. It writes the cache size, +the number of names which have had to removed from the cache before +they expired in order to make room for new names and the total number +of names that have been inserted into the cache. For each upstream +server it gives the number of queries sent, and the number which +resulted in an error. In +.B --no-daemon +mode or when full logging is enabled (-q), a complete dump of the +contents of the cache is made. +.PP +When it receives SIGUSR2 and it is logging direct to a file (see +.B --log-facility +) +.B dnsmasq +will close and reopen the log file. Note that during this operation, +dnsmasq will not be running as root. When it first creates the logfile +dnsmasq changes the ownership of the file to the non-root user it will run +as. Logrotate should be configured to create a new log file with +the ownership which matches the existing one before sending SIGUSR2. +If TCP DNS queries are in progress, the old logfile will remain open in +child processes which are handling TCP queries and may continue to be +written. There is a limit of 150 seconds, after which all existing TCP +processes will have expired: for this reason, it is not wise to +configure logfile compression for logfiles which have just been +rotated. Using logrotate, the required options are +.B create +and +.B delaycompress. + + +.PP +Dnsmasq is a DNS query forwarder: it it not capable of recursively +answering arbitrary queries starting from the root servers but +forwards such queries to a fully recursive upstream DNS server which is +typically provided by an ISP. By default, dnsmasq reads +.I /etc/resolv.conf +to discover the IP +addresses of the upstream nameservers it should use, since the +information is typically stored there. Unless +.B --no-poll +is used, +.B dnsmasq +checks the modification time of +.I /etc/resolv.conf +(or equivalent if +.B \--resolv-file +is used) and re-reads it if it changes. This allows the DNS servers to +be set dynamically by PPP or DHCP since both protocols provide the +information. +Absence of +.I /etc/resolv.conf +is not an error +since it may not have been created before a PPP connection exists. Dnsmasq +simply keeps checking in case +.I /etc/resolv.conf +is created at any +time. Dnsmasq can be told to parse more than one resolv.conf +file. This is useful on a laptop, where both PPP and DHCP may be used: +dnsmasq can be set to poll both +.I /etc/ppp/resolv.conf +and +.I /etc/dhcpc/resolv.conf +and will use the contents of whichever changed +last, giving automatic switching between DNS servers. +.PP +Upstream servers may also be specified on the command line or in +the configuration file. These server specifications optionally take a +domain name which tells dnsmasq to use that server only to find names +in that particular domain. +.PP +In order to configure dnsmasq to act as cache for the host on which it is running, put "nameserver 127.0.0.1" in +.I /etc/resolv.conf +to force local processes to send queries to +dnsmasq. Then either specify the upstream servers directly to dnsmasq +using +.B \--server +options or put their addresses real in another file, say +.I /etc/resolv.dnsmasq +and run dnsmasq with the +.B \-r /etc/resolv.dnsmasq +option. This second technique allows for dynamic update of the server +addresses by PPP or DHCP. +.PP +Addresses in /etc/hosts will "shadow" different addresses for the same +names in the upstream DNS, so "mycompany.com 1.2.3.4" in /etc/hosts will ensure that +queries for "mycompany.com" always return 1.2.3.4 even if queries in +the upstream DNS would otherwise return a different address. There is +one exception to this: if the upstream DNS contains a CNAME which +points to a shadowed name, then looking up the CNAME through dnsmasq +will result in the unshadowed address associated with the target of +the CNAME. To work around this, add the CNAME to /etc/hosts so that +the CNAME is shadowed too. + +.PP +The tag system works as follows: For each DHCP request, dnsmasq +collects a set of valid tags from active configuration lines which +include set:<tag>, including one from the +.B dhcp-range +used to allocate the address, one from any matching +.B dhcp-host +(and "known" if a dhcp-host matches) +The tag "bootp" is set for BOOTP requests, and a tag whose name is the +name of the interface on which the request arrived is also set. + +Any configuration lines which includes one or more tag:<tag> contructs +will only be valid if all that tags are matched in the set derived +above. Typically this is dhcp-option. +.B dhcp-option +which has tags will be used in preference to an untagged +.B dhcp-option, +provided that _all_ the tags match somewhere in the +set collected as described above. The prefix '!' on a tag means 'not' +so --dhcp=option=tag:!purple,3,1.2.3.4 sends the option when the +tag purple is not in the set of valid tags. (If using this in a +command line rather than a configuration file, be sure to escape !, +which is a shell metacharacter) +.PP +Note that for +.B dhcp-range +both tag:<tag> and set:<tag> are allowed, to both select the range in +use based on (eg) dhcp-host, and to affect the options sent, based on +the range selected. + +This system evolved from an earlier, more limited one and for backward +compatibility "net:" may be used instead of "tag:" and "set:" may be +omitted. (Except in +.B dhcp-host, +where "net:" may be used instead of "set:".) For the same reason, '#' +may be used instead of '!' to indicate NOT. +.PP +The DHCP server in dnsmasq will function as a BOOTP server also, +provided that the MAC address and IP address for clients are given, +either using +.B dhcp-host +configurations or in +.I /etc/ethers +, and a +.B dhcp-range +configuration option is present to activate the DHCP server +on a particular network. (Setting --bootp-dynamic removes the need for +static address mappings.) The filename +parameter in a BOOTP request is used as a tag, +as is the tag "bootp", allowing some control over the options returned to +different classes of hosts. + +.B dhcp-range +may have an interface name supplied as +"interface:<interface-name>". The semantics if this are as follows: +For DHCP, if any other dhcp-range exists _without_ an interface name, +then the interface name is ignored and and dnsmasq behaves as if the +interface parts did not exist, otherwise DHCP is only provided to +interfaces mentioned in dhcp-range +declarations. For DNS, if there are no +.B --interface +or +.B --listen-address +flags, behaviour is unchanged by the interface part. If either of +these flags are present, the interfaces mentioned in +dhcp-ranges are added to the set which get DNS service. + +Similarly, +.B enable-tftp +may take an interface name, which enables TFTP only for a particular +interface, ignoring +.B --interface +or +.B --listen-address +flags. In addition +.B --tftp-secure +and +.B --tftp-unique-root +and +.B --tftp-no-blocksize +are ignored for requests from such interfaces. (A +.B --tftp-root +directive giving a root path and an interface should be +provided too.) + +These rules may seem odd at first sight, but they +allow a single line of the form "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" +to be added to dnsmasq configuration which then supplies +DHCP and DNS services to that interface, without affecting +what services are supplied to other interfaces and irrespective of +the existance or lack of "interface=<interface>" +lines elsewhere in the dnsmasq configuration. +"enable-tftp=virt0" and "tftp-root=<root>,virt0" do the same job for TFTP. + The idea is +that such a line can be added automatically by libvirt +or equivalent systems, without disturbing any manual +configuration. + +.SH EXIT CODES +.PP +0 - Dnsmasq successfully forked into the background, or terminated +normally if backgrounding is not enabled. +.PP +1 - A problem with configuration was detected. +.PP +2 - A problem with network access occurred (address in use, attempt +to use privileged ports without permission). +.PP +3 - A problem occurred with a filesystem operation (missing +file/directory, permissions). +.PP +4 - Memory allocation failure. +.PP +5 - Other miscellaneous problem. +.PP +11 or greater - a non zero return code was received from the +lease-script process "init" call. The exit code from dnsmasq is the +script's exit code with 10 added. + +.SH LIMITS +The default values for resource limits in dnsmasq are generally +conservative, and appropriate for embedded router type devices with +slow processors and limited memory. On more capable hardware, it is +possible to increase the limits, and handle many more clients. The +following applies to dnsmasq-2.37: earlier versions did not scale as well. + +.PP +Dnsmasq is capable of handling DNS and DHCP for at least a thousand +clients. The DHCP lease times should not be very short (less than one hour). The +value of +.B --dns-forward-max +can be increased: start with it equal to +the number of clients and increase if DNS seems slow. Note that DNS +performance depends too on the performance of the upstream +nameservers. The size of the DNS cache may be increased: the hard +limit is 10000 names and the default (150) is very low. Sending +SIGUSR1 to dnsmasq makes it log information which is useful for tuning +the cache size. See the +.B NOTES +section for details. + +.PP +The built-in TFTP server is capable of many simultaneous file +transfers: the absolute limit is related to the number of file-handles +allowed to a process and the ability of the select() system call to +cope with large numbers of file handles. If the limit is set too high +using +.B --tftp-max +it will be scaled down and the actual limit logged at +start-up. Note that more transfers are possible when the same file is +being sent than when each transfer sends a different file. + +.PP +It is possible to use dnsmasq to block Web advertising by using a list +of known banner-ad servers, all resolving to 127.0.0.1 or 0.0.0.0, in +.B /etc/hosts +or an additional hosts file. The list can be very long, +dnsmasq has been tested successfully with one million names. That size +file needs a 1GHz processor and about 60Mb of RAM. + +.SH INTERNATIONALISATION +Dnsmasq can be compiled to support internationalisation. To do this, +the make targets "all-i18n" and "install-i18n" should be used instead of +the standard targets "all" and "install". When internationalisation +is compiled in, dnsmasq will produce log messages in the local +language and support internationalised domain names (IDN). Domain +names in /etc/hosts, /etc/ethers and /etc/dnsmasq.conf which contain +non-ASCII characters will be translated to the DNS-internal punycode +representation. Note that +dnsmasq determines both the language for messages and the assumed +charset for configuration +files from the LANG environment variable. This should be set to the system +default value by the script which is responsible for starting +dnsmasq. When editing the configuration files, be careful to do so +using only the system-default locale and not user-specific one, since +dnsmasq has no direct way of determining the charset in use, and must +assume that it is the system default. + +.SH FILES +.IR /etc/dnsmasq.conf + +.IR /usr/local/etc/dnsmasq.conf + +.IR /etc/resolv.conf +.IR /var/run/dnsmasq/resolv.conf +.IR /etc/ppp/resolv.conf +.IR /etc/dhcpc/resolv.conf + +.IR /etc/hosts + +.IR /etc/ethers + +.IR /var/lib/misc/dnsmasq.leases + +.IR /var/db/dnsmasq.leases + +.IR /var/run/dnsmasq.pid +.SH SEE ALSO +.BR hosts (5), +.BR resolver (5) +.SH AUTHOR +This manual page was written by Simon Kelley <simon@thekelleys.org.uk>. + + diff --git a/man/es/dnsmasq.8 b/man/es/dnsmasq.8 new file mode 100644 index 0000000..65e4b72 --- /dev/null +++ b/man/es/dnsmasq.8 @@ -0,0 +1,1517 @@ +.TH DNSMASQ 8 +.SH NOMBRE +dnsmasq \- Un ligero servidor DHCP y DNS con caché. +.SH SINOPSIS +.B dnsmasq +.I [OPCION]... +.SH "DESCRIPCIÓN" +.BR dnsmasq +es un ligero servidor DNS, TFTP y DHCP. Su propósito es proveer servicios DNS +y DHCP a una red de área local. +.PP +Dnsmasq acepta búsquedas DNS y las responde desde un pequeño +caché local, o las reenvía hacia un servidor DNS real recursivo. +Carga el contenido de /etc/hosts, de tal forma que nombres de +hosts locales los cuales no aparecen en el DNS mundial puedan ser +resueltos. También responde a búsquedas DNS para hosts configurados +vía DHCP. +.PP +El servidor DHCP dnsmasq incluye soporte para asignación de direcciones +estáticas y redes múltiples. Automáticamente envía un predeterminado sensible de +opciones DHCP, y puede ser configurado para enviar cualquier opciones DHCP deseadas, +incluyendo opciones encapsuladas por vendedores. Incluye un servidor seguro +TFTP solo-lectura para permitir el inicio vía red/PXE de hosts DHCP. Tambíen +incluye soporte para BOOTP. +.PP +Dnsmasq +incluye soporte IPv6 para DNS, pero no para DHCP. +.SH OPCIONES +Nótese que en general parámetros ausentes son permitidos y deshabilitan +funciones, por ejemplo "--pid-file=" deshabilita la escritura de un +archivo PID. En BSD, a menos que la librería GNU getopt esté enlazada, +la forma larga de las opciones no funciona en la línea de comandos, +pero todavía es reconocida en el archivo de configuración. +.TP +.B --test +Leer archivo(s) de configuración y revisar su sintaxis. Salir con código +0 si todo está bien, o un código no-cero en cualquier otro caso. No +iniciar dnsmasq. +.TP +.B \-h, --no-hosts +No leer los nombres de hosts en /etc/hosts. +.TP +.B \-H, --addn-hosts=<archivo> +Archivo de hosts adicional. Leer el archivo especificado adicionalmente +a /etc/hosts. Si se brinda -h, leer solo el archivo especificado. Esta +opción puede ser repetida para más de un archivo de hosts adicional. Si +un directorio es brindado, entonces leer todos los archivos contenidos en +ese directorio. +.TP +.B \-E, --expand-hosts +Agregar el dominio a nombres sencillos (sin punto) en /etc/hosts de la +misma manera que con nombres derivados de DHCP. Nótese que esto no +aplica a nombres de dominio en cnames, expedientes PTR, TXT, etc. +.TP +.B \-T, --local-ttl=<tiempo> +Al responder con información desde /etc/hosts o desde el archivo +de arriendos DHCP, dnsmasq fija el tiempo de vida (TTL) a cero por +predeterminado, significando que el remitente no debrá cachear +la información por sí mismo. Esto es lo correcto a hacer en casi +todas las situaciones. Esta opción permite que se especifique +cierto tiempo de vida (en segundos) para estas respuestas. Esto +reduce la carga sobre el servidor al costo de que los clientes +usaran datos añejos bajo algunas circunstancias. +.TP +.B --neg-ttl=<tiempo> +Respuestas negativas desde servidores upstream normalmente contienen +información time-to-live (tiempo de vida) en expedientes SOA que +dnsmasq usa para hacer caché. Si las respuestas de servidores upstream +omiten esta información, dnsmasq no mete la respuesta en el caché. +Esta opción brinda un valor predeterminado para el time-to-live que +dnsmasq usa para meter respuestas negativas en el caché aún en la +ausencia de un expediente SOA. +.TP +.B --max-ttl=<tiempo> +Fijar un valor TTL (tiempo de vida) máximo que será entregado a +clientes. El TTL máximo especificado será otorgado a clientes en vez +del TTL verdadero si es menor. El valor TTL real es mantenido en el caché +para prevenir la inundación de los servidores DNS upstream. +.TP +.B \-k, --keep-in-foreground +No ir hacia el fondo al iniciar, pero aparte de eso ejecutar como +normal. La intención de esto es para cuando dnsmasq es ejecutado +bajo daemontools o launchd. +.TP +.B \-d, --no-daemon +Modo debug: no hacer un fork hacia el fondo, no crear un archivo PID, +no cambiar el ID del usuario, generar un cache dump completo al +recibir un SIGUSR1, bitacorear a stderr al igual que a syslog, no +forkear procesos nuevos para manejar búsquedas TCP. +.TP +.B \-q, --log-queries +Bitacorear los resultados de búsquedas DNS manejadas por dnsmasq. +Habilitar un dump de caché completo al recibir un SIGUSR1. +.TP +.B \-8, --log-facility=<facilidad> +Fijar la facilidad a la cual dnsmasq deberá enviar mensajes syslog, +esto es DAEMON por predeterminado, y LOCAL0 cuando el modo debug está +en operación. Si la facilidad brindada contiene por lo menos un carácter +"/", se trata como un nombre de archivo, y dnsmasq bitacoreará a dicho +archivo, en vez de syslog. Si la facilidad es '-' entonces dnsmasq +bitacorea a stderr. (Errores durante la lectura de la configuración +irán a syslog todavía, pero todo output desde un inicio exitoso, y todo +output mientras en ejecución, irá a este archivo exclusivamente.) +Al bitacorear a un archivo, dnsmasq cerrará y reabrirá el archivo al +recibir un SIGUSR2. Esto permite que el archivo de bitácora sea rotado +sin detener a dnsmasq. +.TP +.B --log-async[=<líneas>] +Habilitar bitacoréo asincrónico y opcionalmente fijar el límite de número +de líneas que serán enviadas a la coleta por dnsmasq cuando syslog está +lento. Dnsmasq puede bitacorear asincrónicamente: esto le permite continuar +funcionando sin ser bloqueado por syslog, y permite a syslog usar dnsmasq +para búsquedas DNS sin riesgo de tranque. Si la coleta de líneas de bitácora +se llena, dnsmasq bitacoreará el desbordamiento, y el número de mensajes +perdidos. El tamaño predeterminado de coleta es 5, un valor sano sería 5-25, +y un límite de 100 es impuesto. +.TP +.B \-x, --pid-file=<path> +Especificar un path alterno donde dnsmasq debe guardar su PID. +Normalmente es /var/run/dnsmasq.pid. +.TP +.B \-u, --user=<usuario> +Especificar el userid al cual dnsmasq debe cambiarse despues de iniciar. +Dnsmasq normalmente debe ser iniciado como root, pero soltará los +privilegios root despues del inicio, cambiando a otro usuario. +Normalmente este usuario es "nobody", pero eso se puede cambiar +con esta opción. +.TP +.B \-g, --group=<grupo> +Especificar el grupo como el cual dnsmasq correrá. El predeterminado +es "dip", si está disponible, para facilitar el acceso a +/etc/ppp/resolv.conf el cuál normálmente no es globalmente leíble. +.TP +.B \-v, --version +Mostrar el número de versión. +.TP +.B \-p, --port=<puerto> +Escuchar en el puerto <puerto> en vez del puerto estándar DNS (53). +Fijar esto a cero deshabilita completamente la función DNS, dejando +solo DHCP y/o TFTP. +.TP +.B \-P, --edns-packet-max=<tamaño> +Especificar el paquete UDP EDNS.0 más grande que es soportado por +el reenviador DNS. Por predeterminado es 4096, lo cual es el +tamaño recomendado en RFC5625. +.TP +.B \-Q, --query-port=<puerto> +Enviar búsquedas outbound desde, y escuchar por respuestas en, +el puerto UDP <puerto> en vez de usar puertos aleatorios. Nótese +que usar esta opción hace que dnsmasq sea menos seguro contra +ataques de spoofing DNS, pero puede ser más rápido y usar menos +recursos. +Fijar esta opción a zero hace que dnsmasq use un solo puerto, +asignado por el sistema operativo (esto era el comportamiento +predeterminado en versiones anteriores a 2.43). +.TP +.B --min-port=<puerto> +No usar puertos menores a <puerto> como remitentes para búsquedas +DNS outbound. Dnsmasq escoje puertos aleatorios como remitentes +para búsquedas DNS outbound. Cuando esta opción es brindada, los +puertos usados siempre serán mayores que el especificado. Esto es +útil para sistemas detras de firewalls. +.TP +.B \-i, --interface=<nombre de interface> +Escuchar solo en las interfaces especificadas. Dnsmasq automáticamente +agrega la interface loopback a la lista de interfaces para usar cuando +la opción +.B \--interface +es usada. Si ninguna opción +.B \--interface +o +.B \--listen-address +es brindada, dnsmasq escucha en todas las interfaces disponibles excepto +cualquiera fijada con opciones +.B \--except-interface +Interfaces IP alias (por ejemplo, "eth1:0") no pueden ser utilizadas con +.B --interface +o +.B --except-interface +, usar --listen-address en vez. +.TP +.B \-I, --except-interface=<nombre de interface> +No escuchar en la interface especificada. Nótese que el orden de +las opciones +.B \--listen-address +.B --interface +y +.B --except-interface +no importa y las opciones +.B --except-interface +siempre invalidan a las otras. +.TP +.B \-2, --no-dhcp-interface=<nombre de interface> +No proveer DHCP ni TFTP en la interface especificada, pero sí +proveer servicio DNS. +.TP +.B \-a, --listen-address=<dirección IP> +Escuchar en la(s) dirección(es) IP especificada(s). Las opciones +.B \--interface +y +.B \--listen-address +ambas pueden ser brindadas, y en tal caso el juego de ambas +direcciones IP y interfaces es usada. Nótese que si ninguna opción +.B \--interface +es brindada, pero sí se brinda la opción +.B \--listen-address +, entonces dnsmasq no escuchará automáticamente en la interface +loopback. Para obtener esto, su dirección IP, 127.0.0.1, debe ser +explícitamente brindada como una opción +.B \--listen-address +.TP +.B \-z, --bind-interfaces +En sistemas que inluyen el soporte, dnsmasq acopla la dirección +de comodín, aún cuando está escuchando solamente en algunas +interfaces. Entonces descarta búsquedas a las cuales no debe +responder. Esto tiene la ventaja de funcionar aún cuando +interfaces van y vienen y cambian direcciones. Esta opción forza +a dnsmasq a acoplarse realmente solo a las interfaces en +las cuales está escuchando. Casi la única vez que esto es útil +es cuando se está corriendo otro servidor DNS (o otra instancia +de dnsmasq) en la misma máquina. Fijar esta opción tambien +habilita multiples instancias de dnsmasq, las cuales proveen +servicio DHCP en la misma máquina. +.TP +.B \-y, --localise-queries +Retornar respuestas a búsquedas DNS desde /etc/hosts las cuales dependen +de la interface donde entró la búsqueda. Si un nombre en /etc/hosts tiene +mas de una dirección asociada con el, y por lo menos una de esas direcciones +está en la misma subred de la interface donde fue enviada, entónces +retornar solo las direcciones en esa subred. Esto permite a un servidor +tener direcciones múltiples en /etc/hosts correspondientes a cada una de +sus interfaces y cada host recibirá la respuesta adecuada +dependiendo de cual red tengan adjunta. Por el momento, esta facilidad +está limitada a IPv4. +.TP +.B \-b, --bogus-priv +Búsquedas privadas reversas raras. Toda búsqueda reversa para rangos de IP +privados (192.168.x.x, etc.) los cuales no se encuentren en +/etc/hosts o en el archivo de arriendos DHCP es respondida con +"dominio no existente" en vez de ser reenviada upstream. +.TP +.B \-V, --alias=[<IP viejo>]|[<IP inicio>-<IP final>],<IP nuevo>[,<máscara>] +Modificar direcciones IPv4 retornadas desde servidores DNS upstream; +<IP viejo> es remplazado con <IP nuevo>. Si la máscara opcional +es brindada, entonces cualquier dirección que coincida con el +<IP viejo> enmascarado será re-escrita. Así que, por ejemplo, +.B --alias=1.2.3.0,6.7.8.0,255.255.255.0 trazará 1.2.3.56 a 6.7.8.56 +y 1.2.3.67 a 6.7.8.67. Esto es lo que +ruteadores Cisco PIX llaman "DNS doctoring". Si la dirección vieja es +brindada como un rango, entonces solo direcciones en ese rango, y no +la subred entera, son re-escritas. De tal manera que +.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0 +relaciona 192.168.0.10->192.168.0.40 a 10.0.0.10->10.0.0.40 +.TP +.B \-B, --bogus-nxdomain=<dirección IP> +Transformar respuestas que contienen la dirección IP brindada a +respuestas tipo "Dominio no existe". La intención de esto es actuar +en contra de una movida desviada hecha por Verisign en septiembre +del 2003, cuando comenzaron a retornar la dirección de un servidor +de publicidad en respuesta a búsquedas por nombres no registrados, +en vez de la correcta respuesta NXDOMAIN. Esta opción le dice a dnsmasq +que debe forjear la respuesta correcta cuando ve este comportamiento. +Para septiembre 2003 la dirección IP siendo retornada por Verisign +es 64.94.110.11 +.TP +.B \-f, --filterwin2k +Algunas versiones de Windows hacen búsquedas DNS periódicas las cuales no +reciben respuestas sensibles desde el DNS público y pueden causar problemas +activando enlaces marcación-en-demanda. Esta opción filtra dichas búsquedas. +Las búsquedas filtradas son para registros tipo SOA y SRV, al igual que +tipo ANY donde el nombre pedido contiene _, para atrapar búsquedas LDAP. +.TP +.B \-r, --resolv-file=<archivo> +Leer las direcciones IP de servidores DNS upstream desde <archivo>, +en vez de /etc/resolv.conf. Para el formato de este archivo, ver +.BR resolv.conf (5) +Las únicas líneas relevantes a dnsmasq son las de servidores DNS. A +dnsmasq se le puede decir que revise más de un archivo resolv.conf, +el primer archivo especificado remplaza al predeterminado, y los +subsiguientes son agregados a la lista. Esto es solo +permitido al hacer polling; el archivo con la actual fecha +de modificación más nueva es el que será usado. +.TP +.B \-R, --no-resolv +No leer /etc/resolv.conf. Obtener los servidores DNS upstream solo +desde la línea de comandos o desde el archivo de configuración de +dnsmasq. +.TP +.B \-1, --enable-dbus +Permitir que la configuración de dnsmasq sea actualizada vía llamadas +de método DBus. La configuración que puede ser cambiada es servidores +DNS upstream (y dominios correspondientes) y limpieza de caché. Esta +opción requiere que dnsmasq haya sido compilado con soporte para DBus. +.TP +.B \-o, --strict-order +Por predeterminado, dnsmasq enviará búsquedas a cualquiera de los +servidores upstream que conoce, y trata de favorecer servidores los +cuales sabe que están activos. Fijar esta opción forza a dnsmasq a +probar cada búsqueda con cada servidor estrictamente en el orden +que aparecen en /etc/resolv.conf +.TP +.B --all-servers +Por predeterminado, cuando dnsmasq tiene más de un servidor upstream +disponible, enviará búsquedas a solo un servidor. Fijar esta opción +forza a dnsmasq a enviar todas las búsquedas a todos los servidores +disponibles. La respuesta del servidor que responda primero será +devuelta al solicitante original. +.TP +.B --stop-dns-rebind +Denegar (y bitacorear) direcciones de servidores upstream que están +dentro de rangos IP privados. Esto bloquea un ataque donde un navegador +detrás de un firewall es usado para analizar máquinas en la red local. +.TP +.B --rebind-localhost-ok +Eximir a 127.0.0.0/8 de verificaciones de rebinding. Este rango de +direcciones es retornado por servidores de tiempo real tipo hoyo +negro, así que bloquearlo puede deshabilitar estos servicios. +.TP +.B --rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/] +No detectar y bloquear dns-rebind en búsquedas a estos dominios. El +argumento puede ser o un dominio sencillo, o múltiples dominios +rodeados por '/', como el syntax de --server, por ejemplo +.B --rebind-domain-ok=/dominio1/dominio2/dominio3/ +.TP +.B \-n, --no-poll +No revisar periodicamente a /etc/resolv.conf en busca de cambios. +.TP +.B --clear-on-reload +Cuando sea que /etc/resolv.conf es re-leida, liberar el caché DNS. +Esto es útil cuando servidores DNS nuevos puedan tener datos diferentes +a los contenidos en el caché. +.TP +.B \-D, --domain-needed +Le dice a dnsmasq que no debe reenviar búsquedas para nombres sencillos, +sin puntos o partes de dominios, a servidores upstream. Si el nombre +no se conoce desde /etc/hosts o desde DHCP entonces una respuesta +"no encontrado" es devuelta. +.TP +.B \-S, --local, --server=[/[<dominio>]/[dominio/]][<dirección IP>[#<puerto>][@<IP de remitente>|<interface>[#<puerto>]] +Especificar la dirección IP de servidores upstream directamente. Fijar +esta opción no suprime la lectura de /etc/resolv.conf, use -R para +hacer eso. Si uno a más dominios opcionales son brindados, ese servidor +es usado solo para esos dominios y las búsquedas son hechas usando +el servidor especificado solamente. La intención de esto es para el +uso con servidores DNS privados: si usted tiene un servidor DNS en su +red el cual lidea con nombres de la forma +xxx.internal.thekelleys.org.uk en 192.168.1.1 entonces brindar la +opción +.B -S /internal.thekelleys.org.uk/192.168.1.1 +enviará todas las búsquedas de máquinas internas a ese servidor DNS, +todas las demás búsquedas serán enviadas a los servidores en +/etc/resolv.conf. Una especificación de dominio en blanco, +.B // +tiene el significado especial de "solo nombres no calificados", o +sea nombres sin ningún punto en ellos. Un puerto no-estándar puede +ser especificado como parte de la dirección IP usando el caracter +#. Más de una opción -S es permitida, con partes de dominio o +dirección IP repetidas como sea necesario. + +Dominios más específicos toman precedencia sobre los menos específicos, +así que: +.B --server=/google.com/1.2.3.4 +.B --server=/www.google.com/2.3.4.5 +enviará búsquedas por *.google.com hacia 1.2.3.4, excepto +*www.google.com, el cual irá a 2.3.4.5. + +La dirección especial de servidor '#' significa "usar los servidores +estándares", así que +.B --server=/google.com/1.2.3.4 +.B --server=/www.google.com/# +enviará búsquedas por *.google.com hacia 1.2.3.4, excepto +*www.google.com, el cual será reenviado de manera usual. + +También se permite una opción -S la cual brinda un dominio pero +ninguna dirección IP; esto le dice a dnsmasq que un dominio es local +y puede responder a búsquedas desde /etc/hosts o DHCP pero nunca +deberá reenviar búsquedas en ese dominio a ningún servidor upstream. +.B local +es un sinónimo de +.B server +para hacer los archivos de configuración mas claros en este caso. + +El string opcional despues del carácter @ le dice a dnsmasq como fijar +el remitente de las búsquedas hacia este servidor DNS. Debe ser una +dirección IP, la cual debe ser perteneciente a la máquina en la cual +corre dnsmasq, de forma contraria esta línea de servidor será bitacoreada +y después ignorada, o un nombre de interface. Si un nombre de interface +es brindado, entonces búsquedas hacia el servidor serán forzadas vía esa +interface; si una dirección IP es brindada, entonces la dirección de +remitente de las búsquedas será fijada a esa dirección. +La etiqueta query-port es ignorada para cualquier servidores que tengan +una dirección remitente especificada, pero el puerto puede ser +especificado directamente como parte de la dirección remitente. Forzar +búsquedas a una interface no está implementado en todas las plataformas +soportadas por dnsmasq. +.TP +.B \-A, --address=/<dominio>/[dominio/]<dirección IP> +Especificar una dirección IP para retornar por cualquier host en +los dominios brindados. Búsquedas en estos dominios nunca son +reenviadas, y siempre son respondidas con la dirección IP +especificada, la cual puede ser IPv4 o IPv6. Para brindar ambas +direcciones IPv4 y IPv6 para un dominio, usar opciones -A repetidas. +Nótese que /etc/hosts y arriendos DHCP invalidan esto para nombres +individuales. Un uso común para esto es redireccionar el dominio +doubleclick.net entero a algún servidor web local amigable para +evitar banners de publicidad. La especificación funciona de la misma +forma que con --server, con la facilidad adicional que /#/ coincide +con cualquier dominio. De tal forma, --address=/#/1.2.3.4 siempre +retornará 1.2.3.4 para cualquier búsqueda no respondida desde +/etc/hosts o DHCP y que no haya sido enviada a un servidor DNS +upstream por una directiva --server mas especifica. +.TP +.B \-m, --mx-host=<nombre mx>[[,<nombre de host>],<preferencia>] +Retornar un record llamado <mx name> apuntando hacia el nombre de +host brindado (opcionalmente), o el host especificado en la opción +--mx-target, o si esa opción no es brindada, el host en el cual +dnsmasq está corriendo. El predeterminado es útil para redireccionar +correo de sistemas en la red local hacia un servidor central. La +opción de preferencia es opcional, y su predeterminado es 1 si no +es brindada. Más de un record MX puede ser brindado para un host. +.TP +.B \-t, --mx-target=<nombre de host> +Especificar el target predeterminado para el record MX devuelto +por dnsmasq. Ver --mx-host. Si --mx-target es brindado, pero no +--mx-host, entonces dnsmasq devuelve un record MX conteniendo +el target MX para búsquedas MX en el nombre de host de la máquina donde +dnsmasq está corriendo. +.TP +.B \-e, --selfmx +Retornar un record MX apuntándose a sí mismo para cada máquina local. +Máquinas locales son aquellas en /etc/hosts o con arriendos DHCP. +.TP +.B \-L, --localmx +Retornar un record MX apuntando al host brindado por mx-target (o +la máquina donde dnsmasq está corriendo) para cada máquina local. +Máquinas locales son aquellas en /etc/hosts o con arriendos DHCP. +.TP +.B \-W, --srv-host=<_servicio>.<_prot>.[<dominio>],[<target>[,<puerto>[,<prioridad>[,<peso>]]]] +Retornar un record DNS SRV. Ver RFC2782 para detalles. Si no es +brindada, el dominio se predetermina a el brindado por +.B --domain. +El predeterminado para el dominio target está vacío, el predeterminado +para puerto es uno, y los predeterminados para peso y prioridad son cero. +Tener cuidado al transponer data desde archivos de zona BIND: los +números de puerto, peso, y prioridad están en un orden diferente. Más +de un record SRV para un servicio/dominio es permitido, todos los que +coincidan son retornados. +.TP +.B \-Y, --txt-record=<nombre>[[,<texto>],<texto>] +Retornar un récord DNS TXT. El valor del récord TXT es una serie de +strings, así que cualquier número puede ser incluido, dividido por +comas. +.TP +.B --ptr-record=<nombre>[,<target>] +Retornar un récord DNS PTR. +.TP +.B --naptr-record=<nombre>,<orden>,<preferencia>,<opciones>,<servicio>,<regexp>[,<remplazo>] +Retornar un récord DNS NAPTR, como especificado en RFC3403. +.TP +.B --cname=<cname>,<target> +Retornar un expediente CNAME que indica que <cname> es realmente <target>. Hay +limitaciones significativas en el target. Debe ser un nombre DNS que le es conocido +a dnsmasq desde /etc/hosts (o archivos hosts adicionales) o de DHCP. Si el target +no satisface este criterio, el cname entero es ignorado. El cname debe ser único, +pero es permisible tener más de un cname indicando el mismo target. +.TP +.B --interface-name=<nombre>,<interface> +Retornar un expediente DNS, asociando el nombre con la dirección primaria +en la interface brindada. Esta opción especifica un expediente tipo A +para el nombre brindado de la misma forma que una línea de /etc/hosts, +excepto que la dirección no es constante y es en vez tomada de la +interface brindada. Si la interface está deshabilitada, nó configurada, +o nó existente, un récord vacío es devuelto. El récord PTR relevante +tambien es creado, trazando la dirección de la interface a el nombre. +Más de un nombre puede ser asociado con una dirección de interface, +repitiendo la opción. En tal caso, la primera instancia es usada para +la traza reversa dirección-a-nombre. +.TP +.B \-c, --cache-size=<tamaño de caché> +Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres. +Fijar el tamaño a cero deshabilita el caché. +.TP +.B \-N, --no-negcache +Deshabilitar caché negativo. El caché negativo le permite a dnsmasq +recordar resultados tipo "dominio no existe" desde servidores DNS +upstream y responder búsquedas idénticas sin reenviarlas nuevamente. +.TP +.B \-0, --dns-forward-max=<búsquedas> +Fijar el número máximo de búsquedas DNS simultáneas. El valor +predeterminado es 150, lo cuál debería estar bien para la mayoría +de casos. La única situación conocida donde esto debe ser incrementado +es al usar resolvedores de bitácoras de servidores web, los cuales pueden +generar un número inmenso de búsquedas simultáneas. +.TP +.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<dirección-inicio>,<dirección-final>[,<netmask>[,<broadcast>]][,<tiempo de arriendo>] +Habilitar el servidor DHCP. Direcciones serán distribuidas desde el +rango <dirección-inicio> hasta <dirección-final> y desde direcciones definidas +estáticamente en opciones +.B dhcp-host +Si el tiempo de arriendo es especificado, entonces arriendos serán +otorgados por esa cantidad de tiempo. El tiempo de arriendo es en +segundos, o minutos (por ejemplo, 45m), u horas (por ejemplo, 1h), o +"infinite". Si no es brindada, el tiempo de arriendo predeterminado +es de una hora. El tiempo de arriendo mínimo es de dos minutos. +Esta opción puede ser repetida, con diferentes +direcciones, para habilitar servicio DHCP en más de una red. Para +redes conectadas diréctamente (en otras palabras, redes en las +cuales la máquina corriendo dnsmasq tiene una interface) la +máscara de subred es opcional. Pero, es requerida para redes que +reciben servicio DHCP vía un agente de relay. La dirección de +broadcast siempre es opcional. Siempre se permite tener más de +un rango dhcp (dhcp-range) en una subred. + +El parámetro opcional +.B set:<tag> +fija una etiqueta alfanumérica la cual marca esta red de +tal forma que opciones dhcp puedan ser especificadas en base a cada red. +Cuando es prefijada con 'tag:' en vez, entonces el significado cambia +de "fijar etiqueta" a "coincidir con etiqueta". Solo una etiqueta puede +ser fijada, pero más de una puede ser revisada por coincidencias. La +dirección final puede ser remplazada por la palabra clave +.B static +la cual le dice a dnsmasq que debe habilitar DHCP para la red +especificada, pero no alocar dinámicamente direcciones IP: +Solo hosts que tienen direcciones estáticas brindadas vía +.B dhcp-host +o desde /etc/ethers serán servidas. La dirección final puede ser +remplazada por la palabra clave +.B proxy +caso en el cual dnsmasq proveerá proxy-DHCP en la subred especificada. (Ver +.B pxe-prompt +y +.B pxe-service +para detalles.) + +La sección interface:<interface name> no es normalmente usada. Ver la +sección NOTAS para detalles sobre esto. +.TP +.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<tiempo_de_arriendo>][,ignorar] +Especificar parámetros por host para el servidor DHCP. Esto permite +que una máquina con una dirección de hardware particular sea siempre +alocada el mismo nombre de host, dirección IP, y tiempo de arriendo. +Un nombre de host especificado de esta manera toma presedencia +sobre cualquiera suministrado por el cliente DHCP en la máquina. +También se permite omitir la direccion de hardware y incluir el +nombre de host; en tal caso la dirección IP y los tiempos de arriendo +serán aplicables a cualquier máquina que reclame ese nombre. +Por ejemplo: +.B --dhcp-host=00:20:e0:3b:13:af,wap,infinite +le dice a dnsmasq que debe darle a la máquina con dirección +ethernet 00:20:e0:3b:13:af el nombre wap, y un arriendo DHCP infinito. +.B --dhcp-host=lap,192.168.0.199 +le dice a dnsmasq que siempre debe alocarle a la maquina lap +la dirección IP 192.168.0.199. + +Direcciones alocadas de esta manera no tienen que estar dentro +del rango dado con la opción --dhcp-range, pero deben estar en la subred +de un rango DHCP (dhcp-range) válido. Para subredes que no necesitan +una collección de direcciones dinamicamente alocadas, usar la palabra +clave "static" in la declaración dhcp-range. + +Es permitido usar identificadores de cliente en vez de direcciones de +hardware para identificar hosts prefijando 'id:'. O sea que: +.B --dhcp-host=id:01:02:03:04,..... +se refiere al host con identificador de cliente 01:02:03:04. +También se permite especificar el ID de cliente como texto, así: +.B --dhcp-host=id:iddeclientecomotexto,..... + +La opción especial id:* significa "ignorar cualquier ID de cliente +y usar solamente direcciones MAC." Esto es útil cuando un cliente +presenta un ID de cliente algunas veces pero otras no. + +Si un nombre aparece en /etc/hosts, la dirección asociada puede +ser alocada a un arriendo DHCP, pero solo si existe una opción +.B --dhcp-host +la cual especifica el nombre también. Solo un hostname puede ser +brindado en una opción +.B dhcp-host +pero aliases son posibles por medio del uso de CNAMEs. (Ver +.B --cname +). + +La palabra clave "ignore" +le dice a dnsmasq que no debe ofrecer jamás un arriendo DHCP a +una máquina. La máquina puede ser especificada por dirección de +hardware, ID de cliente, o nombre de host, por ejemplo: +.B --dhcp-host=00:20:e0:3b:13:af,ignore +Esto es útil cuando hay otro servidor DHCP en la red que debe ser +usado por algúnas máquinas. + +El set:<tag> fija la etiqueta cuando sea que +esta directiva dhcp-host está en uso. Esto puede ser usado para +enviar selectivamente opciones DHCP a este host. Más de una etiqueta +puede ser fijada en una directiva dhcp-host (pero no en otros lugares +donde "set:<tag>" es permitido). Cuando un host coincide con +cualquier directiva dhcp-host (o una implicada por +/etc/ethers) entonces la etiqueta especial "known" es +fijada. Esto permite que dnsmasq sea configurado para ignorar +pedidos desde máquinas desconocidas usando +.B --dhcp-ignore=tag:!known +Direcciones ethernet (pero no client-ids) pueden tener bytes +comodínes, así que por ejemplo +.B --dhcp-host=00:20:e0:3b:13:*,ignore +causará que dnsmasq ignore un rango de direcciones ethernet. Nótese +que el "*" necesitará ser escapado o escrito entre comillas en la +línea de comandos, pero no en el archivo de configuración. + +Direcciones de hardware normalmente coinciden con cualquier +tipo de red (ARP), pero es posible restringirlas a un tipo ARP +singular precediendolo con el tipo ARP (en HEX) y "-". Así que +.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4 +solo coincidiría con una dirección de hardware Token-Ring, dado que +el tipo ARP para Token-Ring es 6. + +Como caso especial, es posible incluir más de una dirección de +hardware. Ejemplo: +.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2 +Esto permite que una dirección IP sea asociada con +direcciones de hardware múltiples, y le brinda a dnsmasq permiso +para abandonar un arriendo DHCP a una de las direcciones de hardware +cuando otra pide un arriendo. Nótese que esto es algo peligroso, +sólo funcionará dependiblemente si una de las direcciones de hardware +está activa en cualquier momento y dnsmasq no tiene forma de enforzar +esto. Pero es útil, por ejemplo, para alocar una dirección IP estable +a una laptop que tiene interface alámbrica e inalámbrica. +.TP +.B --dhcp-hostsfile=<archivo> +Leer información host DHCP desde el archivo especificado. El archivo contiene información de un host por línea. El formato de una línea es igual que texto hacia la derecha de '=' en --dhcp-host. La ventaja de almacenar información host DHCP en este archivo es que puede ser cambiada sin tener que reiniciar dnsmasq. El archivo será re-leído cuando dnsmasq recibe un SIGHUP. +.TP +.B --dhcp-optsfile=<archivo> +Leer información sobre opciones DHCP desde el archivo especificado. La +ventaja de usar esta opción es la misma que con --dhcp-hostsfile: el +archivo dhcp-optsfile será re-leído cuando dnsmasq recibe un SIGHUP. +Nótese que es posible colocar la información mediante +.B --dhcp-boot +como opciones DHCP, usando los nombres de opción bootfile-name, +server-ip-address, y tftp-server. Esto permite que sean incluidas en +un archivo dhcp-optsfile. +.TP +.B \-Z, --read-ethers +Leer /etc/ethers en busca de información sobre hosts para el servidor +DHCP. El formato de /etc/ethers es una dirección de hardware, seguida +por ya sea un nombre de host o una dirección IP. Al ser leidas por +dnsmasq, estas líneas tienen exáctamente el mismo efecto que opciones +.B --dhcp-host +que contienen la misma información. /etc/ethers es re-leída cuando +dnsmasq recibe un SIGHUP. +.TP +.B \-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]] +Especificar opciones diferentes o extra a clientes DHCP. Por +predeterminado, dnsmasq envía algunas opciones estándar a clientes +DHCP. La máscara de subred y dirección broadcast son fijadas igual +a las del host que corre dnsmasq, y el servidor DNS y ruteador +a la dirección de la máquina que corre dnsmasq. Si la opción de +nombre de dominio ha sido fijada, es enviada. Esta opción permite +que esos predeterminados sean sobrescritos, o que sean especificadas +otras opciones. La opción a ser enviada puede ser brindada como un +número decimal o como "option:<option-name>". Los números de opción +están especificados en RFC2132 y RFCs subsiguientes. El juego de +option-names conocido por dnsmasq puede ser descubierto ejecutando +"dnsmasq --help dhcp". Por ejemplo, para fijar la ruta predeterminada a +192.168.4.4, hágase un +.B --dhcp-option=3,192.168.4.4 +o +.B --dhcp-option=option:router, 192.168.4.4 +y para fijar la dirección de servidor de tiempo a 192.168.0.4, +hágase un +.B --dhcp-option=42,192.168.0.4 +o +.B --dhcp-option=option:ntp-server, 192.168.0.4 +La dirección especial 0.0.0.0 es entendida que significa "la +dirección de la máquina que corre dnsmasq". Tipos de data permitidos +son direcciones IP de cuatro segmentos, un número decimal, dígitos hex +separados por colones, y un string de texto. Si las etiquetas +opcionales son brindadas, entonces esta opción es solo enviada cuando +todas las etiquetas coinciden. + +Procesamiento especial es llevado a cabo en un argumento de texto para +la opción 119, en conforme con RFC3397. Direcciones IP textuales o de +cuatro segmentos como argumentos a la opción 120 son manejados mediante +RFC3361. Direcciones IP de cuatro segmentos que son seguidas por un diagonal +(slash) y después una máscara son codificados mediante RFC3442. + +Tener cuidado: niguna verificación es hecha sobre si el número de tipo +correcto es enviado, y es muy posible persuadir a dnsmasq para que +genere paquetes DHCP ilegales mediante uso inadecuado de esta opción. +Cuando el valor es un número decimal, dnsmasq debe determinar qué tan +grande es el objeto de data. Esto es hecho mediante una examinación del +número de opción, y/o el valor, pero puede ser invalidado agregándole +una opción de una sola letra de esta forma: b = un byte, s = dos bytes, +i = cuatro bytes. Esto es principalmente útil con opciones encapsuladas +tipo vendedor (ver abajo) donde dnsmasq no puede determinar el tamaño +de data usando el número de opción. Data de opción la cual consiste +solo de puntos y dígitos será interpretada por dnsmasq como una +dirección IP, y será insertada dentro de una opción de esa manera. +Para forzar un string literal, usar comillas. Por ejemplo, cuando se +usa la opción 66 para enviar una IP literal como un nombre de servidor +TFTP, es necesario hacer: +.B --dhcp-option=66,"1.2.3.4" + +Opciones encapsuladas vendor-class también pueden ser especificadas usando +--dhcp-option: por ejemplo +.B --dhcp-option=vendor:PXEClient,1,0.0.0.0 +envía la opción específica de clase de vendedor "mftp-address=0.0.0.0" a +cualquier cliente cuyo vendor-class +coincida con "PXEClient". El revisado de coincidencias vendor-class está +basado en substrings (ver --dhcp-vendorclass para detalles). Si una opción +vendor-class (número 60) es enviada por dnsmasq, entonces es usada para +seleccionar opciones encapsuladas en preferencia sobre cualquiera enviada +por el cliente. Es posible omitir el vendorclass completamente; +.B --dhcp-option=vendor:,1,0.0.0.0 +caso en el cuál la opción encapsulada siempre es enviada. +Opciones pueden ser encapsuladas dentro de otras opciones, por ejemplo: +.B --dhcp-option=encap:175, 190, "iscsi-client0" +enviará opción 175, dentro de la cual está opción 190. Si múltiples +opciones son brindadas que están encapsuladas con el mismo número de +opción entonces serán correctamente combinadas en una opción encapsulada. +encap: y vendor: no pueden ser fijadas ambas dentro de la misma opción dhcp-option. + +La variante final en opciones encapsuladas es "Vendor-Identifying Vendor Options" +como especificado en RFC3925. Estos son denotados así: +.B --dhcp-option=rfc3925-encap:2, 10, "text" +El número en la sección rfc3925-encap: es el número enterprise usado +para identificar esta opción. + +La dirección 0.0.0.0 no es tratada de forma especial en opciones encapsuladas. +.TP +.B --dhcp-option-force=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]] +Esto funciona exáctamente de la misma forma que +.B --dhcp-option +excepto que la opción siempre será enviada, aún si el cliente no la pide en +la lista de pedido de parámetros. Esto se necesita aveces, por ejemplo cuando +enviando opciones a PXELinux. +.TP +.B --dhcp-no-override +Deshabilitar la reutilización de los campos DHCP de nombre de servidor y +archivo como espacio para opciones extra. Si puede, dnsmasq mueve la información +del servidor boot y del nombre de archivo (de dhcp-boot) de sus campos dedicados +hacia opciones DHCP. Esto crea espacio extra en el paquete DHCP para opciones, +pero puede raramente confundir clientes viejos o defectuosos. Esta opción forza +comportamiento "simple y sencillo" para prevenir problemas en tales casos. +.TP +.B \-U, --dhcp-vendorclass=set:<tag>,<vendor-class> +Trazar desde un string vendor-class a una etiqueta. La mayoría de los +clientes DHCP proveen una "vendor class" la cual representa, en cierto +sentido, el tipo de host. Esta opción traza clases de vendedor a network +ids, de tal forma que opciones DHCP pueden ser selectivamente entregadas +a diferentes clases de hosts. Por ejemplo +.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect +peritiría que opciones sean fijadas solo para impresoras HP así: +.B --dhcp-option=tag:printers,3,192.168.4.4 +El string vendor-class es coordinado con el vendor-class proveido por +el cliente, para permitir coincidencias borrosas. El prefijo set: es +opcional, pero permitido por razones de consistencia. +.TP +.B \-j, --dhcp-userclass=set:<tag>,<user-class> +Trazar desde un string user-class a una etiqueta (con coordinación +substring, como con vendor-class). La mayoría de los clientes DHCP +proveen un "user class" el cual es configurable. Esta opción traza +clases user a network ids, de tal manera que opciones DHCP puedan +ser selectivamente enviadas a diferentes tipos de hosts. Es posible, +por ejemplo, usar esto para especificar una impresora diferente para +hosts en la clase "cuentas" que para los de la clase "ingenieria". +.TP +.B \-4, --dhcp-mac=set:<tag>,<MAC address> +Trazar desde una dirección MAC a una etiqueta. La dirección MAC +puede incluir comodínes. Por ejemplo: +.B --dhcp-mac=set:3com,01:34:23:*:*:* +fijaría el tag "3com" a cualquier host el cual su MAC coincida con +el patrón. +.TP +.B --dhcp-circuitid=<network-id>,<circuit-id>, --dhcp-remoteid=<network-id>,<remote-id> +Trazar de opciones agente de relay RFC3046 a etiquetas. Estos +datos pueden ser proveídos por agentes de relay DHCP. El circuit-id o +remote-id es normlamente brindado como hex separado por doblepuntos, pero +también se permite un string simple. Si se obtiene una coincidencia exacta +entre el circuit o agent ID y uno proveído por un agente de relay, +la etiqueta es fijada. +.TP +.B --dhcp-subscrid=set:<tag>,<subscriber-id> +Trazar de opciones relay subscriber-id RFC3993 a etiquetas. +.TP +.B --dhcp-proxy[=<ip addr>]...... +Un agente de relay normal es usado solamente para reenviar las partes +iniciales de una interacción DHCP con el servidor DHCP. Una vez que +un cliente es configurado, se comunica diectamente con el servidor. Esto +es indeseable si el agente de relay está agregando información extra a +los paquetes DHCP, tal como usado por +.B dhcp-circuitid +y +.B dhcp-remoteid. +Una implementación relay completa puede usar la opción serverid-override +RFC 5107 para obligar al servidor DHCP a usar el relay como un proxy +completo, con todos los paquetes pasando a travez de el. Esta opción +provee una manera alternativa de hacer la misma cosa, para relays que +no tienen soporte RFC 5107. Brindada por si sola, manipula el server-id +para todas las interacciones via relays. Si una lista de IPs es brindada, +solo interacciones via relays en esas direcciones son afectadas. +.TP +.B --dhcp-match=set:<tag>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>] +Sin un valor, fijar la etiqueta si el cliente envía una opción +DHCP del número o valor brindado. Cuando un valor es brindado, fijar la +etiqueta solo si la opción es enviada y coincide con el valor. El valor puede +ser de la forma "01:ff:*:02", caso en el cual el valor debe coincidir (aparte +de los comodines) pero la opción enviada puede tener data que no coincide despues +del final del valor. El valor también puede ser de la misma forma que +.B dhcp-option +caso en el cual la opción enviada es tratada como un array, y un elemento debe +coincidir, así que + +--dhcp-match=set:efi-ia32,option:client-arch,6 + +fijará la etiqueta a "efi-ia32" si el número 6 aparece en la lista de +architecturas enviada por los clientes en opción 93. (Ver RFC 4578 para +detalles.) Si el valor es un string, coincidencia substring es usada. + +La forma especial con vi-encap:<enterpise number> busca coincidencia con +clases de vendedor identificadoras para el enterprise especificado. Por +favor ver RFC 3925 para mas detalles sobre estas bestias raras e interesantes. +.TP +.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]] +Llevar a cabo operaciones boolean en etiquetas. Cualquier etiqueta +que aparece como set:<tag> es fijada si todas las etiquetas que aparecen +como tag:<tag> estan fijadas, (o desfijadas cuando tag:!<tag> es +usado). Si ningún tag:<tag> aparece, etiquetas set:<tag> son fijadas +incondicionalmente. Cualquier cantidad de formas set: y tag: +pueden aparecer, en cualquier orden. Líneas tag-if son ejecutadas +en orden, así que si la etiqueta en tag:<tag> es una etiqueta fijada +por otra +.B tag-if, +la línea que fija la etiqueta debe preceder a la que comprueba. +.TP +.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>] +Cuando todoas las etiquetas brindadas aparecen en el juego de etiquetas +ignorar el host y no brindarle un arriendo DHCP. +.TP +.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]] +Cuando todos las etiquetas brindadas aparecen en el juego de etiquetas, ignorar cualquier nombre de host proveido por el host. Nótese que, +a diferencia de dhcp-ignore, es permisible no brindar ninguna etiqueta, +y en tal caso nombres de host proveidos por clientes DHCP siempre son +ignorados, y hosts DHCP son agregados al DNS usando solo la configuración +dhcp-host en dnsmasq y el contenido de /etc/hosts y /etc/ethers. +.TP +.B --dhcp-generate-names=tag:<tag>[,tag:<tag>] +Generar un nombre para clientes DHCP que de otra forma no tienen uno, +usando la dirección MAC expresada en hex, separada por guiones. Nótese +que si un host provee un nombre, será usado preferiblemente sobre este, +a menos que +.B --dhcp-ignore-names +esté fijado. +.TP +.B --dhcp-broadcast[=tag:<tag>[,tag:<tag>]] +Cuando todas las etiquetas aparecen en el juego de etiquetas, siempre +usar broadcast para comunicar con el host cuando no está configurado. +Es permisible omitir las etiquetas, caso en el cual esto es +incondicional. La mayoría de clientes DHCP que necesitan +respuestas broadcast fijan una opción en sus pedidos para que esto pase automaticamente, algunos clientes BOOTP viejos no lo hacen. +.TP +.B \-M, --dhcp-boot=[tag:<tag>,]<filename>,[<servername>[,<server address>]] +Fijar opciones BOOTP que han de ser devueltas por el servidor DHCP. Nombre +y dirección de servidor son opcionales: si no son brindadas, el nombre es +dejado en blanco, y la dirección es fijada a la de la máquina que corre +dnsmasq. Si dnsmasq está brindando servicio TFTP (ver +.B --enable-tftp +) entonces solo el nombre de archivo es requirido aquí para habilitar +el inicio atravéz de una red. Si las opcionales etiquetas son brindadas, +ellas deberán coincidir para que esta configuración sea enviada. Nótese +que network-ids están prefijadas con "net:" para distinguirlas. +.TP +.B --pxe-service=[tag:<tag>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>] +La mayoría de usos para boot-ROMS PXE simplemente permiten al sistema PXE +obtener una dirección IP y entonces bajar el archivo especificado por +.B dhcp-boot +y ejecutarlo. Sin embargo, el sistema PXE es capaz de llevar +a cabo funciones más complejas cuando están soportadas por un +servidor DHCP adecuado. + +Esto especifica una opción boot que puede aparecer en un menú de boot +PXE. <CSA> es tipo de sistema de cliente, solo servicios del tipo correcto +aparecerán en un menú. Los tipos conocidos son x86PC, PC98, IA64_EFI, +Alpha, Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI y X86-64_EFI; +un número entero puede ser utilizado para otros tipos. El parámetro después +del texto de menú puede ser un nombre de archivo, caso en el cuál dnsmasq +actúa como un servidor boot y le ordena al cliente PXE bajar el archivo +vía TFTP, ya sea de sí mismo ( +.B enable-tftp +debe estar fijado para que esto funcione) o desde otro servidor TFTP si la +dirección IP final es brindada. +Nótese que el sufijo "layer" (normalmente ".0") es brindado por PXE, y +no debe ser agregado al nombre base. Si un número entero es brindado en vez +de un nombre base, entonces el cliente PXE buscará un servicio boot adecuado +para ese tipo de red. Esta búsqueda puede ser hecha mediante broadcast, +o directamente a un servidor si la dirección IP es brindada. Si ningún tipo +de servicio boot o nombre de archivo es brindado (o un tipo de servicio boot +de 0 es especificado), entonces la opción de menú abortará el proceso net boot +y continuará desde el medio local. +.TP +.B --pxe-prompt=[tag:<tag>,]<prompt>[,<timeout>] +Fijar esto hace que un aviso sea expuesto despues del boot PXE. Si el timeout +es brindado, entonces despues que el timeout se haya vencido sin input del +teclado, la primera opción del menú sera automaticamente ejecutada. Si el +timeout es cero entonces la primera opción del menú sera automaticamente +ejecutada. Si +.B pxe-prompt +es omitido, el sistema esperará para el input del usuario si hay múltiples +artículos en el menú, pero hará boot imediatamente si hay solo uno. Ver +.B pxe-service +para detalles sobre artículos de menu. + +Dnsmasq tiene soporte para "proxy-DHCP" PXE, en este caso otro servidor +DHCP en la red es responsable por asignar direcciones IP, y dnsmasq +simplemente provee la dirección brindada en +.B pxe-prompt +y +.B pxe-service +para permitir boot a travez de la red. Este modo es habilitado usando +la palabra clave +.B proxy +en +.B dhcp-range. +.TP +.B \-X, --dhcp-lease-max=<número> +Limita a dnsmasq a el número especificado de arriendos DHCP. El +predeterminado es 1000. El limite es para prevenir ataques DoS desde +hosts que crean cientos de arriendos y usan mucha de la memoria del +proceso dnsmasq. +.TP +.B \-K, --dhcp-authoritative +Esta opción debe ser fijada cuando dnsmasq es definitivamente el único +servidor DHCP en la red. Cambia el comportamiento de RFC de tal manera +que pedidos desde hosts no conocidos no serán ignorados. Esto permite que +hosts nuevos puedan conseguir un arriendo sin sin un timeout bajo toda +circunstancia. También permite que dnsmasq reconstruya su base de datos +de arriendos sin que cada cliente necesite readquirir un arriendo +si la base de datos es perdida. +.TP +.B --dhcp-alternate-port[=<puerto de servidor>[,<puerto de cliente>]] +Cambiar del predeterminado los puertos usados para DHCP. Si esta opción +es brindada sola, sin argumentos, cambia los puertos usados para DHCP +de 67 y 68 a 1067 y 1068. Si un solo argumento es brindado, ese puerto +es usado para el servidor y el número de puerto mas uno es usado +para el cliente. Finalmente, dos números permiten que se especifiquen +ambos los puertos de servidor y cliente para DHCP. +.TP +.B \-3, --bootp-dynamic[=<network-id>[,<network-id>]] +Habilitar alocación dinámica de direcciones IP a clientes BOOTP. Usar +esto con cuidado, ya que cada dirección alocada a un cliente BOOTP +es arrendada para siempre, y consecuentemente queda no-disponible +para re-uso por otros hosts. Si esto es brindado sin etiquetas, +entonces incondicionalmente habilita alocación dinámica. Con +etiquetas, solo cuando todas las etiquetas están fijadas. Puede +ser repetido con diferentes juegos de etiquetas. +.TP +.B \-5, --no-ping +Por predetermindado, el servidor DHCP tratará de asegurarse que una +dirección no esté en uso antes de alocarsela a un host. Hace esto +enviando un echo ICMP (ping) a la dirección referente. Si recibe una +respuesta, entonces la dirección debe estar siendo usada, y se repite +la prueba con otra. Esta opción deshabilita esta prueba. Usar con +cuidado. +.TP +.B --log-dhcp +Bitacoréo extra para DHCP: Bitacorear todas las opciones enviadas a +clientes DHCP y las etiquetas usadas para determinarlos. +.TP +.B \-l, --dhcp-leasefile=<path> +Usar el archivo especificado para almacenar información de arriendos +DHCP. +.TP +.B \-6 --dhcp-script=<path> +Cuando un arriendo DHCP nuevo es creado, o uno viejo es +destruido, el ejecutable especificado por esta opción es ejecutado. +<path> debe ser un pathname absoluto, ninguna búsqueda PATH ocurre. +Los argumentos para el binario son "add", "old", o "del", la dirección +MAC del host, la dirección IP, y el hostname, si es +conocido. "add" significa que un arriendo ha sido creado, "del" que +ha sido destruido, y "old" es una notificación de un arriendo existente +cuando dnsmasq inicia o un cambio a una MAC o nombre host de un arriendo +existente (también, tiempo de arriendo o vencimiento y client-id, si +leasefile-ro está fijado). Si la dirección MAC es de un tipo de red +que no es ethernet, tendrá el tipo de red precolocado, por ejemplo +"06-01:23:45:67:89:ab" para token ring. El proceso es ejecutado como root +(asumiendo que dnsmasq fue originalmente ejecutado como root) aún si dnsmasq +está configurado para cambiar su UID a un usuario sin privilegios. + + +El ambiente es heredado del usuario que ha invocado a dnsmasq, con algunas +o todas de las siguientes variables agregadas. + +DNSMASQ_CLIENT_ID si el host brindo un client-id. + +DNSMASQ_DOMAIN si el nombre de dominio completamente calificado del host +es conocido, esto es fijado a la parte del dominio. + +Si el cliente brinda vendor-class, hostname o user-class, estos son +brindados en las variables +DNSMASQ_VENDOR_CLASS, DNSMASQ_SUPPLIED_HOSTNAME, y +DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add" +y "old" cuando un host reanuda un arriendo existente, dado a que estos +datos no son almacenados en la base de datos de arriendos de dnsmasq. + +Si dnsmasq fue compilado con HAVE_BROKEN_RTC, entonces la duración del +arriendo (en segundos) es almacenada en DNSMASQ_LEASE_LENGTH, de otra +manera el tiempo de vencimiento es almacenado en DNSMASQ_LEASE_EXPIRES. +El número de segundos faltante para el vencimiento del arriendo siempre +es almacenado en DNSMASQ_TIME_REMAINING. + +Si un arriendo solía tener un nombre de host, el cual es removido, un +evento "old" es generado con el nuevo estado del arriendo, (por ejemplo, sin +nombre), y el nombre anterior es brindado en la variable de ambiente +DNSMASQ_OLD_HOSTNAME. + +DNSMASQ_INTERFACE almacena el nombre de la interface +en la cual llegó el pedido; esto no es fijado para acciones "viejas" +cuando dnsmasq re-inicia. + +DNSMASQ_RELAY_ADDRESS es fijado si el cliente +usó un relay DHCP para contactar a dnsmasq y la dirección IP del relay +es conocida. + +DNSMASQ_TAGS contiene todas las etiquetas network-id fijadas +durante la transacción DHCP, separadas por espacios. + +Todos los descriptores de archivo están cerrados +excepto stdin, stdout, y stderr los cuales están abiertos a /dev/null +(excepto en modo debug). + +Este guión no es invocado concurrentemente: máximo una instamcia del +guión está corriendo a la vez (dnsmasq espera a que una instancia de +guión haga exit antes de correr la siguiente). Cambios a la base de +datos de arriendos que requieren que el guión sea invocado son puestos +en cola esperando el exit de una instancia corriente. Si esta cola permite +que cambios multiples de estado le ocurran a un arriendo individual antes +de que el guión pueda ser ejecutado entonces estados anteriores son descartados +y el estado actual del arriendo es reflejado cuando el guión finalmente corre. + +Al inicio de dnsmasq, el guión +será invocado para todos los arriendos existentes mientras van siendo +leídos desde el archivo de arriendos. Arriendos vencidos serán llamados +con "del" y otros con "old". <path> debe ser un path absoluto, ninguna +búsqueda PATH ocurre cuando arriendos dnsmasq serán llamados con "del" +y otros con "old". Cuando dnsmasq recibe una señal HUP, el guión será +invocado para arriendos existentes con un evento "old". +.TP +.B --dhcp-scriptuser +Especificar el usuario como el cual se debe correr el archivo +guión de cambio de arriendos. Este es root por predeterminado, +pero puede ser cambiado a otro usuario mediante esta opción. +.TP +.B \-9, --leasefile-ro +Suprimir completamente el uso del archivo de arriendos. El archivo no será +creado, leído, ni escrito. Cambiar la manera en la cuál el archivo guión de +cambio de arriendo (si es brindado) es llamado, de tal forma que la base de +datos de arriendospueda ser mantenida en almacenaje externo por el archivo +guión. Adicionálmente a las invocaciones brindadas en +.B --dhcp-script +el archivo de cambio de arriendos es llamado una vez, al inicio de dnsmasq, +con el único argumento "init". Cuando invocado de esta forma, el guión debería +escribir el estado guardado de la base de datos de arriendos, en formato de +archivo de arriendos dnsmasq, a stdout y hacer exit con código exit cero. Fijar +esta opción también forza que el archivo de cambio de arriendos sea llamado +cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento. +.TP +.B --bridge-interface=<nombre de interface>,<alias>[,<alias>] +Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias> +como si hubieran llegado a la interface <nombre de interface>. Esta opción +es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que +los paquetes llegan a interfaces tap que no tienen una dirección IP. +.TP +.B \-s, --domain=<dominio>[,<rango de IPs>] +Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser +brindados incondicionalmente (sin el rango de IPs) o para rangos limitados. Esto +tiene dos efectos: Primeramente, causa que el servidor DHCP le devuelva el +dominio a cualquier host que lo pida. Segundamente, fija el dominio para el +cual es legal para hosts configurados mediante DHCP reclamar. La intención es +restringir nombres de host para que un host no-confiado en la LAN no +pueda proclamar su nombre vía DHCP, como por ejemplo "microsoft.com" y +capturar tráfico no destinado a ella. Si ningún sufijo de dominio es +especificado, entonces cualquier nombre de host con una parte de dominio +(o sea con un punto) será negada y bitacorada. Si un sufijo es especificado, +entonces nombres de host con una parte de dominio son permitidos, con tal +que la parte de dominio coincida con el sufijo. Adicionalmente, cuando +un sufijo es fijado, entonces nombres de host sin parte de dominio tienen +el sufijo agregado como una parte de dominio opcional. Por ejemplo, en +mi red puedo fijar +.B --domain=thekelleys.org.uk +y tener una maquina cuyo nombre host DHCP es "laptop". La dirección IP +de esa máquina es disponible desde +.B dnsmasq +como "laptop" y "laptop.thekelleys.org.uk". Si el dominio es brindado +como "#" entonces el dominio es leido desde la primera directiva search +en /etc/resolv.conf (o equivalente). El rango de direcciones puede ser +<dirección IP>,<dirección IP> or <dirección IP>/<máscara de subred>. Ver +.B --dhcp-fqdn el cual puede cambiar el comportamiento de dnsmasq con +dominios. +.TP +.B --dhcp-fqdn +En el modo predeterminado, dnsmasq pone los nombres no-calificados +de clientes DHCP en el DNS. Por esta razón, los nombres deben ser únicos, +aún si dos clientes que tienen el mismo nombre están en dominios +diferentes. Si un segundo cliente DHCP aparece el cual tiene el mismo +nombre que un cliente existente, el nombre es transferido al cliente nuevo. Si +.B --dhcp-fqdn +está fijado, este comportamiento cambia: El nombre no-calificado +no es puesto en el DNS, solo el nombre calificado. Dos clientes DHCP con +el mismo nombre pueden ambos quedarse con el nombre, con tal que la parte +de dominio sea diferente (o sea que los nombres completamente calificados +difieran). Para asegurar que todos los nombres tengan una parte de dominio, +debe haber al menos +.B --domain +sin una dirección especificada cuando +.B --dhcp-fqdn +está fijado. +.TP +.B --enable-tftp[=<interface>] +Habilitar la función de servidor TFTP. Esto está deliberadamente limitado +a lo necesario para hacerle a un cliente un inicio vía red. Solo lectura es +permitida; las extensiones tsize y blksize son soportadas (tsize solo es +soportada en modo octeto). Ver sección de NOTAS para el uso de el argumento +de interface. +.TP +.B --tftp-root=<directory>[,<interface>] +Buscar, relativo al directorio brindado, archivos para transferir mediante el +uso de TFTP. Cuando esta opción está fijada, paths TFTP que incluyen ".." son +rechazados, para prevenir que clientes salgan de la raíz especificada. Paths +absolutos (los que comienzan con "/") están permitidos, pero deben estar +dentro del tftp-root. Si el argumento opcional de interface es brindado, el +directorio es solo usado para pedidos TFTP vía esa interface. +.TP +.B --tftp-unique-root +Agregar la dirección IP del cliente TFTP como un componente path del lado del +TFTP-root (en formato estándar de cuatro puntos). Solo válido si un tftp-root +está fijado y el directorio existe. Por ejemplo, si tftp-root es "/tftp" y el +cliente 1.2.3.4 pide el archivo "miarchivo" entonces el path efectivo será +"/tftp/1.2.3.4/miarchivo" si /tftp/1.2.3.4 existe o /tftp/miarchivo si no. +.TP +.B --tftp-secure +Habilitar modo TFTP seguro: sin esto, cualquier archivo que es leíble por el +proceso dnsmasq bajo reglas normales de control de acceso UNIX, está disponible +vía TFTP. Cuando la opción --tftp-secure es fijada, solo archivos +pertenecientes al usuario que corre el proceso dnsmasq están accesibles. Si +dnsmasq está corriendo como root, reglas diferentes aplican: --tftp-secure no +tiene ningún efecto, pero solo archivos que tienen el bit de lectura global +fijados están accesibles. No se recomienda correr dnsmasq como root con TFTP +habilitado, y mucho menos sin especificar --tftp-root, ya que se puede exponer +cualquier archivo de lectura global en el servidor a cualquier host de la red. +.TP +.B --tftp-max=<conecciones> +Fijar el número máximo permitido de conecciones TFTP simultáneas. Esto es 50 +por predeterminado. Al servir un número grande de conecciones TFTP, límites +de descriptor de archivo por proceso pueden ser encontrados. Dnsmasq necesita +un descriptor de archivo por cada coneccion TFTP concurrente, y por archivo +único (mas algunos otros). De tal manera que servirle el mismo archivo +simultáneo a n clientes requerirá el uso de n + 10 descriptores de archivo, +y servirles archivos diferentes simultáneamente requerirá (2*n) + 10 +descriptores. Si +.B --tftp-port-range +es brindado, eso puede afectar el número de conexiones simultáneas. +.TP +.B --tftp-no-blocksize +No permitir que el servidor negocie la opción "blocksize" con un cliente. +Algunos clientes con errores piden esta opción pero se portán mal cuando se +les brinda. +.TP +.B --tftp-port-range=<inicio>,<final> +Un servidor TFTP escucha por inicios de conexión en un puerto bien conocido +(69), pero tambien usa un puerto dinamicamente seleccionado para cada +conexión. Normalmente estos son seleccionados por el sistema operativo, +pero esta opción especifica un rango de puertos para ser usado por transferencias +TFTP. Esto puede ser útil cuando TFTP tiene que pasar atraves de un firewall. +El comienzo del rango no puede ser menor a 1025 a menos que dnsmasq esté corriendo +como root. El número de conexiones simultáneas está limitado por el tamaño del +rango de puertos. +.TP +.B \-C, --conf-file=<archivo> +Especificar un archivo de configuración diferente. La opción conf-file +también es permitida en archivos de configuración, para incluir múltiples +archivos de configuración. +.TP +.B \-7, --conf-dir=<directorio>[,<file-extension>......] +Leer todos los archivos dentro del directorio brindado como archivos +de configuración. Si extensiones son brindadas, cualquier archivo que +termine en esas extensiones son ignorados. Cualquier archivos cuyos nombres +terminen con ~ o comienzen con . o comienzen y terminen con # siempre son +ignorados. Esta opción puede ser brindada en la línea de comandos o en un +archivo de configuración. +.SH ARCHIVO DE CONFIGURACION +Al inicio, dnsmasq lee +.I /etc/dnsmasq.conf, +si existe. (En FreeBSD, el archivo es +.I /usr/local/etc/dnsmasq.conf +) (pero ver las opciónes +.B \-C +y +.B \-7 +porfavor.) El formato de este archivo consiste de una opción por línea, +exáctamente como las opciones largas detalladas en la sección OPCIONES +pero sin el "--" al frente. Líneas que comienzan con # son comentarios +y son ignoradas. Para opciones que solo pueden ser especificadas una +sola vez, el archivo de configuración invalida la línea de comandos. +Las comillas son permitidas en el archivo de configuración: entre comillas +tipo " los significados especiales de ,:. y # son eliminados y los +siguientes escapes son permitidos: \\\\ \\" \\t \\e \\b \\r y \\n. +Corresponden a tab, escape, backspace, return y newline. +.SH NOTAS +Al recibir un SIGHUP +.B dnsmasq +libera su cache y entonces recarga +.I /etc/hosts +y +.I /etc/ethers +al igual que cualquier archivo brindado con --dhcp-hostsfile, --dhcp-optsfile, +o --addn-hosts. +El archivo guión de cambio de arriendos es llamado para todos los arriendos +DHCP existentes. Si +.B +--no-poll +está fijado entonces SIGHUP también re-lee +.I /etc/resolv.conf. +SIGHUP +NO re-lee el archivo de configuración. +.PP +Al recibir un SIGUSR1, +.B dnsmasq +escribe estadísticas a la bitácora del sistema. Escribe el tamaño +del caché, el numero de nombres que han tenido que ser removidos del +caché antes de que vencieran para hacer espacio para nombres nuevos, y el +número total de nombres que han sido insertados en el caché. Para cada +servidor upstream brinda el número de búsquedas enviadas, y el +número que resultaron en error. En modo +.B --no-daemon +o cuando bitacoréo completo está habilitado (-q), una descarga completa de +el contenido del caché es hecha. +.PP +Cuando recibe un SIGUSR2 y está bitacoreando diréctamente a un archivo (ver +.B --log-facility +) +.B dnsmasq +cerrará y reabrirá el archivo de bitácora. Nótese que durante esta +operación, dnsmasq no estará corriendo como root. Al crear el archivo de +bitácora, dnsmasq cambia el dueño del archivo a el usuario normal como +el que correrá. Logrotate debe ser configurado para crear un archivo de +bitácora nuevo con permisos iguales al existente, antes de enviar +SIGUSR2. Si búsquedas DNS TCP están en progreso, el archivo de bitácora +viejo se mantendrá abierto en procesos hijos que están manejando +búsquedas TCP, y puede continuarse a escribirle. Hay un límite de 150 +segundos, después de lo cual todos los procesos TCP existentes se habrán +vencido: por esta razón, no es sabio configurar compresión de archivos +de bitácora para archivos que acaban de ser rotados. Con logrotate, las +opciones requeridas son +.B create +y +.B delaycompress. +.PP +Dnsmasq es un reenviador de búsquedas DNS: no puede responder búsquedas +arbitrarias comenzando desde los servidores root pero reenvía dichas +búsquedas a un servidor DNS recursivo, el cual es típicamente proveído +por el proveedor de Internet. Por predeterminado, dnsmasq lee +.I /etc/resolv.conf +para descubir las direcciones IP de los servidores DNS upstream que +debe usar, dado a que esta información es normalmente almacenada allí. +Amenos que +.B --no-poll +sea usado, +.B dnsmasq +revisa el tiempo de modificación de +.I /etc/resolv.conf +(o equivalente si +.B \--resolv-file +es usado) y lo re-lee si ha cambiado. Esto permite que servidores DNS séan +fijados dinámicamente vía PPP o DHCP ya que ambos protocolos brindan esta +información. +La ausencia de +.I /etc/resolv.conf +no es un error ya que pudo haber sido creada antes de que una conexión PPP +haya existido. Dnsmasq simplemente sigue revisando en caso de que +.I /etc/resolv.conf +sea creado en algún momento. A dnsmasq se le puede decir que revise más +de un archivo resolv.conf. Esto es útil en una laptop, donde ambos PPP y +DHCP podrían estar siendo usados: dnsmasq puede ser fijado para revisar ambos +.I /etc/ppp/resolv.conf +y +.I /etc/dhcpc/resolv.conf +y usará el contenido del que haya cambiado mas recientemente, +brindando así la habilidad de cambio automático entre servidores DNS. +.PP +Servidores upstream también pueden ser especificados en la línea de +comandos o en el archivo de configuración. Estas especificaciones de +servidor opcionalmente llevan un nombre de dominio el cual le dice a +dnsmasq que debe usar ese servidor solo para encontrar nombres en ese +dominio en particular. +.PP +Para configurar dnsmasq como caché para el host donde está +corriendo, poner un "nameserver 127.0.0.1" en +.I /etc/resolv.conf +para así forzar procesos locales a enviar búsquedas a dnsmasq. Entonces, +o especificar los servidores upstream diréctamente a dnsmasq usando opciones +.B \--server +o poniendo sus direcciones reales en otro archivo, digamos +.I /etc/resolv.dnsmasq +y correr dnsmasq con la opcion +.B \-r /etc/resolv.dnsmasq +Esta segunda técnica permite la actualización dinámica de las direcciones +de servidor mediante PPP o DHCP. +.PP +Direcciones en /etc/hosts "harán sombra" a diferentes direcciones para +los mismos nombres en servidores DNS upstream, así que +"miempresa.com 1.2.3.4" en /etc/hosts se asegurará que las búsquedas +por "miempresa.com" siempre retornarán 1.2.3.4 aún si búsquedas en el +servidor DNS upstream devolverían una dirección diferente. Hay una +excepción a esto: si el servidor DNS upstream contiene un CNAME que +apunta a un nombre sombreado, entonces buscando el CNAME a travéz de +dnsmasq resultará en que la dirección no-sombreada será asociada con +el destino del CNAME. Para circumventar esto, agregar el CNAME a +/etc/hosts de tal manera que el CNAME es sombreado también. + +.PP +El sistema de etiquetas funciona de la siguiente manera: Para cada pedido +DHCP, dnsmasq colecciona un juego de etiquetas válidas de líneas de +configuración activas que incluyen set:<tag>, incluyendo una del +.B dhcp-range +usado para alocar la dirección, una de cualquier +.B dhcp-host +que coincida (y "known" si un dhcp-host coincide). +La etiqueta "bootp" es fijada para pedidos BOOTP, y una etiqueta cuyo +nombre es el nombre de la interface donde llegó el pedido tambien es +fijada. + +Cualquier linea de configuración que incluya uno o mas +construcciones tag:<tag> solo será válida si todas las etiquetas +coinciden en el juego derivado arriba. Típicamente esto es dhcp-option. +.B dhcp-option +que tenga etiquetas será usada en preferencia de una opción +.B dhcp-option, +sin etiqueta, con tal que _todas_ las etiquetas coincidan en alguna +parte del juego coleccionado describido arriba. El prefijo '!' en una +etiqueta significa "no" así que --dhcp=option=tag:!purple,3,1.2.3.4 envía +la opción cuando la etiqueta "purple" no está en el juego +de etiquetas válidas. (Si se está usando esto en una línea de comandos +en vez de un archivo de configuración, asegurese de escapar !, el cual +es un metacaracter de shell.) +.PP +Nótese que para +.B dhcp-range +ambos tag:<tag> y set:<tag> son permitidos, para seleccionar el rango +en uso basado en (por ejemplo) dhcp-host, y para afectar las opciones +enviadas, basadas en el rango seleccionado. + +Este sistema evolucionó de uno anterior mas limitado y para compatibildad +reversa "net:" puede ser usada en vez de "tag:" y "set:" puede ser +omitida. (Excepto en +.B dhcp-host, +donde "net:" puede ser usado en vez de "set:".) Por la misma razón, '#' +puede ser usado en vez de '!' para indicar NO. +.PP +El servidor DHCP de dnsmasq funcionará como servidor BOOTP tambien, +con tal que las direcciones MAC y IP de los clientes sean brindadas, +ya sea usando configuraciones +.B dhcp-host +o en +.I /etc/ethers +, y una configuración +.B dhcp-range +esté presente para activar el servidor DHCP en una red particular. +(Fijar --bootp-dynamic elimina la necesidad de trazados estáticos.) El +parámetro de nombre de archivos en un pedido BOOTP es usado como +una etiqueta, al igual que la etiqueta "bootp", permitiendo así algún +control sobre las opciones devueltas a diferentes clases de hosts. + +.B dhcp-range +puede tener un nombre de interface brindado como +"interface:<interface-name>". La semántica de esto es así: +Para DHCP, si cualquier otro dhcp-range existe _sin_ un nombre de +interface, entonces el nombre de interface es ignorado y dnsmasq +se comporta como si las partes de interface no existieran, de otra forma +DHCP solo se provee a interfaces mencionadas en declaraciones +dhcp-range. Para DNS, si no hay opciones +.B --interface +o +.B --listen-address +el comportamiento no se modifica por la parte de interface. Si cualquiera +de estas opciones está presente, las interfaces mencionadas en dhcp-ranges +son agregadas all juego que obtienen servicio DNS. + +Similarmente, +.B enable-tftp +puede tomar un nombre de interface, el cual habilita TFTP solo para una +interface en particular, ignorando opciones +.B --interface +o +.B --listen-address. +Adicionalmente, +.B --tftp-secure +y +.B --tftp-unique-root +y +.B --tftp-no-blocksize +son ignorados por pedidos desde dichas interfaces. (Una directiva +.B --tftp-root +brindando un path raíz y una interface debe ser brindada tambien.) + +Estas reglas pueden parecer raras a primera vista, pero permiten que +una simple linea de la forma +"dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" sea agregada a +configuración dnsmasq, lo cual brinda servicios DHCP y DNS a esa interface, +sin afectar los servicios en otras interfaces y irrespectivamente de +la existencia o no de lineas "interface=<interface>" en alguna otra parte +de la configuración dnsmasq. +"enable-tftp=virt0" y "tftp-root=<root>,virt0" hacen el mismo trabajo +para TFTP. +La idea es que una linea así pueda ser agregada automaticamente +por libvirt o sistemas equivalentes, sin estorbar alguna +configuración manual. + +.SH CÓDIGOS EXIT +.PP +0 - Dnsmasq hizo fork hacia el fondo exitosamente, o terminó de manera +normal si ir al fondo no está habilitado. +.PP +1 - Un problema con la configuración ha sido detectado. +.PP +2 - Un problema con acceso a redes ocurrió (dirección en uso, intento +de usar puertos privilegiados sin permiso). +.PP +3 - Un problema con una operación de sistema de archivos ocurrió (archivo +o directorio ausente, permisos). +.PP +4 - Falla de alocación de memoria. +.PP +5 - Otro problema misceláneo. +.PP +11 o mayor - un codigo de retorno no cero fué recibido del llamado "init" +del proceso de archivo guión de arriendos. El código exit de dnsmasq es +el código exit del archivo guión con 10 sumado. + +.SH LIMITES +Los valores predeterminados para limites de recursos son generálmente +conservadores, y apropiados para uso en dispositivos tipo enrutador +encrustrado con procesadores lentos y poca memoria. En hardware más +capáz, es posible incrementar los límites, y soportar muchos mas +clientes. Lo siguiente se aplica a dnsmasq-2.37: versiones previas +no escalaban tan bien. + +.PP +Dnsmasq es capaz de soportar con DNS y DHCP a por lo menos mil (1,000) +clientes. Los tiempos de arriendo no deben ser muy cortos (menos +de una hora). El valor de +.B --dns-forward-max +puede ser aumentado: comienze con el equivalente a el número de clientes y +auméntelo si parece lento el DNS. Nótese que el rendimiento DNS depende +también de los servidores DNS upstream. El tamaño del caché DNS puede ser +incrementado: el límite obligatorio es 10,000 nombres y el predeterminado +(150) es muy bajo. El enviarle un SIGUSR1 a dnsmasq hace que bitacorée +información que es útil para afinar el tamaño de caché. Ver la sección +.B NOTAS +para detalles. + +.PP +El servidor TFTP incorporado es capáz de soportar varias transferencias +simultáneas de archivos: el límite absoluto está relacionado con el número +de file-handles permitidos a un proceso y la habilidad del system call +select() a soportar números grandes de file-handles. Si el límite es fijado +demasiado alto con +.B --tftp-max +será de-escalado y el límite real será bitacoreado al inicio. Nótese que más +transferencias son posibles cuando el mismo archivo es enviado qué cuando +cada transferencia envía un archivo diferente. + +.PP +Es posible usar dnsmasq para negar publicidad Web usando una lista de +servidores de banners bien conocidos, todos resolviendose a 127.0.0.1 o +0.0.0.0 en +.B /etc/hosts +o en un archivo hosts adicional. La lista puede ser muy larga. Dnsmasq ha sido +probado exitósamente con un millón de nombres. Ese tamaño de archivo necesita +un CPU de 1GHz y aproximadamente 60MB de RAM. + +.SH INTERNACIONALIZACION + +Dnsmasq puede ser compilado con soporte para internacionalización. Para hacer esto, +los targets make "all-i18n" y "install-i18n" deberán ser usados en vez de +los targets estándares "all" y "install". Cuando internacionalización es +compilada, dnsmasq producirá mensajes de bitácora en el lenguaje local y soportará +dominios internacionalizados (IDN). Nombres de dominio en /etc/hosts, /etc/ethers, +y /etc/dnsmasq.conf que contienen carácteres no-ASCII serán traducidos a +representación interna DNS punycode. Nótese que dnsmasq determina ambos el +lenguaje para mensajes y el juego de carácteres asumido para archivos de configuración +de la variable ambiental LANG. Esto debe estar fijado al valor predeterminado del sistema +por el guión responsable de iniciar dnsmasq. Al editar archivos de configuración, +tener cuidado de hacerlo usando solo el locale predeterminado del sistema y no +uno especifico del usuario, dado a que dnsmasq no tiene ninguna manera directa de +determinar el juego de caracteres en uso, y debe asumir que es el predeterminado +del sistema. + +.SH ARCHIVOS +.IR /etc/dnsmasq.conf + +.IR /usr/local/etc/dnsmasq.conf + +.IR /etc/resolv.conf + +.IR /etc/hosts + +.IR /etc/ethers + +.IR /var/lib/misc/dnsmasq.leases + +.IR /var/db/dnsmasq.leases + +.IR /var/run/dnsmasq.pid +.SH VER TAMBIEN +.BR hosts (5), +.BR resolver (5) +.SH AUTOR +Este manual fue escrito por Simon Kelley <simon@thekelleys.org.uk>. + +Traducido a español por Christopher Chatham <chrislinux@gmail.com>. diff --git a/man/fr/dnsmasq.8 b/man/fr/dnsmasq.8 new file mode 100644 index 0000000..44c301b --- /dev/null +++ b/man/fr/dnsmasq.8 @@ -0,0 +1,1695 @@ +.TH DNSMASQ 8 +.SH NAME +Dnsmasq \- Un serveur DHCP et cache DNS poids-plume. +.SH SYNOPSIS +.B dnsmasq +.I [OPTION]... +.SH "DESCRIPTION" +.BR dnsmasq +est un serveur DHCP et DNS à faible empreinte mémoire. Il offre à la fois les +services DNS et DHCP pour un réseau local (LAN). +.PP +Dnsmasq accepte les requêtes DNS et y réponds soit en utilisant un petit cache +local, soit en effectuant une requête à un serveur DNS récursif externe (par +exemple celui de votre fournisseur d'accès internet). Il charge le contenu du +fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS +globaux soient tout de même résolus, et assure également la résolution de nom +pour les hôtes présents dans le service DHCP. +.PP +Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques et les +réseaux multiples. Il envoie par défaut un jeu raisonnable de paramètres DHCP, et +peut être configuré pour envoyer n'importe quel option DHCP. +Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via +le réseau/PXE de clients DHCP et supporte également le protocole BOOTP. +.PP +Dnsmasq supporte IPv6 pour le DNS et TFTP mais pas pour le DHCP. +.SH OPTIONS +Notes : Il est possible d'utiliser des options sans leur donner de paramètre. +Dans ce cas, la fonction correspondante sera désactivée. Par exemple +.B --pid-file= +(sans paramètre après le =) désactive l'écriture du fichier PID. +Sur BSD, à moins que le logiciel ne soit compilé avec la bibliothèque GNU +getopt, la forme longue des options ne fonctionne pas en ligne de commande; Elle +est toujours supportée dans le fichier de configuration. +.TP +.B --test +Vérifie la syntaxe du ou des fichiers de configurations. Se termine avec le +code de retour 0 si tout est OK, ou un code différent de 0 dans le cas +contraire. Ne démarre pas Dnsmasq. +.TP +.B \-h, --no-hosts +Ne pas charger les noms du fichier /etc/hosts. +.TP +.B \-H, --addn-hosts=<fichier> +Fichiers d'hôtes additionnels. Lire le fichier spécifié en plus de /etc/hosts. +Si +.B -h +est spécifié, lire uniquement le fichier spécifié. Cette option peut être +répétée afin d'ajouter d'autres fichiers. Si un répertoire est donné, lis les +fichiers contenus dans ce répertoire. +.TP +.B \-E, --expand-hosts +Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le +nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service +DHCP. Notez que cela ne s'applique pas au nom de domaine dans les CNAME, les +enregistrements PTR, TXT, etc... +.TP +.B \-T, --local-ttl=<durée> +Lorsque Dnsmasq répond avec une information provenant du fichier /etc/hosts ou +avec un bail DHCP, il donne un temps de vie (time-to-live) positionné à zéro, +afin d'indiquer à la machine faisant la requête que celle-ci ne doit pas être +mise dans un cache. Ceci est le comportement correct dans presque toutes les +situations. +Cette option permet de spécifier la valeur de time-to-live à retourner (en +secondes). Cela permet de réduire la charge sur le serveur, mais les clients +risquent d'utiliser des données périmées dans certains cas. +.TP +.B --neg-ttl=<durée> +Les réponses négatives provenant des serveurs amonts contiennent normalement +une information de durée de vie (time-to-live) dans les enregistrements SOA, +information dont dnsmasq se sert pour mettre la réponse en cache. Si la réponse +du serveur amont omet cette information, dnsmasq ne cache pas la réponse. Cette +option permet de doner une valeur de durée de vie par défaut (en secondes) que +dnsmasq utilise pour mettre les réponses négatives dans son cache, même en +l'absence d'enregistrement SOA. +.TP +.B --max-ttl=<durée> +Définie la valeur de TTL maximum qui sera fournie aux clients. La valeur maximum +de TTL spécifiée sera fournie aux clients en remplacement de la vraie valeur de TTL +si cette dernière est supérieure. La valeur réelle de TTL est cependant conservée dans +le cache afin d'éviter de saturer les serveurs DNS en amont. +.TP +.B \-k, --keep-in-foreground +Ne pas aller en tâche de fond au lancement, mais en dehors de cela, fonctionner +normalement. Ce mode est prévu pour les cas où Dnsmasq est lancé par daemontools +ou launchd. +.TP +.B \-d, --no-daemon +Mode debug (déverminage) : ne pas aller en tâche de fond, ne pas écrire de +fichier pid, ne pas changer d'identifiant utilisateur, générer un état complet +du cache lors de la réception d'un signal SIGUSR1, envoyer les logs sur la +sortie standard d'erreur ("stderr") de même que dans le syslog, ne pas créer de +processus fils pour traiter les requêtes TCP. +.TP +.B \-q, --log-queries +Enregistrer les résultats des requêtes DNS traitées par Dnsmasq dans un fichier +de traces ("logs"). Active la génération d'un état complet du cache lors de la +réception d'un signal SIGUSR1. +.TP +.B \-8, --log-facility=<facility> +Définit la "facility" dans laquelle Dnsmasq enverra ses entrées syslog, par +défaut DAEMON ou LOCAL0 si le mode debug est activé. Si la "facility" contient +au moins un caractère "/", alors Dnsmasq considère qu'il s'agit d'un fichier et +enverra les logs dans le fichier correspondant à la place du syslog. Si la +"facility" est '-', alors dnsmasq envoie les logs sur la sortie d'erreur +standard stderr. (Les erreurs lors de la lecture de la configuration vont +toujours vers le syslog, mais tous les messages postérieurs à un démarrage +réussi seront exclusivement envoyés vers le fichier de logs). +Lorsque Dnsmasq est configuré pour envoyer +ses traces vers un fichier, la réception d'un signal SIGUSR2 entraine la +fermeture et réouverture du fichier. Cela permet la rotation de fichiers de +traces sans nécessiter l'arrêt de Dnsmasq. +.TP +.B --log-async[=<lignes>] +Permet l'envoi de traces de manière asynchrone, et de manière optionnelle, le +nombre de lignes devant être mises dans la file d'attente par Dnsmasq lorsque +l'écriture vers le syslog est lente. +Dnsmasq peut envoyer ses logs de manière asynchrone : cela lui permet de +continuer à fonctionner sans être bloqué par le syslog, et permet à syslog +d'utiliser Dnsmasq pour les résolutions DNS sans risque d'interblocage. +Si la file d'attente devient pleine, Dnsmasq loggera le dépassement de file et +le nombre de messages perdus. La longueur par défaut de la file d'attente est de +5 et une valeur saine sera comprise entre 5 et 25, avec une limite maximum +imposée de 100. +.TP +.B \-x, --pid-file=<chemin> +Spécifie un fichier dans lequel stocker le numéro de processus (pid). La valeur +par défaut est /var/run/dnsmasq.pid. +.TP +.B \-u, --user=<nom d'utilisateur> +Spécifie l'identité (nom d'utilisateur) prise par Dnsmasq après le démarrage. +Dnsmasq doit normalement être démarré en temps que root ("super-utilisateur"), +mais abandonne ses privilèges après le démarrage en changeant d'identité. +Normalement cet utilisateur est l'utilisateur nobody ("personne"), mais il est +possible d'en définir un autre par le biais de ce paramètre. +.TP +.B \-g, --group=<nom de groupe> +Spécifie le groupe sous lequel Dnsmasq s'exécute. Par défaut, il s'agit du +groupe "dip", afin de faciliter l'accès au fichier /etc/ppp/resolv.conf qui +n'est en général pas en lecture par tout le monde. +.TP +.B \-v, --version +Imprime le numéro de version. +.TP +.B \-p, --port=<port> +Ecoute sur le port numéro <port> au lieu du port DNS standard (53). Paramétrer +cette valeur à zéro désactive complètement la fonction DNS pour ne laisser actif +que le DHCP ou le TFTP. +.TP +.B \-P, --edns-packet-max=<taille> +Spécifie la taille maximum de paquet UDP EDNS.0 supporté par le relai DNS. Le +défaut est de 4096, qui est la valeur recommandée dans la RFC5625. +.TP +.B \-Q, --query-port=<numéro de port> +Envoie et écoute les requêtes DNS sortantes depuis le port UDP spécifié par +<numéro de port>, et non sur un port aléatoire. NOTE : Cette option rends +dnsmasq moins sûr contre les attaques par usurpation DNS ("DNS spoofing"), mais +cela peut permettre d'utiliser moins de ressources et d'être plus rapide. Donner +une valeur de zéro à cette option restaure le comportement par défaut présent dans +les versions de dnsmasq inférieures à 2.43 qui consiste à n'allouer qu'un seul port +alloué par le système d'exploitation. +.TP +.B --min-port=<port> +Ne pas utiliser de port dont le numéro est inférieur à la valeur donnée en paramètre +pour les requêtes DNS sortantes. Dnsmasq choisis un port source aléatoire pour les +requêtes sortantes : lorsque cette option est fournie, les ports utilisés seront toujours +au dessus de la valeur spécifiée. Utile pour des systèmes derrière des dispositifs +garde-barrières ("firewalls"). +.TP +.B \-i, --interface=<nom d'interface> +N'écouter que sur l'interface réseau spécifiée. Dnsmasq aujoute automatiquement +l'interface locale ("loopback") à la liste des interfaces lorsque l'option +.B --interface +est utilisée. +Si aucune option +.B --interface +ou +.B --listen-address +n'est donnée, Dnsmasq écoutera sur toutes les interfaces disponibles sauf +celle(s) spécifiée(s) par l'option +.B --except-interface. +Les alias d'interfaces IP (e-g "eth1:0") ne peuvent être utilisés ni avec +.B --interface +ni +.B \--except-interface. +Utiliser l'option +.B --listen-address +à la place. +.TP +.B \-I, --except-interface=<interface name> +Ne pas écouter sur l'interface spécifiée. Notez que l'ordre dans lesquelles les +options +.B \--listen-address +, +.B --interface +et +.B --except-interface +sont fournies n'importe pas, et que l'option +.B --except-interface +l'emporte toujours sur les autres. +.TP +.B \-2, --no-dhcp-interface=<nom d'interface> +Ne pas fournir de service DHCP sur l'interface spécifiée, mais fournir tout de +même le service DNS. +.TP +.B \-a, --listen-address=<adresse IP> +Ecouter sur la ou les adresse(s) IP spécifiée(s). Les options +.B \--interface +et +.B \--listen-address +peuvent-être spécifiées simultanément, auquel cas un jeu d'interfaces et +d'adresses seront utilisées. Notez que si +aucune option +.B \--interface +n'est donnée alors qu'une option +.B \--listen-address +l'est, Dnsmasq n'écoutera pas automatiquement sur l'interface locale +("loopback"). Pour activer l'écoute sur l'interface locale, il est alors +nécessaire de fournir explicitement son adresse IP, 127.0.0.1 via l'option +.B \--listen-address. +.TP +.B \-z, --bind-interfaces +Sur les systèmes qui le supporte, Dnsmasq s'associe avec l'interface joker +("wildcard"), même lorsqu'il ne doit écouter que sur certaines interfaces. Par +la suite, il rejette les requêtes auxquelles il ne doit pas répondre. Cette +situation présente l'avantage de fonctionner même lorsque les interfaces vont +et viennent ou changent d'adresses. L'option +.B --bind-interfaces +force Dnsmasq à ne réellement s'associer qu'avec les interfaces sur lesquelles +il doit écouter. L'un des seuls cas où cette option est utile est celui où un +autre serveur de nom (ou une autre instance de Dnsmasq) tourne sur la même +machine. Utiliser cette option permet également d'avoir plusieurs instances de +Dnsmasq fournissant un service DHCP sur la même machine. +.TP +.B \-y, --localise-queries +Retourne des réponses aux requêtes DNS dépendantes de l'interface sur laquelle +la requête a été reçue, à partir du fichier /etc/hosts. Si un nom dans +/etc/hosts a plus d'une adresse associée avec lui, et qu'une des adresses au +moins est dans le même sous-réseau que l'interface sur laquelle la requête a été +reçue, alors ne retourne que la(les) adresse(s) du sous-réseau considéré. Cela +permet d'avoir dans /etc/hosts un serveur avec de multiples adresses, une pour +chacune de ses interfaces, et de fournir aux hôtes l'adresse correcte (basée sur +le réseau auquel ils sont attachés). Cette possibilité est actuellement limitée +à IPv4. +.TP +.B \-b, --bogus-priv +Fausse résolution inverse pour les réseaux privés. Toutes les requêtes DNS +inverses pour des adresses IP privées (ie 192.168.x.x, etc...) qui ne sont pas +trouvées dans /etc/hosts ou dans le fichier de baux DHCP se voient retournées +une réponse "pas de tel domaine" ("no such domain") au lieu d'être transmises +aux serveurs de nom amont ("upstream server"). +.TP +.B \-V, --alias=[<ancienne IP>]|[<IP de début>-<IP de fin>],<nouvelle IP>[,<masque>] +Modifie les adresses IPv4 retournées par les serveurs de nom amont; +<ancienne IP> est remplacée par <nouvelle IP>. Si le <masque> optionnel est +fourni, alors toute adresse correspondant à l'adresse <ancienne IP>/<masque> +sera réécrite. Ainsi par exemple +.B --alias=1.2.3.0,6.7.8.0,255.255.255.0 +modifiera 1.2.3.56 en 6.7.8.56 et 1.2.3.67 en 6.7.8.67. +Cette fonctionnalité correspond à ce que les routeurs Cisco PIX appellent +"bidouillage DNS" ("DNS doctoring"). Si l'ancienne IP est donnée sous la forme +d'une gamme d'adresses, alors seules les adresses dans cette gamme seront +réecrites, et non le sous-réseau dans son ensemble. Ainsi, +.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0 +fait correspondre 192.168.0.10->192.168.0.40 à 10.0.0.10->10.0.0.40 +.TP +.B \-B, --bogus-nxdomain=<adresse IP> +Transforme les réponses contenant l'adresse IP fournie en réponses "pas de tel +domaine" ("no such domain"). Ceci a pour but de neutraliser la modification +sournoise mise en place par Verisign en septembre 2003, lorsqu'ils ont commencé +à retourner l'adresse d'un serveur web publicitaire en réponse aux requêtes pour +les noms de domaines non enregistrés, au lieu de la réponse correcte "NXDOMAIN". +Cette option demande à Dnsmasq de retourner la réponse correcte lorsqu'il +constate ce comportement. L'adresse retournée par Verisign en septembre 2003 +est 64.94.110.11. +.TP +.B \-f, --filterwin2k +Les dernières versions de windows font des requêtes DNS périodiques auxquelles +non seulement les serveurs DNS publics ne peuvent donner de réponse, mais qui, +de surcroît, peuvent poser des problèmes en déclenchant des connexions +intempestives pour des liens réseaux avec des connexions "à la demande". Fournir +cette option active le filtrage des requêtes de ce type. Les requêtes bloquées +sont les requêtes pour les entrées de type SOA ou SRV, ainsi que les requêtes de +type ANY avec des noms possédant des caractères sous-lignés (requêtes pour des +serveurs LDAP). +.TP +.B \-r, --resolv-file=<fichier> +Lis les adresses des serveurs de nom amont dans le fichier de nom <fichier>, +au lieu du fichier /etc/resolv.conf. Pour le format de ce fichier, voir dans le +manuel pour +.BR resolv.conf (5) +les entrées correspondant aux serveurs de noms (nameserver). Dnsmasq peut lire +plusieurs fichiers de type resolv.conf, le premier fichier spécifié remplace le +fichier par défaut, le contenu des suivants est rajouté dans la liste des +fichiers à consulter. Seul le fichier ayant la dernière date de modification +sera chargé en mémoire. +.TP +.B \-R, --no-resolv +Ne pas lire le contenu du fichier /etc/resolv.conf. N'obtenir l'adresse des +serveurs de nom amont que depuis la ligne de commande ou le fichier de +configuration de Dnsmasq. +.TP +.B \-1, --enable-dbus +Autoriser la mise à jour de la configuration de Dnsmasq par le biais d'appel de +méthodes DBus. Il est possible par ce biais de mettre à jour l'adresse de +serveurs DNS amont (et les domaines correspondants) et de vider le cache. Cette +option nécessite que Dnsmasq soit compilé avec le support DBus. +.TP +.B \-o, --strict-order +Par défaut, Dnsmasq envoie les requêtes à n'importe lequel des serveurs amonts +dont il a connaissance tout en essayant de favoriser les serveurs qu'il sait +fonctionner. Cette option force Dnsmasq à essayer d'interroger, pour chaque +requête, les serveurs DNS dans leur ordre d'apparition dans le fichier +/etc/resolv.conf. +.TP +.B --all-servers +Par défaut, lorsque dnsmasq a plus d'un serveur amont disponible, il n'envoie +les requêtes qu'à un seul serveur. Spécifier cette option force dnsmasq à +effectuer ses requêtes à tous les serveurs disponibles. Le résultat renvoyé +au client sera celui fournit par le premier serveur ayant répondu. +.TP +.B --stop-dns-rebind +Rejete (et enregistre dans le journal d'activité) les adresses dans la gamme +d'adresses IP privée (au sens RFC1918) qui pourraient être renvoyées par les +serveurs amonts suite à une résolution de nom. Cela bloque les attaques cherchant +à détourner de leur usage les logiciels de navigation web ('browser') en s'en +servant pour découvrir les machines situées sur le réseau local. +.TP +.B --rebind-localhost-ok +Exclue 127.0.0/8 des vérifications de réassociation DNS. Cette gamme d'adresses +est retournée par les serveurs Realtime Blackhole (RBL, utilisés dans la +lutte contre le spam), la bloquer peut entraîner des disfonctionnements de ces +services. +.TP +.B --rebind-domain-ok=[<domaine>]|[[/<domaine>/[<domaine>/] +Ne pas détecter ni bloquer les actions de type dns-rebind pour ces domaines. +Cette option peut prendre comme valeur soit un nom de domaine soit plusieurs +noms de domains entourés par des '/', selon une syntaxe similaire à l'option +--server, c-à -d : +.B --rebind-domain-ok=/domaine1/domaine2/domaine3/ +.TP +.B \-n, --no-poll +Ne pas vérifier régulièrement si le fichier /etc/resolv.conf a été modifié. +.TP +.B --clear-on-reload +Lorsque le fichier /etc/resolv.conf est relu, vider le cache DNS. +Cela est utile si les nouveaux serveurs sont susceptibles d'avoir des données +différentes de celles stockées dans le cache. +.TP +.B \-D, --domain-needed +Indique à Dnsmasq de ne jamais transmettre en amont de requêtes pour des noms +simples, ne comprenant donc ni points ni nom de domaine. Si un nom n'est pas +dans /etc/hosts ou dans la liste des baux DHCP, alors une réponse de type +"non trouvé" est renvoyée. +.TP +.B \-S, --local, --server=[/[<domaine>]/[domaine/]][<Adresse IP>[#<port>][@<Adresse IP source>|<interface>[#<port>]]] +Spécifie directement l'adresse IP d'un serveur de nom amont. Cette option ne +supprime pas la lecture du fichier /etc/resolv.conf : utiliser pour cela +l'option +.B -R . +Si un ou plusieurs nom(s) de domaine(s) optionnel(s) sont fournis, ce +serveur sera uniquement utilisé uniquement pour ce(s) domaine(s), et toute +requête concernant ce(s) domaine(s) sera adressée uniquement à ce serveur. +Cette option est destinée aux serveurs de nom privés : si vous avez un serveur +de nom sur votre réseau ayant pour adresse IP 192.168.1.1 et effectuant la +résolution des noms de la forme xxx.internal.thekelleys.org.uk, alors +.B -S /internal.thekelleys.org.uk/192.168.1.1 +enverra toutes les requêtes pour les machines internes vers ce serveur de nom, +alors que toutes les autres requêtes seront adressées aux serveurs indiqués dans +le fichier /etc/resolv.conf. Une spécification de nom de domaine vide, +.B // +possède le sens particulier de "pour les noms non qualifiés uniquement", +c'est-à -dire les noms ne possédant pas de points. Un port non standard peut être +rajouté à la suite des adresses IP en utilisant le caractère #. Plus d'une +option +.B -S +est autorisée, en répétant les domaines et adresses IP comme requis. + +Le domaine le plus spécifique l'emporte sur le domaine le moins spécifique, +ainsi : +.B --server=/google.com/1.2.3.4 +.B --server=/www.google.com/2.3.4.5 +enverra les requêtes pour *.google.com à 1.2.3.4, à l'exception des requêtes +*www.google.com, qui seront envoyées à 2.3.4.5. + +L'adresse spéciale '#' signifie "utiliser les serveurs standards", ainsi +.B --server=/google.com/1.2.3.4 +.B --server=/www.google.com/# +enverra les requêtes pour *.google.com à 1.2.3.4, à l'exception des requêtes +pour *www.google.com qui seront envoyées comme d'habitude (c-à -d aux serveurs +définis par défaut). + +Il est également permis de donner une option +.B -S +avec un nom de domaine mais sans +adresse IP; Cela informe Dnsmasq que le domaine est local et qu'il doit répondre +aux requêtes le concernant depuis les entrées contenues dans le fichier +/etc/hosts ou les baux DHCP, et ne doit en aucun cas transmettre les requêtes +aux serveurs amonts. +.B local +est synonyme de +.B server +("serveur") afin de rendre plus claire l'utilisation de cette option pour cet +usage particulier. + +La chaîne de caractères optionnelle suivant le caractère @ permet de définir +la source que Dnsmasq doit utiliser pour les réponses à ce +serveur de nom. Il doit s'agir d'une des adresses IP appartenant à la machine sur +laquelle tourne Dnsmasq ou sinon la ligne sera ignorée et une erreur sera +consignée dans le journal des événements, ou alors d'un nom d'interface. Si un nom +d'interface est donné, alors les requêtes vers le serveur de nom seront envoyées +depuis cette interface; si une adresse ip est donnée, alors l'adresse source de +la requête sera l'adresse en question. L'option query-port est ignorée pour tous +les serveurs ayant une adresse source spécifiée, mais il est possible de la donner +directement dans la spécification de l'adresse source. Forcer les requêtes à être +émises depuis une interface spécifique n'est pas possible sur toutes les plateformes +supportées par dnsmasq. +.TP +.B \-A, --address=/<domaine>/[domaine/]<adresse IP> +Spécifie une adresse IP à retourner pour toute requête pour les domaines fournis +en option. Les requêtes pour ce(s) domaine(s) ne sont jamais transmises aux +serveurs amonts et reçoivent comme réponse l'adresse IP spécifiée qui peut être +une adresse IPv4 ou IPv6. Pour donner à la fois une adresse IPv4 et une adresse +IPv6 pour un domaine, utiliser plusieurs options +.B -A. +Il faut noter que le +contenu du fichier /etc/hosts et de celui des baux DHCP supplante ceci pour des +noms individuels. Une utilisation courante de cette option est de rediriger la +totalité du domaine doubleclick.net vers un serveur web local afin d'éviter les +bannières publicitaires. La spécification de domaine fonctionne de la même façon +que +.B --server, +avec la caractéristique supplémentaire que +.B /#/ +coïncide avec tout domaine. Ainsi, +.B --address=/#/1.2.3.4 +retournera 1.2.3.4 pour toute requête +n'ayant de réponse ni dans /etc/hosts, ni dans les baux DHCP, et n'étant pas +transmise à un serveur spécifique par le biais d'une directive +.B --server. +.TP +.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préference>] +Spécifie un enregistrement de type MX pour <nom de l'hôte> retournant le nom +donné dans <nom du MX> (s'il est présent), ou sinon le nom spécifié dans +l'option +.B --mx-target +si elle est présente. Sinon retourne le nom de la machine +sur laquelle Dnsmasq tourne. La valeur par défaut (spécifiée dans l'option +.B --mx-target +) est utile dans un réseau local pour rediriger les courriers +électroniques vers un serveur central. La valeur de préférence est optionnelle +et vaut par défaut 1 si elle n'est pas spécifiée. Plus d'une entrée MX peut être +fournie pour un hôte donné. +.TP +.B \-t, --mx-target=<nom d'hôte> +Spécifie la réponse par défaut fournie par Dnsmasq pour les requêtes sur des +enregistrements de type MX. Voir +.B --mx-host. +Si +.B --mx-target +est donné mais pas de +.B --mx-host, +alors Dnsmasq retourne comme réponse un enregistrement MX +contenant le nom d'hôte spécifié dans l'option +.B --mx-target +pour toute requête +concernant le MX de la machine sur laquelle tourne Dnsmasq. +.TP +.B \-e, --selfmx +Définit, pour toutes les machines locales, un MX correspondant à l'hôte +considéré. Les machines locales sont celles définies dans le fichier /etc/hosts +ou dans un bail DHCP. +.TP +.B \-L, --localmx +Définit, pour toutes les machines locales, un enregistrement MX pointant sur +l'hôte spécifié par mx-target (ou la machine sur laquelle Dnsmasq tourne). Les +machines locales sont celles définies dans le fichier /etc/hosts ou dans un bail +DHCP. +.TP +.B \-W --srv-host=<_service>.<_protocole>.[<domaine>],[<cible>[,<port>[,<priorité>[,<poids>]]]] +Spécifie un enregistrement DNS de type SRV. Voir la RFC2782 pour plus de +détails. Si le champs <domaine> n'est pas fourni, prends par défaut la valeur +fournie dans l'option +.B --domain. +La valeur par défaut pour le domaine est vide et le port par défaut est 1, alors +que les poids et priorités par défaut sont 0. Attention lorsque vous transposez +des valeurs issues d'une configuration BIND : les ports, poids et priorités sont +dans un ordre différents. Pour un service/domaine donné, plus d'un +enregistrement SRV est autorisé et tous les enregistrements qui coïncident sont +retournés dans la réponse. +.TP +.B \-Y, --txt-record=<nom>[[,<texte>],<texte>] +Définit un enregistrement DNS de type TXT. La valeur de l'enregistrement TXT est +un ensemble de chaînes de caractères, donc un nombre variable de chaînes de +caractères peuvent être spécifiées, séparées par des virgules. Utilisez des +guillemets pour mettre une virgule dans une chaîne de caractères. Notez que la +longueur maximale pour une chaîne est de 255 caractères, les chaînes plus +longues étant découpées en morceaux de 255 caractères de longs. +.TP +.B --ptr-record=<nom>[,<cible>] +Définit un enregistrement DNS de type PTR. +.TP +.B --naptr-record=<nom>,<ordre>,<préférence>,<drapeaux>,<service>,<expr. régulière>[,<remplacement>] +Retourne un enregistrement de type NAPTR, tel que spécifié dans le RFC3403. +.TP +.B --cname=<cname>,<cible> +Retourne un enregistrement de type CNAME qui indique que <cname> est en +réalité <cible>. Il existe des contraintes significatives sur la valeur +de cible; il doit s'agir d'un nom DNS qui est connu de dnsmasq via /etc/hosts +(ou un fichier hôtes additionnel) ou via DHCP. Si une cible ne satisfait +pas ces critères, le CNAME est ignoré. Le CNAME doit être unique, mais +il est autorisé d'avoir plus d'un CNAME pointant vers la même cible. +.TP +.B --interface-name=<nom>,<interface> +Définit un entregistrement DNS associant le nom avec l'adresse primaire sur +l'interface donnée en argument. Cette option spécifie un enregistrement de type +A pour le nom donné en argument de la même façon que s'il était défini par une +ligne de /etc/hosts, sauf que l'adresse n'est pas constante mais dépendante de +l'interface définie. Si l'interface est inactive, non existante ou non +configurée, une réponse vide est fournie. Un enregistrement inverse (PTR) est +également créé par cette option, associant l'adresse de l'interface avec le nom. +Plus d'un nom peut être associé à une interface donnée en répétant cette option +plusieurs fois; dans ce cas, l'enregistrement inverse pointe vers le nom fourni +dans la première instance de cette option. +.TP +.B --add-mac +Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises aux serveurs +amonts. Cela peut être utilisé dans un but de filtrage DNS par les serveurs +amonts. L'adresse MAC peut uniquement être ajoutée si le requêteur est sur le +même sous-réseau que le serveur dnsmasq. Veuillez noter que le mécanisme +utilisé pour effectuer cela (une option EDNS0) n'est pas encore standardisée, +aussi cette fonctionalité doit être considérée comme expérimentale. Notez +également qu'exposer les adresses MAC de la sorte peut avoir des implications +en termes de sécurité et de vie privée. +.TP +.B \-c, --cache-size=<taille> +Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms. +Définir une valeur de zéro désactive le cache. +.TP +.B \-N, --no-negcache +Désactive le "cache négatif". Le "cache négatif" permet à Dnsmasq de se souvenir +des réponses de type "no such domain" fournies par les serveurs DNS en amont et +de fournir les réponses sans avoir à re-transmettre les requêtes aux serveurs +amont. +.TP +.B \-0, --dns-forward-max=<nombre de requêtes> +Définit le nombre maximum de requêtes DNS simultanées. La valeur par défaut est +150, ce qui devrait être suffisant dans la majorité des configurations. La seule +situation identifiée dans laquelle cette valeur nécessite d'être augmentée est +lorsqu'un serveur web a la résolution de nom activée pour l'enregistrement de +son journal des requêtes, ce qui peut générer un nombre important de requêtes +simultanées. +.TP +.B --proxy-dnssec +Un resolveur sur une machine cliente peut effectuer la validation DNSSEC de +deux façons : il peut effectuer lui-même les opérations de chiffrements sur +la réponse reçue, ou il peut laisser le serveur récursif amont faire la +validation et positionner un drapeau dans la réponse au cas où celle-ci est +correcte. Dnsmasq n'est pas un validateur DNSSEC, aussi il ne peut effectuer +la validation comme un serveur de nom récursif, cependant il peut retransmettre +les résultats de validation de ses serveurs amonts. Cette option permet +l'activation de cette fonctionalité. Vous ne devriez utiliser cela que si vous +faites confiance aux serveurs amonts +.I ainsi que le réseau entre vous et eux. +Si vous utilisez le premier mode DNSSEC, la validation par le resolveur des +clients, cette option n'est pas requise. Dnsmasq retourne toujours toutes les +données nécessaires par un client pour effectuer la validation lui-même. +.TP +.B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label],]<adresse de début>,<adresse de fin>[,<masque de réseau>[,<broadcast>]][,<durée de bail>] +Active le serveur DHCP. Les adresses seront données dans la plage comprise entre +<adresse de début> et <adresse de fin> et à partir des adresses définies +statiquement dans l'option +.B dhcp-host. +Si une durée de bail est donnée, alors les baux seront donnés pour cette +durée. La durée de bail est donnée en secondes, en minutes (exemple : 45m), +en heures (exemple : 1h) ou être la chaine de caractère "infinite" pour une +durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par défaut +de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2 +minutes. +Cette option peut être répétée, avec différentes adresses, +pour activer le service DHCP sur plus d'un réseau. Pour des réseaux directement +connectés (c'est-à -dire des réseaux dans lesquels la machine sur laquelle tourne +Dnsmasq possède une interface), le masque de réseau est optionnel. Il est par +contre requis pour les réseaux pour lesquels le service DHCP se fait via un +relais DHCP ("relay agent"). L'adresse de broadcast est toujours optionnelle. + +Il est toujours possible d'avoir plus d'une plage DHCP pour un même +sous-réseau. +L'identifiant de label optionnel +.B set:<label> +fournie une étiquette alphanumérique qui identifie ce réseau, afin de permettre +la fourniture d'options DHCP spécifiques à chaque réseau. +Lorsque préfixé par 'tag:', la signification change, et au lieu de définir un +label, il définit le label pour laquelle la règle s'applique. Un seul label peut- +être défini mais plusieurs labels peuvent coïncider. + +L'adresse de fin peut être remplacée par le mot-clef +.B static +("statique") qui indique à Dnsmasq d'activer le service DHCP pour le réseau +spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP : Seuls +les hôtes possédant des adresses IP statiques fournies via +.B dhcp-host +ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP. + +L'adresse de fin peut-être remplacée par le mot-clef +.B proxy +, auquel cas Dnsmasq fournira un service de DHCP proxy pour le sous-réseau +spécifié. (voir +.B pxe-prompt +et +.B pxe-service +pour plus de détails). + +La section interface:<nom d'interface> n'est normalement pas utilisée. Se +référer aux indications de la section NOTES pour plus de détail à ce sujet. +.TP +.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore] +Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine +possédant une adresse matérielle spécifique de se voir toujours allouée les +mêmes nom d'hôte, adresse IP et durée de bail. Un nom d'hôte spécifié comme +ceci remplace le nom fourni par le client DHCP de la machine hôte. Il est +également possible d'omettre l'adresse matérielle et d'inclure le nom d'hôte, +auquel cas l'adresse IP et la durée de bail s'appliqueront à toute machine se +réclamant de ce nom. Par exemple +.B --dhcp-host=00:20:e0:3b:13:af,wap,infinite +spécifie à Dnsmasq de fournir à la machine d'adresse matérielle +00:20:e0:3b:13:af le nom, et un bail de durée indéterminée. + +.B --dhcp-host=lap,192.168.0.199 +spécifie à Dnsmasq d'allouer toujours à la machine portant le nom lap +l'adresse IP 192.168.0.199. + +Les adresses allouées de la sorte ne sont pas contraintes à une plage d'adresse +spécifiée par une option --dhcp-range, mais elles se trouver dans le même +sous-réseau qu'une plage dhcp-range valide. Pour les sous-réseaux qui n'ont pas +besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la +déclaration de plage d'adresses dhcp-range. + +Il est possible +d'utiliser des identifiants clients plutôt que des adresses matérielles pour +identifier les hôtes, en préfixant par ceux-ci par 'id:'. Ainsi, +.B --dhcp-host=id:01:02:03:04,..... +réfère à l'hôte d'identifiant 01:02:03:04. Il est également possible de +spécifier l'identifiant client sous la forme d'une chaîne de caractères, comme +ceci : +.B --dhcp-host=id:identifiantclientsousformedechaine,..... + +L'option spéciale id:* signifie : "ignorer tout identifiant client et n'utiliser +que l'adresse matérielle". Cela est utile lorsqu'un client présente un +identifiant client mais pas les autres. + +Si un nom apparaît dans /etc/hosts, l'adresse associée peut être allouée à un +bail DHCP mais seulement si une option +.B --dhcp-host +spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut-être donné dans +une option +.B dhcp-host +, mais les alias sont possibles au travers de l'utilisation des CNAMEs. (Voir +.B --cname +). +Le mot clef "ignore" ("ignorer") indique +à Dnsmasq de ne jamais fournir de bail DHCP à une machine. La machine peut être +spécifiée par son adresse matérielle, son identifiant client ou son nom d'hôte. +Par exemple +.B --dhcp-host=00:20:e0:3b:13:af,ignore +Cela est utile lorsqu'un autre serveur DHCP sur le réseau doit être utilisé par +certaines machines. + +Le paramètre set:<identifiant réseau> permet de définir un +identifiant de réseau lorsque l'option dhcp-host est utilisée. Cela peut servir +à sélectionner des options DHCP juste pour cet hôte. Plus d'un label peut être +fourni dans une directive dhcp-host (et dans cette seule directive). Lorsqu'une +machine coïncide avec une directive dhcp-host (ou une impliquée par +/etc/ethers), alors le label réservé "known" ("connu") est associé. Cela permet à +Dnsmasq d'être configuré pour ignorer les requêtes issus de machines inconnue + par le biais de +.B --dhcp-ignore=tag:!known. + +Les adresses ethernet (mais pas les identifiants clients) peuvent être définies +avec des octets joker, ainsi par exemple +.B --dhcp-host=00:20:e0:3b:13:*,ignore +demande à Dnsmasq d'ignorer une gamme d'adresses matérielles. Il est à noter +que "*" doit-être précédé d'un caractère d'échappement ou mis entre guillemets +lorsque spécifié en option de ligne de commande, mais pas dans le fichier de +configuration. + +Les adresses matérielles coïncident en principe avec n'importe +quel type de réseau (ARP), mais il est possible de les limiter à un seul type +ARP en les précédant du type ARP (en Hexadécimal) et de "-". Ainsi +.B --dhcp-host=06-00:20:e0:3b:13:af,1.2.3.4 +coïncidera uniquement avec des adresses matérielles Token-Ring, puisque le type +ARP pour une adresse Token-Ring est 6. + +Un cas spécial correspond à l'inclusion d'une ou plusieurs adresses +matérielles, c-à -d : +.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2. +Cela permet à une adresse IP d'être associé à plusieurs adresses +matérielles, et donne à dnsmasq la permission d'abandonner un bail DHCP +attribué à l'une de ces adresses lorsqu'une autre adresse dans la liste +demande un bail. Ceci est une opération dangereuse qui ne fonctionnera +de manière fiable que si une adresse matérielle est active à un moment +donné et dnsmasq n'a aucun moyen de s'assurer de cela. Cela est utile, +par exemple, pour allouer une adresse IP stable à un laptop qui +aurait à la fois une connexion filaire et sans-fil. +.TP +.B --dhcp-hostsfile=<chemin> +Lis les informations d'hôtes DHCP dans le fichier spécifié. Si l'argument est +un chemin vers un répertoire, lis tous les fichiers de ce répertoire. Le +fichier contient des informations à raison d'un hôte par ligne. Le format +d'une ligne est la même que le texte fourni à la droite sur caractère "=" dans +l'option +.B --dhcp-host. +L'avantage de stocker les informations sur les hôtes DHCP dans ce fichier est +que celles-ci peuvent être modifiées sans recharger Dnsmasq; le fichier sera +relu lorsque Dnsmasq reçoit un signal SIGHUP. +.TP +.B --dhcp-optsfile=<chemin> +Lis les informations relatives aux options DHCP dans le fichier spécifié. Si +l'argument est un chemin vers un répertoire, lis tous les fichiers de ce +répertoire. L'intérêt d'utiliser cette option est le même que pour + --dhcp-hostsfile : le fichier spécifié sera rechargé à la réception par +dnsmasq d'un signal SIGHUP. Notez qu'il est possible d'encoder l'information +via +.B --dhcp-boot +en utilisant les noms optionnels bootfile-name, server-ip-address et +tftp-server. Ceci permet d'inclure ces options dans un fichier "dhcp-optsfile".DNSMASQ_SUPPLIED_HOSTNAME +.TP +.B \-Z, --read-ethers +Lis les informations d'hôtes DHCP dans le fichier /etc/ethers. Le format de +/etc/ethers est une adresse matérielle suivie, soit par un nom d'hôte, soit par +une adresse IP sous la forme de 4 chiffres séparés par des points. Lorsque lu +par Dnsmasq, ces lignes ont exactement le même effet que l'option +.B --dhcp-host +contenant les mêmes informations. /etc/ethers est relu à la réception d'un +signal SIGHUP par Dnsmasq. +.TP +.B \-O, --dhcp-option=[tag:<label>,[tag:<label>]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]] +Spécifie des options différentes ou supplémentaires pour des clients DHCP. Par +défaut, Dnsmasq envoie un ensemble standard d'options aux clients DHCP : le +masque de réseau et l'adresse de broadcast sont les mêmes que pour l'hôte +sur lequel tourne Dnsmasq, et le serveur DNS ainsi que la route par défaut +prennent comme valeur l'adresse de la machine sur laquelle tourne Dnsmasq. Si +une option de nom de domaine a été définie, son contenu est transmis. Cette +option de configuration permet de changer toutes ces valeurs par défaut, ou de +spécifier d'autres options. L'option DHCP à transmettre peut être fournie sous +forme d'un nombre décimal ou sous la forme "option:<nom d'option>". Les nombres +correspondants aux options sont définis dans la RFC2132 et suivants. Les noms +d'options connus par Dnsmasq peuvent être obtenus via "Dnsmasq --help dhcp". +Par exemple, pour définir la route par défaut à 192.168.4.4, il est possible de +faire +.B --dhcp-option=3,192.168.4.4 +ou +.B --dhcp-option = option:router, 192.168.4.4 +ou encore, pour positionner l'adresse du serveur de temps à 192.168.0.4, on peut +faire +.B --dhcp-option = 42,192.168.0.4 +ou +.B --dhcp-option = option:ntp-server, 192.168.0.4 +L'adresse 0.0.0.0 prends ici le sens "d'adresse de la machine sur laquelle +tourne Dnsmasq". Les types de données autorisées sont des adresses IP sous la +forme de 4 chiffres séparés par des points, un nombre décimal, une liste de +caractères hexadécimaux séparés par des 2 points, ou une chaîne de caractères. +Si des labels optionnels sont fournis, alors cette option n'est envoyée +qu'aux réseaux dont tous les labels coïncident avec ceux de la requête. + +Un traitement spécial est effectué sur les chaînes de caractères fournies pour +l'option 119, conformément à la RFC 3397. Les chaînes de caractères ou les +adresses IP sous forme de 4 chiffres séparés par des points donnés en arguments +de l'option 120 sont traités conforméments à la RFC 3361. Les adresses IP sous +forme de 4 chiffres séparés par des points suivies par une barre montante "/", +puis une taille de masque sont encodés conforméments à la RFC 3442. + +Attention : aucun test n'étant fait pour vérifier que des données d'un type +adéquat sont envoyées pour un numéro d'option donné, il est tout à fait possible +de persuader Dnsmasq de générer des paquets DHCP illégaux par une utilisation +incorrecte de cette option. Lorsque la valeur est un nombre décimal, Dnsmasq +doit déterminer la taille des données. Cela est fait en examinant le numéro de +l'option et/ou la valeur, mais peut-être évité en rajoutant un suffixe d'une +lettre comme suit : +b = un octet, s = 2 octets, i = 4 octets. Cela sert essentiellement pour des +options encapsulées de classes de vendeurs (voir plus bas), pour lesquelles +Dnsmasq ne peut déterminer la taille de la valeur. Les données d'options +consistant uniquement de points et de décimaux sont interprétées par Dnsmasq +comme des adresses IP, et envoyées comme telles. Pour forcer l'envoi sous forme +de chaîne de caractère, il est nécessaire d'utiliser des guillemets doubles. Par +exemple, l'utilisation de l'option 66 pour fournir une adresse IP sous la forme +d'une chaîne de caractères comme nom de serveur TFTP, il est nécessaire de faire +comme suit : +.B --dhcp-option=66,"1.2.3.4" + +Les options encapsulées de classes de vendeurs peuvent-être aussi spécifiées en +utilisant +.B --dhcp-option +: par exemple +.B --dhcp-option=vendor:PXEClient,1,0.0.0.0 +envoie l'option encapsulée de classe de vendeur "mftp-address=0.0.0.0" à +n'importe quel client dont la classe de vendeur correspond à "PXEClient". La +correspondance pour les classes de vendeur s'effectue sur des sous-chaînes de +caractères (voir +.B --dhcp-vendorclass +pour plus de détails). Si une option de +classe de vendeur (numéro 60) est envoyée par Dnsmasq, alors cela est utilisé +pour sélectionner les options encapsulées, de préférence à toute option envoyée +par le client. Il est possible d'omettre complètement une classe de vendeur : +.B --dhcp-option=vendor:,1,0.0.0.0 +Dans ce cas l'option encapsulée est toujours envoyée. + +Les options peuvent-être encapsulées au sein d'autres options : +par exemple +.B --dhcp-option=encap:175, 190, "iscsi-client0" +enverra l'option 175, au sein de laquelle se trouve l'option 190. +Plusieurs options encapsulées avec le même numéro d'option seront correctement +combinées au sein d'une seule option encapsulée. Il n'est pas possible de +spécifier encap: et vendor: au sein d'une même option dhcp. + +La dernière variante pour les options encapsulées est "l'option de Vendeur +identifiant le vendeur" ("Vendor-Identifying Vendor Options") telle que +décrite dans le RFC3925. Celles-ci sont spécifiées comme suit : +.B --dhcp-option=vi-encap:2, 10, "text" +Le numéro dans la section vi-encap: est le numéro IANA de l'entreprise servant +à identifier cette option. + +L'adresse 0.0.0.0 n'est pas traitée de manière particulière lorsque fournie dans +une option encapsulée. +.TP +.B --dhcp-option-force=[tag:<label>,[tag:<label>]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]] +Cela fonctionne exactement de la même façon que +.B --dhcp-option +sauf que cette option sera toujours envoyée, même si le client ne la demande pas +dans la liste de paramêtres requis. Cela est parfois nécessaire, par exemple lors +de la fourniture d'options à PXELinux. +.TP +.B --dhcp-no-override +Désactive la réutilisation des champs DHCP nom de serveur et nom de +fichier comme espace supplémentaire pour les options. Si cela est +possible, dnsmasq déplace les informations sur le serveur de démarrage +et le nom de fichier (fournis par 'dhcp-boot') en dehors des champs +dédiés à cet usage dans les options DHCP. Cet espace supplémentaire est +alors disponible dans le paquet DHCP pour d'autres options, mais peut, dans +quelques rares cas, perturber des clients vieux ou défectueux. Cette +option force le comportement à l'utilisation des valeurs "simples et sûres" +afin d'éviter des problèmes dans de tels cas. +.TP +.B \-U, --dhcp-vendorclass=set:<label>,<classe de vendeur> +Associe une chaîne de classe de vendeur à un label. La plupart +des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui +représente, d'une certaine façon, le type d'hôte. Cette option associe des +classes de vendeur à des labels, de telle sorte que des options DHCP peuvent-être +fournie de manière sélective aux différentes classes d'hôtes. Par exemple, +.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect +ou +.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect +permet de n'allouer des options qu'aux imprimantes HP de la manière suivante : +.B --dhcp-option=tag:printers,3,192.168.4.4 +La chaîne de caractères de la classe de vendeur founie en argument est cherchée +en temps que sous-chaîne de caractères au sein de la classe de vendeur fournie +par le client, de façon à permettre la recherche d'un sous-ensemble de la chaîne +de caractères ("fuzzy matching"). Le préfixe set: est optionnel mais autorisé +afin de conserver une certaine homogénéité. +.TP +.B \-j, --dhcp-userclass=set:<label>,<classe utilisateur> +Associe une chaîne de classe d'utilisateur à un label (effectue la +recherche sur des sous-chaînes, comme pour les classes de vendeur). La plupart +des clients permettent de configurer une "classe d'utilisateur". Cette option +associe une classe d'utilisateur à un label, de telle manière qu'il soit +possible de fournir des options DHCP spécifiques à différentes classes d'hôtes. +Il est possible, par exemple, d'utiliser ceci pour définir un serveur +d'impression différent pour les hôtes de la classe "comptes" et ceux de la +classe "ingénierie". +.TP +.B \-4, --dhcp-mac=set:<label>,<adresse MAC> +Associe une adresse matérielle (MAC) à un label. L'adresse +matérielle peut inclure des jokers. Par exemple +.B --dhcp-mac=set:3com,01:34:23:*:*:* +permet de définir le label "3com" pour n'importe quel hôte dont l'adresse +matérielle coïncide avec les critères définis. +.TP +.B --dhcp-circuitid=set:<label>,<identifiant de circuit>, --dhcp-remoteid=set:<label>,<identifiant distant> +Associe des options de relais DHCP issus de la RFC3046 à des labels. +Cette information peut-être fournie par des relais DHCP. L'identifiant +de circuit ou l'identifiant distant est normalement fourni sous la forme d'une +chaîne de valeurs hexadécimales séparées par des ":", mais il est également +possible qu'elle le soit sous la forme d'une simple chaîne de caractères. Si +l'identifiant de circuit ou d'agent correspond exactement à celui fourni par le +relais DHCP, alors le label est apposé. +.TP +.B --dhcp-subscrid=set:<label>,<identifiant d'abonné> +Associe des options de relais DHCP issues de la RFC3993 à des labels. +.TP +.B --dhcp-proxy[=<adresse ip>]...... +Un agent relai DHCP normal est uniquement utilisé pour faire suivre les +éléments initiaux de l'interaction avec le serveur DHCP. Une fois que le +client est configuré, il communique directement avec le serveur. Cela n'est pas +souhaitable si le relais rajoute des informations supplémentaires aux paquets +DHCP, telles que celles utilisées dans +.B dhcp-circuitid +et +.B dhcp-remoteid. +Une implémentation complète de relai peut utiliser l'option serverid-override +de la RFC 5107 afin de forcer le serveur DHCP à utiliser le relai en temps que +proxy complet, de sorte que tous les paquets passent par le relai. Cette option +permet d'obtenir le même résultat pour des relais ne supportant pas la RFC +5107. Fournie seule, elle manipule la valeur de server-id pour toutes les +interactions via des relais. Si une liste d'adresses IP est donnée, seules les +interactions avec les relais dont l'adresse est dans la liste seront affectées. +.TP +.B --dhcp-match=set:<label>,<numéro d'option>|option:<nom d'option>|vi-encap:<entreprise>[,<valeur>] +Si aucune valeur n'est spécifiée, associe le label si le client +envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est +fournie, positionne le label seulement dans le cas où l'option est fournie et +correspond à la valeur. La valeur peut-être de la forme "01:ff:*:02", auquel +cas le début de l'option doit correspondre (en respectant les jokers). La +valeur peut aussi être de la même forme que dans +.B dhcp-option +, auquel cas l'option est traitée comme un tableau de valeur, et un des +éléments doit correspondre, ainsi + +--dhcp-match=set:efi-ia32,option:client-arch,6 + +spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste +d'architectures envoyé par le client au sein de l'option 93. (se réferer +au RFC 4578 pour plus de détails). Si la valeur est un chaine de caractères, +celle-ci est recherchée (correspondance en temps que sous-chaîne). + +Pour la forme particulière vi-encap:<numéro d'entreprise>, la comparaison se +fait avec les classes de vendeur "identifiant de vendeur" ("vendor-identifying +vendor classes") pour l'entreprise dont le numéro est fourni en option. +Veuillez vous réferer à la RFC 3925 pour plus de détail. +.TP +.B --tag-if=set:<label>[,set:<label>[,tag:<label>[,tag:<label>]]] +Effectue une opération booléenne sur les labels. Si tous les labels +apparaissant dans la liste tag:<label> sont positionnés, alors tous les +la de la liste "set:<labels>" sont positionnés (ou supprimés, dans le cas +où "tag:!<label>" utilisé). +Si aucun tag:<label> n'est spécifié, alors tous les labels fournis par +set:<label> sont positionnés. +N'importe quel nombre de set: ou tag: peuvent être fournis, et l'ordre est sans +importance. +Les lignes tag-if sont executées dans l'ordre, ce qui fait que si un label dans +tag:<label> est un label positionné par une rêgle +.B tag-if, +la ligne qui positionne le label doit précéder celle qui le teste. +.TP +.B \-J, --dhcp-ignore=tag:<label>[,tag:<label>] +Lorsque tous les labels fournis dans l'option sont présents, ignorer l'hôte et +ne pas donner de bail DHCP. +.TP +.B --dhcp-ignore-names[=tag:<label>[,tag:<label>]] +Lorsque tous les labels fournis dans l'option sont présents, ignorer le +nom de machine fourni par l'hôte. Il est à noter que, à la différence de +l'option "dhcp-ignore", il est permis de ne pas fournir de label. +Dans ce cas, les noms d'hôtes fournis par les clients DHCP seront toujours +ignorés, et les noms d'hôtes seront ajoutés au DNS en utilisant uniquement la +configuration dhcp-host de Dnsmasq, ainsi que le contenu des fichiers /etc/hosts +et /etc/ethers. +.TP +.B --dhcp-generate-names=tag:<label>[,tag:<label>] +Générer un nom pour les clients DHCP qui autrement n'en aurait pas, en +utilisant l'adresse MAC sous sa forme hexadécimale, séparée par des tirets. +Noter que si un hôte fourni un nom, celui-ci sera utilisé de préférence au nom +autogénéré, à moins que +.B --dhcp-ignore-names +ne soit positionné. +.TP +.B --dhcp-broadcast=[tag:<label>[,tag:<label>]] +Lorsque tous les labels fournis dans l'option sont présents, toujours utiliser +le broadcast pour communiquer avec l'hôte lorsque celui-ci n'est +pas configuré. Il est possible de ne spécifier aucun label, auquel cas cette +option s'applique inconditionnellement. La plupart des clients DHCP nécessitant une réponse par le biais +d'un broadcast activent une option dans leur requête, ce qui fait que cela +se fait automatiquement, mais ce n'est pas la cas de certains vieux clients BOOTP. +.TP +.B \-M, --dhcp-boot=[tag:<label>,]<nom de fichier>,[<nom de serveur>[,<adresse de serveur>]] +Spécifie les options BOOTP devant être retournées par le serveur DHCP. Le nom de +serveur ainsi que l'adresse sont optionnels : s'ils ne sont pas fournis, le nom +est laissé vide et l'adresse fournie est celle de la machine sur laquelle +s'exécute Dnsmasq. Si Dnsmasq founit un service TFTP (voir +.B --enable-tftp +), alors seul un nom de fichier est requis ici pour permettre un démarrage par +le réseau. +Si d'éventuels labels sont fournis, ils doivent coïncider avec +ceux du client pour que cet élement de configuration lui soit envoyé. +.TP +.B --pxe-service=[tag:<label>,]<CSA>,<entrée de menu>[,<nom de fichier>|<type de service de démarrage>][,<adresse de serveur>] +La plupart des ROMS de démarrage PXE ne permettent au système PXE que la simple +obtention d'une adresse IP, le téléchargement du fichier spécifié dans +.B dhcp-boot +et son exécution. Cependant, le système PXE est capable de fonctions bien plus +complexes pour peu que le serveur DHCP soit adapté. + +Ceci spécifie l'option de démarrage qui apparaitra dans un menu de démarrage +PXE. <CSA> est le type du système client. Seuls des types de services valides +apparaitront dans un menu. Les types connus sont x86PC, PC98, IA64_EFI, Alpha, +Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI et X86-64_EFI; +D'autres types peuvent-être spécifiés sous la forme d'une valeur entière. Le +paramètre après le texte correspondant à l'entrée dans le menu peut être un nom +de fichier, auquel cas Dnsmasq agit comme un serveur de démarrage et indique au +client PXE qu'il faut télécharger ce fichier via TFTP, soit depuis ce serveur +(l'option +.B enable-tftp +doit être spécifiée pour que cela marche), soit depuis un autre serveur TFTP +si une adresse de serveur est fournie. +Veuillez noter que le suffixe de "couche" (en principe ".0") est fourni par PXE +et ne doit pas être rajouté au nom de fichier. Si une valeur numérique entière +est fournir pour le type de démarrage, en remplacement du nom de fichier, le +client PXE devra chercher un service de démarrage de ce type sur le réseau. +Cette recherche peut être faite via broadcast ou directement auprès d'un +serveur si son adresse IP est fournie dans l'option. +Si aucun nom de fichier n'est donné ni aucune valeur de type de service de +démarrage n'est fournie (ou qu'une valeur de 0 est donnée pour le type de +service), alors l'entrée de menu provoque l'interruption du démarrage par +le réseau et la poursuite du démarrage sur un média local. +.TP +.B --pxe-prompt=[tag:<label>,]<invite>[,<délai>] +Cette option permet d'afficher une invite à la suite du démarrage PXE. Si un +délai est fourni, alors la première entrée du menu de démarrage sera +automatiquement exécutée après ce délai. Si le délai vaut 0, alors la première +entrée disponible sera exécutée immédiatement. Si +.B pxe-prompt +est omis, le système attendra un choix de l'utilisateur s'il existe plusieurs +entrées dans le menu, ou démarrera immédiatement dans le cas où il n'y a qu'une +seule entrée. Voir +.B pxe-service +pour plus de détails sur les entrées de menu. + +Dnsmasq peut servir de "proxy-DHCP" PXE, dans le cas où un autre serveur DHCP +sur le réseau est responsable de l'allocation des adresses IP, auquel cas +Dnsmasq se contente de fournir les informations données dans les options +.B pxe-prompt +et +.B pxe-service +pour permettre le démarrage par le réseau. Ce mode est activé en utilisant le +mot-clef +.B proxy +dans +.B dhcp-range. +.TP +.B \-X, --dhcp-lease-max=<nombre> +Limite Dnsmasq à un maximum de <nombre> baux DHCP. Le défaut est de 1000. Cette +limite permet d'éviter des attaques de déni de service ("DoS") par des hôtes +créant des milliers de baux et utilisant beaucoup de mémoire dans le processus +Dnsmasq. +.TP +.B \-K, --dhcp-authoritative +Cette option doit être donnée lorsque Dnsmasq est le seul serveur DHCP sur le +réseau. Cela change le comportement par défaut qui est celui d'un strict respect +des RFC, afin que les requêtes DHCP pour des baux inconnus par des hôtes +inconnus ne soient pas ignorées. Cela permet à de nouveaux hôtes d'obtenir des +baux sans tenir compte de fastidieuses temporisations ("timeout"). Cela permet +également à Dnsmasq de reconstruire sa base de donnée contenant les baux sans +que les clients n'aient besoin de redemander un bail, si celle-ci est perdue. +.TP +.B --dhcp-alternate-port[=<port serveur>[,<port client>]] +Change les ports utilisés par défaut pour le DHCP. Si cette option est donnée +toute seule sans arguments, alors change les ports utilisés pour le DHCP +de 67 et 68 respectivement à 1067 et 1068. Si un seul argument est donné, ce +numéro est utilisé pour le port serveur et ce numéro plus 1 est utilisé pour le +port client. Enfin, en fournissant deux numéros de ports, il est possible de +spécifier arbitrairement 2 ports à la fois pour le serveur et pour le client DHCP. +.TP +.B \-3, --bootp-dynamic[=<identifiant de réseau>[,<identifiant de réseau>]] +Permet l'allocation dynamique d'adresses IP à des clients BOOTP. Utiliser cette +option avec précaution, une adresse allouée à un client BOOTP étant perpétuelle, +et de fait n'est plus disponibles pour d'autres hôtes. Si aucun argument n'est +donné, alors cette option permet une allocation dynamique dans tous les cas. Si +des arguments sont spécifiés, alors l'allocation ne se fait que lorsque tous +les identifiants coïncident. Il est possible de répeter cette option avec +plusieurs jeux d'arguments. +.TP +.B \-5, --no-ping +Par défaut, le serveur DHCP tente de s'assurer qu'une adresse n'est pas utilisée +avant de l'allouer à un hôte. Cela est fait en envoyant une requête ICMP de type +"echo request" (aussi connue sous le nom de "ping") à l'adresse en question. Si +le serveur obtient une réponse, alors l'adresse doit déjà être utilisée et une +autre est essayée. Cette option permet de supprimer cette vérification. A +utiliser avec précaution. +.TP +.B --log-dhcp +Traces additionnelles pour le service DHCP : enregistre toutes les options +envoyées aux clients DHCP et les labels utilisés pour la +détermination de celles-ci. +.TP +.B \-l, --dhcp-leasefile=<chemin de fichier> +Utilise le fichier dont le chemin est fourni pour stocker les informations de +baux DHCP. +.TP +.B \-6 --dhcp-script=<chemin de fichier> +Lorsqu'un bail DHCP est créé, ou qu'un ancien est supprimé, le fichier dont le +chemin est spécifié est exécuté. Le <chemin de fichier> doit être un chemin +absolu, aucune recherche n'est effectuée via la variable d'environnement PATH. +Les arguments fournis à celui-ci sont soit +"add" ("ajouter"), "old" ("ancien") ou "del" ("supprimer"), suivi de l'adresse +MAC de l'hôte puis l'adresse IP et le nom d'hôte si celui-ci est +connu."add" signifie qu'un bail a été créé, "del" signifie qu'il a été supprimé, +"old" notifie que le bail existait au lancement de Dnsmasq, ou un changement +d'adresse MAC ou de nom d'hôte pour un bail existant (ou, dans le cas où +leasefile-ro est spécifié, un changement de durée de bail ou d'identifiant +d'hôte). Si l'adresse Mac est d'un type de réseau autre qu'ethernet, il est +nécessaire de la préceder du type de réseau, par exemple "06-01:23:45:67:89:ab" +pour du token ring. Le processus est exécuté en temps que super-utilisateur +(si Dnsmasq a été lancé en temps que "root"), même si Dnsmasq est configuré +pour changer son UID pour celle d'un utilisateur non-privilégié. + +L'environnement est hérité de celui de l'invocation du processus Dnsmasq, +auquel se rajoute quelques unes ou toutes les variables décrites ci-dessous : + +DNSMASQ_CLIENT_ID, si l'hôte a fourni un identifiant de client. + +DNSMASQ_DOMAIN si le nom de domaine pleinement qualifié de l'hôte est connu, la +part relative au domaine y est stockée. (Notez que le nom d'hôte transmis comme +argument au script n'est jamais pleinement qualifié). + +Si le client fournit une information de classe de vendeur, un nom d'hôte, ou +des classes d'utilisateur, celles-ci sont fournies dans les +variables DNSMASQ_VENDOR_CLASS et DNSMASQ_USER_CLASS0 à DNSMASQ_USER_CLASSn +et DNSMASQ_SUPPLIED_HOSTNAME respectivement, mais seulement pour les actions +"add" et "old" lorsqu'un hôte reprend un bail existant, ces variables n'étant +pas stockées dans la base de baux de Dnsmasq. + +Si Dnsmasq a été compilé avec l'option HAVE_BROKEN_RTC ("horloge RTC +défectueuse"), alors la durée du bail (en secondes) est stockée dans la +variable DNSMASQ_LEASE_LENGTH, sinon la date d'expiration du bail est toujours +stocké dans la variable d'environnement DNSMASQ_LEASE_EXPIRES. Le nombre de +secondes avant expiration est toujours stocké dans DNSMASQ_TIME_REMAINING. + +Si un bail était associé à un nom d'hôte et +que celui-ci est supprimé, un évênement de type "old" est généré avec le +nouveau statut du bail, c-à -d sans nom d'hôte, et le nom initial est fourni +dans la variable d'environnement DNSMASQ_OLD_HOSTNAME. + +La variable DNSMASQ_INTERFACE contient le nom de l'interface sur laquelle la +requête est arrivée; ceci n'est pas renseigné dans le cas des actions "old" +ayant lieu après un redémarrage de dnsmasq. + +La variable DNSMASQ_RELAY_ADDRESS est renseignée si le client a utilisé un +relai DHCP pour contacter Dnsmasq, si l'adresse IP du relai est connue. + +DNSMASQ_TAGS contient tous les labels fournis pendant la transaction DHCP, +séparés par des espaces. + +Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui +sont ouverts sur /dev/null (sauf en mode déverminage). + +Le script n'est pas lancé de manière concurrente : au plus une instance du +script est executée à la fois (dnsmasq attends qu'une instance de script se +termine avant de lancer la suivante). Les changements dans la base des baux +nécessitant le lancement du script sont placé en attente dans une queue jusqu'à +terminaison d'une instance du script en cours. Si cette mise en queue fait que +plusieurs changements d'états apparaissent pour un bail donné avant que le +script puisse être lancé, alors les états les plus anciens sont supprimés et +lorsque le script sera finalement lancé, ce sera avec l'état courant du bail. + +Au démarrage de Dnsmasq, le script sera invoqué pour chacun des baux existants +dans le fichier des baux. Le script sera lancé avec l'action "del" pour les +baux expirés, et "old" pour les autres. Lorsque Dnsmasq reçoit un signal HUP, +le script sera invoqué avec une action "old" pour tous les baux existants. +.TP +.B --dhcp-scriptuser +Spécifie l'utilisateur sous lequel le script lease-change doit être exécuté. La +valeur par défaut correspond à l'utilisateur root mais peut-être changée par le +biais de cette option. +.TP +.B \-9, --leasefile-ro +Supprimer complètement l'usage du fichier servant de base de donnée pour les +baux DHCP. Le fichier ne sera ni créé, ni lu, ni écrit. Change la façon dont le +script de changement d'état de bail est lancé (si celui-ci est fourni par le +biais de l'option +.B --dhcp-script +), de sorte que la base de données de baux puisse +être complètement gérée par le script sur un stockage externe. En addition aux +actions décrites dans +.B --dhcp-script, +le script de changement d'état de bail est appellé une fois, au lancement de +Dnsmasq, avec pour seul argument "init". Lorsqu'appellé de la sorte, le script +doit fournir l'état de la base de baux, dans le format de fichier de baux de +Dnsmasq, sur sa sortie standard (stdout) et retourner un code de retour de 0. +Positionner cette option provoque également une invocation du script de +changement d'état de bail à chaque changement de l'identifiant de client, de +longueur de bail ou de date d'expiration. +.TP +.B --bridge-interface=<interface>,<alias>[,<alias>] +Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias> +comme si elles arrivaient de l'interface <interface>. Cette option est +nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme +BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont +pas d'adresse IP. +.TP +.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]] +Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière +inconditionnelle (sans spécifier de gamme d'adresses IP) ou pour des gammes +d'adresses IP limitées. Cela a deux effets; tout d'abord, le +serveur DHCP retourne le domaine à tous les hôtes le demandant, deuxièmement, +cela spécifie le domaine valide pour les hôtes DHCP configurés. Le but de cela +est de contraindre les noms d'hôte afin qu'aucun hôte sur le LAN ne puisse +fournir via DHCP un nom tel que par exemple "microsoft.com" et capturer du +trafic de manière illégitime. Si aucun nom de domaine n'est spécifié, alors +les noms d'hôtes avec un nom de domaine (c-à -d un point dans le nom) seront +interdits et enregistrés dans le journal (logs). Si un suffixe est fourni, alors +les noms d'hôtes possédant un domaine sont autorisés, pour peu que le nom de +domaine coïncide avec le nom fourni. De plus, si un suffixe est fourni, alors +les noms d'hôtes ne possédant pas de nom de domain se voient rajouter le +suffixe fourni dans l'option +.B --domain. +Ainsi, sur mon réseau, je peux configurer +.B --domain=thekelleys.org.uk +et avoir une machine dont le nom DHCP serait "laptop". L'adresse IP de cette +machine sera disponible à la fois pour "laptop" et "laptop.thekelleys.org.uk". +Si la valeur fournie pour <domaine> est "#", alors le nom de domaine est +positionné à la première valeur de la directive "search" du fichier +/etc/resolv.conf (ou équivalent). + +La gamme d'adresses peut être de la forme +<adresse ip>,<adresse ip> ou <adresse ip>/<masque de réseau> voire une simple +<adresse ip>. Voir +.B --dhcp-fqdn +qui peut changer le comportement de dnsmasq relatif aux domaines. + +Si la gamme d'adresse est fournie sous la forme +<adresse ip>/<taille de réseau>, alors le drapeau "local" peut-être rajouté +qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et +inverses. C-à -d +.B --domain=thekelleys.org.uk,192.168.0.0/24,local +est indentique à +.B --domain=thekelleys.org.uk,192.168.0.0/24 +--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/ +La taille de réseau doit-être de 8, 16 ou 24 pour être valide. +.TP +.B --dhcp-fqdn +Dans le mode par défaut, dnsmasq insère les noms non-qualifiés des clients +DHCP dans le DNS. Pour cette raison, les noms doivent être uniques, même si +deux clients ayant le même nom sont dans deux domaines différents. Si un +deuxième client DHCP apparaît ayant le même nom qu'un client déjà existant, +ce nom est transféré au nouveau client. Si +.B --dhcp-fqdn +est spécifié, ce comportement change : les noms non qualifiés ne sont plus +rajoutés dans le DNS, seuls les noms qualifiés le sont. Deux clients DHCP +avec le même nom peuvent tous les deux garder le nom, pour peu que la partie +relative au domaine soit différente (c-à -d que les noms pleinements qualifiés +diffèrent). Pour d'assurer que tous les noms ont une partie domaine, il doit-y +avoir au moins un +.B --domain +sans gamme d'adresses de spécifié lorsque l'option +.B --dhcp-fqdn +est configurée. +.TP +.B --enable-tftp[=<interface>] +Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux +fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul +un accès en lecture est possible; les extensions tsize et blksize sont supportées +(tsize est seulement supporté en mode octet). Voir dans la section NOTES les +informations relatives à la spécification de l'interface. +.TP +.B --tftp-root=<répertoire>[,<interface>] +Les fichiers à fournir dans les transferts TFTP seront cherchés en prenant le +répertoire fourni comme racine. Lorsque cela est fourni, les chemins TFTP +incluant ".." sont rejetés, afin d'éviter que les clients ne puissent sortir de +la racine spécifiée. Les chemins absolus (commençant par "/") sont autorisés, +mais ils doivent être à la racine TFTP fournie. Si l'option interface est +spécifiée, le répertoire n'est utilisé que pour les requêtes TFTP reçues sur +cette interface. +.TP +.B --tftp-unique-root +Ajouter l'adresse IP du client TFTP en temps qu'élément de chemin, à la suite +de la racine tftp (adresse sous forme de 4 chiffres séparés par des points). +Uniquement valable si une racine TFTP est spécifiée et si le répertoire +correspond existe. Ainsi, si la valeur pour tftp-root est "/tftp" et que le +client d'adresse IP 1.2.3.4 requiert le fichier "monfichier", alors le chemin +effective résultant sera "/tftp/1.2.3.4/monfichier" si /tftp/1.2.3.4 existe, ou +"/tftp/monfichier" dans le cas contraire. +.TP +.B --tftp-secure +Active le mode TFTP sécurisé : sans cela, tout fichier lisible +par Dnsmasq est disponible via TFTP (les règles de contrôle d'accès unix +habituelles s'appliquent). Lorsque l'option +.B --tftp-secure +est spécifiée, seuls les fichiers possédés par l'utilisateur sous lequel tourne +le processus Dnsmasq sont accessibles. Si Dnsmasq est exécuté en temps que +super-utilisateur ("root"), des règles différentes s'appliquent : +.B --tftp-secure +n'a aucun effet, mais seuls les fichiers ayant un droit de lecture pour tout le +monde sont accessibles. Il n'est pas recommandé d'exécuter Dnsmasq sous +l'utilisateur "root" lorsque le service TFTP est activé, et il est formellement +déconseillé de le faire sans fournir l'option +.B --tftp-root. +Sans cela, en effet, l'accès de tous les fichiers du serveur pour lequel le +droit de lecture pour tout le monde est positionné ("world-readable") devient +possible par n'importe quel hôte sur le réseau. +.TP +.B --tftp-max=<connexions> +Définit le nombre maximum de connexions TFTP simultanées autorisées. La valeur +par défaut est de 50. Lorsqu'un grand nombre de connexions TFTP est spécifié, +il se peut que la limite de nombre de descripteurs de fichiers par processus +soit atteinte. Dnsmasq nécessite quelques descripteurs de fichiers, ainsi qu'un +descripteur de fichier pour chaque connexion TFTP simultanée et pour chacun des +fichiers devant être fournis. De fait, servir le même fichier à n clients ne +nécessitera qu'environ n + 10 descripteurs de fichiers, alors que fournir des +fichiers tous différents à n clients utilisera environ (2*n) + 10 descripteurs. +Si elle est donnée, l'option +.B --tftp-port-range +peut affecter le nombre maximum de connexions concurrentes. +.TP +.B --tftp-no-blocksize +Empêche le serveur TFTP de négocier l'option "blocksize" (taille de bloc) avec +les clients. Certains clients buggés spécifient cette option mais se comportent +ensuite de manière incorrecte si celle-ci est accordée. +.TP +.B --tftp-port-range=<début>,<fin> +Un serveur TFTP écoute sur le port prédéfini 69 ("well-known port") pour +l'initiation de la connexion, mais utilise également un port dynamiquement +alloué pour chaque connexion. Normalement, ces ports sont alloués par +le système d'exploitation, mais cette option permet de spécifier une gamme +de ports à utiliser pour les transferts TFTP. Cela peut-être utile si +TFTP doit traverser un dispositif garde-barrière ("firewall"). La valeur +de début pour la plage de port ne peut-être inférieure à 1025 sauf si +dnsmasq tourne en temps que super-utilisateur ("root"). Le nombre de +connexions TFTP concurrentes est limitée par la taille de la gamme de +ports ainsi spécifiée. +.TP +.B --tftp-port-range=<début>,<fin> +Un serveur TFTP écoute sur un numéro de port bien connu (69) pour l'initiation +de la connexion, et alloue dynamiquement un port pour chaque connexion. Ces +numéros de ports sont en principe alloués par le système d'exploitation, mais +cette option permet de spécifier une gamme de ports à utiliser pour les +transferts TFTP. Cela peut-être utile lorsque ceux-ci doivent traverser un +dispositif garde-barrière ("firewall"). Le début de la plage ne peut-être +inférieur à 1024 à moins que Dnsmasq ne fonctionne en temps que +super-utilisateur ("root"). Le nombre maximal de connexions TFTP concurrentes +est limitée par la taille de la plage de ports ainsi définie. +.TP +.B \-C, --conf-file=<fichier> +Spécifie un fichier de configuration différent. L'option "conf-file" est +également autorisée dans des fichiers de configuration, ce qui permet +l'inclusion de multiples fichiers de configuration. L'utilisation de "-" comme +nom de fichier permet la lecture par dnsmasq de sa configuration sur l'entrée standard +stdin. +.TP +.B \-7, --conf-dir=<répertoire>[,<extension de fichier>...] +Lis tous les fichiers du répertoire spécifié et les traite comme des fichiers de +configuration. Si des extensions sont données, tout fichier finissant par ces +extensions seront ignorés. Tout fichier dont le nom se termine en ~ ou commence +par ., ainsi que ceux commençant ou se terminant par # seront systématiquement +ignorés. +Cette option peut être donnée en ligne de commande ou dans un fichier de +configuration. +.SH FICHIER DE CONFIGURATION +Au démarrage, Dnsmasq lis +.I /etc/dnsmasq.conf, +si ce fichier existe. (Sur FreeBSD, ce fichier est +.I /usr/local/etc/dnsmasq.conf +) (voir cependant les options +.B \-C +et +.B \-7 +). Le format de ce fichier consiste en une option par ligne, exactement comme +les options longues détaillées dans la section OPTIONS, mais sans être précédées +par "--". Les lignes commençant par # sont des commentaires et sont ignorées. +Pour les options qui ne peuvent-être spécifiées qu'une seule fois, celle du +fichier de configuration prends le pas sur celle fournie en ligne de commande. +Il est possible d'utiliser des guillemets afin d'éviter que les ",",":","." et +"#" ne soit interprêtés, et il est possible d'utiliser les séquences +d'échappement suivantes : \\\\ \\" \\t \\e \\b \\r et \\n. Elles correspondent +respectivement à la barre oblique descendante ("anti-slash"), guillemets doubles, +tabulation, caractère d'échappement ("escape"), suppression ("backspace"), retour ("return") et +nouvelle ligne ("newline"). +.SH NOTES +A la réception d'un signal SIGHUP, +.B Dnsmasq +vide son cache et recharge les fichiers +.I /etc/hosts +et +.I /etc/ethers +ainsi que tout autre fichier spécifié par les options +.B --dhcp-hostsfile +, +.B --dhcp-optsfile +ou +.B --addn-hosts. +Le script de changement de bail est appellé pour chaque bail DHCP existant. Si +l'option +.B --no-poll +est positionnée, alors le fichier +.I /etc/resolv.conf +est également rechargé. +SIGHUP ne provoque PAS de rechargement du fichier de configuration. +.PP +A la réception d'un signal SIGUSR1, +.B Dnsmasq +écrit des statistiques dans les traces système. Les informations fournies sont : +la taille du cache, le nombre de noms ayant été supprimés du cache avant +expiration afin de faire de la place pour les nouveaux noms, ainsi que le nombre +total d'entrées ayant été insérées dans le cache. Pour chaque serveur amont, il fournit +le nomnbre de requêtes transmises ainsi que le nombre de requêtes ayant résulté par une +erreur. Lorsque Dnsmasq a été lancé via +.B --no-daemon +ou lorsque la traçabilité maximale a été activée ( +.B -q +), la totalité du contenu du +cache est de surcroît fournie. +.PP +A la réception d'un signal SIGUSR2 et lorsqu'il enregistre directement ses +traces dans un fichier (voir +.B --log-facility +), alors +.B Dnsmasq +ferme et re-rouvre le fichier de traces. Il faut noter que pendant cette +opération Dnsmasq ne s'exécute pas en temps que "root". Lorsqu'il créé un +fichier de traces pour la première fois, Dnsmasq change le propriétaire du +fichier afin de le faire appartenir à l'utilisateur non "root" sous lequel +Dnsmasq s'exécute. Le logiciel de rotation de fichiers de trace logrotate doit +être configuré pour créer un nouveau fichier avec un propriétaire identique au +fichier existant avant d'envoyer le signal SIGUSR2. Si une requête DNS TCP est +en cours, l'ancien fichier de traces reste ouvert dans le processus fils qui +traite la requête TCP et il peut y être écrit. Il existe cependant une limite +de 150 secondes après laquelle tous les processus traitant des requêtes TCP +expirent : pour cette raison, il est préférable de ne pas configurer la +compression des fichiers de traces venant juste de faire l'objet d'une rotation. +Dans le cas de l'utilisation du logiciel logrotate, les options requises sont +.B create +et +.B delaycompress. + + +.PP +Dnsmasq est un logiciel de transmission de requêtes DNS : il n'est pas capable +d'effectuer une résolution de nom récursive en partant des serveurs DNS racine, +mais transmet de telles requêtes à un serveur DNS amont capable de telles +recherches récursives, ce qui est typiquement le cas d'un serveur DNS de FAI. +Par défaut, Dnsmasq lis +.I /etc/resolv.conf +pour découvrir les adresses IP des serveurs DNS amonts à utiliser, puisque cette +information est en général stockée à cet endroit. A moins que l'option +.B --no-poll +ne soit utilisée, +.B Dnsmasq +vérifie la date de modification du fichier +.I /etc/resolv.conf +(ou l'équivalent si +.B \--resolv-file +est utilisé), et le relis lorsqu'il change. Cela permet de définir les serveurs +DNS amont de manière dynamique lorsque PPP ou DHCP sont utilisés, puisque ces +protocoles fournissent cette information. +L'absence du fichier +.I /etc/resolv.conf +ne conduit pas à une erreur, puisqu'il peut très bien ne pas être créé avant +qu'une connexion PPP ne soit établie. Dans ce cas, Dnsmasq vérifie régulièrement +pour voir si un fichier +.I /etc/resolv.conf +est créé. Dnsmasq peut être configuré pour lire plus d'un fichier resolv.conf. +Cela est utile sur un ordinateur portable où PPP et DHCP peuvent-être utilisés : +Dnsmasq peut alors être configuré pour lire à la fois +.I /etc/ppp/resolv.conf +et +.I /etc/dhcpc/resolv.conf +et utilisera le contenu du fichier ayant changé en dernier, ce qui permet de +passer automatiquement de serveurs DNS à d'autres. +.PP +Les serveurs amonts peuvent aussi être spécifiés sur la ligne de commande ou +dans un fichier de configuration. Ces spécifications de serveurs peuvent +éventuellement se voir adjoindre d'un nom de domaine qui précise à Dnsmasq quel +serveur utiliser pour trouver les noms d'un domaine donné. +.PP +Pour configurer Dnsmasq afin qu'il se comporte comme un cache pour la machine +sur laquelle il tourne, mettre "nameserver 127.0.0.1" dans le fichier +.I /etc/resolv.conf +afin de forcer les processus locaux à envoyer leurs requêtes à Dnsmasq. Ensuite, +spécifier les serveurs DNS amont soit en les fournissant directement à Dnsmasq +via l'option +.B \--server +ou alors en mettant leurs adresses dans un autre fichier, par exemple +.I /etc/resolv.dnsmasq +et en lançant Dnsmasq avec l'option +.B \-r /etc/resolv.dnsmasq. +Cette deuxième technique permet la mise-à -jour dynamique des addresses de +serveurs DNS amont par le biais de PPP ou DHCP. +.PP +Les adresses dans /etc/hosts prennent le dessus sur celles fournies par le +serveur DNS amont, ainsi "macompagnie.com 1.2.3.4" dans /etc/hosts assure que +les requêtes pour "macompagnie.com" retourneront toujours 1.2.3.4, même si une +requête au serveur DNS amont retournerait une adresse différente. Il y a une +exception à ceci : si le DNS amont contient un CNAME qui pointe vers un nom +présent dans /etc/hosts, alors la recherche du CNAME via Dnsmasq fournira +l'adresse DNS amont. Pour contourner cela, il suffit de mettre l'entrée +correspondant au CNAME dans /etc/hosts. +.PP +le système de label fonctionne comme suit : pour chaque requête DHCP, dnsmasq +associe un ensemble de labels obtenus à partir des lignes de la configuration +incluant set:<label>, y compris un pour la plage d'adresse ( +.B dhcp-range +) utilisée pour allouer l'adresse, un pour chaque entrée +.B dhcp-host +associée (auquel est rajouté le mot-clef "known" si une entrée dhcp-host +coïncide). + +Le label "bootp" est associé aux requêtes BOOTP, un label dont le nom est le +nom de l'interface sur laquelle la requête est arrivée. + +Pour les lignes de configuration comportant des éléments tag:<label>, +seules seront valides celles pour lesquels tous les labels correspondants +seront présents. C'est typiquement le cas des lignes dhcp-options. +Un +.B dhcp-option +possédant des labels sera utilisé de préférence à un +.B dhcp-option +sans label, pour peu que _tous_ les labels positionnés correspondent à l'ensemble +de labels décrit plus haut. +Le préfixe '!' sur un label est un indicateur de négation, ainsi +.B --dhcp=option=tag:!purple,3,1.2.3.4 +n'envoie l'option que lorsque le label "purple" n'est pas dans la liste de +labels définis pour l'hôte considéré. (dans le cas de l'utilisation dans une +ligne de commande au lieu d'un fichier de configuration, ne pas oublier +d'échapper le caractère !, qui est un méta-caractère d'interpréteur de commande +shell). +.PP +Veuillez noter que pour +.B dhcp-range +, les éléments tag:<label> et set:<label> sont tous les deux autorisés +pour sélectionner la plage à utiliser selon, par exemple, le dhcp-host, +et pour affecter l'option envoyée, sur la base de la plage sélectionnée. + +Ce système a évolué d'un système plus ancien et aux possibilités plus limitées, +et pour des raisons de compatibilité "net:" peut être utilisé à la place de +"tag:" et "set:" peut-être omis (à l'exception de +.B dhcp-host, +où "net:" peut-être utilisé à la place de "set:"). Pour les mêmes raisons, '#' +peut-être utilisé à la place de '!' pour indiquer la négation. +.PP +Le serveur DHCP intégré dans Dnsmasq fonctionne également en temps que serveur +BOOTP, pour peu que l'adresse MAC et l'adresse IP des clients soient fournies, +que ce soit par le biais de l'option +.B dhcp-host +ou dans le fichier +.I /etc/ethers +, et que l'option +.B dhcp-range +soit présente afin d'activer le serveur DHCP pour un réseau donné (L'option +.B --bootp-dynamic +supprime la nécessité des associations statiques). Le paramètre +"filename" (nom de fichier) de la requête BOOTP est utilisé comme label, ainsi +que le label "bootp", permettant un certain contrôle sur les options retournées +aux différentes classes d'hôtes. + +Il est possible de spécifier un nom d'interface à +.B dhcp-range +sous la forme "interface:<nom d'interface>". La sémantique est comme suit : +Pour le DHCP, s'il existe une autre valeur de dhcp-range pour laquelle +_aucun_ nom d'interface n'est donné, alors le nom d'interface est ignoré +et dnsmasq se comporte comme si la partie spécifiant l'interface n'existait +pas, sinon le service DHCP n'est fourni qu'aux interfaces mentionnées dans +les déclarations dhcp-range. Pour le DNS, si il n'y a pas d'option +.B --interface +ou +.B --listen-address +, alors le comportement n'est pas impacté par la spécification d'interface. Si +l'une ou l'autre de ces options est présente, alors les interfaces mentionnées +dans les plages d'adresses dhcp-range sont rajoutées à la liste de celles +où le service DNS est assuré. + +De manière similaire, +.B enable-tftp +peut prendre un nom d'interface, ce qui active le TFTP pour cette seule +interface, en ignorant les options +.B --interface +ou +.B --listen-address +De plus, +.B --tftp-secure +, +.B --tftp-unique-root +et +.B --tftp-no-blocksize +sont ignorées pour les requêtes sur de telles interfaces. (une directive +.B --tftp-root +donnant le chemin de la racine et une interface doit-être fournie). + +Ces règles peuvent paraître étrange à première vue, mais elles permettent +d'ajouter à la configuration de dnsmasq des lignes de configuration de la +forme "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" afin de fournir +un service DHCP et DNS sur cette interface, sans pour autant affecter les +services fournis sur d'autres interfaces, malgré l'absence de paramètres +"interface=<interface>" sur les autres lignes de configuration. +"enable-tftp=virt0" et "tftp-root=<root>,virt0" effectuent la même chose pour +TFTP. +L'idée de tout cela est de permettre l'addition de telles lignes +automatiquement par libvirt ou un système équivalent, sans perturbation +d'une configuration manuelle existant par ailleurs. + +.SH CODES DE SORTIE +.PP +0 - Dnsmasq s'est correctement lancé en tâche de fond, ou alors s'est +correctement terminé si le lancement en tâche de fond n'a pas été activé. +.PP +1 - Un problème de configuration a été détecté. +.PP +2 - Un problème est survenu avec un accès réseau (adresse déjà utilisée, +tentative d'utiliser un port privilégié sans les permissions nécessaires). +.PP +3 - Un problème est survenu avec une opération sur un système de fichier +(fichier ou répertoire manquant, permissions). +.PP +4 - Impossibilité d'allouer de la mémoire. +.PP +5 - Autre problème. +.PP +11 ou plus - un code de retour différent de 0 a été reçu lors de l'appel au +processus "init" du script des bails. Le code de retour de Dnsmasq correspond +au code de retour du script plus 10. + +.SH LIMITES +Les valeurs par défaut pour les limites de ressources de Dnsmasq sont en général +conservatrices et appropriées pour des utilisations embarquées sur des machines +de type routeur ayant des processeurs lents et une mémoire limitée. Sur du +matériel plus performant, il est possible d'augmenter les limites et de gérer +plus de clients. Les remarques suivantes s'appliquent à Dnsmasq version 2.37 et +ultérieur : les versions précédentes ne montaient pas en charge aussi bien. + +.PP +Dnsmasq est capable de gérer le DNS et DHCP pour au moins un millier de clients. +Pour cela, la durée des bail ne doit pas être très courte (moins d'une heure). +La valeur de +.B --dns-forward-max +peut-être augmentée : commencer par la rendre égale au nombre de clients et +l'augmenter si le DNS semble lent. Noter que la performance du DNS dépends +également de la performance des serveurs amonts. La taille du cache DNS peut- +être augmentée : la limite en dur est de 10000 entrées et la valeur par défaut +(150) est très basse. Envoyer un signal SIGUSR1 à Dnsmasq le fait émettre des +informations utiles pour paramétrer la taille de cache. Voir la section +.B NOTES +pour plus de détails. +.PP +Le serveur TFTP intégré est capable de plusieurs transferts de fichiers +simultanés : La limite absolue est liée au nombre maximal de descripteurs de +fichiers alloué à un processus et à la capacité de l'appel système select() à +gérer un grand nombre de HANDLE de fichier. Si la limite est fixée trop haut par +le biais de +.B --tftp-max +elle sera réduite et la limite actuelle sera enregistrée au démarrage. Il faut +noter que plus de transferts sont possible lorsque le même fichier est transmis +au lieu d'avoir un fichier différent pour chaque transfert. + +.PP +Il est possible d'utiliser Dnsmasq pour bloquer la publicité sur la toile +en associant des serveurs de publicité bien connus à l'adresse 127.0.0.1 ou +0.0.0.0 par le biais du fichier +.B /etc/hosts +ou d'un fichier d'hôte additionnel. Cette liste peut-être très longue, Dnsmasq +ayant été testé avec succès avec un million de noms. Cette taille de fichier +nécessite un processeur à 1 Ghz et environ 60 Mo de RAM. + +.SH INTERNATIONALISATION +Dnsmasq peut être compilé pour supporter l'internationalisation. Pour cela, +les cibles "all-i18n" et "install-i18n" doivent être données à make, en lieu +et place des cibles standards "all" et "install". Lorsque compilé avec le +support de l'internationalisation, dnsmasq supporte les noms de domaines +internationalisés ("internationalised domain names" ou IDN), et les messages de +traces ("logs") sont écrits dans la langue locale. Les noms de domaines dans +/etc/hosts, /etc/ethers et /etc/dnsmasq.conf contenant des caractères +non-ASCII seront transformés selon la représentation punycode interne +aux DNS. Veuillez noter que dnsmasq détermine la langue pour les messages +ainsi que le jeu de caractères susceptible d'être utilisé dans les fichiers +de configuration à partir de la variable d'environnement LANG. Ceci devrait +être configuré à la valeur par défaut du système par les scripts démarrant +dnsmasq. Lorsque les fichiers de configuration sont édités, veuillez faire +attention à le faire en utilisant la valeur de locale par défaut du système +et non une valeur spécifique à l'utilisateur, puisque dnsmasq n'a aucun +moyen de déterminer directement la valeur de jeu de caractère utilisé, +et assume de ce fait qu'il s'agit de la valeur par défaut du système. + +.SH FICHIERS +.IR /etc/dnsmasq.conf + +.IR /usr/local/etc/dnsmasq.conf +.IR /var/run/dnsmasq/resolv.conf +.IR /etc/ppp/resolv.conf +.IR /etc/dhcpc/resolv.conf + +.IR /etc/resolv.conf + +.IR /etc/hosts + +.IR /etc/ethers + +.IR /var/lib/misc/dnsmasq.leases + +.IR /var/db/dnsmasq.leases + +.IR /var/run/dnsmasq.pid +.SH VOIR AUSSI +.BR hosts (5), +.BR resolver (5) +.SH AUTEUR +Cette page de manuel a été écrite par Simon Kelley <simon@thekelleys.org.uk>. + +La traduction dans un français bancal a été commise par Gildas Le Nadan +<3ntr0p13@gmail.com> : Toute révision/correction permettant de corriger +orthographe ou grammaire mais surtout les éventuelles fautes de sens sera la +bienvenue! diff --git a/packaging/dnsmasq.spec b/packaging/dnsmasq.spec new file mode 100644 index 0000000..4045f59 --- /dev/null +++ b/packaging/dnsmasq.spec @@ -0,0 +1,40 @@ +Name: dnsmasq +Summary: dnsmasq, DNS forwarder. +Version: 2.57 +Release: 6 +Group: TO_BE/FILLED_IN +License: GPLv2 +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: pkgconfig(dbus-1) + +%description +Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP server. + +%prep +%setup -q + +%build +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} +make %{?jobs:-j%jobs} + +%post +mkdir -p /opt/var/lib/misc + +%install +rm -rf %{buildroot} +%make_install + +%files +%manifest dnsmasq.manifest +%{_bindir}/dnsmasq + +%changelog +* Tue Jan 15 2013 Seungyoun Ju <sy39.ju@samsung.com> 2.57-6 +- Send the indication for DHCP connection every time + +* Fri Nov 02 2012 Seungyoun Ju <sy39.ju@samsung.com> 2.57-5 +- Default manifest file is added + +* Mon Apr 16 2012 Seungyoun Ju <sy39.ju@samsung.com> 2.57-4 +- "/opt/var/lib/misc" directory for lease file is created explicitly diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..30ecb0e --- /dev/null +++ b/po/de.po @@ -0,0 +1,1511 @@ +# German translations for dnsmasq package. +# +# This revised version is (C) Copyright by +# Matthias Andree <matthias.andree@gmx.de>, 2010. +# It is subject to the GNU General Public License v2, +# or at your option, any later version. +# +# An older version of this file was originally put in the public domain by +# Simon Kelley <simon@thekelleys.org.uk>, 2005. +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.53rc1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2010-05-24 16:29+0200\n" +"Last-Translator: Matthias Andree <matthias.andree@gmx.de>\n" +"Language-Team: German <de@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cache.c:761 +#, c-format +msgid "failed to load names from %s: %s" +msgstr "Fehler beim Laden der Namen von %s: %s" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "Fehlerhafte Adresse in %s Zeile %d" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "Fehlerhafter Name in %s Zeile %d" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "%s gelesen - %d Adressen" + +#: cache.c:899 +msgid "cleared cache" +msgstr "Cache geleert" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "%s ist ein CNAME, weise es der DHCP-Lease von %s nicht zu" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "Name %s wurde dem DHCP-Lease von %s nicht zugewiesen, da der Name in %s bereits mit Adresse %s existiert" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "Zeit %lu" + +#: cache.c:1040 +#, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "Cache Größe %d, %d/%d Cache-Einfügungen verwendeten nicht abgelaufene Cache-Einträge wieder." + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "%u weitergeleitete Anfragen, %u lokal beantwortete Anfragen" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "Server %s#%d: %u Anfragen gesendet, %u erneut versucht oder fehlgeschlagen" + +#: util.c:57 +#, c-format +msgid "failed to seed the random number generator: %s" +msgstr "Konnte den Zufallszahlengenerator nicht initialisieren: %s" + +#: util.c:189 +msgid "failed to allocate memory" +msgstr "Konnte Speicher nicht belegen" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "Speicher nicht verfügbar" + +#: util.c:237 +#, c-format +msgid "cannot create pipe: %s" +msgstr "Konnte Pipe nicht erzeugen: %s" + +#: util.c:245 +#, c-format +msgid "failed to allocate %d bytes" +msgstr "Konnte %d Bytes nicht belegen" + +# @Simon: not perfect but I cannot get nearer right now. +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "unendlich" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "Lokale abzuhörende Adresse(n) angeben." + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "IP-Adresse für alle Hosts in angebenen Domänen festlegen." + +# FIXME: the English test is not to the point. Just use a shortened description +# from the manpage instead. -- MA +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "Für private Adressbereiche nach RFC1918 \"keine solche Domain\" liefern." + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "Diese IP-Adresse als NXDOMAIN interpretieren (wehrt \"Suchhilfen\" ab)." + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "Größe des Caches (Zahl der Einträge) festlegen (Voreinstellung: %s)." + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "Konfigurationsdatei festlegen (Voreinstellung: %s)." + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "NICHT in den Hintergrund gehen: Betrieb im Debug-Modus" + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "Anfragen ohne Domänen-Teil NICHT weiterschicken." + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "Für lokale Einträge MX-Einträge liefern, die auf sich selbst zeigen." + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "Erweitere einfache Namen in /etc/hosts mit der Domänen-Endung." + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "'unechte' DNS-Anfragen von Windows-Rechnern nicht weiterleiten" + +# @Simon: I'm a bit unsure about "spurious" +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "DHCP für angegebenen Bereich und Dauer einschalten" + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "Nach dem Start in diese Benutzergruppe wechseln (Voreinstellung %s)." + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "Adresse oder Hostnamen für einen angegebenen Computer setzen." + +#: option.c:258 +#, fuzzy +msgid "Read DHCP host specs from file." +msgstr "DHCP-Host-Angaben aus Datei lesen" + +#: option.c:259 +#, fuzzy +msgid "Read DHCP option specs from file." +msgstr "DHCP-Optionen aus Datei lesen" + +#: option.c:260 +#, fuzzy +msgid "Evaluate conditional tag expression." +msgstr "Auswertung eines Ausdrucks bedingter Marken" + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "%s-Datei NICHT laden." + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "Hosts-Datei festlegen, die zusätzlich zu %s gelesen wird." + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "Schnittstelle(n) zum Empfang festlegen." + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "Schnittstelle(n) festlegen, die NICHT empfangen sollen." + +#: option.c:265 +msgid "Map DHCP user class to tag." +msgstr "DHCP-Benutzerklasse auf Marke abbilden." + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "RFC3046 \"circuit-id\" auf Marke abbilden." + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "RFC3046 \"remote-id\" auf Marke abbilden." + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "RFC3993 \"subscriber-id\" auf Marke abbilden." + +#: option.c:269 +msgid "Don't do DHCP for hosts with tag set." +msgstr "Kein DHCP für Hosts mit gesetzter Marke verwenden." + +#: option.c:270 +msgid "Force broadcast replies for hosts with tag set." +msgstr "Rundsendung für Hosts mit gesetzter Marke erzwingen." + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "NICHT in den Hintergrund wechseln, NICHT im Debug-Modus laufen." + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "Voraussetzen, dass wir der einzige DHCP-Server im lokalen Netz sind." + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "Festlegen, wo DHCP-Leases gespeichert werden (Voreinstellung %s)." + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "MX-Einträge für lokale Hosts liefern." + +#: option.c:275 +msgid "Specify an MX record." +msgstr "Einen MX-Eintrag festlegen." + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "BOOTP-Optionen für DHCP-Server festlegen." + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "%s-Datei NICHT abfragen, nur bei SIGHUP neu laden." + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "Fehlerhafte Suchergebnisse NICHT zwischenspeichern." + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "Namensserver streng in der in %s angegebenen Reihenfolge verwenden." + +#: option.c:280 +msgid "Specify options to be sent to DHCP clients." +msgstr "Optionen festlegen, die an DHCP-Klienten gesendet werden." + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "DHCP-Option, die selbst ohne Klientenanfrage gesendet wird." + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "Port zum Abhören der DNS-Anfragen festlegen (53 voreingestellt)." + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "Maximale unterstützte UDP-Paketgröße für EDNS.0 (Voreinstellung %s)." + +#: option.c:284 +msgid "Log DNS queries." +msgstr "DNS-Anfragen protokollieren." + +#: option.c:285 +msgid "Force the originating port for upstream DNS queries." +msgstr "Ausgehenden Port erzwingen für DNS-Anfragen an vorgelagerte Server." + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "resolv.conf NICHT lesen." + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "Pfad zu resolv.conf festlegen (%s voreingestellt)." + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "Adresse(n) vorgelagerter Server festlegen, optional mit Domänen." + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "Anfragen für angegebene Domänen niemals weiterleiten." + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "Domäne festlegen, die für DHCP-Leases zugewiesen wird." + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "Voreingestelltes Ziel für MX-Einträge festlegen." + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "Gültigkeitsdauer für Antworten aus /etc/hosts festlegen." + +#: option.c:293 +msgid "Specify time-to-live in seconds for negative caching." +msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen." + +#: option.c:294 +#, fuzzy +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen." + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "Nach dem Start diese Benutzerrechte annehmen (%s voreingestellt)." + +#: option.c:296 +msgid "Map DHCP vendor class to tag." +msgstr "DHCP-\"vendor class\" auf Marke abbilden." + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "dnsmasq-Version und Urheberrecht anzeigen." + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "IPv4-Adressen von vorgelagerten Servern übersetzen." + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "SRV-Eintrag festlegen." + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "Diese Hilfe anzeigen. Benutzen Sie --help dhcp für bekannte DHCP-Optionen." + +#: option.c:301 +#, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "Dateipfad für Prozesskennung (PID) festlegen (Voreinstellung: %s)." + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "Höchstzahl der DHCP-Leases festlegen (%s voreingestellt)." + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "DNS-Anfragen abhängig der Emfpangsschnittstelle beantworten." + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "DNS-TXT-Eintrag festlegen." + +#: option.c:305 +msgid "Specify PTR DNS record." +msgstr "DNS-PTR-Eintrag festlegen." + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "Schnittstellennamen zur IPv4-Adresse des Interfaces auflösen." + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "Nur an verwendete Schnittstellen binden." + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "Statische DHCP-Host-Information aus %s lesen." + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "DBus-Schnittstelle zum Festlegen vorgelagerter Server usw. festlegen." + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "Auf dieser Schnittstelle kein DHCP anbieten, sondern nur DNS." + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "Dynamische Adressbelegung für bootp einschalten." + +#: option.c:312 +msgid "Map MAC address (with wildcards) to option set." +msgstr "MAC-Adresse (mit Jokerzeichen) auf Netzmarke abbilden." + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "DHCP-Anfragen von Alias-Schnittstellen für die Hauptschnittstelle beantworten." + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "ICMP-Echo-Adressprüfung im DHCP-Server abschalten." + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "Skript, das bei Erzeugung/Löschung einer DHCP-Lease laufen soll." + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "Konfiguration aus allen Dateien in diesem Verzeichnis lesen." + +#: option.c:317 +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "Für diese Syslog-Anlage oder in Datei loggen (Voreinstellung DAEMON)." + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "Keine Lease-Datei benützen." + +#: option.c:319 +#, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "Höchstzahl nebenläufiger DNS-Anfragen (%s voreingestellt)." + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "DNS-Cache beim Neuladen von %s löschen." + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "Von DHCP-Clients gelieferte Hostnamen ignorieren." + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "Dateinamen und Server-Datenfehler für zusätzliche DHCP-Optionen NICHT wiederverwenden." + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "Eingebauten Nur-Lese-TFTP-Server einschalten." + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "Nur vom festgelegten Unterbaum Dateien per TFTP exportieren." + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "IP-Adresse des Klienten an tftp-root anhängen." + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "Zugriff nur auf Dateien gestatten, die dem dnsmasq aufrufenden Benutzer gehören." + +#: option.c:327 +#, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "Höchstzahl nebenläufiger TFTP-Ãœbertragungen (%s voreingestellt)." + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "TFTP-Blockgrößen-Erweiterung abschalten." + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "Bereich für vorübergehende Ports für TFTP-Ãœbertragungen." + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "Erweiterte DHCP-Protokollierung." + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "Asynchrone Protokollierung einschalten, opt. Warteschlangenlänge festlegen." + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "DNS-Rebinding unterbinden, private IP-Bereiche bei der Auflösung ausfiltern." + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "Auflösung zu 127.0.0.0/8 erlauben, für RBL-Server." + +#: option.c:334 +#, fuzzy +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "DNS-Rebind-Schutz für diese Domäne sperren." + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "DNS-Anfragen immer an alle Server weiterleiten." + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "Marke setzen, wenn Klient eine entsprechende Option anfragt." + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "Alternative Ports für DHCP verwenden." + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "Lease-Änderungs-Skript mit den Rechten dieses Nutzers ausführen." + +#: option.c:339 +msgid "Specify NAPTR DNS record." +msgstr "DNS-NAPTR-Eintrag festlegen." + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "Niedrigsten verfügbaren Port für Ãœbertragung von DNS-Anfragen festlegen." + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "Für DHCP-Klienten nur vollständig bestimmte Domänennamen benutzen." + +# FIXME: probably typo in original message. -- MA +#: option.c:342 +#, fuzzy +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "Für namenlose Klienten die Hostnamen MAC-basiert erzeugen." + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "Diese DHCP-Relais als vollwertige Proxies verwenden." + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "Alias für LOKALEN DNS-Namen festlegen." + +#: option.c:345 +msgid "Prompt to send to PXE clients." +msgstr "Aufforderung, die an PXE-Klienten geschickt wird." + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "Boot-Dienst für PXE-Menü." + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "Konfigurationssyntax prüfen." + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +#: option.c:349 +#, fuzzy +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "IPv4-Adressen von vorgelagerten Servern übersetzen." + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" +"Verwendung: dnsmasq [Optionen]\n" +"\n" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "Auf der Befehlszeile nur kurze Optionen verwenden!\n" + +#: option.c:642 +#, c-format +msgid "Valid options are:\n" +msgstr "Gültige Optionen sind:\n" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "Bekannte DHCP-Optionen:\n" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "Fehlerhafte DHCP-Option" + +#: option.c:860 +msgid "bad IP address" +msgstr "Fehlerhafte IP-Adresse" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "Fehlerhafte Domäne in DHCP-Option" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "DHCP-Option zu lang" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "Unzulässige dhcp-match-Option" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "unzulässig wiederholte Markierung" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "unzulässig wiederholtes Schlüsselwort" + +#: option.c:1147 option.c:3030 +#, c-format +msgid "cannot access directory %s: %s" +msgstr "Kann auf Verzeichnis %s nicht zugreifen: %s" + +#: option.c:1178 tftp.c:460 +#, c-format +msgid "cannot access %s: %s" +msgstr "Kann auf %s nicht zugreifen: %s" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "unzulässige MX-Präferenz-Angabe" + +#: option.c:1270 +msgid "bad MX name" +msgstr "unzulässiger MX-Name" + +#: option.c:1284 +msgid "bad MX target" +msgstr "unzulässiges MX-Ziel" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "unter uClinux ist die Skriptausführung nicht möglich" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "Neuübersetzung mit HAVE_SCRIPT nötig, um Lease-Änderungs-Skripte auszuführen" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "unzulässiger Port" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "Schnittstellenbindung nicht unterstützt" + +#: option.c:1791 +msgid "bad port range" +msgstr "unzulässiger Portbereich" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "unzulässige Brücken-Schnittstelle" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "unzulässiger DHCP-Bereich" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "nur eine Marke zulässig" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "inkonsistenter DHCP-Bereich" + +#: option.c:2019 option.c:2045 +msgid "bad hex constant" +msgstr "" + +#: option.c:2107 +msgid "bad DHCP host name" +msgstr "unzulässiger DHCP-Hostname" + +#: option.c:2188 +msgid "bad tag-if" +msgstr "unzulässige bedingte Marke (tag-if)" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "unzulässige Portnummer" + +#: option.c:2529 +msgid "bad dhcp-proxy address" +msgstr "Fehlerhafte DHCP-Proxy-Adresse" + +#: option.c:2569 +msgid "invalid alias range" +msgstr "unzulässiger Alias-Bereich" + +#: option.c:2582 +msgid "bad interface name" +msgstr "unzulässiger Schnittestellenname" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "unzulässiger CNAME" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "doppelter CNAME" + +#: option.c:2632 +msgid "bad PTR record" +msgstr "unzulässiger PTR-Eintrag" + +#: option.c:2663 +msgid "bad NAPTR record" +msgstr "unzulässiger NAPTR-Eintrag" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "unzulässiger TXT-Eintrag" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "unzulässiger SRV-Eintrag" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "unzulässiges SRV-Ziel" + +#: option.c:2759 +msgid "invalid priority" +msgstr "unzulässige Priorität" + +#: option.c:2766 +msgid "invalid weight" +msgstr "unzulässige Wichtung" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "unzulässige Option (prüfen Sie, ob dnsmasq mit DHCP/TFTP/DBus-Unterstützt übersetzt wurde)" + +#: option.c:2849 +msgid "missing \"" +msgstr "fehlende \\\"" + +#: option.c:2908 +msgid "bad option" +msgstr "unzulässige Option" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "überschüssiger Parameter" + +#: option.c:2912 +msgid "missing parameter" +msgstr "fehler Parameter" + +#: option.c:2916 +msgid "error" +msgstr "Fehler" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "%s in Zeile %d von %%s" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "kann %s nicht lesen: %s" + +#: option.c:3151 option.c:3187 +#, c-format +msgid "read %s" +msgstr "%s gelesen" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "Dnsmasq Version %s %s\n" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" +"Ãœbersetzungs-Optionen %s\n" +"\n" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "Für diese Software wird ABSOLUT KEINE GARANTIE gewährt.\n" + +# FIXME: this must be one long string! -- MA +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "" + +#: option.c:3273 +#, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "" + +#: option.c:3284 +msgid "try --help" +msgstr "versuchen Sie --help" + +#: option.c:3286 +msgid "try -w" +msgstr "versuchen Sie -w" + +#: option.c:3289 +#, c-format +msgid "bad command line options: %s" +msgstr "unzulässige Optionen auf der Befehlszeile: %s" + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "kann Hostnamen nicht ermitteln: %s" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "mit -n/--no-poll ist nur eine resolv.conf-Datei zulässig." + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "Um die Domäne zu lesen, muss genau eine resolv.conf-Datei verwendet werden." + +#: option.c:3371 network.c:848 dhcp.c:814 +#, c-format +msgid "failed to read %s: %s" +msgstr "konnte %s nicht lesen: %s" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "keine \"search\"-Anweisung in %s gefunden" + +#: option.c:3409 +#, fuzzy +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "für --dhcp-fqdn muss eine Domäne vorausgewählt werden" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "Syntaxprüfung OK" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "Namensserver %s hat eine rekursive Anfrage verweigert" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s" + +#: network.c:171 +#, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "unbekannte Schnittstelle %s in bridge-interface" + +#: network.c:380 +#, fuzzy, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "Konnte Empfangs-Socket nicht erzeugen: %s" + +#: network.c:746 +#, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "konnte nicht an Server-Socket für %s binden: %s" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "ignoriere Namensserver %s - lokale Schnittstelle" + +#: network.c:794 +#, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "ignoriere Namensserver %s - kann Socket nicht erzeugen/binden: %s" + +# FIXME: this isn't translatable - always provide full strings, do not assemble yourself! -- MA +#: network.c:811 +msgid "unqualified" +msgstr "" + +#: network.c:811 +msgid "names" +msgstr "" + +#: network.c:813 +msgid "default" +msgstr "" + +#: network.c:815 +msgid "domain" +msgstr "" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "" + +#: network.c:820 +#, c-format +msgid "using standard nameservers for %s %s" +msgstr "" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "" + +#: network.c:825 +#, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "" + +#: dnsmasq.c:148 +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "TFTP-Server nicht verfügbar, setzen Sie HAVE_TFTP in src/config.h" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "asynchrone Protokollierung unter Solaris nicht verfügbar" + +#: dnsmasq.c:158 +#, fuzzy +msgid "asychronous logging is not available under Android" +msgstr "asynchrone Protokollierung unter Solaris nicht verfügbar" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "konnte Schnitstellenliste nicht beziehen: %s" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "unbekannte Schnittstelle %s" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "keine Schnittstelle mit Adresse %s" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "DBus-Fehler: %s" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "Unbekannter Benutzer oder Gruppe: %s" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "kann nicht ins Wurzelverzeichnis des Dateisystems wechseln: %s" + +# FIXME: this and the next would need commas after the version +#: dnsmasq.c:455 +#, c-format +msgid "started, version %s DNS disabled" +msgstr "gestartet, Version %s, DNS abgeschaltet" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "gestartet, Version %s, Cachegröße %d" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "Ãœbersetzungsoptionen: %s" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "DBus-Unterstützung eingeschaltet: mit Systembus verbunden" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "DBus-Unterstützung eingeschaltet: warte auf Systembus-Verbindung" + +#: dnsmasq.c:474 +#, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "Warnung: konnte den Besitzer von %s nicht ändern: %s" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "Aktiviere --bind-interfaces wegen Einschränkungen des Betriebssystems" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "Warnung: Schnittstelle %s existiert derzeit nicht" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "Warnung: Ignoriere \"resolv-file\", weil \"no-resolv\" aktiv ist" + +#: dnsmasq.c:491 +msgid "warning: no upstream servers configured" +msgstr "Warnung: keine vorgelagerten (Upstream) Server konfiguriert" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "asynchrone Protokollierung eingeschaltet, Warteschlange fasst %d Nachrichten" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "DHCP, nur statische Leases auf %.0s%s, Lease-Zeit %s" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "DHCP, Proxy im Subnetz %.0s%s%.0s" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "DHCP, IP-Bereich %s - %s, Lease-Zeit %s " + +#: dnsmasq.c:526 +msgid "root is " +msgstr "FIXME: this and the next few must be full strings to be translatable - do not assemble in code" + +#: dnsmasq.c:526 +msgid "enabled" +msgstr "" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "Begrenze gleichzeitige TFTP-Ãœbertragungen auf maximal %d" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "Mit System-DBus verbunden" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "kann nicht in den Hintergrund abspalten: %s" + +#: dnsmasq.c:778 +#, c-format +msgid "failed to create helper: %s" +msgstr "kann Helfer nicht erzeugen: %s" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "kann \"capabilities\" nicht setzen: %s" + +#: dnsmasq.c:785 +#, c-format +msgid "failed to change user-id to %s: %s" +msgstr "Kann nicht Benutzerrechte %s annehmen: %s" + +#: dnsmasq.c:790 +#, c-format +msgid "failed to change group-id to %s: %s" +msgstr "Kann nicht Gruppenrechte %s annehmen: %s" + +#: dnsmasq.c:793 +#, c-format +msgid "failed to open pidfile %s: %s" +msgstr "kann die Prozessidentifikations-(PID)-Datei %s nicht öffnen: %s" + +#: dnsmasq.c:796 +#, c-format +msgid "cannot open %s: %s" +msgstr "kann %s nicht öffnen: %s" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "Tochterprozess durch Signal %d zerstört" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "Tochterprozess beendete sich mit Status %d" + +#: dnsmasq.c:859 +#, c-format +msgid "failed to execute %s: %s" +msgstr "konnte %s nicht ausführen: %s" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "beende nach Empfang von SIGTERM" + +#: dnsmasq.c:931 +#, c-format +msgid "failed to access %s: %s" +msgstr "konnte auf %s nicht zugreifen: %s" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "lese %s" + +#: dnsmasq.c:972 +#, c-format +msgid "no servers found in %s, will retry" +msgstr "keine Server in %s gefunden, werde es später neu versuchen" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "kann DHCP-Socket nicht erzeugen: %s" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "kann Optionen für DHCP-Socket nicht setzen: %s" + +#: dhcp.c:65 +#, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "kann SO_REUSE{ADDR|PORT} für DHCP-Socket nicht aktivieren: %s" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "kann nicht an DHCP-Server-Socket binden: %s" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "kann ICMP-Rohdaten-Socket nicht erzeugen: %s." + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "DHCP-Paket ohne Adresse an Schnittstelle %s empfangen" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "DHCP-Bereich %s - %s passt nicht zur Netzmaske %s" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "ungültige Zeile %2$d in Datei %1$s" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "ignoriere %s Zeile %d, doppelter Name oder doppelte IP-Adresse" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "doppelte IP-Adresse %s in \"dhcp-config\"-Anweisung" + +#: dhcp.c:981 +#, c-format +msgid "duplicate IP address %s in %s." +msgstr "doppelte IP-Adresse %s in %s." + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "%s hat mehr als eine Adresse in hosts-Datei, benutze %s für DHCP" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "doppelte IP-Adresse %s (%s) in \"dhcp-config\"-Anweisung" + +#: lease.c:67 +#, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "kann Lease-Datei %s nicht öffnen: %s" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "zu viele Leases gespeichert" + +#: lease.c:129 +#, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "kann Lease-Start-Skript %s nicht ausführen: %s" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "Lease-Start-Skript beendete sich mit Code %s" + +# FIXME: This should be %u s also in English according to NIST and SI rules. -- MA +#: lease.c:235 +#, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "Konnte %s nicht schreiben: %s (Neuversuch in %u s)" + +# FIXME: this and the next few are not translatable. Please provide full +# strings, do not programmatically assemble them. +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "" + +#: rfc2131.c:316 +msgid "via" +msgstr "" + +#: rfc2131.c:331 +#, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "%u verfügbare(s) DHCP-Subnetz: %s/%s" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "%u verfügbare(r) DHCP-Bereich: %s - %s" + +# FIXME: do not programmatically assemble strings - untranslatable +#: rfc2131.c:363 +msgid "disabled" +msgstr "" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "%u Klient stellt Name bereit: %s" + +#: rfc2131.c:700 +#, c-format +msgid "%u vendor class: %s" +msgstr "%u \"Vendor class\": %s" + +#: rfc2131.c:702 +#, c-format +msgid "%u user class: %s" +msgstr "%u Benutzerklasse: %s" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "PXE BIS nicht unterstützt" + +#: rfc2131.c:886 +#, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "schalte statische DHCP-Adresse %s für %s ab" + +# FIXME: do not assemble +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "benutze konfigurierte Adresse %s nicht, weil sie an %s verleast ist" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "benutze konfigurierte Adresse %s nicht, weil sie von Server/Relais verwendet wird" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "benutze konfigurierte Adresse %s nicht, weil sie zuvor abgelehnt wurde" + +# FIXME: do not assemble +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "Gebe Lease von %2$s an %1$s auf" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "%u Marken: %s" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "%u Name der Bootdatei: %s" + +#: rfc2131.c:1732 +#, c-format +msgid "%u server name: %s" +msgstr "%u Servername: %s" + +#: rfc2131.c:1746 +#, c-format +msgid "%u next server: %s" +msgstr "%u nächster Server: %s" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "%u Antwort per Rundsendung" + +#: rfc2131.c:1812 +#, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "kann DHCP/BOOTP-Opition %d nicht setzen: kein Platz mehr im Paket" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "PXE-Menüeintrag zu groß" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "Ignoriere Domäne %s für DHCP-Hostnamen %s" + +#: rfc2131.c:2189 +#, c-format +msgid "%u requested options: %s" +msgstr "%u angeforderte Optionen: %s" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "Kann RFC3925-Option nicht senden: zu viele Optionen für Unternehmen Nr. %d" + +#: netlink.c:70 +#, c-format +msgid "cannot create netlink socket: %s" +msgstr "kann Netlink-Socket nicht erzeugen: %s" + +#: netlink.c:288 +#, c-format +msgid "netlink returns error: %s" +msgstr "Netlink liefert Fehler %s" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "Versuch, via DBus eine IPv6-Serveradresse zu setzen: keine IPv6-Unterstützung" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "vorgelagerte Server von DBus gesetzt" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "konnte Steuerungsprogramm für DBus-Nachrichten nicht anmelden" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "konnte DHCP-BPF-Socket nicht einrichten: %s" + +#: bpf.c:245 +#, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "DHCP-Anfrage für nicht unterstützen Hardwaretyp (%d) auf %s empfangen" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "konnte keinen freien Port für TFTP bekommen" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "nicht unterstützte Anfrage von %s" + +#: tftp.c:406 +#, c-format +msgid "file %s not found" +msgstr "Datei %s nicht gefunden" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "Fehler %d %s von %s empfangen" + +#: tftp.c:554 +#, c-format +msgid "failed sending %s to %s" +msgstr "konnte %s nicht an %s senden" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "%s an %s verschickt" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "Ãœberlauf: %d Protokolleinträge verloren" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "Protokollierung fehlgeschlagen: %s" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "Start fehlgeschlagen" + +#~ msgid "only one dhcp-hostsfile allowed" +#~ msgstr "nur eine DHCP-Hostdatei (dhcp-hostsfile) zulässig" + +#~ msgid "only one dhcp-optsfile allowed" +#~ msgstr "nur eine DHCP-Optionsdatei (dhcp-optsfile) zulässig" + +#~ msgid "files nested too deep in %s" +#~ msgstr "Dateien in %s zu tief verschachtelt" + +#~ msgid "TXT record string too long" +#~ msgstr "TXT-Eintrag zu lang" + +#~ msgid "failed to set IPV6 options on listening socket: %s" +#~ msgstr "konnte IPV6-Optionen auf Empfangs-Socket nicht einstellen: %s" + +#~ msgid "failed to bind listening socket for %s: %s" +#~ msgstr "konnte Empfangs-Socket nicht an %s binden: %s" + +#~ msgid "failed to listen on socket: %s" +#~ msgstr "konnte Socket nicht zum Empfang einrichten: %s" + +#~ msgid "failed to create TFTP socket: %s" +#~ msgstr "konnte TFTP-Socket nicht erzeugen: %s" diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..efdd24e --- /dev/null +++ b/po/es.po @@ -0,0 +1,1575 @@ +# Spanish translations for dnsmasq package. +# This file is put in the public domain. +# Christopher Chatham <chrislinux@gmail.com>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.24\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2005-10-07 11:04+0100\n" +"Last-Translator: Christopher Chatham <chrislinux@gmail.com>\n" +"Language-Team: Spanish <es@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cache.c:761 +#, fuzzy, c-format +msgid "failed to load names from %s: %s" +msgstr "no se pudo cargar nombres desde %s: %s" + +#: cache.c:795 dhcp.c:865 +#, fuzzy, c-format +msgid "bad address at %s line %d" +msgstr "dirección errónea en %s línea %d" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "nombre erróneo en %s línea %d" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "direcciónes %s - %d leídas" + +#: cache.c:899 +msgid "cleared cache" +msgstr "el caché fue liberado" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "%s es un CNAME, no se le está dando al arriendo DHCP de %s" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "no otorgando nombre %s al arriendo DHCP de %s porque el nombre existe en %s con dirección %s" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "tiempo %lu" + +#: cache.c:1040 +#, fuzzy, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "tamaño de caché %d, %d/%d inserciónes de caché reutilizaron objetos no vencidos." + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "búsquedas reenviadas %u, búsquedas respondidas localmente %u" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "servidor %s#%d: búsquedas enviadas %u, reintentadas o fallidas %u" + +#: util.c:57 +#, fuzzy, c-format +msgid "failed to seed the random number generator: %s" +msgstr "no se pudo crear valor semilla para el generador de números aleatorios: %s" + +#: util.c:189 +#, fuzzy +msgid "failed to allocate memory" +msgstr "no se pudo asignar memoria" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "no se pudo adquirir memoria" + +#: util.c:237 +#, fuzzy, c-format +msgid "cannot create pipe: %s" +msgstr "no se puede crear pipe: %s" + +#: util.c:245 +#, fuzzy, c-format +msgid "failed to allocate %d bytes" +msgstr "no se pudo asignar %d bytes" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "infinito" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "Especificar dirección(es) locales dónde escuchar." + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "Retornar ipaddr (dirección IP) para todos los hosts en los dominios especificados." + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "Falsificar búsquedas reversas para rangos de dirección privados RFC1918." + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "Tratar ipaddr (dirección IP) como NXDOMAIN (derrota comodín Verisign)." + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "Especificar tamaño de caché en cuanto a cantidad de objetos (%s por predeterminado)." + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "Especificar archivo de configuración (%s por predeterminado)." + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "NO hacer un fork hacia el fondo: correr en modo debug." + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "NO reenviar búsquedas sin parte de dominio." + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "Retornar expedientes MX auto-señaladores para hosts locales." + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "Expandir nombres simples en /etc/hosts con domain-suffix (sufijo de dominio)." + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "No reenviar pedidos DNS falsos desde máquinas Windows." + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "Habilitar DHCP dentro del rango brindado con duración del arriendo." + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "Cambiar a este grupo después del inicio (%s por predeterminado)." + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "Fijar dirección o nombre de host para una máquina especificada." + +#: option.c:258 +#, fuzzy +msgid "Read DHCP host specs from file." +msgstr "Leer especificaciones DHCP de host desde archivo" + +#: option.c:259 +#, fuzzy +msgid "Read DHCP option specs from file." +msgstr "Leer opciones DHCP de host desde archivo" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "Evaluar expresión condicional de etiqueta." + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "NO cargar archivo %s." + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "Especificar un archivo de hosts para ser leído adicionalmente a %s." + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "Especificar interface(s) donde escuchar." + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "Especificar interface(s) donde NO escuchar." + +#: option.c:265 +#, fuzzy +msgid "Map DHCP user class to tag." +msgstr "Trazar clase de usuario DHCP a etiqueta." + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "Trazar circuit-id (identificación de circuito) RFC3046 a etiqueta." + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "Trazar remote-id (identificación remota) RFC3046 a etiqueta." + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "Trazar subscriber-id (identificación de suscritor) RFC3993 a etiqueta." + +#: option.c:269 +#, fuzzy +msgid "Don't do DHCP for hosts with tag set." +msgstr "No hacer DHCP para hosts con etiqueta fijada." + +#: option.c:270 +#, fuzzy +msgid "Force broadcast replies for hosts with tag set." +msgstr "Forzar respuestas broadcast para hosts con etiqueta fijada." + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "NO hacer un fork hacia el fondo, NO correr en modo debug." + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "Asumir que somos el único servidor DHCP en la red local." + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "Especificar donde almacenar arriendos DHCP (%s por predeterminado)." + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "Retornar expedientes MX para hosts locales." + +#: option.c:275 +msgid "Specify an MX record." +msgstr "Especificar un expediente MX." + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "Especificar opciones BOOTP a servidor DHCP." + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "NO revisar archivo %s periódicamente, recargar solo con SIGHUP." + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "NO almacenar en caché resultados de búsquedas fallidas." + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "Usar servidores DNS estrictamente en el órden brindado en %s." + +#: option.c:280 +#, fuzzy +msgid "Specify options to be sent to DHCP clients." +msgstr "Especificar opciones para ser enviadas a clientes DHCP." + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "Opción DHCP enviada aún si el cliente no la pide." + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "Especificar puerto donde escuchar por búsquedas DNS (53 por predeterminado)." + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "Tamaño máximo de paquetes UDP soportado para EDNS.0 (%s por predeterminado)." + +#: option.c:284 +#, fuzzy +msgid "Log DNS queries." +msgstr "Bitacorear búsquedas DNS." + +#: option.c:285 +#, fuzzy +msgid "Force the originating port for upstream DNS queries." +msgstr "Enforzar el puerto original para búsquedas DNS upstream." + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "NO leer resolv.conf." + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "Especificar el path hacia resolv.conf (%s por predeterminado)." + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "Especificar dirección(es) de servidores upstream con dominios opcionales." + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "Nunca reenviar búsquedas a dominios especificados." + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "Especificar el dominio para ser asignado en arriendos DHCP." + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "Especificar destino predeterminado en un expediente MX." + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "Especificar tiempo de vida en segundos para respuestas desde /etc/hosts." + +#: option.c:293 +#, fuzzy +msgid "Specify time-to-live in seconds for negative caching." +msgstr "Especificar tiempo de vida en segundos para caché negativo." + +#: option.c:294 +#, fuzzy +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "Especificar tiempo de vida en segundos para respuestas desde /etc/hosts." + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "Cambiar a este usuario despues del inicio (%s por predeterminado)." + +#: option.c:296 +#, fuzzy +msgid "Map DHCP vendor class to tag." +msgstr "Trazar clase de vendedor DHCP a etiqueta." + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "Mostrar información sobre la versión y copyright de dnsmasq." + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "Traducir direcciones IPv4 desde servidores upstream." + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "Especificar un expediente SRV." + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "Mostrar este mensaje. Usar --help dhcp para opciones DHCP conocidas." + +#: option.c:301 +#, fuzzy, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "Especificar path de archivo PID (%s por predeterminado)." + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "Especificar número máximo de arriendos DHCP (%s por predeterminado)." + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "Responder a búsquedas DNS en base a la interface a la cuál fueron enviadas." + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "Especificar expediente DNS TXT." + +#: option.c:305 +#, fuzzy +msgid "Specify PTR DNS record." +msgstr "Especificar expediente DNS PTR." + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "Otorgar nombre DNS a dirección IPv4 de interface." + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "Acoplar solo a interfaces en uso." + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "Leer información sobre hosts DHCP estáticos desde %s." + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "Habilitar la interface DBus para fijar servidores upstream, etc." + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "No proveer DHCP en esta interface, sólo proveer DNS." + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "Habilitar alocación dinámica de direcciónes para BOOTP." + +#: option.c:312 +#, fuzzy +msgid "Map MAC address (with wildcards) to option set." +msgstr "Trazar dirección MAC (con comodínes) a opción fijada." + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "Tratar pedidos DHCP en alias como si llegaran de la interface." + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "Deshabilitar verificación de direcciónes para echo ICMP en el servidor DHCP." + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "Archivo guión para ejecutar cuando se crea o destruye un arriendo DHCP." + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "Leer configuración desde todos los archivos en este directorio." + +#: option.c:317 +#, fuzzy +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "Bitacorear a esta facilidad syslog o archivo. (DAEMON por predeterminado)" + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "No usar archivo de arriendos." + +#: option.c:319 +#, fuzzy, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "Número máximo de búsquedas DNS simultáneas. (%s por predeterminado)" + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "Liberar caché DNS al recargar %s." + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "Ignorar nombres de host brindados por clientes DHCP." + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "NO reutilizar campos de nombre de archivo y servidor para opciones DHCP extra." + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "Habilitar servidor integrado TFTP solo-lectura." + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "Exportar archivos vía TFTP solo del sub-árbol especificado." + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "Agregar IP de cliente a tftp-root." + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "Permitir acceso solo a archivos pertenecientes al usuario que corre dnsmasq." + +#: option.c:327 +#, fuzzy, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "Número máximo de transferencias TFTP simultáneas (%s por predeterminado)." + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "Deshabilitar la extensión TFTP blocksize (tamaño de bloque)." + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "Rango de puertos efímeros para ser usados por transferencias TFTP." + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "Bitacoreo extra para DHCP." + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "Habilitar bitacoreo asincrónico; opcionalmente fijar tamaño de cola." + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "Detener revinculación DNS. Filtrar rangos de IP privados al resolver." + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "Permitir revinculación de 127.0.0.0/8, para servidores RBL." + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "Inhibir protección de revinculación DNS en este dominio." + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "Siempre realizar búsquedas DNS a todos los servidores." + +#: option.c:336 +#, fuzzy +msgid "Set tag if client includes matching option in request." +msgstr "Fijar etiqueta si cliente incluye opción coincidente en pedido." + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "Usar puertos alternativos para DHCP." + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "Correr archivo guión de cambio de arriendos como este usuario." + +#: option.c:339 +#, fuzzy +msgid "Specify NAPTR DNS record." +msgstr "Especificar expediente DNS NAPTR." + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "Especificar puerto más bajo disponible para transmisión de búsquedas DNS." + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "Usar solo nombres de dominio completamente calificados para clientes DHCP." + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "Generar hostnames basados en direcciones MAC para clientes sin nombre." + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "Usar estos relays DHCP como proxies completos." + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "Especificar nombre alias para nombre DNS LOCAL." + +#: option.c:345 +#, fuzzy +msgid "Prompt to send to PXE clients." +msgstr "Aviso a ser enviado a clientes PXE." + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "Servico boot para menú PXE." + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "Revisar sintaxis de configuración." + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +#: option.c:349 +#, fuzzy +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "Traducir direcciones IPv4 desde servidores upstream." + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" +"Modo de uso: dnsmasq [opciones]\n" +"\n" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "Usar opciones cortas solo en la línea de comandos.\n" + +#: option.c:642 +#, fuzzy, c-format +msgid "Valid options are:\n" +msgstr "Opciones válidas son :\n" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "Opciones DHCP conocidas:\n" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "opción dhcp-option errónea" + +#: option.c:860 +#, fuzzy +msgid "bad IP address" +msgstr "dirección IP errónea" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "dominio erróneo en dhcp-option" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "opción dhcp-option demasiado larga" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "dhcp-match ilegal" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "opción repetida ilegal" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "palabra clave repetida ilegal" + +#: option.c:1147 option.c:3030 +#, fuzzy, c-format +msgid "cannot access directory %s: %s" +msgstr "no se puede accesar directorio %s: %s" + +#: option.c:1178 tftp.c:460 +#, fuzzy, c-format +msgid "cannot access %s: %s" +msgstr "no se puede accesar %s: %s" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "preferencia MX errónea" + +#: option.c:1270 +msgid "bad MX name" +msgstr "nombre MX erróneo" + +#: option.c:1284 +msgid "bad MX target" +msgstr "destino MX erróneo" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "no se pueden correr archivos guiónes bajo uClinux" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "recompilar con HAVE_SCRIPT definido para habilitar guiónes de cambio de arriendo" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "puerto erróneo" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "vinculación de interface no está soportado" + +#: option.c:1791 +#, fuzzy +msgid "bad port range" +msgstr "rango de puertos erróneo" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "opción bridge-interface (interface puente) errónea" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "opción dhcp-range (rango DHCP) errónea" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "solo una etiqueta permitida" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "rango DHCP inconsistente" + +#: option.c:2019 option.c:2045 +#, fuzzy +msgid "bad hex constant" +msgstr "opción dhcp-host errónea" + +#: option.c:2107 +#, fuzzy +msgid "bad DHCP host name" +msgstr "nombre de host DHCP erróneo" + +#: option.c:2188 +#, fuzzy +msgid "bad tag-if" +msgstr "destino MX erróneo" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "número de puerto inválido" + +#: option.c:2529 +#, fuzzy +msgid "bad dhcp-proxy address" +msgstr "dirección IP errónea" + +#: option.c:2569 +#, fuzzy +msgid "invalid alias range" +msgstr "rango alias inválido" + +#: option.c:2582 +#, fuzzy +msgid "bad interface name" +msgstr "nombre de interface erróneo" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "CNAME erróneo" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "CNAME duplicado" + +#: option.c:2632 +#, fuzzy +msgid "bad PTR record" +msgstr "expediente PTR erróneo" + +#: option.c:2663 +#, fuzzy +msgid "bad NAPTR record" +msgstr "expediente NAPTR erróneo" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "expediente TXT erróneo" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "expediente SRV erróneo" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "destino SRV erróneo" + +#: option.c:2759 +msgid "invalid priority" +msgstr "prioridad inválida" + +#: option.c:2766 +msgid "invalid weight" +msgstr "peso inválido" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "opción no soportada (verificar que dnsmasq fue compilado con soporte para DHCP/TFTP/DBus)" + +#: option.c:2849 +msgid "missing \"" +msgstr "falta \"" + +#: option.c:2908 +msgid "bad option" +msgstr "opción errónea" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "parámetro extraño" + +#: option.c:2912 +msgid "missing parameter" +msgstr "parámetro ausente" + +#: option.c:2916 +msgid "error" +msgstr "error" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "%s en línea %d de %%s" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "no se puede leer %s: %s" + +#: option.c:3151 option.c:3187 +#, fuzzy, c-format +msgid "read %s" +msgstr "leyendo %s" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "Dnsmasq versión %s %s\n" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" +"Opciones de compilación %s\n" +"\n" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "Este software viene SIN NINGUNA GARANTIA.\n" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "Dnsmasq es software libre, y usted está bienvenido a redistribuirlo\n" + +#: option.c:3273 +#, fuzzy, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "bajo los términos de la GNU General Public License, versión 2 o 3.\n" + +#: option.c:3284 +msgid "try --help" +msgstr "pruebe --help" + +#: option.c:3286 +msgid "try -w" +msgstr "pruebe -w" + +#: option.c:3289 +#, fuzzy, c-format +msgid "bad command line options: %s" +msgstr "opciones de línea de comandos erróneas: %s" + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "no se puede obtener host-name (nombre de host): %s" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "solo un archivo resolv.conf permitido en modo no-poll." + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "debe haber exáctamente un resolv.conf desde donde leer dominio." + +#: option.c:3371 network.c:848 dhcp.c:814 +#, fuzzy, c-format +msgid "failed to read %s: %s" +msgstr "no se pudo leer %s: %s" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "ninguna directiva de búsqueda encontrada en %s" + +#: option.c:3409 +#, fuzzy +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "debe haber un dominio predeterminado cuando --dhcp-fqdn está fijado" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "revisión de sintaxis OK" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "servidor DNS %s se reusó a hacer una búsqueda recursiva" + +#: forward.c:489 +#, fuzzy, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "posible ataque de revinculación DNS detectado" + +#: network.c:171 +#, fuzzy, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "interface desconocida %s en bridge-interface" + +#: network.c:380 +#, fuzzy, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "no se pudo crear un socket escuchador: %s" + +#: network.c:746 +#, fuzzy, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "no se pudo acoplar socket escuchador para %s: %s" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "ignorando servidor DNS %s - interface local" + +#: network.c:794 +#, fuzzy, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "ignorando servidor DNS %s - no se puede crear/acoplar socket: %s" + +#: network.c:811 +msgid "unqualified" +msgstr "no calificado" + +#: network.c:811 +msgid "names" +msgstr "nombres" + +#: network.c:813 +msgid "default" +msgstr "predeterminado" + +#: network.c:815 +msgid "domain" +msgstr "dominio" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "usando direcciones locales solo para %s %s" + +#: network.c:820 +#, fuzzy, c-format +msgid "using standard nameservers for %s %s" +msgstr "usando servidor DNS %s#%d para %s %s" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "usando servidor DNS %s#%d para %s %s" + +#: network.c:825 +#, fuzzy, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "usando servidor DNS %s#%d(vía %s)" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "usando servidor DNS %s#%d" + +#: dnsmasq.c:148 +#, fuzzy +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "servidor TFTP no disponible: fijar HAVE_TFTP en src/config.h" + +#: dnsmasq.c:153 +#, fuzzy +msgid "asychronous logging is not available under Solaris" +msgstr "bitacoreo asincrónico no está disponible bajo Solaris" + +#: dnsmasq.c:158 +#, fuzzy +msgid "asychronous logging is not available under Android" +msgstr "bitacoreo asincrónico no está disponible bajo Solaris" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "no se pudo encontrar lista de interfaces: %s" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "interface desconocida %s" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "ninguna interface con dirección %s" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "error DBus: %s" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "DBus no disponible: fijar HAVE_DBUS en src/config.h" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "usuario o grupo desconocido: %s" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "no se puede cambiar directorio a raíz de sistema de archivos: %s" + +#: dnsmasq.c:455 +#, fuzzy, c-format +msgid "started, version %s DNS disabled" +msgstr "iniciado, versión %s DNS deshabilitado" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "iniciado, versión %s tamaño de caché %d" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "iniciado, versión %s caché deshabilitado" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "opciones de compilación: %s" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "soporte DBus habilitado: conectado a bus de sistema" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "soporte DBus habilitado: conección a bus pendiente" + +#: dnsmasq.c:474 +#, fuzzy, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "advertencia: no se pudo cambiar dueño de %s: %s" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "fijando opción --bind-interfaces debido a limitaciones de sistema operativo" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "advertencia: interface %s no existe actuálmente" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "advertencia: ignorando opción resolv-file porque no-resolv está fijado" + +#: dnsmasq.c:491 +#, fuzzy +msgid "warning: no upstream servers configured" +msgstr "advertencia: ningún servidor upstream configurado" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "bitacoreo asincrónico habilitado, límite de cola es %d mensajes" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "DHCP, arriendos estáticos solo en %.0s%s, tiempo de arriendo %s" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "DHCP, proxy en subred %.0s%s%.0s" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "DHCP, rango de IPs %s -- %s, tiempo de arriendo %s" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "root es " + +#: dnsmasq.c:526 +#, fuzzy +msgid "enabled" +msgstr "habilitado" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "modo seguro" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "limitando número máximo de transferencias TFTP simultáneas a %d" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "conectado a DBus de sistema" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "no se puede hacer fork hacia el fondo: %s" + +#: dnsmasq.c:778 +#, fuzzy, c-format +msgid "failed to create helper: %s" +msgstr "no se pudo crear ayudante: %s" + +#: dnsmasq.c:781 +#, fuzzy, c-format +msgid "setting capabilities failed: %s" +msgstr "configuración de capacidades ha fallado: %s" + +#: dnsmasq.c:785 +#, fuzzy, c-format +msgid "failed to change user-id to %s: %s" +msgstr "no se pudo cambiar user-id a %s: %s" + +#: dnsmasq.c:790 +#, fuzzy, c-format +msgid "failed to change group-id to %s: %s" +msgstr "no se pudo cambiar group-id a %s: %s" + +#: dnsmasq.c:793 +#, fuzzy, c-format +msgid "failed to open pidfile %s: %s" +msgstr "no se pudo abrir archivo PID %s: %s" + +#: dnsmasq.c:796 +#, fuzzy, c-format +msgid "cannot open %s: %s" +msgstr "no se puede abrir %s: %s" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "proceso hijo eliminado por señal %d" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "proceso hijo hizo exit con estado %d" + +#: dnsmasq.c:859 +#, fuzzy, c-format +msgid "failed to execute %s: %s" +msgstr "no se pudo ejecutar %s: %s" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "saliendo al recibir SIGTERM" + +#: dnsmasq.c:931 +#, fuzzy, c-format +msgid "failed to access %s: %s" +msgstr "no se pudo accesar %s: %s" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "leyendo %s" + +#: dnsmasq.c:972 +#, fuzzy, c-format +msgid "no servers found in %s, will retry" +msgstr "ningún servidor encontrado en %s, se reintentará" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "no se puede crear socket DHCP: %s" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "no se pudo fijar opciones en socket DHCP: %s" + +#: dhcp.c:65 +#, fuzzy, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "no se pudo fijar SO_REUSE{ADDR|PORT} en socket DHCP: %s" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "no se pudo acoplar socket de servidor DHCP: %s" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "no se puede crear socket crudo ICMP: %s." + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "Paquete DHCP recibido en %s que no tiene dirección" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "rango DHCP %s -- %s no coincide con máscara de subred %s" + +#: dhcp.c:852 +#, fuzzy, c-format +msgid "bad line at %s line %d" +msgstr "línea errónea en %s línea %d" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "ignorando %s línea %d, nombre o dirección IP duplicada" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "dirección IP duplicada %s en directiva dhcp-config." + +#: dhcp.c:981 +#, fuzzy, c-format +msgid "duplicate IP address %s in %s." +msgstr "dirección IP duplicada %s en %s." + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "%s tiene más de una dirección en hostsfile, usando %s para DHCP" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "dirección IP duplicada %s (%s) en directiva dhcp-config" + +#: lease.c:67 +#, fuzzy, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "no se puede abrir o crear archivo de arriendos %s: %s" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "demasiados arriendos almacenados" + +#: lease.c:129 +#, fuzzy, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "no se puede ejecutar archivo guión lease-init %s: %s" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "archivo guión lease-init retornó exit code %s" + +#: lease.c:235 +#, fuzzy, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "error al escribir %s: %s (reintentar en %us)" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "ningún rango de direcciónes disponible para pedido DHCP %s %s" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "con selector de subred" + +#: rfc2131.c:316 +msgid "via" +msgstr "vía" + +#: rfc2131.c:331 +#, fuzzy, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "%u Subred DHCP disponible: %s/%s" + +#: rfc2131.c:334 +#, fuzzy, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "%u Rango DHCP disponible: %s -- %s" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "deshabilitado" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "ignorado" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "dirección en uso" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "ninguna dirección disponible" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "red equivocada" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "ninguna dirección configurada" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "no sobra ningún arriendo" + +#: rfc2131.c:545 +#, fuzzy, c-format +msgid "%u client provides name: %s" +msgstr "%u cliente provee nombre: %s" + +#: rfc2131.c:700 +#, fuzzy, c-format +msgid "%u vendor class: %s" +msgstr "%u Clase de vendedor: %s" + +#: rfc2131.c:702 +#, fuzzy, c-format +msgid "%u user class: %s" +msgstr "%u Clase de usuario: %s" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "no hay soporte para BIS PXE" + +#: rfc2131.c:886 +#, fuzzy, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "deshabilitando dirección DHCP estática %s para %s" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "arriendo desconocido" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "no usando dirección configurada %s porque está arrendada a %s" + +#: rfc2131.c:949 +#, fuzzy, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "no usando dirección configurada %s porque está en uso por el servidor o relay" + +#: rfc2131.c:952 +#, fuzzy, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "no usando dirección configurada %s porque fué previamente denegada" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "ningún unique-id (identificación única)" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "ID de servidor equivocada" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "dirección equivocada" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "arriendo no encontrado" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "dirección no disponible" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "arriendo estático disponible" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "dirección reservada" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "abandonando arriendo a %s de %s" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "%u etiquetas: %s" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "%u nombre de bootfile: %s" + +#: rfc2131.c:1732 +#, c-format +msgid "%u server name: %s" +msgstr "%u nombre de servidor: %s" + +#: rfc2131.c:1746 +#, fuzzy, c-format +msgid "%u next server: %s" +msgstr "%u siguiente servidor: %s" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "" + +#: rfc2131.c:1812 +#, fuzzy, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "no se puede enviar opción DHCP/BOOTP %d: no queda espacio en paquete" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "menú PXE demasiado grande" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "Ignorando dominio %s para nombre de host DHCP %s" + +#: rfc2131.c:2189 +#, fuzzy, c-format +msgid "%u requested options: %s" +msgstr "%u opciones solicitadas: %s" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "no se puede enviar opción RFC3925: demasiadas opciones para número enterprise %d" + +#: netlink.c:70 +#, fuzzy, c-format +msgid "cannot create netlink socket: %s" +msgstr "no se puede crear socket netlink: %s" + +#: netlink.c:288 +#, fuzzy, c-format +msgid "netlink returns error: %s" +msgstr "netlink retorna error: %s" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "intento de fijar dirección de servidor IPv6 vía DBus - no hay soporte IPv6" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "fijando servidores upstream desde DBus" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "no se pudo registrar un manejador de mensajes DBus" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "no se puede crear socket BPF DHCP: %s" + +#: bpf.c:245 +#, fuzzy, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "pedido DHCP por tipo de hardware no-soportado (%d) recibido en %s" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "incapaz de conseguir puerto libre para TFTP" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "pedido no-soportado desde %s" + +#: tftp.c:406 +#, fuzzy, c-format +msgid "file %s not found" +msgstr "archivo %s no encontrado" + +#: tftp.c:522 +#, fuzzy, c-format +msgid "error %d %s received from %s" +msgstr "error TFTP %d %s recibido de %s" + +#: tftp.c:554 +#, fuzzy, c-format +msgid "failed sending %s to %s" +msgstr "TFTP no pudo enviar %s a %s" + +#: tftp.c:568 +#, fuzzy, c-format +msgid "sent %s to %s" +msgstr "TFTP envió %s a %s" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "desbordamiento: %d entradas de bitácora perdidas" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "bitácora falló: %s" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "el inicio ha FALLADO" + +#, fuzzy +#~ msgid "only one dhcp-hostsfile allowed" +#~ msgstr "solo un dhcp-hostsfile permitido" + +#, fuzzy +#~ msgid "only one dhcp-optsfile allowed" +#~ msgstr "solo un dhcp-optsfile permitido" + +#~ msgid "files nested too deep in %s" +#~ msgstr "archivos jerarquizados demasiado profundo en %s" + +#~ msgid "TXT record string too long" +#~ msgstr "expediente TXT demasiado largo" + +#~ msgid "failed to set IPV6 options on listening socket: %s" +#~ msgstr "no se pudo fijar opciones IPv6 sobre socket escuchador: %s" + +#~ msgid "failed to bind listening socket for %s: %s" +#~ msgstr "no se pudo acoplar socket escuchador para %s: %s" + +#~ msgid "failed to listen on socket: %s" +#~ msgstr "no se pudo escuchar en socket: %s" + +#, fuzzy +#~ msgid "failed to create TFTP socket: %s" +#~ msgstr "no se pudo crear socket TFTP: %s" + +#~ msgid "DHCP packet: transaction-id is %u" +#~ msgstr "paquete DHCP: transaction-id (identificación de transacción) es %u" + +#~ msgid "must set exactly one interface on broken systems without IP_RECVIF" +#~ msgstr "debe fijarse exáctamente una interface en sistemas rotos sin IP_RECVIF" + +#, fuzzy +#~ msgid "failed to load %s: %s" +#~ msgstr "no se pudo cargar %s: %s" + +#~ msgid "bad name in %s" +#~ msgstr "nombre erróneo en %s" + +#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part" +#~ msgstr "Ignorando arriendo DHCP para %s porque tiene una parte ilegal de dominio" + +#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h" +#~ msgstr "integración dhcpd ISC no disponible: fijar HAVE_ISC_READER en src/config.h" + +#, fuzzy +#~ msgid "illegal domain %s in dhcp-config directive." +#~ msgstr "dominio ilegal %s en directiva dhcp-config." + +#~ msgid "illegal domain %s in %s." +#~ msgstr "dominio ilegal %s en %s." + +#~ msgid "running as root" +#~ msgstr "corriendo como root" + +#~ msgid "Read leases at startup, but never write the lease file." +#~ msgstr "Leer arriendos al inicio, pero nunca escribir el archivo de arriendos." + +#, fuzzy +#~ msgid "read %s - %d hosts" +#~ msgstr "direcciónes %s - %d leídas" + +#~ msgid "Limit of %d leases exceeded." +#~ msgstr "Límite de %d arriendos excedido." + +#~ msgid "domains" +#~ msgstr "dominios" + +#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part" +#~ msgstr "Ignorando nombre de host DHCP %s porque contiene una parte ilegal de dominio" + +#~ msgid "Display this message." +#~ msgstr "Mostrar este mensaje." + +#~ msgid "failed to read %s: %m" +#~ msgstr "no se pudo leer %s: %m" + +#~ msgid "failed to read %s:%m" +#~ msgstr "no se pudo leer %s:%m" diff --git a/po/fi.po b/po/fi.po new file mode 100644 index 0000000..ccd0338 --- /dev/null +++ b/po/fi.po @@ -0,0 +1,1455 @@ +# Finnish translations for dnsmasq package. +# This file is put in the public domain. +# Simon Kelley <simon@thekelleys.org.uk>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.24\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2005-11-28 22:05+0000\n" +"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n" +"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cache.c:761 +#, c-format +msgid "failed to load names from %s: %s" +msgstr "" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "" + +#: cache.c:899 +msgid "cleared cache" +msgstr "" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "" + +#: cache.c:1040 +#, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "" + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "" + +#: util.c:57 +#, c-format +msgid "failed to seed the random number generator: %s" +msgstr "" + +#: util.c:189 +msgid "failed to allocate memory" +msgstr "" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "" + +#: util.c:237 +#, c-format +msgid "cannot create pipe: %s" +msgstr "" + +#: util.c:245 +#, c-format +msgid "failed to allocate %d bytes" +msgstr "" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "" + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "" + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "" + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "" + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "" + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "" + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "" + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "" + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "" + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "" + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "" + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "" + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "" + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "" + +#: option.c:258 +msgid "Read DHCP host specs from file." +msgstr "" + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "" + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "" + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "" + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "" + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "" + +#: option.c:265 +msgid "Map DHCP user class to tag." +msgstr "" + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "" + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "" + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "" + +#: option.c:269 +msgid "Don't do DHCP for hosts with tag set." +msgstr "" + +#: option.c:270 +msgid "Force broadcast replies for hosts with tag set." +msgstr "" + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "" + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "" + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "" + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "" + +#: option.c:275 +msgid "Specify an MX record." +msgstr "" + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "" + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "" + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "" + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "" + +#: option.c:280 +msgid "Specify options to be sent to DHCP clients." +msgstr "" + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "" + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "" + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "" + +#: option.c:284 +msgid "Log DNS queries." +msgstr "" + +#: option.c:285 +msgid "Force the originating port for upstream DNS queries." +msgstr "" + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "" + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "" + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "" + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "" + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "" + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "" + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "" + +#: option.c:293 +msgid "Specify time-to-live in seconds for negative caching." +msgstr "" + +#: option.c:294 +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "" + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "" + +#: option.c:296 +msgid "Map DHCP vendor class to tag." +msgstr "" + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "" + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "" + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "" + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "" + +#: option.c:301 +#, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "" + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "" + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "" + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "" + +#: option.c:305 +msgid "Specify PTR DNS record." +msgstr "" + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "" + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "" + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "" + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "" + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "" + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "" + +#: option.c:312 +msgid "Map MAC address (with wildcards) to option set." +msgstr "" + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "" + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "" + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "" + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "" + +#: option.c:317 +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "" + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "" + +#: option.c:319 +#, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "" + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "" + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "" + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "" + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "" + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "" + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "" + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "" + +#: option.c:327 +#, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "" + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "" + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "" + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "" + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "" + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "" + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "" + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "" + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "" + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "" + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "" + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "" + +#: option.c:339 +msgid "Specify NAPTR DNS record." +msgstr "" + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "" + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "" + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "" + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "" + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "" + +#: option.c:345 +msgid "Prompt to send to PXE clients." +msgstr "" + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "" + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "" + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +#: option.c:349 +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "" + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "" + +#: option.c:642 +#, c-format +msgid "Valid options are:\n" +msgstr "" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "" + +#: option.c:860 +msgid "bad IP address" +msgstr "" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "" + +#: option.c:1147 option.c:3030 +#, c-format +msgid "cannot access directory %s: %s" +msgstr "" + +#: option.c:1178 tftp.c:460 +#, c-format +msgid "cannot access %s: %s" +msgstr "" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "" + +#: option.c:1270 +msgid "bad MX name" +msgstr "" + +#: option.c:1284 +msgid "bad MX target" +msgstr "" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "" + +#: option.c:1791 +msgid "bad port range" +msgstr "" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "" + +#: option.c:2019 option.c:2045 +msgid "bad hex constant" +msgstr "" + +#: option.c:2107 +msgid "bad DHCP host name" +msgstr "" + +#: option.c:2188 +msgid "bad tag-if" +msgstr "" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "" + +#: option.c:2529 +msgid "bad dhcp-proxy address" +msgstr "" + +#: option.c:2569 +msgid "invalid alias range" +msgstr "" + +#: option.c:2582 +msgid "bad interface name" +msgstr "" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "" + +#: option.c:2632 +msgid "bad PTR record" +msgstr "" + +#: option.c:2663 +msgid "bad NAPTR record" +msgstr "" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "" + +#: option.c:2759 +msgid "invalid priority" +msgstr "" + +#: option.c:2766 +msgid "invalid weight" +msgstr "" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "" + +#: option.c:2849 +msgid "missing \"" +msgstr "" + +#: option.c:2908 +msgid "bad option" +msgstr "" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "" + +#: option.c:2912 +msgid "missing parameter" +msgstr "" + +#: option.c:2916 +msgid "error" +msgstr "" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "" + +#: option.c:3151 option.c:3187 +#, c-format +msgid "read %s" +msgstr "" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "" + +#: option.c:3273 +#, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "" + +#: option.c:3284 +msgid "try --help" +msgstr "" + +#: option.c:3286 +msgid "try -w" +msgstr "" + +#: option.c:3289 +#, c-format +msgid "bad command line options: %s" +msgstr "" + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "" + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "" + +#: option.c:3371 network.c:848 dhcp.c:814 +#, c-format +msgid "failed to read %s: %s" +msgstr "" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "" + +#: option.c:3409 +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "" + +#: network.c:171 +#, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "" + +#: network.c:380 +#, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "" + +#: network.c:746 +#, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "" + +#: network.c:794 +#, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "" + +#: network.c:811 +msgid "unqualified" +msgstr "" + +#: network.c:811 +msgid "names" +msgstr "" + +#: network.c:813 +msgid "default" +msgstr "" + +#: network.c:815 +msgid "domain" +msgstr "" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "" + +#: network.c:820 +#, c-format +msgid "using standard nameservers for %s %s" +msgstr "" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "" + +#: network.c:825 +#, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "" + +#: dnsmasq.c:148 +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "" + +#: dnsmasq.c:158 +msgid "asychronous logging is not available under Android" +msgstr "" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "" + +#: dnsmasq.c:455 +#, c-format +msgid "started, version %s DNS disabled" +msgstr "" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "" + +#: dnsmasq.c:474 +#, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "" + +#: dnsmasq.c:491 +msgid "warning: no upstream servers configured" +msgstr "" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "" + +#: dnsmasq.c:526 +msgid "enabled" +msgstr "" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "" + +#: dnsmasq.c:778 +#, c-format +msgid "failed to create helper: %s" +msgstr "" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "" + +#: dnsmasq.c:785 +#, c-format +msgid "failed to change user-id to %s: %s" +msgstr "" + +#: dnsmasq.c:790 +#, c-format +msgid "failed to change group-id to %s: %s" +msgstr "" + +#: dnsmasq.c:793 +#, c-format +msgid "failed to open pidfile %s: %s" +msgstr "" + +#: dnsmasq.c:796 +#, c-format +msgid "cannot open %s: %s" +msgstr "" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "" + +#: dnsmasq.c:859 +#, c-format +msgid "failed to execute %s: %s" +msgstr "" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "" + +#: dnsmasq.c:931 +#, c-format +msgid "failed to access %s: %s" +msgstr "" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "" + +#: dnsmasq.c:972 +#, c-format +msgid "no servers found in %s, will retry" +msgstr "" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "" + +#: dhcp.c:65 +#, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "" + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "" + +#: dhcp.c:981 +#, c-format +msgid "duplicate IP address %s in %s." +msgstr "" + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "" + +#: lease.c:67 +#, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "" + +#: lease.c:129 +#, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "" + +#: lease.c:235 +#, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "" + +#: rfc2131.c:316 +msgid "via" +msgstr "" + +#: rfc2131.c:331 +#, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "" + +#: rfc2131.c:700 +#, c-format +msgid "%u vendor class: %s" +msgstr "" + +#: rfc2131.c:702 +#, c-format +msgid "%u user class: %s" +msgstr "" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "" + +#: rfc2131.c:886 +#, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "" + +#: rfc2131.c:1732 +#, c-format +msgid "%u server name: %s" +msgstr "" + +#: rfc2131.c:1746 +#, c-format +msgid "%u next server: %s" +msgstr "" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "" + +#: rfc2131.c:1812 +#, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "" + +#: rfc2131.c:2189 +#, c-format +msgid "%u requested options: %s" +msgstr "" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "" + +#: netlink.c:70 +#, c-format +msgid "cannot create netlink socket: %s" +msgstr "" + +#: netlink.c:288 +#, c-format +msgid "netlink returns error: %s" +msgstr "" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "" + +#: bpf.c:245 +#, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "" + +#: tftp.c:406 +#, c-format +msgid "file %s not found" +msgstr "" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "" + +#: tftp.c:554 +#, c-format +msgid "failed sending %s to %s" +msgstr "" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..6863785 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,1571 @@ +# French translations for dnsmasq package. +# This file is put in the public domain. +# Lionel Tricon <lionel.tricon@free.fr>, 2005. +# Translation completed by Gildas Le Nadan <3ntr0p13@gmail.com> +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.56\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2011-02-10 20:40+0100\n" +"Last-Translator: Gildas Le Nadan <3ntr0p13@gmail.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: cache.c:761 +#, c-format +msgid "failed to load names from %s: %s" +msgstr "Impossible de charger les noms à partir de %s : %s" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "mauvaise adresse dans %s ligne %d" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "mauvais nom dans %s ligne %d" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "lecture %s - %d adresses" + +#: cache.c:899 +msgid "cleared cache" +msgstr "cache vidé" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "%s est un CNAME, il ne sera pas donné au bail DHCP de %s" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "ne donne pas de nom %s au bail DHCP de %s parce-que le nom existe dans %s avec l'adresse %s" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "horodatage %lu" + +#: cache.c:1040 +#, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "taille de cache %d, %d/%d insertions dans le cache entrées non-expirées réutilisées" + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "requêtes transmises %u, requêtes résolues localement %u" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "serveur %s#%d: requêtes envoyées %u, requêtes réessayées ou échouées %u" + +#: util.c:57 +#, c-format +msgid "failed to seed the random number generator: %s" +msgstr "impossible d'initialiser le générateur de nombre aléatoire : %s" + +#: util.c:189 +msgid "failed to allocate memory" +msgstr "impossible d'allouer la mémoire" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "impossible d'allouer de la mémoire" + +#: util.c:237 +#, c-format +msgid "cannot create pipe: %s" +msgstr "Ne peut pas créer le tube %s : %s" + +#: util.c:245 +#, c-format +msgid "failed to allocate %d bytes" +msgstr "impossible d'allouer %d octets" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "illimité(e)" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "Spécifie la ou les adresse(s) locales où le démon doit se mettre à l'écoute." + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "Retourne les adresses IP pour toutes les machines présentes dans les domaines spécifiés" + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "Traduction inverse truquée pour la plage d'adresse privée RFC1918" + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "Traite l'adresse IP comme un domaine inexistant NXDOMAIN (contourne le systeme de redirection de Verisign)" + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "Spécifie le nombre d'entrées que contiendra le cache (par défaut : %s)." + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "Spécifie le nom du fichier de configuration (par défaut : %s)" + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "Ne passe pas en tâche de fond : démarre en mode debug" + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "Ne retransmet pas les requêtes qui n'ont pas de domaine." + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "Retourne les champs MX pour les machines locales." + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "Etend les noms uniques des machines dans /etc/hosts avec le suffixe du domaine." + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "Ne retransmet pas les fausses requêtes DNS en provenance des machines Windows." + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "Autorise DHCP dans la plage d'adresses donnée sur la durée de validité du bail." + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "On change pour ce groupe après le démarrage (par défaut : %s)." + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "On assigne une adresse ou un nom pour une machine spécifiée." + +#: option.c:258 +msgid "Read DHCP host specs from file." +msgstr "Lecture des spécifications d'hôtes DHCP à partir du fichier" + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "Lecture des options DHCP à partir du fichier" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "Expression d'évaluation conditionnelle d'étiquette" + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "Ne charge PAS le fichier %s." + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "Spécifie un nom de fichier hosts à lire en complément de %s" + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "Spécifie la ou les interface(s) où le démon doit se mettre à l'écoute." + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "Spécifie la ou les interface(s) que le démon ne doit PAS traiter." + +# +#: option.c:265 +msgid "Map DHCP user class to tag." +msgstr "Associe les classes d'utilisateurs ('user class') DHCP aux options." + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "Associe les identifiants de circuits RFC3046 ('circuit-id') aux options" + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "Associe les identifiants distants RFC3046 ('remote-id') aux options" + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "Associe les identifiants de souscripteurs RFC3993 ('subscriber-id') aux options" + +# +#: option.c:269 +msgid "Don't do DHCP for hosts with tag set." +msgstr "Ne pas autoriser DHCP pour les machines énumerées dans les options." + +# +#: option.c:270 +msgid "Force broadcast replies for hosts with tag set." +msgstr "Forcer les réponses par 'broadcast' pour les machines énumerées dans les options." + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "Ne passe pas en tâche de fond, ne pas s'exécuter en mode debug." + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "On considère que l'on est le seul serveur DHCP sur le réseau local." + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "Spécifie où il faut sauvegarder les baux DHCP (par défaut : %s)." + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "Retourne les champs MX pour les machines locales." + +#: option.c:275 +msgid "Specify an MX record." +msgstr "Spécifie un champ MX." + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "Spécifie les options BOOTP pour le serveur DHCP." + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "Ne pas scruter le fichier %s, ne recharger les modifications que sur réception du signal SIGHUP." + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "Ne place pas en cache le résultat des requêtes qui ont échouées." + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "Utilise les serveurs de noms dans l'ordre donné dans %s." + +# +#: option.c:280 +msgid "Specify options to be sent to DHCP clients." +msgstr "Options supplémentaires à associer aux clients DHCP." + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "Option DHCP envoyée même si le client de la demande pas." + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "Spécifie le port où il faut écouter les requêtes DNS (par défaut : 53)." + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "Taille maximale des paquets UDP supportés pour EDNS.0 (par défaut : %s)." + +# +#: option.c:284 +msgid "Log DNS queries." +msgstr "Enregistre les requêtes DNS dans un journal d'activité." + +# +#: option.c:285 +msgid "Force the originating port for upstream DNS queries." +msgstr "Force le port d'origine pour les requêtes vers les serveurs amonts." + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "Ne pas lire le fichier resolv.conf." + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "Spécifie le chemin pour le fichier resolv.conf (par défaut : %s)." + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "Spécifie la ou les adresses des serveurs amonts avec des domaines optionels." + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "Ne jamais retransmettre les requêtes pour les domaines spécifiés." + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "Spécifie le domaine qui doit etre assigné aux baux DHCP." + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "Spécifie la cible par défaut dans un champ MX." + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts." + +# +#: option.c:293 +msgid "Specify time-to-live in seconds for negative caching." +msgstr "Spécifie le TTL en secondes pour les réponses qui utilisent /etc/hosts." + +#: option.c:294 +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "Spécifie, en secondes, la valeur maximum de TTL à renvoyer aux clients." + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "Change pour cet utilisateur après le démarrage (par défaut : %s)." + +# +#: option.c:296 +msgid "Map DHCP vendor class to tag." +msgstr "Associe les classes de fournisseurs ('vendor class') DHCP aux options." + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "Affiche la version de Dnsmasq et les informations liées au copyright." + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "Traduit les adresses IPV4 des serveurs amonts." + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "Spécifie un champ SRV." + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "Afficher ce message. Utiliser --help dhcp pour obtenir la liste des options DHCP connues." + +#: option.c:301 +#, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "Spécifie un chemin pour le fichier PID (par défaut : %s)." + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "Spécifie le nombre maximum de baux DHCP (par défaut : %s)." + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "Repond aux requêtes DNS en se basant sur l'interface ou a été envoyée la requête." + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "Spécifie un champ DNS TXT" + +# +#: option.c:305 +msgid "Specify PTR DNS record." +msgstr "Spécifie un champ DNS PTR" + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "Donne le nom DNS pour l'adresse IPv4 de l'interface." + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "Association uniquement aux interfaces réseau actuellement actives." + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "Lecture des informations de DHCP statique à partir de %s." + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "Autorise l'interface DBus pour la configuration des serveurs amonts, etc." + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "Ne pas assurer de fonction DHCP sur cette interface, mais seulement la fonction DNS." + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "Autorise l'allocation dynamique d'adresse pour bootp." + +# +#: option.c:312 +msgid "Map MAC address (with wildcards) to option set." +msgstr "Associe l'adresse MAC (avec les jokers) aux options." + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "Traiter les requêtes DHCP sur les alias comme arrivant de l'interface." + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "Supprime la vérification d'adresse sur le serveur au moyen de paquets ICMP echo" + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "Script à exécuter lors de la création ou destruction de bail DHCP." + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "Lecture de la configuration dans tous les fichiers de ce répertoire." + +# +#: option.c:317 +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "Enregistrer les journaux d'activité dans cette facilité syslog. (défaut : DAEMON)" + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "Ne pas utiliser de fichier de baux." + +#: option.c:319 +#, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "Spécifie le nombre maximum de requêtes DHCP concurrentes (par défaut : %s)." + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "Vider le cache DNS lors du rechargement de %s." + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "Ignorer les noms d'hôtes fournis par les clients DHCP" + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "Ne pas réutiliser les champs nom de fichier et serveur dans les options DHCP supplémentaires." + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "Activer le server TFTP intégré (fonctionnant en lecture seulement)" + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "N'exporter par TFTP que les fichiers de l'arborescence de fichier spécifiée" + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "Ajouter les adresses IP clientes à la racine tftp ('tftp-root')." + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "Accès aux seuls fichiers appartenants à l'utilisateur sous lequel tourne dnsmasq" + +#: option.c:327 +#, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "Spécifie le nombre maximum de transfert TFTP concurrents (défaut : %s)." + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "Désactivation de l'extension TFTP « taille de bloc »" + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "Gamme de ports dans laquelle seront choisis les ports temporaires utilisés dans les transferts TFTP." + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "Traces supplémentaires pour le DHCP." + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "Active l'écriture de traces en mode asynchrone. Peut prendre en option la valeur de la longueur de la queue." + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "Stopper la réassociation DNS ('DNS rebinding'). Filtre les gammes d'adresses IP privées lors de la résolution." + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "Autorise la réassociation de 127.0.0/8, pour les serveurs RBL (Realtime Blackhole List)" + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "Désactive la protection contre les réassociation DNS pour ce domaine" + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "Toujours effectuer les requêtes DNS à tous les serveurs." + +# +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "Spécifie le label si le client inclus l'option dans la requête." + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "Utiliser des ports alternatifs pour le DHCP." + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "Lancer le script 'lease-change' avec cet utilisateur." + +# +#: option.c:339 +msgid "Specify NAPTR DNS record." +msgstr "Spécifie un champ DNS NAPTR." + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "Définie le plus petit port utilisé pour la transmission d'une requête DNS." + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "Utilise seulement les noms de domaine pleinement qualifiés pour les clients DHCP." + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "Génère les noms d'hôtes à partir de l'adresse MAC pour les clients sans nom." + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "Utilise ces relais DHCP en temps que proxy complets." + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "Spécifie un alias pour un nom DNS local." + +# +#: option.c:345 +msgid "Prompt to send to PXE clients." +msgstr "Invite à envoyer aux clients PXE." + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "Service de démarrage pour menu PXE." + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "vérification de la syntaxe de la configuration." + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "Ajoute l'adresse MAC du requêteur aux requêtes DNS transmises" + +#: option.c:349 +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "Transmet les résultats de validation DNSSEC des serveurs amonts" + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" +"Usage : dnsmasq [options]\n" +"\n" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "Utilisez les options courtes uniquement sur la ligne de commande.\n" + +#: option.c:642 +#, c-format +msgid "Valid options are:\n" +msgstr "Les options valides sont :\n" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "Options DHCP connues :\n" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "mauvaise valeur de 'dhcp-option'" + +# +#: option.c:860 +msgid "bad IP address" +msgstr "mauvaise adresse IP" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "mauvais domaine dans dhcp-option" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "dhcp-option trop long" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "valeur illégale pour 'dhcp-match'" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "Une option ne pouvant être spécifié qu'une seule fois à été donnée plusieurs fois" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "Mot-clef ne pouvant être répété" + +#: option.c:1147 option.c:3030 +#, c-format +msgid "cannot access directory %s: %s" +msgstr "Ne peut pas lire le répertoire %s : %s" + +#: option.c:1178 tftp.c:460 +#, c-format +msgid "cannot access %s: %s" +msgstr "Ne peut pas lire %s : %s" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "préference MX incorrecte" + +#: option.c:1270 +msgid "bad MX name" +msgstr "nom MX incorrect" + +#: option.c:1284 +msgid "bad MX target" +msgstr "valeur MX cible incorrecte" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "ne peut exécuter de script sous uClinux" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "pour permettre l'exécution de scripts au changement de bail (lease-change), recompiler en définissant HAVE_SCRIPT" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "numéro de port incorrect" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "association d'interface non supportée" + +# +#: option.c:1791 +msgid "bad port range" +msgstr "gamme de ports incorrecte" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "interface-pont incorrecte" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "plage d'adresses DHCP (dhcp-range) incorrecte" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "une seule étiquette est autorisée" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "plage d'adresses DHCP incohérente" + +#: option.c:2019 option.c:2045 +msgid "bad hex constant" +msgstr "mauvaise constante hexadecimale" + +# +#: option.c:2107 +msgid "bad DHCP host name" +msgstr "nom d'hôte DHCP incorrect" + +#: option.c:2188 +msgid "bad tag-if" +msgstr "mauvaise étiquette tag-if" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "numéro de port invalide" + +# +#: option.c:2529 +msgid "bad dhcp-proxy address" +msgstr "adresse dhcp-proxy incorrecte" + +# +#: option.c:2569 +msgid "invalid alias range" +msgstr "poids invalide" + +# +#: option.c:2582 +msgid "bad interface name" +msgstr "nom d'interface invalide" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "mauvais CNAME" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "ce CNAME existe déja" + +# +#: option.c:2632 +msgid "bad PTR record" +msgstr "mauvais champ PTR" + +# +#: option.c:2663 +msgid "bad NAPTR record" +msgstr "mauvais champ NAPTR" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "champ TXT invalide" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "champ SRV invalide" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "cible SRV invalide" + +#: option.c:2759 +msgid "invalid priority" +msgstr "priorité invalide" + +#: option.c:2766 +msgid "invalid weight" +msgstr "poids invalide" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "option non supportée (vérifier que Dnsmasq a été compilé avec le support DHCP/TFTP/DBus)" + +#: option.c:2849 +msgid "missing \"" +msgstr "il manque \"" + +#: option.c:2908 +msgid "bad option" +msgstr "mauvaise option" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "paramètre en trop" + +#: option.c:2912 +msgid "missing parameter" +msgstr "paramètre manquant" + +#: option.c:2916 +msgid "error" +msgstr "erreur" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "%s à la ligne %d de %%s" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "Ne peut pas lire %s : %s" + +#: option.c:3151 option.c:3187 +#, c-format +msgid "read %s" +msgstr "Lecture de %s" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "la ligne de commande contient des éléments indésirables ou incompréhensibles" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "Version de Dnsmasq %s %s\n" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" +"Options à la compilation %s\n" +"\n" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "Ce logiciel est fourni sans AUCUNE GARANTIE.\n" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "Dnsmasq est un logiciel libre, il vous est permis de le redistribuer\n" + +#: option.c:3273 +#, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "sous les termes de la licence GPL (GNU General Public License), version 2 ou 3.\n" + +#: option.c:3284 +msgid "try --help" +msgstr "essayez avec --help" + +#: option.c:3286 +msgid "try -w" +msgstr "essayez avec -w" + +#: option.c:3289 +#, c-format +msgid "bad command line options: %s" +msgstr "mauvaises options en ligne de commande : %s." + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "ne peut pas obtenir le nom de la machine : %s" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "seul un fichier resolv.conf est autorisé dans le mode no-poll" + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "un fichier resolv.conf (et un seul) est nécessaire pour y récuperer le nom de domaine." + +#: option.c:3371 network.c:848 dhcp.c:814 +#, c-format +msgid "failed to read %s: %s" +msgstr "impossible de lire %s : %s" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "pas de directive de recherche trouvée dans %s" + +#: option.c:3409 +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "un domaine par défaut doit être spécifié lorsque l'option --dhcp-fqdn est utilisée" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "vérification de syntaxe OK" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "le serveur de nom %s a refusé de faire une recherche récursive" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "détection d'une possible attaque de type DNS-rebind: %s" + +#: network.c:171 +#, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "interface %s inconnue spécifiée comme interface de pont" + +#: network.c:380 +#, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "impossible de créer une socket d'écoute pour %s : %s" + +#: network.c:746 +#, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "impossible de lier la socket de serveur pour %s : %s" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "ignore le serveur de nom %s - interface locale" + +#: network.c:794 +#, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "ignore le serveur de nom %s - ne peut construire/lier la socket : %m" + +#: network.c:811 +msgid "unqualified" +msgstr "non-qualifié(e)" + +#: network.c:811 +msgid "names" +msgstr "noms" + +#: network.c:813 +msgid "default" +msgstr "défaut" + +#: network.c:815 +msgid "domain" +msgstr "domaine" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "utilise les adresses locales seulement pour %s %s" + +#: network.c:820 +#, c-format +msgid "using standard nameservers for %s %s" +msgstr "utilisation des serveurs de nom standards pour %s %s" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "utilise le serveur de nom %s#%d pour %s %s" + +#: network.c:825 +#, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "utilise le serveur de nom %s#%d (via %s)" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "utilise le serveur de nom %s#%d" + +# +#: dnsmasq.c:148 +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "TFTP n'est pas disponible : activez HAVE_TFTP dans src/config.h" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "l'écriture de traces en mode asynchrone n'est pas disponible sous Solaris." + +#: dnsmasq.c:158 +#, fuzzy +msgid "asychronous logging is not available under Android" +msgstr "l'écriture de traces en mode asynchrone n'est pas disponible sous Solaris." + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "impossible de trouver la liste des interfaces : %s" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "interface %s inconnue" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "pas d'interface avec l'adresse %s" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "Erreur DBus : %s" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "DBus n'est pas disponible : activez HAVE_DBUS dans src/config.h" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "utilisateur ou groupe inconnu : %s" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "Ne peut effectuer un 'chdir' à la racine du système de fichier : %s" + +#: dnsmasq.c:455 +#, c-format +msgid "started, version %s DNS disabled" +msgstr "démarrage avec le DNS désactivé (version %s)" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "demarré, version %s (taille de cache %d)" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "démarrage avec le cache désactivé (version %s)" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "options à la compilation : %s" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "Support DBus autorisé : connecté au bus système" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "Support DBus autorisé : connexion au bus en attente" + +#: dnsmasq.c:474 +#, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "Impossible de changer pour l'utilisateur %s : %s" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "active l'option --bind-interfaces à cause de limitations dans le système d'exploitation" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "attention : l'interface %s n'existe pas actuellement" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "attention : l'option « resolv-file » sera ignorée car « no-resolv » a été spécifié" + +# +#: dnsmasq.c:491 +msgid "warning: no upstream servers configured" +msgstr "attention : aucun serveur amont n'est configuré" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "mode asynchrone d'écriture de traces, la taille maximum de la queue est de %d messages." + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "baux statiques DHCP seulement sur %.0s%s, durée de validité de bail %s" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "DHCP, proxy sur le sous-réseau %.0s%s%.0s" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "DHCP, plage d'adresses %s -- %s, durée de bail %s" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "root est" + +# +#: dnsmasq.c:526 +msgid "enabled" +msgstr "activé" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "mode sécurisé" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "le nombre maximum de transferts TFTP simultanés sera restreint à %d" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "connecté au systeme DBus" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "Ne peut se lancer en tâche de fond : %s" + +#: dnsmasq.c:778 +#, c-format +msgid "failed to create helper: %s" +msgstr "impossible de créer le 'helper' : %s" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "impossible de configurer la capacité %s" + +#: dnsmasq.c:785 +#, c-format +msgid "failed to change user-id to %s: %s" +msgstr "Impossible de changer l'identifiant utilisateur pour %s : %s" + +#: dnsmasq.c:790 +#, c-format +msgid "failed to change group-id to %s: %s" +msgstr "Impossible de changer l'identifiant de groupe pour %s : %s" + +#: dnsmasq.c:793 +#, c-format +msgid "failed to open pidfile %s: %s" +msgstr "impossible de lire le fichier de PID %s : %s" + +#: dnsmasq.c:796 +#, c-format +msgid "cannot open %s: %s" +msgstr "Ne peut pas lire %s : %s" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "Le processus fils a été terminé par le signal %d" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "Le processus fils s'est terminé avec le statut %d" + +#: dnsmasq.c:859 +#, c-format +msgid "failed to execute %s: %s" +msgstr "impossible d'exécuter à %s : %s" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "sortie sur réception du signal SIGTERM" + +#: dnsmasq.c:931 +#, c-format +msgid "failed to access %s: %s" +msgstr "impossible d'accéder à %s : %s" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "Lecture de %s" + +#: dnsmasq.c:972 +#, c-format +msgid "no servers found in %s, will retry" +msgstr "aucun serveur trouvé dans %s, va réessayer" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "ne peut créer la socket DHCP: %s" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "impossible d'appliquer les options sur la socket DHCP : %s" + +#: dhcp.c:65 +#, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "impossible de déclarer SO_REUSE{ADDR|PORT} sur la socket DHCP : %s" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "impossible de lier la socket serveur DHCP : %s" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "ne peut créer de socket en mode raw pour ICMP : %s." + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "Paquet DHCP reçu sur %s qui n'a pas d'adresse" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "La plage d'adresses DHCP %s -- %s n'est pas cohérente avec le masque de réseau %s" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "mauvaise ligne dans %s ligne %d" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "ignore %s à la ligne %d : duplication de nom ou d'adresse IP" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "adresse IP %s dupliquée dans la directive dhcp-config." + +#: dhcp.c:981 +#, c-format +msgid "duplicate IP address %s in %s." +msgstr "adresse IP %s dupliquée dans %s." + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "%s a plus d'une adresse dans le fichier d'hôte, utilisation de %s pour le DHCP." + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "adresse IP %s (%s) dupliquée dans la directive dhcp-config." + +#: lease.c:67 +#, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "ne peut ouvrir ou créer le fichiers de baux %s : %s" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "beaucoup trop de baux enregistrés" + +#: lease.c:129 +#, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "Ne peut pas exécuter le script lease-init %s : %s" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "le script lease-init a retourné le code %s" + +#: lease.c:235 +#, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "impossible de lire %s : %s (prochain essai dans %us)" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "pas de plage d'adresse disponible pour la requête DHCP %s %s" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "avec sélecteur de sous-reseau" + +#: rfc2131.c:316 +msgid "via" +msgstr "par l'intermédiaire de" + +#: rfc2131.c:331 +#, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "%u sous-réseaux DHCP disponibles : %s/%s" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "%u la gamme DHCP disponible est : %s -- %s" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "désactivé" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "ignoré" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "adresse déjà utilisée" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "pas d'adresse disponible" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "mauvais réseau" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "pas d'adresse configurée" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "plus aucun bail disponible" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "le client %u fourni le nom : %s" + +#: rfc2131.c:700 +#, c-format +msgid "%u vendor class: %s" +msgstr "%u Classe de vendeur ('Vendor Class') : %s" + +#: rfc2131.c:702 +#, c-format +msgid "%u user class: %s" +msgstr "%u Classe d'utilisateur : %s" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "Service PXE BIS (Boot Integrity Services) non supporté" + +#: rfc2131.c:886 +#, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "désactive l'adresse statique DHCP %s pour %s" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "bail inconnu" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "L'adresse statique %s ne sera pas utilisée car un bail est déjà attribué à %s" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "L'adresse statique %s ne sera pas utilisée car elle est utilisée par le serveur ou un relai" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "L'adresse statique %s ne sera pas utilisée car elle a préalablement été refusée" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "pas d'identifiant unique" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "mauvais identifiant de serveur" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "mauvaise adresse" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "bail non trouvé" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "adresse non disponible" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "bail statique disponible" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "adresse reservée" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "abandon du bail de %s pour %s" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "%u options: %s" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "%u nom de fichier 'bootfile' : %s" + +#: rfc2131.c:1732 +#, c-format +msgid "%u server name: %s" +msgstr "%u nom du serveur : %s" + +#: rfc2131.c:1746 +#, c-format +msgid "%u next server: %s" +msgstr "%u serveur suivant : %s" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "%u réponse broadcast" + +#: rfc2131.c:1812 +#, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "Impossible d'envoyer l'option DHCP/BOOTP %d : pas assez d'espace dans le paquet" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "menu PXE trop grand" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "Le domaine %s est ignoré pour l'hôte DHCP %s" + +#: rfc2131.c:2189 +#, c-format +msgid "%u requested options: %s" +msgstr "%u options demandées : %s" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "ne peux envoyer l'option RFC3925 : trop d'options pour le numéro d'entreprise %d" + +#: netlink.c:70 +#, c-format +msgid "cannot create netlink socket: %s" +msgstr "ne peux lier une socket netlink : %s" + +#: netlink.c:288 +#, c-format +msgid "netlink returns error: %s" +msgstr "Erreur netlink : %s" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "tentative de lier une adresse serveur IPV6 via DBus - pas de support IPV6" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "configuration des serveurs amonts à partir de DBus" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "ne peut enregistrer une routine de traitement des messages DBus" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "impossible de créer une socket BPF pour DHCP : %s" + +#: bpf.c:245 +#, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "requête DHCP pour un type de matériel non supporté (%d) reçue sur %s" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "impossible d'obtenir un port libre pour TFTP" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "requête de %s non supportée" + +#: tftp.c:406 +#, c-format +msgid "file %s not found" +msgstr "fichier %s non trouvé" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "erreur %d %s reçu de %s" + +#: tftp.c:554 +#, c-format +msgid "failed sending %s to %s" +msgstr "impossible d'envoyer %s à %s" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "envoyé %s à %s" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "débordement : %d traces perdues" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "trace perdue : %s" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "IMPOSSIBLE de démarrer" + +# +#~ msgid "only one dhcp-hostsfile allowed" +#~ msgstr "une seule valeur est autorisée pour 'dhcp-hostsfile'" + +# +#~ msgid "only one dhcp-optsfile allowed" +#~ msgstr "une seule valeur est autorisée pour 'dhcp-optsfile'" + +#~ msgid "files nested too deep in %s" +#~ msgstr "trop de niveaux de récursion pour les fichiers dans %s" + +#~ msgid "TXT record string too long" +#~ msgstr "chaîne du champ TXT trop longue" + +#~ msgid "failed to set IPV6 options on listening socket: %s" +#~ msgstr "impossible d'activer les options IPV6 sur la socket de lecture : %s" + +#~ msgid "failed to bind listening socket for %s: %s" +#~ msgstr "impossible de lier la socket de lecture pour %s : %s" + +#~ msgid "failed to listen on socket: %s" +#~ msgstr "impossible de lire sur la socket : %s" + +#~ msgid "failed to create TFTP socket: %s" +#~ msgstr "impossible de créer une socket TFTP : %s" + +#~ msgid "DHCP packet: transaction-id is %u" +#~ msgstr "paquet DHCP : l'identifiant de transaction ('transaction-id') est %u" + +#~ msgid "failed to read %s:%s" +#~ msgstr "impossible de lire %s : %s" + +#~ msgid "must set exactly one interface on broken systems without IP_RECVIF" +#~ msgstr "Une interface et une seule doit être déclarée sur les systèmes sans IP_RECVIF" + +# +#~ msgid "failed to load %s: %s" +#~ msgstr "impossible de charger %s : %m" + +#~ msgid "bad name in %s" +#~ msgstr "mauvais nom dans %s" + +#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part" +#~ msgstr "On ignore le bail DHCP pour %s car il possède un nom de domaine illégal" + +#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h" +#~ msgstr "L'intégration DHCP ISC n'est pas disponible : activez HAVE_ISC_READER dans src/config.h" + +# +#~ msgid "illegal domain %s in dhcp-config directive." +#~ msgstr "domaine %s dupliqué dans la directive dhcp-config." + +#~ msgid "illegal domain %s in %s." +#~ msgstr "domaine %s illégal dans %s." + +#~ msgid "running as root" +#~ msgstr "executé en temps que root" + +#~ msgid "Read leases at startup, but never write the lease file." +#~ msgstr "Lecture des baux au démarrage, mais aucune écriture de fichier de baux" + +# +#~ msgid "read %s - %d hosts" +#~ msgstr "lecture %s - %d hôtes" + +#~ msgid "domains" +#~ msgstr "domaines" + +#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part" +#~ msgstr "Le nom de machine DHCP %s sera ignoré parce qu'il possède un nom de domaine illégal" + +#~ msgid "Display this message." +#~ msgstr "Affiche ce message." + +#~ msgid "failed to read %s: %m" +#~ msgstr "impossible de lire %s : %m" + +#~ msgid "failed to read %s:%m" +#~ msgstr "impossible de lire %s : %m" + +# +#~ msgid "cannot send encapsulated option %d: no space left in wrapper" +#~ msgstr "Impossible d'envoyer l'option DHCP %d : pas assez d'espace dans le paquet" + +#~ msgid "More than one vendor class matches, using %s" +#~ msgstr "Plusieurs classes de fournisseurs correspondent, %s sera utilisé" diff --git a/po/id.po b/po/id.po new file mode 100644 index 0000000..749da19 --- /dev/null +++ b/po/id.po @@ -0,0 +1,1799 @@ +# Indonesian translations for dnsmasq package. +# This file is put in the public domain. +# Salman AS <sas@salman.or.id>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.24\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2005-10-07 11:45+0100\n" +"Last-Translator: Salman AS <sas@salman.or.id>\n" +"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" + +# OK +#: cache.c:761 +#, fuzzy, c-format +msgid "failed to load names from %s: %s" +msgstr "gagal memuat nama-nama dari %s: %s" + +# OK +#: cache.c:795 dhcp.c:865 +#, fuzzy, c-format +msgid "bad address at %s line %d" +msgstr "kesalahan nama pada %s baris %d" + +# OK +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "kesalahan nama pada %s baris %d" + +# OK +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "membaca %s - %d alamat" + +# OK +#: cache.c:899 +msgid "cleared cache" +msgstr "cache telah dihapus" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "" + +# OK +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "tidak memberikan nama %s kepada lease DHCP %s karena nama telah ada dalam %sdengan alamat %s" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "" + +# OK +#: cache.c:1040 +#, fuzzy, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "ukuran cache %d, %d/%d penyisipan cache menimpa cache yang belum kadaluwarsa" + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "" + +# OK +#: util.c:57 +#, fuzzy, c-format +msgid "failed to seed the random number generator: %s" +msgstr "gagal mendengarkan di socket: %s" + +# OK +#: util.c:189 +#, fuzzy +msgid "failed to allocate memory" +msgstr "gagal memuat %S: %m" + +# OK +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "tidak bisa mendapatkan memory" + +# OK +#: util.c:237 +#, fuzzy, c-format +msgid "cannot create pipe: %s" +msgstr "tidak bisa membaca %s: %s" + +# OK +#: util.c:245 +#, fuzzy, c-format +msgid "failed to allocate %d bytes" +msgstr "gagal memuat %S: %m" + +# OK +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "tak terbatas" + +# OK +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "Tentukan alamat lokal untuk mendengarkan." + +# OK +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "Menghasilkan ipaddr untuk semua host dalam domain yang dipilih." + +# OK +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "Fake pencarian balik untuk alamat private sesuai dengan RFC1918." + +# OK +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "Perlakukan ipaddr sebagai NXDOMAIN (mengalahkan wildcard Verisign)." + +# OK +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "Tentukan ukuran cache, dalam jumlah isian (default %s)." + +# OK +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "Tentukan file konfigurasi (default %s)." + +# OK +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "JANGAN berjalan di background: berjalan dalam modus debug." + +# OK +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "JANGAN teruskan permintaan tanpa bagian domain." + +# OK +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "Mengembalikan record MX untuk diri sendiri host-host lokal." + +# OK +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "Melengkapi nama-nama di /etc/hosts dengan akhiran domain." + +# OK +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "Jangan meneruskan permintaan DNS spurious dari host-host Windows." + +# OK +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "Bolehkan DHCP dalam jangkauan yang diberikan dengan durasi lease." + +# OK +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "Ubah ke group ini setelah mulai (default %s)." + +# OK +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "Setel alamat atau nama host untuk mesin yang disebutkan." + +# OK +#: option.c:258 +#, fuzzy +msgid "Read DHCP host specs from file." +msgstr "nama MX salah" + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "" + +# OK +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "JANGAN muat file %s." + +# OK +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "Sebutkan sebuah file hosts yang harus dibaca sebagai tambahan untuk %s." + +# OK +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "Sebutkan antarmuka untuk mendengarkan." + +# OK +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "Sebutkan antarmuka untuk TIDAK mendengarkan." + +# OK +#: option.c:265 +#, fuzzy +msgid "Map DHCP user class to tag." +msgstr "Petakan kelas user DHCP ke setelan yang dipilih." + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "" + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "" + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "" + +# OK +#: option.c:269 +#, fuzzy +msgid "Don't do DHCP for hosts with tag set." +msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih." + +# OK +#: option.c:270 +#, fuzzy +msgid "Force broadcast replies for hosts with tag set." +msgstr "Jangan menggunakan DHCP untuk host-host yang dipilih." + +# OK +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "JANGAN berjalan di background, jangan berjalan dalam modus debug." + +# OK +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "Berpikir bahwa kita satu-satunya DHCP server dalam jaringan." + +# OK +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "Sebutkan lokasi untuk menyimpan lease DHCP (default %s)." + +# OK +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "Kembalikan rekord MX untuk host-host lokal." + +# OK +#: option.c:275 +msgid "Specify an MX record." +msgstr "Sebutkan sebuah rekord MX." + +# OK +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "Sebutkan pilihan-pilihan BOOTP untuk DHCP server." + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "Jangan kumpulkan file %s, muat kembali saat SIGHUP." + +# OK +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "JANGAN menyimpan hasil pencarian yang gagal." + +# OK +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "Gunakan secara ketat namaserver yang disebutkan sesuai urutan di %s." + +# OK +#: option.c:280 +#, fuzzy +msgid "Specify options to be sent to DHCP clients." +msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP." + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "" + +# OK +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "Sebutkan port untuk mendengarkan permintaan DNS (default port 53)." + +# OK +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "Ukuran maksimum paket UDP yang didukung untuk EDNS.0 (default %s)." + +# OK +#: option.c:284 +#, fuzzy +msgid "Log DNS queries." +msgstr "Permintaan log." + +# OK +#: option.c:285 +#, fuzzy +msgid "Force the originating port for upstream DNS queries." +msgstr "Paksa port asal untuk permintaan ke atas." + +# OK +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "JANGAN baca resolv.conf." + +# OK +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "Sebutkan path ke resolv.conf (default %s)." + +# OK +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "Sebutkan alamat-alamat server di atas, boleh dilengkapi dengan nama domain." + +# OK +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "JANGAN pernah meneruskan permintaan ke domain yang disebutkan." + +# OK +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "Sebutkan domain yang digunakan dalam lease DHCP." + +# OK +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "Sebutkan tujuan default dalam rekord MX." + +# OK +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts." + +# OK +#: option.c:293 +#, fuzzy +msgid "Specify time-to-live in seconds for negative caching." +msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts." + +# OK +#: option.c:294 +#, fuzzy +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "Sebutkan time-to-live dalam detik untuk jawaban dari /etc/hosts." + +# OK +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "Ubah ke user ini setelah mulai. (default %s)." + +# OK +#: option.c:296 +#, fuzzy +msgid "Map DHCP vendor class to tag." +msgstr "Memetakan kelas vendor DHCP ke daftar pilihan." + +# OK +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "Menampilkan versi dan informasi hak cipta dnsmasq." + +# OK +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "Terjemahkan alamat-alamat IPv4 dari server-server di atas." + +# OK +#: option.c:299 +msgid "Specify a SRV record." +msgstr "Sebutkan rekord SRV." + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "" + +# OK +#: option.c:301 +#, fuzzy, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "Sebutkan path file PID. (default %s)." + +# OK +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)." + +# OK +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "Jawab permintaan DNS berdasarkan antarmuka dimana permintaan dikirimkan." + +# OK +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "Sebutkan rekord TXT DNS." + +# OK +#: option.c:305 +#, fuzzy +msgid "Specify PTR DNS record." +msgstr "Sebutkan rekord TXT DNS." + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "" + +# OK +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "Hanya kaitkan ke antarmuka yang sedang digunakan saja." + +# OK +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "Baca informasi statik host DHCP dari %s." + +# OK +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "Mungkinkan antar muka DBus untuk menyetel server-server di atas, dsb." + +# OK +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "JANGAN menyediakan DHCP pada antarmuka ini, hanya menyediakan DNS." + +# OK +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "Mungkinkan alokasi alamat dinamis untuk bootp." + +# OK +#: option.c:312 +#, fuzzy +msgid "Map MAC address (with wildcards) to option set." +msgstr "Memetakan kelas vendor DHCP ke daftar pilihan." + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "" + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "" + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "" + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "" + +# OK +#: option.c:317 +#, fuzzy +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "Ubah ke user ini setelah mulai. (default %s)." + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "" + +# OK +#: option.c:319 +#, fuzzy, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)." + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "" + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "" + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "" + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "" + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "" + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "" + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "" + +# OK +#: option.c:327 +#, fuzzy, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "Sebutkan jumlah maksimum lease DHCP (default %s)." + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "" + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "" + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "" + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "" + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "" + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "" + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "" + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "" + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "" + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "" + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "" + +# OK +#: option.c:339 +#, fuzzy +msgid "Specify NAPTR DNS record." +msgstr "Sebutkan rekord TXT DNS." + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "" + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "" + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "" + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "" + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "" + +# OK +#: option.c:345 +#, fuzzy +msgid "Prompt to send to PXE clients." +msgstr "Setel pilihan-pilihan tambahan yang akan disetel untuk klien-klien DHCP." + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "" + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "" + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +# OK +#: option.c:349 +#, fuzzy +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "Terjemahkan alamat-alamat IPv4 dari server-server di atas." + +# OK +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" +"Penggunaan: dnsmasq [pilihan]\n" +"\n" + +# OK +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "Gunakan pilihan pendek saja pada perintah baris.\n" + +# OK +#: option.c:642 +#, fuzzy, c-format +msgid "Valid options are:\n" +msgstr "Pilihan yang boleh adalah:\n" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "" + +# OK +#: option.c:798 +msgid "bad dhcp-option" +msgstr "dhcp-option salah" + +# OK +#: option.c:860 +#, fuzzy +msgid "bad IP address" +msgstr "membaca %s - %d alamat" + +# OK +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "domain dalam dhcp-option salah" + +# OK +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "dhcp-option terlalu panjang" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "" + +# OK +#: option.c:1147 option.c:3030 +#, fuzzy, c-format +msgid "cannot access directory %s: %s" +msgstr "tidak bisa membaca %s: %s" + +# OK +#: option.c:1178 tftp.c:460 +#, fuzzy, c-format +msgid "cannot access %s: %s" +msgstr "tidak bisa membaca %s: %s" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +# OK +#: option.c:1265 +msgid "bad MX preference" +msgstr "kesukaan MX salah" + +# OK +#: option.c:1270 +msgid "bad MX name" +msgstr "nama MX salah" + +# OK +#: option.c:1284 +msgid "bad MX target" +msgstr "target MX salah" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "" + +# OK +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "port salah" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "" + +# OK +#: option.c:1791 +#, fuzzy +msgid "bad port range" +msgstr "port salah" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "" + +# OK +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "dhcp-range salah" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "" + +# OK +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "jangkauan DHCP tidak konsisten" + +# OK +#: option.c:2019 option.c:2045 +#, fuzzy +msgid "bad hex constant" +msgstr "dhcp-host salah" + +# OK +#: option.c:2107 +#, fuzzy +msgid "bad DHCP host name" +msgstr "nama MX salah" + +# OK +#: option.c:2188 +#, fuzzy +msgid "bad tag-if" +msgstr "target MX salah" + +# OK +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "nomor port tidak benar" + +# OK +#: option.c:2529 +#, fuzzy +msgid "bad dhcp-proxy address" +msgstr "membaca %s - %d alamat" + +# OK +#: option.c:2569 +#, fuzzy +msgid "invalid alias range" +msgstr "weight tidak benar" + +# OK +#: option.c:2582 +#, fuzzy +msgid "bad interface name" +msgstr "nama MX salah" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "" + +# OK +#: option.c:2632 +#, fuzzy +msgid "bad PTR record" +msgstr "rekord SRV salah" + +# OK +#: option.c:2663 +#, fuzzy +msgid "bad NAPTR record" +msgstr "rekord SRV salah" + +# OK +#: option.c:2695 +msgid "bad TXT record" +msgstr "rekord TXT salah" + +# OK +#: option.c:2738 +msgid "bad SRV record" +msgstr "rekord SRV salah" + +# OK +#: option.c:2745 +msgid "bad SRV target" +msgstr "target SRV salah" + +# OK +#: option.c:2759 +msgid "invalid priority" +msgstr "prioritas tidak benar" + +# OK +#: option.c:2766 +msgid "invalid weight" +msgstr "weight tidak benar" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "" + +# OK +#: option.c:2849 +msgid "missing \"" +msgstr "kurang \"" + +# OK +#: option.c:2908 +msgid "bad option" +msgstr "pilihan salah" + +# OK +#: option.c:2910 +msgid "extraneous parameter" +msgstr "parameter berlebihan" + +# OK +#: option.c:2912 +msgid "missing parameter" +msgstr "parameter kurang" + +# OK +#: option.c:2916 +msgid "error" +msgstr "kesalahan" + +# OK +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "%s pada baris %d dari %%s" + +# OK +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "tidak bisa membaca %s: %s" + +# OK +#: option.c:3151 option.c:3187 +#, fuzzy, c-format +msgid "read %s" +msgstr "membaca %s" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +# OK +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "Dnsmasq versi %s %s\n" + +# OK +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" +"Pilihan-pilihan saat kompilasi %s\n" +"\n" + +# OK +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "Perangkat lunak ini tersedia TANPA JAMINAN SEDIKITPUN.\n" + +# OK +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "Dnsdmasq adalah perangkat lunak bebas, dan Anda dipersilahkan untuk membagikannya\n" + +# OK +#: option.c:3273 +#, fuzzy, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "dengan aturan GNU General Public License, versi 2.\n" + +#: option.c:3284 +msgid "try --help" +msgstr "" + +#: option.c:3286 +msgid "try -w" +msgstr "" + +# OK +#: option.c:3289 +#, fuzzy, c-format +msgid "bad command line options: %s" +msgstr "pilihan baris perintah salah: %s." + +# OK +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "tidak bisa mendapatkan host-name: %s" + +# OK +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "hanya satu file resolv.conf yang diperbolehkan dalam modus no-poll." + +# OK +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "harus mempunyai tepat satu resolv.conf untuk mendapatkan nama domain." + +# OK +#: option.c:3371 network.c:848 dhcp.c:814 +#, fuzzy, c-format +msgid "failed to read %s: %s" +msgstr "gagal membaca %s: %s" + +# OK +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "tidak ditemukan direktif search di %s" + +#: option.c:3409 +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "" + +# OK +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "nameserver %s menolak melakukan resolusi rekursif" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "" + +# OK +#: network.c:171 +#, fuzzy, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "antarmuka tidak dikenal %s" + +# OK +#: network.c:380 +#, fuzzy, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "gagal membuat socket: %s " + +#: network.c:746 +#, fuzzy, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "gagal mem-bind socket untuk mendengarkan %s: %s" + +# OK +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "mengabaikan nameserver %s - antarmuka lokal" + +# OK +#: network.c:794 +#, fuzzy, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "mengabaikan nameserver %s - tak dapat membuat/mem-bind socket: %s" + +# OK +#: network.c:811 +msgid "unqualified" +msgstr "tidak memenuhi syarat" + +#: network.c:811 +msgid "names" +msgstr "" + +#: network.c:813 +msgid "default" +msgstr "" + +# OK +#: network.c:815 +msgid "domain" +msgstr "domain" + +# OK +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "menggunakan alamat lokal saja untuk %s %s" + +# OK +#: network.c:820 +#, fuzzy, c-format +msgid "using standard nameservers for %s %s" +msgstr "menggunakan nameserver %s#%d untuk %s %s" + +# OK +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "menggunakan nameserver %s#%d untuk %s %s" + +# OK +#: network.c:825 +#, fuzzy, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "menggunakan nameserver %s#%d" + +# OK +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "menggunakan nameserver %s#%d" + +# OK +#: dnsmasq.c:148 +#, fuzzy +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "" + +#: dnsmasq.c:158 +msgid "asychronous logging is not available under Android" +msgstr "" + +# OK +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "gagal mendapatkan daftar antarmuka: %s" + +# OK +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "antarmuka tidak dikenal %s" + +# OK +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "tidak ada antarmuka dengan alamat %s" + +# OK +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "DBus error: %s" + +# OK +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "DBus tidak tersedia: setel HAVE_DBUS dalam src/config.h" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "" + +# OK +#: dnsmasq.c:455 +#, fuzzy, c-format +msgid "started, version %s DNS disabled" +msgstr "dimulai, cache versi %s di disable" + +# OK +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "dimulai, versi %s ukuran cache %d" + +# OK +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "dimulai, cache versi %s di disable" + +# OK +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "pilihan-pilihan saat kompilasi: %s" + +# OK +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "dukungan DBus dimungkinkan: terkoneksi pada bus sistem" + +# OK +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "dukungan DBus dimungkinkan: koneksi bus ditunda" + +# OK +#: dnsmasq.c:474 +#, fuzzy, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "gagal memuat nama-nama dari %s: %s" + +# OK +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "setelan opsi --bind-interfaces disebabkan keterbatasan OS" + +# OK +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "peringatan: antarmuka %s tidak ada" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "" + +# OK +#: dnsmasq.c:491 +#, fuzzy +msgid "warning: no upstream servers configured" +msgstr "menyetel server-server di atas dengan DBus" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "" + +# OK +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "DHCP, lease static pada %.0s%s, waktu lease %s" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "" + +# OK +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "DHCP, jangkaun IP %s -- %s, waktu lease %s" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "" + +# OK +#: dnsmasq.c:526 +#, fuzzy +msgid "enabled" +msgstr "di disable" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "" + +# OK +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "terhubung ke sistem DBus" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "" + +# OK +#: dnsmasq.c:778 +#, fuzzy, c-format +msgid "failed to create helper: %s" +msgstr "gagal membaca %s: %s" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "" + +# OK +#: dnsmasq.c:785 +#, fuzzy, c-format +msgid "failed to change user-id to %s: %s" +msgstr "gagal memuat nama-nama dari %s: %s" + +# OK +#: dnsmasq.c:790 +#, fuzzy, c-format +msgid "failed to change group-id to %s: %s" +msgstr "gagal memuat nama-nama dari %s: %s" + +# OK +#: dnsmasq.c:793 +#, fuzzy, c-format +msgid "failed to open pidfile %s: %s" +msgstr "gagal membaca %s: %s" + +# OK +#: dnsmasq.c:796 +#, fuzzy, c-format +msgid "cannot open %s: %s" +msgstr "tidak bisa membuka %s:%s" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "" + +# OK +#: dnsmasq.c:859 +#, fuzzy, c-format +msgid "failed to execute %s: %s" +msgstr "gagal mengakses %s: %s" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "keluar karena menerima SIGTERM" + +# OK +#: dnsmasq.c:931 +#, fuzzy, c-format +msgid "failed to access %s: %s" +msgstr "gagal mengakses %s: %s" + +# OK +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "membaca %s" + +# OK +#: dnsmasq.c:972 +#, fuzzy, c-format +msgid "no servers found in %s, will retry" +msgstr "tidak ditemukan direktif search di %s" + +# OK +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "tidak bisa membuat socket DHCP: %s" + +# OK +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "gagal menyetel opsi pada socket DHCP: %s" + +# OK +#: dhcp.c:65 +#, fuzzy, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "gagal menyetel SO_REUSEADDR pada socket DHCP: %s" + +# OK +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "gagal mem-bind socket server DHCP: %s" + +# OK +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "tidak dapat membuat socket ICMP raw: %s" + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "" + +# OK +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "jangkauan DHCP %s -- %s tidak konsisten dengan netmask %s" + +# OK +#: dhcp.c:852 +#, fuzzy, c-format +msgid "bad line at %s line %d" +msgstr "kesalahan nama pada %s baris %d" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "" + +# OK +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "alamat IP kembar %s dalam direktif dhcp-config" + +# OK +#: dhcp.c:981 +#, fuzzy, c-format +msgid "duplicate IP address %s in %s." +msgstr "alamat IP kembar %s dalam direktif dhcp-config" + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "" + +# OK +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "alamat IP kembar %s (%s) dalam direktif dhcp-config" + +# OK +#: lease.c:67 +#, fuzzy, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "tidak dapat membuka atau membuat file lease: %s" + +# OK +#: lease.c:93 +msgid "too many stored leases" +msgstr "terlalu banyak lease yang disimpan" + +# OK +#: lease.c:129 +#, fuzzy, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "tidak bisa membaca %s: %s" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "" + +# OK +#: lease.c:235 +#, fuzzy, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "gagal membaca %s: %s" + +# OK +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s" + +# OK +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "dengan pemilih subnet" + +# OK +#: rfc2131.c:316 +msgid "via" +msgstr "lewat" + +# OK +#: rfc2131.c:331 +#, fuzzy, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "tidak ada alamat yang bisa dipakai untuk permintaan DHCP %s %s" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "" + +# OK +#: rfc2131.c:363 +msgid "disabled" +msgstr "di disable" + +# OK +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "diabaikan" + +# OK +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "alamat telah digunakan" + +# OK +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "tak ada alamat yang tersedia" + +# OK +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "jaringan yang salah" + +# OK +#: rfc2131.c:454 +msgid "no address configured" +msgstr "tak ada alamat yang disetel" + +# OK +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "tak ada lease yang tersisa" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "" + +# OK +#: rfc2131.c:700 +#, fuzzy, c-format +msgid "%u vendor class: %s" +msgstr "DBus error: %s" + +# OK +#: rfc2131.c:702 +#, fuzzy, c-format +msgid "%u user class: %s" +msgstr "DBus error: %s" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "" + +# OK +#: rfc2131.c:886 +#, fuzzy, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "men-disable alamat statik DHCP %s" + +# OK +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "lease tidak diketahui" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "" + +# OK +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "alamat salah" + +# OK +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "lease tak ditemukan" + +# OK +#: rfc2131.c:1106 +msgid "address not available" +msgstr "alamat tak tersedia" + +# OK +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "lease statik tak tersedia" + +# OK +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "alamat telah dipesan" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "" + +# OK +#: rfc2131.c:1732 +#, fuzzy, c-format +msgid "%u server name: %s" +msgstr "DBus error: %s" + +# OK +#: rfc2131.c:1746 +#, fuzzy, c-format +msgid "%u next server: %s" +msgstr "DBus error: %s" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "" + +#: rfc2131.c:1812 +#, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "" + +# OK +#: rfc2131.c:2189 +#, fuzzy, c-format +msgid "%u requested options: %s" +msgstr "pilihan-pilihan saat kompilasi: %s" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "" + +# OK +#: netlink.c:70 +#, fuzzy, c-format +msgid "cannot create netlink socket: %s" +msgstr "tidak bisa mem-bind netlink socket: %s" + +# OK +#: netlink.c:288 +#, fuzzy, c-format +msgid "netlink returns error: %s" +msgstr "DBus error: %s" + +# OK +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "mencoba menyetel sebuah alamat IPv6 server lewat DBus - tidak ada dukungan untuk IPv6" + +# OK +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "menyetel server-server di atas dengan DBus" + +# OK +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "tidak bisa mendaftar sebuah DBus message handler" + +# OK +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "tidak dapat membuat socket DHCP BPF: %s" + +# OK +#: bpf.c:245 +#, fuzzy, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "permintaan DHCP untuk tipe hardware yang tidak didukung (%d) diterima pada %s" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "" + +# OK +#: tftp.c:406 +#, fuzzy, c-format +msgid "file %s not found" +msgstr "lease tak ditemukan" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "" + +# OK +#: tftp.c:554 +#, fuzzy, c-format +msgid "failed sending %s to %s" +msgstr "gagal membaca %s: %s" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "" + +# OK +#: log.c:462 +msgid "FAILED to start up" +msgstr "GAGAL untuk memulai" + +# OK +#~ msgid "TXT record string too long" +#~ msgstr "string rekord TXT terlalu panjang" + +# OK +#~ msgid "failed to set IPV6 options on listening socket: %s" +#~ msgstr "gagal menyetel IPV6 pada socket: %s" + +#~ msgid "failed to bind listening socket for %s: %s" +#~ msgstr "gagal mem-bind socket untuk mendengarkan %s: %s" + +# OK +#~ msgid "failed to listen on socket: %s" +#~ msgstr "gagal mendengarkan di socket: %s" + +# OK +#, fuzzy +#~ msgid "failed to create TFTP socket: %s" +#~ msgstr "gagal membuat socket: %s " + +# OK +#~ msgid "must set exactly one interface on broken systems without IP_RECVIF" +#~ msgstr "harus menyetel satu antarmuka saja pada sistem yang tidak benar dengan IP_RECVIF" + +# OK +#, fuzzy +#~ msgid "failed to load %s: %s" +#~ msgstr "gagal memuat %S: %s" + +# OK +#~ msgid "bad name in %s" +#~ msgstr "kesalahan nama di %s" + +# OK +#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part" +#~ msgstr "Mengabaikan lease DHCP untuk %s sebab terdapat bagian domain yang tidak sah" + +# OK +#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h" +#~ msgstr "Integrasi dengan dhcpd ISC tidak tersedia: atur HAVE_ISC_READER dalam src/config.h" + +# OK +#, fuzzy +#~ msgid "illegal domain %s in dhcp-config directive." +#~ msgstr "alamat IP kembar %s dalam direktif dhcp-config" + +# OK +#~ msgid "running as root" +#~ msgstr "berjalan menggunakan root" + +# OK +#, fuzzy +#~ msgid "read %s - %d hosts" +#~ msgstr "membaca %s - %d alamat" + +# OK +#~ msgid "domains" +#~ msgstr "domain-domain" + +# OK +#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part" +#~ msgstr "Mengabaikan nama host DHCP %s sebab memiliki bagian domain yang tidak sah" + +# OK +#~ msgid "Display this message." +#~ msgstr "Menampilkan pesan ini." + +# OK +#~ msgid "failed to read %s: %m" +#~ msgstr "gagal membaca %s: %m" + +# OK +#~ msgid "failed to read %s:%m" +#~ msgstr "gagal membaca %s:%m" + +# OK +#~ msgid "More than one vendor class matches, using %s" +#~ msgstr "Lebih dari satu kelas vendor yang sesuai, menggunakan %s" + +# OK +#~ msgid "forwarding table overflow: check for server loops." +#~ msgstr "meneruskan tabel overflow: memeriksa apakah terjadi loop server." + +# OK +#~ msgid "nested includes not allowed" +#~ msgstr "includes bersarang tidak diijinkan" + +# OK +#~ msgid "DHCP, %s will be written every %s" +#~ msgstr "DHCP, %s akan ditulis setiap %s" + +# OK +#~ msgid "cannot create DHCP packet socket: %s. Is CONFIG_PACKET enabled in your kernel?" +#~ msgstr "tidak dapat membuat socket packet DHCP: %s. Apakah CONFIG_PACKET dimungkinkan pada kernel?" diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..0b42ef1 --- /dev/null +++ b/po/it.po @@ -0,0 +1,1455 @@ +# Italian translations for dnsmasq package. +# This file is put in the public domain. +# Simon Kelley <simon@thekelleys.org.uk>, 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.32\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2006-05-22 11:09+0100\n" +"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n" +"Language-Team: Italian <tp@lists.linux.it>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cache.c:761 +#, c-format +msgid "failed to load names from %s: %s" +msgstr "" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "" + +#: cache.c:899 +msgid "cleared cache" +msgstr "" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "" + +#: cache.c:1040 +#, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "" + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "" + +#: util.c:57 +#, c-format +msgid "failed to seed the random number generator: %s" +msgstr "" + +#: util.c:189 +msgid "failed to allocate memory" +msgstr "" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "" + +#: util.c:237 +#, c-format +msgid "cannot create pipe: %s" +msgstr "" + +#: util.c:245 +#, c-format +msgid "failed to allocate %d bytes" +msgstr "" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "" + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "" + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "" + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "" + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "" + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "" + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "" + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "" + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "" + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "" + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "" + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "" + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "" + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "" + +#: option.c:258 +msgid "Read DHCP host specs from file." +msgstr "" + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "" + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "" + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "" + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "" + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "" + +#: option.c:265 +msgid "Map DHCP user class to tag." +msgstr "" + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "" + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "" + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "" + +#: option.c:269 +msgid "Don't do DHCP for hosts with tag set." +msgstr "" + +#: option.c:270 +msgid "Force broadcast replies for hosts with tag set." +msgstr "" + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "" + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "" + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "" + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "" + +#: option.c:275 +msgid "Specify an MX record." +msgstr "" + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "" + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "" + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "" + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "" + +#: option.c:280 +msgid "Specify options to be sent to DHCP clients." +msgstr "" + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "" + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "" + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "" + +#: option.c:284 +msgid "Log DNS queries." +msgstr "" + +#: option.c:285 +msgid "Force the originating port for upstream DNS queries." +msgstr "" + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "" + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "" + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "" + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "" + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "" + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "" + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "" + +#: option.c:293 +msgid "Specify time-to-live in seconds for negative caching." +msgstr "" + +#: option.c:294 +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "" + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "" + +#: option.c:296 +msgid "Map DHCP vendor class to tag." +msgstr "" + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "" + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "" + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "" + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "" + +#: option.c:301 +#, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "" + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "" + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "" + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "" + +#: option.c:305 +msgid "Specify PTR DNS record." +msgstr "" + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "" + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "" + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "" + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "" + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "" + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "" + +#: option.c:312 +msgid "Map MAC address (with wildcards) to option set." +msgstr "" + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "" + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "" + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "" + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "" + +#: option.c:317 +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "" + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "" + +#: option.c:319 +#, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "" + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "" + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "" + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "" + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "" + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "" + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "" + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "" + +#: option.c:327 +#, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "" + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "" + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "" + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "" + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "" + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "" + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "" + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "" + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "" + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "" + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "" + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "" + +#: option.c:339 +msgid "Specify NAPTR DNS record." +msgstr "" + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "" + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "" + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "" + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "" + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "" + +#: option.c:345 +msgid "Prompt to send to PXE clients." +msgstr "" + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "" + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "" + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +#: option.c:349 +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "" + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "" + +#: option.c:642 +#, c-format +msgid "Valid options are:\n" +msgstr "" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "" + +#: option.c:860 +msgid "bad IP address" +msgstr "" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "" + +#: option.c:1147 option.c:3030 +#, c-format +msgid "cannot access directory %s: %s" +msgstr "" + +#: option.c:1178 tftp.c:460 +#, c-format +msgid "cannot access %s: %s" +msgstr "" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "" + +#: option.c:1270 +msgid "bad MX name" +msgstr "" + +#: option.c:1284 +msgid "bad MX target" +msgstr "" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "" + +#: option.c:1791 +msgid "bad port range" +msgstr "" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "" + +#: option.c:2019 option.c:2045 +msgid "bad hex constant" +msgstr "" + +#: option.c:2107 +msgid "bad DHCP host name" +msgstr "" + +#: option.c:2188 +msgid "bad tag-if" +msgstr "" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "" + +#: option.c:2529 +msgid "bad dhcp-proxy address" +msgstr "" + +#: option.c:2569 +msgid "invalid alias range" +msgstr "" + +#: option.c:2582 +msgid "bad interface name" +msgstr "" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "" + +#: option.c:2632 +msgid "bad PTR record" +msgstr "" + +#: option.c:2663 +msgid "bad NAPTR record" +msgstr "" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "" + +#: option.c:2759 +msgid "invalid priority" +msgstr "" + +#: option.c:2766 +msgid "invalid weight" +msgstr "" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "" + +#: option.c:2849 +msgid "missing \"" +msgstr "" + +#: option.c:2908 +msgid "bad option" +msgstr "" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "" + +#: option.c:2912 +msgid "missing parameter" +msgstr "" + +#: option.c:2916 +msgid "error" +msgstr "" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "" + +#: option.c:3151 option.c:3187 +#, c-format +msgid "read %s" +msgstr "" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "" + +#: option.c:3273 +#, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "" + +#: option.c:3284 +msgid "try --help" +msgstr "" + +#: option.c:3286 +msgid "try -w" +msgstr "" + +#: option.c:3289 +#, c-format +msgid "bad command line options: %s" +msgstr "" + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "" + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "" + +#: option.c:3371 network.c:848 dhcp.c:814 +#, c-format +msgid "failed to read %s: %s" +msgstr "" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "" + +#: option.c:3409 +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "" + +#: network.c:171 +#, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "" + +#: network.c:380 +#, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "" + +#: network.c:746 +#, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "" + +#: network.c:794 +#, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "" + +#: network.c:811 +msgid "unqualified" +msgstr "" + +#: network.c:811 +msgid "names" +msgstr "" + +#: network.c:813 +msgid "default" +msgstr "" + +#: network.c:815 +msgid "domain" +msgstr "" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "" + +#: network.c:820 +#, c-format +msgid "using standard nameservers for %s %s" +msgstr "" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "" + +#: network.c:825 +#, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "" + +#: dnsmasq.c:148 +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "" + +#: dnsmasq.c:158 +msgid "asychronous logging is not available under Android" +msgstr "" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "" + +#: dnsmasq.c:455 +#, c-format +msgid "started, version %s DNS disabled" +msgstr "" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "" + +#: dnsmasq.c:474 +#, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "" + +#: dnsmasq.c:491 +msgid "warning: no upstream servers configured" +msgstr "" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "" + +#: dnsmasq.c:526 +msgid "enabled" +msgstr "" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "" + +#: dnsmasq.c:778 +#, c-format +msgid "failed to create helper: %s" +msgstr "" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "" + +#: dnsmasq.c:785 +#, c-format +msgid "failed to change user-id to %s: %s" +msgstr "" + +#: dnsmasq.c:790 +#, c-format +msgid "failed to change group-id to %s: %s" +msgstr "" + +#: dnsmasq.c:793 +#, c-format +msgid "failed to open pidfile %s: %s" +msgstr "" + +#: dnsmasq.c:796 +#, c-format +msgid "cannot open %s: %s" +msgstr "" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "" + +#: dnsmasq.c:859 +#, c-format +msgid "failed to execute %s: %s" +msgstr "" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "" + +#: dnsmasq.c:931 +#, c-format +msgid "failed to access %s: %s" +msgstr "" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "" + +#: dnsmasq.c:972 +#, c-format +msgid "no servers found in %s, will retry" +msgstr "" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "" + +#: dhcp.c:65 +#, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "" + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "" + +#: dhcp.c:981 +#, c-format +msgid "duplicate IP address %s in %s." +msgstr "" + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "" + +#: lease.c:67 +#, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "" + +#: lease.c:129 +#, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "" + +#: lease.c:235 +#, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "" + +#: rfc2131.c:316 +msgid "via" +msgstr "" + +#: rfc2131.c:331 +#, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "" + +#: rfc2131.c:700 +#, c-format +msgid "%u vendor class: %s" +msgstr "" + +#: rfc2131.c:702 +#, c-format +msgid "%u user class: %s" +msgstr "" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "" + +#: rfc2131.c:886 +#, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "" + +#: rfc2131.c:1732 +#, c-format +msgid "%u server name: %s" +msgstr "" + +#: rfc2131.c:1746 +#, c-format +msgid "%u next server: %s" +msgstr "" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "" + +#: rfc2131.c:1812 +#, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "" + +#: rfc2131.c:2189 +#, c-format +msgid "%u requested options: %s" +msgstr "" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "" + +#: netlink.c:70 +#, c-format +msgid "cannot create netlink socket: %s" +msgstr "" + +#: netlink.c:288 +#, c-format +msgid "netlink returns error: %s" +msgstr "" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "" + +#: bpf.c:245 +#, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "" + +#: tftp.c:406 +#, c-format +msgid "file %s not found" +msgstr "" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "" + +#: tftp.c:554 +#, c-format +msgid "failed sending %s to %s" +msgstr "" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "" diff --git a/po/no.po b/po/no.po new file mode 100644 index 0000000..78382cf --- /dev/null +++ b/po/no.po @@ -0,0 +1,1571 @@ +# Norwegian translations for dnsmasq package. +# This file is put in the public domain. +# Simon Kelley <simon@thekelleys.org.uk>, 2006. +# +# Current translator: Jan Erik Askildt <jeaskildt@gmail.com>, 2006 +# +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.25\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2006-01-11 17:39+0000\n" +"Last-Translator: Jan Erik Askildt <jeaskildt@gmail.com>\n" +"Language-Team: Norwegian <i18n-nb@lister.ping.uio.no>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cache.c:761 +#, fuzzy, c-format +msgid "failed to load names from %s: %s" +msgstr "feilet å laste navn fra %s: %s" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "dårlig adresse ved %s linje %d" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "dårlig navn ved %s linje %d" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "les %s - %d adresser" + +#: cache.c:899 +msgid "cleared cache" +msgstr "mellomlager tømt" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "gir ikke navnet %s til DHCP leien for %s fordi navnet eksisterer i %s med adressen %s" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "" + +#: cache.c:1040 +#, fuzzy, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "mellomlager størrelse %d, %d/%d mellomlager innsettinger re-bruker mellomlager plasser som ikke er utløpt" + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "" + +#: util.c:57 +#, fuzzy, c-format +msgid "failed to seed the random number generator: %s" +msgstr "feilet å lytte på socket: %s" + +#: util.c:189 +#, fuzzy +msgid "failed to allocate memory" +msgstr "feilet å laste %d bytes" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "kunne ikke få minne" + +#: util.c:237 +#, fuzzy, c-format +msgid "cannot create pipe: %s" +msgstr "kan ikke lese %s: %s" + +#: util.c:245 +#, fuzzy, c-format +msgid "failed to allocate %d bytes" +msgstr "feilet å laste %d bytes" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "uendelig" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "Spesifiser lokal(e) adresse(r) å lytte på." + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "Returner ipaddr for alle verter i det spesifiserte domenet." + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "Forfalsk revers oppslag for RFC1918 private adresse områder." + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "Behandle ipaddr som NXDOMAIN (omgår Verisign wildcard)." + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "Spesifiser størrelsen på mellomlager plassene (standard er %s)." + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "Spesifiser konfigurasjonsfil (standard er %s)." + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "IKKE legg (fork) som bakgrunnsprosess: kjør i debug modus." + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "IKKE videresend oppslag som mangler domene del." + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "Returner selv-pekende MX post for lokale verter." + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "Utvid enkle navn i /etc/hosts med domene-suffiks." + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "Ikke videresend falske/uekte DNS forespørsler fra Windows verter." + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "Aktiver DHCP i det gitte området med leie varighet" + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "Skift til denne gruppen etter oppstart (standard er %s)." + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "Sett adresse eller vertsnavn for en spesifikk maskin." + +#: option.c:258 +#, fuzzy +msgid "Read DHCP host specs from file." +msgstr "dårlig MX navn" + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "" + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "IKKE last %s filen." + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "Spesifiser en verts (hosts) fil som skal leses i tilleg til %s." + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "Spesifiser nettverkskort det skal lyttes på." + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "Spesifiser nettverkskort det IKKE skal lyttes på." + +#: option.c:265 +#, fuzzy +msgid "Map DHCP user class to tag." +msgstr "Map DHCP bruker klasse til opsjon sett." + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "" + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "" + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "" + +#: option.c:269 +#, fuzzy +msgid "Don't do DHCP for hosts with tag set." +msgstr "Ikke utfør DHCP for klienter i opsjon sett." + +#: option.c:270 +#, fuzzy +msgid "Force broadcast replies for hosts with tag set." +msgstr "Ikke utfør DHCP for klienter i opsjon sett." + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "IKKE last (fork) som bakgrunnsprosess, IKKE kjør i debug modus." + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "Anta at vi er den eneste DHCP tjeneren på det lokale nettverket." + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "Spesifiser hvor DHCP leiene skal lagres (standard er %s)." + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "Returner MX records for lokale verter." + +#: option.c:275 +msgid "Specify an MX record." +msgstr "Spesifiser en MX post." + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "Spesifiser BOOTP opsjoner til DHCP tjener." + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "IKKE spør (poll) %s fil, les på nytt kun ved SIGHUP" + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "IKKE mellomlagre søkeresultater som feiler." + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "Bruk navnetjenere kun som bestemt i rekkefølgen gitt i %s." + +#: option.c:280 +#, fuzzy +msgid "Specify options to be sent to DHCP clients." +msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene." + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "" + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "Spesifiser lytteport for DNS oppslag (standard er 53)." + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "Maksimal støttet UDP pakkestørrelse for EDNS.0 (standard er %s)." + +#: option.c:284 +#, fuzzy +msgid "Log DNS queries." +msgstr "Logg oppslag." + +#: option.c:285 +#, fuzzy +msgid "Force the originating port for upstream DNS queries." +msgstr "Tving bruk av opprinnelig port for oppstrøms oppslag." + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "IKKE les resolv.conf." + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "Spesifiser stien til resolv.conf (standard er %s)." + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "Spesifiser adressen(e) til oppstrøms tjenere med valgfrie domener." + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "Aldri videresend oppslag til spesifiserte domener." + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "Spesifiser domenet som skal tildeles i DHCP leien." + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "Spesifiser default mål i en MX post." + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts." + +#: option.c:293 +#, fuzzy +msgid "Specify time-to-live in seconds for negative caching." +msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts." + +#: option.c:294 +#, fuzzy +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "Spesifiser time-to-live i sekunder for svar fra /etc/hosts." + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "Skift til denne bruker etter oppstart (standard er %s)." + +#: option.c:296 +#, fuzzy +msgid "Map DHCP vendor class to tag." +msgstr "Map DHCP produsent klasse til opsjon sett." + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "Vis dnsmasq versjon og copyright informasjon." + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "Oversett IPv4 adresser fra oppstrøms tjenere." + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "Spesifiser en SRV post." + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "" + +#: option.c:301 +#, fuzzy, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "Spesifiser stien til PID fil. (standard er %s)." + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)" + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "Svar DNS oppslag basert på nettverkskortet oppslaget ble sendt til." + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "Spesifiser TXT DNS post." + +#: option.c:305 +#, fuzzy +msgid "Specify PTR DNS record." +msgstr "Spesifiser TXT DNS post." + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "" + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "Bind kun til nettverkskort som er i bruk." + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "Les DHCP statisk vert informasjon fra %s." + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "Aktiver DBus interface for å sette oppstrøms tjenere, osv." + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "Ikke lever DHCP på dette nettverkskortet, kun lever DNS." + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "Aktiver dynamisk adresse allokering for bootp." + +#: option.c:312 +#, fuzzy +msgid "Map MAC address (with wildcards) to option set." +msgstr "Map DHCP produsent klasse til opsjon sett." + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "" + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "" + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "" + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "" + +#: option.c:317 +#, fuzzy +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "Skift til denne bruker etter oppstart (standard er %s)." + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "" + +#: option.c:319 +#, fuzzy, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)" + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "" + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "" + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "" + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "" + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "" + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "" + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "" + +#: option.c:327 +#, fuzzy, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "Spesifiser maksimum antall DHCP leier (standard er %s)" + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "" + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "" + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "" + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "" + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "" + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "" + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "" + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "" + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "" + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "" + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "" + +#: option.c:339 +#, fuzzy +msgid "Specify NAPTR DNS record." +msgstr "Spesifiser TXT DNS post." + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "" + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "" + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "" + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "" + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "" + +#: option.c:345 +#, fuzzy +msgid "Prompt to send to PXE clients." +msgstr "Sett ekstra opsjoner som skal fordeles til DHCP klientene." + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "" + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "" + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +#: option.c:349 +#, fuzzy +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "Oversett IPv4 adresser fra oppstrøms tjenere." + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" +"Bruk: dnsmasq [opsjoner]\n" +"\n" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "Bruk korte opsjoner kun på kommandolinjen.\n" + +#: option.c:642 +#, fuzzy, c-format +msgid "Valid options are:\n" +msgstr "Gyldige opsjoner er :\n" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "dårlig dhcp-opsjon" + +#: option.c:860 +#, fuzzy +msgid "bad IP address" +msgstr "les %s - %d adresser" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "dårlig domene i dhcp-opsjon" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "dhcp-opsjon for lang" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "" + +#: option.c:1147 option.c:3030 +#, fuzzy, c-format +msgid "cannot access directory %s: %s" +msgstr "kan ikke lese %s: %s" + +#: option.c:1178 tftp.c:460 +#, fuzzy, c-format +msgid "cannot access %s: %s" +msgstr "kan ikke lese %s: %s" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "dårlig MX preferanse" + +#: option.c:1270 +msgid "bad MX name" +msgstr "dårlig MX navn" + +#: option.c:1284 +msgid "bad MX target" +msgstr "dårlig MX mål" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "dårlig port" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "" + +#: option.c:1791 +#, fuzzy +msgid "bad port range" +msgstr "dårlig port" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "dårlig dhcp-område" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "ikke konsistent DHCP område" + +#: option.c:2019 option.c:2045 +#, fuzzy +msgid "bad hex constant" +msgstr "dårlig dhcp-vert" + +#: option.c:2107 +#, fuzzy +msgid "bad DHCP host name" +msgstr "dårlig MX navn" + +#: option.c:2188 +#, fuzzy +msgid "bad tag-if" +msgstr "dårlig MX mål" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "ugyldig portnummer" + +#: option.c:2529 +#, fuzzy +msgid "bad dhcp-proxy address" +msgstr "les %s - %d adresser" + +#: option.c:2569 +#, fuzzy +msgid "invalid alias range" +msgstr "ugyldig vekt" + +#: option.c:2582 +#, fuzzy +msgid "bad interface name" +msgstr "dårlig MX navn" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "" + +#: option.c:2632 +#, fuzzy +msgid "bad PTR record" +msgstr "dårlig SRV post" + +#: option.c:2663 +#, fuzzy +msgid "bad NAPTR record" +msgstr "dårlig SRV post" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "dårlig TXT post" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "dårlig SRV post" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "dårlig SRV mål" + +#: option.c:2759 +msgid "invalid priority" +msgstr "ugyldig prioritet" + +#: option.c:2766 +msgid "invalid weight" +msgstr "ugyldig vekt" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "" + +#: option.c:2849 +msgid "missing \"" +msgstr "mangler \"" + +#: option.c:2908 +msgid "bad option" +msgstr "dårlig opsjon" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "overflødig parameter" + +#: option.c:2912 +msgid "missing parameter" +msgstr "mangler parameter" + +#: option.c:2916 +msgid "error" +msgstr "feil" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "%s på linje %d av %%s" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "kan ikke lese %s: %s" + +#: option.c:3151 option.c:3187 +#, fuzzy, c-format +msgid "read %s" +msgstr "leser %s" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "Dnsmasq versjon %s %s\n" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" +"Kompileringsopsjoner %s\n" +"\n" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "Denne programvaren kommer med ABSOLUTT INGEN GARANTI.\n" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "DNsmasq er fri programvare, du er velkommen til å redistribuere den\n" + +#: option.c:3273 +#, fuzzy, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "under vilkårene gitt i GNU General Public License, versjon 2.\n" + +#: option.c:3284 +msgid "try --help" +msgstr "" + +#: option.c:3286 +msgid "try -w" +msgstr "" + +#: option.c:3289 +#, fuzzy, c-format +msgid "bad command line options: %s" +msgstr "dårlige kommandlinje opsjoner: %s." + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "klarer ikke å få vertsnavn: %s" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "kun en resolv.conf fil tillat i no-poll modus." + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "må ha nøyaktig en resolv.conf å lese domene fra." + +#: option.c:3371 network.c:848 dhcp.c:814 +#, fuzzy, c-format +msgid "failed to read %s: %s" +msgstr "feilet å lese %s: %s" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "intet søke direktiv funnet i %s" + +#: option.c:3409 +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "navnetjener %s nektet å gjøre et rekursivt oppslag" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "" + +#: network.c:171 +#, fuzzy, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "ukjent tilknytning (interface) %s" + +#: network.c:380 +#, fuzzy, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "feilet å lage lytte socket: %s" + +#: network.c:746 +#, fuzzy, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "feilet å binde lytte socket for %s: %s" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "ignorerer navnetjener %s - lokal tilknytning" + +#: network.c:794 +#, fuzzy, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "ignorerer navnetjener %s - kan ikke lage/dinde socket: %s" + +#: network.c:811 +msgid "unqualified" +msgstr "ikke kvalifisert" + +#: network.c:811 +msgid "names" +msgstr "" + +#: network.c:813 +msgid "default" +msgstr "" + +#: network.c:815 +msgid "domain" +msgstr "domene" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "benytter lokale adresser kun for %s %s" + +#: network.c:820 +#, fuzzy, c-format +msgid "using standard nameservers for %s %s" +msgstr "benytter navnetjener %s#%d for %s %s" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "benytter navnetjener %s#%d for %s %s" + +#: network.c:825 +#, fuzzy, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "benytter navnetjener %s#%d" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "benytter navnetjener %s#%d" + +#: dnsmasq.c:148 +#, fuzzy +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "" + +#: dnsmasq.c:158 +msgid "asychronous logging is not available under Android" +msgstr "" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "feilet å finne liste av tilknytninger (interfaces): %s" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "ukjent tilknytning (interface) %s" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "ingen tilknytning (interface) med adresse %s" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "DBus feil: %s" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "DBus ikke tilgjengelig: sett HAVE_DBUS i src/config.h" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "" + +#: dnsmasq.c:455 +#, fuzzy, c-format +msgid "started, version %s DNS disabled" +msgstr "startet, versjon %s mellomlager deaktivert" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "startet, versjon %s mellomlager størrelse %d" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "startet, versjon %s mellomlager deaktivert" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "kompilerings opsjoner: %s" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "DBus støtte aktivert: koblet til system buss" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "DBus støtte aktivert: avventer buss tilkobling" + +#: dnsmasq.c:474 +#, fuzzy, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "feilet å laste navn fra %s: %s" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "setter --bind-interfaces opsjon på grunn av OS begrensninger" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "advarsel: nettverkskort %s eksisterer ikke for tiden" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "" + +#: dnsmasq.c:491 +#, fuzzy +msgid "warning: no upstream servers configured" +msgstr "setter oppstrøms tjener fra DBus" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "DHCP, statisk leie kun på %.0s%s, leie tid %s" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "DHCP, IP område %s -- %s, leie tid %s" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "" + +#: dnsmasq.c:526 +#, fuzzy +msgid "enabled" +msgstr "deaktivert" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "tilkoblet til system DBus" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "" + +#: dnsmasq.c:778 +#, fuzzy, c-format +msgid "failed to create helper: %s" +msgstr "feilet å lese %s: %s" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "" + +#: dnsmasq.c:785 +#, fuzzy, c-format +msgid "failed to change user-id to %s: %s" +msgstr "feilet å laste navn fra %s: %s" + +#: dnsmasq.c:790 +#, fuzzy, c-format +msgid "failed to change group-id to %s: %s" +msgstr "feilet å laste navn fra %s: %s" + +#: dnsmasq.c:793 +#, fuzzy, c-format +msgid "failed to open pidfile %s: %s" +msgstr "feilet å lese %s: %s" + +#: dnsmasq.c:796 +#, fuzzy, c-format +msgid "cannot open %s: %s" +msgstr "kan ikke åpne %s:%s" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "" + +#: dnsmasq.c:859 +#, fuzzy, c-format +msgid "failed to execute %s: %s" +msgstr "feilet å få tilgang til %s: %s" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "avslutter etter mottak av SIGTERM" + +#: dnsmasq.c:931 +#, fuzzy, c-format +msgid "failed to access %s: %s" +msgstr "feilet å få tilgang til %s: %s" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "leser %s" + +#: dnsmasq.c:972 +#, fuzzy, c-format +msgid "no servers found in %s, will retry" +msgstr "intet søke direktiv funnet i %s" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "kan ikke lage DHCP socket: %s" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "feilet å sette opsjoner på DHCP socket: %s" + +#: dhcp.c:65 +#, fuzzy, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "feilet å sette SO_REUSEADDR på DHCP socket: %s" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "feilet å binde DHCP tjener socket: %s" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "kan ikke lage ICMP raw socket: %s" + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "DHCP område %s -- %s er ikke konsistent med nettmaske %s" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "dårlig linje ved %s linje %d" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "dubliserte IP adresser i %s dhcp-config direktiv." + +#: dhcp.c:981 +#, fuzzy, c-format +msgid "duplicate IP address %s in %s." +msgstr "dubliserte IP adresser i %s dhcp-config direktiv." + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "dubliserte IP adresser i %s (%s) i dhcp-config direktiv" + +#: lease.c:67 +#, fuzzy, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "kan ikke åpne eller lage leie fil: %s" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "for mange lagrede leier" + +#: lease.c:129 +#, fuzzy, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "kan ikke lese %s: %s" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "" + +#: lease.c:235 +#, fuzzy, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "feilet å lese %s: %s" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "ingen adresse område tilgjengelig for DHCP krav %s %s" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "med subnet velger" + +#: rfc2131.c:316 +msgid "via" +msgstr "via" + +#: rfc2131.c:331 +#, fuzzy, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "ingen adresse område tilgjengelig for DHCP krav %s %s" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "deaktivert" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "oversett" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "adresse i bruk" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "ingen adresse tilgjengelig" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "galt nettverk" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "ingen adresse konfigurert" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "ingen leier igjen" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "" + +#: rfc2131.c:700 +#, fuzzy, c-format +msgid "%u vendor class: %s" +msgstr "DBus feil: %s" + +#: rfc2131.c:702 +#, fuzzy, c-format +msgid "%u user class: %s" +msgstr "DBus feil: %s" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "" + +#: rfc2131.c:886 +#, fuzzy, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "deaktiverer DHCP statisk adresse %s" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "ukjent leie" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "gal adresse" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "leie ikke funnet" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "adresse ikke tilgjengelig" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "statisk leie tilgjengelig" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "adresse reservert" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "" + +#: rfc2131.c:1732 +#, fuzzy, c-format +msgid "%u server name: %s" +msgstr "DBus feil: %s" + +#: rfc2131.c:1746 +#, fuzzy, c-format +msgid "%u next server: %s" +msgstr "DBus feil: %s" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "" + +#: rfc2131.c:1812 +#, fuzzy, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "kan ikke sende DHCP opsjon %d: ikke mer plass i pakken" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "" + +#: rfc2131.c:2189 +#, fuzzy, c-format +msgid "%u requested options: %s" +msgstr "kompilerings opsjoner: %s" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "" + +#: netlink.c:70 +#, fuzzy, c-format +msgid "cannot create netlink socket: %s" +msgstr "kan ikke binde netlink socket: %s" + +#: netlink.c:288 +#, fuzzy, c-format +msgid "netlink returns error: %s" +msgstr "DBus feil: %s" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "forsøk på å sette en IPv6 tjener adresse via DBus - ingen IPv6 støtte" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "setter oppstrøms tjener fra DBus" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "kunne ikke registrere en DBus meldingshåndterer" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "kan ikke lage DHCP BPF socket: %s" + +#: bpf.c:245 +#, fuzzy, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "DHCP krav for ikke støttet maskinvare type (%d) mottatt på %s" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "" + +#: tftp.c:406 +#, fuzzy, c-format +msgid "file %s not found" +msgstr "leie ikke funnet" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "" + +#: tftp.c:554 +#, fuzzy, c-format +msgid "failed sending %s to %s" +msgstr "feilet å lese %s: %s" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "FEILET å starte opp" + +#~ msgid "TXT record string too long" +#~ msgstr "TXT post streng for lang" + +#~ msgid "failed to set IPV6 options on listening socket: %s" +#~ msgstr "feilet å sette IPv6 opsjoner på lytte socket: %s" + +#~ msgid "failed to bind listening socket for %s: %s" +#~ msgstr "feilet å binde lytte socket for %s: %s" + +#~ msgid "failed to listen on socket: %s" +#~ msgstr "feilet å lytte på socket: %s" + +#, fuzzy +#~ msgid "failed to create TFTP socket: %s" +#~ msgstr "feilet å lage lytte socket: %s" + +#~ msgid "must set exactly one interface on broken systems without IP_RECVIF" +#~ msgstr "må sette nøyaktig et interface på ødelagte systemer uten IP_RECVIF" + +#, fuzzy +#~ msgid "failed to load %s: %s" +#~ msgstr "feilet å laste %s: %s" + +#~ msgid "bad name in %s" +#~ msgstr "dårlig navn i %s" + +#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part" +#~ msgstr "Ignorerer DHCP leie for %s siden den har en ulovlig domene del" + +#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h" +#~ msgstr "ISC dhcpf integrasjon ikke tilgjengelig: sett HAVE_ISC_READER i src/config.h" + +#, fuzzy +#~ msgid "illegal domain %s in dhcp-config directive." +#~ msgstr "dubliserte IP adresser i %s dhcp-config direktiv." + +#~ msgid "running as root" +#~ msgstr "kjører som rot (root)" + +#, fuzzy +#~ msgid "read %s - %d hosts" +#~ msgstr "les %s - %d adresser" + +#~ msgid "domains" +#~ msgstr "domener" + +#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part" +#~ msgstr "Ignorerer DHCP verts navn %s på grunn av ulovlig domene del" + +#~ msgid "Display this message." +#~ msgstr "Vis denne meldingen." + +#~ msgid "failed to read %s: %m" +#~ msgstr "feilet å lese %s: %m" + +#~ msgid "failed to read %s:%m" +#~ msgstr "feilet å lese %s:%m" + +#, fuzzy +#~ msgid "cannot send encapsulated option %d: no space left in wrapper" +#~ msgstr "kan ikke sende DHCP opsjon %d: ikke mer plass i pakken" + +#~ msgid "More than one vendor class matches, using %s" +#~ msgstr "Mer enn en produsent klasse som passer, bruker %s" + +#~ msgid "forwarding table overflow: check for server loops." +#~ msgstr "fremsendelse (forwarding) tabell overflyt: sjekk etter tjener løkker." + +#~ msgid "nested includes not allowed" +#~ msgstr "nøstede inkluderinger er ikke tillatt" + +#~ msgid "DHCP, %s will be written every %s" +#~ msgstr "DHCP, %s vil bli skrevet hver %s" + +#~ msgid "cannot create DHCP packet socket: %s. Is CONFIG_PACKET enabled in your kernel?" +#~ msgstr "kan ikke lage DHCP pakke socket: %s. Er CONFIG_PACKET aktivert i din kjerne?" + +#~ msgid "Cannot use RTnetlink socket, falling back to ioctl API" +#~ msgstr "Kan ikke benytte RTnetlink socket, faller tilbake til ioctl API" diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 0000000..945df01 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,1490 @@ +# translation of pl.po to polski +# Polish translations for dnsmasq package. +# This file is put in the public domain. +# +# Tomasz Sochañski <nerdhero@gmail.com>, 2005. +# Jan Psota <jasiu@belsznica.pl>, 2008, 2009, 2010. +# Jan Psota <jasiupsota@gmail.com>, 2010, 2011. +msgid "" +msgstr "" +"Project-Id-Version: pl\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-10 20:57+0100\n" +"PO-Revision-Date: 2011-01-16 23:56+0100\n" +"Last-Translator: Jan Psota <jasiupsota@gmail.com>\n" +"Language-Team: Polish <>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Lokalize 1.1\n" +"X-Language: pl_PL\n" + +#: cache.c:761 +#, c-format +msgid "failed to load names from %s: %s" +msgstr "nie potrafiê wczytaæ nazw z %s: %s" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "b³êdny adres w pliku %s, w linii %d" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "b³êdna nazwa w pliku %s, w linii %d" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "wczyta³em %s - %d adresów" + +#: cache.c:899 +msgid "cleared cache" +msgstr "wyczyszczono pamiêæ podrêczn±" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "%s to nazwa CNAME, nie przypisujê jej dzier¿awie DHCP %s" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "nazwa %s nie zosta³a nadana dzier¿awie DHCP %s,poniewa¿ nazwa istnieje w %s i ma ju¿ adres %s" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "czas %lu" + +#: cache.c:1040 +#, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "wielko¶æ pamiêci podrêcznej: %d; %d z %d miejsc aktualnych wpisów u¿yto ponownie." + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "%u zapytañ przes³anych dalej, %u odpowiedzi udzielonych samodzielnie" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "serwer %s#%d: %u zapytañ wys³anych, %u ponowionych lub nieudanych" + +#: util.c:57 +#, c-format +msgid "failed to seed the random number generator: %s" +msgstr "brak mo¿liwo¶ci u¿ycia generatora liczb losowych: %s" + +#: util.c:189 +msgid "failed to allocate memory" +msgstr "nie uda³o siê przydzieliæ pamiêci" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "nie mo¿na dostaæ pamiêci" + +#: util.c:237 +#, c-format +msgid "cannot create pipe: %s" +msgstr "b³±d podczas próby utworzenia potoku: %s" + +#: util.c:245 +#, c-format +msgid "failed to allocate %d bytes" +msgstr "niemo¿liwo¶æ przydzielenia %d bajtów pamiêci" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "nieskoñczona" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "Wskazanie adresów, na których nale¿y nas³uchiwaæ." + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "Zwracanie adresu IP dla wszystkich hostów we wskazanych domenach." + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "Wy³±czenie przekazywania zapytañ odwrotnych dla prywatnych zakresów IP." + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "Traktowanie adresu IP jako NXDOMAIN (uniewa¿nia ,,Verisign wildcard'')." + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "Wskazanie wielko¶ci pamiêci podrêcznej (domy¶lnie: %s miejsc)." + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "Wskazanie pliku konfiguracyjnego (domy¶lnie: %s)." + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "NIE twórz procesu potomnego w tle: dzia³anie w trybie debugowania." + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "Wy³±czenie przekazywania zapytañ bez podanej czê¶ci domenowej." + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "Zwracanie samowskazuj±cego rekordu MX dla lokalnych hostów." + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "Rozwijanie prostych nazw z /etc/hosts przyrostkiem domenowym." + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "Wy³±czenie przekazywania pozornych zapytañ DNS z komputerów dzia³aj±cych pod Windows." + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "W³±czenie serwera DHCP dla wskazanego zakresu adresów." + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "Po uruchomieniu zmiana grupy procesu na podan± (domy¶lnie: %s)." + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "Ustawienie adresu lub nazwy dla wskazanego komputera." + +#: option.c:258 +msgid "Read DHCP host specs from file." +msgstr "Wskazanie pliku z warto¶ciami 'dhcp-host='." + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "Wskazanie pliku z warto¶ciami 'dhcp-option='." + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "Warunkowe ustawianie znaczników." + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "NIE wczytywanie pliku %s." + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "Wskazanie dodatkowego pliku 'hosts' oprócz %s." + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "Interfejsy, na których nas³uchiwaæ." + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "Interfejsy, na których NIE nas³uchiwaæ." + +#: option.c:265 +msgid "Map DHCP user class to tag." +msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od klasy u¿ytkownika DHCP." + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru obwodu (w rozumieniu RFC3046)." + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru agenta (w rozumieniu RFC3046)." + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od numeru subskrybenta (w rozumieniu RFC3993)." + +#: option.c:269 +msgid "Don't do DHCP for hosts with tag set." +msgstr "Wy³±czenie DHCP dla hostów z okre¶lonym znacznikiem." + +#: option.c:270 +msgid "Force broadcast replies for hosts with tag set." +msgstr "Wymuszenie odpowiedzi w trybie rozg³oszeniowym dla hostów z okre¶lonym znacznikiem." + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "NIE twórz procesu potomnego w tle i NIE w³±czaj trybu debugowania." + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "Zak³adanie, ¿e jeste¶my jedynym serwerem DHCP w sieci lokalnej." + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "¦cie¿ka przechowywania pliku dzier¿aw DHCP (domy¶lnie: %s)." + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "W³±czenie zwracania rekordu MX dla hostów lokalnych." + +#: option.c:275 +msgid "Specify an MX record." +msgstr "Specyfikacja rekordu MX." + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "Okre¶lenie opcji BOOTP serwera DHCP." + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "Wy³±czenie obserwowania pliku %s; ponowne odczytywanie tylko po odebraniu sygna³u SIGHUP." + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "Wy³±czenie przechowywania w pamiêci podrêcznej wyników nieudanych wyszukiwañ." + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "Odpytywanie serwerów nazw w kolejno¶ci ich wyst±pienia w %s." + +#: option.c:280 +msgid "Specify options to be sent to DHCP clients." +msgstr "Specyfikacja opcji wysy³anej do klientów DHCP." + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "Opcja DHCP wysy³ana nawet je¿eli klient o ni± nie prosi." + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "Wskazanie portu do nas³uchiwania zapytañ DNS (domy¶lnie: 53)." + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "Maksymalna obs³ugiwana wielko¶æ pakietu EDNS.0 (domy¶lnie: %s)." + +#: option.c:284 +msgid "Log DNS queries." +msgstr "W³±czenie spisywania zapytañ DNS do logu." + +#: option.c:285 +msgid "Force the originating port for upstream DNS queries." +msgstr "Wymuszenie u¿ycia wskazanego portu UDP do odpytywania nadrzêdnych serwerów DNS i odbierania od nich odpowiedzi." + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "Wy³±czenie czytania pliku resolv.conf." + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "Wskazanie po³o¿enia pliku resolv.conf (domy¶lnie: %s)." + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "Wskazywanie adresów serwerów nazw, opcjonalnie z przypisaniem do domeny." + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "Wy³±czenie przekazywania zapytañ do wskazanych domen." + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "Wskazanie domeny dla serwera DHCP." + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "Okre¶lenie domy¶lnego celu w rekordzie MX." + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "Okre¶lenie (w sekundach) czasu wa¿no¶ci odpowiedzi udzielonych na podstawie /etc/hosts (domy¶lnie 0)." + +#: option.c:293 +msgid "Specify time-to-live in seconds for negative caching." +msgstr "Okre¶lenie (w sekundach) czasu wa¿no¶ci negatywnych odpowiedzi." + +#: option.c:294 +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "Ograniczenie maksymalnego czasu wa¿no¶ci odpowiedzi (TTL) podawanego klientom [w sekundach]." + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "Zmiana u¿ytkownika procesu na wskazanego (po uruchomieniu, domy¶lnie: %s)." + +#: option.c:296 +msgid "Map DHCP vendor class to tag." +msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od typu klienta DHCP." + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "Wydrukowanie informacji o programie i ochronie praw autorskich." + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "T³umaczenie adresów IPv4 z serwerów nadrzêdnych." + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "Okre¶lenie rekordu SRV." + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "Wy¶wietla ten komunikat. U¿yj '--help dhcp' chc±c przejrzeæ listê opcji DHCP (dhcp-option=xxx,...)." + +#: option.c:301 +#, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "Okre¶lenie ¶cie¿ki do pliku PID (domy¶lnie: %s)." + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "Maksymalna liczba dzier¿aw DHCP (domy¶lnie: %s)." + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "Uzale¿nienie odpowiedzi DNS od interfejsu, na którym odebrano zapytanie (wygodne dla serwerów kilku podsieci z ró¿nymi adresami w /etc/hosts)." + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "Specyfikacja rekordu DNS TXT." + +#: option.c:305 +msgid "Specify PTR DNS record." +msgstr "Specyfikacja rekordu DNS PTR." + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "Zwraca nazwê domenow± powi±zan± z adresem interfejsu sieciowego." + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "Nas³uchiwanie tylko na wykorzystywanych interfejsach (umo¿liwia uruchomienie osobnych serwerów dla ró¿nych kart)." + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "Wczytanie przyporz±dkowañ adresów z %s." + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "W³±czenie u¿ywania interfejsu DBus do informowania o zmianach konfiguracji." + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "Uruchomienie na wskazanym interfejsie tylko DNS-a, bez us³ug DHCP i TFTP." + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "W³±czenie dynamicznego przydzielania adresów dla klientów BOOTP." + +#: option.c:312 +msgid "Map MAC address (with wildcards) to option set." +msgstr "Przyporz±dkowanie znacznika w zale¿no¶ci od adresu MAC (mo¿na u¿ywaæ uogólnieñ: *)." + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "Traktowanie ¿±dañ DHCP odebranych na interfejsach alias, ..., jako odebranych na iface." + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "Pominiêcie sprawdzania za pomoc± ICMP niezajêto¶ci adresu przed jego wydzier¿awieniem." + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "Wskazanie skryptu uruchamianego w przypadku wydzier¿awienia adresu lub wyga¶niêcia dzier¿awy." + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "Wczytanie wszystkich plików ze wskazanego katalogu jako konfiguracyjnych." + +#: option.c:317 +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "Wskazanie kana³u syslog-a do którego maj± trafiaæ komunikaty (domy¶lnie: DAEMON)" + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "Nieu¿ywanie bazy dzier¿aw." + +#: option.c:319 +#, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "Maksymalna liczba jednocze¶nie obs³ugiwanych zapytañ DNS (domy¶lnie: %s)" + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "Czyszczenie pamiêci podrêcznej serwera nazw w przypadku ponownego odczytu %s." + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "Nie zwracanie uwagi na nazwê podawan± przez klienta w przypadku dopasowania wszystkich wymienionych znaczników." + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "Wy³±czenie oszczêdzania miejsca w pakiecie DHCP przez przesuwanie pól servername i filename do opcji DHCP. Wymusza prostszy tryb budowy pakietu rozwi±zuj±c problemy z nieprzystosowanymi klientami DHCP." + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "W³±czenie wbudowanego serwera TFTP (tylko do wysy³ania)." + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "Ograniczenie dzia³ania serwera TFTP do wskazanego katalogu i podkatalogów. Nazwy z .. s± odrzucane, / odnosi siê do wskazanego katalogu." + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "Doklejanie adresu IP klienta do g³ównego katalogu TFTP. Je¿eli wynikowy katalog nie istnieje, nadal wykorzystuje siê tftp-root." + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "Ograniczenie dostêpu do plików przez TFTP do tych, których w³a¶cicielem jest u¿ytkownik uruchamiaj±cy dnsmasq-a." + +#: option.c:327 +#, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "Maksymalna liczba jednocze¶nie obs³ugiwanych po³±czeñ TFTP (domy¶lnie %s)." + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "Wy³±czenie mo¿liwo¶ci negocjowania wielko¶ci bloku dla przesy³ów przez TFTP." + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "Wskazanie zakresu portów do u¿ytku TFTP." + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "W³±czenie spisywania w logu operacji DHCP." + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "W³±czenie asynchronicznego zapisywania do logu z ewentualnym wskazaniem d³ugo¶ci kolejki." + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "Odfiltrowywanie adresów wskazuj±cych na komputery w sieciach wewnêtrznych spo¶ród odpowiedzi od zewnêtrznych serwerów DNS." + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "Zezwolenie na przekazywanie odpowiedzi w klasie 127.0.0.0/8. Dla serwerów RBL." + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "Dezaktywacja zabezpieczenia przed atakami DNS-rebind dla wskazanych domen." + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "Jednoczesne odpytywanie wszystkich serwerów nadrzêdnych; klientowi przekazywana jest pierwsza odpowied¼." + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "Ustawienie znacznika je¿eli w ¿±daniu DHCP pojawi siê wskazana opcja, ewentualnie o konkretnej warto¶ci." + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "U¿ycie alternatywnych portów dla us³ugi DHCP." + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "Uruchamianie skryptu dhcp-script jako wskazany u¿ytkownik." + +#: option.c:339 +msgid "Specify NAPTR DNS record." +msgstr "Specyfikacja rekordu DNS NAPTR." + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "Ustawienie dolnej granicy numerów portów do przesy³ania zapytañ DNS." + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "Przechowywanie w serwerze DNS dnsmasq-a tylko w pe³ni kwalifikowanych nazw zg³aszanych przez klientów DHCP." + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "Generowanie nazw na podstawie MAC-adresów dla klientów bez nazwy." + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "Traktowanie wskazanych serwerów po¶rednicz±cych DHCP jako dzia³aj±cych w trybie \"pe³nomocnika\" (full-proxy)." + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "Wskazanie synonimu nazwy komputera lokalnego - znanego z /etc/hosts albo z DHCP." + +#: option.c:345 +msgid "Prompt to send to PXE clients." +msgstr "Zg³oszenie wysy³ane klientom PXE." + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "Sk³adnik menu PXE (--> man)." + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "Sprawdzenie sk³adni." + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "Za³±czanie MAC-adresu komputera pytaj±cego w przekazywanych dalej zapytaniach DNS." + +#: option.c:349 +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "Przekazywanie wyników weryfikacji DNSSEC z serwerów nadrzêdnych." + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" +"U¿ycie: dnsmasq [opcje]\n" +"\n" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "W tym systemie w linii poleceñ mo¿na u¿ywaæ wy³±cznie jednoliterowych opcji.\n" + +#: option.c:642 +#, c-format +msgid "Valid options are:\n" +msgstr "Dostêpne opcje:\n" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "Znane opcje DHCP:\n" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "b³±d w dhcp-option" + +#: option.c:860 +msgid "bad IP address" +msgstr "z³y adres IP" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "nieprawid³owa nazwa domeny w dhcp-option" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "zbyt d³uga dhcp-option (>255 znaków)" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "niedopuszczalne dhcp-match" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "wielokrotne u¿ycie opcji niedozwolone (pojawi³a siê wcze¶niej w linii poleceñ)" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "wielokrotne u¿ycie opcji niedozwolone (pojawi³a siê wsze¶niej w pliku konfiguracyjnym)" + +#: option.c:1147 option.c:3030 +#, c-format +msgid "cannot access directory %s: %s" +msgstr "brak dostêpu do katalogu %s: %s" + +#: option.c:1178 tftp.c:460 +#, c-format +msgid "cannot access %s: %s" +msgstr "brak dostêpu do %s: %s" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "nieprawid³owa warto¶æ preferencji MX" + +#: option.c:1270 +msgid "bad MX name" +msgstr "nieprawid³owa nazwa MX" + +#: option.c:1284 +msgid "bad MX target" +msgstr "nieprawid³owa warto¶æ celu MX" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "w uClinuksie nie ma mo¿liwo¶ci uruchamiania skryptów" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "¿eby mieæ mo¿liwo¶æ u¿ywania skryptów wywo³ywanych przy zmianie dzier¿awy, przekompiluj dnsmasq-a z w³±czon± flag± HAVE_SCRIPT" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "nieprawid³owy numer portu" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "nie ma mo¿liwo¶ci dowi±zywania do interfejsu" + +#: option.c:1791 +msgid "bad port range" +msgstr "nieprawid³owy zakres numerów portów" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "nieprawid³owa nazwa urz±dzenia w bridge-interface" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "nieprawid³owy zakres dhcp-range" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "mo¿na wskazaæ tylko jeden znacznik sieci" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "niespójny zakres adresów DHCP" + +#: option.c:2019 option.c:2045 +msgid "bad hex constant" +msgstr "zapis niezgodny z formatem szesnastkowym" + +#: option.c:2107 +msgid "bad DHCP host name" +msgstr "niedopuszczalna nazwa komputera w dhcp-host" + +#: option.c:2188 +msgid "bad tag-if" +msgstr "nieprawid³owa sk³adnia 'tag-if'" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "nieprawid³owy numer portu" + +#: option.c:2529 +msgid "bad dhcp-proxy address" +msgstr "z³y adres dhcp-proxy" + +#: option.c:2569 +msgid "invalid alias range" +msgstr "nieprawid³owy zakres adresów w --alias" + +#: option.c:2582 +msgid "bad interface name" +msgstr "nieprawid³owa nazwa interfejsu" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "z³a CNAME" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "powtórzona CNAME" + +#: option.c:2632 +msgid "bad PTR record" +msgstr "nieprawid³owy zapis rekordu PTR" + +#: option.c:2663 +msgid "bad NAPTR record" +msgstr "nieprawid³owy zapis rekordu NAPTR" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "nieprawid³owy zapis rekordu TXT" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "nieprawid³owy zapis rekordu SRV" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "nieprawid³owa warto¶æ celu SRV" + +#: option.c:2759 +msgid "invalid priority" +msgstr "nieprawid³owy priorytet" + +#: option.c:2766 +msgid "invalid weight" +msgstr "nieprawid³owa waga" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "nieobs³ugiwana opcja (sprawd¼, czy obs³uga DHCP/TFTP/DBus zosta³a wkompilowana)" + +#: option.c:2849 +msgid "missing \"" +msgstr "brakuje \"" + +#: option.c:2908 +msgid "bad option" +msgstr "nieprawid³owa opcja" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "nadwy¿kowy parametr" + +#: option.c:2912 +msgid "missing parameter" +msgstr "brak parametru" + +#: option.c:2916 +msgid "error" +msgstr "b³±d" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "%s w linii %d pliku %%s" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "b³±d odczytu z pliku %s: %s" + +#: option.c:3151 option.c:3187 +#, c-format +msgid "read %s" +msgstr "przeczyta³em %s" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "jakie¶ ¶mieci w linii poleceñ" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "Dnsmasq, wersja %s %s\n" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" +"Wkompilowane opcje %s\n" +"\n" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "Autor nie daje ¯ADNYCH GWARANCJI egzekwowalnych prawnie.\n" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "Dnsmasq jest wolnym oprogramowaniem, mo¿esz go rozprowadzaæ\n" + +#: option.c:3273 +#, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "na warunkach okre¶lonych w GNU General Public Licence, w wersji 2 lub 3.\n" + +#: option.c:3284 +msgid "try --help" +msgstr "spróbuj: --help" + +#: option.c:3286 +msgid "try -w" +msgstr "spróbuj: -w" + +#: option.c:3289 +#, c-format +msgid "bad command line options: %s" +msgstr "nieprawid³owa opcja w linii poleceñ %s" + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "nie mo¿na pobraæ nazwy hosta: %s" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "w trybie no-poll mo¿na wskazaæ najwy¿ej jeden plik resolv.conf." + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "musisz mieæ dok³adnie jeden plik resolv.conf do odczytu domen." + +#: option.c:3371 network.c:848 dhcp.c:814 +#, c-format +msgid "failed to read %s: %s" +msgstr "nie uda³o siê odczytaæ %s: %s" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "brak wytycznych wyszukiwania w %s" + +#: option.c:3409 +#, fuzzy +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "w przypadku u¿ywania --dhcp-fqdn trzeba wskazaæ domy¶ln± domenê" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "sk³adnia sprawdzona, jest prawid³owa" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "serwer nazw %s odmawia wykonania zapytania rekurencyjnego" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "prawdopodobnie wykryto atak DNS-rebind: %s" + +#: network.c:171 +#, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "nieznany interfejs %s w bridge-u" + +#: network.c:380 +#, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "nie uda³o siê otworzyæ gniazda %s: %s" + +#: network.c:746 +#, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "b³±d przy przyznawaniu nazwy gniazdu serwera %s: %s" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "ignorowanie serwera nazw %s - interfejs lokalny" + +#: network.c:794 +#, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "ignorowanie serwera nazw %s - nie mo¿na utworzyæ/dowi±zaæ gniazda: %s" + +#: network.c:811 +msgid "unqualified" +msgstr "niekwalifikowane(-a)" + +#: network.c:811 +msgid "names" +msgstr "nazwy" + +#: network.c:813 +msgid "default" +msgstr "domy¶lne" + +#: network.c:815 +msgid "domain" +msgstr "domeny" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "u¿ywam adresów lokalnych tylko dla %s %s" + +#: network.c:820 +#, c-format +msgid "using standard nameservers for %s %s" +msgstr "u¿ywam standardowych serwerów nazw dla %s %s" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "u¿ywam serwera nazw %s#%d dla %s %s" + +#: network.c:825 +#, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "u¿ywam serwera nazw %s#%d (przez %s)" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "u¿ywam serwera nazw %s#%d" + +#: dnsmasq.c:148 +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "Serwer TFTP nie zosta³ wkompilowany -- ustaw HAVE_TFTP w src/config.h" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "zapis do logów w trybie asynchronicznym nie jest dostêpny w Solarisie" + +#: dnsmasq.c:158 +#, fuzzy +msgid "asychronous logging is not available under Android" +msgstr "zapis do logów w trybie asynchronicznym nie jest dostêpny w Solarisie" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "b³±d podczas tworzenia listy interfejsów sieciowych: %s" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "nieznany interfejs %s" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "brak interfejsu z adresem %s" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "b³±d DBus: %s" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "Obs³uga DBus nie zosta³a wkompilowana -- ustaw HAVE_DBUS w src/config.h" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "nieznany u¿ytkownik lub grupa: %s" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "nie potrafiê wej¶æ do g³ównego katalogu: %s" + +#: dnsmasq.c:455 +#, c-format +msgid "started, version %s DNS disabled" +msgstr "uruchomiony, wersja %s, DNS wy³±czony" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "uruchomiony, wersja %s, %d miejsc w pamiêci podrêcznej" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "uruchomiony, wersja %s, pamiêæ podrêczna wy³±czona" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "opcje kompilacji: %s" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "obs³uga DBus w³±czona, pod³±czono do serwera DBus" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "obs³uga DBus w³±czona, trwa pod³±czanie do serwera DBus" + +#: dnsmasq.c:474 +#, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "UWAGA! Nie uda³o siê zmieniæ u¿ytkownika pliku %s: %s" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "ustawiam --bind-interfaces z powodu ograniczeñ systemu operacyjnego" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "uwaga: interfejs %s nie jest w³±czony" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "uwaga: ignorujê opcjê resolv-file, poniewa¿ wybrano tryb no-resolv" + +#: dnsmasq.c:491 +msgid "warning: no upstream servers configured" +msgstr "uwaga: nie wskazano nadrzêdnych serwerów DNS" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "w³±czono asynchroniczny tryb zapisu do logów z kolejk± na %d komunikatów" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "DHCP: tylko statyczne dzier¿awy na %.0s%s, czas dzier¿awy %s" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "DHCP: po¶rednik na podsieci %.0s%s%.0s" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "DHCP: zakres IP %s -- %s, czas dzier¿awy %s" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "z g³ównym katalogiem w " + +#: dnsmasq.c:526 +msgid "enabled" +msgstr "w³±czony" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "w trybie bezpiecznym" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "ograniczam ilo¶æ jednoczesnych przes³añ TFTP do %d" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "pod³±czono do DBus-a" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "nie potrafiê prze³±czyæ siê do pracy w tle: %s" + +#: dnsmasq.c:778 +#, c-format +msgid "failed to create helper: %s" +msgstr "nie uda³o siê utworzyæ procesu pomocniczego: %s" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "nie powiod³o siê ustawianie ograniczeñ (capabilities): %s" + +#: dnsmasq.c:785 +#, c-format +msgid "failed to change user-id to %s: %s" +msgstr "nie uda³o siê zmieniæ u¿ytkownika procesu na %s: %s" + +#: dnsmasq.c:790 +#, c-format +msgid "failed to change group-id to %s: %s" +msgstr "nie uda³o siê zmieniæ grupy procesu na %s: %s" + +#: dnsmasq.c:793 +#, c-format +msgid "failed to open pidfile %s: %s" +msgstr "nie uda³o siê otworzyæ pliku z PID-em %s: %s" + +#: dnsmasq.c:796 +#, c-format +msgid "cannot open %s: %s" +msgstr "nie mo¿na otworzyæ %s: %s" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "proces potomny zabity sygna³em %d" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "proces potomny zakoñczy³ siê z kodem powrotu %d" + +#: dnsmasq.c:859 +#, c-format +msgid "failed to execute %s: %s" +msgstr "nie uda³o siê uruchomiæ %s: %s" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "zakoñczy³em dzia³anie z powodu odebrania SIGTERM" + +#: dnsmasq.c:931 +#, c-format +msgid "failed to access %s: %s" +msgstr "brak dostêpu do %s: %s" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "czytanie %s" + +#: dnsmasq.c:972 +#, c-format +msgid "no servers found in %s, will retry" +msgstr "w %s nie znalaz³em serwerów, spróbujê ponownie pó¼niej" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "nie uda³o siê utworzyæ gniazda dla DHCP: %s" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "b³±d podczas ustawiania opcji gniazda DHCP: %s" + +#: dhcp.c:65 +#, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "nie uda³o siê ustawiæ SO_REUSE{ADDR|PORT} gniazda DHCP: %s" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "b³±d przy przyznawaniu nazwy gniazdu serwera DHCP: %s" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "nie uda³o siê utworzyæ surowego gniazda ICMP: %s." + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "¿±danie DHCP odebrano na interfejsie %s, który nie ma adresu" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "zakres adresów DHCP %s -- %s jest niespójny z mask± sieci %s" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "z³a zawarto¶æ pliku %s, w linii %d" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "w %s pomijam liniê %d -- powtórzona nazwa lub adres IP" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "powtórzony adres IP (%s) w parametrze dhcp-config" + +#: dhcp.c:981 +#, c-format +msgid "duplicate IP address %s in %s." +msgstr "powtórzony adres IP (%s) w pliku %s" + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "do komputera o nazwie %s pasuje wiêcej ni¿ jeden adres, w odpowiedzi DHCP wysy³am %s" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "powtórzenie adresu IP %s (%s) w opcji dhcp-config" + +#: lease.c:67 +#, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "nie potrafiê otworzyæ albo utworzyæ pliku dzier¿aw %s: %s" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "zbyt du¿a ilo¶æ zapisanych dzier¿aw" + +#: lease.c:129 +#, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "nie potrafiê uruchomiæ skryptu %s: %s" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "skrypt zakoñczy³ siê z kodem powrotu %s" + +#: lease.c:235 +#, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "b³±d zapisu do %s: %s (spróbujê ponownie za %us)" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "nie zdefiniowano zakresu adresów odpowiedniego dla ¿±dania %s %s" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "z wyborem podsieci" + +#: rfc2131.c:316 +msgid "via" +msgstr "przez" + +#: rfc2131.c:331 +#, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "%u dostêpna podsieæ DHCP: %s/%s" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "%u dostêpny zakres adresów DHCP: %s -- %s" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "wy³±czony(a)" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "ignorujê" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "adres jest w u¿yciu" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "brak dostêpnego adresu" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "nieprawid³owa sieæ" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "brak skonfigurowanego adresu" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "brak wolnych dzier¿aw" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "klient %u przedstawia siê jako %s" + +#: rfc2131.c:700 +#, c-format +msgid "%u vendor class: %s" +msgstr "%u klasa dostawcy: %s" + +#: rfc2131.c:702 +#, c-format +msgid "%u user class: %s" +msgstr "%u klasa u¿ytkownika: %s" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "PXE BIS nie jest obs³ugiwane" + +#: rfc2131.c:886 +#, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "wy³±czam statyczne przypisanie adresu %s dla %s" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "nieznana dzier¿awa" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "nie proponujê zak³adanego w konfiguracji adresu %s, bo jest on ju¿ wydzier¿awiony komputerowi %s" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "nie proponujê zak³adanego w konfiguracji adresu %s, bo u¿ywa go który¶ z serwerów" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "nie proponujê zak³adanego w konfiguracji adresu %s, bo ju¿ poprzednio zosta³ odrzucony" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "brak unikalnego id" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "nieprawid³owy identyfikator serwera (server-ID)" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "b³êdny adres" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "dzier¿awa nieznaleziona" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "adres niedostêpny" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "dostêpna statyczna dzier¿awa" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "adres zarezerwowany" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "porzucam przypisanie do %s nazwy %s" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "%u cechy: %s" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "%u nazwa pliku bootowania: %s" + +#: rfc2131.c:1732 +#, c-format +msgid "%u server name: %s" +msgstr "%u nazwa serwera: %s" + +#: rfc2131.c:1746 +#, c-format +msgid "%u next server: %s" +msgstr "%u nastêpny serwer: %s" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "%u odpowied¼ rozg³oszeniowa" + +#: rfc2131.c:1812 +#, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "nie mam mo¿liwo¶ci wys³ania opcji %d DHCP/BOOTP: niedostateczna ilo¶æ miejsca w pakiecie" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "menu PXE zbyt du¿e" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "Nie uwzglêdniam czê¶ci domenowej (%s) dla komputera %s" + +#: rfc2131.c:2189 +#, c-format +msgid "%u requested options: %s" +msgstr "%u za¿±dano: %s" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "nie mogê wys³aæ opcji RFC3925: za d³ugi ³añcuch opcji przy numerze %d" + +#: netlink.c:70 +#, c-format +msgid "cannot create netlink socket: %s" +msgstr "nie potrafiê utworzyæ po³±czenia netlink %s" + +#: netlink.c:288 +#, c-format +msgid "netlink returns error: %s" +msgstr "wyst±pi³ b³±d w po³±czeniu netlink %s" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "próba ustawienia adresu IPv6 serwera przez DBus, ale brak obs³ugi IPv6" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "ustawiam adresy serwerów nadrzêdnych na podstawie informacji odebranych z DBus" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "nie mo¿na zarejestrowaæ uchwytu DBus" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "nie potrafiê utworzyæ gniazda DHCP BPF: %s" + +#: bpf.c:245 +#, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "¿±danie DHCP od urz±dzenia nieobs³ugiwanego typu (%d) odebrano na %s" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "brak wolnego portu dla us³ugi TFTP" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "nieobs³ugiwane ¿±danie od komputera %s" + +#: tftp.c:406 +#, c-format +msgid "file %s not found" +msgstr "plik %s nie zosta³ znaleziony" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "b³±d %d %s odebrano od %s" + +#: tftp.c:554 +#, c-format +msgid "failed sending %s to %s" +msgstr "b³±d wysy³ania pliku %s do komputera %s" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "plik %s przes³ano do %s" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "przepe³nienie: stracono %d wpisów do logów" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "nie uda³o siê zapisaæ komunikatów do %s" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "B£¡D: nie uda³o siê uruchomiæ dnsmasq-a" + +#~ msgid "only one dhcp-hostsfile allowed" +#~ msgstr "mo¿na wskazaæ tylko jeden plik dhcp-hostsfile" + +#~ msgid "only one dhcp-optsfile allowed" +#~ msgstr "mo¿na wskazaæ tylko jeden plik dhcp-optsfile" + +#~ msgid "files nested too deep in %s" +#~ msgstr "zbyt du¿e zag³êbienie plików w %s" + +#~ msgid "TXT record string too long" +#~ msgstr "zbyt d³ugi rekord TXT" + +#~ msgid "failed to set IPV6 options on listening socket: %s" +#~ msgstr "b³±d ustawiania opcji IPV6 na nas³uchuj±cym gnie¼dzie: %s" + +#~ msgid "failed to bind listening socket for %s: %s" +#~ msgstr "b³±d przy przyznawaniu nazwy gniazdu %s: %s" + +#~ msgid "failed to listen on socket: %s" +#~ msgstr "b³±d przy w³±czaniu nas³uchu na gnie¼dzie: %s" + +#~ msgid "failed to create TFTP socket: %s" +#~ msgstr "nie powiod³o siê otwieranie gniazda dla us³ugi TFTP: %s" diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..5fe209e --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,1455 @@ +# Portuguese translations for dnsmasq package. +# This file is put in the public domain. +# Simon Kelley <simon@thekelleys.org.uk>, 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.26\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2006-01-16 20:42+0000\n" +"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n" +"Language-Team: Portuguese <ldp-br@bazar.conectiva.com.br>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ASCII\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: cache.c:761 +#, c-format +msgid "failed to load names from %s: %s" +msgstr "" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "" + +#: cache.c:899 +msgid "cleared cache" +msgstr "" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "" + +#: cache.c:1040 +#, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "" + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "" + +#: util.c:57 +#, c-format +msgid "failed to seed the random number generator: %s" +msgstr "" + +#: util.c:189 +msgid "failed to allocate memory" +msgstr "" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "" + +#: util.c:237 +#, c-format +msgid "cannot create pipe: %s" +msgstr "" + +#: util.c:245 +#, c-format +msgid "failed to allocate %d bytes" +msgstr "" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "" + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "" + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "" + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "" + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "" + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "" + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "" + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "" + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "" + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "" + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "" + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "" + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "" + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "" + +#: option.c:258 +msgid "Read DHCP host specs from file." +msgstr "" + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "" + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "" + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "" + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "" + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "" + +#: option.c:265 +msgid "Map DHCP user class to tag." +msgstr "" + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "" + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "" + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "" + +#: option.c:269 +msgid "Don't do DHCP for hosts with tag set." +msgstr "" + +#: option.c:270 +msgid "Force broadcast replies for hosts with tag set." +msgstr "" + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "" + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "" + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "" + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "" + +#: option.c:275 +msgid "Specify an MX record." +msgstr "" + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "" + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "" + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "" + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "" + +#: option.c:280 +msgid "Specify options to be sent to DHCP clients." +msgstr "" + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "" + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "" + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "" + +#: option.c:284 +msgid "Log DNS queries." +msgstr "" + +#: option.c:285 +msgid "Force the originating port for upstream DNS queries." +msgstr "" + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "" + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "" + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "" + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "" + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "" + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "" + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "" + +#: option.c:293 +msgid "Specify time-to-live in seconds for negative caching." +msgstr "" + +#: option.c:294 +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "" + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "" + +#: option.c:296 +msgid "Map DHCP vendor class to tag." +msgstr "" + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "" + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "" + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "" + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "" + +#: option.c:301 +#, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "" + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "" + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "" + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "" + +#: option.c:305 +msgid "Specify PTR DNS record." +msgstr "" + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "" + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "" + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "" + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "" + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "" + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "" + +#: option.c:312 +msgid "Map MAC address (with wildcards) to option set." +msgstr "" + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "" + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "" + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "" + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "" + +#: option.c:317 +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "" + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "" + +#: option.c:319 +#, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "" + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "" + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "" + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "" + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "" + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "" + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "" + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "" + +#: option.c:327 +#, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "" + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "" + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "" + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "" + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "" + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "" + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "" + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "" + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "" + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "" + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "" + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "" + +#: option.c:339 +msgid "Specify NAPTR DNS record." +msgstr "" + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "" + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "" + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "" + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "" + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "" + +#: option.c:345 +msgid "Prompt to send to PXE clients." +msgstr "" + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "" + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "" + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +#: option.c:349 +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "" + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "" + +#: option.c:642 +#, c-format +msgid "Valid options are:\n" +msgstr "" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "" + +#: option.c:860 +msgid "bad IP address" +msgstr "" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "" + +#: option.c:1147 option.c:3030 +#, c-format +msgid "cannot access directory %s: %s" +msgstr "" + +#: option.c:1178 tftp.c:460 +#, c-format +msgid "cannot access %s: %s" +msgstr "" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "" + +#: option.c:1270 +msgid "bad MX name" +msgstr "" + +#: option.c:1284 +msgid "bad MX target" +msgstr "" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "" + +#: option.c:1791 +msgid "bad port range" +msgstr "" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "" + +#: option.c:2019 option.c:2045 +msgid "bad hex constant" +msgstr "" + +#: option.c:2107 +msgid "bad DHCP host name" +msgstr "" + +#: option.c:2188 +msgid "bad tag-if" +msgstr "" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "" + +#: option.c:2529 +msgid "bad dhcp-proxy address" +msgstr "" + +#: option.c:2569 +msgid "invalid alias range" +msgstr "" + +#: option.c:2582 +msgid "bad interface name" +msgstr "" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "" + +#: option.c:2632 +msgid "bad PTR record" +msgstr "" + +#: option.c:2663 +msgid "bad NAPTR record" +msgstr "" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "" + +#: option.c:2759 +msgid "invalid priority" +msgstr "" + +#: option.c:2766 +msgid "invalid weight" +msgstr "" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "" + +#: option.c:2849 +msgid "missing \"" +msgstr "" + +#: option.c:2908 +msgid "bad option" +msgstr "" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "" + +#: option.c:2912 +msgid "missing parameter" +msgstr "" + +#: option.c:2916 +msgid "error" +msgstr "" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "" + +#: option.c:3151 option.c:3187 +#, c-format +msgid "read %s" +msgstr "" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "" + +#: option.c:3273 +#, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "" + +#: option.c:3284 +msgid "try --help" +msgstr "" + +#: option.c:3286 +msgid "try -w" +msgstr "" + +#: option.c:3289 +#, c-format +msgid "bad command line options: %s" +msgstr "" + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "" + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "" + +#: option.c:3371 network.c:848 dhcp.c:814 +#, c-format +msgid "failed to read %s: %s" +msgstr "" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "" + +#: option.c:3409 +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "" + +#: network.c:171 +#, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "" + +#: network.c:380 +#, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "" + +#: network.c:746 +#, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "" + +#: network.c:794 +#, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "" + +#: network.c:811 +msgid "unqualified" +msgstr "" + +#: network.c:811 +msgid "names" +msgstr "" + +#: network.c:813 +msgid "default" +msgstr "" + +#: network.c:815 +msgid "domain" +msgstr "" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "" + +#: network.c:820 +#, c-format +msgid "using standard nameservers for %s %s" +msgstr "" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "" + +#: network.c:825 +#, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "" + +#: dnsmasq.c:148 +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "" + +#: dnsmasq.c:158 +msgid "asychronous logging is not available under Android" +msgstr "" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "" + +#: dnsmasq.c:455 +#, c-format +msgid "started, version %s DNS disabled" +msgstr "" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "" + +#: dnsmasq.c:474 +#, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "" + +#: dnsmasq.c:491 +msgid "warning: no upstream servers configured" +msgstr "" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "" + +#: dnsmasq.c:526 +msgid "enabled" +msgstr "" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "" + +#: dnsmasq.c:778 +#, c-format +msgid "failed to create helper: %s" +msgstr "" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "" + +#: dnsmasq.c:785 +#, c-format +msgid "failed to change user-id to %s: %s" +msgstr "" + +#: dnsmasq.c:790 +#, c-format +msgid "failed to change group-id to %s: %s" +msgstr "" + +#: dnsmasq.c:793 +#, c-format +msgid "failed to open pidfile %s: %s" +msgstr "" + +#: dnsmasq.c:796 +#, c-format +msgid "cannot open %s: %s" +msgstr "" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "" + +#: dnsmasq.c:859 +#, c-format +msgid "failed to execute %s: %s" +msgstr "" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "" + +#: dnsmasq.c:931 +#, c-format +msgid "failed to access %s: %s" +msgstr "" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "" + +#: dnsmasq.c:972 +#, c-format +msgid "no servers found in %s, will retry" +msgstr "" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "" + +#: dhcp.c:65 +#, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "" + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "" + +#: dhcp.c:981 +#, c-format +msgid "duplicate IP address %s in %s." +msgstr "" + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "" + +#: lease.c:67 +#, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "" + +#: lease.c:129 +#, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "" + +#: lease.c:235 +#, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "" + +#: rfc2131.c:316 +msgid "via" +msgstr "" + +#: rfc2131.c:331 +#, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "" + +#: rfc2131.c:700 +#, c-format +msgid "%u vendor class: %s" +msgstr "" + +#: rfc2131.c:702 +#, c-format +msgid "%u user class: %s" +msgstr "" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "" + +#: rfc2131.c:886 +#, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "" + +#: rfc2131.c:1732 +#, c-format +msgid "%u server name: %s" +msgstr "" + +#: rfc2131.c:1746 +#, c-format +msgid "%u next server: %s" +msgstr "" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "" + +#: rfc2131.c:1812 +#, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "" + +#: rfc2131.c:2189 +#, c-format +msgid "%u requested options: %s" +msgstr "" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "" + +#: netlink.c:70 +#, c-format +msgid "cannot create netlink socket: %s" +msgstr "" + +#: netlink.c:288 +#, c-format +msgid "netlink returns error: %s" +msgstr "" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "" + +#: bpf.c:245 +#, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "" + +#: tftp.c:406 +#, c-format +msgid "file %s not found" +msgstr "" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "" + +#: tftp.c:554 +#, c-format +msgid "failed sending %s to %s" +msgstr "" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "" diff --git a/po/ro.po b/po/ro.po new file mode 100644 index 0000000..094da79 --- /dev/null +++ b/po/ro.po @@ -0,0 +1,1566 @@ +# Romanian translations for dnsmasq package. +# This file is put in the public domain. +# Simon Kelley <simon@thekelleys.org.uk>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: dnsmasq 2.24\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-06-18 12:24+0100\n" +"PO-Revision-Date: 2005-11-22 16:46+0000\n" +"Last-Translator: Simon Kelley <simon@thekelleys.org.uk>\n" +"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +# for compatibility purposes the letters â, ă, ÅŸ, Å£ and î can be written as their look-alike correspondent. +#: cache.c:761 +#, fuzzy, c-format +msgid "failed to load names from %s: %s" +msgstr "încărcarea numelor din %s: %s a eÅŸuat" + +#: cache.c:795 dhcp.c:865 +#, c-format +msgid "bad address at %s line %d" +msgstr "adresă greÅŸită în %s, linia %d" + +#: cache.c:853 dhcp.c:881 +#, c-format +msgid "bad name at %s line %d" +msgstr "nume greÅŸit în %s linia %d" + +#: cache.c:860 dhcp.c:956 +#, c-format +msgid "read %s - %d addresses" +msgstr "citesc %s - %d adrese" + +#: cache.c:899 +msgid "cleared cache" +msgstr "memoria temporară a fost ÅŸtearsă" + +#: cache.c:960 +#, c-format +msgid "%s is a CNAME, not giving it to the DHCP lease of %s" +msgstr "" + +#: cache.c:966 +#, c-format +msgid "not giving name %s to the DHCP lease of %s because the name exists in %s with address %s" +msgstr "nu pot da numele %s împrumutului de adresă DHCP a lui %s deoarece numeleexistă în %s cu adresa %s" + +#: cache.c:1039 +#, c-format +msgid "time %lu" +msgstr "" + +#: cache.c:1040 +#, fuzzy, c-format +msgid "cache size %d, %d/%d cache insertions re-used unexpired cache entries." +msgstr "cantitate de memorie temporară %d, %d/%d stocări temporare aureutilizat locaÅ£ii neexpirate." + +#: cache.c:1042 +#, c-format +msgid "queries forwarded %u, queries answered locally %u" +msgstr "" + +#: cache.c:1068 +#, c-format +msgid "server %s#%d: queries sent %u, retried or failed %u" +msgstr "" + +#: util.c:57 +#, fuzzy, c-format +msgid "failed to seed the random number generator: %s" +msgstr "ascultarea pe socket a eÅŸuat: %s" + +#: util.c:189 +#, fuzzy +msgid "failed to allocate memory" +msgstr "nu pot încărca %d bytes" + +#: util.c:227 option.c:573 +msgid "could not get memory" +msgstr "nu am putut aloca memorie" + +#: util.c:237 +#, fuzzy, c-format +msgid "cannot create pipe: %s" +msgstr "nu pot citi %s: %s" + +#: util.c:245 +#, fuzzy, c-format +msgid "failed to allocate %d bytes" +msgstr "nu pot încărca %d bytes" + +#: util.c:350 +#, c-format +msgid "infinite" +msgstr "infinit" + +#: option.c:244 +msgid "Specify local address(es) to listen on." +msgstr "SpecificaÅ£i adresele locale deservite." + +#: option.c:245 +msgid "Return ipaddr for all hosts in specified domains." +msgstr "AfiÅŸează adresele IP ale maÅŸinilor în domeniul dat." + +#: option.c:246 +msgid "Fake reverse lookups for RFC1918 private address ranges." +msgstr "Simulează căutări după adresă pentru domenii de adresă private (RFC1918)." + +#: option.c:247 +msgid "Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)." +msgstr "Interpretează adresa IP ca NXDOMAIN (împotriva manipulărilor Verisign)" + +#: option.c:248 +#, c-format +msgid "Specify the size of the cache in entries (defaults to %s)." +msgstr "Specifică mărimea înregistrărilor temporare (implicit e %s)." + +#: option.c:249 +#, c-format +msgid "Specify configuration file (defaults to %s)." +msgstr "Specifică fiÅŸier de configurare (implicit e %s)." + +#: option.c:250 +msgid "Do NOT fork into the background: run in debug mode." +msgstr "NU porneÅŸte în fundal: rulează în modul depanare." + +#: option.c:251 +msgid "Do NOT forward queries with no domain part." +msgstr "NU înainta cererile ce nu conÅ£in domeniu DNS." + +#: option.c:252 +msgid "Return self-pointing MX records for local hosts." +msgstr "Răspunde cu înregistrări MX spre el însuÅŸi pentru maÅŸini locale." + +#: option.c:253 +msgid "Expand simple names in /etc/hosts with domain-suffix." +msgstr "Adaugă numelor simple din /etc/hosts numele domeniului ca sufix." + +#: option.c:254 +msgid "Don't forward spurious DNS requests from Windows hosts." +msgstr "Nu inainta cereri DNS defecte provenite de la maÅŸini Windows." + +#: option.c:255 +msgid "Enable DHCP in the range given with lease duration." +msgstr "Activează DHCP în domeniul dat cu durată limitată de împrumut." + +#: option.c:256 +#, c-format +msgid "Change to this group after startup (defaults to %s)." +msgstr "Rulează sub acest grup după pornire (implicit e %s)." + +#: option.c:257 +msgid "Set address or hostname for a specified machine." +msgstr "Schimbă adresa sau numele maÅŸinii specificate." + +#: option.c:258 +#, fuzzy +msgid "Read DHCP host specs from file." +msgstr "nume MX invalid" + +#: option.c:259 +msgid "Read DHCP option specs from file." +msgstr "" + +#: option.c:260 +msgid "Evaluate conditional tag expression." +msgstr "" + +#: option.c:261 +#, c-format +msgid "Do NOT load %s file." +msgstr "Nu încarcă fiÅŸierul %s." + +#: option.c:262 +#, c-format +msgid "Specify a hosts file to be read in addition to %s." +msgstr "Specifică spre citire un fiÅŸier hosts adiÅ£ional la %s." + +#: option.c:263 +msgid "Specify interface(s) to listen on." +msgstr "Specifică interfeÅ£ele deservite." + +#: option.c:264 +msgid "Specify interface(s) NOT to listen on." +msgstr "Specifică interfeÅ£ele NE-deservite." + +#: option.c:265 +#, fuzzy +msgid "Map DHCP user class to tag." +msgstr "Leagă clasa de utilizator DHCP cu grup de opÅ£iuni." + +#: option.c:266 +msgid "Map RFC3046 circuit-id to tag." +msgstr "" + +#: option.c:267 +msgid "Map RFC3046 remote-id to tag." +msgstr "" + +#: option.c:268 +msgid "Map RFC3993 subscriber-id to tag." +msgstr "" + +#: option.c:269 +#, fuzzy +msgid "Don't do DHCP for hosts with tag set." +msgstr "Nu furniza DHCP maÅŸinilor din grupul de opÅ£iuni." + +#: option.c:270 +#, fuzzy +msgid "Force broadcast replies for hosts with tag set." +msgstr "Nu furniza DHCP maÅŸinilor din grupul de opÅ£iuni." + +#: option.c:271 +msgid "Do NOT fork into the background, do NOT run in debug mode." +msgstr "NU porneÅŸte în fundal, NU rulează în modul depanare." + +#: option.c:272 +msgid "Assume we are the only DHCP server on the local network." +msgstr "Presupune că suntem singurul server DHCP din reÅ£eaua locală." + +#: option.c:273 +#, c-format +msgid "Specify where to store DHCP leases (defaults to %s)." +msgstr "Specifică fiÅŸierul de stocare a împrumuturilor DHCP (implicit e %s)." + +#: option.c:274 +msgid "Return MX records for local hosts." +msgstr "Răspunde cu întregistrări MX pentru maÅŸini locale." + +#: option.c:275 +msgid "Specify an MX record." +msgstr "Specifică o înregistrare MX." + +#: option.c:276 +msgid "Specify BOOTP options to DHCP server." +msgstr "Specifică opÅ£iuni BOOTP serverului DHCP." + +#: option.c:277 +#, c-format +msgid "Do NOT poll %s file, reload only on SIGHUP." +msgstr "Nu încărca fiÅŸierul %s, citeÅŸte-l doar la SIGHUP." + +#: option.c:278 +msgid "Do NOT cache failed search results." +msgstr "NU memora rezultatele de căutare DNS eÅŸuatată." + +#: option.c:279 +#, c-format +msgid "Use nameservers strictly in the order given in %s." +msgstr "FoloseÅŸte servere DNS strict în ordinea dată în %s." + +#: option.c:280 +#, fuzzy +msgid "Specify options to be sent to DHCP clients." +msgstr "Configurează opÅ£iuni în plusce trebuie trimise clienÅ£ilor DHCP." + +#: option.c:281 +msgid "DHCP option sent even if the client does not request it." +msgstr "" + +#: option.c:282 +msgid "Specify port to listen for DNS requests on (defaults to 53)." +msgstr "Specifică numărul portului pentru cereri DNS (implicit e 53)." + +#: option.c:283 +#, c-format +msgid "Maximum supported UDP packet size for EDNS.0 (defaults to %s)." +msgstr "Marimea maximă a pachetului UDP pentru EDNS.0 (implicit e %s)." + +#: option.c:284 +#, fuzzy +msgid "Log DNS queries." +msgstr "ÃŽnregistrează tranzacÅ£iile." + +#: option.c:285 +#, fuzzy +msgid "Force the originating port for upstream DNS queries." +msgstr "ForÅ£ează acest port pentru datele ce pleacă." + +#: option.c:286 +msgid "Do NOT read resolv.conf." +msgstr "NU citi fiÅŸierul resolv.conf" + +#: option.c:287 +#, c-format +msgid "Specify path to resolv.conf (defaults to %s)." +msgstr "Specifică calea către resolv.conf (implicit e %s)." + +#: option.c:288 +msgid "Specify address(es) of upstream servers with optional domains." +msgstr "Specifică adresele server(elor) superioare cu domenii opÅ£ionale." + +#: option.c:289 +msgid "Never forward queries to specified domains." +msgstr "Nu înaintează cererile spre domeniile specificate." + +#: option.c:290 +msgid "Specify the domain to be assigned in DHCP leases." +msgstr "Specifică domeniul de transmis prin DHCP." + +#: option.c:291 +msgid "Specify default target in an MX record." +msgstr "Specifică o Å£intă într-o înregistrare MX." + +#: option.c:292 +msgid "Specify time-to-live in seconds for replies from /etc/hosts." +msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts." + +#: option.c:293 +#, fuzzy +msgid "Specify time-to-live in seconds for negative caching." +msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts." + +#: option.c:294 +#, fuzzy +msgid "Specify time-to-live in seconds for maximum TTL to send to clients." +msgstr "Specifică TTL în secunde pentru răspunsurile din /etc/hosts." + +#: option.c:295 +#, c-format +msgid "Change to this user after startup. (defaults to %s)." +msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)." + +#: option.c:296 +#, fuzzy +msgid "Map DHCP vendor class to tag." +msgstr "Trimite opÅ£iuni DHCP în funcÅ£ie de marca plăcii de reÅ£ea." + +#: option.c:297 +msgid "Display dnsmasq version and copyright information." +msgstr "AfiÅŸează versiunea dnsmasq ÅŸi drepturile de autor." + +#: option.c:298 +msgid "Translate IPv4 addresses from upstream servers." +msgstr "Traduce adresele IPv4 de la serverele DNS superioare." + +#: option.c:299 +msgid "Specify a SRV record." +msgstr "Specifică o înregistrare SRV." + +#: option.c:300 +msgid "Display this message. Use --help dhcp for known DHCP options." +msgstr "" + +#: option.c:301 +#, fuzzy, c-format +msgid "Specify path of PID file (defaults to %s)." +msgstr "Specifică o cale pentru fiÅŸierul PID. (implicit %s)." + +#: option.c:302 +#, c-format +msgid "Specify maximum number of DHCP leases (defaults to %s)." +msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)." + +#: option.c:303 +msgid "Answer DNS queries based on the interface a query was sent to." +msgstr "Răspunde cererilor DNS în funcÅ£ie de interfaÅ£a pe care a venit cererea." + +#: option.c:304 +msgid "Specify TXT DNS record." +msgstr "Specifică o înregistrare TXT." + +#: option.c:305 +#, fuzzy +msgid "Specify PTR DNS record." +msgstr "Specifică o înregistrare TXT." + +#: option.c:306 +msgid "Give DNS name to IPv4 address of interface." +msgstr "" + +#: option.c:307 +msgid "Bind only to interfaces in use." +msgstr "Ascultă doar pe interfeÅ£ele active." + +#: option.c:308 +#, c-format +msgid "Read DHCP static host information from %s." +msgstr "CiteÅŸte informaÅ£ii DHCP statice despre maÅŸină din %s." + +#: option.c:309 +msgid "Enable the DBus interface for setting upstream servers, etc." +msgstr "Activeaza interfaÅ£a DBus pentru configurarea serverelor superioare." + +#: option.c:310 +msgid "Do not provide DHCP on this interface, only provide DNS." +msgstr "Nu activează DHCP ci doar DNS pe această interfaţă." + +#: option.c:311 +msgid "Enable dynamic address allocation for bootp." +msgstr "Activează alocarea dinamică a adreselor pentru BOOTP." + +#: option.c:312 +#, fuzzy +msgid "Map MAC address (with wildcards) to option set." +msgstr "Trimite opÅ£iuni DHCP în funcÅ£ie de marca plăcii de reÅ£ea." + +#: option.c:313 +msgid "Treat DHCP requests on aliases as arriving from interface." +msgstr "" + +#: option.c:314 +msgid "Disable ICMP echo address checking in the DHCP server." +msgstr "" + +#: option.c:315 +msgid "Script to run on DHCP lease creation and destruction." +msgstr "" + +#: option.c:316 +msgid "Read configuration from all the files in this directory." +msgstr "" + +#: option.c:317 +#, fuzzy +msgid "Log to this syslog facility or file. (defaults to DAEMON)" +msgstr "Rulează sub acest utilizator după pornire. (implicit e %s)." + +#: option.c:318 +msgid "Do not use leasefile." +msgstr "" + +#: option.c:319 +#, fuzzy, c-format +msgid "Maximum number of concurrent DNS queries. (defaults to %s)" +msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)." + +#: option.c:320 +#, c-format +msgid "Clear DNS cache when reloading %s." +msgstr "" + +#: option.c:321 +msgid "Ignore hostnames provided by DHCP clients." +msgstr "" + +#: option.c:322 +msgid "Do NOT reuse filename and server fields for extra DHCP options." +msgstr "" + +#: option.c:323 +msgid "Enable integrated read-only TFTP server." +msgstr "" + +#: option.c:324 +msgid "Export files by TFTP only from the specified subtree." +msgstr "" + +#: option.c:325 +msgid "Add client IP address to tftp-root." +msgstr "" + +#: option.c:326 +msgid "Allow access only to files owned by the user running dnsmasq." +msgstr "" + +#: option.c:327 +#, fuzzy, c-format +msgid "Maximum number of conncurrent TFTP transfers (defaults to %s)." +msgstr "Specifică numărul maxim de împrumuturi DHCP (implicit %s)." + +#: option.c:328 +msgid "Disable the TFTP blocksize extension." +msgstr "" + +#: option.c:329 +msgid "Ephemeral port range for use by TFTP transfers." +msgstr "" + +#: option.c:330 +msgid "Extra logging for DHCP." +msgstr "" + +#: option.c:331 +msgid "Enable async. logging; optionally set queue length." +msgstr "" + +#: option.c:332 +msgid "Stop DNS rebinding. Filter private IP ranges when resolving." +msgstr "" + +#: option.c:333 +msgid "Allow rebinding of 127.0.0.0/8, for RBL servers." +msgstr "" + +#: option.c:334 +msgid "Inhibit DNS-rebind protection on this domain." +msgstr "" + +#: option.c:335 +msgid "Always perform DNS queries to all servers." +msgstr "" + +#: option.c:336 +msgid "Set tag if client includes matching option in request." +msgstr "" + +#: option.c:337 +msgid "Use alternative ports for DHCP." +msgstr "" + +#: option.c:338 +msgid "Run lease-change script as this user." +msgstr "" + +#: option.c:339 +#, fuzzy +msgid "Specify NAPTR DNS record." +msgstr "Specifică o înregistrare TXT." + +#: option.c:340 +msgid "Specify lowest port available for DNS query transmission." +msgstr "" + +#: option.c:341 +msgid "Use only fully qualified domain names for DHCP clients." +msgstr "" + +#: option.c:342 +msgid "Generate hostnames based on MAC address for nameless clients." +msgstr "" + +#: option.c:343 +msgid "Use these DHCP relays as full proxies." +msgstr "" + +#: option.c:344 +msgid "Specify alias name for LOCAL DNS name." +msgstr "" + +#: option.c:345 +#, fuzzy +msgid "Prompt to send to PXE clients." +msgstr "Configurează opÅ£iuni în plusce trebuie trimise clienÅ£ilor DHCP." + +#: option.c:346 +msgid "Boot service for PXE menu." +msgstr "" + +#: option.c:347 +msgid "Check configuration syntax." +msgstr "" + +#: option.c:348 +msgid "Add requestor's MAC address to forwarded DNS queries" +msgstr "" + +#: option.c:349 +#, fuzzy +msgid "Proxy DNSSEC validation results from upstream nameservers" +msgstr "Traduce adresele IPv4 de la serverele DNS superioare." + +#: option.c:638 +#, c-format +msgid "" +"Usage: dnsmasq [options]\n" +"\n" +msgstr "" +"Utilizare: dnsmasq [opÅ£iuni]\n" +"\n" + +#: option.c:640 +#, c-format +msgid "Use short options only on the command line.\n" +msgstr "FolosiÅ£i opÅ£iunile prescurtate doar în linie de comandă.\n" + +#: option.c:642 +#, fuzzy, c-format +msgid "Valid options are:\n" +msgstr "OpÅ£iunile valide sunt:\n" + +#: option.c:683 +#, c-format +msgid "Known DHCP options:\n" +msgstr "" + +#: option.c:798 +msgid "bad dhcp-option" +msgstr "dhcp-option invalid" + +#: option.c:860 +#, fuzzy +msgid "bad IP address" +msgstr "citesc %s - %d adrese" + +#: option.c:968 +msgid "bad domain in dhcp-option" +msgstr "domeniu DNS invalid în declaraÅ£ia dhcp-option" + +#: option.c:1034 +msgid "dhcp-option too long" +msgstr "declararea dhcp-option este prea lungă" + +#: option.c:1043 +msgid "illegal dhcp-match" +msgstr "" + +#: option.c:1087 +msgid "illegal repeated flag" +msgstr "" + +#: option.c:1095 +msgid "illegal repeated keyword" +msgstr "" + +#: option.c:1147 option.c:3030 +#, fuzzy, c-format +msgid "cannot access directory %s: %s" +msgstr "nu pot citi %s: %s" + +#: option.c:1178 tftp.c:460 +#, fuzzy, c-format +msgid "cannot access %s: %s" +msgstr "nu pot citi %s: %s" + +#: option.c:1207 +msgid "setting log facility is not possible under Android" +msgstr "" + +#: option.c:1216 +msgid "bad log facility" +msgstr "" + +#: option.c:1265 +msgid "bad MX preference" +msgstr "preferinţă MX invalidă" + +#: option.c:1270 +msgid "bad MX name" +msgstr "nume MX invalid" + +#: option.c:1284 +msgid "bad MX target" +msgstr "Å£intă MX invalidă" + +#: option.c:1294 +msgid "cannot run scripts under uClinux" +msgstr "" + +#: option.c:1296 +msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts" +msgstr "" + +#: option.c:1597 option.c:1601 +msgid "bad port" +msgstr "port invalid" + +#: option.c:1620 option.c:1645 +msgid "interface binding not supported" +msgstr "" + +#: option.c:1791 +#, fuzzy +msgid "bad port range" +msgstr "port invalid" + +#: option.c:1808 +msgid "bad bridge-interface" +msgstr "" + +#: option.c:1850 +msgid "bad dhcp-range" +msgstr "dhcp-range invalid" + +#: option.c:1878 +msgid "only one tag allowed" +msgstr "" + +#: option.c:1925 +msgid "inconsistent DHCP range" +msgstr "domeniu DHCP inconsistent" + +#: option.c:2019 option.c:2045 +#, fuzzy +msgid "bad hex constant" +msgstr "dhcp-host invalid" + +#: option.c:2107 +#, fuzzy +msgid "bad DHCP host name" +msgstr "nume MX invalid" + +#: option.c:2188 +#, fuzzy +msgid "bad tag-if" +msgstr "Å£intă MX invalidă" + +#: option.c:2467 option.c:2752 +msgid "invalid port number" +msgstr "număr de port invalid" + +#: option.c:2529 +#, fuzzy +msgid "bad dhcp-proxy address" +msgstr "citesc %s - %d adrese" + +#: option.c:2569 +#, fuzzy +msgid "invalid alias range" +msgstr "pondere invalidă" + +#: option.c:2582 +#, fuzzy +msgid "bad interface name" +msgstr "nume MX invalid" + +#: option.c:2607 +msgid "bad CNAME" +msgstr "" + +#: option.c:2612 +msgid "duplicate CNAME" +msgstr "" + +#: option.c:2632 +#, fuzzy +msgid "bad PTR record" +msgstr "înregistrare SRV invalidă" + +#: option.c:2663 +#, fuzzy +msgid "bad NAPTR record" +msgstr "înregistrare SRV invalidă" + +#: option.c:2695 +msgid "bad TXT record" +msgstr "înregistrare TXT invalidă" + +#: option.c:2738 +msgid "bad SRV record" +msgstr "înregistrare SRV invalidă" + +#: option.c:2745 +msgid "bad SRV target" +msgstr "Å£intă SRV invalidă" + +#: option.c:2759 +msgid "invalid priority" +msgstr "prioritate invalidă" + +#: option.c:2766 +msgid "invalid weight" +msgstr "pondere invalidă" + +#: option.c:2785 +msgid "unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)" +msgstr "" + +#: option.c:2849 +msgid "missing \"" +msgstr "lipseÅŸte \"" + +#: option.c:2908 +msgid "bad option" +msgstr "opÅ£iune invalidă" + +#: option.c:2910 +msgid "extraneous parameter" +msgstr "parametru nerecunoscut" + +#: option.c:2912 +msgid "missing parameter" +msgstr "parametru lipsa" + +#: option.c:2916 +msgid "error" +msgstr "eroare" + +#: option.c:2921 +#, c-format +msgid "%s at line %d of %%s" +msgstr "%s la linia %d din %%s" + +#: option.c:2985 tftp.c:624 +#, c-format +msgid "cannot read %s: %s" +msgstr "nu pot citi %s: %s" + +#: option.c:3151 option.c:3187 +#, fuzzy, c-format +msgid "read %s" +msgstr "citesc %s" + +#: option.c:3239 +msgid "junk found in command line" +msgstr "" + +#: option.c:3269 +#, c-format +msgid "Dnsmasq version %s %s\n" +msgstr "dnsmasq versiunea %s %s\n" + +#: option.c:3270 +#, c-format +msgid "" +"Compile time options %s\n" +"\n" +msgstr "" +"OpÅ£iuni cu care a fost compilat %s\n" +"\n" + +#: option.c:3271 +#, c-format +msgid "This software comes with ABSOLUTELY NO WARRANTY.\n" +msgstr "Acest program vine FÄ‚RÄ‚ NICI O GARANÅ¢IE.\n" + +#: option.c:3272 +#, c-format +msgid "Dnsmasq is free software, and you are welcome to redistribute it\n" +msgstr "Dnsmasq este un program gratuit, sunteÅ£i invitaÅ£i să-l redistribuiÅ£i\n" + +#: option.c:3273 +#, fuzzy, c-format +msgid "under the terms of the GNU General Public License, version 2 or 3.\n" +msgstr "în termenii LicenÅ£ei publice generale GNU, versiunea 2.\n" + +#: option.c:3284 +msgid "try --help" +msgstr "" + +#: option.c:3286 +msgid "try -w" +msgstr "" + +#: option.c:3289 +#, fuzzy, c-format +msgid "bad command line options: %s" +msgstr "opÅ£iuni în linie de comandă invalide: %s." + +#: option.c:3330 +#, c-format +msgid "cannot get host-name: %s" +msgstr "nu pot citi numele maÅŸinii: %s" + +#: option.c:3358 +msgid "only one resolv.conf file allowed in no-poll mode." +msgstr "se permite un singur fiÅŸier resolv.conf în modul no-poll" + +#: option.c:3368 +msgid "must have exactly one resolv.conf to read domain from." +msgstr "am nevoie de un singur resolv.conf din care să citesc numele domeniului." + +#: option.c:3371 network.c:848 dhcp.c:814 +#, fuzzy, c-format +msgid "failed to read %s: %s" +msgstr "nu pot citi %s: %s" + +#: option.c:3388 +#, c-format +msgid "no search directive found in %s" +msgstr "nu s-a găsit nici un criteriu de căutare în %s" + +#: option.c:3409 +msgid "there must be a default domain when --dhcp-fqdn is set" +msgstr "" + +#: option.c:3413 +msgid "syntax check OK" +msgstr "" + +#: forward.c:461 +#, c-format +msgid "nameserver %s refused to do a recursive query" +msgstr "serverul DNS %s refuză interogările recursive" + +#: forward.c:489 +#, c-format +msgid "possible DNS-rebind attack detected: %s" +msgstr "" + +#: network.c:171 +#, fuzzy, c-format +msgid "unknown interface %s in bridge-interface" +msgstr "interfaţă necunoscută %s" + +#: network.c:380 +#, fuzzy, c-format +msgid "failed to create listening socket for %s: %s" +msgstr "creearea socket-ului de ascultare a eÅŸuat: %s" + +#: network.c:746 +#, fuzzy, c-format +msgid "failed to bind server socket for %s: %s" +msgstr "activarea socket-ului de ascultare pentru %s a eÅŸuat: %s" + +#: network.c:783 +#, c-format +msgid "ignoring nameserver %s - local interface" +msgstr "ignorăm serverul DNS %s - interfaţă locală" + +#: network.c:794 +#, fuzzy, c-format +msgid "ignoring nameserver %s - cannot make/bind socket: %s" +msgstr "ignorăm serverul DNS %s - nu pot creea/activa socket-ul: %s" + +#: network.c:811 +msgid "unqualified" +msgstr "invalid" + +#: network.c:811 +msgid "names" +msgstr "" + +#: network.c:813 +msgid "default" +msgstr "" + +#: network.c:815 +msgid "domain" +msgstr "domeniu" + +#: network.c:818 +#, c-format +msgid "using local addresses only for %s %s" +msgstr "folosim adresele locale doar pentru %S %s" + +#: network.c:820 +#, fuzzy, c-format +msgid "using standard nameservers for %s %s" +msgstr "folosim serverul DNS %s#%d pentru %s %s" + +#: network.c:822 +#, c-format +msgid "using nameserver %s#%d for %s %s" +msgstr "folosim serverul DNS %s#%d pentru %s %s" + +#: network.c:825 +#, fuzzy, c-format +msgid "using nameserver %s#%d(via %s)" +msgstr "folosim serverul DNS %s#%d" + +#: network.c:827 +#, c-format +msgid "using nameserver %s#%d" +msgstr "folosim serverul DNS %s#%d" + +#: dnsmasq.c:148 +#, fuzzy +msgid "TFTP server not available: set HAVE_TFTP in src/config.h" +msgstr "DBus nu este disponibil: puneÅ£i HAVE_DBUS in src/config.h" + +#: dnsmasq.c:153 +msgid "asychronous logging is not available under Solaris" +msgstr "" + +#: dnsmasq.c:158 +msgid "asychronous logging is not available under Android" +msgstr "" + +#: dnsmasq.c:177 +#, c-format +msgid "failed to find list of interfaces: %s" +msgstr "enumerarea interfeÅ£elor a eÅŸuat: %s" + +#: dnsmasq.c:185 +#, c-format +msgid "unknown interface %s" +msgstr "interfaţă necunoscută %s" + +#: dnsmasq.c:191 +#, c-format +msgid "no interface with address %s" +msgstr "nu exista interfaţă pentru adresa %s" + +#: dnsmasq.c:207 dnsmasq.c:678 +#, c-format +msgid "DBus error: %s" +msgstr "eroare DBus: %s" + +#: dnsmasq.c:210 +msgid "DBus not available: set HAVE_DBUS in src/config.h" +msgstr "DBus nu este disponibil: puneÅ£i HAVE_DBUS in src/config.h" + +#: dnsmasq.c:236 +#, c-format +msgid "unknown user or group: %s" +msgstr "" + +#: dnsmasq.c:291 +#, c-format +msgid "cannot chdir to filesystem root: %s" +msgstr "" + +#: dnsmasq.c:455 +#, fuzzy, c-format +msgid "started, version %s DNS disabled" +msgstr "am pornit, versiunea %s memorie temporară dezactivată" + +#: dnsmasq.c:457 +#, c-format +msgid "started, version %s cachesize %d" +msgstr "am ponit, versiunea %s memorie temporară %d" + +#: dnsmasq.c:459 +#, c-format +msgid "started, version %s cache disabled" +msgstr "am pornit, versiunea %s memorie temporară dezactivată" + +#: dnsmasq.c:461 +#, c-format +msgid "compile time options: %s" +msgstr "compilat cu opÅ£iunile: %s" + +#: dnsmasq.c:467 +msgid "DBus support enabled: connected to system bus" +msgstr "suportul DBus activ: sunt conectat la magistrala sistem" + +#: dnsmasq.c:469 +msgid "DBus support enabled: bus connection pending" +msgstr "suportul DBus activ: aÅŸtept conexiunea la magistrală" + +# for compatibility purposes the letters â, ă, ÅŸ, Å£ and î can be written as their look-alike correspondent. +#: dnsmasq.c:474 +#, fuzzy, c-format +msgid "warning: failed to change owner of %s: %s" +msgstr "încărcarea numelor din %s: %s a eÅŸuat" + +#: dnsmasq.c:478 +msgid "setting --bind-interfaces option because of OS limitations" +msgstr "specific opÅ£iunea --bind-interfaces din cauza limitărilor SO" + +#: dnsmasq.c:483 +#, c-format +msgid "warning: interface %s does not currently exist" +msgstr "atenÅ£ie: interfaÅ£a %s nu există momentan" + +#: dnsmasq.c:488 +msgid "warning: ignoring resolv-file flag because no-resolv is set" +msgstr "" + +#: dnsmasq.c:491 +#, fuzzy +msgid "warning: no upstream servers configured" +msgstr "configurăm serverele superioare prin Dbus" + +#: dnsmasq.c:495 +#, c-format +msgid "asynchronous logging enabled, queue limit is %d messages" +msgstr "" + +#: dnsmasq.c:508 +#, c-format +msgid "DHCP, static leases only on %.0s%s, lease time %s" +msgstr "DHCP, împrumuturi statice doar către %.0s%s, timpul reînoirii %s" + +#: dnsmasq.c:510 +#, c-format +msgid "DHCP, proxy on subnet %.0s%s%.0s" +msgstr "" + +#: dnsmasq.c:511 +#, c-format +msgid "DHCP, IP range %s -- %s, lease time %s" +msgstr "DHCP, domeniu IP %s -- %s, timpul reînoirii %s" + +#: dnsmasq.c:526 +msgid "root is " +msgstr "" + +#: dnsmasq.c:526 +#, fuzzy +msgid "enabled" +msgstr "dezactivat" + +#: dnsmasq.c:528 +msgid "secure mode" +msgstr "" + +#: dnsmasq.c:554 +#, c-format +msgid "restricting maximum simultaneous TFTP transfers to %d" +msgstr "" + +#: dnsmasq.c:680 +msgid "connected to system DBus" +msgstr "magistrala sistem Dbus conectată" + +#: dnsmasq.c:775 +#, c-format +msgid "cannot fork into background: %s" +msgstr "" + +#: dnsmasq.c:778 +#, fuzzy, c-format +msgid "failed to create helper: %s" +msgstr "nu pot citi %s: %s" + +#: dnsmasq.c:781 +#, c-format +msgid "setting capabilities failed: %s" +msgstr "" + +# for compatibility purposes the letters â, ă, ÅŸ, Å£ and î can be written as their look-alike correspondent. +#: dnsmasq.c:785 +#, fuzzy, c-format +msgid "failed to change user-id to %s: %s" +msgstr "încărcarea numelor din %s: %s a eÅŸuat" + +# for compatibility purposes the letters â, ă, ÅŸ, Å£ and î can be written as their look-alike correspondent. +#: dnsmasq.c:790 +#, fuzzy, c-format +msgid "failed to change group-id to %s: %s" +msgstr "încărcarea numelor din %s: %s a eÅŸuat" + +#: dnsmasq.c:793 +#, fuzzy, c-format +msgid "failed to open pidfile %s: %s" +msgstr "nu pot citi %s: %s" + +#: dnsmasq.c:796 +#, fuzzy, c-format +msgid "cannot open %s: %s" +msgstr "nu pot deschide %s:%s" + +#: dnsmasq.c:851 +#, c-format +msgid "child process killed by signal %d" +msgstr "" + +#: dnsmasq.c:855 +#, c-format +msgid "child process exited with status %d" +msgstr "" + +#: dnsmasq.c:859 +#, fuzzy, c-format +msgid "failed to execute %s: %s" +msgstr "accesarea serverului %s a eÅŸuat: %s" + +#: dnsmasq.c:903 +msgid "exiting on receipt of SIGTERM" +msgstr "am primit SIGTERM, am terminat" + +#: dnsmasq.c:931 +#, fuzzy, c-format +msgid "failed to access %s: %s" +msgstr "accesarea serverului %s a eÅŸuat: %s" + +#: dnsmasq.c:961 +#, c-format +msgid "reading %s" +msgstr "citesc %s" + +#: dnsmasq.c:972 +#, fuzzy, c-format +msgid "no servers found in %s, will retry" +msgstr "nu s-a găsit nici un criteriu de căutare în %s" + +#: dhcp.c:40 +#, c-format +msgid "cannot create DHCP socket: %s" +msgstr "nu pot creea socket DHCP: %s" + +#: dhcp.c:52 +#, c-format +msgid "failed to set options on DHCP socket: %s" +msgstr "configurarea opÅ£iunilor socketului DHCP a eÅŸuat: %s" + +#: dhcp.c:65 +#, fuzzy, c-format +msgid "failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s" +msgstr "configurarea SO_REUSEADDR pe socket-ul DHCP a eÅŸuat: %s" + +#: dhcp.c:77 +#, c-format +msgid "failed to bind DHCP server socket: %s" +msgstr "activarea socket-ului server-ului DHCP a eÅŸuat: %s" + +#: dhcp.c:103 +#, c-format +msgid "cannot create ICMP raw socket: %s." +msgstr "nu pot creea socket ICMP raw: %s." + +#: dhcp.c:281 +#, c-format +msgid "DHCP packet received on %s which has no address" +msgstr "" + +#: dhcp.c:445 +#, c-format +msgid "DHCP range %s -- %s is not consistent with netmask %s" +msgstr "domeniu DHCP %s -- %s nu este consistent cu masca de reÅ£ea %s" + +#: dhcp.c:852 +#, c-format +msgid "bad line at %s line %d" +msgstr "linie invalidă în %s rândul %d" + +#: dhcp.c:895 +#, c-format +msgid "ignoring %s line %d, duplicate name or IP address" +msgstr "" + +#: dhcp.c:978 +#, c-format +msgid "duplicate IP address %s in dhcp-config directive." +msgstr "adresă IP duplicat %s în declaraÅ£ia dhcp-config." + +#: dhcp.c:981 +#, fuzzy, c-format +msgid "duplicate IP address %s in %s." +msgstr "adresă IP duplicat %s în declaraÅ£ia dhcp-config." + +#: dhcp.c:1024 +#, c-format +msgid "%s has more than one address in hostsfile, using %s for DHCP" +msgstr "" + +#: dhcp.c:1029 +#, c-format +msgid "duplicate IP address %s (%s) in dhcp-config directive" +msgstr "adresă IP duplicat %s (%s) în declaraÅ£ia dhcp-config." + +#: lease.c:67 +#, fuzzy, c-format +msgid "cannot open or create lease file %s: %s" +msgstr "nu pot creea sau deschide fiÅŸierul cu împrumuturi: %s" + +#: lease.c:93 +msgid "too many stored leases" +msgstr "prea multe împrumuturi stocate" + +#: lease.c:129 +#, fuzzy, c-format +msgid "cannot run lease-init script %s: %s" +msgstr "nu pot citi %s: %s" + +#: lease.c:135 +#, c-format +msgid "lease-init script returned exit code %s" +msgstr "" + +#: lease.c:235 +#, fuzzy, c-format +msgid "failed to write %s: %s (retry in %us)" +msgstr "nu pot citi %s: %s" + +#: rfc2131.c:315 +#, c-format +msgid "no address range available for DHCP request %s %s" +msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s" + +#: rfc2131.c:316 +msgid "with subnet selector" +msgstr "cu selectorul de subreÅ£ea" + +#: rfc2131.c:316 +msgid "via" +msgstr "prin" + +#: rfc2131.c:331 +#, fuzzy, c-format +msgid "%u available DHCP subnet: %s/%s" +msgstr "nici un domeniu de adrese disponibil pentru cererea DHCP %s %s" + +#: rfc2131.c:334 +#, c-format +msgid "%u available DHCP range: %s -- %s" +msgstr "" + +#: rfc2131.c:363 +msgid "disabled" +msgstr "dezactivat" + +#: rfc2131.c:404 rfc2131.c:916 rfc2131.c:1288 +msgid "ignored" +msgstr "ignorat" + +#: rfc2131.c:419 rfc2131.c:1135 +msgid "address in use" +msgstr "adresa este folosită" + +#: rfc2131.c:433 rfc2131.c:970 +msgid "no address available" +msgstr "nici o adresă disponibilă" + +#: rfc2131.c:440 rfc2131.c:1098 +msgid "wrong network" +msgstr "reÅ£ea greÅŸită" + +#: rfc2131.c:454 +msgid "no address configured" +msgstr "adresă lipsă" + +#: rfc2131.c:460 rfc2131.c:1148 +msgid "no leases left" +msgstr "nu mai am de unde să împrumut" + +#: rfc2131.c:545 +#, c-format +msgid "%u client provides name: %s" +msgstr "" + +#: rfc2131.c:700 +#, fuzzy, c-format +msgid "%u vendor class: %s" +msgstr "eroare DBus: %s" + +#: rfc2131.c:702 +#, fuzzy, c-format +msgid "%u user class: %s" +msgstr "eroare DBus: %s" + +#: rfc2131.c:761 +msgid "PXE BIS not supported" +msgstr "" + +#: rfc2131.c:886 +#, fuzzy, c-format +msgid "disabling DHCP static address %s for %s" +msgstr "dezactivăm adresele DHCP statice %s" + +#: rfc2131.c:907 +msgid "unknown lease" +msgstr "împrumut necunoscut" + +#: rfc2131.c:939 +#, c-format +msgid "not using configured address %s because it is leased to %s" +msgstr "" + +#: rfc2131.c:949 +#, c-format +msgid "not using configured address %s because it is in use by the server or relay" +msgstr "" + +#: rfc2131.c:952 +#, c-format +msgid "not using configured address %s because it was previously declined" +msgstr "" + +#: rfc2131.c:968 rfc2131.c:1141 +msgid "no unique-id" +msgstr "" + +#: rfc2131.c:1037 +msgid "wrong server-ID" +msgstr "" + +#: rfc2131.c:1055 +msgid "wrong address" +msgstr "adresă greÅŸită" + +#: rfc2131.c:1073 +msgid "lease not found" +msgstr "împrumutul nu a fost găsit" + +#: rfc2131.c:1106 +msgid "address not available" +msgstr "adresă indisponibilă" + +#: rfc2131.c:1117 +msgid "static lease available" +msgstr "împrumut static este disponibil" + +#: rfc2131.c:1121 +msgid "address reserved" +msgstr "adresă rezervată" + +#: rfc2131.c:1129 +#, c-format +msgid "abandoning lease to %s of %s" +msgstr "" + +#: rfc2131.c:1710 +#, c-format +msgid "%u tags: %s" +msgstr "" + +#: rfc2131.c:1723 +#, c-format +msgid "%u bootfile name: %s" +msgstr "" + +#: rfc2131.c:1732 +#, fuzzy, c-format +msgid "%u server name: %s" +msgstr "eroare DBus: %s" + +#: rfc2131.c:1746 +#, fuzzy, c-format +msgid "%u next server: %s" +msgstr "eroare DBus: %s" + +#: rfc2131.c:1749 +#, c-format +msgid "%u broadcast response" +msgstr "" + +#: rfc2131.c:1812 +#, fuzzy, c-format +msgid "cannot send DHCP/BOOTP option %d: no space left in packet" +msgstr "nu pot trimite opÅ£iunea DHCP %d: nu mai este loc în pachet" + +#: rfc2131.c:2058 +msgid "PXE menu too large" +msgstr "" + +#: rfc2131.c:2171 +#, c-format +msgid "Ignoring domain %s for DHCP host name %s" +msgstr "" + +#: rfc2131.c:2189 +#, fuzzy, c-format +msgid "%u requested options: %s" +msgstr "compilat cu opÅ£iunile: %s" + +#: rfc2131.c:2456 +#, c-format +msgid "cannot send RFC3925 option: too many options for enterprise number %d" +msgstr "" + +#: netlink.c:70 +#, fuzzy, c-format +msgid "cannot create netlink socket: %s" +msgstr "nu pot să activez socket-ul netlink: %s" + +#: netlink.c:288 +#, fuzzy, c-format +msgid "netlink returns error: %s" +msgstr "eroare DBus: %s" + +#: dbus.c:150 +msgid "attempt to set an IPv6 server address via DBus - no IPv6 support" +msgstr "incerc să configurez un server IPv6 prin Dbus - nu este suport IPv6" + +#: dbus.c:286 +msgid "setting upstream servers from DBus" +msgstr "configurăm serverele superioare prin Dbus" + +#: dbus.c:324 +msgid "could not register a DBus message handler" +msgstr "nu pot activa o interfaţă de mesaje DBus" + +#: bpf.c:217 +#, c-format +msgid "cannot create DHCP BPF socket: %s" +msgstr "nu pot creea socket DHCP BPF: %s" + +#: bpf.c:245 +#, fuzzy, c-format +msgid "DHCP request for unsupported hardware type (%d) received on %s" +msgstr "cerere DHCP pentru dispozitiv nesuportat (%d) recepÅ£ionată prin %s" + +#: tftp.c:281 +msgid "unable to get free port for TFTP" +msgstr "" + +#: tftp.c:296 +#, c-format +msgid "unsupported request from %s" +msgstr "" + +#: tftp.c:406 +#, fuzzy, c-format +msgid "file %s not found" +msgstr "împrumutul nu a fost găsit" + +#: tftp.c:522 +#, c-format +msgid "error %d %s received from %s" +msgstr "" + +#: tftp.c:554 +#, fuzzy, c-format +msgid "failed sending %s to %s" +msgstr "nu pot citi %s: %s" + +#: tftp.c:568 +#, c-format +msgid "sent %s to %s" +msgstr "" + +#: log.c:177 +#, c-format +msgid "overflow: %d log entries lost" +msgstr "" + +#: log.c:254 +#, c-format +msgid "log failed: %s" +msgstr "" + +#: log.c:462 +msgid "FAILED to start up" +msgstr "pornirea A EÅžUAT" + +#~ msgid "TXT record string too long" +#~ msgstr "ÅŸirul de caractere pentru înregistrarea TXT este prea lung" + +#~ msgid "failed to set IPV6 options on listening socket: %s" +#~ msgstr "configurarea opÅ£iunilor IPv6 a eÅŸuat pe socket-ul de ascultare: %s" + +#~ msgid "failed to bind listening socket for %s: %s" +#~ msgstr "activarea socket-ului de ascultare pentru %s a eÅŸuat: %s" + +#~ msgid "failed to listen on socket: %s" +#~ msgstr "ascultarea pe socket a eÅŸuat: %s" + +#, fuzzy +#~ msgid "failed to create TFTP socket: %s" +#~ msgstr "creearea socket-ului de ascultare a eÅŸuat: %s" + +#~ msgid "must set exactly one interface on broken systems without IP_RECVIF" +#~ msgstr "trebuie specificată exact o singură interfaţă pe sistemele defectece nu au IP_RECVIF" + +#, fuzzy +#~ msgid "failed to load %s: %s" +#~ msgstr "nu pot încărca %s: %s" + +#~ msgid "bad name in %s" +#~ msgstr "nume invalid în %s" + +#~ msgid "Ignoring DHCP lease for %s because it has an illegal domain part" +#~ msgstr "ÃŽmprumutul DHCP pentru %s va fi ignorat deoarece are domeniu invalid" + +#~ msgid "ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h" +#~ msgstr "Integrarea cu ISC dhcpd nu este disponibilă:puneÅ£i HAVE_ISC_HEADER în src/config.h" + +#, fuzzy +#~ msgid "illegal domain %s in dhcp-config directive." +#~ msgstr "adresă IP duplicat %s în declaraÅ£ia dhcp-config." + +#~ msgid "running as root" +#~ msgstr "rulez ca root" + +#, fuzzy +#~ msgid "read %s - %d hosts" +#~ msgstr "citesc %s - %d adrese" + +#~ msgid "domains" +#~ msgstr "domenii" + +#~ msgid "Ignoring DHCP host name %s because it has an illegal domain part" +#~ msgstr "Ignor numele DHCP al maÅŸinii %s deoarece are domeniu DNS ilegal" + +#~ msgid "Display this message." +#~ msgstr "AfiÅŸează acest mesaj." + +#~ msgid "failed to read %s:%m" +#~ msgstr "citirea %s:%n a eÅŸuat" + +#, fuzzy +#~ msgid "cannot send encapsulated option %d: no space left in wrapper" +#~ msgstr "nu pot trimite opÅ£iunea DHCP %d: nu mai este loc în pachet" + +#~ msgid "More than one vendor class matches, using %s" +#~ msgstr "Se potrivesc mai multe clase de mărci de interfeÅ£e, folosim %s" + +#~ msgid "forwarding table overflow: check for server loops." +#~ msgstr "depăşire de memorie în tabela cu înaintări DNS: verificaÅ£i de bucle." + +#~ msgid "nested includes not allowed" +#~ msgstr "incluziunile locale nu sunt permise" + +#~ msgid "DHCP, %s will be written every %s" +#~ msgstr "DHCP, %s va fi rescris odată la fiecare %s" + +#~ msgid "cannot create DHCP packet socket: %s. Is CONFIG_PACKET enabled in your kernel?" +#~ msgstr "nu pot creea socket DHCP packet: %s. AveÅ£i activată în nucleulsistemului opÅ£iunea CONFIG_PACKET ?" diff --git a/setup.html b/setup.html new file mode 100644 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 100644 index 0000000..9a77426 --- /dev/null +++ b/src/bpf.c @@ -0,0 +1,321 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) + +static struct iovec ifconf = { + .iov_base = NULL, + .iov_len = 0 +}; + +static struct iovec ifreq = { + .iov_base = NULL, + .iov_len = 0 +}; + +#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) + +#include <sys/sysctl.h> +#include <net/route.h> +#include <net/if_dl.h> +#include <netinet/if_ether.h> + +int arp_enumerate(void *parm, int (*callback)()) +{ + int mib[6]; + size_t needed; + char *next; + struct rt_msghdr *rtm; + struct sockaddr_inarp *sin2; + struct sockaddr_dl *sdl; + int rc; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_INET; + mib[4] = NET_RT_FLAGS; +#ifdef RTF_LLINFO + mib[5] = RTF_LLINFO; +#else + mib[5] = 0; +#endif + if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1 || needed == 0) + return 0; + + while (1) + { + if (!expand_buf(&ifconf, needed)) + return 0; + if ((rc = sysctl(mib, 6, ifconf.iov_base, &needed, NULL, 0)) == 0 || + errno != ENOMEM) + break; + needed += needed / 8; + } + if (rc == -1) + return 0; + + for (next = ifconf.iov_base ; next < (char *)ifconf.iov_base + needed; next += rtm->rtm_msglen) + { + rtm = (struct rt_msghdr *)next; + sin2 = (struct sockaddr_inarp *)(rtm + 1); + sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2)); + if (!(*callback)(AF_INET, &sin2->sin_addr, LLADDR(sdl), sdl->sdl_alen, parm)) + return 0; + } + + return 1; +} + +#endif + + +int iface_enumerate(int family, void *parm, int (*callback)()) +{ + char *ptr; + struct ifreq *ifr; + struct ifconf ifc; + int fd, errsav, ret = 0; + int lastlen = 0; + size_t len = 0; + + if (family == AF_UNSPEC) +#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) + return arp_enumerate(parm, callback); +#else + return 0; /* need code for Solaris and MacOS*/ +#endif + + if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) + return 0; + + while(1) + { + len += 10*sizeof(struct ifreq); + + if (!expand_buf(&ifconf, len)) + goto err; + + ifc.ifc_len = len; + ifc.ifc_buf = ifconf.iov_base; + + if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) + { + if (errno != EINVAL || lastlen != 0) + goto err; + } + else + { + if (ifc.ifc_len == lastlen) + break; /* got a big enough buffer now */ + lastlen = ifc.ifc_len; + } + } + + for (ptr = ifc.ifc_buf; ptr < (char *)(ifc.ifc_buf + ifc.ifc_len); ptr += len) + { + /* subsequent entries may not be aligned, so copy into + an aligned buffer to avoid nasty complaints about + unaligned accesses. */ + + len = sizeof(struct ifreq); + +#ifdef HAVE_SOCKADDR_SA_LEN + ifr = (struct ifreq *)ptr; + if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru)) + len = ifr->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru); +#endif + + if (!expand_buf(&ifreq, len)) + goto err; + + ifr = (struct ifreq *)ifreq.iov_base; + memcpy(ifr, ptr, len); + + if (ifr->ifr_addr.sa_family == family) + { + if (family == AF_INET) + { + struct in_addr addr, netmask, broadcast; + broadcast.s_addr = 0; + addr = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr; + if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1) + continue; + netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr; + if (ioctl(fd, SIOCGIFBRDADDR, ifr) != -1) + broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr; + if (!((*callback)(addr, + (int)if_nametoindex(ifr->ifr_name), + netmask, broadcast, + parm))) + goto err; + } +#ifdef HAVE_IPV6 + else if (family == AF_INET6) + { + struct in6_addr *addr = &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr; + /* voodoo to clear interface field in address */ + if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr)) + { + addr->s6_addr[2] = 0; + addr->s6_addr[3] = 0; + } + if (!((*callback)(addr, + (int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id, + (int)if_nametoindex(ifr->ifr_name), + parm))) + goto err; + } +#endif + } + } + + ret = 1; + + err: + errsav = errno; + close(fd); + errno = errsav; + + return ret; +} +#endif + + +#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) +#include <net/bpf.h> + +void init_bpf(void) +{ + int i = 0; + + while (1) + { + /* useful size which happens to be sufficient */ + if (expand_buf(&ifreq, sizeof(struct ifreq))) + { + sprintf(ifreq.iov_base, "/dev/bpf%d", i++); + if ((daemon->dhcp_raw_fd = open(ifreq.iov_base, O_RDWR, 0)) != -1) + return; + } + if (errno != EBUSY) + die(_("cannot create DHCP BPF socket: %s"), NULL, EC_BADNET); + } +} + +void send_via_bpf(struct dhcp_packet *mess, size_t len, + struct in_addr iface_addr, struct ifreq *ifr) +{ + /* Hairy stuff, packet either has to go to the + net broadcast or the destination can't reply to ARP yet, + but we do know the physical address. + Build the packet by steam, and send directly, bypassing + the kernel IP stack */ + + struct ether_header ether; + struct ip ip; + struct udphdr { + u16 uh_sport; /* source port */ + u16 uh_dport; /* destination port */ + u16 uh_ulen; /* udp length */ + u16 uh_sum; /* udp checksum */ + } udp; + + u32 i, sum; + struct iovec iov[4]; + + /* Only know how to do ethernet on *BSD */ + if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN) + { + my_syslog(MS_DHCP | LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"), + mess->htype, ifr->ifr_name); + return; + } + + ifr->ifr_addr.sa_family = AF_LINK; + if (ioctl(daemon->dhcpfd, SIOCGIFADDR, ifr) < 0) + return; + + memcpy(ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN); + ether.ether_type = htons(ETHERTYPE_IP); + + if (ntohs(mess->flags) & 0x8000) + { + memset(ether.ether_dhost, 255, ETHER_ADDR_LEN); + ip.ip_dst.s_addr = INADDR_BROADCAST; + } + else + { + memcpy(ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN); + ip.ip_dst.s_addr = mess->yiaddr.s_addr; + } + + ip.ip_p = IPPROTO_UDP; + ip.ip_src.s_addr = iface_addr.s_addr; + ip.ip_len = htons(sizeof(struct ip) + + sizeof(struct udphdr) + + len) ; + ip.ip_hl = sizeof(struct ip) / 4; + ip.ip_v = IPVERSION; + ip.ip_tos = 0; + ip.ip_id = htons(0); + ip.ip_off = htons(0x4000); /* don't fragment */ + ip.ip_ttl = IPDEFTTL; + ip.ip_sum = 0; + for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++) + sum += ((u16 *)&ip)[i]; + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + ip.ip_sum = (sum == 0xffff) ? sum : ~sum; + + udp.uh_sport = htons(daemon->dhcp_server_port); + udp.uh_dport = htons(daemon->dhcp_client_port); + if (len & 1) + ((char *)mess)[len] = 0; /* for checksum, in case length is odd. */ + udp.uh_sum = 0; + udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len); + sum += htons(IPPROTO_UDP); + sum += ip.ip_src.s_addr & 0xffff; + sum += (ip.ip_src.s_addr >> 16) & 0xffff; + sum += ip.ip_dst.s_addr & 0xffff; + sum += (ip.ip_dst.s_addr >> 16) & 0xffff; + for (i = 0; i < sizeof(struct udphdr)/2; i++) + sum += ((u16 *)&udp)[i]; + for (i = 0; i < (len + 1) / 2; i++) + sum += ((u16 *)mess)[i]; + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + udp.uh_sum = (sum == 0xffff) ? sum : ~sum; + + ioctl(daemon->dhcp_raw_fd, BIOCSETIF, ifr); + + iov[0].iov_base = ðer; + iov[0].iov_len = sizeof(ether); + iov[1].iov_base = &ip; + iov[1].iov_len = sizeof(ip); + iov[2].iov_base = &udp; + iov[2].iov_len = sizeof(udp); + iov[3].iov_base = mess; + iov[3].iov_len = len; + + while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send()); +} + +#endif + + diff --git a/src/cache.c b/src/cache.c new file mode 100644 index 0000000..77c1972 --- /dev/null +++ b/src/cache.c @@ -0,0 +1,1226 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL; +#ifdef HAVE_DHCP +static struct crec *dhcp_spare = NULL; +#endif +static struct crec *new_chain = NULL; +static int cache_inserted = 0, cache_live_freed = 0, insert_error; +static union bigname *big_free = NULL; +static int bignames_left, hash_size; +static int uid = 0; +static char *addrbuff = NULL; + +/* type->string mapping: this is also used by the name-hash function as a mixing table. */ +static const struct { + unsigned int type; + const char * const name; +} typestr[] = { + { 1, "A" }, + { 2, "NS" }, + { 5, "CNAME" }, + { 6, "SOA" }, + { 10, "NULL" }, + { 11, "WKS" }, + { 12, "PTR" }, + { 13, "HINFO" }, + { 15, "MX" }, + { 16, "TXT" }, + { 22, "NSAP" }, + { 23, "NSAP_PTR" }, + { 24, "SIG" }, + { 25, "KEY" }, + { 28, "AAAA" }, + { 33, "SRV" }, + { 35, "NAPTR" }, + { 36, "KX" }, + { 37, "CERT" }, + { 38, "A6" }, + { 39, "DNAME" }, + { 41, "OPT" }, + { 48, "DNSKEY" }, + { 249, "TKEY" }, + { 250, "TSIG" }, + { 251, "IXFR" }, + { 252, "AXFR" }, + { 253, "MAILB" }, + { 254, "MAILA" }, + { 255, "ANY" } +}; + +static void cache_free(struct crec *crecp); +static void cache_unlink(struct crec *crecp); +static void cache_link(struct crec *crecp); +static void rehash(int size); +static void cache_hash(struct crec *crecp); + +void cache_init(void) +{ + struct crec *crecp; + int i; + + if (option_bool(OPT_LOG)) + addrbuff = safe_malloc(ADDRSTRLEN); + + bignames_left = daemon->cachesize/10; + + if (daemon->cachesize > 0) + { + crecp = safe_malloc(daemon->cachesize*sizeof(struct crec)); + + for (i=0; i < daemon->cachesize; i++, crecp++) + { + cache_link(crecp); + crecp->flags = 0; + crecp->uid = uid++; + } + } + + /* create initial hash table*/ + rehash(daemon->cachesize); +} + +/* In most cases, we create the hash table once here by calling this with (hash_table == NULL) + but if the hosts file(s) are big (some people have 50000 ad-block entries), the table + will be much too small, so the hosts reading code calls rehash every 1000 addresses, to + expand the table. */ +static void rehash(int size) +{ + struct crec **new, **old, *p, *tmp; + int i, new_size, old_size; + + /* hash_size is a power of two. */ + for (new_size = 64; new_size < size/10; new_size = new_size << 1); + + /* must succeed in getting first instance, failure later is non-fatal */ + if (!hash_table) + new = safe_malloc(new_size * sizeof(struct crec *)); + else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec *)))) + return; + + for(i = 0; i < new_size; i++) + new[i] = NULL; + + old = hash_table; + old_size = hash_size; + hash_table = new; + hash_size = new_size; + + if (old) + { + for (i = 0; i < old_size; i++) + for (p = old[i]; p ; p = tmp) + { + tmp = p->hash_next; + cache_hash(p); + } + free(old); + } +} + +static struct crec **hash_bucket(char *name) +{ + unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */ + const unsigned char *mix_tab = (const unsigned char*)typestr; + + while((c = (unsigned char) *name++)) + { + /* don't use tolower and friends here - they may be messed up by LOCALE */ + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c); + } + + /* hash_size is a power of two */ + return hash_table + ((val ^ (val >> 16)) & (hash_size - 1)); +} + +static void cache_hash(struct crec *crecp) +{ + /* maintain an invariant that all entries with F_REVERSE set + are at the start of the hash-chain and all non-reverse + immortal entries are at the end of the hash-chain. + This allows reverse searches and garbage collection to be optimised */ + + struct crec **up = hash_bucket(cache_get_name(crecp)); + + if (!(crecp->flags & F_REVERSE)) + { + while (*up && ((*up)->flags & F_REVERSE)) + up = &((*up)->hash_next); + + if (crecp->flags & F_IMMORTAL) + while (*up && !((*up)->flags & F_IMMORTAL)) + up = &((*up)->hash_next); + } + crecp->hash_next = *up; + *up = crecp; +} + +static void cache_free(struct crec *crecp) +{ + crecp->flags &= ~F_FORWARD; + crecp->flags &= ~F_REVERSE; + crecp->uid = uid++; /* invalidate CNAMES pointing to this. */ + + if (cache_tail) + cache_tail->next = crecp; + else + cache_head = crecp; + crecp->prev = cache_tail; + crecp->next = NULL; + cache_tail = crecp; + + /* retrieve big name for further use. */ + if (crecp->flags & F_BIGNAME) + { + crecp->name.bname->next = big_free; + big_free = crecp->name.bname; + crecp->flags &= ~F_BIGNAME; + } +} + +/* insert a new cache entry at the head of the list (youngest entry) */ +static void cache_link(struct crec *crecp) +{ + if (cache_head) /* check needed for init code */ + cache_head->prev = crecp; + crecp->next = cache_head; + crecp->prev = NULL; + cache_head = crecp; + if (!cache_tail) + cache_tail = crecp; +} + +/* remove an arbitrary cache entry for promotion */ +static void cache_unlink (struct crec *crecp) +{ + if (crecp->prev) + crecp->prev->next = crecp->next; + else + cache_head = crecp->next; + + if (crecp->next) + crecp->next->prev = crecp->prev; + else + cache_tail = crecp->prev; +} + +char *cache_get_name(struct crec *crecp) +{ + if (crecp->flags & F_BIGNAME) + return crecp->name.bname->name; + else if (crecp->flags & F_NAMEP) + return crecp->name.namep; + + return crecp->name.sname; +} + +static int is_outdated_cname_pointer(struct crec *crecp) +{ + if (!(crecp->flags & F_CNAME)) + return 0; + + if (crecp->addr.cname.cache && crecp->addr.cname.uid == crecp->addr.cname.cache->uid) + return 0; + + return 1; +} + +static int is_expired(time_t now, struct crec *crecp) +{ + if (crecp->flags & F_IMMORTAL) + return 0; + + if (difftime(now, crecp->ttd) < 0) + return 0; + + return 1; +} + +static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) +{ + /* Scan and remove old entries. + If (flags & F_FORWARD) then remove any forward entries for name and any expired + entries but only in the same hash bucket as name. + If (flags & F_REVERSE) then remove any reverse entries for addr and any expired + entries in the whole cache. + If (flags == 0) remove any expired entries in the whole cache. + + In the flags & F_FORWARD case, the return code is valid, and returns zero if the + name exists in the cache as a HOSTS or DHCP entry (these are never deleted) + + We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal> + so that when we hit an entry which isn't reverse and is immortal, we're done. */ + + struct crec *crecp, **up; + + if (flags & F_FORWARD) + { + for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next) + if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp)) + { + *up = crecp->hash_next; + if (!(crecp->flags & (F_HOSTS | F_DHCP))) + { + cache_unlink(crecp); + cache_free(crecp); + } + } + else if ((crecp->flags & F_FORWARD) && + ((flags & crecp->flags & (F_IPV4 | F_IPV6)) || ((crecp->flags | flags) & F_CNAME)) && + hostname_isequal(cache_get_name(crecp), name)) + { + if (crecp->flags & (F_HOSTS | F_DHCP)) + return 0; + *up = crecp->hash_next; + cache_unlink(crecp); + cache_free(crecp); + } + else + up = &crecp->hash_next; + } + else + { + int i; +#ifdef HAVE_IPV6 + int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ; +#else + int addrlen = INADDRSZ; +#endif + for (i = 0; i < hash_size; i++) + for (crecp = hash_table[i], up = &hash_table[i]; + crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL)); + crecp = crecp->hash_next) + if (is_expired(now, crecp)) + { + *up = crecp->hash_next; + if (!(crecp->flags & (F_HOSTS | F_DHCP))) + { + cache_unlink(crecp); + cache_free(crecp); + } + } + else if (!(crecp->flags & (F_HOSTS | F_DHCP)) && + (flags & crecp->flags & F_REVERSE) && + (flags & crecp->flags & (F_IPV4 | F_IPV6)) && + memcmp(&crecp->addr.addr, addr, addrlen) == 0) + { + *up = crecp->hash_next; + cache_unlink(crecp); + cache_free(crecp); + } + else + up = &crecp->hash_next; + } + + return 1; +} + +/* Note: The normal calling sequence is + cache_start_insert + cache_insert * n + cache_end_insert + + but an abort can cause the cache_end_insert to be missed + in which can the next cache_start_insert cleans things up. */ + +void cache_start_insert(void) +{ + /* Free any entries which didn't get committed during the last + insert due to error. + */ + while (new_chain) + { + struct crec *tmp = new_chain->next; + cache_free(new_chain); + new_chain = tmp; + } + new_chain = NULL; + insert_error = 0; +} + +struct crec *cache_insert(char *name, struct all_addr *addr, + time_t now, unsigned long ttl, unsigned short flags) +{ + struct crec *new; + union bigname *big_name = NULL; + int freed_all = flags & F_REVERSE; + int free_avail = 0; + + log_query(flags | F_UPSTREAM, name, addr, NULL); + + /* if previous insertion failed give up now. */ + if (insert_error) + return NULL; + + /* First remove any expired entries and entries for the name/address we + are currently inserting. Fail is we attempt to delete a name from + /etc/hosts or DHCP. */ + if (!cache_scan_free(name, addr, now, flags)) + { + insert_error = 1; + return NULL; + } + + /* Now get a cache entry from the end of the LRU list */ + while (1) { + if (!(new = cache_tail)) /* no entries left - cache is too small, bail */ + { + insert_error = 1; + return NULL; + } + + /* End of LRU list is still in use: if we didn't scan all the hash + chains for expired entries do that now. If we already tried that + then it's time to start spilling things. */ + + if (new->flags & (F_FORWARD | F_REVERSE)) + { + /* If free_avail set, we believe that an entry has been freed. + Bugs have been known to make this not true, resulting in + a tight loop here. If that happens, abandon the + insert. Once in this state, all inserts will probably fail. */ + if (free_avail) + { + insert_error = 1; + return NULL; + } + + if (freed_all) + { + free_avail = 1; /* Must be free space now. */ + cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags); + cache_live_freed++; + } + else + { + cache_scan_free(NULL, NULL, now, 0); + freed_all = 1; + } + continue; + } + + /* Check if we need to and can allocate extra memory for a long name. + If that fails, give up now. */ + if (name && (strlen(name) > SMALLDNAME-1)) + { + if (big_free) + { + big_name = big_free; + big_free = big_free->next; + } + else if (!bignames_left || + !(big_name = (union bigname *)whine_malloc(sizeof(union bigname)))) + { + insert_error = 1; + return NULL; + } + else + bignames_left--; + + } + + /* Got the rest: finally grab entry. */ + cache_unlink(new); + break; + } + + new->flags = flags; + if (big_name) + { + new->name.bname = big_name; + new->flags |= F_BIGNAME; + } + + if (name) + strcpy(cache_get_name(new), name); + else + *cache_get_name(new) = 0; + + if (addr) + new->addr.addr = *addr; + else + new->addr.cname.cache = NULL; + + new->ttd = now + (time_t)ttl; + new->next = new_chain; + new_chain = new; + + return new; +} + +/* after end of insertion, commit the new entries */ +void cache_end_insert(void) +{ + if (insert_error) + return; + + while (new_chain) + { + struct crec *tmp = new_chain->next; + /* drop CNAMEs which didn't find a target. */ + if (is_outdated_cname_pointer(new_chain)) + cache_free(new_chain); + else + { + cache_hash(new_chain); + cache_link(new_chain); + cache_inserted++; + } + new_chain = tmp; + } + new_chain = NULL; +} + +struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned short prot) +{ + struct crec *ans; + + if (crecp) /* iterating */ + ans = crecp->next; + else + { + /* first search, look for relevant entries and push to top of list + also free anything which has expired */ + struct crec *next, **up, **insert = NULL, **chainp = &ans; + unsigned short ins_flags = 0; + + for (up = hash_bucket(name), crecp = *up; crecp; crecp = next) + { + next = crecp->hash_next; + + if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp)) + { + if ((crecp->flags & F_FORWARD) && + (crecp->flags & prot) && + hostname_isequal(cache_get_name(crecp), name)) + { + if (crecp->flags & (F_HOSTS | F_DHCP)) + { + *chainp = crecp; + chainp = &crecp->next; + } + else + { + cache_unlink(crecp); + cache_link(crecp); + } + + /* Move all but the first entry up the hash chain + this implements round-robin. + Make sure that re-ordering doesn't break the hash-chain + order invariants. + */ + if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags) + { + *up = crecp->hash_next; + crecp->hash_next = *insert; + *insert = crecp; + insert = &crecp->hash_next; + } + else + { + if (!insert) + { + insert = up; + ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL); + } + up = &crecp->hash_next; + } + } + else + /* case : not expired, incorrect entry. */ + up = &crecp->hash_next; + } + else + { + /* expired entry, free it */ + *up = crecp->hash_next; + if (!(crecp->flags & (F_HOSTS | F_DHCP))) + { + cache_unlink(crecp); + cache_free(crecp); + } + } + } + + *chainp = cache_head; + } + + if (ans && + (ans->flags & F_FORWARD) && + (ans->flags & prot) && + hostname_isequal(cache_get_name(ans), name)) + return ans; + + return NULL; +} + +struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, + time_t now, unsigned short prot) +{ + struct crec *ans; +#ifdef HAVE_IPV6 + int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ; +#else + int addrlen = INADDRSZ; +#endif + + if (crecp) /* iterating */ + ans = crecp->next; + else + { + /* first search, look for relevant entries and push to top of list + also free anything which has expired. All the reverse entries are at the + start of the hash chain, so we can give up when we find the first + non-REVERSE one. */ + int i; + struct crec **up, **chainp = &ans; + + for (i=0; i<hash_size; i++) + for (crecp = hash_table[i], up = &hash_table[i]; + crecp && (crecp->flags & F_REVERSE); + crecp = crecp->hash_next) + if (!is_expired(now, crecp)) + { + if ((crecp->flags & prot) && + memcmp(&crecp->addr.addr, addr, addrlen) == 0) + { + if (crecp->flags & (F_HOSTS | F_DHCP)) + { + *chainp = crecp; + chainp = &crecp->next; + } + else + { + cache_unlink(crecp); + cache_link(crecp); + } + } + up = &crecp->hash_next; + } + else + { + *up = crecp->hash_next; + if (!(crecp->flags & (F_HOSTS | F_DHCP))) + { + cache_unlink(crecp); + cache_free(crecp); + } + } + + *chainp = cache_head; + } + + if (ans && + (ans->flags & F_REVERSE) && + (ans->flags & prot) && + memcmp(&ans->addr.addr, addr, addrlen) == 0) + return ans; + + return NULL; +} + +static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen, + unsigned short flags, int index, int addr_dup) +{ + struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6)); + int i, nameexists = 0; + struct cname *a; + + /* Remove duplicates in hosts files. */ + if (lookup && (lookup->flags & F_HOSTS)) + { + nameexists = 1; + if (memcmp(&lookup->addr.addr, addr, addrlen) == 0) + { + free(cache); + return; + } + } + + /* Ensure there is only one address -> name mapping (first one trumps) + We do this by steam here, first we see if the address is the same as + the last one we saw, which eliminates most in the case of an ad-block + file with thousands of entries for the same address. + Then we search and bail at the first matching address that came from + a HOSTS file. Since the first host entry gets reverse, we know + then that it must exist without searching exhaustively for it. */ + + if (addr_dup) + flags &= ~F_REVERSE; + else + for (i=0; i<hash_size; i++) + { + for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next) + if ((lookup->flags & F_HOSTS) && + (lookup->flags & flags & (F_IPV4 | F_IPV6)) && + memcmp(&lookup->addr.addr, addr, addrlen) == 0) + { + flags &= ~F_REVERSE; + break; + } + if (lookup) + break; + } + + cache->flags = flags; + cache->uid = index; + memcpy(&cache->addr.addr, addr, addrlen); + cache_hash(cache); + + /* don't need to do alias stuff for second and subsequent addresses. */ + if (!nameexists) + for (a = daemon->cnames; a; a = a->next) + if (hostname_isequal(cache->name.sname, a->target) && + (lookup = whine_malloc(sizeof(struct crec)))) + { + lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME; + lookup->name.namep = a->alias; + lookup->addr.cname.cache = cache; + lookup->addr.cname.uid = index; + cache_hash(lookup); + } +} + +static int eatspace(FILE *f) +{ + int c, nl = 0; + + while (1) + { + if ((c = getc(f)) == '#') + while (c != '\n' && c != EOF) + c = getc(f); + + if (c == EOF) + return 1; + + if (!isspace(c)) + { + ungetc(c, f); + return nl; + } + + if (c == '\n') + nl = 1; + } +} + +static int gettok(FILE *f, char *token) +{ + int c, count = 0; + + while (1) + { + if ((c = getc(f)) == EOF) + return (count == 0) ? EOF : 1; + + if (isspace(c) || c == '#') + { + ungetc(c, f); + return eatspace(f); + } + + if (count < (MAXDNAME - 1)) + { + token[count++] = c; + token[count] = 0; + } + } +} + +static int read_hostsfile(char *filename, int index, int cache_size) +{ + FILE *f = fopen(filename, "r"); + char *token = daemon->namebuff, *domain_suffix = NULL; + int addr_count = 0, name_count = cache_size, lineno = 0; + unsigned short flags = 0, saved_flags = 0; + struct all_addr addr, saved_addr; + int atnl, addrlen = 0, addr_dup; + + if (!f) + { + my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno)); + return 0; + } + + eatspace(f); + + while ((atnl = gettok(f, token)) != EOF) + { + addr_dup = 0; + lineno++; + +#ifdef HAVE_IPV6 + if (inet_pton(AF_INET, token, &addr) > 0) + { + flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; + addrlen = INADDRSZ; + domain_suffix = get_domain(addr.addr.addr4); + } + else if (inet_pton(AF_INET6, token, &addr) > 0) + { + flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6; + addrlen = IN6ADDRSZ; + domain_suffix = daemon->domain_suffix; + } +#else + if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1) + { + flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; + addrlen = INADDRSZ; + domain_suffix = get_domain(addr.addr.addr4); + } +#endif + else + { + my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno); + while (atnl == 0) + atnl = gettok(f, token); + continue; + } + + if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0) + addr_dup = 1; + else + { + saved_flags = flags; + saved_addr = addr; + } + + addr_count++; + + /* rehash every 1000 names. */ + if ((name_count - cache_size) > 1000) + { + rehash(name_count); + cache_size = name_count; + } + + while (atnl == 0) + { + struct crec *cache; + int fqdn, nomem; + char *canon; + + if ((atnl = gettok(f, token)) == EOF) + break; + + fqdn = !!strchr(token, '.'); + + if ((canon = canonicalise(token, &nomem))) + { + /* If set, add a version of the name with a default domain appended */ + if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn && + (cache = whine_malloc(sizeof(struct crec) + + strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME))) + { + strcpy(cache->name.sname, canon); + strcat(cache->name.sname, "."); + strcat(cache->name.sname, domain_suffix); + add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup); + addr_dup = 1; + name_count++; + } + if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME))) + { + strcpy(cache->name.sname, canon); + add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup); + name_count++; + } + free(canon); + + } + else if (!nomem) + my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno); + } + } + + fclose(f); + rehash(name_count); + + my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count); + + return name_count; +} + +void cache_reload(void) +{ + struct crec *cache, **up, *tmp; + int i, total_size = daemon->cachesize; + struct hostsfile *ah; + + cache_inserted = cache_live_freed = 0; + + for (i=0; i<hash_size; i++) + for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp) + { + tmp = cache->hash_next; + if (cache->flags & F_HOSTS) + { + *up = cache->hash_next; + free(cache); + } + else if (!(cache->flags & F_DHCP)) + { + *up = cache->hash_next; + if (cache->flags & F_BIGNAME) + { + cache->name.bname->next = big_free; + big_free = cache->name.bname; + } + cache->flags = 0; + } + else + up = &cache->hash_next; + } + + if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts) + { + if (daemon->cachesize > 0) + my_syslog(LOG_INFO, _("cleared cache")); + return; + } + + if (!option_bool(OPT_NO_HOSTS)) + total_size = read_hostsfile(HOSTSFILE, 0, total_size); + + daemon->addn_hosts = expand_filelist(daemon->addn_hosts); + for (ah = daemon->addn_hosts; ah; ah = ah->next) + if (!(ah->flags & AH_INACTIVE)) + total_size = read_hostsfile(ah->fname, ah->index, total_size); +} + +char *get_domain(struct in_addr addr) +{ + struct cond_domain *c; + + for (c = daemon->cond_domain; c; c = c->next) + if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) && + ntohl(addr.s_addr) <= ntohl(c->end.s_addr)) + return c->domain; + + return daemon->domain_suffix; +} + +#ifdef HAVE_DHCP +void cache_unhash_dhcp(void) +{ + struct crec *cache, **up; + int i; + + for (i=0; i<hash_size; i++) + for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next) + if (cache->flags & F_DHCP) + { + *up = cache->hash_next; + cache->next = dhcp_spare; + dhcp_spare = cache; + } + else + up = &cache->hash_next; +} + +void cache_add_dhcp_entry(char *host_name, + struct in_addr *host_address, time_t ttd) +{ + struct crec *crec = NULL, *aliasc; + unsigned short flags = F_NAMEP | F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE; + int in_hosts = 0; + struct cname *a; + + while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME))) + { + /* check all addresses associated with name */ + if (crec->flags & F_HOSTS) + { + /* if in hosts, don't need DHCP record */ + in_hosts = 1; + + if (crec->flags & F_CNAME) + my_syslog(MS_DHCP | LOG_WARNING, + _("%s is a CNAME, not giving it to the DHCP lease of %s"), + host_name, inet_ntoa(*host_address)); + else if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr) + { + strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4)); + my_syslog(MS_DHCP | LOG_WARNING, + _("not giving name %s to the DHCP lease of %s because " + "the name exists in %s with address %s"), + host_name, inet_ntoa(*host_address), + record_source(crec->uid), daemon->namebuff); + } + } + else if (!(crec->flags & F_DHCP)) + { + cache_scan_free(host_name, NULL, 0, crec->flags & (F_IPV4 | F_CNAME | F_FORWARD)); + /* scan_free deletes all addresses associated with name */ + break; + } + } + + if (in_hosts) + return; + + if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, F_IPV4))) + { + if (crec->flags & F_NEG) + cache_scan_free(NULL, (struct all_addr *)host_address, 0, F_IPV4 | F_REVERSE); + else + /* avoid multiple reverse mappings */ + flags &= ~F_REVERSE; + } + + if ((crec = dhcp_spare)) + dhcp_spare = dhcp_spare->next; + else /* need new one */ + crec = whine_malloc(sizeof(struct crec)); + + if (crec) /* malloc may fail */ + { + crec->flags = flags; + if (ttd == 0) + crec->flags |= F_IMMORTAL; + else + crec->ttd = ttd; + crec->addr.addr.addr.addr4 = *host_address; + crec->name.namep = host_name; + crec->uid = uid++; + cache_hash(crec); + + for (a = daemon->cnames; a; a = a->next) + if (hostname_isequal(host_name, a->target)) + { + if ((aliasc = dhcp_spare)) + dhcp_spare = dhcp_spare->next; + else /* need new one */ + aliasc = whine_malloc(sizeof(struct crec)); + + if (aliasc) + { + aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME; + if (ttd == 0) + aliasc->flags |= F_IMMORTAL; + else + aliasc->ttd = ttd; + aliasc->name.namep = a->alias; + aliasc->addr.cname.cache = crec; + aliasc->addr.cname.uid = crec->uid; + cache_hash(aliasc); + } + } + } +} +#endif + + +void dump_cache(time_t now) +{ + struct server *serv, *serv1; + + my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now); + my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."), + daemon->cachesize, cache_live_freed, cache_inserted); + my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"), + daemon->queries_forwarded, daemon->local_answer); + + if (!addrbuff && !(addrbuff = whine_malloc(ADDRSTRLEN))) + return; + + /* sum counts from different records for same server */ + for (serv = daemon->servers; serv; serv = serv->next) + serv->flags &= ~SERV_COUNTED; + + for (serv = daemon->servers; serv; serv = serv->next) + if (!(serv->flags & + (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND))) + { + int port; + unsigned int queries = 0, failed_queries = 0; + for (serv1 = serv; serv1; serv1 = serv1->next) + if (!(serv1->flags & + (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) && + sockaddr_isequal(&serv->addr, &serv1->addr)) + { + serv1->flags |= SERV_COUNTED; + queries += serv1->queries; + failed_queries += serv1->failed_queries; + } + port = prettyprint_addr(&serv->addr, addrbuff); + my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), addrbuff, port, queries, failed_queries); + } + + if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG)) + { + struct crec *cache ; + int i; + my_syslog(LOG_INFO, "Host Address Flags Expires"); + + for (i=0; i<hash_size; i++) + for (cache = hash_table[i]; cache; cache = cache->hash_next) + { + char *a, *p = daemon->namebuff; + p += sprintf(p, "%-40.40s ", cache_get_name(cache)); + if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD)) + a = ""; + else if (cache->flags & F_CNAME) + { + a = ""; + if (!is_outdated_cname_pointer(cache)) + a = cache_get_name(cache->addr.cname.cache); + } +#ifdef HAVE_IPV6 + else + { + a = addrbuff; + if (cache->flags & F_IPV4) + inet_ntop(AF_INET, &cache->addr.addr, addrbuff, ADDRSTRLEN); + else if (cache->flags & F_IPV6) + inet_ntop(AF_INET6, &cache->addr.addr, addrbuff, ADDRSTRLEN); + } +#else + else + a = inet_ntoa(cache->addr.addr.addr.addr4); +#endif + p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a, + cache->flags & F_IPV4 ? "4" : "", + cache->flags & F_IPV6 ? "6" : "", + cache->flags & F_CNAME ? "C" : "", + cache->flags & F_FORWARD ? "F" : " ", + cache->flags & F_REVERSE ? "R" : " ", + cache->flags & F_IMMORTAL ? "I" : " ", + cache->flags & F_DHCP ? "D" : " ", + cache->flags & F_NEG ? "N" : " ", + cache->flags & F_NXDOMAIN ? "X" : " ", + cache->flags & F_HOSTS ? "H" : " "); +#ifdef HAVE_BROKEN_RTC + p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now)); +#else + p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd))); + /* ctime includes trailing \n - eat it */ + *(p-1) = 0; +#endif + my_syslog(LOG_INFO, daemon->namebuff); + } + } +} + +char *record_source(int index) +{ + struct hostsfile *ah; + + if (index == 0) + return HOSTSFILE; + + for (ah = daemon->addn_hosts; ah; ah = ah->next) + if (ah->index == index) + return ah->fname; + + return "<unknown>"; +} + +void querystr(char *str, unsigned short type) +{ + unsigned int i; + + sprintf(str, "query[type=%d]", type); + for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++) + if (typestr[i].type == type) + sprintf(str,"query[%s]", typestr[i].name); +} + +void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg) +{ + char *source, *dest = addrbuff; + char *verb = "is"; + + if (!option_bool(OPT_LOG)) + return; + + if (addr) + { +#ifdef HAVE_IPV6 + inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, + addr, addrbuff, ADDRSTRLEN); +#else + strncpy(addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN); +#endif + } + + if (flags & F_REVERSE) + { + dest = name; + name = addrbuff; + } + + if (flags & F_NEG) + { + if (flags & F_NXDOMAIN) + { + if (flags & F_IPV4) + dest = "NXDOMAIN-IPv4"; + else if (flags & F_IPV6) + dest = "NXDOMAIN-IPv6"; + else + dest = "NXDOMAIN"; + } + else + { + if (flags & F_IPV4) + dest = "NODATA-IPv4"; + else if (flags & F_IPV6) + dest = "NODATA-IPv6"; + else + dest = "NODATA"; + } + } + else if (flags & F_CNAME) + dest = "<CNAME>"; + else if (flags & F_RRNAME) + dest = arg; + + if (flags & F_CONFIG) + source = "config"; + else if (flags & F_DHCP) + source = "DHCP"; + else if (flags & F_HOSTS) + source = arg; + else if (flags & F_UPSTREAM) + source = "reply"; + else if (flags & F_SERVER) + { + source = "forwarded"; + verb = "to"; + } + else if (flags & F_QUERY) + { + source = arg; + verb = "from"; + } + else + source = "cached"; + + if (strlen(name) == 0) + name = "."; + + my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); +} + diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..0039c3e --- /dev/null +++ b/src/config.h @@ -0,0 +1,280 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define VERSION "2.57" + +#define FTABSIZ 150 /* max number of outstanding requests (default) */ +#define MAX_PROCS 20 /* max no children for TCP requests */ +#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */ +#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */ +#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */ +#define FORWARD_TEST 50 /* try all servers every 50 queries */ +#define FORWARD_TIME 20 /* or 20 seconds */ +#define RANDOM_SOCKS 64 /* max simultaneous random ports */ +#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */ +#define CACHESIZ 150 /* default cache size */ +#define MAXLEASES 1000 /* maximum number of DHCP leases */ +#define PING_WAIT 3 /* wait for ping address-in-use test */ +#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */ +#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */ +#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */ +#define SMALLDNAME 40 /* most domain names are smaller than this */ +#define HOSTSFILE "/etc/hosts" +#define ETHERSFILE "/etc/ethers" +#ifdef __uClinux__ +# define RESOLVFILE "/etc/config/resolv.conf" +#else +# define RESOLVFILE "/etc/resolv.conf" +#endif +#define RUNFILE "/var/run/dnsmasq.pid" + +#ifndef LEASEFILE +# if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__) +# define LEASEFILE "/var/db/dnsmasq.leases" +# elif defined(__sun__) || defined (__sun) +# define LEASEFILE "/var/cache/dnsmasq.leases" +# elif defined(__ANDROID__) +# define LEASEFILE "/data/misc/dhcp/dnsmasq.leases" +# else +# define LEASEFILE "/var/lib/misc/dnsmasq.leases" +# endif +#endif + +#ifndef CONFFILE +# if defined(__FreeBSD__) +# define CONFFILE "/usr/local/etc/dnsmasq.conf" +# else +# define CONFFILE "/etc/dnsmasq.conf" +# endif +#endif + +#define DEFLEASE 3600 /* default lease time, 1 hour */ +#define CHUSER "nobody" +#define CHGRP "dip" +#define NAMESERVER_PORT 53 +#define DHCP_SERVER_PORT 67 +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_ALTPORT 1067 +#define DHCP_CLIENT_ALTPORT 1068 +#define PXE_PORT 4011 +#define TFTP_PORT 69 +#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */ +#define LOG_MAX 5 /* log-queue length */ +#define RANDFILE "/dev/urandom" +#define DAD_WAIT 20 /* retry binding IPv6 sockets for this long */ +#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */ + +/* DBUS interface specifics */ +#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" +#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq" + +/* Follows system specific switches. If you run on a + new system, you may want to edit these. + May replace this with Autoconf one day. + +HAVE_LINUX_NETWORK +HAVE_BSD_NETWORK +HAVE_SOLARIS_NETWORK + define exactly one of these to alter interaction with kernel networking. + +HAVE_BROKEN_RTC + define this on embedded systems which don't have an RTC + which keeps time over reboots. Causes dnsmasq to use uptime + for timing, and keep lease lengths rather than expiry times + in its leases file. This also make dnsmasq "flash disk friendly". + Normally, dnsmasq tries very hard to keep the on-disk leases file + up-to-date: rewriting it after every renewal. When HAVE_BROKEN_RTC + is in effect, the lease file is only written when a new lease is + created, or an old one destroyed. (Because those are the only times + it changes.) This vastly reduces the number of file writes, and makes + it viable to keep the lease file on a flash filesystem. + NOTE: when enabling or disabling this, be sure to delete any old + leases file, otherwise dnsmasq may get very confused. + +HAVE_TFTP + define this to get dnsmasq's built-in TFTP server. + +HAVE_DHCP + define this to get dnsmasq's DHCP server. + +HAVE_SCRIPT + define this to get the ability to call scripts on lease-change + +HAVE_GETOPT_LONG + define this if you have GNU libc or GNU getopt. + +HAVE_ARC4RANDOM + define this if you have arc4random() to get better security from DNS spoofs + by using really random ids (OpenBSD) + +HAVE_SOCKADDR_SA_LEN + define this if struct sockaddr has sa_len field (*BSD) + +HAVE_DBUS + define this if you want to link against libdbus, and have dnsmasq + support some methods to allow (re)configuration of the upstream DNS + servers via DBus. + +HAVE_IDN + define this if you want international domain name support. + NOTE: for backwards compatibility, IDN support is automatically + included when internationalisation support is built, using the + *-i18n makefile targets, even if HAVE_IDN is not explicitly set. + +NOTES: + For Linux you should define + HAVE_LINUX_NETWORK + HAVE_GETOPT_LONG + you should NOT define + HAVE_ARC4RANDOM + HAVE_SOCKADDR_SA_LEN + + For *BSD systems you should define + HAVE_BSD_NETWORK + HAVE_SOCKADDR_SA_LEN + and you MAY define + HAVE_ARC4RANDOM - OpenBSD and FreeBSD and NetBSD version 2.0 or later + HAVE_GETOPT_LONG - NetBSD, later FreeBSD + (FreeBSD and OpenBSD only if you link GNU getopt) + +*/ + +/* platform independent options- uncomment to enable */ +#define HAVE_DHCP +#define HAVE_TFTP +#define HAVE_SCRIPT +/* #define HAVE_BROKEN_RTC */ +#define HAVE_DBUS +/* #define HAVE_IDN */ + +/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */ +#ifdef NO_TFTP +#undef HAVE_TFTP +#endif + +/* Allow DHCP to be disabled with COPTS=-DNO_DHCP */ +#ifdef NO_DHCP +#undef HAVE_DHCP +#endif + +/* Allow scripts to be disabled with COPTS=-DNO_SCRIPT */ +#ifdef NO_SCRIPT +#undef HAVE_SCRIPT +#endif + + + +/* platform dependent options. */ + +/* Must preceed __linux__ since uClinux defines __linux__ too. */ +#if defined(__uClinux__) +#define HAVE_LINUX_NETWORK +#define HAVE_GETOPT_LONG +#undef HAVE_ARC4RANDOM +#undef HAVE_SOCKADDR_SA_LEN +/* Never use fork() on uClinux. Note that this is subtly different from the + --keep-in-foreground option, since it also suppresses forking new + processes for TCP connections and disables the call-a-script on leasechange + system. It's intended for use on MMU-less kernels. */ +#define NO_FORK + +#elif defined(__UCLIBC__) +#define HAVE_LINUX_NETWORK +#if defined(__UCLIBC_HAS_GNU_GETOPT__) || \ + ((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21)) +# define HAVE_GETOPT_LONG +#endif +#undef HAVE_ARC4RANDOM +#undef HAVE_SOCKADDR_SA_LEN +#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__) +# define NO_FORK +#endif +#if defined(__UCLIBC_HAS_IPV6__) +# ifndef IPV6_V6ONLY +# define IPV6_V6ONLY 26 +# endif +#endif + +/* This is for glibc 2.x */ +#elif defined(__linux__) +#define HAVE_LINUX_NETWORK +#define HAVE_GETOPT_LONG +#undef HAVE_ARC4RANDOM +#undef HAVE_SOCKADDR_SA_LEN + +#elif defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD_kernel__) +#define HAVE_BSD_NETWORK +/* Later verions of FreeBSD have getopt_long() */ +#if defined(optional_argument) && defined(required_argument) +# define HAVE_GETOPT_LONG +#endif +#if !defined(__FreeBSD_kernel__) +# define HAVE_ARC4RANDOM +#endif +#define HAVE_SOCKADDR_SA_LEN + +#elif defined(__APPLE__) +#define HAVE_BSD_NETWORK +#define HAVE_GETOPT_LONG +#define HAVE_ARC4RANDOM +#define HAVE_SOCKADDR_SA_LEN +/* Define before sys/socket.h is included so we get socklen_t */ +#define _BSD_SOCKLEN_T_ + +#elif defined(__NetBSD__) +#define HAVE_BSD_NETWORK +#define HAVE_GETOPT_LONG +#undef HAVE_ARC4RANDOM +#define HAVE_SOCKADDR_SA_LEN + +#elif defined(__sun) || defined(__sun__) +#define HAVE_SOLARIS_NETWORK +#define HAVE_GETOPT_LONG +#undef HAVE_ARC4RANDOM +#undef HAVE_SOCKADDR_SA_LEN +#define ETHER_ADDR_LEN 6 + +#endif + +/* Decide if we're going to support IPv6 */ +/* IPv6 can be forced off with "make COPTS=-DNO_IPV6" */ +/* We assume that systems which don't have IPv6 + headers don't have ntop and pton either */ + +#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) && !defined(NO_IPV6) +# define HAVE_IPV6 +# define ADDRSTRLEN INET6_ADDRSTRLEN +# if defined(SOL_IPV6) +# define IPV6_LEVEL SOL_IPV6 +# else +# define IPV6_LEVEL IPPROTO_IPV6 +# endif +#elif defined(INET_ADDRSTRLEN) +# undef HAVE_IPV6 +# define ADDRSTRLEN INET_ADDRSTRLEN +#else +# undef HAVE_IPV6 +# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */ +#endif + +/* Can't do scripts without fork */ +#ifdef NOFORK +# undef HAVE_SCRIPT +#endif + diff --git a/src/dbus.c b/src/dbus.c new file mode 100644 index 0000000..5cb43fb --- /dev/null +++ b/src/dbus.c @@ -0,0 +1,440 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#ifdef HAVE_DBUS + +#include <dbus/dbus.h> + +const char* introspection_xml = +"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" +"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" +"<node name=\"" DNSMASQ_PATH "\">\n" +" <interface name=\"org.freedesktop.DBus.Introspectable\">\n" +" <method name=\"Introspect\">\n" +" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n" +" </method>\n" +" </interface>\n" +" <interface name=\"" DNSMASQ_SERVICE "\">\n" +" <method name=\"ClearCache\">\n" +" </method>\n" +" <method name=\"GetVersion\">\n" +" <arg name=\"version\" direction=\"out\" type=\"s\"/>\n" +" </method>\n" +" <method name=\"SetServers\">\n" +" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n" +" </method>\n" +" <signal name=\"DhcpLeaseAdded\">\n" +" <arg name=\"ipaddr\" type=\"s\"/>\n" +" <arg name=\"hwaddr\" type=\"s\"/>\n" +" <arg name=\"hostname\" type=\"s\"/>\n" +" </signal>\n" +" <signal name=\"DhcpLeaseDeleted\">\n" +" <arg name=\"ipaddr\" type=\"s\"/>\n" +" <arg name=\"hwaddr\" type=\"s\"/>\n" +" <arg name=\"hostname\" type=\"s\"/>\n" +" </signal>\n" +" <signal name=\"DhcpLeaseUpdated\">\n" +" <arg name=\"ipaddr\" type=\"s\"/>\n" +" <arg name=\"hwaddr\" type=\"s\"/>\n" +" <arg name=\"hostname\" type=\"s\"/>\n" +" </signal>\n" +" </interface>\n" +"</node>\n"; + +struct watch { + DBusWatch *watch; + struct watch *next; +}; + + +static dbus_bool_t add_watch(DBusWatch *watch, void *data) +{ + struct watch *w; + + for (w = daemon->watches; w; w = w->next) + if (w->watch == watch) + return TRUE; + + if (!(w = whine_malloc(sizeof(struct watch)))) + return FALSE; + + w->watch = watch; + w->next = daemon->watches; + daemon->watches = w; + + w = data; /* no warning */ + return TRUE; +} + +static void remove_watch(DBusWatch *watch, void *data) +{ + struct watch **up, *w; + + for (up = &(daemon->watches), w = daemon->watches; w; w = w->next) + if (w->watch == watch) + { + *up = w->next; + free(w); + } + else + up = &(w->next); + + w = data; /* no warning */ +} + +static void dbus_read_servers(DBusMessage *message) +{ + struct server *serv, *tmp, **up; + DBusMessageIter iter; + union mysockaddr addr, source_addr; + char *domain; + + dbus_message_iter_init(message, &iter); + + /* mark everything from DBUS */ + for (serv = daemon->servers; serv; serv = serv->next) + if (serv->flags & SERV_FROM_DBUS) + serv->flags |= SERV_MARK; + + while (1) + { + int skip = 0; + + if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32) + { + u32 a; + + dbus_message_iter_get_basic(&iter, &a); + dbus_message_iter_next (&iter); + +#ifdef HAVE_SOCKADDR_SA_LEN + source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in); +#endif + addr.in.sin_addr.s_addr = ntohl(a); + source_addr.in.sin_family = addr.in.sin_family = AF_INET; + addr.in.sin_port = htons(NAMESERVER_PORT); + source_addr.in.sin_addr.s_addr = INADDR_ANY; + source_addr.in.sin_port = htons(daemon->query_port); + } + else if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_BYTE) + { + unsigned char p[sizeof(struct in6_addr)]; + unsigned int i; + + skip = 1; + + for(i = 0; i < sizeof(struct in6_addr); i++) + { + dbus_message_iter_get_basic(&iter, &p[i]); + dbus_message_iter_next (&iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE) + break; + } + +#ifndef HAVE_IPV6 + my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support")); +#else + if (i == sizeof(struct in6_addr)-1) + { + memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr)); +#ifdef HAVE_SOCKADDR_SA_LEN + source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6); +#endif + source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6; + addr.in6.sin6_port = htons(NAMESERVER_PORT); + source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0; + source_addr.in6.sin6_scope_id = addr.in6.sin6_scope_id = 0; + source_addr.in6.sin6_addr = in6addr_any; + source_addr.in6.sin6_port = htons(daemon->query_port); + skip = 0; + } +#endif + } + else + /* At the end */ + break; + + do { + if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&iter, &domain); + dbus_message_iter_next (&iter); + } + else + domain = NULL; + + if (!skip) + { + /* See if this is already there, and unmark */ + for (serv = daemon->servers; serv; serv = serv->next) + if ((serv->flags & SERV_FROM_DBUS) && + (serv->flags & SERV_MARK)) + { + if (!(serv->flags & SERV_HAS_DOMAIN) && !domain) + { + serv->flags &= ~SERV_MARK; + break; + } + if ((serv->flags & SERV_HAS_DOMAIN) && + domain && + hostname_isequal(domain, serv->domain)) + { + serv->flags &= ~SERV_MARK; + break; + } + } + + if (!serv && (serv = whine_malloc(sizeof (struct server)))) + { + /* Not found, create a new one. */ + memset(serv, 0, sizeof(struct server)); + + if (domain) + serv->domain = whine_malloc(strlen(domain)+1); + + if (domain && !serv->domain) + { + free(serv); + serv = NULL; + } + else + { + serv->next = daemon->servers; + daemon->servers = serv; + serv->flags = SERV_FROM_DBUS; + if (domain) + { + strcpy(serv->domain, domain); + serv->flags |= SERV_HAS_DOMAIN; + } + } + } + + if (serv) + { + if (source_addr.in.sin_family == AF_INET && + addr.in.sin_addr.s_addr == 0 && + serv->domain) + serv->flags |= SERV_NO_ADDR; + else + { + serv->flags &= ~SERV_NO_ADDR; + serv->addr = addr; + serv->source_addr = source_addr; + } + } + } + } while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING); + } + + /* unlink and free anything still marked. */ + for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) + { + tmp = serv->next; + if (serv->flags & SERV_MARK) + { + server_gone(serv); + *up = serv->next; + free(serv); + } + else + up = &serv->next; + } + +} + +DBusHandlerResult message_handler(DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + char *method = (char *)dbus_message_get_member(message); + + if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) + { + DBusMessage *reply = dbus_message_new_method_return(message); + + dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + } + else if (strcmp(method, "GetVersion") == 0) + { + char *v = VERSION; + DBusMessage *reply = dbus_message_new_method_return(message); + + dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + } + else if (strcmp(method, "SetServers") == 0) + { + my_syslog(LOG_INFO, _("setting upstream servers from DBus")); + dbus_read_servers(message); + check_servers(); + } + else if (strcmp(method, "ClearCache") == 0) + clear_cache_and_reload(dnsmasq_time()); + else + return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + method = user_data; /* no warning */ + + return (DBUS_HANDLER_RESULT_HANDLED); + +} + + +/* returns NULL or error message, may fail silently if dbus daemon not yet up. */ +char *dbus_init(void) +{ + DBusConnection *connection = NULL; + DBusObjectPathVTable dnsmasq_vtable = {NULL, &message_handler, NULL, NULL, NULL, NULL }; + DBusError dbus_error; + DBusMessage *message; + + dbus_error_init (&dbus_error); + if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error))) + return NULL; + + dbus_connection_set_exit_on_disconnect(connection, FALSE); + dbus_connection_set_watch_functions(connection, add_watch, remove_watch, + NULL, NULL, NULL); + dbus_error_init (&dbus_error); + dbus_bus_request_name (connection, DNSMASQ_SERVICE, 0, &dbus_error); + if (dbus_error_is_set (&dbus_error)) + return (char *)dbus_error.message; + + if (!dbus_connection_register_object_path(connection, DNSMASQ_PATH, + &dnsmasq_vtable, NULL)) + return _("could not register a DBus message handler"); + + daemon->dbus = connection; + + if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up"))) + { + dbus_connection_send(connection, message, NULL); + dbus_message_unref(message); + } + + return NULL; +} + + +void set_dbus_listeners(int *maxfdp, + fd_set *rset, fd_set *wset, fd_set *eset) +{ + struct watch *w; + + for (w = daemon->watches; w; w = w->next) + if (dbus_watch_get_enabled(w->watch)) + { + unsigned int flags = dbus_watch_get_flags(w->watch); + int fd = dbus_watch_get_unix_fd(w->watch); + + bump_maxfd(fd, maxfdp); + + if (flags & DBUS_WATCH_READABLE) + FD_SET(fd, rset); + + if (flags & DBUS_WATCH_WRITABLE) + FD_SET(fd, wset); + + FD_SET(fd, eset); + } +} + +void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset) +{ + DBusConnection *connection = (DBusConnection *)daemon->dbus; + struct watch *w; + + for (w = daemon->watches; w; w = w->next) + if (dbus_watch_get_enabled(w->watch)) + { + unsigned int flags = 0; + int fd = dbus_watch_get_unix_fd(w->watch); + + if (FD_ISSET(fd, rset)) + flags |= DBUS_WATCH_READABLE; + + if (FD_ISSET(fd, wset)) + flags |= DBUS_WATCH_WRITABLE; + + if (FD_ISSET(fd, eset)) + flags |= DBUS_WATCH_ERROR; + + if (flags != 0) + dbus_watch_handle(w->watch, flags); + } + + if (connection) + { + dbus_connection_ref (connection); + while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS); + dbus_connection_unref (connection); + } +} + +#ifdef HAVE_DHCP +void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname) +{ + DBusConnection *connection = (DBusConnection *)daemon->dbus; + DBusMessage* message = NULL; + DBusMessageIter args; + char *action_str, *addr, *mac = daemon->namebuff; + unsigned char *p; + int i; + + if (!connection) + return; + + if (!hostname) + hostname = ""; + + p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len, + lease->hwaddr, lease->clid_len, lease->clid, &i); + print_mac(mac, p, i); + + if (action == ACTION_DEL) + action_str = "DhcpLeaseDeleted"; + else if (action == ACTION_ADD) + action_str = "DhcpLeaseAdded"; + else if (action == ACTION_OLD) + action_str = "DhcpLeaseUpdated"; + else if (action == ACTION_CONNECT) + action_str = "DhcpConnected"; + else + return; + + addr = inet_ntoa(lease->addr); + + if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str))) + return; + + dbus_message_iter_init_append(message, &args); + + if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &addr) && + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &mac) && + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &hostname)) + dbus_connection_send(connection, message, NULL); + + dbus_message_unref(message); +} +#endif + +#endif diff --git a/src/dhcp.c b/src/dhcp.c new file mode 100644 index 0000000..29ddf24 --- /dev/null +++ b/src/dhcp.c @@ -0,0 +1,1094 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#ifdef HAVE_DHCP + +struct iface_param { + struct in_addr relay, primary; + struct dhcp_context *current; + int ind; +}; + +static int complete_context(struct in_addr local, int if_index, + struct in_addr netmask, struct in_addr broadcast, void *vparam); + +static int make_fd(int port) +{ + int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + struct sockaddr_in saddr; + int oneopt = 1; +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) + int mtu = IP_PMTUDISC_DONT; +#endif + + if (fd == -1) + die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET); + + if (!fix_fd(fd) || +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) + setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 || +#endif +#if defined(HAVE_LINUX_NETWORK) + setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 || +#else + setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 || +#endif + setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1) + die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET); + + /* When bind-interfaces is set, there might be more than one dnmsasq + instance binding port 67. That's OK if they serve different networks. + Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */ + if (option_bool(OPT_NOWILD)) + { +#ifdef SO_REUSEPORT + int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt)); +#else + int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)); +#endif + if (rc == -1) + die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET); + } + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + saddr.sin_addr.s_addr = INADDR_ANY; +#ifdef HAVE_SOCKADDR_SA_LEN + saddr.sin_len = sizeof(struct sockaddr_in); +#endif + + if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in))) + die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET); + + return fd; +} + +void dhcp_init(void) +{ +#if defined(HAVE_BSD_NETWORK) + int oneopt = 1; +#endif + + daemon->dhcpfd = make_fd(daemon->dhcp_server_port); + if (daemon->enable_pxe) + daemon->pxefd = make_fd(PXE_PORT); + else + daemon->pxefd = -1; + +#if defined(HAVE_BSD_NETWORK) + /* When we're not using capabilities, we need to do this here before + we drop root. Also, set buffer size small, to avoid wasting + kernel buffers */ + + if (option_bool(OPT_NO_PING)) + daemon->dhcp_icmp_fd = -1; + else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 || + setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 ) + die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET); + + /* Make BPF raw send socket */ + init_bpf(); +#endif + + check_dhcp_hosts(1); + + daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet); + daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len); +} + +void dhcp_packet(time_t now, int pxe_fd) +{ + int fd = pxe_fd ? daemon->pxefd : daemon->dhcpfd; + struct dhcp_packet *mess; + struct dhcp_context *context; + struct iname *tmp; + struct ifreq ifr; + struct msghdr msg; + struct sockaddr_in dest; + struct cmsghdr *cmptr; + struct iovec iov; + ssize_t sz; + int iface_index = 0, unicast_dest = 0, is_inform = 0; + struct in_addr iface_addr, *addrp = NULL; + struct iface_param parm; +#ifdef HAVE_LINUX_NETWORK + struct arpreq arp_req; +#endif + + union { + struct cmsghdr align; /* this ensures alignment */ +#if defined(HAVE_LINUX_NETWORK) + char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; +#elif defined(HAVE_SOLARIS_NETWORK) + char control[CMSG_SPACE(sizeof(unsigned int))]; +#elif defined(HAVE_BSD_NETWORK) + char control[CMSG_SPACE(sizeof(struct sockaddr_dl))]; +#endif + } control_u; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &daemon->dhcp_packet; + msg.msg_iovlen = 1; + + while (1) + { + msg.msg_flags = 0; + while ((sz = recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR); + + if (sz == -1) + return; + + if (!(msg.msg_flags & MSG_TRUNC)) + break; + + /* Very new Linux kernels return the actual size needed, + older ones always return truncated size */ + if ((size_t)sz == daemon->dhcp_packet.iov_len) + { + if (!expand_buf(&daemon->dhcp_packet, sz + 100)) + return; + } + else + { + expand_buf(&daemon->dhcp_packet, sz); + break; + } + } + + /* expand_buf may have moved buffer */ + mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base; + msg.msg_controllen = sizeof(control_u); + msg.msg_control = control_u.control; + msg.msg_flags = 0; + msg.msg_name = &dest; + msg.msg_namelen = sizeof(dest); + + while ((sz = recvmsg(fd, &msg, 0)) == -1 && errno == EINTR); + + if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options))) + return; + +#if defined (HAVE_LINUX_NETWORK) + if (msg.msg_controllen >= sizeof(struct cmsghdr)) + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) + { + union { + unsigned char *c; + struct in_pktinfo *p; + } p; + p.c = CMSG_DATA(cmptr); + iface_index = p.p->ipi_ifindex; + if (p.p->ipi_addr.s_addr != INADDR_BROADCAST) + unicast_dest = 1; + } + +#elif defined(HAVE_BSD_NETWORK) + if (msg.msg_controllen >= sizeof(struct cmsghdr)) + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) + { + union { + unsigned char *c; + struct sockaddr_dl *s; + } p; + p.c = CMSG_DATA(cmptr); + iface_index = p.s->sdl_index; + } + +#elif defined(HAVE_SOLARIS_NETWORK) + if (msg.msg_controllen >= sizeof(struct cmsghdr)) + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) + { + union { + unsigned char *c; + unsigned int *i; + } p; + p.c = CMSG_DATA(cmptr); + iface_index = *(p.i); + } +#endif + + if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name)) + return; + +#ifdef HAVE_LINUX_NETWORK + /* ARP fiddling uses original interface even if we pretend to use a different one. */ + strncpy(arp_req.arp_dev, ifr.ifr_name, 16); +#endif + +#ifdef MSG_BCAST + /* OpenBSD tells us when a packet was broadcast */ + if (!(msg.msg_flags & MSG_BCAST)) + unicast_dest = 1; +#endif + + ifr.ifr_addr.sa_family = AF_INET; + if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 ) + { + addrp = &iface_addr; + iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + } + + if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index)) + return; + + for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) + if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) + return; + + /* weird libvirt-inspired access control */ + for (context = daemon->dhcp; context; context = context->next) + if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0) + break; + + if (!context) + return; + + /* unlinked contexts are marked by context->current == context */ + for (context = daemon->dhcp; context; context = context->next) + context->current = context; + + parm.relay = mess->giaddr; + parm.primary = iface_addr; + parm.current = NULL; + parm.ind = iface_index; + + /* interface may have been changed by alias in iface_check, make sure it gets priority in case + there is more than one address on the interface in the same subnet */ + if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1) + { + my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name); + return; + } + else + { + iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + if (ioctl(daemon->dhcpfd, SIOCGIFNETMASK, &ifr) != -1) + { + struct in_addr netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + if (ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) != -1) + { + struct in_addr broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + complete_context(iface_addr, iface_index, netmask, broadcast, &parm); + } + } + } + + if (!iface_enumerate(AF_INET, &parm, complete_context)) + return; + lease_prune(NULL, now); /* lose any expired leases */ + iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, + now, unicast_dest, &is_inform, pxe_fd); + lease_update_file(now); + lease_update_dns(); + + if (iov.iov_len == 0) + return; + + msg.msg_name = &dest; + msg.msg_namelen = sizeof(dest); + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_iov = &iov; + iov.iov_base = daemon->dhcp_packet.iov_base; + + /* packet buffer may have moved */ + mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base; + +#ifdef HAVE_SOCKADDR_SA_LEN + dest.sin_len = sizeof(struct sockaddr_in); +#endif + + if (pxe_fd) + { + if (mess->ciaddr.s_addr != 0) + dest.sin_addr = mess->ciaddr; + } + else if (mess->giaddr.s_addr) + { + /* Send to BOOTP relay */ + dest.sin_port = htons(daemon->dhcp_server_port); + dest.sin_addr = mess->giaddr; + } + else if (mess->ciaddr.s_addr) + { + /* If the client's idea of its own address tallys with + the source address in the request packet, we believe the + source port too, and send back to that. If we're replying + to a DHCPINFORM, trust the source address always. */ + if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) || + dest.sin_port == 0 || dest.sin_addr.s_addr == 0) + { + dest.sin_port = htons(daemon->dhcp_client_port); + dest.sin_addr = mess->ciaddr; + } + } +#if defined(HAVE_LINUX_NETWORK) + else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 || + mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0) + { + /* broadcast to 255.255.255.255 (or mac address invalid) */ + struct in_pktinfo *pkt; + msg.msg_control = control_u.control; + msg.msg_controllen = sizeof(control_u); + cmptr = CMSG_FIRSTHDR(&msg); + pkt = (struct in_pktinfo *)CMSG_DATA(cmptr); + pkt->ipi_ifindex = iface_index; + pkt->ipi_spec_dst.s_addr = 0; + msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + cmptr->cmsg_level = SOL_IP; + cmptr->cmsg_type = IP_PKTINFO; + dest.sin_addr.s_addr = INADDR_BROADCAST; + dest.sin_port = htons(daemon->dhcp_client_port); + } + else + { + /* unicast to unconfigured client. Inject mac address direct into ARP cache. + struct sockaddr limits size to 14 bytes. */ + dest.sin_addr = mess->yiaddr; + dest.sin_port = htons(daemon->dhcp_client_port); + memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in)); + arp_req.arp_ha.sa_family = mess->htype; + memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen); + /* interface name already copied in */ + arp_req.arp_flags = ATF_COM; + ioctl(daemon->dhcpfd, SIOCSARP, &arp_req); + } +#elif defined(HAVE_SOLARIS_NETWORK) + else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER) + { + /* broadcast to 255.255.255.255 (or mac address invalid) */ + dest.sin_addr.s_addr = INADDR_BROADCAST; + dest.sin_port = htons(daemon->dhcp_client_port); + /* note that we don't specify the interface here: that's done by the + IP_BOUND_IF sockopt lower down. */ + } + else + { + /* unicast to unconfigured client. Inject mac address direct into ARP cache. + Note that this only works for ethernet on solaris, because we use SIOCSARP + and not SIOCSXARP, which would be perfect, except that it returns ENXIO + mysteriously. Bah. Fall back to broadcast for other net types. */ + struct arpreq req; + dest.sin_addr = mess->yiaddr; + dest.sin_port = htons(daemon->dhcp_client_port); + *((struct sockaddr_in *)&req.arp_pa) = dest; + req.arp_ha.sa_family = AF_UNSPEC; + memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen); + req.arp_flags = ATF_COM; + ioctl(daemon->dhcpfd, SIOCSARP, &req); + } +#elif defined(HAVE_BSD_NETWORK) + else + { + send_via_bpf(mess, iov.iov_len, iface_addr, &ifr); + return; + } +#endif + +#ifdef HAVE_SOLARIS_NETWORK + setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index)); +#endif + + while(sendmsg(fd, &msg, 0) == -1 && retry_send()); +} + +/* This is a complex routine: it gets called with each (address,netmask,broadcast) triple + of each interface (and any relay address) and does the following things: + + 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived. + 2) Fills in any netmask and broadcast addresses which have not been explicitly configured. + 3) Fills in local (this host) and router (this host or relay) addresses. + 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current. + + Note that the current chain may be superceded later for configured hosts or those coming via gateways. */ + +static int complete_context(struct in_addr local, int if_index, + struct in_addr netmask, struct in_addr broadcast, void *vparam) +{ + struct dhcp_context *context; + struct iface_param *param = vparam; + + for (context = daemon->dhcp; context; context = context->next) + { + if (!(context->flags & CONTEXT_NETMASK) && + (is_same_net(local, context->start, netmask) || + is_same_net(local, context->end, netmask))) + { + if (context->netmask.s_addr != netmask.s_addr && + !(is_same_net(local, context->start, netmask) && + is_same_net(local, context->end, netmask))) + { + strcpy(daemon->dhcp_buff, inet_ntoa(context->start)); + strcpy(daemon->dhcp_buff2, inet_ntoa(context->end)); + my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"), + daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask)); + } + context->netmask = netmask; + } + + if (context->netmask.s_addr) + { + if (is_same_net(local, context->start, context->netmask) && + is_same_net(local, context->end, context->netmask)) + { + /* link it onto the current chain if we've not seen it before */ + if (if_index == param->ind && context->current == context) + { + context->router = local; + context->local = local; + context->current = param->current; + param->current = context; + } + + if (!(context->flags & CONTEXT_BRDCAST)) + { + if (is_same_net(broadcast, context->start, context->netmask)) + context->broadcast = broadcast; + else + context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr; + } + } + else if (param->relay.s_addr && is_same_net(param->relay, context->start, context->netmask)) + { + context->router = param->relay; + context->local = param->primary; + /* fill in missing broadcast addresses for relayed ranges */ + if (!(context->flags & CONTEXT_BRDCAST)) + context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr; + } + + } + } + + return 1; +} + +struct dhcp_context *address_available(struct dhcp_context *context, + struct in_addr taddr, + struct dhcp_netid *netids) +{ + /* Check is an address is OK for this network, check all + possible ranges. Make sure that the address isn't in use + by the server itself. */ + + unsigned int start, end, addr = ntohl(taddr.s_addr); + struct dhcp_context *tmp; + + for (tmp = context; tmp; tmp = tmp->current) + if (taddr.s_addr == context->router.s_addr) + return NULL; + + for (tmp = context; tmp; tmp = tmp->current) + { + start = ntohl(tmp->start.s_addr); + end = ntohl(tmp->end.s_addr); + + if (!(tmp->flags & CONTEXT_STATIC) && + addr >= start && + addr <= end && + match_netid(tmp->filter, netids, 1)) + return tmp; + } + + return NULL; +} + +struct dhcp_context *narrow_context(struct dhcp_context *context, + struct in_addr taddr, + struct dhcp_netid *netids) +{ + /* We start of with a set of possible contexts, all on the current physical interface. + These are chained on ->current. + Here we have an address, and return the actual context correponding to that + address. Note that none may fit, if the address came a dhcp-host and is outside + any dhcp-range. In that case we return a static range if possible, or failing that, + any context on the correct subnet. (If there's more than one, this is a dodgy + configuration: maybe there should be a warning.) */ + + struct dhcp_context *tmp; + + if (!(tmp = address_available(context, taddr, netids))) + { + for (tmp = context; tmp; tmp = tmp->current) + if (match_netid(tmp->filter, netids, 1) && + is_same_net(taddr, tmp->start, tmp->netmask) && + (tmp->flags & CONTEXT_STATIC)) + break; + + if (!tmp) + for (tmp = context; tmp; tmp = tmp->current) + if (match_netid(tmp->filter, netids, 1) && + is_same_net(taddr, tmp->start, tmp->netmask)) + break; + } + + /* Only one context allowed now */ + if (tmp) + tmp->current = NULL; + + return tmp; +} + +struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr) +{ + struct dhcp_config *config; + + for (config = configs; config; config = config->next) + if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr) + return config; + + return NULL; +} + +/* Is every member of check matched by a member of pool? + If tagnotneeded, untagged is OK */ +int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded) +{ + struct dhcp_netid *tmp1; + + if (!check && !tagnotneeded) + return 0; + + for (; check; check = check->next) + { + /* '#' for not is for backwards compat. */ + if (check->net[0] != '!' && check->net[0] != '#') + { + for (tmp1 = pool; tmp1; tmp1 = tmp1->next) + if (strcmp(check->net, tmp1->net) == 0) + break; + if (!tmp1) + return 0; + } + else + for (tmp1 = pool; tmp1; tmp1 = tmp1->next) + if (strcmp((check->net)+1, tmp1->net) == 0) + return 0; + } + return 1; +} + +struct dhcp_netid *run_tag_if(struct dhcp_netid *tags) +{ + struct tag_if *exprs; + struct dhcp_netid_list *list; + + for (exprs = daemon->tag_if; exprs; exprs = exprs->next) + if (match_netid(exprs->tag, tags, 1)) + for (list = exprs->set; list; list = list->next) + { + list->list->next = tags; + tags = list->list; + } + + return tags; +} + +int address_allocate(struct dhcp_context *context, + struct in_addr *addrp, unsigned char *hwaddr, int hw_len, + struct dhcp_netid *netids, time_t now) +{ + /* Find a free address: exclude anything in use and anything allocated to + a particular hwaddr/clientid/hostname in our configuration. + Try to return from contexts which match netids first. */ + + struct in_addr start, addr; + struct dhcp_context *c, *d; + int i, pass; + unsigned int j; + + /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good + dispersal even with similarly-valued "strings". */ + for (j = 0, i = 0; i < hw_len; i++) + j += hwaddr[i] + (j << 6) + (j << 16) - j; + + for (pass = 0; pass <= 1; pass++) + for (c = context; c; c = c->current) + if (c->flags & CONTEXT_STATIC) + continue; + else if (!match_netid(c->filter, netids, pass)) + continue; + else + { + /* pick a seed based on hwaddr then iterate until we find a free address. */ + start.s_addr = addr.s_addr = + htonl(ntohl(c->start.s_addr) + + ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr)))); + + do { + /* eliminate addresses in use by the server. */ + for (d = context; d; d = d->current) + if (addr.s_addr == d->router.s_addr) + break; + + /* Addresses which end in .255 and .0 are broken in Windows even when using + supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0 + then 192.168.0.255 is a valid IP address, but not for Windows as it's + in the class C range. See KB281579. We therefore don't allocate these + addresses to avoid hard-to-diagnose problems. Thanks Bill. */ + if (!d && + !lease_find_by_addr(addr) && + !config_find_by_address(daemon->dhcp_conf, addr) && + (!IN_CLASSC(ntohl(addr.s_addr)) || + ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0)))) + { + struct ping_result *r, *victim = NULL; + int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/ + ((float)PING_WAIT))); + + *addrp = addr; + + if (option_bool(OPT_NO_PING)) + return 1; + + /* check if we failed to ping addr sometime in the last + PING_CACHE_TIME seconds. If so, assume the same situation still exists. + This avoids problems when a stupid client bangs + on us repeatedly. As a final check, if we did more + than 60% of the possible ping checks in the last + PING_CACHE_TIME, we are in high-load mode, so don't do any more. */ + for (count = 0, r = daemon->ping_results; r; r = r->next) + if (difftime(now, r->time) > (float)PING_CACHE_TIME) + victim = r; /* old record */ + else if (++count == max || r->addr.s_addr == addr.s_addr) + return 1; + + if (icmp_ping(addr)) + /* address in use: perturb address selection so that we are + less likely to try this address again. */ + c->addr_epoch++; + else + { + /* at this point victim may hold an expired record */ + if (!victim) + { + if ((victim = whine_malloc(sizeof(struct ping_result)))) + { + victim->next = daemon->ping_results; + daemon->ping_results = victim; + } + } + + /* record that this address is OK for 30s + without more ping checks */ + if (victim) + { + victim->addr = addr; + victim->time = now; + } + return 1; + } + } + + addr.s_addr = htonl(ntohl(addr.s_addr) + 1); + + if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1)) + addr = c->start; + + } while (addr.s_addr != start.s_addr); + } + return 0; +} + +static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config) +{ + if (!context) /* called via find_config() from lease_update_from_configs() */ + return 1; + if (!(config->flags & CONFIG_ADDR)) + return 1; + for (; context; context = context->current) + if (is_same_net(config->addr, context->start, context->netmask)) + return 1; + + return 0; +} + +int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type) +{ + struct hwaddr_config *conf_addr; + + for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next) + if (conf_addr->wildcard_mask == 0 && + conf_addr->hwaddr_len == len && + (conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) && + memcmp(conf_addr->hwaddr, hwaddr, len) == 0) + return 1; + + return 0; +} + +struct dhcp_config *find_config(struct dhcp_config *configs, + struct dhcp_context *context, + unsigned char *clid, int clid_len, + unsigned char *hwaddr, int hw_len, + int hw_type, char *hostname) +{ + int count, new; + struct dhcp_config *config, *candidate; + struct hwaddr_config *conf_addr; + + if (clid) + for (config = configs; config; config = config->next) + if (config->flags & CONFIG_CLID) + { + if (config->clid_len == clid_len && + memcmp(config->clid, clid, clid_len) == 0 && + is_addr_in_context(context, config)) + return config; + + /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and + cope with that here */ + if (*clid == 0 && config->clid_len == clid_len-1 && + memcmp(config->clid, clid+1, clid_len-1) == 0 && + is_addr_in_context(context, config)) + return config; + } + + + for (config = configs; config; config = config->next) + if (config_has_mac(config, hwaddr, hw_len, hw_type) && + is_addr_in_context(context, config)) + return config; + + if (hostname && context) + for (config = configs; config; config = config->next) + if ((config->flags & CONFIG_NAME) && + hostname_isequal(config->hostname, hostname) && + is_addr_in_context(context, config)) + return config; + + /* use match with fewest wildcast octets */ + for (candidate = NULL, count = 0, config = configs; config; config = config->next) + if (is_addr_in_context(context, config)) + for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next) + if (conf_addr->wildcard_mask != 0 && + conf_addr->hwaddr_len == hw_len && + (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) && + (new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count) + { + count = new; + candidate = config; + } + + return candidate; +} + +void dhcp_read_ethers(void) +{ + FILE *f = fopen(ETHERSFILE, "r"); + unsigned int flags; + char *buff = daemon->namebuff; + char *ip, *cp; + struct in_addr addr; + unsigned char hwaddr[ETHER_ADDR_LEN]; + struct dhcp_config **up, *tmp; + struct dhcp_config *config; + int count = 0, lineno = 0; + + addr.s_addr = 0; /* eliminate warning */ + + if (!f) + { + my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno)); + return; + } + + /* This can be called again on SIGHUP, so remove entries created last time round. */ + for (up = &daemon->dhcp_conf, config = daemon->dhcp_conf; config; config = tmp) + { + tmp = config->next; + if (config->flags & CONFIG_FROM_ETHERS) + { + *up = tmp; + /* cannot have a clid */ + if (config->flags & CONFIG_NAME) + free(config->hostname); + free(config->hwaddr); + free(config); + } + else + up = &config->next; + } + + while (fgets(buff, MAXDNAME, f)) + { + char *host = NULL; + + lineno++; + + while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1])) + buff[strlen(buff)-1] = 0; + + if ((*buff == '#') || (*buff == '+') || (*buff == 0)) + continue; + + for (ip = buff; *ip && !isspace((int)*ip); ip++); + for(; *ip && isspace((int)*ip); ip++) + *ip = 0; + if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN) + { + my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno); + continue; + } + + /* check for name or dotted-quad */ + for (cp = ip; *cp; cp++) + if (!(*cp == '.' || (*cp >='0' && *cp <= '9'))) + break; + + if (!*cp) + { + if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1) + { + my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno); + continue; + } + + flags = CONFIG_ADDR; + + for (config = daemon->dhcp_conf; config; config = config->next) + if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr) + break; + } + else + { + int nomem; + if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host)) + { + if (!nomem) + my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno); + free(host); + continue; + } + + flags = CONFIG_NAME; + + for (config = daemon->dhcp_conf; config; config = config->next) + if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host)) + break; + } + + if (config && (config->flags & CONFIG_FROM_ETHERS)) + { + my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno); + continue; + } + + if (!config) + { + for (config = daemon->dhcp_conf; config; config = config->next) + { + struct hwaddr_config *conf_addr = config->hwaddr; + if (conf_addr && + conf_addr->next == NULL && + conf_addr->wildcard_mask == 0 && + conf_addr->hwaddr_len == ETHER_ADDR_LEN && + (conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) && + memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0) + break; + } + + if (!config) + { + if (!(config = whine_malloc(sizeof(struct dhcp_config)))) + continue; + config->flags = CONFIG_FROM_ETHERS; + config->hwaddr = NULL; + config->domain = NULL; + config->netid = NULL; + config->next = daemon->dhcp_conf; + daemon->dhcp_conf = config; + } + + config->flags |= flags; + + if (flags & CONFIG_NAME) + { + config->hostname = host; + host = NULL; + } + + if (flags & CONFIG_ADDR) + config->addr = addr; + } + + config->flags |= CONFIG_NOCLID; + if (!config->hwaddr) + config->hwaddr = whine_malloc(sizeof(struct hwaddr_config)); + if (config->hwaddr) + { + memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN); + config->hwaddr->hwaddr_len = ETHER_ADDR_LEN; + config->hwaddr->hwaddr_type = ARPHRD_ETHER; + config->hwaddr->wildcard_mask = 0; + config->hwaddr->next = NULL; + } + count++; + + free(host); + + } + + fclose(f); + + my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count); +} + +void check_dhcp_hosts(int fatal) +{ + /* If the same IP appears in more than one host config, then DISCOVER + for one of the hosts will get the address, but REQUEST will be NAKed, + since the address is reserved by the other one -> protocol loop. + Also check that FQDNs match the domain we are using. */ + + struct dhcp_config *configs, *cp; + + for (configs = daemon->dhcp_conf; configs; configs = configs->next) + { + char *domain; + + if ((configs->flags & DHOPT_BANK) || fatal) + { + for (cp = configs->next; cp; cp = cp->next) + if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr) + { + if (fatal) + die(_("duplicate IP address %s in dhcp-config directive."), + inet_ntoa(cp->addr), EC_BADCONF); + else + my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."), + inet_ntoa(cp->addr), daemon->dhcp_hosts_file); + configs->flags &= ~CONFIG_ADDR; + } + + /* split off domain part */ + if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname))) + configs->domain = domain; + } + } +} + +void dhcp_update_configs(struct dhcp_config *configs) +{ + /* Some people like to keep all static IP addresses in /etc/hosts. + This goes through /etc/hosts and sets static addresses for any DHCP config + records which don't have an address and whose name matches. + We take care to maintain the invariant that any IP address can appear + in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP, + restore the status-quo ante first. */ + + struct dhcp_config *config; + struct crec *crec; + + for (config = configs; config; config = config->next) + if (config->flags & CONFIG_ADDR_HOSTS) + config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS); + + + if (daemon->port != 0) + for (config = configs; config; config = config->next) + if (!(config->flags & CONFIG_ADDR) && + (config->flags & CONFIG_NAME) && + (crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) && + (crec->flags & F_HOSTS)) + { + if (cache_find_by_name(crec, config->hostname, 0, F_IPV4)) + { + /* use primary (first) address */ + while (crec && !(crec->flags & F_REVERSE)) + crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4); + if (!crec) + continue; /* should be never */ + my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"), + config->hostname, inet_ntoa(crec->addr.addr.addr.addr4)); + } + + if (config_find_by_address(configs, crec->addr.addr.addr.addr4)) + my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"), + inet_ntoa(crec->addr.addr.addr.addr4), config->hostname); + else + { + config->addr = crec->addr.addr.addr.addr4; + config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS; + } + } +} + +/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts + for this address. If it has a domain part, that must match the set domain and + it gets stripped. The set of legal domain names is bigger than the set of legal hostnames + so check here that the domain name is legal as a hostname. + NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */ +char *host_from_dns(struct in_addr addr) +{ + struct crec *lookup; + + if (daemon->port == 0) + return NULL; /* DNS disabled. */ + + lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4); + + if (lookup && (lookup->flags & F_HOSTS)) + { + char *dot, *hostname = cache_get_name(lookup); + dot = strchr(hostname, '.'); + + if (dot && strlen(dot+1) != 0) + { + char *d2 = get_domain(addr); + if (!d2 || !hostname_isequal(dot+1, d2)) + return NULL; /* wrong domain */ + } + + if (!legal_hostname(hostname)) + return NULL; + + strncpy(daemon->dhcp_buff, hostname, 256); + daemon->dhcp_buff[255] = 0; + strip_hostname(daemon->dhcp_buff); + + return daemon->dhcp_buff; + } + + return NULL; +} + +/* return domain or NULL if none. */ +char *strip_hostname(char *hostname) +{ + char *dot = strchr(hostname, '.'); + + if (!dot) + return NULL; + + *dot = 0; /* truncate */ + if (strlen(dot+1) != 0) + return dot+1; + + return NULL; +} + +#endif + diff --git a/src/dhcp_protocol.h b/src/dhcp_protocol.h new file mode 100644 index 0000000..e09cad8 --- /dev/null +++ b/src/dhcp_protocol.h @@ -0,0 +1,91 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define BOOTREQUEST 1 +#define BOOTREPLY 2 +#define DHCP_COOKIE 0x63825363 + +/* The Linux in-kernel DHCP client silently ignores any packet + smaller than this. Sigh........... */ +#define MIN_PACKETSZ 300 + +#define OPTION_PAD 0 +#define OPTION_NETMASK 1 +#define OPTION_ROUTER 3 +#define OPTION_DNSSERVER 6 +#define OPTION_HOSTNAME 12 +#define OPTION_DOMAINNAME 15 +#define OPTION_BROADCAST 28 +#define OPTION_VENDOR_CLASS_OPT 43 +#define OPTION_REQUESTED_IP 50 +#define OPTION_LEASE_TIME 51 +#define OPTION_OVERLOAD 52 +#define OPTION_MESSAGE_TYPE 53 +#define OPTION_SERVER_IDENTIFIER 54 +#define OPTION_REQUESTED_OPTIONS 55 +#define OPTION_MESSAGE 56 +#define OPTION_MAXMESSAGE 57 +#define OPTION_T1 58 +#define OPTION_T2 59 +#define OPTION_VENDOR_ID 60 +#define OPTION_CLIENT_ID 61 +#define OPTION_SNAME 66 +#define OPTION_FILENAME 67 +#define OPTION_USER_CLASS 77 +#define OPTION_CLIENT_FQDN 81 +#define OPTION_AGENT_ID 82 +#define OPTION_ARCH 93 +#define OPTION_PXE_UUID 97 +#define OPTION_SUBNET_SELECT 118 +#define OPTION_DOMAIN_SEARCH 119 +#define OPTION_SIP_SERVER 120 +#define OPTION_VENDOR_IDENT 124 +#define OPTION_VENDOR_IDENT_OPT 125 +#define OPTION_END 255 + +#define SUBOPT_CIRCUIT_ID 1 +#define SUBOPT_REMOTE_ID 2 +#define SUBOPT_SUBNET_SELECT 5 /* RFC 3527 */ +#define SUBOPT_SUBSCR_ID 6 /* RFC 3393 */ +#define SUBOPT_SERVER_OR 11 /* RFC 5107 */ + +#define SUBOPT_PXE_BOOT_ITEM 71 /* PXE standard */ +#define SUBOPT_PXE_DISCOVERY 6 +#define SUBOPT_PXE_SERVERS 8 +#define SUBOPT_PXE_MENU 9 +#define SUBOPT_PXE_MENU_PROMPT 10 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 +#define DHCPINFORM 8 + +#define BRDBAND_FORUM_IANA 3561 /* Broadband forum IANA enterprise */ + +#define DHCP_CHADDR_MAX 16 + +struct dhcp_packet { + u8 op, htype, hlen, hops; + u32 xid; + u16 secs, flags; + struct in_addr ciaddr, yiaddr, siaddr, giaddr; + u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128]; + u8 options[312]; +}; diff --git a/src/dns_protocol.h b/src/dns_protocol.h new file mode 100644 index 0000000..bc18e79 --- /dev/null +++ b/src/dns_protocol.h @@ -0,0 +1,111 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define IN6ADDRSZ 16 +#define INADDRSZ 4 + +#define PACKETSZ 512 /* maximum packet size */ +#define MAXDNAME 1025 /* maximum presentation domain name */ +#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define MAXLABEL 63 /* maximum length of domain label */ + +#define NOERROR 0 /* no error */ +#define FORMERR 1 /* format error */ +#define SERVFAIL 2 /* server failure */ +#define NXDOMAIN 3 /* non existent domain */ +#define NOTIMP 4 /* not implemented */ +#define REFUSED 5 /* query refused */ + +#define QUERY 0 /* opcode */ + +#define C_IN 1 /* the arpa internet */ +#define C_CHAOS 3 /* for chaos net (MIT) */ +#define C_ANY 255 /* wildcard match */ + +#define T_A 1 +#define T_NS 2 +#define T_CNAME 5 +#define T_SOA 6 +#define T_PTR 12 +#define T_MX 15 +#define T_TXT 16 +#define T_SIG 24 +#define T_AAAA 28 +#define T_SRV 33 +#define T_NAPTR 35 +#define T_OPT 41 +#define T_TKEY 249 +#define T_TSIG 250 +#define T_MAILB 253 +#define T_ANY 255 + +struct dns_header { + u16 id; + u8 hb3,hb4; + u16 qdcount,ancount,nscount,arcount; +} ; + +#define HB3_QR 0x80 +#define HB3_OPCODE 0x78 +#define HB3_AA 0x04 +#define HB3_TC 0x02 +#define HB3_RD 0x01 + +#define HB4_RA 0x80 +#define HB4_AD 0x20 +#define HB4_CD 0x10 +#define HB4_RCODE 0x0f + +#define OPCODE(x) (((x)->hb3 & HB3_OPCODE) >> 3) +#define RCODE(x) ((x)->hb4 & HB4_RCODE) +#define SET_RCODE(x, code) (x)->hb4 = ((x)->hb4 & ~HB4_RCODE) | code + +#define GETSHORT(s, cp) { \ + unsigned char *t_cp = (unsigned char *)(cp); \ + (s) = ((u16)t_cp[0] << 8) \ + | ((u16)t_cp[1]) \ + ; \ + (cp) += 2; \ +} + +#define GETLONG(l, cp) { \ + unsigned char *t_cp = (unsigned char *)(cp); \ + (l) = ((u32)t_cp[0] << 24) \ + | ((u32)t_cp[1] << 16) \ + | ((u32)t_cp[2] << 8) \ + | ((u32)t_cp[3]) \ + ; \ + (cp) += 4; \ +} + +#define PUTSHORT(s, cp) { \ + u16 t_s = (u16)(s); \ + unsigned char *t_cp = (unsigned char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += 2; \ +} + +#define PUTLONG(l, cp) { \ + u32 t_l = (u32)(l); \ + unsigned char *t_cp = (unsigned char *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += 4; \ +} + diff --git a/src/dnsmasq.c b/src/dnsmasq.c new file mode 100644 index 0000000..827b0dc --- /dev/null +++ b/src/dnsmasq.c @@ -0,0 +1,1325 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +struct daemon *daemon; + +static char *compile_opts = +#ifndef HAVE_IPV6 +"no-" +#endif +"IPv6 " +#ifndef HAVE_GETOPT_LONG +"no-" +#endif +"GNU-getopt " +#ifdef HAVE_BROKEN_RTC +"no-RTC " +#endif +#ifdef NO_FORK +"no-MMU " +#endif +#ifndef HAVE_DBUS +"no-" +#endif +"DBus " +#ifndef LOCALEDIR +"no-" +#endif +"I18N " +#ifndef HAVE_DHCP +"no-" +#endif +"DHCP " +#if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT) +"no-scripts " +#endif +#ifndef HAVE_TFTP +"no-" +#endif +"TFTP " +#if !defined(LOCALEDIR) && !defined(HAVE_IDN) +"no-" +#endif +"IDN"; + + +static volatile pid_t pid = 0; +static volatile int pipewrite; + +static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp); +static void check_dns_listeners(fd_set *set, time_t now); +static void sig_handler(int sig); +static void async_event(int pipe, time_t now); +static void fatal_event(struct event_desc *ev); + +int main (int argc, char **argv) +{ + int bind_fallback = 0; + time_t now; + struct sigaction sigact; + struct iname *if_tmp; + int piperead, pipefd[2], err_pipe[2]; + struct passwd *ent_pw = NULL; +#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT) + uid_t script_uid = 0; + gid_t script_gid = 0; +#endif + struct group *gp = NULL; + long i, max_fd = sysconf(_SC_OPEN_MAX); + char *baduser = NULL; + int log_err; +#if defined(HAVE_LINUX_NETWORK) + cap_user_header_t hdr = NULL; + cap_user_data_t data = NULL; +#endif + +#ifdef LOCALEDIR + setlocale(LC_ALL, ""); + bindtextdomain("dnsmasq", LOCALEDIR); + textdomain("dnsmasq"); +#endif + + sigact.sa_handler = sig_handler; + sigact.sa_flags = 0; + sigemptyset(&sigact.sa_mask); + sigaction(SIGUSR1, &sigact, NULL); + sigaction(SIGUSR2, &sigact, NULL); + sigaction(SIGHUP, &sigact, NULL); + sigaction(SIGTERM, &sigact, NULL); + sigaction(SIGALRM, &sigact, NULL); + sigaction(SIGCHLD, &sigact, NULL); + + /* ignore SIGPIPE */ + sigact.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sigact, NULL); + + umask(022); /* known umask, create leases and pid files as 0644 */ + + read_opts(argc, argv, compile_opts); + + if (daemon->edns_pktsz < PACKETSZ) + daemon->edns_pktsz = PACKETSZ; + daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ? + daemon->edns_pktsz : DNSMASQ_PACKETSZ; + daemon->packet = safe_malloc(daemon->packet_buff_sz); + +#ifdef HAVE_DHCP + if (!daemon->lease_file) + { + if (daemon->dhcp) + daemon->lease_file = LEASEFILE; + } +#endif + + /* Close any file descriptors we inherited apart from std{in|out|err} */ + for (i = 0; i < max_fd; i++) + if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO) + close(i); + +#ifdef HAVE_LINUX_NETWORK + netlink_init(); +#elif !(defined(IP_RECVDSTADDR) && \ + defined(IP_RECVIF) && \ + defined(IP_SENDSRCADDR)) + if (!option_bool(OPT_NOWILD)) + { + bind_fallback = 1; + set_option_bool(OPT_NOWILD); + } +#endif + +#ifndef HAVE_TFTP + if (daemon->tftp_unlimited || daemon->tftp_interfaces) + die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF); +#endif + +#ifdef HAVE_SOLARIS_NETWORK + if (daemon->max_logs != 0) + die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF); +#endif + +#ifdef __ANDROID__ + if (daemon->max_logs != 0) + die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF); +#endif + + rand_init(); + + now = dnsmasq_time(); + +#ifdef HAVE_DHCP + if (daemon->dhcp) + { + /* Note that order matters here, we must call lease_init before + creating any file descriptors which shouldn't be leaked + to the lease-script init process. */ + lease_init(now); + dhcp_init(); + } +#endif + + if (!enumerate_interfaces()) + die(_("failed to find list of interfaces: %s"), NULL, EC_MISC); + + if (option_bool(OPT_NOWILD)) + { + daemon->listeners = create_bound_listeners(); + + for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) + if (if_tmp->name && !if_tmp->used) + die(_("unknown interface %s"), if_tmp->name, EC_BADNET); + + for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next) + if (!if_tmp->used) + { + prettyprint_addr(&if_tmp->addr, daemon->namebuff); + die(_("no interface with address %s"), daemon->namebuff, EC_BADNET); + } + } + else + daemon->listeners = create_wildcard_listeners(); + + if (daemon->port != 0) + cache_init(); + + if (option_bool(OPT_DBUS)) +#ifdef HAVE_DBUS + { + char *err; + daemon->dbus = NULL; + daemon->watches = NULL; + if ((err = dbus_init())) + die(_("DBus error: %s"), err, EC_MISC); + } +#else + die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF); +#endif + + if (daemon->port != 0) + pre_allocate_sfds(); + +#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT) + /* Note getpwnam returns static storage */ + if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser) + { + if ((ent_pw = getpwnam(daemon->scriptuser))) + { + script_uid = ent_pw->pw_uid; + script_gid = ent_pw->pw_gid; + } + else + baduser = daemon->scriptuser; + } +#endif + + if (daemon->username && !(ent_pw = getpwnam(daemon->username))) + baduser = daemon->username; + else if (daemon->groupname && !(gp = getgrnam(daemon->groupname))) + baduser = daemon->groupname; + + if (baduser) + die(_("unknown user or group: %s"), baduser, EC_BADCONF); + + /* implement group defaults, "dip" if available, or group associated with uid */ + if (!daemon->group_set && !gp) + { + if (!(gp = getgrnam(CHGRP)) && ent_pw) + gp = getgrgid(ent_pw->pw_gid); + + /* for error message */ + if (gp) + daemon->groupname = gp->gr_name; + } + +#if defined(HAVE_LINUX_NETWORK) + /* determine capability API version here, while we can still + call safe_malloc */ + if (ent_pw && ent_pw->pw_uid != 0) + { + int capsize = 1; /* for header version 1 */ + hdr = safe_malloc(sizeof(*hdr)); + + /* find version supported by kernel */ + memset(hdr, 0, sizeof(*hdr)); + capget(hdr, NULL); + + if (hdr->version != LINUX_CAPABILITY_VERSION_1) + { + /* if unknown version, use largest supported version (3) */ + if (hdr->version != LINUX_CAPABILITY_VERSION_2) + hdr->version = LINUX_CAPABILITY_VERSION_3; + capsize = 2; + } + + data = safe_malloc(sizeof(*data) * capsize); + memset(data, 0, sizeof(*data) * capsize); + } +#endif + + /* Use a pipe to carry signals and other events back to the event loop + in a race-free manner and another to carry errors to daemon-invoking process */ + safe_pipe(pipefd, 1); + + piperead = pipefd[0]; + pipewrite = pipefd[1]; + /* prime the pipe to load stuff first time. */ + send_event(pipewrite, EVENT_RELOAD, 0); + + err_pipe[1] = -1; + + if (!option_bool(OPT_DEBUG)) + { + /* The following code "daemonizes" the process. + See Stevens section 12.4 */ + + if (chdir("/") != 0) + die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC); + +#ifndef NO_FORK + if (!option_bool(OPT_NO_FORK)) + { + pid_t pid; + + /* pipe to carry errors back to original process. + When startup is complete we close this and the process terminates. */ + safe_pipe(err_pipe, 0); + + if ((pid = fork()) == -1) + /* fd == -1 since we've not forked, never returns. */ + send_event(-1, EVENT_FORK_ERR, errno); + + if (pid != 0) + { + struct event_desc ev; + + /* close our copy of write-end */ + close(err_pipe[1]); + + /* check for errors after the fork */ + if (read_write(err_pipe[0], (unsigned char *)&ev, sizeof(ev), 1)) + fatal_event(&ev); + + _exit(EC_GOOD); + } + + close(err_pipe[0]); + + /* NO calls to die() from here on. */ + + setsid(); + + if ((pid = fork()) == -1) + send_event(err_pipe[1], EVENT_FORK_ERR, errno); + + if (pid != 0) + _exit(0); + } +#endif + + /* write pidfile _after_ forking ! */ + if (daemon->runfile) + { + FILE *pidfile; + + /* only complain if started as root */ + if ((pidfile = fopen(daemon->runfile, "w"))) + { + fprintf(pidfile, "%d\n", (int) getpid()); + fclose(pidfile); + } + else if (getuid() == 0) + { + send_event(err_pipe[1], EVENT_PIDFILE, errno); + _exit(0); + } + } + } + + log_err = log_start(ent_pw, err_pipe[1]); + + if (!option_bool(OPT_DEBUG)) + { + /* open stdout etc to /dev/null */ + int nullfd = open("/dev/null", O_RDWR); + dup2(nullfd, STDOUT_FILENO); + dup2(nullfd, STDERR_FILENO); + dup2(nullfd, STDIN_FILENO); + close(nullfd); + } + + /* if we are to run scripts, we need to fork a helper before dropping root. */ + daemon->helperfd = -1; +#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT) + if (daemon->dhcp && daemon->lease_change_command) + daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd); +#endif + + if (!option_bool(OPT_DEBUG) && getuid() == 0) + { + int bad_capabilities = 0; + gid_t dummy; + + /* remove all supplimentary groups */ + if (gp && + (setgroups(0, &dummy) == -1 || + setgid(gp->gr_gid) == -1)) + { + send_event(err_pipe[1], EVENT_GROUP_ERR, errno); + _exit(0); + } + + if (ent_pw && ent_pw->pw_uid != 0) + { +#if defined(HAVE_LINUX_NETWORK) + /* On linux, we keep CAP_NETADMIN (for ARP-injection) and + CAP_NET_RAW (for icmp) if we're doing dhcp */ + data->effective = data->permitted = data->inheritable = + (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID); + + /* Tell kernel to not clear capabilities when dropping root */ + if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) + bad_capabilities = errno; + +#elif defined(HAVE_SOLARIS_NETWORK) + /* http://developers.sun.com/solaris/articles/program_privileges.html */ + priv_set_t *priv_set; + + if (!(priv_set = priv_str_to_set("basic", ",", NULL)) || + priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 || + priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1) + bad_capabilities = errno; + + if (priv_set && bad_capabilities == 0) + { + priv_inverse(priv_set); + + if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1) + bad_capabilities = errno; + } + + if (priv_set) + priv_freeset(priv_set); + +#endif + + if (bad_capabilities != 0) + { + send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities); + _exit(0); + } + + /* finally drop root */ + if (setuid(ent_pw->pw_uid) == -1) + { + send_event(err_pipe[1], EVENT_USER_ERR, errno); + _exit(0); + } + +#ifdef HAVE_LINUX_NETWORK + data->effective = data->permitted = + (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW); + data->inheritable = 0; + + /* lose the setuid and setgid capbilities */ + if (capset(hdr, data) == -1) + { + send_event(err_pipe[1], EVENT_CAP_ERR, errno); + _exit(0); + } +#endif + + } + } + +#ifdef HAVE_LINUX_NETWORK + if (option_bool(OPT_DEBUG)) + prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); +#endif + + if (daemon->port == 0) + my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION); + else if (daemon->cachesize != 0) + my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize); + else + my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION); + + my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts); + +#ifdef HAVE_DBUS + if (option_bool(OPT_DBUS)) + { + if (daemon->dbus) + my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus")); + else + my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending")); + } +#endif + + if (log_err != 0) + my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), + daemon->log_file, strerror(log_err)); + + if (bind_fallback) + my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations")); + + if (!option_bool(OPT_NOWILD)) + for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) + if (if_tmp->name && !if_tmp->used) + my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name); + + if (daemon->port != 0 && option_bool(OPT_NO_RESOLV)) + { + if (daemon->resolv_files && !daemon->resolv_files->is_default) + my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set")); + daemon->resolv_files = NULL; + if (!daemon->servers) + my_syslog(LOG_WARNING, _("warning: no upstream servers configured")); + } + + if (daemon->max_logs != 0) + my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs); + +#ifdef HAVE_DHCP + if (daemon->dhcp) + { + struct dhcp_context *dhcp_tmp; + + for (dhcp_tmp = daemon->dhcp; dhcp_tmp; dhcp_tmp = dhcp_tmp->next) + { + prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time); + strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start)); + my_syslog(MS_DHCP | LOG_INFO, + (dhcp_tmp->flags & CONTEXT_STATIC) ? + _("DHCP, static leases only on %.0s%s, lease time %s") : + (dhcp_tmp->flags & CONTEXT_PROXY) ? + _("DHCP, proxy on subnet %.0s%s%.0s") : + _("DHCP, IP range %s -- %s, lease time %s"), + daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2); + } + } +#endif + +#ifdef HAVE_TFTP + if (daemon->tftp_unlimited || daemon->tftp_interfaces) + { +#ifdef FD_SETSIZE + if (FD_SETSIZE < (unsigned)max_fd) + max_fd = FD_SETSIZE; +#endif + + my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s", + daemon->tftp_prefix ? _("root is ") : _("enabled"), + daemon->tftp_prefix ? daemon->tftp_prefix: "", + option_bool(OPT_TFTP_SECURE) ? _("secure mode") : ""); + + /* This is a guess, it assumes that for small limits, + disjoint files might be served, but for large limits, + a single file will be sent to may clients (the file only needs + one fd). */ + + max_fd -= 30; /* use other than TFTP */ + + if (max_fd < 0) + max_fd = 5; + else if (max_fd < 100) + max_fd = max_fd/2; + else + max_fd = max_fd - 20; + + /* if we have to use a limited range of ports, + that will limit the number of transfers */ + if (daemon->start_tftp_port != 0 && + daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd) + max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1; + + if (daemon->tftp_max > max_fd) + { + daemon->tftp_max = max_fd; + my_syslog(MS_TFTP | LOG_WARNING, + _("restricting maximum simultaneous TFTP transfers to %d"), + daemon->tftp_max); + } + } +#endif + + /* finished start-up - release original process */ + if (err_pipe[1] != -1) + close(err_pipe[1]); + + if (daemon->port != 0) + check_servers(); + + pid = getpid(); + + while (1) + { + int maxfd = -1; + struct timeval t, *tp = NULL; + fd_set rset, wset, eset; + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_ZERO(&eset); + + /* if we are out of resources, find how long we have to wait + for some to come free, we'll loop around then and restart + listening for queries */ + if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0) + { + t.tv_usec = 0; + tp = &t; + } + + /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */ + if (daemon->tftp_trans || + (option_bool(OPT_DBUS) && !daemon->dbus)) + { + t.tv_sec = 0; + t.tv_usec = 250000; + tp = &t; + } + +#ifdef HAVE_DBUS + set_dbus_listeners(&maxfd, &rset, &wset, &eset); +#endif + +#ifdef HAVE_DHCP + if (daemon->dhcp) + { + FD_SET(daemon->dhcpfd, &rset); + bump_maxfd(daemon->dhcpfd, &maxfd); + if (daemon->pxefd != -1) + { + FD_SET(daemon->pxefd, &rset); + bump_maxfd(daemon->pxefd, &maxfd); + } + } +#endif + +#ifdef HAVE_LINUX_NETWORK + FD_SET(daemon->netlinkfd, &rset); + bump_maxfd(daemon->netlinkfd, &maxfd); +#endif + + FD_SET(piperead, &rset); + bump_maxfd(piperead, &maxfd); + +#ifdef HAVE_DHCP +# ifdef HAVE_SCRIPT + while (helper_buf_empty() && do_script_run(now)); + + if (!helper_buf_empty()) + { + FD_SET(daemon->helperfd, &wset); + bump_maxfd(daemon->helperfd, &maxfd); + } +# else + /* need this for other side-effects */ + while (do_script_run(now)); +# endif +#endif + + /* must do this just before select(), when we know no + more calls to my_syslog() can occur */ + set_log_writer(&wset, &maxfd); + + if (select(maxfd+1, &rset, &wset, &eset, tp) < 0) + { + /* otherwise undefined after error */ + FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); + } + + now = dnsmasq_time(); + + check_log_writer(&wset); + +#ifdef HAVE_LINUX_NETWORK + if (FD_ISSET(daemon->netlinkfd, &rset)) + netlink_multicast(); +#endif + + /* Check for changes to resolv files once per second max. */ + /* Don't go silent for long periods if the clock goes backwards. */ + if (daemon->last_resolv == 0 || + difftime(now, daemon->last_resolv) > 1.0 || + difftime(now, daemon->last_resolv) < -1.0) + { + /* poll_resolv doesn't need to reload first time through, since + that's queued anyway. */ + + poll_resolv(0, daemon->last_resolv != 0, now); + daemon->last_resolv = now; + } + + if (FD_ISSET(piperead, &rset)) + async_event(piperead, now); + +#ifdef HAVE_DBUS + /* if we didn't create a DBus connection, retry now. */ + if (option_bool(OPT_DBUS) && !daemon->dbus) + { + char *err; + if ((err = dbus_init())) + my_syslog(LOG_WARNING, _("DBus error: %s"), err); + if (daemon->dbus) + my_syslog(LOG_INFO, _("connected to system DBus")); + } + check_dbus_listeners(&rset, &wset, &eset); +#endif + + check_dns_listeners(&rset, now); + +#ifdef HAVE_TFTP + check_tftp_listeners(&rset, now); +#endif + +#ifdef HAVE_DHCP + if (daemon->dhcp) + { + if (FD_ISSET(daemon->dhcpfd, &rset)) + dhcp_packet(now, 0); + if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset)) + dhcp_packet(now, 1); + } + +# ifdef HAVE_SCRIPT + if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset)) + helper_write(); +# endif +#endif + + } +} + +static void sig_handler(int sig) +{ + if (pid == 0) + { + /* ignore anything other than TERM during startup + and in helper proc. (helper ignore TERM too) */ + if (sig == SIGTERM) + exit(EC_MISC); + } + else if (pid != getpid()) + { + /* alarm is used to kill TCP children after a fixed time. */ + if (sig == SIGALRM) + _exit(0); + } + else + { + /* master process */ + int event, errsave = errno; + + if (sig == SIGHUP) + event = EVENT_RELOAD; + else if (sig == SIGCHLD) + event = EVENT_CHILD; + else if (sig == SIGALRM) + event = EVENT_ALARM; + else if (sig == SIGTERM) + event = EVENT_TERM; + else if (sig == SIGUSR1) + event = EVENT_DUMP; + else if (sig == SIGUSR2) + event = EVENT_REOPEN; + else + return; + + send_event(pipewrite, event, 0); + errno = errsave; + } +} + +void send_event(int fd, int event, int data) +{ + struct event_desc ev; + + ev.event = event; + ev.data = data; + + /* error pipe, debug mode. */ + if (fd == -1) + fatal_event(&ev); + else + /* pipe is non-blocking and struct event_desc is smaller than + PIPE_BUF, so this either fails or writes everything */ + while (write(fd, &ev, sizeof(ev)) == -1 && errno == EINTR); +} + +static void fatal_event(struct event_desc *ev) +{ + errno = ev->data; + + switch (ev->event) + { + case EVENT_DIE: + exit(0); + + case EVENT_FORK_ERR: + die(_("cannot fork into background: %s"), NULL, EC_MISC); + + case EVENT_PIPE_ERR: + die(_("failed to create helper: %s"), NULL, EC_MISC); + + case EVENT_CAP_ERR: + die(_("setting capabilities failed: %s"), NULL, EC_MISC); + + case EVENT_USER_ERR: + case EVENT_HUSER_ERR: + die(_("failed to change user-id to %s: %s"), + ev->event == EVENT_USER_ERR ? daemon->username : daemon->scriptuser, + EC_MISC); + + case EVENT_GROUP_ERR: + die(_("failed to change group-id to %s: %s"), daemon->groupname, EC_MISC); + + case EVENT_PIDFILE: + die(_("failed to open pidfile %s: %s"), daemon->runfile, EC_FILE); + + case EVENT_LOG_ERR: + die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE); + } +} + +static void async_event(int pipe, time_t now) +{ + pid_t p; + struct event_desc ev; + int i; + + if (read_write(pipe, (unsigned char *)&ev, sizeof(ev), 1)) + switch (ev.event) + { + case EVENT_RELOAD: + clear_cache_and_reload(now); + if (daemon->port != 0 && daemon->resolv_files && option_bool(OPT_NO_POLL)) + { + reload_servers(daemon->resolv_files->name); + check_servers(); + } +#ifdef HAVE_DHCP + rerun_scripts(); +#endif + break; + + case EVENT_DUMP: + if (daemon->port != 0) + dump_cache(now); + break; + + case EVENT_ALARM: +#ifdef HAVE_DHCP + if (daemon->dhcp) + { + lease_prune(NULL, now); + lease_update_file(now); + } +#endif + break; + + case EVENT_CHILD: + /* See Stevens 5.10 */ + while ((p = waitpid(-1, NULL, WNOHANG)) != 0) + if (p == -1) + { + if (errno != EINTR) + break; + } + else + for (i = 0 ; i < MAX_PROCS; i++) + if (daemon->tcp_pids[i] == p) + daemon->tcp_pids[i] = 0; + break; + + case EVENT_KILLED: + my_syslog(LOG_WARNING, _("child process killed by signal %d"), ev.data); + break; + + case EVENT_EXITED: + my_syslog(LOG_WARNING, _("child process exited with status %d"), ev.data); + break; + + case EVENT_EXEC_ERR: + my_syslog(LOG_ERR, _("failed to execute %s: %s"), + daemon->lease_change_command, strerror(ev.data)); + break; + + /* necessary for fatal errors in helper */ + case EVENT_HUSER_ERR: + case EVENT_DIE: + fatal_event(&ev); + break; + + case EVENT_REOPEN: + /* Note: this may leave TCP-handling processes with the old file still open. + Since any such process will die in CHILD_LIFETIME or probably much sooner, + we leave them logging to the old file. */ + if (daemon->log_file != NULL) + log_reopen(daemon->log_file); + break; + + case EVENT_TERM: + /* Knock all our children on the head. */ + for (i = 0; i < MAX_PROCS; i++) + if (daemon->tcp_pids[i] != 0) + kill(daemon->tcp_pids[i], SIGALRM); + +#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT) + /* handle pending lease transitions */ + if (daemon->helperfd != -1) + { + /* block in writes until all done */ + if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1) + fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK); + do { + helper_write(); + } while (!helper_buf_empty() || do_script_run(now)); + close(daemon->helperfd); + } +#endif + + if (daemon->lease_stream) + fclose(daemon->lease_stream); + + if (daemon->runfile) + unlink(daemon->runfile); + + my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM")); + flush_log(); + exit(EC_GOOD); + } +} + +void poll_resolv(int force, int do_reload, time_t now) +{ + struct resolvc *res, *latest; + struct stat statbuf; + time_t last_change = 0; + /* There may be more than one possible file. + Go through and find the one which changed _last_. + Warn of any which can't be read. */ + + if (daemon->port == 0 || option_bool(OPT_NO_POLL)) + return; + + for (latest = NULL, res = daemon->resolv_files; res; res = res->next) + if (stat(res->name, &statbuf) == -1) + { + if (force) + { + res->mtime = 0; + continue; + } + + if (!res->logged) + my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno)); + res->logged = 1; + + if (res->mtime != 0) + { + /* existing file evaporated, force selection of the latest + file even if its mtime hasn't changed since we last looked */ + poll_resolv(1, do_reload, now); + return; + } + } + else + { + res->logged = 0; + if (force || (statbuf.st_mtime != res->mtime)) + { + res->mtime = statbuf.st_mtime; + if (difftime(statbuf.st_mtime, last_change) > 0.0) + { + last_change = statbuf.st_mtime; + latest = res; + } + } + } + + if (latest) + { + static int warned = 0; + if (reload_servers(latest->name)) + { + my_syslog(LOG_INFO, _("reading %s"), latest->name); + warned = 0; + check_servers(); + if (option_bool(OPT_RELOAD) && do_reload) + clear_cache_and_reload(now); + } + else + { + latest->mtime = 0; + if (!warned) + { + my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name); + warned = 1; + } + } + } +} + +void clear_cache_and_reload(time_t now) +{ + if (daemon->port != 0) + cache_reload(); + +#ifdef HAVE_DHCP + if (daemon->dhcp) + { + if (option_bool(OPT_ETHERS)) + dhcp_read_ethers(); + reread_dhcp(); + dhcp_update_configs(daemon->dhcp_conf); + check_dhcp_hosts(0); + lease_update_from_configs(); + lease_update_file(now); + lease_update_dns(); + } +#endif +} + +static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp) +{ + struct serverfd *serverfdp; + struct listener *listener; + int wait = 0, i; + +#ifdef HAVE_TFTP + int tftp = 0; + struct tftp_transfer *transfer; + for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next) + { + tftp++; + FD_SET(transfer->sockfd, set); + bump_maxfd(transfer->sockfd, maxfdp); + } +#endif + + /* will we be able to get memory? */ + if (daemon->port != 0) + get_new_frec(now, &wait); + + for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) + { + FD_SET(serverfdp->fd, set); + bump_maxfd(serverfdp->fd, maxfdp); + } + + if (daemon->port != 0 && !daemon->osport) + for (i = 0; i < RANDOM_SOCKS; i++) + if (daemon->randomsocks[i].refcount != 0) + { + FD_SET(daemon->randomsocks[i].fd, set); + bump_maxfd(daemon->randomsocks[i].fd, maxfdp); + } + + for (listener = daemon->listeners; listener; listener = listener->next) + { + /* only listen for queries if we have resources */ + if (listener->fd != -1 && wait == 0) + { + FD_SET(listener->fd, set); + bump_maxfd(listener->fd, maxfdp); + } + + /* death of a child goes through the select loop, so + we don't need to explicitly arrange to wake up here */ + if (listener->tcpfd != -1) + for (i = 0; i < MAX_PROCS; i++) + if (daemon->tcp_pids[i] == 0) + { + FD_SET(listener->tcpfd, set); + bump_maxfd(listener->tcpfd, maxfdp); + break; + } + +#ifdef HAVE_TFTP + if (tftp <= daemon->tftp_max && listener->tftpfd != -1) + { + FD_SET(listener->tftpfd, set); + bump_maxfd(listener->tftpfd, maxfdp); + } +#endif + + } + + return wait; +} + +static void check_dns_listeners(fd_set *set, time_t now) +{ + struct serverfd *serverfdp; + struct listener *listener; + int i; + + for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) + if (FD_ISSET(serverfdp->fd, set)) + reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now); + + if (daemon->port != 0 && !daemon->osport) + for (i = 0; i < RANDOM_SOCKS; i++) + if (daemon->randomsocks[i].refcount != 0 && + FD_ISSET(daemon->randomsocks[i].fd, set)) + reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now); + + for (listener = daemon->listeners; listener; listener = listener->next) + { + if (listener->fd != -1 && FD_ISSET(listener->fd, set)) + receive_query(listener, now); + +#ifdef HAVE_TFTP + if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set)) + tftp_request(listener, now); +#endif + + if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set)) + { + int confd; + struct irec *iface = NULL; + pid_t p; + + while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR); + + if (confd == -1) + continue; + + if (option_bool(OPT_NOWILD)) + iface = listener->iface; + else + { + union mysockaddr tcp_addr; + socklen_t tcp_len = sizeof(union mysockaddr); + /* Check for allowed interfaces when binding the wildcard address: + we do this by looking for an interface with the same address as + the local address of the TCP connection, then looking to see if that's + an allowed interface. As a side effect, we get the netmask of the + interface too, for localisation. */ + + /* interface may be new since startup */ + if (enumerate_interfaces() && + getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1) + for (iface = daemon->interfaces; iface; iface = iface->next) + if (sockaddr_isequal(&iface->addr, &tcp_addr)) + break; + } + + if (!iface) + { + shutdown(confd, SHUT_RDWR); + close(confd); + } +#ifndef NO_FORK + else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0) + { + if (p != -1) + { + int i; + for (i = 0; i < MAX_PROCS; i++) + if (daemon->tcp_pids[i] == 0) + { + daemon->tcp_pids[i] = p; + break; + } + } + close(confd); + } +#endif + else + { + unsigned char *buff; + struct server *s; + int flags; + struct in_addr dst_addr_4; + + dst_addr_4.s_addr = 0; + +#ifndef NO_FORK + /* Arrange for SIGALARM after CHILD_LIFETIME seconds to + terminate the process. */ + if (!option_bool(OPT_DEBUG)) + alarm(CHILD_LIFETIME); +#endif + + /* start with no upstream connections. */ + for (s = daemon->servers; s; s = s->next) + s->tcpfd = -1; + + /* The connected socket inherits non-blocking + attribute from the listening socket. + Reset that here. */ + if ((flags = fcntl(confd, F_GETFL, 0)) != -1) + fcntl(confd, F_SETFL, flags & ~O_NONBLOCK); + + if (listener->family == AF_INET) + dst_addr_4 = iface->addr.in.sin_addr; + + buff = tcp_request(confd, now, dst_addr_4, iface->netmask); + + shutdown(confd, SHUT_RDWR); + close(confd); + + if (buff) + free(buff); + + for (s = daemon->servers; s; s = s->next) + if (s->tcpfd != -1) + { + shutdown(s->tcpfd, SHUT_RDWR); + close(s->tcpfd); + } +#ifndef NO_FORK + if (!option_bool(OPT_DEBUG)) + { + flush_log(); + _exit(0); + } +#endif + } + } + } +} + +#ifdef HAVE_DHCP +int make_icmp_sock(void) +{ + int fd; + int zeroopt = 0; + + if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1) + { + if (!fix_fd(fd) || + setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1) + { + close(fd); + fd = -1; + } + } + + return fd; +} + +int icmp_ping(struct in_addr addr) +{ + /* Try and get an ICMP echo from a machine. */ + + /* Note that whilst in the three second wait, we check for + (and service) events on the DNS and TFTP sockets, (so doing that + better not use any resources our caller has in use...) + but we remain deaf to signals or further DHCP packets. */ + + int fd; + struct sockaddr_in saddr; + struct { + struct ip ip; + struct icmp icmp; + } packet; + unsigned short id = rand16(); + unsigned int i, j; + int gotreply = 0; + time_t start, now; + +#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK) + if ((fd = make_icmp_sock()) == -1) + return 0; +#else + int opt = 2000; + fd = daemon->dhcp_icmp_fd; + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)); +#endif + + saddr.sin_family = AF_INET; + saddr.sin_port = 0; + saddr.sin_addr = addr; +#ifdef HAVE_SOCKADDR_SA_LEN + saddr.sin_len = sizeof(struct sockaddr_in); +#endif + + memset(&packet.icmp, 0, sizeof(packet.icmp)); + packet.icmp.icmp_type = ICMP_ECHO; + packet.icmp.icmp_id = id; + for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++) + j += ((u16 *)&packet.icmp)[i]; + while (j>>16) + j = (j & 0xffff) + (j >> 16); + packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j; + + while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0, + (struct sockaddr *)&saddr, sizeof(saddr)) == -1 && + retry_send()); + + for (now = start = dnsmasq_time(); + difftime(now, start) < (float)PING_WAIT;) + { + struct timeval tv; + fd_set rset, wset; + struct sockaddr_in faddr; + int maxfd = fd; + socklen_t len = sizeof(faddr); + + tv.tv_usec = 250000; + tv.tv_sec = 0; + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_SET(fd, &rset); + set_dns_listeners(now, &rset, &maxfd); + set_log_writer(&wset, &maxfd); + + if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0) + { + FD_ZERO(&rset); + FD_ZERO(&wset); + } + + now = dnsmasq_time(); + + check_log_writer(&wset); + check_dns_listeners(&rset, now); + +#ifdef HAVE_TFTP + check_tftp_listeners(&rset, now); +#endif + + if (FD_ISSET(fd, &rset) && + recvfrom(fd, &packet, sizeof(packet), 0, + (struct sockaddr *)&faddr, &len) == sizeof(packet) && + saddr.sin_addr.s_addr == faddr.sin_addr.s_addr && + packet.icmp.icmp_type == ICMP_ECHOREPLY && + packet.icmp.icmp_seq == 0 && + packet.icmp.icmp_id == id) + { + gotreply = 1; + break; + } + } + +#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK) + close(fd); +#else + opt = 1; + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)); +#endif + + return gotreply; +} +#endif + + diff --git a/src/dnsmasq.h b/src/dnsmasq.h new file mode 100644 index 0000000..66c602e --- /dev/null +++ b/src/dnsmasq.h @@ -0,0 +1,941 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define COPYRIGHT "Copyright (c) 2000-2011 Simon Kelley" + +#ifndef NO_LARGEFILE +/* Ensure we can use files >2GB (log files may grow this big) */ +# define _LARGEFILE_SOURCE 1 +# define _FILE_OFFSET_BITS 64 +#endif + +/* Get linux C library versions and define _GNU_SOURCE for kFreeBSD. */ +#if defined(__linux__) || defined(__GLIBC__) +# ifndef __ANDROID__ +# define _GNU_SOURCE +# endif +# include <features.h> +#endif + +/* Need these defined early */ +#if defined(__sun) || defined(__sun__) +# define _XPG4_2 +# define __EXTENSIONS__ +#endif + +/* get these before config.h for IPv6 stuff... */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +/* and this. */ +#include <getopt.h> + +#include "config.h" + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +#include "dns_protocol.h" +#include "dhcp_protocol.h" + +#define gettext_noop(S) (S) +#ifndef LOCALEDIR +# define _(S) (S) +#else +# include <libintl.h> +# include <locale.h> +# define _(S) gettext(S) +#endif + +#include <arpa/inet.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#if defined(HAVE_SOLARIS_NETWORK) +# include <sys/sockio.h> +#endif +#include <sys/select.h> +#include <sys/wait.h> +#include <sys/time.h> +#include <sys/un.h> +#include <limits.h> +#include <net/if.h> +#if defined(HAVE_SOLARIS_NETWORK) && !defined(ifr_mtu) +/* Some solaris net/if./h omit this. */ +# define ifr_mtu ifr_ifru.ifru_metric +#endif +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <ctype.h> +#include <signal.h> +#include <stddef.h> +#include <time.h> +#include <errno.h> +#include <pwd.h> +#include <grp.h> +#include <stdarg.h> +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) || defined (__sun) || defined (__ANDROID__) +# include <netinet/if_ether.h> +#else +# include <net/ethernet.h> +#endif +#include <net/if_arp.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#include <sys/uio.h> +#include <syslog.h> +#include <dirent.h> +#ifndef HAVE_LINUX_NETWORK +# include <net/if_dl.h> +#endif + +#if defined(HAVE_LINUX_NETWORK) +#include <linux/capability.h> +/* There doesn't seem to be a universally-available + userpace header for these. */ +extern int capset(cap_user_header_t header, cap_user_data_t data); +extern int capget(cap_user_header_t header, cap_user_data_t data); +#define LINUX_CAPABILITY_VERSION_1 0x19980330 +#define LINUX_CAPABILITY_VERSION_2 0x20071026 +#define LINUX_CAPABILITY_VERSION_3 0x20080522 + +#include <sys/prctl.h> +#elif defined(HAVE_SOLARIS_NETWORK) +#include <priv.h> +#endif + +/* daemon is function in the C library.... */ +#define daemon dnsmasq_daemon + +/* Async event queue */ +struct event_desc { + int event, data; +}; + +#define EVENT_RELOAD 1 +#define EVENT_DUMP 2 +#define EVENT_ALARM 3 +#define EVENT_TERM 4 +#define EVENT_CHILD 5 +#define EVENT_REOPEN 6 +#define EVENT_EXITED 7 +#define EVENT_KILLED 8 +#define EVENT_EXEC_ERR 9 +#define EVENT_PIPE_ERR 10 +#define EVENT_USER_ERR 11 +#define EVENT_CAP_ERR 12 +#define EVENT_PIDFILE 13 +#define EVENT_HUSER_ERR 14 +#define EVENT_GROUP_ERR 15 +#define EVENT_DIE 16 +#define EVENT_LOG_ERR 17 +#define EVENT_FORK_ERR 18 + +/* Exit codes. */ +#define EC_GOOD 0 +#define EC_BADCONF 1 +#define EC_BADNET 2 +#define EC_FILE 3 +#define EC_NOMEM 4 +#define EC_MISC 5 +#define EC_INIT_OFFSET 10 + +/* Min buffer size: we check after adding each record, so there must be + memory for the largest packet, and the largest record so the + min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000. + This might be increased is EDNS packet size if greater than the minimum. +*/ +#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ + +/* Trust the compiler dead-code eliminator.... */ +#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32))) + +#define OPT_BOGUSPRIV 0 +#define OPT_FILTER 1 +#define OPT_LOG 2 +#define OPT_SELFMX 3 +#define OPT_NO_HOSTS 4 +#define OPT_NO_POLL 5 +#define OPT_DEBUG 6 +#define OPT_ORDER 7 +#define OPT_NO_RESOLV 8 +#define OPT_EXPAND 9 +#define OPT_LOCALMX 10 +#define OPT_NO_NEG 11 +#define OPT_NODOTS_LOCAL 12 +#define OPT_NOWILD 13 +#define OPT_ETHERS 14 +#define OPT_RESOLV_DOMAIN 15 +#define OPT_NO_FORK 16 +#define OPT_AUTHORITATIVE 17 +#define OPT_LOCALISE 18 +#define OPT_DBUS 19 +#define OPT_DHCP_FQDN 20 +#define OPT_NO_PING 21 +#define OPT_LEASE_RO 22 +#define OPT_ALL_SERVERS 23 +#define OPT_RELOAD 24 +#define OPT_LOCAL_REBIND 25 +#define OPT_TFTP_SECURE 26 +#define OPT_TFTP_NOBLOCK 27 +#define OPT_LOG_OPTS 28 +#define OPT_TFTP_APREF 29 +#define OPT_NO_OVERRIDE 30 +#define OPT_NO_REBIND 31 +#define OPT_ADD_MAC 32 +#define OPT_DNSSEC 33 +#define OPT_LAST 34 + +/* extra flags for my_syslog, we use a couple of facilities since they are known + not to occupy the same bits as priorities, no matter how syslog.h is set up. */ +#define MS_TFTP LOG_USER +#define MS_DHCP LOG_DAEMON + +struct all_addr { + union { + struct in_addr addr4; +#ifdef HAVE_IPV6 + struct in6_addr addr6; +#endif + } addr; +}; + +struct bogus_addr { + struct in_addr addr; + struct bogus_addr *next; +}; + +/* dns doctor param */ +struct doctor { + struct in_addr in, end, out, mask; + struct doctor *next; +}; + +struct mx_srv_record { + char *name, *target; + int issrv, srvport, priority, weight; + unsigned int offset; + struct mx_srv_record *next; +}; + +struct naptr { + char *name, *replace, *regexp, *services, *flags; + unsigned int order, pref; + struct naptr *next; +}; + +struct txt_record { + char *name; + unsigned char *txt; + unsigned short class, len; + struct txt_record *next; +}; + +struct ptr_record { + char *name, *ptr; + struct ptr_record *next; +}; + +struct cname { + char *alias, *target; + struct cname *next; +}; + +struct interface_name { + char *name; /* domain name */ + char *intr; /* interface name */ + struct interface_name *next; +}; + +union bigname { + char name[MAXDNAME]; + union bigname *next; /* freelist */ +}; + +struct crec { + struct crec *next, *prev, *hash_next; + time_t ttd; /* time to die */ + int uid; + union { + struct all_addr addr; + struct { + struct crec *cache; + int uid; + } cname; + } addr; + unsigned short flags; + union { + char sname[SMALLDNAME]; + union bigname *bname; + char *namep; + } name; +}; + +#define F_IMMORTAL (1u<<0) +#define F_NAMEP (1u<<1) +#define F_REVERSE (1u<<2) +#define F_FORWARD (1u<<3) +#define F_DHCP (1u<<4) +#define F_NEG (1u<<5) +#define F_HOSTS (1u<<6) +#define F_IPV4 (1u<<7) +#define F_IPV6 (1u<<8) +#define F_BIGNAME (1u<<9) +#define F_NXDOMAIN (1u<<10) +#define F_CNAME (1u<<11) +#define F_NOERR (1u<<12) +#define F_CONFIG (1u<<13) +/* below here are only valid as args to log_query: cache + entries are limited to 16 bits */ +#define F_UPSTREAM (1u<<16) +#define F_RRNAME (1u<<17) +#define F_SERVER (1u<<18) +#define F_QUERY (1u<<19) +#define F_NSRR (1u<<20) + + +/* struct sockaddr is not large enough to hold any address, + and specifically not big enough to hold an IPv6 address. + Blech. Roll our own. */ +union mysockaddr { + struct sockaddr sa; + struct sockaddr_in in; +#if defined(HAVE_IPV6) + struct sockaddr_in6 in6; +#endif +}; + +#define SERV_FROM_RESOLV 1 /* 1 for servers from resolv, 0 for command line. */ +#define SERV_NO_ADDR 2 /* no server, this domain is local only */ +#define SERV_LITERAL_ADDRESS 4 /* addr is the answer, not the server */ +#define SERV_HAS_DOMAIN 8 /* server for one domain only */ +#define SERV_HAS_SOURCE 16 /* source address defined */ +#define SERV_FOR_NODOTS 32 /* server for names with no domain part only */ +#define SERV_WARNED_RECURSIVE 64 /* avoid warning spam */ +#define SERV_FROM_DBUS 128 /* 1 if source is DBus */ +#define SERV_MARK 256 /* for mark-and-delete */ +#define SERV_TYPE (SERV_HAS_DOMAIN | SERV_FOR_NODOTS) +#define SERV_COUNTED 512 /* workspace for log code */ +#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */ +#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */ + +struct serverfd { + int fd; + union mysockaddr source_addr; + char interface[IF_NAMESIZE+1]; + struct serverfd *next; +}; + +struct randfd { + int fd; + unsigned short refcount, family; +}; + +struct server { + union mysockaddr addr, source_addr; + char interface[IF_NAMESIZE+1]; + struct serverfd *sfd; + char *domain; /* set if this server only handles a domain. */ + int flags, tcpfd; + unsigned int queries, failed_queries; + struct server *next; +}; + +struct irec { + union mysockaddr addr; + struct in_addr netmask; /* only valid for IPv4 */ + int tftp_ok, mtu; + char *name; + struct irec *next; +}; + +struct listener { + int fd, tcpfd, tftpfd, family; + struct irec *iface; /* only valid for non-wildcard */ + struct listener *next; +}; + +/* interface and address parms from command line. */ +struct iname { + char *name; + union mysockaddr addr; + int isloop, used; + struct iname *next; +}; + +/* resolv-file parms from command-line */ +struct resolvc { + struct resolvc *next; + int is_default, logged; + time_t mtime; + char *name; +}; + +/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */ +#define AH_DIR 1 +#define AH_INACTIVE 2 +struct hostsfile { + struct hostsfile *next; + int flags; + char *fname; + int index; /* matches to cache entries for logging */ +}; + +#define FREC_NOREBIND 1 +#define FREC_CHECKING_DISABLED 2 + +struct frec { + union mysockaddr source; + struct all_addr dest; + struct server *sentto; /* NULL means free */ + struct randfd *rfd4; +#ifdef HAVE_IPV6 + struct randfd *rfd6; +#endif + unsigned int iface; + unsigned short orig_id, new_id; + int fd, forwardall, flags; + unsigned int crc; + time_t time; + struct frec *next; +}; + +/* actions in the daemon->helper RPC */ +#define ACTION_DEL 1 +#define ACTION_OLD_HOSTNAME 2 +#define ACTION_OLD 3 +#define ACTION_ADD 4 +#define ACTION_CONNECT 5 + +struct dhcp_lease { + int clid_len; /* length of client identifier */ + unsigned char *clid; /* clientid */ + char *hostname, *fqdn; /* name from client-hostname option or config */ + char *old_hostname; /* hostname before it moved to another lease */ + char auth_name; /* hostname came from config, not from client */ + char new; /* newly created */ + char changed; /* modified */ + char aux_changed; /* CLID or expiry changed */ + time_t expires; /* lease expiry */ +#ifdef HAVE_BROKEN_RTC + unsigned int length; +#endif + int hwaddr_len, hwaddr_type; + unsigned char hwaddr[DHCP_CHADDR_MAX]; + struct in_addr addr, override, giaddr; + unsigned char *extradata; + unsigned int extradata_len, extradata_size; + int last_interface; + struct dhcp_lease *next; +}; + +struct dhcp_netid { + char *net; + struct dhcp_netid *next; +}; + +struct dhcp_netid_list { + struct dhcp_netid *list; + struct dhcp_netid_list *next; +}; + +struct tag_if { + struct dhcp_netid_list *set; + struct dhcp_netid *tag; + struct tag_if *next; +}; + +struct hwaddr_config { + int hwaddr_len, hwaddr_type; + unsigned char hwaddr[DHCP_CHADDR_MAX]; + unsigned int wildcard_mask; + struct hwaddr_config *next; +}; + +struct dhcp_config { + unsigned int flags; + int clid_len; /* length of client identifier */ + unsigned char *clid; /* clientid */ + char *hostname, *domain; + struct dhcp_netid_list *netid; + struct in_addr addr; + time_t decline_time; + unsigned int lease_time; + struct hwaddr_config *hwaddr; + struct dhcp_config *next; +}; + +#define CONFIG_DISABLE 1 +#define CONFIG_CLID 2 +#define CONFIG_TIME 8 +#define CONFIG_NAME 16 +#define CONFIG_ADDR 32 +#define CONFIG_NOCLID 128 +#define CONFIG_FROM_ETHERS 256 /* entry created by /etc/ethers */ +#define CONFIG_ADDR_HOSTS 512 /* address added by from /etc/hosts */ +#define CONFIG_DECLINED 1024 /* address declined by client */ +#define CONFIG_BANK 2048 /* from dhcp hosts file */ + +struct dhcp_opt { + int opt, len, flags; + union { + int encap; + unsigned int wildcard_mask; + unsigned char *vendor_class; + } u; + unsigned char *val; + struct dhcp_netid *netid; + struct dhcp_opt *next; +}; + +#define DHOPT_ADDR 1 +#define DHOPT_STRING 2 +#define DHOPT_ENCAPSULATE 4 +#define DHOPT_ENCAP_MATCH 8 +#define DHOPT_FORCE 16 +#define DHOPT_BANK 32 +#define DHOPT_ENCAP_DONE 64 +#define DHOPT_MATCH 128 +#define DHOPT_VENDOR 256 +#define DHOPT_HEX 512 +#define DHOPT_VENDOR_MATCH 1024 +#define DHOPT_RFC3925 2048 + +struct dhcp_boot { + char *file, *sname; + struct in_addr next_server; + struct dhcp_netid *netid; + struct dhcp_boot *next; +}; + +struct pxe_service { + unsigned short CSA, type; + char *menu, *basename; + struct in_addr server; + struct dhcp_netid *netid; + struct pxe_service *next; +}; + +#define MATCH_VENDOR 1 +#define MATCH_USER 2 +#define MATCH_CIRCUIT 3 +#define MATCH_REMOTE 4 +#define MATCH_SUBSCRIBER 5 + +/* vendorclass, userclass, remote-id or cicuit-id */ +struct dhcp_vendor { + int len, match_type, option; + char *data; + struct dhcp_netid netid; + struct dhcp_vendor *next; +}; + +struct dhcp_mac { + unsigned int mask; + int hwaddr_len, hwaddr_type; + unsigned char hwaddr[DHCP_CHADDR_MAX]; + struct dhcp_netid netid; + struct dhcp_mac *next; +}; + +struct dhcp_bridge { + char iface[IF_NAMESIZE]; + struct dhcp_bridge *alias, *next; +}; + +struct cond_domain { + char *domain; + struct in_addr start, end; + struct cond_domain *next; +}; + +struct dhcp_context { + unsigned int lease_time, addr_epoch; + struct in_addr netmask, broadcast; + struct in_addr local, router; + struct in_addr start, end; /* range of available addresses */ + int flags; + char *interface; + struct dhcp_netid netid, *filter; + struct dhcp_context *next, *current; +}; + +#define CONTEXT_STATIC 1 +#define CONTEXT_NETMASK 2 +#define CONTEXT_BRDCAST 4 +#define CONTEXT_PROXY 8 + +struct ping_result { + struct in_addr addr; + time_t time; + struct ping_result *next; +}; + +struct tftp_file { + int refcount, fd; + off_t size; + dev_t dev; + ino_t inode; + char filename[]; +}; + +struct tftp_transfer { + int sockfd; + time_t timeout; + int backoff; + unsigned int block, blocksize, expansion; + off_t offset; + union mysockaddr peer; + char opt_blocksize, opt_transize, netascii, carrylf; + struct tftp_file *file; + struct tftp_transfer *next; +}; + +struct addr_list { + struct in_addr addr; + struct addr_list *next; +}; + +struct interface_list { + char *interface; + struct interface_list *next; +}; + +struct tftp_prefix { + char *interface; + char *prefix; + struct tftp_prefix *next; +}; + + +extern struct daemon { + /* datastuctures representing the command-line and + config file arguments. All set (including defaults) + in option.c */ + + unsigned int options, options2; + struct resolvc default_resolv, *resolv_files; + time_t last_resolv; + struct mx_srv_record *mxnames; + struct naptr *naptr; + struct txt_record *txt; + struct ptr_record *ptr; + struct cname *cnames; + struct interface_name *int_names; + char *mxtarget; + char *lease_file; + char *username, *groupname, *scriptuser; + int group_set, osport; + char *domain_suffix; + struct cond_domain *cond_domain; + char *runfile; + char *lease_change_command; + struct iname *if_names, *if_addrs, *if_except, *dhcp_except; + struct bogus_addr *bogus_addr; + struct server *servers; + int log_fac; /* log facility */ + char *log_file; /* optional log file */ + int max_logs; /* queue limit */ + int cachesize, ftabsize; + int port, query_port, min_port; + unsigned long local_ttl, neg_ttl, max_ttl; + struct hostsfile *addn_hosts; + struct dhcp_context *dhcp; + struct dhcp_config *dhcp_conf; + struct dhcp_opt *dhcp_opts, *dhcp_match; + struct dhcp_vendor *dhcp_vendors; + struct dhcp_mac *dhcp_macs; + struct dhcp_boot *boot_config; + struct pxe_service *pxe_services; + struct tag_if *tag_if; + struct addr_list *override_relays; + int override; + int enable_pxe; + struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names; + struct dhcp_netid_list *force_broadcast, *bootp_dynamic; + struct hostsfile *dhcp_hosts_file, *dhcp_opts_file; + int dhcp_max, tftp_max; + int dhcp_server_port, dhcp_client_port; + int start_tftp_port, end_tftp_port; + unsigned int min_leasetime; + struct doctor *doctors; + unsigned short edns_pktsz; + char *tftp_prefix; + struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */ + struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */ + int tftp_unlimited; + + /* globally used stuff for DNS */ + char *packet; /* packet buffer */ + int packet_buff_sz; /* size of above */ + char *namebuff; /* MAXDNAME size buffer */ + unsigned int local_answer, queries_forwarded; + struct frec *frec_list; + struct serverfd *sfds; + struct irec *interfaces; + struct listener *listeners; + struct server *last_server; + time_t forwardtime; + int forwardcount; + struct server *srv_save; /* Used for resend on DoD */ + size_t packet_len; /* " " */ + struct randfd *rfd_save; /* " " */ + pid_t tcp_pids[MAX_PROCS]; + struct randfd randomsocks[RANDOM_SOCKS]; + int v6pktinfo; + + /* DHCP state */ + int dhcpfd, helperfd, pxefd; +#if defined(HAVE_LINUX_NETWORK) + int netlinkfd; +#elif defined(HAVE_BSD_NETWORK) + int dhcp_raw_fd, dhcp_icmp_fd; +#endif + struct iovec dhcp_packet; + char *dhcp_buff, *dhcp_buff2, *dhcp_buff3; + struct ping_result *ping_results; + FILE *lease_stream; + struct dhcp_bridge *bridges; + + /* DBus stuff */ + /* void * here to avoid depending on dbus headers outside dbus.c */ + void *dbus; +#ifdef HAVE_DBUS + struct watch *watches; +#endif + + /* TFTP stuff */ + struct tftp_transfer *tftp_trans; + +} *daemon; + +/* cache.c */ +void cache_init(void); +void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg); +char *record_source(int index); +void querystr(char *str, unsigned short type); +struct crec *cache_find_by_addr(struct crec *crecp, + struct all_addr *addr, time_t now, + unsigned short prot); +struct crec *cache_find_by_name(struct crec *crecp, + char *name, time_t now, unsigned short prot); +void cache_end_insert(void); +void cache_start_insert(void); +struct crec *cache_insert(char *name, struct all_addr *addr, + time_t now, unsigned long ttl, unsigned short flags); +void cache_reload(void); +void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd); +void cache_unhash_dhcp(void); +void dump_cache(time_t now); +char *cache_get_name(struct crec *crecp); +char *get_domain(struct in_addr addr); + +/* rfc1035.c */ +unsigned int extract_request(struct dns_header *header, size_t qlen, + char *name, unsigned short *typep); +size_t setup_reply(struct dns_header *header, size_t qlen, + struct all_addr *addrp, unsigned int flags, + unsigned long local_ttl); +int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, + time_t now, int is_sign, int checkrebind, int checking_disabled); +size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + struct in_addr local_addr, struct in_addr local_netmask, time_t now); +int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, + struct bogus_addr *addr, time_t now); +unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, + size_t *len, unsigned char **p, int *is_sign); +int check_for_local_domain(char *name, time_t now); +unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff); +size_t resize_packet(struct dns_header *header, size_t plen, + unsigned char *pheader, size_t hlen); +size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3); + +/* util.c */ +void rand_init(void); +unsigned short rand16(void); +int legal_hostname(char *c); +char *canonicalise(char *s, int *nomem); +unsigned char *do_rfc1035_name(unsigned char *p, char *sval); +void *safe_malloc(size_t size); +void safe_pipe(int *fd, int read_noblock); +void *whine_malloc(size_t size); +int sa_len(union mysockaddr *addr); +int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2); +int hostname_isequal(char *a, char *b); +time_t dnsmasq_time(void); +int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask); +int retry_send(void); +void prettyprint_time(char *buf, unsigned int t); +int prettyprint_addr(union mysockaddr *addr, char *buf); +int parse_hex(char *in, unsigned char *out, int maxlen, + unsigned int *wildcard_mask, int *mac_type); +int memcmp_masked(unsigned char *a, unsigned char *b, int len, + unsigned int mask); +int expand_buf(struct iovec *iov, size_t size); +char *print_mac(char *buff, unsigned char *mac, int len); +void bump_maxfd(int fd, int *max); +int read_write(int fd, unsigned char *packet, int size, int rw); + +/* log.c */ +void die(char *message, char *arg1, int exit_code); +int log_start(struct passwd *ent_pw, int errfd); +int log_reopen(char *log_file); +void my_syslog(int priority, const char *format, ...); +void set_log_writer(fd_set *set, int *maxfdp); +void check_log_writer(fd_set *set); +void flush_log(void); + +/* option.c */ +void read_opts (int argc, char **argv, char *compile_opts); +char *option_string(unsigned char opt, int *is_ip, int *is_name); +void reread_dhcp(void); +void set_option_bool(unsigned int opt); +struct hostsfile *expand_filelist(struct hostsfile *list); + +/* forward.c */ +void reply_query(int fd, int family, time_t now); +void receive_query(struct listener *listen, time_t now); +unsigned char *tcp_request(int confd, time_t now, + struct in_addr local_addr, struct in_addr netmask); +void server_gone(struct server *server); +struct frec *get_new_frec(time_t now, int *wait); + +/* network.c */ +int indextoname(int fd, int index, char *name); +int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp); +int random_sock(int family); +void pre_allocate_sfds(void); +int reload_servers(char *fname); +void check_servers(void); +int enumerate_interfaces(); +struct listener *create_wildcard_listeners(void); +struct listener *create_bound_listeners(void); +int iface_check(int family, struct all_addr *addr, char *name, int *indexp); +int fix_fd(int fd); +struct in_addr get_ifaddr(char *intr); + +/* dhcp.c */ +#ifdef HAVE_DHCP +void dhcp_init(void); +void dhcp_packet(time_t now, int pxe_fd); +struct dhcp_context *address_available(struct dhcp_context *context, + struct in_addr addr, + struct dhcp_netid *netids); +struct dhcp_context *narrow_context(struct dhcp_context *context, + struct in_addr taddr, + struct dhcp_netid *netids); +int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly); +int address_allocate(struct dhcp_context *context, + struct in_addr *addrp, unsigned char *hwaddr, int hw_len, + struct dhcp_netid *netids, time_t now); +struct dhcp_netid *run_tag_if(struct dhcp_netid *input); +int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type); +struct dhcp_config *find_config(struct dhcp_config *configs, + struct dhcp_context *context, + unsigned char *clid, int clid_len, + unsigned char *hwaddr, int hw_len, + int hw_type, char *hostname); +void dhcp_update_configs(struct dhcp_config *configs); +void dhcp_read_ethers(void); +void check_dhcp_hosts(int fatal); +struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr); +char *strip_hostname(char *hostname); +char *host_from_dns(struct in_addr addr); +char *get_domain(struct in_addr addr); +#endif + +/* lease.c */ +#ifdef HAVE_DHCP +void lease_update_file(time_t now); +void lease_update_dns(); +void lease_init(time_t now); +struct dhcp_lease *lease_allocate(struct in_addr addr); +void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr, + unsigned char *clid, int hw_len, int hw_type, int clid_len); +void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth); +void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now); +void lease_set_interface(struct dhcp_lease *lease, int interface); +struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type, + unsigned char *clid, int clid_len); +struct dhcp_lease *lease_find_by_addr(struct in_addr addr); +void lease_prune(struct dhcp_lease *target, time_t now); +void lease_update_from_configs(void); +int do_script_run(time_t now); +void rerun_scripts(void); +#endif + +/* rfc2131.c */ +#ifdef HAVE_DHCP +size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, + size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe_fd); +unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, + int clid_len, unsigned char *clid, int *len_out); +#endif + +/* dnsmasq.c */ +#ifdef HAVE_DHCP +int make_icmp_sock(void); +int icmp_ping(struct in_addr addr); +#endif +void send_event(int fd, int event, int data); +void clear_cache_and_reload(time_t now); +void poll_resolv(int force, int do_reload, time_t now); + +/* netlink.c */ +#ifdef HAVE_LINUX_NETWORK +void netlink_init(void); +void netlink_multicast(void); +#endif + +/* bpf.c */ +#ifdef HAVE_BSD_NETWORK +void init_bpf(void); +void send_via_bpf(struct dhcp_packet *mess, size_t len, + struct in_addr iface_addr, struct ifreq *ifr); +#endif + +/* bpf.c or netlink.c */ +int iface_enumerate(int family, void *parm, int (callback)()); + +/* dbus.c */ +#ifdef HAVE_DBUS +char *dbus_init(void); +void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset); +void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset); +# ifdef HAVE_DHCP +void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname); +# endif +#endif + +/* helper.c */ +#if defined(HAVE_DHCP) && !defined(NO_FORK) +int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd); +void helper_write(void); +void queue_script(int action, struct dhcp_lease *lease, + char *hostname, time_t now); +int helper_buf_empty(void); +#endif + +/* tftp.c */ +#ifdef HAVE_TFTP +void tftp_request(struct listener *listen, time_t now); +void check_tftp_listeners(fd_set *rset, time_t now); +#endif diff --git a/src/forward.c b/src/forward.c new file mode 100644 index 0000000..92bc6b0 --- /dev/null +++ b/src/forward.c @@ -0,0 +1,1182 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +static struct frec *lookup_frec(unsigned short id, unsigned int crc); +static struct frec *lookup_frec_by_sender(unsigned short id, + union mysockaddr *addr, + unsigned int crc); +static unsigned short get_id(unsigned int crc); +static void free_frec(struct frec *f); +static struct randfd *allocate_rfd(int family); + +/* Send a UDP packet with its source address set as "source" + unless nowild is true, when we just send it with the kernel default */ +static void send_from(int fd, int nowild, char *packet, size_t len, + union mysockaddr *to, struct all_addr *source, + unsigned int iface) +{ + struct msghdr msg; + struct iovec iov[1]; + union { + struct cmsghdr align; /* this ensures alignment */ +#if defined(HAVE_LINUX_NETWORK) + char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; +#elif defined(IP_SENDSRCADDR) + char control[CMSG_SPACE(sizeof(struct in_addr))]; +#endif +#ifdef HAVE_IPV6 + char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +#endif + } control_u; + + iov[0].iov_base = packet; + iov[0].iov_len = len; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + msg.msg_name = to; + msg.msg_namelen = sa_len(to); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + if (!nowild) + { + struct cmsghdr *cmptr; + msg.msg_control = &control_u; + msg.msg_controllen = sizeof(control_u); + cmptr = CMSG_FIRSTHDR(&msg); + + if (to->sa.sa_family == AF_INET) + { +#if defined(HAVE_LINUX_NETWORK) + struct in_pktinfo p; + p.ipi_ifindex = 0; + p.ipi_spec_dst = source->addr.addr4; + memcpy(CMSG_DATA(cmptr), &p, sizeof(p)); + msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + cmptr->cmsg_level = SOL_IP; + cmptr->cmsg_type = IP_PKTINFO; +#elif defined(IP_SENDSRCADDR) + memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4)); + msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + cmptr->cmsg_level = IPPROTO_IP; + cmptr->cmsg_type = IP_SENDSRCADDR; +#endif + } + else +#ifdef HAVE_IPV6 + { + struct in6_pktinfo p; + p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */ + p.ipi6_addr = source->addr.addr6; + memcpy(CMSG_DATA(cmptr), &p, sizeof(p)); + msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmptr->cmsg_type = daemon->v6pktinfo; + cmptr->cmsg_level = IPV6_LEVEL; + } +#else + iface = 0; /* eliminate warning */ +#endif + } + + retry: + if (sendmsg(fd, &msg, 0) == -1) + { + /* certain Linux kernels seem to object to setting the source address in the IPv6 stack + by returning EINVAL from sendmsg. In that case, try again without setting the + source address, since it will nearly alway be correct anyway. IPv6 stinks. */ + if (errno == EINVAL && msg.msg_controllen) + { + msg.msg_controllen = 0; + goto retry; + } + if (retry_send()) + goto retry; + } +} + +static unsigned int search_servers(time_t now, struct all_addr **addrpp, + unsigned int qtype, char *qdomain, int *type, char **domain, int *norebind) + +{ + /* If the query ends in the domain in one of our servers, set + domain to point to that name. We find the largest match to allow both + domain.org and sub.domain.org to exist. */ + + unsigned int namelen = strlen(qdomain); + unsigned int matchlen = 0; + struct server *serv; + unsigned int flags = 0; + + for (serv = daemon->servers; serv; serv=serv->next) + /* domain matches take priority over NODOTS matches */ + if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0) + { + unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; + *type = SERV_FOR_NODOTS; + if (serv->flags & SERV_NO_ADDR) + flags = F_NXDOMAIN; + else if (serv->flags & SERV_LITERAL_ADDRESS) + { + if (sflag & qtype) + { + flags = sflag; + if (serv->addr.sa.sa_family == AF_INET) + *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; +#ifdef HAVE_IPV6 + else + *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; +#endif + } + else if (!flags || (flags & F_NXDOMAIN)) + flags = F_NOERR; + } + } + else if (serv->flags & SERV_HAS_DOMAIN) + { + unsigned int domainlen = strlen(serv->domain); + char *matchstart = qdomain + namelen - domainlen; + if (namelen >= domainlen && + hostname_isequal(matchstart, serv->domain) && + (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' )) + { + if (serv->flags & SERV_NO_REBIND) + *norebind = 1; + else + { + unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; + /* implement priority rules for --address and --server for same domain. + --address wins if the address is for the correct AF + --server wins otherwise. */ + if (domainlen != 0 && domainlen == matchlen) + { + if ((serv->flags & SERV_LITERAL_ADDRESS)) + { + if (!(sflag & qtype) && flags == 0) + continue; + } + else + { + if (flags & (F_IPV4 | F_IPV6)) + continue; + } + } + + if (domainlen >= matchlen) + { + *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND); + *domain = serv->domain; + matchlen = domainlen; + if (serv->flags & SERV_NO_ADDR) + flags = F_NXDOMAIN; + else if (serv->flags & SERV_LITERAL_ADDRESS) + { + if (sflag & qtype) + { + flags = sflag; + if (serv->addr.sa.sa_family == AF_INET) + *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; +#ifdef HAVE_IPV6 + else + *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; +#endif + } + else if (!flags || (flags & F_NXDOMAIN)) + flags = F_NOERR; + } + else + flags = 0; + } + } + } + } + + if (flags == 0 && !(qtype & F_NSRR) && + option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0) + /* don't forward simple names, make exception for NS queries and empty name. */ + flags = F_NXDOMAIN; + + if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now)) + flags = F_NOERR; + + if (flags) + { + int logflags = 0; + + if (flags == F_NXDOMAIN || flags == F_NOERR) + logflags = F_NEG | qtype; + + log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL); + } + else if ((*type) & SERV_USE_RESOLV) + { + *type = 0; /* use normal servers for this domain */ + *domain = NULL; + } + return flags; +} + +static int forward_query(int udpfd, union mysockaddr *udpaddr, + struct all_addr *dst_addr, unsigned int dst_iface, + struct dns_header *header, size_t plen, time_t now, struct frec *forward) +{ + char *domain = NULL; + int type = 0, norebind = 0; + struct all_addr *addrp = NULL; + unsigned int crc = questions_crc(header, plen, daemon->namebuff); + unsigned int flags = 0; + unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL); + struct server *start = NULL; + + /* RFC 4035: sect 4.6 para 2 */ + header->hb4 &= ~HB4_AD; + + /* may be no servers available. */ + if (!daemon->servers) + forward = NULL; + else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc))) + { + /* retry on existing query, send to all available servers */ + domain = forward->sentto->domain; + forward->sentto->failed_queries++; + if (!option_bool(OPT_ORDER)) + { + forward->forwardall = 1; + daemon->last_server = NULL; + } + type = forward->sentto->flags & SERV_TYPE; + if (!(start = forward->sentto->next)) + start = daemon->servers; /* at end of list, recycle */ + header->id = htons(forward->new_id); + } + else + { + if (gotname) + flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind); + + if (!flags && !(forward = get_new_frec(now, NULL))) + /* table full - server failure. */ + flags = F_NEG; + + if (forward) + { + forward->source = *udpaddr; + forward->dest = *dst_addr; + forward->iface = dst_iface; + forward->orig_id = ntohs(header->id); + forward->new_id = get_id(crc); + forward->fd = udpfd; + forward->crc = crc; + forward->forwardall = 0; + if (norebind) + forward->flags |= FREC_NOREBIND; + if (header->hb4 & HB4_CD) + forward->flags |= FREC_CHECKING_DISABLED; + + header->id = htons(forward->new_id); + + /* In strict_order mode, always try servers in the order + specified in resolv.conf, if a domain is given + always try all the available servers, + otherwise, use the one last known to work. */ + + if (type == 0) + { + if (option_bool(OPT_ORDER)) + start = daemon->servers; + else if (!(start = daemon->last_server) || + daemon->forwardcount++ > FORWARD_TEST || + difftime(now, daemon->forwardtime) > FORWARD_TIME) + { + start = daemon->servers; + forward->forwardall = 1; + daemon->forwardcount = 0; + daemon->forwardtime = now; + } + } + else + { + start = daemon->servers; + if (!option_bool(OPT_ORDER)) + forward->forwardall = 1; + } + } + } + + /* check for send errors here (no route to host) + if we fail to send to all nameservers, send back an error + packet straight away (helps modem users when offline) */ + + if (!flags && forward) + { + struct server *firstsentto = start; + int forwarded = 0; + + if (udpaddr && option_bool(OPT_ADD_MAC)) + plen = add_mac(header, plen, ((char *) header) + PACKETSZ, udpaddr); + + while (1) + { + /* only send to servers dealing with our domain. + domain may be NULL, in which case server->domain + must be NULL also. */ + + if (type == (start->flags & SERV_TYPE) && + (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) && + !(start->flags & SERV_LITERAL_ADDRESS)) + { + int fd; + + /* find server socket to use, may need to get random one. */ + if (start->sfd) + fd = start->sfd->fd; + else + { +#ifdef HAVE_IPV6 + if (start->addr.sa.sa_family == AF_INET6) + { + if (!forward->rfd6 && + !(forward->rfd6 = allocate_rfd(AF_INET6))) + break; + daemon->rfd_save = forward->rfd6; + fd = forward->rfd6->fd; + } + else +#endif + { + if (!forward->rfd4 && + !(forward->rfd4 = allocate_rfd(AF_INET))) + break; + daemon->rfd_save = forward->rfd4; + fd = forward->rfd4->fd; + } + } + + if (sendto(fd, (char *)header, plen, 0, + &start->addr.sa, + sa_len(&start->addr)) == -1) + { + if (retry_send()) + continue; + } + else + { + /* Keep info in case we want to re-send this packet */ + daemon->srv_save = start; + daemon->packet_len = plen; + + if (!gotname) + strcpy(daemon->namebuff, "query"); + if (start->addr.sa.sa_family == AF_INET) + log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&start->addr.in.sin_addr, NULL); +#ifdef HAVE_IPV6 + else + log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&start->addr.in6.sin6_addr, NULL); +#endif + start->queries++; + forwarded = 1; + forward->sentto = start; + if (!forward->forwardall) + break; + forward->forwardall++; + } + } + + if (!(start = start->next)) + start = daemon->servers; + + if (start == firstsentto) + break; + } + + if (forwarded) + return 1; + + /* could not send on, prepare to return */ + header->id = htons(forward->orig_id); + free_frec(forward); /* cancel */ + } + + /* could not send on, return empty answer or address if known for whole domain */ + if (udpfd != -1) + { + plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl); + send_from(udpfd, option_bool(OPT_NOWILD), (char *)header, plen, udpaddr, dst_addr, dst_iface); + } + + return 0; +} + +static size_t process_reply(struct dns_header *header, time_t now, + struct server *server, size_t n, int check_rebind, int checking_disabled) +{ + unsigned char *pheader, *sizep; + int munged = 0, is_sign; + size_t plen; + + /* If upstream is advertising a larger UDP packet size + than we allow, trim it so that we don't get overlarge + requests for the client. We can't do this for signed packets. */ + + if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign) + { + unsigned short udpsz; + unsigned char *psave = sizep; + + GETSHORT(udpsz, sizep); + if (udpsz > daemon->edns_pktsz) + PUTSHORT(daemon->edns_pktsz, psave); + } + + /* RFC 4035 sect 4.6 para 3 */ + if (!is_sign && !option_bool(OPT_DNSSEC)) + header->hb4 &= ~HB4_AD; + + if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN)) + return n; + + /* Complain loudly if the upstream server is non-recursive. */ + if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR && ntohs(header->ancount) == 0 && + server && !(server->flags & SERV_WARNED_RECURSIVE)) + { + prettyprint_addr(&server->addr, daemon->namebuff); + my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff); + if (!option_bool(OPT_LOG)) + server->flags |= SERV_WARNED_RECURSIVE; + } + + if (daemon->bogus_addr && RCODE(header) != NXDOMAIN && + check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now)) + { + munged = 1; + SET_RCODE(header, NXDOMAIN); + header->hb3 &= ~HB3_AA; + } + else + { + if (RCODE(header) == NXDOMAIN && + extract_request(header, n, daemon->namebuff, NULL) && + check_for_local_domain(daemon->namebuff, now)) + { + /* if we forwarded a query for a locally known name (because it was for + an unknown type) and the answer is NXDOMAIN, convert that to NODATA, + since we know that the domain exists, even if upstream doesn't */ + munged = 1; + header->hb3 |= HB3_AA; + SET_RCODE(header, NOERROR); + } + + if (extract_addresses(header, n, daemon->namebuff, now, is_sign, check_rebind, checking_disabled)) + { + my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff); + munged = 1; + } + } + + /* do this after extract_addresses. Ensure NODATA reply and remove + nameserver info. */ + + if (munged) + { + header->ancount = htons(0); + header->nscount = htons(0); + header->arcount = htons(0); + } + + /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide + sections of the packet. Find the new length here and put back pseudoheader + if it was removed. */ + return resize_packet(header, n, pheader, plen); +} + +/* sets new last_server */ +void reply_query(int fd, int family, time_t now) +{ + /* packet from peer server, extract data for cache, and send to + original requester */ + struct dns_header *header; + union mysockaddr serveraddr; + struct frec *forward; + socklen_t addrlen = sizeof(serveraddr); + ssize_t n = recvfrom(fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen); + size_t nn; + struct server *server; + + /* packet buffer overwritten */ + daemon->srv_save = NULL; + + /* Determine the address of the server replying so that we can mark that as good */ + serveraddr.sa.sa_family = family; +#ifdef HAVE_IPV6 + if (serveraddr.sa.sa_family == AF_INET6) + serveraddr.in6.sin6_flowinfo = 0; +#endif + + /* spoof check: answer must come from known server, */ + for (server = daemon->servers; server; server = server->next) + if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) && + sockaddr_isequal(&server->addr, &serveraddr)) + break; + + header = (struct dns_header *)daemon->packet; + + if (!server || + n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) || + !(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff)))) + return; + + server = forward->sentto; + + if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) && + !option_bool(OPT_ORDER) && + forward->forwardall == 0) + /* for broken servers, attempt to send to another one. */ + { + unsigned char *pheader; + size_t plen; + int is_sign; + + /* recreate query from reply */ + pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign); + if (!is_sign) + { + header->ancount = htons(0); + header->nscount = htons(0); + header->arcount = htons(0); + if ((nn = resize_packet(header, (size_t)n, pheader, plen))) + { + header->hb3 &= ~(HB3_QR | HB3_TC); + forward_query(-1, NULL, NULL, 0, header, nn, now, forward); + return; + } + } + } + + if ((forward->sentto->flags & SERV_TYPE) == 0) + { + if (RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) + server = NULL; + else + { + struct server *last_server; + + /* find good server by address if possible, otherwise assume the last one we sent to */ + for (last_server = daemon->servers; last_server; last_server = last_server->next) + if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) && + sockaddr_isequal(&last_server->addr, &serveraddr)) + { + server = last_server; + break; + } + } + if (!option_bool(OPT_ALL_SERVERS)) + daemon->last_server = server; + } + + /* If the answer is an error, keep the forward record in place in case + we get a good reply from another server. Kill it when we've + had replies from all to avoid filling the forwarding table when + everything is broken */ + if (forward->forwardall == 0 || --forward->forwardall == 1 || + (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL)) + { + int check_rebind = !(forward->flags & FREC_NOREBIND); + + if (!option_bool(OPT_NO_REBIND)) + check_rebind = 0; + + if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, forward->flags & FREC_CHECKING_DISABLED))) + { + header->id = htons(forward->orig_id); + header->hb4 |= HB4_RA; /* recursion if available */ + send_from(forward->fd, option_bool(OPT_NOWILD), daemon->packet, nn, + &forward->source, &forward->dest, forward->iface); + } + free_frec(forward); /* cancel */ + } +} + + +void receive_query(struct listener *listen, time_t now) +{ + struct dns_header *header = (struct dns_header *)daemon->packet; + union mysockaddr source_addr; + unsigned short type; + struct all_addr dst_addr; + struct in_addr netmask, dst_addr_4; + size_t m; + ssize_t n; + int if_index = 0; + struct iovec iov[1]; + struct msghdr msg; + struct cmsghdr *cmptr; + union { + struct cmsghdr align; /* this ensures alignment */ +#ifdef HAVE_IPV6 + char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +#endif +#if defined(HAVE_LINUX_NETWORK) + char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; +#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK) + char control[CMSG_SPACE(sizeof(struct in_addr)) + + CMSG_SPACE(sizeof(unsigned int))]; +#elif defined(IP_RECVDSTADDR) + char control[CMSG_SPACE(sizeof(struct in_addr)) + + CMSG_SPACE(sizeof(struct sockaddr_dl))]; +#endif + } control_u; + + /* packet buffer overwritten */ + daemon->srv_save = NULL; + + if (listen->family == AF_INET && option_bool(OPT_NOWILD)) + { + dst_addr_4 = listen->iface->addr.in.sin_addr; + netmask = listen->iface->netmask; + } + else + { + dst_addr_4.s_addr = 0; + netmask.s_addr = 0; + } + + iov[0].iov_base = daemon->packet; + iov[0].iov_len = daemon->edns_pktsz; + + msg.msg_control = control_u.control; + msg.msg_controllen = sizeof(control_u); + msg.msg_flags = 0; + msg.msg_name = &source_addr; + msg.msg_namelen = sizeof(source_addr); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + if ((n = recvmsg(listen->fd, &msg, 0)) == -1) + return; + + if (n < (int)sizeof(struct dns_header) || + (msg.msg_flags & MSG_TRUNC) || + (header->hb3 & HB3_QR)) + return; + + source_addr.sa.sa_family = listen->family; +#ifdef HAVE_IPV6 + if (listen->family == AF_INET6) + source_addr.in6.sin6_flowinfo = 0; +#endif + + if (!option_bool(OPT_NOWILD)) + { + struct ifreq ifr; + + if (msg.msg_controllen < sizeof(struct cmsghdr)) + return; + +#if defined(HAVE_LINUX_NETWORK) + if (listen->family == AF_INET) + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) + { + union { + unsigned char *c; + struct in_pktinfo *p; + } p; + p.c = CMSG_DATA(cmptr); + dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst; + if_index = p.p->ipi_ifindex; + } +#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) + if (listen->family == AF_INET) + { + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + { + union { + unsigned char *c; + unsigned int *i; + struct in_addr *a; +#ifndef HAVE_SOLARIS_NETWORK + struct sockaddr_dl *s; +#endif + } p; + p.c = CMSG_DATA(cmptr); + if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) + dst_addr_4 = dst_addr.addr.addr4 = *(p.a); + else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) +#ifdef HAVE_SOLARIS_NETWORK + if_index = *(p.i); +#else + if_index = p.s->sdl_index; +#endif + } + } +#endif + +#ifdef HAVE_IPV6 + if (listen->family == AF_INET6) + { + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == daemon->v6pktinfo) + { + union { + unsigned char *c; + struct in6_pktinfo *p; + } p; + p.c = CMSG_DATA(cmptr); + + dst_addr.addr.addr6 = p.p->ipi6_addr; + if_index = p.p->ipi6_ifindex; + } + } +#endif + + /* enforce available interface configuration */ + + if (!indextoname(listen->fd, if_index, ifr.ifr_name) || + !iface_check(listen->family, &dst_addr, ifr.ifr_name, &if_index)) + return; + + if (listen->family == AF_INET && + option_bool(OPT_LOCALISE) && + ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1) + return; + + netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + } + + if (extract_request(header, (size_t)n, daemon->namebuff, &type)) + { + char types[20]; + + querystr(types, type); + + if (listen->family == AF_INET) + log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&source_addr.in.sin_addr, types); +#ifdef HAVE_IPV6 + else + log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&source_addr.in6.sin6_addr, types); +#endif + } + + m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, + dst_addr_4, netmask, now); + if (m >= 1) + { + send_from(listen->fd, option_bool(OPT_NOWILD), (char *)header, + m, &source_addr, &dst_addr, if_index); + daemon->local_answer++; + } + else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index, + header, (size_t)n, now, NULL)) + daemon->queries_forwarded++; + else + daemon->local_answer++; +} + +/* The daemon forks before calling this: it should deal with one connection, + blocking as neccessary, and then return. Note, need to be a bit careful + about resources for debug mode, when the fork is suppressed: that's + done by the caller. */ +unsigned char *tcp_request(int confd, time_t now, + struct in_addr local_addr, struct in_addr netmask) +{ + size_t size = 0; + int norebind = 0; + int checking_disabled; + size_t m; + unsigned short qtype, gotname; + unsigned char c1, c2; + /* Max TCP packet + slop */ + unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ); + struct dns_header *header; + struct server *last_server; + + while (1) + { + if (!packet || + !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) || + !(size = c1 << 8 | c2) || + !read_write(confd, packet, size, 1)) + return packet; + + if (size < (int)sizeof(struct dns_header)) + continue; + + header = (struct dns_header *)packet; + + /* save state of "cd" flag in query */ + checking_disabled = header->hb4 & HB4_CD; + + /* RFC 4035: sect 4.6 para 2 */ + header->hb4 &= ~HB4_AD; + + if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype))) + { + union mysockaddr peer_addr; + socklen_t peer_len = sizeof(union mysockaddr); + + if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1) + { + char types[20]; + + querystr(types, qtype); + + if (peer_addr.sa.sa_family == AF_INET) + log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&peer_addr.in.sin_addr, types); +#ifdef HAVE_IPV6 + else + log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&peer_addr.in6.sin6_addr, types); +#endif + } + } + + /* m > 0 if answered from cache */ + m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, + local_addr, netmask, now); + + /* Do this by steam now we're not in the select() loop */ + check_log_writer(NULL); + + if (m == 0) + { + unsigned int flags = 0; + struct all_addr *addrp = NULL; + int type = 0; + char *domain = NULL; + + if (option_bool(OPT_ADD_MAC)) + { + union mysockaddr peer_addr; + socklen_t peer_len = sizeof(union mysockaddr); + + if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1) + size = add_mac(header, size, ((char *) header) + 65536, &peer_addr); + } + + if (gotname) + flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind); + + if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server) + last_server = daemon->servers; + else + last_server = daemon->last_server; + + if (!flags && last_server) + { + struct server *firstsendto = NULL; + unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff); + + /* Loop round available servers until we succeed in connecting to one. + Note that this code subtley ensures that consecutive queries on this connection + which can go to the same server, do so. */ + while (1) + { + if (!firstsendto) + firstsendto = last_server; + else + { + if (!(last_server = last_server->next)) + last_server = daemon->servers; + + if (last_server == firstsendto) + break; + } + + /* server for wrong domain */ + if (type != (last_server->flags & SERV_TYPE) || + (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain))) + continue; + + if ((last_server->tcpfd == -1) && + (last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 && + (!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) || + connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)) + { + close(last_server->tcpfd); + last_server->tcpfd = -1; + } + + if (last_server->tcpfd == -1) + continue; + + c1 = size >> 8; + c2 = size; + + if (!read_write(last_server->tcpfd, &c1, 1, 0) || + !read_write(last_server->tcpfd, &c2, 1, 0) || + !read_write(last_server->tcpfd, packet, size, 0) || + !read_write(last_server->tcpfd, &c1, 1, 1) || + !read_write(last_server->tcpfd, &c2, 1, 1)) + { + close(last_server->tcpfd); + last_server->tcpfd = -1; + continue; + } + + m = (c1 << 8) | c2; + if (!read_write(last_server->tcpfd, packet, m, 1)) + return packet; + + if (!gotname) + strcpy(daemon->namebuff, "query"); + if (last_server->addr.sa.sa_family == AF_INET) + log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&last_server->addr.in.sin_addr, NULL); +#ifdef HAVE_IPV6 + else + log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, + (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL); +#endif + + /* There's no point in updating the cache, since this process will exit and + lose the information after a few queries. We make this call for the alias and + bogus-nxdomain side-effects. */ + /* If the crc of the question section doesn't match the crc we sent, then + someone might be attempting to insert bogus values into the cache by + sending replies containing questions and bogus answers. */ + if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff)) + m = process_reply(header, now, last_server, (unsigned int)m, + option_bool(OPT_NO_REBIND) && !norebind, checking_disabled); + + break; + } + } + + /* In case of local answer or no connections made. */ + if (m == 0) + m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl); + } + + check_log_writer(NULL); + + c1 = m>>8; + c2 = m; + if (!read_write(confd, &c1, 1, 0) || + !read_write(confd, &c2, 1, 0) || + !read_write(confd, packet, m, 0)) + return packet; + } +} + +static struct frec *allocate_frec(time_t now) +{ + struct frec *f; + + if ((f = (struct frec *)whine_malloc(sizeof(struct frec)))) + { + f->next = daemon->frec_list; + f->time = now; + f->sentto = NULL; + f->rfd4 = NULL; + f->flags = 0; +#ifdef HAVE_IPV6 + f->rfd6 = NULL; +#endif + daemon->frec_list = f; + } + + return f; +} + +static struct randfd *allocate_rfd(int family) +{ + static int finger = 0; + int i; + + /* limit the number of sockets we have open to avoid starvation of + (eg) TFTP. Once we have a reasonable number, randomness should be OK */ + + for (i = 0; i < RANDOM_SOCKS; i++) + if (daemon->randomsocks[i].refcount == 0) + { + if ((daemon->randomsocks[i].fd = random_sock(family)) == -1) + break; + + daemon->randomsocks[i].refcount = 1; + daemon->randomsocks[i].family = family; + return &daemon->randomsocks[i]; + } + + /* No free ones or cannot get new socket, grab an existing one */ + for (i = 0; i < RANDOM_SOCKS; i++) + { + int j = (i+finger) % RANDOM_SOCKS; + if (daemon->randomsocks[j].refcount != 0 && + daemon->randomsocks[j].family == family && + daemon->randomsocks[j].refcount != 0xffff) + { + finger = j; + daemon->randomsocks[j].refcount++; + return &daemon->randomsocks[j]; + } + } + + return NULL; /* doom */ +} + +static void free_frec(struct frec *f) +{ + if (f->rfd4 && --(f->rfd4->refcount) == 0) + close(f->rfd4->fd); + + f->rfd4 = NULL; + f->sentto = NULL; + f->flags = 0; + +#ifdef HAVE_IPV6 + if (f->rfd6 && --(f->rfd6->refcount) == 0) + close(f->rfd6->fd); + + f->rfd6 = NULL; +#endif +} + +/* if wait==NULL return a free or older than TIMEOUT record. + else return *wait zero if one available, or *wait is delay to + when the oldest in-use record will expire. Impose an absolute + limit of 4*TIMEOUT before we wipe things (for random sockets) */ +struct frec *get_new_frec(time_t now, int *wait) +{ + struct frec *f, *oldest, *target; + int count; + + if (wait) + *wait = 0; + + for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++) + if (!f->sentto) + target = f; + else + { + if (difftime(now, f->time) >= 4*TIMEOUT) + { + free_frec(f); + target = f; + } + + if (!oldest || difftime(f->time, oldest->time) <= 0) + oldest = f; + } + + if (target) + { + target->time = now; + return target; + } + + /* can't find empty one, use oldest if there is one + and it's older than timeout */ + if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT) + { + /* keep stuff for twice timeout if we can by allocating a new + record instead */ + if (difftime(now, oldest->time) < 2*TIMEOUT && + count <= daemon->ftabsize && + (f = allocate_frec(now))) + return f; + + if (!wait) + { + free_frec(oldest); + oldest->time = now; + } + return oldest; + } + + /* none available, calculate time 'till oldest record expires */ + if (count > daemon->ftabsize) + { + if (oldest && wait) + *wait = oldest->time + (time_t)TIMEOUT - now; + return NULL; + } + + if (!(f = allocate_frec(now)) && wait) + /* wait one second on malloc failure */ + *wait = 1; + + return f; /* OK if malloc fails and this is NULL */ +} + +/* crc is all-ones if not known. */ +static struct frec *lookup_frec(unsigned short id, unsigned int crc) +{ + struct frec *f; + + for(f = daemon->frec_list; f; f = f->next) + if (f->sentto && f->new_id == id && + (f->crc == crc || crc == 0xffffffff)) + return f; + + return NULL; +} + +static struct frec *lookup_frec_by_sender(unsigned short id, + union mysockaddr *addr, + unsigned int crc) +{ + struct frec *f; + + for(f = daemon->frec_list; f; f = f->next) + if (f->sentto && + f->orig_id == id && + f->crc == crc && + sockaddr_isequal(&f->source, addr)) + return f; + + return NULL; +} + +/* A server record is going away, remove references to it */ +void server_gone(struct server *server) +{ + struct frec *f; + + for (f = daemon->frec_list; f; f = f->next) + if (f->sentto && f->sentto == server) + free_frec(f); + + if (daemon->last_server == server) + daemon->last_server = NULL; + + if (daemon->srv_save == server) + daemon->srv_save = NULL; +} + +/* return unique random ids. */ +static unsigned short get_id(unsigned int crc) +{ + unsigned short ret = 0; + + do + ret = rand16(); + while (lookup_frec(ret, crc)); + + return ret; +} + + + + + diff --git a/src/helper.c b/src/helper.c new file mode 100644 index 0000000..93f99f0 --- /dev/null +++ b/src/helper.c @@ -0,0 +1,410 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +/* This file has code to fork a helper process which recieves data via a pipe + shared with the main process and which is responsible for calling a script when + DHCP leases change. + + The helper process is forked before the main process drops root, so it retains root + privs to pass on to the script. For this reason it tries to be paranoid about + data received from the main process, in case that has been compromised. We don't + want the helper to give an attacker root. In particular, the script to be run is + not settable via the pipe, once the fork has taken place it is not alterable by the + main process. +*/ + +#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT) + +static void my_setenv(const char *name, const char *value, int *error); +static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end, char *env, int *err); + +struct script_data +{ + unsigned char action, hwaddr_len, hwaddr_type; + unsigned char clid_len, hostname_len, ed_len; + struct in_addr addr, giaddr; + unsigned int remaining_time; +#ifdef HAVE_BROKEN_RTC + unsigned int length; +#else + time_t expires; +#endif + unsigned char hwaddr[DHCP_CHADDR_MAX]; + char interface[IF_NAMESIZE]; +}; + +static struct script_data *buf = NULL; +static size_t bytes_in_buf = 0, buf_size = 0; + +int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) +{ + pid_t pid; + int i, pipefd[2]; + struct sigaction sigact; + + /* create the pipe through which the main program sends us commands, + then fork our process. */ + if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1) + { + send_event(err_fd, EVENT_PIPE_ERR, errno); + _exit(0); + } + + if (pid != 0) + { + close(pipefd[0]); /* close reader side */ + return pipefd[1]; + } + + /* ignore SIGTERM, so that we can clean up when the main process gets hit + and SIGALRM so that we can use sleep() */ + sigact.sa_handler = SIG_IGN; + sigact.sa_flags = 0; + sigemptyset(&sigact.sa_mask); + sigaction(SIGTERM, &sigact, NULL); + sigaction(SIGALRM, &sigact, NULL); + + if (!option_bool(OPT_DEBUG) && uid != 0) + { + gid_t dummy; + if (setgroups(0, &dummy) == -1 || + setgid(gid) == -1 || + setuid(uid) == -1) + { + if (option_bool(OPT_NO_FORK)) + /* send error to daemon process if no-fork */ + send_event(event_fd, EVENT_HUSER_ERR, errno); + else + { + /* kill daemon */ + send_event(event_fd, EVENT_DIE, 0); + /* return error */ + send_event(err_fd, EVENT_HUSER_ERR, errno); + } + _exit(0); + } + } + + /* close all the sockets etc, we don't need them here. This closes err_fd, so that + main process can return. */ + for (max_fd--; max_fd >= 0; max_fd--) + if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && + max_fd != STDIN_FILENO && max_fd != pipefd[0] && max_fd != event_fd) + close(max_fd); + + /* loop here */ + while(1) + { + struct script_data data; + char *p, *action_str, *hostname = NULL; + unsigned char *buf = (unsigned char *)daemon->namebuff; + unsigned char *end, *alloc_buff = NULL; + int err = 0; + + /* we read zero bytes when pipe closed: this is our signal to exit */ + if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1)) + _exit(0); + + if (data.action == ACTION_DEL) + action_str = "del"; + else if (data.action == ACTION_ADD) + action_str = "add"; + else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME) + action_str = "old"; + else + continue; + + /* stringify MAC into dhcp_buff */ + p = daemon->dhcp_buff; + if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0) + p += sprintf(p, "%.2x-", data.hwaddr_type); + for (i = 0; (i < data.hwaddr_len) && (i < DHCP_CHADDR_MAX); i++) + { + p += sprintf(p, "%.2x", data.hwaddr[i]); + if (i != data.hwaddr_len - 1) + p += sprintf(p, ":"); + } + + /* and CLID into packet, avoid overwrite from bad data */ + if ((data.clid_len > daemon->packet_buff_sz) || !read_write(pipefd[0], buf, data.clid_len, 1)) + continue; + for (p = daemon->packet, i = 0; i < data.clid_len; i++) + { + p += sprintf(p, "%.2x", buf[i]); + if (i != data.clid_len - 1) + p += sprintf(p, ":"); + } + + /* and expiry or length into dhcp_buff2 */ +#ifdef HAVE_BROKEN_RTC + sprintf(daemon->dhcp_buff2, "%u", data.length); +#else + sprintf(daemon->dhcp_buff2, "%lu", (unsigned long)data.expires); +#endif + + /* supplied data may just exceed normal buffer (unlikely) */ + if ((data.hostname_len + data.ed_len) > daemon->packet_buff_sz && + !(alloc_buff = buf = malloc(data.hostname_len + data.ed_len))) + continue; + + if (!read_write(pipefd[0], buf, + data.hostname_len + data.ed_len, 1)) + continue; + + /* possible fork errors are all temporary resource problems */ + while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM)) + sleep(2); + + free(alloc_buff); + + if (pid == -1) + continue; + + /* wait for child to complete */ + if (pid != 0) + { + /* reap our children's children, if necessary */ + while (1) + { + int status; + pid_t rc = wait(&status); + + if (rc == pid) + { + /* On error send event back to main process for logging */ + if (WIFSIGNALED(status)) + send_event(event_fd, EVENT_KILLED, WTERMSIG(status)); + else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) + send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status)); + break; + } + + if (rc == -1 && errno != EINTR) + break; + } + + continue; + } + + if (data.clid_len != 0) + my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err); + + if (strlen(data.interface) != 0) + my_setenv("DNSMASQ_INTERFACE", data.interface, &err); + +#ifdef HAVE_BROKEN_RTC + my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err); +#else + my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); +#endif + + if (data.hostname_len != 0) + { + char *dot; + hostname = (char *)buf; + hostname[data.hostname_len - 1] = 0; + if (!legal_hostname(hostname)) + hostname = NULL; + else if ((dot = strchr(hostname, '.'))) + { + my_setenv("DNSMASQ_DOMAIN", dot+1, &err); + *dot = 0; + } + buf += data.hostname_len; + } + + end = buf + data.ed_len; + buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err); + buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err); + buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err); + buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err); + buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err); + buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); + + for (i = 0; buf; i++) + { + sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i); + buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); + } + + if (data.giaddr.s_addr != 0) + my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err); + + if (data.action != ACTION_DEL) + { + sprintf(daemon->dhcp_buff2, "%u", data.remaining_time); + my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err); + } + + if (data.action == ACTION_OLD_HOSTNAME && hostname) + { + my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err); + hostname = NULL; + } + + /* we need to have the event_fd around if exec fails */ + if ((i = fcntl(event_fd, F_GETFD)) != -1) + fcntl(event_fd, F_SETFD, i | FD_CLOEXEC); + close(pipefd[0]); + + p = strrchr(daemon->lease_change_command, '/'); + if (err == 0) + { + execl(daemon->lease_change_command, + p ? p+1 : daemon->lease_change_command, + action_str, daemon->dhcp_buff, inet_ntoa(data.addr), hostname, (char*)NULL); + err = errno; + } + /* failed, send event so the main process logs the problem */ + send_event(event_fd, EVENT_EXEC_ERR, err); + _exit(0); + } +} + +static void my_setenv(const char *name, const char *value, int *error) +{ + if (*error == 0 && setenv(name, value, 1) != 0) + *error = errno; +} + +static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end, char *env, int *err) +{ + unsigned char *next; + + if (!buf || (buf == end)) + return NULL; + + for (next = buf; *next != 0; next++) + if (next == end) + return NULL; + + if (next != buf) + { + char *p; + /* No "=" in value */ + if ((p = strchr((char *)buf, '='))) + *p = 0; + my_setenv(env, (char *)buf, err); + } + + return next + 1; +} + +/* pack up lease data into a buffer */ +void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now) +{ + unsigned char *p; + size_t size; + unsigned int hostname_len = 0, clid_len = 0, ed_len = 0; + + /* no script */ + if (daemon->helperfd == -1) + return; + + if (lease->extradata) + ed_len = lease->extradata_len; + if (lease->clid) + clid_len = lease->clid_len; + if (hostname) + hostname_len = strlen(hostname) + 1; + + size = sizeof(struct script_data) + clid_len + ed_len + hostname_len; + + if (size > buf_size) + { + struct script_data *new; + + /* start with reasonable size, will almost never need extending. */ + if (size < sizeof(struct script_data) + 200) + size = sizeof(struct script_data) + 200; + + if (!(new = whine_malloc(size))) + return; + if (buf) + free(buf); + buf = new; + buf_size = size; + } + + buf->action = action; + buf->hwaddr_len = lease->hwaddr_len; + buf->hwaddr_type = lease->hwaddr_type; + buf->clid_len = clid_len; + buf->ed_len = ed_len; + buf->hostname_len = hostname_len; + buf->addr = lease->addr; + buf->giaddr = lease->giaddr; + memcpy(buf->hwaddr, lease->hwaddr, lease->hwaddr_len); + if (!indextoname(daemon->dhcpfd, lease->last_interface, buf->interface)) + buf->interface[0] = 0; + +#ifdef HAVE_BROKEN_RTC + buf->length = lease->length; +#else + buf->expires = lease->expires; +#endif + buf->remaining_time = (unsigned int)difftime(lease->expires, now); + + p = (unsigned char *)(buf+1); + if (clid_len != 0) + { + memcpy(p, lease->clid, clid_len); + p += clid_len; + } + if (hostname_len != 0) + { + memcpy(p, hostname, hostname_len); + p += hostname_len; + } + if (ed_len != 0) + { + memcpy(p, lease->extradata, ed_len); + p += ed_len; + } + bytes_in_buf = p - (unsigned char *)buf; +} + +int helper_buf_empty(void) +{ + return bytes_in_buf == 0; +} + +void helper_write(void) +{ + ssize_t rc; + + if (bytes_in_buf == 0) + return; + + if ((rc = write(daemon->helperfd, buf, bytes_in_buf)) != -1) + { + if (bytes_in_buf != (size_t)rc) + memmove(buf, buf + rc, bytes_in_buf - rc); + bytes_in_buf -= rc; + } + else + { + if (errno == EAGAIN || errno == EINTR) + return; + bytes_in_buf = 0; + } +} + +#endif + + diff --git a/src/lease.c b/src/lease.c new file mode 100644 index 0000000..cfa7543 --- /dev/null +++ b/src/lease.c @@ -0,0 +1,615 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#ifdef HAVE_DHCP + +static struct dhcp_lease *leases = NULL, *old_leases = NULL; +static int dns_dirty, file_dirty, leases_left; + +void lease_init(time_t now) +{ + unsigned long ei; + struct in_addr addr; + struct dhcp_lease *lease; + int clid_len, hw_len, hw_type; + FILE *leasestream; + + /* These each hold a DHCP option max size 255 + and get a terminating zero added */ + daemon->dhcp_buff = safe_malloc(256); + daemon->dhcp_buff2 = safe_malloc(256); + daemon->dhcp_buff3 = safe_malloc(256); + + leases_left = daemon->dhcp_max; + + if (option_bool(OPT_LEASE_RO)) + { + /* run "<lease_change_script> init" once to get the + initial state of the database. If leasefile-ro is + set without a script, we just do without any + lease database. */ +#ifdef HAVE_SCRIPT + if (daemon->lease_change_command) + { + strcpy(daemon->dhcp_buff, daemon->lease_change_command); + strcat(daemon->dhcp_buff, " init"); + leasestream = popen(daemon->dhcp_buff, "r"); + } + else +#endif + { + file_dirty = dns_dirty = 0; + return; + } + + } + else + { + /* NOTE: need a+ mode to create file if it doesn't exist */ + leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+"); + + if (!leasestream) + die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE); + + /* a+ mode leaves pointer at end. */ + rewind(leasestream); + } + + /* client-id max length is 255 which is 255*2 digits + 254 colons + borrow DNS packet buffer which is always larger than 1000 bytes */ + if (leasestream) + while (fscanf(leasestream, "%lu %255s %16s %255s %764s", + &ei, daemon->dhcp_buff2, daemon->namebuff, + daemon->dhcp_buff, daemon->packet) == 5) + { + hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type); + /* For backwards compatibility, no explict MAC address type means ether. */ + if (hw_type == 0 && hw_len != 0) + hw_type = ARPHRD_ETHER; + + addr.s_addr = inet_addr(daemon->namebuff); + + /* decode hex in place */ + clid_len = 0; + if (strcmp(daemon->packet, "*") != 0) + clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL); + + if (!(lease = lease_allocate(addr))) + die (_("too many stored leases"), NULL, EC_MISC); + +#ifdef HAVE_BROKEN_RTC + if (ei != 0) + lease->expires = (time_t)ei + now; + else + lease->expires = (time_t)0; + lease->length = ei; +#else + /* strictly time_t is opaque, but this hack should work on all sane systems, + even when sizeof(time_t) == 8 */ + lease->expires = (time_t)ei; +#endif + + lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len); + + if (strcmp(daemon->dhcp_buff, "*") != 0) + lease_set_hostname(lease, daemon->dhcp_buff, 0); + + /* set these correctly: the "old" events are generated later from + the startup synthesised SIGHUP. */ + lease->new = lease->changed = 0; + } + +#ifdef HAVE_SCRIPT + if (!daemon->lease_stream) + { + int rc = 0; + + /* shell returns 127 for "command not found", 126 for bad permissions. */ + if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126) + { + if (WEXITSTATUS(rc) == 127) + errno = ENOENT; + else if (WEXITSTATUS(rc) == 126) + errno = EACCES; + die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE); + } + + if (WEXITSTATUS(rc) != 0) + { + sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc)); + die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET); + } + } +#endif + + /* Some leases may have expired */ + file_dirty = 0; + lease_prune(NULL, now); + dns_dirty = 1; +} + +void lease_update_from_configs(void) +{ + /* changes to the config may change current leases. */ + + struct dhcp_lease *lease; + struct dhcp_config *config; + char *name; + + for (lease = leases; lease; lease = lease->next) + if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, + lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && + (config->flags & CONFIG_NAME) && + (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr)) + lease_set_hostname(lease, config->hostname, 1); + else if ((name = host_from_dns(lease->addr))) + lease_set_hostname(lease, name, 1); /* updates auth flag only */ +} + +static void ourprintf(int *errp, char *format, ...) +{ + va_list ap; + + va_start(ap, format); + if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0) + *errp = errno; + va_end(ap); +} + +void lease_update_file(time_t now) +{ + struct dhcp_lease *lease; + time_t next_event; + int i, err = 0; + + if (file_dirty != 0 && daemon->lease_stream) + { + errno = 0; + rewind(daemon->lease_stream); + if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0) + err = errno; + + for (lease = leases; lease; lease = lease->next) + { +#ifdef HAVE_BROKEN_RTC + ourprintf(&err, "%u ", lease->length); +#else + ourprintf(&err, "%lu ", (unsigned long)lease->expires); +#endif + if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) + ourprintf(&err, "%.2x-", lease->hwaddr_type); + for (i = 0; i < lease->hwaddr_len; i++) + { + ourprintf(&err, "%.2x", lease->hwaddr[i]); + if (i != lease->hwaddr_len - 1) + ourprintf(&err, ":"); + } + + ourprintf(&err, " %s ", inet_ntoa(lease->addr)); + ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*"); + + if (lease->clid && lease->clid_len != 0) + { + for (i = 0; i < lease->clid_len - 1; i++) + ourprintf(&err, "%.2x:", lease->clid[i]); + ourprintf(&err, "%.2x\n", lease->clid[i]); + } + else + ourprintf(&err, "*\n"); + } + + if (fflush(daemon->lease_stream) != 0 || + fsync(fileno(daemon->lease_stream)) < 0) + err = errno; + + if (!err) + file_dirty = 0; + } + + /* Set alarm for when the first lease expires + slop. */ + for (next_event = 0, lease = leases; lease; lease = lease->next) + if (lease->expires != 0 && + (next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0)) + next_event = lease->expires + 10; + + if (err) + { + if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0) + next_event = LEASE_RETRY + now; + + my_syslog(MS_DHCP | LOG_ERR, _("failed to write %s: %s (retry in %us)"), + daemon->lease_file, strerror(err), + (unsigned int)difftime(next_event, now)); + } + + if (next_event != 0) + alarm((unsigned)difftime(next_event, now)); +} + +void lease_update_dns(void) +{ + struct dhcp_lease *lease; + + if (daemon->port != 0 && dns_dirty) + { + cache_unhash_dhcp(); + + for (lease = leases; lease; lease = lease->next) + { + if (lease->fqdn) + cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires); + + if (!option_bool(OPT_DHCP_FQDN) && lease->hostname) + cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires); + } + + dns_dirty = 0; + } +} + +void lease_prune(struct dhcp_lease *target, time_t now) +{ + struct dhcp_lease *lease, *tmp, **up; + + for (lease = leases, up = &leases; lease; lease = tmp) + { + tmp = lease->next; + if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target) + { + file_dirty = 1; + if (lease->hostname) + dns_dirty = 1; + + *up = lease->next; /* unlink */ + + /* Put on old_leases list 'till we + can run the script */ + lease->next = old_leases; + old_leases = lease; + + leases_left++; + } + else + up = &lease->next; + } +} + + +struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type, + unsigned char *clid, int clid_len) +{ + struct dhcp_lease *lease; + + if (clid) + for (lease = leases; lease; lease = lease->next) + if (lease->clid && clid_len == lease->clid_len && + memcmp(clid, lease->clid, clid_len) == 0) + return lease; + + for (lease = leases; lease; lease = lease->next) + if ((!lease->clid || !clid) && + hw_len != 0 && + lease->hwaddr_len == hw_len && + lease->hwaddr_type == hw_type && + memcmp(hwaddr, lease->hwaddr, hw_len) == 0) + return lease; + + return NULL; +} + +struct dhcp_lease *lease_find_by_addr(struct in_addr addr) +{ + struct dhcp_lease *lease; + + for (lease = leases; lease; lease = lease->next) + if (lease->addr.s_addr == addr.s_addr) + return lease; + + return NULL; +} + + +struct dhcp_lease *lease_allocate(struct in_addr addr) +{ + struct dhcp_lease *lease; + if (!leases_left || !(lease = whine_malloc(sizeof(struct dhcp_lease)))) + return NULL; + + memset(lease, 0, sizeof(struct dhcp_lease)); + lease->new = 1; + lease->addr = addr; + lease->hwaddr_len = 256; /* illegal value */ + lease->expires = 1; +#ifdef HAVE_BROKEN_RTC + lease->length = 0xffffffff; /* illegal value */ +#endif + lease->next = leases; + leases = lease; + + file_dirty = 1; + leases_left--; + + return lease; +} + +void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now) +{ + time_t exp = now + (time_t)len; + + if (len == 0xffffffff) + { + exp = 0; + len = 0; + } + + if (exp != lease->expires) + { + dns_dirty = 1; + lease->expires = exp; +#ifndef HAVE_BROKEN_RTC + lease->aux_changed = file_dirty = 1; +#endif + } + +#ifdef HAVE_BROKEN_RTC + if (len != lease->length) + { + lease->length = len; + lease->aux_changed = file_dirty = 1; + } +#endif +} + +void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr, + unsigned char *clid, int hw_len, int hw_type, int clid_len) +{ + if (hw_len != lease->hwaddr_len || + hw_type != lease->hwaddr_type || + (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0)) + { + memcpy(lease->hwaddr, hwaddr, hw_len); + lease->hwaddr_len = hw_len; + lease->hwaddr_type = hw_type; + lease->changed = file_dirty = 1; /* run script on change */ + } + + /* only update clid when one is available, stops packets + without a clid removing the record. Lease init uses + clid_len == 0 for no clid. */ + if (clid_len != 0 && clid) + { + if (!lease->clid) + lease->clid_len = 0; + + if (lease->clid_len != clid_len) + { + lease->aux_changed = file_dirty = 1; + free(lease->clid); + if (!(lease->clid = whine_malloc(clid_len))) + return; + } + else if (memcmp(lease->clid, clid, clid_len) != 0) + lease->aux_changed = file_dirty = 1; + + lease->clid_len = clid_len; + memcpy(lease->clid, clid, clid_len); + } + +} + +static void kill_name(struct dhcp_lease *lease) +{ + /* run script to say we lost our old name */ + + /* this shouldn't happen unless updates are very quick and the + script very slow, we just avoid a memory leak if it does. */ + free(lease->old_hostname); + + /* If we know the fqdn, pass that. The helper will derive the + unqualified name from it, free the unqulaified name here. */ + + if (lease->fqdn) + { + lease->old_hostname = lease->fqdn; + free(lease->hostname); + } + else + lease->old_hostname = lease->hostname; + + lease->hostname = lease->fqdn = NULL; +} + +void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth) +{ + struct dhcp_lease *lease_tmp; + char *new_name = NULL, *new_fqdn = NULL; + + if (lease->hostname && name && hostname_isequal(lease->hostname, name)) + { + lease->auth_name = auth; + return; + } + + if (!name && !lease->hostname) + return; + + /* If a machine turns up on a new net without dropping the old lease, + or two machines claim the same name, then we end up with two interfaces with + the same name. Check for that here and remove the name from the old lease. + Don't allow a name from the client to override a name from dnsmasq config. */ + + if (name) + { + if ((new_name = whine_malloc(strlen(name) + 1))) + { + char *suffix = get_domain(lease->addr); + strcpy(new_name, name); + if (suffix && (new_fqdn = whine_malloc(strlen(new_name) + strlen(suffix) + 2))) + { + strcpy(new_fqdn, name); + strcat(new_fqdn, "."); + strcat(new_fqdn, suffix); + } + } + + /* Depending on mode, we check either unqualified name or FQDN. */ + for (lease_tmp = leases; lease_tmp; lease_tmp = lease_tmp->next) + { + if (option_bool(OPT_DHCP_FQDN)) + { + if (!new_fqdn || !lease_tmp->fqdn || !hostname_isequal(lease_tmp->fqdn, new_fqdn) ) + continue; + } + else + { + if (!new_name || !lease_tmp->hostname || !hostname_isequal(lease_tmp->hostname, new_name) ) + continue; + } + + if (lease_tmp->auth_name && !auth) + { + free(new_name); + free(new_fqdn); + return; + } + + kill_name(lease_tmp); + break; + } + } + + if (lease->hostname) + kill_name(lease); + + lease->hostname = new_name; + lease->fqdn = new_fqdn; + lease->auth_name = auth; + + file_dirty = 1; + dns_dirty = 1; + lease->changed = 1; /* run script on change */ +} + +void lease_set_interface(struct dhcp_lease *lease, int interface) +{ + if (lease->last_interface == interface) + return; + + lease->last_interface = interface; + lease->changed = 1; +} + +void rerun_scripts(void) +{ + struct dhcp_lease *lease; + + for (lease = leases; lease; lease = lease->next) + lease->changed = 1; +} + +/* deleted leases get transferred to the old_leases list. + remove them here, after calling the lease change + script. Also run the lease change script on new/modified leases. + + Return zero if nothing to do. */ +int do_script_run(time_t now) +{ + struct dhcp_lease *lease; + +#ifdef HAVE_DBUS + /* If we're going to be sending DBus signals, but the connection is not yet up, + delay everything until it is. */ + if (option_bool(OPT_DBUS) && !daemon->dbus) + return 0; +#endif + + if (old_leases) + { + lease = old_leases; + + /* If the lease still has an old_hostname, do the "old" action on that first */ + if (lease->old_hostname) + { +#ifdef HAVE_SCRIPT + queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); +#endif + free(lease->old_hostname); + lease->old_hostname = NULL; + return 1; + } + else + { + kill_name(lease); +#ifdef HAVE_SCRIPT + queue_script(ACTION_DEL, lease, lease->old_hostname, now); +#endif +#ifdef HAVE_DBUS + emit_dbus_signal(ACTION_DEL, lease, lease->old_hostname); +#endif + old_leases = lease->next; + + free(lease->old_hostname); + free(lease->clid); + free(lease->extradata); + free(lease); + + return 1; + } + } + + /* make sure we announce the loss of a hostname before its new location. */ + for (lease = leases; lease; lease = lease->next) + if (lease->old_hostname) + { +#ifdef HAVE_SCRIPT + queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now); +#endif + free(lease->old_hostname); + lease->old_hostname = NULL; + return 1; + } + + for (lease = leases; lease; lease = lease->next) + if (lease->new || lease->changed || + (lease->aux_changed && option_bool(OPT_LEASE_RO))) + { +#ifdef HAVE_SCRIPT + queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, + lease->fqdn ? lease->fqdn : lease->hostname, now); +#endif +#ifdef HAVE_DBUS + emit_dbus_signal(lease->new ? ACTION_ADD : ACTION_OLD, lease, + lease->fqdn ? lease->fqdn : lease->hostname); +#endif + lease->new = lease->changed = lease->aux_changed = 0; + + /* this is used for the "add" call, then junked, since they're not in the database */ + free(lease->extradata); + lease->extradata = NULL; + + return 1; + } + + return 0; /* nothing to do */ +} + +#endif + + + + diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..baaae7c --- /dev/null +++ b/src/log.c @@ -0,0 +1,466 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#ifdef __ANDROID__ +# include <android/log.h> +#endif + +/* Implement logging to /dev/log asynchronously. If syslogd is + making DNS lookups through dnsmasq, and dnsmasq blocks awaiting + syslogd, then the two daemons can deadlock. We get around this + by not blocking when talking to syslog, instead we queue up to + MAX_LOGS messages. If more are queued, they will be dropped, + and the drop event itself logged. */ + +/* The "wire" protocol for logging is defined in RFC 3164 */ + +/* From RFC 3164 */ +#define MAX_MESSAGE 1024 + +/* defaults in case we die() before we log_start() */ +static int log_fac = LOG_DAEMON; +static int log_stderr = 0; +static int echo_stderr = 0; +static int log_fd = -1; +static int log_to_file = 0; +static int entries_alloced = 0; +static int entries_lost = 0; +static int connection_good = 1; +static int max_logs = 0; +static int connection_type = SOCK_DGRAM; + +struct log_entry { + int offset, length; + pid_t pid; /* to avoid duplicates over a fork */ + struct log_entry *next; + char payload[MAX_MESSAGE]; +}; + +static struct log_entry *entries = NULL; +static struct log_entry *free_entries = NULL; + + +int log_start(struct passwd *ent_pw, int errfd) +{ + int ret = 0; + + echo_stderr = option_bool(OPT_DEBUG); + + if (daemon->log_fac != -1) + log_fac = daemon->log_fac; +#ifdef LOG_LOCAL0 + else if (option_bool(OPT_DEBUG)) + log_fac = LOG_LOCAL0; +#endif + + if (daemon->log_file) + { + log_to_file = 1; + daemon->max_logs = 0; + if (strcmp(daemon->log_file, "-") == 0) + { + log_stderr = 1; + echo_stderr = 0; + log_fd = dup(STDERR_FILENO); + } + } + + max_logs = daemon->max_logs; + + if (!log_reopen(daemon->log_file)) + { + send_event(errfd, EVENT_LOG_ERR, errno); + _exit(0); + } + + /* if queuing is inhibited, make sure we allocate + the one required buffer now. */ + if (max_logs == 0) + { + free_entries = safe_malloc(sizeof(struct log_entry)); + free_entries->next = NULL; + entries_alloced = 1; + } + + /* If we're running as root and going to change uid later, + change the ownership here so that the file is always owned by + the dnsmasq user. Then logrotate can just copy the owner. + Failure of the chown call is OK, (for instance when started as non-root) */ + if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0 && + fchown(log_fd, ent_pw->pw_uid, -1) != 0) + ret = errno; + + return ret; +} + +int log_reopen(char *log_file) +{ + if (!log_stderr) + { + if (log_fd != -1) + close(log_fd); + + /* NOTE: umask is set to 022 by the time this gets called */ + + if (log_file) + log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP); + else + { +#if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__) + /* Solaris logging is "different", /dev/log is not unix-domain socket. + Just leave log_fd == -1 and use the vsyslog call for everything.... */ +# define _PATH_LOG "" /* dummy */ + return 1; +#else + int flags; + log_fd = socket(AF_UNIX, connection_type, 0); + + /* if max_logs is zero, leave the socket blocking */ + if (log_fd != -1 && max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1) + fcntl(log_fd, F_SETFL, flags | O_NONBLOCK); +#endif + } + } + + return log_fd != -1; +} + +static void free_entry(void) +{ + struct log_entry *tmp = entries; + entries = tmp->next; + tmp->next = free_entries; + free_entries = tmp; +} + +static void log_write(void) +{ + ssize_t rc; + + while (entries) + { + /* Avoid duplicates over a fork() */ + if (entries->pid != getpid()) + { + free_entry(); + continue; + } + + connection_good = 1; + + if ((rc = write(log_fd, entries->payload + entries->offset, entries->length)) != -1) + { + entries->length -= rc; + entries->offset += rc; + if (entries->length == 0) + { + free_entry(); + if (entries_lost != 0) + { + int e = entries_lost; + entries_lost = 0; /* avoid wild recursion */ + my_syslog(LOG_WARNING, _("overflow: %d log entries lost"), e); + } + } + continue; + } + + if (errno == EINTR) + continue; + + if (errno == EAGAIN) + return; /* syslogd busy, go again when select() or poll() says so */ + + if (errno == ENOBUFS) + { + connection_good = 0; + return; + } + + /* errors handling after this assumes sockets */ + if (!log_to_file) + { + /* Once a stream socket hits EPIPE, we have to close and re-open + (we ignore SIGPIPE) */ + if (errno == EPIPE) + { + if (log_reopen(NULL)) + continue; + } + else if (errno == ECONNREFUSED || + errno == ENOTCONN || + errno == EDESTADDRREQ || + errno == ECONNRESET) + { + /* socket went (syslogd down?), try and reconnect. If we fail, + stop trying until the next call to my_syslog() + ECONNREFUSED -> connection went down + ENOTCONN -> nobody listening + (ECONNRESET, EDESTADDRREQ are *BSD equivalents) */ + + struct sockaddr_un logaddr; + +#ifdef HAVE_SOCKADDR_SA_LEN + logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1; +#endif + logaddr.sun_family = AF_UNIX; + strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path)); + + /* Got connection back? try again. */ + if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1) + continue; + + /* errors from connect which mean we should keep trying */ + if (errno == ENOENT || + errno == EALREADY || + errno == ECONNREFUSED || + errno == EISCONN || + errno == EINTR || + errno == EAGAIN) + { + /* try again on next syslog() call */ + connection_good = 0; + return; + } + + /* try the other sort of socket... */ + if (errno == EPROTOTYPE) + { + connection_type = connection_type == SOCK_DGRAM ? SOCK_STREAM : SOCK_DGRAM; + if (log_reopen(NULL)) + continue; + } + } + } + + /* give up - fall back to syslog() - this handles out-of-space + when logging to a file, for instance. */ + log_fd = -1; + my_syslog(LOG_CRIT, _("log failed: %s"), strerror(errno)); + return; + } +} + +/* priority is one of LOG_DEBUG, LOG_INFO, LOG_NOTICE, etc. See sys/syslog.h. + OR'd to priority can be MS_TFTP, MS_DHCP, ... to be able to do log separation between + DNS, DHCP and TFTP services. +*/ +void my_syslog(int priority, const char *format, ...) +{ + va_list ap; + struct log_entry *entry; + time_t time_now; + char *p; + size_t len; + pid_t pid = getpid(); + char *func = ""; + + if ((LOG_FACMASK & priority) == MS_TFTP) + func = "-tftp"; + else if ((LOG_FACMASK & priority) == MS_DHCP) + func = "-dhcp"; + +#ifdef LOG_PRI + priority = LOG_PRI(priority); +#else + /* Solaris doesn't have LOG_PRI */ + priority &= LOG_PRIMASK; +#endif + + if (echo_stderr) + { + fprintf(stderr, "dnsmasq%s: ", func); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc('\n', stderr); + } + + if (log_fd == -1) + { +#ifdef __ANDROID__ + /* do android-specific logging. + log_fd is always -1 on Android except when logging to a file. */ + int alog_lvl; + + if (priority <= LOG_ERR) + alog_lvl = ANDROID_LOG_ERROR; + else if (priority == LOG_WARNING) + alog_lvl = ANDROID_LOG_WARN; + else if (priority <= LOG_INFO) + alog_lvl = ANDROID_LOG_INFO; + else + alog_lvl = ANDROID_LOG_DEBUG; + + va_start(ap, format); + __android_log_vprint(alog_lvl, "dnsmasq", format, ap); + va_end(ap); +#else + /* fall-back to syslog if we die during startup or + fail during running (always on Solaris). */ + static int isopen = 0; + + if (!isopen) + { + openlog("dnsmasq", LOG_PID, log_fac); + isopen = 1; + } + va_start(ap, format); + vsyslog(priority, format, ap); + va_end(ap); +#endif + + return; + } + + if ((entry = free_entries)) + free_entries = entry->next; + else if (entries_alloced < max_logs && (entry = malloc(sizeof(struct log_entry)))) + entries_alloced++; + + if (!entry) + entries_lost++; + else + { + /* add to end of list, consumed from the start */ + entry->next = NULL; + if (!entries) + entries = entry; + else + { + struct log_entry *tmp; + for (tmp = entries; tmp->next; tmp = tmp->next); + tmp->next = entry; + } + + time(&time_now); + p = entry->payload; + if (!log_to_file) + p += sprintf(p, "<%d>", priority | log_fac); + + /* Omit timestamp for default daemontools situation */ + if (!log_stderr || !option_bool(OPT_NO_FORK)) + p += sprintf(p, "%.15s ", ctime(&time_now) + 4); + + p += sprintf(p, "dnsmasq%s[%d]: ", func, (int)pid); + + len = p - entry->payload; + va_start(ap, format); + len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */ + va_end(ap); + entry->length = len > MAX_MESSAGE ? MAX_MESSAGE : len; + entry->offset = 0; + entry->pid = pid; + + /* replace terminator with \n */ + if (log_to_file) + entry->payload[entry->length - 1] = '\n'; + } + + /* almost always, logging won't block, so try and write this now, + to save collecting too many log messages during a select loop. */ + log_write(); + + /* Since we're doing things asynchronously, a cache-dump, for instance, + can now generate log lines very fast. With a small buffer (desirable), + that means it can overflow the log-buffer very quickly, + so that the cache dump becomes mainly a count of how many lines + overflowed. To avoid this, we delay here, the delay is controlled + by queue-occupancy, and grows exponentially. The delay is limited to (2^8)ms. + The scaling stuff ensures that when the queue is bigger than 8, the delay + only occurs for the last 8 entries. Once the queue is full, we stop delaying + to preserve performance. + */ + + if (entries && max_logs != 0) + { + int d; + + for (d = 0,entry = entries; entry; entry = entry->next, d++); + + if (d == max_logs) + d = 0; + else if (max_logs > 8) + d -= max_logs - 8; + + if (d > 0) + { + struct timespec waiter; + waiter.tv_sec = 0; + waiter.tv_nsec = 1000000 << (d - 1); /* 1 ms */ + nanosleep(&waiter, NULL); + + /* Have another go now */ + log_write(); + } + } +} + +void set_log_writer(fd_set *set, int *maxfdp) +{ + if (entries && log_fd != -1 && connection_good) + { + FD_SET(log_fd, set); + bump_maxfd(log_fd, maxfdp); + } +} + +void check_log_writer(fd_set *set) +{ + if (log_fd != -1 && (!set || FD_ISSET(log_fd, set))) + log_write(); +} + +void flush_log(void) +{ + /* write until queue empty, but don't loop forever if there's + no connection to the syslog in existance */ + while (log_fd != -1) + { + struct timespec waiter; + log_write(); + if (!entries || !connection_good) + { + close(log_fd); + break; + } + waiter.tv_sec = 0; + waiter.tv_nsec = 1000000; /* 1 ms */ + nanosleep(&waiter, NULL); + } +} + +void die(char *message, char *arg1, int exit_code) +{ + char *errmess = strerror(errno); + + if (!arg1) + arg1 = errmess; + + if (!log_stderr) + { + echo_stderr = 1; /* print as well as log when we die.... */ + fputc('\n', stderr); /* prettyfy startup-script message */ + } + my_syslog(LOG_CRIT, message, arg1, errmess); + echo_stderr = 0; + my_syslog(LOG_CRIT, _("FAILED to start up")); + flush_log(); + + exit(exit_code); +} diff --git a/src/netlink.c b/src/netlink.c new file mode 100644 index 0000000..f6da7db --- /dev/null +++ b/src/netlink.c @@ -0,0 +1,326 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#ifdef HAVE_LINUX_NETWORK + +#include <linux/types.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> + +/* linux 2.6.19 buggers up the headers, patch it up here. */ +#ifndef IFA_RTA +# define IFA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) + +# include <linux/if_addr.h> +#endif + +#ifndef NDA_RTA +# define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#endif + +static struct iovec iov; +static u32 netlink_pid; + +static void nl_err(struct nlmsghdr *h); +static void nl_routechange(struct nlmsghdr *h); + +void netlink_init(void) +{ + struct sockaddr_nl addr; + socklen_t slen = sizeof(addr); + + addr.nl_family = AF_NETLINK; + addr.nl_pad = 0; + addr.nl_pid = 0; /* autobind */ +#ifdef HAVE_IPV6 + addr.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE; +#else + addr.nl_groups = RTMGRP_IPV4_ROUTE; +#endif + + /* May not be able to have permission to set multicast groups don't die in that case */ + if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1) + { + if (bind(daemon->netlinkfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) + { + addr.nl_groups = 0; + if (errno != EPERM || bind(daemon->netlinkfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) + daemon->netlinkfd = -1; + } + } + + if (daemon->netlinkfd == -1 || + getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == 1) + die(_("cannot create netlink socket: %s"), NULL, EC_MISC); + + /* save pid assigned by bind() and retrieved by getsockname() */ + netlink_pid = addr.nl_pid; + + iov.iov_len = 100; + iov.iov_base = safe_malloc(iov.iov_len); +} + +static ssize_t netlink_recv(void) +{ + struct msghdr msg; + struct sockaddr_nl nladdr; + ssize_t rc; + + while (1) + { + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = &nladdr; + msg.msg_namelen = sizeof(nladdr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + + while ((rc = recvmsg(daemon->netlinkfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR); + + /* make buffer big enough */ + if (rc != -1 && (msg.msg_flags & MSG_TRUNC)) + { + /* Very new Linux kernels return the actual size needed, older ones always return truncated size */ + if ((size_t)rc == iov.iov_len) + { + if (expand_buf(&iov, rc + 100)) + continue; + } + else + expand_buf(&iov, rc); + } + + /* read it for real */ + msg.msg_flags = 0; + while ((rc = recvmsg(daemon->netlinkfd, &msg, 0)) == -1 && errno == EINTR); + + /* Make sure this is from the kernel */ + if (rc == -1 || nladdr.nl_pid == 0) + break; + } + + /* discard stuff which is truncated at this point (expand_buf() may fail) */ + if (msg.msg_flags & MSG_TRUNC) + { + rc = -1; + errno = ENOMEM; + } + + return rc; +} + + +/* family = AF_UNSPEC finds ARP table entries. */ +int iface_enumerate(int family, void *parm, int (*callback)()) +{ + struct sockaddr_nl addr; + struct nlmsghdr *h; + ssize_t len; + static unsigned int seq = 0; + + struct { + struct nlmsghdr nlh; + struct rtgenmsg g; + } req; + + addr.nl_family = AF_NETLINK; + addr.nl_pad = 0; + addr.nl_groups = 0; + addr.nl_pid = 0; /* address to kernel */ + + again: + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = family == AF_UNSPEC ? RTM_GETNEIGH : RTM_GETADDR; + req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = ++seq; + req.g.rtgen_family = family; + + /* Don't block in recvfrom if send fails */ + while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, + (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send()); + + if (len == -1) + return 0; + + while (1) + { + if ((len = netlink_recv()) == -1) + { + if (errno == ENOBUFS) + { + sleep(1); + goto again; + } + return 0; + } + + for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) + if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid) + nl_routechange(h); /* May be multicast arriving async */ + else if (h->nlmsg_type == NLMSG_ERROR) + nl_err(h); + else if (h->nlmsg_type == NLMSG_DONE) + return 1; + else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC) + { + struct ifaddrmsg *ifa = NLMSG_DATA(h); + struct rtattr *rta = IFA_RTA(ifa); + unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)); + + if (ifa->ifa_family == family) + { + if (ifa->ifa_family == AF_INET) + { + struct in_addr netmask, addr, broadcast; + + netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen)); + addr.s_addr = 0; + broadcast.s_addr = 0; + + while (RTA_OK(rta, len1)) + { + if (rta->rta_type == IFA_LOCAL) + addr = *((struct in_addr *)(rta+1)); + else if (rta->rta_type == IFA_BROADCAST) + broadcast = *((struct in_addr *)(rta+1)); + + rta = RTA_NEXT(rta, len1); + } + + if (addr.s_addr) + if (!((*callback)(addr, ifa->ifa_index, netmask, broadcast, parm))) + return 0; + } +#ifdef HAVE_IPV6 + else if (ifa->ifa_family == AF_INET6) + { + struct in6_addr *addrp = NULL; + while (RTA_OK(rta, len1)) + { + if (rta->rta_type == IFA_ADDRESS) + addrp = ((struct in6_addr *)(rta+1)); + + rta = RTA_NEXT(rta, len1); + } + + if (addrp) + if (!((*callback)(addrp, ifa->ifa_index, ifa->ifa_index, parm))) + return 0; + } +#endif + } + } + else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC) + { + struct ndmsg *neigh = NLMSG_DATA(h); + struct rtattr *rta = NDA_RTA(neigh); + unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*neigh)); + size_t maclen = 0; + char *inaddr = NULL, *mac = NULL; + + while (RTA_OK(rta, len1)) + { + if (rta->rta_type == NDA_DST) + inaddr = (char *)(rta+1); + else if (rta->rta_type == NDA_LLADDR) + { + maclen = rta->rta_len - sizeof(struct rtattr); + mac = (char *)(rta+1); + } + + rta = RTA_NEXT(rta, len1); + } + + if (inaddr && mac) + if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm))) + return 0; + } + } +} + +void netlink_multicast(void) +{ + ssize_t len; + struct nlmsghdr *h; + int flags; + + /* don't risk blocking reading netlink messages here. */ + if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 || + fcntl(daemon->netlinkfd, F_SETFL, flags | O_NONBLOCK) == -1) + return; + + if ((len = netlink_recv()) != -1) + { + for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) + if (h->nlmsg_type == NLMSG_ERROR) + nl_err(h); + else + nl_routechange(h); + } + + /* restore non-blocking status */ + fcntl(daemon->netlinkfd, F_SETFL, flags); +} + +static void nl_err(struct nlmsghdr *h) +{ + struct nlmsgerr *err = NLMSG_DATA(h); + + if (err->error != 0) + my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error))); +} + +/* We arrange to receive netlink multicast messages whenever the network route is added. + If this happens and we still have a DNS packet in the buffer, we re-send it. + This helps on DoD links, where frequently the packet which triggers dialling is + a DNS query, which then gets lost. By re-sending, we can avoid the lookup + failing. Note that we only accept these messages from the kernel (pid == 0) */ +static void nl_routechange(struct nlmsghdr *h) +{ + if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE) + { + struct rtmsg *rtm = NLMSG_DATA(h); + int fd; + + if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK) + return; + + /* Force re-reading resolv file right now, for luck. */ + daemon->last_resolv = 0; + + if (daemon->srv_save) + { + if (daemon->srv_save->sfd) + fd = daemon->srv_save->sfd->fd; + else if (daemon->rfd_save && daemon->rfd_save->refcount != 0) + fd = daemon->rfd_save->fd; + else + return; + + while(sendto(fd, daemon->packet, daemon->packet_len, 0, + &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send()); + } + } +} + +#endif + + diff --git a/src/network.c b/src/network.c new file mode 100644 index 0000000..7b2e905 --- /dev/null +++ b/src/network.c @@ -0,0 +1,973 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#ifdef HAVE_LINUX_NETWORK + +int indextoname(int fd, int index, char *name) +{ + struct ifreq ifr; + + if (index == 0) + return 0; + + ifr.ifr_ifindex = index; + if (ioctl(fd, SIOCGIFNAME, &ifr) == -1) + return 0; + + strncpy(name, ifr.ifr_name, IF_NAMESIZE); + + return 1; +} + + +#elif defined(HAVE_SOLARIS_NETWORK) + +#include <zone.h> +#include <alloca.h> +#ifndef LIFC_UNDER_IPMP +# define LIFC_UNDER_IPMP 0 +#endif + +int indextoname(int fd, int index, char *name) +{ + int64_t lifc_flags; + struct lifnum lifn; + int numifs, bufsize, i; + struct lifconf lifc; + struct lifreq *lifrp; + + if (index == 0) + return 0; + + if (getzoneid() == GLOBAL_ZONEID) + { + if (!if_indextoname(index, name)) + return 0; + return 1; + } + + lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP; + lifn.lifn_family = AF_UNSPEC; + lifn.lifn_flags = lifc_flags; + if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0) + return 0; + + numifs = lifn.lifn_count; + bufsize = numifs * sizeof(struct lifreq); + + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = lifc_flags; + lifc.lifc_len = bufsize; + lifc.lifc_buf = alloca(bufsize); + + if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0) + return 0; + + lifrp = lifc.lifc_req; + for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++) + { + struct lifreq lifr; + strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE); + if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0) + return 0; + + if (lifr.lifr_index == index) { + strncpy(name, lifr.lifr_name, IF_NAMESIZE); + return 1; + } + } + return 0; +} + + +#else + +int indextoname(int fd, int index, char *name) +{ + if (index == 0 || !if_indextoname(index, name)) + return 0; + + return 1; +} + +#endif + +int iface_check(int family, struct all_addr *addr, char *name, int *indexp) +{ + struct iname *tmp; + int ret = 1; + + /* Note: have to check all and not bail out early, so that we set the + "used" flags. */ + + if (daemon->if_names || (addr && daemon->if_addrs)) + { +#ifdef HAVE_DHCP + struct dhcp_context *range; +#endif + + ret = 0; + +#ifdef HAVE_DHCP + for (range = daemon->dhcp; range; range = range->next) + if (range->interface && strcmp(range->interface, name) == 0) + ret = 1; +#endif + + for (tmp = daemon->if_names; tmp; tmp = tmp->next) + if (tmp->name && (strcmp(tmp->name, name) == 0)) + ret = tmp->used = 1; + + for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) + if (addr && tmp->addr.sa.sa_family == family) + { + if (family == AF_INET && + tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) + ret = tmp->used = 1; +#ifdef HAVE_IPV6 + else if (family == AF_INET6 && + IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, + &addr->addr.addr6)) + ret = tmp->used = 1; +#endif + } + } + + for (tmp = daemon->if_except; tmp; tmp = tmp->next) + if (tmp->name && (strcmp(tmp->name, name) == 0)) + ret = 0; + + if (indexp) + { + /* One form of bridging on BSD has the property that packets + can be recieved on bridge interfaces which do not have an IP address. + We allow these to be treated as aliases of another interface which does have + an IP address with --dhcp-bridge=interface,alias,alias */ + struct dhcp_bridge *bridge, *alias; + for (bridge = daemon->bridges; bridge; bridge = bridge->next) + { + for (alias = bridge->alias; alias; alias = alias->next) + if (strncmp(name, alias->iface, IF_NAMESIZE) == 0) + { + int newindex; + + if (!(newindex = if_nametoindex(bridge->iface))) + { + my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), name); + return 0; + } + else + { + *indexp = newindex; + strncpy(name, bridge->iface, IF_NAMESIZE); + break; + } + } + if (alias) + break; + } + } + + return ret; +} + +static int iface_allowed(struct irec **irecp, int if_index, + union mysockaddr *addr, struct in_addr netmask) +{ + struct irec *iface; + int fd, mtu = 0, loopback; + struct ifreq ifr; + int tftp_ok = daemon->tftp_unlimited; +#ifdef HAVE_DHCP + struct iname *tmp; +#endif + struct interface_list *ir = NULL; + + /* check whether the interface IP has been added already + we call this routine multiple times. */ + for (iface = *irecp; iface; iface = iface->next) + if (sockaddr_isequal(&iface->addr, addr)) + return 1; + + if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 || + !indextoname(fd, if_index, ifr.ifr_name) || + ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) + { + if (fd != -1) + { + int errsave = errno; + close(fd); + errno = errsave; + } + return 0; + } + + loopback = ifr.ifr_flags & IFF_LOOPBACK; + + if (ioctl(fd, SIOCGIFMTU, &ifr) != -1) + mtu = ifr.ifr_mtu; + + close(fd); + + /* If we are restricting the set of interfaces to use, make + sure that loopback interfaces are in that set. */ + if (daemon->if_names && loopback) + { + struct iname *lo; + for (lo = daemon->if_names; lo; lo = lo->next) + if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0) + { + lo->isloop = 1; + break; + } + + if (!lo && + (lo = whine_malloc(sizeof(struct iname))) && + (lo->name = whine_malloc(strlen(ifr.ifr_name)+1))) + { + strcpy(lo->name, ifr.ifr_name); + lo->isloop = lo->used = 1; + lo->next = daemon->if_names; + daemon->if_names = lo; + } + } + +#ifdef HAVE_TFTP + /* implement wierd TFTP service rules */ + for (ir = daemon->tftp_interfaces; ir; ir = ir->next) + if (strcmp(ir->interface, ifr.ifr_name) == 0) + { + tftp_ok = 1; + break; + } +#endif + + if (!ir) + { + if (addr->sa.sa_family == AF_INET && + !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL)) + return 1; + +#ifdef HAVE_DHCP + for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) + if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) + tftp_ok = 0; +#endif + +#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET6 && + !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL)) + return 1; +#endif + } + + /* add to list */ + if ((iface = whine_malloc(sizeof(struct irec)))) + { + iface->addr = *addr; + iface->netmask = netmask; + iface->tftp_ok = tftp_ok; + iface->mtu = mtu; + if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1))) + strcpy(iface->name, ifr.ifr_name); + iface->next = *irecp; + *irecp = iface; + return 1; + } + + errno = ENOMEM; + return 0; +} + +#ifdef HAVE_IPV6 +static int iface_allowed_v6(struct in6_addr *local, + int scope, int if_index, void *vparam) +{ + union mysockaddr addr; + struct in_addr netmask; /* dummy */ + + netmask.s_addr = 0; + + memset(&addr, 0, sizeof(addr)); +#ifdef HAVE_SOCKADDR_SA_LEN + addr.in6.sin6_len = sizeof(addr.in6); +#endif + addr.in6.sin6_family = AF_INET6; + addr.in6.sin6_addr = *local; + addr.in6.sin6_port = htons(daemon->port); + addr.in6.sin6_scope_id = scope; + + return iface_allowed((struct irec **)vparam, if_index, &addr, netmask); +} +#endif + +static int iface_allowed_v4(struct in_addr local, int if_index, + struct in_addr netmask, struct in_addr broadcast, void *vparam) +{ + union mysockaddr addr; + + memset(&addr, 0, sizeof(addr)); +#ifdef HAVE_SOCKADDR_SA_LEN + addr.in.sin_len = sizeof(addr.in); +#endif + addr.in.sin_family = AF_INET; + addr.in.sin_addr = broadcast; /* warning */ + addr.in.sin_addr = local; + addr.in.sin_port = htons(daemon->port); + + return iface_allowed((struct irec **)vparam, if_index, &addr, netmask); +} + +int enumerate_interfaces(void) +{ +#ifdef HAVE_IPV6 + if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6)) + return 0; +#endif + + return iface_enumerate(AF_INET, &daemon->interfaces, iface_allowed_v4); +} + +/* set NONBLOCK bit on fd: See Stevens 16.6 */ +int fix_fd(int fd) +{ + int flags; + + if ((flags = fcntl(fd, F_GETFL)) == -1 || + fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) + return 0; + + return 1; +} + +static int make_sock(union mysockaddr *addr, int type) +{ + int family = addr->sa.sa_family; + int fd, rc, opt = 1; +#ifdef HAVE_IPV6 + static int dad_count = 0; +#endif + + if ((fd = socket(family, type, 0)) == -1) + { + int port; + + /* No error if the kernel just doesn't support this IP flavour */ + if (errno == EPROTONOSUPPORT || + errno == EAFNOSUPPORT || + errno == EINVAL) + return -1; + + err: + port = prettyprint_addr(addr, daemon->namebuff); + if (!option_bool(OPT_NOWILD)) + sprintf(daemon->namebuff, "port %d", port); + die(_("failed to create listening socket for %s: %s"), + daemon->namebuff, EC_BADNET); + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd)) + goto err; + +#ifdef HAVE_IPV6 + if (family == AF_INET6 && setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) + goto err; +#endif + + while (1) + { + if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) != -1) + break; + +#ifdef HAVE_IPV6 + /* An interface may have an IPv6 address which is still undergoing DAD. + If so, the bind will fail until the DAD completes, so we try over 20 seconds + before failing. */ + if (family == AF_INET6 && + (errno == ENODEV || errno == EADDRNOTAVAIL) && + dad_count++ < DAD_WAIT) + { + sleep(1); + continue; + } +#endif + break; + } + + if (rc == -1) + goto err; + + if (type == SOCK_STREAM) + { + if (listen(fd, 5) == -1) + goto err; + } + else if (!option_bool(OPT_NOWILD)) + { + if (family == AF_INET) + { +#if defined(HAVE_LINUX_NETWORK) + if (setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1) + goto err; +#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) + if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 || + setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1) + goto err; +#endif + } +#ifdef HAVE_IPV6 + else + { + /* The API changed around Linux 2.6.14 but the old ABI is still supported: + handle all combinations of headers and kernel. + OpenWrt note that this fixes the problem addressed by your very broken patch. */ + daemon->v6pktinfo = IPV6_PKTINFO; + +# ifdef IPV6_RECVPKTINFO +# ifdef IPV6_2292PKTINFO + if (setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1) + { + if (errno == ENOPROTOOPT && setsockopt(fd, IPV6_LEVEL, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1) + daemon->v6pktinfo = IPV6_2292PKTINFO; + else + goto err; + } +# else + if (setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1) + goto err; +# endif +# else + if (setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1) + goto err; +# endif + } +#endif + } + + return fd; +} + +static struct listener *create_listeners(union mysockaddr *addr, int do_tftp) +{ + struct listener *l = NULL; + int fd = -1, tcpfd = -1, tftpfd = -1; + + if (daemon->port != 0) + { + fd = make_sock(addr, SOCK_DGRAM); + tcpfd = make_sock(addr, SOCK_STREAM); + } + +#ifdef HAVE_TFTP + if (do_tftp) + { + if (addr->sa.sa_family == AF_INET) + { + /* port must be restored to DNS port for TCP code */ + short save = addr->in.sin_port; + addr->in.sin_port = htons(TFTP_PORT); + tftpfd = make_sock(addr, SOCK_DGRAM); + addr->in.sin_port = save; + } +# ifdef HAVE_IPV6 + else + { + short save = addr->in6.sin6_port; + addr->in6.sin6_port = htons(TFTP_PORT); + tftpfd = make_sock(addr, SOCK_DGRAM); + addr->in6.sin6_port = save; + } +# endif + } +#endif + + if (fd != -1 || tcpfd != -1 || tftpfd != -1) + { + l = safe_malloc(sizeof(struct listener)); + l->next = NULL; + l->family = addr->sa.sa_family; + l->fd = fd; + l->tcpfd = tcpfd; + l->tftpfd = tftpfd; + } + + return l; +} + +struct listener *create_wildcard_listeners(void) +{ + union mysockaddr addr; + struct listener *l; + int tftp_enabled = daemon->tftp_unlimited || daemon->tftp_interfaces; + + memset(&addr, 0, sizeof(addr)); +#ifdef HAVE_SOCKADDR_SA_LEN + addr.in.sin_len = sizeof(addr.in); +#endif + addr.in.sin_family = AF_INET; + addr.in.sin_addr.s_addr = INADDR_ANY; + addr.in.sin_port = htons(daemon->port); + + l = create_listeners(&addr, tftp_enabled); + +#ifdef HAVE_IPV6 + memset(&addr, 0, sizeof(addr)); +# ifdef HAVE_SOCKADDR_SA_LEN + addr.in6.sin6_len = sizeof(addr.in6); +# endif + addr.in6.sin6_family = AF_INET6; + addr.in6.sin6_addr = in6addr_any; + addr.in6.sin6_port = htons(daemon->port); + + if (l) + l->next = create_listeners(&addr, tftp_enabled); + else + l = create_listeners(&addr, tftp_enabled); +#endif + + return l; +} + +struct listener *create_bound_listeners(void) +{ + struct listener *new, *listeners = NULL; + struct irec *iface; + + for (iface = daemon->interfaces; iface; iface = iface->next) + if ((new = create_listeners(&iface->addr, iface->tftp_ok))) + { + new->iface = iface; + new->next = listeners; + listeners = new; + } + + return listeners; +} + + +/* return a UDP socket bound to a random port, have to cope with straying into + occupied port nos and reserved ones. */ +int random_sock(int family) +{ + int fd; + + if ((fd = socket(family, SOCK_DGRAM, 0)) != -1) + { + union mysockaddr addr; + unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port; + int tries = ports_avail < 30 ? 3 * ports_avail : 100; + + memset(&addr, 0, sizeof(addr)); + addr.sa.sa_family = family; + + /* don't loop forever if all ports in use. */ + + if (fix_fd(fd)) + while(tries--) + { + unsigned short port = rand16(); + + if (daemon->min_port != 0) + port = htons(daemon->min_port + (port % ((unsigned short)ports_avail))); + + if (family == AF_INET) + { + addr.in.sin_addr.s_addr = INADDR_ANY; + addr.in.sin_port = port; +#ifdef HAVE_SOCKADDR_SA_LEN + addr.in.sin_len = sizeof(struct sockaddr_in); +#endif + } +#ifdef HAVE_IPV6 + else + { + addr.in6.sin6_addr = in6addr_any; + addr.in6.sin6_port = port; +#ifdef HAVE_SOCKADDR_SA_LEN + addr.in6.sin6_len = sizeof(struct sockaddr_in6); +#endif + } +#endif + + if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0) + return fd; + + if (errno != EADDRINUSE && errno != EACCES) + break; + } + + close(fd); + } + + return -1; +} + + +int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp) +{ + union mysockaddr addr_copy = *addr; + + /* cannot set source _port_ for TCP connections. */ + if (is_tcp) + { + if (addr_copy.sa.sa_family == AF_INET) + addr_copy.in.sin_port = 0; +#ifdef HAVE_IPV6 + else + addr_copy.in6.sin6_port = 0; +#endif + } + + if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1) + return 0; + +#if defined(SO_BINDTODEVICE) + if (intname[0] != 0 && + setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1) + return 0; +#endif + + return 1; +} + +static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname) +{ + struct serverfd *sfd; + int errsave; + + /* when using random ports, servers which would otherwise use + the INADDR_ANY/port0 socket have sfd set to NULL */ + if (!daemon->osport && intname[0] == 0) + { + errno = 0; + + if (addr->sa.sa_family == AF_INET && + addr->in.sin_addr.s_addr == INADDR_ANY && + addr->in.sin_port == htons(0)) + return NULL; + +#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET6 && + memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 && + addr->in6.sin6_port == htons(0)) + return NULL; +#endif + } + + /* may have a suitable one already */ + for (sfd = daemon->sfds; sfd; sfd = sfd->next ) + if (sockaddr_isequal(&sfd->source_addr, addr) && + strcmp(intname, sfd->interface) == 0) + return sfd; + + /* need to make a new one. */ + errno = ENOMEM; /* in case malloc fails. */ + if (!(sfd = whine_malloc(sizeof(struct serverfd)))) + return NULL; + + if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1) + { + free(sfd); + return NULL; + } + + if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd)) + { + errsave = errno; /* save error from bind. */ + close(sfd->fd); + free(sfd); + errno = errsave; + return NULL; + } + + strcpy(sfd->interface, intname); + sfd->source_addr = *addr; + sfd->next = daemon->sfds; + daemon->sfds = sfd; + return sfd; +} + +/* create upstream sockets during startup, before root is dropped which may be needed + this allows query_port to be a low port and interface binding */ +void pre_allocate_sfds(void) +{ + struct server *srv; + + if (daemon->query_port != 0) + { + union mysockaddr addr; + memset(&addr, 0, sizeof(addr)); + addr.in.sin_family = AF_INET; + addr.in.sin_addr.s_addr = INADDR_ANY; + addr.in.sin_port = htons(daemon->query_port); +#ifdef HAVE_SOCKADDR_SA_LEN + addr.in.sin_len = sizeof(struct sockaddr_in); +#endif + allocate_sfd(&addr, ""); +#ifdef HAVE_IPV6 + memset(&addr, 0, sizeof(addr)); + addr.in6.sin6_family = AF_INET6; + addr.in6.sin6_addr = in6addr_any; + addr.in6.sin6_port = htons(daemon->query_port); +#ifdef HAVE_SOCKADDR_SA_LEN + addr.in6.sin6_len = sizeof(struct sockaddr_in6); +#endif + allocate_sfd(&addr, ""); +#endif + } + + for (srv = daemon->servers; srv; srv = srv->next) + if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) && + !allocate_sfd(&srv->source_addr, srv->interface) && + errno != 0 && + option_bool(OPT_NOWILD)) + { + prettyprint_addr(&srv->source_addr, daemon->namebuff); + if (srv->interface[0] != 0) + { + strcat(daemon->namebuff, " "); + strcat(daemon->namebuff, srv->interface); + } + die(_("failed to bind server socket for %s: %s"), + daemon->namebuff, EC_BADNET); + } +} + + +void check_servers(void) +{ + struct irec *iface; + struct server *new, *tmp, *ret = NULL; + int port = 0; + + /* interface may be new since startup */ + if (!option_bool(OPT_NOWILD)) + enumerate_interfaces(); + + for (new = daemon->servers; new; new = tmp) + { + tmp = new->next; + + if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND))) + { + port = prettyprint_addr(&new->addr, daemon->namebuff); + + /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */ + if (new->addr.sa.sa_family == AF_INET && + new->addr.in.sin_addr.s_addr == 0) + { + free(new); + continue; + } + + for (iface = daemon->interfaces; iface; iface = iface->next) + if (sockaddr_isequal(&new->addr, &iface->addr)) + break; + if (iface) + { + my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff); + free(new); + continue; + } + + /* Do we need a socket set? */ + if (!new->sfd && + !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) && + errno != 0) + { + my_syslog(LOG_WARNING, + _("ignoring nameserver %s - cannot make/bind socket: %s"), + daemon->namebuff, strerror(errno)); + free(new); + continue; + } + } + + /* reverse order - gets it right. */ + new->next = ret; + ret = new; + + if (!(new->flags & SERV_NO_REBIND)) + { + if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV)) + { + char *s1, *s2; + if (!(new->flags & SERV_HAS_DOMAIN)) + s1 = _("unqualified"), s2 = _("names"); + else if (strlen(new->domain) == 0) + s1 = _("default"), s2 = ""; + else + s1 = _("domain"), s2 = new->domain; + + if (new->flags & SERV_NO_ADDR) + my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2); + else if (new->flags & SERV_USE_RESOLV) + my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2); + else if (!(new->flags & SERV_LITERAL_ADDRESS)) + my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2); + } + else if (new->interface[0] != 0) + my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface); + else + my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); + } + } + + daemon->servers = ret; +} + +/* Return zero if no servers found, in that case we keep polling. + This is a protection against an update-time/write race on resolv.conf */ +int reload_servers(char *fname) +{ + FILE *f; + char *line; + struct server *old_servers = NULL; + struct server *new_servers = NULL; + struct server *serv; + int gotone = 0; + + /* buff happens to be MAXDNAME long... */ + if (!(f = fopen(fname, "r"))) + { + my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno)); + return 0; + } + + /* move old servers to free list - we can reuse the memory + and not risk malloc if there are the same or fewer new servers. + Servers which were specced on the command line go to the new list. */ + for (serv = daemon->servers; serv;) + { + struct server *tmp = serv->next; + if (serv->flags & SERV_FROM_RESOLV) + { + serv->next = old_servers; + old_servers = serv; + /* forward table rules reference servers, so have to blow them away */ + server_gone(serv); + } + else + { + serv->next = new_servers; + new_servers = serv; + } + serv = tmp; + } + + while ((line = fgets(daemon->namebuff, MAXDNAME, f))) + { + union mysockaddr addr, source_addr; + char *token = strtok(line, " \t\n\r"); + + if (!token) + continue; + if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0) + continue; + if (!(token = strtok(NULL, " \t\n\r"))) + continue; + + memset(&addr, 0, sizeof(addr)); + memset(&source_addr, 0, sizeof(source_addr)); + + if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1) + { +#ifdef HAVE_SOCKADDR_SA_LEN + source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); +#endif + source_addr.in.sin_family = addr.in.sin_family = AF_INET; + addr.in.sin_port = htons(NAMESERVER_PORT); + source_addr.in.sin_addr.s_addr = INADDR_ANY; + source_addr.in.sin_port = htons(daemon->query_port); + } +#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0) + { +#ifdef HAVE_SOCKADDR_SA_LEN + source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6); +#endif + source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6; + addr.in6.sin6_port = htons(NAMESERVER_PORT); + source_addr.in6.sin6_addr = in6addr_any; + source_addr.in6.sin6_port = htons(daemon->query_port); + } +#endif /* IPV6 */ + else + continue; + + if (old_servers) + { + serv = old_servers; + old_servers = old_servers->next; + } + else if (!(serv = whine_malloc(sizeof (struct server)))) + continue; + + /* this list is reverse ordered: + it gets reversed again in check_servers */ + serv->next = new_servers; + new_servers = serv; + serv->addr = addr; + serv->source_addr = source_addr; + serv->domain = NULL; + serv->interface[0] = 0; + serv->sfd = NULL; + serv->flags = SERV_FROM_RESOLV; + serv->queries = serv->failed_queries = 0; + gotone = 1; + } + + /* Free any memory not used. */ + while (old_servers) + { + struct server *tmp = old_servers->next; + free(old_servers); + old_servers = tmp; + } + + daemon->servers = new_servers; + fclose(f); + + return gotone; +} + + +/* Use an IPv4 listener socket for ioctling */ +struct in_addr get_ifaddr(char *intr) +{ + struct listener *l; + struct ifreq ifr; + struct sockaddr_in ret; + + ret.sin_addr.s_addr = -1; + + for (l = daemon->listeners; + l && (l->family != AF_INET || l->fd == -1); + l = l->next); + + strncpy(ifr.ifr_name, intr, IF_NAMESIZE); + ifr.ifr_addr.sa_family = AF_INET; + + if (l && ioctl(l->fd, SIOCGIFADDR, &ifr) != -1) + memcpy(&ret, &ifr.ifr_addr, sizeof(ret)); + + return ret.sin_addr; +} + + + diff --git a/src/option.c b/src/option.c new file mode 100644 index 0000000..4cee0a2 --- /dev/null +++ b/src/option.c @@ -0,0 +1,3416 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* define this to get facilitynames */ +#define SYSLOG_NAMES +#include "dnsmasq.h" +#include <setjmp.h> + +static volatile int mem_recover = 0; +static jmp_buf mem_jmp; +static void one_file(char *file, int hard_opt); + +/* Solaris headers don't have facility names. */ +#ifdef HAVE_SOLARIS_NETWORK +static const struct { + char *c_name; + unsigned int c_val; +} facilitynames[] = { + { "kern", LOG_KERN }, + { "user", LOG_USER }, + { "mail", LOG_MAIL }, + { "daemon", LOG_DAEMON }, + { "auth", LOG_AUTH }, + { "syslog", LOG_SYSLOG }, + { "lpr", LOG_LPR }, + { "news", LOG_NEWS }, + { "uucp", LOG_UUCP }, + { "audit", LOG_AUDIT }, + { "cron", LOG_CRON }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { NULL, 0 } +}; +#endif + +#ifndef HAVE_GETOPT_LONG +struct myoption { + const char *name; + int has_arg; + int *flag; + int val; +}; +#endif + +#define OPTSTRING "951yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:7:8:0:3:" + +/* options which don't have a one-char version */ +#define LOPT_RELOAD 256 +#define LOPT_NO_NAMES 257 +#define LOPT_TFTP 258 +#define LOPT_SECURE 259 +#define LOPT_PREFIX 260 +#define LOPT_PTR 261 +#define LOPT_BRIDGE 262 +#define LOPT_TFTP_MAX 263 +#define LOPT_FORCE 264 +#define LOPT_NOBLOCK 265 +#define LOPT_LOG_OPTS 266 +#define LOPT_MAX_LOGS 267 +#define LOPT_CIRCUIT 268 +#define LOPT_REMOTE 269 +#define LOPT_SUBSCR 270 +#define LOPT_INTNAME 271 +#define LOPT_BANK 272 +#define LOPT_DHCP_HOST 273 +#define LOPT_APREF 274 +#define LOPT_OVERRIDE 275 +#define LOPT_TFTPPORTS 276 +#define LOPT_REBIND 277 +#define LOPT_NOLAST 278 +#define LOPT_OPTS 279 +#define LOPT_DHCP_OPTS 280 +#define LOPT_MATCH 281 +#define LOPT_BROADCAST 282 +#define LOPT_NEGTTL 283 +#define LOPT_ALTPORT 284 +#define LOPT_SCRIPTUSR 285 +#define LOPT_LOCAL 286 +#define LOPT_NAPTR 287 +#define LOPT_MINPORT 288 +#define LOPT_DHCP_FQDN 289 +#define LOPT_CNAME 290 +#define LOPT_PXE_PROMT 291 +#define LOPT_PXE_SERV 292 +#define LOPT_TEST 293 +#define LOPT_TAG_IF 294 +#define LOPT_PROXY 295 +#define LOPT_GEN_NAMES 296 +#define LOPT_MAXTTL 297 +#define LOPT_NO_REBIND 298 +#define LOPT_LOC_REBND 299 +#define LOPT_ADD_MAC 300 +#define LOPT_DNSSEC 301 + +#ifdef HAVE_GETOPT_LONG +static const struct option opts[] = +#else +static const struct myoption opts[] = +#endif + { + { "version", 0, 0, 'v' }, + { "no-hosts", 0, 0, 'h' }, + { "no-poll", 0, 0, 'n' }, + { "help", 0, 0, 'w' }, + { "no-daemon", 0, 0, 'd' }, + { "log-queries", 0, 0, 'q' }, + { "user", 2, 0, 'u' }, + { "group", 2, 0, 'g' }, + { "resolv-file", 2, 0, 'r' }, + { "mx-host", 1, 0, 'm' }, + { "mx-target", 1, 0, 't' }, + { "cache-size", 2, 0, 'c' }, + { "port", 1, 0, 'p' }, + { "dhcp-leasefile", 2, 0, 'l' }, + { "dhcp-lease", 1, 0, 'l' }, + { "dhcp-host", 1, 0, 'G' }, + { "dhcp-range", 1, 0, 'F' }, + { "dhcp-option", 1, 0, 'O' }, + { "dhcp-boot", 1, 0, 'M' }, + { "domain", 1, 0, 's' }, + { "domain-suffix", 1, 0, 's' }, + { "interface", 1, 0, 'i' }, + { "listen-address", 1, 0, 'a' }, + { "bogus-priv", 0, 0, 'b' }, + { "bogus-nxdomain", 1, 0, 'B' }, + { "selfmx", 0, 0, 'e' }, + { "filterwin2k", 0, 0, 'f' }, + { "pid-file", 2, 0, 'x' }, + { "strict-order", 0, 0, 'o' }, + { "server", 1, 0, 'S' }, + { "local", 1, 0, LOPT_LOCAL }, + { "address", 1, 0, 'A' }, + { "conf-file", 2, 0, 'C' }, + { "no-resolv", 0, 0, 'R' }, + { "expand-hosts", 0, 0, 'E' }, + { "localmx", 0, 0, 'L' }, + { "local-ttl", 1, 0, 'T' }, + { "no-negcache", 0, 0, 'N' }, + { "addn-hosts", 1, 0, 'H' }, + { "query-port", 1, 0, 'Q' }, + { "except-interface", 1, 0, 'I' }, + { "no-dhcp-interface", 1, 0, '2' }, + { "domain-needed", 0, 0, 'D' }, + { "dhcp-lease-max", 1, 0, 'X' }, + { "bind-interfaces", 0, 0, 'z' }, + { "read-ethers", 0, 0, 'Z' }, + { "alias", 1, 0, 'V' }, + { "dhcp-vendorclass", 1, 0, 'U' }, + { "dhcp-userclass", 1, 0, 'j' }, + { "dhcp-ignore", 1, 0, 'J' }, + { "edns-packet-max", 1, 0, 'P' }, + { "keep-in-foreground", 0, 0, 'k' }, + { "dhcp-authoritative", 0, 0, 'K' }, + { "srv-host", 1, 0, 'W' }, + { "localise-queries", 0, 0, 'y' }, + { "txt-record", 1, 0, 'Y' }, + { "enable-dbus", 0, 0, '1' }, + { "bootp-dynamic", 2, 0, '3' }, + { "dhcp-mac", 1, 0, '4' }, + { "no-ping", 0, 0, '5' }, + { "dhcp-script", 1, 0, '6' }, + { "conf-dir", 1, 0, '7' }, + { "log-facility", 1, 0 ,'8' }, + { "leasefile-ro", 0, 0, '9' }, + { "dns-forward-max", 1, 0, '0' }, + { "clear-on-reload", 0, 0, LOPT_RELOAD }, + { "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES }, + { "enable-tftp", 2, 0, LOPT_TFTP }, + { "tftp-secure", 0, 0, LOPT_SECURE }, + { "tftp-unique-root", 0, 0, LOPT_APREF }, + { "tftp-root", 1, 0, LOPT_PREFIX }, + { "tftp-max", 1, 0, LOPT_TFTP_MAX }, + { "ptr-record", 1, 0, LOPT_PTR }, + { "naptr-record", 1, 0, LOPT_NAPTR }, + { "bridge-interface", 1, 0 , LOPT_BRIDGE }, + { "dhcp-option-force", 1, 0, LOPT_FORCE }, + { "tftp-no-blocksize", 0, 0, LOPT_NOBLOCK }, + { "log-dhcp", 0, 0, LOPT_LOG_OPTS }, + { "log-async", 2, 0, LOPT_MAX_LOGS }, + { "dhcp-circuitid", 1, 0, LOPT_CIRCUIT }, + { "dhcp-remoteid", 1, 0, LOPT_REMOTE }, + { "dhcp-subscrid", 1, 0, LOPT_SUBSCR }, + { "interface-name", 1, 0, LOPT_INTNAME }, + { "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST }, + { "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS }, + { "dhcp-no-override", 0, 0, LOPT_OVERRIDE }, + { "tftp-port-range", 1, 0, LOPT_TFTPPORTS }, + { "stop-dns-rebind", 0, 0, LOPT_REBIND }, + { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND }, + { "all-servers", 0, 0, LOPT_NOLAST }, + { "dhcp-match", 1, 0, LOPT_MATCH }, + { "dhcp-broadcast", 2, 0, LOPT_BROADCAST }, + { "neg-ttl", 1, 0, LOPT_NEGTTL }, + { "max-ttl", 1, 0, LOPT_MAXTTL }, + { "dhcp-alternate-port", 2, 0, LOPT_ALTPORT }, + { "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR }, + { "min-port", 1, 0, LOPT_MINPORT }, + { "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN }, + { "cname", 1, 0, LOPT_CNAME }, + { "pxe-prompt", 1, 0, LOPT_PXE_PROMT }, + { "pxe-service", 1, 0, LOPT_PXE_SERV }, + { "test", 0, 0, LOPT_TEST }, + { "tag-if", 1, 0, LOPT_TAG_IF }, + { "dhcp-proxy", 2, 0, LOPT_PROXY }, + { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES }, + { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND }, + { "add-mac", 0, 0, LOPT_ADD_MAC }, + { "proxy-dnssec", 0, 0, LOPT_DNSSEC }, + { NULL, 0, 0, 0 } + }; + + +#define ARG_DUP OPT_LAST +#define ARG_ONE OPT_LAST + 1 +#define ARG_USED_CL OPT_LAST + 2 +#define ARG_USED_FILE OPT_LAST + 3 + +static struct { + int opt; + unsigned int rept; + char * const flagdesc; + char * const desc; + char * const arg; +} usage[] = { + { 'a', ARG_DUP, "ipaddr", gettext_noop("Specify local address(es) to listen on."), NULL }, + { 'A', ARG_DUP, "/domain/ipaddr", gettext_noop("Return ipaddr for all hosts in specified domains."), NULL }, + { 'b', OPT_BOGUSPRIV, NULL, gettext_noop("Fake reverse lookups for RFC1918 private address ranges."), NULL }, + { 'B', ARG_DUP, "ipaddr", gettext_noop("Treat ipaddr as NXDOMAIN (defeats Verisign wildcard)."), NULL }, + { 'c', ARG_ONE, "cachesize", gettext_noop("Specify the size of the cache in entries (defaults to %s)."), "$" }, + { 'C', ARG_DUP, "path", gettext_noop("Specify configuration file (defaults to %s)."), CONFFILE }, + { 'd', OPT_DEBUG, NULL, gettext_noop("Do NOT fork into the background: run in debug mode."), NULL }, + { 'D', OPT_NODOTS_LOCAL, NULL, gettext_noop("Do NOT forward queries with no domain part."), NULL }, + { 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL }, + { 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL }, + { 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL }, + { 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL }, + { 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP }, + { 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL }, + { LOPT_DHCP_HOST, ARG_DUP, "<filename>", gettext_noop("Read DHCP host specs from file."), NULL }, + { LOPT_DHCP_OPTS, ARG_DUP, "<filename>", gettext_noop("Read DHCP option specs from file."), NULL }, + { LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL }, + { 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE }, + { 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE }, + { 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL }, + { 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL }, + { 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL }, + { LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL }, + { LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL }, + { LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL }, + { 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL }, + { LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL }, + { 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL }, + { 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL }, + { 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE }, + { 'L', OPT_LOCALMX, NULL, gettext_noop("Return MX records for local hosts."), NULL }, + { 'm', ARG_DUP, "host_name,target,pref", gettext_noop("Specify an MX record."), NULL }, + { 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL }, + { 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE }, + { 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL }, + { 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE }, + { 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL }, + { LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL}, + { 'p', ARG_ONE, "number", gettext_noop("Specify port to listen for DNS requests on (defaults to 53)."), NULL }, + { 'P', ARG_ONE, "<size>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" }, + { 'q', OPT_LOG, NULL, gettext_noop("Log DNS queries."), NULL }, + { 'Q', ARG_ONE, "number", gettext_noop("Force the originating port for upstream DNS queries."), NULL }, + { 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL }, + { 'r', ARG_DUP, "path", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE }, + { 'S', ARG_DUP, "/domain/ipaddr", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL }, + { LOPT_LOCAL, ARG_DUP, "/domain/", gettext_noop("Never forward queries to specified domains."), NULL }, + { 's', ARG_DUP, "<domain>[,<range>]", gettext_noop("Specify the domain to be assigned in DHCP leases."), NULL }, + { 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL }, + { 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL }, + { LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL }, + { LOPT_MAXTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL }, + { 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER }, + { 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL }, + { 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL }, + { 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL }, + { 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL }, + { 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL }, + { 'x', ARG_ONE, "path", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE }, + { 'X', ARG_ONE, "number", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" }, + { 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL }, + { 'Y', ARG_DUP, "name,txt....", gettext_noop("Specify TXT DNS record."), NULL }, + { LOPT_PTR, ARG_DUP, "name,target", gettext_noop("Specify PTR DNS record."), NULL }, + { LOPT_INTNAME, ARG_DUP, "name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL }, + { 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL }, + { 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE }, + { '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL }, + { '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL }, + { '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL }, + { '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL }, + { LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL }, + { '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL }, + { '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL }, + { '7', ARG_DUP, "path", gettext_noop("Read configuration from all the files in this directory."), NULL }, + { '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL }, + { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL }, + { '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" }, + { LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE }, + { LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL }, + { LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL }, + { LOPT_TFTP, ARG_DUP, "[=<interface>]", gettext_noop("Enable integrated read-only TFTP server."), NULL }, + { LOPT_PREFIX, ARG_ONE, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL }, + { LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL }, + { LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL }, + { LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" }, + { LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL }, + { LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL }, + { LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL }, + { LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL }, + { LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL }, + { LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL }, + { LOPT_NO_REBIND, ARG_DUP, "/domain/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL }, + { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL }, + { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL }, + { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL }, + { LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL }, + { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL }, + { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL }, + { LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL }, + { LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL}, + { LOPT_PROXY, ARG_DUP, "[=<ip_address>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL }, + { LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL }, + { LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL }, + { LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL }, + { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL }, + { LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries"), NULL }, + { LOPT_DNSSEC, OPT_DNSSEC, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers"), NULL }, + { 0, 0, NULL, NULL, NULL } +}; + +#ifdef HAVE_DHCP +#define OT_ADDR_LIST 0x80 +#define OT_RFC1035_NAME 0x40 +#define OT_INTERNAL 0x20 +#define OT_NAME 0x10 + + +static const struct { + char *name; + unsigned char val, size; +} opttab[] = { + { "netmask", 1, OT_ADDR_LIST }, + { "time-offset", 2, 4 }, + { "router", 3, OT_ADDR_LIST }, + { "dns-server", 6, OT_ADDR_LIST }, + { "log-server", 7, OT_ADDR_LIST }, + { "lpr-server", 9, OT_ADDR_LIST }, + { "hostname", 12, OT_INTERNAL | OT_NAME }, + { "boot-file-size", 13, 2 }, + { "domain-name", 15, OT_NAME }, + { "swap-server", 16, OT_ADDR_LIST }, + { "root-path", 17, OT_NAME }, + { "extension-path", 18, OT_NAME }, + { "ip-forward-enable", 19, 1 }, + { "non-local-source-routing", 20, 1 }, + { "policy-filter", 21, OT_ADDR_LIST }, + { "max-datagram-reassembly", 22, 2 }, + { "default-ttl", 23, 1 }, + { "mtu", 26, 2 }, + { "all-subnets-local", 27, 1 }, + { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST }, + { "router-discovery", 31, 1 }, + { "router-solicitation", 32, OT_ADDR_LIST }, + { "static-route", 33, OT_ADDR_LIST }, + { "trailer-encapsulation", 34, 1 }, + { "arp-timeout", 35, 4 }, + { "ethernet-encap", 36, 1 }, + { "tcp-ttl", 37, 1 }, + { "tcp-keepalive", 38, 4 }, + { "nis-domain", 40, OT_NAME }, + { "nis-server", 41, OT_ADDR_LIST }, + { "ntp-server", 42, OT_ADDR_LIST }, + { "vendor-encap", 43, OT_INTERNAL }, + { "netbios-ns", 44, OT_ADDR_LIST }, + { "netbios-dd", 45, OT_ADDR_LIST }, + { "netbios-nodetype", 46, 1 }, + { "netbios-scope", 47, 0 }, + { "x-windows-fs", 48, OT_ADDR_LIST }, + { "x-windows-dm", 49, OT_ADDR_LIST }, + { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST }, + { "lease-time", 51, OT_INTERNAL }, + { "option-overload", 52, OT_INTERNAL }, + { "message-type", 53, OT_INTERNAL, }, + { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST }, + { "parameter-request", 55, OT_INTERNAL }, + { "message", 56, OT_INTERNAL }, + { "max-message-size", 57, OT_INTERNAL }, + { "T1", 58, OT_INTERNAL }, + { "T2", 59, OT_INTERNAL }, + { "vendor-class", 60, 0 }, + { "client-id", 61,OT_INTERNAL }, + { "nis+-domain", 64, OT_NAME }, + { "nis+-server", 65, OT_ADDR_LIST }, + { "tftp-server", 66, OT_NAME }, + { "bootfile-name", 67, OT_NAME }, + { "mobile-ip-home", 68, OT_ADDR_LIST }, + { "smtp-server", 69, OT_ADDR_LIST }, + { "pop3-server", 70, OT_ADDR_LIST }, + { "nntp-server", 71, OT_ADDR_LIST }, + { "irc-server", 74, OT_ADDR_LIST }, + { "user-class", 77, 0 }, + { "FQDN", 81, OT_INTERNAL }, + { "agent-id", 82, OT_INTERNAL }, + { "client-arch", 93, 2 }, + { "client-interface-id", 94, 0 }, + { "client-machine-id", 97, 0 }, + { "subnet-select", 118, OT_INTERNAL }, + { "domain-search", 119, OT_RFC1035_NAME }, + { "sip-server", 120, 0 }, + { "classless-static-route", 121, 0 }, + { "vendor-id-encap", 125, 0 }, + { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */ + { NULL, 0, 0 } +}; + +char *option_string(unsigned char opt, int *is_ip, int *is_name) +{ + int i; + + for (i = 0; opttab[i].name; i++) + if (opttab[i].val == opt) + { + if (is_ip) + *is_ip = !!(opttab[i].size & OT_ADDR_LIST); + if (is_name) + *is_name = !!(opttab[i].size & OT_NAME); + return opttab[i].name; + } + + return NULL; +} + +#endif + +/* We hide metacharaters in quoted strings by mapping them into the ASCII control + character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the + following sequence so that they map to themselves: it is therefore possible to call + unhide_metas repeatedly on string without breaking things. + The transformation gets undone by opt_canonicalise, atoi_check and opt_string_alloc, and a + couple of other places. + Note that space is included here so that + --dhcp-option=3, string + has five characters, whilst + --dhcp-option=3," string" + has six. +*/ + +static const char meta[] = "\000123456 \b\t\n78\r90abcdefABCDE\033F:,."; + +static char hide_meta(char c) +{ + unsigned int i; + + for (i = 0; i < (sizeof(meta) - 1); i++) + if (c == meta[i]) + return (char)i; + + return c; +} + +static char unhide_meta(char cr) +{ + unsigned int c = cr; + + if (c < (sizeof(meta) - 1)) + cr = meta[c]; + + return cr; +} + +static void unhide_metas(char *cp) +{ + if (cp) + for(; *cp; cp++) + *cp = unhide_meta(*cp); +} + +static void *opt_malloc(size_t size) +{ + void *ret; + + if (mem_recover) + { + ret = whine_malloc(size); + if (!ret) + longjmp(mem_jmp, 1); + } + else + ret = safe_malloc(size); + + return ret; +} + +static char *opt_string_alloc(char *cp) +{ + char *ret = NULL; + + if (cp && strlen(cp) != 0) + { + ret = opt_malloc(strlen(cp)+1); + strcpy(ret, cp); + + /* restore hidden metachars */ + unhide_metas(ret); + } + + return ret; +} + + +/* find next comma, split string with zero and eliminate spaces. + return start of string following comma */ + +static char *split_chr(char *s, char c) +{ + char *comma, *p; + + if (!s || !(comma = strchr(s, c))) + return NULL; + + p = comma; + *comma = ' '; + + for (; *comma == ' '; comma++); + + for (; (p >= s) && *p == ' '; p--) + *p = 0; + + return comma; +} + +static char *split(char *s) +{ + return split_chr(s, ','); +} + +static char *canonicalise_opt(char *s) +{ + char *ret; + int nomem; + + if (!s) + return 0; + + unhide_metas(s); + if (!(ret = canonicalise(s, &nomem)) && nomem) + { + if (mem_recover) + longjmp(mem_jmp, 1); + else + die(_("could not get memory"), NULL, EC_NOMEM); + } + + return ret; +} + +static int atoi_check(char *a, int *res) +{ + char *p; + + if (!a) + return 0; + + unhide_metas(a); + + for (p = a; *p; p++) + if (*p < '0' || *p > '9') + return 0; + + *res = atoi(a); + return 1; +} + +static int atoi_check16(char *a, int *res) +{ + if (!(atoi_check(a, res)) || + *res < 0 || + *res > 0xffff) + return 0; + + return 1; +} + +static void add_txt(char *name, char *txt) +{ + size_t len = strlen(txt); + struct txt_record *r = opt_malloc(sizeof(struct txt_record)); + + r->name = opt_string_alloc(name); + r->next = daemon->txt; + daemon->txt = r; + r->class = C_CHAOS; + r->txt = opt_malloc(len+1); + r->len = len+1; + *(r->txt) = len; + memcpy((r->txt)+1, txt, len); +} + +static void do_usage(void) +{ + char buff[100]; + int i, j; + + struct { + char handle; + int val; + } tab[] = { + { '$', CACHESIZ }, + { '*', EDNS_PKTSZ }, + { '&', MAXLEASES }, + { '!', FTABSIZ }, + { '#', TFTP_MAX_CONNECTIONS }, + { '\0', 0 } + }; + + printf(_("Usage: dnsmasq [options]\n\n")); +#ifndef HAVE_GETOPT_LONG + printf(_("Use short options only on the command line.\n")); +#endif + printf(_("Valid options are:\n")); + + for (i = 0; usage[i].opt != 0; i++) + { + char *desc = usage[i].flagdesc; + char *eq = "="; + + if (!desc || *desc == '[') + eq = ""; + + if (!desc) + desc = ""; + + for ( j = 0; opts[j].name; j++) + if (opts[j].val == usage[i].opt) + break; + if (usage[i].opt < 256) + sprintf(buff, "-%c, ", usage[i].opt); + else + sprintf(buff, " "); + + sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc); + printf("%-40.40s", buff); + + if (usage[i].arg) + { + strcpy(buff, usage[i].arg); + for (j = 0; tab[j].handle; j++) + if (tab[j].handle == *(usage[i].arg)) + sprintf(buff, "%d", tab[j].val); + } + printf(_(usage[i].desc), buff); + printf("\n"); + } +} + +#ifdef HAVE_DHCP +static void display_opts(void) +{ + int i; + + printf(_("Known DHCP options:\n")); + + for (i = 0; opttab[i].name; i++) + if (!(opttab[i].size & OT_INTERNAL)) + printf("%3d %s\n", opttab[i].val, opttab[i].name); +} + +static int is_tag_prefix(char *arg) +{ + if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg)) + return 1; + + return 0; +} + +static char *set_prefix(char *arg) +{ + if (strstr(arg, "set:") == arg) + return arg+4; + + return arg; +} + +/* This is too insanely large to keep in-line in the switch */ +static char *parse_dhcp_opt(char *arg, int flags) +{ + struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt)); + char lenchar = 0, *cp; + int i, addrs, digs, is_addr, is_hex, is_dec, is_string, dots; + char *comma = NULL, *problem = NULL; + struct dhcp_netid *np = NULL; + unsigned char opt_len = 0; + + new->len = 0; + new->flags = flags; + new->netid = NULL; + new->val = NULL; + new->opt = 0; + + while (arg) + { + comma = split(arg); + + for (cp = arg; *cp; cp++) + if (*cp < '0' || *cp > '9') + break; + + if (!*cp) + { + new->opt = atoi(arg); + opt_len = 0; + break; + } + + if (strstr(arg, "option:") == arg) + { + for (i = 0; opttab[i].name; i++) + if (!(opttab[i].size & OT_INTERNAL) && + strcasecmp(opttab[i].name, arg+7) == 0) + { + new->opt = opttab[i].val; + opt_len = opttab[i].size; + break; + } + /* option:<optname> must follow tag and vendor string. */ + break; + } + else if (strstr(arg, "vendor:") == arg) + { + new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7); + new->flags |= DHOPT_VENDOR; + } + else if (strstr(arg, "encap:") == arg) + { + new->u.encap = atoi(arg+6); + new->flags |= DHOPT_ENCAPSULATE; + } + else if (strstr(arg, "vi-encap:") == arg) + { + new->u.encap = atoi(arg+9); + new->flags |= DHOPT_RFC3925; + if (flags == DHOPT_MATCH) + { + new->opt = 1; /* avoid error below */ + break; + } + } + else + { + new->netid = opt_malloc(sizeof (struct dhcp_netid)); + /* allow optional "net:" or "tag:" for consistency */ + if (is_tag_prefix(arg)) + new->netid->net = opt_string_alloc(arg+4); + else + new->netid->net = opt_string_alloc(set_prefix(arg)); + new->netid->next = np; + np = new->netid; + } + + arg = comma; + } + + if (opt_len == 0 && + !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925))) + for (i = 0; opttab[i].name; i++) + if (new->opt == opttab[i].val) + { + opt_len = opttab[i].size; + if (opt_len & OT_INTERNAL) + opt_len = 0; + break; + } + + /* option may be missing with rfc3925 match */ + if (new->opt == 0) + problem = _("bad dhcp-option"); + else if (comma) + { + /* characterise the value */ + char c; + int found_dig = 0; + is_addr = is_hex = is_dec = is_string = 1; + addrs = digs = 1; + dots = 0; + for (cp = comma; (c = *cp); cp++) + if (c == ',') + { + addrs++; + is_dec = is_hex = 0; + } + else if (c == ':') + { + digs++; + is_dec = is_addr = 0; + } + else if (c == '/') + { + is_dec = is_hex = 0; + if (cp == comma) /* leading / means a pathname */ + is_addr = 0; + } + else if (c == '.') + { + is_dec = is_hex = 0; + dots++; + } + else if (c == '-') + is_hex = is_addr = 0; + else if (c == ' ') + is_dec = is_hex = 0; + else if (!(c >='0' && c <= '9')) + { + is_addr = 0; + if (cp[1] == 0 && is_dec && + (c == 'b' || c == 's' || c == 'i')) + { + lenchar = c; + *cp = 0; + } + else + is_dec = 0; + if (!((c >='A' && c <= 'F') || + (c >='a' && c <= 'f') || + (c == '*' && (flags & DHOPT_MATCH)))) + is_hex = 0; + } + else + found_dig = 1; + + if (!found_dig) + is_dec = is_addr = 0; + + /* We know that some options take addresses */ + if (opt_len & OT_ADDR_LIST) + { + is_string = is_dec = is_hex = 0; + if (!is_addr || dots == 0) + problem = _("bad IP address"); + } + /* or names */ + else if (opt_len & (OT_NAME | OT_RFC1035_NAME)) + is_addr = is_dec = is_hex = 0; + + if (is_hex && digs > 1) + { + new->len = digs; + new->val = opt_malloc(new->len); + parse_hex(comma, new->val, digs, (flags & DHOPT_MATCH) ? &new->u.wildcard_mask : NULL, NULL); + new->flags |= DHOPT_HEX; + } + else if (is_dec) + { + int i, val = atoi(comma); + /* assume numeric arg is 1 byte except for + options where it is known otherwise. + For vendor class option, we have to hack. */ + if (opt_len != 0) + new->len = opt_len; + else if (val & 0xffff0000) + new->len = 4; + else if (val & 0xff00) + new->len = 2; + else + new->len = 1; + + if (lenchar == 'b') + new->len = 1; + else if (lenchar == 's') + new->len = 2; + else if (lenchar == 'i') + new->len = 4; + + new->val = opt_malloc(new->len); + for (i=0; i<new->len; i++) + new->val[i] = val>>((new->len - i - 1)*8); + } + else if (is_addr) + { + struct in_addr in; + unsigned char *op; + char *slash; + /* max length of address/subnet descriptor is five bytes, + add one for the option 120 enc byte too */ + new->val = op = opt_malloc((5 * addrs) + 1); + new->flags |= DHOPT_ADDR; + + if (!(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) && + new->opt == OPTION_SIP_SERVER) + { + *(op++) = 1; /* RFC 3361 "enc byte" */ + new->flags &= ~DHOPT_ADDR; + } + while (addrs--) + { + cp = comma; + comma = split(cp); + slash = split_chr(cp, '/'); + in.s_addr = inet_addr(cp); + if (!slash) + { + memcpy(op, &in, INADDRSZ); + op += INADDRSZ; + } + else + { + unsigned char *p = (unsigned char *)∈ + int netsize = atoi(slash); + *op++ = netsize; + if (netsize > 0) + *op++ = *p++; + if (netsize > 8) + *op++ = *p++; + if (netsize > 16) + *op++ = *p++; + if (netsize > 24) + *op++ = *p++; + new->flags &= ~DHOPT_ADDR; /* cannot re-write descriptor format */ + } + } + new->len = op - new->val; + } + else if (is_string) + { + /* text arg */ + if ((new->opt == OPTION_DOMAIN_SEARCH || new->opt == OPTION_SIP_SERVER) && + !(new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925))) + { + /* dns search, RFC 3397, or SIP, RFC 3361 */ + unsigned char *q, *r, *tail; + unsigned char *p, *m = NULL, *newp; + size_t newlen, len = 0; + int header_size = (new->opt == OPTION_DOMAIN_SEARCH) ? 0 : 1; + + arg = comma; + comma = split(arg); + + while (arg && *arg) + { + char *in, *dom = NULL; + size_t domlen = 1; + /* Allow "." as an empty domain */ + if (strcmp (arg, ".") != 0) + { + if (!(dom = canonicalise_opt(arg))) + { + problem = _("bad domain in dhcp-option"); + break; + } + domlen = strlen(dom) + 2; + } + + newp = opt_malloc(len + domlen + header_size); + if (m) + { + memcpy(newp, m, header_size + len); + free(m); + } + m = newp; + p = m + header_size; + q = p + len; + + /* add string on the end in RFC1035 format */ + for (in = dom; in && *in;) + { + unsigned char *cp = q++; + int j; + for (j = 0; *in && (*in != '.'); in++, j++) + *q++ = *in; + *cp = j; + if (*in) + in++; + } + *q++ = 0; + free(dom); + + /* Now tail-compress using earlier names. */ + newlen = q - p; + for (tail = p + len; *tail; tail += (*tail) + 1) + for (r = p; r - p < (int)len; r += (*r) + 1) + if (strcmp((char *)r, (char *)tail) == 0) + { + PUTSHORT((r - p) | 0xc000, tail); + newlen = tail - p; + goto end; + } + end: + len = newlen; + + arg = comma; + comma = split(arg); + } + + /* RFC 3361, enc byte is zero for names */ + if (new->opt == OPTION_SIP_SERVER) + m[0] = 0; + new->len = (int) len + header_size; + new->val = m; + } + else + { + new->len = strlen(comma); + /* keep terminating zero on string */ + new->val = (unsigned char *)opt_string_alloc(comma); + new->flags |= DHOPT_STRING; + } + } + } + + if ((new->len > 255) || + (new->len > 253 && (new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE))) || + (new->len > 250 && (new->flags & DHOPT_RFC3925))) + problem = _("dhcp-option too long"); + + if (!problem) + { + if (flags == DHOPT_MATCH) + { + if ((new->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR)) || + !new->netid || + new->netid->next) + problem = _("illegal dhcp-match"); + else + { + new->next = daemon->dhcp_match; + daemon->dhcp_match = new; + } + } + else + { + new->next = daemon->dhcp_opts; + daemon->dhcp_opts = new; + } + } + + return problem; +} + +#endif + +void set_option_bool(unsigned int opt) +{ + if (opt < 32) + daemon->options |= 1u << opt; + else + daemon->options2 |= 1u << (opt - 32); +} + +static char *one_opt(int option, char *arg, char *gen_prob, int command_line) +{ + int i; + char *comma, *problem = NULL;; + + if (option == '?') + return gen_prob; + + for (i=0; usage[i].opt != 0; i++) + if (usage[i].opt == option) + { + int rept = usage[i].rept; + + if (command_line) + { + /* command line */ + if (rept == ARG_USED_CL) + return _("illegal repeated flag"); + if (rept == ARG_ONE) + usage[i].rept = ARG_USED_CL; + } + else + { + /* allow file to override command line */ + if (rept == ARG_USED_FILE) + return _("illegal repeated keyword"); + if (rept == ARG_USED_CL || rept == ARG_ONE) + usage[i].rept = ARG_USED_FILE; + } + + if (rept != ARG_DUP && rept != ARG_ONE && rept != ARG_USED_CL) + { + set_option_bool(rept); + return NULL; + } + + break; + } + + switch (option) + { + case 'C': /* --conf-file */ + { + char *file = opt_string_alloc(arg); + if (file) + { + one_file(file, 0); + free(file); + } + break; + } + + case '7': /* --conf-dir */ + { + DIR *dir_stream; + struct dirent *ent; + char *directory, *path; + struct list { + char *suffix; + struct list *next; + } *ignore_suffix = NULL, *li; + + comma = split(arg); + if (!(directory = opt_string_alloc(arg))) + break; + + for (arg = comma; arg; arg = comma) + { + comma = split(arg); + li = opt_malloc(sizeof(struct list)); + li->next = ignore_suffix; + ignore_suffix = li; + /* Have to copy: buffer is overwritten */ + li->suffix = opt_string_alloc(arg); + }; + + if (!(dir_stream = opendir(directory))) + die(_("cannot access directory %s: %s"), directory, EC_FILE); + + while ((ent = readdir(dir_stream))) + { + size_t len = strlen(ent->d_name); + struct stat buf; + + /* ignore emacs backups and dotfiles */ + if (len == 0 || + ent->d_name[len - 1] == '~' || + (ent->d_name[0] == '#' && ent->d_name[len - 1] == '#') || + ent->d_name[0] == '.') + continue; + + for (li = ignore_suffix; li; li = li->next) + { + /* check for proscribed suffices */ + size_t ls = strlen(li->suffix); + if (len > ls && + strcmp(li->suffix, &ent->d_name[len - ls]) == 0) + break; + } + if (li) + continue; + + path = opt_malloc(strlen(directory) + len + 2); + strcpy(path, directory); + strcat(path, "/"); + strcat(path, ent->d_name); + + if (stat(path, &buf) == -1) + die(_("cannot access %s: %s"), path, EC_FILE); + /* only reg files allowed. */ + if (!S_ISREG(buf.st_mode)) + continue; + + /* files must be readable */ + one_file(path, 0); + free(path); + } + + closedir(dir_stream); + free(directory); + for(; ignore_suffix; ignore_suffix = li) + { + li = ignore_suffix->next; + free(ignore_suffix->suffix); + free(ignore_suffix); + } + + break; + } + + case '8': /* --log-facility */ + /* may be a filename */ + if (strchr(arg, '/') || strcmp (arg, "-") == 0) + daemon->log_file = opt_string_alloc(arg); + else + { +#ifdef __ANDROID__ + problem = _("setting log facility is not possible under Android"); +#else + for (i = 0; facilitynames[i].c_name; i++) + if (hostname_isequal((char *)facilitynames[i].c_name, arg)) + break; + + if (facilitynames[i].c_name) + daemon->log_fac = facilitynames[i].c_val; + else + problem = _("bad log facility"); +#endif + } + break; + + case 'x': /* --pid-file */ + daemon->runfile = opt_string_alloc(arg); + break; + + case 'r': /* --resolv-file */ + { + char *name = opt_string_alloc(arg); + struct resolvc *new, *list = daemon->resolv_files; + + if (list && list->is_default) + { + /* replace default resolv file - possibly with nothing */ + if (name) + { + list->is_default = 0; + list->name = name; + } + else + list = NULL; + } + else if (name) + { + new = opt_malloc(sizeof(struct resolvc)); + new->next = list; + new->name = name; + new->is_default = 0; + new->mtime = 0; + new->logged = 0; + list = new; + } + daemon->resolv_files = list; + break; + } + + case 'm': /* --mx-host */ + { + int pref = 1; + struct mx_srv_record *new; + char *name, *target = NULL; + + if ((comma = split(arg))) + { + char *prefstr; + if ((prefstr = split(comma)) && !atoi_check16(prefstr, &pref)) + problem = _("bad MX preference"); + } + + if (!(name = canonicalise_opt(arg)) || + (comma && !(target = canonicalise_opt(comma)))) + problem = _("bad MX name"); + + new = opt_malloc(sizeof(struct mx_srv_record)); + new->next = daemon->mxnames; + daemon->mxnames = new; + new->issrv = 0; + new->name = name; + new->target = target; /* may be NULL */ + new->weight = pref; + break; + } + + case 't': /* --mx-target */ + if (!(daemon->mxtarget = canonicalise_opt(arg))) + problem = _("bad MX target"); + break; + +#ifdef HAVE_DHCP + case 'l': /* --dhcp-leasefile */ + daemon->lease_file = opt_string_alloc(arg); + break; + + case '6': /* --dhcp-script */ +# if defined(NO_FORK) + problem = _("cannot run scripts under uClinux"); +# elif !defined(HAVE_SCRIPT) + problem = _("recompile with HAVE_SCRIPT defined to enable lease-change scripts"); +# else + daemon->lease_change_command = opt_string_alloc(arg); +# endif + break; +#endif + + case LOPT_DHCP_HOST: /* --dhcp-hostfile */ + case LOPT_DHCP_OPTS: /* --dhcp-optsfile */ + case 'H': /* --addn-hosts */ + { + struct hostsfile *new = opt_malloc(sizeof(struct hostsfile)); + static int hosts_index = 1; + new->fname = opt_string_alloc(arg); + new->index = hosts_index++; + new->flags = 0; + if (option == 'H') + { + new->next = daemon->addn_hosts; + daemon->addn_hosts = new; + } + else if (option == LOPT_DHCP_HOST) + { + new->next = daemon->dhcp_hosts_file; + daemon->dhcp_hosts_file = new; + } + else if (option == LOPT_DHCP_OPTS) + { + new->next = daemon->dhcp_opts_file; + daemon->dhcp_opts_file = new; + } + break; + } + + case 's': /* --domain */ + if (strcmp (arg, "#") == 0) + set_option_bool(OPT_RESOLV_DOMAIN); + else + { + char *d; + comma = split(arg); + if (!(d = canonicalise_opt(arg))) + option = '?'; + else + { + if (comma) + { + struct cond_domain *new = safe_malloc(sizeof(struct cond_domain)); + char *netpart; + + unhide_metas(comma); + if ((netpart = split_chr(comma, '/'))) + { + int msize, mask; + arg = split(netpart); + if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 || + !atoi_check(netpart, &msize)) + option = '?'; + else + { + mask = (1 << (32 - msize)) - 1; + new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask); + new->end.s_addr = new->start.s_addr | htonl(mask); + if (arg) + { + /* generate the equivalent of + local=/<domain>/ + local=/xxx.yyy.zzz.in-addr.arpa/ */ + + if (strcmp(arg, "local") != 0 || + (msize != 8 && msize != 16 && msize != 24)) + option = '?'; + else + { + struct server *serv = opt_malloc(sizeof(struct server)); + in_addr_t a = ntohl(new->start.s_addr) >> 8; + char *p; + + memset(serv, 0, sizeof(struct server)); + serv->domain = d; + serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; + serv->next = daemon->servers; + daemon->servers = serv; + + serv = opt_malloc(sizeof(struct server)); + memset(serv, 0, sizeof(struct server)); + p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */ + + if (msize == 24) + p += sprintf(p, "%d.", a & 0xff); + a = a >> 8; + if (msize != 8) + p += sprintf(p, "%d.", a & 0xff); + a = a >> 8; + p += sprintf(p, "%d.in-addr.arpa", a & 0xff); + + serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR; + serv->next = daemon->servers; + daemon->servers = serv; + } + } + } + } + else if ((arg = split(comma))) + { + if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 || + (new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1) + option = '?'; + } + else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1) + option = '?'; + + new->domain = d; + new->next = daemon->cond_domain; + daemon->cond_domain = new; + } + else + daemon->domain_suffix = d; + } + } + break; + + case 'u': /* --user */ + daemon->username = opt_string_alloc(arg); + break; + + case 'g': /* --group */ + daemon->groupname = opt_string_alloc(arg); + daemon->group_set = 1; + break; + +#ifdef HAVE_DHCP + case LOPT_SCRIPTUSR: /* --scriptuser */ + daemon->scriptuser = opt_string_alloc(arg); + break; +#endif + + case 'i': /* --interface */ + do { + struct iname *new = opt_malloc(sizeof(struct iname)); + comma = split(arg); + new->next = daemon->if_names; + daemon->if_names = new; + /* new->name may be NULL if someone does + "interface=" to disable all interfaces except loop. */ + new->name = opt_string_alloc(arg); + new->isloop = new->used = 0; + arg = comma; + } while (arg); + break; + + case 'I': /* --except-interface */ + case '2': /* --no-dhcp-interface */ + do { + struct iname *new = opt_malloc(sizeof(struct iname)); + comma = split(arg); + new->name = opt_string_alloc(arg); + if (option == 'I') + { + new->next = daemon->if_except; + daemon->if_except = new; + } + else + { + new->next = daemon->dhcp_except; + daemon->dhcp_except = new; + } + arg = comma; + } while (arg); + break; + + case 'B': /* --bogus-nxdomain */ + { + struct in_addr addr; + unhide_metas(arg); + if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1) + { + struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr)); + baddr->next = daemon->bogus_addr; + daemon->bogus_addr = baddr; + baddr->addr = addr; + } + else + option = '?'; /* error */ + break; + } + + case 'a': /* --listen-address */ + do { + struct iname *new = opt_malloc(sizeof(struct iname)); + comma = split(arg); + unhide_metas(arg); + new->next = daemon->if_addrs; + if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1) + { + new->addr.sa.sa_family = AF_INET; +#ifdef HAVE_SOCKADDR_SA_LEN + new->addr.in.sin_len = sizeof(new->addr.in); +#endif + } +#ifdef HAVE_IPV6 + else if (arg && inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0) + { + new->addr.sa.sa_family = AF_INET6; + new->addr.in6.sin6_flowinfo = 0; + new->addr.in6.sin6_scope_id = 0; +#ifdef HAVE_SOCKADDR_SA_LEN + new->addr.in6.sin6_len = sizeof(new->addr.in6); +#endif + } +#endif + else + { + option = '?'; /* error */ + break; + } + + daemon->if_addrs = new; + arg = comma; + } while (arg); + break; + + case 'S': /* --server */ + case LOPT_LOCAL: /* --local */ + case 'A': /* --address */ + case LOPT_NO_REBIND: /* --rebind-domain-ok */ + { + struct server *serv, *newlist = NULL; + + unhide_metas(arg); + + if (arg && (*arg == '/' || option == LOPT_NO_REBIND)) + { + int rebind = !(*arg == '/'); + char *end = NULL; + if (!rebind) + arg++; + while (rebind || (end = split_chr(arg, '/'))) + { + char *domain = NULL; + /* elide leading dots - they are implied in the search algorithm */ + while (*arg == '.') arg++; + /* # matches everything and becomes a zero length domain string */ + if (strcmp(arg, "#") == 0) + domain = ""; + else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg))) + option = '?'; + serv = opt_malloc(sizeof(struct server)); + memset(serv, 0, sizeof(struct server)); + serv->next = newlist; + newlist = serv; + serv->domain = domain; + serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS; + arg = end; + if (rebind) + break; + } + if (!newlist) + { + option = '?'; + break; + } + + } + else + { + newlist = opt_malloc(sizeof(struct server)); + memset(newlist, 0, sizeof(struct server)); + } + + if (option == 'A') + { + newlist->flags |= SERV_LITERAL_ADDRESS; + if (!(newlist->flags & SERV_TYPE)) + option = '?'; + } + else if (option == LOPT_NO_REBIND) + newlist->flags |= SERV_NO_REBIND; + + if (!arg || !*arg) + { + if (!(newlist->flags & SERV_NO_REBIND)) + newlist->flags |= SERV_NO_ADDR; /* no server */ + if (newlist->flags & SERV_LITERAL_ADDRESS) + option = '?'; + } + + else if (strcmp(arg, "#") == 0) + { + newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */ + if (newlist->flags & SERV_LITERAL_ADDRESS) + option = '?'; + } + else + { + int source_port = 0, serv_port = NAMESERVER_PORT; + char *portno, *source; + + if ((source = split_chr(arg, '@')) && /* is there a source. */ + (portno = split_chr(source, '#')) && + !atoi_check16(portno, &source_port)) + problem = _("bad port"); + + if ((portno = split_chr(arg, '#')) && /* is there a port no. */ + !atoi_check16(portno, &serv_port)) + problem = _("bad port"); + + if ((newlist->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1) + { + newlist->addr.in.sin_port = htons(serv_port); + newlist->source_addr.in.sin_port = htons(source_port); + newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET; +#ifdef HAVE_SOCKADDR_SA_LEN + newlist->source_addr.in.sin_len = newlist->addr.in.sin_len = sizeof(struct sockaddr_in); +#endif + if (source) + { + newlist->flags |= SERV_HAS_SOURCE; + if ((newlist->source_addr.in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1) + { +#if defined(SO_BINDTODEVICE) + newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY; + strncpy(newlist->interface, source, IF_NAMESIZE - 1); +#else + problem = _("interface binding not supported"); +#endif + } + } + else + newlist->source_addr.in.sin_addr.s_addr = INADDR_ANY; + } +#ifdef HAVE_IPV6 + else if (inet_pton(AF_INET6, arg, &newlist->addr.in6.sin6_addr) > 0) + { + newlist->addr.in6.sin6_port = htons(serv_port); + newlist->source_addr.in6.sin6_port = htons(source_port); + newlist->addr.sa.sa_family = newlist->source_addr.sa.sa_family = AF_INET6; +#ifdef HAVE_SOCKADDR_SA_LEN + newlist->addr.in6.sin6_len = newlist->source_addr.in6.sin6_len = sizeof(newlist->addr.in6); +#endif + if (source) + { + newlist->flags |= SERV_HAS_SOURCE; + if (inet_pton(AF_INET6, source, &newlist->source_addr.in6.sin6_addr) == 0) + { +#if defined(SO_BINDTODEVICE) + newlist->source_addr.in6.sin6_addr = in6addr_any; + strncpy(newlist->interface, source, IF_NAMESIZE - 1); +#else + problem = _("interface binding not supported"); +#endif + } + } + else + newlist->source_addr.in6.sin6_addr = in6addr_any; + } +#endif + else + option = '?'; /* error */ + + } + + serv = newlist; + while (serv->next) + { + serv->next->flags = serv->flags; + serv->next->addr = serv->addr; + serv->next->source_addr = serv->source_addr; + serv = serv->next; + } + serv->next = daemon->servers; + daemon->servers = newlist; + break; + } + + case 'c': /* --cache-size */ + { + int size; + + if (!atoi_check(arg, &size)) + option = '?'; + else + { + /* zero is OK, and means no caching. */ + + if (size < 0) + size = 0; + else if (size > 10000) + size = 10000; + + daemon->cachesize = size; + } + break; + } + + case 'p': /* --port */ + if (!atoi_check16(arg, &daemon->port)) + option = '?'; + break; + + case LOPT_MINPORT: /* --min-port */ + if (!atoi_check16(arg, &daemon->min_port)) + option = '?'; + break; + + case '0': /* --dns-forward-max */ + if (!atoi_check(arg, &daemon->ftabsize)) + option = '?'; + break; + + case LOPT_MAX_LOGS: /* --log-async */ + daemon->max_logs = LOG_MAX; /* default */ + if (arg && !atoi_check(arg, &daemon->max_logs)) + option = '?'; + else if (daemon->max_logs > 100) + daemon->max_logs = 100; + break; + + case 'P': /* --edns-packet-max */ + { + int i; + if (!atoi_check(arg, &i)) + option = '?'; + daemon->edns_pktsz = (unsigned short)i; + break; + } + + case 'Q': /* --query-port */ + if (!atoi_check16(arg, &daemon->query_port)) + option = '?'; + /* if explicitly set to zero, use single OS ephemeral port + and disable random ports */ + if (daemon->query_port == 0) + daemon->osport = 1; + break; + + case 'T': /* --local-ttl */ + case LOPT_NEGTTL: /* --neg-ttl */ + case LOPT_MAXTTL: /* --max-ttl */ + { + int ttl; + if (!atoi_check(arg, &ttl)) + option = '?'; + else if (option == LOPT_NEGTTL) + daemon->neg_ttl = (unsigned long)ttl; + else if (option == LOPT_MAXTTL) + daemon->max_ttl = (unsigned long)ttl; + else + daemon->local_ttl = (unsigned long)ttl; + break; + } + +#ifdef HAVE_DHCP + case 'X': /* --dhcp-lease-max */ + if (!atoi_check(arg, &daemon->dhcp_max)) + option = '?'; + break; +#endif + +#ifdef HAVE_TFTP + case LOPT_TFTP: /* --enable-tftp */ + if (arg) + { + struct interface_list *new = opt_malloc(sizeof(struct interface_list)); + new->interface = opt_string_alloc(arg); + new->next = daemon->tftp_interfaces; + daemon->tftp_interfaces = new; + } + else + daemon->tftp_unlimited = 1; + break; + + case LOPT_TFTP_MAX: /* --tftp-max */ + if (!atoi_check(arg, &daemon->tftp_max)) + option = '?'; + break; + + case LOPT_PREFIX: /* --tftp-prefix */ + comma = split(arg); + if (comma) + { + struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix)); + new->interface = opt_string_alloc(comma); + new->prefix = opt_string_alloc(arg); + new->next = daemon->if_prefix; + daemon->if_prefix = new; + } + else + daemon->tftp_prefix = opt_string_alloc(arg); + break; + + case LOPT_TFTPPORTS: /* --tftp-port-range */ + if (!(comma = split(arg)) || + !atoi_check16(arg, &daemon->start_tftp_port) || + !atoi_check16(comma, &daemon->end_tftp_port)) + problem = _("bad port range"); + + if (daemon->start_tftp_port > daemon->end_tftp_port) + { + int tmp = daemon->start_tftp_port; + daemon->start_tftp_port = daemon->end_tftp_port; + daemon->end_tftp_port = tmp; + } + + break; +#endif + + case LOPT_BRIDGE: /* --bridge-interface */ + { + struct dhcp_bridge *new = opt_malloc(sizeof(struct dhcp_bridge)); + if (!(comma = split(arg)) || strlen(arg) > IF_NAMESIZE - 1 ) + { + problem = _("bad bridge-interface"); + break; + } + + strcpy(new->iface, arg); + new->alias = NULL; + new->next = daemon->bridges; + daemon->bridges = new; + + do { + arg = comma; + comma = split(arg); + if (strlen(arg) != 0 && strlen(arg) <= IF_NAMESIZE - 1) + { + struct dhcp_bridge *b = opt_malloc(sizeof(struct dhcp_bridge)); + b->next = new->alias; + new->alias = b; + strcpy(b->iface, arg); + } + } while (comma); + + break; + } + +#ifdef HAVE_DHCP + case 'F': /* --dhcp-range */ + { + int k, leasepos = 2; + char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL }; + struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context)); + + new->next = daemon->dhcp; + new->lease_time = DEFLEASE; + new->addr_epoch = 0; + new->netmask.s_addr = 0; + new->broadcast.s_addr = 0; + new->router.s_addr = 0; + new->netid.net = NULL; + new->filter = NULL; + new->flags = 0; + new->interface = NULL; + + gen_prob = _("bad dhcp-range"); + + if (!arg) + { + option = '?'; + break; + } + + while(1) + { + for (cp = arg; *cp; cp++) + if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9'))) + break; + + if (*cp != ',' && (comma = split(arg))) + { + if (strstr(arg, "interface:") == arg) + new->interface = opt_string_alloc(arg+10); + else if (is_tag_prefix(arg)) + { + struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid)); + tt->net = opt_string_alloc(arg+4); + tt->next = new->filter; + new->filter = tt; + } + else + { + if (new->netid.net) + problem = _("only one tag allowed"); + else if (strstr(arg, "set:") == arg) + new->netid.net = opt_string_alloc(arg+4); + else + new->netid.net = opt_string_alloc(arg); + } + arg = comma; + } + else + { + a[0] = arg; + break; + } + } + + for (k = 1; k < 5; k++) + if (!(a[k] = split(a[k-1]))) + break; + + if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1)) + option = '?'; + else if (strcmp(a[1], "static") == 0) + { + new->end = new->start; + new->flags |= CONTEXT_STATIC; + } + else if (strcmp(a[1], "proxy") == 0) + { + new->end = new->start; + new->flags |= CONTEXT_PROXY; + } + else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1) + option = '?'; + + if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) + { + struct in_addr tmp = new->start; + new->start = new->end; + new->end = tmp; + } + + if (option != '?' && k >= 3 && strchr(a[2], '.') && + ((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1)) + { + new->flags |= CONTEXT_NETMASK; + leasepos = 3; + if (!is_same_net(new->start, new->end, new->netmask)) + problem = _("inconsistent DHCP range"); + } + daemon->dhcp = new; + + if (k >= 4 && strchr(a[3], '.') && + ((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1)) + { + new->flags |= CONTEXT_BRDCAST; + leasepos = 4; + } + + if (k >= leasepos+1) + { + if (strcmp(a[leasepos], "infinite") == 0) + new->lease_time = 0xffffffff; + else + { + int fac = 1; + if (strlen(a[leasepos]) > 0) + { + switch (a[leasepos][strlen(a[leasepos]) - 1]) + { + case 'd': + case 'D': + fac *= 24; + /* fall though */ + case 'h': + case 'H': + fac *= 60; + /* fall through */ + case 'm': + case 'M': + fac *= 60; + /* fall through */ + case 's': + case 'S': + a[leasepos][strlen(a[leasepos]) - 1] = 0; + } + + new->lease_time = atoi(a[leasepos]) * fac; + /* Leases of a minute or less confuse + some clients, notably Apple's */ + if (new->lease_time < 120) + new->lease_time = 120; + } + } + } + break; + } + + case LOPT_BANK: + case 'G': /* --dhcp-host */ + { + int j, k = 0; + char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL }; + struct dhcp_config *new; + struct in_addr in; + + new = opt_malloc(sizeof(struct dhcp_config)); + + new->next = daemon->dhcp_conf; + new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0; + new->hwaddr = NULL; + new->netid = NULL; + + if ((a[0] = arg)) + for (k = 1; k < 6; k++) + if (!(a[k] = split(a[k-1]))) + break; + + for (j = 0; j < k; j++) + if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */ + { + char *arg = a[j]; + + if ((arg[0] == 'i' || arg[0] == 'I') && + (arg[1] == 'd' || arg[1] == 'D') && + arg[2] == ':') + { + if (arg[3] == '*') + new->flags |= CONFIG_NOCLID; + else + { + int len; + arg += 3; /* dump id: */ + if (strchr(arg, ':')) + len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL); + else + { + unhide_metas(arg); + len = (int) strlen(arg); + } + + if (len == -1) + problem = _("bad hex constant"); + else if ((new->clid = opt_malloc(len))) + { + new->flags |= CONFIG_CLID; + new->clid_len = len; + memcpy(new->clid, arg, len); + } + } + } + /* dhcp-host has strange backwards-compat needs. */ + else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg) + { + struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid)); + struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list)); + newtag->net = opt_malloc(strlen(arg + 4) + 1); + newlist->next = new->netid; + new->netid = newlist; + newlist->list = newtag; + strcpy(newtag->net, arg+4); + unhide_metas(newtag->net); + } + else + { + struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config)); + if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX, + &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1) + problem = _("bad hex constant"); + else + { + + newhw->next = new->hwaddr; + new->hwaddr = newhw; + } + } + } + else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1) + { + new->addr = in; + new->flags |= CONFIG_ADDR; + } + else + { + char *cp, *lastp = NULL, last = 0; + int fac = 1; + + if (strlen(a[j]) > 1) + { + lastp = a[j] + strlen(a[j]) - 1; + last = *lastp; + switch (last) + { + case 'd': + case 'D': + fac *= 24; + /* fall through */ + case 'h': + case 'H': + fac *= 60; + /* fall through */ + case 'm': + case 'M': + fac *= 60; + /* fall through */ + case 's': + case 'S': + *lastp = 0; + } + } + + for (cp = a[j]; *cp; cp++) + if (!isdigit((unsigned char)*cp) && *cp != ' ') + break; + + if (*cp) + { + if (lastp) + *lastp = last; + if (strcmp(a[j], "infinite") == 0) + { + new->lease_time = 0xffffffff; + new->flags |= CONFIG_TIME; + } + else if (strcmp(a[j], "ignore") == 0) + new->flags |= CONFIG_DISABLE; + else + { + if (!(new->hostname = canonicalise_opt(a[j])) || + !legal_hostname(new->hostname)) + problem = _("bad DHCP host name"); + else + new->flags |= CONFIG_NAME; + new->domain = NULL; + } + } + else + { + new->lease_time = atoi(a[j]) * fac; + /* Leases of a minute or less confuse + some clients, notably Apple's */ + if (new->lease_time < 120) + new->lease_time = 120; + new->flags |= CONFIG_TIME; + } + } + + daemon->dhcp_conf = new; + break; + } + + case LOPT_TAG_IF: /* --tag-if */ + { + struct tag_if *new = opt_malloc(sizeof(struct tag_if)); + + new->tag = NULL; + new->set = NULL; + new->next = NULL; + + /* preserve order */ + if (!daemon->tag_if) + daemon->tag_if = new; + else + { + struct tag_if *tmp; + for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next); + tmp->next = new; + } + + while (arg) + { + size_t len; + + comma = split(arg); + len = strlen(arg); + + if (len < 5) + { + new->set = NULL; + break; + } + else + { + struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid)); + newtag->net = opt_malloc(len - 3); + strcpy(newtag->net, arg+4); + unhide_metas(newtag->net); + + if (strstr(arg, "set:") == arg) + { + struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list)); + newlist->next = new->set; + new->set = newlist; + newlist->list = newtag; + } + else if (strstr(arg, "tag:") == arg) + { + newtag->next = new->tag; + new->tag = newtag; + } + else + { + new->set = NULL; + break; + } + } + + arg = comma; + } + + if (!new->set) + problem = _("bad tag-if"); + + break; + } + + + case 'O': /* --dhcp-option */ + case LOPT_FORCE: /* --dhcp-option-force */ + case LOPT_OPTS: + case LOPT_MATCH: /* --dhcp-match */ + problem = parse_dhcp_opt(arg, + option == LOPT_FORCE ? DHOPT_FORCE : + (option == LOPT_MATCH ? DHOPT_MATCH : + (option == LOPT_OPTS ? DHOPT_BANK : 0))); + break; + + case 'M': /* --dhcp-boot */ + { + struct dhcp_netid *id = NULL; + while (is_tag_prefix(arg)) + { + struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid)); + newid->next = id; + id = newid; + comma = split(arg); + newid->net = opt_string_alloc(arg+4); + arg = comma; + }; + + if (!arg) + option = '?'; + else + { + char *dhcp_file, *dhcp_sname = NULL; + struct in_addr dhcp_next_server; + comma = split(arg); + dhcp_file = opt_string_alloc(arg); + dhcp_next_server.s_addr = 0; + if (comma) + { + arg = comma; + comma = split(arg); + dhcp_sname = opt_string_alloc(arg); + if (comma) + { + unhide_metas(comma); + if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) + option = '?'; + } + } + if (option != '?') + { + struct dhcp_boot *new = opt_malloc(sizeof(struct dhcp_boot)); + new->file = dhcp_file; + new->sname = dhcp_sname; + new->next_server = dhcp_next_server; + new->netid = id; + new->next = daemon->boot_config; + daemon->boot_config = new; + } + } + + break; + } + + case LOPT_PXE_PROMT: /* --pxe-prompt */ + { + struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt)); + int timeout; + + new->netid = NULL; + new->opt = 10; /* PXE_MENU_PROMPT */ + + while (is_tag_prefix(arg)) + { + struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); + comma = split(arg); + nn->next = new->netid; + new->netid = nn; + nn->net = opt_string_alloc(arg+4); + arg = comma; + } + + if (!arg) + option = '?'; + else + { + comma = split(arg); + unhide_metas(arg); + new->len = strlen(arg) + 1; + new->val = opt_malloc(new->len); + memcpy(new->val + 1, arg, new->len - 1); + + new->u.vendor_class = (unsigned char *)"PXEClient"; + new->flags = DHOPT_VENDOR; + + if (comma && atoi_check(comma, &timeout)) + *(new->val) = timeout; + else + *(new->val) = 255; + + new->next = daemon->dhcp_opts; + daemon->dhcp_opts = new; + daemon->enable_pxe = 1; + } + + break; + } + + case LOPT_PXE_SERV: /* --pxe-service */ + { + struct pxe_service *new = opt_malloc(sizeof(struct pxe_service)); + char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client", + "IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL }; + static int boottype = 32768; + + new->netid = NULL; + new->server.s_addr = 0; + + while (is_tag_prefix(arg)) + { + struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid)); + comma = split(arg); + nn->next = new->netid; + new->netid = nn; + nn->net = opt_string_alloc(arg+4); + arg = comma; + } + + if (arg && (comma = split(arg))) + { + for (i = 0; CSA[i]; i++) + if (strcasecmp(CSA[i], arg) == 0) + break; + + if (CSA[i] || atoi_check(arg, &i)) + { + arg = comma; + comma = split(arg); + + new->CSA = i; + new->menu = opt_string_alloc(arg); + + if (!comma) + { + new->type = 0; /* local boot */ + new->basename = NULL; + } + else + { + arg = comma; + comma = split(arg); + if (atoi_check(arg, &i)) + { + new->type = i; + new->basename = NULL; + } + else + { + new->type = boottype++; + new->basename = opt_string_alloc(arg); + } + + if (comma && (new->server.s_addr = inet_addr(comma)) == (in_addr_t)-1) + option = '?'; + } + + /* Order matters */ + new->next = NULL; + if (!daemon->pxe_services) + daemon->pxe_services = new; + else + { + struct pxe_service *s; + for (s = daemon->pxe_services; s->next; s = s->next); + s->next = new; + } + + daemon->enable_pxe = 1; + break; + + } + } + + option = '?'; + break; + } + + case '4': /* --dhcp-mac */ + { + if (!(comma = split(arg))) + option = '?'; + else + { + struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac)); + new->netid.net = opt_string_alloc(set_prefix(arg)); + unhide_metas(comma); + new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type); + if (new->hwaddr_len == -1) + option = '?'; + else + { + new->next = daemon->dhcp_macs; + daemon->dhcp_macs = new; + } + } + } + break; + + case 'U': /* --dhcp-vendorclass */ + case 'j': /* --dhcp-userclass */ + case LOPT_CIRCUIT: /* --dhcp-circuitid */ + case LOPT_REMOTE: /* --dhcp-remoteid */ + case LOPT_SUBSCR: /* --dhcp-subscrid */ + { + if (!(comma = split(arg))) + option = '?'; + else + { + unsigned char *p; + int dig = 0; + struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor)); + new->netid.net = opt_string_alloc(set_prefix(arg)); + /* check for hex string - must digits may include : must not have nothing else, + only allowed for agent-options. */ + for (p = (unsigned char *)comma; *p; p++) + if (isxdigit(*p)) + dig = 1; + else if (*p != ':') + break; + unhide_metas(comma); + if (option == 'U' || option == 'j' || *p || !dig) + { + new->len = strlen(comma); + new->data = opt_malloc(new->len); + memcpy(new->data, comma, new->len); + } + else + { + new->len = parse_hex(comma, (unsigned char *)comma, strlen(comma), NULL, NULL); + new->data = opt_malloc(new->len); + memcpy(new->data, comma, new->len); + } + + switch (option) + { + case 'j': + new->match_type = MATCH_USER; + break; + case 'U': + new->match_type = MATCH_VENDOR; + break; + case LOPT_CIRCUIT: + new->match_type = MATCH_CIRCUIT; + break; + case LOPT_REMOTE: + new->match_type = MATCH_REMOTE; + break; + case LOPT_SUBSCR: + new->match_type = MATCH_SUBSCRIBER; + break; + } + new->next = daemon->dhcp_vendors; + daemon->dhcp_vendors = new; + } + break; + } + + case LOPT_ALTPORT: /* --dhcp-alternate-port */ + if (!arg) + { + daemon->dhcp_server_port = DHCP_SERVER_ALTPORT; + daemon->dhcp_client_port = DHCP_CLIENT_ALTPORT; + } + else + { + comma = split(arg); + if (!atoi_check16(arg, &daemon->dhcp_server_port) || + (comma && !atoi_check16(comma, &daemon->dhcp_client_port))) + problem = _("invalid port number"); + if (!comma) + daemon->dhcp_client_port = daemon->dhcp_server_port+1; + } + break; + + case 'J': /* --dhcp-ignore */ + case LOPT_NO_NAMES: /* --dhcp-ignore-names */ + case LOPT_BROADCAST: /* --dhcp-broadcast */ + case '3': /* --bootp-dynamic */ + case LOPT_GEN_NAMES: /* --dhcp-generate-names */ + { + struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list)); + struct dhcp_netid *list = NULL; + if (option == 'J') + { + new->next = daemon->dhcp_ignore; + daemon->dhcp_ignore = new; + } + else if (option == LOPT_BROADCAST) + { + new->next = daemon->force_broadcast; + daemon->force_broadcast = new; + } + else if (option == '3') + { + new->next = daemon->bootp_dynamic; + daemon->bootp_dynamic = new; + } + else if (option == LOPT_GEN_NAMES) + { + new->next = daemon->dhcp_gen_names; + daemon->dhcp_gen_names = new; + } + else + { + new->next = daemon->dhcp_ignore_names; + daemon->dhcp_ignore_names = new; + } + + while (arg) { + struct dhcp_netid *member = opt_malloc(sizeof(struct dhcp_netid)); + comma = split(arg); + member->next = list; + list = member; + if (is_tag_prefix(arg)) + member->net = opt_string_alloc(arg+4); + else + member->net = opt_string_alloc(arg); + arg = comma; + } + + new->list = list; + break; + } + + case LOPT_PROXY: /* --dhcp-proxy */ + daemon->override = 1; + while (arg) { + struct addr_list *new = opt_malloc(sizeof(struct addr_list)); + comma = split(arg); + if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1) + problem = _("bad dhcp-proxy address"); + new->next = daemon->override_relays; + daemon->override_relays = new; + arg = comma; + } + break; +#endif + + case 'V': /* --alias */ + { + char *dash, *a[3] = { NULL, NULL, NULL }; + int k = 0; + struct doctor *new = opt_malloc(sizeof(struct doctor)); + new->next = daemon->doctors; + daemon->doctors = new; + new->mask.s_addr = 0xffffffff; + new->end.s_addr = 0; + + if ((a[0] = arg)) + for (k = 1; k < 3; k++) + { + if (!(a[k] = split(a[k-1]))) + break; + unhide_metas(a[k]); + } + + dash = split_chr(a[0], '-'); + + if ((k < 2) || + ((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) || + ((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1)) + option = '?'; + + if (k == 3) + new->mask.s_addr = inet_addr(a[2]); + + if (dash && + ((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 || + !is_same_net(new->in, new->end, new->mask) || + ntohl(new->in.s_addr) > ntohl(new->end.s_addr))) + problem = _("invalid alias range"); + + break; + } + + case LOPT_INTNAME: /* --interface-name */ + { + struct interface_name *new, **up; + char *domain = NULL; + + comma = split(arg); + + if (!comma || !(domain = canonicalise_opt(arg))) + problem = _("bad interface name"); + + new = opt_malloc(sizeof(struct interface_name)); + new->next = NULL; + /* Add to the end of the list, so that first name + of an interface is used for PTR lookups. */ + for (up = &daemon->int_names; *up; up = &((*up)->next)); + *up = new; + new->name = domain; + new->intr = opt_string_alloc(comma); + break; + } + + case LOPT_CNAME: /* --cname */ + { + struct cname *new; + + if (!(comma = split(arg))) + option = '?'; + else + { + char *alias = canonicalise_opt(arg); + char *target = canonicalise_opt(comma); + + if (!alias || !target) + problem = _("bad CNAME"); + else + { + for (new = daemon->cnames; new; new = new->next) + if (hostname_isequal(new->alias, arg)) + problem = _("duplicate CNAME"); + new = opt_malloc(sizeof(struct cname)); + new->next = daemon->cnames; + daemon->cnames = new; + new->alias = alias; + new->target = target; + } + } + break; + } + + case LOPT_PTR: /* --ptr-record */ + { + struct ptr_record *new; + char *dom, *target = NULL; + + comma = split(arg); + + if (!(dom = canonicalise_opt(arg)) || + (comma && !(target = canonicalise_opt(comma)))) + problem = _("bad PTR record"); + else + { + new = opt_malloc(sizeof(struct ptr_record)); + new->next = daemon->ptr; + daemon->ptr = new; + new->name = dom; + new->ptr = target; + } + break; + } + + case LOPT_NAPTR: /* --naptr-record */ + { + char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + int k = 0; + struct naptr *new; + int order, pref; + char *name, *replace = NULL; + + if ((a[0] = arg)) + for (k = 1; k < 7; k++) + if (!(a[k] = split(a[k-1]))) + break; + + + if (k < 6 || + !(name = canonicalise_opt(a[0])) || + !atoi_check16(a[1], &order) || + !atoi_check16(a[2], &pref) || + (k == 7 && !(replace = canonicalise_opt(a[6])))) + problem = _("bad NAPTR record"); + else + { + new = opt_malloc(sizeof(struct naptr)); + new->next = daemon->naptr; + daemon->naptr = new; + new->name = name; + new->flags = opt_string_alloc(a[3]); + new->services = opt_string_alloc(a[4]); + new->regexp = opt_string_alloc(a[5]); + new->replace = replace; + new->order = order; + new->pref = pref; + } + break; + } + + case 'Y': /* --txt-record */ + { + struct txt_record *new; + unsigned char *p, *cnt; + size_t len; + + comma = split(arg); + + new = opt_malloc(sizeof(struct txt_record)); + new->next = daemon->txt; + daemon->txt = new; + new->class = C_IN; + + if (!(new->name = canonicalise_opt(arg))) + { + problem = _("bad TXT record"); + break; + } + + len = comma ? strlen(comma) : 0; + len += (len/255) + 1; /* room for extra counts */ + new->txt = p = opt_malloc(len); + + cnt = p++; + *cnt = 0; + + while (comma && *comma) + { + unsigned char c = (unsigned char)*comma++; + + if (c == ',' || *cnt == 255) + { + if (c != ',') + comma--; + cnt = p++; + *cnt = 0; + } + else + { + *p++ = unhide_meta(c); + (*cnt)++; + } + } + + new->len = p - new->txt; + + break; + } + + case 'W': /* --srv-host */ + { + int port = 1, priority = 0, weight = 0; + char *name, *target = NULL; + struct mx_srv_record *new; + + comma = split(arg); + + if (!(name = canonicalise_opt(arg))) + problem = _("bad SRV record"); + + if (comma) + { + arg = comma; + comma = split(arg); + if (!(target = canonicalise_opt(arg)) +) problem = _("bad SRV target"); + + if (comma) + { + arg = comma; + comma = split(arg); + if (!atoi_check16(arg, &port)) + problem = _("invalid port number"); + + if (comma) + { + arg = comma; + comma = split(arg); + if (!atoi_check16(arg, &priority)) + problem = _("invalid priority"); + + if (comma) + { + arg = comma; + comma = split(arg); + if (!atoi_check16(arg, &weight)) + problem = _("invalid weight"); + } + } + } + } + + new = opt_malloc(sizeof(struct mx_srv_record)); + new->next = daemon->mxnames; + daemon->mxnames = new; + new->issrv = 1; + new->name = name; + new->target = target; + new->srvport = port; + new->priority = priority; + new->weight = weight; + break; + } + + default: + return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)"); + + } + + if (problem) + return problem; + + if (option == '?') + return gen_prob; + + return NULL; +} + +static void read_file(char *file, FILE *f, int hard_opt) +{ + volatile int lineno = 0; + char *buff = daemon->namebuff; + + while (fgets(buff, MAXDNAME, f)) + { + int white, i, option; ; + char *errmess, *p, *arg, *start; + size_t len; + + /* Memory allocation failure longjmps here if mem_recover == 1 */ + if (hard_opt) + { + if (setjmp(mem_jmp)) + continue; + mem_recover = 1; + } + + lineno++; + errmess = NULL; + + /* Implement quotes, inside quotes we allow \\ \" \n and \t + metacharacters get hidden also strip comments */ + for (white = 1, p = buff; *p; p++) + { + if (*p == '"') + { + memmove(p, p+1, strlen(p+1)+1); + + for(; *p && *p != '"'; p++) + { + if (*p == '\\' && strchr("\"tnebr\\", p[1])) + { + if (p[1] == 't') + p[1] = '\t'; + else if (p[1] == 'n') + p[1] = '\n'; + else if (p[1] == 'b') + p[1] = '\b'; + else if (p[1] == 'r') + p[1] = '\r'; + else if (p[1] == 'e') /* escape */ + p[1] = '\033'; + memmove(p, p+1, strlen(p+1)+1); + } + *p = hide_meta(*p); + } + + if (*p == 0) + { + errmess = _("missing \""); + goto oops; + } + + memmove(p, p+1, strlen(p+1)+1); + } + + if (isspace(*p)) + { + *p = ' '; + white = 1; + } + else + { + if (white && *p == '#') + { + *p = 0; + break; + } + white = 0; + } + } + + + /* strip leading spaces */ + for (start = buff; *start && *start == ' '; start++); + + /* strip trailing spaces */ + for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--); + + if (len == 0) + continue; + else + start[len] = 0; + + if (hard_opt != 0) + arg = start; + else if ((p=strchr(start, '='))) + { + /* allow spaces around "=" */ + for (arg = p+1; *arg == ' '; arg++); + for (; p >= start && (*p == ' ' || *p == '='); p--) + *p = 0; + } + else + arg = NULL; + + if (hard_opt != 0) + option = hard_opt; + else + { + for (option = 0, i = 0; opts[i].name; i++) + if (strcmp(opts[i].name, start) == 0) + { + option = opts[i].val; + break; + } + + if (!option) + errmess = _("bad option"); + else if (opts[i].has_arg == 0 && arg) + errmess = _("extraneous parameter"); + else if (opts[i].has_arg == 1 && !arg) + errmess = _("missing parameter"); + } + + if (!errmess) + errmess = one_opt(option, arg, _("error"), 0); + + if (errmess) + { + oops: + sprintf(buff, _("%s at line %d of %%s"), errmess, lineno); + if (hard_opt != 0) + my_syslog(LOG_ERR, buff, file); + else + die(buff, file, EC_BADCONF); + } + } + + mem_recover = 0; + fclose(f); +} + +static void one_file(char *file, int hard_opt) +{ + FILE *f; + int nofile_ok = 0; + static int read_stdin = 0; + static struct fileread { + dev_t dev; + ino_t ino; + struct fileread *next; + } *filesread = NULL; + + if (hard_opt == '7') + { + /* default conf-file reading */ + hard_opt = 0; + nofile_ok = 1; + } + + if (hard_opt == 0 && strcmp(file, "-") == 0) + { + if (read_stdin == 1) + return; + read_stdin = 1; + file = "stdin"; + f = stdin; + } + else + { + /* ignore repeated files. */ + struct stat statbuf; + + if (hard_opt == 0 && stat(file, &statbuf) == 0) + { + struct fileread *r; + + for (r = filesread; r; r = r->next) + if (r->dev == statbuf.st_dev && r->ino == statbuf.st_ino) + return; + + r = safe_malloc(sizeof(struct fileread)); + r->next = filesread; + filesread = r; + r->dev = statbuf.st_dev; + r->ino = statbuf.st_ino; + } + + if (!(f = fopen(file, "r"))) + { + if (errno == ENOENT && nofile_ok) + return; /* No conffile, all done. */ + else + { + char *str = _("cannot read %s: %s"); + if (hard_opt != 0) + { + my_syslog(LOG_ERR, str, file, strerror(errno)); + return; + } + else + die(str, file, EC_FILE); + } + } + } + + read_file(file, f, hard_opt); +} + +/* expand any name which is a directory */ +struct hostsfile *expand_filelist(struct hostsfile *list) +{ + int i; + struct hostsfile *ah; + + for (i = 0, ah = list; ah; ah = ah->next) + { + if (i <= ah->index) + i = ah->index + 1; + + if (ah->flags & AH_DIR) + ah->flags |= AH_INACTIVE; + else + ah->flags &= ~AH_INACTIVE; + } + + for (ah = list; ah; ah = ah->next) + if (!(ah->flags & AH_INACTIVE)) + { + struct stat buf; + if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode)) + { + DIR *dir_stream; + struct dirent *ent; + + /* don't read this as a file */ + ah->flags |= AH_INACTIVE; + + if (!(dir_stream = opendir(ah->fname))) + my_syslog(LOG_ERR, _("cannot access directory %s: %s"), + ah->fname, strerror(errno)); + else + { + while ((ent = readdir(dir_stream))) + { + size_t lendir = strlen(ah->fname); + size_t lenfile = strlen(ent->d_name); + struct hostsfile *ah1; + char *path; + + /* ignore emacs backups and dotfiles */ + if (lenfile == 0 || + ent->d_name[lenfile - 1] == '~' || + (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') || + ent->d_name[0] == '.') + continue; + + /* see if we have an existing record. + dir is ah->fname + file is ent->d_name + path to match is ah1->fname */ + + for (ah1 = list; ah1; ah1 = ah1->next) + { + if (lendir < strlen(ah1->fname) && + strstr(ah1->fname, ah->fname) == ah1->fname && + ah1->fname[lendir] == '/' && + strcmp(ah1->fname + lendir + 1, ent->d_name) == 0) + { + ah1->flags &= ~AH_INACTIVE; + break; + } + } + + /* make new record */ + if (!ah1) + { + if (!(ah1 = whine_malloc(sizeof(struct hostsfile)))) + continue; + + if (!(path = whine_malloc(lendir + lenfile + 2))) + { + free(ah1); + continue; + } + + strcpy(path, ah->fname); + strcat(path, "/"); + strcat(path, ent->d_name); + ah1->fname = path; + ah1->index = i++; + ah1->flags = AH_DIR; + ah1->next = list; + list = ah1; + } + + /* inactivate record if not regular file */ + if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode)) + ah1->flags |= AH_INACTIVE; + + } + closedir(dir_stream); + } + } + } + + return list; +} + + +#ifdef HAVE_DHCP +void reread_dhcp(void) +{ + struct hostsfile *hf; + + if (daemon->dhcp_hosts_file) + { + struct dhcp_config *configs, *cp, **up; + + /* remove existing... */ + for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp) + { + cp = configs->next; + + if (configs->flags & CONFIG_BANK) + { + struct hwaddr_config *mac, *tmp; + struct dhcp_netid_list *list, *tmplist; + + for (mac = configs->hwaddr; mac; mac = tmp) + { + tmp = mac->next; + free(mac); + } + + if (configs->flags & CONFIG_CLID) + free(configs->clid); + + for (list = configs->netid; list; list = tmplist) + { + free(list->list); + tmplist = list->next; + free(list); + } + + if (configs->flags & CONFIG_NAME) + free(configs->hostname); + + *up = configs->next; + free(configs); + } + else + up = &configs->next; + } + + daemon->dhcp_hosts_file = expand_filelist(daemon->dhcp_hosts_file); + for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next) + if (!(hf->flags & AH_INACTIVE)) + { + one_file(hf->fname, LOPT_BANK); + my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname); + } + } + + if (daemon->dhcp_opts_file) + { + struct dhcp_opt *opts, *cp, **up; + struct dhcp_netid *id, *next; + + for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp) + { + cp = opts->next; + + if (opts->flags & DHOPT_BANK) + { + if ((opts->flags & DHOPT_VENDOR)) + free(opts->u.vendor_class); + free(opts->val); + for (id = opts->netid; id; id = next) + { + next = id->next; + free(id->net); + free(id); + } + *up = opts->next; + free(opts); + } + else + up = &opts->next; + } + + daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file); + for (hf = daemon->dhcp_opts_file; hf; hf = hf->next) + if (!(hf->flags & AH_INACTIVE)) + { + one_file(hf->fname, LOPT_OPTS); + my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname); + } + } +} +#endif + +void read_opts(int argc, char **argv, char *compile_opts) +{ + char *buff = opt_malloc(MAXDNAME); + int option, conffile_opt = '7', testmode = 0; + char *errmess, *arg, *conffile = CONFFILE; + + opterr = 0; + + daemon = opt_malloc(sizeof(struct daemon)); + memset(daemon, 0, sizeof(struct daemon)); + daemon->namebuff = buff; + + /* Set defaults - everything else is zero or NULL */ + daemon->cachesize = CACHESIZ; + daemon->ftabsize = FTABSIZ; + daemon->port = NAMESERVER_PORT; + daemon->dhcp_client_port = DHCP_CLIENT_PORT; + daemon->dhcp_server_port = DHCP_SERVER_PORT; + daemon->default_resolv.is_default = 1; + daemon->default_resolv.name = RESOLVFILE; + daemon->resolv_files = &daemon->default_resolv; + daemon->username = CHUSER; + daemon->runfile = RUNFILE; + daemon->dhcp_max = MAXLEASES; + daemon->tftp_max = TFTP_MAX_CONNECTIONS; + daemon->edns_pktsz = EDNS_PKTSZ; + daemon->log_fac = -1; + add_txt("version.bind", "dnsmasq-" VERSION ); + add_txt("authors.bind", "Simon Kelley"); + add_txt("copyright.bind", COPYRIGHT); + + while (1) + { +#ifdef HAVE_GETOPT_LONG + option = getopt_long(argc, argv, OPTSTRING, opts, NULL); +#else + option = getopt(argc, argv, OPTSTRING); +#endif + + if (option == -1) + { + for (; optind < argc; optind++) + { + unsigned char *c = (unsigned char *)argv[optind]; + for (; *c != 0; c++) + if (!isspace(*c)) + die(_("junk found in command line"), NULL, EC_BADCONF); + } + break; + } + + /* Copy optarg so that argv doesn't get changed */ + if (optarg) + { + strncpy(buff, optarg, MAXDNAME); + buff[MAXDNAME-1] = 0; + arg = buff; + } + else + arg = NULL; + + /* command-line only stuff */ + if (option == LOPT_TEST) + testmode = 1; + else if (option == 'w') + { + if (argc != 3 || strcmp(argv[2], "dhcp") != 0) + do_usage(); +#ifdef HAVE_DHCP + else + display_opts(); +#endif + exit(0); + } + else if (option == 'v') + { + printf(_("Dnsmasq version %s %s\n"), VERSION, COPYRIGHT); + printf(_("Compile time options %s\n\n"), compile_opts); + printf(_("This software comes with ABSOLUTELY NO WARRANTY.\n")); + printf(_("Dnsmasq is free software, and you are welcome to redistribute it\n")); + printf(_("under the terms of the GNU General Public License, version 2 or 3.\n")); + exit(0); + } + else if (option == 'C') + { + conffile_opt = 0; /* file must exist */ + conffile = opt_string_alloc(arg); + } + else + { +#ifdef HAVE_GETOPT_LONG + errmess = one_opt(option, arg, _("try --help"), 1); +#else + errmess = one_opt(option, arg, _("try -w"), 1); +#endif + if (errmess) + die(_("bad command line options: %s"), errmess, EC_BADCONF); + } + } + + if (conffile) + one_file(conffile, conffile_opt); + + /* port might not be known when the address is parsed - fill in here */ + if (daemon->servers) + { + struct server *tmp; + for (tmp = daemon->servers; tmp; tmp = tmp->next) + if (!(tmp->flags & SERV_HAS_SOURCE)) + { + if (tmp->source_addr.sa.sa_family == AF_INET) + tmp->source_addr.in.sin_port = htons(daemon->query_port); +#ifdef HAVE_IPV6 + else if (tmp->source_addr.sa.sa_family == AF_INET6) + tmp->source_addr.in6.sin6_port = htons(daemon->query_port); +#endif + } + } + + if (daemon->if_addrs) + { + struct iname *tmp; + for(tmp = daemon->if_addrs; tmp; tmp = tmp->next) + if (tmp->addr.sa.sa_family == AF_INET) + tmp->addr.in.sin_port = htons(daemon->port); +#ifdef HAVE_IPV6 + else if (tmp->addr.sa.sa_family == AF_INET6) + tmp->addr.in6.sin6_port = htons(daemon->port); +#endif /* IPv6 */ + } + + /* only one of these need be specified: the other defaults to the host-name */ + if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget) + { + struct mx_srv_record *mx; + + if (gethostname(buff, MAXDNAME) == -1) + die(_("cannot get host-name: %s"), NULL, EC_MISC); + + for (mx = daemon->mxnames; mx; mx = mx->next) + if (!mx->issrv && hostname_isequal(mx->name, buff)) + break; + + if ((daemon->mxtarget || option_bool(OPT_LOCALMX)) && !mx) + { + mx = opt_malloc(sizeof(struct mx_srv_record)); + mx->next = daemon->mxnames; + mx->issrv = 0; + mx->target = NULL; + mx->name = opt_string_alloc(buff); + daemon->mxnames = mx; + } + + if (!daemon->mxtarget) + daemon->mxtarget = opt_string_alloc(buff); + + for (mx = daemon->mxnames; mx; mx = mx->next) + if (!mx->issrv && !mx->target) + mx->target = daemon->mxtarget; + } + + if (!option_bool(OPT_NO_RESOLV) && + daemon->resolv_files && + daemon->resolv_files->next && + option_bool(OPT_NO_POLL)) + die(_("only one resolv.conf file allowed in no-poll mode."), NULL, EC_BADCONF); + + if (option_bool(OPT_RESOLV_DOMAIN)) + { + char *line; + FILE *f; + + if (option_bool(OPT_NO_RESOLV) || + !daemon->resolv_files || + (daemon->resolv_files)->next) + die(_("must have exactly one resolv.conf to read domain from."), NULL, EC_BADCONF); + + if (!(f = fopen((daemon->resolv_files)->name, "r"))) + die(_("failed to read %s: %s"), (daemon->resolv_files)->name, EC_FILE); + + while ((line = fgets(buff, MAXDNAME, f))) + { + char *token = strtok(line, " \t\n\r"); + + if (!token || strcmp(token, "search") != 0) + continue; + + if ((token = strtok(NULL, " \t\n\r")) && + (daemon->domain_suffix = canonicalise_opt(token))) + break; + } + + fclose(f); + + if (!daemon->domain_suffix) + die(_("no search directive found in %s"), (daemon->resolv_files)->name, EC_MISC); + } + + if (daemon->domain_suffix) + { + /* add domain for any srv record without one. */ + struct mx_srv_record *srv; + + for (srv = daemon->mxnames; srv; srv = srv->next) + if (srv->issrv && + strchr(srv->name, '.') && + strchr(srv->name, '.') == strrchr(srv->name, '.')) + { + strcpy(buff, srv->name); + strcat(buff, "."); + strcat(buff, daemon->domain_suffix); + free(srv->name); + srv->name = opt_string_alloc(buff); + } + } + else if (option_bool(OPT_DHCP_FQDN)) + die(_("there must be a default domain when --dhcp-fqdn is set"), NULL, EC_BADCONF); + + if (testmode) + { + fprintf(stderr, "dnsmasq: %s.\n", _("syntax check OK")); + exit(0); + } +} diff --git a/src/rfc1035.c b/src/rfc1035.c new file mode 100644 index 0000000..889c1f0 --- /dev/null +++ b/src/rfc1035.c @@ -0,0 +1,1815 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +static int add_resource_record(struct dns_header *header, char *limit, int *truncp, + unsigned int nameoffset, unsigned char **pp, + unsigned long ttl, unsigned int *offset, unsigned short type, + unsigned short class, char *format, ...); + +#define CHECK_LEN(header, pp, plen, len) \ + ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen)) + +#define ADD_RDLEN(header, pp, plen, len) \ + (!CHECK_LEN(header, pp, plen, len) ? 0 : (long)((pp) += (len)), 1) + +static int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, + char *name, int isExtract, int extrabytes) +{ + unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL; + unsigned int j, l, hops = 0; + int retvalue = 1; + + if (isExtract) + *cp = 0; + + while (1) + { + unsigned int label_type; + + if (!CHECK_LEN(header, p, plen, 1)) + return 0; + + if ((l = *p++) == 0) + /* end marker */ + { + /* check that there are the correct no of bytes after the name */ + if (!CHECK_LEN(header, p, plen, extrabytes)) + return 0; + + if (isExtract) + { + if (cp != (unsigned char *)name) + cp--; + *cp = 0; /* terminate: lose final period */ + } + else if (*cp != 0) + retvalue = 2; + + if (p1) /* we jumped via compression */ + *pp = p1; + else + *pp = p; + + return retvalue; + } + + label_type = l & 0xc0; + + if (label_type == 0xc0) /* pointer */ + { + if (!CHECK_LEN(header, p, plen, 1)) + return 0; + + /* get offset */ + l = (l&0x3f) << 8; + l |= *p++; + + if (!p1) /* first jump, save location to go back to */ + p1 = p; + + hops++; /* break malicious infinite loops */ + if (hops > 255) + return 0; + + p = l + (unsigned char *)header; + } + else if (label_type == 0x80) + return 0; /* reserved */ + else if (label_type == 0x40) + { /* ELT */ + unsigned int count, digs; + + if ((l & 0x3f) != 1) + return 0; /* we only understand bitstrings */ + + if (!isExtract) + return 0; /* Cannot compare bitsrings */ + + count = *p++; + if (count == 0) + count = 256; + digs = ((count-1)>>2)+1; + + /* output is \[x<hex>/siz]. which is digs+9 chars */ + if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME) + return 0; + if (!CHECK_LEN(header, p, plen, (count-1)>>3)) + return 0; + + *cp++ = '\\'; + *cp++ = '['; + *cp++ = 'x'; + for (j=0; j<digs; j++) + { + unsigned int dig; + if (j%2 == 0) + dig = *p >> 4; + else + dig = *p++ & 0x0f; + + *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10; + } + cp += sprintf((char *)cp, "/%d]", count); + /* do this here to overwrite the zero char from sprintf */ + *cp++ = '.'; + } + else + { /* label_type = 0 -> label. */ + if (cp - (unsigned char *)name + l + 1 >= MAXDNAME) + return 0; + if (!CHECK_LEN(header, p, plen, l)) + return 0; + + for(j=0; j<l; j++, p++) + if (isExtract) + { + unsigned char c = *p; + if (isascii(c) && !iscntrl(c) && c != '.') + *cp++ = *p; + else + return 0; + } + else + { + unsigned char c1 = *cp, c2 = *p; + + if (c1 == 0) + retvalue = 2; + else + { + cp++; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + + if (c1 != c2) + retvalue = 2; + } + } + + if (isExtract) + *cp++ = '.'; + else if (*cp != 0 && *cp++ != '.') + retvalue = 2; + } + } +} + +/* Max size of input string (for IPv6) is 75 chars.) */ +#define MAXARPANAME 75 +static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp) +{ + int j; + char name[MAXARPANAME+1], *cp1; + unsigned char *addr = (unsigned char *)addrp; + char *lastchunk = NULL, *penchunk = NULL; + + if (strlen(namein) > MAXARPANAME) + return 0; + + memset(addrp, 0, sizeof(struct all_addr)); + + /* turn name into a series of asciiz strings */ + /* j counts no of labels */ + for(j = 1,cp1 = name; *namein; cp1++, namein++) + if (*namein == '.') + { + penchunk = lastchunk; + lastchunk = cp1 + 1; + *cp1 = 0; + j++; + } + else + *cp1 = *namein; + + *cp1 = 0; + + if (j<3) + return 0; + + if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr")) + { + /* IP v4 */ + /* address arives as a name of the form + www.xxx.yyy.zzz.in-addr.arpa + some of the low order address octets might be missing + and should be set to zero. */ + for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1) + { + /* check for digits only (weeds out things like + 50.0/24.67.28.64.in-addr.arpa which are used + as CNAME targets according to RFC 2317 */ + char *cp; + for (cp = cp1; *cp; cp++) + if (!isdigit((unsigned char)*cp)) + return 0; + + addr[3] = addr[2]; + addr[2] = addr[1]; + addr[1] = addr[0]; + addr[0] = atoi(cp1); + } + + return F_IPV4; + } +#ifdef HAVE_IPV6 + else if (hostname_isequal(penchunk, "ip6") && + (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa"))) + { + /* IP v6: + Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa] + or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa] + + Note that most of these the various reprentations are obsolete and + left-over from the many DNS-for-IPv6 wars. We support all the formats + that we can since there is no reason not to. + */ + + if (*name == '\\' && *(name+1) == '[' && + (*(name+2) == 'x' || *(name+2) == 'X')) + { + for (j = 0, cp1 = name+3; *cp1 && isxdigit((unsigned char) *cp1) && j < 32; cp1++, j++) + { + char xdig[2]; + xdig[0] = *cp1; + xdig[1] = 0; + if (j%2) + addr[j/2] |= strtol(xdig, NULL, 16); + else + addr[j/2] = strtol(xdig, NULL, 16) << 4; + } + + if (*cp1 == '/' && j == 32) + return F_IPV6; + } + else + { + for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1) + { + if (*(cp1+1) || !isxdigit((unsigned char)*cp1)) + return 0; + + for (j = sizeof(struct all_addr)-1; j>0; j--) + addr[j] = (addr[j] >> 4) | (addr[j-1] << 4); + addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4); + } + + return F_IPV6; + } + } +#endif + + return 0; +} + +static unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes) +{ + while(1) + { + unsigned int label_type; + + if (!CHECK_LEN(header, ansp, plen, 1)) + return NULL; + + label_type = (*ansp) & 0xc0; + + if (label_type == 0xc0) + { + /* pointer for compression. */ + ansp += 2; + break; + } + else if (label_type == 0x80) + return NULL; /* reserved */ + else if (label_type == 0x40) + { + /* Extended label type */ + unsigned int count; + + if (!CHECK_LEN(header, ansp, plen, 2)) + return NULL; + + if (((*ansp++) & 0x3f) != 1) + return NULL; /* we only understand bitstrings */ + + count = *(ansp++); /* Bits in bitstring */ + + if (count == 0) /* count == 0 means 256 bits */ + ansp += 32; + else + ansp += ((count-1)>>3)+1; + } + else + { /* label type == 0 Bottom six bits is length */ + unsigned int len = (*ansp++) & 0x3f; + + if (!ADD_RDLEN(header, ansp, plen, len)) + return NULL; + + if (len == 0) + break; /* zero length label marks the end. */ + } + } + + if (!CHECK_LEN(header, ansp, plen, extrabytes)) + return NULL; + + return ansp; +} + +static unsigned char *skip_questions(struct dns_header *header, size_t plen) +{ + int q; + unsigned char *ansp = (unsigned char *)(header+1); + + for (q = ntohs(header->qdcount); q != 0; q--) + { + if (!(ansp = skip_name(ansp, header, plen, 4))) + return NULL; + ansp += 4; /* class and type */ + } + + return ansp; +} + +static unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen) +{ + int i, rdlen; + + for (i = 0; i < count; i++) + { + if (!(ansp = skip_name(ansp, header, plen, 10))) + return NULL; + ansp += 8; /* type, class, TTL */ + GETSHORT(rdlen, ansp); + if (!ADD_RDLEN(header, ansp, plen, rdlen)) + return NULL; + } + + return ansp; +} + +/* CRC the question section. This is used to safely detect query + retransmision and to detect answers to questions we didn't ask, which + might be poisoning attacks. Note that we decode the name rather + than CRC the raw bytes, since replies might be compressed differently. + We ignore case in the names for the same reason. Return all-ones + if there is not question section. */ +unsigned int questions_crc(struct dns_header *header, size_t plen, char *name) +{ + int q; + unsigned int crc = 0xffffffff; + unsigned char *p1, *p = (unsigned char *)(header+1); + + for (q = ntohs(header->qdcount); q != 0; q--) + { + if (!extract_name(header, plen, &p, name, 1, 4)) + return crc; /* bad packet */ + + for (p1 = (unsigned char *)name; *p1; p1++) + { + int i = 8; + char c = *p1; + + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + + crc ^= c << 24; + while (i--) + crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1; + } + + /* CRC the class and type as well */ + for (p1 = p; p1 < p+4; p1++) + { + int i = 8; + crc ^= *p1 << 24; + while (i--) + crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1; + } + + p += 4; + if (!CHECK_LEN(header, p, plen, 0)) + return crc; /* bad packet */ + } + + return crc; +} + + +size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *pheader, size_t hlen) +{ + unsigned char *ansp = skip_questions(header, plen); + + /* if packet is malformed, just return as-is. */ + if (!ansp) + return plen; + + if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), + header, plen))) + return plen; + + /* restore pseudoheader */ + if (pheader && ntohs(header->arcount) == 0) + { + /* must use memmove, may overlap */ + memmove(ansp, pheader, hlen); + header->arcount = htons(1); + ansp += hlen; + } + + return ansp - (unsigned char *)header; +} + +unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t *len, unsigned char **p, int *is_sign) +{ + /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. + also return length of pseudoheader in *len and pointer to the UDP size in *p + Finally, check to see if a packet is signed. If it is we cannot change a single bit before + forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */ + + int i, arcount = ntohs(header->arcount); + unsigned char *ansp = (unsigned char *)(header+1); + unsigned short rdlen, type, class; + unsigned char *ret = NULL; + + if (is_sign) + { + *is_sign = 0; + + if (OPCODE(header) == QUERY) + { + for (i = ntohs(header->qdcount); i != 0; i--) + { + if (!(ansp = skip_name(ansp, header, plen, 4))) + return NULL; + + GETSHORT(type, ansp); + GETSHORT(class, ansp); + + if (class == C_IN && type == T_TKEY) + *is_sign = 1; + } + } + } + else + { + if (!(ansp = skip_questions(header, plen))) + return NULL; + } + + if (arcount == 0) + return NULL; + + if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen))) + return NULL; + + for (i = 0; i < arcount; i++) + { + unsigned char *save, *start = ansp; + if (!(ansp = skip_name(ansp, header, plen, 10))) + return NULL; + + GETSHORT(type, ansp); + save = ansp; + GETSHORT(class, ansp); + ansp += 4; /* TTL */ + GETSHORT(rdlen, ansp); + if (!ADD_RDLEN(header, ansp, plen, rdlen)) + return NULL; + if (type == T_OPT) + { + if (len) + *len = ansp - start; + if (p) + *p = save; + ret = start; + } + else if (is_sign && + i == arcount - 1 && + class == C_ANY && + (type == T_SIG || type == T_TSIG)) + *is_sign = 1; + } + + return ret; +} + +struct macparm { + unsigned char *limit; + struct dns_header *header; + size_t plen; + union mysockaddr *l3; +}; + +static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv) +{ + struct macparm *parm = parmv; + int match = 0; + unsigned short rdlen; + struct dns_header *header = parm->header; + unsigned char *lenp, *datap, *p; + + if (family == parm->l3->sa.sa_family) + { + if (family == AF_INET && memcmp (&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0) + match = 1; +#ifdef HAVE_IPV6 + else + if (family == AF_INET6 && memcmp (&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0) + match = 1; +#endif + } + + if (!match) + return 1; /* continue */ + + if (ntohs(header->arcount) == 0) + { + /* We are adding the pseudoheader */ + if (!(p = skip_questions(header, parm->plen)) || + !(p = skip_section(p, + ntohs(header->ancount) + ntohs(header->nscount), + header, parm->plen))) + return 0; + *p++ = 0; /* empty name */ + PUTSHORT(T_OPT, p); + PUTSHORT(PACKETSZ, p); /* max packet length - is 512 suitable default for non-EDNS0 resolvers? */ + PUTLONG(0, p); /* extended RCODE */ + lenp = p; + PUTSHORT(0, p); /* RDLEN */ + rdlen = 0; + if (((ssize_t)maclen) > (parm->limit - (p + 4))) + return 0; /* Too big */ + header->arcount = htons(1); + datap = p; + } + else + { + int i, is_sign; + unsigned short code, len; + + if (ntohs(header->arcount) != 1 || + !(p = find_pseudoheader(header, parm->plen, NULL, NULL, &is_sign)) || + is_sign || + (!(p = skip_name(p, header, parm->plen, 10)))) + return 0; + + p += 8; /* skip UDP length and RCODE */ + + lenp = p; + GETSHORT(rdlen, p); + if (!CHECK_LEN(header, p, parm->plen, rdlen)) + return 0; /* bad packet */ + datap = p; + + /* check if option already there */ + for (i = 0; i + 4 < rdlen; i += len + 4) + { + GETSHORT(code, p); + GETSHORT(len, p); + if (code == EDNS0_OPTION_MAC) + return 0; + p += len; + } + + if (((ssize_t)maclen) > (parm->limit - (p + 4))) + return 0; /* Too big */ + } + + PUTSHORT(EDNS0_OPTION_MAC, p); + PUTSHORT(maclen, p); + memcpy(p, mac, maclen); + p += maclen; + + PUTSHORT(p - datap, lenp); + parm->plen = p - (unsigned char *)header; + + return 0; /* done */ +} + + +size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3) +{ + struct macparm parm; + +/* Must have an existing pseudoheader as the only ar-record, + or have no ar-records. Must also not be signed */ + + if (ntohs(header->arcount) > 1) + return plen; + + parm.header = header; + parm.limit = (unsigned char *)limit; + parm.plen = plen; + parm.l3 = l3; + + iface_enumerate(AF_UNSPEC, &parm, filter_mac); + + return parm.plen; +} + + +/* is addr in the non-globally-routed IP space? */ +static int private_net(struct in_addr addr, int ban_localhost) +{ + in_addr_t ip_addr = ntohl(addr.s_addr); + + return + (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ || + ((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ || + ((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ || + ((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ || + ((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ; +} + +static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name) +{ + int i, qtype, qclass, rdlen; + unsigned long ttl; + + for (i = count; i != 0; i--) + { + if (name && option_bool(OPT_LOG)) + { + if (!extract_name(header, qlen, &p, name, 1, 10)) + return 0; + } + else if (!(p = skip_name(p, header, qlen, 10))) + return 0; /* bad packet */ + + GETSHORT(qtype, p); + GETSHORT(qclass, p); + GETLONG(ttl, p); + GETSHORT(rdlen, p); + + if (qclass == C_IN && qtype == T_A) + { + struct doctor *doctor; + struct in_addr addr; + + if (!CHECK_LEN(header, p, qlen, INADDRSZ)) + return 0; + + /* alignment */ + memcpy(&addr, p, INADDRSZ); + + for (doctor = daemon->doctors; doctor; doctor = doctor->next) + { + if (doctor->end.s_addr == 0) + { + if (!is_same_net(doctor->in, addr, doctor->mask)) + continue; + } + else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) || + ntohl(doctor->end.s_addr) < ntohl(addr.s_addr)) + continue; + + addr.s_addr &= ~doctor->mask.s_addr; + addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr); + /* Since we munged the data, the server it came from is no longer authoritative */ + header->hb3 &= ~HB3_AA; + memcpy(p, &addr, INADDRSZ); + break; + } + } + else if (qtype == T_TXT && name && option_bool(OPT_LOG)) + { + unsigned char *p1 = p; + if (!CHECK_LEN(header, p1, qlen, rdlen)) + return 0; + while ((p1 - p) < rdlen) + { + unsigned int i, len = *p1; + unsigned char *p2 = p1; + /* make counted string zero-term and sanitise */ + for (i = 0; i < len; i++) + if (isprint(*(p2+1))) + { + *p2 = *(p2+1); + p2++; + } + *p2 = 0; + my_syslog(LOG_INFO, "reply %s is %s", name, p1); + /* restore */ + memmove(p1 + 1, p1, len); + *p1 = len; + p1 += len+1; + } + } + + if (!ADD_RDLEN(header, p, qlen, rdlen)) + return 0; /* bad packet */ + } + + return p; +} + +static int find_soa(struct dns_header *header, size_t qlen, char *name) +{ + unsigned char *p; + int qtype, qclass, rdlen; + unsigned long ttl, minttl = ULONG_MAX; + int i, found_soa = 0; + + /* first move to NS section and find TTL from any SOA section */ + if (!(p = skip_questions(header, qlen)) || + !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name))) + return 0; /* bad packet */ + + for (i = ntohs(header->nscount); i != 0; i--) + { + if (!(p = skip_name(p, header, qlen, 10))) + return 0; /* bad packet */ + + GETSHORT(qtype, p); + GETSHORT(qclass, p); + GETLONG(ttl, p); + GETSHORT(rdlen, p); + + if ((qclass == C_IN) && (qtype == T_SOA)) + { + found_soa = 1; + if (ttl < minttl) + minttl = ttl; + + /* MNAME */ + if (!(p = skip_name(p, header, qlen, 0))) + return 0; + /* RNAME */ + if (!(p = skip_name(p, header, qlen, 20))) + return 0; + p += 16; /* SERIAL REFRESH RETRY EXPIRE */ + + GETLONG(ttl, p); /* minTTL */ + if (ttl < minttl) + minttl = ttl; + } + else if (!ADD_RDLEN(header, p, qlen, rdlen)) + return 0; /* bad packet */ + } + + /* rewrite addresses in additioal section too */ + if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL)) + return 0; + + if (!found_soa) + minttl = daemon->neg_ttl; + + return minttl; +} + +/* Note that the following code can create CNAME chains that don't point to a real record, + either because of lack of memory, or lack of SOA records. These are treated by the cache code as + expired and cleaned out that way. + Return 1 if we reject an address because it look like part of dns-rebinding attack. */ +int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now, + int is_sign, int check_rebind, int checking_disabled) +{ + unsigned char *p, *p1, *endrr, *namep; + int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0; + unsigned long ttl = 0; + struct all_addr addr; + + cache_start_insert(); + + /* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */ + if (daemon->doctors || option_bool(OPT_LOG)) + { + searched_soa = 1; + ttl = find_soa(header, qlen, name); + } + + /* go through the questions. */ + p = (unsigned char *)(header+1); + + for (i = ntohs(header->qdcount); i != 0; i--) + { + int found = 0, cname_count = 5; + struct crec *cpp = NULL; + int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0; + unsigned long cttl = ULONG_MAX, attl; + + namep = p; + if (!extract_name(header, qlen, &p, name, 1, 4)) + return 0; /* bad packet */ + + GETSHORT(qtype, p); + GETSHORT(qclass, p); + + if (qclass != C_IN) + continue; + + /* PTRs: we chase CNAMEs here, since we have no way to + represent them in the cache. */ + if (qtype == T_PTR) + { + int name_encoding = in_arpa_name_2_addr(name, &addr); + + if (!name_encoding) + continue; + + if (!(flags & F_NXDOMAIN)) + { + cname_loop: + if (!(p1 = skip_questions(header, qlen))) + return 0; + + for (j = ntohs(header->ancount); j != 0; j--) + { + unsigned char *tmp = namep; + /* the loop body overwrites the original name, so get it back here. */ + if (!extract_name(header, qlen, &tmp, name, 1, 0) || + !(res = extract_name(header, qlen, &p1, name, 0, 10))) + return 0; /* bad packet */ + + GETSHORT(aqtype, p1); + GETSHORT(aqclass, p1); + GETLONG(attl, p1); + if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign) + { + (p1) -= 4; + PUTLONG(daemon->max_ttl, p1); + } + GETSHORT(ardlen, p1); + endrr = p1+ardlen; + + /* TTL of record is minimum of CNAMES and PTR */ + if (attl < cttl) + cttl = attl; + + if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR)) + { + if (!extract_name(header, qlen, &p1, name, 1, 0)) + return 0; + + if (aqtype == T_CNAME) + { + if (!cname_count--) + return 0; /* looped CNAMES */ + goto cname_loop; + } + + cache_insert(name, &addr, now, cttl, name_encoding | F_REVERSE); + found = 1; + } + + p1 = endrr; + if (!CHECK_LEN(header, p1, qlen, 0)) + return 0; /* bad packet */ + } + } + + if (!found && !option_bool(OPT_NO_NEG)) + { + if (!searched_soa) + { + searched_soa = 1; + ttl = find_soa(header, qlen, NULL); + } + if (ttl) + cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags); + } + } + else + { + /* everything other than PTR */ + struct crec *newc; + int addrlen; + + if (qtype == T_A) + { + addrlen = INADDRSZ; + flags |= F_IPV4; + } +#ifdef HAVE_IPV6 + else if (qtype == T_AAAA) + { + addrlen = IN6ADDRSZ; + flags |= F_IPV6; + } +#endif + else + continue; + + if (!(flags & F_NXDOMAIN)) + { + cname_loop1: + if (!(p1 = skip_questions(header, qlen))) + return 0; + + for (j = ntohs(header->ancount); j != 0; j--) + { + if (!(res = extract_name(header, qlen, &p1, name, 0, 10))) + return 0; /* bad packet */ + + GETSHORT(aqtype, p1); + GETSHORT(aqclass, p1); + GETLONG(attl, p1); + if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign) + { + (p1) -= 4; + PUTLONG(daemon->max_ttl, p1); + } + GETSHORT(ardlen, p1); + endrr = p1+ardlen; + + if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype)) + { + if (aqtype == T_CNAME) + { + if (!cname_count--) + return 0; /* looped CNAMES */ + newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD); + if (newc && cpp) + { + cpp->addr.cname.cache = newc; + cpp->addr.cname.uid = newc->uid; + } + + cpp = newc; + if (attl < cttl) + cttl = attl; + + if (!extract_name(header, qlen, &p1, name, 1, 0)) + return 0; + goto cname_loop1; + } + else + { + found = 1; + + /* copy address into aligned storage */ + if (!CHECK_LEN(header, p1, qlen, addrlen)) + return 0; /* bad packet */ + memcpy(&addr, p1, addrlen); + + /* check for returned address in private space */ + if (check_rebind && + (flags & F_IPV4) && + private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND))) + return 1; + + newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD); + if (newc && cpp) + { + cpp->addr.cname.cache = newc; + cpp->addr.cname.uid = newc->uid; + } + cpp = NULL; + } + } + + p1 = endrr; + if (!CHECK_LEN(header, p1, qlen, 0)) + return 0; /* bad packet */ + } + } + + if (!found && !option_bool(OPT_NO_NEG)) + { + if (!searched_soa) + { + searched_soa = 1; + ttl = find_soa(header, qlen, NULL); + } + /* If there's no SOA to get the TTL from, but there is a CNAME + pointing at this, inherit its TTL */ + if (ttl || cpp) + { + newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags); + if (newc && cpp) + { + cpp->addr.cname.cache = newc; + cpp->addr.cname.uid = newc->uid; + } + } + } + } + } + + /* Don't put stuff from a truncated packet into the cache, + also don't cache replies where DNSSEC validation was turned off, either + the upstream server told us so, or the original query specified it. */ + if (!(header->hb3 & HB3_TC) && !(header->hb4 & HB4_CD) && !checking_disabled) + cache_end_insert(); + + return 0; +} + +/* If the packet holds exactly one query + return F_IPV4 or F_IPV6 and leave the name from the query in name */ + +unsigned int extract_request(struct dns_header *header, size_t qlen, char *name, unsigned short *typep) +{ + unsigned char *p = (unsigned char *)(header+1); + int qtype, qclass; + + if (typep) + *typep = 0; + + if (ntohs(header->qdcount) != 1 || OPCODE(header) != QUERY) + return 0; /* must be exactly one query. */ + + if (!extract_name(header, qlen, &p, name, 1, 4)) + return 0; /* bad packet */ + + GETSHORT(qtype, p); + GETSHORT(qclass, p); + + if (typep) + *typep = qtype; + + if (qclass == C_IN) + { + if (qtype == T_A) + return F_IPV4; + if (qtype == T_AAAA) + return F_IPV6; + if (qtype == T_ANY) + return F_IPV4 | F_IPV6; + if (qtype == T_NS || qtype == T_SOA) + return F_QUERY | F_NSRR; + } + + return F_QUERY; +} + + +size_t setup_reply(struct dns_header *header, size_t qlen, + struct all_addr *addrp, unsigned int flags, unsigned long ttl) +{ + unsigned char *p = skip_questions(header, qlen); + + /* clear authoritative and truncated flags, set QR flag */ + header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR; + /* set RA flag */ + header->hb4 |= HB4_RA; + + header->nscount = htons(0); + header->arcount = htons(0); + header->ancount = htons(0); /* no answers unless changed below */ + if (flags == F_NEG) + SET_RCODE(header, SERVFAIL); /* couldn't get memory */ + else if (flags == F_NOERR) + SET_RCODE(header, NOERROR); /* empty domain */ + else if (flags == F_NXDOMAIN) + SET_RCODE(header, NXDOMAIN); + else if (p && flags == F_IPV4) + { /* we know the address */ + SET_RCODE(header, NOERROR); + header->ancount = htons(1); + header->hb3 |= HB3_AA; + add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp); + } +#ifdef HAVE_IPV6 + else if (p && flags == F_IPV6) + { + SET_RCODE(header, NOERROR); + header->ancount = htons(1); + header->hb3 |= HB3_AA; + add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp); + } +#endif + else /* nowhere to forward to */ + SET_RCODE(header, REFUSED); + + return p - (unsigned char *)header; +} + +/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */ +int check_for_local_domain(char *name, time_t now) +{ + struct crec *crecp; + struct mx_srv_record *mx; + struct txt_record *txt; + struct interface_name *intr; + struct ptr_record *ptr; + + if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)) && + (crecp->flags & (F_HOSTS | F_DHCP))) + return 1; + + for (mx = daemon->mxnames; mx; mx = mx->next) + if (hostname_isequal(name, mx->name)) + return 1; + + for (txt = daemon->txt; txt; txt = txt->next) + if (hostname_isequal(name, txt->name)) + return 1; + + for (intr = daemon->int_names; intr; intr = intr->next) + if (hostname_isequal(name, intr->name)) + return 1; + + for (ptr = daemon->ptr; ptr; ptr = ptr->next) + if (hostname_isequal(name, ptr->name)) + return 1; + + return 0; +} + +/* Is the packet a reply with the answer address equal to addr? + If so mung is into an NXDOMAIN reply and also put that information + in the cache. */ +int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, + struct bogus_addr *baddr, time_t now) +{ + unsigned char *p; + int i, qtype, qclass, rdlen; + unsigned long ttl; + struct bogus_addr *baddrp; + + /* skip over questions */ + if (!(p = skip_questions(header, qlen))) + return 0; /* bad packet */ + + for (i = ntohs(header->ancount); i != 0; i--) + { + if (!extract_name(header, qlen, &p, name, 1, 10)) + return 0; /* bad packet */ + + GETSHORT(qtype, p); + GETSHORT(qclass, p); + GETLONG(ttl, p); + GETSHORT(rdlen, p); + + if (qclass == C_IN && qtype == T_A) + { + if (!CHECK_LEN(header, p, qlen, INADDRSZ)) + return 0; + + for (baddrp = baddr; baddrp; baddrp = baddrp->next) + if (memcmp(&baddrp->addr, p, INADDRSZ) == 0) + { + /* Found a bogus address. Insert that info here, since there no SOA record + to get the ttl from in the normal processing */ + cache_start_insert(); + cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG); + cache_end_insert(); + + return 1; + } + } + + if (!ADD_RDLEN(header, p, qlen, rdlen)) + return 0; + } + + return 0; +} + +static int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp, + unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...) +{ + va_list ap; + unsigned char *sav, *p = *pp; + int j; + unsigned short usval; + long lval; + char *sval; + + if (truncp && *truncp) + return 0; + + PUTSHORT(nameoffset | 0xc000, p); + PUTSHORT(type, p); + PUTSHORT(class, p); + PUTLONG(ttl, p); /* TTL */ + + sav = p; /* Save pointer to RDLength field */ + PUTSHORT(0, p); /* Placeholder RDLength */ + + va_start(ap, format); /* make ap point to 1st unamed argument */ + + for (; *format; format++) + switch (*format) + { +#ifdef HAVE_IPV6 + case '6': + sval = va_arg(ap, char *); + memcpy(p, sval, IN6ADDRSZ); + p += IN6ADDRSZ; + break; +#endif + + case '4': + sval = va_arg(ap, char *); + memcpy(p, sval, INADDRSZ); + p += INADDRSZ; + break; + + case 's': + usval = va_arg(ap, int); + PUTSHORT(usval, p); + break; + + case 'l': + lval = va_arg(ap, long); + PUTLONG(lval, p); + break; + + case 'd': + /* get domain-name answer arg and store it in RDATA field */ + if (offset) + *offset = p - (unsigned char *)header; + p = do_rfc1035_name(p, va_arg(ap, char *)); + *p++ = 0; + break; + + case 't': + usval = va_arg(ap, int); + sval = va_arg(ap, char *); + memcpy(p, sval, usval); + p += usval; + break; + + case 'z': + sval = va_arg(ap, char *); + usval = sval ? strlen(sval) : 0; + if (usval > 255) + usval = 255; + *p++ = (unsigned char)usval; + memcpy(p, sval, usval); + p += usval; + break; + } + + va_end(ap); /* clean up variable argument pointer */ + + j = p - sav - 2; + PUTSHORT(j, sav); /* Now, store real RDLength */ + + /* check for overflow of buffer */ + if (limit && ((unsigned char *)limit - p) < 0) + { + if (truncp) + *truncp = 1; + return 0; + } + + *pp = p; + return 1; +} + +static unsigned long crec_ttl(struct crec *crecp, time_t now) +{ + /* Return 0 ttl for DHCP entries, which might change + before the lease expires. */ + + if (crecp->flags & (F_IMMORTAL | F_DHCP)) + return daemon->local_ttl; + + /* Return the Max TTL value if it is lower then the actual TTL */ + if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl)) + return crecp->ttd - now; + else + return daemon->max_ttl; +} + + +/* return zero if we can't answer from cache, or packet size if we can */ +size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + struct in_addr local_addr, struct in_addr local_netmask, time_t now) +{ + char *name = daemon->namebuff; + unsigned char *p, *ansp, *pheader; + int qtype, qclass; + struct all_addr addr; + unsigned int nameoffset; + unsigned short flag; + int q, ans, anscount = 0, addncount = 0; + int dryrun = 0, sec_reqd = 0; + int is_sign; + struct crec *crecp; + int nxdomain = 0, auth = 1, trunc = 0; + struct mx_srv_record *rec; + + /* If there is an RFC2671 pseudoheader then it will be overwritten by + partial replies, so we have to do a dry run to see if we can answer + the query. We check to see if the do bit is set, if so we always + forward rather than answering from the cache, which doesn't include + security information. */ + + if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign)) + { + unsigned short udpsz, ext_rcode, flags; + unsigned char *psave = pheader; + + GETSHORT(udpsz, pheader); + GETSHORT(ext_rcode, pheader); + GETSHORT(flags, pheader); + + sec_reqd = flags & 0x8000; /* do bit */ + + /* If our client is advertising a larger UDP packet size + than we allow, trim it so that we don't get an overlarge + response from upstream */ + + if (!is_sign && (udpsz > daemon->edns_pktsz)) + PUTSHORT(daemon->edns_pktsz, psave); + + dryrun = 1; + } + + if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY ) + return 0; + + for (rec = daemon->mxnames; rec; rec = rec->next) + rec->offset = 0; + + rerun: + /* determine end of question section (we put answers there) */ + if (!(ansp = skip_questions(header, qlen))) + return 0; /* bad packet */ + + /* now process each question, answers go in RRs after the question */ + p = (unsigned char *)(header+1); + + for (q = ntohs(header->qdcount); q != 0; q--) + { + /* save pointer to name for copying into answers */ + nameoffset = p - (unsigned char *)header; + + /* now extract name as .-concatenated string into name */ + if (!extract_name(header, qlen, &p, name, 1, 4)) + return 0; /* bad packet */ + + GETSHORT(qtype, p); + GETSHORT(qclass, p); + + ans = 0; /* have we answered this question */ + + if (qtype == T_TXT || qtype == T_ANY) + { + struct txt_record *t; + for(t = daemon->txt; t ; t = t->next) + { + if (t->class == qclass && hostname_isequal(name, t->name)) + { + ans = 1; + if (!dryrun) + { + log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>"); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + daemon->local_ttl, NULL, + T_TXT, t->class, "t", t->len, t->txt)) + anscount++; + + } + } + } + } + + if (qclass == C_IN) + { + if (qtype == T_PTR || qtype == T_ANY) + { + /* see if it's w.z.y.z.in-addr.arpa format */ + int is_arpa = in_arpa_name_2_addr(name, &addr); + struct ptr_record *ptr; + struct interface_name* intr = NULL; + + for (ptr = daemon->ptr; ptr; ptr = ptr->next) + if (hostname_isequal(name, ptr->name)) + break; + + if (is_arpa == F_IPV4) + for (intr = daemon->int_names; intr; intr = intr->next) + { + if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr) + break; + else + while (intr->next && strcmp(intr->intr, intr->next->intr) == 0) + intr = intr->next; + } + + if (intr) + { + ans = 1; + if (!dryrun) + { + log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + daemon->local_ttl, NULL, + T_PTR, C_IN, "d", intr->name)) + anscount++; + } + } + else if (ptr) + { + ans = 1; + if (!dryrun) + { + log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>"); + for (ptr = daemon->ptr; ptr; ptr = ptr->next) + if (hostname_isequal(name, ptr->name) && + add_resource_record(header, limit, &trunc, nameoffset, &ansp, + daemon->local_ttl, NULL, + T_PTR, C_IN, "d", ptr->ptr)) + anscount++; + + } + } + else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa))) + do + { + /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */ + if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) + continue; + + if (crecp->flags & F_NEG) + { + ans = 1; + auth = 0; + if (crecp->flags & F_NXDOMAIN) + nxdomain = 1; + if (!dryrun) + log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL); + } + else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) + { + ans = 1; + if (!(crecp->flags & (F_HOSTS | F_DHCP))) + auth = 0; + if (!dryrun) + { + log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, + record_source(crecp->uid)); + + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + crec_ttl(crecp, now), NULL, + T_PTR, C_IN, "d", cache_get_name(crecp))) + anscount++; + } + } + } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa))); + else if (is_arpa == F_IPV4 && + option_bool(OPT_BOGUSPRIV) && + private_net(addr.addr.addr4, 1)) + { + /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */ + ans = 1; + nxdomain = 1; + if (!dryrun) + log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, + name, &addr, NULL); + } + } + + for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0) + { + unsigned short type = T_A; + + if (flag == F_IPV6) +#ifdef HAVE_IPV6 + type = T_AAAA; +#else + break; +#endif + + if (qtype != type && qtype != T_ANY) + continue; + + /* Check for "A for A" queries; be rather conservative + about what looks like dotted-quad. */ + if (qtype == T_A) + { + char *cp; + unsigned int i, a; + int x; + + for (cp = name, i = 0, a = 0; *cp; i++) + { + if (!isdigit((unsigned char)*cp) || (x = strtol(cp, &cp, 10)) > 255) + { + i = 5; + break; + } + + a = (a << 8) + x; + + if (*cp == '.') + cp++; + } + + if (i == 4) + { + ans = 1; + if (!dryrun) + { + addr.addr.addr4.s_addr = htonl(a); + log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + daemon->local_ttl, NULL, type, C_IN, "4", &addr)) + anscount++; + } + continue; + } + } + + /* interface name stuff */ + if (qtype == T_A) + { + struct interface_name *intr; + + for (intr = daemon->int_names; intr; intr = intr->next) + if (hostname_isequal(name, intr->name)) + break; + + if (intr) + { + ans = 1; + if (!dryrun) + { + if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1) + log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL); + else + { + log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + daemon->local_ttl, NULL, type, C_IN, "4", &addr)) + anscount++; + } + } + continue; + } + } + + cname_restart: + if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME))) + { + int localise = 0; + + /* See if a putative address is on the network from which we recieved + the query, is so we'll filter other answers. */ + if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && flag == F_IPV4) + { + struct crec *save = crecp; + do { + if ((crecp->flags & F_HOSTS) && + is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask)) + { + localise = 1; + break; + } + } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME))); + crecp = save; + } + + do + { + /* don't answer wildcard queries with data not from /etc/hosts + or DHCP leases */ + if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) + break; + + if (crecp->flags & F_CNAME) + { + if (!dryrun) + { + log_query(crecp->flags, name, NULL, record_source(crecp->uid)); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + crec_ttl(crecp, now), &nameoffset, + T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache))) + anscount++; + } + + strcpy(name, cache_get_name(crecp->addr.cname.cache)); + goto cname_restart; + } + + if (crecp->flags & F_NEG) + { + ans = 1; + auth = 0; + if (crecp->flags & F_NXDOMAIN) + nxdomain = 1; + if (!dryrun) + log_query(crecp->flags, name, NULL, NULL); + } + else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) + { + /* If we are returning local answers depending on network, + filter here. */ + if (localise && + (crecp->flags & F_HOSTS) && + !is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask)) + continue; + + if (!(crecp->flags & (F_HOSTS | F_DHCP))) + auth = 0; + + ans = 1; + if (!dryrun) + { + log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr, + record_source(crecp->uid)); + + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + crec_ttl(crecp, now), NULL, type, C_IN, + type == T_A ? "4" : "6", &crecp->addr)) + anscount++; + } + } + } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME))); + } + } + + if (qtype == T_MX || qtype == T_ANY) + { + int found = 0; + for (rec = daemon->mxnames; rec; rec = rec->next) + if (!rec->issrv && hostname_isequal(name, rec->name)) + { + ans = found = 1; + if (!dryrun) + { + unsigned int offset; + log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>"); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, + &offset, T_MX, C_IN, "sd", rec->weight, rec->target)) + { + anscount++; + if (rec->target) + rec->offset = offset; + } + } + } + + if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && + cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP)) + { + ans = 1; + if (!dryrun) + { + log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>"); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL, + T_MX, C_IN, "sd", 1, + option_bool(OPT_SELFMX) ? name : daemon->mxtarget)) + anscount++; + } + } + } + + if (qtype == T_SRV || qtype == T_ANY) + { + int found = 0; + struct mx_srv_record *move = NULL, **up = &daemon->mxnames; + + for (rec = daemon->mxnames; rec; rec = rec->next) + if (rec->issrv && hostname_isequal(name, rec->name)) + { + found = ans = 1; + if (!dryrun) + { + unsigned int offset; + log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>"); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, + &offset, T_SRV, C_IN, "sssd", + rec->priority, rec->weight, rec->srvport, rec->target)) + { + anscount++; + if (rec->target) + rec->offset = offset; + } + } + + /* unlink first SRV record found */ + if (!move) + { + move = rec; + *up = rec->next; + } + else + up = &rec->next; + } + else + up = &rec->next; + + /* put first SRV record back at the end. */ + if (move) + { + *up = move; + move->next = NULL; + } + + if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_')))) + { + ans = 1; + if (!dryrun) + log_query(F_CONFIG | F_NEG, name, NULL, NULL); + } + } + + if (qtype == T_NAPTR || qtype == T_ANY) + { + struct naptr *na; + for (na = daemon->naptr; na; na = na->next) + if (hostname_isequal(name, na->name)) + { + ans = 1; + if (!dryrun) + { + log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>"); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, + NULL, T_NAPTR, C_IN, "sszzzd", + na->order, na->pref, na->flags, na->services, na->regexp, na->replace)) + anscount++; + } + } + } + + if (qtype == T_MAILB) + ans = 1, nxdomain = 1; + + if (qtype == T_SOA && option_bool(OPT_FILTER)) + { + ans = 1; + if (!dryrun) + log_query(F_CONFIG | F_NEG, name, &addr, NULL); + } + } + + if (!ans) + return 0; /* failed to answer a question */ + } + + if (dryrun) + { + dryrun = 0; + goto rerun; + } + + /* create an additional data section, for stuff in SRV and MX record replies. */ + for (rec = daemon->mxnames; rec; rec = rec->next) + if (rec->offset != 0) + { + /* squash dupes */ + struct mx_srv_record *tmp; + for (tmp = rec->next; tmp; tmp = tmp->next) + if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target)) + tmp->offset = 0; + + crecp = NULL; + while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6))) + { +#ifdef HAVE_IPV6 + int type = crecp->flags & F_IPV4 ? T_A : T_AAAA; +#else + int type = T_A; +#endif + if (crecp->flags & F_NEG) + continue; + + if (add_resource_record(header, limit, NULL, rec->offset, &ansp, + crec_ttl(crecp, now), NULL, type, C_IN, + crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr)) + addncount++; + } + } + + /* done all questions, set up header and return length of result */ + /* clear authoritative and truncated flags, set QR flag */ + header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR; + /* set RA flag */ + header->hb4 |= HB4_RA; + + /* authoritive - only hosts and DHCP derived names. */ + if (auth) + header->hb3 |= HB3_AA; + + /* truncation */ + if (trunc) + header->hb3 |= HB3_TC; + + if (anscount == 0 && nxdomain) + SET_RCODE(header, NXDOMAIN); + else + SET_RCODE(header, NOERROR); /* no error */ + header->ancount = htons(anscount); + header->nscount = htons(0); + header->arcount = htons(addncount); + return ansp - (unsigned char *)header; +} + + + + + diff --git a/src/rfc2131.c b/src/rfc2131.c new file mode 100644 index 0000000..4f942b5 --- /dev/null +++ b/src/rfc2131.c @@ -0,0 +1,2512 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + Copyright (c) 2012, 2013 Samsung Electronices Co., Ltd. + + 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/>. + + * Modifications by Samsung Electronices Co., Ltd. + 1. ACTION_CONNECT is added to notify IP address assignment +*/ + +#include "dnsmasq.h" + +#ifdef HAVE_DHCP + +#define have_config(config, mask) ((config) && ((config)->flags & (mask))) +#define option_len(opt) ((int)(((unsigned char *)(opt))[1])) +#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)])) + +#ifdef HAVE_SCRIPT +static void add_extradata_data(struct dhcp_lease *lease, unsigned char *data, size_t len, int delim); +static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt); +#endif + +static int match_bytes(struct dhcp_opt *o, unsigned char *p, int len); +static int sanitise(unsigned char *opt, char *buf); +static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback); +static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt); +static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val); +static void option_put_string(struct dhcp_packet *mess, unsigned char *end, + int opt, char *string, int null_term); +static struct in_addr option_addr(unsigned char *opt); +static struct in_addr option_addr_arr(unsigned char *opt, int offset); +static unsigned int option_uint(unsigned char *opt, int i, int size); +static void log_packet(char *type, void *addr, unsigned char *ext_mac, + int mac_len, char *interface, char *string, u32 xid); +static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize); +static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize); +static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid, + unsigned char *agent_id, unsigned char *real_end); +static void clear_packet(struct dhcp_packet *mess, unsigned char *end); +static void do_options(struct dhcp_context *context, + struct dhcp_packet *mess, + unsigned char *real_end, + unsigned char *req_options, + char *hostname, + char *domain, char *config_domain, + struct dhcp_netid *netid, + struct in_addr subnet_addr, + unsigned char fqdn_flags, + int null_term, int pxearch, + unsigned char *uuid, + int vendor_class_len); + + +static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); +static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term); +static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid); +static int prune_vendor_opts(struct dhcp_netid *netid); +static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local); +struct dhcp_boot *find_boot(struct dhcp_netid *netid); + + +size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, + size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe) +{ + unsigned char *opt, *clid = NULL; + struct dhcp_lease *ltmp, *lease = NULL; + struct dhcp_vendor *vendor; + struct dhcp_mac *mac; + struct dhcp_netid_list *id_list; + int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1; + struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base; + unsigned char *end = (unsigned char *)(mess + 1); + unsigned char *real_end = (unsigned char *)(mess + 1); + char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL; + int hostname_auth = 0, borken_opt = 0; + unsigned char *req_options = NULL; + char *message = NULL; + unsigned int time; + struct dhcp_config *config; + struct dhcp_netid *netid, *tagif_netid; + struct in_addr subnet_addr, fallback, override; + unsigned short fuzz = 0; + unsigned int mess_type = 0; + unsigned char fqdn_flags = 0; + unsigned char *agent_id = NULL, *uuid = NULL; + unsigned char *emac = NULL; + int vendor_class_len = 0, emac_len = 0; + struct dhcp_netid known_id, iface_id, cpewan_id; + struct dhcp_opt *o; + unsigned char pxe_uuid[17]; + unsigned char *oui = NULL, *serial = NULL, *class = NULL; + + subnet_addr.s_addr = override.s_addr = 0; + + /* set tag with name == interface */ + iface_id.net = iface_name; + iface_id.next = NULL; + netid = &iface_id; + + if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX) + return 0; + + if (mess->htype == 0 && mess->hlen != 0) + return 0; + + /* check for DHCP rather than BOOTP */ + if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1))) + { + u32 cookie = htonl(DHCP_COOKIE); + + /* only insist on a cookie for DHCP. */ + if (memcmp(mess->options, &cookie, sizeof(u32)) != 0) + return 0; + + mess_type = option_uint(opt, 0, 1); + + /* two things to note here: expand_buf may move the packet, + so reassign mess from daemon->packet. Also, the size + sent includes the IP and UDP headers, hence the magic "-28" */ + if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2))) + { + size_t size = (size_t)option_uint(opt, 0, 2) - 28; + + if (size > DHCP_PACKET_MAX) + size = DHCP_PACKET_MAX; + else if (size < sizeof(struct dhcp_packet)) + size = sizeof(struct dhcp_packet); + + if (expand_buf(&daemon->dhcp_packet, size)) + { + mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base; + real_end = end = ((unsigned char *)mess) + size; + } + } + + /* Some buggy clients set ciaddr when they shouldn't, so clear that here since + it can affect the context-determination code. */ + if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER)) + mess->ciaddr.s_addr = 0; + + /* search for device identity from CPEWAN devices, we pass this through to the script */ + if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5))) + { + unsigned int elen, offset, len = option_len(opt); + + for (offset = 0; offset < (len - 5); offset += elen + 5) + { + elen = option_uint(opt, offset + 4 , 1); + if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA) + { + unsigned char *x = option_ptr(opt, offset + 5); + unsigned char *y = option_ptr(opt, offset + elen + 5); + oui = option_find1(x, y, 1, 1); + serial = option_find1(x, y, 2, 1); + class = option_find1(x, y, 3, 1); + + /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing + the gateway id back. Note that the device class is optional */ + if (oui && serial) + { + cpewan_id.net = "cpewan-id"; + cpewan_id.next = netid; + netid = &cpewan_id; + } + break; + } + } + } + + if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1))) + { + /* Any agent-id needs to be copied back out, verbatim, as the last option + in the packet. Here, we shift it to the very end of the buffer, if it doesn't + get overwritten, then it will be shuffled back at the end of processing. + Note that the incoming options must not be overwritten here, so there has to + be enough free space at the end of the packet to copy the option. */ + unsigned char *sopt; + unsigned int total = option_len(opt) + 2; + unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0); + if (last_opt && last_opt < end - total) + { + end -= total; + agent_id = end; + memcpy(agent_id, opt, total); + } + + /* look for RFC3527 Link selection sub-option */ + if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ))) + subnet_addr = option_addr(sopt); + + /* look for RFC5107 server-identifier-override */ + if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ))) + override = option_addr(sopt); + + /* if a circuit-id or remote-is option is provided, exact-match to options. */ + for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next) + { + int search; + + if (vendor->match_type == MATCH_CIRCUIT) + search = SUBOPT_CIRCUIT_ID; + else if (vendor->match_type == MATCH_REMOTE) + search = SUBOPT_REMOTE_ID; + else if (vendor->match_type == MATCH_SUBSCRIBER) + search = SUBOPT_SUBSCR_ID; + else + continue; + + if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) && + vendor->len == option_len(sopt) && + memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0) + { + vendor->netid.next = netid; + netid = &vendor->netid; + } + } + } + + /* Check for RFC3011 subnet selector - only if RFC3527 one not present */ + if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ))) + subnet_addr = option_addr(opt); + + /* If there is no client identifier option, use the hardware address */ + if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1))) + { + clid_len = option_len(opt); + clid = option_ptr(opt, 0); + } + + /* do we have a lease in store? */ + lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len); + + /* If this request is missing a clid, but we've seen one before, + use it again for option matching etc. */ + if (lease && !clid && lease->clid) + { + clid_len = lease->clid_len; + clid = lease->clid; + } + + /* find mac to use for logging and hashing */ + emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len); + } + + for (mac = daemon->dhcp_macs; mac; mac = mac->next) + if (mac->hwaddr_len == mess->hlen && + (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) && + memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask)) + { + mac->netid.next = netid; + netid = &mac->netid; + } + + /* Determine network for this packet. Our caller will have already linked all the + contexts which match the addresses of the receiving interface but if the + machine has an address already, or came via a relay, or we have a subnet selector, + we search again. If we don't have have a giaddr or explicit subnet selector, + use the ciaddr. This is necessary because a machine which got a lease via a + relay won't use the relay to renew. If matching a ciaddr fails but we have a context + from the physical network, continue using that to allow correct DHCPNAK generation later. */ + if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr) + { + struct dhcp_context *context_tmp, *context_new = NULL; + struct in_addr addr; + int force = 0; + + if (subnet_addr.s_addr) + { + addr = subnet_addr; + force = 1; + } + else if (mess->giaddr.s_addr) + { + addr = mess->giaddr; + force = 1; + } + else + { + /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */ + addr = mess->ciaddr; + for (context_tmp = context; context_tmp; context_tmp = context_tmp->current) + if (context_tmp->netmask.s_addr && + is_same_net(addr, context_tmp->start, context_tmp->netmask) && + is_same_net(addr, context_tmp->end, context_tmp->netmask)) + { + context_new = context; + break; + } + } + + if (!context_new) + for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next) + if (context_tmp->netmask.s_addr && + is_same_net(addr, context_tmp->start, context_tmp->netmask) && + is_same_net(addr, context_tmp->end, context_tmp->netmask)) + { + context_tmp->current = context_new; + context_new = context_tmp; + } + + if (context_new || force) + context = context_new; + + } + + if (!context) + { + my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"), + subnet_addr.s_addr ? _("with subnet selector") : _("via"), + subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name)); + return 0; + } + + /* keep _a_ local address available. */ + fallback = context->local; + + if (option_bool(OPT_LOG_OPTS)) + { + struct dhcp_context *context_tmp; + for (context_tmp = context; context_tmp; context_tmp = context_tmp->current) + { + strcpy(daemon->namebuff, inet_ntoa(context_tmp->start)); + if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) + my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"), + ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask)); + else + my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"), + ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end)); + } + } + + mess->op = BOOTREPLY; + + config = find_config(daemon->dhcp_conf, context, clid, clid_len, + mess->chaddr, mess->hlen, mess->htype, NULL); + + /* set "known" tag for known hosts */ + if (config) + { + known_id.net = "known"; + known_id.next = netid; + netid = &known_id; + } + + if (mess_type == 0 && !pxe) + { + /* BOOTP request */ + struct dhcp_netid id, bootp_id; + struct in_addr *logaddr = NULL; + + /* must have a MAC addr for bootp */ + if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY)) + return 0; + + if (have_config(config, CONFIG_DISABLE)) + message = _("disabled"); + + end = mess->options + 64; /* BOOTP vend area is only 64 bytes */ + + if (have_config(config, CONFIG_NAME)) + { + hostname = config->hostname; + domain = config->domain; + } + + if (config) + { + struct dhcp_netid_list *list; + + for (list = config->netid; list; list = list->next) + { + list->list->next = netid; + netid = list->list; + } + } + + /* Match incoming filename field as a netid. */ + if (mess->file[0]) + { + memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file)); + daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */ + id.net = (char *)daemon->dhcp_buff2; + id.next = netid; + netid = &id; + } + + /* Add "bootp" as a tag to allow different options, address ranges etc + for BOOTP clients */ + bootp_id.net = "bootp"; + bootp_id.next = netid; + netid = &bootp_id; + + tagif_netid = run_tag_if(netid); + + for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next) + if (match_netid(id_list->list, tagif_netid, 0)) + message = _("ignored"); + + if (!message) + { + int nailed = 0; + + if (have_config(config, CONFIG_ADDR)) + { + nailed = 1; + logaddr = &config->addr; + mess->yiaddr = config->addr; + if ((lease = lease_find_by_addr(config->addr)) && + (lease->hwaddr_len != mess->hlen || + lease->hwaddr_type != mess->htype || + memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0)) + message = _("address in use"); + } + else + { + if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) || + !address_available(context, lease->addr, tagif_netid)) + { + if (lease) + { + /* lease exists, wrong network. */ + lease_prune(lease, now); + lease = NULL; + } + if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now)) + message = _("no address available"); + } + else + mess->yiaddr = lease->addr; + } + + if (!message && !(context = narrow_context(context, mess->yiaddr, netid))) + message = _("wrong network"); + else if (context->netid.net) + { + context->netid.next = netid; + netid = &context->netid; + tagif_netid = run_tag_if(netid); + } + + if (!message && !nailed) + { + for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next) + if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0)) + break; + if (!id_list) + message = _("no address configured"); + } + + if (!message && + !lease && + (!(lease = lease_allocate(mess->yiaddr)))) + message = _("no leases left"); + + if (!message) + { + logaddr = &mess->yiaddr; + + lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0); + if (hostname) + lease_set_hostname(lease, hostname, 1); + /* infinite lease unless nailed in dhcp-host line. */ + lease_set_expires(lease, + have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff, + now); + lease_set_interface(lease, int_index); + + clear_packet(mess, end); + do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr), + domain, tagif_netid, subnet_addr, 0, 0, 0, NULL, 0); + } + } + + log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid); + + return message ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end); + } + + if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4))) + { + /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */ + int len = option_len(opt); + char *pq = daemon->dhcp_buff; + unsigned char *pp, *op = option_ptr(opt, 0); + + fqdn_flags = *op; + len -= 3; + op += 3; + pp = op; + + /* Always force update, since the client has no way to do it itself. */ + if (!(fqdn_flags & 0x01)) + fqdn_flags |= 0x02; + + fqdn_flags &= ~0x08; + fqdn_flags |= 0x01; + + if (fqdn_flags & 0x04) + while (*op != 0 && ((op + (*op) + 1) - pp) < len) + { + memcpy(pq, op+1, *op); + pq += *op; + op += (*op)+1; + *(pq++) = '.'; + } + else + { + memcpy(pq, op, len); + if (len > 0 && op[len-1] == 0) + borken_opt = 1; + pq += len + 1; + } + + if (pq != daemon->dhcp_buff) + pq--; + + *pq = 0; + + if (legal_hostname(daemon->dhcp_buff)) + offer_hostname = client_hostname = daemon->dhcp_buff; + } + else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1))) + { + int len = option_len(opt); + memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len); + /* Microsoft clients are broken, and need zero-terminated strings + in options. We detect this state here, and do the same in + any options we send */ + if (len > 0 && daemon->dhcp_buff[len-1] == 0) + borken_opt = 1; + else + daemon->dhcp_buff[len] = 0; + if (legal_hostname(daemon->dhcp_buff)) + client_hostname = daemon->dhcp_buff; + } + + if (client_hostname && option_bool(OPT_LOG_OPTS)) + my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname); + + if (have_config(config, CONFIG_NAME)) + { + hostname = config->hostname; + domain = config->domain; + hostname_auth = 1; + /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */ + if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname)) + offer_hostname = hostname; + } + else if (client_hostname) + { + domain = strip_hostname(client_hostname); + + if (strlen(client_hostname) != 0) + { + hostname = client_hostname; + if (!config) + { + /* Search again now we have a hostname. + Only accept configs without CLID and HWADDR here, (they won't match) + to avoid impersonation by name. */ + struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0, + mess->chaddr, mess->hlen, + mess->htype, hostname); + if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr) + { + config = new; + /* set "known" tag for known hosts */ + known_id.net = "known"; + known_id.next = netid; + netid = &known_id; + } + } + } + } + + if (config) + { + struct dhcp_netid_list *list; + + for (list = config->netid; list; list = list->next) + { + list->list->next = netid; + netid = list->list; + } + } + + /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match. + Otherwise assume the option is an array, and look for a matching element. + If no data given, existance of the option is enough. This code handles + rfc3925 V-I classes too. */ + for (o = daemon->dhcp_match; o; o = o->next) + { + unsigned int len, elen, match = 0; + size_t offset, o2; + + if (o->flags & DHOPT_RFC3925) + { + if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5))) + continue; + + for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5) + { + len = option_uint(opt, offset + 4 , 1); + /* Need to take care that bad data can't run us off the end of the packet */ + if ((offset + len + 5 <= (option_len(opt))) && + (option_uint(opt, offset, 4) == (unsigned int)o->u.encap)) + for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1) + { + elen = option_uint(opt, o2, 1); + if ((o2 + elen + 1 <= option_len(opt)) && + (match = match_bytes(o, option_ptr(opt, o2 + 1), elen))) + break; + } + if (match) + break; + } + } + else + { + if (!(opt = option_find(mess, sz, o->opt, 1))) + continue; + + match = match_bytes(o, option_ptr(opt, 0), option_len(opt)); + } + + if (match) + { + o->netid->next = netid; + netid = o->netid; + } + } + + /* user-class options are, according to RFC3004, supposed to contain + a set of counted strings. Here we check that this is so (by seeing + if the counts are consistent with the overall option length) and if + so zero the counts so that we don't get spurious matches between + the vendor string and the counts. If the lengths don't add up, we + assume that the option is a single string and non RFC3004 compliant + and just do the substring match. dhclient provides these broken options. + The code, later, which sends user-class data to the lease-change script + relies on the transformation done here. + */ + + if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1))) + { + unsigned char *ucp = option_ptr(opt, 0); + int tmp, j; + for (j = 0; j < option_len(opt); j += ucp[j] + 1); + if (j == option_len(opt)) + for (j = 0; j < option_len(opt); j = tmp) + { + tmp = j + ucp[j] + 1; + ucp[j] = 0; + } + } + + for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next) + { + int mopt; + + if (vendor->match_type == MATCH_VENDOR) + mopt = OPTION_VENDOR_ID; + else if (vendor->match_type == MATCH_USER) + mopt = OPTION_USER_CLASS; + else + continue; + + if ((opt = option_find(mess, sz, mopt, 1))) + { + int i; + for (i = 0; i <= (option_len(opt) - vendor->len); i++) + if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0) + { + vendor->netid.next = netid; + netid = &vendor->netid; + break; + } + } + } + + /* mark vendor-encapsulated options which match the client-supplied vendor class, + save client-supplied vendor class */ + if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1))) + { + memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt)); + vendor_class_len = option_len(opt); + } + match_vendor_opts(opt, daemon->dhcp_opts); + + if (option_bool(OPT_LOG_OPTS)) + { + if (sanitise(opt, daemon->namebuff)) + my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff); + if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff)) + my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff); + } + + tagif_netid = run_tag_if(netid); + + /* if all the netids in the ignore list are present, ignore this client */ + for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next) + if (match_netid(id_list->list, tagif_netid, 0)) + ignore = 1; + + /* If configured, we can override the server-id to be the address of the relay, + so that all traffic goes via the relay and can pick up agent-id info. This can be + configured for all relays, or by address. */ + if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0) + { + if (!daemon->override_relays) + override = mess->giaddr; + else + { + struct addr_list *l; + for (l = daemon->override_relays; l; l = l->next) + if (l->addr.s_addr == mess->giaddr.s_addr) + break; + if (l) + override = mess->giaddr; + } + } + + /* Can have setting to ignore the client ID for a particular MAC address or hostname */ + if (have_config(config, CONFIG_NOCLID)) + clid = NULL; + + /* Check if client is PXE client. */ + if (daemon->enable_pxe && + (opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) && + strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0) + { + if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17))) + { + memcpy(pxe_uuid, option_ptr(opt, 0), 17); + uuid = pxe_uuid; + } + + /* Check if this is really a PXE bootserver request, and handle specially if so. */ + if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) && + (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) && + (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4))) + { + struct pxe_service *service; + int type = option_uint(opt, 0, 2); + int layer = option_uint(opt, 2, 2); + unsigned char save71[4]; + struct dhcp_opt opt71; + + if (ignore) + return 0; + + if (layer & 0x8000) + { + my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported")); + return 0; + } + + memcpy(save71, option_ptr(opt, 0), 4); + + for (service = daemon->pxe_services; service; service = service->next) + if (service->type == type) + break; + + if (!service || !service->basename) + return 0; + + clear_packet(mess, end); + + mess->yiaddr = mess->ciaddr; + mess->ciaddr.s_addr = 0; + if (service->server.s_addr != 0) + mess->siaddr = service->server; + else + mess->siaddr = context->local; + + snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer); + option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK); + option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr)); + pxe_misc(mess, end, uuid); + + prune_vendor_opts(tagif_netid); + opt71.val = save71; + opt71.opt = SUBOPT_PXE_BOOT_ITEM; + opt71.len = 4; + opt71.flags = DHOPT_VENDOR_MATCH; + opt71.netid = NULL; + opt71.next = daemon->dhcp_opts; + do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0); + + log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid); + return dhcp_packet_size(mess, tagif_netid, agent_id, real_end); + } + + if ((opt = option_find(mess, sz, OPTION_ARCH, 2))) + { + pxearch = option_uint(opt, 0, 2); + + /* proxy DHCP here. */ + if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST))) + { + struct dhcp_context *tmp; + + for (tmp = context; tmp; tmp = tmp->current) + if ((tmp->flags & CONTEXT_PROXY) && + match_netid(tmp->filter, tagif_netid, 1)) + break; + + if (tmp) + { + struct dhcp_boot *boot = find_boot(tagif_netid); + + mess->yiaddr.s_addr = 0; + if (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0) + { + mess->ciaddr.s_addr = 0; + mess->flags |= htons(0x8000); /* broadcast */ + } + + clear_packet(mess, end); + + /* Provide the bootfile here, for gPXE, and in case we have no menu items + and set discovery_control = 8 */ + if (boot) + { + if (boot->next_server.s_addr) + mess->siaddr = boot->next_server; + + if (boot->file) + strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1); + } + + option_put(mess, end, OPTION_MESSAGE_TYPE, 1, + mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK); + option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr)); + pxe_misc(mess, end, uuid); + prune_vendor_opts(tagif_netid); + do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0); + + log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", mess->xid); + return ignore ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end); + } + } + } + } + + /* if we're just a proxy server, go no further */ + if ((context->flags & CONTEXT_PROXY) || pxe) + return 0; + + if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0))) + { + req_options = (unsigned char *)daemon->dhcp_buff2; + memcpy(req_options, option_ptr(opt, 0), option_len(opt)); + req_options[option_len(opt)] = OPTION_END; + } + + switch (mess_type) + { + case DHCPDECLINE: + if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) || + option_addr(opt).s_addr != server_id(context, override, fallback).s_addr) + return 0; + + /* sanitise any message. Paranoid? Moi? */ + sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff); + + if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ))) + return 0; + + log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, daemon->dhcp_buff, mess->xid); + + if (lease && lease->addr.s_addr == option_addr(opt).s_addr) + lease_prune(lease, now); + + if (have_config(config, CONFIG_ADDR) && + config->addr.s_addr == option_addr(opt).s_addr) + { + prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF); + my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"), + inet_ntoa(config->addr), daemon->dhcp_buff); + config->flags |= CONFIG_DECLINED; + config->decline_time = now; + } + else + /* make sure this host gets a different address next time. */ + for (; context; context = context->current) + context->addr_epoch++; + + return 0; + + case DHCPRELEASE: + if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) || + !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) || + option_addr(opt).s_addr != server_id(context, override, fallback).s_addr) + return 0; + + if (lease && lease->addr.s_addr == mess->ciaddr.s_addr) + lease_prune(lease, now); + else + message = _("unknown lease"); + + log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid); + + return 0; + + case DHCPDISCOVER: + if (ignore || have_config(config, CONFIG_DISABLE)) + { + message = _("ignored"); + opt = NULL; + } + else + { + struct in_addr addr, conf; + + addr.s_addr = conf.s_addr = 0; + + if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ))) + addr = option_addr(opt); + + if (have_config(config, CONFIG_ADDR)) + { + char *addrs = inet_ntoa(config->addr); + + if ((ltmp = lease_find_by_addr(config->addr)) && + ltmp != lease && + !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type)) + { + int len; + unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len, + ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len); + my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"), + addrs, print_mac(daemon->namebuff, mac, len)); + } + else + { + struct dhcp_context *tmp; + for (tmp = context; tmp; tmp = tmp->current) + if (context->router.s_addr == config->addr.s_addr) + break; + if (tmp) + my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs); + else if (have_config(config, CONFIG_DECLINED) && + difftime(now, config->decline_time) < (float)DECLINE_BACKOFF) + my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs); + else + conf = config->addr; + } + } + + if (conf.s_addr) + mess->yiaddr = conf; + else if (lease && + address_available(context, lease->addr, tagif_netid) && + !config_find_by_address(daemon->dhcp_conf, lease->addr)) + mess->yiaddr = lease->addr; + else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) && + !config_find_by_address(daemon->dhcp_conf, addr)) + mess->yiaddr = addr; + else if (emac_len == 0) + message = _("no unique-id"); + else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now)) + message = _("no address available"); + } + + log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid); + + if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid))) + return 0; + + log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid); + + if (context->netid.net) + { + context->netid.next = netid; + netid = &context->netid; + tagif_netid = run_tag_if(netid); + } + + time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4)); + clear_packet(mess, end); + option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER); + option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr)); + option_put(mess, end, OPTION_LEASE_TIME, 4, time); + /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */ + if (time != 0xffffffff) + { + option_put(mess, end, OPTION_T1, 4, (time/2)); + option_put(mess, end, OPTION_T2, 4, (time*7)/8); + } + do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr), + domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len); + + return dhcp_packet_size(mess, tagif_netid, agent_id, real_end); + + case DHCPREQUEST: + if (ignore || have_config(config, CONFIG_DISABLE)) + return 0; + if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ))) + { + /* SELECTING or INIT_REBOOT */ + mess->yiaddr = option_addr(opt); + + /* send vendor and user class info for new or recreated lease */ + do_classes = 1; + + if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ))) + { + /* SELECTING */ + selecting = 1; + + if (override.s_addr != 0) + { + if (option_addr(opt).s_addr != override.s_addr) + return 0; + } + else + { + for (; context; context = context->current) + if (context->local.s_addr == option_addr(opt).s_addr) + break; + + if (!context) + { + /* In auth mode, a REQUEST sent to the wrong server + should be faulted, so that the client establishes + communication with us, otherwise, silently ignore. */ + if (!option_bool(OPT_AUTHORITATIVE)) + return 0; + message = _("wrong server-ID"); + } + } + + /* If a lease exists for this host and another address, squash it. */ + if (lease && lease->addr.s_addr != mess->yiaddr.s_addr) + { + lease_prune(lease, now); + lease = NULL; + } + } + else + { + /* INIT-REBOOT */ + if (!lease && !option_bool(OPT_AUTHORITATIVE)) + return 0; + + if (lease && lease->addr.s_addr != mess->yiaddr.s_addr) + message = _("wrong address"); + } + } + else + { + /* RENEWING or REBINDING */ + /* Check existing lease for this address. + We allow it to be missing if dhcp-authoritative mode + as long as we can allocate the lease now - checked below. + This makes for a smooth recovery from a lost lease DB */ + if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) || + (!lease && !option_bool(OPT_AUTHORITATIVE))) + { + /* A client rebinding will broadcast the request, so we may see it even + if the lease is held by another server. Just ignore it in that case. + If the request is unicast to us, then somethings wrong, NAK */ + if (!unicast_dest) + return 0; + message = _("lease not found"); + /* ensure we broadcast NAK */ + unicast_dest = 0; + } + + /* desynchronise renewals */ + fuzz = rand16(); + mess->yiaddr = mess->ciaddr; + } + + log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid); + + if (!message) + { + struct dhcp_config *addr_config; + struct dhcp_context *tmp = NULL; + + if (have_config(config, CONFIG_ADDR)) + for (tmp = context; tmp; tmp = tmp->current) + if (context->router.s_addr == config->addr.s_addr) + break; + + if (!(context = narrow_context(context, mess->yiaddr, tagif_netid))) + { + /* If a machine moves networks whilst it has a lease, we catch that here. */ + message = _("wrong network"); + /* ensure we broadcast NAK */ + unicast_dest = 0; + } + + /* Check for renewal of a lease which is outside the allowed range. */ + else if (!address_available(context, mess->yiaddr, tagif_netid) && + (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr)) + message = _("address not available"); + + /* Check if a new static address has been configured. Be very sure that + when the client does DISCOVER, it will get the static address, otherwise + an endless protocol loop will ensue. */ + else if (!tmp && !selecting && + have_config(config, CONFIG_ADDR) && + (!have_config(config, CONFIG_DECLINED) || + difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) && + config->addr.s_addr != mess->yiaddr.s_addr && + (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease)) + message = _("static lease available"); + + /* Check to see if the address is reserved as a static address for another host */ + else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config) + message = _("address reserved"); + + else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr))) + { + /* If a host is configured with more than one MAC address, it's OK to 'nix + a lease from one of it's MACs to give the address to another. */ + if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type)) + { + my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"), + print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len), + inet_ntoa(ltmp->addr)); + lease = ltmp; + } + else + message = _("address in use"); + } + + if (!message) + { + if (emac_len == 0) + message = _("no unique-id"); + + else if (!lease) + { + if ((lease = lease_allocate(mess->yiaddr))) + do_classes = 1; + else + message = _("no leases left"); + } + } + } + + if (message) + { + log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, message, mess->xid); + + mess->yiaddr.s_addr = 0; + clear_packet(mess, end); + option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK); + option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr)); + option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt); + /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on + a distant subnet which unicast a REQ to us won't work. */ + if (!unicast_dest || mess->giaddr.s_addr != 0 || + mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask)) + { + mess->flags |= htons(0x8000); /* broadcast */ + mess->ciaddr.s_addr = 0; + } + } + else + { + if (context->netid.net) + { + context->netid.next = netid; + netid = &context->netid; + tagif_netid = run_tag_if(netid); + } + +#ifdef HAVE_SCRIPT + if (do_classes && daemon->lease_change_command) + { + struct dhcp_netid *n; + + if (mess->giaddr.s_addr) + lease->giaddr = mess->giaddr; + + lease->changed = 1; + free(lease->extradata); + lease->extradata = NULL; + lease->extradata_size = lease->extradata_len = 0; + + add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1)); + add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1)); + add_extradata_opt(lease, oui); + add_extradata_opt(lease, serial); + add_extradata_opt(lease, class); + + /* space-concat tag set */ + if (!tagif_netid) + add_extradata_opt(lease, NULL); + else + for (n = tagif_netid; n; n = n->next) + add_extradata_data(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0); + + if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1))) + { + int len = option_len(opt); + unsigned char *ucp = option_ptr(opt, 0); + /* If the user-class option started as counted strings, the first byte will be zero. */ + if (len != 0 && ucp[0] == 0) + ucp++, len--; + add_extradata_data(lease, ucp, len, 0); + } + } +#endif + + if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr))) + { + domain = get_domain(mess->yiaddr); + hostname = client_hostname; + hostname_auth = 1; + } + + time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4)); + lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len); + + /* if all the netids in the ignore_name list are present, ignore client-supplied name */ + if (!hostname_auth) + { + for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next) + if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0)) + break; + if (id_list) + hostname = NULL; + } + + /* Last ditch, if configured, generate hostname from mac address */ + if (!hostname && emac_len != 0) + { + for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next) + if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0)) + break; + if (id_list) + { + int i; + + hostname = daemon->dhcp_buff; + /* buffer is 256 bytes, 3 bytes per octet */ + for (i = 0; (i < emac_len) && (i < 80); i++) + hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-"); + hostname = daemon->dhcp_buff; + } + } + + if (hostname) + lease_set_hostname(lease, hostname, hostname_auth); + + lease_set_expires(lease, time, now); + lease_set_interface(lease, int_index); + + if (override.s_addr != 0) + lease->override = override; + else + override = lease->override; + + log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, mess->xid); + emit_dbus_signal(ACTION_CONNECT, lease, hostname); + + clear_packet(mess, end); + option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK); + option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr)); + option_put(mess, end, OPTION_LEASE_TIME, 4, time); + if (time != 0xffffffff) + { + while (fuzz > (time/16)) + fuzz = fuzz/2; + option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz); + option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz); + } + do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr), + domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len); + } + + return dhcp_packet_size(mess, tagif_netid, agent_id, real_end); + + case DHCPINFORM: + if (ignore || have_config(config, CONFIG_DISABLE)) + message = _("ignored"); + + log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, mess->xid); + + if (message || mess->ciaddr.s_addr == 0) + return 0; + + /* For DHCPINFORM only, cope without a valid context */ + context = narrow_context(context, mess->ciaddr, tagif_netid); + + /* Find a least based on IP address if we didn't + get one from MAC address/client-d */ + if (!lease && + (lease = lease_find_by_addr(mess->ciaddr)) && + lease->hostname) + hostname = lease->hostname; + + if (!hostname && (hostname = host_from_dns(mess->ciaddr))) + domain = get_domain(mess->ciaddr); + + log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid); + + if (context && context->netid.net) + { + context->netid.next = netid; + netid = &context->netid; + tagif_netid = run_tag_if(netid); + } + + if (lease) + { + if (override.s_addr != 0) + lease->override = override; + else + override = lease->override; + } + + clear_packet(mess, end); + option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK); + option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr)); + + if (lease) + { + if (lease->expires == 0) + time = 0xffffffff; + else + time = (unsigned int)difftime(lease->expires, now); + option_put(mess, end, OPTION_LEASE_TIME, 4, time); + lease_set_interface(lease, int_index); + } + + do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr), + domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len); + + *is_inform = 1; /* handle reply differently */ + return dhcp_packet_size(mess, tagif_netid, agent_id, real_end); + } + + return 0; +} + +static int match_bytes(struct dhcp_opt *o, unsigned char *p, int len) +{ + int i; + + if (o->len > len) + return 0; + + if (o->len == 0) + return 1; + + if (o->flags & DHOPT_HEX) + { + if (memcmp_masked(o->val, p, o->len, o->u.wildcard_mask)) + return 1; + } + else + for (i = 0; i <= (len - o->len); ) + { + if (memcmp(o->val, p + i, o->len) == 0) + return 1; + + if (o->flags & DHOPT_STRING) + i++; + else + i += o->len; + } + + return 0; +} + + +/* find a good value to use as MAC address for logging and address-allocation hashing. + This is normally just the chaddr field from the DHCP packet, + but eg Firewire will have hlen == 0 and use the client-id instead. + This could be anything, but will normally be EUI64 for Firewire. + We assume that if the first byte of the client-id equals the htype byte + then the client-id is using the usual encoding and use the rest of the + client-id: if not we can use the whole client-id. This should give + sane MAC address logs. */ +unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, + int clid_len, unsigned char *clid, int *len_out) +{ + if (hwlen == 0 && clid && clid_len > 3) + { + if (clid[0] == hwtype) + { + *len_out = clid_len - 1 ; + return clid + 1; + } + +#if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394) + if (clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394) + { + *len_out = clid_len - 1 ; + return clid + 1; + } +#endif + + *len_out = clid_len; + return clid; + } + + *len_out = hwlen; + return hwaddr; +} + +static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt) +{ + unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time; + + if (opt) + { + unsigned int req_time = option_uint(opt, 0, 4); + if (req_time < 120 ) + req_time = 120; /* sanity */ + if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time)) + time = req_time; + } + + return time; +} + +static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback) +{ + if (override.s_addr != 0) + return override; + else if (context) + return context->local; + else + return fallback; +} + +static int sanitise(unsigned char *opt, char *buf) +{ + char *p; + int i; + + *buf = 0; + + if (!opt) + return 0; + + p = option_ptr(opt, 0); + + for (i = option_len(opt); i > 0; i--) + { + char c = *p++; + if (isprint((int)c)) + *buf++ = c; + } + *buf = 0; /* add terminator */ + + return 1; +} + +#ifdef HAVE_SCRIPT +static void add_extradata_data(struct dhcp_lease *lease, unsigned char *data, size_t len, int delim) +{ + if ((lease->extradata_size - lease->extradata_len) < (len + 1)) + { + size_t newsz = lease->extradata_len + len + 100; + unsigned char *new = whine_malloc(newsz); + + if (!new) + return; + + if (lease->extradata) + { + memcpy(new, lease->extradata, lease->extradata_len); + free(lease->extradata); + } + + lease->extradata = new; + lease->extradata_size = newsz; + } + + if (len != 0) + memcpy(lease->extradata + lease->extradata_len, data, len); + lease->extradata[lease->extradata_len + len] = delim; + lease->extradata_len += len + 1; +} + +static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt) +{ + if (!opt) + add_extradata_data(lease, NULL, 0, 0); + else + { + size_t i, len = option_len(opt); + unsigned char *ucp = option_ptr(opt, 0); + + /* check for embeded NULLs */ + for (i = 0; i < len; i++) + if (ucp[i] == 0) + { + len = i; + break; + } + + add_extradata_data(lease, ucp, len, 0); + } +} +#endif + +static void log_packet(char *type, void *addr, unsigned char *ext_mac, + int mac_len, char *interface, char *string, u32 xid) +{ + struct in_addr a; + + /* addr may be misaligned */ + if (addr) + memcpy(&a, addr, sizeof(a)); + + print_mac(daemon->namebuff, ext_mac, mac_len); + + if(option_bool(OPT_LOG_OPTS)) + my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s", + ntohl(xid), + type, + interface, + addr ? inet_ntoa(a) : "", + addr ? " " : "", + daemon->namebuff, + string ? string : ""); + else + my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s", + type, + interface, + addr ? inet_ntoa(a) : "", + addr ? " " : "", + daemon->namebuff, + string ? string : ""); +} + +static void log_options(unsigned char *start, u32 xid) +{ + while (*start != OPTION_END) + { + int is_ip, is_name, i; + char *text = option_string(start[0], &is_ip, &is_name); + unsigned char trunc = option_len(start); + + if (is_ip) + for (daemon->namebuff[0]= 0, i = 0; i <= trunc - INADDRSZ; i += INADDRSZ) + { + if (i != 0) + strncat(daemon->namebuff, ", ", 256 - strlen(daemon->namebuff)); + strncat(daemon->namebuff, inet_ntoa(option_addr_arr(start, i)), 256 - strlen(daemon->namebuff)); + } + else if (!is_name || !sanitise(start, daemon->namebuff)) + { + if (trunc > 13) + trunc = 13; + print_mac(daemon->namebuff, option_ptr(start, 0), trunc); + } + + my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d%s%s%s%s%s", + ntohl(xid), option_len(start), start[0], + text ? ":" : "", text ? text : "", + trunc == 0 ? "" : " ", + trunc == 0 ? "" : daemon->namebuff, + trunc == option_len(start) ? "" : "..."); + start += start[1] + 2; + } +} + +static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize) +{ + while (1) + { + if (p > end) + return NULL; + else if (*p == OPTION_END) + return opt == OPTION_END ? p : NULL; + else if (*p == OPTION_PAD) + p++; + else + { + int opt_len; + if (p > end - 2) + return NULL; /* malformed packet */ + opt_len = option_len(p); + if (p > end - (2 + opt_len)) + return NULL; /* malformed packet */ + if (*p == opt && opt_len >= minsize) + return p; + p += opt_len + 2; + } + } +} + +static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize) +{ + unsigned char *ret, *overload; + + /* skip over DHCP cookie; */ + if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize))) + return ret; + + /* look for overload option. */ + if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1))) + return NULL; + + /* Can we look in filename area ? */ + if ((overload[2] & 1) && + (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize))) + return ret; + + /* finally try sname area */ + if ((overload[2] & 2) && + (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize))) + return ret; + + return NULL; +} + +static struct in_addr option_addr_arr(unsigned char *opt, int offset) +{ + /* this worries about unaligned data in the option. */ + /* struct in_addr is network byte order */ + struct in_addr ret; + + memcpy(&ret, option_ptr(opt, offset), INADDRSZ); + + return ret; +} + +static struct in_addr option_addr(unsigned char *opt) +{ + return option_addr_arr(opt, 0); +} + +static unsigned int option_uint(unsigned char *opt, int offset, int size) +{ + /* this worries about unaligned data and byte order */ + unsigned int ret = 0; + int i; + unsigned char *p = option_ptr(opt, offset); + + for (i = 0; i < size; i++) + ret = (ret << 8) | *p++; + + return ret; +} + +static unsigned char *dhcp_skip_opts(unsigned char *start) +{ + while (*start != 0) + start += start[1] + 2; + return start; +} + +/* only for use when building packet: doesn't check for bad data. */ +static unsigned char *find_overload(struct dhcp_packet *mess) +{ + unsigned char *p = &mess->options[0] + sizeof(u32); + + while (*p != 0) + { + if (*p == OPTION_OVERLOAD) + return p; + p += p[1] + 2; + } + return NULL; +} + +static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *netid, + unsigned char *agent_id, unsigned char *real_end) +{ + unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32)); + unsigned char *overload; + size_t ret; + struct dhcp_netid_list *id_list; + struct dhcp_netid *n; + + /* move agent_id back down to the end of the packet */ + if (agent_id) + { + memmove(p, agent_id, real_end - agent_id); + p += real_end - agent_id; + memset(p, 0, real_end - p); /* in case of overlap */ + } + + /* We do logging too */ + if (netid && option_bool(OPT_LOG_OPTS)) + { + char *s = daemon->namebuff; + for (*s = 0; netid; netid = netid->next) + { + /* kill dupes. */ + for (n = netid->next; n; n = n->next) + if (strcmp(netid->net, n->net) == 0) + break; + + if (!n) + { + strncat (s, netid->net, (MAXDNAME-1) - strlen(s)); + if (netid->next) + strncat (s, ", ", (MAXDNAME-1) - strlen(s)); + } + } + my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), ntohl(mess->xid), s); + } + + /* add END options to the regions. */ + overload = find_overload(mess); + + if (overload && (option_uint(overload, 0, 1) & 1)) + { + *dhcp_skip_opts(mess->file) = OPTION_END; + if (option_bool(OPT_LOG_OPTS)) + log_options(mess->file, mess->xid); + } + else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0) + my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file); + + if (overload && (option_uint(overload, 0, 1) & 2)) + { + *dhcp_skip_opts(mess->sname) = OPTION_END; + if (option_bool(OPT_LOG_OPTS)) + log_options(mess->sname, mess->xid); + } + else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0) + my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname); + + + *p++ = OPTION_END; + + for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next) + if ((!id_list->list) || match_netid(id_list->list, netid, 0)) + break; + if (id_list) + mess->flags |= htons(0x8000); /* force broadcast */ + + if (option_bool(OPT_LOG_OPTS)) + { + if (mess->siaddr.s_addr != 0) + my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr)); + + if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0) + my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid)); + + log_options(&mess->options[0] + sizeof(u32), mess->xid); + } + + ret = (size_t)(p - (unsigned char *)mess); + + if (ret < MIN_PACKETSZ) + ret = MIN_PACKETSZ; + + return ret; +} + +static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len) +{ + unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32)); + + if (p + len + 3 >= end) + /* not enough space in options area, try and use overload, if poss */ + { + unsigned char *overload; + + if (!(overload = find_overload(mess)) && + (mess->file[0] == 0 || mess->sname[0] == 0)) + { + /* attempt to overload fname and sname areas, we've reserved space for the + overflow option previuously. */ + overload = p; + *(p++) = OPTION_OVERLOAD; + *(p++) = 1; + } + + p = NULL; + + /* using filename field ? */ + if (overload) + { + if (mess->file[0] == 0) + overload[2] |= 1; + + if (overload[2] & 1) + { + p = dhcp_skip_opts(mess->file); + if (p + len + 3 >= mess->file + sizeof(mess->file)) + p = NULL; + } + + if (!p) + { + /* try to bring sname into play (it may be already) */ + if (mess->sname[0] == 0) + overload[2] |= 2; + + if (overload[2] & 2) + { + p = dhcp_skip_opts(mess->sname); + if (p + len + 3 >= mess->sname + sizeof(mess->file)) + p = NULL; + } + } + } + + if (!p) + my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt); + } + + if (p) + { + *(p++) = opt; + *(p++) = len; + } + + return p; +} + +static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val) +{ + int i; + unsigned char *p = free_space(mess, end, opt, len); + + if (p) + for (i = 0; i < len; i++) + *(p++) = val >> (8 * (len - (i + 1))); +} + +static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt, + char *string, int null_term) +{ + unsigned char *p; + size_t len = strlen(string); + + if (null_term && len != 255) + len++; + + if ((p = free_space(mess, end, opt, len))) + memcpy(p, string, len); +} + +/* return length, note this only does the data part */ +static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term) +{ + int len = opt->len; + + if ((opt->flags & DHOPT_STRING) && null_term && len != 255) + len++; + + if (p && len != 0) + { + if (context && (opt->flags & DHOPT_ADDR)) + { + int j; + struct in_addr *a = (struct in_addr *)opt->val; + for (j = 0; j < opt->len; j+=INADDRSZ, a++) + { + /* zero means "self" (but not in vendorclass options.) */ + if (a->s_addr == 0) + memcpy(p, &context->local, INADDRSZ); + else + memcpy(p, a, INADDRSZ); + p += INADDRSZ; + } + } + else + memcpy(p, opt->val, len); + } + return len; +} + +static int in_list(unsigned char *list, int opt) +{ + int i; + + /* If no requested options, send everything, not nothing. */ + if (!list) + return 1; + + for (i = 0; list[i] != OPTION_END; i++) + if (opt == list[i]) + return 1; + + return 0; +} + +static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *opts, int opt) +{ + struct dhcp_opt *tmp; + for (tmp = opts; tmp; tmp = tmp->next) + if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925))) + if (match_netid(tmp->netid, netid, 0)) + return tmp; + + /* No match, look for one without a netid */ + for (tmp = opts; tmp; tmp = tmp->next) + if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925))) + if (match_netid(tmp->netid, netid, 1)) + return tmp; + + return NULL; +} + +/* mark vendor-encapsulated options which match the client-supplied or + config-supplied vendor class */ +static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt) +{ + for (; dopt; dopt = dopt->next) + { + dopt->flags &= ~DHOPT_VENDOR_MATCH; + if (opt && (dopt->flags & DHOPT_VENDOR)) + { + int i, len = 0; + if (dopt->u.vendor_class) + len = strlen((char *)dopt->u.vendor_class); + for (i = 0; i <= (option_len(opt) - len); i++) + if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0) + { + dopt->flags |= DHOPT_VENDOR_MATCH; + break; + } + } + } +} + +static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, + struct dhcp_packet *mess, unsigned char *end, int null_term) +{ + int len, enc_len, ret = 0; + struct dhcp_opt *start; + unsigned char *p; + + /* find size in advance */ + for (enc_len = 0, start = opt; opt; opt = opt->next) + if (opt->flags & flag) + { + int new = do_opt(opt, NULL, NULL, null_term) + 2; + ret = 1; + if (enc_len + new <= 255) + enc_len += new; + else + { + p = free_space(mess, end, encap, enc_len); + for (; start && start != opt; start = start->next) + if (p && (start->flags & flag)) + { + len = do_opt(start, p + 2, NULL, null_term); + *(p++) = start->opt; + *(p++) = len; + p += len; + } + enc_len = new; + start = opt; + } + } + + if (enc_len != 0 && + (p = free_space(mess, end, encap, enc_len + 1))) + { + for (; start; start = start->next) + if (start->flags & flag) + { + len = do_opt(start, p + 2, NULL, null_term); + *(p++) = start->opt; + *(p++) = len; + p += len; + } + *p = OPTION_END; + } + + return ret; +} + +static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid) +{ + unsigned char *p; + + option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0); + if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17))) + memcpy(p, uuid, 17); +} + +static int prune_vendor_opts(struct dhcp_netid *netid) +{ + int force = 0; + struct dhcp_opt *opt; + + /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */ + for (opt = daemon->dhcp_opts; opt; opt = opt->next) + if (opt->flags & DHOPT_VENDOR_MATCH) + { + if (!match_netid(opt->netid, netid, 1)) + opt->flags &= ~DHOPT_VENDOR_MATCH; + else if (opt->flags & DHOPT_FORCE) + force = 1; + } + return force; +} + +static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local) +{ +#define NUM_OPTS 4 + + unsigned char *p, *q; + struct pxe_service *service; + static struct dhcp_opt *o, *ret; + int i, j = NUM_OPTS - 1; + struct in_addr boot_server; + + /* We pass back references to these, hence they are declared static */ + static unsigned char discovery_control; + static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' }; + static struct dhcp_opt *fake_opts = NULL; + + /* Disable multicast, since we don't support it, and broadcast + unless we need it */ + discovery_control = 3; + + ret = daemon->dhcp_opts; + + if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt)))) + return ret; + + for (i = 0; i < NUM_OPTS; i++) + { + fake_opts[i].flags = DHOPT_VENDOR_MATCH; + fake_opts[i].netid = NULL; + fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1]; + } + + /* create the data for the PXE_MENU and PXE_SERVERS options. */ + p = (unsigned char *)daemon->dhcp_buff; + q = (unsigned char *)daemon->dhcp_buff3; + + for (i = 0, service = daemon->pxe_services; service; service = service->next) + if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1)) + { + size_t len = strlen(service->menu); + /* opt 43 max size is 255. encapsulated option has type and length + bytes, so its max size is 253. */ + if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253) + { + *(p++) = service->type >> 8; + *(p++) = service->type; + *(p++) = len; + memcpy(p, service->menu, len); + p += len; + i++; + } + else + { + toobig: + my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large")); + return daemon->dhcp_opts; + } + + boot_server = service->basename ? local : service->server; + + if (boot_server.s_addr != 0) + { + if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253) + goto toobig; + + /* Boot service with known address - give it */ + *(q++) = service->type >> 8; + *(q++) = service->type; + *(q++) = 1; + /* dest misaligned */ + memcpy(q, &boot_server.s_addr, INADDRSZ); + q += INADDRSZ; + } + else if (service->type != 0) + /* We don't know the server for a service type, so we'll + allow the client to broadcast for it */ + discovery_control = 2; + } + + /* if no prompt, wait forever if there's a choice */ + fake_prompt[0] = (i > 1) ? 255 : 0; + + if (i == 0) + discovery_control = 8; /* no menu - just use use mess->filename */ + else + { + ret = &fake_opts[j--]; + ret->len = p - (unsigned char *)daemon->dhcp_buff; + ret->val = (unsigned char *)daemon->dhcp_buff; + ret->opt = SUBOPT_PXE_MENU; + + if (q - (unsigned char *)daemon->dhcp_buff3 != 0) + { + ret = &fake_opts[j--]; + ret->len = q - (unsigned char *)daemon->dhcp_buff3; + ret->val = (unsigned char *)daemon->dhcp_buff3; + ret->opt = SUBOPT_PXE_SERVERS; + } + } + + for (o = daemon->dhcp_opts; o; o = o->next) + if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT) + break; + + if (!o) + { + ret = &fake_opts[j--]; + ret->len = sizeof(fake_prompt); + ret->val = fake_prompt; + ret->opt = SUBOPT_PXE_MENU_PROMPT; + } + + ret = &fake_opts[j--]; + ret->len = 1; + ret->opt = SUBOPT_PXE_DISCOVERY; + ret->val= &discovery_control; + + return ret; +} + +static void clear_packet(struct dhcp_packet *mess, unsigned char *end) +{ + memset(mess->sname, 0, sizeof(mess->sname)); + memset(mess->file, 0, sizeof(mess->file)); + memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32))); + mess->siaddr.s_addr = 0; +} + +struct dhcp_boot *find_boot(struct dhcp_netid *netid) +{ + struct dhcp_boot *boot; + + /* decide which dhcp-boot option we're using */ + for (boot = daemon->boot_config; boot; boot = boot->next) + if (match_netid(boot->netid, netid, 0)) + break; + if (!boot) + /* No match, look for one without a netid */ + for (boot = daemon->boot_config; boot; boot = boot->next) + if (match_netid(boot->netid, netid, 1)) + break; + + return boot; +} + +static void do_options(struct dhcp_context *context, + struct dhcp_packet *mess, + unsigned char *end, + unsigned char *req_options, + char *hostname, + char *domain, char *config_domain, + struct dhcp_netid *netid, + struct in_addr subnet_addr, + unsigned char fqdn_flags, + int null_term, int pxe_arch, + unsigned char *uuid, + int vendor_class_len) +{ + struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts; + struct dhcp_boot *boot; + unsigned char *p; + int i, len, force_encap = 0; + unsigned char f0 = 0, s0 = 0; + int done_file = 0, done_server = 0; + int done_vendor_class = 0; + + if (config_domain && (!domain || !hostname_isequal(domain, config_domain))) + my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, hostname); + + /* logging */ + if (option_bool(OPT_LOG_OPTS) && req_options) + { + char *q = daemon->namebuff; + for (i = 0; req_options[i] != OPTION_END; i++) + { + char *s = option_string(req_options[i], NULL, NULL); + q += snprintf(q, MAXDNAME - (q - daemon->namebuff), + "%d%s%s%s", + req_options[i], + s ? ":" : "", + s ? s : "", + req_options[i+1] == OPTION_END ? "" : ", "); + if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40) + { + q = daemon->namebuff; + my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff); + } + } + } + + if (context) + mess->siaddr = context->local; + + /* See if we can send the boot stuff as options. + To do this we need a requested option list, BOOTP + and very old DHCP clients won't have this, we also + provide an manual option to disable it. + Some PXE ROMs have bugs (surprise!) and need zero-terminated + names, so we always send those. */ + if ((boot = find_boot(netid))) + { + if (boot->sname) + { + if (!option_bool(OPT_NO_OVERRIDE) && + req_options && + in_list(req_options, OPTION_SNAME)) + option_put_string(mess, end, OPTION_SNAME, boot->sname, 1); + else + strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1); + } + + if (boot->file) + { + if (!option_bool(OPT_NO_OVERRIDE) && + req_options && + in_list(req_options, OPTION_FILENAME)) + option_put_string(mess, end, OPTION_FILENAME, boot->file, 1); + else + strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1); + } + + if (boot->next_server.s_addr) + mess->siaddr = boot->next_server; + } + else + /* Use the values of the relevant options if no dhcp-boot given and + they're not explicitly asked for as options. OPTION_END is used + as an internal way to specify siaddr without using dhcp-boot, for use in + dhcp-optsfile. */ + { + if ((!req_options || !in_list(req_options, OPTION_FILENAME)) && + (opt = option_find2(netid, config_opts, OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE)) + { + strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1); + done_file = 1; + } + + if ((!req_options || !in_list(req_options, OPTION_SNAME)) && + (opt = option_find2(netid, config_opts, OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE)) + { + strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1); + done_server = 1; + } + + if ((opt = option_find2(netid, config_opts, OPTION_END))) + mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr; + } + + /* We don't want to do option-overload for BOOTP, so make the file and sname + fields look like they are in use, even when they aren't. This gets restored + at the end of this function. */ + + if (!req_options || option_bool(OPT_NO_OVERRIDE)) + { + f0 = mess->file[0]; + mess->file[0] = 1; + s0 = mess->sname[0]; + mess->sname[0] = 1; + } + + /* At this point, if mess->sname or mess->file are zeroed, they are available + for option overload, reserve space for the overload option. */ + if (mess->file[0] == 0 || mess->sname[0] == 0) + end -= 3; + + /* rfc3011 says this doesn't need to be in the requested options list. */ + if (subnet_addr.s_addr) + option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr)); + + /* replies to DHCPINFORM may not have a valid context */ + if (context) + { + if (!option_find2(netid, config_opts, OPTION_NETMASK)) + option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr)); + + /* May not have a "guessed" broadcast address if we got no packets via a relay + from this net yet (ie just unicast renewals after a restart */ + if (context->broadcast.s_addr && + !option_find2(netid, config_opts, OPTION_BROADCAST)) + option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr)); + + /* Same comments as broadcast apply, and also may not be able to get a sensible + default when using subnet select. User must configure by steam in that case. */ + if (context->router.s_addr && + in_list(req_options, OPTION_ROUTER) && + !option_find2(netid, config_opts, OPTION_ROUTER)) + option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr)); + + if (in_list(req_options, OPTION_DNSSERVER) && + !option_find2(netid, config_opts, OPTION_DNSSERVER)) + option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr)); + } + + if (domain && in_list(req_options, OPTION_DOMAINNAME) && + !option_find2(netid, config_opts, OPTION_DOMAINNAME)) + option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term); + + /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */ + if (hostname) + { + if (in_list(req_options, OPTION_HOSTNAME) && + !option_find2(netid, config_opts, OPTION_HOSTNAME)) + option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term); + + if (fqdn_flags != 0) + { + len = strlen(hostname) + 3; + + if (fqdn_flags & 0x04) + len += 2; + else if (null_term) + len++; + + if (domain) + len += strlen(domain) + 1; + + if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len))) + { + *(p++) = fqdn_flags; + *(p++) = 255; + *(p++) = 255; + + if (fqdn_flags & 0x04) + { + p = do_rfc1035_name(p, hostname); + if (domain) + p = do_rfc1035_name(p, domain); + *p++ = 0; + } + else + { + memcpy(p, hostname, strlen(hostname)); + p += strlen(hostname); + if (domain) + { + *(p++) = '.'; + memcpy(p, domain, strlen(domain)); + p += strlen(domain); + } + if (null_term) + *(p++) = 0; + } + } + } + } + + for (opt = config_opts; opt; opt = opt->next) + { + int optno = opt->opt; + + /* was it asked for, or are we sending it anyway? */ + if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno)) + continue; + + /* prohibit some used-internally options */ + if (optno == OPTION_CLIENT_FQDN || + optno == OPTION_MAXMESSAGE || + optno == OPTION_OVERLOAD || + optno == OPTION_PAD || + optno == OPTION_END) + continue; + + if (optno == OPTION_SNAME && done_server) + continue; + + if (optno == OPTION_FILENAME && done_file) + continue; + + /* netids match and not encapsulated? */ + if (opt != option_find2(netid, config_opts, optno)) + continue; + + /* For the options we have default values on + dhc-option=<optionno> means "don't include this option" + not "include a zero-length option" */ + if (opt->len == 0 && + (optno == OPTION_NETMASK || + optno == OPTION_BROADCAST || + optno == OPTION_ROUTER || + optno == OPTION_DNSSERVER || + optno == OPTION_DOMAINNAME || + optno == OPTION_HOSTNAME)) + continue; + + /* vendor-class comes from elsewhere for PXE */ + if (pxe_arch != -1 && optno == OPTION_VENDOR_ID) + continue; + + /* always force null-term for filename and servername - buggy PXE again. */ + len = do_opt(opt, NULL, context, + (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term); + + if ((p = free_space(mess, end, optno, len))) + { + do_opt(opt, p, context, + (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term); + + /* If we send a vendor-id, revisit which vendor-ops we consider + it appropriate to send. */ + if (optno == OPTION_VENDOR_ID) + { + match_vendor_opts(p - 2, config_opts); + done_vendor_class = 1; + } + } + } + + /* Now send options to be encapsulated in arbitrary options, + eg dhcp-option=encap:172,17,....... + Also hand vendor-identifying vendor-encapsulated options, + dhcp-option = rfc3925-encap:13,17,....... + The may be more that one "outer" to do, so group + all the options which match each outer in turn. */ + for (opt = config_opts; opt; opt = opt->next) + opt->flags &= ~DHOPT_ENCAP_DONE; + + for (opt = config_opts; opt; opt = opt->next) + { + int flags; + + if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925)))) + { + int found = 0; + struct dhcp_opt *o; + + if (opt->flags & DHOPT_ENCAP_DONE) + continue; + + for (len = 0, o = config_opts; o; o = o->next) + { + int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT; + + o->flags &= ~DHOPT_ENCAP_MATCH; + + if (!(o->flags & flags) || opt->u.encap != o->u.encap) + continue; + + o->flags |= DHOPT_ENCAP_DONE; + if (match_netid(o->netid, netid, 1) && + ((o->flags & DHOPT_FORCE) || in_list(req_options, outer))) + { + o->flags |= DHOPT_ENCAP_MATCH; + found = 1; + len += do_opt(o, NULL, NULL, 0) + 2; + } + } + + if (found) + { + if (flags & DHOPT_ENCAPSULATE) + do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term); + else if (len > 250) + my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap); + else if ((p = free_space(mess, end, OPTION_VENDOR_IDENT_OPT, len + 5))) + { + int swap_ent = htonl(opt->u.encap); + memcpy(p, &swap_ent, 4); + p += 4; + *(p++) = len; + for (o = config_opts; o; o = o->next) + if (o->flags & DHOPT_ENCAP_MATCH) + { + len = do_opt(o, p + 2, NULL, 0); + *(p++) = o->opt; + *(p++) = len; + p += len; + } + } + } + } + } + + force_encap = prune_vendor_opts(netid); + + if (context && pxe_arch != -1) + { + pxe_misc(mess, end, uuid); + config_opts = pxe_opts(pxe_arch, netid, context->local); + } + + if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) && + do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) && + pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 && + (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len))) + /* If we send vendor encapsulated options, and haven't already sent option 60, + echo back the value we got from the client. */ + memcpy(p, daemon->dhcp_buff3, vendor_class_len); + + /* restore BOOTP anti-overload hack */ + if (!req_options || option_bool(OPT_NO_OVERRIDE)) + { + mess->file[0] = f0; + mess->sname[0] = s0; + } +} + +#endif + + + + + + + diff --git a/src/tftp.c b/src/tftp.c new file mode 100644 index 0000000..789c444 --- /dev/null +++ b/src/tftp.c @@ -0,0 +1,711 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dnsmasq.h" + +#ifdef HAVE_TFTP + +static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special); +static void free_transfer(struct tftp_transfer *transfer); +static ssize_t tftp_err(int err, char *packet, char *mess, char *file); +static ssize_t tftp_err_oops(char *packet, char *file); +static ssize_t get_block(char *packet, struct tftp_transfer *transfer); +static char *next(char **p, char *end); + +#define OP_RRQ 1 +#define OP_WRQ 2 +#define OP_DATA 3 +#define OP_ACK 4 +#define OP_ERR 5 +#define OP_OACK 6 + +#define ERR_NOTDEF 0 +#define ERR_FNF 1 +#define ERR_PERM 2 +#define ERR_FULL 3 +#define ERR_ILL 4 + +void tftp_request(struct listener *listen, time_t now) +{ + ssize_t len; + char *packet = daemon->packet; + char *filename, *mode, *p, *end, *opt; + union mysockaddr addr, peer; + struct msghdr msg; + struct iovec iov; + struct ifreq ifr; + int is_err = 1, if_index = 0, mtu = 0, special = 0; +#ifdef HAVE_DHCP + struct iname *tmp; +#endif + struct tftp_transfer *transfer; + int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */ +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) + int mtuflag = IP_PMTUDISC_DONT; +#endif + char namebuff[IF_NAMESIZE]; + char pretty_addr[ADDRSTRLEN]; + char *name; + char *prefix = daemon->tftp_prefix; + struct tftp_prefix *pref; + struct interface_list *ir; + + union { + struct cmsghdr align; /* this ensures alignment */ +#ifdef HAVE_IPV6 + char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +#endif +#if defined(HAVE_LINUX_NETWORK) + char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; +#elif defined(HAVE_SOLARIS_NETWORK) + char control[CMSG_SPACE(sizeof(unsigned int))]; +#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) + char control[CMSG_SPACE(sizeof(struct sockaddr_dl))]; +#endif + } control_u; + + msg.msg_controllen = sizeof(control_u); + msg.msg_control = control_u.control; + msg.msg_flags = 0; + msg.msg_name = &peer; + msg.msg_namelen = sizeof(peer); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + iov.iov_base = packet; + iov.iov_len = daemon->packet_buff_sz; + + /* we overwrote the buffer... */ + daemon->srv_save = NULL; + + if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2) + return; + + if (option_bool(OPT_NOWILD)) + { + addr = listen->iface->addr; + mtu = listen->iface->mtu; + name = listen->iface->name; + } + else + { + struct cmsghdr *cmptr; + int check; + struct interface_list *ir; + + if (msg.msg_controllen < sizeof(struct cmsghdr)) + return; + + addr.sa.sa_family = listen->family; + +#if defined(HAVE_LINUX_NETWORK) + if (listen->family == AF_INET) + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) + { + union { + unsigned char *c; + struct in_pktinfo *p; + } p; + p.c = CMSG_DATA(cmptr); + addr.in.sin_addr = p.p->ipi_spec_dst; + if_index = p.p->ipi_ifindex; + } + +#elif defined(HAVE_SOLARIS_NETWORK) + if (listen->family == AF_INET) + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + { + union { + unsigned char *c; + struct in_addr *a; + unsigned int *i; + } p; + p.c = CMSG_DATA(cmptr); + if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) + addr.in.sin_addr = *(p.a); + else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) + if_index = *(p.i); + } + +#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) + if (listen->family == AF_INET) + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + { + union { + unsigned char *c; + struct in_addr *a; + struct sockaddr_dl *s; + } p; + p.c = CMSG_DATA(cmptr); + if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) + addr.in.sin_addr = *(p.a); + else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) + if_index = p.s->sdl_index; + } + +#endif + +#ifdef HAVE_IPV6 + if (listen->family == AF_INET6) + { + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) + if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == daemon->v6pktinfo) + { + union { + unsigned char *c; + struct in6_pktinfo *p; + } p; + p.c = CMSG_DATA(cmptr); + + addr.in6.sin6_addr = p.p->ipi6_addr; + if_index = p.p->ipi6_ifindex; + } + } +#endif + + if (!indextoname(listen->tftpfd, if_index, namebuff)) + return; + + name = namebuff; + +#ifdef HAVE_IPV6 + if (listen->family == AF_INET6) + check = iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name, &if_index); + else +#endif + check = iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name, &if_index); + + /* wierd TFTP service override */ + for (ir = daemon->tftp_interfaces; ir; ir = ir->next) + if (strcmp(ir->interface, name) == 0) + break; + + if (!ir) + { + if (!daemon->tftp_unlimited || !check) + return; + +#ifdef HAVE_DHCP + /* allowed interfaces are the same as for DHCP */ + for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) + if (tmp->name && (strcmp(tmp->name, name) == 0)) + return; +#endif + } + + strncpy(ifr.ifr_name, name, IF_NAMESIZE); + if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1) + mtu = ifr.ifr_mtu; + } + + /* check for per-interface prefix */ + for (pref = daemon->if_prefix; pref; pref = pref->next) + if (strcmp(pref->interface, name) == 0) + prefix = pref->prefix; + + /* wierd TFTP interfaces disable special options. */ + for (ir = daemon->tftp_interfaces; ir; ir = ir->next) + if (strcmp(ir->interface, name) == 0) + special = 1; + +#ifdef HAVE_SOCKADDR_SA_LEN + addr.sa.sa_len = sa_len(&addr); +#endif + + if (listen->family == AF_INET) + addr.in.sin_port = htons(port); +#ifdef HAVE_IPV6 + else + { + addr.in6.sin6_port = htons(port); + addr.in6.sin6_flowinfo = 0; + } +#endif + + if (!(transfer = whine_malloc(sizeof(struct tftp_transfer)))) + return; + + if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1) + { + free(transfer); + return; + } + + transfer->peer = peer; + transfer->timeout = now + 2; + transfer->backoff = 1; + transfer->block = 1; + transfer->blocksize = 512; + transfer->offset = 0; + transfer->file = NULL; + transfer->opt_blocksize = transfer->opt_transize = 0; + transfer->netascii = transfer->carrylf = 0; + + prettyprint_addr(&peer, pretty_addr); + + /* if we have a nailed-down range, iterate until we find a free one. */ + while (1) + { + if (bind(transfer->sockfd, &addr.sa, sizeof(addr)) == -1 || +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) + setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 || +#endif + !fix_fd(transfer->sockfd)) + { + if (errno == EADDRINUSE && daemon->start_tftp_port != 0) + { + if (++port <= daemon->end_tftp_port) + { + if (listen->family == AF_INET) + addr.in.sin_port = htons(port); +#ifdef HAVE_IPV6 + else + addr.in6.sin6_port = htons(port); +#endif + continue; + } + my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP")); + } + free_transfer(transfer); + return; + } + break; + } + + p = packet + 2; + end = packet + len; + + if (ntohs(*((unsigned short *)packet)) != OP_RRQ || + !(filename = next(&p, end)) || + !(mode = next(&p, end)) || + (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0)) + len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), pretty_addr); + else + { + if (strcasecmp(mode, "netascii") == 0) + transfer->netascii = 1; + + while ((opt = next(&p, end))) + { + if (strcasecmp(opt, "blksize") == 0) + { + if ((opt = next(&p, end)) && + (special || !option_bool(OPT_TFTP_NOBLOCK))) + { + transfer->blocksize = atoi(opt); + if (transfer->blocksize < 1) + transfer->blocksize = 1; + if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4) + transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4; + /* 32 bytes for IP, UDP and TFTP headers */ + if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32) + transfer->blocksize = (unsigned)mtu - 32; + transfer->opt_blocksize = 1; + transfer->block = 0; + } + } + else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii) + { + transfer->opt_transize = 1; + transfer->block = 0; + } + } + + /* cope with backslashes from windows boxen. */ + while ((p = strchr(filename, '\\'))) + *p = '/'; + + strcpy(daemon->namebuff, "/"); + if (prefix) + { + if (prefix[0] == '/') + daemon->namebuff[0] = 0; + strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff)); + if (prefix[strlen(prefix)-1] != '/') + strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff)); + + if (!special && option_bool(OPT_TFTP_APREF)) + { + size_t oldlen = strlen(daemon->namebuff); + struct stat statbuf; + + strncat(daemon->namebuff, pretty_addr, (MAXDNAME-1) - strlen(daemon->namebuff)); + strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff)); + + /* remove unique-directory if it doesn't exist */ + if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode)) + daemon->namebuff[oldlen] = 0; + } + + /* Absolute pathnames OK if they match prefix */ + if (filename[0] == '/') + { + if (strstr(filename, daemon->namebuff) == filename) + daemon->namebuff[0] = 0; + else + filename++; + } + } + else if (filename[0] == '/') + daemon->namebuff[0] = 0; + strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff)); + + /* check permissions and open file */ + if ((transfer->file = check_tftp_fileperm(&len, prefix, special))) + { + if ((len = get_block(packet, transfer)) == -1) + len = tftp_err_oops(packet, daemon->namebuff); + else + is_err = 0; + } + } + + while (sendto(transfer->sockfd, packet, len, 0, + (struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR); + + if (is_err) + free_transfer(transfer); + else + { + transfer->next = daemon->tftp_trans; + daemon->tftp_trans = transfer; + } +} + +static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special) +{ + char *packet = daemon->packet, *namebuff = daemon->namebuff; + struct tftp_file *file; + struct tftp_transfer *t; + uid_t uid = geteuid(); + struct stat statbuf; + int fd = -1; + + /* trick to ban moving out of the subtree */ + if (prefix && strstr(namebuff, "/../")) + goto perm; + + if ((fd = open(namebuff, O_RDONLY)) == -1) + { + if (errno == ENOENT) + { + *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff); + return NULL; + } + else if (errno == EACCES) + goto perm; + else + goto oops; + } + + /* stat the file descriptor to avoid stat->open races */ + if (fstat(fd, &statbuf) == -1) + goto oops; + + /* running as root, must be world-readable */ + if (uid == 0) + { + if (!(statbuf.st_mode & S_IROTH)) + goto perm; + } + /* in secure mode, must be owned by user running dnsmasq */ + else if (!special && option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid) + goto perm; + + /* If we're doing many tranfers from the same file, only + open it once this saves lots of file descriptors + when mass-booting a big cluster, for instance. + Be conservative and only share when inode and name match + this keeps error messages sane. */ + for (t = daemon->tftp_trans; t; t = t->next) + if (t->file->dev == statbuf.st_dev && + t->file->inode == statbuf.st_ino && + strcmp(t->file->filename, namebuff) == 0) + { + close(fd); + t->file->refcount++; + return t->file; + } + + if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1))) + { + errno = ENOMEM; + goto oops; + } + + file->fd = fd; + file->size = statbuf.st_size; + file->dev = statbuf.st_dev; + file->inode = statbuf.st_ino; + file->refcount = 1; + strcpy(file->filename, namebuff); + return file; + + perm: + errno = EACCES; + *len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff); + if (fd != -1) + close(fd); + return NULL; + + oops: + *len = tftp_err_oops(packet, namebuff); + if (fd != -1) + close(fd); + return NULL; +} + +void check_tftp_listeners(fd_set *rset, time_t now) +{ + struct tftp_transfer *transfer, *tmp, **up; + ssize_t len; + char pretty_addr[ADDRSTRLEN]; + + struct ack { + unsigned short op, block; + } *mess = (struct ack *)daemon->packet; + + /* Check for activity on any existing transfers */ + for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp) + { + tmp = transfer->next; + + if (FD_ISSET(transfer->sockfd, rset)) + { + /* we overwrote the buffer... */ + daemon->srv_save = NULL; + + prettyprint_addr(&transfer->peer, pretty_addr); + + if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack)) + { + if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block) + { + /* Got ack, ensure we take the (re)transmit path */ + transfer->timeout = now; + transfer->backoff = 0; + if (transfer->block++ != 0) + transfer->offset += transfer->blocksize - transfer->expansion; + } + else if (ntohs(mess->op) == OP_ERR) + { + char *p = daemon->packet + sizeof(struct ack); + char *end = daemon->packet + len; + char *err = next(&p, end); + + /* Sanitise error message */ + if (!err) + err = ""; + else + { + unsigned char *q, *r; + for (q = r = (unsigned char *)err; *r; r++) + if (isprint(*r)) + *(q++) = *r; + *q = 0; + } + + my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"), + (int)ntohs(mess->block), err, + pretty_addr); + + /* Got err, ensure we take abort */ + transfer->timeout = now; + transfer->backoff = 100; + } + } + } + + if (difftime(now, transfer->timeout) >= 0.0) + { + int endcon = 0; + + /* timeout, retransmit */ + transfer->timeout += 1 + (1<<transfer->backoff); + + /* we overwrote the buffer... */ + daemon->srv_save = NULL; + + if ((len = get_block(daemon->packet, transfer)) == -1) + { + len = tftp_err_oops(daemon->packet, transfer->file->filename); + endcon = 1; + } + else if (++transfer->backoff > 5) + { + /* don't complain about timeout when we're awaiting the last + ACK, some clients never send it */ + if (len != 0) + { + my_syslog(MS_TFTP | LOG_ERR, _("failed sending %s to %s"), + transfer->file->filename, pretty_addr); + len = 0; + endcon = 1; + } + } + + if (len != 0) + while(sendto(transfer->sockfd, daemon->packet, len, 0, + (struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR); + + if (endcon || len == 0) + { + if (!endcon) + my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, pretty_addr); + /* unlink */ + *up = tmp; + free_transfer(transfer); + continue; + } + } + + up = &transfer->next; + } +} + +static void free_transfer(struct tftp_transfer *transfer) +{ + close(transfer->sockfd); + if (transfer->file && (--transfer->file->refcount) == 0) + { + close(transfer->file->fd); + free(transfer->file); + } + free(transfer); +} + +static char *next(char **p, char *end) +{ + char *ret = *p; + size_t len; + + if (*(end-1) != 0 || + *p == end || + (len = strlen(ret)) == 0) + return NULL; + + *p += len + 1; + return ret; +} + +static ssize_t tftp_err(int err, char *packet, char *message, char *file) +{ + struct errmess { + unsigned short op, err; + char message[]; + } *mess = (struct errmess *)packet; + ssize_t ret = 4; + char *errstr = strerror(errno); + + mess->op = htons(OP_ERR); + mess->err = htons(err); + ret += (snprintf(mess->message, 500, message, file, errstr) + 1); + my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message); + + return ret; +} + +static ssize_t tftp_err_oops(char *packet, char *file) +{ + return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file); +} + +/* return -1 for error, zero for done. */ +static ssize_t get_block(char *packet, struct tftp_transfer *transfer) +{ + if (transfer->block == 0) + { + /* send OACK */ + char *p; + struct oackmess { + unsigned short op; + char data[]; + } *mess = (struct oackmess *)packet; + + p = mess->data; + mess->op = htons(OP_OACK); + if (transfer->opt_blocksize) + { + p += (sprintf(p, "blksize") + 1); + p += (sprintf(p, "%d", transfer->blocksize) + 1); + } + if (transfer->opt_transize) + { + p += (sprintf(p,"tsize") + 1); + p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1); + } + + return p - packet; + } + else + { + /* send data packet */ + struct datamess { + unsigned short op, block; + unsigned char data[]; + } *mess = (struct datamess *)packet; + + size_t size = transfer->file->size - transfer->offset; + + if (transfer->offset > transfer->file->size) + return 0; /* finished */ + + if (size > transfer->blocksize) + size = transfer->blocksize; + + mess->op = htons(OP_DATA); + mess->block = htons((unsigned short)(transfer->block)); + + if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 || + !read_write(transfer->file->fd, mess->data, size, 1)) + return -1; + + transfer->expansion = 0; + + /* Map '\n' to CR-LF in netascii mode */ + if (transfer->netascii) + { + size_t i; + int newcarrylf; + + for (i = 0, newcarrylf = 0; i < size; i++) + if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf)) + { + if (size == transfer->blocksize) + { + transfer->expansion++; + if (i == size - 1) + newcarrylf = 1; /* don't expand LF again if it moves to the next block */ + } + else + size++; /* room in this block */ + + /* make space and insert CR */ + memmove(&mess->data[i+1], &mess->data[i], size - (i + 1)); + mess->data[i] = '\r'; + + i++; + } + transfer->carrylf = newcarrylf; + + } + + return size + 4; + } +} + +#endif diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..e64f1a6 --- /dev/null +++ b/src/util.c @@ -0,0 +1,516 @@ +/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991, or + (at your option) version 3 dated 29 June, 2007. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* The SURF random number generator was taken from djbdns-1.05, by + Daniel J Bernstein, which is public domain. */ + + +#include "dnsmasq.h" + +#ifdef HAVE_BROKEN_RTC +#include <sys/times.h> +#endif + +#if defined(LOCALEDIR) || defined(HAVE_IDN) +#include <idna.h> +#endif + +#ifdef HAVE_ARC4RANDOM +void rand_init(void) +{ + return; +} + +unsigned short rand16(void) +{ + return (unsigned short) (arc4random() >> 15); +} + +#else + +/* SURF random number generator */ + +static u32 seed[32]; +static u32 in[12]; +static u32 out[8]; + +void rand_init() +{ + int fd = open(RANDFILE, O_RDONLY); + + if (fd == -1 || + !read_write(fd, (unsigned char *)&seed, sizeof(seed), 1) || + !read_write(fd, (unsigned char *)&in, sizeof(in), 1)) + die(_("failed to seed the random number generator: %s"), NULL, EC_MISC); + + close(fd); +} + +#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b)))) +#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b)); + +static void surf(void) +{ + u32 t[12]; u32 x; u32 sum = 0; + int r; int i; int loop; + + for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i]; + for (i = 0;i < 8;++i) out[i] = seed[24 + i]; + x = t[11]; + for (loop = 0;loop < 2;++loop) { + for (r = 0;r < 16;++r) { + sum += 0x9e3779b9; + MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13) + MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13) + MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13) + } + for (i = 0;i < 8;++i) out[i] ^= t[i + 4]; + } +} + +unsigned short rand16(void) +{ + static int outleft = 0; + + if (!outleft) { + if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3]; + surf(); + outleft = 8; + } + + return (unsigned short) out[--outleft]; +} + +#endif + +static int check_name(char *in) +{ + /* remove trailing . + also fail empty string and label > 63 chars */ + size_t dotgap = 0, l = strlen(in); + char c; + int nowhite = 0; + + if (l == 0 || l > MAXDNAME) return 0; + + if (in[l-1] == '.') + { + if (l == 1) return 0; + in[l-1] = 0; + } + + for (; (c = *in); in++) + { + if (c == '.') + dotgap = 0; + else if (++dotgap > MAXLABEL) + return 0; + else if (isascii((unsigned char)c) && iscntrl((unsigned char)c)) + /* iscntrl only gives expected results for ascii */ + return 0; +#if !defined(LOCALEDIR) && !defined(HAVE_IDN) + else if (!isascii((unsigned char)c)) + return 0; +#endif + else if (c != ' ') + nowhite = 1; + } + + if (!nowhite) + return 0; + + return 1; +} + +/* Hostnames have a more limited valid charset than domain names + so check for legal char a-z A-Z 0-9 - _ + Note that this may receive a FQDN, so only check the first label + for the tighter criteria. */ +int legal_hostname(char *name) +{ + char c; + + if (!check_name(name)) + return 0; + + for (; (c = *name); name++) + /* check for legal char a-z A-Z 0-9 - _ . */ + { + if ((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '-' || c == '_') + continue; + + /* end of hostname part */ + if (c == '.') + return 1; + + return 0; + } + + return 1; +} + +char *canonicalise(char *in, int *nomem) +{ + char *ret = NULL; +#if defined(LOCALEDIR) || defined(HAVE_IDN) + int rc; +#endif + + if (nomem) + *nomem = 0; + + if (!check_name(in)) + return NULL; + +#if defined(LOCALEDIR) || defined(HAVE_IDN) + if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS) + { + if (ret) + free(ret); + + if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR)) + { + my_syslog(LOG_ERR, _("failed to allocate memory")); + *nomem = 1; + } + + return NULL; + } +#else + if ((ret = whine_malloc(strlen(in)+1))) + strcpy(ret, in); + else if (nomem) + *nomem = 1; +#endif + + return ret; +} + +unsigned char *do_rfc1035_name(unsigned char *p, char *sval) +{ + int j; + + while (sval && *sval) + { + unsigned char *cp = p++; + for (j = 0; *sval && (*sval != '.'); sval++, j++) + *p++ = *sval; + *cp = j; + if (*sval) + sval++; + } + return p; +} + +/* for use during startup */ +void *safe_malloc(size_t size) +{ + void *ret = malloc(size); + + if (!ret) + die(_("could not get memory"), NULL, EC_NOMEM); + + return ret; +} + +void safe_pipe(int *fd, int read_noblock) +{ + if (pipe(fd) == -1 || + !fix_fd(fd[1]) || + (read_noblock && !fix_fd(fd[0]))) + die(_("cannot create pipe: %s"), NULL, EC_MISC); +} + +void *whine_malloc(size_t size) +{ + void *ret = malloc(size); + + if (!ret) + my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size); + + return ret; +} + +int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2) +{ + if (s1->sa.sa_family == s2->sa.sa_family) + { + if (s1->sa.sa_family == AF_INET && + s1->in.sin_port == s2->in.sin_port && + s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr) + return 1; +#ifdef HAVE_IPV6 + if (s1->sa.sa_family == AF_INET6 && + s1->in6.sin6_port == s2->in6.sin6_port && + IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr)) + return 1; +#endif + } + return 0; +} + +int sa_len(union mysockaddr *addr) +{ +#ifdef HAVE_SOCKADDR_SA_LEN + return addr->sa.sa_len; +#else +#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET6) + return sizeof(addr->in6); + else +#endif + return sizeof(addr->in); +#endif +} + +/* don't use strcasecmp and friends here - they may be messed up by LOCALE */ +int hostname_isequal(char *a, char *b) +{ + unsigned int c1, c2; + + do { + c1 = (unsigned char) *a++; + c2 = (unsigned char) *b++; + + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + + if (c1 != c2) + return 0; + } while (c1); + + return 1; +} + +time_t dnsmasq_time(void) +{ +#ifdef HAVE_BROKEN_RTC + struct tms dummy; + static long tps = 0; + + if (tps == 0) + tps = sysconf(_SC_CLK_TCK); + + return (time_t)(times(&dummy)/tps); +#else + return time(NULL); +#endif +} + +int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask) +{ + return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); +} + +/* returns port number from address */ +int prettyprint_addr(union mysockaddr *addr, char *buf) +{ + int port = 0; + +#ifdef HAVE_IPV6 + if (addr->sa.sa_family == AF_INET) + { + inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN); + port = ntohs(addr->in.sin_port); + } + else if (addr->sa.sa_family == AF_INET6) + { + inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, ADDRSTRLEN); + port = ntohs(addr->in6.sin6_port); + } +#else + strcpy(buf, inet_ntoa(addr->in.sin_addr)); + port = ntohs(addr->in.sin_port); +#endif + + return port; +} + +void prettyprint_time(char *buf, unsigned int t) +{ + if (t == 0xffffffff) + sprintf(buf, _("infinite")); + else + { + unsigned int x, p = 0; + if ((x = t/86400)) + p += sprintf(&buf[p], "%dd", x); + if ((x = (t/3600)%24)) + p += sprintf(&buf[p], "%dh", x); + if ((x = (t/60)%60)) + p += sprintf(&buf[p], "%dm", x); + if ((x = t%60)) + p += sprintf(&buf[p], "%ds", x); + } +} + + +/* in may equal out, when maxlen may be -1 (No max len). + Return -1 for extraneous no-hex chars found. */ +int parse_hex(char *in, unsigned char *out, int maxlen, + unsigned int *wildcard_mask, int *mac_type) +{ + int mask = 0, i = 0; + char *r; + + if (mac_type) + *mac_type = 0; + + while (maxlen == -1 || i < maxlen) + { + for (r = in; *r != 0 && *r != ':' && *r != '-'; r++) + if (*r != '*' && !isxdigit((unsigned char)*r)) + return -1; + + if (*r == 0) + maxlen = i; + + if (r != in ) + { + if (*r == '-' && i == 0 && mac_type) + { + *r = 0; + *mac_type = strtol(in, NULL, 16); + mac_type = NULL; + } + else + { + *r = 0; + mask = mask << 1; + if (strcmp(in, "*") == 0) + mask |= 1; + else + out[i] = strtol(in, NULL, 16); + i++; + } + } + in = r+1; + } + + if (wildcard_mask) + *wildcard_mask = mask; + + return i; +} + +/* return 0 for no match, or (no matched octets) + 1 */ +int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask) +{ + int i, count; + for (count = 1, i = len - 1; i >= 0; i--, mask = mask >> 1) + if (!(mask & 1)) + { + if (a[i] == b[i]) + count++; + else + return 0; + } + return count; +} + +/* _note_ may copy buffer */ +int expand_buf(struct iovec *iov, size_t size) +{ + void *new; + + if (size <= (size_t)iov->iov_len) + return 1; + + if (!(new = whine_malloc(size))) + { + errno = ENOMEM; + return 0; + } + + if (iov->iov_base) + { + memcpy(new, iov->iov_base, iov->iov_len); + free(iov->iov_base); + } + + iov->iov_base = new; + iov->iov_len = size; + + return 1; +} + +char *print_mac(char *buff, unsigned char *mac, int len) +{ + char *p = buff; + int i; + + if (len == 0) + sprintf(p, "<null>"); + else + for (i = 0; i < len; i++) + p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":"); + + return buff; +} + +void bump_maxfd(int fd, int *max) +{ + if (fd > *max) + *max = fd; +} + +int retry_send(void) +{ + struct timespec waiter; + if (errno == EAGAIN) + { + waiter.tv_sec = 0; + waiter.tv_nsec = 10000; + nanosleep(&waiter, NULL); + return 1; + } + + if (errno == EINTR) + return 1; + + return 0; +} + +int read_write(int fd, unsigned char *packet, int size, int rw) +{ + ssize_t n, done; + + for (done = 0; done < size; done += n) + { + retry: + if (rw) + n = read(fd, &packet[done], (size_t)(size - done)); + else + n = write(fd, &packet[done], (size_t)(size - done)); + + if (n == 0) + return 0; + else if (n == -1) + { + if (retry_send() || errno == ENOMEM || errno == ENOBUFS) + goto retry; + else + return 0; + } + } + return 1; +} + |