import of dnsmasq-2.53.tar.gz

This commit is contained in:
Simon Kelley
2010-06-03 19:42:45 +01:00
parent 316e2730ac
commit 8ef5ada238
34 changed files with 6223 additions and 4426 deletions

167
CHANGELOG
View File

@@ -1,3 +1,163 @@
version 2.53
Fix failure to compile on Debian/kFreeBSD. Thanks to
Axel Beckert and Petr Salinger.
Fix code to avoid scary strict-aliasing warnings
generated by gcc 4.4.
Added FAQ entry warning about DHCP failures with Vista
when firewalls block 255.255.255.255.
Fixed bug which caused bad things to happen if a
resolv.conf file which exists is subsequently removed.
Thanks to Nikolai Saoukh for the patch.
Rationalised the DHCP tag system. Every configuration item
which can set a tag does so by adding "set:<tag>" and
every configuration item which is conditional on a tag is
made so by "tag:<tag>". The NOT operator changes to '!',
which is a bit more intuitive too. Dhcp-host directives
can set more than one tag now. The old '#' NOT,
"net:" prefix and no-prefixes are still honoured, so
no existing config file needs to be changed, but
the documentation and new-style config files should be
much less confusing.
Added --tag-if to allow boolean operations on tags.
This allows complicated logic to be clearer and more
general. A great suggestion from Richard Voigt.
Add broadcast/unicast information to DHCP logging.
Allow --dhcp-broadcast to be unconditional.
Fixed incorrect behaviour with NOT <tag> conditionals in
dhcp-options. Thanks to Max Turkewitz for assistance
finding this.
If we send vendor-class encapsulated options based on the
vendor-class supplied by the client, and no explicit
vendor-class option is given, echo back the vendor-class
from the client.
Fix bug which stopped dnsmasq from matching both a
circuitid and a remoteid. Thanks to Ignacio Bravo for
finding this.
Add --dhcp-proxy, which makes it possible to configure
dnsmasq to use a DHCP relay agent as a full proxy, with
all DHCP messages passing through the proxy. This is
useful if the relay adds extra information to the packets
it forwards, but cannot be configured with the RFC 5107
server-override option.
Added interface:<iface name> part to dhcp-range. The
semantics of this are very odd at first sight, but it
allows a single line of the form
dhcp-range=interface:virt0,192.168.0.4,192.168.0.200
to be added to dnsmasq configuration which then supplies
DHCP and DNS services to that interface, without affecting
what services are supplied to other interfaces and
irrespective of the existance or lack of
interface=<interface>
lines elsewhere in the dnsmasq configuration. The idea is
that such a line can be added automatically by libvirt
or equivalent systems, without disturbing any manual
configuration.
Similarly to the above, allow --enable-tftp=<interface>
Allow a TFTP root to be set separately for requests via
different interfaces, --tftp-root=<path>,<interface>
Correctly handle and log clashes between CNAMES and
DNS names being given to DHCP leases. This fixes a bug
which caused nonsense IP addresses to be logged. Thanks to
Sergei Zhirikov for finding and analysing the problem.
Tweak flush_log so as to avoid leaving the log
file in non-blocking mode. O_NONBLOCK is a property of the
file, not the process/descriptor.
Fix contrib/Solaris10/create_package
(/usr/man -> /usr/share/man) Thanks to Vita Batrla.
Fix a problem where, if a client got a lease, then went
to another subnet and got another lease, then moved back,
it couldn't resume the old lease, but would instead get
a new address. Thanks to Leonardo Rodrigues for spotting
this and testing the fix.
Fix weird bug which sometimes omitted certain characters
from the start of quoted strings in dhcp-options. Thanks
to Dayton Turner for spotting the problem.
Add facility to redirect some domains to the standard
upstream servers: this allows something like
--server=/google.com/1.2.3.4 --server=/www.google.com/#
which will send queries for *.google.com to 1.2.3.4,
except *www.google.com which will be forwarded as usual.
Thanks to AJ Weber for prompting this addition.
Improve the hash-algorithm used to generate IP addresses
from MAC addresses during initial DHCP address
allocation. This improves performance when large numbers
of hosts with similar MAC addresses all try and get an IP
address at the same time. Thanks to Paul Smith for his
work on this.
Tweak DHCP code so that --bridge-interface can be used to
select which IP alias of an interface should be used for
DHCP purposes on Linux. If eth0 has an alias eth0:dhcp
then adding --bridge-interface=eth0:dhcp,eth0 will use
the address of eth0:dhcp to determine the correct subnet
for DHCP address allocation. Thanks to Pawel Golaszewski
for prompting this and Eric Cooper for further testing.
Add --dhcp-generate-names. Suggestion by Ferenc Wagner.
Tweak DNS server selection algorithm when there is more
than one server available for a domain, eg.
--server=/mydomain/1.1.1.1
--server=/mydomain/2.2.2.2
Thanks to Alberto Cuesta-Canada for spotting a weakness
here.
Add --max-ttl. Thanks to Fredrik Ringertz for the patch.
Allow --log-facility=- to force all logging to
stderr. Suggestion from Clemens Fischer.
Fix regression which caused configuration like
--address=/.domain.com/1.2.3.4 to be rejected. The dot to the
left of the domain has been implied and not required for a
long time, but it should be accepted for backward
compatibility. Thanks to Andrew Burcin for spotting this.
Add --rebind-domain-ok and --rebind-localhost-ok.
Suggestion from Clemens Fischer.
Log replies to queries of type TXT, when --log-queries
is set.
Fix compiler warnings when compiled with -DNO_DHCP. Thanks
to Shantanu Gadgil for the patch.
Updated French translation. Thanks to Gildas Le Nadan.
Updated Polish translation. Thanks to Jan Psota.
Updated German translation. Thanks to Matthias Andree.
Added contrib/static-arp, thanks to Darren Hoo.
Fix corruption of the domain when a name from /etc/hosts
overrides one supplied by a DHCP client. Thanks to Fedor
Kozhevnikov for spotting the problem.
Updated Spanish translation. Thanks to Chris Chatham.
version 2.52
Work around a Linux kernel bug which insists that the
length of the option passed to setsockopt must be at least
@@ -81,7 +241,7 @@ version 2.52
reconfigured using --edns-packet-max if needed. Thanks to
Francis Dupont for pointing this out.
Rewrite query-ids even for DNSSEC signed packets, since
Rewrite query-ids even for TSIG signed packets, since
this is allowed by RFC5625 section 4.5.
Use getopt_long by default on OS X. It has been supported
@@ -101,7 +261,12 @@ version 2.52
Updated Spanish translation. Thanks to Chris Chatham.
Fixed confusion about domains, when looking up DHCP hosts
in /etc/hosts. This could cause spurious "Ignoring
domain..." messages. Thanks to Fedor Kozhevnikov for
finding and analysing the problem.
version 2.51
Add support for internationalised DNS. Non-ASCII characters
in domain names found in /etc/hosts, /etc/ethers and

10
FAQ
View File

@@ -456,6 +456,16 @@ A: In almost all cases: none. If you have the normal arrangement with
and turn on syslog-ng's dns-cache function.
Q: DHCP doesn't work with windows Vista, but everything else is fine.
A: The DHCP client on windows Vista (and possibly later versions)
demands that the DHCP server send replies as broadcasts. Most other
clients don't do this. The broadcasts are send to
255.255.255.255. A badly configured firewall which blocks such
packets will show exactly these symptoms (Vista fails, others
work).

View File

@@ -0,0 +1,8 @@
Hi Simon,
I just wanted to let you know that I have built a Solaris .pkg install package of your dnsmasq utility for people to use. Feel free to point them in my direction if you have people who want this sort of thing.
http://ejesconsulting.wordpress.com/2010/05/12/gnu-dnsmasq-for-opensolaris-sparc/
Thanks
-evan

View File

@@ -6,7 +6,7 @@
#
BIN_DIR="/usr/sbin"
CONF_DIR="/etc"
MAN_DIR="/usr/man/man8"
MAN_DIR="/usr/share/man/man8"
PACKAGE_NAME="dnsmasq"

View File

@@ -0,0 +1,35 @@
#!/bin/sh
# Contributed by Darren Hoo <darren.hoo@gmail.com>
# If you use dnsmasq as DHCP server on a router, you may have
# met with attackers trying ARP Poison Routing (APR) on your
# local area network. This script will setup a 'permanent' entry
# in the router's ARP table upon each DHCP transaction so as to
# make the attacker's efforts less successful.
# Usage:
# edit /etc/dnsmasq.conf and specify the path of this script
# to dhcp-script, for example:
# dhcp-script=/usr/sbin/static-arp
# if $1 is add or old, update the static arp table entry.
# if $1 is del, then delete the entry from the table
# if $1 is init which is called by dnsmasq at startup, it's ignored
ARP=/usr/sbin/arp
# Arguments.
# $1 is action (add, del, old)
# $2 is MAC
# $3 is address
# $4 is hostname (optional, may be unset)
if [ ${1} = del ] ; then
${ARP} -d $3
fi
if [ ${1} = old ] || [ ${1} = add ] ; then
${ARP} -s $3 $2
fi

View File

@@ -66,12 +66,12 @@
# You can control how dnsmasq talks to a server: this forces
# queries to 10.1.2.3 to be routed via eth1
# --server=10.1.2.3@eth1
# server=10.1.2.3@eth1
# and this sets the source (ie local) address used to talk to
# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
# IP on the machine, obviously).
# --server=10.1.2.3@192.168.1.1#55
# server=10.1.2.3@192.168.1.1#55
# If you want dnsmasq to change uid and gid to something other
# than the default, edit the following lines.
@@ -141,10 +141,22 @@
# don't need to worry about this.
#dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h
# This is an example of a DHCP range with a network-id, so that
# This is an example of a DHCP range which sets a tag, so that
# some DHCP options may be set only for this network.
#dhcp-range=red,192.168.0.50,192.168.0.150
#dhcp-range=set:red,192.168.0.50,192.168.0.150
# Use this DHCP range only when the tag "green" is set.
#dhcp-range=tag:green,192.168.0.50,192.168.0.150,12h
# Specify a subnet which can't be used for dynamic address allocation,
# is available for hosts with matching --dhcp-host lines. Note that
# dhcp-host declarations will be ignored unless there is a dhcp-range
# of some type for the subnet in question.
# In this case the netmask is implied (it comes from the network
# configuration on the machine running dnsmasq) it is possible to give
# an explict netmask instead.
#dhcp-range=192.168.0.0,static
# Supply parameters for specified hosts using DHCP. There are lots
# of valid alternatives, so we will give examples of each. Note that
# IP addresses DO NOT have to be in the range given above, they just
@@ -200,29 +212,29 @@
# Send extra options which are tagged as "red" to
# the machine with ethernet address 11:22:33:44:55:66
#dhcp-host=11:22:33:44:55:66,net:red
#dhcp-host=11:22:33:44:55:66,set:red
# Send extra options which are tagged as "red" to
# any machine with ethernet address starting 11:22:33:
#dhcp-host=11:22:33:*:*:*,net:red
#dhcp-host=11:22:33:*:*:*,set:red
# Ignore any clients which are specified in dhcp-host lines
# or /etc/ethers. Equivalent to ISC "deny unkown-clients".
# This relies on the special "known" tag which is set when
# a host is matched.
#dhcp-ignore=#known
#dhcp-ignore=tag:!known
# Send extra options which are tagged as "red" to any machine whose
# DHCP vendorclass string includes the substring "Linux"
#dhcp-vendorclass=red,Linux
#dhcp-vendorclass=set:red,Linux
# Send extra options which are tagged as "red" to any machine one
# of whose DHCP userclass strings includes the substring "accounts"
#dhcp-userclass=red,accounts
#dhcp-userclass=set:red,accounts
# Send extra options which are tagged as "red" to any machine whose
# MAC address matches the pattern.
#dhcp-mac=red,00:60:8C:*:*:*
#dhcp-mac=set:red,00:60:8C:*:*:*
# If this line is uncommented, dnsmasq will read /etc/ethers and act
# on the ethernet-address/IP pairs found there just as if they had
@@ -276,8 +288,8 @@
# Specify an option which will only be sent to the "red" network
# (see dhcp-range for the declaration of the "red" network)
# Note that the net: part must precede the option: part.
#dhcp-option = net:red, option:ntp-server, 192.168.1.1
# Note that the tag: part must precede the option: part.
#dhcp-option = tag:red, option:ntp-server, 192.168.1.1
# The following DHCP options set up dnsmasq in the same way as is specified
# for the ISC dhcpcd in
@@ -338,8 +350,8 @@
# Boot for Etherboot gPXE. The idea is to send two different
# filenames, the first loads gPXE, and the second tells gPXE what to
# load. The dhcp-match sets the gpxe tag for requests from gPXE.
#dhcp-match=gpxe,175 # gPXE sends a 175 option.
#dhcp-boot=net:#gpxe,undionly.kpxe
#dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
#dhcp-boot=tag:!gpxe,undionly.kpxe
#dhcp-boot=mybootimage
# Encapsulated options for Etherboot gPXE. All the options are
@@ -490,11 +502,11 @@
# set for this to work.)
# A SRV record sending LDAP for the example.com domain to
# ldapserver.example.com port 289
# ldapserver.example.com port 389
#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389
# A SRV record sending LDAP for the example.com domain to
# ldapserver.example.com port 289 (using domain=)
# ldapserver.example.com port 389 (using domain=)
#domain=example.com
#srv-host=_ldap._tcp,ldapserver.example.com,389

View File

@@ -65,6 +65,12 @@ cache the reply. This option gives a default value for time-to-live
(in seconds) which dnsmasq uses to cache negative replies even in
the absence of an SOA record.
.TP
.B --max-ttl=<time>
Set a maximum TTL value that will be handed out to clients. The specified
maximum TTL will be given to clients instead of the true TTL value if it is
lower. The true TTL value is however kept in the cache to avoid flooding
the upstream DNS servers.
.TP
.B \-k, --keep-in-foreground
Do not go into the background at startup but otherwise run as
normal. This is intended for use when dnsmasq is run under daemontools
@@ -84,7 +90,8 @@ Set the facility to which dnsmasq will send syslog entries, this
defaults to DAEMON, and to LOCAL0 when debug mode is in operation. If
the facility given contains at least one '/' character, it is taken to
be a filename, and dnsmasq logs to the given file, instead of
syslog. (Errors whilst reading configuration will still go to syslog,
syslog. If the facility is '-' then dnsmasq logs to stderr.
(Errors whilst reading configuration will still go to syslog,
but all output from a successful startup, and all output whilst
running, will go exclusively to the file.) When logging to a file,
dnsmasq will close and reopen the file when it receives SIGUSR2. This
@@ -276,6 +283,17 @@ Reject (and log) addresses from upstream nameservers which are in the
private IP ranges. This blocks an attack where a browser behind a
firewall is used to probe machines on the local network.
.TP
.B --rebind-localhost-ok
Exempt 127.0.0.0/8 from rebinding checks. This address range is
returned by realtime black hole servers, so blocking it may disable
these services.
.TP
.B --rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/]
Do not detect and block dns-rebind on queries to these domains. The
argument may be either a single domain, or multiple domains surrounded
by '/', like the --server syntax, eg.
.B --rebind-domain-ok=/domain1/domain2/domain3/
.TP
.B \-n, --no-poll
Don't poll /etc/resolv.conf for changes.
.TP
@@ -308,7 +326,19 @@ dots in them. A non-standard port may be specified as
part of the IP
address using a # character.
More than one -S flag is allowed, with
repeated domain or ipaddr parts as required.
repeated domain or ipaddr parts as required.
More specific domains take precendence over less specific domains, so:
.B --server=/google.com/1.2.3.4
.B --server=/www.google.com/2.3.4.5
will send queries for *.google.com to 1.2.3.4, except *www.google.com,
which will go to 2.3.4.5
The special server address '#' means, "use the standard servers", so
.B --server=/google.com/1.2.3.4
.B --server=/www.google.com/#
will send queries for *.google.com to 1.2.3.4, except *www.google.com which will
be forwarded as usual.
Also permitted is a -S
flag which gives a domain but no IP address; this tells dnsmasq that
@@ -426,7 +456,7 @@ Set the maximum number of concurrent DNS queries. The default value is
where this needs to be increased is when using web-server log file
resolvers, which can generate large numbers of concurrent queries.
.TP
.B \-F, --dhcp-range=[[net:]network-id,]<start-addr>,<end-addr>[,<netmask>[,<broadcast>]][,<lease time>]
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>,<end-addr>[,<netmask>[,<broadcast>]][,<lease time>]
Enable the DHCP server. Addresses will be given out from the range
<start-addr> to <end-addr> and from statically defined addresses given
in
@@ -442,10 +472,13 @@ networks on which the machine running dnsmasq has an interface) the
netmask is optional. It is, however, required for networks which
receive DHCP service via a relay agent. The broadcast address is
always optional. It is always
allowed to have more than one dhcp-range in a single subnet. The optional
network-id is a alphanumeric label which marks this network so that
allowed to have more than one dhcp-range in a single subnet.
The optional
.B set:<tag>
sets an alphanumeric label which marks this network so that
dhcp options may be specified on a per-network basis.
When it is prefixed with 'net:' then its meaning changes from setting
When it is prefixed with 'tag:' instead, then its meaning changes from setting
a tag to matching it. Only one tag may be set, but more than one tag may be matched.
The end address may be replaced by the keyword
.B static
@@ -462,8 +495,11 @@ subnet. (See
and
.B pxe-service
for details.)
The interface:<interface name> section is not normally used. See the
NOTES section for details of this.
.TP
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
Specify per host parameters for the DHCP server. This allows a machine
with a particular hardware address to be always allocated the same
hostname, IP address and lease time. A hostname specified like this
@@ -478,9 +514,15 @@ an infinite DHCP lease.
.B --dhcp-host=lap,192.168.0.199
tells
dnsmasq to always allocate the machine lap the IP address
192.168.0.199. Addresses allocated like this are not constrained to be
in the range given by the --dhcp-range option, but they must be on the
network being served by the DHCP server. It is allowed to use client identifiers rather than
192.168.0.199.
Addresses allocated like this are not constrained to be
in the range given by the --dhcp-range option, but they must be in
the same subnet as some valid dhcp-range. For
subnets which don't need a pool of dynamically allocated addresses,
use the "static" keyword in the dhcp-range declaration.
It is allowed to use client identifiers rather than
hardware addresses to identify hosts by prefixing with 'id:'. Thus:
.B --dhcp-host=id:01:02:03:04,.....
refers to the host with client identifier 01:02:03:04. It is also
@@ -494,7 +536,14 @@ but not others.
If a name appears in /etc/hosts, the associated address can be
allocated to a DHCP lease, but only if a
.B --dhcp-host
option specifying the name also exists. The special keyword "ignore"
option specifying the name also exists. Only one hostname can be
given in a
.B dhcp-host
option, but aliases are possible by using CNAMEs. (See
.B --cname
).
The special keyword "ignore"
tells dnsmasq to never offer a DHCP lease to a machine. The machine
can be specified by hardware address, client ID or hostname, for
instance
@@ -503,13 +552,15 @@ This is
useful when there is another DHCP server on the network which should
be used by some machines.
The net:<network-id> sets the network-id tag
The set:<tag> contruct sets the tag
whenever this dhcp-host directive is in use. This can be used to
selectively send DHCP options just for this host. When a host matches any
selectively send DHCP options just for this host. More than one tag
can be set in a dhcp-host directive (but not in other places where
"set:<tag>" is allowed). When a host matches any
dhcp-host directive (or one implied by /etc/ethers) then the special
network-id tag "known" is set. This allows dnsmasq to be configured to
tag "known" is set. This allows dnsmasq to be configured to
ignore requests from unknown machines using
.B --dhcp-ignore=#known
.B --dhcp-ignore=tag:!known
Ethernet addresses (but not client-ids) may have
wildcard bytes, so for example
.B --dhcp-host=00:20:e0:3b:13:*,ignore
@@ -563,7 +614,7 @@ have exactly the same effect as
options containing the same information. /etc/ethers is re-read when
dnsmasq receives SIGHUP.
.TP
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]]
.B \-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]]
Specify different or extra options to DHCP clients. By default,
dnsmasq sends some standard options to DHCP clients, the netmask and
broadcast address are set to the same as the host running dnsmasq, and
@@ -586,8 +637,8 @@ or
The special address 0.0.0.0 is taken to mean "the address of the
machine running dnsmasq". Data types allowed are comma separated
dotted-quad IP addresses, a decimal number, colon-separated hex digits
and a text string. If the optional network-ids are given then
this option is only sent when all the network-ids are matched.
and a text string. If the optional tags are given then
this option is only sent when all the tags are matched.
Special processing is done on a text argument for option 119, to
conform with RFC 3397. Text or dotted-quad IP addresses as arguments
@@ -640,7 +691,7 @@ used to identify this option.
The address 0.0.0.0 is not treated specially in
encapsulated options.
.TP
.B --dhcp-option-force=[<network-id>,[<network-id>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]]
.B --dhcp-option-force=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]]
This works in exactly the same way as
.B --dhcp-option
except that the option will always be sent, even if the client does
@@ -655,20 +706,20 @@ DHCP options. This make extra space available in the DHCP packet for
options but can, rarely, confuse old or broken clients. This flag
forces "simple and safe" behaviour to avoid problems in such a case.
.TP
.B \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
Map from a vendor-class string to a network id tag. Most DHCP clients provide a
.B \-U, --dhcp-vendorclass=set:<tag>,<vendor-class>
Map from a vendor-class string to a tag. Most DHCP clients provide a
"vendor class" which represents, in some sense, the type of host. This option
maps vendor classes to tags, so that DHCP options may be selectively delivered
to different classes of hosts. For example
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
will allow options to be set only for HP printers like so:
.B --dhcp-option=printers,3,192.168.4.4
.B --dhcp-option=tag:printers,3,192.168.4.4
The vendor-class string is
substring matched against the vendor-class supplied by the client, to
allow fuzzy matching.
allow fuzzy matching. The set: prefix is optional but allowed for consistency.
.TP
.B \-j, --dhcp-userclass=<network-id>,<user-class>
Map from a user-class string to a network id tag (with substring
.B \-j, --dhcp-userclass=set:<tag>,<user-class>
Map from a user-class string to a tag (with substring
matching, like vendor classes). Most DHCP clients provide a
"user class" which is configurable. This option
maps user classes to tags, so that DHCP options may be selectively delivered
@@ -676,24 +727,41 @@ to different classes of hosts. It is possible, for instance to use
this to set a different printer server for hosts in the class
"accounts" than for hosts in the class "engineering".
.TP
.B \-4, --dhcp-mac=<network-id>,<MAC address>
Map from a MAC address to a network-id tag. The MAC address may include
.B \-4, --dhcp-mac=set:<tag>,<MAC address>
Map from a MAC address to a tag. The MAC address may include
wildcards. For example
.B --dhcp-mac=3com,01:34:23:*:*:*
.B --dhcp-mac=set:3com,01:34:23:*:*:*
will set the tag "3com" for any host whose MAC address matches the pattern.
.TP
.B --dhcp-circuitid=<network-id>,<circuit-id>, --dhcp-remoteid=<network-id>,<remote-id>
Map from RFC3046 relay agent options to network-id tags. This data may
.B --dhcp-circuitid=set:<tag>,<circuit-id>, --dhcp-remoteid=set:<tag>,<remote-id>
Map from RFC3046 relay agent options to tags. This data may
be provided by DHCP relay agents. The circuit-id or remote-id is
normally given as colon-separated hex, but is also allowed to be a
simple string. If an exact match is achieved between the circuit or
agent ID and one provided by a relay agent, the network-id tag is set.
agent ID and one provided by a relay agent, the tag is set.
.TP
.B --dhcp-subscrid=<network-id>,<subscriber-id>
Map from RFC3993 subscriber-id relay agent options to network-id tags.
.B --dhcp-subscrid=set:<tag>,<subscriber-id>
Map from RFC3993 subscriber-id relay agent options to tags.
.TP
.B --dhcp-match=<network-id>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>]
Without a value, set the network-id tag if the client sends a DHCP
.B --dhcp-proxy[=<ip addr>]......
A normal DHCP relay agent is only used to forward the initial parts of
a DHCP interaction to the DHCP server. Once a client is configured, it
communicates directly with the server. This is undesirable if the
relay agent is addding extra information to the DHCP packets, such as
that used by
.B dhcp-circuitid
and
.B dhcp-remoteid.
A full relay implementation can use the RFC 5107 serverid-override
option to force the DHCP server to use the relay as a full proxy, with all
packets passing through it. This flag provides an alternative method
of doing the same thing, for relays which don't support RFC
5107. Given alone, it manipulates the server-id for all interactions
via relays. If a list of IP addresses is given, only interactions via
relays at those addresses are affected.
.TP
.B --dhcp-match=set:<tag>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>]
Without a value, set the tag if the client sends a DHCP
option of the given number or name. When a value is given, set the tag only if
the option is sent and matches the value. The value may be of the form
"01:ff:*:02" in which case the value must match (apart from widcards)
@@ -703,7 +771,7 @@ value. The value may also be of the same form as in
in which case the option sent is treated as an array, and one element
must match, so
--dhcp-match=efi-ia32,option:client-arch,6
--dhcp-match=set:efi-ia32,option:client-arch,6
will set the tag "efi-ia32" if the the number 6 appears in the list of
architectures sent by the client in option 93. (See RFC 4578 for
@@ -711,41 +779,56 @@ details.) If the value is a string, substring matching is used.
The special form with vi-encap:<enterpise number> matches against
vendor-identifying vendor classes for the specified enterprise. Please
see RFC 3925 for more details of the rare and interesting beasts.
see RFC 3925 for more details of these rare and interesting beasts.
.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
.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
If no tag:<tag> appears set:<tag> tags are set unconditionally.
Any number of set: and tag: forms may appear, in any order.
Tag-if lines ares executed in order, so if the tag in tag:<tag> is a
tag set by another
.B tag-if,
the line which sets the tag must precede the one which tests it.
.TP
.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
When all the given tags appear in the tag set ignore the host and do
not allocate it a DHCP lease.
.TP
.B --dhcp-ignore-names[=<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
.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]]
When all the given tags appear in the tag set, ignore any hostname
provided by the host. Note that, unlike dhcp-ignore, it is permissible
to supply no netid tags, in which case DHCP-client supplied hostnames
to supply no tags, in which case DHCP-client supplied hostnames
are always ignored, and DHCP hosts are added to the DNS using only
dhcp-host configuration in dnsmasq and the contents of /etc/hosts and
/etc/ethers.
.TP
.B --dhcp-broadcast=<network-id>[,<network-id>]
When all the given network-ids match the set of network-ids derived
from the net, host, vendor and user classes, always use broadcast to
communicate with the host when it is unconfigured. Most DHCP clients which
.B --dhcp-generate-names=tag:<tag>[,tag:<tag>]
Generate a name for DHCP clients which do not otherwise have one,
using the MAC address expressed in hex, seperated by dashes. Note that
if a host provides a name, it will be used by preference to this,
unless
.B --dhcp-ignore-names
is set.
.TP
.B --dhcp-broadcast[=tag:<tag>[,tag:<tag>]]
When all the given tags appear in the tag set, always use broadcast to
communicate with the host when it is unconfigured. It is permissible
to supply no tags, in which case this is unconditional. Most DHCP clients which
need broadcast replies set a flag in their requests so that this
happens automatically, some old BOOTP clients do not.
.TP
.B \-M, --dhcp-boot=[net:<network-id>,]<filename>,[<servername>[,<server address>]]
.B \-M, --dhcp-boot=[tag:<tag>,]<filename>,[<servername>[,<server address>]]
Set BOOTP options to be returned by the DHCP server. Server name and
address are optional: if not provided, the name is left empty, and the
address set to the address of the machine running dnsmasq. If dnsmasq
is providing a TFTP service (see
.B --enable-tftp
) then only the filename is required here to enable network booting.
If the optional 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.
If the optional tag(s) are given,
they must match for this configuration to be sent.
.TP
.B --pxe-service=[net:<network-id>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>]
.B --pxe-service=[tag:<tag>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>]
Most uses of PXE boot-ROMS simply allow the PXE
system to obtain an IP address and then download the file specified by
.B dhcp-boot
@@ -773,7 +856,7 @@ If no boot service type or filename is provided (or a boot service type of 0 is
then the menu entry will abort the net boot procedure and
continue booting from local media.
.TP
.B --pxe-prompt=[net:<network-id>,]<prompt>[,<timeout>]
.B --pxe-prompt=[tag:<tag>,]<prompt>[,<timeout>]
Setting this provides a prompt to be displayed after PXE boot. If the
timeout is given then after the
timeout has elapsed with no keyboard input, the first available menu
@@ -799,7 +882,7 @@ keyword in
.TP
.B \-X, --dhcp-lease-max=<number>
Limits dnsmasq to the specified maximum number of DHCP leases. The
default is 150. This limit is to prevent DoS attacks from hosts which
default is 1000. This limit is to prevent DoS attacks from hosts which
create thousands of leases and use lots of memory in the dnsmasq
process.
.TP
@@ -836,14 +919,16 @@ 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.
the tags used to determine them.
.TP
.B \-l, --dhcp-leasefile=<path>
Use the specified file to store DHCP lease information.
.TP
.B \-6 --dhcp-script=<path>
Whenever a new DHCP lease is created, or an old one destroyed, the
executable specified by this option is run. The arguments to the process
executable specified by this option is run. <path>
must be an absolute pathname, no PATH search occurs.
The arguments to the process
are "add", "old" or "del", the MAC
address of the host, the IP address, and the hostname,
if known. "add" means a lease has been created, "del" means it has
@@ -854,39 +939,61 @@ If the MAC address is from a network type other than ethernet,
it will have the network type prepended, eg "06-01:23:45:67:89:ab" for
token ring. The process is run as root (assuming that dnsmasq was originally run as
root) even if dnsmasq is configured to change UID to an unprivileged user.
The environment is inherited from the invoker of dnsmasq, and if the
host provided a client-id, this is stored in the environment variable
DNSMASQ_CLIENT_ID. If the fully-qualified domain name of the host is
known, the domain part is stored in DNSMASQ_DOMAIN.
If the client provides vendor-class, hostname or user-class,
these are provided in DNSMASQ_VENDOR_CLASS
The environment is inherited from the invoker of dnsmasq, with some or
all of the following variables added.
DNSMASQ_CLIENT_ID if the host provided a client-id.
DNSMASQ_DOMAIN if the fully-qualified domain name of the host is
known, this is set to the domain part.
If the client provides vendor-class, hostname or user-class,
these are provided in DNSMASQ_VENDOR_CLASS
DNSMASQ_SUPPLIED_HOSTNAME and
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn variables, but only for
"add" actions or "old" actions when a host resumes an existing lease,
since these data are not held in dnsmasq's lease
database. If dnsmasq was compiled with HAVE_BROKEN_RTC, then
database.
If dnsmasq was compiled with HAVE_BROKEN_RTC, then
the length of the lease (in seconds) is stored in
DNSMASQ_LEASE_LENGTH, otherwise the time of lease expiry is stored in
DNSMASQ_LEASE_EXPIRES. The number of seconds until lease expiry is
always stored in DNSMASQ_TIME_REMAINING.
If a lease used to have a hostname, which is
removed, an "old" event is generated with the new state of the lease,
ie no name, and the former name is provided in the environment
variable DNSMASQ_OLD_HOSTNAME. DNSMASQ_INTERFACE stores the name of
variable DNSMASQ_OLD_HOSTNAME.
DNSMASQ_INTERFACE stores the name of
the interface on which the request arrived; this is not set for "old"
actions when dnsmasq restarts. DNSMASQ_RELAY_ADDRESS is set if the client
actions when dnsmasq restarts.
DNSMASQ_RELAY_ADDRESS is set if the client
used a DHCP relay to contact dnsmasq and the IP address of the relay
is known. DNSMASQ_TAGS contains all the network-id tags set during the
is known.
DNSMASQ_TAGS contains all the tags set during the
DHCP transaction, separated by spaces.
All file descriptors are
closed except stdin, stdout and stderr which are open to /dev/null
(except in debug mode).
The script is not invoked concurrently: if subsequent lease
changes occur, the script is not invoked again until any existing
invocation exits. At dnsmasq startup, the script will be invoked for
The script is not invoked concurrently: at most one instance
of the script is ever running (dnsmasq waits for an instance of script to exit
before running the next). Changes to the lease database are which
require the script to be invoked are queued awaiting exit of a running instance.
If this queueing allows multiple state changes occur to a single
lease before the script can be run then
earlier states are discarded and the current state of that lease is
reflected when the script finally runs.
At dnsmasq startup, the script will be invoked for
all existing leases as they are read from the lease file. Expired
leases will be called with "del" and others with "old". <path>
must be an absolute pathname, no PATH search occurs. When dnsmasq
leases will be called with "del" and others with "old". When dnsmasq
receives a HUP signal, the script will be invoked for existing leases
with an "old " event.
.TP
@@ -955,17 +1062,20 @@ without an address specified when
.B --dhcp-fqdn
is set.
.TP
.B --enable-tftp
.B --enable-tftp[=<interface>]
Enable the TFTP server function. This is deliberately limited to that
needed to net-boot a client. Only reading is allowed; the tsize and
blksize extensions are supported (tsize is only supported in octet mode).
blksize extensions are supported (tsize is only supported in octet
mode). See NOTES section for use of the interface argument.
.TP
.B --tftp-root=<directory>
.B --tftp-root=<directory>[,<interface>]
Look for files to transfer using TFTP relative to the given
directory. When this is set, TFTP paths which include ".." are
rejected, to stop clients getting outside the specified root.
Absolute paths (starting with /) are allowed, but they must be within
the tftp-root.
the tftp-root. If the optional interface argument is given, the
directory is only used for TFTP requests via that interface.
.TP
.B --tftp-unique-root
Add the IP address of the TFTP client as a path component on the end
@@ -1152,31 +1262,41 @@ the CNAME. To work around this, add the CNAME to /etc/hosts so that
the CNAME is shadowed too.
.PP
The network-id system works as follows: For each DHCP request, dnsmasq
collects a set of valid network-id tags, one from the
The tag system works as follows: For each DHCP request, dnsmasq
collects a set of valid tags from active configuration lines which
include set:<tag>, including one from the
.B dhcp-range
used to allocate the address, one from any matching
.B dhcp-host
(and "known" if a dhcp-host matches)
the tag "bootp" for BOOTP requests, a tag whose name is the
name if the interface on which the request arrived,
and possibly many from matching vendor classes and user
classes sent by the DHCP client. Any
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
name of the interface on which the request arrived is also set.
Any configuration lines which includes one or more tag:<tag> contructs
will only be valid if all that tags are matched in the set derived
above. Typically this is dhcp-option.
.B dhcp-option
which has network-id tags will be used in preference to an untagged
which has tags will be used in preference to an untagged
.B dhcp-option,
provided that _all_ the tags match somewhere in the
set collected as described above. The prefix '#' on a tag means 'not'
so --dhcp=option=#purple,3,1.2.3.4 sends the option when the
network-id tag purple is not in the set of valid tags.
set collected as described above. The prefix '!' on a tag means 'not'
so --dhcp=option=tag:!purple,3,1.2.3.4 sends the option when the
tag purple is not in the set of valid tags. (If using this in a
command line rather than a configuration file, be sure to escape !,
which is a shell metacharacter)
.PP
If the network-id in a
Note that for
.B dhcp-range
is prefixed with 'net:' then its meaning changes from setting a
tag to matching it. Thus if there is more than dhcp-range on a subnet,
and one is tagged with a network-id which is set (for instance
from a vendorclass option) then hosts which set the netid tag will be
allocated addresses in the tagged range.
both tag:<tag> and set:<tag> are allowed, to both select the range in
use based on (eg) dhcp-host, and to affect the options sent, based on
the range selected.
This system evolved from an earlier, more limited one and for backward
compatibility "net:" may be used instead of "tag:" and "set:" may be
omitted. (Except in
.B dhcp-host,
where "net:" may be used instead of "set:".) For the same reason, '#'
may be used instead of '!' to indicate NOT.
.PP
The DHCP server in dnsmasq will function as a BOOTP server also,
provided that the MAC address and IP address for clients are given,
@@ -1189,11 +1309,56 @@ configurations or in
configuration option is present to activate the DHCP server
on a particular network. (Setting --bootp-dynamic removes the need for
static address mappings.) The filename
parameter in a BOOTP request is matched against netids in
.B dhcp-option
configurations, as is the tag "bootp", allowing some control over the options returned to
parameter in a BOOTP request is used as a tag,
as is the tag "bootp", allowing some control over the options returned to
different classes of hosts.
.B dhcp-range
may have an interface name supplied as
"interface:<interface-name>". The semantics if this are as follows:
For DHCP, if any other dhcp-range exists _without_ an interface name,
then the interface name is ignored and and dnsmasq behaves as if the
interface parts did not exist, otherwise DHCP is only provided to
interfaces mentioned in dhcp-range
declarations. For DNS, if there are no
.B --interface
or
.B --listen-address
flags, behaviour is unchanged by the interface part. If either of
these flags are present, the interfaces mentioned in
dhcp-ranges are added to the set which get DNS service.
Similarly,
.B enable-tftp
may take an interface name, which enables TFTP only for a particular
interface, ignoring
.B --interface
or
.B --listen-address
flags. In addition
.B --tftp-secure
and
.B --tftp-unique-root
and
.B --tftp-no-blocksize
are ignored for requests from such interfaces. (A
.B --tftp-root
directive giving a root path and an interface should be
provided too.)
These rules may seem odd at first sight, but they
allow a single line of the form "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200"
to be added to dnsmasq configuration which then supplies
DHCP and DNS services to that interface, without affecting
what services are supplied to other interfaces and irrespective of
the existance or lack of "interface=<interface>"
lines elsewhere in the dnsmasq configuration.
"enable-tftp=virt0" and "tftp-root=<root>,virt0" do the same job for TFTP.
The idea is
that such a line can be added automatically by libvirt
or equivalent systems, without disturbing any manual
configuration.
.SH EXIT CODES
.PP
0 - Dnsmasq successfully forked into the background, or terminated
@@ -1224,10 +1389,7 @@ 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
clients. The DHCP lease times should not be very short (less than one hour). The
value of
.B --dns-forward-max
can be increased: start with it equal to

View File

@@ -68,8 +68,14 @@ informaci
dnsmasq usa para hacer cach<63>. Si las respuestas de servidores upstream
omiten esta informaci<63>n, dnsmasq no mete la respuesta en el cach<63>.
Esta opci<63>n brinda un valor predeterminado para el time-to-live que
dnsmasq usa para meter respuestas en el cach<63> a<>n en la ausencia de
un expediente SOA.
dnsmasq usa para meter respuestas negativas en el cach<63> a<>n en la
ausencia de un expediente SOA.
.TP
.B --max-ttl=<tiempo>
Fijar un valor TTL (tiempo de vida) m<>ximo que ser<65> entregado a
clientes. El TTL m<>ximo especificado ser<65> otorgado a clientes en vez
del TTL verdadero si es menor. El valor TTL real es mantenido en el cach<63>
para prevenir la inundaci<63>n de los servidores DNS upstream.
.TP
.B \-k, --keep-in-foreground
No ir hacia el fondo al iniciar, pero aparte de eso ejecutar como
@@ -91,7 +97,8 @@ Fijar la facilidad a la cual dnsmasq deber
esto es DAEMON por predeterminado, y LOCAL0 cuando el modo debug est<73>
en operaci<63>n. Si la facilidad brindada contiene por lo menos un car<61>cter
"/", se trata como un nombre de archivo, y dnsmasq bitacorear<61> a dicho
archivo, en vez de syslog. (Errores durante la lectura de la configuraci<63>n
archivo, en vez de syslog. Si la facilidad es '-' entonces dnsmasq
bitacorea a stderr. (Errores durante la lectura de la configuraci<63>n
ir<EFBFBD>n a syslog todav<61>a, pero todo output desde un inicio exitoso, y todo
output mientras en ejecuci<63>n, ir<69> a este archivo exclusivamente.)
Al bitacorear a un archivo, dnsmasq cerrar<61> y reabrir<69> el archivo al
@@ -304,6 +311,17 @@ Denegar (y bitacorear) direcciones de servidores upstream que est
dentro de rangos IP privados. Esto bloquea un ataque donde un navegador
detr<EFBFBD>s de un firewall es usado para analizar m<>quinas en la red local.
.TP
.B --rebind-localhost-ok
Eximir a 127.0.0.0/8 de verificaciones de rebinding. Este rango de
direcciones es retornado por servidores de tiempo real tipo hoyo
negro, as<61> que bloquearlo puede deshabilitar estos servicios.
.TP
.B --rebind-domain-ok=[<domain>]|[[/<domain>/[<domain>/]
No detectar y bloquear dns-rebind en b<>squedas a estos dominios. El
argumento puede ser o un dominio sencillo, o m<>ltiples dominios
rodeados por '/', como el syntax de --server, por ejemplo
.B --rebind-domain-ok=/dominio1/dominio2/dominio3/
.TP
.B \-n, --no-poll
No revisar periodicamente a /etc/resolv.conf en busca de cambios.
.TP
@@ -339,6 +357,20 @@ ser especificado como parte de la direcci
#. M<>s de una opci<63>n -S es permitida, con partes de dominio o
direcci<EFBFBD>n IP repetidas como sea necesario.
Dominios m<>s espec<65>ficos toman precedencia sobre los menos espec<65>ficos,
as<EFBFBD> que:
.B --server=/google.com/1.2.3.4
.B --server=/www.google.com/2.3.4.5
enviar<EFBFBD> b<>squedas por *.google.com hacia 1.2.3.4, excepto
*www.google.com, el cual ir<69> a 2.3.4.5.
La direcci<63>n especial de servidor '#' significa "usar los servidores
est<EFBFBD>ndares", as<61> que
.B --server=/google.com/1.2.3.4
.B --server=/www.google.com/#
enviar<EFBFBD> b<>squedas por *.google.com hacia 1.2.3.4, excepto
*www.google.com, el cual ser<65> reenviado de manera usual.
Tambi<EFBFBD>n se permite una opci<63>n -S la cual brinda un dominio pero
ninguna direcci<63>n IP; esto le dice a dnsmasq que un dominio es local
y puede responder a b<>squedas desde /etc/hosts o DHCP pero nunca
@@ -460,7 +492,7 @@ de casos. La
es al usar resolvedores de bit<69>coras de servidores web, los cuales pueden
generar un n<>mero inmenso de b<>squedas simult<6C>neas.
.TP
.B \-F, --dhcp-range=[[net:]network-id,]<direcci<63>n-inicio>,<direcci<63>n-final>[,<m<EFBFBD>scara>[,<broadcast>]][,<tiempo de arriendo>]
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<direcci<63>n-inicio>,<direcci<63>n-final>[,<netmask>[,<broadcast>]][,<tiempo de arriendo>]
Habilitar el servidor DHCP. Direcciones ser<65>n distribuidas desde el
rango <direcci<63>n-inicio> hasta <direcci<63>n-final> y desde direcciones definidas
est<EFBFBD>ticamente en opciones
@@ -477,10 +509,13 @@ cuales la m
m<EFBFBD>scara de subred es opcional. Pero, es requerida para redes que
reciben servicio DHCP v<>a un agente de relay. La direcci<63>n de
broadcast siempre es opcional. Siempre se permite tener m<>s de
un rango dhcp (dhcp-range) en una subred. El par<61>metro opcional
network-id es una etiqueta alfanum<75>rica la cual marca esta red de
un rango dhcp (dhcp-range) en una subred.
El par<61>metro opcional
.B set:<tag>
fija una etiqueta alfanum<75>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
Cuando es prefijada con 'tag:' en vez, entonces el significado cambia
de "fijar etiqueta" a "coincidir con etiqueta". Solo una etiqueta puede
ser fijada, pero m<>s de una puede ser revisada por coincidencias. La
direcci<EFBFBD>n final puede ser remplazada por la palabra clave
@@ -497,8 +532,11 @@ caso en el cual dnsmasq proveer
y
.B pxe-service
para detalles.)
La secci<63>n interface:<interface name> no es normalmente usada. Ver la
secci<EFBFBD>n NOTAS para detalles sobre esto.
.TP
.B \-G, --dhcp-host=[<direcci<EFBFBD>n de hardware>][,id:<client_id>|*][,net:<netid>][,<direcci<63>n IP>][,<nombre de host>][,<tiempo de arriendo>][,ignore]
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<tiempo_de_arriendo>][,ignorar]
Especificar par<61>metros por host para el servidor DHCP. Esto permite
que una m<>quina con una direcci<63>n de hardware particular sea siempre
alocada el mismo nombre de host, direcci<63>n IP, y tiempo de arriendo.
@@ -513,10 +551,15 @@ le dice a dnsmasq que debe darle a la m
ethernet 00:20:e0:3b:13:af el nombre wap, y un arriendo DHCP infinito.
.B --dhcp-host=lap,192.168.0.199
le dice a dnsmasq que siempre debe alocarle a la maquina lap
la direcci<63>n IP 192.168.0.199. Direcciones alocadas de esta manera
no tienen que estar dentro del rango dado con la opci<63>n --dhcp-range,
pero deben estar en la red siendo servida por el servidor DHCP. Se
permite usar identificadores de clientes en vez de direcciones de
la direcci<63>n IP 192.168.0.199.
Direcciones alocadas de esta manera no tienen que estar dentro
del rango dado con la opci<63>n --dhcp-range, pero deben estar en la subred
de un rango DHCP (dhcp-range) v<>lido. Para subredes que no necesitan
una collecci<63>n de direcciones dinamicamente alocadas, usar la palabra
clave "static" in la declaraci<63>n dhcp-range.
Es permitido usar identificadores de cliente en vez de direcciones de
hardware para identificar hosts prefijando 'id:'. O sea que:
.B --dhcp-host=id:01:02:03:04,.....
se refiere al host con identificador de cliente 01:02:03:04.
@@ -530,7 +573,14 @@ presenta un ID de cliente algunas veces pero otras no.
Si un nombre aparece en /etc/hosts, la direcci<63>n asociada puede
ser alocada a un arriendo DHCP, pero solo si existe una opci<63>n
.B --dhcp-host
la cual especifica el nombre tambi<62>n. La palabra clave "ignore"
la cual especifica el nombre tambi<62>n. Solo un hostname puede ser
brindado en una opci<63>n
.B dhcp-host
pero aliases son posibles por medio del uso de CNAMEs. (Ver
.B --cname
).
La palabra clave "ignore"
le dice a dnsmasq que no debe ofrecer jam<61>s un arriendo DHCP a
una m<>quina. La m<>quina puede ser especificada por direcci<63>n de
hardware, ID de cliente, o nombre de host, por ejemplo:
@@ -538,14 +588,16 @@ hardware, ID de cliente, o nombre de host, por ejemplo:
Esto es <20>til cuando hay otro servidor DHCP en la red que debe ser
usado por alg<6C>nas m<>quinas.
El net:<network-id> fija la etiqueta network-id cuando sea que
El set:<tag> fija la etiqueta cuando sea que
esta directiva dhcp-host est<73> en uso. Esto puede ser usado para
enviar selectivamente opciones DHCP a este host. Cuando un host
coincide con cualquier directiva dhcp-host (o una implicada por
/etc/ethers) entonces la etiqueta network-id especial "known" es
enviar selectivamente opciones DHCP a este host. M<EFBFBD>s de una etiqueta
puede ser fijada en una directiva dhcp-host (pero no en otros lugares
donde "set:<tag>" es permitido). Cuando un host coincide con
cualquier directiva dhcp-host (o una implicada por
/etc/ethers) entonces la etiqueta especial "known" es
fijada. Esto permite que dnsmasq sea configurado para ignorar
pedidos desde m<>quinas desconocidas usando
.B --dhcp-ignore=#known
.B --dhcp-ignore=tag:!known
Direcciones ethernet (pero no client-ids) pueden tener bytes
comod<EFBFBD>nes, as<61> que por ejemplo
.B --dhcp-host=00:20:e0:3b:13:*,ignore
@@ -591,9 +643,10 @@ DHCP. El formato de /etc/ethers es una direcci
por ya sea un nombre de host o una direcci<63>n IP. Al ser leidas por
dnsmasq, estas l<>neas tienen ex<65>ctamente el mismo efecto que opciones
.B --dhcp-host
que contienen la misma informaci<63>n. /etc/ethers es re-le<6C>da cuando dnsmasq recibe un SIGHUP.
que contienen la misma informaci<63>n. /etc/ethers es re-le<6C>da cuando
dnsmasq recibe un SIGHUP.
.TP
.B \-O, --dhcp-option=[<network-id>,[<network-id>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<valor>[,<valor>]]
.B \-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>],[<value>[,<value>]]
Especificar opciones diferentes o extra a clientes DHCP. Por
predeterminado, dnsmasq env<6E>a algunas opciones est<73>ndar a clientes
DHCP. La m<>scara de subred y direcci<63>n broadcast son fijadas igual
@@ -618,9 +671,9 @@ o
La direcci<63>n especial 0.0.0.0 es entendida que significa "la
direcci<EFBFBD>n de la m<>quina que corre dnsmasq". Tipos de data permitidos
son direcciones IP de cuatro segmentos, un n<>mero decimal, d<>gitos hex
separados por colones, y un string de texto. Si las network-ids
separados por colones, y un string de texto. Si las etiquetas
opcionales son brindadas, entonces esta opci<63>n es solo enviada cuando
todas las network-ids coinciden.
todas las etiquetas coinciden.
Procesamiento especial es llevado a cabo en un argumento de texto para
la opci<63>n 119, en conforme con RFC3397. Direcciones IP textuales o de
@@ -672,7 +725,7 @@ para identificar esta opci
La direcci<63>n 0.0.0.0 no es tratada de forma especial en opciones encapsuladas.
.TP
.B --dhcp-option-force=[<network-id>,[<network-id>,]][encap:<opt>,][rfc3925-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<valor>[,<valor>]]
.B --dhcp-option-force=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],]<opt>,[<value>[,<value>]]
Esto funciona ex<65>ctamente de la misma forma que
.B --dhcp-option
excepto que la opci<63>n siempre ser<65> enviada, a<>n si el cliente no la pide en
@@ -687,20 +740,21 @@ hacia opciones DHCP. Esto crea espacio extra en el paquete DHCP para opciones,
pero puede raramente confundir clientes viejos o defectuosos. Esta opci<63>n forza
comportamiento "simple y sencillo" para prevenir problemas en tales casos.
.TP
.B \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
Trazar desde un string vendor-class a un network id. La mayor<6F>a de los
.B \-U, --dhcp-vendorclass=set:<tag>,<vendor-class>
Trazar desde un string vendor-class a una etiqueta. La mayor<6F>a de los
clientes DHCP proveen una "vendor class" la cual representa, en cierto
sentido, el tipo de host. Esta opci<63>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
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
peritir<EFBFBD>a que opciones sean fijadas solo para impresoras HP as<61>:
.B --dhcp-option=printers,3,192.168.4.4
.B --dhcp-option=tag:printers,3,192.168.4.4
El string vendor-class es coordinado con el vendor-class proveido por
el cliente, para permitir coincidencias borrosas.
el cliente, para permitir coincidencias borrosas. El prefijo set: es
opcional, pero permitido por razones de consistencia.
.TP
.B \-j, --dhcp-userclass=<network-id>,<user-class>
Trazar desde un string user-class a un network id (con coordinaci<63>n
.B \-j, --dhcp-userclass=set:<tag>,<user-class>
Trazar desde un string user-class a una etiqueta (con coordinaci<63>n
substring, como con vendor-class). La mayor<6F>a de los clientes DHCP
proveen un "user class" el cual es configurable. Esta opci<63>n traza
clases user a network ids, de tal manera que opciones DHCP puedan
@@ -708,26 +762,43 @@ ser selectivamente enviadas a diferentes tipos de hosts. Es posible,
por ejemplo, usar esto para especificar una impresora diferente para
hosts en la clase "cuentas" que para los de la clase "ingenieria".
.TP
.B \-4, --dhcp-mac=<network-id>,<direcci<63>n MAC>
Trazar desde una direcci<63>n MAC a una network id. La direcci<63>n MAC
.B \-4, --dhcp-mac=set:<tag>,<MAC address>
Trazar desde una direcci<63>n MAC a una etiqueta. La direcci<63>n MAC
puede incluir comod<6F>nes. Por ejemplo:
.B --dhcp-mac=3com,01:34:23:*:*:*
.B --dhcp-mac=set:3com,01:34:23:*:*:*
fijar<EFBFBD>a el tag "3com" a cualquier host el cual su MAC coincida con
el patr<74>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
Trazar de opciones agente de relay RFC3046 a etiquetas. Estos
datos pueden ser prove<76>dos por agentes de relay DHCP. El circuit-id o
remote-id es normlamente brindado como hex separado por doblepuntos, pero
tambi<EFBFBD>n se permite un string simple. Si se obtiene una coincidencia exacta
entre el circuit o agent ID y uno prove<76>do por un agente de relay,
network-id es fijado.
la etiqueta es fijada.
.TP
.B --dhcp-subscrid=<network-id>,<subscriber-id>
Trazar de opciones relay subscriber-id RFC3993 a opciones network-id.
.B --dhcp-subscrid=set:<tag>,<subscriber-id>
Trazar de opciones relay subscriber-id RFC3993 a etiquetas.
.TP
.B --dhcp-match=<network-id>,<option number>|option:<option name>|vi-encap:<enterprise>[,<valor>]
Sin un valor, fijar la etiqueta network-id si el cliente env<6E>a una opci<63>n
.B --dhcp-proxy[=<ip addr>]......
Un agente de relay normal es usado solamente para reenviar las partes
iniciales de una interacci<63>n DHCP con el servidor DHCP. Una vez que
un cliente es configurado, se comunica diectamente con el servidor. Esto
es indeseable si el agente de relay est<73> agregando informaci<63>n extra a
los paquetes DHCP, tal como usado por
.B dhcp-circuitid
y
.B dhcp-remoteid.
Una implementaci<63>n relay completa puede usar la opci<63>n serverid-override
RFC 5107 para obligar al servidor DHCP a usar el relay como un proxy
completo, con todos los paquetes pasando a travez de el. Esta opci<63>n
provee una manera alternativa de hacer la misma cosa, para relays que
no tienen soporte RFC 5107. Brindada por si sola, manipula el server-id
para todas las interacciones via relays. Si una lista de IPs es brindada,
solo interacciones via relays en esas direcciones son afectadas.
.TP
.B --dhcp-match=set:<tag>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>]
Sin un valor, fijar la etiqueta si el cliente env<6E>a una opci<63>n
DHCP del n<>mero o valor brindado. Cuando un valor es brindado, fijar la
etiqueta solo si la opci<63>n es enviada y coincide con el valor. El valor puede
ser de la forma "01:ff:*:02", caso en el cual el valor debe coincidir (aparte
@@ -737,7 +808,7 @@ del final del valor. El valor tambi
caso en el cual la opci<63>n enviada es tratada como un array, y un elemento debe
coincidir, as<61> que
--dhcp-match=efi-ia32,option:client-arch,6
--dhcp-match=set:efi-ia32,option:client-arch,6
fijar<EFBFBD> la etiqueta a "efi-ia32" si el n<>mero 6 aparece en la lista de
architecturas enviada por los clientes en opci<63>n 93. (Ver RFC 4578 para
@@ -745,42 +816,58 @@ detalles.) Si el valor es un string, coincidencia substring es usada.
La forma especial con vi-encap:<enterpise number> busca coincidencia con
clases de vendedor identificadoras para el enterprise especificado. Por
favor ver RFC 3925 para mas detalles sobre las bestias raras e interesantes.
favor ver RFC 3925 para mas detalles sobre estas bestias raras e interesantes.
.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.
.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
Llevar a cabo operaciones boolean en etiquetas. Cualquier etiqueta
que aparece como set:<tag> es fijada si todas las etiquetas que aparecen
como tag:<tag> estan fijadas, (o desfijadas cuando tag:!<tag> es
usado). Si ning<6E>n tag:<tag> aparece, etiquetas set:<tag> son fijadas
incondicionalmente. Cualquier cantidad de formas set: y tag:
pueden aparecer, en cualquier orden. L<>neas tag-if son ejecutadas
en orden, as<61> que si la etiqueta en tag:<tag> es una etiqueta fijada
por otra
.B tag-if,
la l<>nea que fija la etiqueta debe preceder a la que comprueba.
.TP
.B --dhcp-ignore-names[=<network-id>[,<network-id>]]
Cuando todos los network-ids brindados coinciden con el juego de
network-ids derivado de la red, host, classes de vendedor y usuario,
ignorar cualquier nombre de host proveido por el host. N<>tese que,
a diferencia de dhcp-ignore, es permisible no brindar ning<6E>n tag netid,
.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
Cuando todoas las etiquetas brindadas aparecen en el juego de etiquetas
ignorar el host y no brindarle un arriendo DHCP.
.TP
.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]]
Cuando todos las etiquetas brindadas aparecen en el juego de etiquetas, ignorar cualquier nombre de host proveido por el host. N<>tese que,
a diferencia de dhcp-ignore, es permisible no brindar ninguna etiqueta,
y en tal caso nombres de host proveidos por clientes DHCP siempre son
ignorados, y hosts DHCP son agregados al DNS usando solo la configuraci<63>n
dhcp-host en dnsmasq y el contenido de /etc/hosts y /etc/ethers.
.TP
.B --dhcp-broadcast=<network-id>[,<network-id>]
Cuando todos los network-ids brindados coinciden con el juego de network-ids
derivados de la red, host, clases de vendedor y usuarios, siempre usar
broadcast para comunicarse con el host cuando est<73> sin configurar. La
mayor<EFBFBD>a de clientes DHCP que necesitan respuestas broadcast fijan una
opci<EFBFBD>n en sus pedidos para que esto pase automaticamente, algunos
clientes BOOTP viejos no lo hacen.
.B --dhcp-generate-names=tag:<tag>[,tag:<tag>]
Generar un nombre para clientes DHCP que de otra forma no tienen uno,
usando la direcci<63>n MAC expresada en hex, separada por guiones. N<>tese
que si un host provee un nombre, ser<65> usado preferiblemente sobre este,
a menos que
.B --dhcp-ignore-names
est<EFBFBD> fijado.
.TP
.B \-M, --dhcp-boot=[net:<network-id>,]<filename>,[<servername>[,<server address>]]
.B --dhcp-broadcast[=tag:<tag>[,tag:<tag>]]
Cuando todas las etiquetas aparecen en el juego de etiquetas, siempre
usar broadcast para comunicar con el host cuando no est<73> configurado.
Es permisible omitir las etiquetas, caso en el cual esto es
incondicional. La mayor<6F>a de clientes DHCP que necesitan
respuestas broadcast fijan una opci<63>n en sus pedidos para que esto pase automaticamente, algunos clientes BOOTP viejos no lo hacen.
.TP
.B \-M, --dhcp-boot=[tag:<tag>,]<filename>,[<servername>[,<server address>]]
Fijar opciones BOOTP que han de ser devueltas por el servidor DHCP. Nombre
y direcci<63>n de servidor son opcionales: si no son brindadas, el nombre es
dejado en blanco, y la direcci<63>n es fijada a la de la m<>quina que corre
dnsmasq. Si dnsmasq est<73> brindando servicio TFTP (ver
.B --enable-tftp
) entonces solo el nombre de archivo es requirido aqu<71> para habilitar
el inicio atrav<61>z de una red. Si las opcionales network-ids son brindadas,
el inicio atrav<61>z de una red. Si las opcionales etiquetas son brindadas,
ellas deber<65>n coincidir para que esta configuraci<63>n sea enviada. N<>tese
que network-ids est<73>n prefijadas con "net:" para distinguirlas.
.TP
.B --pxe-service=[net:<network-id>,]<CSA>,<texto de men<EFBFBD>>[,<nombre base>|<tipo de servicio boot>][,<direcci<63>n de servidor>]
.B --pxe-service=[tag:<tag>,]<CSA>,<menu text>[,<basename>|<bootservicetype>][,<server address>]
La mayor<6F>a de usos para boot-ROMS PXE simplemente permiten al sistema PXE
obtener una direcci<63>n IP y entonces bajar el archivo especificado por
.B dhcp-boot
@@ -808,7 +895,7 @@ de servicio boot o nombre de archivo es brindado (o un tipo de servicio boot
de 0 es especificado), entonces la opci<63>n de men<65> abortar<61> el proceso net boot
y continuar<61> desde el medio local.
.TP
.B --pxe-prompt=[net:<network-id>,]<prompt>[,<timeout>]
.B --pxe-prompt=[tag:<tag>,]<prompt>[,<timeout>]
Fijar esto hace que un aviso sea expuesto despues del boot PXE. Si el timeout
es brindado, entonces despues que el timeout se haya vencido sin input del
teclado, la primera opci<63>n del men<65> sera automaticamente ejecutada. Si el
@@ -834,7 +921,7 @@ en
.TP
.B \-X, --dhcp-lease-max=<n<>mero>
Limita a dnsmasq a el n<>mero especificado de arriendos DHCP. El
predeterminado es 150. El limite es para prevenir ataques DoS desde
predeterminado es 1000. El limite es para prevenir ataques DoS desde
hosts que crean cientos de arriendos y usan mucha de la memoria del
proceso dnsmasq.
.TP
@@ -874,7 +961,7 @@ cuidado.
.TP
.B --log-dhcp
Bitacor<EFBFBD>o extra para DHCP: Bitacorear todas las opciones enviadas a
clientes DHCP y las etiquetas netid usadas para determinarlos.
clientes DHCP y las etiquetas usadas para determinarlos.
.TP
.B \-l, --dhcp-leasefile=<path>
Usar el archivo especificado para almacenar informaci<63>n de arriendos
@@ -883,6 +970,7 @@ DHCP.
.B \-6 --dhcp-script=<path>
Cuando un arriendo DHCP nuevo es creado, o uno viejo es
destruido, el ejecutable especificado por esta opci<63>n es ejecutado.
<path> debe ser un pathname absoluto, ninguna b<>squeda PATH ocurre.
Los argumentos para el binario son "add", "old", o "del", la direcci<63>n
MAC del host, la direcci<63>n IP, y el hostname, si es
conocido. "add" significa que un arriendo ha sido creado, "del" que
@@ -894,40 +982,64 @@ que no es ethernet, tendr
"06-01:23:45:67:89:ab" para token ring. El proceso es ejecutado como root
(asumiendo que dnsmasq fue originalmente ejecutado como root) a<>n si dnsmasq
est<EFBFBD> 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<6E> un client-id, es almacenado en la variable de ambiente
DNSMASQ_CLIENT_ID. Si el dominio completamente calificado del host
es conocido, la parte de dominio es almacenada en DNSMASQ_DOMAIN. Si
el cliente brinda informaci<63>n de clase de vendedor, nombre de host,
o clase de usuario, estos son brindados en las variables
El ambiente es heredado del usuario que ha invocado a dnsmasq, con algunas
o todas de las siguientes variables agregadas.
DNSMASQ_CLIENT_ID si el host brindo un client-id.
DNSMASQ_DOMAIN si el nombre de dominio completamente calificado del host
es conocido, esto es fijado a la parte del dominio.
Si el cliente brinda vendor-class, hostname o user-class, estos son
brindados en las variables
DNSMASQ_VENDOR_CLASS, DNSMASQ_SUPPLIED_HOSTNAME, y
DNSMASQ_USER_CLASS0..DNSMASQ_USER_CLASSn, pero solo para acciones "add"
y "old" cuando un host reanuda un arriendo existente, dado a que estos
datos no son almacenados en la base de datos de arriendos de dnsmasq.
Si dnsmasq fue compilado con HAVE_BROKEN_RTC, entonces la duraci<63>n del
arriendo (en segundos) es almacenada en DNSMASQ_LEASE_LENGTH, de otra
manera el tiempo de vencimiento es almacenado en DNSMASQ_LEASE_EXPIRES.
El n<>mero de segundos faltante para el vencimiento del arriendo siempre
es almacenado en DNSMASQ_TIME_REMAINING.
Si un arriendo sol<6F>a tener un nombre de host, el cual es removido, un
evento "old" es generado con el nuevo estado del arriendo, (por ejemplo, sin
nombre), y el nombre anterior es brindado en la variable de ambiente
DNSMASQ_OLD_HOSTNAME. DNSMASQ_INTERFACE almacena el nombre de la interface
DNSMASQ_OLD_HOSTNAME.
DNSMASQ_INTERFACE almacena el nombre de la interface
en la cual lleg<65> el pedido; esto no es fijado para acciones "viejas"
cuando dnsmasq re-inicia. DNSMASQ_RELAY_ADDRESS es fijado si el cliente
cuando dnsmasq re-inicia.
DNSMASQ_RELAY_ADDRESS es fijado si el cliente
us<EFBFBD> un relay DHCP para contactar a dnsmasq y la direcci<63>n IP del relay
es conocida. DNSMASQ_TAGS contiene todas las etiquetas network-id fijadas
es conocida.
DNSMASQ_TAGS contiene todas las etiquetas network-id fijadas
durante la transacci<63>n DHCP, separadas por espacios.
Todos los descriptores de archivo est<73>n cerrados
excepto stdin, stdout, y stderr los cuales est<73>n abiertos a /dev/null
(excepto en modo debug).
Este gui<75>n no es invocado concurrentemente: si cambios de arriendos
subsiguientes ocurren, el gui<75>n no es invocado otra vez hasta que
cualquier invocaci<63>n existente haga exit. Al inicio de dnsmasq, el gui<75>n
Este gui<75>n no es invocado concurrentemente: m<>ximo una instamcia del
gui<EFBFBD>n est<73> corriendo a la vez (dnsmasq espera a que una instancia de
gui<EFBFBD>n haga exit antes de correr la siguiente). Cambios a la base de
datos de arriendos que requieren que el gui<75>n sea invocado son puestos
en cola esperando el exit de una instancia corriente. Si esta cola permite
que cambios multiples de estado le ocurran a un arriendo individual antes
de que el gui<75>n pueda ser ejecutado entonces estados anteriores son descartados
y el estado actual del arriendo es reflejado cuando el gui<75>n finalmente corre.
Al inicio de dnsmasq, el gui<75>n
ser<EFBFBD> invocado para todos los arriendos existentes mientras van siendo
le<EFBFBD>dos desde el archivo de arriendos. Arriendos vencidos ser<65>n llamados
con "del" y otros con "old". <path> debe ser un path absoluto, ninguna
b<EFBFBD>squeda PATH ocurre. Cuando dnsmasq recibe una se<73>al HUP, el gui<75>n ser<65>
b<EFBFBD>squeda PATH ocurre cuando arriendos dnsmasq ser<65>n llamados con "del"
y otros con "old". Cuando dnsmasq recibe una se<73>al HUP, el gui<75>n ser<65>
invocado para arriendos existentes con un evento "old".
.TP
.B --dhcp-scriptuser
@@ -1000,18 +1112,20 @@ sin una direcci
.B --dhcp-fqdn
est<EFBFBD> fijado.
.TP
.B --enable-tftp
.B --enable-tftp[=<interface>]
Habilitar la funci<63>n de servidor TFTP. Esto est<73> deliberadamente limitado
a lo necesario para hacerle a un cliente un inicio v<>a red. Solo lectura es
permitida; las extensiones tsize y blksize son soportadas (tsize solo es
soportada en modo octeto).
soportada en modo octeto). Ver secci<63>n de NOTAS para el uso de el argumento
de interface.
.TP
.B --tftp-root=<directorio>
.B --tftp-root=<directory>[,<interface>]
Buscar, relativo al directorio brindado, archivos para transferir mediante el
uso de TFTP. Cuando esta opci<63>n est<73> fijada, paths TFTP que incluyen ".." son
rechazados, para prevenir que clientes salgan de la ra<72>z especificada. Paths
absolutos (los que comienzan con "/") est<73>n permitidos, pero deben estar
dentro del tftp-root.
dentro del tftp-root. Si el argumento opcional de interface es brindado, el
directorio es solo usado para pedidos TFTP v<>a esa interface.
.TP
.B --tftp-unique-root
Agregar la direcci<63>n IP del cliente TFTP como un componente path del lado del
@@ -1199,36 +1313,46 @@ apunta a un nombre sombreado, entonces buscando el CNAME a trav
dnsmasq resultar<61> en que la direcci<63>n no-sombreada ser<65> asociada con
el destino del CNAME. Para circumventar esto, agregar el CNAME a
/etc/hosts de tal manera que el CNAME es sombreado tambi<62>n.
.PP
El sistema network-id funciona de la siguiente manera: Para cada pedido
DHCP, dnsmasq colecciona un juego de etiquetas network-id v<>lidas,
una del
El sistema de etiquetas funciona de la siguiente manera: Para cada pedido
DHCP, dnsmasq colecciona un juego de etiquetas v<EFBFBD>lidas de l<>neas de
configuraci<EFBFBD>n activas que incluyen set:<tag>, incluyendo una del
.B dhcp-range
usado para alocar la direcci<63>n, una de cualquier
.B dhcp-host
que coincida (y "known" si un dhcp-host coincide), la etiqueta "bootp"
para pedidos BOOTP, una etiqueta cuyo nombre es el nombre de la
interface donde lleg<65> el pedido, y posiblemente muchas de clases
de vendedor y usuario que coincidan que hayan sido enviadas por
el cliente DHCP. Cualquier opci<63>n
que coincida (y "known" si un dhcp-host coincide).
La etiqueta "bootp" es fijada para pedidos BOOTP, y una etiqueta cuyo
nombre es el nombre de la interface donde lleg<65> el pedido tambien es
fijada.
Cualquier linea de configuraci<63>n que incluya uno o mas
construcciones tag:<tag> solo ser<65> v<>lida si todas las etiquetas
coinciden en el juego derivado arriba. T<>picamente esto es dhcp-option.
.B dhcp-option
que tenga etiquetas network-id ser<EFBFBD> usada en preferencia de una opci<EFBFBD>n
que tenga etiquetas ser<EFBFBD> usada en preferencia de una opci<EFBFBD>n
.B dhcp-option,
sin etiqueta, con tal que _todas_ las etiquetas coincidan en alguna
parte del juego coleccionado describido arriba. El prefijo "#" en una
etiqueta significa "no" as<61> que --dhcp=option=#purple,3,1.2.3.4 env<6E>a
la opci<63>n cuando la etiqueta network-id "purple" no est<73> en el juego
de etiquetas v<>lidas.
parte del juego coleccionado describido arriba. El prefijo '!' en una
etiqueta significa "no" as<61> que --dhcp=option=tag:!purple,3,1.2.3.4 env<6E>a
la opci<63>n cuando la etiqueta "purple" no est<73> en el juego
de etiquetas v<>lidas. (Si se est<73> usando esto en una l<>nea de comandos
en vez de un archivo de configuraci<63>n, asegurese de escapar !, el cual
es un metacaracter de shell.)
.PP
N<EFBFBD>tese que para
.B dhcp-range
ambos tag:<tag> y set:<tag> son permitidos, para seleccionar el rango
en uso basado en (por ejemplo) dhcp-host, y para afectar las opciones
enviadas, basadas en el rango seleccionado.
Este sistema evolucion<6F> de uno anterior mas limitado y para compatibildad
reversa "net:" puede ser usada en vez de "tag:" y "set:" puede ser
omitida. (Excepto en
.B dhcp-host,
donde "net:" puede ser usado en vez de "set:".) Por la misma raz<61>n, '#'
puede ser usado en vez de '!' para indicar NO.
.PP
Si el network-id en un
.B dhcp-range
es prefijado con "net:", entonces su significado cambia de "fijar
etiqueta" a "coincidir con etiqueta". O sea que si hay m<>s de un
dhcp-range en en una subred, y uno tiene una etiqueta network-id la
cual est<73> fijada (por ejemplo una opci<63>n de clase de vendedor) entonces
hosts que fijen la etiqueta network-id ser<65>n alocados direcciones en
el rango etiquetado.
.PP
El servidor DHCP de dnsmasq funcionar<61> como servidor BOOTP tambien,
con tal que las direcciones MAC y IP de los clientes sean brindadas,
ya sea usando configuraciones
@@ -1239,11 +1363,54 @@ o en
.B dhcp-range
est<EFBFBD> presente para activar el servidor DHCP en una red particular.
(Fijar --bootp-dynamic elimina la necesidad de trazados est<73>ticos.) El
par<EFBFBD>metro de nombre de archivos en un pedido BOOTP es revisado para
ver si coincide con alg<6C>n network-id en configuraci<63>nes
.B dhcp-option
al igual que la etiqueta "bootp", permitiendo as<EFBFBD> alg<EFBFBD>n control sobre
las opciones devueltas a diferentes clases de hosts.
par<EFBFBD>metro de nombre de archivos en un pedido BOOTP es usado como
una etiqueta, al igual que la etiqueta "bootp", permitiendo as<61> alg<6C>n
control sobre las opciones devueltas a diferentes clases de hosts.
.B dhcp-range
puede tener un nombre de interface brindado como
"interface:<interface-name>". La sem<65>ntica de esto es as<61>:
Para DHCP, si cualquier otro dhcp-range existe _sin_ un nombre de
interface, entonces el nombre de interface es ignorado y dnsmasq
se comporta como si las partes de interface no existieran, de otra forma
DHCP solo se provee a interfaces mencionadas en declaraciones
dhcp-range. Para DNS, si no hay opciones
.B --interface
o
.B --listen-address
el comportamiento no se modifica por la parte de interface. Si cualquiera
de estas opciones est<73> presente, las interfaces mencionadas en dhcp-ranges
son agregadas all juego que obtienen servicio DNS.
Similarmente,
.B enable-tftp
puede tomar un nombre de interface, el cual habilita TFTP solo para una
interface en particular, ignorando opciones
.B --interface
o
.B --listen-address.
Adicionalmente,
.B --tftp-secure
y
.B --tftp-unique-root
y
.B --tftp-no-blocksize
son ignorados por pedidos desde dichas interfaces. (Una directiva
.B --tftp-root
brindando un path ra<72>z y una interface debe ser brindada tambien.)
Estas reglas pueden parecer raras a primera vista, pero permiten que
una simple linea de la forma
"dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" sea agregada a
configuraci<EFBFBD>n dnsmasq, lo cual brinda servicios DHCP y DNS a esa interface,
sin afectar los servicios en otras interfaces y irrespectivamente de
la existencia o no de lineas "interface=<interface>" en alguna otra parte
de la configuraci<63>n dnsmasq.
"enable-tftp=virt0" y "tftp-root=<root>,virt0" hacen el mismo trabajo
para TFTP.
La idea es que una linea as<61> pueda ser agregada automaticamente
por libvirt o sistemas equivalentes, sin estorbar alguna
configuraci<EFBFBD>n manual.
.SH C<EFBFBD>DIGOS EXIT
.PP
@@ -1276,10 +1443,8 @@ no escalaban tan bien.
.PP
Dnsmasq es capaz de soportar con DNS y DHCP a por lo menos mil (1,000)
clientes. Por supuesto que para lograr esto debe aumentarse el valor de
.B --dhcp-lease-max
, y tiempos de arriendo no deben ser muy cortos (menos de una hora).
El valor de
clientes. Los tiempos de arriendo no deben ser muy cortos (menos
de una hora). El valor de
.B --dns-forward-max
puede ser aumentado: comienze con el equivalente a el n<>mero de clientes y
aum<EFBFBD>ntelo si parece lento el DNS. N<>tese que el rendimiento DNS depende

View File

@@ -73,6 +73,12 @@ option permet de doner une valeur de durée de vie par défaut (en secondes) que
dnsmasq utilise pour mettre les réponses négatives dans son cache, même en
l'absence d'enregistrement SOA.
.TP
.B --max-ttl=<durée>
Définie la valeur de TTL maximum qui sera fournie aux clients. La valeur maximum
de TTL spécifiée sera fournie aux clients en remplacement de la vraie valeur de TTL
si cette dernière est supérieure. La valeur réelle de TTL est cependant conservée dans
le cache afin d'éviter de saturer les serveurs DNS en amont.
.TP
.B \-k, --keep-in-foreground
Ne pas aller en tâche de fond au lancement, mais en dehors de cela, fonctionner
normalement. Ce mode est prévu pour les cas où Dnsmasq est lancé par daemontools
@@ -94,10 +100,12 @@ réception d'un signal SIGUSR1.
Définit la "facility" dans laquelle Dnsmasq enverra ses entrées syslog, par
défaut DAEMON ou LOCAL0 si le mode debug est activé. Si la "facility" contient
au moins un caractère "/", alors Dnsmasq considère qu'il s'agit d'un fichier et
enverra les logs dans le fichier correspondant à la place du syslog. (Les
erreurs lors de la lecture de la configuration vont toujours vers le syslog,
mais tous les messages postérieures à un démarrage réussi seront exclusivement
envoyés vers le fichier de logs). Lorsque Dnsmasq est configuré pour envoyer
enverra les logs dans le fichier correspondant à la place du syslog. Si la
"facility" est '-', alors dnsmasq envoie les logs sur la sortie d'erreur
standard stderr. (Les erreurs lors de la lecture de la configuration vont
toujours vers le syslog, mais tous les messages postérieurs à un démarrage
réussi seront exclusivement envoyés vers le fichier de logs).
Lorsque Dnsmasq est configuré pour envoyer
ses traces vers un fichier, la réception d'un signal SIGUSR2 entraine la
fermeture et réouverture du fichier. Cela permet la rotation de fichiers de
traces sans nécessiter l'arrêt de Dnsmasq.
@@ -317,6 +325,19 @@ serveurs amonts suite à une résolution de nom. Cela bloque les attaques cherch
à détourner de leur usage les logiciels de navigation web ('browser') en s'en
servant pour découvrir les machines situées sur le réseau local.
.TP
.B --rebind-localhost-ok
Exclue 127.0.0/8 des vérifications de réassociation DNS. Cette gamme d'adresses
est retournée par les serveurs Realtime Blackhole (RBL, utilisés dans la
lutte contre le spam), la bloquer peut entraîner des disfonctionnements de ces
services.
.TP
.B --rebind-domain-ok=[<domaine>]|[[/<domaine>/[<domaine>/]
Ne pas détecter ni bloquer les actions de type dns-rebind pour ces domaines.
Cette option peut prendre comme valeur soit un nom de domaine soit plusieurs
noms de domains entourés par des '/', selon une syntaxe similaire à l'option
--server, c-à-d :
.B --rebind-domain-ok=/domaine1/domaine2/domaine3/
.TP
.B \-n, --no-poll
Ne pas vérifier régulièrement si le fichier /etc/resolv.conf a été modifié.
.TP
@@ -354,6 +375,20 @@ option
.B -S
est autorisée, en répétant les domaines et adresses IP comme requis.
Le domaine le plus spécifique l'emporte sur le domaine le moins spécifique,
ainsi :
.B --server=/google.com/1.2.3.4
.B --server=/www.google.com/2.3.4.5
enverra les requêtes pour *.google.com à 1.2.3.4, à l'exception des requêtes
*www.google.com, qui seront envoyées à 2.3.4.5.
L'adresse spéciale '#' signifie "utiliser les serveurs standards", ainsi
.B --server=/google.com/1.2.3.4
.B --server=/www.google.com/#
enverra les requêtes pour *.google.com à 1.2.3.4, à l'exception des requêtes
pour *www.google.com qui seront envoyées comme d'habitude (c-à-d aux serveurs
définis par défaut).
Il est également permis de donner une option
.B -S
avec un nom de domaine mais sans
@@ -502,7 +537,7 @@ lorsqu'un serveur web a la résolution de nom activée pour l'enregistrement de
son journal des requêtes, ce qui peut générer un nombre important de requêtes
simultanées.
.TP
.B \-F, --dhcp-range=[[net:]identifiant de réseau,]<adresse de début>,<adresse de fin>[,<masque de réseau>[,<broadcast>]][,<durée de bail>]
.B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label],]<adresse de début>,<adresse de fin>[,<masque de réseau>[,<broadcast>]][,<durée de bail>]
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
<adresse de début> et <adresse de fin> et à partir des adresses définies
statiquement dans l'option
@@ -522,10 +557,11 @@ relais DHCP ("relay agent"). L'adresse de broadcast est toujours optionnelle.
Il est toujours possible d'avoir plus d'une plage DHCP pour un même
sous-réseau.
L'identifiant de réseau optionnel est un label alphanumérique qui permet de
marquer ce réseau afin de fournir des options DHCP spécifiques à chaque réseau.
Lorsque préfixé par 'net:', la signification change est au lieu de définir un
L'identifiant de label optionnel
.B set:<label>
fournie une étiquette alphanumérique qui identifie ce réseau, afin de permettre
la fourniture d'options DHCP spécifiques à chaque réseau.
Lorsque préfixé par 'tag:', la signification change, et au lieu de définir un
label, il définit le label pour laquelle la règle s'applique. Un seul label peut-
être défini mais plusieurs labels peuvent coïncider.
@@ -545,8 +581,11 @@ spécifié. (voir
et
.B pxe-service
pour plus de détails).
La section interface:<nom d'interface> n'est normalement pas utilisée. Se
référer aux indications de la section NOTES pour plus de détail à ce sujet.
.TP
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,net:<identifiant de réseau>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
possédant une adresse matérielle spécifique de se voir toujours allouée les
mêmes nom d'hôte, adresse IP et durée de bail. Un nom d'hôte spécifié comme
@@ -560,9 +599,15 @@ spécifie à Dnsmasq de fournir à la machine d'adresse matérielle
.B --dhcp-host=lap,192.168.0.199
spécifie à Dnsmasq d'allouer toujours à la machine portant le nom lap
l'adresse IP 92.168.0.199. Les adresses allouées comme ceci ne sont pas
contraintes dans une plage d'adresse spécifiée par une option --dhcp-range, mais
elles doivent être sur un réseau servi par le serveur DHCP. Il est possible
l'adresse IP 192.168.0.199.
Les adresses allouées de la sorte ne sont pas contraintes à une plage d'adresse
spécifiée par une option --dhcp-range, mais elles se trouver dans le même
sous-réseau qu'une plage dhcp-range valide. Pour les sous-réseaux qui n'ont pas
besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la
déclaration de plage d'adresses dhcp-range.
Il est possible
d'utiliser des identifiants clients plutôt que des adresses matérielles pour
identifier les hôtes, en préfixant par ceux-ci par 'id:'. Ainsi,
.B --dhcp-host=id:01:02:03:04,.....
@@ -578,7 +623,13 @@ identifiant client mais pas les autres.
Si un nom apparaît dans /etc/hosts, l'adresse associée peut être allouée à un
bail DHCP mais seulement si une option
.B --dhcp-host
spécifiant le nom existe par ailleurs. Le mot clef "ignore" ("ignorer") indique
spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut-être donné dans
une option
.B dhcp-host
, mais les alias sont possibles au travers de l'utilisation des CNAMEs. (Voir
.B --cname
).
Le mot clef "ignore" ("ignorer") indique
à Dnsmasq de ne jamais fournir de bail DHCP à une machine. La machine peut être
spécifiée par son adresse matérielle, son identifiant client ou son nom d'hôte.
Par exemple
@@ -586,14 +637,15 @@ Par exemple
Cela est utile lorsqu'un autre serveur DHCP sur le réseau doit être utilisé par
certaines machines.
Le paramètre net:<identifiant réseau> permet de définir un
Le paramètre set:<identifiant réseau> permet de définir un
identifiant de réseau lorsque l'option dhcp-host est utilisée. Cela peut servir
à sélectionner des options DHCP juste pour cet hôte. Lorsqu'une machine coïncide
avec une directive dhcp-host (ou une impliquée par /etc/ethers), alors
l'identifiant réseau réservé "known" ("connu") est associé. Cela permet à
à sélectionner des options DHCP juste pour cet hôte. Plus d'un label peut être
fourni dans une directive dhcp-host (et dans cette seule directive). Lorsqu'une
machine coïncide avec une directive dhcp-host (ou une impliquée par
/etc/ethers), alors le label réservé "known" ("connu") est associé. Cela permet à
Dnsmasq d'être configuré pour ignorer les requêtes issus de machines inconnue
par le biais de
.B --dhcp-ignore=#known.
.B --dhcp-ignore=tag:!known.
Les adresses ethernet (mais pas les identifiants clients) peuvent être définies
avec des octets joker, ainsi par exemple
@@ -649,7 +701,7 @@ par Dnsmasq, ces lignes ont exactement le même effet que l'option
contenant les mêmes informations. /etc/ethers est relu à la réception d'un
signal SIGHUP par Dnsmasq.
.TP
.B \-O, --dhcp-option=[<identifiant_de_réseau>,[<identifiant_de_réseau>,]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]]
.B \-O, --dhcp-option=[tag:<label>,[tag:<label>]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]]
Spécifie des options différentes ou supplémentaires pour des clients DHCP. Par
défaut, Dnsmasq envoie un ensemble standard d'options aux clients DHCP : le
masque de réseau et l'adresse de broadcast sont les mêmes que pour l'hôte
@@ -675,8 +727,8 @@ L'adresse 0.0.0.0 prends ici le sens "d'adresse de la machine sur laquelle
tourne Dnsmasq". Les types de données autorisées sont des adresses IP sous la
forme de 4 chiffres séparés par des points, un nombre décimal, une liste de
caractères hexadécimaux séparés par des 2 points, ou une chaîne de caractères.
Si des identifiants de réseaux sont fournis, alors cette option n'est envoyée
qu'aux réseaux dont tous les identifiants coïncident.
Si des labels optionnels sont fournis, alors cette option n'est envoyée
qu'aux réseaux dont tous les labels coïncident avec ceux de la requête.
Un traitement spécial est effectué sur les chaînes de caractères fournies pour
l'option 119, conformément à la RFC 3397. Les chaînes de caractères ou les
@@ -738,7 +790,7 @@ Le numéro dans la section vi-encap: est le numéro IANA de l'entreprise servant
L'adresse 0.0.0.0 n'est pas traitée de manière particulière lorsque fournie dans
une option encapsulée.
.TP
.B --dhcp-option-force=[<identifiant de réseau>,[<identifiant de réseau>,]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe de vendeur>],]<option>,[<valeur>[,<valeur>]]
.B --dhcp-option-force=[tag:<label>,[tag:<label>]][encap:<option>,][vi-encap:<entreprise>,][vendor:[<classe_vendeur>],][<option>|option:<nom d'option>],[<valeur>[,<valeur>]]
Cela fonctionne exactement de la même façon que
.B --dhcp-option
sauf que cette option sera toujours envoyée, même si le client ne la demande pas
@@ -756,22 +808,25 @@ quelques rares cas, perturber des clients vieux ou défectueux. Cette
option force le comportement à l'utilisation des valeurs "simples et sûres"
afin d'éviter des problèmes dans de tels cas.
.TP
.B \-U, --dhcp-vendorclass=<identifiant de réseau>,<classe de vendeur>
Associe une chaîne de classe de vendeur à un indentifiant de réseau. La plupart
.B \-U, --dhcp-vendorclass=set:<label>,<classe de vendeur>
Associe une chaîne de classe de vendeur à un label. La plupart
des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui
représente, d'une certaine façon, le type d'hôte. Cette option associe des
classes de vendeur à des labels, de telle sorte que des options DHCP peuvent-être
fournie de manière sélective aux différentes classes d'hôtes. Par exemple,
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
ou
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
permet de n'allouer des options qu'aux imprimantes HP de la manière suivante :
.B --dhcp-option=printers,3,192.168.4.4
.B --dhcp-option=tag:printers,3,192.168.4.4
La chaîne de caractères de la classe de vendeur founie en argument est cherchée
en temps que sous-chaîne de caractères au sein de la classe de vendeur fournie
par le client, de façon à permettre la recherche d'un sous-ensemble de la chaîne
de caractères ("fuzzy matching").
de caractères ("fuzzy matching"). Le préfixe set: est optionnel mais autorisé
afin de conserver une certaine homogénéité.
.TP
.B \-j, --dhcp-userclass=<identifiant de réseau>,<classe utilisateur>
Associe une chaîne de classe d'utilisateur à un identifiant réseau (effectue la
.B \-j, --dhcp-userclass=set:<label>,<classe utilisateur>
Associe une chaîne de classe d'utilisateur à un label (effectue la
recherche sur des sous-chaînes, comme pour les classes de vendeur). La plupart
des clients permettent de configurer une "classe d'utilisateur". Cette option
associe une classe d'utilisateur à un label, de telle manière qu'il soit
@@ -780,28 +835,44 @@ Il est possible, par exemple, d'utiliser ceci pour définir un serveur
d'impression différent pour les hôtes de la classe "comptes" et ceux de la
classe "ingénierie".
.TP
.B \-4, --dhcp-mac=<identifiant de réseau>,<adresse MAC>
Associe une adresse matérielle (MAC) à un identifiant réseau. L'adresse
.B \-4, --dhcp-mac=set:<label>,<adresse MAC>
Associe une adresse matérielle (MAC) à un label. L'adresse
matérielle peut inclure des jokers. Par exemple
.B --dhcp-mac=3com,01:34:23:*:*:*
.B --dhcp-mac=set:3com,01:34:23:*:*:*
permet de définir le label "3com" pour n'importe quel hôte dont l'adresse
matérielle coïncide avec les critères définis.
.TP
.B --dhcp-circuitid=<identifiant de réseau>,<identifiant de circuit>, --dhcp-remoteid=<identifiant de réseau>,<identifiant distant>
Associe des options de relais DHCP issus de la RFC3046 à des identifiants de
réseau. Cette information peut-être fournie par des relais DHCP. L'identifiant
.B --dhcp-circuitid=set:<label>,<identifiant de circuit>, --dhcp-remoteid=set:<label>,<identifiant distant>
Associe des options de relais DHCP issus de la RFC3046 à des labels.
Cette information peut-être fournie par des relais DHCP. L'identifiant
de circuit ou l'identifiant distant est normalement fourni sous la forme d'une
chaîne de valeurs hexadécimales séparées par des ":", mais il est également
possible qu'elle le soit sous la forme d'une simple chaîne de caractères. Si
l'identifiant de circuit ou d'agent correspond exactement à celui fourni par le
relais DHCP, alors l'identifiant de réseau est positionné.
relais DHCP, alors le label est apposé.
.TP
.B --dhcp-subscrid=<identifiant de réseau>,<identifiant d'abonné>
Associe des options de relais DHCP issues de la RFC3993 à des identifiants de
réseau.
.B --dhcp-subscrid=set:<label>,<identifiant d'abonné>
Associe des options de relais DHCP issues de la RFC3993 à des labels.
.TP
.B --dhcp-match=<identifiant de réseau>,<numéro d'option>|option:<nom d'option>|vi-encap:<entreprise>[,<valeur>]
Si aucune valeur n'est spécifiée, associe l'identifiant de réseau si le client
.B --dhcp-proxy[=<adresse ip>]......
Un agent relai DHCP normal est uniquement utilisé pour faire suivre les
éléments initiaux de l'interaction avec le serveur DHCP. Une fois que le
client est configuré, il communique directement avec le serveur. Cela n'est pas
souhaitable si le relais rajoute des informations supplémentaires aux paquets
DHCP, telles que celles utilisées dans
.B dhcp-circuitid
et
.B dhcp-remoteid.
Une implémentation complète de relai peut utiliser l'option serverid-override
de la RFC 5107 afin de forcer le serveur DHCP à utiliser le relai en temps que
proxy complet, de sorte que tous les paquets passent par le relai. Cette option
permet d'obtenir le même résultat pour des relais ne supportant pas la RFC
5107. Fournie seule, elle manipule la valeur de server-id pour toutes les
interactions via des relais. Si une liste d'adresses IP est donnée, seules les
interactions avec les relais dont l'adresse est dans la liste seront affectées.
.TP
.B --dhcp-match=set:<label>,<numéro d'option>|option:<nom d'option>|vi-encap:<entreprise>[,<valeur>]
Si aucune valeur n'est spécifiée, associe le label si le client
envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est
fournie, positionne le label seulement dans le cas où l'option est fournie et
correspond à la valeur. La valeur peut-être de la forme "01:ff:*:02", auquel
@@ -811,7 +882,7 @@ valeur peut aussi être de la même forme que dans
, auquel cas l'option est traitée comme un tableau de valeur, et un des
éléments doit correspondre, ainsi
--dhcp-match=efi-ia32,option:client-arch,6
--dhcp-match=set:efi-ia32,option:client-arch,6
spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste
d'architectures envoyé par le client au sein de l'option 93. (se réferer
@@ -823,30 +894,50 @@ fait avec les classes de vendeur "identifiant de vendeur" ("vendor-identifying
vendor classes") pour l'entreprise dont le numéro est fourni en option.
Veuillez vous réferer à la RFC 3925 pour plus de détail.
.TP
.B \-J, --dhcp-ignore=<identifiant de réseau>[,<identifiant de réseau>]
Lorsque tous les identifiants de réseau fournis coïncident avec la liste
d'identifiants réseau dérivée des classes de réseau, hôte, vendeur et
utilisateur, ignorer l'hôte et ne pas donner de bail DHCP.
.B --tag-if=set:<label>[,set:<label>[,tag:<label>[,tag:<label>]]]
Effectue une opération booléenne sur les labels. Si tous les labels
apparaissant dans la liste tag:<label> sont positionnés, alors tous les
la de la liste "set:<labels>" sont positionnés (ou supprimés, dans le cas
où "tag:!<label>" utilisé).
Si aucun tag:<label> n'est spécifié, alors tous les labels fournis par
set:<label> sont positionnés.
N'importe quel nombre de set: ou tag: peuvent être fournis, et l'ordre est sans
importance.
Les lignes tag-if sont executées dans l'ordre, ce qui fait que si un label dans
tag:<label> est un label positionné par une rêgle
.B tag-if,
la ligne qui positionne le label doit précéder celle qui le teste.
.TP
.B --dhcp-ignore-names[=<identifiant de réseau>[,<identifiant de réseau>]]
Lorsque tous les identifiant de réseau coïncident avec la liste d'identifiants
réseau dérivées des classes de réseau, hôte, vendeur et utilisateur, ignorer le
.B \-J, --dhcp-ignore=tag:<label>[,tag:<label>]
Lorsque tous les labels fournis dans l'option sont présents, ignorer l'hôte et
ne pas donner de bail DHCP.
.TP
.B --dhcp-ignore-names[=tag:<label>[,tag:<label>]]
Lorsque tous les labels fournis dans l'option sont présents, ignorer le
nom de machine fourni par l'hôte. Il est à noter que, à la différence de
l'option "dhcp-ignore", il est permis de ne pas fournir d'identifiant réseau.
l'option "dhcp-ignore", il est permis de ne pas fournir de label.
Dans ce cas, les noms d'hôtes fournis par les clients DHCP seront toujours
ignorés, et les noms d'hôtes seront ajoutés au DNS en utilisant uniquement la
configuration dhcp-host de Dnsmasq, ainsi que le contenu des fichiers /etc/hosts
et /etc/ethers.
.TP
.B --dhcp-broadcast=<identifiant de réseau>[,<identifiant de réseau>]
Lorsque tous les identifiants de réseaux fournis correspondent à ceux
obtenus à partir des classes de réseau, d'hôte ou d'utilisateur, force
l'utilisation du broadcast pour communiquer avec l'hôte lorsque celui-ci n'est
pas configuré. La plupart des clients DHCP nécessitant une réponse par le biais
.B --dhcp-generate-names=tag:<label>[,tag:<label>]
Générer un nom pour les clients DHCP qui autrement n'en aurait pas, en
utilisant l'adresse MAC sous sa forme hexadécimale, séparée par des tirets.
Noter que si un hôte fourni un nom, celui-ci sera utilisé de préférence au nom
autogénéré, à moins que
.B --dhcp-ignore-names
ne soit positionné.
.TP
.B --dhcp-broadcast=[tag:<label>[,tag:<label>]]
Lorsque tous les labels fournis dans l'option sont présents, toujours utiliser
le broadcast pour communiquer avec l'hôte lorsque celui-ci n'est
pas configuré. Il est possible de ne spécifier aucun label, auquel cas cette
option s'applique inconditionnellement. La plupart des clients DHCP nécessitant une réponse par le biais
d'un broadcast activent une option dans leur requête, ce qui fait que cela
se fait automatiquement, mais ce n'est pas la cas de certains vieux clients BOOTP.
.TP
.B \-M, --dhcp-boot=[net:<identifiant de réseau>,]<nom de fichier>,[<nom de serveur>[,<adresse de serveur>]]
.B \-M, --dhcp-boot=[tag:<label>,]<nom de fichier>,[<nom de serveur>[,<adresse de serveur>]]
Spécifie les options BOOTP devant être retournées par le serveur DHCP. Le nom de
serveur ainsi que l'adresse sont optionnels : s'ils ne sont pas fournis, le nom
est laissé vide et l'adresse fournie est celle de la machine sur laquelle
@@ -854,11 +945,10 @@ s'exécute Dnsmasq. Si Dnsmasq founit un service TFTP (voir
.B --enable-tftp
), alors seul un nom de fichier est requis ici pour permettre un démarrage par
le réseau.
Si d'éventuels identifiants de réseau sont fournis, ils doivent coïncider avec
ceux du client pour que cet élement de configuration lui soit envoyé. Il est à
noter que les identifiants de réseau doivent-être préfixés par "net:".
Si d'éventuels labels sont fournis, ils doivent coïncider avec
ceux du client pour que cet élement de configuration lui soit envoyé.
.TP
.B --pxe-service=[net:<identifiant de réseau>,]<CSA>,<entrée de menu>[,<nom de fichier>|<type de service de démarrage>][,<adresse de serveur>]
.B --pxe-service=[tag:<label>,]<CSA>,<entrée de menu>[,<nom de fichier>|<type de service de démarrage>][,<adresse de serveur>]
La plupart des ROMS de démarrage PXE ne permettent au système PXE que la simple
obtention d'une adresse IP, le téléchargement du fichier spécifié dans
.B dhcp-boot
@@ -888,7 +978,7 @@ démarrage n'est fournie (ou qu'une valeur de 0 est donnée pour le type de
service), alors l'entrée de menu provoque l'interruption du démarrage par
le réseau et la poursuite du démarrage sur un média local.
.TP
.B --pxe-prompt=[net:<identifiant de réseau>,]<invite>[,<délai>]
.B --pxe-prompt=[tag:<label>,]<invite>[,<délai>]
Cette option permet d'afficher une invite à la suite du démarrage PXE. Si un
délai est fourni, alors la première entrée du menu de démarrage sera
automatiquement exécutée après ce délai. Si le délai vaut 0, alors la première
@@ -913,7 +1003,7 @@ dans
.B dhcp-range.
.TP
.B \-X, --dhcp-lease-max=<nombre>
Limite Dnsmasq à un maximum de <nombre> baux DHCP. Le défaut est de 150. Cette
Limite Dnsmasq à un maximum de <nombre> baux DHCP. Le défaut est de 1000. Cette
limite permet d'éviter des attaques de déni de service ("DoS") par des hôtes
créant des milliers de baux et utilisant beaucoup de mémoire dans le processus
Dnsmasq.
@@ -954,7 +1044,7 @@ utiliser avec précaution.
.TP
.B --log-dhcp
Traces additionnelles pour le service DHCP : enregistre toutes les options
envoyées aux clients DHCP et les identifiants de réseaux utilisés pour la
envoyées aux clients DHCP et les labels utilisés pour la
détermination de celles-ci.
.TP
.B \-l, --dhcp-leasefile=<chemin de fichier>
@@ -963,7 +1053,9 @@ baux DHCP.
.TP
.B \-6 --dhcp-script=<chemin de fichier>
Lorsqu'un bail DHCP est créé, ou qu'un ancien est supprimé, le fichier dont le
chemin est spécifié est exécuté. Les arguments fournis à celui-ci sont soit
chemin est spécifié est exécuté. Le <chemin de fichier> doit être un chemin
absolu, aucune recherche n'est effectuée via la variable d'environnement PATH.
Les arguments fournis à celui-ci sont soit
"add" ("ajouter"), "old" ("ancien") ou "del" ("supprimer"), suivi de l'adresse
MAC de l'hôte puis l'adresse IP et le nom d'hôte si celui-ci est
connu."add" signifie qu'un bail a été créé, "del" signifie qu'il a été supprimé,
@@ -975,43 +1067,59 @@ nécessaire de la préceder du type de réseau, par exemple "06-01:23:45:67:89:a
pour du token ring. Le processus est exécuté en temps que super-utilisateur
(si Dnsmasq a été lancé en temps que "root"), même si Dnsmasq est configuré
pour changer son UID pour celle d'un utilisateur non-privilégié.
L'environnement est hérité de celui de l'invocation du processus Dnsmasq, et
si l'hôte fournit un identifiant de client, celui-ci est stocké dans la
variable d'environnement DNSMASQ_CLIENT_ID. Si un nom de domaine pleinement
qualifié (FQDN) est connu pour l'hôte, la part relative au domaine est stockée
dans DNSMASQ_DOMAIN. Si le client fournit une information de classe de vendeur,
de classe d'utilisateur ou un nom d'hôte, celles-ci sont positionnées dans les
L'environnement est hérité de celui de l'invocation du processus Dnsmasq,
auquel se rajoute quelques unes ou toutes les variables décrites ci-dessous :
DNSMASQ_CLIENT_ID, si l'hôte a fourni un identifiant de client.
DNSMASQ_DOMAIN si le nom de domaine pleinement qualifié de l'hôte est connu, la
part relative au domaine y est stockée.
Si le client fournit une information de classe de vendeur, un nom d'hôte, ou
des classes d'utilisateur, celles-ci sont fournies dans les
variables DNSMASQ_VENDOR_CLASS et DNSMASQ_USER_CLASS0 à DNSMASQ_USER_CLASSn
et DNSMASQ_SUPPLIED_HOSTNAME respectivement, mais seulement pour les actions
"add" et "old" lorsqu'un hôte reprend un bail existant, ces variables n'étant
pas stockées dans la base de baux de Dnsmasq. Si Dnsmasq a été compilé avec
l'option HAVE_BROKEN_RTC ("horloge RTC défectueuse"), alors la durée du bail
(en secondes) est stockée dans la variable DNSMASQ_LEASE_LENGTH, sinon la date
d'expiration du bail est toujours stocké dans la variable d'environnement
DNSMASQ_LEASE_EXPIRES. Le nombre de secondes avant expiration est toujours
stocké dans DNSMASQ_TIME_REMAINING. Si un bail était associé à un nom d'hôte et
pas stockées dans la base de baux de Dnsmasq.
Si Dnsmasq a été compilé avec l'option HAVE_BROKEN_RTC ("horloge RTC
défectueuse"), alors la durée du bail (en secondes) est stockée dans la
variable DNSMASQ_LEASE_LENGTH, sinon la date d'expiration du bail est toujours
stocké dans la variable d'environnement DNSMASQ_LEASE_EXPIRES. Le nombre de
secondes avant expiration est toujours stocké dans DNSMASQ_TIME_REMAINING.
Si un bail était associé à un nom d'hôte et
que celui-ci est supprimé, un évênement de type "old" est généré avec le
nouveau statut du bail, c-à-d sans nom d'hôte, et le nom initial est fourni
dans la variable d'environnement DNSMASQ_OLD_HOSTNAME. La variable
DNSMASQ_INTERFACE contient le nom de l'interface sur laquelle la requête est
arrivée; ceci n'est pas renseigné dans le cas des actions "old" ayant lieu
après un redémarrage de dnsmasq. La variable DNSMASQ_RELAY_ADDRESS est
renseignée si le client a utilisé un relai DHCP pour contacter Dnsmasq, si
l'adresse IP du relai est connue. DNSMASQ_TAGS contient tous les labels
d'identifiants de réseau fournis pendant la transaction DHCP, séparés par des
espaces.
dans la variable d'environnement DNSMASQ_OLD_HOSTNAME.
La variable DNSMASQ_INTERFACE contient le nom de l'interface sur laquelle la
requête est arrivée; ceci n'est pas renseigné dans le cas des actions "old"
ayant lieu après un redémarrage de dnsmasq.
La variable DNSMASQ_RELAY_ADDRESS est renseignée si le client a utilisé un
relai DHCP pour contacter Dnsmasq, si l'adresse IP du relai est connue.
DNSMASQ_TAGS contient tous les labels fournis pendant la transaction DHCP,
séparés par des espaces.
Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui
sont ouverts sur /dev/null (sauf en mode déverminage).
Le script n'est pas lancé de manière concurrente : si un autre changement de
bail intervient, le script ne sera relancé que lorsque l'exécution actuelle sera
terminée.
Le script n'est pas lancé de manière concurrente : au plus une instance du
script est executée à la fois (dnsmasq attends qu'une instance de script se
termine avant de lancer la suivante). Les changements dans la base des baux
nécessitant le lancement du script sont placé en attente dans une queue jusqu'à
terminaison d'une instance du script en cours. Si cette mise en queue fait que
plusieurs changements d'états apparaissent pour un bail donné avant que le
script puisse être lancé, alors les états les plus anciens sont supprimés et
lorsque le script sera finalement lancé, ce sera avec l'état courant du bail.
Au démarrage de Dnsmasq, le script sera invoqué pour chacun des baux existants
dans le fichier des baux. Le script sera lancé avec l'action "del" pour les baux
expirés, et "old" pour les autres. <chemin de fichier> doit être un chemin
absolu (c'est-à-dire partant de la racine "/"), aucune recherche n'aura lieu
dans les répertoires de la variable d'environnement PATH. Lorsque Dnsmasq reçoit
un signal HUP, le script sera invoqué avec une action "old" pour tous les baux
existants.
dans le fichier des baux. Le script sera lancé avec l'action "del" pour les
baux expirés, et "old" pour les autres. Lorsque Dnsmasq reçoit un signal HUP,
le script sera invoqué avec une action "old" pour tous les baux existants.
.TP
.B --dhcp-scriptuser
Spécifie l'utilisateur sous lequel le script lease-change doit être exécuté. La
@@ -1089,18 +1197,21 @@ sans gamme d'adresses de spécifié lorsque l'option
.B --dhcp-fqdn
est configurée.
.TP
.B --enable-tftp
.B --enable-tftp[=<interface>]
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
un accès en lecture est possible; les extensions tsize et blksize sont supportées
(tsize est seulement supporté en mode octet).
(tsize est seulement supporté en mode octet). Voir dans la section NOTES les
informations relatives à la spécification de l'interface.
.TP
.B --tftp-root=<répertoire>
.B --tftp-root=<répertoire>[,<interface>]
Les fichiers à fournir dans les transferts TFTP seront cherchés en prenant le
répertoire fourni comme racine. Lorsque cela est fourni, les chemins TFTP
incluant ".." sont rejetés, afin d'éviter que les clients ne puissent sortir de
la racine spécifiée. Les chemins absolus (commençant par "/") sont autorisés,
mais ils doivent être à la racine TFTP fournie.
mais ils doivent être à la racine TFTP fournie. Si l'option interface est
spécifiée, le répertoire n'est utilisé que pour les requêtes TFTP reçues sur
cette interface.
.TP
.B --tftp-unique-root
Ajouter l'adresse IP du client TFTP en temps qu'élément de chemin, à la suite
@@ -1322,38 +1433,48 @@ exception à ceci : si le DNS amont contient un CNAME qui pointe vers un nom
présent dans /etc/hosts, alors la recherche du CNAME via Dnsmasq fournira
l'adresse DNS amont. Pour contourner cela, il suffit de mettre l'entrée
correspondant au CNAME dans /etc/hosts.
.PP
les identifiants de réseau fonctionnent comme suit : Dnsmasq associe à chaque
requête DHCP un ensemble d'identifiants de réseau; un pour la plage d'adresse
DHCP (
le système de label fonctionne comme suit : pour chaque requête DHCP, dnsmasq
associe un ensemble de labels obtenus à partir des lignes de la configuration
incluant set:<label>, y compris un pour la plage d'adresse (
.B dhcp-range
) utilisée pour allouer l'adresse, un identifiant pour chaque entrée
) utilisée pour allouer l'adresse, un pour chaque entrée
.B dhcp-host
associée (il ajoute "known" lorsqu'une entrée dhcp-host coïncide), l'étiquette
"bootp" pour les requêtes BOOTP, un identifiant dont le nom est le nom de
l'interface sur laquelle la requête est arrivée, et éventuellement un
identifiant pour chaque classe de vendeur ou d'utilisateur
fournie par le client DHCP dans sa requête. Les options DHCP (
associée (auquel est rajouté le mot-clef "known" si une entrée dhcp-host
coïncide).
Le label "bootp" est associé aux requêtes BOOTP, un label dont le nom est le
nom de l'interface sur laquelle la requête est arrivée.
Pour les lignes de configuration comportant des éléments tag:<label>,
seules seront valides celles pour lesquels tous les labels correspondants
seront présents. C'est typiquement le cas des lignes dhcp-options.
Un
.B dhcp-option
) ayant un identifiant de réseau seront utilisés de préférence à celles
sans identifiants de réseau, pour peu que
.I tous
les labels correspondent.
Le préfixe '#' sur un label est un indicateur de négation, ainsi
.B --dhcp=option=#purple,3,1.2.3.4
envoie l'option lorsque le label "purple" n'est pas dans la liste de labels
valides pour l'hôte considéré.
possédant des labels sera utilisé de préférence à un
.B dhcp-option
sans label, pour peu que _tous_ les labels positionnés correspondent à l'ensemble
de labels décrit plus haut.
Le préfixe '!' sur un label est un indicateur de négation, ainsi
.B --dhcp=option=tag:!purple,3,1.2.3.4
n'envoie l'option que lorsque le label "purple" n'est pas dans la liste de
labels définis pour l'hôte considéré. (dans le cas de l'utilisation dans une
ligne de commande au lieu d'un fichier de configuration, ne pas oublier
d'échapper le caractère !, qui est un méta-caractère d'interpréteur de commande
shell).
.PP
Si l'identifiant de réseau dans la plage d'adresses DHCP (
.B dhcp-range
) est préfixé par 'net:', alors sa signification change : au lieu d'associer un
label à la plage spécifiée, cela indique un label de réseau devant être spécifié
par le client DHCP. Ainsi, s'il y a plus d'une plage d'adresses DHCP sur un
sous-réseau, et que l'une est préfixée par un identifiant de réseau (par exemple
l'un spécifié dans une option de classe de vendeur), alors un hôte ayant
l'identifiant de réseau en question positionné se verra allouer une adresse dans
la plage d'adresses DHCP préfixée.
Veuillez noter que pour
.B dhcp-range
, les éléments tag:<label> et set:<label> sont tous les deux autorisés
pour sélectionner la plage à utiliser selon, par exemple, le dhcp-host,
et pour affecter l'option envoyée, sur la base de la plage sélectionnée.
Ce système a évolué d'un système plus ancien et aux possibilités plus limitées,
et pour des raisons de compatibilité "net:" peut être utilisé à la place de
"tag:" et "set:" peut-être omis (à l'exception de
.B dhcp-host,
où "net:" peut-être utilisé à la place de "set:"). Pour les mêmes raisons, '#'
peut-être utilisé à la place de '!' pour indiquer la négation.
.PP
Le serveur DHCP intégré dans Dnsmasq fonctionne également en temps que serveur
BOOTP, pour peu que l'adresse MAC et l'adresse IP des clients soient fournies,
@@ -1366,12 +1487,55 @@ ou dans le fichier
soit présente afin d'activer le serveur DHCP pour un réseau donné (L'option
.B --bootp-dynamic
supprime la nécessité des associations statiques). Le paramètre
"filename" (nom de fichier) de la requête BOOTP est comparé avec les
identifiants de réseaux des options
.B dhcp-option
ainsi que le label "bootp", ce qui permet de contrôler les options retournées
"filename" (nom de fichier) de la requête BOOTP est utilisé comme label, ainsi
que le label "bootp", permettant un certain contrôle sur les options retournées
aux différentes classes d'hôtes.
Il est possible de spécifier un nom d'interface à
.B dhcp-range
sous la forme "interface:<nom d'interface>". La sémantique est comme suit :
Pour le DHCP, s'il existe une autre valeur de dhcp-range pour laquelle
_aucun_ nom d'interface n'est donné, alors le nom d'interface est ignoré
et dnsmasq se comporte comme si la partie spécifiant l'interface n'existait
pas, sinon le service DHCP n'est fourni qu'aux interfaces mentionnées dans
les déclarations dhcp-range. Pour le DNS, si il n'y a pas d'option
.B --interface
ou
.B --listen-address
, alors le comportement n'est pas impacté par la spécification d'interface. Si
l'une ou l'autre de ces options est présente, alors les interfaces mentionnées
dans les plages d'adresses dhcp-range sont rajoutées à la liste de celles
où le service DNS est assuré.
De manière similaire,
.B enable-tftp
peut prendre un nom d'interface, ce qui active le TFTP pour cette seule
interface, en ignorant les options
.B --interface
ou
.B --listen-address
De plus,
.B --tftp-secure
,
.B --tftp-unique-root
et
.B --tftp-no-blocksize
sont ignorées pour les requêtes sur de telles interfaces. (une directive
.B --tftp-root
donnant le chemin de la racine et une interface doit-être fournie).
Ces règles peuvent paraître étrange à première vue, mais elles permettent
d'ajouter à la configuration de dnsmasq des lignes de configuration de la
forme "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" afin de fournir
un service DHCP et DNS sur cette interface, sans pour autant affecter les
services fournis sur d'autres interfaces, malgré l'absence de paramètres
"interface=<interface>" sur les autres lignes de configuration.
"enable-tftp=virt0" et "tftp-root=<root>,virt0" effectuent la même chose pour
TFTP.
L'idée de tout cela est de permettre l'addition de telles lignes
automatiquement par libvirt ou un système équivalent, sans perturbation
d'une configuration manuelle existant par ailleurs.
.SH CODES DE SORTIE
.PP
0 - Dnsmasq s'est correctement lancé en tâche de fond, ou alors s'est
@@ -1403,10 +1567,8 @@ ultérieur : les versions précédentes ne montaient pas en charge aussi bien.
.PP
Dnsmasq est capable de gérer le DNS et DHCP pour au moins un millier de clients.
Evidement, pour cela la valeur de
.B --dhcp-lease-max
doit être augmentée et la durée des baux ne doit pas être très courte (moins
d'une heure). La valeur de
Pour cela, la durée des bail ne doit pas être très courte (moins d'une heure).
La valeur de
.B --dns-forward-max
peut-être augmentée : commencer par la rendre égale au nombre de clients et
l'augmenter si le DNS semble lent. Noter que la performance du DNS dépends

1374
po/de.po

File diff suppressed because it is too large Load Diff

631
po/es.po

File diff suppressed because it is too large Load Diff

768
po/fi.po

File diff suppressed because it is too large Load Diff

657
po/fr.po

File diff suppressed because it is too large Load Diff

640
po/id.po

File diff suppressed because it is too large Load Diff

768
po/it.po

File diff suppressed because it is too large Load Diff

634
po/no.po

File diff suppressed because it is too large Load Diff

644
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

634
po/ro.po

File diff suppressed because it is too large Load Diff

View File

@@ -1045,7 +1045,14 @@ void cache_add_dhcp_entry(char *host_name,
/* check all addresses associated with name */
if (crec->flags & F_HOSTS)
{
if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
/* if in hosts, don't need DHCP record */
in_hosts = 1;
if (crec->flags & F_CNAME)
my_syslog(LOG_WARNING,
_("%s is a CNAME, not giving it to the DHCP lease of %s"),
host_name, inet_ntoa(*host_address));
else if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
{
strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
my_syslog(LOG_WARNING,
@@ -1053,11 +1060,7 @@ void cache_add_dhcp_entry(char *host_name,
"the name exists in %s with address %s"),
host_name, inet_ntoa(*host_address),
record_source(crec->uid), daemon->namebuff);
return;
}
else
/* if in hosts, don't need DHCP record */
in_hosts = 1;
}
}
else if (!(crec->flags & F_DHCP))
{

View File

@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define VERSION "2.52"
#define VERSION "2.54"
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
@@ -22,7 +22,7 @@
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define FORWARD_TEST 50 /* try all servers every 50 queries */
#define FORWARD_TIME 10 /* or 10 seconds */
#define FORWARD_TIME 20 /* or 10 seconds */
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */
@@ -230,13 +230,13 @@ NOTES:
#elif defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__DragonFly__) || \
defined (__FreeBSD_kernel__)
defined(__FreeBSD_kernel__)
#define HAVE_BSD_NETWORK
/* Later verions of FreeBSD have getopt_long() */
#if defined(optional_argument) && defined(required_argument)
# define HAVE_GETOPT_LONG
#endif
#if !defined (__FreeBSD_kernel__)
#if !defined(__FreeBSD_kernel__)
# define HAVE_ARC4RANDOM
#endif
#define HAVE_SOCKADDR_SA_LEN

View File

@@ -127,7 +127,10 @@ void dhcp_packet(time_t now, int pxe_fd)
int iface_index = 0, unicast_dest = 0, is_inform = 0;
struct in_addr iface_addr, *addrp = NULL;
struct iface_param parm;
#ifdef HAVE_LINUX_NETWORK
struct arpreq arp_req;
#endif
union {
struct cmsghdr align; /* this ensures alignment */
#if defined(HAVE_LINUX_NETWORK)
@@ -189,8 +192,13 @@ void dhcp_packet(time_t now, int pxe_fd)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
iface_index = p.p->ipi_ifindex;
if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
unicast_dest = 1;
}
@@ -198,20 +206,37 @@ void dhcp_packet(time_t now, int pxe_fd)
if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
{
union {
unsigned char *c;
struct sockaddr_dl *s;
} p;
p.c = CMSG_DATA(cmptr);
iface_index = p.s->sdl_index;
}
#elif defined(HAVE_SOLARIS_NETWORK)
if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
iface_index = *((unsigned int *)CMSG_DATA(cmptr));
{
union {
unsigned char *c;
unsigned int *i;
} p;
p.c = CMSG_DATA(cmptr);
iface_index = *(p.i);
}
#endif
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
return;
#ifdef HAVE_LINUX_NETWORK
/* ARP fiddling uses original interface even if we pretend to use a different one. */
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
#endif
#ifdef MSG_BCAST
/* OpenBSD tells us when a packet was broadcast */
if (!(msg.msg_flags & MSG_BCAST))
@@ -231,18 +256,14 @@ void dhcp_packet(time_t now, int pxe_fd)
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return;
/* interface may have been changed by alias in iface_check */
if (!addrp)
{
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
{
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
return;
}
else
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
/* weird libvirt-inspired access control */
for (context = daemon->dhcp; context; context = context->next)
if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
break;
if (!context)
return;
/* unlinked contexts are marked by context->current == context */
for (context = daemon->dhcp; context; context = context->next)
@@ -253,6 +274,27 @@ void dhcp_packet(time_t now, int pxe_fd)
parm.current = NULL;
parm.ind = iface_index;
/* interface may have been changed by alias in iface_check, make sure it gets priority in case
there is more than one address on the interface in the same subnet */
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
{
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
return;
}
else
{
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
if (ioctl(daemon->dhcpfd, SIOCGIFNETMASK, &ifr) != -1)
{
struct in_addr netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
if (ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) != -1)
{
struct in_addr broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
complete_context(iface_addr, iface_index, netmask, broadcast, &parm);
}
}
}
if (!iface_enumerate(&parm, complete_context, NULL))
return;
lease_prune(NULL, now); /* lose any expired leases */
@@ -324,15 +366,14 @@ void dhcp_packet(time_t now, int pxe_fd)
{
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
struct arpreq req;
dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port);
*((struct sockaddr_in *)&req.arp_pa) = dest;
req.arp_ha.sa_family = mess->htype;
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
strncpy(req.arp_dev, ifr.ifr_name, 16);
req.arp_flags = ATF_COM;
ioctl(daemon->dhcpfd, SIOCSARP, &req);
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
arp_req.arp_ha.sa_family = mess->htype;
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
/* interface name already copied in */
arp_req.arp_flags = ATF_COM;
ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
}
#elif defined(HAVE_SOLARIS_NETWORK)
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
@@ -491,13 +532,15 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
if (!(tmp = address_available(context, taddr, netids)))
{
for (tmp = context; tmp; tmp = tmp->current)
if (is_same_net(taddr, tmp->start, tmp->netmask) &&
if (match_netid(tmp->filter, netids, 1) &&
is_same_net(taddr, tmp->start, tmp->netmask) &&
(tmp->flags & CONTEXT_STATIC))
break;
if (!tmp)
for (tmp = context; tmp; tmp = tmp->current)
if (is_same_net(taddr, tmp->start, tmp->netmask))
if (match_netid(tmp->filter, netids, 1) &&
is_same_net(taddr, tmp->start, tmp->netmask))
break;
}
@@ -530,7 +573,8 @@ int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotnee
for (; check; check = check->next)
{
if (check->net[0] != '#')
/* '#' for not is for backwards compat. */
if (check->net[0] != '!' && check->net[0] != '#')
{
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
if (strcmp(check->net, tmp1->net) == 0)
@@ -546,6 +590,22 @@ int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotnee
return 1;
}
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
{
struct tag_if *exprs;
struct dhcp_netid_list *list;
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
if (match_netid(exprs->tag, tags, 1))
for (list = exprs->set; list; list = list->next)
{
list->list->next = tags;
tags = list->list;
}
return tags;
}
int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now)
@@ -559,9 +619,10 @@ int address_allocate(struct dhcp_context *context,
int i, pass;
unsigned int j;
/* hash hwaddr */
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
dispersal even with similarly-valued "strings". */
for (j = 0, i = 0; i < hw_len; i++)
j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
j += hwaddr[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current)
@@ -977,29 +1038,40 @@ void dhcp_update_configs(struct dhcp_config *configs)
/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
for this address. If it has a domain part, that must match the set domain and
it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
so check here that the domain name is legal as a hostname. */
so check here that the domain name is legal as a hostname.
NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */
char *host_from_dns(struct in_addr addr)
{
struct crec *lookup;
char *hostname = NULL;
char *d1, *d2;
if (daemon->port == 0)
return NULL; /* DNS disabled. */
lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
if (lookup && (lookup->flags & F_HOSTS))
{
hostname = daemon->dhcp_buff;
strncpy(hostname, cache_get_name(lookup), 256);
hostname[255] = 0;
d1 = strip_hostname(hostname);
d2 = get_domain(addr);
if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2))))
hostname = NULL;
char *dot, *hostname = cache_get_name(lookup);
dot = strchr(hostname, '.');
if (dot && strlen(dot+1) != 0)
{
char *d2 = get_domain(addr);
if (!d2 || !hostname_isequal(dot+1, d2))
return NULL; /* wrong domain */
}
if (!legal_hostname(hostname))
return NULL;
strncpy(daemon->dhcp_buff, hostname, 256);
daemon->dhcp_buff[255] = 0;
strip_hostname(daemon->dhcp_buff);
return daemon->dhcp_buff;
}
return hostname;
return NULL;
}
/* return domain or NULL if none. */

View File

@@ -63,7 +63,6 @@ static void check_dns_listeners(fd_set *set, time_t now);
static void sig_handler(int sig);
static void async_event(int pipe, time_t now);
static void fatal_event(struct event_desc *ev);
static void poll_resolv(void);
int main (int argc, char **argv)
{
@@ -142,7 +141,7 @@ int main (int argc, char **argv)
#endif
#ifndef HAVE_TFTP
if (daemon->options & OPT_TFTP)
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
#endif
@@ -184,7 +183,7 @@ int main (int argc, char **argv)
die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
}
}
else if ((daemon->port != 0 || (daemon->options & OPT_TFTP)) &&
else if ((daemon->port != 0 || daemon->tftp_interfaces || daemon->tftp_unlimited) &&
!(daemon->listeners = create_wildcard_listeners()))
die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
@@ -278,8 +277,6 @@ int main (int argc, char **argv)
if (!(daemon->options & OPT_DEBUG))
{
int nullfd;
/* The following code "daemonizes" the process.
See Stevens section 12.4 */
@@ -344,16 +341,19 @@ int main (int argc, char **argv)
_exit(0);
}
}
/* open stdout etc to /dev/null */
nullfd = open("/dev/null", O_RDWR);
dup2(nullfd, STDOUT_FILENO);
dup2(nullfd, STDERR_FILENO);
dup2(nullfd, STDIN_FILENO);
close(nullfd);
}
log_err = log_start(ent_pw, err_pipe[1]);
log_err = log_start(ent_pw, err_pipe[1]);
if (!(daemon->options & OPT_DEBUG))
{
/* open stdout etc to /dev/null */
int nullfd = open("/dev/null", O_RDWR);
dup2(nullfd, STDOUT_FILENO);
dup2(nullfd, STDERR_FILENO);
dup2(nullfd, STDIN_FILENO);
close(nullfd);
}
/* if we are to run scripts, we need to fork a helper before dropping root. */
daemon->helperfd = -1;
@@ -508,7 +508,7 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_TFTP
if (daemon->options & OPT_TFTP)
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
{
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
@@ -647,10 +647,11 @@ int main (int argc, char **argv)
difftime(now, daemon->last_resolv) > 1.0 ||
difftime(now, daemon->last_resolv) < -1.0)
{
daemon->last_resolv = now;
/* poll_resolv doesn't need to reload first time through, since
that's queued anyway. */
if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL))
poll_resolv();
poll_resolv(0, daemon->last_resolv != 0, now);
daemon->last_resolv = now;
}
if (FD_ISSET(piperead, &rset))
@@ -898,7 +899,7 @@ static void async_event(int pipe, time_t now)
}
}
static void poll_resolv()
void poll_resolv(int force, int do_reload, time_t now)
{
struct resolvc *res, *latest;
struct stat statbuf;
@@ -906,19 +907,37 @@ static void poll_resolv()
/* There may be more than one possible file.
Go through and find the one which changed _last_.
Warn of any which can't be read. */
if (daemon->port == 0 || (daemon->options & OPT_NO_POLL))
return;
for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
if (stat(res->name, &statbuf) == -1)
{
if (force)
{
res->mtime = 0;
continue;
}
if (!res->logged)
my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
res->logged = 1;
if (res->mtime != 0)
{
/* existing file evaporated, force selection of the latest
file even if its mtime hasn't changed since we last looked */
poll_resolv(1, do_reload, now);
return;
}
}
else
{
res->logged = 0;
if (statbuf.st_mtime != res->mtime)
{
res->mtime = statbuf.st_mtime;
if (force || (statbuf.st_mtime != res->mtime))
{
res->mtime = statbuf.st_mtime;
if (difftime(statbuf.st_mtime, last_change) > 0.0)
{
last_change = statbuf.st_mtime;
@@ -935,8 +954,8 @@ static void poll_resolv()
my_syslog(LOG_INFO, _("reading %s"), latest->name);
warned = 0;
check_servers();
if (daemon->options & OPT_RELOAD)
cache_reload();
if ((daemon->options & OPT_RELOAD) && do_reload)
clear_cache_and_reload(now);
}
else
{
@@ -1125,11 +1144,13 @@ static void check_dns_listeners(fd_set *set, time_t now)
dst_addr_4.s_addr = 0;
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
terminate the process. */
#ifndef NO_FORK
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
terminate the process. */
if (!(daemon->options & OPT_DEBUG))
alarm(CHILD_LIFETIME);
#endif
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
s->tcpfd = -1;

View File

@@ -22,8 +22,8 @@
# define _FILE_OFFSET_BITS 64
#endif
/* Get linux C library versions. */
#ifdef __linux__
/* Get linux C library versions and define _GNU_SOURCE for kFreeBSD. */
#if defined(__linux__) || defined(__GLIBC__)
# define _GNU_SOURCE
# include <features.h>
#endif
@@ -188,7 +188,7 @@ struct event_desc {
#define OPT_LEASE_RO (1u<<22)
#define OPT_ALL_SERVERS (1u<<23)
#define OPT_RELOAD (1u<<24)
#define OPT_TFTP (1u<<25)
#define OPT_LOCAL_REBIND (1u<<25)
#define OPT_TFTP_SECURE (1u<<26)
#define OPT_TFTP_NOBLOCK (1u<<27)
#define OPT_LOG_OPTS (1u<<28)
@@ -319,6 +319,8 @@ union mysockaddr {
#define SERV_MARK 256 /* for mark-and-delete */
#define SERV_TYPE (SERV_HAS_DOMAIN | SERV_FOR_NODOTS)
#define SERV_COUNTED 512 /* workspace for log code */
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
struct serverfd {
int fd;
@@ -345,7 +347,8 @@ struct server {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int dhcp_ok, mtu;
int tftp_ok, mtu;
char *name;
struct irec *next;
};
@@ -391,7 +394,7 @@ struct frec {
#endif
unsigned int iface;
unsigned short orig_id, new_id;
int fd, forwardall;
int fd, forwardall, norebind;
unsigned int crc;
time_t time;
struct frec *next;
@@ -437,6 +440,12 @@ struct dhcp_netid_list {
struct dhcp_netid_list *next;
};
struct tag_if {
struct dhcp_netid_list *set;
struct dhcp_netid *tag;
struct tag_if *next;
};
struct hwaddr_config {
int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX];
@@ -449,7 +458,7 @@ struct dhcp_config {
int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */
char *hostname, *domain;
struct dhcp_netid netid;
struct dhcp_netid_list *netid;
struct in_addr addr;
time_t decline_time;
unsigned int lease_time;
@@ -462,7 +471,6 @@ struct dhcp_config {
#define CONFIG_TIME 8
#define CONFIG_NAME 16
#define CONFIG_ADDR 32
#define CONFIG_NETID 64
#define CONFIG_NOCLID 128
#define CONFIG_FROM_ETHERS 256 /* entry created by /etc/ethers */
#define CONFIG_ADDR_HOSTS 512 /* address added by from /etc/hosts */
@@ -548,6 +556,7 @@ struct dhcp_context {
struct in_addr local, router;
struct in_addr start, end; /* range of available addresses */
int flags;
char *interface;
struct dhcp_netid netid, *filter;
struct dhcp_context *next, *current;
};
@@ -598,6 +607,23 @@ struct tftp_transfer {
struct tftp_transfer *next;
};
struct addr_list {
struct in_addr addr;
struct addr_list *next;
};
struct interface_list {
char *interface;
struct interface_list *next;
};
struct tftp_prefix {
char *interface;
char *prefix;
struct tftp_prefix *next;
};
extern struct daemon {
/* datastuctures representing the command-line and
config file arguments. All set (including defaults)
@@ -628,7 +654,7 @@ extern struct daemon {
int max_logs; /* queue limit */
int cachesize, ftabsize;
int port, query_port, min_port;
unsigned long local_ttl, neg_ttl;
unsigned long local_ttl, neg_ttl, max_ttl;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp;
struct dhcp_config *dhcp_conf;
@@ -637,8 +663,12 @@ extern struct daemon {
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
struct pxe_service *pxe_services;
struct tag_if *tag_if;
struct addr_list *override_relays;
int override;
int enable_pxe;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
char *dhcp_hosts_file, *dhcp_opts_file;
int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port;
@@ -647,6 +677,9 @@ extern struct daemon {
struct doctor *doctors;
unsigned short edns_pktsz;
char *tftp_prefix;
struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
int tftp_unlimited;
/* globally used stuff for DNS */
char *packet; /* packet buffer */
@@ -675,7 +708,7 @@ extern struct daemon {
int dhcp_raw_fd, dhcp_icmp_fd;
#endif
struct iovec dhcp_packet;
char *dhcp_buff, *dhcp_buff2;
char *dhcp_buff, *dhcp_buff2, *dhcp_buff3;
struct ping_result *ping_results;
FILE *lease_stream;
struct dhcp_bridge *bridges;
@@ -719,7 +752,8 @@ unsigned short extract_request(HEADER *header, size_t qlen,
size_t setup_reply(HEADER *header, size_t qlen,
struct all_addr *addrp, unsigned short flags,
unsigned long local_ttl);
int extract_addresses(HEADER *header, size_t qlen, char *namebuff, time_t now);
int extract_addresses(HEADER *header, size_t qlen, char *namebuff,
time_t now, int is_sign, int checkrebind);
size_t answer_request(HEADER *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask, time_t now);
int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
@@ -803,9 +837,11 @@ struct dhcp_context *address_available(struct dhcp_context *context,
struct dhcp_context *narrow_context(struct dhcp_context *context,
struct in_addr taddr,
struct dhcp_netid *netids);
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);int address_allocate(struct dhcp_context *context,
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now);
struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context,
@@ -856,6 +892,7 @@ int icmp_ping(struct in_addr addr);
#endif
void send_event(int fd, int event, int data);
void clear_cache_and_reload(time_t now);
void poll_resolv(int force, int do_reload, time_t now);
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK

View File

@@ -65,15 +65,15 @@ static void send_from(int fd, int nowild, char *packet, size_t len,
if (to->sa.sa_family == AF_INET)
{
#if defined(HAVE_LINUX_NETWORK)
struct in_pktinfo *pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
pkt->ipi_ifindex = 0;
pkt->ipi_spec_dst = source->addr.addr4;
struct in_pktinfo p;
p.ipi_ifindex = 0;
p.ipi_spec_dst = source->addr.addr4;
memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
cmptr->cmsg_level = SOL_IP;
cmptr->cmsg_type = IP_PKTINFO;
#elif defined(IP_SENDSRCADDR)
struct in_addr *a = (struct in_addr *)CMSG_DATA(cmptr);
*a = source->addr.addr4;
memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
cmptr->cmsg_level = IPPROTO_IP;
cmptr->cmsg_type = IP_SENDSRCADDR;
@@ -82,9 +82,10 @@ static void send_from(int fd, int nowild, char *packet, size_t len,
else
#ifdef HAVE_IPV6
{
struct in6_pktinfo *pkt = (struct in6_pktinfo *)CMSG_DATA(cmptr);
pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
pkt->ipi6_addr = source->addr.addr6;
struct in6_pktinfo p;
p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
p.ipi6_addr = source->addr.addr6;
memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmptr->cmsg_type = daemon->v6pktinfo;
cmptr->cmsg_level = IPV6_LEVEL;
@@ -111,7 +112,7 @@ static void send_from(int fd, int nowild, char *packet, size_t len,
}
static unsigned short search_servers(time_t now, struct all_addr **addrpp,
unsigned short qtype, char *qdomain, int *type, char **domain)
unsigned short qtype, char *qdomain, int *type, char **domain, int *norebind)
{
/* If the query ends in the domain in one of our servers, set
@@ -153,38 +154,44 @@ static unsigned short search_servers(time_t now, struct all_addr **addrpp,
char *matchstart = qdomain + namelen - domainlen;
if (namelen >= domainlen &&
hostname_isequal(matchstart, serv->domain) &&
domainlen >= matchlen &&
(domainlen == 0 || namelen == domainlen || *(serv->domain) == '.' || *(matchstart-1) == '.' ))
(domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
{
unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
*type = SERV_HAS_DOMAIN;
*domain = serv->domain;
matchlen = domainlen;
if (serv->flags & SERV_NO_ADDR)
flags = F_NXDOMAIN;
else if (serv->flags & SERV_LITERAL_ADDRESS)
if (serv->flags & SERV_NO_REBIND)
*norebind = 1;
else if (domainlen >= matchlen)
{
if (sflag & qtype)
unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
*type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND);
*domain = serv->domain;
matchlen = domainlen;
if (serv->flags & SERV_NO_ADDR)
flags = F_NXDOMAIN;
else if (serv->flags & SERV_LITERAL_ADDRESS)
{
flags = sflag;
if (serv->addr.sa.sa_family == AF_INET)
*addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
if (sflag & qtype)
{
flags = sflag;
if (serv->addr.sa.sa_family == AF_INET)
*addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
#ifdef HAVE_IPV6
else
*addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
else
*addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
#endif
}
else if (!flags || (flags & F_NXDOMAIN))
flags = F_NOERR;
}
else if (!flags || (flags & F_NXDOMAIN))
flags = F_NOERR;
}
}
else
flags = 0;
}
}
}
if (flags == 0 && !(qtype & F_BIGNAME) &&
(daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
/* don't forward simple names, make exception for NS queries and empty name. */
flags = F_NXDOMAIN;
if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
flags = F_NOERR;
@@ -197,7 +204,11 @@ static unsigned short search_servers(time_t now, struct all_addr **addrpp,
log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
}
else if ((*type) & SERV_USE_RESOLV)
{
*type = 0; /* use normal servers for this domain */
*domain = NULL;
}
return flags;
}
@@ -206,7 +217,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
HEADER *header, size_t plen, time_t now, struct frec *forward)
{
char *domain = NULL;
int type = 0;
int type = 0, norebind = 0;
struct all_addr *addrp = NULL;
unsigned int crc = questions_crc(header, plen, daemon->namebuff);
unsigned short flags = 0;
@@ -234,7 +245,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
else
{
if (gotname)
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain);
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
if (!flags && !(forward = get_new_frec(now, NULL)))
/* table full - server failure. */
@@ -250,22 +261,33 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward->fd = udpfd;
forward->crc = crc;
forward->forwardall = 0;
forward->norebind = norebind;
header->id = htons(forward->new_id);
/* In strict_order mode, or when using domain specific servers
always try servers in the order specified in resolv.conf,
/* In strict_order mode, always try servers in the order
specified in resolv.conf, if a domain is given
always try all the available servers,
otherwise, use the one last known to work. */
if (type != 0 || (daemon->options & OPT_ORDER))
start = daemon->servers;
else if (!(start = daemon->last_server) ||
daemon->forwardcount++ > FORWARD_TEST ||
difftime(now, daemon->forwardtime) > FORWARD_TIME)
if (type == 0)
{
if (daemon->options & OPT_ORDER)
start = daemon->servers;
else if (!(start = daemon->last_server) ||
daemon->forwardcount++ > FORWARD_TEST ||
difftime(now, daemon->forwardtime) > FORWARD_TIME)
{
start = daemon->servers;
forward->forwardall = 1;
daemon->forwardcount = 0;
daemon->forwardtime = now;
}
}
else
{
start = daemon->servers;
forward->forwardall = 1;
daemon->forwardcount = 0;
daemon->forwardtime = now;
if (!(daemon->options & OPT_ORDER))
forward->forwardall = 1;
}
}
}
@@ -374,7 +396,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
static size_t process_reply(HEADER *header, time_t now,
struct server *server, size_t n)
struct server *server, size_t n, int check_rebind)
{
unsigned char *pheader, *sizep;
int munged = 0, is_sign;
@@ -428,9 +450,9 @@ static size_t process_reply(HEADER *header, time_t now,
header->rcode = NOERROR;
}
if (extract_addresses(header, n, daemon->namebuff, now))
if (extract_addresses(header, n, daemon->namebuff, now, is_sign, check_rebind))
{
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected"));
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
munged = 1;
}
}
@@ -543,7 +565,12 @@ void reply_query(int fd, int family, time_t now)
if (forward->forwardall == 0 || --forward->forwardall == 1 ||
(header->rcode != REFUSED && header->rcode != SERVFAIL))
{
if ((nn = process_reply(header, now, server, (size_t)n)))
int check_rebind = !forward->norebind;
if (!(daemon->options & OPT_NO_REBIND))
check_rebind = 0;
if ((nn = process_reply(header, now, server, (size_t)n, check_rebind)))
{
header->id = htons(forward->orig_id);
header->ra = 1; /* recursion if available */
@@ -635,21 +662,37 @@ void receive_query(struct listener *listen, time_t now)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{
dst_addr_4 = dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
if_index = p.p->ipi_ifindex;
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (listen->family == AF_INET)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
dst_addr_4 = dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
#ifdef HAVE_SOLARIS_NETWORK
if_index = *((unsigned int *)CMSG_DATA(cmptr));
#else
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
{
union {
unsigned char *c;
unsigned int *i;
struct in_addr *a;
#ifndef HAVE_SOLARIS_NETWORK
struct sockaddr_dl *s;
#endif
} p;
p.c = CMSG_DATA(cmptr);
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
#ifdef HAVE_SOLARIS_NETWORK
if_index = *(p.i);
#else
if_index = p.s->sdl_index;
#endif
}
}
#endif
@@ -659,8 +702,14 @@ void receive_query(struct listener *listen, time_t now)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == daemon->v6pktinfo)
{
dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
union {
unsigned char *c;
struct in6_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
dst_addr.addr.addr6 = p.p->ipi6_addr;
if_index = p.p->ipi6_ifindex;
}
}
#endif
@@ -717,7 +766,7 @@ void receive_query(struct listener *listen, time_t now)
unsigned char *tcp_request(int confd, time_t now,
struct in_addr local_addr, struct in_addr netmask)
{
int size = 0;
int size = 0, norebind = 0;
size_t m;
unsigned short qtype, gotname;
unsigned char c1, c2;
@@ -776,7 +825,7 @@ unsigned char *tcp_request(int confd, time_t now,
char *domain = NULL;
if (gotname)
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain);
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server)
last_server = daemon->servers;
@@ -792,7 +841,7 @@ unsigned char *tcp_request(int confd, time_t now,
Note that this code subtley ensures that consecutive queries on this connection
which can go to the same server, do so. */
while (1)
{
{
if (!firstsendto)
firstsendto = last_server;
else
@@ -857,7 +906,7 @@ unsigned char *tcp_request(int confd, time_t now,
someone might be attempting to insert bogus values into the cache by
sending replies containing questions and bogus answers. */
if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff))
m = process_reply(header, now, last_server, (unsigned int)m);
m = process_reply(header, now, last_server, (unsigned int)m, (daemon->options & OPT_NO_REBIND) && !norebind );
break;
}

View File

@@ -245,9 +245,12 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
if (data.giaddr.s_addr != 0)
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
sprintf(daemon->dhcp_buff2, "%u", data.remaining_time);
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
if (data.action != ACTION_DEL)
{
sprintf(daemon->dhcp_buff2, "%u", data.remaining_time);
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);

View File

@@ -29,11 +29,12 @@ void lease_init(time_t now)
int clid_len, hw_len, hw_type;
FILE *leasestream;
/* These two each hold a DHCP option max size 255
/* These each hold a DHCP option max size 255
and get a terminating zero added */
daemon->dhcp_buff = safe_malloc(256);
daemon->dhcp_buff2 = safe_malloc(256);
daemon->dhcp_buff3 = safe_malloc(256);
leases_left = daemon->dhcp_max;
if (daemon->options & OPT_LEASE_RO)

View File

@@ -30,7 +30,8 @@
/* defaults in case we die() before we log_start() */
static int log_fac = LOG_DAEMON;
static int log_stderr = 0;
static int log_stderr = 0;
static int echo_stderr = 0;
static int log_fd = -1;
static int log_to_file = 0;
static int entries_alloced = 0;
@@ -54,7 +55,7 @@ int log_start(struct passwd *ent_pw, int errfd)
{
int ret = 0;
log_stderr = !!(daemon->options & OPT_DEBUG);
echo_stderr = !!(daemon->options & OPT_DEBUG);
if (daemon->log_fac != -1)
log_fac = daemon->log_fac;
@@ -67,6 +68,12 @@ int log_start(struct passwd *ent_pw, int errfd)
{
log_to_file = 1;
daemon->max_logs = 0;
if (strcmp(daemon->log_file, "-") == 0)
{
log_stderr = 1;
echo_stderr = 0;
log_fd = dup(STDERR_FILENO);
}
}
max_logs = daemon->max_logs;
@@ -90,7 +97,7 @@ int log_start(struct passwd *ent_pw, int errfd)
change the ownership here so that the file is always owned by
the dnsmasq user. Then logrotate can just copy the owner.
Failure of the chown call is OK, (for instance when started as non-root) */
if (log_to_file && ent_pw && ent_pw->pw_uid != 0 &&
if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0 &&
fchown(log_fd, ent_pw->pw_uid, -1) != 0)
ret = errno;
@@ -99,37 +106,34 @@ int log_start(struct passwd *ent_pw, int errfd)
int log_reopen(char *log_file)
{
if (log_fd != -1)
close(log_fd);
/* NOTE: umask is set to 022 by the time this gets called */
if (log_file)
{
log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
return log_fd != -1;
}
else
if (!log_stderr)
{
if (log_fd != -1)
close(log_fd);
/* NOTE: umask is set to 022 by the time this gets called */
if (log_file)
log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
else
{
#ifdef HAVE_SOLARIS_NETWORK
/* Solaris logging is "different", /dev/log is not unix-domain socket.
Just leave log_fd == -1 and use the vsyslog call for everything.... */
/* Solaris logging is "different", /dev/log is not unix-domain socket.
Just leave log_fd == -1 and use the vsyslog call for everything.... */
# define _PATH_LOG "" /* dummy */
log_fd = -1;
return 1;
#else
{
int flags;
log_fd = socket(AF_UNIX, connection_type, 0);
if (log_fd == -1)
return 0;
/* if max_logs is zero, leave the socket blocking */
if (max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1)
fcntl(log_fd, F_SETFL, flags | O_NONBLOCK);
}
int flags;
log_fd = socket(AF_UNIX, connection_type, 0);
/* if max_logs is zero, leave the socket blocking */
if (log_fd != -1 && max_logs != 0 && (flags = fcntl(log_fd, F_GETFL)) != -1)
fcntl(log_fd, F_SETFL, flags | O_NONBLOCK);
#endif
return 1;
}
}
return log_fd != -1;
}
static void free_entry(void)
@@ -274,7 +278,7 @@ void my_syslog(int priority, const char *format, ...)
priority &= LOG_PRIMASK;
#endif
if (log_stderr)
if (echo_stderr)
{
fprintf(stderr, "dnsmasq%s: ", func);
va_start(ap, format);
@@ -394,14 +398,19 @@ void check_log_writer(fd_set *set)
void flush_log(void)
{
/* block until queue empty */
if (log_fd != -1)
/* write until queue empty */
while (log_fd != -1)
{
int flags;
if ((flags = fcntl(log_fd, F_GETFL)) != -1)
fcntl(log_fd, F_SETFL, flags & ~O_NONBLOCK);
struct timespec waiter;
log_write();
close(log_fd);
if (!entries)
{
close(log_fd);
break;
}
waiter.tv_sec = 0;
waiter.tv_nsec = 1000000; /* 1 ms */
nanosleep(&waiter, NULL);
}
}
@@ -412,11 +421,13 @@ void die(char *message, char *arg1, int exit_code)
if (!arg1)
arg1 = errmess;
log_stderr = 1; /* print as well as log when we die.... */
fputc('\n', stderr); /* prettyfy startup-script message */
if (!log_stderr)
{
echo_stderr = 1; /* print as well as log when we die.... */
fputc('\n', stderr); /* prettyfy startup-script message */
}
my_syslog(LOG_CRIT, message, arg1, errmess);
log_stderr = 0;
echo_stderr = 0;
my_syslog(LOG_CRIT, _("FAILED to start up"));
flush_log();

View File

@@ -281,8 +281,8 @@ static void nl_routechange(struct nlmsghdr *h)
return;
/* Force re-reading resolv file right now, for luck. */
daemon->last_resolv = 0;
poll_resolv(1, 1, dnsmasq_time());
if (daemon->srv_save)
{
if (daemon->srv_save->sfd)

View File

@@ -53,7 +53,44 @@ int iface_check(int family, struct all_addr *addr, char *name, int *indexp)
/* Note: have to check all and not bail out early, so that we set the
"used" flags. */
if (daemon->if_names || (addr && daemon->if_addrs))
{
#ifdef HAVE_DHCP
struct dhcp_context *range;
#endif
ret = 0;
#ifdef HAVE_DHCP
for (range = daemon->dhcp; range; range = range->next)
if (range->interface && strcmp(range->interface, name) == 0)
ret = 1;
#endif
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
ret = tmp->used = 1;
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (addr && tmp->addr.sa.sa_family == family)
{
if (family == AF_INET &&
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
ret = tmp->used = 1;
#ifdef HAVE_IPV6
else if (family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
&addr->addr.addr6))
ret = tmp->used = 1;
#endif
}
}
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
ret = 0;
if (indexp)
{
/* One form of bridging on BSD has the property that packets
@@ -85,33 +122,6 @@ int iface_check(int family, struct all_addr *addr, char *name, int *indexp)
}
}
if (daemon->if_names || (addr && daemon->if_addrs))
{
ret = 0;
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
ret = tmp->used = 1;
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (addr && tmp->addr.sa.sa_family == family)
{
if (family == AF_INET &&
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
ret = tmp->used = 1;
#ifdef HAVE_IPV6
else if (family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
&addr->addr.addr6))
ret = tmp->used = 1;
#endif
}
}
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
ret = 0;
return ret;
}
@@ -121,9 +131,12 @@ static int iface_allowed(struct irec **irecp, int if_index,
struct irec *iface;
int fd, mtu = 0, loopback;
struct ifreq ifr;
int dhcp_ok = 1;
int tftp_ok = daemon->tftp_unlimited;
#ifdef HAVE_DHCP
struct iname *tmp;
#endif
struct interface_list *ir = NULL;
/* check whether the interface IP has been added already
we call this routine multiple times. */
for (iface = *irecp; iface; iface = iface->next)
@@ -173,27 +186,45 @@ static int iface_allowed(struct irec **irecp, int if_index,
}
}
if (addr->sa.sa_family == AF_INET &&
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL))
return 1;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
dhcp_ok = 0;
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL))
return 1;
#ifdef HAVE_TFTP
/* implement wierd TFTP service rules */
if (addr->sa.sa_family == AF_INET)
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, ifr.ifr_name) == 0)
{
tftp_ok = 1;
break;
}
#endif
if (!ir)
{
if (addr->sa.sa_family == AF_INET &&
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL))
return 1;
#ifdef HAVE_DHCP
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
tftp_ok = 0;
#endif
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL))
return 1;
#endif
}
/* add to list */
if ((iface = whine_malloc(sizeof(struct irec))))
{
iface->addr = *addr;
iface->netmask = netmask;
iface->dhcp_ok = dhcp_ok;
iface->tftp_ok = tftp_ok;
iface->mtu = mtu;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
strcpy(iface->name, ifr.ifr_name);
iface->next = *irecp;
*irecp = iface;
return 1;
@@ -377,7 +408,7 @@ struct listener *create_wildcard_listeners(void)
}
#ifdef HAVE_TFTP
if (daemon->options & OPT_TFTP)
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
{
addr.in.sin_port = htons(TFTP_PORT);
if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
@@ -475,7 +506,7 @@ struct listener *create_bound_listeners(void)
}
#ifdef HAVE_TFTP
if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
if (iface->addr.sa.sa_family == AF_INET && iface->tftp_ok)
{
short save = iface->addr.in.sin_port;
iface->addr.in.sin_port = htons(TFTP_PORT);
@@ -666,7 +697,7 @@ void pre_allocate_sfds(void)
}
for (srv = daemon->servers; srv; srv = srv->next)
if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
!allocate_sfd(&srv->source_addr, srv->interface) &&
errno != 0 &&
(daemon->options & OPT_NOWILD))
@@ -697,7 +728,7 @@ void check_servers(void)
{
tmp = new->next;
if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
{
port = prettyprint_addr(&new->addr, daemon->namebuff);
@@ -736,25 +767,30 @@ void check_servers(void)
new->next = ret;
ret = new;
if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
if (!(new->flags & SERV_NO_REBIND))
{
char *s1, *s2;
if (!(new->flags & SERV_HAS_DOMAIN))
s1 = _("unqualified"), s2 = _("names");
else if (strlen(new->domain) == 0)
s1 = _("default"), s2 = "";
if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
{
char *s1, *s2;
if (!(new->flags & SERV_HAS_DOMAIN))
s1 = _("unqualified"), s2 = _("names");
else if (strlen(new->domain) == 0)
s1 = _("default"), s2 = "";
else
s1 = _("domain"), s2 = new->domain;
if (new->flags & SERV_NO_ADDR)
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
else if (new->flags & SERV_USE_RESOLV)
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
else if (!(new->flags & SERV_LITERAL_ADDRESS))
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
}
else if (new->interface[0] != 0)
my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
else
s1 = _("domain"), s2 = new->domain;
if (new->flags & SERV_NO_ADDR)
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
else if (!(new->flags & SERV_LITERAL_ADDRESS))
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
}
else if (new->interface[0] != 0)
my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
else
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
}
daemon->servers = ret;
@@ -881,16 +917,19 @@ struct in_addr get_ifaddr(char *intr)
{
struct listener *l;
struct ifreq ifr;
struct sockaddr_in ret;
ret.sin_addr.s_addr = -1;
for (l = daemon->listeners; l && l->family != AF_INET; l = 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;
if (l && ioctl(l->fd, SIOCGIFADDR, &ifr) != -1)
memcpy(&ret, &ifr.ifr_addr, sizeof(ret));
return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
return ret.sin_addr;
}

View File

@@ -102,6 +102,12 @@ struct myoption {
#define LOPT_PXE_PROMT 291
#define LOPT_PXE_SERV 292
#define LOPT_TEST 293
#define LOPT_TAG_IF 294
#define LOPT_PROXY 295
#define LOPT_GEN_NAMES 296
#define LOPT_MAXTTL 297
#define LOPT_NO_REBIND 298
#define LOPT_LOC_REBND 299
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -176,7 +182,7 @@ static const struct myoption opts[] =
{ "dns-forward-max", 1, 0, '0' },
{ "clear-on-reload", 0, 0, LOPT_RELOAD },
{ "dhcp-ignore-names", 2, 0, LOPT_NO_NAMES },
{ "enable-tftp", 0, 0, LOPT_TFTP },
{ "enable-tftp", 2, 0, LOPT_TFTP },
{ "tftp-secure", 0, 0, LOPT_SECURE },
{ "tftp-unique-root", 0, 0, LOPT_APREF },
{ "tftp-root", 1, 0, LOPT_PREFIX },
@@ -197,10 +203,12 @@ static const struct myoption opts[] =
{ "dhcp-no-override", 0, 0, LOPT_OVERRIDE },
{ "tftp-port-range", 1, 0, LOPT_TFTPPORTS },
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
{ "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
{ "all-servers", 0, 0, LOPT_NOLAST },
{ "dhcp-match", 1, 0, LOPT_MATCH },
{ "dhcp-broadcast", 1, 0, LOPT_BROADCAST },
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL },
{ "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
{ "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
{ "min-port", 1, 0, LOPT_MINPORT },
@@ -209,6 +217,10 @@ static const struct myoption opts[] =
{ "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
{ "pxe-service", 1, 0, LOPT_PXE_SERV },
{ "test", 0, 0, LOPT_TEST },
{ "tag-if", 1, 0, LOPT_TAG_IF },
{ "dhcp-proxy", 2, 0, LOPT_PROXY },
{ "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
{ "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
{ NULL, 0, 0, 0 }
};
@@ -239,18 +251,19 @@ static struct {
{ 'F', ARG_DUP, "ipaddr,ipaddr,time", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
{ 'g', ARG_ONE, "groupname", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
{ LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file"), NULL },
{ LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file"), NULL },
{ LOPT_DHCP_HOST, ARG_ONE, "<filename>", gettext_noop("Read DHCP host specs from file."), NULL },
{ LOPT_DHCP_OPTS, ARG_ONE, "<filename>", gettext_noop("Read DHCP option specs from file."), NULL },
{ LOPT_TAG_IF, ARG_DUP, "tag-expression", gettext_noop("Evaluate conditional tag expression."), NULL },
{ 'h', OPT_NO_HOSTS, NULL, gettext_noop("Do NOT load %s file."), HOSTSFILE },
{ 'H', ARG_DUP, "path", gettext_noop("Specify a hosts file to be read in addition to %s."), HOSTSFILE },
{ 'i', ARG_DUP, "interface", gettext_noop("Specify interface(s) to listen on."), NULL },
{ 'I', ARG_DUP, "int", gettext_noop("Specify interface(s) NOT to listen on.") , NULL },
{ 'j', ARG_DUP, "<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
{ LOPT_CIRCUIT, ARG_DUP, "<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
{ LOPT_REMOTE, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
{ LOPT_SUBSCR, ARG_DUP, "<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
{ 'J', ARG_DUP, "=<id>[,<id>]", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
{ LOPT_BROADCAST, ARG_DUP, "=<id>[,<id>]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
{ 'j', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP user class to tag."), NULL },
{ LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
{ LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
{ LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
{ 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
{ LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
{ 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
{ 'K', OPT_AUTHORITATIVE, NULL, gettext_noop("Assume we are the only DHCP server on the local network."), NULL },
{ 'l', ARG_ONE, "path", gettext_noop("Specify where to store DHCP leases (defaults to %s)."), LEASEFILE },
@@ -274,8 +287,9 @@ static struct {
{ 't', ARG_ONE, "host_name", gettext_noop("Specify default target in an MX record."), NULL },
{ 'T', ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
{ LOPT_NEGTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
{ LOPT_MAXTTL, ARG_ONE, "time", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
{ 'u', ARG_ONE, "username", gettext_noop("Change to this user after startup. (defaults to %s)."), CHUSER },
{ 'U', ARG_DUP, "<id>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
{ 'U', ARG_DUP, "set:<tag>,<class>", gettext_noop("Map DHCP vendor class to tag."), NULL },
{ 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
{ 'V', ARG_DUP, "addr,addr,mask", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
{ 'W', ARG_DUP, "name,target,...", gettext_noop("Specify a SRV record."), NULL },
@@ -290,8 +304,8 @@ static struct {
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
{ '1', OPT_DBUS, NULL, gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
{ '2', ARG_DUP, "interface", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
{ '3', ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
{ LOPT_BRIDGE, ARG_DUP, "iface,alias,..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
{ '5', OPT_NO_PING, NULL, gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
{ '6', ARG_ONE, "path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
@@ -300,10 +314,10 @@ static struct {
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
{ '0', ARG_ONE, "<queries>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
{ LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
{ LOPT_NO_NAMES, ARG_DUP, "[=<id>[,<id>]]", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
{ LOPT_NO_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Ignore hostnames provided by DHCP clients."), NULL },
{ LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
{ LOPT_TFTP, OPT_TFTP, NULL, gettext_noop("Enable integrated read-only TFTP server."), NULL },
{ LOPT_PREFIX, ARG_ONE, "<directory>", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
{ LOPT_TFTP, ARG_DUP, "[=<interface>]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
{ LOPT_PREFIX, ARG_ONE, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
{ LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
{ LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
{ LOPT_TFTP_MAX, ARG_ONE, "<connections>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
@@ -312,13 +326,17 @@ static struct {
{ LOPT_LOG_OPTS, OPT_LOG_OPTS, NULL, gettext_noop("Extra logging for DHCP."), NULL },
{ LOPT_MAX_LOGS, ARG_ONE, "[=<log lines>]", gettext_noop("Enable async. logging; optionally set queue length."), NULL },
{ LOPT_REBIND, OPT_NO_REBIND, NULL, gettext_noop("Stop DNS rebinding. Filter private IP ranges when resolving."), NULL },
{ LOPT_LOC_REBND, OPT_LOCAL_REBIND, NULL, gettext_noop("Allow rebinding of 127.0.0.0/8, for RBL servers."), NULL },
{ LOPT_NO_REBIND, ARG_DUP, "/domain/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
{ LOPT_MATCH, ARG_DUP, "<netid>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
{ LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change script as this user."), NULL },
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
{ LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
{ LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]...", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
{ LOPT_PROXY, ARG_DUP, "[=<ip_address>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
{ LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
@@ -519,9 +537,9 @@ static char *split_chr(char *s, char c)
p = comma;
*comma = ' ';
for (; isspace((int)*comma); comma++);
for (; *comma == ' '; comma++);
for (; (p >= s) && isspace((int)*p); p--)
for (; (p >= s) && *p == ' '; p--)
*p = 0;
return comma;
@@ -637,7 +655,7 @@ static void do_usage(void)
sprintf(buff, " ");
sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
printf("%-36.36s", buff);
printf("%-40.40s", buff);
if (usage[i].arg)
{
@@ -663,6 +681,22 @@ static void display_opts(void)
printf("%3d %s\n", opttab[i].val, opttab[i].name);
}
static int is_tag_prefix(char *arg)
{
if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
return 1;
return 0;
}
static char *set_prefix(char *arg)
{
if (strstr(arg, "set:") == arg)
return arg+4;
return arg;
}
/* This is too insanely large to keep in-line in the switch */
static char *parse_dhcp_opt(char *arg, int flags)
{
@@ -730,11 +764,11 @@ static char *parse_dhcp_opt(char *arg, int flags)
else
{
new->netid = opt_malloc(sizeof (struct dhcp_netid));
/* allow optional "net:" for consistency */
if (strstr(arg, "net:") == arg)
/* allow optional "net:" or "tag:" for consistency */
if (is_tag_prefix(arg))
new->netid->net = opt_string_alloc(arg+4);
else
new->netid->net = opt_string_alloc(arg);
new->netid->net = opt_string_alloc(set_prefix(arg));
new->netid->next = np;
np = new->netid;
}
@@ -1121,7 +1155,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case '8': /* --log-facility */
/* may be a filename */
if (strchr(arg, '/'))
if (strchr(arg, '/') || strcmp (arg, "-") == 0)
daemon->log_file = opt_string_alloc(arg);
else
{
@@ -1391,21 +1425,26 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
} while (arg);
break;
case 'S': /* --server */
case LOPT_LOCAL: /* --local */
case 'A': /* --address */
case 'S': /* --server */
case LOPT_LOCAL: /* --local */
case 'A': /* --address */
case LOPT_NO_REBIND: /* --rebind-domain-ok */
{
struct server *serv, *newlist = NULL;
unhide_metas(arg);
if (arg && *arg == '/')
if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
{
char *end;
arg++;
while ((end = split_chr(arg, '/')))
int rebind = !(*arg == '/');
char *end = NULL;
if (!rebind)
arg++;
while (rebind || (end = split_chr(arg, '/')))
{
char *domain = NULL;
/* elide leading dots - they are implied in the search algorithm */
while (*arg == '.') arg++;
/* # matches everything and becomes a zero length domain string */
if (strcmp(arg, "#") == 0)
domain = "";
@@ -1418,6 +1457,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
serv->domain = domain;
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
arg = end;
if (rebind)
break;
}
if (!newlist)
{
@@ -1438,10 +1479,20 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if (!(newlist->flags & SERV_TYPE))
option = '?';
}
else if (option == LOPT_NO_REBIND)
newlist->flags |= SERV_NO_REBIND;
if (!arg || !*arg)
{
newlist->flags |= SERV_NO_ADDR; /* no server */
if (!(newlist->flags & SERV_NO_REBIND))
newlist->flags |= SERV_NO_ADDR; /* no server */
if (newlist->flags & SERV_LITERAL_ADDRESS)
option = '?';
}
else if (strcmp(arg, "#") == 0)
{
newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
if (newlist->flags & SERV_LITERAL_ADDRESS)
option = '?';
}
@@ -1590,12 +1641,15 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case 'T': /* --local-ttl */
case LOPT_NEGTTL: /* --neg-ttl */
case LOPT_MAXTTL: /* --max-ttl */
{
int ttl;
if (!atoi_check(arg, &ttl))
option = '?';
else if (option == LOPT_NEGTTL)
daemon->neg_ttl = (unsigned long)ttl;
else if (option == LOPT_MAXTTL)
daemon->max_ttl = (unsigned long)ttl;
else
daemon->local_ttl = (unsigned long)ttl;
break;
@@ -1609,13 +1663,35 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
#endif
#ifdef HAVE_TFTP
case LOPT_TFTP: /* --enable-tftp */
if (arg)
{
struct interface_list *new = opt_malloc(sizeof(struct interface_list));
new->interface = opt_string_alloc(arg);
new->next = daemon->tftp_interfaces;
daemon->tftp_interfaces = new;
}
else
daemon->tftp_unlimited = 1;
break;
case LOPT_TFTP_MAX: /* --tftp-max */
if (!atoi_check(arg, &daemon->tftp_max))
option = '?';
break;
case LOPT_PREFIX: /* --tftp-prefix */
daemon->tftp_prefix = opt_string_alloc(arg);
comma = split(arg);
if (comma)
{
struct tftp_prefix *new = opt_malloc(sizeof(struct tftp_prefix));
new->interface = opt_string_alloc(comma);
new->prefix = opt_string_alloc(arg);
new->next = daemon->if_prefix;
daemon->if_prefix = new;
}
else
daemon->tftp_prefix = opt_string_alloc(arg);
break;
case LOPT_TFTPPORTS: /* --tftp-port-range */
@@ -1679,7 +1755,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->netid.net = NULL;
new->filter = NULL;
new->flags = 0;
new->interface = NULL;
gen_prob = _("bad dhcp-range");
if (!arg)
@@ -1696,7 +1773,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
if (*cp != ',' && (comma = split(arg)))
{
if (strstr(arg, "net:") == arg)
if (strstr(arg, "interface:") == arg)
new->interface = opt_string_alloc(arg+10);
else if (is_tag_prefix(arg))
{
struct dhcp_netid *tt = opt_malloc(sizeof (struct dhcp_netid));
tt->net = opt_string_alloc(arg+4);
@@ -1706,7 +1785,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
else
{
if (new->netid.net)
problem = _("only one netid tag allowed");
problem = _("only one tag allowed");
else if (strstr(arg, "set:") == arg)
new->netid.net = opt_string_alloc(arg+4);
else
new->netid.net = opt_string_alloc(arg);
}
@@ -1814,7 +1895,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->next = daemon->dhcp_conf;
new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
new->hwaddr = NULL;
new->netid = NULL;
if ((a[0] = arg))
for (k = 1; k < 6; k++)
if (!(a[k] = split(a[k-1])))
@@ -1851,15 +1933,17 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
}
}
}
else if (strstr(arg, "net:") == arg)
/* dhcp-host has strange backwards-compat needs. */
else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
{
int len = strlen(arg + 4) + 1;
if ((new->netid.net = opt_malloc(len)))
{
new->flags |= CONFIG_NETID;
strcpy(new->netid.net, arg+4);
unhide_metas(new->netid.net);
}
struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
newtag->net = opt_malloc(strlen(arg + 4) + 1);
newlist->next = new->netid;
new->netid = newlist;
newlist->list = newtag;
strcpy(newtag->net, arg+4);
unhide_metas(newtag->net);
}
else
{
@@ -1943,6 +2027,72 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
daemon->dhcp_conf = new;
break;
}
case LOPT_TAG_IF: /* --tag-if */
{
struct tag_if *new = opt_malloc(sizeof(struct tag_if));
new->tag = NULL;
new->set = NULL;
new->next = NULL;
/* preserve order */
if (!daemon->tag_if)
daemon->tag_if = new;
else
{
struct tag_if *tmp;
for (tmp = daemon->tag_if; tmp->next; tmp = tmp->next);
tmp->next = new;
}
while (arg)
{
size_t len;
comma = split(arg);
len = strlen(arg);
if (len < 5)
{
new->set = NULL;
break;
}
else
{
struct dhcp_netid *newtag = opt_malloc(sizeof(struct dhcp_netid));
newtag->net = opt_malloc(len - 3);
strcpy(newtag->net, arg+4);
unhide_metas(newtag->net);
if (strstr(arg, "set:") == arg)
{
struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
newlist->next = new->set;
new->set = newlist;
newlist->list = newtag;
}
else if (strstr(arg, "tag:") == arg)
{
newtag->next = new->tag;
new->tag = newtag;
}
else
{
new->set = NULL;
break;
}
}
arg = comma;
}
if (!new->set)
problem = _("bad tag-if");
break;
}
case 'O': /* --dhcp-option */
case LOPT_FORCE: /* --dhcp-option-force */
@@ -1957,7 +2107,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case 'M': /* --dhcp-boot */
{
struct dhcp_netid *id = NULL;
while (arg && strstr(arg, "net:") == arg)
while (is_tag_prefix(arg))
{
struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
newid->next = id;
@@ -2011,8 +2161,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->netid = NULL;
new->opt = 10; /* PXE_MENU_PROMPT */
while (arg && strstr(arg, "net:") == arg)
{
while (is_tag_prefix(arg))
{
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
comma = split(arg);
nn->next = new->netid;
@@ -2057,7 +2207,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->netid = NULL;
new->server.s_addr = 0;
while (arg && strstr(arg, "net:") == arg)
while (is_tag_prefix(arg))
{
struct dhcp_netid *nn = opt_malloc(sizeof (struct dhcp_netid));
comma = split(arg);
@@ -2133,10 +2283,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
else
{
struct dhcp_mac *new = opt_malloc(sizeof(struct dhcp_mac));
if (strstr(arg, "net:") == arg)
new->netid.net = opt_string_alloc(arg+4);
else
new->netid.net = opt_string_alloc(arg);
new->netid.net = opt_string_alloc(set_prefix(arg));
unhide_metas(comma);
new->hwaddr_len = parse_hex(comma, new->hwaddr, DHCP_CHADDR_MAX, &new->mask, &new->hwaddr_type);
new->next = daemon->dhcp_macs;
@@ -2158,10 +2305,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
char *p;
int dig = 0;
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
if (strstr(arg, "net:") == arg)
new->netid.net = opt_string_alloc(arg+4);
else
new->netid.net = opt_string_alloc(arg);
new->netid.net = opt_string_alloc(set_prefix(arg));
/* check for hex string - must digits may include : must not have nothing else,
only allowed for agent-options. */
for (p = comma; *p; p++)
@@ -2227,7 +2371,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
case 'J': /* --dhcp-ignore */
case LOPT_NO_NAMES: /* --dhcp-ignore-names */
case LOPT_BROADCAST: /* --dhcp-broadcast */
case '3': /* --bootp-dynamic */
case '3': /* --bootp-dynamic */
case LOPT_GEN_NAMES: /* --dhcp-generate-names */
{
struct dhcp_netid_list *new = opt_malloc(sizeof(struct dhcp_netid_list));
struct dhcp_netid *list = NULL;
@@ -2246,6 +2391,11 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->next = daemon->bootp_dynamic;
daemon->bootp_dynamic = new;
}
else if (option == LOPT_GEN_NAMES)
{
new->next = daemon->dhcp_gen_names;
daemon->dhcp_gen_names = new;
}
else
{
new->next = daemon->dhcp_ignore_names;
@@ -2257,7 +2407,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
comma = split(arg);
member->next = list;
list = member;
if (strstr(arg, "net:") == arg)
if (is_tag_prefix(arg))
member->net = opt_string_alloc(arg+4);
else
member->net = opt_string_alloc(arg);
@@ -2267,6 +2417,19 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
new->list = list;
break;
}
case LOPT_PROXY: /* --dhcp-proxy */
daemon->override = 1;
while (arg) {
struct addr_list *new = opt_malloc(sizeof(struct addr_list));
comma = split(arg);
if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
problem = _("bad dhcp-proxy address");
new->next = daemon->override_relays;
daemon->override_relays = new;
arg = comma;
}
break;
#endif
case 'V': /* --alias */
@@ -2547,9 +2710,8 @@ static char *one_opt(int option, char *arg, char *gen_prob, int nest)
static void one_file(char *file, int nest, int hard_opt)
{
volatile int lineno = 0;
int i, option;
FILE *f;
char *p, *arg, *start, *buff = daemon->namebuff;
char *buff = daemon->namebuff;
static struct fileread {
dev_t dev;
ino_t ino;
@@ -2595,9 +2757,9 @@ static void one_file(char *file, int nest, int hard_opt)
while (fgets(buff, MAXDNAME, f))
{
int white;
unsigned int lastquote;
char *errmess;
int white, i, option; ;
char *errmess, *p, *arg, *start;
size_t len;
/* Memory allocation failure longjmps here if mem_recover == 1 */
if (hard_opt)
@@ -2612,12 +2774,12 @@ static void one_file(char *file, int nest, int hard_opt)
/* Implement quotes, inside quotes we allow \\ \" \n and \t
metacharacters get hidden also strip comments */
for (white = 1, lastquote = 0, p = buff; *p; p++)
for (white = 1, p = buff; *p; p++)
{
if (*p == '"')
{
memmove(p, p+1, strlen(p+1)+1);
for(; *p && *p != '"'; p++)
{
if (*p == '\\' && strchr("\"tnebr\\", p[1]))
@@ -2636,40 +2798,51 @@ static void one_file(char *file, int nest, int hard_opt)
}
*p = hide_meta(*p);
}
if (*p == '"')
{
memmove(p, p+1, strlen(p+1)+1);
lastquote = p - buff;
}
else
if (*p == 0)
{
errmess = _("missing \"");
goto oops;
}
memmove(p, p+1, strlen(p+1)+1);
}
if (white && *p == '#')
{
*p = 0;
break;
if (isspace(*p))
{
*p = ' ';
white = 1;
}
white = isspace((int)unhide_meta(*p));
else
{
if (white && *p == '#')
{
*p = 0;
break;
}
white = 0;
}
}
/* fgets gets end of line char too. */
while (strlen(buff) > lastquote && isspace((int)unhide_meta(buff[strlen(buff)-1])))
buff[strlen(buff)-1] = 0;
if (*buff == 0)
/* strip leading spaces */
for (start = buff; *start && *start == ' '; start++);
/* strip trailing spaces */
for (len = strlen(start); (len != 0) && (start[len-1] == ' '); len--);
if (len == 0)
continue;
else
start[len] = 0;
if (hard_opt != 0)
arg = buff;
else if ((p=strchr(buff, '=')))
arg = start;
else if ((p=strchr(start, '=')))
{
/* allow spaces around "=" */
arg = p+1;
for (; p >= buff && (isspace((int)*p) || *p == '='); p--)
for (arg = p+1; *arg == ' '; arg++);
for (; p >= start && (*p == ' ' || *p == '='); p--)
*p = 0;
}
else
@@ -2679,9 +2852,6 @@ static void one_file(char *file, int nest, int hard_opt)
option = hard_opt;
else
{
/* skip leading space */
for (start = buff; *start && isspace((int)*start); start++);
for (option = 0, i = 0; opts[i].name; i++)
if (strcmp(opts[i].name, start) == 0)
{
@@ -2698,12 +2868,7 @@ static void one_file(char *file, int nest, int hard_opt)
}
if (!errmess)
{
if (arg)
for (; isspace((int)*arg); arg++);
errmess = one_opt(option, arg, _("error"), nest + 1);
}
errmess = one_opt(option, arg, _("error"), nest + 1);
if (errmess)
{
@@ -2716,7 +2881,7 @@ static void one_file(char *file, int nest, int hard_opt)
}
}
mem_recover = 1;
mem_recover = 0;
fclose(f);
}
@@ -2735,16 +2900,24 @@ void reread_dhcp(void)
if (configs->flags & CONFIG_BANK)
{
struct hwaddr_config *mac, *tmp;
struct dhcp_netid_list *list, *tmplist;
for (mac = configs->hwaddr; mac; mac = tmp)
{
tmp = mac->next;
free(mac);
}
if (configs->flags & CONFIG_CLID)
free(configs->clid);
if (configs->flags & CONFIG_NETID)
free(configs->netid.net);
for (list = configs->netid; list; list = tmplist)
{
free(list->list);
tmplist = list->next;
free(list);
}
if (configs->flags & CONFIG_NAME)
free(configs->hostname);

View File

@@ -513,26 +513,31 @@ unsigned char *find_pseudoheader(HEADER *header, size_t plen, size_t *len, unsi
/* is addr in the non-globally-routed IP space? */
static int private_net(struct in_addr addr)
static int private_net(struct in_addr addr, int ban_localhost)
{
in_addr_t ip_addr = ntohl(addr.s_addr);
return
((ip_addr & 0xFF000000) == 0x7F000000) /* 127.0.0.0/8 (loopback) */ ||
(((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ ||
((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ;
}
static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, size_t qlen)
static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, size_t qlen, char *name)
{
int i, qtype, qclass, rdlen;
unsigned long ttl;
for (i = count; i != 0; i--)
{
if (!(p = skip_name(p, header, qlen, 10)))
if (name && (daemon->options & OPT_LOG))
{
if (!extract_name(header, qlen, &p, name, 1, 10))
return 0;
}
else if (!(p = skip_name(p, header, qlen, 10)))
return 0; /* bad packet */
GETSHORT(qtype, p);
@@ -540,15 +545,15 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
GETLONG(ttl, p);
GETSHORT(rdlen, p);
if ((qclass == C_IN) && (qtype == T_A))
if (qclass == C_IN && qtype == T_A)
{
struct doctor *doctor;
struct in_addr addr;
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
return 0;
/* alignment */
/* alignment */
memcpy(&addr, p, INADDRSZ);
for (doctor = daemon->doctors; doctor; doctor = doctor->next)
@@ -561,7 +566,7 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) ||
ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
continue;
addr.s_addr &= ~doctor->mask.s_addr;
addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
/* Since we munged the data, the server it came from is no longer authoritative */
@@ -570,6 +575,30 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
break;
}
}
else if (qtype == T_TXT && name && (daemon->options & OPT_LOG))
{
unsigned char *p1 = p;
if (!CHECK_LEN(header, p1, qlen, rdlen))
return 0;
while ((p1 - p) < rdlen)
{
unsigned int i, len = *p1;
unsigned char *p2 = p1;
/* make counted string zero-term and sanitise */
for (i = 0; i < len; i++)
if (isprint(*(p2+1)))
{
*p2 = *(p2+1);
p2++;
}
*p2 = 0;
my_syslog(LOG_DEBUG, "reply %s is %s", name, p1);
/* restore */
memmove(p1 + 1, p1, len);
*p1 = len;
p1 += len+1;
}
}
if (!ADD_RDLEN(header, p, qlen, rdlen))
return 0; /* bad packet */
@@ -578,7 +607,7 @@ static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, siz
return p;
}
static int find_soa(HEADER *header, size_t qlen)
static int find_soa(HEADER *header, size_t qlen, char *name)
{
unsigned char *p;
int qtype, qclass, rdlen;
@@ -587,7 +616,7 @@ static int find_soa(HEADER *header, size_t qlen)
/* first move to NS section and find TTL from any SOA section */
if (!(p = skip_questions(header, qlen)) ||
!(p = do_doctor(p, ntohs(header->ancount), header, qlen)))
!(p = do_doctor(p, ntohs(header->ancount), header, qlen, name)))
return 0; /* bad packet */
for (i = ntohs(header->nscount); i != 0; i--)
@@ -623,7 +652,7 @@ static int find_soa(HEADER *header, size_t qlen)
}
/* rewrite addresses in additioal section too */
if (!do_doctor(p, ntohs(header->arcount), header, qlen))
if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL))
return 0;
if (!found_soa)
@@ -635,8 +664,8 @@ static int find_soa(HEADER *header, size_t qlen)
/* Note that the following code can create CNAME chains that don't point to a real record,
either because of lack of memory, or lack of SOA records. These are treated by the cache code as
expired and cleaned out that way.
Return 1 if we reject an address because it look like parct of dns-rebinding attack. */
int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
Return 1 if we reject an address because it look like part of dns-rebinding attack. */
int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now, int is_sign, int check_rebind)
{
unsigned char *p, *p1, *endrr, *namep;
int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
@@ -645,11 +674,11 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
cache_start_insert();
/* find_soa is needed for dns_doctor side-effects, so don't call it lazily if there are any. */
if (daemon->doctors)
/* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
if (daemon->doctors || (daemon->options & OPT_LOG))
{
searched_soa = 1;
ttl = find_soa(header, qlen);
ttl = find_soa(header, qlen, name);
}
/* go through the questions. */
@@ -698,6 +727,11 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
GETSHORT(aqtype, p1);
GETSHORT(aqclass, p1);
GETLONG(attl, p1);
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
{
(p1) -= NS_INT32SZ;
PUTLONG(daemon->max_ttl, p1);
}
GETSHORT(ardlen, p1);
endrr = p1+ardlen;
@@ -732,7 +766,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
if (!searched_soa)
{
searched_soa = 1;
ttl = find_soa(header, qlen);
ttl = find_soa(header, qlen, NULL);
}
if (ttl)
cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags);
@@ -773,6 +807,11 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
GETSHORT(aqtype, p1);
GETSHORT(aqclass, p1);
GETLONG(attl, p1);
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
{
(p1) -= NS_INT32SZ;
PUTLONG(daemon->max_ttl, p1);
}
GETSHORT(ardlen, p1);
endrr = p1+ardlen;
@@ -807,9 +846,9 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
memcpy(&addr, p1, addrlen);
/* check for returned address in private space */
if ((daemon->options & OPT_NO_REBIND) &&
if (check_rebind &&
(flags & F_IPV4) &&
private_net(addr.addr.addr4))
private_net(addr.addr.addr4, !(daemon->options & OPT_LOCAL_REBIND)))
return 1;
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
@@ -833,7 +872,7 @@ int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now)
if (!searched_soa)
{
searched_soa = 1;
ttl = find_soa(header, qlen);
ttl = find_soa(header, qlen, NULL);
}
/* If there's no SOA to get the TTL from, but there is a CNAME
pointing at this, inherit its TTL */
@@ -1120,7 +1159,11 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now)
if (crecp->flags & (F_IMMORTAL | F_DHCP))
return daemon->local_ttl;
return crecp->ttd - now;
/* Return the Max TTL value if it is lower then the actual TTL */
if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
return crecp->ttd - now;
else
return daemon->max_ttl;
}
@@ -1302,7 +1345,7 @@ size_t answer_request(HEADER *header, char *limit, size_t qlen,
} 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))
private_net(addr.addr.addr4, 1))
{
/* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
ans = 1;

View File

@@ -116,11 +116,12 @@ static void do_options(struct dhcp_context *context,
struct in_addr subnet_addr,
unsigned char fqdn_flags,
int null_term, int pxearch,
unsigned char *uuid);
unsigned char *uuid,
int vendor_class_len);
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
static void do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
static int prune_vendor_opts(struct dhcp_netid *netid);
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local);
@@ -145,14 +146,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
char *message = NULL;
unsigned int time;
struct dhcp_config *config;
struct dhcp_netid *netid;
struct dhcp_netid *netid, *tagif_netid;
struct in_addr subnet_addr, fallback, override;
unsigned short fuzz = 0;
unsigned int mess_type = 0;
unsigned char fqdn_flags = 0;
unsigned char *agent_id = NULL, *uuid = NULL;
unsigned char *emac = NULL;
int emac_len = 0;
int vendor_class_len = 0, emac_len = 0;
struct dhcp_netid known_id, iface_id, cpewan_id;
struct dhcp_opt *o;
unsigned char pxe_uuid[17];
@@ -174,12 +175,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
/* check for DHCP rather than BOOTP */
if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
{
mess_type = option_uint(opt, 0, 1);
u32 cookie = htonl(DHCP_COOKIE);
/* only insist on a cookie for DHCP. */
if (*((u32 *)&mess->options) != htonl(DHCP_COOKIE))
if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
return 0;
mess_type = option_uint(opt, 0, 1);
/* two things to note here: expand_buf may move the packet,
so reassign mess from daemon->packet. Also, the size
sent includes the IP and UDP headers, hence the magic "-28" */
@@ -278,7 +281,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
vendor->netid.next = netid;
netid = &vendor->netid;
break;
}
}
}
@@ -388,10 +390,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
my_syslog(MS_DHCP | LOG_INFO, _("%u Available DHCP subnet: %s/%s"),
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
else
my_syslog(MS_DHCP | LOG_INFO, _("%u Available DHCP range: %s -- %s"),
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
}
}
@@ -430,10 +432,15 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
domain = config->domain;
}
if (have_config(config, CONFIG_NETID))
if (config)
{
config->netid.next = netid;
netid = &config->netid;
struct dhcp_netid_list *list;
for (list = config->netid; list; list = list->next)
{
list->list->next = netid;
netid = list->list;
}
}
/* Match incoming filename field as a netid. */
@@ -452,8 +459,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
bootp_id.next = netid;
netid = &bootp_id;
tagif_netid = run_tag_if(netid);
for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
if (match_netid(id_list->list, netid, 0))
if (match_netid(id_list->list, tagif_netid, 0))
message = _("ignored");
if (!message)
@@ -474,7 +483,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
{
if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
!address_available(context, lease->addr, netid))
!address_available(context, lease->addr, tagif_netid))
{
if (lease)
{
@@ -482,7 +491,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease_prune(lease, now);
lease = NULL;
}
if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, netid, now))
if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
message = _("no address available");
}
else
@@ -494,13 +503,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else if (context->netid.net)
{
context->netid.next = netid;
netid = &context->netid;
}
netid = &context->netid;
tagif_netid = run_tag_if(netid);
}
if (!message && !nailed)
{
for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
if ((!id_list->list) || match_netid(id_list->list, netid, 0))
if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
break;
if (!id_list)
message = _("no address configured");
@@ -526,13 +536,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clear_packet(mess, end);
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
domain, netid, subnet_addr, 0, 0, 0, NULL);
domain, tagif_netid, subnet_addr, 0, 0, 0, NULL, 0);
}
}
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, message, mess->xid);
return message ? 0 : dhcp_packet_size(mess, netid, agent_id, real_end);
return message ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
}
if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 4)))
@@ -632,10 +642,15 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
}
if (have_config(config, CONFIG_NETID))
if (config)
{
config->netid.next = netid;
netid = &config->netid;
struct dhcp_netid_list *list;
for (list = config->netid; list; list = list->next)
{
list->list->next = netid;
netid = list->list;
}
}
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
@@ -732,22 +747,48 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
}
/* mark vendor-encapsulated options which match the client-supplied vendor class */
match_vendor_opts(option_find(mess, sz, OPTION_VENDOR_ID, 1), daemon->dhcp_opts);
/* mark vendor-encapsulated options which match the client-supplied vendor class,
save client-supplied vendor class */
if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
{
memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
vendor_class_len = option_len(opt);
}
match_vendor_opts(opt, daemon->dhcp_opts);
if (daemon->options & OPT_LOG_OPTS)
{
if (sanitise(option_find(mess, sz, OPTION_VENDOR_ID, 1), daemon->namebuff))
my_syslog(MS_DHCP | LOG_INFO, _("%u Vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
if (sanitise(opt, daemon->namebuff))
my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
my_syslog(MS_DHCP | LOG_INFO, _("%u User class: %s"), ntohl(mess->xid), daemon->namebuff);
my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
}
tagif_netid = run_tag_if(netid);
/* if all the netids in the ignore list are present, ignore this client */
for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
if (match_netid(id_list->list, netid, 0))
if (match_netid(id_list->list, tagif_netid, 0))
ignore = 1;
/* If configured, we can override the server-id to be the address of the relay,
so that all traffic goes via the relay and can pick up agent-id info. This can be
configured for all relays, or by address. */
if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
{
if (!daemon->override_relays)
override = mess->giaddr;
else
{
struct addr_list *l;
for (l = daemon->override_relays; l; l = l->next)
if (l->addr.s_addr == mess->giaddr.s_addr)
break;
if (l)
override = mess->giaddr;
}
}
/* Can have setting to ignore the client ID for a particular MAC address or hostname */
if (have_config(config, CONFIG_NOCLID))
clid = NULL;
@@ -806,7 +847,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
pxe_misc(mess, end, uuid);
prune_vendor_opts(netid);
prune_vendor_opts(tagif_netid);
opt71.val = save71;
opt71.opt = SUBOPT_PXE_BOOT_ITEM;
opt71.len = 4;
@@ -816,7 +857,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, mess->xid);
return dhcp_packet_size(mess, netid, agent_id, real_end);
return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
}
if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
@@ -827,7 +868,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)) &&
(context->flags & CONTEXT_PROXY))
{
struct dhcp_boot *boot = find_boot(netid);
struct dhcp_boot *boot = find_boot(tagif_netid);
mess->yiaddr.s_addr = 0;
if (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
@@ -853,11 +894,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
pxe_misc(mess, end, uuid);
prune_vendor_opts(netid);
do_encap_opts(pxe_opts(pxearch, netid, context->local), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
prune_vendor_opts(tagif_netid);
do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", mess->xid);
return ignore ? 0 : dhcp_packet_size(mess, netid, agent_id, real_end);
return ignore ? 0 : dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
}
}
}
@@ -908,7 +949,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
return 0;
case DHCPRELEASE:
if (!(context = narrow_context(context, mess->ciaddr, netid)) ||
if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
return 0;
@@ -970,21 +1011,21 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (conf.s_addr)
mess->yiaddr = conf;
else if (lease &&
address_available(context, lease->addr, netid) &&
address_available(context, lease->addr, tagif_netid) &&
!config_find_by_address(daemon->dhcp_conf, lease->addr))
mess->yiaddr = lease->addr;
else if (opt && address_available(context, addr, netid) && !lease_find_by_addr(addr) &&
else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
!config_find_by_address(daemon->dhcp_conf, addr))
mess->yiaddr = addr;
else if (emac_len == 0)
message = _("no unique-id");
else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, netid, now))
else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
message = _("no address available");
}
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, message, mess->xid);
if (message || !(context = narrow_context(context, mess->yiaddr, netid)))
if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
return 0;
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, mess->xid);
@@ -993,6 +1034,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
context->netid.next = netid;
netid = &context->netid;
tagif_netid = run_tag_if(netid);
}
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
@@ -1007,9 +1049,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_T2, 4, (time*7)/8);
}
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
domain, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
return dhcp_packet_size(mess, netid, agent_id, real_end);
return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
case DHCPREQUEST:
if (ignore || have_config(config, CONFIG_DISABLE))
@@ -1063,12 +1105,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
return 0;
if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
{
message = _("wrong address");
/* avoid loops when client brain-dead */
lease_prune(lease, now);
lease = NULL;
}
message = _("wrong address");
}
}
else
@@ -1085,6 +1122,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
/* ensure we broadcast NAK */
unicast_dest = 0;
}
/* desynchronise renewals */
fuzz = rand16();
mess->yiaddr = mess->ciaddr;
@@ -1102,7 +1140,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (context->router.s_addr == config->addr.s_addr)
break;
if (!(context = narrow_context(context, mess->yiaddr, netid)))
if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
{
/* If a machine moves networks whilst it has a lease, we catch that here. */
message = _("wrong network");
@@ -1111,7 +1149,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
/* Check for renewal of a lease which is outside the allowed range. */
else if (!address_available(context, mess->yiaddr, netid) &&
else if (!address_available(context, mess->yiaddr, tagif_netid) &&
(!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
message = _("address not available");
@@ -1184,64 +1222,84 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
context->netid.next = netid;
netid = &context->netid;
tagif_netid = run_tag_if(netid);
}
#ifdef HAVE_SCRIPT
if (do_classes && daemon->lease_change_command)
{
struct dhcp_netid *n;
if (mess->giaddr.s_addr)
lease->giaddr = mess->giaddr;
lease->changed = 1;
free(lease->extradata);
lease->extradata_size = lease->extradata_len = 0;
add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
add_extradata_opt(lease, oui);
add_extradata_opt(lease, serial);
add_extradata_opt(lease, class);
/* space-concat tag set */
if (!netid)
add_extradata_opt(lease, NULL);
else
for (n = netid; n; n = n->next)
add_extradata_data(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
{
int len = option_len(opt);
unsigned char *ucp = option_ptr(opt, 0);
/* If the user-class option started as counted strings, the first byte will be zero. */
if (len != 0 && ucp[0] == 0)
ucp++, len--;
add_extradata_data(lease, ucp, len, 0);
}
}
if (do_classes && daemon->lease_change_command)
{
struct dhcp_netid *n;
if (mess->giaddr.s_addr)
lease->giaddr = mess->giaddr;
lease->changed = 1;
free(lease->extradata);
lease->extradata_size = lease->extradata_len = 0;
add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
add_extradata_opt(lease, oui);
add_extradata_opt(lease, serial);
add_extradata_opt(lease, class);
/* space-concat tag set */
if (!tagif_netid)
add_extradata_opt(lease, NULL);
else
for (n = tagif_netid; n; n = n->next)
add_extradata_data(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
{
int len = option_len(opt);
unsigned char *ucp = option_ptr(opt, 0);
/* If the user-class option started as counted strings, the first byte will be zero. */
if (len != 0 && ucp[0] == 0)
ucp++, len--;
add_extradata_data(lease, ucp, len, 0);
}
}
#endif
if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
{
if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
{
domain = get_domain(mess->yiaddr);
hostname = client_hostname;
hostname_auth = 1;
}
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len);
/* if all the netids in the ignore_name list are present, ignore client-supplied name */
if (!hostname_auth)
{
for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
if ((!id_list->list) || match_netid(id_list->list, netid, 0))
if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
break;
if (id_list)
hostname = NULL;
}
/* Last ditch, if configured, generate hostname from mac address */
if (!hostname && emac_len != 0)
{
for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
break;
if (id_list)
{
int i;
hostname = daemon->dhcp_buff;
/* buffer is 256 bytes, 3 bytes per octet */
for (i = 0; (i < emac_len) && (i < 80); i++)
hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
hostname = daemon->dhcp_buff;
}
}
if (hostname)
lease_set_hostname(lease, hostname, hostname_auth);
@@ -1267,10 +1325,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
}
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
domain, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
}
return dhcp_packet_size(mess, netid, agent_id, real_end);
return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
case DHCPINFORM:
if (ignore || have_config(config, CONFIG_DISABLE))
@@ -1282,7 +1340,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
return 0;
/* For DHCPINFORM only, cope without a valid context */
context = narrow_context(context, mess->ciaddr, netid);
context = narrow_context(context, mess->ciaddr, tagif_netid);
/* Find a least based on IP address if we didn't
get one from MAC address/client-d */
@@ -1291,8 +1349,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease->hostname)
hostname = lease->hostname;
if (!hostname)
hostname = host_from_dns(mess->ciaddr);
if (!hostname && (hostname = host_from_dns(mess->ciaddr)))
domain = get_domain(mess->ciaddr);
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, mess->xid);
@@ -1300,6 +1358,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
context->netid.next = netid;
netid = &context->netid;
tagif_netid = run_tag_if(netid);
}
if (lease)
@@ -1325,10 +1384,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
domain, netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid);
domain, tagif_netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len);
*is_inform = 1; /* handle reply differently */
return dhcp_packet_size(mess, netid, agent_id, real_end);
return dhcp_packet_size(mess, tagif_netid, agent_id, real_end);
}
return 0;
@@ -1722,23 +1781,28 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, struct dhcp_netid *neti
*p++ = OPTION_END;
for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
if ((!id_list->list) || match_netid(id_list->list, netid, 0))
break;
if (id_list)
mess->flags |= htons(0x8000); /* force broadcast */
if (daemon->options & OPT_LOG_OPTS)
{
if (mess->siaddr.s_addr != 0)
my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
log_options(&mess->options[0] + sizeof(u32), mess->xid);
}
for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
if (match_netid(id_list->list, netid, 0))
mess->flags |= htons(0x8000); /* force broadcast */
ret = (size_t)(p - (unsigned char *)mess);
if (ret < MIN_PACKETSZ)
ret = MIN_PACKETSZ;
return ret;
}
@@ -1877,10 +1941,16 @@ static struct dhcp_opt *option_find2(struct dhcp_netid *netid, struct dhcp_opt *
struct dhcp_opt *tmp;
for (tmp = opts; tmp; tmp = tmp->next)
if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
if (match_netid(tmp->netid, netid, netid ? 0 : 1))
if (match_netid(tmp->netid, netid, 0))
return tmp;
return netid ? option_find2(NULL, opts, opt) : NULL;
/* No match, look for one without a netid */
for (tmp = opts; tmp; tmp = tmp->next)
if (tmp->opt == opt && !(tmp->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)))
if (match_netid(tmp->netid, netid, 1))
return tmp;
return NULL;
}
/* mark vendor-encapsulated options which match the client-supplied or
@@ -1905,10 +1975,10 @@ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
}
}
static void do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
struct dhcp_packet *mess, unsigned char *end, int null_term)
static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
struct dhcp_packet *mess, unsigned char *end, int null_term)
{
int len, enc_len;
int len, enc_len, ret = 0;
struct dhcp_opt *start;
unsigned char *p;
@@ -1917,6 +1987,7 @@ static void do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
if (opt->flags & flag)
{
int new = do_opt(opt, NULL, NULL, null_term) + 2;
ret = 1;
if (enc_len + new <= 255)
enc_len += new;
else
@@ -1948,6 +2019,8 @@ static void do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
}
*p = OPTION_END;
}
return ret;
}
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
@@ -2009,7 +2082,7 @@ static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct
/* create the data for the PXE_MENU and PXE_SERVERS options. */
p = (unsigned char *)daemon->dhcp_buff;
q = (unsigned char *)daemon->dhcp_buff2;
q = (unsigned char *)daemon->dhcp_buff3;
for (i = 0, service = daemon->pxe_services; service; service = service->next)
if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
@@ -2037,7 +2110,7 @@ static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct
if (boot_server.s_addr != 0)
{
if (q - (unsigned char *)daemon->dhcp_buff2 + 3 + INADDRSZ >= 253)
if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
goto toobig;
/* Boot service with known address - give it */
@@ -2066,11 +2139,11 @@ static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct
ret->val = (unsigned char *)daemon->dhcp_buff;
ret->opt = SUBOPT_PXE_MENU;
if (q - (unsigned char *)daemon->dhcp_buff2 != 0)
if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
{
ret = &fake_opts[j--];
ret->len = q - (unsigned char *)daemon->dhcp_buff2;
ret->val = (unsigned char *)daemon->dhcp_buff2;
ret->len = q - (unsigned char *)daemon->dhcp_buff3;
ret->val = (unsigned char *)daemon->dhcp_buff3;
ret->opt = SUBOPT_PXE_SERVERS;
}
}
@@ -2130,7 +2203,8 @@ static void do_options(struct dhcp_context *context,
struct in_addr subnet_addr,
unsigned char fqdn_flags,
int null_term, int pxe_arch,
unsigned char *uuid)
unsigned char *uuid,
int vendor_class_len)
{
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
struct dhcp_boot *boot;
@@ -2138,6 +2212,7 @@ static void do_options(struct dhcp_context *context,
int i, len, force_encap = 0;
unsigned char f0 = 0, s0 = 0;
int done_file = 0, done_server = 0;
int done_vendor_class = 0;
if (config_domain && (!domain || !hostname_isequal(domain, config_domain)))
my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring domain %s for DHCP host name %s"), config_domain, hostname);
@@ -2203,7 +2278,7 @@ static void do_options(struct dhcp_context *context,
as an internal way to specify siaddr without using dhcp-boot, for use in
dhcp-optsfile. */
{
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) && mess->file[0] == 0 &&
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
(opt = option_find2(netid, config_opts, OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
{
strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
@@ -2373,7 +2448,10 @@ static void do_options(struct dhcp_context *context,
/* If we send a vendor-id, revisit which vendor-ops we consider
it appropriate to send. */
if (optno == OPTION_VENDOR_ID)
match_vendor_opts(p - 2, config_opts);
{
match_vendor_opts(p - 2, config_opts);
done_vendor_class = 1;
}
}
}
@@ -2442,20 +2520,22 @@ static void do_options(struct dhcp_context *context,
}
}
/* Must precede pxe_opts, since it overwrites req_options */
force_encap = prune_vendor_opts(netid);
if (in_list(req_options, OPTION_VENDOR_CLASS_OPT))
force_encap = 1;
if (context && pxe_arch != -1)
{
pxe_misc(mess, end, uuid);
config_opts = pxe_opts(pxe_arch, netid, context->local);
}
if (force_encap)
do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term);
if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) &&
pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
(p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
/* If we send vendor encapsulated options, and haven't already sent option 60,
echo back the value we got from the client. */
memcpy(p, daemon->dhcp_buff3, vendor_class_len);
/* restore BOOTP anti-overload hack */
if (!req_options || (daemon->options & OPT_NO_OVERRIDE))
{

View File

@@ -18,7 +18,7 @@
#ifdef HAVE_TFTP
static struct tftp_file *check_tftp_fileperm(ssize_t *len);
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special);
static void free_transfer(struct tftp_transfer *transfer);
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
static ssize_t tftp_err_oops(char *packet, char *file);
@@ -47,14 +47,21 @@ void tftp_request(struct listener *listen, time_t now)
struct msghdr msg;
struct iovec iov;
struct ifreq ifr;
int is_err = 1, if_index = 0, mtu = 0;
int is_err = 1, if_index = 0, mtu = 0, special = 0;
#ifdef HAVE_DHCP
struct iname *tmp;
#endif
struct tftp_transfer *transfer;
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
int mtuflag = IP_PMTUDISC_DONT;
#endif
char namebuff[IF_NAMESIZE];
char *name;
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct interface_list *ir;
union {
struct cmsghdr align; /* this ensures alignment */
#if defined(HAVE_LINUX_NETWORK)
@@ -87,54 +94,101 @@ void tftp_request(struct listener *listen, time_t now)
{
addr = listen->iface->addr.in;
mtu = listen->iface->mtu;
name = listen->iface->name;
}
else
{
char name[IF_NAMESIZE];
struct cmsghdr *cmptr;
int check;
struct interface_list *ir;
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;
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
addr.sin_addr = p.p->ipi_spec_dst;
if_index = p.p->ipi_ifindex;
}
#elif defined(HAVE_SOLARIS_NETWORK)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
addr.sin_addr = *((struct in_addr *)CMSG_DATA(cmptr));
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_index = *((unsigned int *)CMSG_DATA(cmptr));
{
union {
unsigned char *c;
struct in_addr *a;
unsigned int *i;
} p;
p.c = CMSG_DATA(cmptr);
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
addr.sin_addr = *(p.a);
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_index = *(p.i);
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
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;
{
union {
unsigned char *c;
struct in_addr *a;
struct sockaddr_dl *s;
} p;
p.c = CMSG_DATA(cmptr);
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
addr.sin_addr = *(p.a);
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
if_index = p.s->sdl_index;
}
#endif
if (!indextoname(listen->tftpfd, if_index, name) ||
addr.sin_addr.s_addr == 0 ||
!iface_check(AF_INET, (struct all_addr *)&addr.sin_addr, name, &if_index))
if (!indextoname(listen->tftpfd, if_index, namebuff) ||
addr.sin_addr.s_addr == 0)
return;
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
return;
name = namebuff;
check = iface_check(AF_INET, (struct all_addr *)&addr.sin_addr, name, &if_index);
/* wierd TFTP service override */
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, name) == 0)
break;
if (!ir)
{
if (!daemon->tftp_unlimited || !check)
return;
#ifdef HAVE_DHCP
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
return;
#endif
}
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
}
/* check for per-interface prefix */
for (pref = daemon->if_prefix; pref; pref = pref->next)
if (strcmp(pref->interface, name) == 0)
prefix = pref->prefix;
/* wierd TFTP interfaces disable special options. */
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, name) == 0)
special = 1;
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -202,7 +256,7 @@ void tftp_request(struct listener *listen, time_t now)
if (strcasecmp(opt, "blksize") == 0)
{
if ((opt = next(&p, end)) &&
!(daemon->options & OPT_TFTP_NOBLOCK))
(special || !(daemon->options & OPT_TFTP_NOBLOCK)))
{
transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1)
@@ -228,15 +282,15 @@ void tftp_request(struct listener *listen, time_t now)
*p = '/';
strcpy(daemon->namebuff, "/");
if (daemon->tftp_prefix)
if (prefix)
{
if (daemon->tftp_prefix[0] == '/')
if (prefix[0] == '/')
daemon->namebuff[0] = 0;
strncat(daemon->namebuff, daemon->tftp_prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/')
strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
if (prefix[strlen(prefix)-1] != '/')
strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
if (daemon->options & OPT_TFTP_APREF)
if (!special && (daemon->options & OPT_TFTP_APREF))
{
size_t oldlen = strlen(daemon->namebuff);
struct stat statbuf;
@@ -263,7 +317,7 @@ void tftp_request(struct listener *listen, time_t now)
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
/* check permissions and open file */
if ((transfer->file = check_tftp_fileperm(&len)))
if ((transfer->file = check_tftp_fileperm(&len, prefix, special)))
{
if ((len = get_block(packet, transfer)) == -1)
len = tftp_err_oops(packet, daemon->namebuff);
@@ -285,7 +339,7 @@ void tftp_request(struct listener *listen, time_t now)
}
}
static struct tftp_file *check_tftp_fileperm(ssize_t *len)
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special)
{
char *packet = daemon->packet, *namebuff = daemon->namebuff;
struct tftp_file *file;
@@ -295,7 +349,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len)
int fd = -1;
/* trick to ban moving out of the subtree */
if (daemon->tftp_prefix && strstr(namebuff, "/../"))
if (prefix && strstr(namebuff, "/../"))
goto perm;
if ((fd = open(namebuff, O_RDONLY)) == -1)
@@ -322,7 +376,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len)
goto perm;
}
/* in secure mode, must be owned by user running dnsmasq */
else if ((daemon->options & OPT_TFTP_SECURE) && uid != statbuf.st_uid)
else if (!special && (daemon->options & OPT_TFTP_SECURE) && uid != statbuf.st_uid)
goto perm;
/* If we're doing many tranfers from the same file, only