mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
113
Commits
v2.63test2
...
v2.66test4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b43646a08 | ||
|
|
3bc0d932d0 | ||
|
|
60225f4e75 | ||
|
|
1962446269 | ||
|
|
be37986a0f | ||
|
|
d7346a1e8c | ||
|
|
87d346f6a7 | ||
|
|
f0dd7f807d | ||
|
|
0c0502426f | ||
|
|
7f035f58c6 | ||
|
|
81e84f8dac | ||
|
|
55b42f6de3 | ||
|
|
ed8b68ad06 | ||
|
|
bad7b875eb | ||
|
|
5d162f20a9 | ||
|
|
9d29949440 | ||
|
|
1b75c1e61f | ||
|
|
293fd0f700 | ||
|
|
c1be917782 | ||
|
|
bb86e858b6 | ||
|
|
8445f5d2e2 | ||
|
|
72c9c3b11b | ||
|
|
6e3dba3fde | ||
|
|
7558ecd9ac | ||
|
|
1f776932a1 | ||
|
|
4820dce97a | ||
|
|
f8abe0c566 | ||
|
|
9def963c65 | ||
|
|
990123a937 | ||
|
|
1d6c639310 | ||
|
|
429798fd08 | ||
|
|
b5a8dd1dec | ||
|
|
95a0bd3701 | ||
|
|
8ff556739e | ||
|
|
496787677e | ||
|
|
e1ff419cf9 | ||
|
|
ee86ce68fc | ||
|
|
b75e936372 | ||
|
|
aa79235194 | ||
|
|
7c305be1bd | ||
|
|
f7fe362721 | ||
|
|
36bec089f7 | ||
|
|
45dd1fece4 | ||
|
|
29d28dda95 | ||
|
|
421594f83d | ||
|
|
d89fb4ed4f | ||
|
|
295a54eed3 | ||
|
|
5c0bd5b112 | ||
|
|
86e3b9a026 | ||
|
|
2f38141f43 | ||
|
|
8273ea5a19 | ||
|
|
4f7b304f53 | ||
|
|
8e4b87918f | ||
|
|
83b2198e86 | ||
|
|
d1a5975f9b | ||
|
|
52002051ad | ||
|
|
b191a77901 | ||
|
|
23780dd577 | ||
|
|
d1e9a582ad | ||
|
|
819ff4dd0f | ||
|
|
de604c18a0 | ||
|
|
be6cfb42ab | ||
|
|
2022310f95 | ||
|
|
657ed09693 | ||
|
|
c99df938d7 | ||
|
|
cf568a3726 | ||
|
|
e4807d8bb2 | ||
|
|
35239a302a | ||
|
|
db3946c358 | ||
|
|
0d28af84d0 | ||
|
|
42698cb7ab | ||
|
|
1d860415f2 | ||
|
|
289a253569 | ||
|
|
faafb3f7b7 | ||
|
|
2b127a1eab | ||
|
|
dfb23b3f77 | ||
|
|
b269221c00 | ||
|
|
8b46061e73 | ||
|
|
4d0f5b4c44 | ||
|
|
1dedeb87cc | ||
|
|
79cfefd856 | ||
|
|
0c0d4793ac | ||
|
|
12d71ed28c | ||
|
|
9fed0f71c2 | ||
|
|
2e34ac1403 | ||
|
|
bc54ae392b | ||
|
|
00acd06340 | ||
|
|
476e4a03c1 | ||
|
|
5f11b3e5e0 | ||
|
|
3169daad46 | ||
|
|
fd05f12790 | ||
|
|
ad094275b0 | ||
|
|
c740e4f342 | ||
|
|
132255b5da | ||
|
|
c4c0488ac6 | ||
|
|
a2ce6fcc91 | ||
|
|
12090548d2 | ||
|
|
8223cb15e7 | ||
|
|
4ba9b38cc5 | ||
|
|
42243214b5 | ||
|
|
23245c0cb2 | ||
|
|
b271446f82 | ||
|
|
611ebc5f1e | ||
|
|
be0f45cdbc | ||
|
|
9b40cbf587 | ||
|
|
c4a7f90ebb | ||
|
|
9609baee41 | ||
|
|
395eb71931 | ||
|
|
8bc4cecee6 | ||
|
|
6b617c0d15 | ||
|
|
55d290a3bf | ||
|
|
e17b4b3871 | ||
|
|
236e072cab |
No files matched your search
+13
@@ -0,0 +1,13 @@
|
|||||||
|
src/*.o
|
||||||
|
src/*.mo
|
||||||
|
src/dnsmasq.pot
|
||||||
|
src/dnsmasq
|
||||||
|
src/.configured
|
||||||
|
contrib/wrt/dhcp_lease_time
|
||||||
|
contrib/wrt/dhcp_release
|
||||||
|
debian/base/
|
||||||
|
debian/daemon/
|
||||||
|
debian/files
|
||||||
|
debian/substvars
|
||||||
|
debian/utils-substvars
|
||||||
|
debian/utils/
|
||||||
@@ -1,3 +1,85 @@
|
|||||||
|
version 2.65
|
||||||
|
Fix regression which broke forwarding of queries sent via
|
||||||
|
TCP which are not for A and AAAA and which were directed to
|
||||||
|
non-default servers. Thanks to Niax for the bug report.
|
||||||
|
|
||||||
|
Fix failure to build with DHCP support excluded. Thanks to
|
||||||
|
Gustavo Zacarias for the patch.
|
||||||
|
|
||||||
|
Fix nasty regression in 2.64 which completely broke cacheing.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.64
|
||||||
|
Handle DHCP FQDN options with all flag bits zero and
|
||||||
|
--dhcp-client-update set. Thanks to Bernd Krumbroeck for
|
||||||
|
spotting the problem.
|
||||||
|
|
||||||
|
Finesse the check for /etc/hosts names which conflict with
|
||||||
|
DHCP names. Previously a name/address pair in /etc/hosts
|
||||||
|
which didn't match the name/address of a DHCP lease would
|
||||||
|
generate a warning. Now that only happesn if there is not
|
||||||
|
also a match. This allows multiple addresses for a name in
|
||||||
|
/etc/hosts with one of them assigned via DHCP.
|
||||||
|
|
||||||
|
Fix broken vendor-option processing for BOOTP. Thanks to
|
||||||
|
Hans-Joachim Baader for the bug report.
|
||||||
|
|
||||||
|
Don't report spurious netlink errors, regression in
|
||||||
|
2.63. Thanks to Vladislav Grishenko for the patch.
|
||||||
|
|
||||||
|
Flag DHCP or DHCPv6 in starup logging. Thanks to
|
||||||
|
Vladislav Grishenko for the patch.
|
||||||
|
|
||||||
|
Add SetServersEx method in DBus interface. Thanks to Dan
|
||||||
|
Williams for the patch.
|
||||||
|
|
||||||
|
Add SetDomainServers method in DBus interface. Thanks to
|
||||||
|
Roy Marples for the patch.
|
||||||
|
|
||||||
|
Fix build with later Lua libraries. Thansk to Cristian
|
||||||
|
Rodriguez for the patch.
|
||||||
|
|
||||||
|
Add --max-cache-ttl option. Thanks to Dennis Kaarsemaker
|
||||||
|
for the patch.
|
||||||
|
|
||||||
|
Fix breakage of --host-record parsing, resulting in
|
||||||
|
infinte loop at startup. Regression in 2.63. Thanks to
|
||||||
|
Haim Gelfenbeyn for spotting this.
|
||||||
|
|
||||||
|
Set SO_REUSEADDRESS and SO_V6ONLY options on the DHCPv6
|
||||||
|
socket, this allows multiple instances of dnsmasq on a
|
||||||
|
single machine, in the same way as for DHCPv4. Thanks to
|
||||||
|
Gene Czarcinski and Vladislav Grishenko for work on this.
|
||||||
|
|
||||||
|
Fix DHCPv6 to do access control correctly when it's
|
||||||
|
configured with --listen-address. Thanks to
|
||||||
|
Gene Czarcinski for sorting this out.
|
||||||
|
|
||||||
|
Add a "wildcard" dhcp-range which works for any IPv6
|
||||||
|
subnet, --dhcp-range=::,static Useful for Stateless
|
||||||
|
DHCPv6. Thanks to Vladislav Grishenko for the patch.
|
||||||
|
|
||||||
|
Don't include lease-time in DHCPACK replies to DHCPINFORM
|
||||||
|
queries, since RFC-2131 says we shouldn't. Thanks to
|
||||||
|
Wouter Ibens for pointing this out.
|
||||||
|
|
||||||
|
Makefile tweak to do dependency checking on header files.
|
||||||
|
Thanks to Johan Peeters for the patch.
|
||||||
|
|
||||||
|
Check interface for outgoing unsolicited router
|
||||||
|
advertisements, rather than relying on interface address
|
||||||
|
configuration. Thanks to Gene Czarinski for the patch.
|
||||||
|
|
||||||
|
Handle better attempts to transmit on interfaces which are
|
||||||
|
still doing DAD, and specifically do not just transmit
|
||||||
|
without setting source address and interface, since this
|
||||||
|
can cause very puzzling effects when a router
|
||||||
|
advertisement goes astray. Thanks again to Gene Czarinski.
|
||||||
|
|
||||||
|
Get RA timers right when there is more than one
|
||||||
|
dhcp-range on a subnet.
|
||||||
|
|
||||||
|
|
||||||
version 2.63
|
version 2.63
|
||||||
Do duplicate dhcp-host address check in --test mode.
|
Do duplicate dhcp-host address check in --test mode.
|
||||||
|
|
||||||
@@ -10,6 +92,43 @@ version 2.63
|
|||||||
Add --bind-dynamic. A hybrid mode between the default and
|
Add --bind-dynamic. A hybrid mode between the default and
|
||||||
--bind-interfaces which copes with dynamically created
|
--bind-interfaces which copes with dynamically created
|
||||||
interfaces.
|
interfaces.
|
||||||
|
|
||||||
|
A couple of fixes to the build system for Android. Thanks
|
||||||
|
to Metin Kaya for the patches.
|
||||||
|
|
||||||
|
Remove the interface:<interface> argument in --dhcp-range, and
|
||||||
|
the interface argument to --enable-tftp. These were a
|
||||||
|
still-born attempt to allow automatic isolated
|
||||||
|
configuration by libvirt, but have never (to my knowledge)
|
||||||
|
been used, had very strange semantics, and have been
|
||||||
|
superceded by other mechanisms.
|
||||||
|
|
||||||
|
Fixed bug logging filenames when duplicate dhcp-host
|
||||||
|
addresses are found. Thanks to John Hanks for the patch.
|
||||||
|
|
||||||
|
Fix regression in 2.61 which broke caching of CNAME
|
||||||
|
chains. Thanks to Atul Gupta for the bug report.
|
||||||
|
|
||||||
|
Allow the target of a --cname flag to be another --cname.
|
||||||
|
|
||||||
|
Teach DHCPv6 about the RFC 4242 information-refresh-time
|
||||||
|
option, and add parsing if the minutes, hours and days
|
||||||
|
format for options. Thanks to Francois-Xavier Le Bail for
|
||||||
|
the suggestion.
|
||||||
|
|
||||||
|
Allow "w" (for week) as multiplier in lease times, as well
|
||||||
|
as seconds, minutes, hours and days. Álvaro Gámez Machado
|
||||||
|
spotted the ommission.
|
||||||
|
|
||||||
|
Update French translation. Thanks to Gildas Le Nadan.
|
||||||
|
|
||||||
|
Allow a DBus service name to be given with --enable-dbus
|
||||||
|
which overrides the default,
|
||||||
|
uk.org.thekelleys.dnsmasq. Thanks to Mathieu
|
||||||
|
Trudel-Lapierre for the patch.
|
||||||
|
|
||||||
|
Set the "prefix on-link" bit in Router
|
||||||
|
Advertisements. Thanks to Gui Iribarren for the patch.
|
||||||
|
|
||||||
|
|
||||||
version 2.62
|
version 2.62
|
||||||
@@ -36,7 +155,6 @@ version 2.62
|
|||||||
two addresses in the same network. Thanks to Jim Bos for
|
two addresses in the same network. Thanks to Jim Bos for
|
||||||
his help nailing this.
|
his help nailing this.
|
||||||
|
|
||||||
|
|
||||||
version 2.61
|
version 2.61
|
||||||
Re-write interface discovery code on *BSD to use
|
Re-write interface discovery code on *BSD to use
|
||||||
getifaddrs. This is more portable, more straightforward,
|
getifaddrs. This is more portable, more straightforward,
|
||||||
@@ -323,7 +441,7 @@ version 2.58
|
|||||||
|
|
||||||
Fix regression in TFTP server on *BSD platforms introduced
|
Fix regression in TFTP server on *BSD platforms introduced
|
||||||
in version 2.56, due to confusion with sockaddr
|
in version 2.56, due to confusion with sockaddr
|
||||||
length. Many thanks to Loïc Pefferkorn for finding this.
|
length. Many thanks to Loic Pefferkorn for finding this.
|
||||||
|
|
||||||
Support scope-ids in IPv6 addresses of nameservers from
|
Support scope-ids in IPv6 addresses of nameservers from
|
||||||
/etc/resolv.conf and in --server options. Eg
|
/etc/resolv.conf and in --server options. Eg
|
||||||
|
|||||||
@@ -236,53 +236,70 @@ Q: What network types are supported by the DHCP server?
|
|||||||
A: Ethernet (and 802.11 wireless) are supported on all platforms. On
|
A: Ethernet (and 802.11 wireless) are supported on all platforms. On
|
||||||
Linux all network types (including FireWire) are supported.
|
Linux all network types (including FireWire) are supported.
|
||||||
|
|
||||||
Q: What is this strange "bind-interface" option?
|
Q: What are these strange "bind-interface" and "bind-dynamic" options?
|
||||||
|
|
||||||
A: The DNS spec says that the reply to a DNS query must come from the
|
A: Dnsmasq from v2.63 can operate in one of three different "networking
|
||||||
same address it was sent to. The traditional way to write an UDP
|
modes". This is unfortunate as it requires users configuring dnsmasq
|
||||||
server to do this is to find all of the addresses belonging to the
|
to take into account some rather bizzare contraints and select the
|
||||||
machine (ie all the interfaces on the machine) and then create a
|
mode which best fits the requirements of a particular installation.
|
||||||
socket for each interface which is bound to the address of the
|
The origin of these are deficiencies in the Unix networking
|
||||||
interface. Then when a packet is sent to address A, it is received
|
model and APIs and each mode has different advantages and
|
||||||
on the socket bound to address A and when the reply is also sent
|
problems. Just to add to the confusion, not all modes are available on
|
||||||
via that socket, the source address is set to A by the kernel and
|
all platforms (due the to lack of supporting network APIs).To further
|
||||||
everything works. This is the how dnsmasq works when
|
add to the confusion, the rules for the DHCP subsystem on dnsmasq are
|
||||||
"bind-interfaces" is set, with the obvious extension that is misses
|
different to the rules for the DNS and TFTP subsystems.
|
||||||
out creating sockets for some interfaces depending on the
|
|
||||||
--interface, --address and --except-interface flags. The
|
|
||||||
disadvantage of this approach is that it breaks if interfaces don't
|
|
||||||
exist or are not configured when the daemon starts and does the
|
|
||||||
socket creation step. In a hotplug-aware world this is a real
|
|
||||||
problem.
|
|
||||||
|
|
||||||
The alternative approach is to have only one socket, which is bound
|
The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
|
||||||
to the correct port and the wildcard IP address (0.0.0.0). That
|
|
||||||
socket will receive _all_ packets sent to port 53, no matter what
|
|
||||||
destination address they have. This solves the problem of
|
|
||||||
interfaces which are created or reconfigured after daemon
|
|
||||||
start-up. To make this work is more complicated because of the
|
|
||||||
"reply source address" problem. When a UDP packet is sent by a
|
|
||||||
socket bound to 0.0.0.0 its source address will be set to the
|
|
||||||
address of one of the machine's interfaces, but which one is not
|
|
||||||
determined and can vary depending on the OS being run. To get round
|
|
||||||
this it is neccessary to use a scary advanced API to determine the
|
|
||||||
address to which a query was sent, and force that to be the source
|
|
||||||
address in the reply. For IPv4 this stuff in non-portable and quite
|
|
||||||
often not even available (It's different between FreeBSD 5.x and
|
|
||||||
Linux, for instance, and FreeBSD 4.x, Linux 2.0.x and OpenBSD don't
|
|
||||||
have it at all.) Hence "bind-interfaces" has to always be available
|
|
||||||
as a fall back. For IPv6 the API is standard and universally
|
|
||||||
available.
|
|
||||||
|
|
||||||
It could be argued that if the --interface or --address flags are
|
In "wildcard" mode, dnsmasq binds the wildcard IP address (0.0.0.0 or
|
||||||
used then binding interfaces is more appropriate, but using
|
::). This allows it to recieve all the packets sent to the server on
|
||||||
wildcard binding means that dnsmasq will quite happily start up
|
the relevant port. Access control (--interface, --except-interface,
|
||||||
after being told to use interfaces which don't exist, but which are
|
--listen-address, etc) is implemented by dnsmasq: it queries the
|
||||||
created later. Wildcard binding breaks the scenario when dnsmasq is
|
kernel to determine the interface on which a packet was recieved and
|
||||||
listening on one interface and another server (most probably BIND)
|
the address to which it was sent, and applies the configured
|
||||||
is listening on another. It's not possible for BIND to bind to an
|
rules. Wildcard mode is the default if neither of the other modes are
|
||||||
(address,port) pair when dnsmasq has bound (wildcard,port), hence
|
specified.
|
||||||
the ability to explicitly turn off wildcard binding.
|
|
||||||
|
In "bind-interfaces" mode, dnsmasq runs through all the network
|
||||||
|
interfaces available when it starts, finds the set of IP addresses on
|
||||||
|
those interfaces, filters that set using the access control
|
||||||
|
configuration, and then binds the set of IP addresses. Only packets
|
||||||
|
sent to the allowed addresses are delivered by the kernel to dnsmasq.
|
||||||
|
|
||||||
|
In "bind-dynamic" mode, access control filtering is done both by
|
||||||
|
binding individual IP addresses, as for bind-interfaces, and by
|
||||||
|
inspecting individual packets on arrival as for wildcard mode. In
|
||||||
|
addition, dnsmasq notices when new interfaces appear or new addresses
|
||||||
|
appear on existing interfaces, and the resulting IP addresses are
|
||||||
|
bound automatically without having to restart dnsmasq.
|
||||||
|
|
||||||
|
The mode chosen has four different effects: co-existence with other
|
||||||
|
servers, semantics of --interface access control, effect of new
|
||||||
|
interfaces, and legality of --interface specifications for
|
||||||
|
non-existent inferfaces. We will deal with these in order.
|
||||||
|
|
||||||
|
A dnsmasq instance running in wildcard mode precludes a machine from
|
||||||
|
running a second instance of dnsmasq or any other DNS, TFTP or DHCP
|
||||||
|
server. Attempts to do so will fail with an "address in use" error.
|
||||||
|
Dnsmasq running in --bind-interfaces or bind-dynamic mode allow other
|
||||||
|
instances of dnsmasq or other servers, as long as no two servers are
|
||||||
|
configured to listen on the same interface address.
|
||||||
|
|
||||||
|
The semantics of --interface varies subtly between wildcard or
|
||||||
|
bind-dynamic mode and bind-interfaces mode. The situation where this
|
||||||
|
matters is a request which arrives via one interface (A), but with a
|
||||||
|
destination address of a second interface (B) and when dnsmasq is
|
||||||
|
configured to listen only on B. In wildcard or bind-dynamic mode, such
|
||||||
|
a request will be ignored, in bind-interfaces mode, it will be
|
||||||
|
accepted.
|
||||||
|
|
||||||
|
The creation of new network interfaces after dnsmasq starts is ignored
|
||||||
|
by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
|
||||||
|
mode, such interfaces are handled normally.
|
||||||
|
|
||||||
|
A --interface specification for a non-existent interface is a fatal
|
||||||
|
error at start-up when in --bind-interfaces mode, by just generates a
|
||||||
|
warning in wildcard or bind-dynamic mode.
|
||||||
|
|
||||||
Q: Why doesn't Kerberos work/why can't I get sensible answers to
|
Q: Why doesn't Kerberos work/why can't I get sensible answers to
|
||||||
queries for SRV records.
|
queries for SRV records.
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
|||||||
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||||
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
||||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||||
dhcp-common.o outpacket.o radv.o slaac.o
|
dhcp-common.o outpacket.o radv.o slaac.o auth.o
|
||||||
|
|
||||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||||
dns-protocol.h radv-protocol.h
|
dns-protocol.h radv-protocol.h
|
||||||
@@ -79,7 +79,8 @@ all : $(BUILDDIR)
|
|||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f *~ $(BUILDDIR)/*.mo contrib/*/*~ */*~ $(BUILDDIR)/*.pot
|
rm -f *~ $(BUILDDIR)/*.mo contrib/*/*~ */*~ $(BUILDDIR)/*.pot
|
||||||
rm -f $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq core */core
|
rm -f $(BUILDDIR)/.configured $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq
|
||||||
|
rm -rf core */core
|
||||||
|
|
||||||
install : all install-common
|
install : all install-common
|
||||||
|
|
||||||
@@ -113,7 +114,11 @@ $(BUILDDIR):
|
|||||||
mkdir -p $(BUILDDIR)
|
mkdir -p $(BUILDDIR)
|
||||||
|
|
||||||
|
|
||||||
# rules below are targets in recusive makes with cwd=$(SRC)
|
# rules below are targets in recusive makes with cwd=$(BUILDDIR)
|
||||||
|
|
||||||
|
.configured: $(hdrs)
|
||||||
|
@rm -f *.o
|
||||||
|
@touch $@
|
||||||
|
|
||||||
$(objs:.o=.c) $(hdrs):
|
$(objs:.o=.c) $(hdrs):
|
||||||
ln -s $(top)/$(SRC)/$@ .
|
ln -s $(top)/$(SRC)/$@ .
|
||||||
@@ -121,7 +126,7 @@ $(objs:.o=.c) $(hdrs):
|
|||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $<
|
$(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $<
|
||||||
|
|
||||||
dnsmasq : $(hdrs) $(objs)
|
dnsmasq : .configured $(hdrs) $(objs)
|
||||||
$(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS)
|
$(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS)
|
||||||
|
|
||||||
dnsmasq.pot : $(objs:.o=.c) $(hdrs)
|
dnsmasq.pot : $(objs:.o=.c) $(hdrs)
|
||||||
|
|||||||
+3
-1
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
|||||||
netlink.c network.c option.c rfc1035.c \
|
netlink.c network.c option.c rfc1035.c \
|
||||||
rfc2131.c tftp.c util.c conntrack.c \
|
rfc2131.c tftp.c util.c conntrack.c \
|
||||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||||
radv.c slaac.c
|
radv.c slaac.c auth.c
|
||||||
|
|
||||||
LOCAL_MODULE := dnsmasq
|
LOCAL_MODULE := dnsmasq
|
||||||
|
|
||||||
@@ -17,4 +17,6 @@ LOCAL_C_INCLUDES := external/dnsmasq/src
|
|||||||
LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
|
LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
|
||||||
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils
|
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils
|
||||||
|
|
||||||
|
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
+4
-2
@@ -8,6 +8,8 @@
|
|||||||
# which has a set of references substituted into it by git.
|
# which has a set of references substituted into it by git.
|
||||||
# If we can find one which matches $v[0-9].* then we assume it's
|
# If we can find one which matches $v[0-9].* then we assume it's
|
||||||
# a version-number tag, else we just use the whole string.
|
# a version-number tag, else we just use the whole string.
|
||||||
|
# If there is more than one v[0-9].* tag, sort them and use the
|
||||||
|
# first. This favours, eg v2.63 over 2.63rc6.
|
||||||
|
|
||||||
if which git >/dev/null 2>&1 && [ -d $1/.git ]; then
|
if which git >/dev/null 2>&1 && [ -d $1/.git ]; then
|
||||||
cd $1; git describe
|
cd $1; git describe
|
||||||
@@ -15,10 +17,10 @@ elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
|
|||||||
# unsubstituted VERSION, but no git available.
|
# unsubstituted VERSION, but no git available.
|
||||||
echo UNKNOWN
|
echo UNKNOWN
|
||||||
else
|
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 | sed 's/^v//'
|
echo "${vers}" | sort | head -n 1 | sed 's/^v//'
|
||||||
else
|
else
|
||||||
cat $1/VERSION
|
cat $1/VERSION
|
||||||
fi
|
fi
|
||||||
|
|||||||
Executable
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import dbus
|
||||||
|
|
||||||
|
bus = dbus.SystemBus()
|
||||||
|
p = bus.get_object("uk.org.thekelleys.dnsmasq", "/uk/org/thekelleys/dnsmasq")
|
||||||
|
l = dbus.Interface(p, dbus_interface="uk.org.thekelleys.dnsmasq")
|
||||||
|
|
||||||
|
# The new more flexible SetServersEx method
|
||||||
|
array = dbus.Array()
|
||||||
|
array.append(["1.2.3.5"])
|
||||||
|
array.append(["1.2.3.4#664", "foobar.com"])
|
||||||
|
array.append(["1003:1234:abcd::1%eth0", "eng.mycorp.com", "lab.mycorp.com"])
|
||||||
|
print l.SetServersEx(array)
|
||||||
|
|
||||||
|
# Must create a new object for dnsmasq as the introspection gives the wrong
|
||||||
|
# signature for SetServers (av) while the code only expects a bunch of arguments
|
||||||
|
# instead of an array of variants
|
||||||
|
p = bus.get_object("uk.org.thekelleys.dnsmasq", "/uk/org/thekelleys/dnsmasq", introspect=False)
|
||||||
|
l = dbus.Interface(p, dbus_interface="uk.org.thekelleys.dnsmasq")
|
||||||
|
|
||||||
|
# The previous method; all addresses in machine byte order
|
||||||
|
print l.SetServers(dbus.UInt32(16909060), # 1.2.3.5
|
||||||
|
dbus.UInt32(16909061), # 1.2.3.4
|
||||||
|
"foobar.com",
|
||||||
|
dbus.Byte(0x10), # 1003:1234:abcd::1
|
||||||
|
dbus.Byte(0x03),
|
||||||
|
dbus.Byte(0x12),
|
||||||
|
dbus.Byte(0x34),
|
||||||
|
dbus.Byte(0xab),
|
||||||
|
dbus.Byte(0xcd),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x00),
|
||||||
|
dbus.Byte(0x01),
|
||||||
|
"eng.mycorp.com",
|
||||||
|
"lab.mycorp.com")
|
||||||
|
|
||||||
+61
-1
@@ -19,7 +19,8 @@ and avoids startup races with the provider of nameserver information.
|
|||||||
|
|
||||||
|
|
||||||
Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq
|
Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq
|
||||||
and a single object: /uk/org/thekelleys/dnsmasq
|
and a single object: /uk/org/thekelleys/dnsmasq
|
||||||
|
The name of the service may be changed by giving an argument to --enable-dbus.
|
||||||
|
|
||||||
1. METHODS
|
1. METHODS
|
||||||
----------
|
----------
|
||||||
@@ -94,6 +95,65 @@ Each call to SetServers completely replaces the set of servers
|
|||||||
specified by via the DBus, but it leaves any servers specified via the
|
specified by via the DBus, but it leaves any servers specified via the
|
||||||
command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
|
command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
|
||||||
|
|
||||||
|
SetServersEx
|
||||||
|
------------
|
||||||
|
|
||||||
|
This function is more flexible and the SetServers function, in that it can
|
||||||
|
handle address scoping, port numbers, and is easier for clients to use.
|
||||||
|
|
||||||
|
Returns nothing. Takes a set of arguments representing the new
|
||||||
|
upstream DNS servers to be used by dnsmasq. All addresses (both IPv4 and IPv6)
|
||||||
|
are represented as STRINGS. Each server address may be followed by one or more
|
||||||
|
STRINGS, which are the domains for which the preceding server should be used.
|
||||||
|
|
||||||
|
This function takes an array of STRING arrays, where each inner array represents
|
||||||
|
a set of DNS servers and domains for which those servers may be used. Each
|
||||||
|
string represents a list of upstream DNS servers first, and domains second.
|
||||||
|
Mixing of domains and servers within a the string array is not allowed.
|
||||||
|
|
||||||
|
Examples.
|
||||||
|
|
||||||
|
[
|
||||||
|
["1.2.3.4", "foobar.com"],
|
||||||
|
["1003:1234:abcd::1%eth0", "eng.mycorp.com", "lab.mycorp.com"]
|
||||||
|
]
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
--server=/foobar.com/1.2.3.4 \
|
||||||
|
--server=/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0
|
||||||
|
|
||||||
|
An IPv4 address of 0.0.0.0 is interpreted as "no address, local only",
|
||||||
|
so
|
||||||
|
|
||||||
|
[ ["0.0.0.0", "local.domain"] ]
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
--local=/local.domain/
|
||||||
|
|
||||||
|
|
||||||
|
Each call to SetServersEx completely replaces the set of servers
|
||||||
|
specified by via the DBus, but it leaves any servers specified via the
|
||||||
|
command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
|
||||||
|
|
||||||
|
|
||||||
|
SetDomainServers
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Yes another variation for setting DNS servers, with the capability of
|
||||||
|
SetServersEx, but without using arrays of arrays, which are not
|
||||||
|
sendable with dbus-send. The arguments are an array of strings which
|
||||||
|
are identical to the equivalent arguments --server, so the example
|
||||||
|
for SetServersEx is represented as
|
||||||
|
|
||||||
|
[
|
||||||
|
"/foobar.com/1.2.3.4"
|
||||||
|
"/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2. SIGNALS
|
2. SIGNALS
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|||||||
Vendored
+41
@@ -1,6 +1,47 @@
|
|||||||
|
dnsmasq (2.66-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 14 Dec 2012 11:58:41 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.65-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 14 Dec 2012 11:34:12 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.64-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 21 Sep 2012 17:17:22 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.63-4) unstable; urgency=low
|
||||||
|
|
||||||
|
* Make pid-file creation immune to symlink attacks. (closes: #686484)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 21 Sep 2012 17:16:34 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.63-3) unstable; urgency=low
|
||||||
|
|
||||||
|
* Move adduser dependency to dnsmasq-base. (closes: #686694)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 4 Sep 2012 21:44:15 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.63-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fix version script to report correct version.
|
||||||
|
* Unbotch move of dbus config file by using correct versions in
|
||||||
|
Replaces: and Breaks: lines. (closes: #685204)
|
||||||
|
* Create dnsmasq user in dnsmasq-base so that Dbus doesn't complain if
|
||||||
|
only dnsmasq-base is installed. (closes: #685987)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 28 Aug 2012 16:18:35 +0000
|
||||||
|
|
||||||
dnsmasq (2.63-1) unstable; urgency=low
|
dnsmasq (2.63-1) unstable; urgency=low
|
||||||
|
|
||||||
* New upstream.
|
* New upstream.
|
||||||
|
* Move /etc/dbus-1/system.d/dnsmasq.conf from dnsmasq to dnsmasq-base.
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 11 Jun 2012 21:55:35 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 11 Jun 2012 21:55:35 +0000
|
||||||
|
|
||||||
|
|||||||
Vendored
-1
@@ -2,5 +2,4 @@
|
|||||||
/etc/default/dnsmasq
|
/etc/default/dnsmasq
|
||||||
/etc/dnsmasq.conf
|
/etc/dnsmasq.conf
|
||||||
/etc/resolvconf/update.d/dnsmasq
|
/etc/resolvconf/update.d/dnsmasq
|
||||||
/etc/dbus-1/system.d/dnsmasq.conf
|
|
||||||
/etc/insserv.conf.d/dnsmasq
|
/etc/insserv.conf.d/dnsmasq
|
||||||
Vendored
+4
-3
@@ -7,7 +7,7 @@ Standards-Version: 3.9.3
|
|||||||
|
|
||||||
Package: dnsmasq
|
Package: dnsmasq
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: netbase, adduser, dnsmasq-base(>= ${source:Version})
|
Depends: netbase, dnsmasq-base(>= ${source:Version})
|
||||||
Suggests: resolvconf
|
Suggests: resolvconf
|
||||||
Conflicts: resolvconf (<<1.15)
|
Conflicts: resolvconf (<<1.15)
|
||||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||||
@@ -22,8 +22,9 @@ Description: Small caching DNS proxy and DHCP/TFTP server
|
|||||||
|
|
||||||
Package: dnsmasq-base
|
Package: dnsmasq-base
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}
|
Depends: adduser, ${shlibs:Depends}
|
||||||
Conflicts: dnsmasq (<<2.41)
|
Breaks: dnsmasq (<< 2.63-1~)
|
||||||
|
Replaces: dnsmasq (<< 2.63-1~)
|
||||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||||
This package contains the dnsmasq executable and documentation, but
|
This package contains the dnsmasq executable and documentation, but
|
||||||
not the infrastructure required to run it as a system daemon. For
|
not the infrastructure required to run it as a system daemon. For
|
||||||
|
|||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
/etc/dbus-1/system.d/dnsmasq.conf
|
||||||
Vendored
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Create the dnsmasq user in dnsmasq-base, so that Dbus doesn't complain.
|
||||||
|
|
||||||
|
# create a user to run as (code stolen from dovecot-common)
|
||||||
|
if [ "$1" = "configure" ]; then
|
||||||
|
if [ -z "`id -u dnsmasq 2> /dev/null`" ]; then
|
||||||
|
adduser --system --home /var/lib/misc --gecos "dnsmasq" \
|
||||||
|
--no-create-home --disabled-password \
|
||||||
|
--quiet dnsmasq || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make the directory where we keep the pid file - this
|
||||||
|
# has to be owned by "dnsmasq" so that the file can be unlinked.
|
||||||
|
# This is only actually used by the dnsmasq binary package, not
|
||||||
|
# dnsmasq-base, but it's much easier to create it here so that
|
||||||
|
# we don't have synchronisation issues with the creation of the
|
||||||
|
# dnsmasq user.
|
||||||
|
if [ ! -d /var/run/dnsmasq ]; then
|
||||||
|
mkdir /var/run/dnsmasq
|
||||||
|
chown dnsmasq:nogroup /var/run/dnsmasq
|
||||||
|
fi
|
||||||
|
fi
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ purge = "$1" ]; then
|
||||||
|
if [ -x "$(command -v deluser)" ]; then
|
||||||
|
deluser --quiet --system dnsmasq > /dev/null || true
|
||||||
|
else
|
||||||
|
echo >&2 "not removing dnsmasq system account because deluser command was not found"
|
||||||
|
fi
|
||||||
|
rm -rf /var/run/dnsmasq
|
||||||
|
fi
|
||||||
Vendored
-27
@@ -1,27 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# create a user to run as (code stolen from dovecot-common)
|
|
||||||
if [ "$1" = "configure" ]; then
|
|
||||||
if [ -z "`id -u dnsmasq 2> /dev/null`" ]; then
|
|
||||||
adduser --system --home /var/lib/misc --gecos "dnsmasq" \
|
|
||||||
--no-create-home --disabled-password \
|
|
||||||
--quiet dnsmasq || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make the directory where we keep the pid file - this
|
|
||||||
# has to be owned by "dnsmasq" do that the file can be unlinked.
|
|
||||||
if [ ! -d /var/run/dnsmasq ]; then
|
|
||||||
mkdir /var/run/dnsmasq
|
|
||||||
chown dnsmasq:nogroup /var/run/dnsmasq
|
|
||||||
fi
|
|
||||||
|
|
||||||
# handle new location of pidfile during an upgrade
|
|
||||||
if [ -e /var/run/dnsmasq.pid ]; then
|
|
||||||
mv /var/run/dnsmasq.pid /var/run/dnsmasq
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -x /etc/init.d/dnsmasq ]; then
|
if [ -x /etc/init.d/dnsmasq ]; then
|
||||||
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
||||||
|
|
||||||
@@ -40,10 +19,4 @@ if [ -x /etc/init.d/dnsmasq ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# dpkg can botch the change of /usr/share/doc/dnsmasq from
|
|
||||||
# directory to symlink. Fix up here.
|
|
||||||
if [ ! -h /usr/share/doc/dnsmasq ] && { rmdir /usr/share/doc/dnsmasq; }; then
|
|
||||||
cd /usr/share/doc/
|
|
||||||
ln -s /usr/share/doc/dnsmasq-base dnsmasq
|
|
||||||
fi
|
|
||||||
|
|
||||||
Vendored
-6
@@ -3,10 +3,4 @@ set -e
|
|||||||
|
|
||||||
if [ purge = "$1" ]; then
|
if [ purge = "$1" ]; then
|
||||||
update-rc.d dnsmasq remove >/dev/null
|
update-rc.d dnsmasq remove >/dev/null
|
||||||
if [ -x "$(command -v deluser)" ]; then
|
|
||||||
deluser --quiet --system dnsmasq > /dev/null || true
|
|
||||||
else
|
|
||||||
echo >&2 "not removing dnsmasq system account because deluser command was not found"
|
|
||||||
fi
|
|
||||||
rm -rf /var/run/dnsmasq
|
|
||||||
fi
|
fi
|
||||||
Vendored
+5
-2
@@ -85,7 +85,6 @@ binary-indep: checkroot
|
|||||||
-d debian/daemon/etc/resolvconf/update.d \
|
-d debian/daemon/etc/resolvconf/update.d \
|
||||||
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
|
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
|
||||||
-d debian/daemon/etc/default \
|
-d debian/daemon/etc/default \
|
||||||
-d debian/daemon/etc/dbus-1/system.d \
|
|
||||||
-d debian/daemon/lib/systemd/system \
|
-d debian/daemon/lib/systemd/system \
|
||||||
-d debian/daemon/etc/insserv.conf.d
|
-d debian/daemon/etc/insserv.conf.d
|
||||||
install -m 644 debian/conffiles debian/daemon/DEBIAN
|
install -m 644 debian/conffiles debian/daemon/DEBIAN
|
||||||
@@ -96,7 +95,6 @@ binary-indep: checkroot
|
|||||||
install -m 644 debian/default debian/daemon/etc/default/dnsmasq
|
install -m 644 debian/default debian/daemon/etc/default/dnsmasq
|
||||||
install -m 644 dnsmasq.conf.example debian/daemon/etc/dnsmasq.conf
|
install -m 644 dnsmasq.conf.example debian/daemon/etc/dnsmasq.conf
|
||||||
install -m 644 debian/readme.dnsmasq.d debian/daemon/etc/dnsmasq.d/README
|
install -m 644 debian/readme.dnsmasq.d debian/daemon/etc/dnsmasq.d/README
|
||||||
install -m 644 debian/dbus.conf debian/daemon/etc/dbus-1/system.d/dnsmasq.conf
|
|
||||||
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
|
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
|
||||||
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
|
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
|
||||||
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
|
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
|
||||||
@@ -111,6 +109,7 @@ binary-arch: checkroot
|
|||||||
rm -rf debian/base
|
rm -rf debian/base
|
||||||
install -m 755 \
|
install -m 755 \
|
||||||
-d debian/base/DEBIAN \
|
-d debian/base/DEBIAN \
|
||||||
|
-d debian/base/etc/dbus-1/system.d \
|
||||||
-d debian/base/usr/share/doc/$(package) \
|
-d debian/base/usr/share/doc/$(package) \
|
||||||
-d debian/base/usr/share/doc/$(package)/examples \
|
-d debian/base/usr/share/doc/$(package)/examples \
|
||||||
-d debian/base/var/run \
|
-d debian/base/var/run \
|
||||||
@@ -129,10 +128,14 @@ ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
|||||||
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
|
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
|
||||||
gzip -9 debian/base/usr/share/doc/$(package)/DBus-interface
|
gzip -9 debian/base/usr/share/doc/$(package)/DBus-interface
|
||||||
endif
|
endif
|
||||||
|
install -m 644 debian/dnsmasq-base.conffiles debian/base/DEBIAN/conffiles
|
||||||
|
install -m 755 debian/dnsmasq-base.postinst debian/base/DEBIAN/postinst
|
||||||
|
install -m 755 debian/dnsmasq-base.postrm debian/base/DEBIAN/postrm
|
||||||
install -m 644 debian/changelog debian/base/usr/share/doc/$(package)/changelog.Debian
|
install -m 644 debian/changelog debian/base/usr/share/doc/$(package)/changelog.Debian
|
||||||
gzip -9 debian/base/usr/share/doc/$(package)/changelog.Debian
|
gzip -9 debian/base/usr/share/doc/$(package)/changelog.Debian
|
||||||
install -m 644 debian/readme debian/base/usr/share/doc/$(package)/README.Debian
|
install -m 644 debian/readme debian/base/usr/share/doc/$(package)/README.Debian
|
||||||
install -m 644 debian/copyright debian/base/usr/share/doc/$(package)/copyright
|
install -m 644 debian/copyright debian/base/usr/share/doc/$(package)/copyright
|
||||||
|
install -m 644 debian/dbus.conf debian/base/etc/dbus-1/system.d/dnsmasq.conf
|
||||||
gzip -9 debian/base/usr/share/man/man8/dnsmasq.8
|
gzip -9 debian/base/usr/share/man/man8/dnsmasq.8
|
||||||
for f in debian/base/usr/share/man/*; do \
|
for f in debian/base/usr/share/man/*; do \
|
||||||
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
||||||
|
|||||||
@@ -326,6 +326,9 @@
|
|||||||
# dnsmasq and another.
|
# dnsmasq and another.
|
||||||
#dhcp-option=option6:dns-server,[::],[1234::88]
|
#dhcp-option=option6:dns-server,[::],[1234::88]
|
||||||
|
|
||||||
|
# Ask client to poll for option changes every six hours. (RFC4242)
|
||||||
|
#dhcp-option=option6:information-refresh-time,6h
|
||||||
|
|
||||||
# Set the NTP time server address to be the same machine as
|
# Set the NTP time server address to be the same machine as
|
||||||
# is running dnsmasq
|
# is running dnsmasq
|
||||||
#dhcp-option=42,0.0.0.0
|
#dhcp-option=42,0.0.0.0
|
||||||
@@ -477,7 +480,7 @@
|
|||||||
#tftp-no-blocksize
|
#tftp-no-blocksize
|
||||||
|
|
||||||
# Set the boot file name only when the "red" tag is set.
|
# Set the boot file name only when the "red" tag is set.
|
||||||
#dhcp-boot=net:red,pxelinux.red-net
|
#dhcp-boot=tag:red,pxelinux.red-net
|
||||||
|
|
||||||
# An example of dhcp-boot with an external TFTP server: the name and IP
|
# An example of dhcp-boot with an external TFTP server: the name and IP
|
||||||
# address of the server are given after the filename.
|
# address of the server are given after the filename.
|
||||||
@@ -522,7 +525,7 @@
|
|||||||
# If you want to disable negative caching, uncomment this.
|
# If you want to disable negative caching, uncomment this.
|
||||||
#no-negcache
|
#no-negcache
|
||||||
|
|
||||||
# Normally responses which come form /etc/hosts and the DHCP lease
|
# Normally responses which come from /etc/hosts and the DHCP lease
|
||||||
# file have Time-To-Live set as zero, which conventionally means
|
# file have Time-To-Live set as zero, which conventionally means
|
||||||
# do not cache further. If you are happy to trade lower load on the
|
# do not cache further. If you are happy to trade lower load on the
|
||||||
# server for potentially stale date, you can set a time-to-live (in
|
# server for potentially stale date, you can set a time-to-live (in
|
||||||
@@ -618,6 +621,6 @@
|
|||||||
# Log lots of extra information about DHCP transactions.
|
# Log lots of extra information about DHCP transactions.
|
||||||
#log-dhcp
|
#log-dhcp
|
||||||
|
|
||||||
# Include a another lot of configuration options.
|
# Include another lot of configuration options.
|
||||||
#conf-file=/etc/dnsmasq.more.conf
|
#conf-file=/etc/dnsmasq.more.conf
|
||||||
#conf-dir=/etc/dnsmasq.d
|
#conf-dir=/etc/dnsmasq.d
|
||||||
+25
-61
@@ -71,6 +71,9 @@ maximum TTL will be given to clients instead of the true TTL value if it is
|
|||||||
lower. The true TTL value is however kept in the cache to avoid flooding
|
lower. The true TTL value is however kept in the cache to avoid flooding
|
||||||
the upstream DNS servers.
|
the upstream DNS servers.
|
||||||
.TP
|
.TP
|
||||||
|
.B --max-cache-ttl=<time>
|
||||||
|
Set a maximum TTL value for entries in the cache.
|
||||||
|
.TP
|
||||||
.B \-k, --keep-in-foreground
|
.B \-k, --keep-in-foreground
|
||||||
Do not go into the background at startup but otherwise run as
|
Do not go into the background at startup but otherwise run as
|
||||||
normal. This is intended for use when dnsmasq is run under daemontools
|
normal. This is intended for use when dnsmasq is run under daemontools
|
||||||
@@ -80,7 +83,9 @@ or launchd.
|
|||||||
Debug mode: don't fork to the background, don't write a pid file,
|
Debug mode: don't fork to the background, don't write a pid file,
|
||||||
don't change user id, generate a complete cache dump on receipt on
|
don't change user id, generate a complete cache dump on receipt on
|
||||||
SIGUSR1, log to stderr as well as syslog, don't fork new processes
|
SIGUSR1, log to stderr as well as syslog, don't fork new processes
|
||||||
to handle TCP queries.
|
to handle TCP queries. Note that this option is for use in debugging
|
||||||
|
only, to stop dnsmasq daemonising in production, use
|
||||||
|
.B -k.
|
||||||
.TP
|
.TP
|
||||||
.B \-q, --log-queries
|
.B \-q, --log-queries
|
||||||
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
|
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
|
||||||
@@ -207,12 +212,12 @@ dnsmasq which provide DHCP service to run in the same machine.
|
|||||||
.B --bind-dynamic
|
.B --bind-dynamic
|
||||||
Enable a network mode which is a hybrid between
|
Enable a network mode which is a hybrid between
|
||||||
.B --bind-interfaces
|
.B --bind-interfaces
|
||||||
and the default. Dnsmasq binds the address of indivdual interfaces,
|
and the default. Dnsmasq binds the address of individual interfaces,
|
||||||
allowing multiple dnsmasq instances, but if new interfaces or
|
allowing multiple dnsmasq instances, but if new interfaces or
|
||||||
addresses appear, it automatically listens on those (subject to any
|
addresses appear, it automatically listens on those (subject to any
|
||||||
access-control configuration). This makes dynamically created
|
access-control configuration). This makes dynamically created
|
||||||
interfaces work in the same way as the default. Implementing this
|
interfaces work in the same way as the default. Implementing this
|
||||||
option requires non-standard networking APIs and it is only availble
|
option requires non-standard networking APIs and it is only available
|
||||||
under Linux. On other platforms it falls-back to --bind-interfaces mode.
|
under Linux. On other platforms it falls-back to --bind-interfaces mode.
|
||||||
.TP
|
.TP
|
||||||
.B \-y, --localise-queries
|
.B \-y, --localise-queries
|
||||||
@@ -271,11 +276,13 @@ time is the one used.
|
|||||||
Don't read /etc/resolv.conf. Get upstream servers only from the command
|
Don't read /etc/resolv.conf. Get upstream servers only from the command
|
||||||
line or the dnsmasq configuration file.
|
line or the dnsmasq configuration file.
|
||||||
.TP
|
.TP
|
||||||
.B \-1, --enable-dbus
|
.B \-1, --enable-dbus[=<service-name>]
|
||||||
Allow dnsmasq configuration to be updated via DBus method calls. The
|
Allow dnsmasq configuration to be updated via DBus method calls. The
|
||||||
configuration which can be changed is upstream DNS servers (and
|
configuration which can be changed is upstream DNS servers (and
|
||||||
corresponding domains) and cache clear. Requires that dnsmasq has
|
corresponding domains) and cache clear. Requires that dnsmasq has
|
||||||
been built with DBus support.
|
been built with DBus support. If the service name is given, dnsmasq
|
||||||
|
provides service at that name, rather than the default which is
|
||||||
|
.B uk.org.thekelleys.dnsmasq
|
||||||
.TP
|
.TP
|
||||||
.B \-o, --strict-order
|
.B \-o, --strict-order
|
||||||
By default, dnsmasq will send queries to any of the upstream servers
|
By default, dnsmasq will send queries to any of the upstream servers
|
||||||
@@ -461,14 +468,16 @@ Return an NAPTR DNS record, as specified in RFC3403.
|
|||||||
Return a CNAME record which indicates that <cname> is really
|
Return a CNAME record which indicates that <cname> is really
|
||||||
<target>. There are significant limitations on the target; it must be a
|
<target>. There are significant limitations on the target; it must be a
|
||||||
DNS name which is known to dnsmasq from /etc/hosts (or additional
|
DNS name which is known to dnsmasq from /etc/hosts (or additional
|
||||||
hosts files) or from DHCP. If the target does not satisfy this
|
hosts files), from DHCP or from another
|
||||||
|
.B --cname.
|
||||||
|
If the target does not satisfy this
|
||||||
criteria, the whole cname is ignored. The cname must be unique, but it
|
criteria, the whole cname is ignored. The cname must be unique, but it
|
||||||
is permissable to have more than one cname pointing to the same target.
|
is permissable to have more than one cname pointing to the same target.
|
||||||
.TP
|
.TP
|
||||||
.B --dns-rr=<name>,<RR-number>,[<hex data>]
|
.B --dns-rr=<name>,<RR-number>,[<hex data>]
|
||||||
Return an arbitrary DNS Resource Record. The number is the type of the
|
Return an arbitrary DNS Resource Record. The number is the type of the
|
||||||
record (which is always in the C_IN class). The value of the record is
|
record (which is always in the C_IN class). The value of the record is
|
||||||
given by the hex data, which may be of the for 01:23:45 or 01 23 45 or
|
given by the hex data, which may be of the form 01:23:45 or 01 23 45 or
|
||||||
012345 or any mixture of these.
|
012345 or any mixture of these.
|
||||||
.TP
|
.TP
|
||||||
.B --interface-name=<name>,<interface>
|
.B --interface-name=<name>,<interface>
|
||||||
@@ -529,9 +538,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>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
|
.B \-F, --dhcp-range=[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>][,<mode>][,<prefix-len>][,<lease time>]
|
.B \-F, --dhcp-range=[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
|
||||||
@@ -577,7 +586,11 @@ 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
|
||||||
addresses given via
|
addresses given via
|
||||||
.B dhcp-host
|
.B dhcp-host
|
||||||
or from /etc/ethers will be served.
|
or from /etc/ethers will be served. A static-only subnet with address
|
||||||
|
all zeros may be used as a "catch-all" address to enable replies to all
|
||||||
|
Information-request packets on a subnet which is provided with
|
||||||
|
stateless DHCPv6, ie
|
||||||
|
.B --dhcp=range=::,static
|
||||||
|
|
||||||
For IPv4, the <mode> may be
|
For IPv4, the <mode> may be
|
||||||
.B proxy
|
.B proxy
|
||||||
@@ -624,8 +637,6 @@ can be combined with
|
|||||||
and
|
and
|
||||||
.B slaac.
|
.B slaac.
|
||||||
|
|
||||||
The interface:<interface name> section is not normally used. See the
|
|
||||||
NOTES section for details of this.
|
|
||||||
.TP
|
.TP
|
||||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||||
Specify per host parameters for the DHCP server. This allows a machine
|
Specify per host parameters for the DHCP server. This allows a machine
|
||||||
@@ -1369,12 +1380,11 @@ the relevant link-local address of the machine running dnsmasq is sent
|
|||||||
as recursive DNS server. If provided, the DHCPv6 options dns-server and
|
as recursive DNS server. If provided, the DHCPv6 options dns-server and
|
||||||
domain-search are used for RDNSS and DNSSL.
|
domain-search are used for RDNSS and DNSSL.
|
||||||
.TP
|
.TP
|
||||||
.B --enable-tftp[=<interface>]
|
.B --enable-tftp
|
||||||
Enable the TFTP server function. This is deliberately limited to that
|
Enable the TFTP server function. This is deliberately limited to that
|
||||||
needed to net-boot a client. Only reading is allowed; the tsize and
|
needed to net-boot a client. Only reading is allowed; the tsize and
|
||||||
blksize extensions are supported (tsize is only supported in octet
|
blksize extensions are supported (tsize is only supported in octet
|
||||||
mode). See NOTES section for use of the interface argument.
|
mode).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B --tftp-root=<directory>[,<interface>]
|
.B --tftp-root=<directory>[,<interface>]
|
||||||
Look for files to transfer using TFTP relative to the given
|
Look for files to transfer using TFTP relative to the given
|
||||||
@@ -1638,52 +1648,6 @@ parameter in a BOOTP request is used as a tag,
|
|||||||
as is the tag "bootp", allowing some control over the options returned to
|
as is the tag "bootp", allowing some control over the options returned to
|
||||||
different classes of hosts.
|
different classes of hosts.
|
||||||
|
|
||||||
.B dhcp-range
|
|
||||||
may have an interface name supplied as
|
|
||||||
"interface:<interface-name>". The semantics if this are as follows:
|
|
||||||
For DHCP, if any other dhcp-range exists _without_ an interface name,
|
|
||||||
then the interface name is ignored and and dnsmasq behaves as if the
|
|
||||||
interface parts did not exist, otherwise DHCP is only provided to
|
|
||||||
interfaces mentioned in dhcp-range
|
|
||||||
declarations. For DNS, if there are no
|
|
||||||
.B --interface
|
|
||||||
or
|
|
||||||
.B --listen-address
|
|
||||||
flags, behaviour is unchanged by the interface part. If either of
|
|
||||||
these flags are present, the interfaces mentioned in
|
|
||||||
dhcp-ranges are added to the set which get DNS service.
|
|
||||||
|
|
||||||
Similarly,
|
|
||||||
.B enable-tftp
|
|
||||||
may take an interface name, which enables TFTP only for a particular
|
|
||||||
interface, ignoring
|
|
||||||
.B --interface
|
|
||||||
or
|
|
||||||
.B --listen-address
|
|
||||||
flags. In addition
|
|
||||||
.B --tftp-secure
|
|
||||||
and
|
|
||||||
.B --tftp-unique-root
|
|
||||||
and
|
|
||||||
.B --tftp-no-blocksize
|
|
||||||
are ignored for requests from such interfaces. (A
|
|
||||||
.B --tftp-root
|
|
||||||
directive giving a root path and an interface should be
|
|
||||||
provided too.)
|
|
||||||
|
|
||||||
These rules may seem odd at first sight, but they
|
|
||||||
allow a single line of the form "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200"
|
|
||||||
to be added to dnsmasq configuration which then supplies
|
|
||||||
DHCP and DNS services to that interface, without affecting
|
|
||||||
what services are supplied to other interfaces and irrespective of
|
|
||||||
the existance or lack of "interface=<interface>"
|
|
||||||
lines elsewhere in the dnsmasq configuration.
|
|
||||||
"enable-tftp=virt0" and "tftp-root=<root>,virt0" do the same job for TFTP.
|
|
||||||
The idea is
|
|
||||||
that such a line can be added automatically by libvirt
|
|
||||||
or equivalent systems, without disturbing any manual
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
.SH EXIT CODES
|
.SH EXIT CODES
|
||||||
.PP
|
.PP
|
||||||
0 - Dnsmasq successfully forked into the background, or terminated
|
0 - Dnsmasq successfully forked into the background, or terminated
|
||||||
|
|||||||
+34
-55
@@ -232,6 +232,18 @@ autre serveur de nom (ou une autre instance de Dnsmasq) tourne sur la même
|
|||||||
machine. Utiliser cette option permet également d'avoir plusieurs instances de
|
machine. Utiliser cette option permet également d'avoir plusieurs instances de
|
||||||
Dnsmasq fournissant un service DHCP sur la même machine.
|
Dnsmasq fournissant un service DHCP sur la même machine.
|
||||||
.TP
|
.TP
|
||||||
|
.B --bind-dynamic
|
||||||
|
Autorise un mode réseau intermédiaire entre
|
||||||
|
.B --bind-interfaces
|
||||||
|
et le mode par défaut. Dnsmasq s'associe à une seule interface, ce qui permet
|
||||||
|
plusieurs instances de dnsmasq, mais si une interface ou adresse apparaissent,
|
||||||
|
il se mettra automatiquement à écouter sur celles-ci (les règles de contrôle
|
||||||
|
d'accès s'appliquent).
|
||||||
|
De fait, les interfaces créées dynamiquement fonctionnent de la même façon que
|
||||||
|
dans le comportement par défaut. Ce fonctionnement nécessite des APIs réseau
|
||||||
|
non standard et n'est disponible que sous Linux. Sur les autres plateformes,
|
||||||
|
le fonctionnement est celui du mode --bind-interfaces.
|
||||||
|
.TP
|
||||||
.B \-y, --localise-queries
|
.B \-y, --localise-queries
|
||||||
Retourne des réponses aux requêtes DNS dépendantes de l'interface sur laquelle
|
Retourne des réponses aux requêtes DNS dépendantes de l'interface sur laquelle
|
||||||
la requête a été reçue, à partir du fichier /etc/hosts. Si un nom dans
|
la requête a été reçue, à partir du fichier /etc/hosts. Si un nom dans
|
||||||
@@ -532,9 +544,17 @@ Retourne un enregistrement de type NAPTR, tel que spécifié dans le RFC3403.
|
|||||||
Retourne un enregistrement de type CNAME qui indique que <cname> est en
|
Retourne un enregistrement de type CNAME qui indique que <cname> est en
|
||||||
réalité <cible>. Il existe des contraintes significatives sur la valeur
|
réalité <cible>. Il existe des contraintes significatives sur la valeur
|
||||||
de cible; il doit s'agir d'un nom DNS qui est connu de dnsmasq via /etc/hosts
|
de cible; il doit s'agir d'un nom DNS qui est connu de dnsmasq via /etc/hosts
|
||||||
(ou un fichier hôtes additionnel) ou via DHCP. Si une cible ne satisfait
|
(ou un fichier hôtes additionnel), ou via DHCP, ou par un autre
|
||||||
pas ces critères, le CNAME est ignoré. Le CNAME doit être unique, mais
|
.B --cname.
|
||||||
il est autorisé d'avoir plus d'un CNAME pointant vers la même cible.
|
Si une cible ne satisfait pas ces critères, le CNAME est ignoré. Le CNAME
|
||||||
|
doit être unique, mais il est autorisé d'avoir plus d'un CNAME pointant
|
||||||
|
vers la même cible.
|
||||||
|
.TP
|
||||||
|
.B --dns-rr=<nom>,<numéro-RR>,[<données hexadécimales>]
|
||||||
|
Retourne un enregistrement DNS arbitraire. Le numéro correspond au type
|
||||||
|
d'enregistrement (qui est toujours de la classe C_IN). La valeur de
|
||||||
|
l'enregistrement est donnée dans les données hexadécimales, qui peuvent
|
||||||
|
être de la forme 01:23:45, 01 23 45,+012345 ou n'importe quelle combinaison.
|
||||||
.TP
|
.TP
|
||||||
.B --interface-name=<nom>,<interface>
|
.B --interface-name=<nom>,<interface>
|
||||||
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
|
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
|
||||||
@@ -601,9 +621,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>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
|
.B \-F, --dhcp-range=[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>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
|
.B \-F, --dhcp-range=[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
|
||||||
@@ -705,8 +725,6 @@ peut-être combiné avec
|
|||||||
et
|
et
|
||||||
.B slaac.
|
.B slaac.
|
||||||
|
|
||||||
La section interface:<nom d'interface> n'est normalement pas utilisée. Se
|
|
||||||
référer aux indications de la section NOTES pour plus de détail à ce sujet.
|
|
||||||
.TP
|
.TP
|
||||||
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
|
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
|
||||||
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
|
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
|
||||||
@@ -1517,12 +1535,11 @@ 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
|
options dns-server et domain-search sont utilisées respectivement pour RDNSS et
|
||||||
DNSSL.
|
DNSSL.
|
||||||
.TP
|
.TP
|
||||||
.B --enable-tftp[=<interface>]
|
.B --enable-tftp
|
||||||
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
|
||||||
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
|
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
|
||||||
un accès en lecture est possible; les extensions tsize et blksize sont supportées
|
un accès en lecture est possible; les extensions tsize et blksize sont supportées
|
||||||
(tsize est seulement supporté en mode octet). Voir dans la section NOTES les
|
(tsize est seulement supporté en mode octet).
|
||||||
informations relatives à la spécification de l'interface.
|
|
||||||
.TP
|
.TP
|
||||||
.B --tftp-root=<répertoire>[,<interface>]
|
.B --tftp-root=<répertoire>[,<interface>]
|
||||||
Les fichiers à fournir dans les transferts TFTP seront cherchés en prenant le
|
Les fichiers à fournir dans les transferts TFTP seront cherchés en prenant le
|
||||||
@@ -1560,6 +1577,13 @@ Sans cela, en effet, l'accès de tous les fichiers du serveur pour lequel le
|
|||||||
droit de lecture pour tout le monde est positionné ("world-readable") devient
|
droit de lecture pour tout le monde est positionné ("world-readable") devient
|
||||||
possible par n'importe quel hôte sur le réseau.
|
possible par n'importe quel hôte sur le réseau.
|
||||||
.TP
|
.TP
|
||||||
|
.B --tftp-lowercase
|
||||||
|
Converti les noms de fichiers des requêtes TFTP en minuscules. Cela est utile
|
||||||
|
pour les requêtes effectuées depuis les machines Windows, dont les systèmes
|
||||||
|
de fichiers sont insensibles à la casse et pour lesquels la détermination
|
||||||
|
de la casse est parfois un peu aléatoire. A noter que le serveur tftp de
|
||||||
|
dnsmasq converti systématiquement les "\\" en "/" dans les noms de fichiers.
|
||||||
|
.TP
|
||||||
.B --tftp-max=<connexions>
|
.B --tftp-max=<connexions>
|
||||||
Définit le nombre maximum de connexions TFTP simultanées autorisées. La valeur
|
Définit le nombre maximum de connexions TFTP simultanées autorisées. La valeur
|
||||||
par défaut est de 50. Lorsqu'un grand nombre de connexions TFTP est spécifié,
|
par défaut est de 50. Lorsqu'un grand nombre de connexions TFTP est spécifié,
|
||||||
@@ -1823,51 +1847,6 @@ supprime la nécessité des associations statiques). Le paramètre
|
|||||||
que le label "bootp", permettant un certain contrôle sur les options retournées
|
que le label "bootp", permettant un certain contrôle sur les options retournées
|
||||||
aux différentes classes d'hôtes.
|
aux différentes classes d'hôtes.
|
||||||
|
|
||||||
Il est possible de spécifier un nom d'interface à
|
|
||||||
.B dhcp-range
|
|
||||||
sous la forme "interface:<nom d'interface>". La sémantique est comme suit :
|
|
||||||
Pour le DHCP, s'il existe une autre valeur de dhcp-range pour laquelle
|
|
||||||
_aucun_ nom d'interface n'est donné, alors le nom d'interface est ignoré
|
|
||||||
et dnsmasq se comporte comme si la partie spécifiant l'interface n'existait
|
|
||||||
pas, sinon le service DHCP n'est fourni qu'aux interfaces mentionnées dans
|
|
||||||
les déclarations dhcp-range. Pour le DNS, si il n'y a pas d'option
|
|
||||||
.B --interface
|
|
||||||
ou
|
|
||||||
.B --listen-address
|
|
||||||
, alors le comportement n'est pas impacté par la spécification d'interface. Si
|
|
||||||
l'une ou l'autre de ces options est présente, alors les interfaces mentionnées
|
|
||||||
dans les plages d'adresses dhcp-range sont rajoutées à la liste de celles
|
|
||||||
où le service DNS est assuré.
|
|
||||||
|
|
||||||
De manière similaire,
|
|
||||||
.B enable-tftp
|
|
||||||
peut prendre un nom d'interface, ce qui active le TFTP pour cette seule
|
|
||||||
interface, en ignorant les options
|
|
||||||
.B --interface
|
|
||||||
ou
|
|
||||||
.B --listen-address
|
|
||||||
De plus,
|
|
||||||
.B --tftp-secure
|
|
||||||
,
|
|
||||||
.B --tftp-unique-root
|
|
||||||
et
|
|
||||||
.B --tftp-no-blocksize
|
|
||||||
sont ignorées pour les requêtes sur de telles interfaces. (une directive
|
|
||||||
.B --tftp-root
|
|
||||||
donnant le chemin de la racine et une interface doit-être fournie).
|
|
||||||
|
|
||||||
Ces règles peuvent paraître étrange à première vue, mais elles permettent
|
|
||||||
d'ajouter à la configuration de dnsmasq des lignes de configuration de la
|
|
||||||
forme "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" afin de fournir
|
|
||||||
un service DHCP et DNS sur cette interface, sans pour autant affecter les
|
|
||||||
services fournis sur d'autres interfaces, malgré l'absence de paramètres
|
|
||||||
"interface=<interface>" sur les autres lignes de configuration.
|
|
||||||
"enable-tftp=virt0" et "tftp-root=<root>,virt0" effectuent la même chose pour
|
|
||||||
TFTP.
|
|
||||||
L'idée de tout cela est de permettre l'addition de telles lignes
|
|
||||||
automatiquement par libvirt ou un système équivalent, sans perturbation
|
|
||||||
d'une configuration manuelle existant par ailleurs.
|
|
||||||
|
|
||||||
.SH CODES DE SORTIE
|
.SH CODES DE SORTIE
|
||||||
.PP
|
.PP
|
||||||
0 - Dnsmasq s'est correctement lancé en tâche de fond, ou alors s'est
|
0 - Dnsmasq s'est correctement lancé en tâche de fond, ou alors s'est
|
||||||
|
|||||||
+758
@@ -0,0 +1,758 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
|
||||||
|
static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||||
|
{
|
||||||
|
struct subnet *subnet;
|
||||||
|
|
||||||
|
for (subnet = zone->subnet; subnet; subnet = subnet->next)
|
||||||
|
{
|
||||||
|
if (subnet->is6 && (flag & F_IPV4))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!subnet->is6)
|
||||||
|
{
|
||||||
|
struct in_addr addr = addr_u->addr.addr4;
|
||||||
|
struct in_addr mask;
|
||||||
|
|
||||||
|
mask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
|
||||||
|
|
||||||
|
if (is_same_net(addr, subnet->addr4, mask))
|
||||||
|
return subnet;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr6, subnet->prefixlen))
|
||||||
|
return subnet;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int filter_constructed_dhcp(int flag, struct all_addr *addr_u)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
struct dhcp_context *context;
|
||||||
|
|
||||||
|
if (flag | F_IPV6)
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
if ((context->flags & CONTEXT_CONSTRUCTED) &&
|
||||||
|
is_same_net6(&(addr_u->addr.addr6), &context->start6, context->prefix))
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int in_zone(struct auth_zone *zone, char *name, char **cut)
|
||||||
|
{
|
||||||
|
size_t namelen = strlen(name);
|
||||||
|
size_t domainlen = strlen(zone->domain);
|
||||||
|
|
||||||
|
if (cut)
|
||||||
|
*cut = NULL;
|
||||||
|
|
||||||
|
if (namelen >= domainlen &&
|
||||||
|
hostname_isequal(zone->domain, &name[namelen - domainlen]))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (namelen == domainlen)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (name[namelen - domainlen - 1] == '.')
|
||||||
|
{
|
||||||
|
if (cut)
|
||||||
|
*cut = &name[namelen - domainlen - 1];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr)
|
||||||
|
{
|
||||||
|
char *name = daemon->namebuff;
|
||||||
|
unsigned char *p, *ansp;
|
||||||
|
int qtype, qclass;
|
||||||
|
int nameoffset, axfroffset = 0;
|
||||||
|
int q, anscount = 0, authcount = 0;
|
||||||
|
struct crec *crecp;
|
||||||
|
int auth = 1, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
|
||||||
|
struct auth_zone *zone = NULL;
|
||||||
|
struct subnet *subnet = NULL;
|
||||||
|
char *cut;
|
||||||
|
struct mx_srv_record *rec, *move, **up;
|
||||||
|
struct txt_record *txt;
|
||||||
|
struct interface_name *intr;
|
||||||
|
struct naptr *na;
|
||||||
|
struct all_addr addr;
|
||||||
|
struct cname *a;
|
||||||
|
|
||||||
|
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* determine end of question section (we put answers there) */
|
||||||
|
if (!(ansp = skip_questions(header, qlen)))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
/* now process each question, answers go in RRs after the question */
|
||||||
|
p = (unsigned char *)(header+1);
|
||||||
|
|
||||||
|
for (q = ntohs(header->qdcount); q != 0; q--)
|
||||||
|
{
|
||||||
|
unsigned short flag = 0;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
/* save pointer to name for copying into answers */
|
||||||
|
nameoffset = p - (unsigned char *)header;
|
||||||
|
|
||||||
|
/* now extract name as .-concatenated string into name */
|
||||||
|
if (!extract_name(header, qlen, &p, name, 1, 4))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
GETSHORT(qtype, p);
|
||||||
|
GETSHORT(qclass, p);
|
||||||
|
|
||||||
|
if (qclass != C_IN)
|
||||||
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype == T_PTR)
|
||||||
|
{
|
||||||
|
if (!(flag = in_arpa_name_2_addr(name, &addr)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
|
if ((subnet = filter_zone(zone, flag, &addr)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!zone)
|
||||||
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == F_IPV4)
|
||||||
|
{
|
||||||
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
|
{
|
||||||
|
if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||||
|
intr = intr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intr)
|
||||||
|
{
|
||||||
|
if (in_zone(zone, intr->name, NULL))
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", intr->name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
|
||||||
|
do {
|
||||||
|
strcpy(name, cache_get_name(crecp));
|
||||||
|
|
||||||
|
if (crecp->flags & F_DHCP && !option_bool(OPT_DHCP_FQDN))
|
||||||
|
{
|
||||||
|
char *p = strchr(name, '.');
|
||||||
|
if (p)
|
||||||
|
*p = 0; /* must be bare name */
|
||||||
|
|
||||||
|
/* add external domain */
|
||||||
|
strcat(name, ".");
|
||||||
|
strcat(name, zone->domain);
|
||||||
|
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
|
||||||
|
{
|
||||||
|
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | F_AUTH, NULL, &addr, NULL);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cname_restart:
|
||||||
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
|
if (in_zone(zone, name, &cut))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!zone)
|
||||||
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
|
if (!rec->issrv && hostname_isequal(name, rec->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
|
||||||
|
if (qtype == T_MX)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
|
if (rec->issrv && hostname_isequal(name, rec->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
|
||||||
|
if (qtype == T_SRV)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_SRV, C_IN, "sssd",
|
||||||
|
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||||
|
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlink first SRV record found */
|
||||||
|
if (!move)
|
||||||
|
{
|
||||||
|
move = rec;
|
||||||
|
*up = rec->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &rec->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &rec->next;
|
||||||
|
|
||||||
|
/* put first SRV record back at the end. */
|
||||||
|
if (move)
|
||||||
|
{
|
||||||
|
*up = move;
|
||||||
|
move->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (txt = daemon->rr; txt; txt = txt->next)
|
||||||
|
if (hostname_isequal(name, txt->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (txt->class == qtype)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (txt = daemon->txt; txt; txt = txt->next)
|
||||||
|
if (txt->class == C_IN && hostname_isequal(name, txt->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (qtype == T_TXT)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (na = daemon->naptr; na; na = na->next)
|
||||||
|
if (hostname_isequal(name, na->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (qtype == T_NAPTR)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||||
|
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
|
if (hostname_isequal(name, intr->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (qtype == T_A && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_A, C_IN, "4", &addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
|
if (hostname_isequal(name, a->alias) )
|
||||||
|
{
|
||||||
|
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
||||||
|
strcpy(name, a->target);
|
||||||
|
if (!strchr(name, '.'))
|
||||||
|
{
|
||||||
|
strcat(name, ".");
|
||||||
|
strcat(name, zone->domain);
|
||||||
|
}
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_CNAME, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
goto cname_restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype == T_A)
|
||||||
|
flag = F_IPV4;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (qtype == T_AAAA)
|
||||||
|
flag = F_IPV6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!cut)
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
|
||||||
|
if (qtype == T_SOA)
|
||||||
|
{
|
||||||
|
soa = 1; /* inhibits auth section */
|
||||||
|
found = 1;
|
||||||
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
|
||||||
|
}
|
||||||
|
else if (qtype == T_AXFR)
|
||||||
|
{
|
||||||
|
if (daemon->auth_peers)
|
||||||
|
{
|
||||||
|
struct iname *peers;
|
||||||
|
|
||||||
|
if (peer_addr->sa.sa_family == AF_INET)
|
||||||
|
peer_addr->in.sin_port = 0;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
peer_addr->in6.sin6_port = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
||||||
|
if (sockaddr_isequal(peer_addr, &peers->addr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!peers)
|
||||||
|
{
|
||||||
|
if (peer_addr->sa.sa_family == AF_INET)
|
||||||
|
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
soa = 1; /* inhibits auth section */
|
||||||
|
ns = 1; /* ensure we include NS records! */
|
||||||
|
axfr = 1;
|
||||||
|
found = 1;
|
||||||
|
axfroffset = nameoffset;
|
||||||
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
|
||||||
|
}
|
||||||
|
else if (qtype == T_NS)
|
||||||
|
{
|
||||||
|
ns = 1; /* inhibits auth section */
|
||||||
|
found = 1;
|
||||||
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option_bool(OPT_DHCP_FQDN) && cut)
|
||||||
|
{
|
||||||
|
*cut = 0; /* remove domain part */
|
||||||
|
|
||||||
|
if (!strchr(name, '.') && (crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
|
||||||
|
{
|
||||||
|
if (crecp->flags & F_DHCP)
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if ((crecp->flags & flag) &&
|
||||||
|
(filter_zone(zone, flag, &(crecp->addr.addr)) || filter_constructed_dhcp(flag, &(crecp->addr.addr))))
|
||||||
|
{
|
||||||
|
*cut = '.'; /* restore domain part */
|
||||||
|
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||||
|
*cut = 0; /* remove domain part */
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
|
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
|
||||||
|
}
|
||||||
|
|
||||||
|
*cut = '.'; /* restore domain part */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
|
||||||
|
{
|
||||||
|
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if ((crecp->flags & flag) && filter_zone(zone, flag, &(crecp->addr.addr)))
|
||||||
|
{
|
||||||
|
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
|
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add auth section */
|
||||||
|
if (auth)
|
||||||
|
{
|
||||||
|
char *authname;
|
||||||
|
int newoffset, offset = 0;
|
||||||
|
|
||||||
|
if (!subnet)
|
||||||
|
authname = zone->domain;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* handle NS and SOA for PTR records */
|
||||||
|
|
||||||
|
authname = name;
|
||||||
|
|
||||||
|
if (!subnet->is6)
|
||||||
|
{
|
||||||
|
in_addr_t a = ntohl(subnet->addr4.s_addr) >> 8;
|
||||||
|
char *p = name;
|
||||||
|
|
||||||
|
if (subnet->prefixlen == 24)
|
||||||
|
p += sprintf(p, "%d.", a & 0xff);
|
||||||
|
a = a >> 8;
|
||||||
|
if (subnet->prefixlen != 8)
|
||||||
|
p += sprintf(p, "%d.", a & 0xff);
|
||||||
|
a = a >> 8;
|
||||||
|
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
|
||||||
|
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *p = name;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
|
||||||
|
{
|
||||||
|
int dig = ((unsigned char *)&subnet->addr6)[i>>3];
|
||||||
|
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
||||||
|
}
|
||||||
|
p += sprintf(p, "ip6.arpa");
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle NS and SOA in auth section or for explicit queries */
|
||||||
|
newoffset = ansp - (unsigned char *)header;
|
||||||
|
if (((anscount == 0 && !ns) || soa) &&
|
||||||
|
add_resource_record(header, limit, &trunc, 0, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
|
||||||
|
authname, daemon->authserver, daemon->hostmaster,
|
||||||
|
daemon->soa_sn, daemon->soa_refresh,
|
||||||
|
daemon->soa_retry, daemon->soa_expiry,
|
||||||
|
daemon->auth_ttl))
|
||||||
|
{
|
||||||
|
offset = newoffset;
|
||||||
|
if (soa)
|
||||||
|
anscount++;
|
||||||
|
else
|
||||||
|
authcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anscount != 0 || ns)
|
||||||
|
{
|
||||||
|
struct name_list *secondary;
|
||||||
|
|
||||||
|
newoffset = ansp - (unsigned char *)header;
|
||||||
|
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
|
||||||
|
{
|
||||||
|
if (offset == 0)
|
||||||
|
offset = newoffset;
|
||||||
|
if (ns)
|
||||||
|
anscount++;
|
||||||
|
else
|
||||||
|
authcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subnet)
|
||||||
|
for (secondary = daemon->secondary_forward_server; secondary; secondary = secondary->next)
|
||||||
|
if (add_resource_record(header, limit, &trunc, offset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_NS, C_IN, "d", secondary->name))
|
||||||
|
{
|
||||||
|
if (ns)
|
||||||
|
anscount++;
|
||||||
|
else
|
||||||
|
authcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (axfr)
|
||||||
|
{
|
||||||
|
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
|
if (in_zone(zone, rec->name, &cut))
|
||||||
|
{
|
||||||
|
if (cut)
|
||||||
|
*cut = 0;
|
||||||
|
|
||||||
|
if (rec->issrv)
|
||||||
|
{
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_SRV, C_IN, "sssd", cut ? rec->name : NULL,
|
||||||
|
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||||
|
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_MX, C_IN, "sd", cut ? rec->name : NULL, rec->weight, rec->target))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore config data */
|
||||||
|
if (cut)
|
||||||
|
*cut = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (txt = daemon->rr; txt; txt = txt->next)
|
||||||
|
if (in_zone(zone, txt->name, &cut))
|
||||||
|
{
|
||||||
|
if (cut)
|
||||||
|
*cut = 0;
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, txt->class, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
/* restore config data */
|
||||||
|
if (cut)
|
||||||
|
*cut = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (txt = daemon->txt; txt; txt = txt->next)
|
||||||
|
if (txt->class == C_IN && in_zone(zone, txt->name, &cut))
|
||||||
|
{
|
||||||
|
if (cut)
|
||||||
|
*cut = 0;
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_TXT, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
/* restore config data */
|
||||||
|
if (cut)
|
||||||
|
*cut = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (na = daemon->naptr; na; na = na->next)
|
||||||
|
if (in_zone(zone, na->name, &cut))
|
||||||
|
{
|
||||||
|
if (cut)
|
||||||
|
*cut = 0;
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_NAPTR, C_IN, "sszzzd", cut ? na->name : NULL,
|
||||||
|
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
/* restore config data */
|
||||||
|
if (cut)
|
||||||
|
*cut = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
|
if (in_zone(zone, intr->name, &cut) && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
|
||||||
|
{
|
||||||
|
if (cut)
|
||||||
|
*cut = 0;
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addr))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
/* restore config data */
|
||||||
|
if (cut)
|
||||||
|
*cut = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
|
if (in_zone(zone, a->alias, &cut))
|
||||||
|
{
|
||||||
|
strcpy(name, a->target);
|
||||||
|
if (!strchr(name, '.'))
|
||||||
|
{
|
||||||
|
strcat(name, ".");
|
||||||
|
strcat(name, zone->domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cut)
|
||||||
|
*cut = 0;
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_CNAME, C_IN, "d", cut ? a->alias : NULL, name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_enumerate(1);
|
||||||
|
while ((crecp = cache_enumerate(0)))
|
||||||
|
{
|
||||||
|
if ((crecp->flags & (F_IPV4 | F_IPV6)) &&
|
||||||
|
!(crecp->flags & (F_NEG | F_NXDOMAIN)) &&
|
||||||
|
(crecp->flags & F_FORWARD))
|
||||||
|
{
|
||||||
|
if ((crecp->flags & F_DHCP) && !option_bool(OPT_DHCP_FQDN))
|
||||||
|
{
|
||||||
|
char *cache_name = cache_get_name(crecp);
|
||||||
|
if (!strchr(cache_name, '.') && filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))
|
||||||
|
{
|
||||||
|
qtype = T_A;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (crecp->flags & F_IPV6)
|
||||||
|
qtype = T_AAAA;
|
||||||
|
#endif
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
|
(crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
|
||||||
|
{
|
||||||
|
strcpy(name, cache_get_name(crecp));
|
||||||
|
if (in_zone(zone, name, &cut) && filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))
|
||||||
|
{
|
||||||
|
qtype = T_A;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (crecp->flags & F_IPV6)
|
||||||
|
qtype = T_AAAA;
|
||||||
|
#endif
|
||||||
|
if (cut)
|
||||||
|
*cut = 0;
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
|
(crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* repeat SOA as last record */
|
||||||
|
if (add_resource_record(header, limit, &trunc, axfroffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
|
||||||
|
daemon->authserver, daemon->hostmaster,
|
||||||
|
daemon->soa_sn, daemon->soa_refresh,
|
||||||
|
daemon->soa_retry, daemon->soa_expiry,
|
||||||
|
daemon->auth_ttl))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* done all questions, set up header and return length of result */
|
||||||
|
/* clear authoritative and truncated flags, set QR flag */
|
||||||
|
header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
|
||||||
|
/* clear RA flag */
|
||||||
|
header->hb4 &= ~HB4_RA;
|
||||||
|
|
||||||
|
/* authoritive */
|
||||||
|
if (auth)
|
||||||
|
header->hb3 |= HB3_AA;
|
||||||
|
|
||||||
|
/* truncation */
|
||||||
|
if (trunc)
|
||||||
|
header->hb3 |= HB3_TC;
|
||||||
|
|
||||||
|
if (anscount == 0 && auth && nxdomain)
|
||||||
|
SET_RCODE(header, NXDOMAIN);
|
||||||
|
else
|
||||||
|
SET_RCODE(header, NOERROR); /* no error */
|
||||||
|
header->ancount = htons(anscount);
|
||||||
|
header->nscount = htons(authcount);
|
||||||
|
header->arcount = htons(0);
|
||||||
|
return ansp - (unsigned char *)header;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
||||||
@@ -146,7 +147,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
addr->s6_addr[3] = 0;
|
addr->s6_addr[3] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((*callback)(addr, prefix, scope_id, iface_index, 0, parm)))
|
/* preferred and valid times == forever until we known how to dtermine them. */
|
||||||
|
if (!((*callback)(addr, prefix, scope_id, iface_index, 0, -1, -1, parm)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+115
-67
@@ -235,6 +235,29 @@ char *cache_get_name(struct crec *crecp)
|
|||||||
return crecp->name.sname;
|
return crecp->name.sname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct crec *cache_enumerate(int init)
|
||||||
|
{
|
||||||
|
static int bucket;
|
||||||
|
static struct crec *cache;
|
||||||
|
|
||||||
|
if (init)
|
||||||
|
{
|
||||||
|
bucket = 0;
|
||||||
|
cache = NULL;
|
||||||
|
}
|
||||||
|
else if (cache && cache->hash_next)
|
||||||
|
cache = cache->hash_next;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cache = NULL;
|
||||||
|
while (bucket < hash_size)
|
||||||
|
if ((cache = hash_table[bucket++]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
static int is_outdated_cname_pointer(struct crec *crecp)
|
static int is_outdated_cname_pointer(struct crec *crecp)
|
||||||
{
|
{
|
||||||
if (!(crecp->flags & F_CNAME))
|
if (!(crecp->flags & F_CNAME))
|
||||||
@@ -243,7 +266,7 @@ static int is_outdated_cname_pointer(struct crec *crecp)
|
|||||||
/* NB. record may be reused as DS or DNSKEY, where uid is
|
/* NB. record may be reused as DS or DNSKEY, where uid is
|
||||||
overloaded for something completely different */
|
overloaded for something completely different */
|
||||||
if (crecp->addr.cname.cache &&
|
if (crecp->addr.cname.cache &&
|
||||||
(crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6)) &&
|
(crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
|
||||||
crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
|
crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -371,6 +394,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
|||||||
int freed_all = flags & F_REVERSE;
|
int freed_all = flags & F_REVERSE;
|
||||||
int free_avail = 0;
|
int free_avail = 0;
|
||||||
|
|
||||||
|
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
|
||||||
|
ttl = daemon->max_cache_ttl;
|
||||||
|
|
||||||
/* Don't log keys */
|
/* Don't log keys */
|
||||||
if (flags & (F_IPV4 | F_IPV6))
|
if (flags & (F_IPV4 | F_IPV6))
|
||||||
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
||||||
@@ -645,13 +671,29 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_hosts_cname(struct crec *target)
|
||||||
|
{
|
||||||
|
struct crec *crec;
|
||||||
|
struct cname *a;
|
||||||
|
|
||||||
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
|
if (hostname_isequal(cache_get_name(target), a->target) &&
|
||||||
|
(crec = whine_malloc(sizeof(struct crec))))
|
||||||
|
{
|
||||||
|
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
||||||
|
crec->name.namep = a->alias;
|
||||||
|
crec->addr.cname.cache = target;
|
||||||
|
crec->addr.cname.uid = target->uid;
|
||||||
|
cache_hash(crec);
|
||||||
|
add_hosts_cname(crec); /* handle chains */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
||||||
int index, struct crec **rhash, int hashsz)
|
int index, struct crec **rhash, int hashsz)
|
||||||
{
|
{
|
||||||
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
|
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
|
||||||
int i, nameexists = 0;
|
int i, nameexists = 0;
|
||||||
struct cname *a;
|
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
|
||||||
/* Remove duplicates in hosts files. */
|
/* Remove duplicates in hosts files. */
|
||||||
@@ -702,16 +744,7 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
|||||||
|
|
||||||
/* don't need to do alias stuff for second and subsequent addresses. */
|
/* don't need to do alias stuff for second and subsequent addresses. */
|
||||||
if (!nameexists)
|
if (!nameexists)
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
add_hosts_cname(cache);
|
||||||
if (hostname_isequal(cache_get_name(cache), a->target) &&
|
|
||||||
(lookup = whine_malloc(sizeof(struct crec))))
|
|
||||||
{
|
|
||||||
lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
|
||||||
lookup->name.namep = a->alias;
|
|
||||||
lookup->addr.cname.cache = cache;
|
|
||||||
lookup->addr.cname.uid = index;
|
|
||||||
cache_hash(lookup);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eatspace(FILE *f)
|
static int eatspace(FILE *f)
|
||||||
@@ -1003,13 +1036,41 @@ void cache_unhash_dhcp(void)
|
|||||||
up = &cache->hash_next;
|
up = &cache->hash_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_dhcp_cname(struct crec *target, time_t ttd)
|
||||||
|
{
|
||||||
|
struct crec *aliasc;
|
||||||
|
struct cname *a;
|
||||||
|
|
||||||
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
|
if (hostname_isequal(cache_get_name(target), a->target))
|
||||||
|
{
|
||||||
|
if ((aliasc = dhcp_spare))
|
||||||
|
dhcp_spare = dhcp_spare->next;
|
||||||
|
else /* need new one */
|
||||||
|
aliasc = whine_malloc(sizeof(struct crec));
|
||||||
|
|
||||||
|
if (aliasc)
|
||||||
|
{
|
||||||
|
aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
|
||||||
|
if (ttd == 0)
|
||||||
|
aliasc->flags |= F_IMMORTAL;
|
||||||
|
else
|
||||||
|
aliasc->ttd = ttd;
|
||||||
|
aliasc->name.namep = a->alias;
|
||||||
|
aliasc->addr.cname.cache = target;
|
||||||
|
aliasc->addr.cname.uid = target->uid;
|
||||||
|
cache_hash(aliasc);
|
||||||
|
add_dhcp_cname(aliasc, ttd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cache_add_dhcp_entry(char *host_name, int prot,
|
void cache_add_dhcp_entry(char *host_name, int prot,
|
||||||
struct all_addr *host_address, time_t ttd)
|
struct all_addr *host_address, time_t ttd)
|
||||||
{
|
{
|
||||||
struct crec *crec = NULL, *aliasc;
|
struct crec *crec = NULL, *fail_crec = NULL;
|
||||||
unsigned short flags = F_IPV4;
|
unsigned short flags = F_IPV4;
|
||||||
int in_hosts = 0;
|
int in_hosts = 0;
|
||||||
struct cname *a;
|
|
||||||
size_t addrlen = sizeof(struct in_addr);
|
size_t addrlen = sizeof(struct in_addr);
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -1020,29 +1081,21 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
|
||||||
while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
|
while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
|
||||||
{
|
{
|
||||||
/* check all addresses associated with name */
|
/* check all addresses associated with name */
|
||||||
if (crec->flags & F_HOSTS)
|
if (crec->flags & F_HOSTS)
|
||||||
{
|
{
|
||||||
/* if in hosts, don't need DHCP record */
|
|
||||||
in_hosts = 1;
|
|
||||||
|
|
||||||
inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
|
|
||||||
if (crec->flags & F_CNAME)
|
if (crec->flags & F_CNAME)
|
||||||
|
|
||||||
my_syslog(MS_DHCP | LOG_WARNING,
|
my_syslog(MS_DHCP | LOG_WARNING,
|
||||||
_("%s is a CNAME, not giving it to the DHCP lease of %s"),
|
_("%s is a CNAME, not giving it to the DHCP lease of %s"),
|
||||||
host_name, daemon->addrbuff);
|
host_name, daemon->addrbuff);
|
||||||
else if (memcmp(&crec->addr.addr, host_address, addrlen) != 0)
|
else if (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
|
||||||
{
|
in_hosts = 1;
|
||||||
inet_ntop(prot, &crec->addr.addr, daemon->namebuff, MAXDNAME);
|
else
|
||||||
my_syslog(MS_DHCP | LOG_WARNING,
|
fail_crec = crec;
|
||||||
_("not giving name %s to the DHCP lease of %s because "
|
|
||||||
"the name exists in %s with address %s"),
|
|
||||||
host_name, daemon->addrbuff,
|
|
||||||
record_source(crec->uid), daemon->namebuff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!(crec->flags & F_DHCP))
|
else if (!(crec->flags & F_DHCP))
|
||||||
{
|
{
|
||||||
@@ -1052,21 +1105,34 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_hosts)
|
/* if in hosts, don't need DHCP record */
|
||||||
|
if (in_hosts)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
|
/* Name in hosts, address doesn't match */
|
||||||
{
|
if (fail_crec)
|
||||||
if (crec->flags & F_NEG)
|
{
|
||||||
{
|
inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
|
||||||
flags |= F_REVERSE;
|
my_syslog(MS_DHCP | LOG_WARNING,
|
||||||
cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags);
|
_("not giving name %s to the DHCP lease of %s because "
|
||||||
}
|
"the name exists in %s with address %s"),
|
||||||
}
|
host_name, daemon->addrbuff,
|
||||||
else
|
record_source(fail_crec->uid), daemon->namebuff);
|
||||||
flags |= F_REVERSE;
|
return;
|
||||||
|
}
|
||||||
if ((crec = dhcp_spare))
|
|
||||||
|
if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
|
||||||
|
{
|
||||||
|
if (crec->flags & F_NEG)
|
||||||
|
{
|
||||||
|
flags |= F_REVERSE;
|
||||||
|
cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
flags |= F_REVERSE;
|
||||||
|
|
||||||
|
if ((crec = dhcp_spare))
|
||||||
dhcp_spare = dhcp_spare->next;
|
dhcp_spare = dhcp_spare->next;
|
||||||
else /* need new one */
|
else /* need new one */
|
||||||
crec = whine_malloc(sizeof(struct crec));
|
crec = whine_malloc(sizeof(struct crec));
|
||||||
@@ -1083,27 +1149,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
crec->uid = uid++;
|
crec->uid = uid++;
|
||||||
cache_hash(crec);
|
cache_hash(crec);
|
||||||
|
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
add_dhcp_cname(crec, ttd);
|
||||||
if (hostname_isequal(host_name, a->target))
|
|
||||||
{
|
|
||||||
if ((aliasc = dhcp_spare))
|
|
||||||
dhcp_spare = dhcp_spare->next;
|
|
||||||
else /* need new one */
|
|
||||||
aliasc = whine_malloc(sizeof(struct crec));
|
|
||||||
|
|
||||||
if (aliasc)
|
|
||||||
{
|
|
||||||
aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
|
|
||||||
if (ttd == 0)
|
|
||||||
aliasc->flags |= F_IMMORTAL;
|
|
||||||
else
|
|
||||||
aliasc->ttd = ttd;
|
|
||||||
aliasc->name.namep = a->alias;
|
|
||||||
aliasc->addr.cname.cache = crec;
|
|
||||||
aliasc->addr.cname.uid = crec->uid;
|
|
||||||
cache_hash(aliasc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1225,14 +1271,14 @@ char *record_source(int index)
|
|||||||
return "<unknown>";
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void querystr(char *str, unsigned short type)
|
void querystr(char *desc, char *str, unsigned short type)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
sprintf(str, "query[type=%d]", type);
|
sprintf(str, "%s[type=%d]", desc, type);
|
||||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||||
if (typestr[i].type == type)
|
if (typestr[i].type == type)
|
||||||
sprintf(str,"query[%s]", typestr[i].name);
|
sprintf(str,"%s[%s]", desc, typestr[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
||||||
@@ -1293,6 +1339,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
|||||||
source = arg;
|
source = arg;
|
||||||
else if (flags & F_UPSTREAM)
|
else if (flags & F_UPSTREAM)
|
||||||
source = "reply";
|
source = "reply";
|
||||||
|
else if (flags & F_AUTH)
|
||||||
|
source = "auth";
|
||||||
else if (flags & F_SERVER)
|
else if (flags & F_SERVER)
|
||||||
{
|
{
|
||||||
source = "forwarded";
|
source = "forwarded";
|
||||||
|
|||||||
+28
-5
@@ -33,7 +33,6 @@
|
|||||||
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
||||||
#define HOSTSFILE "/etc/hosts"
|
#define HOSTSFILE "/etc/hosts"
|
||||||
#define ETHERSFILE "/etc/ethers"
|
#define ETHERSFILE "/etc/ethers"
|
||||||
#define RUNFILE "/var/run/dnsmasq.pid"
|
|
||||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||||
#define CHUSER "nobody"
|
#define CHUSER "nobody"
|
||||||
#define CHGRP "dip"
|
#define CHGRP "dip"
|
||||||
@@ -41,9 +40,13 @@
|
|||||||
#define LOG_MAX 5 /* log-queue length */
|
#define LOG_MAX 5 /* log-queue length */
|
||||||
#define RANDFILE "/dev/urandom"
|
#define RANDFILE "/dev/urandom"
|
||||||
#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
|
#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
|
||||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* DBUS interface specifics */
|
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
|
||||||
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
||||||
|
#define AUTH_TTL 600 /* default TTL for auth DNS */
|
||||||
|
#define SOA_REFRESH 1200 /* SOA refresh default */
|
||||||
|
#define SOA_RETRY 180 /* SOA retry default */
|
||||||
|
#define SOA_EXPIRY 1209600 /* SOA expiry default */
|
||||||
|
|
||||||
/* compile-time options: uncomment below to enable or do eg.
|
/* compile-time options: uncomment below to enable or do eg.
|
||||||
make COPTS=-DHAVE_BROKEN_RTC
|
make COPTS=-DHAVE_BROKEN_RTC
|
||||||
|
|
||||||
@@ -93,12 +96,18 @@ HAVE_CONNTRACK
|
|||||||
a build-dependency on libnetfilter_conntrack, but the resulting binary will
|
a build-dependency on libnetfilter_conntrack, but the resulting binary will
|
||||||
still run happily on a kernel without conntrack support.
|
still run happily on a kernel without conntrack support.
|
||||||
|
|
||||||
|
HAVE_AUTH
|
||||||
|
define this to include the facility to act as an authoritative DNS
|
||||||
|
server for one or more zones.
|
||||||
|
|
||||||
|
|
||||||
NO_IPV6
|
NO_IPV6
|
||||||
NO_TFTP
|
NO_TFTP
|
||||||
NO_DHCP
|
NO_DHCP
|
||||||
NO_DHCP6
|
NO_DHCP6
|
||||||
NO_SCRIPT
|
NO_SCRIPT
|
||||||
NO_LARGEFILE
|
NO_LARGEFILE
|
||||||
|
NO_AUTH
|
||||||
these are avilable to explictly disable compile time options which would
|
these are avilable to explictly disable compile time options which would
|
||||||
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
||||||
which are enabled by default in the distributed source tree. Building dnsmasq
|
which are enabled by default in the distributed source tree. Building dnsmasq
|
||||||
@@ -120,6 +129,7 @@ RESOLVFILE
|
|||||||
#define HAVE_DHCP6
|
#define HAVE_DHCP6
|
||||||
#define HAVE_TFTP
|
#define HAVE_TFTP
|
||||||
#define HAVE_SCRIPT
|
#define HAVE_SCRIPT
|
||||||
|
#define HAVE_AUTH
|
||||||
/* #define HAVE_LUASCRIPT */
|
/* #define HAVE_LUASCRIPT */
|
||||||
/* #define HAVE_BROKEN_RTC */
|
/* #define HAVE_BROKEN_RTC */
|
||||||
/* #define HAVE_DBUS */
|
/* #define HAVE_DBUS */
|
||||||
@@ -158,7 +168,13 @@ RESOLVFILE
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef RUNFILE
|
||||||
|
# if defined(__ANDROID__)
|
||||||
|
# define RUNFILE "/data/dnsmasq.pid"
|
||||||
|
# else
|
||||||
|
# define RUNFILE "/var/run/dnsmasq.pid"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* platform dependent options: these are determined automatically below
|
/* platform dependent options: these are determined automatically below
|
||||||
|
|
||||||
@@ -302,6 +318,9 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#define HAVE_SCRIPT
|
#define HAVE_SCRIPT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_AUTH
|
||||||
|
#undef HAVE_AUTH
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define a string indicating which options are in use.
|
/* Define a string indicating which options are in use.
|
||||||
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
|
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
|
||||||
@@ -360,7 +379,11 @@ static char *compile_opts =
|
|||||||
#ifndef HAVE_CONNTRACK
|
#ifndef HAVE_CONNTRACK
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
"conntrack";
|
"conntrack "
|
||||||
|
#ifndef HAVE_AUTH
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"auth";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+324
-94
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <dbus/dbus.h>
|
#include <dbus/dbus.h>
|
||||||
|
|
||||||
const char* introspection_xml =
|
const char* introspection_xml_template =
|
||||||
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
||||||
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
||||||
"<node name=\"" DNSMASQ_PATH "\">\n"
|
"<node name=\"" DNSMASQ_PATH "\">\n"
|
||||||
@@ -29,7 +29,7 @@ const char* introspection_xml =
|
|||||||
" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
|
" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
" </interface>\n"
|
" </interface>\n"
|
||||||
" <interface name=\"" DNSMASQ_SERVICE "\">\n"
|
" <interface name=\"%s\">\n"
|
||||||
" <method name=\"ClearCache\">\n"
|
" <method name=\"ClearCache\">\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
" <method name=\"GetVersion\">\n"
|
" <method name=\"GetVersion\">\n"
|
||||||
@@ -38,6 +38,12 @@ const char* introspection_xml =
|
|||||||
" <method name=\"SetServers\">\n"
|
" <method name=\"SetServers\">\n"
|
||||||
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
|
" <method name=\"SetDomainServers\">\n"
|
||||||
|
" <arg name=\"servers\" direction=\"in\" type=\"as\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
|
" <method name=\"SetServersEx\">\n"
|
||||||
|
" <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
" <signal name=\"DhcpLeaseAdded\">\n"
|
" <signal name=\"DhcpLeaseAdded\">\n"
|
||||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||||
@@ -56,6 +62,8 @@ const char* introspection_xml =
|
|||||||
" </interface>\n"
|
" </interface>\n"
|
||||||
"</node>\n";
|
"</node>\n";
|
||||||
|
|
||||||
|
static char *introspection_xml = NULL;
|
||||||
|
|
||||||
struct watch {
|
struct watch {
|
||||||
DBusWatch *watch;
|
DBusWatch *watch;
|
||||||
struct watch *next;
|
struct watch *next;
|
||||||
@@ -97,20 +105,118 @@ static void remove_watch(DBusWatch *watch, void *data)
|
|||||||
w = data; /* no warning */
|
w = data; /* no warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dbus_read_servers(DBusMessage *message)
|
static void add_update_server(union mysockaddr *addr,
|
||||||
|
union mysockaddr *source_addr,
|
||||||
|
const char *interface,
|
||||||
|
const char *domain)
|
||||||
|
{
|
||||||
|
struct server *serv;
|
||||||
|
|
||||||
|
/* See if there is a suitable candidate, and unmark */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if ((serv->flags & SERV_FROM_DBUS) &&
|
||||||
|
(serv->flags & SERV_MARK))
|
||||||
|
{
|
||||||
|
if (domain)
|
||||||
|
{
|
||||||
|
if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (serv->flags & SERV_HAS_DOMAIN)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
serv->flags &= ~SERV_MARK;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
||||||
|
{
|
||||||
|
/* Not found, create a new one. */
|
||||||
|
memset(serv, 0, sizeof(struct server));
|
||||||
|
|
||||||
|
if (domain && !(serv->domain = whine_malloc(strlen(domain)+1)))
|
||||||
|
{
|
||||||
|
free(serv);
|
||||||
|
serv = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serv->next = daemon->servers;
|
||||||
|
daemon->servers = serv;
|
||||||
|
serv->flags = SERV_FROM_DBUS;
|
||||||
|
if (domain)
|
||||||
|
{
|
||||||
|
strcpy(serv->domain, domain);
|
||||||
|
serv->flags |= SERV_HAS_DOMAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serv)
|
||||||
|
{
|
||||||
|
if (interface)
|
||||||
|
strcpy(serv->interface, interface);
|
||||||
|
else
|
||||||
|
serv->interface[0] = 0;
|
||||||
|
|
||||||
|
if (source_addr->in.sin_family == AF_INET &&
|
||||||
|
addr->in.sin_addr.s_addr == 0 &&
|
||||||
|
serv->domain)
|
||||||
|
serv->flags |= SERV_NO_ADDR;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serv->flags &= ~SERV_NO_ADDR;
|
||||||
|
serv->addr = *addr;
|
||||||
|
serv->source_addr = *source_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_dbus(void)
|
||||||
|
{
|
||||||
|
struct server *serv;
|
||||||
|
|
||||||
|
/* mark everything from DBUS */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (serv->flags & SERV_FROM_DBUS)
|
||||||
|
serv->flags |= SERV_MARK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cleanup_dbus()
|
||||||
{
|
{
|
||||||
struct server *serv, *tmp, **up;
|
struct server *serv, *tmp, **up;
|
||||||
|
|
||||||
|
/* unlink and free anything still marked. */
|
||||||
|
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||||
|
{
|
||||||
|
tmp = serv->next;
|
||||||
|
if (serv->flags & SERV_MARK)
|
||||||
|
{
|
||||||
|
server_gone(serv);
|
||||||
|
*up = serv->next;
|
||||||
|
if (serv->domain)
|
||||||
|
free(serv->domain);
|
||||||
|
free(serv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &serv->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbus_read_servers(DBusMessage *message)
|
||||||
|
{
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
union mysockaddr addr, source_addr;
|
union mysockaddr addr, source_addr;
|
||||||
char *domain;
|
char *domain;
|
||||||
|
|
||||||
dbus_message_iter_init(message, &iter);
|
dbus_message_iter_init(message, &iter);
|
||||||
|
|
||||||
/* mark everything from DBUS */
|
mark_dbus();
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
|
||||||
if (serv->flags & SERV_FROM_DBUS)
|
|
||||||
serv->flags |= SERV_MARK;
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
@@ -169,6 +275,7 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
/* At the end */
|
/* At the end */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* process each domain */
|
||||||
do {
|
do {
|
||||||
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
|
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
|
||||||
{
|
{
|
||||||
@@ -179,83 +286,183 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
domain = NULL;
|
domain = NULL;
|
||||||
|
|
||||||
if (!skip)
|
if (!skip)
|
||||||
{
|
add_update_server(&addr, &source_addr, NULL, domain);
|
||||||
/* See if this is already there, and unmark */
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
||||||
if ((serv->flags & SERV_FROM_DBUS) &&
|
|
||||||
(serv->flags & SERV_MARK))
|
|
||||||
{
|
|
||||||
if (!(serv->flags & SERV_HAS_DOMAIN) && !domain)
|
|
||||||
{
|
|
||||||
serv->flags &= ~SERV_MARK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((serv->flags & SERV_HAS_DOMAIN) &&
|
|
||||||
domain &&
|
|
||||||
hostname_isequal(domain, serv->domain))
|
|
||||||
{
|
|
||||||
serv->flags &= ~SERV_MARK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
|
||||||
{
|
|
||||||
/* Not found, create a new one. */
|
|
||||||
memset(serv, 0, sizeof(struct server));
|
|
||||||
|
|
||||||
if (domain)
|
|
||||||
serv->domain = whine_malloc(strlen(domain)+1);
|
|
||||||
|
|
||||||
if (domain && !serv->domain)
|
|
||||||
{
|
|
||||||
free(serv);
|
|
||||||
serv = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serv->next = daemon->servers;
|
|
||||||
daemon->servers = serv;
|
|
||||||
serv->flags = SERV_FROM_DBUS;
|
|
||||||
if (domain)
|
|
||||||
{
|
|
||||||
strcpy(serv->domain, domain);
|
|
||||||
serv->flags |= SERV_HAS_DOMAIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serv)
|
|
||||||
{
|
|
||||||
if (source_addr.in.sin_family == AF_INET &&
|
|
||||||
addr.in.sin_addr.s_addr == 0 &&
|
|
||||||
serv->domain)
|
|
||||||
serv->flags |= SERV_NO_ADDR;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serv->flags &= ~SERV_NO_ADDR;
|
|
||||||
serv->addr = addr;
|
|
||||||
serv->source_addr = source_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unlink and free anything still marked. */
|
/* unlink and free anything still marked. */
|
||||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
cleanup_dbus();
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||||
|
{
|
||||||
|
DBusMessageIter iter, array_iter, string_iter;
|
||||||
|
DBusMessage *error = NULL;
|
||||||
|
const char *addr_err;
|
||||||
|
char *dup = NULL;
|
||||||
|
|
||||||
|
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
|
||||||
|
|
||||||
|
if (!dbus_message_iter_init(message, &iter))
|
||||||
{
|
{
|
||||||
tmp = serv->next;
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
if (serv->flags & SERV_MARK)
|
"Failed to initialize dbus message iter");
|
||||||
{
|
|
||||||
server_gone(serv);
|
|
||||||
*up = serv->next;
|
|
||||||
free(serv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
up = &serv->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check that the message contains an array of arrays */
|
||||||
|
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||||
|
(dbus_message_iter_get_element_type(&iter) != (strings ? DBUS_TYPE_STRING : DBUS_TYPE_ARRAY)))
|
||||||
|
{
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
strings ? "Expected array of string" : "Expected array of string arrays");
|
||||||
|
}
|
||||||
|
|
||||||
|
mark_dbus();
|
||||||
|
|
||||||
|
/* array_iter points to each "as" element in the outer array */
|
||||||
|
dbus_message_iter_recurse(&iter, &array_iter);
|
||||||
|
while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID)
|
||||||
|
{
|
||||||
|
const char *str = NULL;
|
||||||
|
union mysockaddr addr, source_addr;
|
||||||
|
char interface[IF_NAMESIZE];
|
||||||
|
char *str_addr, *str_domain = NULL;
|
||||||
|
|
||||||
|
if (strings)
|
||||||
|
{
|
||||||
|
dbus_message_iter_get_basic(&array_iter, &str);
|
||||||
|
if (!str || !strlen (str))
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Empty string");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dup the string because it gets modified during parsing */
|
||||||
|
if (!(dup = str_domain = whine_malloc(strlen(str)+1)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
strcpy(str_domain, str);
|
||||||
|
|
||||||
|
/* point to address part of old string for error message */
|
||||||
|
if ((str_addr = strrchr(str, '/')))
|
||||||
|
str = str_addr+1;
|
||||||
|
|
||||||
|
if ((str_addr = strrchr(str_domain, '/')))
|
||||||
|
{
|
||||||
|
if (*str_domain != '/' || str_addr == str_domain)
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error_printf(message,
|
||||||
|
DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"No domain terminator '%s'",
|
||||||
|
str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*str_addr++ = 0;
|
||||||
|
str_domain++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str_addr = str_domain;
|
||||||
|
str_domain = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* check the types of the struct and its elements */
|
||||||
|
if ((dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY) ||
|
||||||
|
(dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_STRING))
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected inner array of strings");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* string_iter points to each "s" element in the inner array */
|
||||||
|
dbus_message_iter_recurse(&array_iter, &string_iter);
|
||||||
|
if (dbus_message_iter_get_arg_type(&string_iter) != DBUS_TYPE_STRING)
|
||||||
|
{
|
||||||
|
/* no IP address given */
|
||||||
|
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected IP address");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&string_iter, &str);
|
||||||
|
if (!str || !strlen (str))
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Empty IP address");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dup the string because it gets modified during parsing */
|
||||||
|
if (!(dup = str_addr = whine_malloc(strlen(str)+1)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
strcpy(str_addr, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
memset(&source_addr, 0, sizeof(source_addr));
|
||||||
|
memset(&interface, 0, sizeof(interface));
|
||||||
|
|
||||||
|
/* parse the IP address */
|
||||||
|
addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, NULL);
|
||||||
|
|
||||||
|
if (addr_err)
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid IP address '%s': %s",
|
||||||
|
str, addr_err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strings)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (str_domain)
|
||||||
|
{
|
||||||
|
if ((p = strchr(str_domain, '/')))
|
||||||
|
*p++ = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p = NULL;
|
||||||
|
|
||||||
|
add_update_server(&addr, &source_addr, interface, str_domain);
|
||||||
|
} while ((str_domain = p));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* jump past the address to the domain list (if any) */
|
||||||
|
dbus_message_iter_next (&string_iter);
|
||||||
|
|
||||||
|
/* parse domains and add each server/domain pair to the list */
|
||||||
|
do {
|
||||||
|
str = NULL;
|
||||||
|
if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
|
||||||
|
dbus_message_iter_get_basic(&string_iter, &str);
|
||||||
|
dbus_message_iter_next (&string_iter);
|
||||||
|
|
||||||
|
add_update_server(&addr, &source_addr, interface, str);
|
||||||
|
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* jump to next element in outer array */
|
||||||
|
dbus_message_iter_next(&array_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_dbus();
|
||||||
|
|
||||||
|
if (dup)
|
||||||
|
free(dup);
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||||
@@ -263,23 +470,27 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
char *method = (char *)dbus_message_get_member(message);
|
char *method = (char *)dbus_message_get_member(message);
|
||||||
|
DBusMessage *reply = NULL;
|
||||||
|
|
||||||
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
|
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
|
||||||
{
|
{
|
||||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
/* string length: "%s" provides space for termination zero */
|
||||||
|
if (!introspection_xml &&
|
||||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
|
(introspection_xml = whine_malloc(strlen(introspection_xml_template) + strlen(daemon->dbus_name))))
|
||||||
dbus_connection_send (connection, reply, NULL);
|
sprintf(introspection_xml, introspection_xml_template, daemon->dbus_name);
|
||||||
dbus_message_unref (reply);
|
|
||||||
|
if (introspection_xml)
|
||||||
|
{
|
||||||
|
reply = dbus_message_new_method_return(message);
|
||||||
|
dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(method, "GetVersion") == 0)
|
else if (strcmp(method, "GetVersion") == 0)
|
||||||
{
|
{
|
||||||
char *v = VERSION;
|
char *v = VERSION;
|
||||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
reply = dbus_message_new_method_return(message);
|
||||||
|
|
||||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
|
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
|
||||||
dbus_connection_send (connection, reply, NULL);
|
|
||||||
dbus_message_unref (reply);
|
|
||||||
}
|
}
|
||||||
else if (strcmp(method, "SetServers") == 0)
|
else if (strcmp(method, "SetServers") == 0)
|
||||||
{
|
{
|
||||||
@@ -287,6 +498,16 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
dbus_read_servers(message);
|
dbus_read_servers(message);
|
||||||
check_servers();
|
check_servers();
|
||||||
}
|
}
|
||||||
|
else if (strcmp(method, "SetServersEx") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_read_servers_ex(message, 0);
|
||||||
|
check_servers();
|
||||||
|
}
|
||||||
|
else if (strcmp(method, "SetDomainServers") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_read_servers_ex(message, 1);
|
||||||
|
check_servers();
|
||||||
|
}
|
||||||
else if (strcmp(method, "ClearCache") == 0)
|
else if (strcmp(method, "ClearCache") == 0)
|
||||||
clear_cache_and_reload(dnsmasq_time());
|
clear_cache_and_reload(dnsmasq_time());
|
||||||
else
|
else
|
||||||
@@ -294,8 +515,17 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
|
|
||||||
method = user_data; /* no warning */
|
method = user_data; /* no warning */
|
||||||
|
|
||||||
|
/* If no reply or no error, return nothing */
|
||||||
|
if (!reply)
|
||||||
|
reply = dbus_message_new_method_return(message);
|
||||||
|
|
||||||
|
if (reply)
|
||||||
|
{
|
||||||
|
dbus_connection_send (connection, reply, NULL);
|
||||||
|
dbus_message_unref (reply);
|
||||||
|
}
|
||||||
|
|
||||||
return (DBUS_HANDLER_RESULT_HANDLED);
|
return (DBUS_HANDLER_RESULT_HANDLED);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -315,7 +545,7 @@ char *dbus_init(void)
|
|||||||
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
|
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
dbus_error_init (&dbus_error);
|
dbus_error_init (&dbus_error);
|
||||||
dbus_bus_request_name (connection, DNSMASQ_SERVICE, 0, &dbus_error);
|
dbus_bus_request_name (connection, daemon->dbus_name, 0, &dbus_error);
|
||||||
if (dbus_error_is_set (&dbus_error))
|
if (dbus_error_is_set (&dbus_error))
|
||||||
return (char *)dbus_error.message;
|
return (char *)dbus_error.message;
|
||||||
|
|
||||||
@@ -325,7 +555,7 @@ char *dbus_init(void)
|
|||||||
|
|
||||||
daemon->dbus = connection;
|
daemon->dbus = connection;
|
||||||
|
|
||||||
if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up")))
|
if ((message = dbus_message_new_signal(DNSMASQ_PATH, daemon->dbus_name, "Up")))
|
||||||
{
|
{
|
||||||
dbus_connection_send(connection, message, NULL);
|
dbus_connection_send(connection, message, NULL);
|
||||||
dbus_message_unref(message);
|
dbus_message_unref(message);
|
||||||
@@ -430,7 +660,7 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
|
|||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
|
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, daemon->dbus_name, action_str)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dbus_message_iter_init_append(message, &args);
|
dbus_message_iter_init_append(message, &args);
|
||||||
|
|||||||
+105
-138
@@ -246,40 +246,6 @@ int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_dhcp_hosts(int fatal)
|
|
||||||
{
|
|
||||||
/* If the same IP appears in more than one host config, then DISCOVER
|
|
||||||
for one of the hosts will get the address, but REQUEST will be NAKed,
|
|
||||||
since the address is reserved by the other one -> protocol loop.
|
|
||||||
Also check that FQDNs match the domain we are using. */
|
|
||||||
|
|
||||||
struct dhcp_config *configs, *cp;
|
|
||||||
|
|
||||||
for (configs = daemon->dhcp_conf; configs; configs = configs->next)
|
|
||||||
{
|
|
||||||
char *domain;
|
|
||||||
|
|
||||||
if ((configs->flags & DHOPT_BANK) || fatal)
|
|
||||||
{
|
|
||||||
for (cp = configs->next; cp; cp = cp->next)
|
|
||||||
if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
|
|
||||||
{
|
|
||||||
if (fatal)
|
|
||||||
die(_("duplicate IP address %s in dhcp-config directive."),
|
|
||||||
inet_ntoa(cp->addr), EC_BADCONF);
|
|
||||||
else
|
|
||||||
my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."),
|
|
||||||
inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
|
|
||||||
configs->flags &= ~CONFIG_ADDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* split off domain part */
|
|
||||||
if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
|
|
||||||
configs->domain = domain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dhcp_update_configs(struct dhcp_config *configs)
|
void dhcp_update_configs(struct dhcp_config *configs)
|
||||||
{
|
{
|
||||||
/* Some people like to keep all static IP addresses in /etc/hosts.
|
/* Some people like to keep all static IP addresses in /etc/hosts.
|
||||||
@@ -289,7 +255,7 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
|
in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
|
||||||
restore the status-quo ante first. */
|
restore the status-quo ante first. */
|
||||||
|
|
||||||
struct dhcp_config *config;
|
struct dhcp_config *config, *conf_tmp;
|
||||||
struct crec *crec;
|
struct crec *crec;
|
||||||
int prot = AF_INET;
|
int prot = AF_INET;
|
||||||
|
|
||||||
@@ -331,7 +297,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
config->hostname, daemon->addrbuff);
|
config->hostname, daemon->addrbuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prot == AF_INET && !config_find_by_address(configs, crec->addr.addr.addr.addr4))
|
if (prot == AF_INET &&
|
||||||
|
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config))
|
||||||
{
|
{
|
||||||
config->addr = crec->addr.addr.addr.addr4;
|
config->addr = crec->addr.addr.addr.addr4;
|
||||||
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
|
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
|
||||||
@@ -339,7 +306,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (prot == AF_INET6 && !config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0))
|
if (prot == AF_INET6 &&
|
||||||
|
(!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
|
||||||
{
|
{
|
||||||
memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
|
memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
|
||||||
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
|
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
|
||||||
@@ -365,93 +333,6 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
static int join_multicast_worker(struct in6_addr *local, int prefix,
|
|
||||||
int scope, int if_index, int dad, void *vparam)
|
|
||||||
{
|
|
||||||
char ifrn_name[IFNAMSIZ];
|
|
||||||
struct ipv6_mreq mreq;
|
|
||||||
int fd, i, max = *((int *)vparam);
|
|
||||||
struct dhcp_context *context;
|
|
||||||
struct iname *tmp;
|
|
||||||
|
|
||||||
(void)prefix;
|
|
||||||
(void)scope;
|
|
||||||
(void)dad;
|
|
||||||
|
|
||||||
/* record which interfaces we join on, so that we do it at most one per
|
|
||||||
interface, even when they have multiple addresses. Use outpacket
|
|
||||||
as an array of int, since it's always allocated here and easy
|
|
||||||
to expand for theoretical vast numbers of interfaces. */
|
|
||||||
for (i = 0; i < max; i++)
|
|
||||||
if (if_index == ((int *)daemon->outpacket.iov_base)[i])
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if ((fd = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!indextoname(fd, if_index, ifrn_name))
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* Are we doing DHCP on this interface? */
|
|
||||||
if (!iface_check(AF_INET6, (struct all_addr *)local, ifrn_name))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
|
||||||
if (tmp->name && (strcmp(tmp->name, ifrn_name) == 0))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* weird libvirt-inspired access control */
|
|
||||||
for (context = daemon->ra_contexts ? daemon->ra_contexts : daemon->dhcp6;
|
|
||||||
context; context = context->next)
|
|
||||||
if (!context->interface || strcmp(context->interface, ifrn_name) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!context)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
mreq.ipv6mr_interface = if_index;
|
|
||||||
|
|
||||||
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
|
|
||||||
|
|
||||||
if (daemon->dhcp6 &&
|
|
||||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
|
|
||||||
|
|
||||||
if (daemon->dhcp6 &&
|
|
||||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
|
|
||||||
|
|
||||||
if (daemon->ra_contexts &&
|
|
||||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
expand_buf(&daemon->outpacket, (max+1) * sizeof(int));
|
|
||||||
((int *)daemon->outpacket.iov_base)[max++] = if_index;
|
|
||||||
|
|
||||||
*((int *)vparam) = max;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void join_multicast(void)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
if (!iface_enumerate(AF_INET6, &count, join_multicast_worker))
|
|
||||||
die(_("failed to join DHCPv6 multicast group: %s"), NULL, EC_BADNET);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
void bindtodevice(int fd)
|
void bindtodevice(int fd)
|
||||||
{
|
{
|
||||||
@@ -462,7 +343,7 @@ void bindtodevice(int fd)
|
|||||||
SO_BINDTODEVICE is only available Linux. */
|
SO_BINDTODEVICE is only available Linux. */
|
||||||
|
|
||||||
struct irec *iface, *found;
|
struct irec *iface, *found;
|
||||||
|
|
||||||
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
|
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
if (iface->dhcp_ok)
|
if (iface->dhcp_ok)
|
||||||
{
|
{
|
||||||
@@ -477,14 +358,14 @@ void bindtodevice(int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
strcpy(ifr.ifr_name, found->name);
|
strcpy(ifr.ifr_name, found->name);
|
||||||
/* only allowed by root. */
|
/* only allowed by root. */
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
|
||||||
errno != EPERM)
|
errno != EPERM)
|
||||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -531,15 +412,15 @@ static const struct opttab_t {
|
|||||||
{ "x-windows-fs", 48, OT_ADDR_LIST },
|
{ "x-windows-fs", 48, OT_ADDR_LIST },
|
||||||
{ "x-windows-dm", 49, OT_ADDR_LIST },
|
{ "x-windows-dm", 49, OT_ADDR_LIST },
|
||||||
{ "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
|
{ "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
|
||||||
{ "lease-time", 51, OT_INTERNAL | OT_DEC },
|
{ "lease-time", 51, OT_INTERNAL | OT_TIME },
|
||||||
{ "option-overload", 52, OT_INTERNAL },
|
{ "option-overload", 52, OT_INTERNAL },
|
||||||
{ "message-type", 53, OT_INTERNAL | OT_DEC },
|
{ "message-type", 53, OT_INTERNAL | OT_DEC },
|
||||||
{ "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
|
{ "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
|
||||||
{ "parameter-request", 55, OT_INTERNAL },
|
{ "parameter-request", 55, OT_INTERNAL },
|
||||||
{ "message", 56, OT_INTERNAL },
|
{ "message", 56, OT_INTERNAL },
|
||||||
{ "max-message-size", 57, OT_INTERNAL },
|
{ "max-message-size", 57, OT_INTERNAL },
|
||||||
{ "T1", 58, OT_INTERNAL | OT_DEC},
|
{ "T1", 58, OT_INTERNAL | OT_TIME},
|
||||||
{ "T2", 59, OT_INTERNAL | OT_DEC},
|
{ "T2", 59, OT_INTERNAL | OT_TIME},
|
||||||
{ "vendor-class", 60, 0 },
|
{ "vendor-class", 60, 0 },
|
||||||
{ "client-id", 61, OT_INTERNAL },
|
{ "client-id", 61, OT_INTERNAL },
|
||||||
{ "nis+-domain", 64, OT_NAME },
|
{ "nis+-domain", 64, OT_NAME },
|
||||||
@@ -590,6 +471,7 @@ static const struct opttab_t opttab6[] = {
|
|||||||
{ "nis-domain", 29, OT_RFC1035_NAME },
|
{ "nis-domain", 29, OT_RFC1035_NAME },
|
||||||
{ "nis+-domain", 30, OT_RFC1035_NAME },
|
{ "nis+-domain", 30, OT_RFC1035_NAME },
|
||||||
{ "sntp-server", 31, OT_ADDR_LIST },
|
{ "sntp-server", 31, OT_ADDR_LIST },
|
||||||
|
{ "information-refresh-time", 32, OT_TIME },
|
||||||
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
||||||
{ "ntp-server", 56, OT_ADDR_LIST },
|
{ "ntp-server", 56, OT_ADDR_LIST },
|
||||||
{ "bootfile-url", 59, OT_NAME },
|
{ "bootfile-url", 59, OT_NAME },
|
||||||
@@ -754,14 +636,17 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if ((ot[o].size & OT_DEC) && opt_len != 0)
|
else if ((ot[o].size & (OT_DEC | OT_TIME)) && opt_len != 0)
|
||||||
{
|
{
|
||||||
unsigned int dec = 0;
|
unsigned int dec = 0;
|
||||||
|
|
||||||
for (i = 0; i < opt_len; i++)
|
for (i = 0; i < opt_len; i++)
|
||||||
dec = (dec << 8) | val[i];
|
dec = (dec << 8) | val[i];
|
||||||
|
|
||||||
sprintf(buf, "%u", dec);
|
if (ot[o].size & OT_TIME)
|
||||||
|
prettyprint_time(buf, dec);
|
||||||
|
else
|
||||||
|
sprintf(buf, "%u", dec);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nodecode = 1;
|
nodecode = 1;
|
||||||
@@ -788,4 +673,86 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void log_context(int family, struct dhcp_context *context)
|
||||||
|
{
|
||||||
|
/* Cannot use dhcp_buff* for RA contexts */
|
||||||
|
|
||||||
|
void *start = &context->start;
|
||||||
|
void *end = &context->end;
|
||||||
|
char *n = "", *m = "", *p = daemon->namebuff;
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (family == AF_INET6)
|
||||||
|
{
|
||||||
|
struct in6_addr subnet = context->start6;
|
||||||
|
if (!(context->flags & CONTEXT_TEMPLATE))
|
||||||
|
setaddr6part(&subnet, 0);
|
||||||
|
inet_ntop(AF_INET6, &subnet, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
start = &context->start6;
|
||||||
|
end = &context->end6;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((context->flags & CONTEXT_DHCP) ||
|
||||||
|
!(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)))
|
||||||
|
{
|
||||||
|
if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
|
||||||
|
strcpy(daemon->namebuff, _(", prefix deprecated"));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p += sprintf(p, _(", lease time "));
|
||||||
|
m = p;
|
||||||
|
prettyprint_time(p, context->lease_time);
|
||||||
|
p += strlen(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
|
{
|
||||||
|
n = p;
|
||||||
|
p += sprintf(p, ", constructed for %s", context->template_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_TEMPLATE)
|
||||||
|
{
|
||||||
|
n = p;
|
||||||
|
p += sprintf(p, ", template for %s", context->template_interface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((context->flags & CONTEXT_DHCP) || family == AF_INET)
|
||||||
|
{
|
||||||
|
inet_ntop(family, start, daemon->dhcp_buff, 256);
|
||||||
|
inet_ntop(family, end, daemon->dhcp_buff3, 256);
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO,
|
||||||
|
(context->flags & CONTEXT_RA_STATELESS) ?
|
||||||
|
_("%s stateless on %s%.0s%.0s") :
|
||||||
|
(context->flags & CONTEXT_STATIC) ?
|
||||||
|
_("%s, static leases only on %.0s%s%s") :
|
||||||
|
(context->flags & CONTEXT_PROXY) ?
|
||||||
|
_("%s, proxy on subnet %.0s%s%.0s") :
|
||||||
|
_("%s, IP range %s -- %s%s"),
|
||||||
|
(family != AF_INET) ? "DHCPv6" : "DHCP",
|
||||||
|
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (context->flags & CONTEXT_RA_NAME)
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"),
|
||||||
|
daemon->addrbuff, n);
|
||||||
|
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_RA)
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s%s"),
|
||||||
|
daemon->addrbuff,
|
||||||
|
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? "" : ", prefix valid ",
|
||||||
|
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? n : m);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+3
-13
@@ -116,9 +116,7 @@ void dhcp_init(void)
|
|||||||
|
|
||||||
/* Make BPF raw send socket */
|
/* Make BPF raw send socket */
|
||||||
init_bpf();
|
init_bpf();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
check_dhcp_hosts(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dhcp_packet(time_t now, int pxe_fd)
|
void dhcp_packet(time_t now, int pxe_fd)
|
||||||
@@ -257,14 +255,6 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* weird libvirt-inspired access control */
|
|
||||||
for (context = daemon->dhcp; context; context = context->next)
|
|
||||||
if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!context)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* unlinked contexts are marked by context->current == context */
|
/* unlinked contexts are marked by context->current == context */
|
||||||
for (context = daemon->dhcp; context; context = context->next)
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
context->current = context;
|
context->current = context;
|
||||||
@@ -272,12 +262,12 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
parm.current = NULL;
|
parm.current = NULL;
|
||||||
parm.ind = iface_index;
|
parm.ind = iface_index;
|
||||||
|
|
||||||
if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name))
|
if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
|
||||||
{
|
{
|
||||||
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
|
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
|
||||||
for a secondary */
|
for a secondary */
|
||||||
struct match_param match;
|
struct match_param match;
|
||||||
|
|
||||||
match.matched = 0;
|
match.matched = 0;
|
||||||
match.ind = iface_index;
|
match.ind = iface_index;
|
||||||
|
|
||||||
|
|||||||
+232
-34
@@ -21,11 +21,12 @@
|
|||||||
struct iface_param {
|
struct iface_param {
|
||||||
struct dhcp_context *current;
|
struct dhcp_context *current;
|
||||||
struct in6_addr fallback;
|
struct in6_addr fallback;
|
||||||
int ind;
|
int ind, addr_match;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int complete_context6(struct in6_addr *local, int prefix,
|
static int complete_context6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam);
|
int scope, int if_index, int flags,
|
||||||
|
unsigned int preferred, unsigned int valid, void *vparam);
|
||||||
|
|
||||||
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||||
|
|
||||||
@@ -36,15 +37,31 @@ void dhcp6_init(void)
|
|||||||
#if defined(IPV6_TCLASS) && 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 oneopt = 1;
|
||||||
|
|
||||||
if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 ||
|
if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 ||
|
||||||
#if defined(IPV6_TCLASS) && 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
|
||||||
|
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &oneopt, sizeof(oneopt)) == -1 ||
|
||||||
!fix_fd(fd) ||
|
!fix_fd(fd) ||
|
||||||
!set_ipv6pktinfo(fd))
|
!set_ipv6pktinfo(fd))
|
||||||
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
|
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
|
||||||
|
|
||||||
|
/* When bind-interfaces is set, there might be more than one dnmsasq
|
||||||
|
instance binding port 547. That's OK if they serve different networks.
|
||||||
|
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
|
||||||
|
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
|
||||||
|
{
|
||||||
|
#ifdef SO_REUSEPORT
|
||||||
|
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
|
||||||
|
#else
|
||||||
|
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
|
||||||
|
#endif
|
||||||
|
if (rc == -1)
|
||||||
|
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL, EC_BADNET);
|
||||||
|
}
|
||||||
|
|
||||||
memset(&saddr, 0, sizeof(saddr));
|
memset(&saddr, 0, sizeof(saddr));
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
saddr.sin6_len = sizeof(struct sockaddr_in6);
|
saddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||||
@@ -71,7 +88,6 @@ void dhcp6_packet(time_t now)
|
|||||||
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;
|
||||||
struct all_addr dest;
|
|
||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
@@ -98,41 +114,52 @@ void dhcp6_packet(time_t now)
|
|||||||
p.c = CMSG_DATA(cmptr);
|
p.c = CMSG_DATA(cmptr);
|
||||||
|
|
||||||
if_index = p.p->ipi6_ifindex;
|
if_index = p.p->ipi6_ifindex;
|
||||||
dest.addr.addr6 = p.p->ipi6_addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!iface_check(AF_INET6, (struct all_addr *)&dest, ifr.ifr_name))
|
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||||
return;
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
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))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* weird libvirt-inspired access control */
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
|
||||||
if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!context)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* unlinked contexts are marked by context->current == context */
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
|
||||||
{
|
|
||||||
context->current = context;
|
|
||||||
memset(&context->local6, 0, IN6ADDRSZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
parm.current = NULL;
|
parm.current = NULL;
|
||||||
parm.ind = if_index;
|
parm.ind = if_index;
|
||||||
|
parm.addr_match = 0;
|
||||||
memset(&parm.fallback, 0, IN6ADDRSZ);
|
memset(&parm.fallback, 0, IN6ADDRSZ);
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
|
||||||
|
{
|
||||||
|
/* wildcard context for DHCP-stateless only */
|
||||||
|
parm.current = context;
|
||||||
|
context->current = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* unlinked contexts are marked by context->current == context */
|
||||||
|
context->current = context;
|
||||||
|
memset(&context->local6, 0, IN6ADDRSZ);
|
||||||
|
}
|
||||||
|
|
||||||
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
|
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (daemon->if_names || daemon->if_addrs)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!tmp && !parm.addr_match)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
lease_prune(NULL, now); /* lose any expired leases */
|
lease_prune(NULL, now); /* lose any expired leases */
|
||||||
|
|
||||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||||
@@ -155,19 +182,27 @@ void dhcp6_packet(time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int complete_context6(struct in6_addr *local, int prefix,
|
static int complete_context6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int flags, unsigned int preferred,
|
||||||
|
unsigned int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct iface_param *param = vparam;
|
struct iface_param *param = vparam;
|
||||||
|
struct iname *tmp;
|
||||||
|
|
||||||
(void)scope; /* warning */
|
(void)scope; /* warning */
|
||||||
(void)dad;
|
|
||||||
|
|
||||||
if (if_index == param->ind &&
|
if (if_index == param->ind &&
|
||||||
!IN6_IS_ADDR_LOOPBACK(local) &&
|
!IN6_IS_ADDR_LOOPBACK(local) &&
|
||||||
!IN6_IS_ADDR_LINKLOCAL(local) &&
|
!IN6_IS_ADDR_LINKLOCAL(local) &&
|
||||||
!IN6_IS_ADDR_MULTICAST(local))
|
!IN6_IS_ADDR_MULTICAST(local))
|
||||||
{
|
{
|
||||||
|
/* if we have --listen-address config, see if the
|
||||||
|
arrival interface has a matching address. */
|
||||||
|
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->addr.sa.sa_family == AF_INET6 &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
|
||||||
|
param->addr_match = 1;
|
||||||
|
|
||||||
/* Determine a globally address on the arrival interface, even
|
/* Determine a globally address on the arrival interface, even
|
||||||
if we have no matching dhcp-context, because we're only
|
if we have no matching dhcp-context, because we're only
|
||||||
allocating on remote subnets via relays. This
|
allocating on remote subnets via relays. This
|
||||||
@@ -176,16 +211,37 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
{
|
{
|
||||||
if (prefix == context->prefix &&
|
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
|
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))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/* link it onto the current chain if we've not seen it before */
|
/* link it onto the current chain if we've not seen it before */
|
||||||
if (context->current == context)
|
if (context->current == context)
|
||||||
{
|
{
|
||||||
context->current = param->current;
|
struct dhcp_context *tmp, **up;
|
||||||
param->current = context;
|
|
||||||
|
/* use interface values only for contructed contexts */
|
||||||
|
if (!(context->flags & CONTEXT_CONSTRUCTED))
|
||||||
|
preferred = valid = 0xffffffff;
|
||||||
|
else if (flags & IFACE_DEPRECATED)
|
||||||
|
preferred = 0;
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_DEPRECATE)
|
||||||
|
preferred = 0;
|
||||||
|
|
||||||
|
/* order chain, longest preferred time first */
|
||||||
|
for (up = ¶m->current, tmp = param->current; tmp; tmp = tmp->current)
|
||||||
|
if (tmp->preferred <= preferred)
|
||||||
|
break;
|
||||||
|
|
||||||
|
context->current = *up;
|
||||||
|
*up = context;
|
||||||
context->local6 = *local;
|
context->local6 = *local;
|
||||||
|
context->preferred = preferred;
|
||||||
|
context->valid = valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,14 +387,21 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_addr_in_context6(struct dhcp_context *context, struct dhcp_config *config)
|
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
|
||||||
{
|
{
|
||||||
if (!context) /* called via find_config() from lease_update_from_configs() */
|
if (!context) /* called via find_config() from lease_update_from_configs() */
|
||||||
return 1;
|
return 1;
|
||||||
if (!(config->flags & CONFIG_ADDR6))
|
if (!(config->flags & CONFIG_ADDR6) || is_addr_in_context6(context, &config->addr6))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr)
|
||||||
|
{
|
||||||
for (; context; context = context->current)
|
for (; context; context = context->current)
|
||||||
if (is_same_net6(&config->addr6, &context->start6, context->prefix))
|
if (is_same_net6(addr, &context->start6, context->prefix))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -358,7 +421,7 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
|
|||||||
{
|
{
|
||||||
if (config->clid_len == duid_len &&
|
if (config->clid_len == duid_len &&
|
||||||
memcmp(config->clid, duid, duid_len) == 0 &&
|
memcmp(config->clid, duid, duid_len) == 0 &&
|
||||||
is_addr_in_context6(context, config))
|
is_config_in_context6(context, config))
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +429,7 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
|
|||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if ((config->flags & CONFIG_NAME) &&
|
if ((config->flags & CONFIG_NAME) &&
|
||||||
hostname_isequal(config->hostname, hostname) &&
|
hostname_isequal(config->hostname, hostname) &&
|
||||||
is_addr_in_context6(context, config))
|
is_config_in_context6(context, config))
|
||||||
return config;
|
return config;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -426,6 +489,141 @@ static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, vo
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct cparam {
|
||||||
|
time_t now;
|
||||||
|
int newone, newname;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int construct_worker(struct in6_addr *local, int prefix,
|
||||||
|
int scope, int if_index, int flags,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
|
{
|
||||||
|
char ifrn_name[IFNAMSIZ];
|
||||||
|
struct in6_addr start6, end6;
|
||||||
|
struct dhcp_context *template, *context;
|
||||||
|
|
||||||
|
(void)scope;
|
||||||
|
(void)flags;
|
||||||
|
(void)valid;
|
||||||
|
(void)preferred;
|
||||||
|
|
||||||
|
struct cparam *param = vparam;
|
||||||
|
|
||||||
|
if (IN6_IS_ADDR_LOOPBACK(local) ||
|
||||||
|
IN6_IS_ADDR_LINKLOCAL(local) ||
|
||||||
|
IN6_IS_ADDR_MULTICAST(local))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, if_index, ifrn_name))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (template = daemon->dhcp6; template; template = template->next)
|
||||||
|
if (!(template->flags & CONTEXT_TEMPLATE))
|
||||||
|
{
|
||||||
|
/* non-template entries, just fill in interface and local addresses */
|
||||||
|
if (prefix == template->prefix &&
|
||||||
|
is_same_net6(local, &template->start6, prefix) &&
|
||||||
|
is_same_net6(local, &template->end6, prefix))
|
||||||
|
{
|
||||||
|
template->if_index = if_index;
|
||||||
|
template->local6 = *local;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (strcmp(ifrn_name, template->template_interface) == 0 &&
|
||||||
|
addr6part(local) == addr6part(&template->start6))
|
||||||
|
{
|
||||||
|
start6 = *local;
|
||||||
|
setaddr6part(&start6, addr6part(&template->start6));
|
||||||
|
end6 = *local;
|
||||||
|
setaddr6part(&end6, addr6part(&template->end6));
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
if ((context->flags & CONTEXT_CONSTRUCTED) &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
|
||||||
|
{
|
||||||
|
context->flags &= ~CONTEXT_GC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
|
||||||
|
{
|
||||||
|
*context = *template;
|
||||||
|
context->start6 = start6;
|
||||||
|
context->end6 = end6;
|
||||||
|
context->flags &= ~CONTEXT_TEMPLATE;
|
||||||
|
context->flags |= CONTEXT_CONSTRUCTED;
|
||||||
|
context->if_index = if_index;
|
||||||
|
context->local6 = *local;
|
||||||
|
|
||||||
|
context->next = daemon->dhcp6;
|
||||||
|
daemon->dhcp6 = context;
|
||||||
|
|
||||||
|
ra_start_unsolicted(param->now, context);
|
||||||
|
/* we created a new one, need to call
|
||||||
|
lease_update_file to get periodic functions called */
|
||||||
|
param->newone = 1;
|
||||||
|
|
||||||
|
/* Will need to add new putative SLAAC addresses to existing leases */
|
||||||
|
if (context->flags & CONTEXT_RA_NAME)
|
||||||
|
param->newname = 1;
|
||||||
|
|
||||||
|
log_context(AF_INET6, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dhcp_construct_contexts(time_t now)
|
||||||
|
{
|
||||||
|
struct dhcp_context *tmp, *context, **up;
|
||||||
|
struct cparam param;
|
||||||
|
param.newone = 0;
|
||||||
|
param.newname = 0;
|
||||||
|
param.now = now;
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
{
|
||||||
|
context->if_index = 0;
|
||||||
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
|
context->flags |= CONTEXT_GC;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_enumerate(AF_INET6, ¶m, construct_worker);
|
||||||
|
|
||||||
|
for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
|
||||||
|
{
|
||||||
|
tmp = context->next;
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_GC)
|
||||||
|
{
|
||||||
|
*up = context->next;
|
||||||
|
free(context);
|
||||||
|
param.newone = 1; /* include deletion */
|
||||||
|
if (context->flags & CONTEXT_RA_NAME)
|
||||||
|
param.newname = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &context->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.newone)
|
||||||
|
{
|
||||||
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
{
|
||||||
|
if (param.newname)
|
||||||
|
lease_update_slaac(now);
|
||||||
|
lease_update_file(now);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
||||||
|
send_alarm(periodic_ra(now), now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
#define T_OPT 41
|
#define T_OPT 41
|
||||||
#define T_TKEY 249
|
#define T_TKEY 249
|
||||||
#define T_TSIG 250
|
#define T_TSIG 250
|
||||||
|
#define T_AXFR 252
|
||||||
#define T_MAILB 253
|
#define T_MAILB 253
|
||||||
#define T_ANY 255
|
#define T_ANY 255
|
||||||
|
|
||||||
|
|||||||
+137
-146
@@ -51,6 +51,7 @@ int main (int argc, char **argv)
|
|||||||
cap_user_header_t hdr = NULL;
|
cap_user_header_t hdr = NULL;
|
||||||
cap_user_data_t data = NULL;
|
cap_user_data_t data = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
struct dhcp_context *context;
|
||||||
|
|
||||||
#ifdef LOCALEDIR
|
#ifdef LOCALEDIR
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
@@ -84,6 +85,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (!daemon->lease_file)
|
if (!daemon->lease_file)
|
||||||
{
|
{
|
||||||
@@ -120,12 +122,12 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
bind_fallback = 1;
|
bind_fallback = 1;
|
||||||
set_option_bool(OPT_NOWILD);
|
set_option_bool(OPT_NOWILD);
|
||||||
reset_option_bool(OPT_CLVERBIND);
|
reset_option_bool(OPT_CLEVERBIND);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_TFTP
|
#ifndef HAVE_TFTP
|
||||||
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
|
if (option_bool(OPT_TFTP))
|
||||||
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
|
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -147,69 +149,77 @@ int main (int argc, char **argv)
|
|||||||
die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
|
die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_AUTH
|
||||||
|
if (daemon->authserver)
|
||||||
|
die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
|
||||||
rand_init();
|
rand_init();
|
||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
|
/* Create a serial at startup is not configured. */
|
||||||
|
if (daemon->authinterface && daemon->soa_sn == 0)
|
||||||
|
#ifdef HAVE_BROKEN_RTC
|
||||||
|
die(_("zone serial must be configured in --auth-soa"));
|
||||||
|
#else
|
||||||
|
daemon->soa_sn = now;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
if (daemon->dhcp || daemon->dhcp6)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
# ifdef HAVE_DHCP6
|
||||||
|
if (daemon->dhcp6)
|
||||||
|
{
|
||||||
|
daemon->doing_ra = option_bool(OPT_RA);
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
{
|
||||||
|
if (context->flags & CONTEXT_DHCP)
|
||||||
|
daemon->doing_dhcp6 = 1;
|
||||||
|
if (context->flags & CONTEXT_RA)
|
||||||
|
daemon->doing_ra = 1;
|
||||||
|
#ifndef HAVE_LINUX_NETWORK
|
||||||
|
if (context->flags & CONTEXT_TEMPLATE)
|
||||||
|
die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
/* Note that order matters here, we must call lease_init before
|
/* Note that order matters here, we must call lease_init before
|
||||||
creating any file descriptors which shouldn't be leaked
|
creating any file descriptors which shouldn't be leaked
|
||||||
to the lease-script init process. We need to call common_init
|
to the lease-script init process. We need to call common_init
|
||||||
before lease_init to allocate buffers it uses.*/
|
before lease_init to allocate buffers it uses.*/
|
||||||
dhcp_common_init();
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
lease_init(now);
|
{
|
||||||
|
dhcp_common_init();
|
||||||
|
lease_init(now);
|
||||||
|
}
|
||||||
|
|
||||||
if (daemon->dhcp)
|
if (daemon->dhcp)
|
||||||
dhcp_init();
|
dhcp_init();
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef HAVE_DHCP6
|
# ifdef HAVE_DHCP6
|
||||||
/* Start RA subsystem if --enable-ra OR dhcp-range=<subnet>, ra-only */
|
if (daemon->doing_ra)
|
||||||
if (daemon->ra_contexts || option_bool(OPT_RA))
|
ra_init(now);
|
||||||
{
|
|
||||||
/* link the DHCP6 contexts to the ra-only ones so we can traverse them all
|
|
||||||
from ->ra_contexts, but only the non-ra-onlies from ->dhcp6 */
|
|
||||||
struct dhcp_context *context;
|
|
||||||
|
|
||||||
if (!daemon->ra_contexts)
|
if (daemon->doing_dhcp6)
|
||||||
daemon->ra_contexts = daemon->dhcp6;
|
dhcp6_init();
|
||||||
else
|
|
||||||
{
|
|
||||||
for (context = daemon->ra_contexts; context->next; context = context->next);
|
|
||||||
context->next = daemon->dhcp6;
|
|
||||||
}
|
|
||||||
ra_init(now);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon->dhcp6)
|
|
||||||
dhcp6_init();
|
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
/* After lease_init */
|
|
||||||
netlink_init();
|
netlink_init();
|
||||||
|
|
||||||
if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
|
||||||
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
|
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
/* after netlink_init */
|
|
||||||
if (daemon->ra_contexts || daemon->dhcp6)
|
|
||||||
join_multicast();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
|
||||||
/* after netlink_init */
|
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
|
||||||
lease_find_interfaces(now);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!enumerate_interfaces())
|
if (!enumerate_interfaces())
|
||||||
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
@@ -239,6 +249,12 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
create_wildcard_listeners();
|
create_wildcard_listeners();
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
/* after enumerate_interfaces() */
|
||||||
|
if (daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
|
join_multicast(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
cache_init();
|
cache_init();
|
||||||
@@ -383,15 +399,48 @@ int main (int argc, char **argv)
|
|||||||
/* write pidfile _after_ forking ! */
|
/* write pidfile _after_ forking ! */
|
||||||
if (daemon->runfile)
|
if (daemon->runfile)
|
||||||
{
|
{
|
||||||
FILE *pidfile;
|
int fd, err = 0;
|
||||||
|
|
||||||
|
sprintf(daemon->namebuff, "%d\n", (int) getpid());
|
||||||
|
|
||||||
|
/* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
|
||||||
|
in a directory which is writable by the non-privileged user that dnsmasq runs as. This
|
||||||
|
allows the daemon to delete the file as part of its shutdown. This is a security hole to the
|
||||||
|
extent that an attacker running as the unprivileged user could replace the pidfile with a
|
||||||
|
symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
|
||||||
|
|
||||||
|
The folowing code first deletes any existing file, and then opens it with the O_EXCL flag,
|
||||||
|
ensuring that the open() fails should there be any existing file (because the unlink() failed,
|
||||||
|
or an attacker exploited the race between unlink() and open()). This ensures that no symlink
|
||||||
|
attack can succeed.
|
||||||
|
|
||||||
|
Any compromise of the non-privileged user still theoretically allows the pid-file to be
|
||||||
|
replaced whilst dnsmasq is running. The worst that could allow is that the usual
|
||||||
|
"shutdown dnsmasq" shell command could be tricked into stopping any other process.
|
||||||
|
|
||||||
|
Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
|
||||||
|
failure to write the pid-file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unlink(daemon->runfile);
|
||||||
|
|
||||||
/* only complain if started as root */
|
if ((fd = open(daemon->runfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1)
|
||||||
if ((pidfile = fopen(daemon->runfile, "w")))
|
|
||||||
{
|
{
|
||||||
fprintf(pidfile, "%d\n", (int) getpid());
|
/* only complain if started as root */
|
||||||
fclose(pidfile);
|
if (getuid() == 0)
|
||||||
|
err = 1;
|
||||||
}
|
}
|
||||||
else if (getuid() == 0)
|
else
|
||||||
|
{
|
||||||
|
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
|
||||||
|
err = 1;
|
||||||
|
|
||||||
|
while (!err && close(fd) == -1)
|
||||||
|
if (!retry_send())
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
{
|
{
|
||||||
send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
|
send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
|
||||||
_exit(0);
|
_exit(0);
|
||||||
@@ -512,7 +561,7 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
|
if (option_bool(OPT_TFTP))
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct tftp_prefix *p;
|
struct tftp_prefix *p;
|
||||||
@@ -581,94 +630,30 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
if (daemon->max_logs != 0)
|
if (daemon->max_logs != 0)
|
||||||
my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
|
my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
|
||||||
|
|
||||||
if (daemon->ra_contexts)
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6 || daemon->ra_contexts)
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
{
|
log_context(AF_INET, context);
|
||||||
struct dhcp_context *dhcp_tmp;
|
|
||||||
int family = AF_INET;
|
|
||||||
dhcp_tmp = daemon->dhcp;
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
again:
|
|
||||||
#endif
|
|
||||||
for (; dhcp_tmp; dhcp_tmp = dhcp_tmp->next)
|
|
||||||
{
|
|
||||||
void *start = &dhcp_tmp->start;
|
|
||||||
void *end = &dhcp_tmp->end;
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
if (family == AF_INET6)
|
|
||||||
{
|
|
||||||
start = &dhcp_tmp->start6;
|
|
||||||
end = &dhcp_tmp->end6;
|
|
||||||
struct in6_addr subnet = dhcp_tmp->start6;
|
|
||||||
setaddr6part(&subnet, 0);
|
|
||||||
inet_ntop(AF_INET6, &subnet, daemon->addrbuff, 256);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (family != AF_INET && (dhcp_tmp->flags & CONTEXT_DEPRECATE))
|
|
||||||
strcpy(daemon->namebuff, _("prefix deprecated"));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *p = daemon->namebuff;
|
|
||||||
p += sprintf(p, _("lease time "));
|
|
||||||
prettyprint_time(p, dhcp_tmp->lease_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon->dhcp_buff)
|
|
||||||
inet_ntop(family, start, daemon->dhcp_buff, 256);
|
|
||||||
if (daemon->dhcp_buff3)
|
|
||||||
inet_ntop(family, end, daemon->dhcp_buff3, 256);
|
|
||||||
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)
|
# ifdef HAVE_DHCP6
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s"),
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
daemon->addrbuff);
|
log_context(AF_INET6, context);
|
||||||
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
|
|
||||||
if (family == AF_INET)
|
|
||||||
{
|
|
||||||
family = AF_INET6;
|
|
||||||
if (daemon->ra_contexts)
|
|
||||||
dhcp_tmp = daemon->ra_contexts;
|
|
||||||
else
|
|
||||||
dhcp_tmp = daemon->dhcp6;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
if (daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
#endif
|
dhcp_construct_contexts(now);
|
||||||
|
|
||||||
|
if (option_bool(OPT_RA))
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* after dhcp_contruct_contexts */
|
||||||
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
lease_find_interfaces(now);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
|
if (option_bool(OPT_TFTP))
|
||||||
{
|
{
|
||||||
#ifdef FD_SETSIZE
|
#ifdef FD_SETSIZE
|
||||||
if (FD_SETSIZE < (unsigned)max_fd)
|
if (FD_SETSIZE < (unsigned)max_fd)
|
||||||
@@ -772,13 +757,13 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->dhcp6)
|
if (daemon->doing_dhcp6)
|
||||||
{
|
{
|
||||||
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->doing_ra)
|
||||||
{
|
{
|
||||||
FD_SET(daemon->icmp6fd, &rset);
|
FD_SET(daemon->icmp6fd, &rset);
|
||||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
bump_maxfd(daemon->icmp6fd, &maxfd);
|
||||||
@@ -842,7 +827,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
if (FD_ISSET(daemon->netlinkfd, &rset))
|
||||||
netlink_multicast();
|
netlink_multicast(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for changes to resolv files once per second max. */
|
/* Check for changes to resolv files once per second max. */
|
||||||
@@ -890,11 +875,11 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->dhcp6 && FD_ISSET(daemon->dhcp6fd, &rset))
|
if (daemon->doing_dhcp6 && FD_ISSET(daemon->dhcp6fd, &rset))
|
||||||
dhcp6_packet(now);
|
dhcp6_packet(now);
|
||||||
|
|
||||||
if (daemon->ra_contexts && FD_ISSET(daemon->icmp6fd, &rset))
|
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
||||||
icmp6_packet();
|
icmp6_packet(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# ifdef HAVE_SCRIPT
|
# ifdef HAVE_SCRIPT
|
||||||
@@ -1074,13 +1059,13 @@ static void async_event(int pipe, time_t now)
|
|||||||
|
|
||||||
case EVENT_ALARM:
|
case EVENT_ALARM:
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
{
|
{
|
||||||
lease_prune(NULL, now);
|
lease_prune(NULL, now);
|
||||||
lease_update_file(now);
|
lease_update_file(now);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (daemon->ra_contexts)
|
else if (daemon->doing_ra)
|
||||||
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
||||||
send_alarm(periodic_ra(now), now);
|
send_alarm(periodic_ra(now), now);
|
||||||
#endif
|
#endif
|
||||||
@@ -1237,19 +1222,18 @@ void clear_cache_and_reload(time_t now)
|
|||||||
cache_reload();
|
cache_reload();
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
{
|
{
|
||||||
if (option_bool(OPT_ETHERS))
|
if (option_bool(OPT_ETHERS))
|
||||||
dhcp_read_ethers();
|
dhcp_read_ethers();
|
||||||
reread_dhcp();
|
reread_dhcp();
|
||||||
dhcp_update_configs(daemon->dhcp_conf);
|
dhcp_update_configs(daemon->dhcp_conf);
|
||||||
check_dhcp_hosts(0);
|
|
||||||
lease_update_from_configs();
|
lease_update_from_configs();
|
||||||
lease_update_file(now);
|
lease_update_file(now);
|
||||||
lease_update_dns(1);
|
lease_update_dns(1);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (daemon->ra_contexts)
|
else if (daemon->doing_ra)
|
||||||
/* Not doing DHCP, so no lease system, manage
|
/* Not doing DHCP, so no lease system, manage
|
||||||
alarms for ra only */
|
alarms for ra only */
|
||||||
send_alarm(periodic_ra(now), now);
|
send_alarm(periodic_ra(now), now);
|
||||||
@@ -1409,11 +1393,18 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
struct server *s;
|
struct server *s;
|
||||||
int flags;
|
int flags;
|
||||||
struct in_addr netmask;
|
struct in_addr netmask;
|
||||||
|
int auth_dns;
|
||||||
|
|
||||||
if (iface)
|
if (iface)
|
||||||
netmask = iface->netmask;
|
{
|
||||||
|
netmask = iface->netmask;
|
||||||
|
auth_dns = iface->dns_auth;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
netmask.s_addr = 0;
|
{
|
||||||
|
netmask.s_addr = 0;
|
||||||
|
auth_dns = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NO_FORK
|
#ifndef NO_FORK
|
||||||
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
|
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
|
||||||
@@ -1432,7 +1423,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, &tcp_addr, netmask);
|
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
||||||
|
|
||||||
shutdown(confd, SHUT_RDWR);
|
shutdown(confd, SHUT_RDWR);
|
||||||
close(confd);
|
close(confd);
|
||||||
@@ -1545,7 +1536,7 @@ int icmp_ping(struct in_addr addr)
|
|||||||
set_log_writer(&wset, &maxfd);
|
set_log_writer(&wset, &maxfd);
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->ra_contexts)
|
if (daemon->doing_ra)
|
||||||
{
|
{
|
||||||
FD_SET(daemon->icmp6fd, &rset);
|
FD_SET(daemon->icmp6fd, &rset);
|
||||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
bump_maxfd(daemon->icmp6fd, &maxfd);
|
||||||
@@ -1564,8 +1555,8 @@ int icmp_ping(struct in_addr addr)
|
|||||||
check_dns_listeners(&rset, now);
|
check_dns_listeners(&rset, now);
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->ra_contexts && FD_ISSET(daemon->icmp6fd, &rset))
|
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
||||||
icmp6_packet();
|
icmp6_packet(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
|
|||||||
+74
-27
@@ -220,7 +220,8 @@ struct event_desc {
|
|||||||
#define OPT_RA 37
|
#define OPT_RA 37
|
||||||
#define OPT_TFTP_LC 38
|
#define OPT_TFTP_LC 38
|
||||||
#define OPT_CLEVERBIND 39
|
#define OPT_CLEVERBIND 39
|
||||||
#define OPT_LAST 40
|
#define OPT_TFTP 40
|
||||||
|
#define OPT_LAST 41
|
||||||
|
|
||||||
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
||||||
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
||||||
@@ -277,6 +278,20 @@ struct cname {
|
|||||||
struct cname *next;
|
struct cname *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct auth_zone {
|
||||||
|
char *domain;
|
||||||
|
struct subnet {
|
||||||
|
int is6, prefixlen;
|
||||||
|
struct in_addr addr4;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
struct in6_addr addr6;
|
||||||
|
#endif
|
||||||
|
struct subnet *next;
|
||||||
|
} *subnet;
|
||||||
|
struct auth_zone *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct host_record {
|
struct host_record {
|
||||||
struct name_list {
|
struct name_list {
|
||||||
char *name;
|
char *name;
|
||||||
@@ -356,6 +371,8 @@ struct crec {
|
|||||||
#define F_SERVER (1u<<18)
|
#define F_SERVER (1u<<18)
|
||||||
#define F_QUERY (1u<<19)
|
#define F_QUERY (1u<<19)
|
||||||
#define F_NOERR (1u<<20)
|
#define F_NOERR (1u<<20)
|
||||||
|
#define F_AUTH (1u<<21)
|
||||||
|
|
||||||
/* composites */
|
/* composites */
|
||||||
#define F_TYPE (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS) /* Only one may be set */
|
#define F_TYPE (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS) /* Only one may be set */
|
||||||
|
|
||||||
@@ -372,6 +389,11 @@ union mysockaddr {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* bits in flag param to IPv6 callbacks from iface_enumerate() */
|
||||||
|
#define IFACE_TENTATIVE 1
|
||||||
|
#define IFACE_DEPRECATED 2
|
||||||
|
|
||||||
|
|
||||||
#define SERV_FROM_RESOLV 1 /* 1 for servers from resolv, 0 for command line. */
|
#define SERV_FROM_RESOLV 1 /* 1 for servers from resolv, 0 for command line. */
|
||||||
#define SERV_NO_ADDR 2 /* no server, this domain is local only */
|
#define SERV_NO_ADDR 2 /* no server, this domain is local only */
|
||||||
#define SERV_LITERAL_ADDRESS 4 /* addr is the answer, not the server */
|
#define SERV_LITERAL_ADDRESS 4 /* addr is the answer, not the server */
|
||||||
@@ -411,8 +433,8 @@ 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, dhcp_ok, mtu, done, dad;
|
int tftp_ok, dhcp_ok, mtu, done, dad, dns_auth, index, multicast_done;
|
||||||
char *name;
|
char *name;
|
||||||
struct irec *next;
|
struct irec *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -474,7 +496,7 @@ struct frec {
|
|||||||
#define OT_NAME 0x1000
|
#define OT_NAME 0x1000
|
||||||
#define OT_CSTRING 0x0800
|
#define OT_CSTRING 0x0800
|
||||||
#define OT_DEC 0x0400
|
#define OT_DEC 0x0400
|
||||||
|
#define OT_TIME 0x0200
|
||||||
|
|
||||||
/* actions in the daemon->helper RPC */
|
/* actions in the daemon->helper RPC */
|
||||||
#define ACTION_DEL 1
|
#define ACTION_DEL 1
|
||||||
@@ -650,7 +672,7 @@ struct cond_domain {
|
|||||||
#endif
|
#endif
|
||||||
int is6;
|
int is6;
|
||||||
struct cond_domain *next;
|
struct cond_domain *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp_context {
|
struct dhcp_context {
|
||||||
unsigned int lease_time, addr_epoch;
|
unsigned int lease_time, addr_epoch;
|
||||||
@@ -661,10 +683,11 @@ struct dhcp_context {
|
|||||||
struct in6_addr start6, end6; /* range of available addresses */
|
struct in6_addr start6, end6; /* range of available addresses */
|
||||||
struct in6_addr local6;
|
struct in6_addr local6;
|
||||||
int prefix, if_index;
|
int prefix, if_index;
|
||||||
time_t ra_time;
|
unsigned int valid, preferred;
|
||||||
|
time_t ra_time, ra_short_period_start;
|
||||||
|
char *template_interface;
|
||||||
#endif
|
#endif
|
||||||
int flags;
|
int flags;
|
||||||
char *interface;
|
|
||||||
struct dhcp_netid netid, *filter;
|
struct dhcp_netid netid, *filter;
|
||||||
struct dhcp_context *next, *current;
|
struct dhcp_context *next, *current;
|
||||||
};
|
};
|
||||||
@@ -679,6 +702,11 @@ struct dhcp_context {
|
|||||||
#define CONTEXT_RA_STATELESS 128
|
#define CONTEXT_RA_STATELESS 128
|
||||||
#define CONTEXT_DHCP 256
|
#define CONTEXT_DHCP 256
|
||||||
#define CONTEXT_DEPRECATE 512
|
#define CONTEXT_DEPRECATE 512
|
||||||
|
#define CONTEXT_TEMPLATE 1024 /* create contexts using addresses */
|
||||||
|
#define CONTEXT_CONSTRUCTED 2048
|
||||||
|
#define CONTEXT_GC 4096
|
||||||
|
#define CONTEXT_RA 8192
|
||||||
|
|
||||||
|
|
||||||
struct ping_result {
|
struct ping_result {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
@@ -712,11 +740,6 @@ struct addr_list {
|
|||||||
struct addr_list *next;
|
struct addr_list *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct interface_list {
|
|
||||||
char *interface;
|
|
||||||
struct interface_list *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tftp_prefix {
|
struct tftp_prefix {
|
||||||
char *interface;
|
char *interface;
|
||||||
char *prefix;
|
char *prefix;
|
||||||
@@ -738,17 +761,21 @@ extern struct daemon {
|
|||||||
struct ptr_record *ptr;
|
struct ptr_record *ptr;
|
||||||
struct host_record *host_records, *host_records_tail;
|
struct host_record *host_records, *host_records_tail;
|
||||||
struct cname *cnames;
|
struct cname *cnames;
|
||||||
|
struct auth_zone *auth_zones;
|
||||||
struct interface_name *int_names;
|
struct interface_name *int_names;
|
||||||
char *mxtarget;
|
char *mxtarget;
|
||||||
char *lease_file;
|
char *lease_file;
|
||||||
char *username, *groupname, *scriptuser;
|
char *username, *groupname, *scriptuser;
|
||||||
char *luascript;
|
char *luascript;
|
||||||
|
char *authserver, *hostmaster;
|
||||||
|
struct iname *authinterface;
|
||||||
|
struct name_list *secondary_forward_server;
|
||||||
int group_set, osport;
|
int group_set, osport;
|
||||||
char *domain_suffix;
|
char *domain_suffix;
|
||||||
struct cond_domain *cond_domain;
|
struct cond_domain *cond_domain;
|
||||||
char *runfile;
|
char *runfile;
|
||||||
char *lease_change_command;
|
char *lease_change_command;
|
||||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
|
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers;
|
||||||
struct bogus_addr *bogus_addr;
|
struct bogus_addr *bogus_addr;
|
||||||
struct server *servers;
|
struct server *servers;
|
||||||
int log_fac; /* log facility */
|
int log_fac; /* log facility */
|
||||||
@@ -756,9 +783,9 @@ extern struct daemon {
|
|||||||
int max_logs; /* queue limit */
|
int max_logs; /* queue limit */
|
||||||
int cachesize, ftabsize;
|
int cachesize, ftabsize;
|
||||||
int port, query_port, min_port;
|
int port, query_port, min_port;
|
||||||
unsigned long local_ttl, neg_ttl, max_ttl;
|
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
|
||||||
struct hostsfile *addn_hosts;
|
struct hostsfile *addn_hosts;
|
||||||
struct dhcp_context *dhcp, *dhcp6, *ra_contexts;
|
struct dhcp_context *dhcp, *dhcp6;
|
||||||
struct dhcp_config *dhcp_conf;
|
struct dhcp_config *dhcp_conf;
|
||||||
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
||||||
struct dhcp_vendor *dhcp_vendors;
|
struct dhcp_vendor *dhcp_vendors;
|
||||||
@@ -769,6 +796,7 @@ extern struct daemon {
|
|||||||
struct addr_list *override_relays;
|
struct addr_list *override_relays;
|
||||||
int override;
|
int override;
|
||||||
int enable_pxe;
|
int enable_pxe;
|
||||||
|
int doing_ra, doing_dhcp6;
|
||||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
||||||
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
||||||
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
|
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
|
||||||
@@ -780,10 +808,10 @@ extern struct daemon {
|
|||||||
unsigned short edns_pktsz;
|
unsigned short edns_pktsz;
|
||||||
char *tftp_prefix;
|
char *tftp_prefix;
|
||||||
struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
|
struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
|
||||||
struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
|
|
||||||
int tftp_unlimited;
|
|
||||||
unsigned int duid_enterprise, duid_config_len;
|
unsigned int duid_enterprise, duid_config_len;
|
||||||
unsigned char *duid_config;
|
unsigned char *duid_config;
|
||||||
|
char *dbus_name;
|
||||||
|
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
||||||
|
|
||||||
/* globally used stuff for DNS */
|
/* globally used stuff for DNS */
|
||||||
char *packet; /* packet buffer */
|
char *packet; /* packet buffer */
|
||||||
@@ -841,7 +869,7 @@ extern struct daemon {
|
|||||||
void cache_init(void);
|
void cache_init(void);
|
||||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
||||||
char *record_source(int index);
|
char *record_source(int index);
|
||||||
void querystr(char *str, unsigned short type);
|
void querystr(char *desc, char *str, unsigned short type);
|
||||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||||
struct all_addr *addr, time_t now,
|
struct all_addr *addr, time_t now,
|
||||||
unsigned short prot);
|
unsigned short prot);
|
||||||
@@ -857,6 +885,7 @@ struct in_addr a_record_from_hosts(char *name, time_t now);
|
|||||||
void cache_unhash_dhcp(void);
|
void cache_unhash_dhcp(void);
|
||||||
void dump_cache(time_t now);
|
void dump_cache(time_t now);
|
||||||
char *cache_get_name(struct crec *crecp);
|
char *cache_get_name(struct crec *crecp);
|
||||||
|
struct crec *cache_enumerate(int init);
|
||||||
char *get_domain(struct in_addr addr);
|
char *get_domain(struct in_addr addr);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
char *get_domain6(struct in6_addr *addr);
|
char *get_domain6(struct in6_addr *addr);
|
||||||
@@ -885,6 +914,18 @@ unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
|
|||||||
size_t resize_packet(struct dns_header *header, size_t plen,
|
size_t resize_packet(struct dns_header *header, size_t plen,
|
||||||
unsigned char *pheader, size_t hlen);
|
unsigned char *pheader, size_t hlen);
|
||||||
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
|
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
|
||||||
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||||
|
int nameoffset, unsigned char **pp, unsigned long ttl,
|
||||||
|
int *offset, unsigned short type, unsigned short class, char *format, ...);
|
||||||
|
unsigned char *skip_questions(struct dns_header *header, size_t plen);
|
||||||
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
|
char *name, int isExtract, int extrabytes);
|
||||||
|
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
||||||
|
|
||||||
|
/* auth.c */
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
void rand_init(void);
|
void rand_init(void);
|
||||||
@@ -897,7 +938,7 @@ void safe_pipe(int *fd, int read_noblock);
|
|||||||
void *whine_malloc(size_t size);
|
void *whine_malloc(size_t size);
|
||||||
int sa_len(union mysockaddr *addr);
|
int sa_len(union mysockaddr *addr);
|
||||||
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
||||||
int hostname_isequal(char *a, char *b);
|
int hostname_isequal(const char *a, const char *b);
|
||||||
time_t dnsmasq_time(void);
|
time_t dnsmasq_time(void);
|
||||||
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -934,12 +975,14 @@ void reread_dhcp(void);
|
|||||||
void set_option_bool(unsigned int opt);
|
void set_option_bool(unsigned int opt);
|
||||||
void reset_option_bool(unsigned int opt);
|
void reset_option_bool(unsigned int opt);
|
||||||
struct hostsfile *expand_filelist(struct hostsfile *list);
|
struct hostsfile *expand_filelist(struct hostsfile *list);
|
||||||
|
char *parse_server(char *arg, union mysockaddr *addr,
|
||||||
|
union mysockaddr *source_addr, char *interface, int *flags);
|
||||||
|
|
||||||
/* forward.c */
|
/* forward.c */
|
||||||
void reply_query(int fd, int family, time_t now);
|
void reply_query(int fd, int family, time_t now);
|
||||||
void receive_query(struct listener *listen, time_t now);
|
void receive_query(struct listener *listen, time_t now);
|
||||||
unsigned char *tcp_request(int confd, time_t now,
|
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, int auth_dns);
|
||||||
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);
|
||||||
int send_from(int fd, int nowild, char *packet, size_t len,
|
int send_from(int fd, int nowild, char *packet, size_t len,
|
||||||
@@ -957,12 +1000,15 @@ int enumerate_interfaces();
|
|||||||
void create_wildcard_listeners(void);
|
void create_wildcard_listeners(void);
|
||||||
void create_bound_listeners(int die);
|
void create_bound_listeners(int die);
|
||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
int iface_check(int family, struct all_addr *addr, char *name);
|
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
||||||
int fix_fd(int fd);
|
int fix_fd(int fd);
|
||||||
struct in_addr get_ifaddr(char *intr);
|
struct in_addr get_ifaddr(char *intr);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
int set_ipv6pktinfo(int fd);
|
int set_ipv6pktinfo(int fd);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
void join_multicast(int dienow);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* dhcp.c */
|
/* dhcp.c */
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
@@ -998,9 +1044,11 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr);
|
|||||||
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
|
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
|
||||||
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
||||||
int lease_type, int iaid, struct in6_addr *addr);
|
int lease_type, int iaid, struct in6_addr *addr);
|
||||||
|
void lease6_filter(int lease_type, int iaid, struct dhcp_context *context);
|
||||||
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
|
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
|
||||||
u64 lease_find_max_addr6(struct dhcp_context *context);
|
u64 lease_find_max_addr6(struct dhcp_context *context);
|
||||||
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);
|
||||||
|
void lease_update_slaac(time_t now);
|
||||||
#endif
|
#endif
|
||||||
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||||
unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
|
unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
|
||||||
@@ -1043,7 +1091,7 @@ void poll_resolv(int force, int do_reload, time_t now);
|
|||||||
/* netlink.c */
|
/* netlink.c */
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
void netlink_init(void);
|
void netlink_init(void);
|
||||||
void netlink_multicast(void);
|
void netlink_multicast(time_t now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bpf.c */
|
/* bpf.c */
|
||||||
@@ -1097,6 +1145,7 @@ void dhcp6_init(void);
|
|||||||
void dhcp6_packet(time_t now);
|
void dhcp6_packet(time_t now);
|
||||||
int address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
|
int address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
|
||||||
int serial, struct dhcp_netid *netids, struct in6_addr *ans);
|
int serial, struct dhcp_netid *netids, struct in6_addr *ans);
|
||||||
|
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr);
|
||||||
struct dhcp_context *address6_available(struct dhcp_context *context,
|
struct dhcp_context *address6_available(struct dhcp_context *context,
|
||||||
struct in6_addr *taddr,
|
struct in6_addr *taddr,
|
||||||
struct dhcp_netid *netids);
|
struct dhcp_netid *netids);
|
||||||
@@ -1110,6 +1159,7 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
|
|||||||
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net,
|
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net,
|
||||||
int prefix, u64 addr);
|
int prefix, u64 addr);
|
||||||
void make_duid(time_t now);
|
void make_duid(time_t now);
|
||||||
|
void dhcp_construct_contexts(time_t now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* rfc3315.c */
|
/* rfc3315.c */
|
||||||
@@ -1130,7 +1180,6 @@ char *strip_hostname(char *hostname);
|
|||||||
void log_tags(struct dhcp_netid *netid, u32 xid);
|
void log_tags(struct dhcp_netid *netid, u32 xid);
|
||||||
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
||||||
void dhcp_update_configs(struct dhcp_config *configs);
|
void dhcp_update_configs(struct dhcp_config *configs);
|
||||||
void check_dhcp_hosts(int fatal);
|
|
||||||
void display_opts(void);
|
void display_opts(void);
|
||||||
u16 lookup_dhcp_opt(int prot, char *name);
|
u16 lookup_dhcp_opt(int prot, char *name);
|
||||||
u16 lookup_dhcp_len(int prot, u16 val);
|
u16 lookup_dhcp_len(int prot, u16 val);
|
||||||
@@ -1141,8 +1190,8 @@ void bindtodevice(int fd);
|
|||||||
#endif
|
#endif
|
||||||
# ifdef HAVE_DHCP6
|
# ifdef HAVE_DHCP6
|
||||||
void display_opts6(void);
|
void display_opts6(void);
|
||||||
void join_multicast(void);
|
|
||||||
# endif
|
# endif
|
||||||
|
void log_context(int family, struct dhcp_context *context);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* outpacket.c */
|
/* outpacket.c */
|
||||||
@@ -1161,16 +1210,14 @@ void put_opt6_string(char *s);
|
|||||||
/* radv.c */
|
/* radv.c */
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
void ra_init(time_t now);
|
void ra_init(time_t now);
|
||||||
void icmp6_packet(void);
|
void icmp6_packet(time_t now);
|
||||||
time_t periodic_ra(time_t now);
|
time_t periodic_ra(time_t now);
|
||||||
void ra_start_unsolicted(time_t now, struct dhcp_context *context);
|
void ra_start_unsolicted(time_t now, struct dhcp_context *context);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* slaac.c */
|
/* slaac.c */
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
void build_subnet_map(void);
|
|
||||||
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force);
|
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force);
|
||||||
time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
|
time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
|
||||||
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
|
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
|
||||||
void schedule_subnet_map(void);
|
|
||||||
#endif
|
#endif
|
||||||
+173
-154
@@ -95,26 +95,19 @@ int send_from(int fd, int nowild, char *packet, size_t len,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
retry:
|
while (sendmsg(fd, &msg, 0) == -1)
|
||||||
if (sendmsg(fd, &msg, 0) == -1)
|
|
||||||
{
|
{
|
||||||
/* certain Linux kernels seem to object to setting the source address in the IPv6 stack
|
|
||||||
by returning EINVAL from sendmsg. In that case, try again without setting the
|
|
||||||
source address, since it will nearly alway be correct anyway. IPv6 stinks. */
|
|
||||||
if (errno == EINVAL && msg.msg_controllen)
|
|
||||||
{
|
|
||||||
msg.msg_controllen = 0;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retry_send())
|
if (retry_send())
|
||||||
goto retry;
|
continue;
|
||||||
|
|
||||||
|
/* If interface is still in DAD, EINVAL results - ignore that. */
|
||||||
|
if (errno == EINVAL)
|
||||||
|
break;
|
||||||
|
|
||||||
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 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,6 +635,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
size_t m;
|
size_t m;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int if_index = 0;
|
int if_index = 0;
|
||||||
|
int auth_dns = 0;
|
||||||
struct iovec iov[1];
|
struct iovec iov[1];
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct cmsghdr *cmptr;
|
struct cmsghdr *cmptr;
|
||||||
@@ -664,17 +658,20 @@ 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->iface && listen->family == AF_INET && option_bool(OPT_NOWILD))
|
dst_addr_4.s_addr = 0;
|
||||||
|
netmask.s_addr = 0;
|
||||||
|
|
||||||
|
if (listen->iface && option_bool(OPT_NOWILD))
|
||||||
{
|
{
|
||||||
dst_addr_4 = listen->iface->addr.in.sin_addr;
|
auth_dns = listen->iface->dns_auth;
|
||||||
netmask = listen->iface->netmask;
|
|
||||||
|
if (listen->family == AF_INET)
|
||||||
|
{
|
||||||
|
dst_addr_4 = listen->iface->addr.in.sin_addr;
|
||||||
|
netmask = listen->iface->netmask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
dst_addr_4.s_addr = 0;
|
|
||||||
netmask.s_addr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
iov[0].iov_base = daemon->packet;
|
iov[0].iov_base = daemon->packet;
|
||||||
iov[0].iov_len = daemon->edns_pktsz;
|
iov[0].iov_len = daemon->edns_pktsz;
|
||||||
|
|
||||||
@@ -767,7 +764,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
/* enforce available interface configuration */
|
/* enforce available interface configuration */
|
||||||
|
|
||||||
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
|
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
|
||||||
!iface_check(listen->family, &dst_addr, ifr.ifr_name))
|
!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
|
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
|
||||||
@@ -803,7 +800,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
char types[20];
|
char types[20];
|
||||||
|
|
||||||
querystr(types, type);
|
querystr(auth_dns ? "auth" : "query", types, type);
|
||||||
|
|
||||||
if (listen->family == AF_INET)
|
if (listen->family == AF_INET)
|
||||||
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||||
@@ -815,19 +812,32 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n,
|
#ifdef HAVE_AUTH
|
||||||
dst_addr_4, netmask, now);
|
if (auth_dns)
|
||||||
if (m >= 1)
|
|
||||||
{
|
{
|
||||||
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr);
|
||||||
(char *)header, m, &source_addr, &dst_addr, if_index);
|
if (m >= 1)
|
||||||
daemon->local_answer++;
|
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||||
|
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||||
}
|
}
|
||||||
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
|
|
||||||
header, (size_t)n, now, NULL))
|
|
||||||
daemon->queries_forwarded++;
|
|
||||||
else
|
else
|
||||||
daemon->local_answer++;
|
#endif
|
||||||
|
{
|
||||||
|
m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n,
|
||||||
|
dst_addr_4, netmask, now);
|
||||||
|
|
||||||
|
if (m >= 1)
|
||||||
|
{
|
||||||
|
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||||
|
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||||
|
daemon->local_answer++;
|
||||||
|
}
|
||||||
|
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
|
||||||
|
header, (size_t)n, now, NULL))
|
||||||
|
daemon->queries_forwarded++;
|
||||||
|
else
|
||||||
|
daemon->local_answer++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The daemon forks before calling this: it should deal with one connection,
|
/* The daemon forks before calling this: it should deal with one connection,
|
||||||
@@ -835,13 +845,14 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
about resources for debug mode, when the fork is suppressed: that's
|
about resources for debug mode, when the fork is suppressed: that's
|
||||||
done by the caller. */
|
done by the caller. */
|
||||||
unsigned char *tcp_request(int confd, time_t now,
|
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, int auth_dns)
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
int norebind = 0;
|
int norebind = 0;
|
||||||
int checking_disabled;
|
int checking_disabled;
|
||||||
size_t m;
|
size_t m;
|
||||||
unsigned short qtype, gotname;
|
unsigned short qtype;
|
||||||
|
unsigned int gotname;
|
||||||
unsigned char c1, c2;
|
unsigned char c1, c2;
|
||||||
/* Max TCP packet + slop */
|
/* Max TCP packet + slop */
|
||||||
unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ);
|
unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ);
|
||||||
@@ -877,7 +888,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
{
|
{
|
||||||
char types[20];
|
char types[20];
|
||||||
|
|
||||||
querystr(types, qtype);
|
querystr(auth_dns ? "auth" : "query", types, qtype);
|
||||||
|
|
||||||
if (peer_addr.sa.sa_family == AF_INET)
|
if (peer_addr.sa.sa_family == AF_INET)
|
||||||
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||||
@@ -894,142 +905,150 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
else
|
else
|
||||||
dst_addr_4.s_addr = 0;
|
dst_addr_4.s_addr = 0;
|
||||||
|
|
||||||
/* m > 0 if answered from cache */
|
#ifdef HAVE_AUTH
|
||||||
m = answer_request(header, ((char *) header) + 65536, (unsigned int)size,
|
if (auth_dns)
|
||||||
dst_addr_4, netmask, now);
|
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr);
|
||||||
|
else
|
||||||
/* Do this by steam now we're not in the select() loop */
|
#endif
|
||||||
check_log_writer(NULL);
|
|
||||||
|
|
||||||
if (m == 0)
|
|
||||||
{
|
{
|
||||||
unsigned int flags = 0;
|
/* m > 0 if answered from cache */
|
||||||
struct all_addr *addrp = NULL;
|
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
||||||
int type = 0;
|
dst_addr_4, netmask, now);
|
||||||
char *domain = NULL;
|
|
||||||
|
|
||||||
if (option_bool(OPT_ADD_MAC))
|
|
||||||
size = add_mac(header, size, ((char *) header) + 65536, &peer_addr);
|
|
||||||
|
|
||||||
if (gotname)
|
|
||||||
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
|
|
||||||
|
|
||||||
if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
|
/* Do this by steam now we're not in the select() loop */
|
||||||
last_server = daemon->servers;
|
check_log_writer(NULL);
|
||||||
else
|
|
||||||
last_server = daemon->last_server;
|
if (m == 0)
|
||||||
|
|
||||||
if (!flags && last_server)
|
|
||||||
{
|
{
|
||||||
struct server *firstsendto = NULL;
|
unsigned int flags = 0;
|
||||||
unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
|
struct all_addr *addrp = NULL;
|
||||||
|
int type = 0;
|
||||||
/* Loop round available servers until we succeed in connecting to one.
|
char *domain = NULL;
|
||||||
Note that this code subtley ensures that consecutive queries on this connection
|
|
||||||
which can go to the same server, do so. */
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (!firstsendto)
|
|
||||||
firstsendto = last_server;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!(last_server = last_server->next))
|
|
||||||
last_server = daemon->servers;
|
|
||||||
|
|
||||||
if (last_server == firstsendto)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* server for wrong domain */
|
if (option_bool(OPT_ADD_MAC))
|
||||||
if (type != (last_server->flags & SERV_TYPE) ||
|
size = add_mac(header, size, ((char *) header) + 65536, &peer_addr);
|
||||||
(type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
|
|
||||||
continue;
|
if (gotname)
|
||||||
|
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
|
||||||
if (last_server->tcpfd == -1)
|
|
||||||
|
if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
|
||||||
|
last_server = daemon->servers;
|
||||||
|
else
|
||||||
|
last_server = daemon->last_server;
|
||||||
|
|
||||||
|
if (!flags && last_server)
|
||||||
|
{
|
||||||
|
struct server *firstsendto = NULL;
|
||||||
|
unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
|
||||||
|
|
||||||
|
/* Loop round available servers until we succeed in connecting to one.
|
||||||
|
Note that this code subtley ensures that consecutive queries on this connection
|
||||||
|
which can go to the same server, do so. */
|
||||||
|
while (1)
|
||||||
{
|
{
|
||||||
if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
|
if (!firstsendto)
|
||||||
|
firstsendto = last_server;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(last_server = last_server->next))
|
||||||
|
last_server = daemon->servers;
|
||||||
|
|
||||||
|
if (last_server == firstsendto)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* server for wrong domain */
|
||||||
|
if (type != (last_server->flags & SERV_TYPE) ||
|
||||||
|
(type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
|
if (last_server->tcpfd == -1)
|
||||||
connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
|
{
|
||||||
|
if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, 1) ||
|
||||||
|
connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
|
||||||
|
{
|
||||||
|
close(last_server->tcpfd);
|
||||||
|
last_server->tcpfd = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CONNTRACK
|
||||||
|
/* Copy connection mark of incoming query to outgoing connection. */
|
||||||
|
if (option_bool(OPT_CONNTRACK))
|
||||||
|
{
|
||||||
|
unsigned int mark;
|
||||||
|
struct all_addr local;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (local_addr->sa.sa_family == AF_INET6)
|
||||||
|
local.addr.addr6 = local_addr->in6.sin6_addr;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
local.addr.addr4 = local_addr->in.sin_addr;
|
||||||
|
|
||||||
|
if (get_incoming_mark(&peer_addr, &local, 1, &mark))
|
||||||
|
setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
c1 = size >> 8;
|
||||||
|
c2 = size;
|
||||||
|
|
||||||
|
if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
|
||||||
|
!read_write(last_server->tcpfd, &c2, 1, 0) ||
|
||||||
|
!read_write(last_server->tcpfd, packet, size, 0) ||
|
||||||
|
!read_write(last_server->tcpfd, &c1, 1, 1) ||
|
||||||
|
!read_write(last_server->tcpfd, &c2, 1, 1))
|
||||||
{
|
{
|
||||||
close(last_server->tcpfd);
|
close(last_server->tcpfd);
|
||||||
last_server->tcpfd = -1;
|
last_server->tcpfd = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
m = (c1 << 8) | c2;
|
||||||
/* Copy connection mark of incoming query to outgoing connection. */
|
if (!read_write(last_server->tcpfd, packet, m, 1))
|
||||||
if (option_bool(OPT_CONNTRACK))
|
return packet;
|
||||||
{
|
|
||||||
unsigned int mark;
|
if (!gotname)
|
||||||
struct all_addr local;
|
strcpy(daemon->namebuff, "query");
|
||||||
#ifdef HAVE_IPV6
|
if (last_server->addr.sa.sa_family == AF_INET)
|
||||||
if (local_addr->sa.sa_family == AF_INET6)
|
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||||
local.addr.addr6 = local_addr->in6.sin6_addr;
|
(struct all_addr *)&last_server->addr.in.sin_addr, NULL);
|
||||||
else
|
|
||||||
#endif
|
|
||||||
local.addr.addr4 = local_addr->in.sin_addr;
|
|
||||||
|
|
||||||
if (get_incoming_mark(&peer_addr, &local, 1, &mark))
|
|
||||||
setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
c1 = size >> 8;
|
|
||||||
c2 = size;
|
|
||||||
|
|
||||||
if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
|
|
||||||
!read_write(last_server->tcpfd, &c2, 1, 0) ||
|
|
||||||
!read_write(last_server->tcpfd, packet, size, 0) ||
|
|
||||||
!read_write(last_server->tcpfd, &c1, 1, 1) ||
|
|
||||||
!read_write(last_server->tcpfd, &c2, 1, 1))
|
|
||||||
{
|
|
||||||
close(last_server->tcpfd);
|
|
||||||
last_server->tcpfd = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
m = (c1 << 8) | c2;
|
|
||||||
if (!read_write(last_server->tcpfd, packet, m, 1))
|
|
||||||
return packet;
|
|
||||||
|
|
||||||
if (!gotname)
|
|
||||||
strcpy(daemon->namebuff, "query");
|
|
||||||
if (last_server->addr.sa.sa_family == AF_INET)
|
|
||||||
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
|
|
||||||
(struct all_addr *)&last_server->addr.in.sin_addr, NULL);
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
else
|
||||||
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
|
||||||
(struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
|
(struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* There's no point in updating the cache, since this process will exit and
|
/* There's no point in updating the cache, since this process will exit and
|
||||||
lose the information after a few queries. We make this call for the alias and
|
lose the information after a few queries. We make this call for the alias and
|
||||||
bogus-nxdomain side-effects. */
|
bogus-nxdomain side-effects. */
|
||||||
/* If the crc of the question section doesn't match the crc we sent, then
|
/* If the crc of the question section doesn't match the crc we sent, then
|
||||||
someone might be attempting to insert bogus values into the cache by
|
someone might be attempting to insert bogus values into the cache by
|
||||||
sending replies containing questions and bogus answers. */
|
sending replies containing questions and bogus answers. */
|
||||||
if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff))
|
if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff))
|
||||||
m = process_reply(header, now, last_server, (unsigned int)m,
|
m = process_reply(header, now, last_server, (unsigned int)m,
|
||||||
option_bool(OPT_NO_REBIND) && !norebind, checking_disabled);
|
option_bool(OPT_NO_REBIND) && !norebind, checking_disabled);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In case of local answer or no connections made. */
|
||||||
|
if (m == 0)
|
||||||
|
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case of local answer or no connections made. */
|
|
||||||
if (m == 0)
|
|
||||||
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_log_writer(NULL);
|
check_log_writer(NULL);
|
||||||
|
|
||||||
c1 = m>>8;
|
c1 = m>>8;
|
||||||
c2 = m;
|
c2 = m;
|
||||||
if (!read_write(confd, &c1, 1, 0) ||
|
if (m == 0 ||
|
||||||
|
!read_write(confd, &c1, 1, 0) ||
|
||||||
!read_write(confd, &c2, 1, 0) ||
|
!read_write(confd, &c2, 1, 0) ||
|
||||||
!read_write(confd, packet, m, 0))
|
!read_write(confd, packet, m, 0))
|
||||||
return packet;
|
return packet;
|
||||||
|
|||||||
@@ -34,10 +34,15 @@ static void my_setenv(const char *name, const char *value, int *error);
|
|||||||
static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end, char *env, int *err);
|
static unsigned char *grab_extradata(unsigned char *buf, unsigned char *end, char *env, int *err);
|
||||||
|
|
||||||
#ifdef HAVE_LUASCRIPT
|
#ifdef HAVE_LUASCRIPT
|
||||||
|
#define LUA_COMPAT_ALL
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#ifndef lua_open
|
||||||
|
#define lua_open() luaL_newstate()
|
||||||
|
#endif
|
||||||
|
|
||||||
lua_State *lua;
|
lua_State *lua;
|
||||||
|
|
||||||
static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end, char *field);
|
static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end, char *field);
|
||||||
|
|||||||
+43
-14
@@ -308,7 +308,7 @@ void lease_update_file(time_t now)
|
|||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
/* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
|
/* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
|
||||||
if (daemon->ra_contexts)
|
if (daemon->doing_ra)
|
||||||
{
|
{
|
||||||
time_t event;
|
time_t event;
|
||||||
|
|
||||||
@@ -363,12 +363,15 @@ static int find_interface_v4(struct in_addr local, int if_index,
|
|||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
static int find_interface_v6(struct in6_addr *local, int prefix,
|
static int find_interface_v6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int flags,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
(void)scope;
|
(void)scope;
|
||||||
(void)dad;
|
(void)flags;
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
if ((lease->flags & (LEASE_TA | LEASE_NA)))
|
if ((lease->flags & (LEASE_TA | LEASE_NA)))
|
||||||
@@ -386,6 +389,18 @@ void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
|||||||
slaac_ping_reply(sender, packet, interface, leases);
|
slaac_ping_reply(sender, packet, interface, leases);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lease_update_slaac(time_t now)
|
||||||
|
{
|
||||||
|
/* Called when we contruct a new RA-names context, to add putative
|
||||||
|
new SLAAC addresses to existing leases. */
|
||||||
|
|
||||||
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
|
if (daemon->dhcp)
|
||||||
|
for (lease = leases; lease; lease = lease->next)
|
||||||
|
slaac_add_addrs(lease, now, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -395,10 +410,6 @@ void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
|||||||
start-time. */
|
start-time. */
|
||||||
void lease_find_interfaces(time_t now)
|
void lease_find_interfaces(time_t now)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
build_subnet_map();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
iface_enumerate(AF_INET, &now, find_interface_v4);
|
iface_enumerate(AF_INET, &now, find_interface_v4);
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
||||||
@@ -420,6 +431,11 @@ void lease_update_dns(int force)
|
|||||||
|
|
||||||
if (daemon->port != 0 && (dns_dirty || force))
|
if (daemon->port != 0 && (dns_dirty || force))
|
||||||
{
|
{
|
||||||
|
#ifndef HAVE_BROKEN_RTC
|
||||||
|
/* force transfer to authoritative secondaries */
|
||||||
|
daemon->soa_sn++;
|
||||||
|
#endif
|
||||||
|
|
||||||
cache_unhash_dhcp();
|
cache_unhash_dhcp();
|
||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
@@ -562,18 +578,31 @@ struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
|||||||
memcmp(clid, lease->clid, clid_len) != 0))
|
memcmp(clid, lease->clid, clid_len) != 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (clid || addr)
|
lease->flags |= LEASE_USED;
|
||||||
{
|
return lease;
|
||||||
lease->flags |= LEASE_USED;
|
|
||||||
return lease;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lease->flags &= ~LEASE_USED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lease6_filter(int lease_type, int iaid, struct dhcp_context *context)
|
||||||
|
{
|
||||||
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
|
for (lease = leases; lease; lease = lease->next)
|
||||||
|
{
|
||||||
|
/* reset "USED flag */
|
||||||
|
lease->flags &= ~LEASE_USED;
|
||||||
|
|
||||||
|
if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* leases on the wrong interface get filtered out here */
|
||||||
|
if (!is_addr_in_context6(context, (struct in6_addr *)&lease->hwaddr))
|
||||||
|
lease->flags |= LEASE_USED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
|
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|||||||
+77
-60
@@ -39,7 +39,7 @@ static struct iovec iov;
|
|||||||
static u32 netlink_pid;
|
static u32 netlink_pid;
|
||||||
|
|
||||||
static int nl_async(struct nlmsghdr *h);
|
static int nl_async(struct nlmsghdr *h);
|
||||||
static void nl_routechange(struct nlmsghdr *h);
|
static void nl_newaddress(time_t now);
|
||||||
|
|
||||||
void netlink_init(void)
|
void netlink_init(void)
|
||||||
{
|
{
|
||||||
@@ -51,10 +51,14 @@ void netlink_init(void)
|
|||||||
addr.nl_pid = 0; /* autobind */
|
addr.nl_pid = 0; /* autobind */
|
||||||
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
||||||
if (option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
||||||
if (daemon->ra_contexts || option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
|
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (daemon->doing_ra || daemon->doing_dhcp6)
|
||||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -188,7 +192,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||||
{
|
{
|
||||||
/* May be multicast arriving async */
|
/* May be multicast arriving async */
|
||||||
if (nl_async(h) && option_bool(OPT_CLEVERBIND))
|
if (nl_async(h))
|
||||||
newaddr = 1;
|
newaddr = 1;
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == NLMSG_DONE)
|
else if (h->nlmsg_type == NLMSG_DONE)
|
||||||
@@ -196,11 +200,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
/* handle async new interface address arrivals, these have to be done
|
/* handle async new interface address arrivals, these have to be done
|
||||||
after we complete as we're not re-entrant */
|
after we complete as we're not re-entrant */
|
||||||
if (newaddr)
|
if (newaddr)
|
||||||
{
|
nl_newaddress(dnsmasq_time());
|
||||||
enumerate_interfaces();
|
|
||||||
create_bound_listeners(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback_ok;
|
return callback_ok;
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
||||||
@@ -237,17 +238,32 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
else if (ifa->ifa_family == AF_INET6)
|
else if (ifa->ifa_family == AF_INET6)
|
||||||
{
|
{
|
||||||
struct in6_addr *addrp = NULL;
|
struct in6_addr *addrp = NULL;
|
||||||
|
u32 valid = 0, preferred = 0;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
while (RTA_OK(rta, len1))
|
while (RTA_OK(rta, len1))
|
||||||
{
|
{
|
||||||
if (rta->rta_type == IFA_ADDRESS)
|
if (rta->rta_type == IFA_ADDRESS)
|
||||||
addrp = ((struct in6_addr *)(rta+1));
|
addrp = ((struct in6_addr *)(rta+1));
|
||||||
|
else if (rta->rta_type == IFA_CACHEINFO)
|
||||||
|
{
|
||||||
|
struct ifa_cacheinfo *ifc = (struct ifa_cacheinfo *)(rta+1);
|
||||||
|
preferred = ifc->ifa_prefered;
|
||||||
|
valid = ifc->ifa_valid;
|
||||||
|
}
|
||||||
rta = RTA_NEXT(rta, len1);
|
rta = RTA_NEXT(rta, len1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifa->ifa_flags & IFA_F_TENTATIVE)
|
||||||
|
flags |= IFACE_TENTATIVE;
|
||||||
|
|
||||||
|
if (ifa->ifa_flags & IFA_F_DEPRECATED)
|
||||||
|
flags |= IFACE_DEPRECATED;
|
||||||
|
|
||||||
if (addrp && callback_ok)
|
if (addrp && callback_ok)
|
||||||
if (!((*callback)(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope),
|
if (!((*callback)(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope),
|
||||||
(int)(ifa->ifa_index), (int)(ifa->ifa_flags & IFA_F_TENTATIVE), parm)))
|
(int)(ifa->ifa_index), flags,
|
||||||
|
(int) preferred, (int)valid, parm)))
|
||||||
callback_ok = 0;
|
callback_ok = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -306,7 +322,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void netlink_multicast(void)
|
void netlink_multicast(time_t now)
|
||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
@@ -319,17 +335,14 @@ void netlink_multicast(void)
|
|||||||
|
|
||||||
if ((len = netlink_recv()) != -1)
|
if ((len = netlink_recv()) != -1)
|
||||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||||
if (nl_async(h) && option_bool(OPT_CLEVERBIND))
|
if (nl_async(h))
|
||||||
newaddr = 1;
|
newaddr = 1;
|
||||||
|
|
||||||
/* restore non-blocking status */
|
/* restore non-blocking status */
|
||||||
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
||||||
|
|
||||||
if (newaddr)
|
if (newaddr)
|
||||||
{
|
nl_newaddress(now);
|
||||||
enumerate_interfaces();
|
|
||||||
create_bound_listeners(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl_async(struct nlmsghdr *h)
|
static int nl_async(struct nlmsghdr *h)
|
||||||
@@ -337,61 +350,65 @@ static int nl_async(struct nlmsghdr *h)
|
|||||||
if (h->nlmsg_type == NLMSG_ERROR)
|
if (h->nlmsg_type == NLMSG_ERROR)
|
||||||
{
|
{
|
||||||
struct nlmsgerr *err = NLMSG_DATA(h);
|
struct nlmsgerr *err = NLMSG_DATA(h);
|
||||||
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
if (err->error != 0)
|
||||||
|
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
||||||
{
|
{
|
||||||
nl_routechange(h);
|
/* We arrange to receive netlink multicast messages whenever the network route is added.
|
||||||
|
If this happens and we still have a DNS packet in the buffer, we re-send it.
|
||||||
|
This helps on DoD links, where frequently the packet which triggers dialling is
|
||||||
|
a DNS query, which then gets lost. By re-sending, we can avoid the lookup
|
||||||
|
failing. */
|
||||||
|
struct rtmsg *rtm = NLMSG_DATA(h);
|
||||||
|
|
||||||
|
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK)
|
||||||
|
{
|
||||||
|
/* Force re-reading resolv file right now, for luck. */
|
||||||
|
daemon->last_resolv = 0;
|
||||||
|
|
||||||
|
if (daemon->srv_save)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (daemon->srv_save->sfd)
|
||||||
|
fd = daemon->srv_save->sfd->fd;
|
||||||
|
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
||||||
|
fd = daemon->rfd_save->fd;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
||||||
|
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR)
|
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||||
{
|
return 1; /* clever bind mode - rescan */
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
/* force RAs to sync new network and pick up new interfaces. */
|
|
||||||
if (daemon->ra_contexts)
|
|
||||||
{
|
|
||||||
schedule_subnet_map();
|
|
||||||
ra_start_unsolicted(dnsmasq_time(), NULL);
|
|
||||||
/* cause lease_update_file to run after we return, in case we were called from
|
|
||||||
iface_enumerate and can't re-enter it now */
|
|
||||||
send_alarm(0, 0);
|
|
||||||
}
|
|
||||||
return 1; /* clever bind mode - rescan */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We arrange to receive netlink multicast messages whenever the network route is added.
|
static void nl_newaddress(time_t now)
|
||||||
If this happens and we still have a DNS packet in the buffer, we re-send it.
|
|
||||||
This helps on DoD links, where frequently the packet which triggers dialling is
|
|
||||||
a DNS query, which then gets lost. By re-sending, we can avoid the lookup
|
|
||||||
failing. */
|
|
||||||
static void nl_routechange(struct nlmsghdr *h)
|
|
||||||
{
|
{
|
||||||
struct rtmsg *rtm = NLMSG_DATA(h);
|
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
int fd;
|
enumerate_interfaces();
|
||||||
|
|
||||||
if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK)
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
return;
|
create_bound_listeners(0);
|
||||||
|
|
||||||
/* Force re-reading resolv file right now, for luck. */
|
#ifdef HAVE_DHCP6
|
||||||
daemon->last_resolv = 0;
|
if (daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
|
|
||||||
if (daemon->srv_save)
|
|
||||||
{
|
{
|
||||||
if (daemon->srv_save->sfd)
|
join_multicast(0);
|
||||||
fd = daemon->srv_save->sfd->fd;
|
dhcp_construct_contexts(now);
|
||||||
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
|
||||||
fd = daemon->rfd_save->fd;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
|
||||||
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (daemon->doing_dhcp6)
|
||||||
|
lease_find_interfaces(now);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+150
-69
@@ -107,7 +107,7 @@ int indextoname(int fd, int index, char *name)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int iface_check(int family, struct all_addr *addr, char *name)
|
int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
||||||
{
|
{
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
@@ -115,43 +115,59 @@ int iface_check(int family, struct all_addr *addr, char *name)
|
|||||||
/* Note: have to check all and not bail out early, so that we set the
|
/* Note: have to check all and not bail out early, so that we set the
|
||||||
"used" flags. */
|
"used" flags. */
|
||||||
|
|
||||||
|
if (auth)
|
||||||
|
*auth = 0;
|
||||||
|
|
||||||
if (daemon->if_names || daemon->if_addrs)
|
if (daemon->if_names || daemon->if_addrs)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DHCP
|
|
||||||
struct dhcp_context *range;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
|
||||||
for (range = daemon->dhcp; range; range = range->next)
|
|
||||||
if (range->interface && strcmp(range->interface, name) == 0)
|
|
||||||
ret = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||||
ret = tmp->used = 1;
|
ret = tmp->used = 1;
|
||||||
|
|
||||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
if (addr)
|
||||||
if (tmp->addr.sa.sa_family == family)
|
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||||
{
|
if (tmp->addr.sa.sa_family == family)
|
||||||
if (family == AF_INET &&
|
{
|
||||||
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
if (family == AF_INET &&
|
||||||
ret = tmp->used = 1;
|
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
||||||
|
ret = tmp->used = 1;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (family == AF_INET6 &&
|
else if (family == AF_INET6 &&
|
||||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
||||||
&addr->addr.addr6))
|
&addr->addr.addr6))
|
||||||
ret = tmp->used = 1;
|
ret = tmp->used = 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name)
|
||||||
|
{
|
||||||
|
if (strcmp(tmp->name, name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
||||||
|
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
||||||
|
break;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (tmp && auth)
|
||||||
|
{
|
||||||
|
*auth = 1;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,12 +177,12 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
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 = !!option_bool(OPT_TFTP);
|
||||||
int dhcp_ok = 1;
|
int dhcp_ok = 1;
|
||||||
|
int auth_dns = 0;
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
#endif
|
#endif
|
||||||
struct interface_list *ir = NULL;
|
|
||||||
|
|
||||||
/* check whether the interface IP has been added already
|
/* check whether the interface IP has been added already
|
||||||
we call this routine multiple times. */
|
we call this routine multiple times. */
|
||||||
@@ -220,38 +236,32 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
if (addr->sa.sa_family == AF_INET &&
|
||||||
/* implement wierd TFTP service rules */
|
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, &auth_dns))
|
||||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
return 1;
|
||||||
if (strcmp(ir->interface, ifr.ifr_name) == 0)
|
|
||||||
{
|
|
||||||
tftp_ok = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!ir)
|
|
||||||
{
|
|
||||||
if (addr->sa.sa_family == AF_INET &&
|
|
||||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
|
||||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
|
||||||
{
|
|
||||||
tftp_ok = 0;
|
|
||||||
dhcp_ok = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr->sa.sa_family == AF_INET6 &&
|
|
||||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (addr->sa.sa_family == AF_INET6 &&
|
||||||
|
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &auth_dns))
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP
|
||||||
|
/* No DHCP where we're doing auth DNS. */
|
||||||
|
if (auth_dns)
|
||||||
|
{
|
||||||
|
tftp_ok = 0;
|
||||||
|
dhcp_ok = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
|
{
|
||||||
|
tftp_ok = 0;
|
||||||
|
dhcp_ok = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* add to list */
|
/* add to list */
|
||||||
if ((iface = whine_malloc(sizeof(struct irec))))
|
if ((iface = whine_malloc(sizeof(struct irec))))
|
||||||
{
|
{
|
||||||
@@ -259,9 +269,11 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
iface->netmask = netmask;
|
iface->netmask = netmask;
|
||||||
iface->tftp_ok = tftp_ok;
|
iface->tftp_ok = tftp_ok;
|
||||||
iface->dhcp_ok = dhcp_ok;
|
iface->dhcp_ok = dhcp_ok;
|
||||||
|
iface->dns_auth = auth_dns;
|
||||||
iface->mtu = mtu;
|
iface->mtu = mtu;
|
||||||
iface->dad = dad;
|
iface->dad = dad;
|
||||||
iface->done = 0;
|
iface->done = iface->multicast_done = 0;
|
||||||
|
iface->index = if_index;
|
||||||
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
||||||
{
|
{
|
||||||
strcpy(iface->name, ifr.ifr_name);
|
strcpy(iface->name, ifr.ifr_name);
|
||||||
@@ -270,6 +282,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
free(iface);
|
free(iface);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
@@ -278,7 +291,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int flags,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
struct in_addr netmask; /* dummy */
|
struct in_addr netmask; /* dummy */
|
||||||
@@ -286,6 +300,8 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
(void)prefix; /* warning */
|
(void)prefix; /* warning */
|
||||||
(void)scope; /* warning */
|
(void)scope; /* warning */
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
@@ -296,7 +312,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
|||||||
addr.in6.sin6_port = htons(daemon->port);
|
addr.in6.sin6_port = htons(daemon->port);
|
||||||
addr.in6.sin6_scope_id = if_index;
|
addr.in6.sin6_scope_id = if_index;
|
||||||
|
|
||||||
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, dad);
|
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -361,13 +377,22 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
|||||||
sprintf(daemon->addrbuff, "port %d", port);
|
sprintf(daemon->addrbuff, "port %d", port);
|
||||||
s = _("failed to create listening socket for %s: %s");
|
s = _("failed to create listening socket for %s: %s");
|
||||||
|
|
||||||
|
if (fd != -1)
|
||||||
|
close (fd);
|
||||||
|
|
||||||
if (dienow)
|
if (dienow)
|
||||||
die(s, daemon->addrbuff, EC_BADNET);
|
{
|
||||||
|
/* failure to bind addresses given by --listen-address at this point
|
||||||
|
is OK if we're doing bind-dynamic */
|
||||||
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
|
die(s, daemon->addrbuff, EC_BADNET);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
|
||||||
|
|
||||||
my_syslog(LOG_ERR, s, daemon->addrbuff, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@@ -485,8 +510,7 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
|
|||||||
void create_wildcard_listeners(void)
|
void create_wildcard_listeners(void)
|
||||||
{
|
{
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
struct listener *l;
|
struct listener *l, *l6;
|
||||||
int tftp_enabled = daemon->tftp_unlimited || daemon->tftp_interfaces;
|
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
@@ -496,7 +520,7 @@ void create_wildcard_listeners(void)
|
|||||||
addr.in.sin_addr.s_addr = INADDR_ANY;
|
addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||||
addr.in.sin_port = htons(daemon->port);
|
addr.in.sin_port = htons(daemon->port);
|
||||||
|
|
||||||
l = create_listeners(&addr, tftp_enabled, 1);
|
l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
@@ -506,11 +530,12 @@ void create_wildcard_listeners(void)
|
|||||||
addr.in6.sin6_family = AF_INET6;
|
addr.in6.sin6_family = AF_INET6;
|
||||||
addr.in6.sin6_addr = in6addr_any;
|
addr.in6.sin6_addr = in6addr_any;
|
||||||
addr.in6.sin6_port = htons(daemon->port);
|
addr.in6.sin6_port = htons(daemon->port);
|
||||||
|
|
||||||
|
l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
|
||||||
if (l)
|
if (l)
|
||||||
l->next = create_listeners(&addr, tftp_enabled, 1);
|
l->next = l6;
|
||||||
else
|
else
|
||||||
l = create_listeners(&addr, tftp_enabled, 1);
|
l = l6;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
daemon->listeners = l;
|
daemon->listeners = l;
|
||||||
@@ -536,7 +561,8 @@ void create_bound_listeners(int dienow)
|
|||||||
no interface with a matching address. These may be valid: eg it's possible
|
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
|
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().
|
If the address isn't valid the bind() will fail and we'll die()
|
||||||
|
(except in bind-dynamic mode, when we'll complain but keep trying.)
|
||||||
|
|
||||||
The resulting listeners have the ->iface field NULL, and this has to be
|
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
|
handled by the DNS and TFTP code. It disables --localise-queries processing
|
||||||
@@ -544,7 +570,7 @@ void create_bound_listeners(int dienow)
|
|||||||
|
|
||||||
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
|
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
|
||||||
if (!if_tmp->used &&
|
if (!if_tmp->used &&
|
||||||
(new = create_listeners(&if_tmp->addr, daemon->tftp_unlimited, dienow)))
|
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
|
||||||
{
|
{
|
||||||
new->iface = NULL;
|
new->iface = NULL;
|
||||||
new->next = daemon->listeners;
|
new->next = daemon->listeners;
|
||||||
@@ -563,6 +589,61 @@ int is_dad_listeners(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
void join_multicast(int dienow)
|
||||||
|
{
|
||||||
|
struct irec *iface, *tmp;
|
||||||
|
|
||||||
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
|
if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
|
||||||
|
{
|
||||||
|
/* There's an irec per address but we only want to join for multicast
|
||||||
|
once per interface. Weed out duplicates. */
|
||||||
|
for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->multicast_done && tmp->index == iface->index)
|
||||||
|
break;
|
||||||
|
|
||||||
|
iface->multicast_done = 1;
|
||||||
|
|
||||||
|
if (!tmp)
|
||||||
|
{
|
||||||
|
struct ipv6_mreq mreq;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
mreq.ipv6mr_interface = iface->index;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
|
||||||
|
|
||||||
|
if (daemon->doing_dhcp6 &&
|
||||||
|
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||||
|
err = 1;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
|
||||||
|
|
||||||
|
if (daemon->doing_dhcp6 &&
|
||||||
|
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||||
|
err = 1;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
|
||||||
|
|
||||||
|
if (daemon->doing_ra &&
|
||||||
|
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||||
|
err = 1;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
|
||||||
|
if (dienow)
|
||||||
|
die(s, iface->name, EC_BADNET);
|
||||||
|
else
|
||||||
|
my_syslog(LOG_ERR, s, iface->name, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* return a UDP socket bound to a random port, have to cope with straying into
|
/* return a UDP socket bound to a random port, have to cope with straying into
|
||||||
occupied port nos and reserved ones. */
|
occupied port nos and reserved ones. */
|
||||||
int random_sock(int family)
|
int random_sock(int family)
|
||||||
|
|||||||
+659
-447
File diff suppressed because it is too large.
Load diff
+141
-81
@@ -27,25 +27,28 @@
|
|||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
|
|
||||||
struct ra_param {
|
struct ra_param {
|
||||||
|
time_t now;
|
||||||
int ind, managed, other, found_context, first;
|
int ind, managed, other, found_context, first;
|
||||||
char *if_name;
|
char *if_name;
|
||||||
struct dhcp_netid *tags;
|
struct dhcp_netid *tags;
|
||||||
struct in6_addr link_local;
|
struct in6_addr link_local, link_global;
|
||||||
|
unsigned int pref_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct search_param {
|
struct search_param {
|
||||||
time_t now; int iface;
|
time_t now; int iface;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void send_ra(int iface, char *iface_name, struct in6_addr *dest);
|
static void send_ra(time_t now, 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 flags,
|
||||||
|
unsigned int preferred, unsigned int valid, void *vparam);
|
||||||
static int iface_search(struct in6_addr *local, int prefix,
|
static int iface_search(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam);
|
int scope, int if_index, int flags,
|
||||||
|
int prefered, int valid, void *vparam);
|
||||||
static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||||
|
|
||||||
static int hop_limit;
|
static int hop_limit;
|
||||||
static time_t ra_short_period_start;
|
|
||||||
|
|
||||||
void ra_init(time_t now)
|
void ra_init(time_t now)
|
||||||
{
|
{
|
||||||
@@ -62,7 +65,7 @@ void ra_init(time_t now)
|
|||||||
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
|
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
|
||||||
|
|
||||||
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
|
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if ((context->flags & CONTEXT_RA_NAME))
|
if ((context->flags & CONTEXT_RA_NAME))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -94,18 +97,20 @@ void ra_start_unsolicted(time_t now, struct dhcp_context *context)
|
|||||||
if it's not appropriate to advertise those contexts.
|
if it's not appropriate to advertise those contexts.
|
||||||
This gets re-called on a netlink route-change to re-do the advertisement
|
This gets re-called on a netlink route-change to re-do the advertisement
|
||||||
and pick up new interfaces */
|
and pick up new interfaces */
|
||||||
|
|
||||||
if (context)
|
if (context)
|
||||||
context->ra_time = now;
|
context->ra_short_period_start = context->ra_time = now;
|
||||||
else
|
else
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
context->ra_time = now + (rand16()/13000); /* range 0 - 5 */
|
if (!(context->flags & CONTEXT_TEMPLATE))
|
||||||
|
{
|
||||||
/* re-do frequently for a minute or so, in case the first gets lost. */
|
context->ra_time = now + (rand16()/13000); /* range 0 - 5 */
|
||||||
ra_short_period_start = now;
|
/* re-do frequently for a minute or so, in case the first gets lost. */
|
||||||
|
context->ra_short_period_start = now;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void icmp6_packet(void)
|
void icmp6_packet(time_t now)
|
||||||
{
|
{
|
||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
@@ -119,7 +124,6 @@ void icmp6_packet(void)
|
|||||||
struct sockaddr_in6 from;
|
struct sockaddr_in6 from;
|
||||||
unsigned char *packet;
|
unsigned char *packet;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
struct dhcp_context *context;
|
|
||||||
|
|
||||||
/* Note: use outpacket for input buffer */
|
/* Note: use outpacket for input buffer */
|
||||||
msg.msg_control = control_u.control6;
|
msg.msg_control = control_u.control6;
|
||||||
@@ -150,22 +154,16 @@ void icmp6_packet(void)
|
|||||||
if (!indextoname(daemon->icmp6fd, if_index, interface))
|
if (!indextoname(daemon->icmp6fd, if_index, interface))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!iface_check(AF_LOCAL, NULL, interface))
|
if (!iface_check(AF_LOCAL, NULL, interface, NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, interface) == 0))
|
if (tmp->name && (strcmp(tmp->name, interface) == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* weird libvirt-inspired access control */
|
if (packet[1] != 0)
|
||||||
for (context = daemon->ra_contexts ? daemon->ra_contexts : daemon->dhcp6;
|
|
||||||
context; context = context->next)
|
|
||||||
if (!context->interface || strcmp(context->interface, interface) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!context || packet[1] != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (packet[0] == ICMP6_ECHO_REPLY)
|
if (packet[0] == ICMP6_ECHO_REPLY)
|
||||||
lease_ping_reply(&from.sin6_addr, packet, interface);
|
lease_ping_reply(&from.sin6_addr, packet, interface);
|
||||||
else if (packet[0] == ND_ROUTER_SOLICIT)
|
else if (packet[0] == ND_ROUTER_SOLICIT)
|
||||||
@@ -181,11 +179,11 @@ void icmp6_packet(void)
|
|||||||
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||||
/* source address may not be valid in solicit request. */
|
/* source address may not be valid in solicit request. */
|
||||||
send_ra(if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
|
||||||
{
|
{
|
||||||
struct ra_packet *ra;
|
struct ra_packet *ra;
|
||||||
struct ra_param parm;
|
struct ra_param parm;
|
||||||
@@ -195,7 +193,10 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
|||||||
struct dhcp_netid iface_id;
|
struct dhcp_netid iface_id;
|
||||||
struct dhcp_opt *opt_cfg;
|
struct dhcp_opt *opt_cfg;
|
||||||
int done_dns = 0;
|
int done_dns = 0;
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
FILE *f;
|
||||||
|
#endif
|
||||||
|
|
||||||
save_counter(0);
|
save_counter(0);
|
||||||
ra = expand(sizeof(struct ra_packet));
|
ra = expand(sizeof(struct ra_packet));
|
||||||
|
|
||||||
@@ -213,13 +214,15 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
|||||||
parm.found_context = 0;
|
parm.found_context = 0;
|
||||||
parm.if_name = iface_name;
|
parm.if_name = iface_name;
|
||||||
parm.first = 1;
|
parm.first = 1;
|
||||||
|
parm.now = now;
|
||||||
|
parm.pref_time = 0;
|
||||||
|
|
||||||
/* set tag with name == interface */
|
/* set tag with name == interface */
|
||||||
iface_id.net = iface_name;
|
iface_id.net = iface_name;
|
||||||
iface_id.next = NULL;
|
iface_id.next = NULL;
|
||||||
parm.tags = &iface_id;
|
parm.tags = &iface_id;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
{
|
{
|
||||||
context->flags &= ~CONTEXT_RA_DONE;
|
context->flags &= ~CONTEXT_RA_DONE;
|
||||||
context->netid.next = &context->netid;
|
context->netid.next = &context->netid;
|
||||||
@@ -230,14 +233,23 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
strncpy(ifr.ifr_name, iface_name, IF_NAMESIZE);
|
strncpy(ifr.ifr_name, iface_name, IF_NAMESIZE);
|
||||||
|
|
||||||
if (ioctl(daemon->icmp6fd, SIOCGIFMTU, &ifr) != -1)
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
|
||||||
|
available from SIOCGIFMTU */
|
||||||
|
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name);
|
||||||
|
if ((f = fopen(daemon->namebuff, "r")))
|
||||||
{
|
{
|
||||||
put_opt6_char(ICMP6_OPT_MTU);
|
if (fgets(daemon->namebuff, MAXDNAME, f))
|
||||||
put_opt6_char(1);
|
{
|
||||||
put_opt6_short(0);
|
put_opt6_char(ICMP6_OPT_MTU);
|
||||||
put_opt6_long(ifr.ifr_mtu);
|
put_opt6_char(1);
|
||||||
|
put_opt6_short(0);
|
||||||
|
put_opt6_long(atoi(daemon->namebuff));
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
iface_enumerate(AF_LOCAL, &iface, add_lla);
|
iface_enumerate(AF_LOCAL, &iface, add_lla);
|
||||||
|
|
||||||
@@ -267,7 +279,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
|||||||
/* zero means "self" */
|
/* zero means "self" */
|
||||||
for (i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++)
|
for (i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++)
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(a))
|
if (IN6_IS_ADDR_UNSPECIFIED(a))
|
||||||
put_opt6(&parm.link_local, IN6ADDRSZ);
|
put_opt6(&parm.link_global, IN6ADDRSZ);
|
||||||
else
|
else
|
||||||
put_opt6(a, IN6ADDRSZ);
|
put_opt6(a, IN6ADDRSZ);
|
||||||
}
|
}
|
||||||
@@ -295,7 +307,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
|||||||
put_opt6_char(3);
|
put_opt6_char(3);
|
||||||
put_opt6_short(0);
|
put_opt6_short(0);
|
||||||
put_opt6_long(1800); /* lifetime - twice RA retransmit */
|
put_opt6_long(1800); /* lifetime - twice RA retransmit */
|
||||||
put_opt6(&parm.link_local, IN6ADDRSZ);
|
put_opt6(&parm.link_global, 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 */
|
||||||
@@ -327,29 +339,30 @@ 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 flags,
|
||||||
|
unsigned int preferred, unsigned int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct ra_param *param = vparam;
|
struct ra_param *param = vparam;
|
||||||
|
|
||||||
(void)scope; /* warning */
|
(void)scope; /* warning */
|
||||||
(void)dad;
|
|
||||||
|
|
||||||
if (if_index == param->ind)
|
if (if_index == param->ind)
|
||||||
{
|
{
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(local))
|
if (IN6_IS_ADDR_LINKLOCAL(local))
|
||||||
param->link_local = *local;
|
param->link_local = *local;
|
||||||
else if (!IN6_IS_ADDR_LOOPBACK(local) &&
|
else if (!IN6_IS_ADDR_LOOPBACK(local) &&
|
||||||
!IN6_IS_ADDR_LINKLOCAL(local) &&
|
|
||||||
!IN6_IS_ADDR_MULTICAST(local))
|
!IN6_IS_ADDR_MULTICAST(local))
|
||||||
{
|
{
|
||||||
int do_prefix = 0;
|
int do_prefix = 0;
|
||||||
int do_slaac = 0;
|
int do_slaac = 0;
|
||||||
int deprecate = 0;
|
int deprecate = 0;
|
||||||
|
int constructed = 0;
|
||||||
unsigned int time = 0xffffffff;
|
unsigned int time = 0xffffffff;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if (prefix == context->prefix &&
|
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
|
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))
|
||||||
{
|
{
|
||||||
@@ -372,13 +385,21 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
param->managed = 1;
|
param->managed = 1;
|
||||||
param->other = 1;
|
param->other = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find floor time */
|
|
||||||
if (time > context->lease_time)
|
|
||||||
time = context->lease_time;
|
|
||||||
|
|
||||||
|
/* find floor time, don't reduce below RA interval. */
|
||||||
|
if (time > context->lease_time)
|
||||||
|
{
|
||||||
|
time = context->lease_time;
|
||||||
|
if (time < 600u)
|
||||||
|
time = 600;
|
||||||
|
}
|
||||||
|
|
||||||
if (context->flags & CONTEXT_DEPRECATE)
|
if (context->flags & CONTEXT_DEPRECATE)
|
||||||
deprecate = 1;
|
deprecate = 1;
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
|
constructed = 1;
|
||||||
|
|
||||||
|
|
||||||
/* collect dhcp-range tags */
|
/* collect dhcp-range tags */
|
||||||
if (context->netid.next == &context->netid && context->netid.net)
|
if (context->netid.next == &context->netid && context->netid.net)
|
||||||
@@ -402,6 +423,26 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
param->first = 0;
|
param->first = 0;
|
||||||
param->found_context = 1;
|
param->found_context = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* configured time is ceiling */
|
||||||
|
if (!constructed || valid > time)
|
||||||
|
valid = time;
|
||||||
|
|
||||||
|
if (flags & IFACE_DEPRECATED)
|
||||||
|
preferred = 0;
|
||||||
|
|
||||||
|
if (deprecate)
|
||||||
|
time = 0;
|
||||||
|
|
||||||
|
/* configured time is ceiling */
|
||||||
|
if (!constructed || preferred > time)
|
||||||
|
preferred = time;
|
||||||
|
|
||||||
|
if (preferred > param->pref_time)
|
||||||
|
{
|
||||||
|
param->pref_time = preferred;
|
||||||
|
param->link_global = *local;
|
||||||
|
}
|
||||||
|
|
||||||
if (do_prefix)
|
if (do_prefix)
|
||||||
{
|
{
|
||||||
@@ -412,17 +453,13 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
/* zero net part of address */
|
/* zero net part of address */
|
||||||
setaddr6part(local, addr6part(local) & ~((prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU));
|
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->type = ICMP6_OPT_PREFIX;
|
||||||
opt->len = 4;
|
opt->len = 4;
|
||||||
opt->prefix_len = prefix;
|
opt->prefix_len = prefix;
|
||||||
/* autonomous only if we're not doing dhcp */
|
/* autonomous only if we're not doing dhcp, always set "on-link" */
|
||||||
opt->flags = do_slaac ? 0x40 : 0x00;
|
opt->flags = do_slaac ? 0xC0 : 0x80;
|
||||||
opt->valid_lifetime = htonl(time);
|
opt->valid_lifetime = htonl(valid);
|
||||||
opt->preferred_lifetime = htonl(deprecate ? 0 : time);
|
opt->preferred_lifetime = htonl(preferred);
|
||||||
opt->reserved = 0;
|
opt->reserved = 0;
|
||||||
opt->prefix = *local;
|
opt->prefix = *local;
|
||||||
|
|
||||||
@@ -464,11 +501,12 @@ time_t periodic_ra(time_t now)
|
|||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
|
|
||||||
param.now = now;
|
param.now = now;
|
||||||
|
param.iface = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* find overdue events, and time of first future event */
|
/* find overdue events, and time of first future event */
|
||||||
for (next_event = 0, context = daemon->ra_contexts; context; context = context->next)
|
for (next_event = 0, context = daemon->dhcp6; 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)
|
||||||
@@ -489,42 +527,64 @@ time_t periodic_ra(time_t now)
|
|||||||
ever be able to send ra's and satistfy it. */
|
ever be able to send ra's and satistfy it. */
|
||||||
if (iface_enumerate(AF_INET6, ¶m, iface_search))
|
if (iface_enumerate(AF_INET6, ¶m, iface_search))
|
||||||
context->ra_time = 0;
|
context->ra_time = 0;
|
||||||
else if (indextoname(daemon->icmp6fd, param.iface, interface))
|
else if (param.iface != 0 &&
|
||||||
send_ra(param.iface, interface, NULL);
|
indextoname(daemon->icmp6fd, param.iface, interface) &&
|
||||||
}
|
iface_check(AF_LOCAL, NULL, interface, NULL))
|
||||||
|
{
|
||||||
|
struct iname *tmp;
|
||||||
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name && (strcmp(tmp->name, interface) == 0))
|
||||||
|
break;
|
||||||
|
if (!tmp)
|
||||||
|
send_ra(now, param.iface, interface, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
return next_event;
|
return next_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iface_search(struct in6_addr *local, int prefix,
|
static int iface_search(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int flags,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct search_param *param = vparam;
|
struct search_param *param = vparam;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
|
||||||
(void)scope;
|
(void)scope;
|
||||||
(void)dad;
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if (prefix == context->prefix &&
|
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
|
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->ra_time != 0 && difftime(context->ra_time, param->now) <= 0.0)
|
context->ra_time != 0 &&
|
||||||
{
|
difftime(context->ra_time, param->now) <= 0.0)
|
||||||
/* found an interface that's overdue for RA determine new
|
{
|
||||||
timeout value and zap other contexts on the same interface
|
/* found an interface that's overdue for RA determine new
|
||||||
so they don't timeout independently .*/
|
timeout value and arrange for RA to be sent unless interface is
|
||||||
|
still doing DAD.*/
|
||||||
|
|
||||||
|
if (!(flags & IFACE_TENTATIVE))
|
||||||
param->iface = if_index;
|
param->iface = if_index;
|
||||||
|
|
||||||
if (difftime(param->now, ra_short_period_start) < 60.0)
|
if (difftime(param->now, context->ra_short_period_start) < 60.0)
|
||||||
/* range 5 - 20 */
|
/* range 5 - 20 */
|
||||||
context->ra_time = param->now + 5 + (rand16()/4400);
|
context->ra_time = param->now + 5 + (rand16()/4400);
|
||||||
else
|
else
|
||||||
/* range 450 - 600 */
|
/* range 450 - 600 */
|
||||||
context->ra_time = param->now + 450 + (rand16()/440);
|
context->ra_time = param->now + 450 + (rand16()/440);
|
||||||
|
|
||||||
return 0; /* found, abort */
|
/* zero timers for other contexts on the same subnet, so they don't timeout
|
||||||
}
|
independently */
|
||||||
|
for (context = context->next; context; context = context->next)
|
||||||
|
if (prefix == context->prefix &&
|
||||||
|
is_same_net6(local, &context->start6, prefix) &&
|
||||||
|
is_same_net6(local, &context->end6, prefix))
|
||||||
|
context->ra_time = 0;
|
||||||
|
|
||||||
|
return 0; /* found, abort */
|
||||||
|
}
|
||||||
|
|
||||||
return 1; /* keep searching */
|
return 1; /* keep searching */
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-20
@@ -16,10 +16,6 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
static int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
|
||||||
unsigned int nameoffset, unsigned char **pp,
|
|
||||||
unsigned long ttl, unsigned int *offset, unsigned short type,
|
|
||||||
unsigned short class, char *format, ...);
|
|
||||||
|
|
||||||
#define CHECK_LEN(header, pp, plen, len) \
|
#define CHECK_LEN(header, pp, plen, len) \
|
||||||
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
|
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
|
||||||
@@ -27,8 +23,8 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
|
|||||||
#define ADD_RDLEN(header, pp, plen, len) \
|
#define ADD_RDLEN(header, pp, plen, len) \
|
||||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
||||||
|
|
||||||
static int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
char *name, int isExtract, int extrabytes)
|
char *name, int isExtract, int extrabytes)
|
||||||
{
|
{
|
||||||
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||||
unsigned int j, l, hops = 0;
|
unsigned int j, l, hops = 0;
|
||||||
@@ -173,7 +169,7 @@ static int extract_name(struct dns_header *header, size_t plen, unsigned char **
|
|||||||
|
|
||||||
/* Max size of input string (for IPv6) is 75 chars.) */
|
/* Max size of input string (for IPv6) is 75 chars.) */
|
||||||
#define MAXARPANAME 75
|
#define MAXARPANAME 75
|
||||||
static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
char name[MAXARPANAME+1], *cp1;
|
char name[MAXARPANAME+1], *cp1;
|
||||||
@@ -333,7 +329,7 @@ static unsigned char *skip_name(unsigned char *ansp, struct dns_header *header,
|
|||||||
return ansp;
|
return ansp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *skip_questions(struct dns_header *header, size_t plen)
|
unsigned char *skip_questions(struct dns_header *header, size_t plen)
|
||||||
{
|
{
|
||||||
int q;
|
int q;
|
||||||
unsigned char *ansp = (unsigned char *)(header+1);
|
unsigned char *ansp = (unsigned char *)(header+1);
|
||||||
@@ -1189,8 +1185,8 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
||||||
unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...)
|
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
unsigned char *sav, *p = *pp;
|
unsigned char *sav, *p = *pp;
|
||||||
@@ -1201,8 +1197,26 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
|
|||||||
|
|
||||||
if (truncp && *truncp)
|
if (truncp && *truncp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
va_start(ap, format); /* make ap point to 1st unamed argument */
|
||||||
|
|
||||||
|
if (nameoffset > 0)
|
||||||
|
{
|
||||||
|
PUTSHORT(nameoffset | 0xc000, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *name = va_arg(ap, char *);
|
||||||
|
if (name)
|
||||||
|
p = do_rfc1035_name(p, name);
|
||||||
|
if (nameoffset < 0)
|
||||||
|
{
|
||||||
|
PUTSHORT(-nameoffset | 0xc000, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*p++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
PUTSHORT(nameoffset | 0xc000, p);
|
|
||||||
PUTSHORT(type, p);
|
PUTSHORT(type, p);
|
||||||
PUTSHORT(class, p);
|
PUTSHORT(class, p);
|
||||||
PUTLONG(ttl, p); /* TTL */
|
PUTLONG(ttl, p); /* TTL */
|
||||||
@@ -1210,8 +1224,6 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
|
|||||||
sav = p; /* Save pointer to RDLength field */
|
sav = p; /* Save pointer to RDLength field */
|
||||||
PUTSHORT(0, p); /* Placeholder RDLength */
|
PUTSHORT(0, p); /* Placeholder RDLength */
|
||||||
|
|
||||||
va_start(ap, format); /* make ap point to 1st unamed argument */
|
|
||||||
|
|
||||||
for (; *format; format++)
|
for (; *format; format++)
|
||||||
switch (*format)
|
switch (*format)
|
||||||
{
|
{
|
||||||
@@ -1307,7 +1319,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
unsigned char *p, *ansp, *pheader;
|
unsigned char *p, *ansp, *pheader;
|
||||||
int qtype, qclass;
|
int qtype, qclass;
|
||||||
struct all_addr addr;
|
struct all_addr addr;
|
||||||
unsigned int nameoffset;
|
int nameoffset;
|
||||||
unsigned short flag;
|
unsigned short flag;
|
||||||
int q, ans, anscount = 0, addncount = 0;
|
int q, ans, anscount = 0, addncount = 0;
|
||||||
int dryrun = 0, sec_reqd = 0;
|
int dryrun = 0, sec_reqd = 0;
|
||||||
@@ -1689,7 +1701,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ans = found = 1;
|
ans = found = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
unsigned int offset;
|
int offset;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||||
&offset, T_MX, C_IN, "sd", rec->weight, rec->target))
|
&offset, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||||
@@ -1727,7 +1739,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
found = ans = 1;
|
found = ans = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
unsigned int offset;
|
int offset;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||||
&offset, T_SRV, C_IN, "sssd",
|
&offset, T_SRV, C_IN, "sssd",
|
||||||
@@ -1857,7 +1869,3 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
return ansp - (unsigned char *)header;
|
return ansp - (unsigned char *)header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+20
-17
@@ -493,8 +493,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
lease_set_interface(lease, int_index, now);
|
lease_set_interface(lease, int_index, now);
|
||||||
|
|
||||||
clear_packet(mess, end);
|
clear_packet(mess, end);
|
||||||
|
match_vendor_opts(NULL, daemon->dhcp_opts); /* clear flags */
|
||||||
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
|
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
|
||||||
netid, subnet_addr, 0, 0, 0, NULL, 0, now);
|
netid, subnet_addr, 0, 0, -1, NULL, 0, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,11 +516,22 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
op += 3;
|
op += 3;
|
||||||
pp = op;
|
pp = op;
|
||||||
|
|
||||||
/* Always force update, since the client has no way to do it itself. */
|
/* NB, the following always sets at least one bit */
|
||||||
if (!option_bool(OPT_FQDN_UPDATE) && !(fqdn_flags & 0x01))
|
if (option_bool(OPT_FQDN_UPDATE))
|
||||||
fqdn_flags |= 0x03;
|
{
|
||||||
|
if (fqdn_flags & 0x01)
|
||||||
fqdn_flags &= ~0x08;
|
{
|
||||||
|
fqdn_flags |= 0x02; /* set O */
|
||||||
|
fqdn_flags &= ~0x01; /* clear S */
|
||||||
|
}
|
||||||
|
fqdn_flags |= 0x08; /* set N */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(fqdn_flags & 0x01))
|
||||||
|
fqdn_flags |= 0x03; /* set S and O */
|
||||||
|
fqdn_flags &= ~0x08; /* clear N */
|
||||||
|
}
|
||||||
|
|
||||||
if (fqdn_flags & 0x04)
|
if (fqdn_flags & 0x04)
|
||||||
while (*op != 0 && ((op + (*op) + 1) - pp) < len)
|
while (*op != 0 && ((op + (*op) + 1) - pp) < len)
|
||||||
@@ -1375,6 +1387,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
if (lease)
|
if (lease)
|
||||||
{
|
{
|
||||||
|
lease_set_interface(lease, int_index, now);
|
||||||
if (override.s_addr != 0)
|
if (override.s_addr != 0)
|
||||||
lease->override = override;
|
lease->override = override;
|
||||||
else
|
else
|
||||||
@@ -1385,16 +1398,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||||
|
|
||||||
if (lease)
|
|
||||||
{
|
|
||||||
if (lease->expires == 0)
|
|
||||||
time = 0xffffffff;
|
|
||||||
else
|
|
||||||
time = (unsigned int)difftime(lease->expires, now);
|
|
||||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
|
||||||
lease_set_interface(lease, int_index, now);
|
|
||||||
}
|
|
||||||
|
|
||||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
|
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
|
||||||
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
|
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
|
||||||
|
|
||||||
@@ -2261,7 +2264,7 @@ static void do_options(struct dhcp_context *context,
|
|||||||
|
|
||||||
if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
|
if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
|
||||||
{
|
{
|
||||||
*(p++) = fqdn_flags;
|
*(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */
|
||||||
*(p++) = 255;
|
*(p++) = 255;
|
||||||
*(p++) = 255;
|
*(p++) = 255;
|
||||||
|
|
||||||
|
|||||||
+34
-11
@@ -180,7 +180,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
char *client_hostname= NULL, *hostname = NULL;
|
char *client_hostname= NULL, *hostname = NULL;
|
||||||
char *domain = NULL, *send_domain = NULL;
|
char *domain = NULL, *send_domain = NULL;
|
||||||
struct dhcp_config *config = NULL;
|
struct dhcp_config *config = NULL;
|
||||||
struct dhcp_netid known_id, iface_id;
|
struct dhcp_netid known_id, iface_id, v6_id;
|
||||||
int done_dns = 0, hostname_auth = 0, do_encap = 0;
|
int done_dns = 0, hostname_auth = 0, do_encap = 0;
|
||||||
unsigned char *outmsgtypep;
|
unsigned char *outmsgtypep;
|
||||||
struct dhcp_opt *opt_cfg;
|
struct dhcp_opt *opt_cfg;
|
||||||
@@ -194,6 +194,11 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
iface_id.next = tags;
|
iface_id.next = tags;
|
||||||
tags = &iface_id;
|
tags = &iface_id;
|
||||||
|
|
||||||
|
/* set tag "dhcpv6" */
|
||||||
|
v6_id.net = "dhcpv6";
|
||||||
|
v6_id.next = tags;
|
||||||
|
tags = &v6_id;
|
||||||
|
|
||||||
/* copy over transaction-id, and save pointer to message type */
|
/* copy over transaction-id, and save pointer to message type */
|
||||||
outmsgtypep = put_opt6(inbuff, 4);
|
outmsgtypep = put_opt6(inbuff, 4);
|
||||||
start_opts = save_counter(-1);
|
start_opts = save_counter(-1);
|
||||||
@@ -497,7 +502,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
ia_option = opt6_find(opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4), ia_end, OPTION6_IAADDR, 24);
|
ia_option = opt6_find(opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4), ia_end, OPTION6_IAADDR, 24);
|
||||||
|
|
||||||
/* reset "USED" flags on leases */
|
/* reset "USED" flags on leases */
|
||||||
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
|
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
|
||||||
|
|
||||||
o = new_opt6(ia_type);
|
o = new_opt6(ia_type);
|
||||||
put_opt6_long(iaid);
|
put_opt6_long(iaid);
|
||||||
@@ -570,14 +575,18 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
|
||||||
daemon->addrbuff);
|
daemon->addrbuff);
|
||||||
else
|
else
|
||||||
addrp = &config->addr6;
|
{
|
||||||
|
addrp = &config->addr6;
|
||||||
|
/* may have existing lease for this address */
|
||||||
|
lease = lease6_find(clid, clid_len,
|
||||||
|
ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, addrp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* existing lease */
|
/* existing lease */
|
||||||
if (!addrp &&
|
if (!addrp &&
|
||||||
(lease = lease6_find(clid, clid_len,
|
(lease = lease6_find(clid, clid_len,
|
||||||
ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL)) &&
|
ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL)) &&
|
||||||
address6_available(context, (struct in6_addr *)&lease->hwaddr, tags) &&
|
|
||||||
!config_find_by_address6(daemon->dhcp_conf, (struct in6_addr *)&lease->hwaddr, 128, 0))
|
!config_find_by_address6(daemon->dhcp_conf, (struct in6_addr *)&lease->hwaddr, 128, 0))
|
||||||
addrp = (struct in6_addr *)&lease->hwaddr;
|
addrp = (struct in6_addr *)&lease->hwaddr;
|
||||||
|
|
||||||
@@ -616,10 +625,16 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
hostname = NULL;
|
hostname = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (have_config(valid_config, CONFIG_TIME))
|
||||||
|
lease_time = valid_config->lease_time;
|
||||||
|
else
|
||||||
|
lease_time = this_context->lease_time;
|
||||||
|
|
||||||
lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time;
|
if (this_context->valid < lease_time)
|
||||||
|
lease_time = this_context->valid;
|
||||||
|
|
||||||
if (ia_option)
|
if (ia_option)
|
||||||
{
|
{
|
||||||
if (requested_time < 120u )
|
if (requested_time < 120u )
|
||||||
requested_time = 120u; /* sanity */
|
requested_time = 120u; /* sanity */
|
||||||
@@ -731,7 +746,8 @@ 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));
|
||||||
/* preferred lifetime */
|
/* preferred lifetime */
|
||||||
put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
|
put_opt6_long(this_context && (this_context->preferred < lease_time) ?
|
||||||
|
this_context->preferred : lease_time);
|
||||||
put_opt6_long(lease_time); /* valid lifetime */
|
put_opt6_long(lease_time); /* valid lifetime */
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
|
|
||||||
@@ -832,7 +848,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
iacntr = save_counter(-1);
|
iacntr = save_counter(-1);
|
||||||
|
|
||||||
/* reset "USED" flags on leases */
|
/* reset "USED" flags on leases */
|
||||||
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
|
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
|
||||||
|
|
||||||
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
|
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
|
||||||
ia_end = opt6_ptr(opt, opt6_len(opt));
|
ia_end = opt6_ptr(opt, opt6_len(opt));
|
||||||
@@ -1001,10 +1017,17 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
|
|
||||||
case DHCP6IREQ:
|
case DHCP6IREQ:
|
||||||
{
|
{
|
||||||
|
/* We can't discriminate contexts based on address, as we don't know it.
|
||||||
|
If there is only one possible context, we can use its tags */
|
||||||
|
if (context && !context->current)
|
||||||
|
{
|
||||||
|
context->netid.next = NULL;
|
||||||
|
context_tags = &context->netid;
|
||||||
|
}
|
||||||
|
log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, ignore ? "ignored" : hostname);
|
||||||
if (ignore)
|
if (ignore)
|
||||||
return 0;
|
return 0;
|
||||||
*outmsgtypep = DHCP6REPLY;
|
*outmsgtypep = DHCP6REPLY;
|
||||||
log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, hostname);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1036,7 +1059,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
|
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
|
||||||
|
|
||||||
/* reset "USED" flags on leases */
|
/* reset "USED" flags on leases */
|
||||||
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
|
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
|
||||||
|
|
||||||
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
|
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
|
||||||
ia_option;
|
ia_option;
|
||||||
@@ -1115,7 +1138,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
|
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
|
||||||
|
|
||||||
/* reset "USED" flags on leases */
|
/* reset "USED" flags on leases */
|
||||||
lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
|
lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
|
||||||
|
|
||||||
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
|
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
|
||||||
ia_option;
|
ia_option;
|
||||||
|
|||||||
+2
-56
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
|
|
||||||
static int map_rebuild = 0;
|
|
||||||
static int ping_id = 0;
|
static int ping_id = 0;
|
||||||
|
|
||||||
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
|
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
|
||||||
@@ -38,7 +37,7 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
|
|||||||
old = lease->slaac_address;
|
old = lease->slaac_address;
|
||||||
lease->slaac_address = NULL;
|
lease->slaac_address = NULL;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if ((context->flags & CONTEXT_RA_NAME) && lease->last_interface == context->if_index)
|
if ((context->flags & CONTEXT_RA_NAME) && lease->last_interface == context->if_index)
|
||||||
{
|
{
|
||||||
struct in6_addr addr = context->start6;
|
struct in6_addr addr = context->start6;
|
||||||
@@ -123,7 +122,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
|||||||
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->dhcp6; context; context = context->next)
|
||||||
if ((context->flags & CONTEXT_RA_NAME))
|
if ((context->flags & CONTEXT_RA_NAME))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -134,12 +133,6 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
|||||||
while (ping_id == 0)
|
while (ping_id == 0)
|
||||||
ping_id = rand16();
|
ping_id = rand16();
|
||||||
|
|
||||||
if (map_rebuild)
|
|
||||||
{
|
|
||||||
map_rebuild = 0;
|
|
||||||
build_subnet_map();
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -211,51 +204,4 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
|||||||
lease_update_dns(gotone);
|
lease_update_dns(gotone);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build a map from ra-names subnets to corresponding interfaces. This
|
|
||||||
is used to go from DHCPv4 leases to SLAAC addresses,
|
|
||||||
interface->IPv6-subnet, IPv6-subnet + MAC address -> SLAAC.
|
|
||||||
*/
|
|
||||||
static int add_subnet(struct in6_addr *local, int prefix,
|
|
||||||
int scope, int if_index, int dad, void *vparam)
|
|
||||||
{
|
|
||||||
struct dhcp_context *context;
|
|
||||||
|
|
||||||
(void)scope;
|
|
||||||
(void)dad;
|
|
||||||
(void)vparam;
|
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
|
||||||
if ((context->flags & CONTEXT_RA_NAME) &&
|
|
||||||
prefix == context->prefix &&
|
|
||||||
is_same_net6(local, &context->start6, prefix) &&
|
|
||||||
is_same_net6(local, &context->end6, prefix))
|
|
||||||
{
|
|
||||||
context->if_index = if_index;
|
|
||||||
context->local6 = *local;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void build_subnet_map(void)
|
|
||||||
{
|
|
||||||
struct dhcp_context *context;
|
|
||||||
int ok = 0;
|
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
|
||||||
{
|
|
||||||
context->if_index = 0;
|
|
||||||
if ((context->flags & CONTEXT_RA_NAME))
|
|
||||||
ok = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ra-names configured */
|
|
||||||
if (ok)
|
|
||||||
iface_enumerate(AF_INET6, NULL, add_subnet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void schedule_subnet_map(void)
|
|
||||||
{
|
|
||||||
map_rebuild = 1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
+19
-35
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
|
|
||||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special);
|
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
||||||
static void free_transfer(struct tftp_transfer *transfer);
|
static void free_transfer(struct tftp_transfer *transfer);
|
||||||
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
|
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
|
||||||
static ssize_t tftp_err_oops(char *packet, char *file);
|
static ssize_t tftp_err_oops(char *packet, char *file);
|
||||||
@@ -48,7 +48,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int is_err = 1, if_index = 0, mtu = 0, special = 0;
|
int is_err = 1, if_index = 0, mtu = 0;
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
#endif
|
#endif
|
||||||
@@ -61,7 +61,6 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
char *name = NULL;
|
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;
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct cmsghdr align; /* this ensures alignment */
|
struct cmsghdr align; /* this ensures alignment */
|
||||||
@@ -114,8 +113,6 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct cmsghdr *cmptr;
|
struct cmsghdr *cmptr;
|
||||||
int check;
|
|
||||||
struct interface_list *ir;
|
|
||||||
|
|
||||||
if (msg.msg_controllen < sizeof(struct cmsghdr))
|
if (msg.msg_controllen < sizeof(struct cmsghdr))
|
||||||
return;
|
return;
|
||||||
@@ -195,29 +192,22 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (listen->family == AF_INET6)
|
if (listen->family == AF_INET6)
|
||||||
check = iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name);
|
{
|
||||||
|
if (!iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name, NULL))
|
||||||
|
return;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
check = iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name);
|
if (!iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
/* wierd TFTP service override */
|
|
||||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
|
||||||
if (strcmp(ir->interface, name) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!ir)
|
|
||||||
{
|
|
||||||
if (!daemon->tftp_unlimited || !check)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
/* allowed interfaces are the same as for DHCP */
|
/* allowed interfaces are the same as for 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, name) == 0))
|
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||||
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
||||||
mtu = ifr.ifr_mtu;
|
mtu = ifr.ifr_mtu;
|
||||||
@@ -228,12 +218,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
/* check for per-interface prefix */
|
/* check for per-interface prefix */
|
||||||
for (pref = daemon->if_prefix; pref; pref = pref->next)
|
for (pref = daemon->if_prefix; pref; pref = pref->next)
|
||||||
if (strcmp(pref->interface, name) == 0)
|
if (strcmp(pref->interface, name) == 0)
|
||||||
prefix = pref->prefix;
|
prefix = pref->prefix;
|
||||||
|
|
||||||
/* wierd TFTP interfaces disable special options. */
|
|
||||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
|
||||||
if (strcmp(ir->interface, name) == 0)
|
|
||||||
special = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen->family == AF_INET)
|
if (listen->family == AF_INET)
|
||||||
@@ -325,8 +310,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
if (strcasecmp(opt, "blksize") == 0)
|
if (strcasecmp(opt, "blksize") == 0)
|
||||||
{
|
{
|
||||||
if ((opt = next(&p, end)) &&
|
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
|
||||||
(special || !option_bool(OPT_TFTP_NOBLOCK)))
|
|
||||||
{
|
{
|
||||||
transfer->blocksize = atoi(opt);
|
transfer->blocksize = atoi(opt);
|
||||||
if (transfer->blocksize < 1)
|
if (transfer->blocksize < 1)
|
||||||
@@ -363,7 +347,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
if (prefix[strlen(prefix)-1] != '/')
|
if (prefix[strlen(prefix)-1] != '/')
|
||||||
strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
|
strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||||
|
|
||||||
if (!special && option_bool(OPT_TFTP_APREF))
|
if (option_bool(OPT_TFTP_APREF))
|
||||||
{
|
{
|
||||||
size_t oldlen = strlen(daemon->namebuff);
|
size_t oldlen = strlen(daemon->namebuff);
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
@@ -390,7 +374,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
|
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||||
|
|
||||||
/* check permissions and open file */
|
/* check permissions and open file */
|
||||||
if ((transfer->file = check_tftp_fileperm(&len, prefix, special)))
|
if ((transfer->file = check_tftp_fileperm(&len, prefix)))
|
||||||
{
|
{
|
||||||
if ((len = get_block(packet, transfer)) == -1)
|
if ((len = get_block(packet, transfer)) == -1)
|
||||||
len = tftp_err_oops(packet, daemon->namebuff);
|
len = tftp_err_oops(packet, daemon->namebuff);
|
||||||
@@ -411,7 +395,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special)
|
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
||||||
{
|
{
|
||||||
char *packet = daemon->packet, *namebuff = daemon->namebuff;
|
char *packet = daemon->packet, *namebuff = daemon->namebuff;
|
||||||
struct tftp_file *file;
|
struct tftp_file *file;
|
||||||
@@ -448,7 +432,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int spe
|
|||||||
goto perm;
|
goto perm;
|
||||||
}
|
}
|
||||||
/* in secure mode, must be owned by user running dnsmasq */
|
/* in secure mode, must be owned by user running dnsmasq */
|
||||||
else if (!special && option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
|
else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
|
||||||
goto perm;
|
goto perm;
|
||||||
|
|
||||||
/* If we're doing many tranfers from the same file, only
|
/* If we're doing many tranfers from the same file, only
|
||||||
|
|||||||
+1
-1
@@ -280,7 +280,7 @@ int sa_len(union mysockaddr *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
|
/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
|
||||||
int hostname_isequal(char *a, char *b)
|
int hostname_isequal(const char *a, const char *b)
|
||||||
{
|
{
|
||||||
unsigned int c1, c2;
|
unsigned int c1, c2;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user