Compare commits

..
36 Commits
Author SHA1 Message Date
Simon Kelley d1c759c5c1 Answer CNAME queries correctly. 2012-04-16 17:26:19 +01:00
Simon Kelley e46164e0bd Updated French translation. 2012-04-16 16:39:38 +01:00
Simon Kelley 7389ce7ff5 substitue non-portable tail command with sed. 2012-04-16 15:07:48 +01:00
Simon Kelley 2f77797b17 Add port option to example dnsmasq.conf 2012-04-16 14:58:53 +01:00
Simon Kelley 9380ba70d6 Set SO_BINDTODEVICE on DHCP sockets when doing DHCP on one interface
only. Fixes OpenSTack use-case.
2012-04-16 14:41:56 +01:00
Simon Kelley 1023dcbc9e Don't cache DNS data from non-recursive nameservers. 2012-04-09 18:00:08 +01:00
Simon Kelley 83e854e359 Typo. 2012-04-05 13:21:58 +01:00
Simon Kelley 50303b19d8 Remove redundant send_from logging code. 2012-04-04 22:13:17 +01:00
Simon Kelley 89382bacaa Tweak sending ICMP6 echo requests for slaac. 2012-04-04 20:48:16 +01:00
Simon Kelley 6c559c34df tweak favicon 2012-04-02 20:40:34 +01:00
Simon Kelley adaa6888dd Move FIXME message to comment - having it emitted by the code is just confusing. 2012-04-02 10:02:12 +01:00
Simon Kelley a813111379 Fix bug in tag-matching logic with negated tags. 2012-03-31 21:35:12 +01:00
Simon Kelley 18f0fb050b RDNSS and DNSSL data in router advertisements. 2012-03-31 21:18:55 +01:00
Simon Kelley 05e92e5afe More RA flag evolution. 2012-03-30 22:24:15 +01:00
Simon Kelley 4723d49dad Set managed RA flag always when doing DHCP. 2012-03-30 21:04:17 +01:00
Simon Kelley fbbc14541a Fix off-by-one in DHCPv6 FQDN option decoding. 2012-03-30 20:48:20 +01:00
Simon Kelley 5ef33279f2 Tidying radv 2012-03-30 15:10:28 +01:00
Simon Kelley 1e02a85970 radv.c tidying. 2012-03-29 11:07:25 +01:00
Simon Kelley 0e88d53faa Fix preprocessor checks, IP_TOS -> IPV6_TCLASS 2012-03-28 22:22:05 +01:00
Simon Kelley 01d1b8ddf2 Changelog update. 2012-03-28 21:37:25 +01:00
Simon Kelley c8257540bc "deprecated" lease-time keyword for IPv6 2012-03-28 21:15:41 +01:00
Simon Kelley 2240704863 DHCP start-up logging tweak 2012-03-27 14:42:48 +01:00
Simon Kelley e8ca69ea16 Doc updates for latest RA changes. 2012-03-26 21:23:26 +01:00
Simon Kelley da632e7cc1 Comment typo. 2012-03-26 11:14:05 +01:00
Simon Kelley 30cd96663f More flexible RA configuration. 2012-03-25 20:44:38 +01:00
Simon Kelley 7dbe98147d tweak ra timer code to avoid missing events. 2012-03-25 14:49:54 +01:00
Simon Kelley 5d71d83420 Listen on ICMP6 file decriptor even when on ra-only only in use. 2012-03-24 14:40:42 +00:00
Simon Kelley 38a59a9ff7 debian changelog untangle. 2012-03-23 10:08:12 +00:00
Simon Kelley 4b028ad612 Merge branch 'bind' 2012-03-23 10:02:30 +00:00
Simon Kelley 442560beb4 Debian changelog for preivious fix. 2012-03-23 10:01:13 +00:00
Simon Kelley 7d2b5c9583 Fix crash in DHCPINFORM without valid --dhcp-range. 2012-03-23 10:00:02 +00:00
Simon Kelley 29689cfa5a Handle errors when sending ICMP6 pings better. 2012-03-22 14:01:00 +00:00
Simon Kelley 52d4abf2f9 Make --listen-address work for all 127.0.0.0/8 addresses. 2012-03-21 21:39:48 +00:00
Simon Kelley a953096485 Send "FTP transfer complete" events to the DHCP lease script. 2012-03-20 22:07:35 +00:00
Simon Kelley 884a6dfe6d RA managed-bit and use-SLAAC bit tweaks. 2012-03-20 16:20:22 +00:00
Simon Kelley 0068301d24 Conditional compilation tweak. 2012-03-19 20:29:55 +00:00
27 changed files with 1126 additions and 513 deletions

No files matched your search

+71 -2
View File
@@ -4,8 +4,12 @@ version 2.61
and allows us to find the prefix length for IPv6 and allows us to find the prefix length for IPv6
addresses. addresses.
Add ra-names DHCPv6 keyword which adds AAAA records Add ra-names, ra-stateless and slaac keywords for DHCPv6.
for dual-stack hosts which get IPv6 addresses via SLAAC. Dnsmasq can now synthesise AAAA records for dual-stack
hosts which get IPv6 addresses via SLAAC. It is also now
possible to use SLAAC and stateless DHCPv6, and to
tell clients to use SLAAC addresses as well as DHCP ones.
Thanks to Dave Taht for help with this.
Add --dhcp-duid to allow DUID-EN uids to be used. Add --dhcp-duid to allow DUID-EN uids to be used.
@@ -24,6 +28,71 @@ version 2.61
Add --host-record. Thanks to Rob Zwissler for the Add --host-record. Thanks to Rob Zwissler for the
suggestion. suggestion.
Invoke the DHCP script with action "tftp" when a TFTP file
transfer completes. The size of the file, address to which
it was sent and complete pathname are supplied. Note that
version 2.60 introduced some script incompatibilties
associated with DHCPv6, and this is a further change. To
be safe, scripts should ignore unknown actions, and if
not IPv6-aware, should exit if the environment
variable DNSMASQ_IAID is set. The use-case for this is
to track netboot/install. Suggestion from Shantanu
Gadgil.
Update contrib/port-forward/dnsmasq-portforward to reflect
the above.
Set the environment variable DNSMASQ_LOG_DHCP when running
the script id --log-dhcp is in effect, so that script can
taylor their logging verbosity. Suggestion from Malte
Forkel.
Arrange that addresses specified with --listen-address
work even if there is no interface carrying the
address. This is chiefly useful for IPv4 loopback
addresses, where any address in 127.0.0.0/8 is a valid
loopback address, but normally only 127.0.0.1 appears on
the lo interface. Thanks to Mathieu Trudel-Lapierre for
the idea and initial patch.
Fix crash, introduced in 2.60, when a DHCPINFORM is
received from a network which has no valid dhcp-range.
Thanks to Stephane Glondu for the bug report.
Add a new DHCP lease time keyword, "deprecated" for
--dhcp-range. This is only valid for IPv6, and sets the
preffered lease time for both DHCP and RA to zero. The
effect is that clients can continue to use the address
for existing connections, but new connections will use
other addresses, if they exist. This makes hitless
renumbering at least possible.
Fix bug in address6_available() which caused DHCPv6 lease
aquistion to fail if more than one dhcp-range in use.
Provide RDNSS and DNSSL data in router advertisements,
using the settings provided for DHCP options
option6:domain-search and option6:dns-server.
Tweak logo/favicon.ico to add some transparency. Thanks to
SamLT for work on this.
Don't cache data from non-recursive nameservers, since it
may erroneously look like a valid CNAME to a non-exitant
name. Thanks to Ben Winslow for finding this.
Call SO_BINDTODEVICE on the DHCP socket(s) when doing DHCP
on exacly one interface and --bind-interfaces is set. This
makes the OpenStack use-case of one dnsmasq per virtual
interface work. This is only available on Linux; it's not
supported on other platforms. Thanks to Vishvananda Ishaya
and the OpenStack team for the suggestion.
Updated French translation. Thanks to Gildas Le Nadan.
Give correct from-cache answers to explict CNAME queries.
Thanks to Rob Zwissler for spotting this.
version 2.60 version 2.60
Fix compilation problem in Mac OS X Lion. Thanks to Olaf Fix compilation problem in Mac OS X Lion. Thanks to Olaf
+1 -1
View File
@@ -18,7 +18,7 @@ else
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep $v[0-9]` vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep $v[0-9]`
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "${vers}" | head -n 1 | tail -c +2 echo "${vers}" | head -n 1 | sed 's/^v//'
else else
cat $1/VERSION cat $1/VERSION
fi fi
+10
View File
@@ -34,11 +34,21 @@ if [ ${DNSMASQ_OLD_HOSTNAME} ] && [ ${action} = old ] ; then
hostname=${DNSMASQ_OLD_HOSTNAME} hostname=${DNSMASQ_OLD_HOSTNAME}
fi fi
# IPv6 leases are not our concern. no NAT there!
if [ ${DNSMASQ_IAID} ] ; then
exit 0
fi
# action init is not relevant, and will only be seen when leasefile-ro is set. # action init is not relevant, and will only be seen when leasefile-ro is set.
if [ ${action} = init ] ; then if [ ${action} = init ] ; then
exit 0 exit 0
fi fi
# action tftp is not relevant.
if [ ${action} = tftp ] ; then
exit 0
fi
if [ ${hostname} ]; then if [ ${hostname} ]; then
ports=$(sed -n -e "/^${hostname}\ .*/ s/^.* //p" ${PORTSFILE}) ports=$(sed -n -e "/^${hostname}\ .*/ s/^.* //p" ${PORTSFILE})
+7
View File
@@ -4,9 +4,16 @@ dnsmasq (2.61-1) unstable; urgency=low
* Provide "dump-stats" initscript method. (closes: #654656) * Provide "dump-stats" initscript method. (closes: #654656)
* Add (empty) build-indep and build-arch rules targets. * Add (empty) build-indep and build-arch rules targets.
* Bump standards-version to 3.9.3 * Bump standards-version to 3.9.3
* Add port option to example dnsmasq.conf (closes: #668386)
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 6 Mar 2012 19:45:43 +0000 -- Simon Kelley <simon@thekelleys.org.uk> Tue, 6 Mar 2012 19:45:43 +0000
dnsmasq (2.60-2) unstable; urgency=high
* Fix DHCPv4 segfault. (closes: #665008)
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 23 Mar 2012 09:37:23 +0000
dnsmasq (2.60-1) unstable; urgency=low dnsmasq (2.60-1) unstable; urgency=low
* New upstream. * New upstream.
+25 -2
View File
@@ -4,6 +4,11 @@
# as the long options legal on the command line. See # as the long options legal on the command line. See
# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details. # "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details.
# Listen on this specific port instead of the standard DNS port
# (53). Setting this to zero completely disables DNS function,
# leaving only DHCP and/or TFTP.
#port=5353
# The following two options make you a better netizen, since they # The following two options make you a better netizen, since they
# tell dnsmasq to filter out queries which the public DNS cannot # tell dnsmasq to filter out queries which the public DNS cannot
# answer, and which load the servers (especially the root servers) # answer, and which load the servers (especially the root servers)
@@ -169,14 +174,32 @@
# hosts. Use the DHCPv4 lease to derive the name, network segment and # hosts. Use the DHCPv4 lease to derive the name, network segment and
# MAC address and assume that the host will also have an # MAC address and assume that the host will also have an
# IPv6 address calculated using the SLAAC alogrithm. # IPv6 address calculated using the SLAAC alogrithm.
# This will generate an erroneous AAAA record if a host is using privacy
# extensions or does not support IPv6. Use with care.
#dhcp-range=1234::, ra-names #dhcp-range=1234::, ra-names
# Do Router Advertisements, BUT NOT DHCP for this subnet. # Do Router Advertisements, BUT NOT DHCP for this subnet.
# Set the lifetime to 46 hours. (Note: minimum lifetime is 2 hours.) # Set the lifetime to 46 hours. (Note: minimum lifetime is 2 hours.)
#dhcp-range=1234::, ra-only, 48h #dhcp-range=1234::, ra-only, 48h
# Do DHCP and Router Advertisements for this subnet. Set the A bit in the RA
# so that clients can use SLAAC addresses as well as DHCP ones.
#dhcp-range=1234::2, 1234::500, slaac
# Do Router Advertisements and stateless DHCP for this subnet. Clients will
# not get addresses from DHCP, but they will get other configuration information.
# They will use SLAAC for addresses.
#dhcp-range=1234::, ra-stateless
# Do stateless DHCP, SLAAC, and generate DNS names for SLAAC addresses
# from DHCPv4 leases.
#dhcp-range=1234::, ra-stateless, ra-names
# Do router advertisements for all subnets where we're doing DHCPv6
# Unless overriden by ra-stateless, ra-names, et al, the router
# advertisements will have the M and O bits set, so that the clients
# get addresses and configuration from DHCPv6, and the A bit reset, so the
# clients don't use SLAAC addresses.
#enable-ra
# Supply parameters for specified hosts using DHCP. There are lots # Supply parameters for specified hosts using DHCP. There are lots
# of valid alternatives, so we will give examples of each. Note that # 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 # IP addresses DO NOT have to be in the range given above, they just
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

+87 -38
View File
@@ -23,7 +23,7 @@ options. It includes a secure, read-only,
TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP. TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP.
.PP .PP
Dnsmasq Dnsmasq
supports IPv6 for all functions and a minimal router-advertisemnet daemon. supports IPv6 for all functions and a minimal router-advertisement daemon.
.SH OPTIONS .SH OPTIONS
Note that in general missing parameters are allowed and switch off Note that in general missing parameters are allowed and switch off
functions, for instance "--pid-file" disables writing a PID file. On functions, for instance "--pid-file" disables writing a PID file. On
@@ -416,7 +416,7 @@ zone files: the port, weight and priority numbers are in a different
order. More than one SRV record for a given service/domain is allowed, order. More than one SRV record for a given service/domain is allowed,
all that match are returned. all that match are returned.
.TP .TP
.B --host-record=<name>[,<name>....][<IPv4-address>],[IPv6-address] .B --host-record=<name>[,<name>....][<IPv4-address>],[<IPv6-address>]
Add A, AAAA and PTR records to the DNS. This adds one or more names to Add A, AAAA and PTR records to the DNS. This adds one or more names to
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
appear in more than one appear in more than one
@@ -427,10 +427,12 @@ the same rule as is used reading hosts-files.
.B host-record .B host-record
options are considered to be read before host-files, so a name options are considered to be read before host-files, so a name
appearing there inhibits PTR-record creation if it appears in appearing there inhibits PTR-record creation if it appears in
hosts-file also. Unlike host-files, names are not expanded, even when hosts-file also. Unlike hosts-files, names are not expanded, even when
.B expand-hosts .B expand-hosts
is in effect. Short and long names may appear in the same is in effect. Short and long names may appear in the same
.B host-record, eg. --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100 .B host-record,
eg.
.B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
.TP .TP
.B \-Y, --txt-record=<name>[[,<text>],<text>] .B \-Y, --txt-record=<name>[[,<text>],<text>]
Return a TXT DNS record. The value of TXT record is a set of strings, Return a TXT DNS record. The value of TXT record is a set of strings,
@@ -510,9 +512,9 @@ compiled in and the kernel must have conntrack support
included and configured. This option cannot be combined with included and configured. This option cannot be combined with
--query-port. --query-port.
.TP .TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>,<end-addr>[,<netmask>[,<broadcast>]][,<lease time>] .B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
.TP .TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-IPv6addr>,<end-IPv6addr>[,<prefix-len>][,<lease time>] .B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-IPv6addr>[,<end-IPv6addr>][,<mode>][,<prefix-len>][,<lease time>]
Enable the DHCP server. Addresses will be given out from the range Enable the DHCP server. Addresses will be given out from the range
<start-addr> to <end-addr> and from statically defined addresses given <start-addr> to <end-addr> and from statically defined addresses given
@@ -522,8 +524,12 @@ options. If the lease time is given, then leases
will be given for that length of time. The lease time is in seconds, will be given for that length of time. The lease time is in seconds,
or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given, or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given,
the default lease time is one hour. The the default lease time is one hour. The
minimum lease time is two minutes. This minimum lease time is two minutes. For IPv6 ranges, the lease time
option may be repeated, with different addresses, to enable DHCP maybe "deprecated"; this sets the preferred lifetime sent in a DHCP
lease or router advertisement to zero, which causes clients to use
other addresses, if available, for new connections as a prelude to renumbering.
This option may be repeated, with different addresses, to enable DHCP
service to more than one network. For directly connected networks (ie, service to more than one network. For directly connected networks (ie,
networks on which the machine running dnsmasq has an interface) the networks on which the machine running dnsmasq has an interface) the
netmask is optional: dnsmasq will determine it from the interface netmask is optional: dnsmasq will determine it from the interface
@@ -548,7 +554,7 @@ 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 a tag to matching it. Only one tag may be set, but more than one tag
may be matched. may be matched.
The end address may be replaced by the keyword The optional <mode> keyword may be
.B static .B static
which tells dnsmasq to enable DHCP for the network specified, but not which tells dnsmasq to enable DHCP for the network specified, but not
to dynamically allocate IP addresses: only hosts which have static to dynamically allocate IP addresses: only hosts which have static
@@ -556,34 +562,50 @@ addresses given via
.B dhcp-host .B dhcp-host
or from /etc/ethers will be served. or from /etc/ethers will be served.
The end address may be replaced by For IPv4, the <mode> may be
the keyword
.B proxy .B proxy
in which case dnsmasq will provide proxy-DHCP on the specified in which case dnsmasq will provide proxy-DHCP on the specified
subnet. (See subnet. (See
.B pxe-prompt .B pxe-prompt
and and
.B pxe-service .B pxe-service
for details, applies to IPv4 only.) for details.)
For IPv6, the mode may be some combination of
.B ra-only, slaac, ra-names, ra-stateless.
The end address may be replaced by
the keyword
.B ra-only .B ra-only
which tells dnsmasq to offer Router Advertisement only on this subnet, tells dnsmasq to offer Router Advertisement only on this subnet,
and not DHCP. This applies to IPv6 only, see and not DHCP.
.B enable-ra
for details. Instead, the keyword .B slaac
tells dnsmasq to offer Router Advertisement on this subnet and to set
the A bit in the router advertisement, so that the client will use
SLAAC addresses. When used with a DHCP range or static DHCP address
this results in the client having both a DHCP-assigned and a SLAAC
address.
.B ra-stateless
sends router advertisements with the O and A bits set, and provides a
stateless DHCP service. The client will use a SLAAC address, and use
DHCP for other configuration information.
.B ra-names .B ra-names
may be used. This does the same at ra-only, but also enables a mode enables a mode
which gives DNS names to dual-stack hosts which do SLAAC for which gives DNS names to dual-stack hosts which do SLAAC for
IPv6. Dnsmasq uses the hosts IPv4 lease to derive the name, network IPv6. Dnsmasq uses the host's IPv4 lease to derive the name, network
segment and MAC address and assumes that the host will also have an segment and MAC address and assumes that the host will also have an
IPv6 address calculated using the SLAAC alogrithm, on the same network IPv6 address calculated using the SLAAC algorithm, on the same network
segment. An AAAA record is added to the DNS for this IPv6 segment. The address is pinged, and if a reply is received, an AAAA
record is added to the DNS for this IPv6
address. Note that this is only happens for directly-connected address. Note that this is only happens for directly-connected
networks, (not one doing DHCP via a relay) and it will generate an networks, (not one doing DHCP via a relay) and it will not work
erroneous AAAA record if a host is using privacy extensions or does if a host is using privacy extensions.
not support IPv6. Use with care. .B ra-names
can be combined with
.B ra-stateless
and
.B slaac.
The interface:<interface name> section is not normally used. See the The interface:<interface name> section is not normally used. See the
NOTES section for details of this. NOTES section for details of this.
@@ -1069,7 +1091,8 @@ re-intialised. The enterprise-id is assigned by IANA, and the uid is a
string of hex octets unique to a particular device. string of hex octets unique to a particular device.
.TP .TP
.B \-6 --dhcp-script=<path> .B \-6 --dhcp-script=<path>
Whenever a new DHCP lease is created, or an old one destroyed, the Whenever a new DHCP lease is created, or an old one destroyed, or a
TFTP file transfer completes, the
executable specified by this option is run. <path> executable specified by this option is run. <path>
must be an absolute pathname, no PATH search occurs. must be an absolute pathname, no PATH search occurs.
The arguments to the process The arguments to the process
@@ -1119,6 +1142,10 @@ is known.
DNSMASQ_TAGS contains all the tags set during the DNSMASQ_TAGS contains all the tags set during the
DHCP transaction, separated by spaces. DHCP transaction, separated by spaces.
DNSMASQ_LOG_DHCP is set if
.B --log-dhcp
is in effect.
For IPv4 only: For IPv4 only:
DNSMASQ_CLIENT_ID if the host provided a client-id. DNSMASQ_CLIENT_ID if the host provided a client-id.
@@ -1145,6 +1172,8 @@ only supplied for
since these data are not held in dnsmasq's lease since these data are not held in dnsmasq's lease
database. database.
All file descriptors are All file descriptors are
closed except stdin, stdout and stderr which are open to /dev/null closed except stdin, stdout and stderr which are open to /dev/null
(except in debug mode). (except in debug mode).
@@ -1163,6 +1192,17 @@ all existing leases as they are read from the lease file. Expired
leases will be called with "del" and others with "old". 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 receives a HUP signal, the script will be invoked for existing leases
with an "old " event. with an "old " event.
There are two further actions which may appear as the first argument
to the script, "init" and "tftp". More may be added in the future, so
scripts should be written to ignore unknown actions. "init" is
described below in
.B --leasefile-ro
The "tftp" action is invoked when a TFTP file transfer completes: the
arguments are the file size in bytes, the address to which the file
was sent, and the complete pathname of the file.
.TP .TP
.B --dhcp-luascript=<path> .B --dhcp-luascript=<path>
Specify a script written in Lua, to be run when leases are created, Specify a script written in Lua, to be run when leases are created,
@@ -1176,11 +1216,13 @@ function, and may provide
and and
.B shutdown .B shutdown
functions, which are called, without arguments when dnsmasq starts up functions, which are called, without arguments when dnsmasq starts up
and terminates. and terminates. It may also provide a
.B tftp
function.
The The
.B lease .B lease
method receives the information detailed in function receives the information detailed in
.B --dhcp-script. .B --dhcp-script.
It gets two arguments, firstly the action, which is a string It gets two arguments, firstly the action, which is a string
containing, "add", "old" or "del", and secondly a table of tag value containing, "add", "old" or "del", and secondly a table of tag value
@@ -1198,6 +1240,15 @@ for IPv4, and
and and
.B hostname .B hostname
for IPv6. for IPv6.
The
.B tftp
function is called in the same way as the lease function, and the
table holds the tags
.B destination_address,
.B file_name
and
.B file_size.
.TP .TP
.B --dhcp-scriptuser .B --dhcp-scriptuser
Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag. Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag.
@@ -1292,16 +1343,14 @@ only a subset of this is needed, and dnsmasq can handle it, using
existing DHCP configuration to provide most data. When RA is enabled, existing DHCP configuration to provide most data. When RA is enabled,
dnsmasq will advertise a prefix for each dhcp-range, with default dnsmasq will advertise a prefix for each dhcp-range, with default
router and recursive DNS server as the relevant link-local address on router and recursive DNS server as the relevant link-local address on
the machine running dnsmasq. The "managed address" bits are set, the machine running dnsmasq. By default, he "managed address" bits are set, and
except for a dhcp-range which is marked as "ra-only", in which case RA the "use SLAAC" bit is reset. This can be changed for individual
is provided but no DHCPv6 service and the managed address bits are subnets with the mode keywords described in
cleared. .B --dhcp-range.
.B enable-ra RFC6106 DNS parameters are included in the advertisements. By default,
enables router advertisement for prefixes where dnsmasq is doing the relevant link-local address of the machine running dnsmasq is sent
DHCPv6. It is not needed to "ra-only" prefixes. Creating an "ra-only" as recursive DNS server. If provided, the DHCPv6 options dns-server and
prefix and not setting domain-search are used for RDNSS and DNSSL.
.B enable-ra
sends advertisements only to "ra-only" prefixes.
.TP .TP
.B --enable-tftp[=<interface>] .B --enable-tftp[=<interface>]
Enable the TFTP server function. This is deliberately limited to that Enable the TFTP server function. This is deliberately limited to that
+121 -20
View File
@@ -22,7 +22,8 @@ peut être configuré pour envoyer n'importe quel option DHCP.
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP. le réseau/PXE de clients DHCP et supporte également le protocole BOOTP.
.PP .PP
Dnsmasq supporte IPv6 pour le DNS et TFTP mais pas pour le DHCP. Dnsmasq supporte IPv6 et contient un démon minimaliste capable de faire des
annonces routeurs ("router-advertisements").
.SH OPTIONS .SH OPTIONS
Notes : Il est possible d'utiliser des options sans leur donner de paramètre. Notes : Il est possible d'utiliser des options sans leur donner de paramètre.
Dans ce cas, la fonction correspondante sera désactivée. Par exemple Dans ce cas, la fonction correspondante sera désactivée. Par exemple
@@ -492,6 +493,27 @@ dans un ordre différents. Pour un service/domaine donné, plus d'un
enregistrement SRV est autorisé et tous les enregistrements qui coïncident sont enregistrement SRV est autorisé et tous les enregistrements qui coïncident sont
retournés dans la réponse. retournés dans la réponse.
.TP .TP
.B --host-record=<nom>[,<nom>....][<adresse IPv4>],[<adresse IPv6>]
Ajoute des enregistrements A, AAAA et PTR dans le DNS. Ceci permet d'ajouter
un ou plusieurs noms dans le DNS et de les associer à des enregistrements IPv4
(A) ou IPv6 (AAAA). Un nom peut apparaître dans plus d'une entrée
.B host-record
et de fait être associé à plus d'une adresse. Seule la première entrée créée
l'enregistrement PTR associée au nom. Ceci correspond à la même règle que celle
utilisée lors de la lecture du fichier hosts.
Les options
.B host-record
sont considérées lues avant le fichier hosts, ainsi un nom apparaissant dans
une option host-record et dans le fichier hosts n'aura pas d'enregistrement
PTR associé à l'entrée dans le fichier hosts. A l'inverse du fichier hosts, les
noms ne sont pas étendus, même lorsque l'option
.B expand-hosts
est activée. Les noms longs et les noms courts peuvent apparaitre dans la même
entrée
.B host-record,
c-à-d
.B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
.TP
.B \-Y, --txt-record=<nom>[[,<texte>],<texte>] .B \-Y, --txt-record=<nom>[[,<texte>],<texte>]
Définit un enregistrement DNS de type TXT. La valeur de l'enregistrement TXT est Définit un enregistrement DNS de type TXT. La valeur de l'enregistrement TXT est
un ensemble de chaînes de caractères, donc un nombre variable de chaînes de un ensemble de chaînes de caractères, donc un nombre variable de chaînes de
@@ -579,9 +601,9 @@ avec le support conntrack, le noyau doit également inclure conntrack et être
configuré pour cela. Cette option ne peut pas être combinée avec configuré pour cela. Cette option ne peut pas être combinée avec
--query-port. --query-port.
.TP .TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>,<adresse de fin>[,<masque de réseau>[,<broadcast>]][,<durée de bail>] .B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>[,<adresse de fin>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
.TP .TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>,<adresse IPv6 de fin>[,<longueur de préfixe>][,<durée de bail>] .B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>[,<adresse IPv6 de fin>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre 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 <adresse de début> et <adresse de fin> et à partir des adresses définies
statiquement dans l'option statiquement dans l'option
@@ -592,6 +614,13 @@ en heures (exemple : 1h) ou être la chaine de caractère "infinite" pour une
durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par défaut durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par défaut
de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2 de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2
minutes. minutes.
Pour les plages IPv6, la durée de bail peut-être égale au mot-clef "deprecated"
(obsolète); Cela positionne la durée de vie préférée envoyée dans les baux DHCP
ou les annonces routeurs à zéro, ce qui incite les clients à utiliser d'autres
adresses autant que possible, pour toute nouvelle connexion, en préalable à
la renumérotation.
Cette option peut être répétée, avec différentes adresses, Cette option peut être répétée, avec différentes adresses,
pour activer le service DHCP sur plus d'un réseau. Pour des réseaux directement pour activer le service DHCP sur plus d'un réseau. Pour des réseaux directement
connectés (c'est-à-dire des réseaux dans lesquels la machine sur laquelle tourne connectés (c'est-à-dire des réseaux dans lesquels la machine sur laquelle tourne
@@ -622,30 +651,59 @@ 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- 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. être défini mais plusieurs labels peuvent coïncider.
L'adresse de fin peut être remplacée par le mot-clef Le mot clef optionnel <mode> peut être égal à
.B static .B static
("statique") qui indique à Dnsmasq d'activer le service DHCP pour le réseau ("statique") ce qui indique à Dnsmasq d'activer le service DHCP pour le réseau
spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP : Seuls spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP : Seuls
les hôtes possédant des adresses IP statiques fournies via les hôtes possédant des adresses IP statiques fournies via
.B dhcp-host .B dhcp-host
ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP. ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP.
L'adresse de fin peut-être remplacée par le mot-clef Pour IPv4, le <mode> peut est égal à
.B proxy .B proxy
, auquel cas Dnsmasq fournira un service de DHCP proxy pour le sous-réseau , auquel cas Dnsmasq fournira un service de DHCP proxy pour le sous-réseau
spécifié. (voir spécifié. (voir
.B pxe-prompt .B pxe-prompt
et et
.B pxe-service .B pxe-service
pour plus de détails, s'applique à IPv4 seulement). pour plus de détails).
Pour IPv6, le mode peut-être une combinaison des valeurs
.B ra-only, slaac, ra-names, ra-stateless.
L'adresse de fin peut être remplacée par le mot-clef
.B ra-only .B ra-only
qui indique à dnsmasq de n'effectuer que des annonces de routeur (Router indique à dnsmasq de n'effectuer que des annonces de routeur (Router
Advertisement, RA) sur ce sous-réseau, et de ne pas faire de DHCP. Ceci Advertisement, RA) sur ce sous-réseau, et de ne pas faire de DHCP.
s'applique uniquement à IPv6, voir
.B enable-ra .B slaac
pour plus de détails. indique à dnsmasq d'effectuer des annonces de routeur sur ce sous-réseau
et de positionner dans celles-ci le bit A, afin que les clients utilisent
des adresses SLAAC. Lorsqu'utilisé conjointement avec une plage DHCP ou des
affectations statiques d'adresses DHCP, les clients disposeront à la fois
d'adresses DHCP assignées et d'adresses SLAAC.
.B ra-stateless
indique à dnsmasq d'effectuer des annonces de routeur avec les bits 0 et A
positionnés, et de fournir un service DHCP sans état ("stateless"). Les clients
utiliseront des adresses SLAAC, et utiliseront DHCP pour toutes les autres
informations de configuration.
.B ra-names
active un mode qui fourni des noms DNS aux hôtes fonctionnant en double pile
("dual stack") et configurés pour faire du SLAAC en IPv6. Dnsmasq utilise le
bail IPv4 de l'hôte afin de dériver le nom, le segment de réseau et l'adresse
MAC et assume que l'hôte disposera d'une adresse IPv6 calculée via l'algorithme
SLAAC, sur le même segment de réseau. Un ping est envoyé à l'adresse, et si une
réponse est obtenue, un enregistrement AAAA est rajouté dans le DNS pour cette
adresse IPv6. Veuillez-noter que cela n'arrive que pour les réseaux directement
connectés (et non ceux pour lesquels DHCP se fait via relai), et ne
fonctionnera pas si un hôte utilise les "extensions de vie privée"
("privacy extensions").
.B ra-names
peut-être combiné avec
.B ra-stateless
et
.B slaac.
La section interface:<nom d'interface> n'est normalement pas utilisée. Se 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. référer aux indications de la section NOTES pour plus de détail à ce sujet.
@@ -1171,8 +1229,20 @@ détermination de celles-ci.
Utilise le fichier dont le chemin est fourni pour stocker les informations de Utilise le fichier dont le chemin est fourni pour stocker les informations de
baux DHCP. baux DHCP.
.TP .TP
.B --dhcp-duid=<ID d'entreprise>,<uid>
(IPv6 seulement) Spécifie le numéro d'UID de serveur persistant que le serveur
DHCPv6 doit utiliser. Cette option n'est normalement pas requise, Dnsmasq
créant un DUID automatiquement lorsque cela est nécessaire. Lorsque cette
option est positionnée, elle fournit à Dnsmasq les données nécessaires à la
création d'un DUID de type DUID-EN. Veuillez noter qu'une fois créé, le DUID
est stocké dans la base des baux, aussi changer entre un DUID créé
automatiquement et un DUID-EN et vice-versa impose de réinitialiser la base de
baux. Le numéro d'ID d'entreprise est assigné par l'IANA, et l'uid est une
chaine hexadécimale unique à chaque serveur.
.TP
.B \-6 --dhcp-script=<chemin de fichier> .B \-6 --dhcp-script=<chemin de fichier>
Lorsqu'un bail DHCP est créé, ou qu'un ancien est supprimé, le fichier dont le Lorsqu'un bail DHCP est créé, qu'un ancien est supprimé, ou qu'un transfert
TFTP est terminé, le fichier dont le
chemin est spécifié est exécuté. Le <chemin de fichier> doit être un chemin 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. absolu, aucune recherche n'est effectuée via la variable d'environnement PATH.
Les arguments fournis à celui-ci sont soit Les arguments fournis à celui-ci sont soit
@@ -1223,6 +1293,10 @@ relai DHCP pour contacter Dnsmasq, si l'adresse IP du relai est connue.
DNSMASQ_TAGS contient tous les labels fournis pendant la transaction DHCP, DNSMASQ_TAGS contient tous les labels fournis pendant la transaction DHCP,
séparés par des espaces. séparés par des espaces.
DNSMASQ_LOG_DHCP est positionné si
.B --log-dhcp
est activé.
Pour IPv4 seulement : Pour IPv4 seulement :
DNSMASQ_CLIENT_ID, si l'hôte a fourni un identifiant de client. DNSMASQ_CLIENT_ID, si l'hôte a fourni un identifiant de client.
@@ -1262,6 +1336,16 @@ 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 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, 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. le script sera invoqué avec une action "old" pour tous les baux existants.
Il existe deux autres actions pouvant apparaître comme argument au script :
"init" et "tftp". D'autres sont susceptibles d'être rajoutées dans le futur,
aussi les scripts devraient-être écrits de sorte à ignorer les actions
inconnues. "init" est décrite ci-dessous dans
.B --leasefile-ro.
L'action "tftp" est invoquée lorsqu'un transfert de fichier TFTP s'est
terminé. Ses arguments sont la taille du fichier en octets, l'adresse à
laquelle le fichier a été envoyé, ainsi que le chemin complet du fichier.
.TP .TP
.B --dhcp-luascript=<chemin> .B --dhcp-luascript=<chemin>
Spécifie un script écrit en Lua, devant être exécuté lorsque des baux sont Spécifie un script écrit en Lua, devant être exécuté lorsque des baux sont
@@ -1276,8 +1360,10 @@ et peut fournir des fonctions
et et
.B shutdown .B shutdown
qui sont appellées, sans arguments, lorsque dnsmasq démarre ou s'arrête. qui sont appellées, sans arguments, lorsque dnsmasq démarre ou s'arrête.
Il peut également fournir une fonction
.B tftp.
La méthode La fonction
.B lease .B lease
reçoit les informations détaillées dans reçoit les informations détaillées dans
.B --dhcp-script. .B --dhcp-script.
@@ -1301,6 +1387,16 @@ et
ainsi que ainsi que
.B hostname .B hostname
(le nom d'hôte) dans le cas d'IPv6. (le nom d'hôte) dans le cas d'IPv6.
La fonction
.B tftp
est appelée de la même façon que la fonction "lease", et la table contient les
labels
.B destination_address,
.B file_name
et
.B file_size
(respectivement "adresse de destination", "nom de fichier" et "taille de fichier").
.TP .TP
.B --dhcp-scriptuser .B --dhcp-scriptuser
Spécifie l'utilisateur sous lequel le script shell lease-change ou le script Spécifie l'utilisateur sous lequel le script shell lease-change ou le script
@@ -1367,7 +1463,7 @@ Si la gamme d'adresse est fournie sous la forme
qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et
inverses. C-à-d inverses. C-à-d
.B --domain=thekelleys.org.uk,192.168.0.0/24,local .B --domain=thekelleys.org.uk,192.168.0.0/24,local
est indentique à est identique à
.B --domain=thekelleys.org.uk,192.168.0.0/24 .B --domain=thekelleys.org.uk,192.168.0.0/24
--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/ --local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
La taille de réseau doit-être de 8, 16 ou 24 pour être valide. La taille de réseau doit-être de 8, 16 ou 24 pour être valide.
@@ -1411,10 +1507,15 @@ Advertisement") sont activées, dnsmasq va annoncer un préfixe pour chaque
dhcp-range et, par défaut, fournir comme valeur de routeur et de DNS récursif dhcp-range et, par défaut, fournir comme valeur de routeur et de DNS récursif
la valeur d'adresse link-local appropriée parmi celles de la machine sur la valeur d'adresse link-local appropriée parmi celles de la machine sur
laquelle tourne dnsmasq. laquelle tourne dnsmasq.
Les bits "managed address" sont positionnés, sauf pour un dhcp-range marqué Par défaut, les bits "managed address" sont positionnés, et le bit "use SLAAC"
comme "ra-only" (annonce routeur uniquement). Dans ce cas le service d'annonce ("utiliser SLAAC") est réinitialisé. Cela peut-être changé pour des
routeur est rendu mais aucun service DHCPv6 n'est assuré, et les bits "managed sous-réseaux donnés par le biais du mot clef de mode décris dans
address" ne sont pas positionnés. .B --dhcp-range.
Les paramètres DNS du RFC6106 sont inclus dans les annonces. Par défaut,
l'adresse link-local appropriée parmi celles de la machine sur laquelle tourne
dnsmasq est spécifiée comme DNS récursif. Si elles sont fournies, les
options dns-server et domain-search sont utilisées respectivement pour RDNSS et
DNSSL.
.TP .TP
.B --enable-tftp[=<interface>] .B --enable-tftp[=<interface>]
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
+2 -1
View File
@@ -1128,9 +1128,10 @@ msgstr "DHCP, Proxy im Subnetz %.0s%s%.0s"
msgid "DHCP, IP range %s -- %s, lease time %s" msgid "DHCP, IP range %s -- %s, lease time %s"
msgstr "DHCP, IP-Bereich %s - %s, Lease-Zeit %s " msgstr "DHCP, IP-Bereich %s - %s, Lease-Zeit %s "
# FIXME: this and the next few must be full strings to be translatable - do not assemble in code"
#: dnsmasq.c:588 #: dnsmasq.c:588
msgid "root is " msgid "root is "
msgstr "FIXME: this and the next few must be full strings to be translatable - do not assemble in code" msgstr ""
#: dnsmasq.c:588 #: dnsmasq.c:588
msgid "enabled" msgid "enabled"
+1 -1
View File
@@ -167,7 +167,7 @@ HAVE_SOLARIS_NETWORK
define exactly one of these to alter interaction with kernel networking. define exactly one of these to alter interaction with kernel networking.
HAVE_GETOPT_LONG HAVE_GETOPT_LONG
defined when GNU-sty;e getopt_long available. defined when GNU-style getopt_long available.
HAVE_ARC4RANDOM HAVE_ARC4RANDOM
defined if arc4random() available to get better security from DNS spoofs defined if arc4random() available to get better security from DNS spoofs
+42
View File
@@ -111,6 +111,13 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
last_tag->next = tags; last_tag->next = tags;
tagif = run_tag_if(context_tags); tagif = run_tag_if(context_tags);
/* reset stuff with tag:!<tag> which now matches. */
for (opt = opts; opt; opt = opt->next)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
(opt->flags & DHOPT_TAGOK) &&
!match_netid(opt->netid, tagif, 0))
opt->flags &= ~DHOPT_TAGOK;
for (opt = opts; opt; opt = opt->next) for (opt = opts; opt; opt = opt->next)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) && if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) &&
match_netid(opt->netid, tagif, 0)) match_netid(opt->netid, tagif, 0))
@@ -444,6 +451,41 @@ void join_multicast(void)
} }
#endif #endif
#ifdef HAVE_LINUX_NETWORK
void bindtodevice(int fd)
{
/* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
to that device. This is for the use case of (eg) OpenStack, which runs a new
dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE,
individual processes don't always see the packets they should.
SO_BINDTODEVICE is only available Linux. */
struct irec *iface, *found;
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
if (iface->dhcp_ok)
{
if (!found)
found = iface;
else if (strcmp(found->name, iface->name) != 0)
{
/* more than one. */
found = NULL;
break;
}
}
if (found)
{
struct ifreq ifr;
strcpy(ifr.ifr_name, found->name);
/* only allowed by root. */
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
errno != EPERM)
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
}
}
#endif
static const struct opttab_t { static const struct opttab_t {
char *name; char *name;
+1
View File
@@ -54,6 +54,7 @@
#define OPTION6_RECONFIGURE_MSG 19 #define OPTION6_RECONFIGURE_MSG 19
#define OPTION6_RECONF_ACCEPT 20 #define OPTION6_RECONF_ACCEPT 20
#define OPTION6_DNS_SERVER 23 #define OPTION6_DNS_SERVER 23
#define OPTION6_DOMAIN_SEARCH 24
#define OPTION6_REMOTE_ID 37 #define OPTION6_REMOTE_ID 37
#define OPTION6_SUBSCRIBER_ID 38 #define OPTION6_SUBSCRIBER_ID 38
#define OPTION6_FQDN 39 #define OPTION6_FQDN 39
+6 -6
View File
@@ -33,12 +33,12 @@ void dhcp6_init(void)
{ {
int fd; int fd;
struct sockaddr_in6 saddr; struct sockaddr_in6 saddr;
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6) #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
int class = IPTOS_CLASS_CS6; int class = IPTOS_CLASS_CS6;
#endif #endif
if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 || if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 ||
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6) #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 || setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
#endif #endif
!fix_fd(fd) || !fix_fd(fd) ||
@@ -229,7 +229,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
for (pass = 0; pass <= 1; pass++) for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current) for (c = context; c; c = c->current)
if (c->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS))
continue; continue;
else if (!match_netid(c->filter, netids, pass)) else if (!match_netid(c->filter, netids, pass))
continue; continue;
@@ -282,9 +282,9 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
start = addr6part(&tmp->start6); start = addr6part(&tmp->start6);
end = addr6part(&tmp->end6); end = addr6part(&tmp->end6);
if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) && if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_RA_STATELESS)) &&
is_same_net6(&context->start6, taddr, context->prefix) && is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
is_same_net6(&context->end6, taddr, context->prefix) && is_same_net6(&tmp->end6, taddr, tmp->prefix) &&
addr >= start && addr >= start &&
addr <= end && addr <= end &&
match_netid(tmp->filter, netids, 1)) match_netid(tmp->filter, netids, 1))
+91 -49
View File
@@ -23,7 +23,6 @@ struct daemon *daemon;
static volatile pid_t pid = 0; static volatile pid_t pid = 0;
static volatile int pipewrite; static volatile int pipewrite;
static int alarm_queued = 0;
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp); static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
static void check_dns_listeners(fd_set *set, time_t now); static void check_dns_listeners(fd_set *set, time_t now);
@@ -211,12 +210,20 @@ int main (int argc, char **argv)
if (if_tmp->name && !if_tmp->used) if (if_tmp->name && !if_tmp->used)
die(_("unknown interface %s"), if_tmp->name, EC_BADNET); die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next) #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
if (!if_tmp->used) /* after enumerate_interfaces() */
{ if (daemon->dhcp)
prettyprint_addr(&if_tmp->addr, daemon->namebuff); {
die(_("no interface with address %s"), daemon->namebuff, EC_BADNET); bindtodevice(daemon->dhcpfd);
} if (daemon->enable_pxe)
bindtodevice(daemon->pxefd);
}
#endif
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
if (daemon->dhcp6)
bindtodevice(daemon->dhcp6fd);
#endif
} }
else else
create_wildcard_listeners(); create_wildcard_listeners();
@@ -538,7 +545,7 @@ int main (int argc, char **argv)
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled")); my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
if (daemon->dhcp || daemon->dhcp6) if (daemon->dhcp || daemon->dhcp6 || daemon->ra_contexts)
{ {
struct dhcp_context *dhcp_tmp; struct dhcp_context *dhcp_tmp;
int family = AF_INET; int family = AF_INET;
@@ -557,23 +564,50 @@ int main (int argc, char **argv)
{ {
start = &dhcp_tmp->start6; start = &dhcp_tmp->start6;
end = &dhcp_tmp->end6; end = &dhcp_tmp->end6;
struct in6_addr subnet = dhcp_tmp->start6;
setaddr6part(&subnet, 0);
inet_ntop(AF_INET6, &subnet, daemon->addrbuff, 256);
} }
#endif #endif
prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time); if (family != AF_INET && (dhcp_tmp->flags & CONTEXT_DEPRECATE))
inet_ntop(family, start, daemon->dhcp_buff, 256); strcpy(daemon->namebuff, _("prefix deprecated"));
inet_ntop(family, end, daemon->dhcp_buff3, 256); else
my_syslog(MS_DHCP | LOG_INFO, {
(dhcp_tmp->flags & CONTEXT_STATIC) ? char *p = daemon->namebuff;
_("DHCP, static leases only on %.0s%s, lease time %s") : p += sprintf(p, _("lease time "));
(dhcp_tmp->flags & CONTEXT_RA_NAME) ? prettyprint_time(p, dhcp_tmp->lease_time);
_("router advertisement with DHCPv4-derived names on %.0s%s, lifetime %s") : }
(dhcp_tmp->flags & CONTEXT_RA_ONLY) ?
_("router advertisement only on %.0s%s, lifetime %s") : if (daemon->dhcp_buff)
(dhcp_tmp->flags & CONTEXT_PROXY) ? inet_ntop(family, start, daemon->dhcp_buff, 256);
_("DHCP, proxy on subnet %.0s%s%.0s") : if (daemon->dhcp_buff3)
_("DHCP, IP range %s -- %s, lease time %s"), inet_ntop(family, end, daemon->dhcp_buff3, 256);
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->dhcp_buff2); if ((dhcp_tmp->flags & CONTEXT_DHCP) || family == AF_INET)
my_syslog(MS_DHCP | LOG_INFO,
(dhcp_tmp->flags & CONTEXT_RA_STATELESS) ?
_("stateless DHCPv6 on %s%.0s%.0s") :
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("DHCP, static leases only on %.0s%s, %s") :
(dhcp_tmp->flags & CONTEXT_PROXY) ?
_("DHCP, proxy on subnet %.0s%s%.0s") :
_("DHCP, IP range %s -- %s, %s"),
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
if (dhcp_tmp->flags & CONTEXT_RA_NAME)
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s"),
daemon->addrbuff);
if (dhcp_tmp->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS))
{
if (!(dhcp_tmp->flags & CONTEXT_DEPRECATE))
{
char *p = daemon->namebuff;
p += sprintf(p, _("prefix valid "));
prettyprint_time(p, dhcp_tmp->lease_time > 7200 ? dhcp_tmp->lease_time : 7200);
}
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC on %s %s"),
daemon->addrbuff, daemon->namebuff);
}
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
@@ -701,12 +735,12 @@ int main (int argc, char **argv)
{ {
FD_SET(daemon->dhcp6fd, &rset); FD_SET(daemon->dhcp6fd, &rset);
bump_maxfd(daemon->dhcp6fd, &maxfd); bump_maxfd(daemon->dhcp6fd, &maxfd);
}
if (daemon->ra_contexts) if (daemon->ra_contexts)
{ {
FD_SET(daemon->icmp6fd, &rset); FD_SET(daemon->icmp6fd, &rset);
bump_maxfd(daemon->icmp6fd, &maxfd); bump_maxfd(daemon->icmp6fd, &maxfd);
}
} }
#endif #endif
@@ -722,6 +756,10 @@ int main (int argc, char **argv)
# ifdef HAVE_SCRIPT # ifdef HAVE_SCRIPT
while (helper_buf_empty() && do_script_run(now)); while (helper_buf_empty() && do_script_run(now));
# ifdef HAVE_TFTP
while (helper_buf_empty() && do_tftp_script_run());
# endif
if (!helper_buf_empty()) if (!helper_buf_empty())
{ {
FD_SET(daemon->helperfd, &wset); FD_SET(daemon->helperfd, &wset);
@@ -730,6 +768,11 @@ int main (int argc, char **argv)
# else # else
/* need this for other side-effects */ /* need this for other side-effects */
while (do_script_run(now)); while (do_script_run(now));
# ifdef HAVE_TFTP
while (do_tftp_script_run());
# endif
# endif # endif
#endif #endif
@@ -868,20 +911,14 @@ static void sig_handler(int sig)
/* now == 0 -> queue immediate callback */ /* now == 0 -> queue immediate callback */
void send_alarm(time_t event, time_t now) void send_alarm(time_t event, time_t now)
{ {
if (now == 0 || event != 0)
if (now != 0 && event == 0)
return;
if ((now == 0 || difftime(event, now) <= 0.0))
{ {
if (!alarm_queued) /* alarm(0) or alarm(-ve) doesn't do what we want.... */
{ if ((now == 0 || difftime(event, now) <= 0.0))
send_event(pipewrite, EVENT_ALARM, 0, NULL); send_event(pipewrite, EVENT_ALARM, 0, NULL);
alarm_queued = 1; else
} alarm((unsigned)difftime(event, now));
} }
else
alarm((unsigned)difftime(event, now));
} }
void send_event(int fd, int event, int data, char *msg) void send_event(int fd, int event, int data, char *msg)
@@ -995,7 +1032,6 @@ static void async_event(int pipe, time_t now)
break; break;
case EVENT_ALARM: case EVENT_ALARM:
alarm_queued = 0;
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
if (daemon->dhcp || daemon->dhcp6) if (daemon->dhcp || daemon->dhcp6)
{ {
@@ -1283,18 +1319,19 @@ static void check_dns_listeners(fd_set *set, time_t now)
int confd; int confd;
struct irec *iface = NULL; struct irec *iface = NULL;
pid_t p; pid_t p;
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR); while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1) if (confd == -1 ||
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
continue; continue;
if (option_bool(OPT_NOWILD)) if (option_bool(OPT_NOWILD))
iface = listener->iface; iface = listener->iface; /* May be NULL */
else else
{ {
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address: /* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's the local address of the TCP connection, then looking to see if that's
@@ -1302,14 +1339,13 @@ static void check_dns_listeners(fd_set *set, time_t now)
interface too, for localisation. */ interface too, for localisation. */
/* interface may be new since startup */ /* interface may be new since startup */
if (enumerate_interfaces() && if (enumerate_interfaces())
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr)) if (sockaddr_isequal(&iface->addr, &tcp_addr))
break; break;
} }
if (!iface) if (!iface && !option_bool(OPT_NOWILD))
{ {
shutdown(confd, SHUT_RDWR); shutdown(confd, SHUT_RDWR);
close(confd); close(confd);
@@ -1335,6 +1371,12 @@ static void check_dns_listeners(fd_set *set, time_t now)
unsigned char *buff; unsigned char *buff;
struct server *s; struct server *s;
int flags; int flags;
struct in_addr netmask;
if (iface)
netmask = iface->netmask;
else
netmask.s_addr = 0;
#ifndef NO_FORK #ifndef NO_FORK
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
@@ -1353,7 +1395,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if ((flags = fcntl(confd, F_GETFL, 0)) != -1) if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK); fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
buff = tcp_request(confd, now, &iface->addr, iface->netmask); buff = tcp_request(confd, now, &tcp_addr, netmask);
shutdown(confd, SHUT_RDWR); shutdown(confd, SHUT_RDWR);
close(confd); close(confd);
+23 -12
View File
@@ -388,14 +388,14 @@ struct server {
struct irec { struct irec {
union mysockaddr addr; union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */ struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, mtu, done, dad; int tftp_ok, dhcp_ok, mtu, done, dad;
char *name; char *name;
struct irec *next; struct irec *next;
}; };
struct listener { struct listener {
int fd, tcpfd, tftpfd, family; int fd, tcpfd, tftpfd, family;
struct irec *iface; /* only valid for non-wildcard */ struct irec *iface; /* only sometimes valid for non-wildcard */
struct listener *next; struct listener *next;
}; };
@@ -458,6 +458,7 @@ struct frec {
#define ACTION_OLD_HOSTNAME 2 #define ACTION_OLD_HOSTNAME 2
#define ACTION_OLD 3 #define ACTION_OLD 3
#define ACTION_ADD 4 #define ACTION_ADD 4
#define ACTION_TFTP 5
#define LEASE_NEW 1 /* newly created */ #define LEASE_NEW 1 /* newly created */
#define LEASE_CHANGED 2 /* modified */ #define LEASE_CHANGED 2 /* modified */
@@ -645,13 +646,16 @@ struct dhcp_context {
struct dhcp_context *next, *current; struct dhcp_context *next, *current;
}; };
#define CONTEXT_STATIC 1 #define CONTEXT_STATIC 1
#define CONTEXT_NETMASK 2 #define CONTEXT_NETMASK 2
#define CONTEXT_BRDCAST 4 #define CONTEXT_BRDCAST 4
#define CONTEXT_PROXY 8 #define CONTEXT_PROXY 8
#define CONTEXT_RA_ONLY 16 #define CONTEXT_RA_ONLY 16
#define CONTEXT_RA_DONE 32 #define CONTEXT_RA_DONE 32
#define CONTEXT_RA_NAME 64 #define CONTEXT_RA_NAME 64
#define CONTEXT_RA_STATELESS 128
#define CONTEXT_DHCP 256
#define CONTEXT_DEPRECATE 512
struct ping_result { struct ping_result {
struct in_addr addr; struct in_addr addr;
@@ -803,7 +807,7 @@ extern struct daemon {
#endif #endif
/* TFTP stuff */ /* TFTP stuff */
struct tftp_transfer *tftp_trans; struct tftp_transfer *tftp_trans, *tftp_done_trans;
/* utility string buffer, hold max sized IP address as string */ /* utility string buffer, hold max sized IP address as string */
char *addrbuff; char *addrbuff;
@@ -910,7 +914,7 @@ unsigned char *tcp_request(int confd, time_t now,
union mysockaddr *local_addr, struct in_addr netmask); union mysockaddr *local_addr, struct in_addr netmask);
void server_gone(struct server *server); void server_gone(struct server *server);
struct frec *get_new_frec(time_t now, int *wait); struct frec *get_new_frec(time_t now, int *wait);
void send_from(int fd, int nowild, char *packet, size_t len, int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source, union mysockaddr *to, struct all_addr *source,
unsigned int iface); unsigned int iface);
@@ -1035,11 +1039,14 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
#endif #endif
/* helper.c */ /* helper.c */
#if defined(HAVE_DHCP) && !defined(NO_FORK) #if defined(HAVE_SCRIPT)
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd); int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
void helper_write(void); void helper_write(void);
void queue_script(int action, struct dhcp_lease *lease, void queue_script(int action, struct dhcp_lease *lease,
char *hostname, time_t now); char *hostname, time_t now);
#ifdef HAVE_TFTP
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
#endif
int helper_buf_empty(void); int helper_buf_empty(void);
#endif #endif
@@ -1047,6 +1054,7 @@ int helper_buf_empty(void);
#ifdef HAVE_TFTP #ifdef HAVE_TFTP
void tftp_request(struct listener *listen, time_t now); void tftp_request(struct listener *listen, time_t now);
void check_tftp_listeners(fd_set *rset, time_t now); void check_tftp_listeners(fd_set *rset, time_t now);
int do_tftp_script_run(void);
#endif #endif
/* conntrack.c */ /* conntrack.c */
@@ -1100,6 +1108,9 @@ u16 lookup_dhcp_opt(int prot, char *name);
u16 lookup_dhcp_len(int prot, u16 val); u16 lookup_dhcp_len(int prot, u16 val);
char *option_string(int prot, unsigned int opt, unsigned char *val, char *option_string(int prot, unsigned int opt, unsigned char *val,
int opt_len, char *buf, int buf_len); int opt_len, char *buf, int buf_len);
#ifdef HAVE_LINUX_NETWORK
void bindtodevice(int fd);
#endif
# ifdef HAVE_DHCP6 # ifdef HAVE_DHCP6
void display_opts6(void); void display_opts6(void);
void join_multicast(void); void join_multicast(void);
+8 -4
View File
@@ -26,9 +26,9 @@ static struct randfd *allocate_rfd(int family);
/* Send a UDP packet with its source address set as "source" /* Send a UDP packet with its source address set as "source"
unless nowild is true, when we just send it with the kernel default */ unless nowild is true, when we just send it with the kernel default */
void send_from(int fd, int nowild, char *packet, size_t len, int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source, union mysockaddr *to, struct all_addr *source,
unsigned int iface) unsigned int iface)
{ {
struct msghdr msg; struct msghdr msg;
struct iovec iov[1]; struct iovec iov[1];
@@ -111,7 +111,11 @@ void send_from(int fd, int nowild, char *packet, size_t len,
goto retry; goto retry;
my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno)); my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
return 0;
} }
return 1;
} }
static unsigned int search_servers(time_t now, struct all_addr **addrpp, static unsigned int search_servers(time_t now, struct all_addr **addrpp,
@@ -660,7 +664,7 @@ void receive_query(struct listener *listen, time_t now)
/* packet buffer overwritten */ /* packet buffer overwritten */
daemon->srv_save = NULL; daemon->srv_save = NULL;
if (listen->family == AF_INET && option_bool(OPT_NOWILD)) if (listen->iface && listen->family == AF_INET && option_bool(OPT_NOWILD))
{ {
dst_addr_4 = listen->iface->addr.in.sin_addr; dst_addr_4 = listen->iface->addr.in.sin_addr;
netmask = listen->iface->netmask; netmask = listen->iface->netmask;
+241 -168
View File
@@ -193,16 +193,22 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
_exit(0); _exit(0);
} }
is6 = !!(data.flags & (LEASE_TA | LEASE_NA));
if (data.action == ACTION_DEL) if (data.action == ACTION_DEL)
action_str = "del"; action_str = "del";
else if (data.action == ACTION_ADD) else if (data.action == ACTION_ADD)
action_str = "add"; action_str = "add";
else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME) else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME)
action_str = "old"; action_str = "old";
else if (data.action == ACTION_TFTP)
{
action_str = "tftp";
is6 = (data.flags != AF_INET);
}
else else
continue; continue;
is6 = !!(data.flags & (LEASE_TA | LEASE_NA));
if (!is6) if (!is6)
{ {
@@ -271,12 +277,15 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
char *dot; char *dot;
hostname = (char *)buf; hostname = (char *)buf;
hostname[data.hostname_len - 1] = 0; hostname[data.hostname_len - 1] = 0;
if (!legal_hostname(hostname)) if (data.action != ACTION_TFTP)
hostname = NULL;
else if ((dot = strchr(hostname, '.')))
{ {
domain = dot+1; if (!legal_hostname(hostname))
*dot = 0; hostname = NULL;
else if ((dot = strchr(hostname, '.')))
{
domain = dot+1;
*dot = 0;
}
} }
} }
@@ -289,116 +298,141 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN); inet_ntop(AF_INET6, &data.hwaddr, daemon->addrbuff, ADDRSTRLEN);
#endif #endif
/* file length */
if (data.action == ACTION_TFTP)
sprintf(daemon->dhcp_buff, "%u", data.hwaddr_len);
#ifdef HAVE_LUASCRIPT #ifdef HAVE_LUASCRIPT
if (daemon->luascript) if (daemon->luascript)
{ {
lua_getglobal(lua, "lease"); /* function to call */ if (data.action == ACTION_TFTP)
lua_pushstring(lua, action_str); /* arg1 - action */
lua_newtable(lua); /* arg2 - data table */
if (is6)
{ {
lua_pushstring(lua, daemon->dhcp_buff); lua_getglobal(lua, "tftp");
lua_setfield(lua, -2, "client_duid"); if (lua_type(lua, -1) != LUA_TFUNCTION)
lua_pushstring(lua, daemon->packet); lua_pop(lua, 1); /* tftp function optional */
lua_setfield(lua, -2, "server_duid"); else
lua_pushstring(lua, daemon->dhcp_buff3); {
lua_setfield(lua, -2, "iaid"); lua_pushstring(lua, action_str); /* arg1 - action */
lua_newtable(lua); /* arg2 - data table */
lua_pushstring(lua, daemon->addrbuff);
lua_setfield(lua, -2, "destination_address");
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "file_name");
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "file_size");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
}
} }
else
if (!is6 && data.clid_len != 0)
{ {
lua_pushstring(lua, daemon->packet); lua_getglobal(lua, "lease"); /* function to call */
lua_setfield(lua, -2, "client_id"); lua_pushstring(lua, action_str); /* arg1 - action */
} lua_newtable(lua); /* arg2 - data table */
if (strlen(data.interface) != 0) if (is6)
{ {
lua_pushstring(lua, data.interface); lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "interface"); lua_setfield(lua, -2, "client_duid");
} lua_pushstring(lua, daemon->packet);
lua_setfield(lua, -2, "server_duid");
lua_pushstring(lua, daemon->dhcp_buff3);
lua_setfield(lua, -2, "iaid");
}
if (!is6 && data.clid_len != 0)
{
lua_pushstring(lua, daemon->packet);
lua_setfield(lua, -2, "client_id");
}
if (strlen(data.interface) != 0)
{
lua_pushstring(lua, data.interface);
lua_setfield(lua, -2, "interface");
}
#ifdef HAVE_BROKEN_RTC #ifdef HAVE_BROKEN_RTC
lua_pushnumber(lua, data.length); lua_pushnumber(lua, data.length);
lua_setfield(lua, -2, "lease_length"); lua_setfield(lua, -2, "lease_length");
#else #else
lua_pushnumber(lua, data.expires); lua_pushnumber(lua, data.expires);
lua_setfield(lua, -2, "lease_expires"); lua_setfield(lua, -2, "lease_expires");
#endif #endif
if (hostname) if (hostname)
{ {
lua_pushstring(lua, hostname); lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "hostname"); lua_setfield(lua, -2, "hostname");
} }
if (domain) if (domain)
{ {
lua_pushstring(lua, domain); lua_pushstring(lua, domain);
lua_setfield(lua, -2, "domain"); lua_setfield(lua, -2, "domain");
} }
end = extradata + data.ed_len; end = extradata + data.ed_len;
buf = extradata; buf = extradata;
if (!is6) if (!is6)
buf = grab_extradata_lua(buf, end, "vendor_class"); buf = grab_extradata_lua(buf, end, "vendor_class");
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
else else
for (i = 0; i < data.hwaddr_len; i++) for (i = 0; i < data.hwaddr_len; i++)
{ {
sprintf(daemon->dhcp_buff2, "vendor_class%i", i); sprintf(daemon->dhcp_buff2, "vendor_class%i", i);
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2); buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
} }
#endif #endif
buf = grab_extradata_lua(buf, end, "supplied_hostname"); buf = grab_extradata_lua(buf, end, "supplied_hostname");
if (!is6) if (!is6)
{ {
buf = grab_extradata_lua(buf, end, "cpewan_oui"); buf = grab_extradata_lua(buf, end, "cpewan_oui");
buf = grab_extradata_lua(buf, end, "cpewan_serial"); buf = grab_extradata_lua(buf, end, "cpewan_serial");
buf = grab_extradata_lua(buf, end, "cpewan_class"); buf = grab_extradata_lua(buf, end, "cpewan_class");
}
buf = grab_extradata_lua(buf, end, "tags");
if (is6)
buf = grab_extradata_lua(buf, end, "relay_address");
else if (data.giaddr.s_addr != 0)
{
lua_pushstring(lua, inet_ntoa(data.giaddr));
lua_setfield(lua, -2, "relay_address");
}
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "user_class%i", i);
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
}
if (data.action != ACTION_DEL && data.remaining_time != 0)
{
lua_pushnumber(lua, data.remaining_time);
lua_setfield(lua, -2, "time_remaining");
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "old_hostname");
}
if (!is6)
{
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "mac_address");
}
lua_pushstring(lua, daemon->addrbuff);
lua_setfield(lua, -2, "ip_address");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
} }
buf = grab_extradata_lua(buf, end, "tags");
if (is6)
buf = grab_extradata_lua(buf, end, "relay_address");
else if (data.giaddr.s_addr != 0)
{
lua_pushstring(lua, inet_ntoa(data.giaddr));
lua_setfield(lua, -2, "relay_address");
}
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "user_class%i", i);
buf = grab_extradata_lua(buf, end, daemon->dhcp_buff2);
}
if (data.action != ACTION_DEL && data.remaining_time != 0)
{
lua_pushnumber(lua, data.remaining_time);
lua_setfield(lua, -2, "time_remaining");
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "old_hostname");
}
if (!is6)
{
lua_pushstring(lua, daemon->dhcp_buff);
lua_setfield(lua, -2, "mac_address");
}
lua_pushstring(lua, daemon->addrbuff);
lua_setfield(lua, -2, "ip_address");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
} }
#endif #endif
@@ -439,80 +473,86 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
continue; continue;
} }
if (is6) if (data.action != ACTION_TFTP)
{ {
my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err); if (is6)
my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err); {
} my_setenv("DNSMASQ_IAID", daemon->dhcp_buff3, &err);
my_setenv("DNSMASQ_SERVER_DUID", daemon->packet, &err);
}
if (!is6 && data.clid_len != 0) if (!is6 && data.clid_len != 0)
my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err); my_setenv("DNSMASQ_CLIENT_ID", daemon->packet, &err);
if (strlen(data.interface) != 0) if (strlen(data.interface) != 0)
my_setenv("DNSMASQ_INTERFACE", data.interface, &err); my_setenv("DNSMASQ_INTERFACE", data.interface, &err);
#ifdef HAVE_BROKEN_RTC #ifdef HAVE_BROKEN_RTC
my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err); my_setenv("DNSMASQ_LEASE_LENGTH", daemon->dhcp_buff2, &err);
#else #else
my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err); my_setenv("DNSMASQ_LEASE_EXPIRES", daemon->dhcp_buff2, &err);
#endif #endif
if (domain) if (domain)
my_setenv("DNSMASQ_DOMAIN", domain, &err); my_setenv("DNSMASQ_DOMAIN", domain, &err);
end = extradata + data.ed_len; end = extradata + data.ed_len;
buf = extradata; buf = extradata;
if (!is6) if (!is6)
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err); buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
else else
{
if (data.hwaddr_len != 0)
{ {
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err); if (data.hwaddr_len != 0)
for (i = 0; i < data.hwaddr_len - 1; i++)
{ {
sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i); buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS_ID", &err);
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err); for (i = 0; i < data.hwaddr_len - 1; i++)
{
sprintf(daemon->dhcp_buff2, "DNSMASQ_VENDOR_CLASS%i", i);
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
}
} }
} }
}
#endif #endif
buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err); buf = grab_extradata(buf, end, "DNSMASQ_SUPPLIED_HOSTNAME", &err);
if (!is6) if (!is6)
{ {
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err); buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_OUI", &err);
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err); buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_SERIAL", &err);
buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err); buf = grab_extradata(buf, end, "DNSMASQ_CPEWAN_CLASS", &err);
}
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
if (is6)
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
else if (data.giaddr.s_addr != 0)
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i);
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
}
if (data.action != ACTION_DEL && data.remaining_time != 0)
{
sprintf(daemon->dhcp_buff2, "%u", data.remaining_time);
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);
hostname = NULL;
}
} }
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err); if (option_bool(OPT_LOG_OPTS))
my_setenv("DNSMASQ_LOG_DHCP", "1", &err);
if (is6)
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
else if (data.giaddr.s_addr != 0)
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
for (i = 0; buf; i++)
{
sprintf(daemon->dhcp_buff2, "DNSMASQ_USER_CLASS%i", i);
buf = grab_extradata(buf, end, daemon->dhcp_buff2, &err);
}
if (data.action != ACTION_DEL && data.remaining_time != 0)
{
sprintf(daemon->dhcp_buff2, "%u", data.remaining_time);
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
}
if (data.action == ACTION_OLD_HOSTNAME && hostname)
{
my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);
hostname = NULL;
}
/* we need to have the event_fd around if exec fails */ /* we need to have the event_fd around if exec fails */
if ((i = fcntl(event_fd, F_GETFD)) != -1) if ((i = fcntl(event_fd, F_GETFD)) != -1)
@@ -584,11 +624,29 @@ static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end,
} }
#endif #endif
static void buff_alloc(size_t size)
{
if (size > buf_size)
{
struct script_data *new;
/* start with reasonable size, will almost never need extending. */
if (size < sizeof(struct script_data) + 200)
size = sizeof(struct script_data) + 200;
if (!(new = whine_malloc(size)))
return;
if (buf)
free(buf);
buf = new;
buf_size = size;
}
}
/* pack up lease data into a buffer */ /* pack up lease data into a buffer */
void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now) void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now)
{ {
unsigned char *p; unsigned char *p;
size_t size;
unsigned int hostname_len = 0, clid_len = 0, ed_len = 0; unsigned int hostname_len = 0, clid_len = 0, ed_len = 0;
int fd = daemon->dhcpfd; int fd = daemon->dhcpfd;
@@ -608,23 +666,7 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
if (hostname) if (hostname)
hostname_len = strlen(hostname) + 1; hostname_len = strlen(hostname) + 1;
size = sizeof(struct script_data) + clid_len + ed_len + hostname_len; buff_alloc(sizeof(struct script_data) + clid_len + ed_len + hostname_len);
if (size > buf_size)
{
struct script_data *new;
/* start with reasonable size, will almost never need extending. */
if (size < sizeof(struct script_data) + 200)
size = sizeof(struct script_data) + 200;
if (!(new = whine_malloc(size)))
return;
if (buf)
free(buf);
buf = new;
buf_size = size;
}
buf->action = action; buf->action = action;
buf->flags = lease->flags; buf->flags = lease->flags;
@@ -669,6 +711,37 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
bytes_in_buf = p - (unsigned char *)buf; bytes_in_buf = p - (unsigned char *)buf;
} }
#ifdef HAVE_TFTP
/* This nastily re-uses DHCP-fields for TFTP stuff */
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
{
unsigned int filename_len;
/* no script */
if (daemon->helperfd == -1)
return;
filename_len = strlen(filename) + 1;
buff_alloc(sizeof(struct script_data) + filename_len);
memset(buf, 0, sizeof(struct script_data));
buf->action = ACTION_TFTP;
buf->hostname_len = filename_len;
buf->hwaddr_len = file_len;
if ((buf->flags = peer->sa.sa_family) == AF_INET)
buf->addr = peer->in.sin_addr;
#ifdef HAVE_IPV6
else
memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ);
#endif
memcpy((unsigned char *)(buf+1), filename, filename_len);
bytes_in_buf = sizeof(struct script_data) + filename_len;
}
#endif
int helper_buf_empty(void) int helper_buf_empty(void)
{ {
return bytes_in_buf == 0; return bytes_in_buf == 0;
+4 -1
View File
@@ -373,7 +373,10 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface) void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface)
{ {
slaac_ping_reply(sender, packet, interface, leases); /* We may be doing RA but not DHCPv4, in which case the lease
database may not exist and we have nothing to do anyway */
if (daemon->dhcp)
slaac_ping_reply(sender, packet, interface, leases);
} }
#endif #endif
+29 -1
View File
@@ -162,6 +162,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
int fd, mtu = 0, loopback; int fd, mtu = 0, loopback;
struct ifreq ifr; struct ifreq ifr;
int tftp_ok = daemon->tftp_unlimited; int tftp_ok = daemon->tftp_unlimited;
int dhcp_ok = 1;
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
struct iname *tmp; struct iname *tmp;
#endif #endif
@@ -191,6 +192,9 @@ static int iface_allowed(struct irec **irecp, int if_index,
loopback = ifr.ifr_flags & IFF_LOOPBACK; loopback = ifr.ifr_flags & IFF_LOOPBACK;
if (loopback)
dhcp_ok = 0;
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1) if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu; mtu = ifr.ifr_mtu;
@@ -238,7 +242,10 @@ static int iface_allowed(struct irec **irecp, int if_index,
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
tftp_ok = 0; {
tftp_ok = 0;
dhcp_ok = 0;
}
#endif #endif
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@@ -254,6 +261,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
iface->addr = *addr; iface->addr = *addr;
iface->netmask = netmask; iface->netmask = netmask;
iface->tftp_ok = tftp_ok; iface->tftp_ok = tftp_ok;
iface->dhcp_ok = dhcp_ok;
iface->mtu = mtu; iface->mtu = mtu;
iface->dad = dad; iface->dad = dad;
iface->done = 0; iface->done = 0;
@@ -511,6 +519,7 @@ void create_bound_listeners(int dienow)
{ {
struct listener *new; struct listener *new;
struct irec *iface; struct irec *iface;
struct iname *if_tmp;
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad && if (!iface->done && !iface->dad &&
@@ -521,6 +530,25 @@ void create_bound_listeners(int dienow)
daemon->listeners = new; daemon->listeners = new;
iface->done = 1; iface->done = 1;
} }
/* Check for --listen-address options that haven't been used because there's
no interface with a matching address. These may be valid: eg it's possible
to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
If the address isn't valid the bind() will fail and we'll die().
The resulting listeners have the ->iface field NULL, and this has to be
handled by the DNS and TFTP code. It disables --localise-queries processing
(no netmask) and some MTU login the tftp code. */
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, 1, dienow)))
{
new->iface = NULL;
new->next = daemon->listeners;
daemon->listeners = new;
}
} }
int is_dad_listeners(void) int is_dad_listeners(void)
+61 -61
View File
@@ -1000,6 +1000,7 @@ static char *parse_dhcp_opt(char *arg, int flags)
while (arg && *arg) while (arg && *arg)
{ {
u16 len = strlen(arg); u16 len = strlen(arg);
unhide_metas(arg);
PUTSHORT(len, p); PUTSHORT(len, p);
memcpy(p, arg, len); memcpy(p, arg, len);
p += len; p += len;
@@ -1013,29 +1014,40 @@ static char *parse_dhcp_opt(char *arg, int flags)
} }
else if (comma && (opt_len & OT_RFC1035_NAME)) else if (comma && (opt_len & OT_RFC1035_NAME))
{ {
int i, commas = 1; unsigned char *p = NULL, *newp, *end;
unsigned char *p, *newp; int len = 0;
for (i = 0; comma[i]; i++)
if (comma[i] == ',')
commas++;
newp = opt_malloc(strlen(comma)+(2*commas));
p = newp;
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
while (arg && *arg) while (arg && *arg)
{ {
p = do_rfc1035_name(p, arg); char *dom = canonicalise_opt(arg);
*p++ = 0; if (!dom)
{
problem = _("bad domain in dhcp-option");
break;
}
newp = opt_malloc(len + strlen(dom) + 2);
if (p)
{
memcpy(newp, p, len);
free(p);
}
p = newp;
end = do_rfc1035_name(p + len, dom);
*end++ = 0;
len = end - p;
free(dom);
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
} }
new->val = newp; new->val = p;
new->len = p - newp; new->len = len;
} }
#endif #endif
else else
@@ -1959,7 +1971,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
case 'F': /* --dhcp-range */ case 'F': /* --dhcp-range */
{ {
int k, leasepos = 2; int k, leasepos = 2;
char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL }; char *cp, *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context)); struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
memset (new, 0, sizeof(*new)); memset (new, 0, sizeof(*new));
@@ -2010,7 +2022,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
} }
} }
for (k = 1; k < 5; k++) for (k = 1; k < 7; k++)
if (!(a[k] = split(a[k-1]))) if (!(a[k] = split(a[k-1])))
break; break;
@@ -2020,17 +2032,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
{ {
new->next = daemon->dhcp; new->next = daemon->dhcp;
daemon->dhcp = new; daemon->dhcp = new;
new->end = new->start;
if (strcmp(a[1], "static") == 0) if (strcmp(a[1], "static") == 0)
{ new->flags |= CONTEXT_STATIC;
new->end = new->start;
new->flags |= CONTEXT_STATIC;
}
else if (strcmp(a[1], "proxy") == 0) else if (strcmp(a[1], "proxy") == 0)
{ new->flags |= CONTEXT_PROXY;
new->end = new->start; else if (!inet_pton(AF_INET, a[1], &new->end))
new->flags |= CONTEXT_PROXY;
}
else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
option = '?'; option = '?';
if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
@@ -2060,53 +2067,54 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
else if (inet_pton(AF_INET6, a[0], &new->start6)) else if (inet_pton(AF_INET6, a[0], &new->start6))
{ {
new->prefix = 64; /* default */ new->prefix = 64; /* default */
new->end6 = new->start6;
if (strcmp(a[1], "static") == 0) for (leasepos = 1; leasepos < k; leasepos++)
{ {
memcpy(&new->end6, &new->start6, IN6ADDRSZ); if (strcmp(a[leasepos], "static") == 0)
new->flags |= CONTEXT_STATIC; new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
new->flags |= CONTEXT_RA_ONLY;
else if (strcmp(a[leasepos], "ra-names") == 0)
new->flags |= CONTEXT_RA_NAME;
else if (strcmp(a[leasepos], "ra-stateless") == 0)
new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP;
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
new->flags |= CONTEXT_DHCP;
else
break;
} }
else if (strcmp(a[1], "ra-only") == 0)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_RA_ONLY;
}
else if (strcmp(a[1], "ra-names") == 0)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_RA_NAME | CONTEXT_RA_ONLY;
}
else if (!inet_pton(AF_INET6, a[1], &new->end6))
option = '?';
if (new->flags & CONTEXT_RA_ONLY) if (new->flags & CONTEXT_DHCP)
{
new->next = daemon->ra_contexts;
daemon->ra_contexts = new;
}
else
{ {
new->next = daemon->dhcp6; new->next = daemon->dhcp6;
daemon->dhcp6 = new; daemon->dhcp6 = new;
} }
else
{
new->next = daemon->ra_contexts;
daemon->ra_contexts = new;
}
/* bare integer < 128 is prefix value */ /* bare integer < 128 is prefix value */
if (option != '?' && k >= 3) if (option != '?' && leasepos < k)
{ {
int pref; int pref;
for (cp = a[2]; *cp; cp++) for (cp = a[leasepos]; *cp; cp++)
if (!(*cp >= '0' && *cp <= '9')) if (!(*cp >= '0' && *cp <= '9'))
break; break;
if (!*cp && (pref = atoi(a[2])) <= 128) if (!*cp && (pref = atoi(a[leasepos])) <= 128)
{ {
new->prefix = pref; new->prefix = pref;
leasepos = 3; leasepos++;
if ((new->flags & CONTEXT_RA_ONLY) && new->prefix != 64) if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) &&
new->prefix != 64)
problem = _("prefix must be exactly 64 for RA subnets"); problem = _("prefix must be exactly 64 for RA subnets");
else if (new->prefix < 64) else if (new->prefix < 64)
problem = _("prefix must be at least 64"); problem = _("prefix must be at least 64");
} }
} }
if (!problem && !is_same_net6(&new->start6, &new->end6, new->prefix)) if (!problem && !is_same_net6(&new->start6, &new->end6, new->prefix))
problem = _("inconsistent DHCPv6 range"); problem = _("inconsistent DHCPv6 range");
else if (addr6part(&new->start6) > addr6part(&new->end6)) else if (addr6part(&new->start6) > addr6part(&new->end6))
@@ -2118,10 +2126,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
} }
#endif #endif
if (k >= leasepos+1) if (leasepos < k)
{ {
if (strcmp(a[leasepos], "infinite") == 0) if (strcmp(a[leasepos], "infinite") == 0)
new->lease_time = 0xffffffff; new->lease_time = 0xffffffff;
else if (strcmp(a[leasepos], "deprecated") == 0)
new->flags |= CONTEXT_DEPRECATE;
else else
{ {
int fac = 1; int fac = 1;
@@ -2154,16 +2164,6 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
} }
} }
} }
#ifdef HAVE_DHCP6
/* lifetimes must be min 2 hrs, by RFC 2462.
This gets enforced in radv.c for DHCP ranges
which are legitimately less. */
if ((new->flags & CONTEXT_RA_ONLY) &&
new->lease_time < 7200)
new->lease_time = 7200;
#endif
break; break;
} }
+1
View File
@@ -43,6 +43,7 @@ struct prefix_opt {
#define ICMP6_OPT_PREFIX 3 #define ICMP6_OPT_PREFIX 3
#define ICMP6_OPT_MTU 5 #define ICMP6_OPT_MTU 5
#define ICMP6_OPT_RDNSS 25 #define ICMP6_OPT_RDNSS 25
#define ICMP6_OPT_DNSSL 31
+161 -81
View File
@@ -27,8 +27,9 @@
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
struct ra_param { struct ra_param {
int ind, managed, found_context, first; int ind, managed, other, found_context, first;
char *if_name; char *if_name;
struct dhcp_netid *tags;
struct in6_addr link_local; struct in6_addr link_local;
}; };
@@ -50,7 +51,7 @@ void ra_init(time_t now)
{ {
struct icmp6_filter filter; struct icmp6_filter filter;
int fd; int fd;
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6) #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
int class = IPTOS_CLASS_CS6; int class = IPTOS_CLASS_CS6;
#endif #endif
int val = 255; /* radvd uses this value */ int val = 255; /* radvd uses this value */
@@ -72,7 +73,7 @@ void ra_init(time_t now)
if ((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1 || if ((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1 ||
getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, &len) || getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, &len) ||
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6) #if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 || setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
#endif #endif
!fix_fd(fd) || !fix_fd(fd) ||
@@ -116,8 +117,7 @@ void icmp6_packet(void)
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
} control_u; } control_u;
struct sockaddr_in6 from; struct sockaddr_in6 from;
unsigned char *p; unsigned char *packet;
char *mac = "";
struct iname *tmp; struct iname *tmp;
struct dhcp_context *context; struct dhcp_context *context;
@@ -133,6 +133,8 @@ void icmp6_packet(void)
if ((sz = recv_dhcp_packet(daemon->icmp6fd, &msg)) == -1 || sz < 8) if ((sz = recv_dhcp_packet(daemon->icmp6fd, &msg)) == -1 || sz < 8)
return; return;
packet = (unsigned char *)daemon->outpacket.iov_base;
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
{ {
@@ -160,36 +162,25 @@ void icmp6_packet(void)
if (!context->interface || strcmp(context->interface, interface) == 0) if (!context->interface || strcmp(context->interface, interface) == 0)
break; break;
if (!context) if (!context || packet[1] != 0)
return; return;
p = (unsigned char *)daemon->outpacket.iov_base; if (packet[0] == ICMP6_ECHO_REPLY)
lease_ping_reply(&from.sin6_addr, packet, interface);
if (p[1] != 0) else if (packet[0] == ND_ROUTER_SOLICIT)
return;
if (p[0] == ICMP6_ECHO_REPLY)
{ {
/* We may be doing RA but not DHCPv4, in which case the lease char *mac = "";
database may not exist and we have nothing to do anyway */
if (daemon->dhcp) /* look for link-layer address option for logging */
lease_ping_reply(&from.sin6_addr, p, interface); if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
return; {
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
mac = daemon->namebuff;
}
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
send_ra(if_index, interface, &from.sin6_addr);
} }
if (p[0] != ND_ROUTER_SOLICIT)
return;
/* look for link-layer address option for logging */
if (sz >= 16 && p[8] == ICMP6_OPT_SOURCE_MAC && (p[9] * 8) + 8 <= sz)
{
print_mac(daemon->namebuff, &p[10], (p[9] * 8) - 2);
mac = daemon->namebuff;
}
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
send_ra(if_index, interface, &from.sin6_addr);
} }
static void send_ra(int iface, char *iface_name, struct in6_addr *dest) static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
@@ -199,6 +190,9 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
struct ifreq ifr; struct ifreq ifr;
struct sockaddr_in6 addr; struct sockaddr_in6 addr;
struct dhcp_context *context; struct dhcp_context *context;
struct dhcp_netid iface_id;
struct dhcp_opt *opt_cfg;
int done_dns = 0;
save_counter(0); save_counter(0);
ra = expand(sizeof(struct ra_packet)); ra = expand(sizeof(struct ra_packet));
@@ -206,19 +200,28 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
ra->type = ND_ROUTER_ADVERT; ra->type = ND_ROUTER_ADVERT;
ra->code = 0; ra->code = 0;
ra->hop_limit = hop_limit; ra->hop_limit = hop_limit;
ra->flags = 0; ra->flags = 0x00;
ra->lifetime = htons(1800); /* AdvDefaultLifetime*/ ra->lifetime = htons(1800); /* AdvDefaultLifetime*/
ra->reachable_time = 0; ra->reachable_time = 0;
ra->retrans_time = 0; ra->retrans_time = 0;
parm.ind = iface; parm.ind = iface;
parm.managed = 0; parm.managed = 0;
parm.other = 0;
parm.found_context = 0; parm.found_context = 0;
parm.if_name = iface_name; parm.if_name = iface_name;
parm.first = 1; parm.first = 1;
/* set tag with name == interface */
iface_id.net = iface_name;
iface_id.next = NULL;
parm.tags = &iface_id;
for (context = daemon->ra_contexts; context; context = context->next) for (context = daemon->ra_contexts; context; context = context->next)
context->flags &= ~CONTEXT_RA_DONE; {
context->flags &= ~CONTEXT_RA_DONE;
context->netid.next = &context->netid;
}
if (!iface_enumerate(AF_INET6, &parm, add_prefixes) || if (!iface_enumerate(AF_INET6, &parm, add_prefixes) ||
!parm.found_context) !parm.found_context)
@@ -236,17 +239,68 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
iface_enumerate(AF_LOCAL, &iface, add_lla); iface_enumerate(AF_LOCAL, &iface, add_lla);
/* RDNSS, RFC 6106 */ /* RDNSS, RFC 6106, use relevant DHCP6 options */
put_opt6_char(ICMP6_OPT_RDNSS); (void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
put_opt6_char(3);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(&parm.link_local, IN6ADDRSZ);
for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
{
int i;
/* netids match and not encapsulated? */
if (!(opt_cfg->flags & DHOPT_TAGOK))
continue;
if (opt_cfg->opt == OPTION6_DNS_SERVER)
{
struct in6_addr *a = (struct in6_addr *)opt_cfg->val;
done_dns = 1;
if (opt_cfg->len == 0)
continue;
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char((opt_cfg->len/8) + 1);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
/* zero means "self" */
for (i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++)
if (IN6_IS_ADDR_UNSPECIFIED(a))
put_opt6(&parm.link_local, IN6ADDRSZ);
else
put_opt6(a, IN6ADDRSZ);
}
if (opt_cfg->opt == OPTION6_DOMAIN_SEARCH && opt_cfg->len != 0)
{
int len = ((opt_cfg->len+7)/8);
put_opt6_char(ICMP6_OPT_DNSSL);
put_opt6_char(len + 1);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(opt_cfg->val, opt_cfg->len);
/* pad */
for (i = opt_cfg->len; i < len * 8; i++)
put_opt6_char(0);
}
}
if (!done_dns)
{
/* default == us. */
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char(3);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(&parm.link_local, IN6ADDRSZ);
}
/* set managed bits unless we're providing only RA on this link */ /* set managed bits unless we're providing only RA on this link */
if (parm.managed) if (parm.managed)
ra->flags = 0xc0; ra->flags |= 0x80; /* M flag, managed, */
if (parm.other)
ra->flags |= 0x40; /* O flag, other */
/* decide where we're sending */ /* decide where we're sending */
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
@@ -273,9 +327,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
static int add_prefixes(struct in6_addr *local, int prefix, static int add_prefixes(struct in6_addr *local, int prefix,
int scope, int if_index, int dad, void *vparam) int scope, int if_index, int dad, void *vparam)
{ {
struct dhcp_context *context, *tmp;
struct ra_param *param = vparam; struct ra_param *param = vparam;
struct prefix_opt *opt;
(void)scope; /* warning */ (void)scope; /* warning */
(void)dad; (void)dad;
@@ -288,64 +340,92 @@ static int add_prefixes(struct in6_addr *local, int prefix,
!IN6_IS_ADDR_LINKLOCAL(local) && !IN6_IS_ADDR_LINKLOCAL(local) &&
!IN6_IS_ADDR_MULTICAST(local)) !IN6_IS_ADDR_MULTICAST(local))
{ {
int do_prefix = 0;
int do_slaac = 0;
int deprecate = 0;
unsigned int time = 0xffffffff;
struct dhcp_context *context;
for (context = daemon->ra_contexts; context; context = context->next) for (context = daemon->ra_contexts; context; context = context->next)
if (prefix == context->prefix && if (prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) && is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix)) is_same_net6(local, &context->end6, prefix))
{ {
if (!(context->flags & CONTEXT_RA_ONLY)) if ((context->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
{
do_slaac = 1;
if (context->flags & CONTEXT_DHCP)
{
param->other = 1;
if (!(context->flags & CONTEXT_RA_STATELESS))
param->managed = 1;
}
}
else
{ {
/* don't do RA for non-ra-only unless --enable-ra is set */ /* don't do RA for non-ra-only unless --enable-ra is set */
if (!option_bool(OPT_RA)) if (!option_bool(OPT_RA))
continue; continue;
param->managed = 1; param->managed = 1;
param->other = 1;
} }
if (context->flags & CONTEXT_RA_DONE) /* find floor time */
continue; if (time > context->lease_time)
time = context->lease_time;
/* subsequent prefixes on the same interface don't need timers */ if (context->flags & CONTEXT_DEPRECATE)
deprecate = 1;
/* subsequent prefixes on the same interface
and subsequent instances of this prefix don't need timers */
if (!param->first) if (!param->first)
context->ra_time = 0; context->ra_time = 0;
param->first = 0; param->first = 0;
param->found_context = 1; param->found_context = 1;
context->flags |= CONTEXT_RA_DONE;
/* mark this subnet and duplicates: as done. */ /* collect dhcp-range tags */
for (tmp = context->next; tmp; tmp = tmp->next) if (context->netid.next == &context->netid && context->netid.net)
if (tmp->prefix == prefix &&
is_same_net6(local, &tmp->start6, prefix) &&
is_same_net6(local, &tmp->end6, prefix))
{
tmp->flags |= CONTEXT_RA_DONE;
context->ra_time = 0;
}
if ((opt = expand(sizeof(struct prefix_opt))))
{ {
u64 addrpart = addr6part(&context->start6); context->netid.next = param->tags;
u64 mask = (prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU; param->tags = &context->netid;
unsigned int time = context->lease_time; }
/* lifetimes must be min 2 hrs, by RFC 2462 */ if (!(context->flags & CONTEXT_RA_DONE))
if (time < 7200) {
time = 7200; context->flags |= CONTEXT_RA_DONE;
do_prefix = 1;
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = prefix;
/* autonomous only is we're not doing dhcp */
opt->flags = (context->flags & CONTEXT_RA_ONLY) ? 0xc0 : 0x00;
opt->valid_lifetime = opt->preferred_lifetime = htonl(time);
opt->reserved = 0;
opt->prefix = context->start6;
setaddr6part(&opt->prefix, addrpart & ~mask);
inet_ntop(AF_INET6, &opt->prefix, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff);
} }
} }
if (do_prefix)
{
struct prefix_opt *opt;
if ((opt = expand(sizeof(struct prefix_opt))))
{
/* zero net part of address */
setaddr6part(local, addr6part(local) & ~((prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU));
/* lifetimes must be min 2 hrs, by RFC 2462 */
if (time < 7200)
time = 7200;
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = prefix;
/* autonomous only if we're not doing dhcp */
opt->flags = do_slaac ? 0x40 : 0x00;
opt->valid_lifetime = htonl(time);
opt->preferred_lifetime = htonl(deprecate ? 0 : time);
opt->reserved = 0;
opt->prefix = *local;
inet_ntop(AF_INET6, local, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff);
}
}
} }
} }
return 1; return 1;
@@ -387,11 +467,11 @@ time_t periodic_ra(time_t now)
for (next_event = 0, context = daemon->ra_contexts; context; context = context->next) for (next_event = 0, context = daemon->ra_contexts; context; context = context->next)
if (context->ra_time != 0) if (context->ra_time != 0)
{ {
if (difftime(context->ra_time, now) < 0.0) if (difftime(context->ra_time, now) <= 0.0)
break; /* overdue */ break; /* overdue */
if (next_event == 0 || difftime(next_event, context->ra_time + 2) > 0.0) if (next_event == 0 || difftime(next_event, context->ra_time) > 0.0)
next_event = context->ra_time + 2; next_event = context->ra_time;
} }
/* none overdue */ /* none overdue */
+27 -4
View File
@@ -1003,10 +1003,16 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
} }
} }
/* Don't put stuff from a truncated packet into the cache, /* Don't put stuff from a truncated packet into the cache.
also don't cache replies where DNSSEC validation was turned off, either Don't cache replies where DNSSEC validation was turned off, either
the upstream server told us so, or the original query specified it. */ the upstream server told us so, or the original query specified it.
if (!(header->hb3 & HB3_TC) && !(header->hb4 & HB4_CD) && !checking_disabled) Don't cache replies from non-recursive nameservers, since we may get a
reply containing a CNAME but not its target, even though the target
does exist. */
if (!(header->hb3 & HB3_TC) &&
!(header->hb4 & HB4_CD) &&
(header->hb4 & HB4_RA) &&
!checking_disabled)
cache_end_insert(); cache_end_insert();
return 0; return 0;
@@ -1634,6 +1640,23 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
} }
} }
if (qtype == T_CNAME || qtype == T_ANY)
{
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP))))
{
ans = 1;
if (!dryrun)
{
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), &nameoffset,
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
anscount++;
}
}
}
if (qtype == T_MX || qtype == T_ANY) if (qtype == T_MX || qtype == T_ANY)
{ {
int found = 0; int found = 0;
+2 -1
View File
@@ -2095,7 +2095,8 @@ static void do_options(struct dhcp_context *context,
struct dhcp_netid_list *id_list; struct dhcp_netid_list *id_list;
/* filter options based on tags, those we want get DHOPT_TAGOK bit set */ /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
context->netid.next = NULL; if (context)
context->netid.next = NULL;
tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts); tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
/* logging */ /* logging */
+40 -35
View File
@@ -349,28 +349,28 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (len != 0 && len < 255) if (len != 0 && len < 255)
{ {
unsigned char *pp, *op = opt6_ptr(opt, 1); unsigned char *pp, *op = opt6_ptr(opt, 1);
char *pq = daemon->dhcp_buff; char *pq = daemon->dhcp_buff;
pp = op; pp = op;
while (*op != 0 && ((op + (*op) + 1) - pp) < len) while (*op != 0 && ((op + (*op)) - pp) < len)
{ {
memcpy(pq, op+1, *op); memcpy(pq, op+1, *op);
pq += *op; pq += *op;
op += (*op)+1; op += (*op)+1;
*(pq++) = '.'; *(pq++) = '.';
} }
if (pq != daemon->dhcp_buff) if (pq != daemon->dhcp_buff)
pq--; pq--;
*pq = 0; *pq = 0;
if (legal_hostname(daemon->dhcp_buff)) if (legal_hostname(daemon->dhcp_buff))
{ {
client_hostname = daemon->dhcp_buff; client_hostname = daemon->dhcp_buff;
if (option_bool(OPT_LOG_OPTS)) if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), xid, client_hostname); my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), xid, client_hostname);
} }
} }
} }
@@ -513,13 +513,13 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
while (1) while (1)
{ {
struct in6_addr alloced_addr, *addrp = NULL; struct in6_addr alloced_addr, *addrp = NULL;
u32 preferred_time = 0; u32 requested_time = 0;
struct dhcp_lease *lease = NULL; struct dhcp_lease *lease = NULL;
if (ia_option) if (ia_option)
{ {
struct in6_addr *req_addr = opt6_ptr(ia_option, 0); struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
preferred_time = opt6_uint(ia_option, 16, 4); requested_time = opt6_uint(ia_option, 16, 4);
if (!address6_available(context, req_addr, tags) && if (!address6_available(context, req_addr, tags) &&
(!have_config(config, CONFIG_ADDR6) || memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0)) (!have_config(config, CONFIG_ADDR6) || memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0))
@@ -621,10 +621,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (ia_option) if (ia_option)
{ {
if (preferred_time < 120u ) if (requested_time < 120u )
preferred_time = 120u; /* sanity */ requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (preferred_time != 0xffffffff && preferred_time < lease_time)) if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = preferred_time; lease_time = requested_time;
} }
if (lease_time < min_time) if (lease_time < min_time)
@@ -730,8 +730,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
o1 = new_opt6(OPTION6_IAADDR); o1 = new_opt6(OPTION6_IAADDR);
put_opt6(addrp, sizeof(*addrp)); put_opt6(addrp, sizeof(*addrp));
put_opt6_long(lease_time); /* preferred lifetime */
put_opt6_long(lease_time); put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
put_opt6_long(lease_time); /* valid lifetime */
end_opt6(o1); end_opt6(o1);
log6_packet( make_lease ? "DHCPREPLY" : "DHCPADVERTISE", log6_packet( make_lease ? "DHCPREPLY" : "DHCPADVERTISE",
@@ -842,7 +843,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{ {
struct dhcp_lease *lease = NULL; struct dhcp_lease *lease = NULL;
struct in6_addr *req_addr = opt6_ptr(ia_option, 0); struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
u32 preferred_time = opt6_uint(ia_option, 16, 4); u32 requested_time = opt6_uint(ia_option, 16, 4);
unsigned int lease_time; unsigned int lease_time;
struct dhcp_context *this_context; struct dhcp_context *this_context;
struct dhcp_config *valid_config = config; struct dhcp_config *valid_config = config;
@@ -873,7 +874,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (!address6_available(context, req_addr, tagif) || if (!address6_available(context, req_addr, tagif) ||
!(this_context = narrow_context6(context, req_addr, tagif))) !(this_context = narrow_context6(context, req_addr, tagif)))
lease_time = 0; {
lease_time = 0;
this_context = NULL;
}
else else
{ {
/* get tags from context if we've not used it before */ /* get tags from context if we've not used it before */
@@ -895,10 +899,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time; lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time;
if (preferred_time < 120u ) if (requested_time < 120u )
preferred_time = 120u; /* sanity */ requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (preferred_time != 0xffffffff && preferred_time < lease_time)) if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = preferred_time; lease_time = requested_time;
lease_set_expires(lease, lease_time, now); lease_set_expires(lease, lease_time, now);
if (ia_type == OPTION6_IA_NA && hostname) if (ia_type == OPTION6_IA_NA && hostname)
@@ -917,8 +921,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
o1 = new_opt6(OPTION6_IAADDR); o1 = new_opt6(OPTION6_IAADDR);
put_opt6(req_addr, sizeof(*req_addr)); put_opt6(req_addr, sizeof(*req_addr));
put_opt6_long(lease_time); /* preferred lifetime */
put_opt6_long(lease_time); put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
put_opt6_long(lease_time); /* valid lifetime */
end_opt6(o1); end_opt6(o1);
} }
+18 -12
View File
@@ -108,8 +108,8 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
{ {
struct dhcp_context *context; struct dhcp_context *context;
struct dhcp_lease *lease; struct dhcp_lease *lease;
struct slaac_address *slaac; struct slaac_address *slaac;
time_t next_event = 0; time_t next_event = 0;
for (context = daemon->ra_contexts; context; context = context->next) for (context = daemon->ra_contexts; context; context = context->next)
if ((context->flags & CONTEXT_RA_NAME)) if ((context->flags & CONTEXT_RA_NAME))
@@ -131,8 +131,8 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
for (slaac = lease->slaac_address; slaac; slaac = slaac->next) for (slaac = lease->slaac_address; slaac; slaac = slaac->next)
{ {
/* confirmed? */ /* confirmed or given up? */
if (slaac->backoff == 0) if (slaac->backoff == 0 || slaac->ping_time == 0)
continue; continue;
if (difftime(slaac->ping_time, now) <= 0.0) if (difftime(slaac->ping_time, now) <= 0.0)
@@ -155,16 +155,22 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
addr.sin6_port = htons(IPPROTO_ICMPV6); addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = slaac->addr; addr.sin6_addr = slaac->addr;
send_from(daemon->icmp6fd, 0, daemon->outpacket.iov_base, save_counter(0), if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
(union mysockaddr *)&addr, (struct all_addr *)&slaac->local, lease->last_interface); (struct sockaddr *)&addr, sizeof(addr)) == -1 &&
errno == EHOSTUNREACH)
slaac->ping_time += (1 << (slaac->backoff - 1)) + (rand16()/21785); /* 0 - 3 */ slaac->ping_time = 0; /* Give up */
if (slaac->backoff > 4) else
slaac->ping_time += rand16()/4000; /* 0 - 15 */ {
slaac->backoff++; slaac->ping_time += (1 << (slaac->backoff - 1)) + (rand16()/21785); /* 0 - 3 */
if (slaac->backoff > 4)
slaac->ping_time += rand16()/4000; /* 0 - 15 */
if (slaac->backoff < 12)
slaac->backoff++;
}
} }
if (next_event == 0 || difftime(next_event, slaac->ping_time) >= 0.0) if (slaac->ping_time != 0 &&
(next_event == 0 || difftime(next_event, slaac->ping_time) >= 0.0))
next_event = slaac->ping_time; next_event = slaac->ping_time;
} }
+46 -13
View File
@@ -57,7 +57,7 @@ void tftp_request(struct listener *listen, time_t now)
int mtuflag = IP_PMTUDISC_DONT; int mtuflag = IP_PMTUDISC_DONT;
#endif #endif
char namebuff[IF_NAMESIZE]; char namebuff[IF_NAMESIZE];
char *name; char *name = NULL;
char *prefix = daemon->tftp_prefix; char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref; struct tftp_prefix *pref;
struct interface_list *ir; struct interface_list *ir;
@@ -95,9 +95,20 @@ void tftp_request(struct listener *listen, time_t now)
if (option_bool(OPT_NOWILD)) if (option_bool(OPT_NOWILD))
{ {
addr = listen->iface->addr; if (listen->iface)
mtu = listen->iface->mtu; {
name = listen->iface->name; addr = listen->iface->addr;
mtu = listen->iface->mtu;
name = listen->iface->name;
}
else
{
/* we're listening on an address that doesn't appear on an interface,
ask the kernel what the socket is bound to */
socklen_t tcp_len = sizeof(union mysockaddr);
if (getsockname(listen->tftpfd, (struct sockaddr *)&addr, &tcp_len) == -1)
return;
}
} }
else else
{ {
@@ -211,15 +222,18 @@ void tftp_request(struct listener *listen, time_t now)
mtu = ifr.ifr_mtu; mtu = ifr.ifr_mtu;
} }
/* check for per-interface prefix */ if (name)
for (pref = daemon->if_prefix; pref; pref = pref->next) {
if (strcmp(pref->interface, name) == 0) /* check for per-interface prefix */
prefix = pref->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. */ /* wierd TFTP interfaces disable special options. */
for (ir = daemon->tftp_interfaces; ir; ir = ir->next) for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, name) == 0) if (strcmp(ir->interface, name) == 0)
special = 1; special = 1;
}
if (listen->family == AF_INET) if (listen->family == AF_INET)
{ {
@@ -571,7 +585,9 @@ void check_tftp_listeners(fd_set *rset, time_t now)
my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, daemon->addrbuff); my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, daemon->addrbuff);
/* unlink */ /* unlink */
*up = tmp; *up = tmp;
free_transfer(transfer); /* put on queue to be sent to script and deleted */
transfer->next = daemon->tftp_done_trans;
daemon->tftp_done_trans = transfer;
continue; continue;
} }
} }
@@ -709,4 +725,21 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
} }
} }
int do_tftp_script_run(void)
{
struct tftp_transfer *transfer;
if ((transfer = daemon->tftp_done_trans))
{
daemon->tftp_done_trans = transfer->next;
#ifdef HAVE_SCRIPT
queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer);
#endif
free_transfer(transfer);
return 1;
}
return 0;
}
#endif #endif