Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2621c7ff0 | ||
|
|
6b01084f8e | ||
|
|
1b7ecd111d | ||
|
|
832af0bafb |
196
CHANGELOG
196
CHANGELOG
@@ -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
45
FAQ
@@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
8
Makefile
8
Makefile
@@ -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
|
||||
|
||||
@@ -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
19
contrib/try-all-ns/README
Normal 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
|
||||
|
||||
61
contrib/try-all-ns/dnsmasq-2.35-try-all-ns.patch
Normal file
61
contrib/try-all-ns/dnsmasq-2.35-try-all-ns.patch
Normal 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 }
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
7
doc.html
7
doc.html
@@ -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>.
|
||||
|
||||
|
||||
256
man/dnsmasq.8
256
man/dnsmasq.8
@@ -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
|
||||
|
||||
|
||||
473
man/es/dnsmasq.8
473
man/es/dnsmasq.8
@@ -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
|
||||
|
||||
|
||||
896
po/pt_BR.po
896
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
199
src/cache.c
199
src/cache.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
30
src/config.h
30
src/config.h
@@ -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 */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
48
src/dhcp.c
48
src/dhcp.c
@@ -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
|
||||
|
||||
395
src/dnsmasq.c
395
src/dnsmasq.c
@@ -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) &&
|
||||
|
||||
155
src/dnsmasq.h
155
src/dnsmasq.h
@@ -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
|
||||
|
||||
224
src/forward.c
224
src/forward.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
15
src/helper.c
15
src/helper.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
14
src/isc.c
14
src/isc.c
@@ -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;
|
||||
|
||||
@@ -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
342
src/log.c
Normal 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);
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
135
src/network.c
135
src/network.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1270
src/option.c
1270
src/option.c
File diff suppressed because it is too large
Load Diff
280
src/rfc1035.c
280
src/rfc1035.c
@@ -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)))
|
||||
{
|
||||
|
||||
1090
src/rfc2131.c
1090
src/rfc2131.c
File diff suppressed because it is too large
Load Diff
519
src/tftp.c
Normal file
519
src/tftp.c
Normal 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
|
||||
48
src/util.c
48
src/util.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user