Compare commits

...

4 Commits
v2.35 ... v2.39

Author SHA1 Message Date
Simon Kelley
f2621c7ff0 import of dnsmasq-2.39.tar.gz 2012-01-05 17:31:13 +00:00
Simon Kelley
6b01084f8e import of dnsmasq-2.38.tar.gz 2012-01-05 17:31:13 +00:00
Simon Kelley
1b7ecd111d import of dnsmasq-2.37.tar.gz 2012-01-05 17:31:13 +00:00
Simon Kelley
832af0bafb import of dnsmasq-2.36.tar.gz 2012-01-05 17:31:13 +00:00
40 changed files with 9539 additions and 4566 deletions

196
CHANGELOG
View File

@@ -2036,5 +2036,201 @@ version 2.35
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.

45
FAQ
View File

@@ -311,7 +311,7 @@ A: Because when a Gentoo box shuts down, it releases its lease with
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 irrespcetive of which
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
@@ -393,6 +393,49 @@ A: Dnsmasq is in Suse itself, and the latest releases are also
available at ftp://ftp.suse.com/pub/people/ug/
Q: Can I run dnsmasq in a Linux vserver?
A: Yes, as a DNS server, dnsmasq will just work in a vserver.
To use dnsmasq's DHCP function you need to give the vserver
extra system capabilities. Please note that doing so will lesser
the overall security of your system. The capabilities
required are NET_ADMIN and NET_RAW. NET_ADMIN is essential, NET_RAW
is required to do an ICMP "ping" check on newly allocated
addresses. If you don't need this check, you can disable it with
--no-ping and omit the NET_RAW capability.
Adding the capabilities is done by adding them, one per line, to
either /etc/vservers/<vservername>/ccapabilities for a 2.4 kernel or
/etc/vservers/<vservername>/bcapabilities for a 2.6 kernel (please
refer to the vserver documentation for more information).
Q: What's the problem with syslog and dnsmasq?
A: In almost all cases: none. If you have the normal arrangement with
local daemons logging to a local syslog, which then writes to disk,
then there's never a problem. If you use network logging, then
there's a potential problem with deadlock: the syslog daemon will
do DNS lookups so that it can log the source of log messages,
these lookups will (depending on exact configuration) go through
dnsmasq, which also sends log messages. With bad timing, you can
arrive at a situation where syslog is waiting for dnsmasq, and
dnsmasq is waiting for syslog; they will both wait forever. This
problem is fixed from dnsmasq-2.39, which introduces asynchronous
logging: dnsmasq no longer waits for syslog and the deadlock is
broken. There is a remaining problem in 2.39, where "log-queries"
is in use. In this case most DNS queries generate two log lines, if
these go to a syslog which is doing a DNS lookup for each log line,
then those queries will in turn generate two more log lines, and a
chain reaction runaway will occur. To avoid this, use syslog-ng
and turn on syslog-ng's dns-cache function.

View File

@@ -1,7 +1,7 @@
PREFIX?=/usr/local
BINDIR = ${PREFIX}/sbin
MANDIR = ${PREFIX}/share/man
LOCALEDIR = ${PREFIX}/share/locale
PREFIX ?= /usr/local
BINDIR ?= ${PREFIX}/sbin
MANDIR ?= ${PREFIX}/share/man
LOCALEDIR ?= ${PREFIX}/share/locale
SRC = src
PO = po

View File

@@ -3,7 +3,8 @@ PKG_CONFIG ?= pkg-config
OBJS = cache.o rfc1035.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
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o
.c.o:
$(CC) $(CFLAGS) $(COPTS) $(I18N) `echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --cflags dbus-1` $(RPM_OPT_FLAGS) -Wall -W -c $<

19
contrib/try-all-ns/README Normal file
View File

@@ -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

View File

@@ -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 }
};

View File

@@ -37,7 +37,7 @@
# 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
# uncomment this.
#no-resolv
# If you don't want dnsmasq to poll /etc/resolv.conf or other resolv
@@ -48,6 +48,10 @@
# 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/
@@ -196,24 +200,30 @@
# 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
# 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.
# For reference, the common options are:
# subnet mask - 1
# default router - 3
# DNS server - 6
# broadcast address - 28
# 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=42,192.168.0.4,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
@@ -234,7 +244,8 @@
# Specify an option which will only be sent to the "red" network
# (see dhcp-range for the declaration of the "red" network)
#dhcp-option=red,42,192.168.1.1
# Note that the net: part must precede the option: part.
#dhcp-option = net:red, option:ntp-server, 192.168.1.1
# The following DHCP options set up dnsmasq in the same way as is specified
# for the ISC dhcpcd in
@@ -250,21 +261,63 @@
# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
# probably doesn't support this......
#dhcp-option=119,eng.apple.com,marketing.apple.com
#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 encapsulated vendor-class specific options. The vendor-class
# is sent as DHCP option 60, and all the options marked with the
# vendor class are send encapsulated in DHCP option 43. The meaning of
# the options is defined by the vendor-class. This example sets the
# mtftp address to 0.0.0.0 for PXEClients
# 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
# Set the boot filename and tftpd server name and address
# for BOOTP. You will only need this is you want to
# boot machines over the network.
# 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 BOOTP. 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
# Enable dnsmasq's built-in TFTP server
#enable-tftp
# Set the root directory for files availble via FTP.
#tftp-root=/var/ftpd
# Make the TFTP server more secure: with this set, only files owned by
# the user dnsmasq is running as will be send over the net.
#tftp-secure
# 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 server: the name and IP
# address of the server are given after the filename.
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3
# Set the limit on DHCP leases, the default is 150
@@ -363,6 +416,11 @@
# 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
@@ -370,7 +428,7 @@
# occur for TXT records.)
#Example SPF.
#txt-record=example.com,v=spf1 a -all
#txt-record=example.com,"v=spf1 a -all"
#Example zeroconf
#txt-record=_http._tcp.example.com,name=value,paper=A4
@@ -380,6 +438,9 @@
# 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

View File

@@ -11,11 +11,12 @@ Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP
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.
DHCP leases and BOOTP/TFTP 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 small network where low
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 and
@@ -83,7 +84,7 @@ for any or all local machines.
<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>.
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>.

2
hosts
View File

@@ -1,2 +0,0 @@
127.0.0.1 host1.domain

View File

@@ -6,7 +6,7 @@ dnsmasq \- A lightweight DHCP and caching DNS server.
.I [OPTION]...
.SH "DESCRIPTION"
.BR dnsmasq
is a lightweight DNS and DHCP server. It is intended to provide coupled DNS and DHCP service to a
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,
@@ -18,13 +18,15 @@ DNS queries for DHCP configured hosts.
The dnsmasq DHCP server supports static address assignments, multiple
networks, DHCP-relay and RFC3011 subnet specifiers. It automatically
sends a sensible default set of DHCP options, and can be configured to
send any desired set of DHCP options. It also supports BOOTP.
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.
supports IPv6 for DNS, but not DHCP.
.SH OPTIONS
Note that in general missing parameters are allowed and switch off
functions, for instance "--pid-file=" disables writing a PID file. On
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.
@@ -37,6 +39,10 @@ Additional hosts file. Read the specified file as well as /etc/hosts. If -h is g
only the specified file. This option may be repeated for more than one
additional hosts file.
.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.
.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
@@ -62,7 +68,23 @@ Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on r
.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.
defaults to DAEMON, and to LOCAL0 when debug mode is in operation. If
the facilty given contains at least one '/' character, it is taken to
be a filename, and dnsmasq logs to the given file, instead of
syslog. (Errors whilst reading configuration will still go to syslog,
but all output from a successful startup, and all output whilst
running, will go exclusively to the file.)
.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.
@@ -123,7 +145,7 @@ options does not matter and that
options always override the others.
.TP
.B \-2, --no-dhcp-interface=<interface name>
Do not provide DHCP on the specified interface, but do provide DNS service.
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
@@ -229,7 +251,7 @@ 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, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source>[#<port>]]]
.B \-S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source>[#<port>]]]
Specify IP address of upstream severs directly. Setting this flag does
not suppress reading of /etc/resolv.conf, use -R to do that. If one or
more
@@ -322,6 +344,20 @@ all that match are returned.
Return a TXT DNS record. The value of TXT record is a set of strings,
so any number may be included, split by commas.
.TP
.B --ptr-record=<name>[,<target>]
Return a PTR DNS record.
.TP
.B --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-existant, an empty record is returned. The
matching PTR record is also created, mapping the interface address to
the name. More than one name may be associated with an interface
address by repeating the flag; in that case the first instance is used
for the reverse address-to-name mapping.
.TP
.B \-c, --cache-size=<cachesize>
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
.TP
@@ -368,7 +404,7 @@ addresses given via
.B dhcp-host
or from /etc/ethers will be served.
.TP
.B \-G, --dhcp-host=[[<hwaddr>]|[id:[<client_id>][*]]][,net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
Specify per host parameters for the DHCP server. This allows a machine
with a particular hardware address to be always allocated the same
hostname, IP address and lease time. A hostname specified like this
@@ -429,19 +465,26 @@ have exactly the same effect as
.B --dhcp-host
options containing the same information.
.TP
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][vendor:<vendor-class>]<opt>,[<value>[,<value>]]
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][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 option allows these defaults to be overridden,
or other options specified. The <opt> is the number of the option, as
specified in RFC2132. For example, to set the default route option to
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
.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
.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
@@ -449,9 +492,10 @@ and a text string. If the optional network-ids are given then
this option is only sent when all the network-ids are matched.
Special processing is done on a text argument for option 119, to
conform with RFC 3397, and dotted-quad IP addresses which are followed
by a slash and then a netmask size are encoded as described in RFC
3442.
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
@@ -470,16 +514,31 @@ a literal IP address as TFTP server name, it is necessary to do
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 vendor class "PXEClient" and the encapsulated vendor class-specific option "mftp-address=0.0.0.0" Only one vendor class is allowed for any
host, but multiple options are allowed, provided they all have
the same vendor class. The address 0.0.0.0 is not treated specially in
.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.
The address 0.0.0.0 is not treated specially in
encapsulated vendor class options.
.TP
.B --dhcp-option-force=[<network-id>,[<network-id>,]][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 \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
Map from a vendor-class string to a network id. Most DHCP clients provide a
Map from a vendor-class string to a network id tag. Most DHCP clients provide a
"vendor class" which represents, in some sense, the type of host. This option
maps vendor classes to network ids, so that DHCP options may be selectively delivered
maps vendor classes to tags, so that DHCP options may be selectively delivered
to different classes of hosts. For example
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
will allow options to be set only for HP printers like so:
@@ -489,29 +548,52 @@ substring matched against the vendor-class supplied by the client, to
allow fuzzy matching.
.TP
.B \-j, --dhcp-userclass=<network-id>,<user-class>
Map from a user-class string to a network id (with substring
Map from a user-class string to a network id tag (with substring
matching, like vendor classes). Most DHCP clients provide a
"user class" which is configurable. This option
maps user classes to network ids, so that DHCP options may be selectively delivered
maps user classes to tags, so that DHCP options may be selectively delivered
to different classes of hosts. It is possible, for instance to use
this to set a different printer server for hosts in the class
"accounts" than for hosts in the class "engineering".
.TP
.B \-4, --dhcp-mac=<network-id>,<MAC address>
Map from a MAC address to a network-id. The MAC address may include
Map from a MAC address to a network-id tag. The MAC address may include
wildcards. For example
.B --dhcp-mac=3com,01:34:23:*:*:*
will set the tag "3com" for any host whose MAC address matches the pattern.
.TP
.B --dhcp-circuitid=<network-id>,<circuit-id>, --dhcp-remoteid=<network-id>,<remote-id>
Map from RFC3046 relay agent options to network-id tags. This data may
be provided by DHCP relay agents. The circuit-id or remote-id is
normally given as colon-separated hex, but is also allowed to be a
simple string. If an exact match is achieved between the circuit or
agent ID and one provided by a relay agent, the network-id tag is set.
.TP
.B --dhcp-subscrid=<network-id>,<subscriber-id>
Map from RFC3993 subscriber-d relay agent options to network-id tags.
.TP
.B \-J, --dhcp-ignore=<network-id>[,<network-id>]
When all the given network-ids match the set of network-ids derived
from the net, host, vendor and user classes, ignore the host and do
not allocate it a DHCP lease.
.TP
.B --dhcp-ignore-name[=<network-id>[,<network-id>]]
When all the given network-ids match the set of network-ids derived
from the net, host, vendor and user classes, ignore any hostname
provided by the host. Note that, unlike dhcp-ignore, it is permissable
to supply no netid tags, in which case DHCP-client supplied hostnames
are always ignored, and DHCP hosts are added to the DNS using only
dhcp-host configuration in dnsmasq and the contents of /etc/hosts and
/etc/ethers.
.TP
.B \-M, --dhcp-boot=[net:<network-id>,]<filename>,[<servername>[,<server address>]]
Set BOOTP options to be returned by the DHCP server. These are needed
for machines which network boot, and tell the machine where to collect
its initial configuration. If the optional network-id(s) are given,
Set BOOTP options to be returned by the DHCP server. Server name and
address are optional: if not provided, the name is left empty, and the
address set to the address of the machine running dnsmasq. If dnsmasq
is providing a TFTP service (see
.B --enable-tftp
) then only the filename is required here to enable network booting.
If the optional network-id(s) are given,
they must match for this configuration to be sent. Note that
network-ids are prefixed by "net:" to distinguish them.
.TP
@@ -522,7 +604,7 @@ create thousands of leases and use lots of memory in the dnsmasq
process.
.TP
.B \-K, --dhcp-authoritative
Should be set when dnsmasq is definately the only DHCP server on a network.
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
@@ -542,6 +624,10 @@ ICMP echo request (aka "ping") to the address in question. If it gets
a reply, then the address must already be in use, and another is
tried. This flag disables this check. Use with caution.
.TP
.B --log-dhcp
Extra logging for DHCP: log all the options sent to DHCP clients and
the netid tags used to determine them.
.TP
.B \-l, --dhcp-leasefile=<path>
Use the specified file to store DHCP lease information. If this option
is given but no dhcp-range option is given then dnsmasq version 1
@@ -568,7 +654,7 @@ The environment is inherited from the invoker of dnsmasq, and if the
host provided a client-id, this is stored in the environment variable
DNSMASQ_CLIENT_ID. If the client provides vendor-class or user-class
information, these are provided in DNSMASQ_VENDOR_CLASS and
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only fory
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
@@ -583,7 +669,7 @@ closed except stdin, stdout and stderr which are open to /dev/null
(except in debug mode).
The script is not invoked concurrently: if subsequent lease
changes occur, the script is not invoked again until any existing
invokation exits. At dnsmasq startup, the script will be invoked for
invocation exits. At dnsmasq startup, the script will be invoked for
all existing leases as they are read from the lease file. Expired
leases will be called with "del" and others with "old". <path>
must be an absolute pathname, no PATH search occurs.
@@ -593,7 +679,7 @@ 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
invokations given in
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
@@ -602,11 +688,25 @@ 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 only available
on FreeBSD and Dragonfly BSD, and is necessary when using "old style" bridging, since
packets arrive at tap interfaces which don't have an IP address.
.TP
.B \-s, --domain=<domain>
Specifies the domain for the DHCP server. 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 it's 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
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
@@ -614,10 +714,44 @@ 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).
.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.
.B --enable-tftp
Enable the TFTP server function. This is deliberately limited to that
needed to net-boot a client: Only reading is allowed, and only in
binary/octet mode. The tsize and blksize extensions are supported.
.TP
.B --tftp-root=<directory>
Look for files to transfer using TFTP relative to the given
directory. When this is set, TFTP paths which include ".." are
rejected, to stop clients getting outside the specified root.
Absolute paths (starting with /) are allowed, but they must be within
the tftp-root.
.TP
.B --tftp-secure
Enable TFTP secure mode: without this, any file which is readble 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.
.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 \-C, --conf-file=<file>
Specify a different configuration file. The conf-file option is also allowed in
configuration files, to include multiple configuration files.
@@ -649,7 +783,7 @@ corresponding to tab, bell, backspace, return and newline.
When it receives a SIGHUP,
.B dnsmasq
clears its cache and then re-loads
.I /etc/hosts.
.I /etc/hosts and /etc/ethers.
If
.B
--no-poll
@@ -766,9 +900,53 @@ on a particular network. (Setting --bootp-dynamic removes the need for
static address mappings.) The filename
parameter in a BOOTP request is matched against netids in
.B dhcp-option
configurations, allowing some control over the options returned to
configurations, as is the tag "bootp", allowing some control over the options returned to
different classes of hosts.
.SH LIMITS
The default values for resource limits in dnsmasq are generally
conservative, and appropriate for embedded router type devices with
slow processors and limited memory. On more capable hardware, it is
possible to increase the limits, and handle many more clients. The
following applies to dnsmasq-2.37: earlier versions did not scale as well.
.PP
Dnsmasq is capable of handling DNS and DHCP for at least a thousand
clients. Clearly to do this the value of
.B --dhcp-lease-max
must be increased,
and lease times should not be very short (less than one hour). The
value of
.B --dns-forward-max
can be increased: start with it equal to
the number of clients and increase if DNS seems slow. Note that DNS
performance depends too on the performance of the upstream
nameservers. The size of the DNS cache may be increased: the hard
limit is 10000 names and the default (150) is very low. Sending
SIGUSR1 to dnsmasq makes it log information which is useful for tuning
the cache size. See the
.B NOTES
section for details.
.PP
The built-in TFTP server is capable of many simultaneous file
transfers: the absolute limit is related to the number of file-handles
allowed to a process and the ability of the select() system call to
cope with large numbers of file handles. If the limit is set too high
using
.B --tftp-max
it will be scaled down and the actual limit logged at
start-up. Note that more transfers are possible when the same file is
being sent than when each transfer sends a different file.
.PP
It is possible to use dnsmasq to block Web advertising by using a list
of known banner-ad servers, all resolving to 127.0.0.1 or 0.0.0.0, in
.B /etc/hosts
or an additional hosts file. The list can be very long,
dnsmasq has been tested successfully with one million names. That size
file needs a 1GHz processor and about 60Mb of RAM.
.SH FILES
.IR /etc/dnsmasq.conf

View File

@@ -6,7 +6,7 @@ dnsmasq \- Un ligero servidor DHCP y DNS con cach
.I [OPCION]...
.SH "DESCRIPCION"
.BR dnsmasq
es un ligero servidor DNS y DHCP. Su propósito es proveer servicios DNS
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
@@ -19,11 +19,12 @@ v
El servidor DHCP dnsmasq incluye soporte para assignación de direcciones
estáticas, redes múltiples, DHCP-relay y especificadores de subredes
RFC3011. Automáticamente envía un predeterminado sensible de opciones
DHCP, y puede ser configurado para enviar cualquier opciones DHCP
deseadas. Tambíen incluye soporte para BOOTP.
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 para IPv6.
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
@@ -39,9 +40,13 @@ 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.
.TP
.B \-E, --expand-hosts
Agregar el dominio a nombres sencillos (sin punto) en /etc/hosts de la
misma manera que con nombres derivados de DHCP.
.TP
.B \-T, --local-ttl=<tiempo>
Al responder con información desde /etc/hosts o desde el archivo
de arriendos DHCP, dnsmasq fija el tiempo de vida a cero por
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
@@ -50,15 +55,15 @@ reduce la carga sobre el servidor al costo de que los clientes
usaran datos añejos bajo algunas circunstancias.
.TP
.B \-k, --keep-in-foreground
No ir hacia el fondo al iniciar, pero aparte de eso correr como
normal. La intención de esto es para cuando dnsmasq es corrido
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
hacerle fork a procesos nuevos para manejar búsquedas TCP.
forkear procesos nuevos para manejar búsquedas TCP.
.TP
.B \-q, --log-queries
Bitacorear los resultados de búsquedas DNS manejadas por dnsmasq.
@@ -66,7 +71,22 @@ Habilitar un dump de cach
.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 en modo debug.
esto es DAEMON por predeterminado, y LOCAL0 cuando el modo debug está
en operación. Si la facilidad brindada contiene por lo menos un carácter
"/", se trata como un nombre de archivo, y dnsmasq bitacoreará a dicho
archivo, en vez de syslog. (Errores durante la lectura de la configuración
irán a syslog todavía, pero todo output desde un inicio exitoso, y todo
output mientras en ejecución, irá a este archivo exclusivamente.)
.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 el valor máximo de 100 es impuesto.
.TP
.B \-x, --pid-file=<path>
Especificar un path alterno donde dnsmasq debe guardar su PID.
@@ -82,7 +102,7 @@ con esta opci
.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 normalmente no es globalmente leíble.
/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.
@@ -105,37 +125,37 @@ servidores DNS for
adaptarse dinámicamente al puerto siendo usado por la actual
instancia de dnsmasq.
.TP
.B \-i, --interface=<interface>
Escuchar solo en las interfaces especificadas. Dnsmasq automaticamente
.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 opcion
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 la opcion
cualquiera fijada con la opción
.B \--except-interface
Interfaces IP alias (eg "eth1:0") no pueden ser utilizadas con
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=<interface>
.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 la opcion
no importa y la opción
.B --except-interface
siempre invalida a las otras.
siempre invalida las otras.
.TP
.B \-2, --no-dhcp-interface=<interface>
No proveer DHCP en la interface especificada, pero sí
.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>
@@ -149,8 +169,8 @@ direcciones IP y interfaces es usada. N
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, la dirección IP 127.0.0.1 debe ser
explícitamente dada como una opción
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
@@ -178,18 +198,18 @@ 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 para rangos de IP
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 vieja>,<IP nueva>[,<máscara>]
.B \-V, --alias=<IP viejo>,<IP nuevo>[,<máscara>]
Modificar direcciones IPv4 retornadas desde servidores DNS upstream;
<IP vieja> es remplazada con <IP nueva>. Si la máscara opcional
es brindada, entonces cualquier dirección que coincida con la
<IP vieja> enmascarada será re-escrita. Así que, por ejemplo,
.B --alias=1.2.3.0,6.7.8.0,255.255.255.0
mapeará 1.2.3.56 a 6.7.8.56 y 1.2.3.67 a 6.7.8.67. Esto es lo que
<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".
.TP
.B \-B, --bogus-nxdomain=<dirección IP>
@@ -200,7 +220,7 @@ del 2003, cuando comenzaron a retornar la direcci
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.
Desde septiembre 2003 la dirección IP siendo retornada por Verisign
Para septiembre 2003 la dirección IP siendo retornada por Verisign
es 64.94.110.11
.TP
.B \-f, --filterwin2k
@@ -217,9 +237,9 @@ en vez de /etc/resolv.conf. Para el formato de este archivo, ver
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 archivos son agregados a la lista. Esto es solo
permitido cuando haciendo polling; el archivo con la actual fecha
de modificación más nueva es el que es usado.
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
@@ -242,13 +262,18 @@ que aparecen en /etc/resolv.conf
.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, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source>[#<port>]]]
.B \-S, --local, --server=[/[<dominio>]/[dominio/]][<dirección IP>[#<puerto>][@<remitente>[#<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
@@ -261,10 +286,10 @@ opci
.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
/etc/resolv.conf. Una especificación de dominio en blanco,
.B //
tiene el significado especial de "solo nombres no calificados", o
sea nombres sin ningun punto en ellos. Un puerto no-estándar puede
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.
@@ -303,8 +328,8 @@ retornar
/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=<mx name>[[,<hostname>],<preference>]
Retornar un record llamado <nombre MX> apuntando hacia un nombre de
.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
@@ -312,11 +337,11 @@ 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=<hostname>
.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 hostname de la máquina donde
el target MX para búsquedas MX en el nombre de host de la máquina donde
dnsmasq está corriendo.
.TP
.B \-e, --selfmx
@@ -328,23 +353,26 @@ 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=<_service>.<_prot>.[<domain>],[<target>[,<port>[,<priority>[,<weight>]]]]
.B \-W, --srv-host=<_servicio>.<_prot>.[<dominio>],[<target>[,<puerto>[,<prioridad>[,<peso>]]]]
Retornar un record SRV DNS. 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, y el predeterminado
para puerto es uno y los predeterminados para peso y prioridad son cero.
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=<name>[[,<text>],<text>]
.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 \-c, --cache-size=<cachesize>
.B --ptr-record=<nombre>[,<target>]
Retornar un récord DNS PTR.
.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
@@ -354,32 +382,40 @@ recordar resultados tipo "dominio no existe" desde servidores DNS
upstream y responder búsquedas idénticas sin reenviarlas nuevamente.
Esta opción deshabilita el caché negativo.
.TP
.B \-F, --dhcp-range=[[net:]network-id,]<start-addr>,<end-addr>[[,<netmask>],<broadcast>][,<default lease time>]
.B \-0, --dns-forward-max=<búsquedas>
Fijar el número máximo de búsquedas DNS simultáneas. El valor
predeterminado es 150, lo cuál debería estar bien para la mayoría
de casos. La única situación conocida donde esto debe ser incrementado
es al usar resolvedores de bitácoras de servidores web, los cuales pueden
generar un número inmenso de búsquedas simultáneas.
.TP
.B \-F, --dhcp-range=[[net:]network-id,]<dirección-inicio>,<dirección-final>[[,<máscara>],<broadcast>][,<tiempo de arriendo predeterminado>]
Habilitar el servidor DHCP. Direcciones serán distribuidas desde el
rango <start-addr> hasta <end-addr> y desde direcciones definidas
estáticamente en opciones
.B dhcp-host
Si el tiempo de arriendo es brindado, entonces arriendos serán
dados por esa cantidad de tiempo. El tiempo de arriendo es en
segundos, o minutos (ej. 45m), o horas (ej. 1h), o el literal
"infinite". Esta opción puede ser repetida, con diferentes
segundos, o minutos (por ejemplo, 45m), o horas (por ejemplo, 1h), o el
literal "infinite". 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. Es requerida para redes que
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. En algunos sistemas rotos, dnsmasq
solo puede escuchar en una interface cuando se usa DHCP, y el
nombre de esa interface debe ser brindado usando la opcion
nombre de esa interface debe ser brindado usando la opción
.B interface
Esta limitación actualmente afecta a OpenBSD. Siempre se permite
tener más de un rango dhcp (dhcp-range) en una subred. El
parametro opcional network-id es una etiqueta alfanumerica la
cual marca esta red de tal forma que opciones dhcp puedan ser
Esta limitación actualmente afecta a OpenBSD antes de versión 4.0.
Siempre se permite tener más de un rango dhcp (dhcp-range) en una
subred. El parámetro opcional network-id es una etiqueta alfanumérica
la cual marca esta red de tal forma que opciones dhcp puedan ser
especificadas en base a cada red.
Cuando es prefijada con 'net:' entonces el significado cambia
de "fijar etiqueta" a "coincidir con etiqueta".
La dirección final puede ser remplazada por la palabra
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.
@@ -387,7 +423,7 @@ Solo hosts que tienen direcciones est
.B dhcp-host
o desde /etc/ethers serán servidas.
.TP
.B \-G, --dhcp-host=[[<hwaddr>]|[id:[<client_id>][*]]][net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
.B \-G, --dhcp-host=[<dirección de hardware>][,id:<client_id>|*][,net:<netid>][,<dirección IP>][,<nombre de host>][,<tiempo de arriendo>][,ignore]
Especificar parámetros por host para el servidor DHCP. Esto permite
que una máquina con una dirección de hardware particular sea siempre
alocada el mismo nombre de host, dirección IP, y tiempo de arriendo.
@@ -410,7 +446,7 @@ 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:clientidastext,.....
.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.
@@ -423,7 +459,7 @@ una m
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 para ser
usado por algúnas máquinas. net:<network-id> fija la etiqueta
usado por algúnas máquinas. El net:<network-id> fija la etiqueta
network-id cuando sea que esta directiva dhcp-host está en uso.
Esto puede ser usado para enviar selectivamente opciones DHCP
a este host.
@@ -448,7 +484,7 @@ dnsmasq, estas l
.B --dhcp-host
que contienen la misma información.
.TP
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][vendor:<vendor-class>]<opt>,[<value>[,<value>]]
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][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
@@ -456,20 +492,33 @@ 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. <opt> es el numero de la opción, como especificado
en RFC2132. Por ejemplo, para fijar a ruta predeterminada a
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 a 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 puntos, un número decimal, dígitos hex
son direcciones IP de cuatro segmentos, un número decimal, dígitos hex
separados por colones, y un string de texto. Si las network-ids
opcionales son brindadas, entonces esta opcion es solo enviada cuando
todas las network-ids coinciden.
Procesamiento especial es llevado a cabo en un argumento de texto para
la opción 119, en conforme con RFC3397. Direcciones IP textuales o de
cuatro segmentos como argumentos a la opción 120 son manejados mediante
RFC3361. Direcciones IP de cuatro segmentos que son seguidas por un diagonal
(slash) y después una máscara son codificados mediante RFC3442.
Tener cuidado: niguna verificación es hecha sobre si el número de tipo
correcto es enviado, y es muy posible persuadir a dnsmasq para que
genere paquetes DHCP ilegales mediante uso inadecuado de esta opción.
@@ -486,20 +535,33 @@ 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
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 clase de vendedor "PXEClient" y la clase encapsulada de vendedor
especifica "mftp-address=0.0.0.0". Solo se permite una clase para cualquier
host, pero opciones múltiples son permitidas, con tal que tengan la misma
clase de vendedor. La dirección 0.0.0.0 no es tratada de forma especial
en opciones de clase encapsuladas.
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. La dirección
0.0.0.0 no es tratada de forma especial en opciones de clase de vendedor
encapsuladas.
.TP
.B --dhcp-option-force=[<network-id>,[<network-id>,]][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 lo pide en
la lista de pedido de parámetros. Esto se necesita aveces, por ejemplo cuando
enviando opciones a PXELinux.
.TP
.B \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
Mapear desde un string vendor-class a un network id. La mayoría de los
Trazar desde un string vendor-class a un network id. La mayoría de los
clientes DHCP proveen una "vendor class" la cual representa, en cierto
sentido, el tipo de host. Esta opción mapea clases de vendedor a network
sentido, el tipo de host. Esta opción traza clases de vendedor a network
ids, de tal forma que opciones DHCP pueden ser selectivamente entregadas
a diferentes clases de hosts. Por ejemplo
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
@@ -509,35 +571,58 @@ El string vendor-class es coordinado con el vendor-class proveido por
el cliente, para permitir coincidencias borrosas.
.TP
.B \-j, --dhcp-userclass=<network-id>,<user-class>
Mapear desde un string user-class a un network id (con coordinación
Trazar desde un string user-class a un network id (con coordinación
substring, como con vendor-class). La mayoría de los clientes DHCP
proveen un "user class" el cual es configurable. Esta opción mapea
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 "accounts" que para los de la clase "engineering".
hosts en la clase "cuentas" que para los de la clase "ingenieria".
.TP
.B \-4, --dhcp-mac=<network-id>,<MAC address>
.B \-4, --dhcp-mac=<network-id>,<dirección MAC>
Mapear desde una dirección MAC a una network id. La dirección MAC
puede incluir comodínes. Por ejemplo:
.B --dhcp-mac=3com,01:34:23:*:*:*
fijaría el tag "3com" a cualquier host el cual su MAC coincida con
el patrón.
.TP
.B --dhcp-circuitid=<network-id>,<circuit-id>, --dhcp-remoteid=<network-id>,<remote-id>
Trazar de opciones agente de relay RFC3046 a opciones network-id. Estos
datos pueden ser proveídos por agentes de relay DHCP. El circuit-id o
remote-id es normlamente brindado como hex separado por doblepuntos, pero
también se permite un string simple. Si se obtiene una coincidencia exacta
entre el circuit o agent ID y uno proveído por un agente de relay,
network-id es fijado.
.TP
.B --dhcp-subscrid=<network-id>,<subscriber-id>
Trazar de opciones relay subscriber-id RFC3993 a opciones network-id.
.TP
.B \-J, --dhcp-ignore=<network-id>[,<network-id>]
Cuando todos los network ids brindados coincidan con el juego de
network ids derivados de las clases net, host, y vendor, ignorar
el host y no brindarle un arriendo DHCP.
.TP
.B --dhcp-ignore-name[=<network-id>[,<network-id>]]
Cuando todos los network-ids brindados coinciden con el juego de
network-ids derivado de la red, host, classes de vendedor y usuario,
ignorar cualquier nombre de host proveido por el host. Nótese que,
a diferencia de dhcp-ignore, es permisible no brindar ningún tag netid,
y en tal caso nombres de host proveidos por clientes DHCP siempre son
ignorados, y hosts DHCP son agregados al DNS usando solo la configuración
dhcp-host en dnsmasq y el contenido de /etc/hosts y /etc/ethers.
.TP
.B \-M, --dhcp-boot=[net:<network-id>,]<filename>,[<servername>[,<server address>]]
Fijar opciones BOOTP que han de ser devueltas por el servidor DHCP.
Estas se necesitan para máquinas que bootean desde la red, y decirle
a la máquina donde conseguir su configuración inicial. Si las network
id opcionales son brindadas, deben coincidir con esta opción para ser
enviadas. Nótese que network ids son prefijadas con "net:" para
distinguirlas.
Fijar opciones BOOTP que han de ser devueltas por el servidor DHCP. Nombre
y dirección de servidor son opcionales: si no son brindadas, el nombre es
dejado en blanco, y la dirección es fijada a la de la máquina que corre
dnsmasq. Si dnsmasq está brindando servicio TFTP (ver
.B --enable-tftp
) entonces solo el nombre de archivo es requirido aquí para habilitar
el inicio atravéz de una red. Si las opcionales network-ids son brindadas,
ellas deberán coincidir para que esta configuración sea enviada. Nótese
que network-ids están prefijadas con "net:" para distinguirlas.
.TP
.B \-X, --dhcp-lease-max=<number>
.B \-X, --dhcp-lease-max=<número>
Limita a dnsmasq a el número especificado de arriendos DHCP. El
predeterminado es 150. El limite es para prevenir ataques DoS desde
hosts que crean cientos de arriendos y usan mucha de la memoria del
@@ -554,55 +639,92 @@ es perdida.
.TP
.B \-3, --bootp-dynamic
Habilitar alocación dinámica de direcciones IP a clientes BOOTP. Usar
esto con cuidado, ya que cada cirección alocada a un cliente BOOTP
esto con cuidado, ya que cada dirección alocada a un cliente BOOTP
es arrendada para siempre, y consecuentemente queda no-disponible
para uso por otros hosts.
para re-uso por otros hosts.
.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 opcion deshabilita esta prueba. Usar con
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 los tags netid usados para determinarlos.
.TP
.B \-l, --dhcp-leasefile=<path>
Usar el archivo especificado para almacenar informacion de arriendos
DHCP. Si esta opcion es brindada, pero ninguna opcion dhcp-range es
Usar el archivo especificado para almacenar información de arriendos
DHCP. Si esta opción es brindada, pero ninguna opcion dhcp-range es
brindada, entonces se activa comportamiento tipo dnsmasq versión 1.
El archivo brindado se asume es un archivo de arriendos dhcpd ISC y
es analizado en busca de arriendos los cuales son agregados al sistema
DNS si tienen un nombre de host. Esta funcionalidad pudo haber sido
excluida de dnsmasq a la hora de compilación, y en tal caso ocurrirá
un error. En todo caso, nótese que la integración de archivos de
un error. Nótese que la integración de archivos de
arriendo ISC es una caracterísctica depreciada. No debería ser usada
en instalaciones nuevas, y será eliminada en versiones futuras.
.TP
.B \-6 --dhcp-script=<path>
Cuando sea que un arriendo DHCP nuevo es creado, o uno viejo es
Cuando un arriendo DHCP nuevo es creado, o uno viejo es
destruido, el binario especificado por esta opción es ejecutado.
Los argumentos para el binario son "add", "old", o "del", la dirección
MAC del host (o "<null>"), 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. Este proceso es ejecutado como el usuario sin privilegios
como corre dnsmasq, así que puede ser necesario inhibir el dejar el
usuario root, usando la directiva
.B -u
si el ejecutable necesita privilegios root.
El ambiente es heredado del usuario que ha invocado a dnsmasq, y todos
los descriptores están cerrados excepto stdin, stdout y stderr los cuales
están abiertos a /dev/null (excepto en modo debug).
existente (también, tiempo de arriendo o vencimiento y client-id, si
leasefile-ro está fijado). El proceso es ejecutado como root (asumiendo
que dnsmasq fue originalmente ejecutado como root) aún si dnsmasq está
configurado para cambiar su UID a un usuario sin privilegios.
El ambiente es heredado del usuario que ha invocado a dnsmasq, y si el
host brindó un client-id, es almacenado en la variable de ambiente
DNSMASQ_CLIENT_ID. Si el cliente brinda información de clase de vendedor
o usuario, estos son brindados en las variables DNSMASQ_VENDOR_CLASS y
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add"
y "old" cuando un host resume un arriendo existente, dado a que estos
datos no son almacenados en la base de datos de arriendos de dnsmasq.
Si dnsmasq fue compilado con HAVE_BROKEN_RTC, entonces la duración del
arriendo (en segundos) es almacenada en DNSMASQ_LEASE_LENGTH, de otra
manera el tiempo de vencimiento es almacenado en DNSMASQ_LEASE_EXPIRES.
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. Todos los descriptores de archivo están cerrados
excepto stdin, stdout, y stderr los cuales están abiertos a /dev/null
(excepto en modo debug).
Este guión no es invocado concurrentemente: si cambios de arriendos
subsiguientes ocurren, el guión no es invocado otra vez hasta que
cualquier invocación existennte haga exit. Al inicio de dnsmasq, el guión
cualquier invocación existente haga exit. Al inicio de dnsmasq, el guión
será invocado para todos los arriendos existenetes mientras van siendo
leidos desde el archivo de arriendos. Arriendos vencidos serán llamados
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.
.TP
.B \-s, --domain=<domain>
.B \-9, --leasefile-ro
Suprimir completamente el uso del archivo de arriendos. El archivo no será
creado, leído, o escrito. Cambiar la manera en la cuál el archivo guión de
cambio de arriendo es llamado, de tal forma que la base de datos de arriendos
pueda 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 solo
está disponible en FreeBSD y Dragonfly BSD, y es necesaria cuando se usan
puentes "estilo viejo", ya que los paquetes llegan a interfaces tap que no
tienen una dirección IP.
.TP
.B \-s, --domain=<dominio>
Especifica el dominio para el servidor DHCP. 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
@@ -611,7 +733,7 @@ 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 logeada. Si un sufijo es especificado,
(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
@@ -622,12 +744,47 @@ y tener una maquina cuyo nombre host DHCP es "laptop". La direcci
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 de
búsqueda en /etc/resolv.conf (o equivalente).
como "#" entonces el dominio es leido desde la primera directiva search
en /etc/resolv.conf (o equivalente).
.TP
.B \-E, --expand-hosts
Agregar el dominio a nombres simples (sin un punto) en /etc/hosts de
la misma manera que con nombres derivados de DHCP.
.B --enable-tftp
Habilitar la función de servidor TFTP. Esto está deliberadamente limitado
a lo necesario para hacerle a un cliente un inicio vía red: solo lectura es
permitida, y solo en modo binario/octeto. Las extensiones "tsize" y "blksize"
están soportadas.
.TP
.B --tftp-root=<directorio>
Buscar, relativo al directorio brindado, archivos para transferir mediante el
uso de TFTP. Cuando esta opción está fijada, paths TFTP que incluyen ".." son
rechazados, para prevenir que clientes salgan de la raíz especificada. Paths
absolutos (los que comienzan con "/") están permitidos, pero deben estar
dentro del tftp-root.
.TP
.B --tftp-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.
.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 \-C, --conf-file=<archivo>
Especificar un archivo de configuración diferente. La opción conf-file
@@ -644,7 +801,7 @@ Al inicio, dnsmasq lee
.I /etc/dnsmasq.conf,
si existe. (En FreeBSD, el archivo es
.I /usr/local/etc/dnsmasq.conf
) (ver las opciónes
) (pero ver las opciónes
.B \-C
y
.B \-7
@@ -652,8 +809,8 @@ porfavor.) El formato de este archivo consiste de una opci
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, la línea de comandos invalida el archivo de configuración.
La comillas son permitidas en el archivo de configuración: entre comillas
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 \\a \\b \\r y \\n. El
último corresponde a tab, bell, backspace, return y newline.
@@ -661,24 +818,23 @@ siguientes escapes son permitidos: \\\\ \\" \\t \\a \\b \\r y \\n. El
Al recibir un SIGHUP
.B dnsmasq
libera su cache y entonces recarga
.I /etc/hosts.
.I /etc/hosts y /etc/ethers.
Si
.B
--no-poll
está fijado entnces SIGHUP también re-lee
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 estadisticas de caché al log del sistema. Escribe el tamaño
escribe estadisticas de caché a la biá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é. En
modo
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é. En modo
.B --no-daemon
o cuando logeo completo está habilitado (-q), una descarga completa de
o cuando bitacoréo completo está habilitado (-q), una descarga completa de
el contenido del caché es hecha.
.PP
Dnsmasq es un reenviador de búsquedas DNS: no puede responder búsquedas
@@ -696,7 +852,7 @@ revisa el tiempo de modificaci
.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
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
@@ -705,36 +861,34 @@ no es un error ya que pudo haber sido creada antes de que una conexi
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 laptp, donde ambos PPP y
DHCP podrían estar siendo usados: dnsmasq puede ser fijado para revisar
ambos:
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 de cualquiera que haya cambiado mas recientemente,
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 ocpionalmente llevan un nombre de dominio el cual le dice a
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 para que actúe como caché para el host donde está
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 espesificar los servidores upstream diréctamente a dnsmasq usando
opciones
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 servidores mediante PPP o DHCP.
de servidor mediante PPP o DHCP.
.PP
Direcciones en /etc/hosts harán "sombra" a diferentes direcciones para
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
@@ -742,7 +896,7 @@ servidor DNS upstream devolver
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 en CNAME a
el destino del CNAME. Para circumventar esto, agregar el CNAME a
/etc/hosts de tal manera que el CNAME es sombreado también.
.PP
El sistema network-id funciona de la siguiente manera: Para cada pedido
@@ -753,7 +907,7 @@ usado para alocar la direcci
.B dhcp-host
que coincida, y posiblemente muchas de clases de vendedor y usuario
que coinicdan que hayan sido enviadas por el cliente DHCP.
Cualquier opcion
Cualquier opción
.B dhcp-option
que tenga etiquetas network-id será usada en preferencia de una opción
.B dhcp-option,
@@ -767,8 +921,8 @@ Si el network-id en un
.B dhcp-range
es prefijado con "net:", entonces su significado cambia de "fijar
etiqueta" a "coincidir con etiqueta". O sea que si hay más de un
dhcp-range en enu subred, y una tiene una etiqueta network-id la
cual está fijada (por ejemplo una opcion de clase de vendedor) entonces
dhcp-range en en una subred, y uno tiene una etiqueta network-id la
cual está fijada (por ejemplo una opción de clase de vendedor) entonces
hosts que fijen la etiqueta network-id serán alocados direcciones en
el rango etiquetado.
.PP
@@ -781,12 +935,55 @@ o en
, 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 mapeos estáticos.) El
Parámetro de nombre de archivos en un pedido BOOTP es revisado para
(Fijar --bootp-dynamic elimina la necesidad de trazados estáticos.) El
parámetro de nombre de archivos en un pedido BOOTP es revisado para
ver si coincide con algún network-id en configuraciónes
.B dhcp-option
permitiendo algún control sobre las opciones devueltas a diferentes
clases de hosts.
al igual que la etiqueta "bootp", permitiendo así algún control sobre
las opciones devueltas a diferentes clases de hosts.
.SH LIMITES
Los valores predeterminados para limites de recursos son generálmente
conservadores, y apropiados para uso en dispositivos tipo enrutador
encrustrado con procesadores lentos y poca memoria. En hardware más
capáz, es posible incrementar los límites, y soportar muchos mas
clientes. Lo siguiente se aplica a dnsmasq-2.37: versiones previas
no escalaban tan bien.
.PP
Dnsmasq es capaz de soportar con DNS y DHCP a por lo menos mil (1,000)
clientes. Por supuesto que para lograr esto debe ser aumentadoo el valor de
.B --dhcp-lease-max
debe ser incrementado, y tiempos de arriendo no deben ser muy cortos
(menos de una hora). El valor de
.B --dns-forward-max
puede ser aumentado: comienze con el equivalente a el número de clientes y
auméntelo si parece lento el DNS. Nótese que el rendimiento DNS depende
también de los servidores DNS upstream. El tamaño del caché DNS puede ser
incrementado: el límite obligatorio es 10,000 nombres y el predeterminado
(150) es muy bajo. Enviarle un SIGUSR1 a dnsmasq hace que bitacorée
información que es útil para afinar el tamaño de caché. Ver la sección
.B NOTAS
para detalles.
.PP
El servidor TFTP incorporado es capáz de soportar varias transferencias
simultáneas de archivos: el límite absoluto está relacionado con el número
de file-handles permitidos a un proceso y la habilidad del system call
select() a soportar números grandes de file-handles. Si el límite es fijado
demasiado alto con
.B --tftp-max
será de-escalado y el límite real será bitacoreado al inicio. Nótese que más
transferencias son posibles cuando el mismo archivo es enviado qué cuando
cada transferencia envía un archivo diferente.
.PP
Es posible usar dnsmasq para negar publicidad Web usando una lista de
servidores de banners bien conocidos, todos resolviendose a 127.0.0.1 o
0.0.0.0 en
.B /etc/hosts
o en un archivo hosts adicional. La lista puede ser muy larga. Dnsmasq ha sido
probado exitósamente con un millón de nombres. Ese tamaño de archivo necesita
un CPU de 1GHz y aproximadamente 60MB de RAM.
.SH ARCHIVOS
.IR /etc/dnsmasq.conf

914
po/de.po

File diff suppressed because it is too large Load Diff

848
po/es.po

File diff suppressed because it is too large Load Diff

896
po/fi.po

File diff suppressed because it is too large Load Diff

742
po/fr.po

File diff suppressed because it is too large Load Diff

759
po/id.po

File diff suppressed because it is too large Load Diff

896
po/it.po

File diff suppressed because it is too large Load Diff

734
po/no.po

File diff suppressed because it is too large Load Diff

728
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

734
po/ro.po

File diff suppressed because it is too large Load Diff

View File

@@ -73,8 +73,8 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len,
/* Only know how to do ethernet on *BSD */
if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN)
{
syslog(LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"),
mess->htype, ifr->ifr_name);
my_syslog(LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"),
mess->htype, ifr->ifr_name);
return;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2005 Simon Kelley
/* dnsmasq is Copyright (c) 2000-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
@@ -13,7 +13,7 @@
#include "dnsmasq.h"
static struct crec *cache_head, *cache_tail, **hash_table;
static struct crec *dhcp_inuse, *dhcp_spare, *new_chain;
static struct crec *dhcp_spare, *new_chain;
static int cache_inserted, cache_live_freed, insert_error;
static union bigname *big_free;
static int bignames_left, log_queries, cache_size, hash_size;
@@ -46,6 +46,8 @@ static const struct {
{ 38, "A6" },
{ 39, "DNAME" },
{ 41, "OPT" },
{ 48, "DNSKEY" },
{ 249, "TKEY" },
{ 250, "TSIG" },
{ 251, "IXFR" },
{ 252, "AXFR" },
@@ -72,7 +74,7 @@ void cache_init(int size, int logq)
addrbuff = NULL;
cache_head = cache_tail = NULL;
dhcp_inuse = dhcp_spare = NULL;
dhcp_spare = NULL;
new_chain = NULL;
hash_table = NULL;
cache_size = size;
@@ -155,9 +157,24 @@ static struct crec **hash_bucket(char *name)
static void cache_hash(struct crec *crecp)
{
struct crec **bucket = hash_bucket(cache_get_name(crecp));
crecp->hash_next = *bucket;
*bucket = 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)
@@ -256,10 +273,13 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
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) */
struct crec *crecp, **up;
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)
@@ -294,7 +314,9 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
int addrlen = INADDRSZ;
#endif
for (i = 0; i < hash_size; i++)
for (crecp = hash_table[i], up = &hash_table[i]; crecp; crecp = crecp->hash_next)
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;
@@ -565,16 +587,19 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
else
{
/* first search, look for relevant entries and push to top of list
also free anything which has expired */
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 = crecp->hash_next)
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 & F_REVERSE) &&
(crecp->flags & prot) &&
if ((crecp->flags & prot) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
{
if (crecp->flags & (F_HOSTS | F_DHCP))
@@ -636,15 +661,19 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
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;
}
{
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);
@@ -662,7 +691,7 @@ static int read_hostsfile(char *filename, int opts, char *buff, char *domain_suf
if (!f)
{
syslog(LOG_ERR, _("failed to load names from %s: %m"), filename);
my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
return 0;
}
@@ -696,7 +725,7 @@ static int read_hostsfile(char *filename, int opts, char *buff, char *domain_suf
#endif
else
{
syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
continue;
}
@@ -720,10 +749,11 @@ static int read_hostsfile(char *filename, int opts, char *buff, char *domain_suf
while ((token = strtok(NULL, " \t\n\r")) && (*token != '#'))
{
struct crec *cache;
int fqdn = !!strchr(token, '.');
if (canonicalise(token))
{
/* If set, add a version of the name with a default domain appended */
if ((opts & OPT_EXPAND) && domain_suffix && !strchr(token, '.') &&
if ((opts & OPT_EXPAND) && domain_suffix && !fqdn &&
(cache = malloc(sizeof(struct crec) +
strlen(token)+2+strlen(domain_suffix)-SMALLDNAME)))
{
@@ -742,14 +772,14 @@ static int read_hostsfile(char *filename, int opts, char *buff, char *domain_suf
}
}
else
syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
}
}
fclose(f);
rehash(name_count);
syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
return name_count;
}
@@ -787,7 +817,7 @@ void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *a
if ((opts & OPT_NO_HOSTS) && !addn_hosts)
{
if (cache_size > 0)
syslog(LOG_INFO, _("cleared cache"));
my_syslog(LOG_INFO, _("cleared cache"));
return;
}
@@ -802,25 +832,19 @@ void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *a
void cache_unhash_dhcp(void)
{
struct crec *tmp, *cache, **up;
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;
{
*up = cache->hash_next;
cache->next = dhcp_spare;
dhcp_spare = cache;
}
else
up = &cache->hash_next;
/* prev field links all dhcp entries */
for (cache = dhcp_inuse; cache; cache = tmp)
{
tmp = cache->prev;
cache->prev = dhcp_spare;
dhcp_spare = cache;
}
dhcp_inuse = NULL;
}
void cache_add_dhcp_entry(struct daemon *daemon, char *host_name,
@@ -839,11 +863,11 @@ void cache_add_dhcp_entry(struct daemon *daemon, char *host_name,
if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
{
strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
syslog(LOG_WARNING,
_("not giving name %s to the DHCP lease of %s because "
"the name exists in %s with address %s"),
host_name, inet_ntoa(*host_address),
record_source(daemon->addn_hosts, crec->uid), daemon->namebuff);
my_syslog(LOG_WARNING,
_("not giving name %s to the DHCP lease of %s because "
"the name exists in %s with address %s"),
host_name, inet_ntoa(*host_address),
record_source(daemon->addn_hosts, crec->uid), daemon->namebuff);
}
return;
}
@@ -861,7 +885,7 @@ void cache_add_dhcp_entry(struct daemon *daemon, char *host_name,
}
if ((crec = dhcp_spare))
dhcp_spare = dhcp_spare->prev;
dhcp_spare = dhcp_spare->next;
else /* need new one */
crec = malloc(sizeof(struct crec));
@@ -874,72 +898,69 @@ void cache_add_dhcp_entry(struct daemon *daemon, char *host_name,
crec->ttd = ttd;
crec->addr.addr.addr.addr4 = *host_address;
crec->name.namep = host_name;
crec->prev = dhcp_inuse;
dhcp_inuse = crec;
cache_hash(crec);
}
}
void dump_cache(struct daemon *daemon, time_t now)
{
syslog(LOG_INFO, _("time %lu, cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
(unsigned long)now, daemon->cachesize, cache_live_freed, cache_inserted);
my_syslog(LOG_INFO, _("time %lu, cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
(unsigned long)now, daemon->cachesize, cache_live_freed, cache_inserted);
if ((daemon->options & (OPT_DEBUG | OPT_LOG)) &&
(addrbuff || (addrbuff = malloc(ADDRSTRLEN))))
{
struct crec *cache ;
int i;
syslog(LOG_DEBUG, "Host Address Flags Expires");
my_syslog(LOG_DEBUG, "Host Address Flags Expires");
for (i=0; i<hash_size; i++)
for (cache = hash_table[i]; cache; cache = cache->hash_next)
{
char *a, *p = daemon->namebuff;
p += sprintf(p, "%-40.40s ", cache_get_name(cache));
if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD))
addrbuff[0] = 0;
a = "";
else if (cache->flags & F_CNAME)
{
addrbuff[0] = 0;
addrbuff[ADDRSTRLEN-1] = 0;
a = "";
if (!is_outdated_cname_pointer(cache))
strncpy(addrbuff, cache_get_name(cache->addr.cname.cache), ADDRSTRLEN);
a = cache_get_name(cache->addr.cname.cache);
}
#ifdef HAVE_IPV6
else 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
{
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
strcpy(addrbuff, inet_ntoa(cache->addr.addr.addr.addr4));
a = inet_ntoa(cache->addr.addr.addr.addr4);
#endif
syslog(LOG_DEBUG,
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
"%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %lu",
p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
#else
"%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %s",
p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
/* ctime includes trailing \n - eat it */
*(p-1) = 0;
#endif
cache_get_name(cache), addrbuff,
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
cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now)
#else
cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd))
#endif
);
}
}
my_syslog(LOG_DEBUG, daemon->namebuff);
}
}
}
static char *record_source(struct hostsfile *addn_hosts, int index)
@@ -997,6 +1018,8 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr,
strcpy(addrbuff, "<SRV>");
else if (flags & F_NXDOMAIN)
strcpy(addrbuff, "<TXT>");
else if (flags & F_BIGNAME)
strcpy(addrbuff, "<PTR>");
else
strcpy(addrbuff, "<CNAME>");
}
@@ -1042,8 +1065,8 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr,
name = ".";
if ((flags & F_FORWARD) | (flags & F_NEG))
syslog(LOG_DEBUG, "%s %s %s %s", source, name, verb, addrbuff);
my_syslog(LOG_DEBUG, "%s %s %s %s", source, name, verb, addrbuff);
else if (flags & F_REVERSE)
syslog(LOG_DEBUG, "%s %s is %s", source, addrbuff, name);
my_syslog(LOG_DEBUG, "%s %s is %s", source, addrbuff, name);
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
/* dnsmasq is Copyright (c) 2000-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
@@ -10,7 +10,7 @@
GNU General Public License for more details.
*/
#define VERSION "2.35"
#define VERSION "2.39"
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
@@ -48,6 +48,9 @@
#define CHGRP "dip"
#define DHCP_SERVER_PORT 67
#define DHCP_CLIENT_PORT 68
#define TFTP_PORT 69
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
#define LOG_MAX 5 /* log-queue length */
/* DBUS interface specifics */
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
@@ -55,6 +58,10 @@
/* A small collection of RR-types which are missing on some platforms */
#ifndef T_SIG
# define T_SIG 24
#endif
#ifndef T_SRV
# define T_SRV 33
#endif
@@ -63,6 +70,15 @@
# define T_OPT 41
#endif
#ifndef T_TKEY
# define T_TKEY 249
#endif
#ifndef T_TSIG
# define T_TSIG 250
#endif
/* Get linux C library versions. */
#if defined(__linux__) && !defined(__UCLIBC__) && !defined(__uClinux__)
/*# include <libio.h> */
@@ -98,6 +114,9 @@ HAVE_ISC_READER
define this to include the old ISC dhcpcd integration. Note that you cannot
set both HAVE_ISC_READER and HAVE_BROKEN_RTC.
HAVE_TFTP
define this to get dnsmasq's built-in TFTP server.
HAVE_GETOPT_LONG
define this if you have GNU libc or GNU getopt.
@@ -153,6 +172,7 @@ NOTES:
*/
/* platform independent options- uncomment to enable */
#define HAVE_TFTP
/* #define HAVE_BROKEN_RTC */
/* #define HAVE_ISC_READER */
/* #define HAVE_DBUS */
@@ -161,6 +181,11 @@ NOTES:
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
#endif
/* Allow TFTP to be disabled with COPT=-DNO_TFTP */
#ifdef NO_TFTP
#undef HAVE_TFTP
#endif
/* platform dependent options. */
/* Must preceed __linux__ since uClinux defines __linux__ too. */
@@ -252,6 +277,7 @@ typedef unsigned long in_addr_t;
#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 */

View File

@@ -109,7 +109,7 @@ static void dbus_read_servers(struct daemon *daemon, DBusMessage *message)
}
#ifndef HAVE_IPV6
syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
#else
if (i == sizeof(struct in6_addr)-1)
{
@@ -208,6 +208,7 @@ static void dbus_read_servers(struct daemon *daemon, DBusMessage *message)
tmp = serv->next;
if (serv->flags & SERV_MARK)
{
server_gone(daemon, serv);
*up = serv->next;
free(serv);
}
@@ -235,7 +236,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
}
else if (strcmp(method, "SetServers") == 0)
{
syslog(LOG_INFO, _("setting upstream servers from DBus"));
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
dbus_read_servers(daemon, message);
check_servers(daemon);
}

View File

@@ -117,7 +117,7 @@ void dhcp_packet(struct daemon *daemon, time_t now)
struct iovec iov;
ssize_t sz;
int iface_index = 0, unicast_dest = 0;
struct in_addr iface_addr;
struct in_addr iface_addr, *addrp = NULL;
struct iface_param parm;
union {
@@ -185,7 +185,7 @@ void dhcp_packet(struct daemon *daemon, time_t now)
if (!(msg.msg_flags & MSG_BCAST))
unicast_dest = 1;
#endif
#else
/* fallback for systems without IP_RECVIF - allow only one interface
and assume packets arrive from it - yuk. */
@@ -198,16 +198,30 @@ void dhcp_packet(struct daemon *daemon, time_t now)
#endif
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1 )
return;
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
{
addrp = &iface_addr;
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
if (!iface_check(daemon, AF_INET, (struct all_addr *)addrp, &ifr, &iface_index))
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return;
if (!iface_check(daemon, AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name))
return;
/* interface may have been changed by alias in iface_check */
if (!addrp)
{
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1)
{
my_syslog(LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
return;
}
else
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
/* unlinked contexts are marked by context->current == context */
for (context = daemon->dhcp; context; context = context->next)
@@ -333,8 +347,8 @@ static int complete_context(struct daemon *daemon, struct in_addr local, int if_
{
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
syslog(LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
my_syslog(LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
}
context->netmask = netmask;
}
@@ -650,7 +664,7 @@ void dhcp_read_ethers(struct daemon *daemon)
if (!f)
{
syslog(LOG_ERR, _("failed to read %s:%m"), ETHERSFILE);
my_syslog(LOG_ERR, _("failed to read %s:%s"), ETHERSFILE, strerror(errno));
return;
}
@@ -685,7 +699,7 @@ void dhcp_read_ethers(struct daemon *daemon)
*ip = 0;
if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
{
syslog(LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
my_syslog(LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno);
continue;
}
@@ -698,7 +712,7 @@ void dhcp_read_ethers(struct daemon *daemon)
{
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
{
syslog(LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
my_syslog(LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
continue;
}
@@ -712,7 +726,7 @@ void dhcp_read_ethers(struct daemon *daemon)
{
if (!canonicalise(ip))
{
syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
my_syslog(LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno);
continue;
}
@@ -766,7 +780,7 @@ void dhcp_read_ethers(struct daemon *daemon)
fclose(f);
syslog(LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
my_syslog(LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
}
void dhcp_update_configs(struct dhcp_config *configs)
@@ -792,8 +806,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
(crec->flags & F_HOSTS))
{
if (config_find_by_address(configs, crec->addr.addr.addr.addr4))
syslog(LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
inet_ntoa(crec->addr.addr.addr.addr4), config->hostname);
my_syslog(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;
@@ -828,7 +842,7 @@ char *strip_hostname(struct daemon *daemon, char *hostname)
{
if (!daemon->domain_suffix || !hostname_isequal(dot+1, daemon->domain_suffix))
{
syslog(LOG_WARNING, _("Ignoring DHCP host name %s because it has an illegal domain part"), hostname);
my_syslog(LOG_WARNING, _("Ignoring DHCP host name %s because it has an illegal domain part"), hostname);
hostname = NULL;
}
else

View File

@@ -38,7 +38,11 @@ static char *compile_opts =
#ifdef NO_GETTEXT
"no-"
#endif
"I18N ";
"I18N "
#ifndef HAVE_TFTP
"no-"
#endif
"TFTP";
static pid_t pid;
static int pipewrite;
@@ -55,7 +59,7 @@ int main (int argc, char **argv)
time_t now, last = 0;
struct sigaction sigact;
struct iname *if_tmp;
int piperead, pipefd[2];
int piperead, pipefd[2], log_fd;
unsigned char sig;
#ifndef NO_GETTEXT
@@ -80,6 +84,7 @@ int main (int argc, char **argv)
sigaction(SIGPIPE, &sigact, NULL);
daemon = read_opts(argc, argv, compile_opts);
log_fd = log_start(daemon);
if (daemon->edns_pktsz < PACKETSZ)
daemon->edns_pktsz = PACKETSZ;
@@ -109,6 +114,11 @@ int main (int argc, char **argv)
}
#endif
#ifndef HAVE_TFTP
if (daemon->options & OPT_TFTP)
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL);
#endif
daemon->interfaces = NULL;
if (!enumerate_interfaces(daemon))
die(_("failed to find list of interfaces: %s"), NULL);
@@ -128,7 +138,7 @@ int main (int argc, char **argv)
die(_("no interface with address %s"), daemon->namebuff);
}
}
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port)))
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port, daemon->options & OPT_TFTP)))
die(_("failed to create listening socket: %s"), NULL);
cache_init(daemon->cachesize, daemon->options & OPT_LOG);
@@ -241,7 +251,7 @@ int main (int argc, char **argv)
#endif
for (i=0; i<64; i++)
{
if (i == piperead || i == pipewrite)
if (i == piperead || i == pipewrite || i == log_fd)
continue;
#ifdef HAVE_LINUX_NETWORK
@@ -270,8 +280,8 @@ int main (int argc, char **argv)
}
/* if we are to run scripts, we need to fork a helper before dropping root. */
daemon->helperfd = create_helper(daemon);
daemon->helperfd = create_helper(daemon, log_fd);
if (!(daemon->options & OPT_DEBUG))
{
/* UID changing, etc */
@@ -326,45 +336,48 @@ int main (int argc, char **argv)
}
}
log_start(daemon);
#ifdef HAVE_LINUX_NETWORK
if (daemon->options & OPT_DEBUG)
prctl(PR_SET_DUMPABLE, 1);
#endif
if (daemon->cachesize != 0)
syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
else
syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
#ifdef HAVE_DBUS
if (daemon->options & OPT_DBUS)
{
if (daemon->dbus)
syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
else
syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
}
#endif
if (bind_fallback)
syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
if (!(daemon->options & OPT_NOWILD))
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
if (daemon->options & OPT_NO_RESOLV)
{
if (daemon->resolv_files && !daemon->resolv_files->is_default)
syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
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);
if (daemon->dhcp)
{
struct dhcp_context *dhcp_tmp;
@@ -373,22 +386,59 @@ int main (int argc, char **argv)
{
prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
syslog(LOG_INFO,
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("DHCP, static leases only on %.0s%s, lease time %s") :
_("DHCP, IP range %s -- %s, lease time %s"),
daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
my_syslog(LOG_INFO,
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("DHCP, static leases only on %.0s%s, lease time %s") :
_("DHCP, IP range %s -- %s, lease time %s"),
daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
}
}
#ifdef HAVE_TFTP
if (daemon->options & OPT_TFTP)
{
long max_fd = sysconf(_SC_OPEN_MAX);
#ifdef FD_SETSIZE
if (FD_SETSIZE < max_fd)
max_fd = FD_SETSIZE;
#endif
my_syslog(LOG_INFO, "TFTP %s%s %s",
daemon->tftp_prefix ? _("root is ") : _("enabled"),
daemon->tftp_prefix ? daemon->tftp_prefix: "",
daemon->options & OPT_TFTP_SECURE ? _("secure mode") : "");
/* This is a guess, it assumes that for small limits,
disjoint files might be served, but for large limits,
a single file will be sent to may clients (the file only needs
one fd). */
max_fd -= 30; /* use other than TFTP */
if (max_fd < 0)
max_fd = 5;
else if (max_fd < 100)
max_fd = max_fd/2;
else
max_fd = max_fd - 20;
if (daemon->tftp_max > max_fd)
{
daemon->tftp_max = max_fd;
my_syslog(LOG_WARNING,
_("restricting maximum simultaneous TFTP transfers to %d"),
daemon->tftp_max);
}
}
#endif
if (!(daemon->options & OPT_DEBUG) && (getuid() == 0 || geteuid() == 0))
{
if (bad_capabilities)
{
errno = bad_capabilities;
syslog(LOG_WARNING, _("warning: setting capabilities failed: %m"));
}
syslog(LOG_WARNING, _("running as root"));
my_syslog(LOG_WARNING, _("warning: setting capabilities failed: %s"), strerror(bad_capabilities));
my_syslog(LOG_WARNING, _("running as root"));
}
check_servers(daemon);
@@ -414,15 +464,16 @@ int main (int argc, char **argv)
tp = &t;
}
#ifdef HAVE_DBUS
/* Whilst polling for the dbus, wake every quarter second */
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
if (daemon->tftp_trans ||
((daemon->options & OPT_DBUS) && !daemon->dbus))
{
t.tv_sec = 0;
t.tv_usec = 250000;
tp = &t;
}
#ifdef HAVE_DBUS
set_dbus_listeners(daemon, &maxfd, &rset, &wset, &eset);
#endif
@@ -447,7 +498,11 @@ int main (int argc, char **argv)
FD_SET(daemon->helperfd, &wset);
bump_maxfd(daemon->helperfd, &maxfd);
}
/* 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 */
@@ -456,6 +511,8 @@ int main (int argc, char **argv)
now = dnsmasq_time();
check_log_writer(&wset);
/* Check for changes to resolv files once per second max. */
/* Don't go silent for long periods if the clock goes backwards. */
if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < -1.0)
@@ -479,7 +536,7 @@ int main (int argc, char **argv)
if (stat(res->name, &statbuf) == -1)
{
if (!res->logged)
syslog(LOG_WARNING, _("failed to access %s: %m"), res->name);
my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
res->logged = 1;
}
else
@@ -501,7 +558,7 @@ int main (int argc, char **argv)
static int warned = 0;
if (reload_servers(latest->name, daemon))
{
syslog(LOG_INFO, _("reading %s"), latest->name);
my_syslog(LOG_INFO, _("reading %s"), latest->name);
warned = 0;
check_servers(daemon);
if (daemon->options & OPT_RELOAD)
@@ -512,7 +569,7 @@ int main (int argc, char **argv)
latest->mtime = 0;
if (!warned)
{
syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
warned = 1;
}
}
@@ -571,7 +628,7 @@ int main (int argc, char **argv)
if (daemon->lease_stream)
fclose(daemon->lease_stream);
syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
exit(0);
}
@@ -606,15 +663,19 @@ int main (int argc, char **argv)
{
char *err;
if ((err = dbus_init(daemon)))
syslog(LOG_WARNING, _("DBus error: %s"), err);
my_syslog(LOG_WARNING, _("DBus error: %s"), err);
if (daemon->dbus)
syslog(LOG_INFO, _("connected to system DBus"));
my_syslog(LOG_INFO, _("connected to system DBus"));
}
check_dbus_listeners(daemon, &rset, &wset, &eset);
#endif
check_dns_listeners(daemon, &rset, now);
#ifdef HAVE_TFTP
check_tftp_listeners(daemon, &rset, now);
#endif
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
dhcp_packet(daemon, now);
@@ -668,7 +729,18 @@ static int set_dns_listeners(struct daemon *daemon, time_t now, fd_set *set, int
struct serverfd *serverfdp;
struct listener *listener;
int wait, 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? */
get_new_frec(daemon, now, &wait);
@@ -696,8 +768,17 @@ static int set_dns_listeners(struct daemon *daemon, time_t now, fd_set *set, int
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;
}
@@ -705,116 +786,121 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
{
struct serverfd *serverfdp;
struct listener *listener;
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
if (FD_ISSET(serverfdp->fd, set))
reply_query(serverfdp, daemon, now);
for (listener = daemon->listeners; listener; listener = listener->next)
{
if (FD_ISSET(listener->fd, set))
receive_query(listener, daemon, now);
if (FD_ISSET(listener->tcpfd, set))
{
int confd;
struct irec *iface = NULL;
pid_t p;
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1)
continue;
if (daemon->options & OPT_NOWILD)
iface = listener->iface;
else
{
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces(daemon) &&
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
}
if (!iface)
{
shutdown(confd, SHUT_RDWR);
close(confd);
}
#ifndef NO_FORK
else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0)
{
if (p != -1)
{
int i;
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == 0)
{
daemon->tcp_pids[i] = p;
break;
}
}
close(confd);
}
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
if (FD_ISSET(serverfdp->fd, set))
reply_query(serverfdp, daemon, now);
for (listener = daemon->listeners; listener; listener = listener->next)
{
if (FD_ISSET(listener->fd, set))
receive_query(listener, daemon, now);
#ifdef HAVE_TFTP
if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
tftp_request(listener, daemon, now);
#endif
else
{
unsigned char *buff;
struct server *s;
int flags;
struct in_addr dst_addr_4;
dst_addr_4.s_addr = 0;
if (FD_ISSET(listener->tcpfd, set))
{
int confd;
struct irec *iface = NULL;
pid_t p;
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1)
continue;
if (daemon->options & OPT_NOWILD)
iface = listener->iface;
else
{
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces(daemon) &&
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
}
if (!iface)
{
shutdown(confd, SHUT_RDWR);
close(confd);
}
#ifndef NO_FORK
else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0)
{
if (p != -1)
{
int i;
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == 0)
{
daemon->tcp_pids[i] = p;
break;
}
}
close(confd);
}
#endif
else
{
unsigned char *buff;
struct server *s;
int flags;
struct in_addr dst_addr_4;
dst_addr_4.s_addr = 0;
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
terminate the process. */
if (!(daemon->options & OPT_DEBUG))
alarm(CHILD_LIFETIME);
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
if (!(daemon->options & OPT_DEBUG))
alarm(CHILD_LIFETIME);
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
s->tcpfd = -1;
/* The connected socket inherits non-blocking
attribute from the listening socket.
Reset that here. */
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
if (listener->family == AF_INET)
dst_addr_4 = iface->addr.in.sin_addr;
buff = tcp_request(daemon, confd, now, dst_addr_4, iface->netmask);
/* 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(daemon, 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);
}
shutdown(confd, SHUT_RDWR);
close(confd);
if (buff)
free(buff);
for (s = daemon->servers; s; s = s->next)
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
}
#ifndef NO_FORK
if (!(daemon->options & OPT_DEBUG))
_exit(0);
if (!(daemon->options & OPT_DEBUG))
_exit(0);
#endif
}
}
}
}
}
}
}
@@ -841,7 +927,7 @@ int icmp_ping(struct daemon *daemon, 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 sockets, (so doing that
(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. */
@@ -889,7 +975,7 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
difftime(now, start) < (float)PING_WAIT;)
{
struct timeval tv;
fd_set rset;
fd_set rset, wset;
struct sockaddr_in faddr;
int maxfd = fd;
socklen_t len = sizeof(faddr);
@@ -898,15 +984,26 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
tv.tv_sec = 0;
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_SET(fd, &rset);
set_dns_listeners(daemon, now, &rset, &maxfd);
if (select(maxfd+1, &rset, NULL, NULL, &tv) < 0)
FD_ZERO(&rset);
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(daemon, &rset, now);
#ifdef HAVE_TFTP
check_tftp_listeners(daemon, &rset, now);
#endif
if (FD_ISSET(fd, &rset) &&
recvfrom(fd, &packet, sizeof(packet), 0,
(struct sockaddr *)&faddr, &len) == sizeof(packet) &&

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2005 Simon Kelley
/* dnsmasq is Copyright (c) 2000-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
@@ -10,7 +10,7 @@
GNU General Public License for more details.
*/
#define COPYRIGHT "Copyright (C) 2000-2006 Simon Kelley"
#define COPYRIGHT "Copyright (C) 2000-2007 Simon Kelley"
/* get these before config.h for IPv6 stuff... */
#include <sys/types.h>
@@ -43,6 +43,7 @@
#include <sys/select.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/un.h>
#include <limits.h>
#include <net/if.h>
#include <unistd.h>
@@ -88,30 +89,34 @@ extern int capset(cap_user_header_t header, cap_user_data_t data);
*/
#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
#define OPT_BOGUSPRIV 1
#define OPT_FILTER 2
#define OPT_LOG 4
#define OPT_SELFMX 8
#define OPT_NO_HOSTS 16
#define OPT_NO_POLL 32
#define OPT_DEBUG 64
#define OPT_ORDER 128
#define OPT_NO_RESOLV 256
#define OPT_EXPAND 512
#define OPT_LOCALMX 1024
#define OPT_NO_NEG 2048
#define OPT_NODOTS_LOCAL 4096
#define OPT_NOWILD 8192
#define OPT_ETHERS 16384
#define OPT_RESOLV_DOMAIN 32768
#define OPT_NO_FORK 65536
#define OPT_AUTHORITATIVE 131072
#define OPT_LOCALISE 262144
#define OPT_DBUS 524288
#define OPT_BOOTP_DYNAMIC 1048576
#define OPT_NO_PING 2097152
#define OPT_LEASE_RO 4194304
#define OPT_RELOAD 8388608
#define OPT_BOGUSPRIV (1<<0)
#define OPT_FILTER (1<<1)
#define OPT_LOG (1<<2)
#define OPT_SELFMX (1<<3)
#define OPT_NO_HOSTS (1<<4)
#define OPT_NO_POLL (1<<5)
#define OPT_DEBUG (1<<6)
#define OPT_ORDER (1<<7)
#define OPT_NO_RESOLV (1<<8)
#define OPT_EXPAND (1<<9)
#define OPT_LOCALMX (1<<10)
#define OPT_NO_NEG (1<<11)
#define OPT_NODOTS_LOCAL (1<<12)
#define OPT_NOWILD (1<<13)
#define OPT_ETHERS (1<<14)
#define OPT_RESOLV_DOMAIN (1<<15)
#define OPT_NO_FORK (1<<16)
#define OPT_AUTHORITATIVE (1<<17)
#define OPT_LOCALISE (1<<18)
#define OPT_DBUS (1<<19)
#define OPT_BOOTP_DYNAMIC (1<<20)
#define OPT_NO_PING (1<<21)
#define OPT_LEASE_RO (1<<22)
#define OPT_RELOAD (1<<24)
#define OPT_TFTP (1<<25)
#define OPT_TFTP_SECURE (1<<26)
#define OPT_TFTP_NOBLOCK (1<<27)
#define OPT_LOG_OPTS (1<<28)
struct all_addr {
union {
@@ -146,6 +151,17 @@ struct txt_record {
struct txt_record *next;
};
struct ptr_record {
char *name, *ptr;
struct ptr_record *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 */
@@ -239,11 +255,12 @@ struct server {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int dhcp_ok;
struct irec *next;
};
struct listener {
int fd, tcpfd, family;
int fd, tcpfd, tftpfd, family;
struct irec *iface; /* only valid for non-wildcard */
struct listener *next;
};
@@ -274,7 +291,7 @@ struct hostsfile {
struct frec {
union mysockaddr source;
struct all_addr dest;
struct server *sentto;
struct server *sentto; /* NULL means free */
unsigned int iface;
unsigned short orig_id, new_id;
int fd, forwardall;
@@ -357,6 +374,9 @@ struct dhcp_opt {
#define DHOPT_ADDR 1
#define DHOPT_STRING 2
#define DHOPT_ENCAPSULATE 4
#define DHOPT_VENDOR_MATCH 8
#define DHOPT_FORCE 16
struct dhcp_boot {
char *file, *sname;
@@ -365,8 +385,15 @@ struct dhcp_boot {
struct dhcp_boot *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, is_vendor;
int len, match_type;
char *data;
struct dhcp_netid netid;
struct dhcp_vendor *next;
@@ -380,6 +407,13 @@ struct dhcp_mac {
struct dhcp_mac *next;
};
#if defined(__FreeBSD__) || defined(__DragonFly__)
struct dhcp_bridge {
char iface[IF_NAMESIZE];
struct dhcp_bridge *alias, *next;
};
#endif
struct dhcp_context {
unsigned int lease_time, addr_epoch;
struct in_addr netmask, broadcast;
@@ -415,6 +449,23 @@ struct ping_result {
struct ping_result *next;
};
struct tftp_file {
int refcount, fd;
off_t size;
char filename[];
};
struct tftp_transfer {
int sockfd;
time_t timeout;
int backoff;
unsigned int block, blocksize;
struct sockaddr_in peer;
char opt_blocksize, opt_transize;
struct tftp_file *file;
struct tftp_transfer *next;
};
struct daemon {
/* datastuctures representing the command-line and
config file arguments. All set (including defaults)
@@ -424,6 +475,8 @@ struct daemon {
struct resolvc default_resolv, *resolv_files;
struct mx_srv_record *mxnames;
struct txt_record *txt;
struct ptr_record *ptr;
struct interface_name *int_names;
char *mxtarget;
char *lease_file;
char *username, *groupname;
@@ -434,18 +487,20 @@ struct daemon {
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;
unsigned long local_ttl;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp;
struct dhcp_config *dhcp_conf;
struct dhcp_opt *dhcp_opts, *vendor_opts;
struct dhcp_opt *dhcp_opts;
struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
struct dhcp_netid_list *dhcp_ignore;
int dhcp_max;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names;
int dhcp_max, tftp_max;
unsigned int min_leasetime;
struct doctor *doctors;
unsigned short edns_pktsz;
@@ -473,14 +528,20 @@ struct daemon {
char *dhcp_buff, *dhcp_buff2;
struct ping_result *ping_results;
FILE *lease_stream;
#if defined(__FreeBSD__) || defined(__DragonFly__)
struct dhcp_bridge *bridges;
#endif
/* DBus stuff */
#ifdef HAVE_DBUS
/* 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;
char *tftp_prefix;
};
/* cache.c */
@@ -515,7 +576,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen, struct daemon *d
int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now);
unsigned char *find_pseudoheader(HEADER *header, size_t plen,
size_t *len, unsigned char **p);
size_t *len, unsigned char **p, int *is_sign);
int check_for_local_domain(char *name, time_t now, struct daemon *daemon);
unsigned int questions_crc(HEADER *header, size_t plen, char *buff);
size_t resize_packet(HEADER *header, size_t plen,
@@ -526,8 +587,6 @@ unsigned short rand16(void);
int legal_char(char c);
int canonicalise(char *s);
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
void die(char *message, char *arg1);
void complain(char *message, int lineno, char *file);
void *safe_malloc(size_t size);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
@@ -544,11 +603,18 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len,
int expand_buf(struct iovec *iov, size_t size);
char *print_mac(struct daemon *daemon, unsigned char *mac, int len);
void bump_maxfd(int fd, int *max);
void log_start(struct daemon *daemon);
int read_write(int fd, unsigned char *packet, int size, int rw);
/* log.c */
void die(char *message, char *arg1);
int log_start(struct daemon *daemon);
void my_syslog(int priority, const char *format, ...);
void set_log_writer(fd_set *set, int *maxfdp);
void check_log_writer(fd_set *set);
/* option.c */
struct daemon *read_opts (int argc, char **argv, char *compile_opts);
char *option_string(unsigned char opt);
/* forward.c */
void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now);
@@ -563,11 +629,12 @@ struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds);
int reload_servers(char *fname, struct daemon *daemon);
void check_servers(struct daemon *daemon);
int enumerate_interfaces(struct daemon *daemon);
struct listener *create_wildcard_listeners(int port);
struct listener *create_wildcard_listeners(int port, int have_tftp);
struct listener *create_bound_listeners(struct daemon *daemon);
int iface_check(struct daemon *daemon, int family,
struct all_addr *addr, char *name);
int iface_check(struct daemon *daemon, int family, struct all_addr *addr,
struct ifreq *ifr, int *indexp);
int fix_fd(int fd);
struct in_addr get_ifaddr(struct daemon* daemon, char *intr);
/* dhcp.c */
void dhcp_init(struct daemon *daemon);
@@ -647,8 +714,14 @@ void set_dbus_listeners(struct daemon *daemon, int *maxfdp,
#endif
/* helper.c */
int create_helper(struct daemon *daemon);
int create_helper(struct daemon *daemon, int log_fd);
void helper_write(struct daemon *daemon);
void queue_script(struct daemon *daemon, int action,
struct dhcp_lease *lease, char *hostname);
int helper_buf_empty(void);
/* tftp.c */
#ifdef HAVE_TFTP
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

View File

@@ -14,11 +14,11 @@
static struct frec *frec_list = NULL;
static struct frec *lookup_frec(unsigned short id);
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(void);
static unsigned short get_id(int force, unsigned short force_id, unsigned int crc);
/* Send a UDP packet with it's source address set as "source"
@@ -163,7 +163,7 @@ static unsigned short search_servers(struct daemon *daemon, time_t now, struct a
{
if ((sflag | F_QUERY ) & qtype)
{
flags = qtype;
flags = qtype & ~F_BIGNAME;
if (serv->addr.sa.sa_family == AF_INET)
*addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
#ifdef HAVE_IPV6
@@ -184,7 +184,9 @@ static unsigned short search_servers(struct daemon *daemon, time_t now, struct a
else
log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0, NULL, 0);
}
else if (qtype && (daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
else if (qtype && !(qtype & F_BIGNAME) &&
(daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
/* don't forward simple names, make exception from NS queries and empty name. */
flags = F_NXDOMAIN;
if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now, daemon))
@@ -237,12 +239,16 @@ static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *ud
if (forward)
{
/* force unchanging id for signed packets */
int is_sign;
find_pseudoheader(header, plen, NULL, NULL, &is_sign);
forward->source = *udpaddr;
forward->dest = *dst_addr;
forward->iface = dst_iface;
forward->new_id = get_id();
forward->fd = udpfd;
forward->orig_id = ntohs(header->id);
forward->new_id = get_id(is_sign, forward->orig_id, crc);
forward->fd = udpfd;
forward->crc = crc;
forward->forwardall = 0;
header->id = htons(forward->new_id);
@@ -325,7 +331,7 @@ static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *ud
/* could not send on, prepare to return */
header->id = htons(forward->orig_id);
forward->new_id = 0; /* cancel */
forward->sentto = NULL; /* cancel */
}
/* could not send on, return empty answer or address if known for whole domain */
@@ -339,17 +345,17 @@ static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *ud
}
static size_t process_reply(struct daemon *daemon, HEADER *header, time_t now,
unsigned int query_crc, struct server *server, size_t n)
struct server *server, size_t n)
{
unsigned char *pheader, *sizep;
int munged = 0;
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. */
requests for the client. We can't do this for signed packets. */
if ((pheader = find_pseudoheader(header, n, &plen, &sizep)))
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
{
unsigned short udpsz;
unsigned char *psave = sizep;
@@ -367,7 +373,7 @@ static size_t process_reply(struct daemon *daemon, HEADER *header, time_t now,
server && !(server->flags & SERV_WARNED_RECURSIVE))
{
prettyprint_addr(&server->addr, daemon->namebuff);
syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
if (!(daemon->options & OPT_LOG))
server->flags |= SERV_WARNED_RECURSIVE;
}
@@ -392,12 +398,8 @@ static size_t process_reply(struct daemon *daemon, HEADER *header, time_t now,
header->aa = 1;
header->rcode = NOERROR;
}
/* 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 (query_crc == questions_crc(header, n, daemon->namebuff))
extract_addresses(header, n, daemon->namebuff, now, daemon);
extract_addresses(header, n, daemon->namebuff, now, daemon);
}
/* do this after extract_addresses. Ensure NODATA reply and remove
@@ -421,16 +423,16 @@ void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
{
/* packet from peer server, extract data for cache, and send to
original requester */
struct frec *forward;
HEADER *header;
union mysockaddr serveraddr;
struct frec *forward;
socklen_t addrlen = sizeof(serveraddr);
ssize_t n = recvfrom(sfd->fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
size_t nn;
/* 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 = sfd->source_addr.sa.sa_family;
#ifdef HAVE_IPV6
@@ -439,51 +441,57 @@ void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
#endif
header = (HEADER *)daemon->packet;
forward = lookup_frec(ntohs(header->id));
if (n >= (int)sizeof(HEADER) && header->qr && forward)
if (n >= (int)sizeof(HEADER) && header->qr &&
(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff))))
{
struct server *server = forward->sentto;
if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0)
/* for broken servers, attempt to send to another one. */
{
unsigned char *pheader;
size_t plen;
/* recreate query from reply */
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL);
header->ancount = htons(0);
header->nscount = htons(0);
header->arcount = htons(0);
if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
{
header->qr = 0;
header->tc = 0;
forward_query(daemon, -1, NULL, NULL, 0, header, nn, now, forward);
return;
}
}
if ((forward->sentto->flags & SERV_TYPE) == 0)
{
if (header->rcode == SERVFAIL || header->rcode == REFUSED)
server = NULL;
else
{
struct server *last_server;
/* find good server by address if possible, otherwise assume the last one we sent to */
for (last_server = daemon->servers; last_server; last_server = last_server->next)
if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
sockaddr_isequal(&last_server->addr, &serveraddr))
{
server = last_server;
break;
}
}
daemon->last_server = server;
}
struct server *server = forward->sentto;
if ((header->rcode == SERVFAIL || header->rcode == REFUSED) &&
!(daemon->options & OPT_ORDER) &&
forward->forwardall == 0)
/* for broken servers, attempt to send to another one. */
{
unsigned char *pheader;
size_t plen;
int is_sign;
/* recreate query from reply */
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
if (!is_sign)
{
header->ancount = htons(0);
header->nscount = htons(0);
header->arcount = htons(0);
if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
{
header->qr = 0;
header->tc = 0;
forward_query(daemon, -1, NULL, NULL, 0, header, nn, now, forward);
return;
}
}
}
if ((forward->sentto->flags & SERV_TYPE) == 0)
{
if (header->rcode == SERVFAIL || header->rcode == REFUSED)
server = NULL;
else
{
struct server *last_server;
/* find good server by address if possible, otherwise assume the last one we sent to */
for (last_server = daemon->servers; last_server; last_server = last_server->next)
if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
sockaddr_isequal(&last_server->addr, &serveraddr))
{
server = last_server;
break;
}
}
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
@@ -491,14 +499,14 @@ void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
if (forward->forwardall == 0 || --forward->forwardall == 1 ||
(header->rcode != REFUSED && header->rcode != SERVFAIL))
{
if ((nn = process_reply(daemon, header, now, forward->crc, server, (size_t)n)))
if ((nn = process_reply(daemon, header, now, server, (size_t)n)))
{
header->id = htons(forward->orig_id);
header->ra = 1; /* recursion if available */
send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn,
&forward->source, &forward->dest, forward->iface);
}
forward->new_id = 0; /* cancel */
forward->sentto = NULL; /* cancel */
}
}
}
@@ -611,27 +619,24 @@ void receive_query(struct listener *listen, struct daemon *daemon, time_t now)
if (if_index == 0)
return;
if (daemon->if_except || daemon->if_names || (daemon->options & OPT_LOCALISE))
{
#ifdef SIOCGIFNAME
ifr.ifr_ifindex = if_index;
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
return;
#else
if (!if_indextoname(if_index, ifr.ifr_name))
return;
#endif
if (listen->family == AF_INET &&
(daemon->options & OPT_LOCALISE) &&
ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1)
return;
netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
if (!iface_check(daemon, listen->family, &dst_addr, ifr.ifr_name))
ifr.ifr_ifindex = if_index;
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
return;
#else
if (!if_indextoname(if_index, ifr.ifr_name))
return;
#endif
if (!iface_check(daemon, listen->family, &dst_addr, &ifr, &if_index))
return;
if (listen->family == AF_INET &&
(daemon->options & OPT_LOCALISE) &&
ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1)
return;
netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
@@ -788,9 +793,13 @@ unsigned char *tcp_request(struct daemon *daemon, int confd, time_t now,
#endif
/* There's no point in updating the cache, since this process will exit and
lose the information after one query. We make this call for the alias and
lose the information after a few queries. We make this call for the alias and
bogus-nxdomain side-effects. */
m = process_reply(daemon, header, now, crc, last_server, (unsigned int)m);
/* 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(daemon, header, now, last_server, (unsigned int)m);
break;
}
@@ -818,7 +827,7 @@ static struct frec *allocate_frec(time_t now)
{
f->next = frec_list;
f->time = now;
f->new_id = 0;
f->sentto = NULL;
frec_list = f;
}
@@ -837,7 +846,7 @@ struct frec *get_new_frec(struct daemon *daemon, time_t now, int *wait)
*wait = 0;
for (f = frec_list, oldest = NULL, count = 0; f; f = f->next, count++)
if (f->new_id == 0)
if (!f->sentto)
{
f->time = now;
return f;
@@ -858,7 +867,7 @@ struct frec *get_new_frec(struct daemon *daemon, time_t now, int *wait)
if (!wait)
{
oldest->new_id = 0;
oldest->sentto = 0;
oldest->time = now;
}
return oldest;
@@ -879,12 +888,14 @@ struct frec *get_new_frec(struct daemon *daemon, time_t now, int *wait)
return f; /* OK if malloc fails and this is NULL */
}
static struct frec *lookup_frec(unsigned short id)
/* crc is all-ones if not known. */
static struct frec *lookup_frec(unsigned short id, unsigned int crc)
{
struct frec *f;
for(f = frec_list; f; f = f->next)
if (f->new_id == id)
if (f->sentto && f->new_id == id &&
(f->crc == crc || crc == 0xffffffff))
return f;
return NULL;
@@ -897,7 +908,7 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
struct frec *f;
for(f = frec_list; f; f = f->next)
if (f->new_id &&
if (f->sentto &&
f->orig_id == id &&
f->crc == crc &&
sockaddr_isequal(&f->source, addr))
@@ -912,8 +923,8 @@ void server_gone(struct daemon *daemon, struct server *server)
struct frec *f;
for (f = frec_list; f; f = f->next)
if (f->new_id != 0 && f->sentto == server)
f->new_id = 0;
if (f->sentto && f->sentto == server)
f->sentto = NULL;
if (daemon->last_server == server)
daemon->last_server = NULL;
@@ -922,20 +933,25 @@ void server_gone(struct daemon *daemon, struct server *server)
daemon->srv_save = NULL;
}
/* return unique random ids between 1 and 65535 */
static unsigned short get_id(void)
/* return unique random ids.
For signed packets we can't change the ID without breaking the
signing, so we keep the same one. In this case force is set, and this
routine degenerates into killing any conflicting forward record. */
static unsigned short get_id(int force, unsigned short force_id, unsigned int crc)
{
unsigned short ret = 0;
while (ret == 0)
if (force)
{
ret = rand16();
/* scrap ids already in use */
if ((ret != 0) && lookup_frec(ret))
ret = 0;
struct frec *f = lookup_frec(force_id, crc);
if (f)
f->sentto = NULL; /* free */
ret = force_id;
}
else do
ret = rand16();
while (lookup_frec(ret, crc));
return ret;
}

View File

@@ -40,7 +40,7 @@ struct script_data
static struct script_data *buf;
static size_t bytes_in_buf, buf_size;
int create_helper(struct daemon *daemon)
int create_helper(struct daemon *daemon, int log_fd)
{
pid_t pid;
int i, pipefd[2];
@@ -72,11 +72,8 @@ int create_helper(struct daemon *daemon)
/* close all the sockets etc, we don't need them here */
for (i = 0; i < 64; i++)
if (i != STDOUT_FILENO && i != STDERR_FILENO &&
i != STDIN_FILENO && i != pipefd[0])
i != STDIN_FILENO && i != pipefd[0] && i != log_fd)
close(i);
/* we open our own log connection. */
log_start(daemon);
/* don't give our end of the pipe to our children */
if ((i = fcntl(pipefd[0], F_GETFD)) != -1)
@@ -142,9 +139,9 @@ int create_helper(struct daemon *daemon)
int status;
waitpid(pid, &status, 0);
if (WIFSIGNALED(status))
syslog(LOG_WARNING, _("child process killed by signal %d"), WTERMSIG(status));
my_syslog(LOG_WARNING, _("child process killed by signal %d"), WTERMSIG(status));
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
syslog(LOG_WARNING, _("child process exited with status %d"), WEXITSTATUS(status));
my_syslog(LOG_WARNING, _("child process exited with status %d"), WEXITSTATUS(status));
continue;
}
@@ -213,8 +210,8 @@ int create_helper(struct daemon *daemon)
action_str, daemon->dhcp_buff, inet_ntoa(data.addr), hostname, (char*)NULL);
/* log socket should still be open, right? */
syslog(LOG_ERR, _("failed to execute %s: %m"),
daemon->lease_change_command);
my_syslog(LOG_ERR, _("failed to execute %s: %s"),
daemon->lease_change_command, strerror(errno));
_exit(0);
}
}

View File

@@ -70,7 +70,7 @@ void load_dhcp(struct daemon *daemon, time_t now)
if (stat(daemon->lease_file, &statbuf) == -1)
{
if (!logged_lease)
syslog(LOG_WARNING, _("failed to access %s: %m"), daemon->lease_file);
my_syslog(LOG_WARNING, _("failed to access %s: %s"), daemon->lease_file, strerror(errno));
logged_lease = 1;
return;
}
@@ -86,11 +86,11 @@ void load_dhcp(struct daemon *daemon, time_t now)
if (!(fp = fopen (daemon->lease_file, "r")))
{
syslog (LOG_ERR, _("failed to load %s: %m"), daemon->lease_file);
my_syslog (LOG_ERR, _("failed to load %s: %s"), daemon->lease_file, strerror(errno));
return;
}
syslog (LOG_INFO, _("reading %s"), daemon->lease_file);
my_syslog (LOG_INFO, _("reading %s"), daemon->lease_file);
while ((next_token(token, MAXTOK, fp)))
{
@@ -112,7 +112,7 @@ void load_dhcp(struct daemon *daemon, time_t now)
if (!canonicalise(hostname))
{
*hostname = 0;
syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file);
my_syslog(LOG_ERR, _("bad name in %s"), daemon->lease_file);
}
}
else if ((strcmp(token, "ends") == 0) ||
@@ -173,9 +173,9 @@ void load_dhcp(struct daemon *daemon, time_t now)
{
if (!daemon->domain_suffix || hostname_isequal(dot+1, daemon->domain_suffix))
{
syslog(LOG_WARNING,
_("Ignoring DHCP lease for %s because it has an illegal domain part"),
hostname);
my_syslog(LOG_WARNING,
_("Ignoring DHCP lease for %s because it has an illegal domain part"),
hostname);
continue;
}
*dot = 0;

View File

@@ -214,9 +214,9 @@ void lease_update_file(struct daemon *daemon, time_t now)
if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
next_event = LEASE_RETRY + now;
syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"),
daemon->lease_file, strerror(err),
(unsigned int)difftime(next_event, now));
my_syslog(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)
@@ -312,7 +312,7 @@ struct dhcp_lease *lease_allocate(struct in_addr addr)
memset(lease, 0, sizeof(struct dhcp_lease));
lease->new = 1;
lease->addr = addr;
lease->hwaddr_len = 225; /* illegal value */
lease->hwaddr_len = 256; /* illegal value */
lease->expires = 1;
#ifdef HAVE_BROKEN_RTC
lease->length = 0xffffffff; /* illegal value */

342
src/log.c Normal file
View File

@@ -0,0 +1,342 @@
/* dnsmasq is Copyright (c) 2000-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.
*/
#include "dnsmasq.h"
/* Implement logging to /dev/log asynchronously. If syslogd is
making DNS lookups through dnsmasq, and dnsmasq blocks awaiting
syslogd, then the two daemons can deadlock. We get around this
by not blocking when talking to syslog, instead we queue up to
MAX_LOGS messages. If more are queued, they will be dropped,
and the drop event itself logged. */
/* The "wire" protocol for logging is defined in RFC 3164 */
/* From RFC 3164 */
#define MAX_MESSAGE 1024
/* defaults in case we die() before we log_start() */
static int log_fac = LOG_DAEMON;
static int log_stderr = 0;
static int log_fd = -1;
static int log_to_file = 0;
static int entries_alloced = 0;
static int entries_lost = 0;
static int connection_good = 1;
static int max_logs = 0;
struct log_entry {
int offset, length;
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 daemon *daemon)
{
int flags;
log_stderr = !!(daemon->options & OPT_DEBUG);
if (daemon->log_fac != -1)
log_fac = daemon->log_fac;
#ifdef LOG_LOCAL0
else if (daemon->options & OPT_DEBUG)
log_fac = LOG_LOCAL0;
#endif
if (daemon->log_file)
{
log_fd = open(daemon->log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
log_to_file = 1;
daemon->max_logs = 0;
}
else
log_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (log_fd == -1)
die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log");
/* if queuing is inhibited, make sure we allocate
the one required buffer now. */
if ((max_logs = daemon->max_logs) == 0)
{
free_entries = safe_malloc(sizeof(struct log_entry));
free_entries->next = NULL;
entries_alloced = 1;
}
if ((flags = fcntl(log_fd, F_GETFD)) != -1)
fcntl(log_fd, F_SETFD, flags | FD_CLOEXEC);
/* if max_log is zero, leave the socket blocking */
if (max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1)
fcntl(log_fd, F_SETFL, flags | O_NONBLOCK);
return log_fd;
}
static void log_write(void)
{
ssize_t rc;
int tried_stream = 0;
while (entries)
{
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)
{
struct log_entry *tmp = entries;
entries = tmp->next;
tmp->next = free_entries;
free_entries = tmp;
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;
}
/* Once a stream socket hits EPIPE, we have to close and re-open */
if (errno == EPIPE)
goto reopen_stream;
if (!log_to_file &&
(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)
EPIPE comes from broken stream socket (we ignore SIGPIPE) */
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_LOCAL;
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;
}
/* we start with a SOCK_DGRAM socket, but syslog may want SOCK_STREAM */
if (!tried_stream && errno == EPROTOTYPE)
{
reopen_stream:
tried_stream = 1;
close(log_fd);
if ((log_fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1)
{
int flags;
if ((flags = fcntl(log_fd, F_GETFD)) != -1)
fcntl(log_fd, F_SETFD, flags | FD_CLOEXEC);
/* if max_log is zero, leave the socket blocking */
if (max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1)
fcntl(log_fd, F_SETFL, flags | O_NONBLOCK);
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;
}
}
void my_syslog(int priority, const char *format, ...)
{
va_list ap;
struct log_entry *entry;
time_t time_now;
char *p;
size_t len;
va_start(ap, format);
if (log_stderr)
{
fprintf(stderr, "dnsmasq: ");
vfprintf(stderr, format, ap);
fputc('\n', stderr);
}
if (log_fd == -1)
{
/* fall-back to syslog if we die during startup or fail during running. */
static int isopen = 0;
if (!isopen)
{
openlog("dnsmasq", LOG_PID, log_fac);
isopen = 1;
}
vsyslog(priority, format, ap);
va_end(ap);
return;
}
if ((entry = free_entries))
free_entries = entry->next;
else if (entries_alloced < max_logs && (entry = malloc(sizeof(struct log_entry))))
entries_alloced++;
if (!entry)
entries_lost++;
else
{
/* add to end of list, consumed from the start */
entry->next = NULL;
if (!entries)
entries = entry;
else
{
struct log_entry *tmp;
for (tmp = entries; tmp->next; tmp = tmp->next);
tmp->next = entry;
}
time(&time_now);
p = entry->payload;
if (!log_to_file)
p += sprintf(p, "<%d>", priority | log_fac);
p += sprintf(p, "%.15s dnsmasq[%d]: ", ctime(&time_now) + 4, getpid());
len = p - entry->payload;
len += vsnprintf(p, MAX_MESSAGE - len, format, ap) + 1; /* include zero-terminator */
entry->length = len > MAX_MESSAGE ? MAX_MESSAGE : len;
entry->offset = 0;
/* 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();
}
}
va_end(ap);
}
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 && FD_ISSET(log_fd, set))
log_write();
}
void die(char *message, char *arg1)
{
char *errmess = strerror(errno);
if (!arg1)
arg1 = errmess;
log_stderr = 1; /* print as well as log when we die.... */
my_syslog(LOG_CRIT, message, arg1, errmess);
log_stderr = 0;
my_syslog(LOG_CRIT, _("FAILED to start up"));
exit(1);
}

View File

@@ -18,6 +18,14 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
/* linux 2.6.19 buggers up the headers, patch it up here. */
#ifndef IFA_RTA
# define IFA_RTA(r) \
((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
# include <linux/if_addr.h>
#endif
static struct iovec iov;
static void nl_err(struct nlmsghdr *h);
@@ -221,7 +229,7 @@ static void nl_err(struct nlmsghdr *h)
{
struct nlmsgerr *err = NLMSG_DATA(h);
if (err->error != 0)
syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
}
/* We arrange to receive netlink multicast messages whenever the network route is added.

View File

@@ -12,7 +12,8 @@
#include "dnsmasq.h"
int iface_check(struct daemon *daemon, int family, struct all_addr *addr, char *name)
int iface_check(struct daemon *daemon, int family, struct all_addr *addr,
struct ifreq *ifr, int *indexp)
{
struct iname *tmp;
int ret = 1;
@@ -20,16 +21,49 @@ int iface_check(struct daemon *daemon, int family, struct all_addr *addr, char *
/* Note: have to check all and not bail out early, so that we set the
"used" flags. */
if (daemon->if_names || daemon->if_addrs)
if (indexp)
{
#if defined(__FreeBSD__) || defined(__DragonFly__)
/* One form of bridging on FreeBSD 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(ifr->ifr_name, alias->iface, IF_NAMESIZE) == 0)
{
int newindex;
if (!(newindex = if_nametoindex(bridge->iface)))
{
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr->ifr_name);
return 0;
}
else
{
*indexp = newindex;
strncpy(ifr->ifr_name, bridge->iface, IF_NAMESIZE);
break;
}
}
if (alias)
break;
}
#endif
}
if (daemon->if_names || (addr && daemon->if_addrs))
{
ret = 0;
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
ret = tmp->used = 1;
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (tmp->addr.sa.sa_family == family)
if (addr && tmp->addr.sa.sa_family == family)
{
if (family == AF_INET &&
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
@@ -44,7 +78,7 @@ int iface_check(struct daemon *daemon, int family, struct all_addr *addr, char *
}
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
ret = 0;
return ret;
@@ -56,6 +90,8 @@ static int iface_allowed(struct daemon *daemon, struct irec **irecp, int if_inde
struct irec *iface;
int fd;
struct ifreq ifr;
int dhcp_ok = 1;
struct iname *tmp;
/* check whether the interface IP has been added already
we call this routine multiple times. */
@@ -109,12 +145,16 @@ static int iface_allowed(struct daemon *daemon, struct irec **irecp, int if_inde
}
if (addr->sa.sa_family == AF_INET &&
!iface_check(daemon, AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name))
!iface_check(daemon, AF_INET, (struct all_addr *)&addr->in.sin_addr, &ifr, NULL))
return 1;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
dhcp_ok = 0;
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(daemon, AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
!iface_check(daemon, AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, &ifr, NULL))
return 1;
#endif
@@ -123,8 +163,9 @@ static int iface_allowed(struct daemon *daemon, struct irec **irecp, int if_inde
{
iface->addr = *addr;
iface->netmask = netmask;
iface->dhcp_ok = dhcp_ok;
iface->next = *irecp;
*irecp = iface;
*irecp = iface;
return 1;
}
@@ -239,6 +280,7 @@ static int create_ipv6_listener(struct listener **link, int port)
l = safe_malloc(sizeof(struct listener));
l->fd = fd;
l->tcpfd = tcpfd;
l->tftpfd = -1;
l->family = AF_INET6;
l->next = NULL;
*link = l;
@@ -247,12 +289,12 @@ static int create_ipv6_listener(struct listener **link, int port)
}
#endif
struct listener *create_wildcard_listeners(int port)
struct listener *create_wildcard_listeners(int port, int have_tftp)
{
union mysockaddr addr;
int opt = 1;
struct listener *l, *l6 = NULL;
int tcpfd, fd;
int tcpfd, fd, tftpfd = -1;
memset(&addr, 0, sizeof(addr));
addr.in.sin_family = AF_INET;
@@ -283,11 +325,32 @@ struct listener *create_wildcard_listeners(int port)
#endif
bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
return NULL;
#ifdef HAVE_TFTP
if (have_tftp)
{
addr.in.sin_port = htons(TFTP_PORT);
if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
return NULL;
if (setsockopt(tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
!fix_fd(tftpfd) ||
#if defined(HAVE_LINUX_NETWORK)
setsockopt(tftpfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
setsockopt(tftpfd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(tftpfd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
#endif
bind(tftpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
return NULL;
}
#endif
l = safe_malloc(sizeof(struct listener));
l->family = AF_INET;
l->fd = fd;
l->tcpfd = tcpfd;
l->tftpfd = tftpfd;
l->next = l6;
return l;
@@ -295,7 +358,6 @@ struct listener *create_wildcard_listeners(int port)
struct listener *create_bound_listeners(struct daemon *daemon)
{
struct listener *listeners = NULL;
struct irec *iface;
int opt = 1;
@@ -306,6 +368,8 @@ struct listener *create_bound_listeners(struct daemon *daemon)
new->family = iface->addr.sa.sa_family;
new->iface = iface;
new->next = listeners;
new->tftpfd = -1;
if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
(new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
@@ -347,8 +411,20 @@ struct listener *create_bound_listeners(struct daemon *daemon)
if (listen(new->tcpfd, 5) == -1)
die(_("failed to listen on socket: %s"), NULL);
}
if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
{
short save = iface->addr.in.sin_port;
iface->addr.in.sin_port = htons(TFTP_PORT);
if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
!fix_fd(new->tftpfd) ||
bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
die(_("failed to create TFTP socket: %s"), NULL);
iface->addr.in.sin_port = save;
}
}
return listeners;
}
@@ -416,7 +492,7 @@ void check_servers(struct daemon *daemon)
break;
if (iface)
{
syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
free(new);
continue;
}
@@ -424,8 +500,9 @@ void check_servers(struct daemon *daemon)
/* Do we need a socket set? */
if (!new->sfd && !(new->sfd = allocate_sfd(&new->source_addr, &daemon->sfds)))
{
syslog(LOG_WARNING,
_("ignoring nameserver %s - cannot make/bind socket: %m"), daemon->namebuff);
my_syslog(LOG_WARNING,
_("ignoring nameserver %s - cannot make/bind socket: %s"),
daemon->namebuff, strerror(errno));
free(new);
continue;
}
@@ -444,12 +521,12 @@ void check_servers(struct daemon *daemon)
s1 = _("unqualified"), s2 = _("domains");
if (new->flags & SERV_NO_ADDR)
syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
else if (!(new->flags & SERV_LITERAL_ADDRESS))
syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
}
else
syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
}
daemon->servers = ret;
@@ -469,7 +546,7 @@ int reload_servers(char *fname, struct daemon *daemon)
/* buff happens to be MAXDNAME long... */
if (!(f = fopen(fname, "r")))
{
syslog(LOG_ERR, _("failed to read %s: %m"), fname);
my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
return 0;
}
@@ -568,8 +645,22 @@ int reload_servers(char *fname, struct daemon *daemon)
}
/* Use an IPv4 listener socket for ioctling */
struct in_addr get_ifaddr(struct daemon* daemon, char *intr)
{
struct listener *l;
struct ifreq ifr;
for (l = daemon->listeners; l && l->family != AF_INET; l = l->next);
strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
ifr.ifr_addr.sa_family = AF_INET;
if (!l || ioctl(l->fd, SIOCGIFADDR, &ifr) == -1)
((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = -1;
return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000 - 2005 Simon Kelley
/* dnsmasq is Copyright (c) 2000 - 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
@@ -341,7 +341,8 @@ static unsigned char *skip_section(unsigned char *ansp, int count, HEADER *heade
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. */
We ignore case in the names for the same reason. Return all-ones
if there is not question section. */
unsigned int questions_crc(HEADER *header, size_t plen, char *name)
{
int q;
@@ -407,21 +408,49 @@ size_t resize_packet(HEADER *header, size_t plen, unsigned char *pheader, size_t
return ansp - (unsigned char *)header;
}
unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsigned char **p)
unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsigned char **p, int *is_sign)
{
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
also return length of pseudoheader in *len and pointer to the UDP size in *p */
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 short rdlen, type;
unsigned char *ansp = (unsigned char *)(header+1);
unsigned short rdlen, type, class;
unsigned char *ret = NULL;
if (arcount == 0 || !(ansp = skip_questions(header, plen)))
if (is_sign)
{
*is_sign = 0;
if (header->opcode == QUERY)
{
for (i = 0; i < ntohs(header->qdcount); i++)
{
if (!(ansp = skip_name(ansp, header, plen)))
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;
@@ -430,35 +459,42 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
GETSHORT(type, ansp);
save = ansp;
ansp += 6; /* class, TTL */
GETSHORT(class, ansp);
ansp += 4; /* TTL */
GETSHORT(rdlen, ansp);
if ((size_t)(ansp + rdlen - (unsigned char *)header) > plen)
return NULL;
ansp += rdlen;
if (type == T_OPT)
ansp += rdlen;
if (type == T_OPT)
{
if (len)
*len = ansp - start;
if (p)
*p = save;
return start;
ret = start;
}
else if (is_sign &&
i == arcount - 1 &&
class == C_ANY &&
(type == T_SIG || type == T_TSIG))
*is_sign = 1;
}
return NULL;
return ret;
}
/* is addr in the non-globally-routed IP space? */
static int private_net(struct all_addr *addrp)
static int private_net(struct in_addr addr)
{
struct in_addr addr = *(struct in_addr *)addrp;
if (inet_netof(addr) == 0xA ||
(inet_netof(addr) >= 0xAC10 && inet_netof(addr) < 0xAC20) ||
(inet_netof(addr) >> 8) == 0xC0A8)
return 1;
else
return 0;
in_addr_t ip_addr = ntohl(addr.s_addr);
return
((ip_addr & 0xFF000000) == 0x7F000000) /* 127.0.0.0/8 (loopback) */ ||
((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ;
}
static void dns_doctor(HEADER *header, struct doctor *doctor, struct in_addr *addr)
@@ -744,7 +780,8 @@ void extract_addresses(HEADER *header, size_t qlen, char *name, time_t now, stru
}
/* If the packet holds exactly one query
return 1 and leave the name from the query in name. */
return F_IPV4 or F_IPV6 and leave the name from the query in name.
Abuse F_BIGNAME to indicate an NS query - yuck. */
unsigned short extract_request(HEADER *header, size_t qlen, char *name, unsigned short *typep)
{
@@ -774,6 +811,8 @@ unsigned short extract_request(HEADER *header, size_t qlen, char *name, unsigned
return F_IPV6;
if (qtype == T_ANY)
return F_IPV4 | F_IPV6;
if (qtype == T_NS || qtype == T_SOA)
return F_QUERY | F_BIGNAME;
}
return F_QUERY;
@@ -826,7 +865,9 @@ int check_for_local_domain(char *name, time_t now, struct daemon *daemon)
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;
@@ -838,7 +879,15 @@ int check_for_local_domain(char *name, time_t now, struct daemon *daemon)
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;
}
@@ -975,27 +1024,25 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen, struct daemon *d
{
char *name = daemon->namebuff;
unsigned char *p, *ansp, *pheader;
int qtype, qclass, is_arpa;
int qtype, qclass;
struct all_addr addr;
unsigned int nameoffset;
unsigned short flag;
int qdcount = ntohs(header->qdcount);
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 (!qdcount || header->opcode != QUERY )
return 0;
/* 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))
if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
{
unsigned short udpsz, ext_rcode, flags;
unsigned char *psave = pheader;
@@ -1010,12 +1057,15 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen, struct daemon *d
than we allow, trim it so that we don't get an overlarge
response from upstream */
if (udpsz > daemon->edns_pktsz)
if (!is_sign && (udpsz > daemon->edns_pktsz))
PUTSHORT(daemon->edns_pktsz, psave);
dryrun = 1;
}
if (!qdcount || header->opcode != QUERY )
return 0;
for (rec = daemon->mxnames; rec; rec = rec->next)
rec->offset = 0;
@@ -1035,11 +1085,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen, struct daemon *d
/* now extract name as .-concatenated string into name */
if (!extract_name(header, qlen, &p, name, 1))
return 0; /* bad packet */
/* see if it's w.z.y.z.in-addr.arpa format */
is_arpa = in_arpa_name_2_addr(name, &addr);
GETSHORT(qtype, p);
GETSHORT(qclass, p);
@@ -1070,62 +1116,104 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen, struct daemon *d
{
if (qtype == T_PTR || qtype == T_ANY)
{
if (!(crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
{
if (is_arpa == F_IPV4 && (daemon->options & OPT_BOGUSPRIV) && private_net(&addr))
/* 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(daemon, intr->intr).s_addr)
break;
if (intr)
{
ans = 1;
if (!dryrun)
{
/* 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, 0, NULL, 0);
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, 0, NULL, 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
T_PTR, C_IN, "d", intr->name))
anscount++;
}
}
else 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)
else if (ptr)
{
ans = 1;
if (!dryrun)
{
ans = 1;
auth = 0;
if (crecp->flags & F_NXDOMAIN)
nxdomain = 1;
if (!dryrun)
log_query(crecp->flags & ~F_FORWARD, name, &addr, 0, NULL, 0);
log_query(F_CNAME | F_FORWARD | F_CONFIG | F_BIGNAME, name, NULL, 0, NULL, 0);
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->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
{
ans = 1;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
}
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 (!dryrun)
{
unsigned long ttl;
/* Return 0 ttl for DHCP entries, which might change
before the lease expires. */
if (crecp->flags & (F_IMMORTAL | F_DHCP))
ttl = daemon->local_ttl;
else
ttl = crecp->ttd - now;
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
0, daemon->addn_hosts, crecp->uid);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL,
T_PTR, C_IN, "d", cache_get_name(crecp)))
anscount++;
}
}
} while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
if (crecp->flags & F_NXDOMAIN)
nxdomain = 1;
if (!dryrun)
log_query(crecp->flags & ~F_FORWARD, name, &addr, 0, NULL, 0);
}
else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
{
ans = 1;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
auth = 0;
if (!dryrun)
{
unsigned long ttl;
/* Return 0 ttl for DHCP entries, which might change
before the lease expires. */
if (crecp->flags & (F_IMMORTAL | F_DHCP))
ttl = daemon->local_ttl;
else
ttl = crecp->ttd - now;
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
0, daemon->addn_hosts, crecp->uid);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL,
T_PTR, C_IN, "d", cache_get_name(crecp)))
anscount++;
}
}
} while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
else if (is_arpa == F_IPV4 &&
(daemon->options & OPT_BOGUSPRIV) &&
private_net(addr.addr.addr4))
{
/* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
ans = 1;
nxdomain = 1;
if (!dryrun)
log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN,
name, &addr, 0, NULL, 0);
}
}
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;
@@ -1136,7 +1224,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen, struct daemon *d
if (qtype != type && qtype != T_ANY)
continue;
/* Check for "A for A" queries. */
/* Check for "A for A" queries */
if (qtype == T_A && (addr.addr.addr4.s_addr = inet_addr(name)) != (in_addr_t) -1)
{
ans = 1;
@@ -1150,6 +1238,34 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen, struct daemon *d
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(daemon, intr->intr)).s_addr == (in_addr_t) -1)
log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, 0, NULL, 0);
else
{
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, 0, NULL, 0);
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)))
{

File diff suppressed because it is too large Load Diff

519
src/tftp.c Normal file
View File

@@ -0,0 +1,519 @@
/* dnsmasq is Copyright (c) 2000-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.
*/
#include "dnsmasq.h"
#ifdef HAVE_TFTP
static struct tftp_file *check_tftp_fileperm(struct daemon *daemon, ssize_t *len);
static void free_transfer(struct tftp_transfer *transfer);
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
static ssize_t tftp_err_oops(char *packet, char *file);
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
static char *next(char **p, char *end);
#define OP_RRQ 1
#define OP_WRQ 2
#define OP_DATA 3
#define OP_ACK 4
#define OP_ERR 5
#define OP_OACK 6
#define ERR_NOTDEF 0
#define ERR_FNF 1
#define ERR_PERM 2
#define ERR_FULL 3
#define ERR_ILL 4
void tftp_request(struct listener *listen, struct daemon *daemon, time_t now)
{
ssize_t len;
char *packet = daemon->packet;
char *filename, *mode, *p, *end, *opt;
struct sockaddr_in addr, peer;
struct msghdr msg;
struct cmsghdr *cmptr;
struct iovec iov;
struct ifreq ifr;
int is_err = 1, if_index = 0;
struct iname *tmp;
struct tftp_transfer *transfer, *t;
union {
struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_LINUX_NETWORK
char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
#else
char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
msg.msg_controllen = sizeof(control_u);
msg.msg_control = control_u.control;
msg.msg_flags = 0;
msg.msg_name = &peer;
msg.msg_namelen = sizeof(peer);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
iov.iov_base = packet;
iov.iov_len = daemon->packet_buff_sz;
/* we overwrote the buffer... */
daemon->srv_save = NULL;
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
return;
if (daemon->options & OPT_NOWILD)
addr = listen->iface->addr.in;
else
{
addr.sin_addr.s_addr = 0;
#if defined(HAVE_LINUX_NETWORK)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{
addr.sin_addr = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
}
if (!(ifr.ifr_ifindex = if_index) ||
ioctl(listen->tftpfd, SIOCGIFNAME, &ifr) == -1)
return;
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
if (if_index == 0 || !if_indextoname(if_index, ifr.ifr_name))
return;
#endif
if (addr.sin_addr.s_addr == 0)
return;
if (!iface_check(daemon, AF_INET, (struct all_addr *)&addr.sin_addr,
&ifr, &if_index))
return;
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return;
}
/* tell kernel to use ephemeral port */
addr.sin_port = 0;
addr.sin_family = AF_INET;
#ifdef HAVE_SOCKADDR_SA_LEN
addr.sin_len = sizeof(addr);
#endif
if (!(transfer = malloc(sizeof(struct tftp_transfer))))
return;
if ((transfer->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
free(transfer);
return;
}
transfer->peer = peer;
transfer->timeout = now + 1;
transfer->backoff = 1;
transfer->block = 1;
transfer->blocksize = 512;
transfer->file = NULL;
transfer->opt_blocksize = transfer->opt_transize = 0;
if (bind(transfer->sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 ||
!fix_fd(transfer->sockfd))
{
free_transfer(transfer);
return;
}
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)
len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), inet_ntoa(peer.sin_addr));
else
{
while ((opt = next(&p, end)))
{
if (strcasecmp(opt, "blksize") == 0 &&
(opt = next(&p, end)) &&
!(daemon->options & OPT_TFTP_NOBLOCK))
{
transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1)
transfer->blocksize = 1;
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
transfer->opt_blocksize = 1;
transfer->block = 0;
}
if (strcasecmp(opt, "tsize") == 0 && next(&p, end))
{
transfer->opt_transize = 1;
transfer->block = 0;
}
}
strcpy(daemon->namebuff, "/");
if (daemon->tftp_prefix)
{
if (daemon->tftp_prefix[0] == '/')
daemon->namebuff[0] = 0;
strncat(daemon->namebuff, daemon->tftp_prefix, MAXDNAME);
if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/')
strncat(daemon->namebuff, "/", MAXDNAME);
/* 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);
daemon->namebuff[MAXDNAME-1] = 0;
/* 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. */
for (t = daemon->tftp_trans; t; t = t->next)
if (strcmp(t->file->filename, daemon->namebuff) == 0)
break;
if (t)
{
/* file already open */
transfer->file = t->file;
transfer->file->refcount++;
}
else
/* check permissions and open file */
transfer->file = check_tftp_fileperm(daemon, &len);
if (transfer->file)
{
if ((len = get_block(packet, transfer)) == -1)
len = tftp_err_oops(packet, daemon->namebuff);
else
is_err = 0;
}
}
while (sendto(transfer->sockfd, packet, len, 0,
(struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR);
if (is_err)
free_transfer(transfer);
else
{
my_syslog(LOG_INFO, _("TFTP sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr));
transfer->next = daemon->tftp_trans;
daemon->tftp_trans = transfer;
}
}
static struct tftp_file *check_tftp_fileperm(struct daemon *daemon, ssize_t *len)
{
char *packet = daemon->packet, *namebuff = daemon->namebuff;
struct tftp_file *file;
uid_t uid = geteuid();
struct stat statbuf;
/* trick to ban moving out of the subtree */
if (daemon->tftp_prefix && strstr(namebuff, "/../"))
{
errno = EACCES;
goto perm;
}
if (stat(namebuff, &statbuf) == -1)
{
if (errno == ENOENT || errno == ENOTDIR)
goto nofile;
else if (errno == EACCES)
goto perm;
else
goto oops;
}
/* running as root, must be world-readable */
if (uid == 0)
{
if (!(statbuf.st_mode & S_IROTH))
{
errno = EACCES;
goto perm;
}
}
/* in secure mode, must be owned by user running dnsmasq */
else if ((daemon->options & OPT_TFTP_SECURE) && uid != statbuf.st_uid)
{
errno = EACCES;
goto perm;
}
if (!(file = malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
{
errno = ENOMEM;
goto oops;
}
if ((file->fd = open(namebuff, O_RDONLY)) == -1)
{
free(file);
if (errno == EACCES || errno == EISDIR)
goto perm;
else
goto oops;
}
file->size = statbuf.st_size;
file->refcount = 1;
strcpy(file->filename, namebuff);
return file;
nofile:
*len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
return NULL;
perm:
*len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
return NULL;
oops:
*len = tftp_err_oops(packet, namebuff);
return NULL;
}
void check_tftp_listeners(struct daemon *daemon, fd_set *rset, time_t now)
{
struct tftp_transfer *transfer, *tmp, **up;
ssize_t len;
struct ack {
unsigned short op, block;
} *mess = (struct ack *)daemon->packet;
/* Check for activity on any existing transfers */
for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
{
tmp = transfer->next;
if (FD_ISSET(transfer->sockfd, rset))
{
/* we overwrote the buffer... */
daemon->srv_save = NULL;
if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
{
if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
{
/* Got ack, ensure we take the (re)transmit path */
transfer->timeout = now;
transfer->backoff = 0;
transfer->block++;
}
else if (ntohs(mess->op) == OP_ERR)
{
char *p = daemon->packet + sizeof(struct ack);
char *end = daemon->packet + len;
char *err = next(&p, end);
/* Sanitise error message */
if (!err)
err = "";
else
{
char *q, *r;
for (q = r = err; *r; r++)
if (isprint(*r))
*(q++) = *r;
*q = 0;
}
my_syslog(LOG_ERR, _("TFTP error %d %s received from %s"),
(int)ntohs(mess->block), err,
inet_ntoa(transfer->peer.sin_addr));
/* Got err, ensure we take abort */
transfer->timeout = now;
transfer->backoff = 100;
}
}
}
if (difftime(now, transfer->timeout) >= 0.0)
{
int endcon = 0;
/* timeout, retransmit */
transfer->timeout += 1<<(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(LOG_ERR, _("TFTP failed sending %s to %s"),
transfer->file->filename, inet_ntoa(transfer->peer.sin_addr));
len = 0;
}
if (len != 0)
while(sendto(transfer->sockfd, daemon->packet, len, 0,
(struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR);
if (endcon || len == 0)
{
/* unlink */
*up = tmp;
free_transfer(transfer);
continue;
}
}
up = &transfer->next;
}
}
static void free_transfer(struct tftp_transfer *transfer)
{
close(transfer->sockfd);
if (transfer->file && (--transfer->file->refcount) == 0)
{
close(transfer->file->fd);
free(transfer->file);
}
free(transfer);
}
static char *next(char **p, char *end)
{
char *ret = *p;
size_t len;
if (*(end-1) != 0 ||
*p == end ||
(len = strlen(ret)) == 0)
return NULL;
*p += len + 1;
return ret;
}
static ssize_t tftp_err(int err, char *packet, char *message, char *file)
{
struct errmess {
unsigned short op, err;
char message[];
} *mess = (struct errmess *)packet;
ssize_t ret = 4;
char *errstr = strerror(errno);
mess->op = htons(OP_ERR);
mess->err = htons(err);
ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
if (err != ERR_FNF)
my_syslog(LOG_ERR, "TFTP %s", mess->message);
return ret;
}
static ssize_t tftp_err_oops(char *packet, char *file)
{
return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file);
}
/* return -1 for error, zero for done. */
static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
{
if (transfer->block == 0)
{
/* send OACK */
char *p;
struct oackmess {
unsigned short op;
char data[];
} *mess = (struct oackmess *)packet;
p = mess->data;
mess->op = htons(OP_OACK);
if (transfer->opt_blocksize)
{
p += (sprintf(p, "blksize") + 1);
p += (sprintf(p, "%d", transfer->blocksize) + 1);
}
if (transfer->opt_transize)
{
p += (sprintf(p,"tsize") + 1);
p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
}
return p - packet;
}
else
{
/* send data packet */
struct datamess {
unsigned short op, block;
unsigned char data[];
} *mess = (struct datamess *)packet;
off_t offset = transfer->blocksize * (transfer->block - 1);
size_t size = transfer->file->size - offset;
if (offset > transfer->file->size)
return 0; /* finished */
if (size > transfer->blocksize)
size = transfer->blocksize;
lseek(transfer->file->fd, offset, SEEK_SET);
mess->op = htons(OP_DATA);
mess->block = htons((unsigned short)(transfer->block));
if (!read_write(transfer->file->fd, mess->data, size, 1))
return -1;
else
return size + 4;
}
}
#endif

View File

@@ -92,11 +92,12 @@ unsigned short rand16(void)
int legal_char(char c)
{
/* check for legal char a-z A-Z 0-9 -
(also / , used for RFC2317 and _ used in windows queries) */
(also / , used for RFC2317 and _ used in windows queries
and space, for DNS-SD stuff) */
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
c == '-' || c == '/' || c == '_')
c == '-' || c == '/' || c == '_' || c == ' ')
return 1;
return 0;
@@ -155,35 +156,6 @@ void *safe_malloc(size_t size)
return ret;
}
static void log_err(char *message, char *arg1)
{
char *errmess = strerror(errno);
if (!arg1)
arg1 = errmess;
fprintf(stderr, "dnsmasq: ");
fprintf(stderr, message, arg1, errmess);
fprintf(stderr, "\n");
syslog(LOG_CRIT, message, arg1, errmess);
}
void complain(char *message, int lineno, char *file)
{
char buff[256];
sprintf(buff, _("%s at line %d of %%s"), message, lineno);
log_err(buff, file);
}
void die(char *message, char *arg1)
{
log_err(message, arg1);
syslog(LOG_CRIT, _("FAILED to start up"));
exit(1);
}
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
{
if (s1->sa.sa_family == s2->sa.sa_family)
@@ -417,20 +389,6 @@ void bump_maxfd(int fd, int *max)
*max = fd;
}
void log_start(struct daemon *daemon)
{
if (daemon->options & OPT_DEBUG)
{
#ifdef LOG_PERROR
openlog("dnsmasq", LOG_PERROR, daemon->log_fac);
#else
openlog("dnsmasq", 0, daemon->log_fac);
#endif
}
else
openlog("dnsmasq", LOG_PID, daemon->log_fac);
}
int read_write(int fd, unsigned char *packet, int size, int rw)
{
ssize_t n, done;