Compare commits

...

130 Commits

Author SHA1 Message Date
Simon Kelley
29d28dda95 Don't send RAs to the wrong place when DAD in progress. 2012-12-03 14:05:59 +00:00
Simon Kelley
421594f83d Forgot --dhcp-except check in previous commit. 2012-12-02 12:17:35 +00:00
Simon Kelley
d89fb4ed4f Check interface for router advertisements. 2012-12-01 21:21:13 +00:00
Simon Kelley
295a54eed3 SetDomainServers Dbus method. 2012-12-01 21:02:15 +00:00
Simon Kelley
2f38141f43 Don't elide code needed for --bind-dynamic if compiled without IPv6. 2012-11-29 21:16:44 +00:00
Simon Kelley
8e4b87918f Header-file dependency checking in Makefile. 2012-11-14 14:12:56 +00:00
Simon Kelley
83b2198e86 Add warning to man page, -d option 2012-11-12 21:07:44 +00:00
Simon Kelley
d1a5975f9b No lease-time in DHCPINFORM replies. 2012-11-05 16:50:30 +00:00
Simon Kelley
52002051ad Doc update for previous checkin. 2012-10-26 11:39:02 +01:00
Simon Kelley
b191a77901 trivial indent fix. 2012-10-24 14:16:00 +01:00
Simon Kelley
23780dd577 Set tag "dhcpv6" rather than "DHCPv6", hardwired tags in lower-case is consistent. 2012-10-23 17:04:37 +01:00
Simon Kelley
d1e9a582ad Use dhcp-range tags when replying to DHCPv6 information-request. 2012-10-23 17:00:57 +01:00
Simon Kelley
819ff4dd0f Wildcard IPv6 dhcp-range. 2012-10-21 18:25:12 +01:00
Simon Kelley
de604c18a0 Remove non-7-bit character from CHANGELOG 2012-10-19 09:50:01 +01:00
Simon Kelley
be6cfb42ab Fix DHCPv6 to do access control correctly when it's configured with --listen-address. 2012-10-16 20:38:31 +01:00
Simon Kelley
2022310f95 SO_REUSEADDR and SO_V6ONLY options on DHCPv6 socket. 2012-10-15 10:41:17 +01:00
Simon Kelley
657ed09693 Add contrib/dbus-test/dbus-test.py 2012-10-12 14:45:55 +01:00
Simon Kelley
c99df938d7 Fix compilation warnings. 2012-10-12 13:39:04 +01:00
Simon Kelley
cf568a3726 Fix typos in sample config file. 2012-10-09 20:51:31 +01:00
Simon Kelley
e4807d8bb2 Fix breakage of --host-record parsing. 2012-09-27 21:52:26 +01:00
Simon Kelley
35239a302a Tweak dhcp-config sanity checking. 2012-09-24 15:09:33 +01:00
Simon Kelley
db3946c358 Debian changelog update. 2012-09-21 17:21:05 +01:00
Simon Kelley
0d28af84d0 Set tag "DHCPv6" for v6 transactions. 2012-09-20 21:24:06 +01:00
Simon Kelley
42698cb7ab Log ignored DHCPv6 information-requests. 2012-09-20 21:19:35 +01:00
Simon Kelley
1d860415f2 Add --max-cache-ttl option. 2012-09-20 20:48:04 +01:00
Simon Kelley
289a253569 Fix build with later Lua libraries. 2012-09-20 15:29:35 +01:00
Simon Kelley
faafb3f7b7 Add SetServersEX method in DBus interface. 2012-09-20 14:17:39 +01:00
Simon Kelley
2b127a1eab Flag DHCP or DHCPv6 in starup logging. 2012-09-18 21:51:22 +01:00
Simon Kelley
dfb23b3f77 Don't report spurious netlink errors. 2012-09-18 21:44:47 +01:00
Simon Kelley
b269221c00 Address allocation tweaking - lease outside dhcp-range but in subnet. 2012-09-16 22:22:23 +01:00
Simon Kelley
8b46061e73 Fix DHCPv6 address allocation for some pathalogical cases. 2012-09-08 21:47:28 +01:00
Simon Kelley
4d0f5b4c44 Fix BOOTP option processing. 2012-09-05 23:29:30 +01:00
Simon Kelley
1dedeb87cc Fix Debian package adduser dependency. 2012-09-04 21:50:52 +01:00
Simon Kelley
79cfefd856 Make pid-file creation immune to symlink attack. 2012-09-02 13:29:51 +01:00
Simon Kelley
0c0d4793ac Tidy buffer use in DHCP startup logging. 2012-09-02 12:57:43 +01:00
Simon Kelley
12d71ed28c Finesse the check for /etc/hosts names which conflict with DHCP names. 2012-08-30 15:16:41 +01:00
Simon Kelley
9fed0f71c2 Further tweaks to DHCP FQDN option. 2012-08-30 11:43:35 +01:00
Simon Kelley
2e34ac1403 Handle DHCP FQDN option with all flags zero and --dhcp-client-update 2012-08-29 14:15:25 +01:00
Simon Kelley
bc54ae392b Debian packaging fixes. 2012-08-28 21:26:56 +01:00
Simon Kelley
00acd06340 Tweak get-version to do the right thing with multiple head tags. 2012-08-17 14:18:50 +01:00
Simon Kelley
476e4a03c1 Bump Debian version 2012-08-17 13:45:49 +01:00
Simon Kelley
5f11b3e5e0 Cope with --listen-address for not yet existent addr in bind-dynamic mode. 2012-08-16 14:04:05 +01:00
Simon Kelley
3169daad46 Fix TFTP access control, broken earlier in release. 2012-08-13 17:39:57 +01:00
Simon Kelley
fd05f12790 Set prefix on-link bit in RAs 2012-08-12 17:48:50 +01:00
Simon Kelley
ad094275b0 Alternate DBus service name via --enable-dbus 2012-08-10 17:10:54 +01:00
Simon Kelley
c740e4f342 Fix FTBFS when -DNO_DHCP - thanks Sung Pae. 2012-08-09 16:19:01 +01:00
Simon Kelley
132255b5da OpenBSD build fix. 2012-08-06 20:12:04 +01:00
Simon Kelley
c4c0488ac6 Update french translation. 2012-08-06 20:09:15 +01:00
Simon Kelley
a2ce6fcc91 Man page typos 2012-08-06 20:05:48 +01:00
Simon Kelley
12090548d2 Add debian/dnsmasq-base.conffiles 2012-08-06 20:00:58 +01:00
Simon Kelley
8223cb15e7 Update FAQ to cover --bind-dynamic. 2012-07-29 20:21:57 +01:00
Simon Kelley
4ba9b38cc5 Debian package: move /etc/dbus-1/system.d/dnsmasq.conf. 2012-07-29 17:07:48 +01:00
Simon Kelley
42243214b5 "w" multiplier in lease times. 2012-07-20 15:19:18 +01:00
Simon Kelley
23245c0cb2 RFC 4242 support. 2012-07-18 16:21:11 +01:00
Simon Kelley
b271446f82 Typo. 2012-07-17 12:09:26 +01:00
Simon Kelley
611ebc5f1e Fix broken caching of CNAME chains. 2012-07-16 16:23:46 +01:00
Simon Kelley
be0f45cdbc Typo fix. Thanks Wieland Hoffmann. 2012-07-16 13:35:25 +01:00
Simon Kelley
9b40cbf587 Fix FTBFS when TFTP disabled. 2012-07-13 19:58:26 +01:00
Simon Kelley
c4a7f90ebb Config parsing error-handling update. 2012-07-12 20:52:12 +01:00
Simon Kelley
9609baee41 Merge branch 'access_control' 2012-07-10 15:06:34 +01:00
Simon Kelley
395eb71931 Better log message when dhcp hosts|opts file cannot be read. 2012-07-06 22:07:05 +01:00
Simon Kelley
8bc4cecee6 Remove libvirt-inspired but never used access control features. 2012-07-03 21:04:11 +01:00
Simon Kelley
6b617c0d15 Logging library in Android build scaffold. 2012-06-29 22:11:26 +01:00
Simon Kelley
55d290a3bf Handle pid-file location in Android. 2012-06-29 20:58:32 +01:00
Simon Kelley
e17b4b3871 Fix build-failure with -DNO_DHCP6. 2012-06-28 21:44:30 +01:00
Simon Kelley
236e072cab Typo in BSD-only code. 2012-06-26 21:33:01 +01:00
Simon Kelley
05ff1ed7cc Man page update. 2012-06-26 16:58:12 +01:00
Simon Kelley
2b5bae9a8f Fall back from --bind-dynamic to --bind-interfaces in BSD, rather than quitting. 2012-06-26 16:55:23 +01:00
Simon Kelley
39f1b8e73d Better logging of socket-creation errors. 2012-06-20 20:04:27 +01:00
Simon Kelley
af576b56c2 Tidy up - no functional change. 2012-06-20 14:17:04 +01:00
Simon Kelley
54dd393f39 Add --bind-dynamic 2012-06-20 11:23:38 +01:00
Simon Kelley
4ce4f3779b Fix un-initialised "used" field in --listen-address structure.
Also remove unused "isloop" field.
2012-06-14 11:50:45 +01:00
Simon Kelley
8b3ae2fd43 Check tftp-root exists and is accessible at startup. 2012-06-13 13:43:49 +01:00
Simon Kelley
ed55cb66e6 Correct listener logic when no TFTP and no-interface listen address. 2012-06-12 21:56:29 +01:00
Simon Kelley
2cd9a0de1f Debian systemd startup fixes for resolvconf integration. 2012-06-11 21:56:10 +01:00
Simon Kelley
c514ab9907 Update Debian changelog. 2012-06-07 15:35:08 +01:00
Simon Kelley
078a630bba Do duplicate dhcp-host address check in --test mode. 2012-06-07 13:56:23 +01:00
Simon Kelley
43c271b07c Debian package build - pass calculated LDFLAGS to make. 2012-06-07 10:02:53 +01:00
Simon Kelley
24ce681e51 Add instructions/patches for dbus activation to contrib/systemd. 2012-06-04 21:40:11 +01:00
Simon Kelley
5ae34bf3c8 Fix RA when interface has more than one address on the same network. 2012-06-04 21:14:03 +01:00
Simon Kelley
51931b888a Fix access control when DHCPv6 but no RA in use. 2012-05-29 17:06:02 +01:00
Simon Kelley
9f7f3b1216 Add --dns-rr option. 2012-05-28 21:39:57 +01:00
Simon Kelley
97c83bb05b Use dpkg-buildflags in Debian rules file. 2012-05-28 18:21:59 +01:00
Simon Kelley
8767ceecd4 Make libvirt-style access control work when only doing RA. 2012-05-21 20:54:19 +01:00
Simon Kelley
18c63eff8f Fix non-response to router-solicitations when
router-advertisement configured, but DHCPv6 not
configured.
2012-05-21 14:34:15 +01:00
Simon Kelley
c64b7f6a78 Fix is_same_net6 - bugged if prefix length not divisible by 8. 2012-05-18 10:19:59 +01:00
Simon Kelley
068b4b51e3 Bump Debian version. 2012-05-12 15:25:33 +01:00
Simon Kelley
919dd7cf14 Fixed missing periodic-ras in some configurations. 2012-05-12 15:23:09 +01:00
Simon Kelley
f632e56793 Cope with router-solicit packets without valid source address. 2012-05-12 15:05:34 +01:00
Simon Kelley
2021c66251 code-size tweak 2012-05-07 16:43:21 +01:00
Simon Kelley
8358e0f4b2 Update German translation and fix CHANGELOG typos. Sorry, Conrad! 2012-04-29 21:53:09 +01:00
Simon Kelley
7f61b3ad59 Small SLAAC optimisation. 2012-04-29 16:01:28 +01:00
Simon Kelley
a9ab732e35 reconfirm SLAAC addresses when DHCPv4 leases go though INIT_REBOOT state. 2012-04-29 16:01:28 +01:00
Simon Kelley
11263a462c isprint cast. 2012-04-29 16:01:28 +01:00
Simon Kelley
231d061b45 Tidy TXT record sanitising 2012-04-29 16:01:28 +01:00
Simon Kelley
cdbee9a40b Find room to store key-id and digest-type in DS records.
->uid is now overloaded to store key length
2012-04-27 10:30:49 +01:00
Simon Kelley
7b4ad2eb34 Teach cache to store DS and DNSKEY records 2012-04-27 10:30:49 +01:00
Simon Kelley
19d69be220 CHANGELOG update. 2012-04-27 10:14:34 +01:00
Simon Kelley
04363607aa Fix tftp-over-IPv4 regression on OpenBSD. 2012-04-27 10:11:51 +01:00
Simon Kelley
dcffad2a86 Ensure that the DBus DhcpLeaseUpdated events are generated. 2012-04-24 15:25:18 +01:00
Simon Kelley
6a69ab5ebd Fix error-handling problem in TFTP server. 2012-04-24 14:42:26 +01:00
Simon Kelley
fc92ead0dd CHANGELOG typo. 2012-04-22 21:28:24 +01:00
Simon Kelley
61ce600b20 --tftp-lowercase option. 2012-04-20 21:28:49 +01:00
Simon Kelley
7a14dfebbb Tidy previous commit. 2012-04-20 20:50:42 +01:00
Simon Kelley
42fb8153ba Sanitise filenames logged by TFTP 2012-04-20 17:15:01 +01:00
Simon Kelley
6f13e53886 Tidy up malloc-failure handling. 2012-04-17 14:25:06 +01:00
Simon Kelley
d1c759c5c1 Answer CNAME queries correctly. 2012-04-16 17:26:19 +01:00
Simon Kelley
e46164e0bd Updated French translation. 2012-04-16 16:39:38 +01:00
Simon Kelley
7389ce7ff5 substitue non-portable tail command with sed. 2012-04-16 15:07:48 +01:00
Simon Kelley
2f77797b17 Add port option to example dnsmasq.conf 2012-04-16 14:58:53 +01:00
Simon Kelley
9380ba70d6 Set SO_BINDTODEVICE on DHCP sockets when doing DHCP on one interface
only. Fixes OpenSTack use-case.
2012-04-16 14:41:56 +01:00
Simon Kelley
1023dcbc9e Don't cache DNS data from non-recursive nameservers. 2012-04-09 18:00:08 +01:00
Simon Kelley
83e854e359 Typo. 2012-04-05 13:21:58 +01:00
Simon Kelley
50303b19d8 Remove redundant send_from logging code. 2012-04-04 22:13:17 +01:00
Simon Kelley
89382bacaa Tweak sending ICMP6 echo requests for slaac. 2012-04-04 20:48:16 +01:00
Simon Kelley
6c559c34df tweak favicon 2012-04-02 20:40:34 +01:00
Simon Kelley
adaa6888dd Move FIXME message to comment - having it emitted by the code is just confusing. 2012-04-02 10:02:12 +01:00
Simon Kelley
a813111379 Fix bug in tag-matching logic with negated tags. 2012-03-31 21:35:12 +01:00
Simon Kelley
18f0fb050b RDNSS and DNSSL data in router advertisements. 2012-03-31 21:18:55 +01:00
Simon Kelley
05e92e5afe More RA flag evolution. 2012-03-30 22:24:15 +01:00
Simon Kelley
4723d49dad Set managed RA flag always when doing DHCP. 2012-03-30 21:04:17 +01:00
Simon Kelley
fbbc14541a Fix off-by-one in DHCPv6 FQDN option decoding. 2012-03-30 20:48:20 +01:00
Simon Kelley
5ef33279f2 Tidying radv 2012-03-30 15:10:28 +01:00
Simon Kelley
1e02a85970 radv.c tidying. 2012-03-29 11:07:25 +01:00
Simon Kelley
0e88d53faa Fix preprocessor checks, IP_TOS -> IPV6_TCLASS 2012-03-28 22:22:05 +01:00
Simon Kelley
01d1b8ddf2 Changelog update. 2012-03-28 21:37:25 +01:00
Simon Kelley
c8257540bc "deprecated" lease-time keyword for IPv6 2012-03-28 21:15:41 +01:00
Simon Kelley
2240704863 DHCP start-up logging tweak 2012-03-27 14:42:48 +01:00
Simon Kelley
e8ca69ea16 Doc updates for latest RA changes. 2012-03-26 21:23:26 +01:00
Simon Kelley
da632e7cc1 Comment typo. 2012-03-26 11:14:05 +01:00
48 changed files with 3082 additions and 1685 deletions

205
CHANGELOG
View File

@@ -1,18 +1,168 @@
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
Do duplicate dhcp-host address check in --test mode.
Check that tftp-root directories are accessible before
start-up. Thanks to Daniel Veillard for the initial patch.
Allow more than one --tfp-root flag. The per-interface
stuff is pointless without that.
Add --bind-dynamic. A hybrid mode between the default and
--bind-interfaces which copes with dynamically created
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
Update German translation. Thanks to Conrad Kostecki.
Cope with router-solict packets wich don't have a valid
source address. Thanks to Vladislav Grishenko for the patch.
Fixed bug which caused missing periodic router
advertisements with some configurations. Thanks to
Vladislav Grishenko for the patch.
Fixed bug which broke DHCPv6/RA with prefix lengths
which are not divisible by 8. Thanks to Andre Coetzee
for spotting this.
Fix non-response to router-solicitations when
router-advertisement configured, but DHCPv6 not
configured. Thanks to Marien Zwart for the patch.
Add --dns-rr, to allow arbitrary DNS resource records.
Fixed bug which broke RA scheduling when an interface had
two addresses in the same network. Thanks to Jim Bos for
his help nailing this.
version 2.61
Re-write interface discovery code on *BSD to use
getifaddrs. This is more portable, more straightforward,
and allows us to find the prefix length for IPv6
addresses.
Add ra-names DHCPv6 keyword which adds AAAA records
for dual-stack hosts which get IPv6 addresses via SLAAC.
Add ra-names, ra-stateless and slaac keywords for DHCPv6.
Dnsmasq can now synthesise AAAA records for dual-stack
hosts which get IPv6 addresses via SLAAC. It is also now
possible to use SLAAC and stateless DHCPv6, and to
tell clients to use SLAAC addresses as well as DHCP ones.
Thanks to Dave Taht for help with this.
Add --dhcp-duid to allow DUID-EN uids to be used.
Explicity send DHCPv6 replies to the correct port, instead
of relying on clients to send requests with the correct
source address, since at least one client in the wild gets
this wrong. Thanks to Conrda Kostecki for help tracking
this wrong. Thanks to Conrad Kostecki for help tracking
this down.
Send a preference value of 255 in DHCPv6 replies when
@@ -55,7 +205,52 @@ version 2.61
received from a network which has no valid dhcp-range.
Thanks to Stephane Glondu for the bug report.
Add a new DHCP lease time keyword, "deprecated" for
--dhcp-range. This is only valid for IPv6, and sets the
preffered lease time for both DHCP and RA to zero. The
effect is that clients can continue to use the address
for existing connections, but new connections will use
other addresses, if they exist. This makes hitless
renumbering at least possible.
Fix bug in address6_available() which caused DHCPv6 lease
aquisition to fail if more than one dhcp-range in use.
Provide RDNSS and DNSSL data in router advertisements,
using the settings provided for DHCP options
option6:domain-search and option6:dns-server.
Tweak logo/favicon.ico to add some transparency. Thanks to
SamLT for work on this.
Don't cache data from non-recursive nameservers, since it
may erroneously look like a valid CNAME to a non-exitant
name. Thanks to Ben Winslow for finding this.
Call SO_BINDTODEVICE on the DHCP socket(s) when doing DHCP
on exactly one interface and --bind-interfaces is set. This
makes the OpenStack use-case of one dnsmasq per virtual
interface work. This is only available on Linux; it's not
supported on other platforms. Thanks to Vishvananda Ishaya
and the OpenStack team for the suggestion.
Updated French translation. Thanks to Gildas Le Nadan.
Give correct from-cache answers to explict CNAME queries.
Thanks to Rob Zwissler for spotting this.
Add --tftp-lowercase option. Thanks to Oliver Rath for the
patch.
Ensure that the DBus DhcpLeaseUpdated events are generated
when a lease goes through INIT_REBOOT state, even if the
dhcp-script is not in use. Thanks to Antoaneta-Ecaterina
Ene for the patch.
Fix failure of TFTP over IPv4 on OpenBSD platform. Thanks
to Brad Smith for spotting this.
version 2.60
Fix compilation problem in Mac OS X Lion. Thanks to Olaf
Flebbe for the patch.
@@ -235,7 +430,7 @@ version 2.58
Fix regression in TFTP server on *BSD platforms introduced
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
/etc/resolv.conf and in --server options. Eg

105
FAQ
View File

@@ -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
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
same address it was sent to. The traditional way to write an UDP
server to do this is to find all of the addresses belonging to the
machine (ie all the interfaces on the machine) and then create a
socket for each interface which is bound to the address of the
interface. Then when a packet is sent to address A, it is received
on the socket bound to address A and when the reply is also sent
via that socket, the source address is set to A by the kernel and
everything works. This is the how dnsmasq works when
"bind-interfaces" is set, with the obvious extension that is misses
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.
A: Dnsmasq from v2.63 can operate in one of three different "networking
modes". This is unfortunate as it requires users configuring dnsmasq
to take into account some rather bizzare contraints and select the
mode which best fits the requirements of a particular installation.
The origin of these are deficiencies in the Unix networking
model and APIs and each mode has different advantages and
problems. Just to add to the confusion, not all modes are available on
all platforms (due the to lack of supporting network APIs).To further
add to the confusion, the rules for the DHCP subsystem on dnsmasq are
different to the rules for the DNS and TFTP subsystems.
The alternative approach is to have only one socket, which is bound
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.
The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
It could be argued that if the --interface or --address flags are
used then binding interfaces is more appropriate, but using
wildcard binding means that dnsmasq will quite happily start up
after being told to use interfaces which don't exist, but which are
created later. Wildcard binding breaks the scenario when dnsmasq is
listening on one interface and another server (most probably BIND)
is listening on another. It's not possible for BIND to bind to an
(address,port) pair when dnsmasq has bound (wildcard,port), hence
the ability to explicitly turn off wildcard binding.
In "wildcard" mode, dnsmasq binds the wildcard IP address (0.0.0.0 or
::). This allows it to recieve all the packets sent to the server on
the relevant port. Access control (--interface, --except-interface,
--listen-address, etc) is implemented by dnsmasq: it queries the
kernel to determine the interface on which a packet was recieved and
the address to which it was sent, and applies the configured
rules. Wildcard mode is the default if neither of the other modes are
specified.
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
queries for SRV records.

View File

@@ -79,7 +79,8 @@ all : $(BUILDDIR)
clean :
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
@@ -113,7 +114,11 @@ $(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):
ln -s $(top)/$(SRC)/$@ .
@@ -121,7 +126,7 @@ $(objs:.o=.c) $(hdrs):
.c.o:
$(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $<
dnsmasq : $(hdrs) $(objs)
dnsmasq : .configured $(hdrs) $(objs)
$(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS)
dnsmasq.pot : $(objs:.o=.c) $(hdrs)

View File

@@ -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_SYSTEM_SHARED_LIBRARIES := libc libcutils
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_EXECUTABLE)

View File

@@ -8,6 +8,8 @@
# 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
# 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
cd $1; git describe
@@ -18,7 +20,7 @@ else
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep $v[0-9]`
if [ $? -eq 0 ]; then
echo "${vers}" | head -n 1 | tail -c +2
echo "${vers}" | sort | head -n 1 | sed 's/^v//'
else
cat $1/VERSION
fi

43
contrib/dbus-test/dbus-test.py Executable file
View File

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

View File

@@ -0,0 +1,57 @@
To: dnsmasq-discuss@lists.thekelleys.org.uk
From: Alex Elsayed <eternaleye+usenet@gmail.com>
Date: Tue, 15 May 2012 01:53:54 -0700
Subject: [Dnsmasq-discuss] [PATCH] Support dbus activation
Introduce dbus service file and turn dbus on in the systemd
unit.
Note to packagers:
To add support for dbus activation, you must install the dbus
service file (dbus/uk.org.thekelleys.dnsmasq.service) into
$DATADIR/dbus-1/system-services.
---
contrib/systemd/dnsmasq.service | 2 +-
dbus/uk.org.thekelleys.dnsmasq.service | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
create mode 100644 dbus/uk.org.thekelleys.dnsmasq.service
diff --git a/contrib/systemd/dnsmasq.service
b/contrib/systemd/dnsmasq.service
index a27fe6d..4a784d3 100644
--- a/contrib/systemd/dnsmasq.service
+++ b/contrib/systemd/dnsmasq.service
@@ -5,7 +5,7 @@ Description=A lightweight DHCP and caching DNS server
Type=dbus
BusName=uk.org.thekelleys.dnsmasq
ExecStartPre=/usr/sbin/dnsmasq --test
-ExecStart=/usr/sbin/dnsmasq -k
+ExecStart=/usr/sbin/dnsmasq -k -1
ExecReload=/bin/kill -HUP $MAINPID
[Install]
diff --git a/dbus/uk.org.thekelleys.dnsmasq.service
b/dbus/uk.org.thekelleys.dnsmasq.service
new file mode 100644
index 0000000..f5fe98d
--- /dev/null
+++ b/dbus/uk.org.thekelleys.dnsmasq.service
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=uk.org.thekelleys.dnsmasq
+Exec=/usr/sbin/dnsmasq -k -1
+User=root
+SystemdService=dnsmasq.service
+
+
--
1.7.10.2
_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

View File

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

58
debian/changelog vendored
View File

@@ -1,10 +1,66 @@
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
* 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
dnsmasq (2.62-3) unstable; urgency=low
* Do resolvconf and /etc/default startup logic when
starting with systemd. (closes: #675854)
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 11 Jun 2012 21:50:11 +0000
dnsmasq (2.62-2) unstable; urgency=low
* Pass LDFLAGS to make to get hardening in linker.
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jun 2012 09:53:43 +0000
dnsmasq (2.62-1) unstable; urgency=low
* New upstream.
* Use dpkg-buildflags. (Enables hardening).
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 12 May 2012 15:25:23 +0000
dnsmasq (2.61-1) unstable; urgency=low
* New upstream.
* Provide "dump-stats" initscript method. (closes: #654656)
* Add (empty) build-indep and build-arch rules targets.
* Bump standards-version to 3.9.3
* Add port option to example dnsmasq.conf (closes: #668386)
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 6 Mar 2012 19:45:43 +0000
dnsmasq (2.60-2) unstable; urgency=high

1
debian/conffiles vendored
View File

@@ -2,5 +2,4 @@
/etc/default/dnsmasq
/etc/dnsmasq.conf
/etc/resolvconf/update.d/dnsmasq
/etc/dbus-1/system.d/dnsmasq.conf
/etc/insserv.conf.d/dnsmasq

7
debian/control vendored
View File

@@ -7,7 +7,7 @@ Standards-Version: 3.9.3
Package: dnsmasq
Architecture: all
Depends: netbase, adduser, dnsmasq-base(>= ${source:Version})
Depends: netbase, dnsmasq-base(>= ${source:Version})
Suggests: resolvconf
Conflicts: resolvconf (<<1.15)
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
Architecture: any
Depends: ${shlibs:Depends}
Conflicts: dnsmasq (<<2.41)
Depends: adduser, ${shlibs:Depends}
Breaks: dnsmasq (<< 2.63-1~)
Replaces: dnsmasq (<< 2.63-1~)
Description: Small caching DNS proxy and DHCP/TFTP server
This package contains the dnsmasq executable and documentation, but
not the infrastructure required to run it as a system daemon. For

1
debian/dnsmasq-base.conffiles vendored Normal file
View File

@@ -0,0 +1 @@
/etc/dbus-1/system.d/dnsmasq.conf

24
debian/dnsmasq-base.postinst vendored Normal file
View File

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

11
debian/dnsmasq-base.postrm vendored Normal file
View File

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

21
debian/init vendored
View File

@@ -259,6 +259,27 @@ case "$1" in
dump-stats)
kill -s USR1 `cat /var/run/dnsmasq/$NAME.pid`
;;
systemd-start-resolvconf)
start_resolvconf
;;
systemd-stop-resolvconf)
stop_resolvconf
;;
systemd-exec)
# --pid-file without argument disables writing a PIDfile, we don't need one with sytemd.
# Enable DBus by default because we use DBus activation with systemd.
exec $DAEMON --keep-in-foreground --pid-file --enable-dbus \
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
${MAILTARGET:+ -t $MAILTARGET} \
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
${DNSMASQ_INTERFACES:+ $DNSMASQ_INTERFACES} \
${DHCP_LEASE:+ -l $DHCP_LEASE} \
${DOMAIN_SUFFIX:+ -s $DOMAIN_SUFFIX} \
${RESOLV_CONF:+ -r $RESOLV_CONF} \
${CACHESIZE:+ -c $CACHESIZE} \
${CONFIG_DIR:+ -7 $CONFIG_DIR} \
${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}
;;
*)
echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|dump-stats|status}" >&2
exit 3

27
debian/postinst vendored
View File

@@ -1,27 +1,6 @@
#!/bin/sh
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
update-rc.d dnsmasq defaults 15 85 >/dev/null
@@ -40,10 +19,4 @@ if [ -x /etc/init.d/dnsmasq ]; then
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

6
debian/postrm vendored
View File

@@ -3,10 +3,4 @@ set -e
if [ purge = "$1" ]; then
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

23
debian/rules vendored
View File

@@ -11,14 +11,14 @@
package=dnsmasq-base
# policy manual, section 10.1
ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS = -g -O0 -Wall -W
else
CFLAGS = -g -O2 -Wall -W
endif
CFLAGS = $(shell export DEB_BUILD_OPTIONS=$(DEB_BUILD_OPTIONS); dpkg-buildflags --get CFLAGS)
CFLAGS += $(shell dpkg-buildflags --get CPPFLAGS)
CFLAGS += -Wall -W
LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS)
COPTS =
TARGET = install-i18n
DEB_BUILD_ARCH_OS := $(shell dpkg-architecture -qDEB_BUILD_ARCH_OS)
@@ -85,7 +85,6 @@ binary-indep: checkroot
-d debian/daemon/etc/resolvconf/update.d \
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
-d debian/daemon/etc/default \
-d debian/daemon/etc/dbus-1/system.d \
-d debian/daemon/lib/systemd/system \
-d debian/daemon/etc/insserv.conf.d
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 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/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/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
@@ -111,11 +109,12 @@ binary-arch: checkroot
rm -rf debian/base
install -m 755 \
-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)/examples \
-d debian/base/var/run \
-d debian/base/var/lib/misc
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" COPTS="$(COPTS)" CC=gcc
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(COPTS)" CC=gcc
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
install -m 644 doc.html debian/base/usr/share/doc/$(package)/.
install -m 644 setup.html debian/base/usr/share/doc/$(package)/.
@@ -129,10 +128,14 @@ ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
gzip -9 debian/base/usr/share/doc/$(package)/DBus-interface
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
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/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
for f in debian/base/usr/share/man/*; do \
if [ -f $$f/man8/dnsmasq.8 ]; then \
@@ -155,7 +158,7 @@ ifeq ($(DEB_BUILD_ARCH_OS),linux)
-d debian/utils/usr/share/man/man1 \
-d debian/utils/usr/bin \
-d debian/utils/usr/share/doc/dnsmasq-utils
make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" COPTS="$(COPTS)" CC=gcc
make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(COPTS)" CC=gcc
install -m 755 contrib/wrt/dhcp_release debian/utils/usr/bin/dhcp_release
install -m 644 contrib/wrt/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
gzip -9 debian/utils/usr/share/man/man1/dhcp_release.1

View File

@@ -8,22 +8,24 @@ BusName=uk.org.thekelleys.dnsmasq
# Test the config file and refuse starting if it is not valid.
ExecStartPre=/usr/sbin/dnsmasq --test
# Enable DBus by default because we use DBus activation.
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
# wrapper picking up extra configuration files and then execs dnsmasq
# itself, when called with the "systemd-exec" function.
#
# Drop privileges and become the 'dnsmasq' user. It is recommended by dnsmasq
# upstream to run dnsmasq as an isolated user that does not run any other
# processes, owns no files and has no shell. The default 'nobody' user has a
# shell and might be used for other processes.
# It also adds the command-line flags
# --keep-in-foreground --pid-file --enable-dbus
# to disable writing a pid-file (not needed with systemd) and
# enable DBus by default because we use DBus activation.
#
# Debian-specific: add /etc/dnsmasq.d to config search path (with the exception
# of .dpkg-*). Packages such as libvirt leave config files there.
#
# --pid-file without argument disables writing a PIDfile, we don't need one.
ExecStart=/usr/sbin/dnsmasq -k \
--enable-dbus \
--user=dnsmasq \
-7 /etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new \
--pid-file
ExecStart=/etc/init.d/dnsmasq systemd-exec
# The systemd-*-resolvconf functions configure (and deconfigure)
# resolvconf to work with the dnsmasq DNS server. They're called liek
# this to get correct error handling (ie don't start-resolvconf if the
# dnsmasq daemon fails to start.
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf
ExecReload=/bin/kill -HUP $MAINPID

View File

@@ -4,6 +4,11 @@
# as the long options legal on the command line. See
# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details.
# Listen on this specific port instead of the standard DNS port
# (53). Setting this to zero completely disables DNS function,
# leaving only DHCP and/or TFTP.
#port=5353
# The following two options make you a better netizen, since they
# tell dnsmasq to filter out queries which the public DNS cannot
# answer, and which load the servers (especially the root servers)
@@ -169,14 +174,32 @@
# hosts. Use the DHCPv4 lease to derive the name, network segment and
# MAC address and assume that the host will also have an
# IPv6 address calculated using the SLAAC alogrithm.
# This will generate an erroneous AAAA record if a host is using privacy
# extensions or does not support IPv6. Use with care.
#dhcp-range=1234::, ra-names
# Do Router Advertisements, BUT NOT DHCP for this subnet.
# Set the lifetime to 46 hours. (Note: minimum lifetime is 2 hours.)
#dhcp-range=1234::, ra-only, 48h
# Do DHCP and Router Advertisements for this subnet. Set the A bit in the RA
# so that clients can use SLAAC addresses as well as DHCP ones.
#dhcp-range=1234::2, 1234::500, slaac
# Do Router Advertisements and stateless DHCP for this subnet. Clients will
# not get addresses from DHCP, but they will get other configuration information.
# They will use SLAAC for addresses.
#dhcp-range=1234::, ra-stateless
# Do stateless DHCP, SLAAC, and generate DNS names for SLAAC addresses
# from DHCPv4 leases.
#dhcp-range=1234::, ra-stateless, ra-names
# Do router advertisements for all subnets where we're doing DHCPv6
# Unless overriden by ra-stateless, ra-names, et al, the router
# advertisements will have the M and O bits set, so that the clients
# get addresses and configuration from DHCPv6, and the A bit reset, so the
# clients don't use SLAAC addresses.
#enable-ra
# Supply parameters for specified hosts using DHCP. There are lots
# of valid alternatives, so we will give examples of each. Note that
# IP addresses DO NOT have to be in the range given above, they just
@@ -303,6 +326,9 @@
# dnsmasq and another.
#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
# is running dnsmasq
#dhcp-option=42,0.0.0.0
@@ -454,7 +480,7 @@
#tftp-no-blocksize
# 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
# address of the server are given after the filename.
@@ -499,7 +525,7 @@
# If you want to disable negative caching, uncomment this.
#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
# 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
@@ -595,6 +621,6 @@
# Log lots of extra information about DHCP transactions.
#log-dhcp
# Include a another lot of configuration options.
# Include another lot of configuration options.
#conf-file=/etc/dnsmasq.more.conf
#conf-dir=/etc/dnsmasq.d

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -23,7 +23,7 @@ options. It includes a secure, read-only,
TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP.
.PP
Dnsmasq
supports IPv6 for all functions and a minimal router-advertisemnet daemon.
supports IPv6 for all functions and a minimal router-advertisement daemon.
.SH OPTIONS
Note that in general missing parameters are allowed and switch off
functions, for instance "--pid-file" disables writing a PID file. On
@@ -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
the upstream DNS servers.
.TP
.B --max-cache-ttl=<time>
Set a maximum TTL value for entries in the cache.
.TP
.B \-k, --keep-in-foreground
Do not go into the background at startup but otherwise run as
normal. This is intended for use when dnsmasq is run under daemontools
@@ -80,7 +83,9 @@ or launchd.
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
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
.B \-q, --log-queries
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
@@ -204,6 +209,17 @@ running another nameserver (or another instance of dnsmasq) on the
same machine. Setting this option also enables multiple instances of
dnsmasq which provide DHCP service to run in the same machine.
.TP
.B --bind-dynamic
Enable a network mode which is a hybrid between
.B --bind-interfaces
and the default. Dnsmasq binds the address of individual interfaces,
allowing multiple dnsmasq instances, but if new interfaces or
addresses appear, it automatically listens on those (subject to any
access-control configuration). This makes dynamically created
interfaces work in the same way as the default. Implementing this
option requires non-standard networking APIs and it is only available
under Linux. On other platforms it falls-back to --bind-interfaces mode.
.TP
.B \-y, --localise-queries
Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was
received. If a name in /etc/hosts has more than one address associated with
@@ -260,11 +276,13 @@ time is the one used.
Don't read /etc/resolv.conf. Get upstream servers only from the command
line or the dnsmasq configuration file.
.TP
.B \-1, --enable-dbus
.B \-1, --enable-dbus[=<service-name>]
Allow dnsmasq configuration to be updated via DBus method calls. The
configuration which can be changed is upstream DNS servers (and
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
.B \-o, --strict-order
By default, dnsmasq will send queries to any of the upstream servers
@@ -416,7 +434,7 @@ zone files: the port, weight and priority numbers are in a different
order. More than one SRV record for a given service/domain is allowed,
all that match are returned.
.TP
.B --host-record=<name>[,<name>....][<IPv4-address>],[IPv6-address]
.B --host-record=<name>[,<name>....][<IPv4-address>],[<IPv6-address>]
Add A, AAAA and PTR records to the DNS. This adds one or more names to
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
appear in more than one
@@ -427,10 +445,12 @@ the same rule as is used reading hosts-files.
.B host-record
options are considered to be read before host-files, so a name
appearing there inhibits PTR-record creation if it appears in
hosts-file also. Unlike host-files, names are not expanded, even when
hosts-file also. Unlike hosts-files, names are not expanded, even when
.B expand-hosts
is in effect. Short and long names may appear in the same
.B host-record, eg. --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
.B host-record,
eg.
.B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
.TP
.B \-Y, --txt-record=<name>[[,<text>],<text>]
Return a TXT DNS record. The value of TXT record is a set of strings,
@@ -448,10 +468,18 @@ Return an NAPTR DNS record, as specified in RFC3403.
Return a CNAME record which indicates that <cname> is really
<target>. There are significant limitations on the target; it must be a
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
is permissable to have more than one cname pointing to the same target.
.TP
.B --dns-rr=<name>,<RR-number>,[<hex data>]
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
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.
.TP
.B --interface-name=<name>,<interface>
Return a DNS record associating the name with the primary address on
the given interface. This flag specifies an A record for the given
@@ -510,9 +538,9 @@ compiled in and the kernel must have conntrack support
included and configured. This option cannot be combined with
--query-port.
.TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>,<end-addr>[,<netmask>[,<broadcast>]][,<lease time>]
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag],]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
.TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<tag>[,tag:<tag>],][set:<tag],]<start-IPv6addr>,<end-IPv6addr>[,<prefix-len>][,<lease time>]
.B \-F, --dhcp-range=[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
<start-addr> to <end-addr> and from statically defined addresses given
@@ -522,8 +550,12 @@ options. If the lease time is given, then leases
will be given for that length of time. The lease time is in seconds,
or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given,
the default lease time is one hour. The
minimum lease time is two minutes. This
option may be repeated, with different addresses, to enable DHCP
minimum lease time is two minutes. For IPv6 ranges, the lease time
maybe "deprecated"; this sets the preferred lifetime sent in a DHCP
lease or router advertisement to zero, which causes clients to use
other addresses, if available, for new connections as a prelude to renumbering.
This option may be repeated, with different addresses, to enable DHCP
service to more than one network. For directly connected networks (ie,
networks on which the machine running dnsmasq has an interface) the
netmask is optional: dnsmasq will determine it from the interface
@@ -548,45 +580,63 @@ When it is prefixed with 'tag:' instead, then its meaning changes from setting
a tag to matching it. Only one tag may be set, but more than one tag
may be matched.
The end address may be replaced by the keyword
The optional <mode> keyword may be
.B static
which tells dnsmasq to enable DHCP for the network specified, but not
to dynamically allocate IP addresses: only hosts which have static
addresses given via
.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
The end address may be replaced by
the keyword
For IPv4, the <mode> may be
.B proxy
in which case dnsmasq will provide proxy-DHCP on the specified
subnet. (See
.B pxe-prompt
and
.B pxe-service
for details, applies to IPv4 only.)
for details.)
For IPv6, the mode may be some combination of
.B ra-only, slaac, ra-names, ra-stateless.
The end address may be replaced by
the keyword
.B ra-only
which tells dnsmasq to offer Router Advertisement only on this subnet,
and not DHCP. This applies to IPv6 only, see
.B enable-ra
for details. Instead, the keyword
tells dnsmasq to offer Router Advertisement only on this subnet,
and not DHCP.
.B slaac
tells dnsmasq to offer Router Advertisement on this subnet and to set
the A bit in the router advertisement, so that the client will use
SLAAC addresses. When used with a DHCP range or static DHCP address
this results in the client having both a DHCP-assigned and a SLAAC
address.
.B ra-stateless
sends router advertisements with the O and A bits set, and provides a
stateless DHCP service. The client will use a SLAAC address, and use
DHCP for other configuration information.
.B ra-names
may be used. This does the same at ra-only, but also enables a mode
enables a mode
which gives DNS names to dual-stack hosts which do SLAAC for
IPv6. Dnsmasq uses the host's IPv4 lease to derive the name, network
segment and MAC address and assumes that the host will also have an
IPv6 address calculated using the SLAAC alogrithm, on the same network
IPv6 address calculated using the SLAAC algorithm, on the same network
segment. The address is pinged, and if a reply is received, an AAAA
record is added to the DNS for this IPv6
address. Note that this is only happens for directly-connected
networks, (not one doing DHCP via a relay) and it will not work
if a host is using privacy extensions.
.B ra-names
can be combined with
.B ra-stateless
and
.B slaac.
The interface:<interface name> section is not normally used. See the
NOTES section for details of this.
.TP
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
Specify per host parameters for the DHCP server. This allows a machine
@@ -1120,7 +1170,9 @@ is known.
DNSMASQ_TAGS contains all the tags set during the
DHCP transaction, separated by spaces.
DNSMASQ_LOG_DHCP is set if --log-dhcp is in effect.
DNSMASQ_LOG_DHCP is set if
.B --log-dhcp
is in effect.
For IPv4 only:
@@ -1173,7 +1225,7 @@ with an "old " event.
There are two further actions which may appear as the first argument
to the script, "init" and "tftp". More may be added in the future, so
scripts should be written to ignore unknown actions. "init" is
decsribed below in
described below in
.B --leasefile-ro
The "tftp" action is invoked when a TFTP file transfer completes: the
arguments are the file size in bytes, the address to which the file
@@ -1319,27 +1371,20 @@ only a subset of this is needed, and dnsmasq can handle it, using
existing DHCP configuration to provide most data. When RA is enabled,
dnsmasq will advertise a prefix for each dhcp-range, with default
router and recursive DNS server as the relevant link-local address on
the machine running dnsmasq. The "managed address" bits are set, and
the "use SLAAC" bit is reset, except for a dhcp-range which is
marked as "ra-only" or "ra-names", in which case RA is provided but no
DHCPv6 service and the managed address bits are
cleared and the "use SLAAC" bit set. If the same subnet appears in a
normal dhcp-range and an "ra-only" dhcp-range, then the "managed
address" bits and the "use SLAAC" bits are all set, allowing SLAAC and
DHCP address to co-exist on the same subnet.
.B enable-ra
enables router advertisement for prefixes where dnsmasq is doing
DHCPv6. It is not needed for "ra-only" prefixes. Creating an "ra-only"
prefix and not setting
.B enable-ra
sends advertisements only to "ra-only" prefixes.
the machine running dnsmasq. By default, he "managed address" bits are set, and
the "use SLAAC" bit is reset. This can be changed for individual
subnets with the mode keywords described in
.B --dhcp-range.
RFC6106 DNS parameters are included in the advertisements. By default,
the relevant link-local address of the machine running dnsmasq is sent
as recursive DNS server. If provided, the DHCPv6 options dns-server and
domain-search are used for RDNSS and DNSSL.
.TP
.B --enable-tftp[=<interface>]
.B --enable-tftp
Enable the TFTP server function. This is deliberately limited to that
needed to net-boot a client. Only reading is allowed; the tsize and
blksize extensions are supported (tsize is only supported in octet
mode). See NOTES section for use of the interface argument.
mode).
.TP
.B --tftp-root=<directory>[,<interface>]
Look for files to transfer using TFTP relative to the given
@@ -1367,6 +1412,12 @@ are accessible. It is not recommended to run dnsmasq as root with TFTP
enabled, and certainly not without specifying --tftp-root. Doing so
can expose any world-readable file on the server to any host on the net.
.TP
.B --tftp-lowercase
Convert filenames in TFTP requests to all lowercase. This is useful
for requests from Windows machines, which have case-insensitive
filesystems and tend to play fast-and-loose with case in filenames.
Note that dnsmasq's tftp server always converts "\\" to "/" in filenames.
.TP
.B --tftp-max=<connections>
Set the maximum number of concurrent TFTP connections allowed. This
defaults to 50. When serving a large number of TFTP connections,
@@ -1597,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
different classes of hosts.
.B dhcp-range
may have an interface name supplied as
"interface:<interface-name>". The semantics if this are as follows:
For DHCP, if any other dhcp-range exists _without_ an interface name,
then the interface name is ignored and and dnsmasq behaves as if the
interface parts did not exist, otherwise DHCP is only provided to
interfaces mentioned in dhcp-range
declarations. For DNS, if there are no
.B --interface
or
.B --listen-address
flags, behaviour is unchanged by the interface part. If either of
these flags are present, the interfaces mentioned in
dhcp-ranges are added to the set which get DNS service.
Similarly,
.B enable-tftp
may take an interface name, which enables TFTP only for a particular
interface, ignoring
.B --interface
or
.B --listen-address
flags. In addition
.B --tftp-secure
and
.B --tftp-unique-root
and
.B --tftp-no-blocksize
are ignored for requests from such interfaces. (A
.B --tftp-root
directive giving a root path and an interface should be
provided too.)
These rules may seem odd at first sight, but they
allow a single line of the form "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200"
to be added to dnsmasq configuration which then supplies
DHCP and DNS services to that interface, without affecting
what services are supplied to other interfaces and irrespective of
the existance or lack of "interface=<interface>"
lines elsewhere in the dnsmasq configuration.
"enable-tftp=virt0" and "tftp-root=<root>,virt0" do the same job for TFTP.
The idea is
that such a line can be added automatically by libvirt
or equivalent systems, without disturbing any manual
configuration.
.SH EXIT CODES
.PP
0 - Dnsmasq successfully forked into the background, or terminated

View File

@@ -22,7 +22,8 @@ peut être configuré pour envoyer n'importe quel option DHCP.
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP.
.PP
Dnsmasq supporte IPv6 pour le DNS et TFTP mais pas pour le DHCP.
Dnsmasq supporte IPv6 et contient un démon minimaliste capable de faire des
annonces routeurs ("router-advertisements").
.SH OPTIONS
Notes : Il est possible d'utiliser des options sans leur donner de paramètre.
Dans ce cas, la fonction correspondante sera désactivée. Par exemple
@@ -231,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
Dnsmasq fournissant un service DHCP sur la même machine.
.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
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
@@ -492,6 +505,27 @@ dans un ordre différents. Pour un service/domaine donné, plus d'un
enregistrement SRV est autorisé et tous les enregistrements qui coïncident sont
retournés dans la réponse.
.TP
.B --host-record=<nom>[,<nom>....][<adresse IPv4>],[<adresse IPv6>]
Ajoute des enregistrements A, AAAA et PTR dans le DNS. Ceci permet d'ajouter
un ou plusieurs noms dans le DNS et de les associer à des enregistrements IPv4
(A) ou IPv6 (AAAA). Un nom peut apparaître dans plus d'une entrée
.B host-record
et de fait être associé à plus d'une adresse. Seule la première entrée créée
l'enregistrement PTR associée au nom. Ceci correspond à la même règle que celle
utilisée lors de la lecture du fichier hosts.
Les options
.B host-record
sont considérées lues avant le fichier hosts, ainsi un nom apparaissant dans
une option host-record et dans le fichier hosts n'aura pas d'enregistrement
PTR associé à l'entrée dans le fichier hosts. A l'inverse du fichier hosts, les
noms ne sont pas étendus, même lorsque l'option
.B expand-hosts
est activée. Les noms longs et les noms courts peuvent apparaitre dans la même
entrée
.B host-record,
c-à-d
.B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
.TP
.B \-Y, --txt-record=<nom>[[,<texte>],<texte>]
Définit un enregistrement DNS de type TXT. La valeur de l'enregistrement TXT est
un ensemble de chaînes de caractères, donc un nombre variable de chaînes de
@@ -510,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
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
(ou un fichier hôtes additionnel) ou via DHCP. 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.
(ou un fichier hôtes additionnel), ou via DHCP, ou par un autre
.B --cname.
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
.B --interface-name=<nom>,<interface>
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
@@ -577,11 +619,11 @@ l'ayant déclenché, ce qui est pratique pour la gestion de la bande passante
(accounting) et le filtrage (firewall). Dnsmasq doit pour cela être compilé
avec le support conntrack, le noyau doit également inclure conntrack et être
configuré pour cela. Cette option ne peut pas être combinée avec
--query-port.
--query-port.
.TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>,<adresse de fin>[,<masque de réseau>[,<broadcast>]][,<durée de bail>]
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>[,<adresse de fin>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
.TP
.B \-F, --dhcp-range=[interface:<interface>,][tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>,<adresse IPv6 de fin>[,<longueur de préfixe>][,<durée de bail>]
.B \-F, --dhcp-range=[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
<adresse de début> et <adresse de fin> et à partir des adresses définies
statiquement dans l'option
@@ -592,6 +634,13 @@ en heures (exemple : 1h) ou être la chaine de caractère "infinite" pour une
durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par défaut
de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2
minutes.
Pour les plages IPv6, la durée de bail peut-être égale au mot-clef "deprecated"
(obsolète); Cela positionne la durée de vie préférée envoyée dans les baux DHCP
ou les annonces routeurs à zéro, ce qui incite les clients à utiliser d'autres
adresses autant que possible, pour toute nouvelle connexion, en préalable à
la renumérotation.
Cette option peut être répétée, avec différentes adresses,
pour activer le service DHCP sur plus d'un réseau. Pour des réseaux directement
connectés (c'est-à-dire des réseaux dans lesquels la machine sur laquelle tourne
@@ -622,33 +671,60 @@ Lorsque préfixé par 'tag:', la signification change, et au lieu de définir un
label, il définit le label pour laquelle la règle s'applique. Un seul label peut-
être défini mais plusieurs labels peuvent coïncider.
L'adresse de fin peut être remplacée par le mot-clef
Le mot clef optionnel <mode> peut être égal à
.B static
("statique") qui indique à Dnsmasq d'activer le service DHCP pour le réseau
("statique") ce qui indique à Dnsmasq d'activer le service DHCP pour le réseau
spécifié, mais de ne pas activer l'allocation dynamique d'adresses IP : Seuls
les hôtes possédant des adresses IP statiques fournies via
.B dhcp-host
ou présentes dans le fichier /etc/ethers seront alors servis par le DHCP.
L'adresse de fin peut-être remplacée par le mot-clef
Pour IPv4, le <mode> peut est égal à
.B proxy
, auquel cas Dnsmasq fournira un service de DHCP proxy pour le sous-réseau
spécifié. (voir
.B pxe-prompt
et
.B pxe-service
pour plus de détails, s'applique à IPv4 seulement).
pour plus de détails).
Pour IPv6, le mode peut-être une combinaison des valeurs
.B ra-only, slaac, ra-names, ra-stateless.
L'adresse de fin peut être remplacée par le mot-clef
.B ra-only
qui indique à dnsmasq de n'effectuer que des annonces de routeur (Router
Advertisement, RA) sur ce sous-réseau, et de ne pas faire de DHCP. Ceci
s'applique uniquement à IPv6, voir
.B enable-ra
pour plus de détails.
indique à dnsmasq de n'effectuer que des annonces de routeur (Router
Advertisement, RA) sur ce sous-réseau, et de ne pas faire de DHCP.
.B slaac
indique à dnsmasq d'effectuer des annonces de routeur sur ce sous-réseau
et de positionner dans celles-ci le bit A, afin que les clients utilisent
des adresses SLAAC. Lorsqu'utilisé conjointement avec une plage DHCP ou des
affectations statiques d'adresses DHCP, les clients disposeront à la fois
d'adresses DHCP assignées et d'adresses SLAAC.
.B ra-stateless
indique à dnsmasq d'effectuer des annonces de routeur avec les bits 0 et A
positionnés, et de fournir un service DHCP sans état ("stateless"). Les clients
utiliseront des adresses SLAAC, et utiliseront DHCP pour toutes les autres
informations de configuration.
.B ra-names
active un mode qui fourni des noms DNS aux hôtes fonctionnant en double pile
("dual stack") et configurés pour faire du SLAAC en IPv6. Dnsmasq utilise le
bail IPv4 de l'hôte afin de dériver le nom, le segment de réseau et l'adresse
MAC et assume que l'hôte disposera d'une adresse IPv6 calculée via l'algorithme
SLAAC, sur le même segment de réseau. Un ping est envoyé à l'adresse, et si une
réponse est obtenue, un enregistrement AAAA est rajouté dans le DNS pour cette
adresse IPv6. Veuillez-noter que cela n'arrive que pour les réseaux directement
connectés (et non ceux pour lesquels DHCP se fait via relai), et ne
fonctionnera pas si un hôte utilise les "extensions de vie privée"
("privacy extensions").
.B ra-names
peut-être combiné avec
.B ra-stateless
et
.B slaac.
La section interface:<nom d'interface> n'est normalement pas utilisée. Se
référer aux indications de la section NOTES pour plus de détail à ce sujet.
.TP
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,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
@@ -1170,9 +1246,21 @@ détermination de celles-ci.
.B \-l, --dhcp-leasefile=<chemin de fichier>
Utilise le fichier dont le chemin est fourni pour stocker les informations de
baux DHCP.
.TP
.TP
.B --dhcp-duid=<ID d'entreprise>,<uid>
(IPv6 seulement) Spécifie le numéro d'UID de serveur persistant que le serveur
DHCPv6 doit utiliser. Cette option n'est normalement pas requise, Dnsmasq
créant un DUID automatiquement lorsque cela est nécessaire. Lorsque cette
option est positionnée, elle fournit à Dnsmasq les données nécessaires à la
création d'un DUID de type DUID-EN. Veuillez noter qu'une fois créé, le DUID
est stocké dans la base des baux, aussi changer entre un DUID créé
automatiquement et un DUID-EN et vice-versa impose de réinitialiser la base de
baux. Le numéro d'ID d'entreprise est assigné par l'IANA, et l'uid est une
chaine hexadécimale unique à chaque serveur.
.TP
.B \-6 --dhcp-script=<chemin de fichier>
Lorsqu'un bail DHCP est créé, ou qu'un ancien est supprimé, le fichier dont le
Lorsqu'un bail DHCP est créé, qu'un ancien est supprimé, ou qu'un transfert
TFTP est terminé, le fichier dont le
chemin est spécifié est exécuté. Le <chemin de fichier> doit être un chemin
absolu, aucune recherche n'est effectuée via la variable d'environnement PATH.
Les arguments fournis à celui-ci sont soit
@@ -1223,6 +1311,10 @@ relai DHCP pour contacter Dnsmasq, si l'adresse IP du relai est connue.
DNSMASQ_TAGS contient tous les labels fournis pendant la transaction DHCP,
séparés par des espaces.
DNSMASQ_LOG_DHCP est positionné si
.B --log-dhcp
est activé.
Pour IPv4 seulement :
DNSMASQ_CLIENT_ID, si l'hôte a fourni un identifiant de client.
@@ -1262,6 +1354,16 @@ Au démarrage de Dnsmasq, le script sera invoqué pour chacun des baux existants
dans le fichier des baux. Le script sera lancé avec l'action "del" pour les
baux expirés, et "old" pour les autres. Lorsque Dnsmasq reçoit un signal HUP,
le script sera invoqué avec une action "old" pour tous les baux existants.
Il existe deux autres actions pouvant apparaître comme argument au script :
"init" et "tftp". D'autres sont susceptibles d'être rajoutées dans le futur,
aussi les scripts devraient-être écrits de sorte à ignorer les actions
inconnues. "init" est décrite ci-dessous dans
.B --leasefile-ro.
L'action "tftp" est invoquée lorsqu'un transfert de fichier TFTP s'est
terminé. Ses arguments sont la taille du fichier en octets, l'adresse à
laquelle le fichier a été envoyé, ainsi que le chemin complet du fichier.
.TP
.B --dhcp-luascript=<chemin>
Spécifie un script écrit en Lua, devant être exécuté lorsque des baux sont
@@ -1276,8 +1378,10 @@ et peut fournir des fonctions
et
.B shutdown
qui sont appellées, sans arguments, lorsque dnsmasq démarre ou s'arrête.
Il peut également fournir une fonction
.B tftp.
La méthode
La fonction
.B lease
reçoit les informations détaillées dans
.B --dhcp-script.
@@ -1301,6 +1405,16 @@ et
ainsi que
.B hostname
(le nom d'hôte) dans le cas d'IPv6.
La fonction
.B tftp
est appelée de la même façon que la fonction "lease", et la table contient les
labels
.B destination_address,
.B file_name
et
.B file_size
(respectivement "adresse de destination", "nom de fichier" et "taille de fichier").
.TP
.B --dhcp-scriptuser
Spécifie l'utilisateur sous lequel le script shell lease-change ou le script
@@ -1367,7 +1481,7 @@ Si la gamme d'adresse est fournie sous la forme
qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et
inverses. C-à-d
.B --domain=thekelleys.org.uk,192.168.0.0/24,local
est indentique à
est identique à
.B --domain=thekelleys.org.uk,192.168.0.0/24
--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
La taille de réseau doit-être de 8, 16 ou 24 pour être valide.
@@ -1411,17 +1525,21 @@ Advertisement") sont activées, dnsmasq va annoncer un préfixe pour chaque
dhcp-range et, par défaut, fournir comme valeur de routeur et de DNS récursif
la valeur d'adresse link-local appropriée parmi celles de la machine sur
laquelle tourne dnsmasq.
Les bits "managed address" sont positionnés, sauf pour un dhcp-range marqué
comme "ra-only" (annonce routeur uniquement). Dans ce cas le service d'annonce
routeur est rendu mais aucun service DHCPv6 n'est assuré, et les bits "managed
address" ne sont pas positionnés.
Par défaut, les bits "managed address" sont positionnés, et le bit "use SLAAC"
("utiliser SLAAC") est réinitialisé. Cela peut-être changé pour des
sous-réseaux donnés par le biais du mot clef de mode décris dans
.B --dhcp-range.
Les paramètres DNS du RFC6106 sont inclus dans les annonces. Par défaut,
l'adresse link-local appropriée parmi celles de la machine sur laquelle tourne
dnsmasq est spécifiée comme DNS récursif. Si elles sont fournies, les
options dns-server et domain-search sont utilisées respectivement pour RDNSS et
DNSSL.
.TP
.B --enable-tftp[=<interface>]
.B --enable-tftp
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
un accès en lecture est possible; les extensions tsize et blksize sont supportées
(tsize est seulement supporté en mode octet). Voir dans la section NOTES les
informations relatives à la spécification de l'interface.
(tsize est seulement supporté en mode octet).
.TP
.B --tftp-root=<répertoire>[,<interface>]
Les fichiers à fournir dans les transferts TFTP seront cherchés en prenant le
@@ -1459,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
possible par n'importe quel hôte sur le réseau.
.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>
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é,
@@ -1722,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
aux différentes classes d'hôtes.
Il est possible de spécifier un nom d'interface à
.B dhcp-range
sous la forme "interface:<nom d'interface>". La sémantique est comme suit :
Pour le DHCP, s'il existe une autre valeur de dhcp-range pour laquelle
_aucun_ nom d'interface n'est donné, alors le nom d'interface est ignoré
et dnsmasq se comporte comme si la partie spécifiant l'interface n'existait
pas, sinon le service DHCP n'est fourni qu'aux interfaces mentionnées dans
les déclarations dhcp-range. Pour le DNS, si il n'y a pas d'option
.B --interface
ou
.B --listen-address
, alors le comportement n'est pas impacté par la spécification d'interface. Si
l'une ou l'autre de ces options est présente, alors les interfaces mentionnées
dans les plages d'adresses dhcp-range sont rajoutées à la liste de celles
où le service DNS est assuré.
De manière similaire,
.B enable-tftp
peut prendre un nom d'interface, ce qui active le TFTP pour cette seule
interface, en ignorant les options
.B --interface
ou
.B --listen-address
De plus,
.B --tftp-secure
,
.B --tftp-unique-root
et
.B --tftp-no-blocksize
sont ignorées pour les requêtes sur de telles interfaces. (une directive
.B --tftp-root
donnant le chemin de la racine et une interface doit-être fournie).
Ces règles peuvent paraître étrange à première vue, mais elles permettent
d'ajouter à la configuration de dnsmasq des lignes de configuration de la
forme "dhcp-range=interface:virt0,192.168.0.4,192.168.0.200" afin de fournir
un service DHCP et DNS sur cette interface, sans pour autant affecter les
services fournis sur d'autres interfaces, malgré l'absence de paramètres
"interface=<interface>" sur les autres lignes de configuration.
"enable-tftp=virt0" et "tftp-root=<root>,virt0" effectuent la même chose pour
TFTP.
L'idée de tout cela est de permettre l'addition de telles lignes
automatiquement par libvirt ou un système équivalent, sans perturbation
d'une configuration manuelle existant par ailleurs.
.SH CODES DE SORTIE
.PP
0 - Dnsmasq s'est correctement lancé en tâche de fond, ou alors s'est

294
po/de.po
View File

@@ -12,8 +12,8 @@ msgstr ""
"Project-Id-Version: dnsmasq 2.53rc1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-18 12:24+0100\n"
"PO-Revision-Date: 2010-05-24 16:29+0200\n"
"Last-Translator: Matthias Andree <matthias.andree@gmx.de>\n"
"PO-Revision-Date: 2012-04-05 17:54+0100\n"
"Last-Translator: Conrad Kostecki <ConiKost@gmx.de>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -25,17 +25,20 @@ msgstr ""
msgid "failed to load names from %s: %s"
msgstr "Fehler beim Laden der Namen von %s: %s"
#: cache.c:797 dhcp.c:855
#: cache.c:797
#: dhcp.c:855
#, c-format
msgid "bad address at %s line %d"
msgstr "Fehlerhafte Adresse in %s Zeile %d"
#: cache.c:846 dhcp.c:871
#: cache.c:846
#: dhcp.c:871
#, c-format
msgid "bad name at %s line %d"
msgstr "Fehlerhafter Name in %s Zeile %d"
#: cache.c:853 dhcp.c:946
#: cache.c:853
#: dhcp.c:946
#, c-format
msgid "read %s - %d addresses"
msgstr "%s gelesen - %d Adressen"
@@ -47,7 +50,7 @@ msgstr "Cache geleert"
#: cache.c:953
#, c-format
msgid "No IPv4 address found for %s"
msgstr ""
msgstr "Keine IPv4-Adresse für %s gefunden"
#: cache.c:1005
#, c-format
@@ -88,7 +91,8 @@ msgstr "Konnte den Zufallszahlengenerator nicht initialisieren: %s"
msgid "failed to allocate memory"
msgstr "Konnte Speicher nicht belegen"
#: util.c:227 option.c:717
#: util.c:227
#: option.c:717
msgid "could not get memory"
msgstr "Speicher nicht verfügbar"
@@ -171,19 +175,16 @@ msgid "Set address or hostname for a specified machine."
msgstr "Adresse oder Hostnamen für einen angegebenen Computer setzen."
#: option.c:268
#, fuzzy
msgid "Read DHCP host specs from file."
msgstr "DHCP-Host-Angaben aus Datei lesen"
msgstr "DHCP-Host-Angaben aus Datei lesen."
#: option.c:269
#, fuzzy
msgid "Read DHCP option specs from file."
msgstr "DHCP-Optionen aus Datei lesen"
msgstr "DHCP-Optionen aus Datei lesen."
#: option.c:270
#, fuzzy
msgid "Evaluate conditional tag expression."
msgstr "Auswertung eines Ausdrucks bedingter Marken"
msgstr "Auswertung eines Ausdrucks bedingter Marken."
#: option.c:271
#, c-format
@@ -325,7 +326,6 @@ msgid "Specify time-to-live in seconds for negative caching."
msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
#: option.c:304
#, fuzzy
msgid "Specify time-to-live in seconds for maximum TTL to send to clients."
msgstr "Gültigkeitsdauer in Sekunden für Caching negativer Ergebnisse festlegen."
@@ -414,17 +414,14 @@ msgid "Disable ICMP echo address checking in the DHCP server."
msgstr "ICMP-Echo-Adressprüfung im DHCP-Server abschalten."
#: option.c:325
#, fuzzy
msgid "Shell script to run on DHCP lease creation and destruction."
msgstr "Skript, das bei Erzeugung/Löschung einer DHCP-Lease laufen soll."
#: option.c:326
#, fuzzy
msgid "Lua script to run on DHCP lease creation and destruction."
msgstr "Skript, das bei Erzeugung/Löschung einer DHCP-Lease laufen soll."
msgstr "Lua-Skript, welches bei Erzeugung/Löschung eines DHCP-Leases laufen soll."
#: option.c:327
#, fuzzy
msgid "Run lease-change scripts as this user."
msgstr "Lease-Änderungs-Skript mit den Rechten dieses Nutzers ausführen."
@@ -504,7 +501,6 @@ msgid "Allow rebinding of 127.0.0.0/8, for RBL servers."
msgstr "Auflösung zu 127.0.0.0/8 erlauben, für RBL-Server."
#: option.c:346
#, fuzzy
msgid "Inhibit DNS-rebind protection on this domain."
msgstr "DNS-Rebind-Schutz für diese Domäne sperren."
@@ -534,9 +530,8 @@ msgstr "Für DHCP-Klienten nur vollständig bestimmte Domänennamen benutzen."
# FIXME: probably typo in original message. -- MA
#: option.c:353
#, fuzzy
msgid "Generate hostnames based on MAC address for nameless clients."
msgstr "Für namenlose Klienten die Hostnamen MAC-basiert erzeugen."
msgstr "Generiere Hostnamen auf Basis der MAC-Adresse für namenlose Klienten."
#: option.c:354
msgid "Use these DHCP relays as full proxies."
@@ -560,28 +555,27 @@ msgstr "Konfigurationssyntax prüfen."
#: option.c:359
msgid "Add requestor's MAC address to forwarded DNS queries."
msgstr ""
msgstr "Anfragende MAC-Adresse in die weiterleitende DNS-Anfrage einfügen"
#: option.c:360
#, fuzzy
msgid "Proxy DNSSEC validation results from upstream nameservers."
msgstr "IPv4-Adressen von vorgelagerten Servern übersetzen."
msgstr "Proxy-DNSSEC-Validierung-Ergebnisse von Upstream-Namensservern."
#: option.c:361
msgid "Attempt to allocate sequential IP addresses to DHCP clients."
msgstr ""
msgstr "Versuche sequenzielle IP-Adressen an DHCP-Klienten zu vergeben."
#: option.c:362
msgid "Copy connection-track mark from queries to upstream connections."
msgstr ""
msgstr "Kopiere \"connection-track mark\" von Anfragen nach Upstream-Verbindungen."
#: option.c:363
msgid "Allow DHCP clients to do their own DDNS updates."
msgstr ""
msgstr "Erlaube DHCP-Klienten ihre eigenen DDNS-Updates durchzuführen."
#: option.c:364
msgid "Send router-advertisements for interfaces doing DHCPv6"
msgstr ""
msgstr "Sende \"Router-Advertisments\" für Netzwerkschnittstellen, welche DHCPv6 nutzen"
#: option.c:782
#, c-format
@@ -608,13 +602,13 @@ msgid "Known DHCP options:\n"
msgstr "Bekannte DHCP-Optionen:\n"
#: option.c:838
#, fuzzy, c-format
#, c-format
msgid "Known DHCPv6 options:\n"
msgstr "Bekannte DHCP-Optionen:\n"
msgstr "Bekannte DHCPv6-Optionen:\n"
#: option.c:973
msgid "unsupported encapsulation for IPv6 option"
msgstr ""
msgstr "Nicht unterstützte Verkapselung für eine IPv6-Option"
#: option.c:1001
msgid "bad dhcp-option"
@@ -624,10 +618,11 @@ msgstr "Fehlerhafte DHCP-Option"
msgid "bad IP address"
msgstr "Fehlerhafte IP-Adresse"
#: option.c:1071 option.c:1177 option.c:2511
#, fuzzy
#: option.c:1071
#: option.c:1177
#: option.c:2511
msgid "bad IPv6 address"
msgstr "Fehlerhafte IP-Adresse"
msgstr "Fehlerhafte IPv6-Adresse"
#: option.c:1205
msgid "bad domain in dhcp-option"
@@ -649,23 +644,25 @@ msgstr "unzulässig wiederholte Markierung"
msgid "illegal repeated keyword"
msgstr "unzulässig wiederholtes Schlüsselwort"
#: option.c:1452 option.c:3536
#: option.c:1452
#: option.c:3536
#, c-format
msgid "cannot access directory %s: %s"
msgstr "Kann auf Verzeichnis %s nicht zugreifen: %s"
#: option.c:1483 tftp.c:464
#: option.c:1483
#: tftp.c:464
#, c-format
msgid "cannot access %s: %s"
msgstr "Kann auf %s nicht zugreifen: %s"
#: option.c:1512
msgid "setting log facility is not possible under Android"
msgstr ""
msgstr "Die Einstellung Protokolliereinrichtung kann unter Android nicht gesetzt werden"
#: option.c:1521
msgid "bad log facility"
msgstr ""
msgstr "Falsche Protokolliereinrichtung"
#: option.c:1570
msgid "bad MX preference"
@@ -688,19 +685,21 @@ msgid "recompile with HAVE_SCRIPT defined to enable lease-change scripts"
msgstr "Neuübersetzung mit HAVE_SCRIPT nötig, um Lease-Änderungs-Skripte auszuführen"
#: option.c:1607
#, fuzzy
msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
msgstr "Neuübersetzung mit HAVE_SCRIPT nötig, um Lease-Änderungs-Skripte auszuführen"
msgstr "Um Benutzerdefinierte Lua-Scripte zu ermöglichen, muss mit HAVE_LUASCRIPT neu kompiliert werden"
#: option.c:1988 option.c:1992
#: option.c:1988
#: option.c:1992
msgid "bad port"
msgstr "unzulässiger Port"
#: option.c:2015 option.c:2046
#: option.c:2015
#: option.c:2046
msgid "interface binding not supported"
msgstr "Schnittstellenbindung nicht unterstützt"
#: option.c:2026 option.c:3088
#: option.c:2026
#: option.c:3088
msgid "bad interface name"
msgstr "unzulässiger Schnittestellenname"
@@ -726,20 +725,20 @@ msgstr "inkonsistenter DHCP-Bereich"
#: option.c:2374
msgid "prefix must be at least 64"
msgstr ""
msgstr "Der Prefix muss mindestens 64 sein"
#: option.c:2378
#, fuzzy
msgid "inconsistent DHCPv6 range"
msgstr "inkonsistenter DHCP-Bereich"
msgstr "Inkonsistenter DHCPv6-Bereich"
#: option.c:2481 option.c:2521
#: option.c:2481
#: option.c:2521
msgid "bad hex constant"
msgstr ""
msgstr "Falscher Hexwert"
#: option.c:2503
msgid "cannot match tags in --dhcp-host"
msgstr ""
msgstr "Kann die Tags in --dhcp-host nicht abgleichen"
#: option.c:2583
msgid "bad DHCP host name"
@@ -749,7 +748,8 @@ msgstr "unzulässiger DHCP-Hostname"
msgid "bad tag-if"
msgstr "unzulässige bedingte Marke (tag-if)"
#: option.c:2973 option.c:3258
#: option.c:2973
#: option.c:3258
msgid "invalid port number"
msgstr "unzulässige Portnummer"
@@ -826,19 +826,21 @@ msgstr "Fehler"
msgid "%s at line %d of %%s"
msgstr "%s in Zeile %d von %%s"
#: option.c:3491 tftp.c:627
#: option.c:3491
#: tftp.c:627
#, c-format
msgid "cannot read %s: %s"
msgstr "kann %s nicht lesen: %s"
#: option.c:3657 option.c:3693
#: option.c:3657
#: option.c:3693
#, c-format
msgid "read %s"
msgstr "%s gelesen"
#: option.c:3745
msgid "junk found in command line"
msgstr ""
msgstr "Mist in der Kommandozeile gefunden"
#: option.c:3780
#, c-format
@@ -846,12 +848,12 @@ msgid "Dnsmasq version %s %s\n"
msgstr "Dnsmasq Version %s %s\n"
#: option.c:3781
#, fuzzy, c-format
#, c-format
msgid ""
"Compile time options: %s\n"
"\n"
msgstr ""
"Übersetzungs-Optionen %s\n"
"Kompilierungs-Optionen %s\n"
"\n"
#: option.c:3782
@@ -863,12 +865,12 @@ msgstr "Für diese Software wird ABSOLUT KEINE GARANTIE gewährt.\n"
#: option.c:3783
#, c-format
msgid "Dnsmasq is free software, and you are welcome to redistribute it\n"
msgstr ""
msgstr "Dnsmasq ist freie Software, und du bist willkommen es weiter zu verteilen\n"
#: option.c:3784
#, c-format
msgid "under the terms of the GNU General Public License, version 2 or 3.\n"
msgstr ""
msgstr "unter den Bedingungen der GNU General Public Lizenz, Version 2 oder 3.\n"
#: option.c:3795
msgid "try --help"
@@ -896,7 +898,9 @@ msgstr "mit -n/--no-poll ist nur eine resolv.conf-Datei zulässig."
msgid "must have exactly one resolv.conf to read domain from."
msgstr "Um die Domäne zu lesen, muss genau eine resolv.conf-Datei verwendet werden."
#: option.c:3882 network.c:822 dhcp.c:804
#: option.c:3882
#: network.c:822
#: dhcp.c:804
#, c-format
msgid "failed to read %s: %s"
msgstr "konnte %s nicht lesen: %s"
@@ -907,18 +911,17 @@ msgid "no search directive found in %s"
msgstr "keine \"search\"-Anweisung in %s gefunden"
#: option.c:3920
#, fuzzy
msgid "there must be a default domain when --dhcp-fqdn is set"
msgstr "für --dhcp-fqdn muss eine Domäne vorausgewählt werden"
msgstr "Es muss eine standard Domain gesetzt sein, wenn --dhcp-fqdn gesetzt ist"
#: option.c:3924
msgid "syntax check OK"
msgstr "Syntaxprüfung OK"
#: forward.c:113
#, fuzzy, c-format
#, c-format
msgid "failed to send packet: %s"
msgstr "konnte Socket nicht zum Empfang einrichten: %s"
msgstr "Fehlgeschlagen, folgendes Paket zu senden: %s"
#: forward.c:474
#, c-format
@@ -931,9 +934,9 @@ msgid "possible DNS-rebind attack detected: %s"
msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s"
#: network.c:355
#, fuzzy, c-format
#, c-format
msgid "failed to create listening socket for %s: %s"
msgstr "Konnte Empfangs-Socket nicht erzeugen: %s"
msgstr "Konnte Empfangs-Socket für %s: %s nicht erzeugen"
#: network.c:720
#, c-format
@@ -953,44 +956,44 @@ msgstr "ignoriere Namensserver %s - kann Socket nicht erzeugen/binden: %s"
# FIXME: this isn't translatable - always provide full strings, do not assemble yourself! -- MA
#: network.c:785
msgid "unqualified"
msgstr ""
msgstr "unqualifiziert"
#: network.c:785
msgid "names"
msgstr ""
msgstr "Namen"
#: network.c:787
msgid "default"
msgstr ""
msgstr "Standard"
#: network.c:789
msgid "domain"
msgstr ""
msgstr "Domain"
#: network.c:792
#, c-format
msgid "using local addresses only for %s %s"
msgstr ""
msgstr "Benutze lokale Adressen nur für %s %s"
#: network.c:794
#, c-format
msgid "using standard nameservers for %s %s"
msgstr ""
msgstr "Benutze standard Namensserver für %s %s"
#: network.c:796
#, c-format
msgid "using nameserver %s#%d for %s %s"
msgstr ""
msgstr "Benutze Namensserver %s#%d für %s %s"
#: network.c:799
#, c-format
msgid "using nameserver %s#%d(via %s)"
msgstr ""
msgstr "Benutze Namensserver %s#%d(via %s)"
#: network.c:801
#, c-format
msgid "using nameserver %s#%d"
msgstr ""
msgstr "Benutze Namensserver %s#%d"
#: dnsmasq.c:123
msgid "TFTP server not available: set HAVE_TFTP in src/config.h"
@@ -998,21 +1001,19 @@ msgstr "TFTP-Server nicht verfügbar, setzen Sie HAVE_TFTP in src/config.h"
#: dnsmasq.c:128
msgid "Cannot use --conntrack AND --query-port"
msgstr ""
msgstr "Kann nicht --conntrack UND --query-port einsetzen"
#: dnsmasq.c:131
#, fuzzy
msgid "Conntrack support not available: set HAVE_CONNTRACK in src/config.h"
msgstr "TFTP-Server nicht verfügbar, setzen Sie HAVE_TFTP in src/config.h"
msgstr "Conntrack-Unterstützung nicht verfügbar: setze HAVE_CONNTRACK in src/config.h"
#: dnsmasq.c:136
msgid "asychronous logging is not available under Solaris"
msgstr "asynchrone Protokollierung unter Solaris nicht verfügbar"
#: dnsmasq.c:141
#, fuzzy
msgid "asychronous logging is not available under Android"
msgstr "asynchrone Protokollierung unter Solaris nicht verfügbar"
msgstr "Asynchrone Protokollierung unter Android nicht verfügbar"
#: dnsmasq.c:190
#, c-format
@@ -1029,7 +1030,8 @@ msgstr "unbekannte Schnittstelle %s"
msgid "no interface with address %s"
msgstr "keine Schnittstelle mit Adresse %s"
#: dnsmasq.c:220 dnsmasq.c:770
#: dnsmasq.c:220
#: dnsmasq.c:770
#, c-format
msgid "DBus error: %s"
msgstr "DBus-Fehler: %s"
@@ -1062,7 +1064,7 @@ msgstr "gestartet, Version %s, Cachegröße %d"
#: dnsmasq.c:485
#, c-format
msgid "started, version %s cache disabled"
msgstr ""
msgstr "Gestartet, Version %s Cache deaktiviert"
#: dnsmasq.c:487
#, c-format
@@ -1106,7 +1108,7 @@ msgstr "asynchrone Protokollierung eingeschaltet, Warteschlange fasst %d Nachric
#: dnsmasq.c:524
msgid "IPv6 router advertisement enabled"
msgstr ""
msgstr "IPv6-Router-Advertisement aktiviert"
#: dnsmasq.c:554
#, c-format
@@ -1114,9 +1116,9 @@ msgid "DHCP, static leases only on %.0s%s, lease time %s"
msgstr "DHCP, nur statische Leases auf %.0s%s, Lease-Zeit %s"
#: dnsmasq.c:556
#, fuzzy, c-format
#, c-format
msgid "router advertisement only on %.0s%s, lifetime %s"
msgstr "DHCP, nur statische Leases auf %.0s%s, Lease-Zeit %s"
msgstr "Router-Advertisment nur auf %.0s%s, Lebenszeit %s"
#: dnsmasq.c:558
#, c-format
@@ -1128,17 +1130,18 @@ msgstr "DHCP, Proxy im Subnetz %.0s%s%.0s"
msgid "DHCP, IP range %s -- %s, lease time %s"
msgstr "DHCP, IP-Bereich %s - %s, Lease-Zeit %s "
# FIXME: this and the next few must be full strings to be translatable - do not assemble in code"
#: dnsmasq.c:588
msgid "root is "
msgstr "FIXME: this and the next few must be full strings to be translatable - do not assemble in code"
msgstr "Wurzel ist"
#: dnsmasq.c:588
msgid "enabled"
msgstr ""
msgstr "Aktiviert"
#: dnsmasq.c:590
msgid "secure mode"
msgstr ""
msgstr "sicherer Modus"
#: dnsmasq.c:616
#, c-format
@@ -1180,24 +1183,24 @@ msgid "failed to open pidfile %s: %s"
msgstr "kann die Prozessidentifikations-(PID)-Datei %s nicht öffnen: %s"
#: dnsmasq.c:930
#, fuzzy, c-format
#, c-format
msgid "cannot open log %s: %s"
msgstr "kann %s nicht öffnen: %s"
msgstr "Kann Logdatei %s nicht öffnen: %s"
#: dnsmasq.c:933
#, fuzzy, c-format
#, c-format
msgid "failed to load Lua script: %s"
msgstr "konnte %s nicht lesen: %s"
msgstr "Konnte Lua-Script nicht laden: %s"
#: dnsmasq.c:1002
#, fuzzy, c-format
#, c-format
msgid "script process killed by signal %d"
msgstr "Tochterprozess durch Signal %d zerstört"
msgstr "Scriptprozess durch Signal %d getötet"
#: dnsmasq.c:1006
#, fuzzy, c-format
#, c-format
msgid "script process exited with status %d"
msgstr "Tochterprozess beendete sich mit Status %d"
msgstr "Scriptprozess hat sich mit Status %d beendet"
#: dnsmasq.c:1010
#, c-format
@@ -1308,22 +1311,23 @@ msgstr "Ignoriere Domäne %s für DHCP-Hostnamen %s"
#: rfc2131.c:337
#, c-format
msgid "no address range available for DHCP request %s %s"
msgstr ""
msgstr "Kein verfügbarer DHCP-Bereich für Anfrage %s %s"
#: rfc2131.c:338
msgid "with subnet selector"
msgstr ""
msgstr "mit Subnetz-Wähler"
#: rfc2131.c:338
msgid "via"
msgstr ""
msgstr "via"
#: rfc2131.c:350
#, c-format
msgid "%u available DHCP subnet: %s/%s"
msgstr "%u verfügbare(s) DHCP-Subnetz: %s/%s"
#: rfc2131.c:353 rfc3315.c:209
#: rfc2131.c:353
#: rfc3315.c:209
#, c-format
msgid "%u available DHCP range: %s -- %s"
msgstr "%u verfügbare(r) DHCP-Bereich: %s - %s"
@@ -1331,33 +1335,40 @@ msgstr "%u verfügbare(r) DHCP-Bereich: %s - %s"
# FIXME: do not programmatically assemble strings - untranslatable
#: rfc2131.c:382
msgid "disabled"
msgstr ""
msgstr "deaktiviert"
#: rfc2131.c:423 rfc2131.c:941 rfc2131.c:1341
#: rfc2131.c:423
#: rfc2131.c:941
#: rfc2131.c:1341
msgid "ignored"
msgstr ""
msgstr "ignoriert"
#: rfc2131.c:438 rfc2131.c:1179
#: rfc2131.c:438
#: rfc2131.c:1179
msgid "address in use"
msgstr ""
msgstr "Adresse in Nutzung"
#: rfc2131.c:452 rfc2131.c:995
#: rfc2131.c:452
#: rfc2131.c:995
msgid "no address available"
msgstr ""
msgstr "Keine Adresse verfügbar"
#: rfc2131.c:459 rfc2131.c:1142
#: rfc2131.c:459
#: rfc2131.c:1142
msgid "wrong network"
msgstr ""
msgstr "Falsches Netzwerk"
#: rfc2131.c:474
msgid "no address configured"
msgstr ""
msgstr "Keine Adresse konfiguriert"
#: rfc2131.c:480 rfc2131.c:1192
#: rfc2131.c:480
#: rfc2131.c:1192
msgid "no leases left"
msgstr ""
msgstr "Keine Leases übrig"
#: rfc2131.c:564 rfc3315.c:362
#: rfc2131.c:564
#: rfc3315.c:362
#, c-format
msgid "%u client provides name: %s"
msgstr "%u Klient stellt Name bereit: %s"
@@ -1376,7 +1387,8 @@ msgstr "%u Benutzerklasse: %s"
msgid "PXE BIS not supported"
msgstr "PXE BIS nicht unterstützt"
#: rfc2131.c:911 rfc3315.c:1098
#: rfc2131.c:911
#: rfc3315.c:1098
#, c-format
msgid "disabling DHCP static address %s for %s"
msgstr "schalte statische DHCP-Adresse %s für %s ab"
@@ -1384,9 +1396,10 @@ msgstr "schalte statische DHCP-Adresse %s für %s ab"
# FIXME: do not assemble
#: rfc2131.c:932
msgid "unknown lease"
msgstr ""
msgstr "Unbekannter Lease"
#: rfc2131.c:964 rfc3315.c:556
#: rfc2131.c:964
#: rfc3315.c:556
#, c-format
msgid "not using configured address %s because it is leased to %s"
msgstr "benutze konfigurierte Adresse %s nicht, weil sie an %s verleast ist"
@@ -1396,39 +1409,41 @@ msgstr "benutze konfigurierte Adresse %s nicht, weil sie an %s verleast ist"
msgid "not using configured address %s because it is in use by the server or relay"
msgstr "benutze konfigurierte Adresse %s nicht, weil sie von Server/Relais verwendet wird"
#: rfc2131.c:977 rfc3315.c:560
#: rfc2131.c:977
#: rfc3315.c:560
#, c-format
msgid "not using configured address %s because it was previously declined"
msgstr "benutze konfigurierte Adresse %s nicht, weil sie zuvor abgelehnt wurde"
# FIXME: do not assemble
#: rfc2131.c:993 rfc2131.c:1185
#: rfc2131.c:993
#: rfc2131.c:1185
msgid "no unique-id"
msgstr ""
msgstr "Keine eindeutige ID"
#: rfc2131.c:1080
msgid "wrong server-ID"
msgstr ""
msgstr "Falsche Server-ID"
#: rfc2131.c:1099
msgid "wrong address"
msgstr ""
msgstr "Falsche Adresse"
#: rfc2131.c:1117
msgid "lease not found"
msgstr ""
msgstr "Lease nicht gefunden"
#: rfc2131.c:1150
msgid "address not available"
msgstr ""
msgstr "Adresse nicht verfügbar"
#: rfc2131.c:1161
msgid "static lease available"
msgstr ""
msgstr "Statischer Lease verfügbar"
#: rfc2131.c:1165
msgid "address reserved"
msgstr ""
msgstr "Adresse reserviert"
#: rfc2131.c:1173
#, c-format
@@ -1464,7 +1479,8 @@ msgstr "kann DHCP/BOOTP-Opition %d nicht setzen: kein Platz mehr im Paket"
msgid "PXE menu too large"
msgstr "PXE-Menüeintrag zu groß"
#: rfc2131.c:2117 rfc3315.c:1294
#: rfc2131.c:2117
#: rfc3315.c:1294
#, c-format
msgid "%u requested options: %s"
msgstr "%u angeforderte Optionen: %s"
@@ -1508,7 +1524,7 @@ msgstr "DHCP-Anfrage für nicht unterstützen Hardwaretyp (%d) auf %s empfangen"
#: helper.c:140
msgid "lease() function missing in Lua script"
msgstr ""
msgstr "Die Funktion lease() fehlt im Lua-Script"
#: tftp.c:285
msgid "unable to get free port for TFTP"
@@ -1556,37 +1572,37 @@ msgstr "Start fehlgeschlagen"
#: conntrack.c:65
#, c-format
msgid "Conntrack connection mark retrieval failed: %s"
msgstr ""
msgstr "\"Conntrack connection mark\"-Abruf fehlgeschlagen: %s"
#: dhcp6.c:46
#, fuzzy, c-format
#, c-format
msgid "cannot create DHCPv6 socket: %s"
msgstr "kann DHCP-Socket nicht erzeugen: %s"
msgstr "Kann DHCPv6-Socket nicht erzeugen: %s"
#: dhcp6.c:57
#, fuzzy, c-format
#, c-format
msgid "failed to bind DHCPv6 server socket: %s"
msgstr "kann nicht an DHCP-Server-Socket binden: %s"
msgstr "Kann nicht an DHCPv6-Server-Socket binden: %s"
#: rfc3315.c:94
#, c-format
msgid "no address range available for DHCPv6 request from relay at %s"
msgstr ""
msgstr "Kein Adressbereich verfügbar für die DHCPv6-Anfrage vom Relay bei %s"
#: rfc3315.c:103
#, c-format
msgid "no address range available for DHCPv6 request via %s"
msgstr ""
msgstr "Kein Adressbereich verfügbar für die DHCPv6-Anfrage via %s"
#: rfc3315.c:206
#, fuzzy, c-format
#, c-format
msgid "%u available DHCPv6 subnet: %s/%d"
msgstr "%u verfügbare(s) DHCP-Subnetz: %s/%s"
msgstr "%u verfügbare(s) DHCPv6-Subnetz: %s/%d"
#: dhcp-common.c:138
#, c-format
msgid "Ignoring duplicate dhcp-option %d"
msgstr ""
msgstr "Ignoriere doppelt vorhandene DHCP-Option %d"
#: dhcp-common.c:208
#, c-format
@@ -1614,14 +1630,14 @@ msgid "duplicate IP address %s (%s) in dhcp-config directive"
msgstr "doppelte IP-Adresse %s (%s) in \"dhcp-config\"-Anweisung"
#: dhcp-common.c:443
#, fuzzy, c-format
#, c-format
msgid "failed to join DHCPv6 multicast group: %s"
msgstr "kann nicht an DHCP-Server-Socket binden: %s"
msgstr "Konnte DHCPv6-Multicast-Gruppe nicht beitreten: %s"
#: radv.c:76
#, fuzzy, c-format
#, c-format
msgid "cannot create ICMPv6 socket: %s"
msgstr "kann DHCP-Socket nicht erzeugen: %s"
msgstr "Kann ICMPv6-Socket nicht erzeugen: %s"
#, fuzzy
#~ msgid "Specify path to Lua script (no default)."

View File

@@ -20,6 +20,7 @@
#include <ifaddrs.h>
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <net/route.h>
#include <net/if_dl.h>

View File

@@ -25,6 +25,9 @@ static int cache_inserted = 0, cache_live_freed = 0, insert_error;
static union bigname *big_free = NULL;
static int bignames_left, hash_size;
static int uid = 0;
#ifdef HAVE_DNSSEC
static struct keydata *keyblock_free = NULL;
#endif
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
static const struct {
@@ -190,6 +193,10 @@ static void cache_free(struct crec *crecp)
big_free = crecp->name.bname;
crecp->flags &= ~F_BIGNAME;
}
#ifdef HAVE_DNSSEC
else if (crecp->flags & (F_DNSKEY | F_DS))
keydata_free(crecp->addr.key.keydata);
#endif
}
/* insert a new cache entry at the head of the list (youngest entry) */
@@ -233,7 +240,11 @@ static int is_outdated_cname_pointer(struct crec *crecp)
if (!(crecp->flags & F_CNAME))
return 0;
if (crecp->addr.cname.cache && crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
/* NB. record may be reused as DS or DNSKEY, where uid is
overloaded for something completely different */
if (crecp->addr.cname.cache &&
(crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
return 0;
return 1;
@@ -280,7 +291,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
}
}
else if ((crecp->flags & F_FORWARD) &&
((flags & crecp->flags & (F_IPV4 | F_IPV6)) || ((crecp->flags | flags) & F_CNAME)) &&
((flags & crecp->flags & F_TYPE) || ((crecp->flags | flags) & F_CNAME)) &&
hostname_isequal(cache_get_name(crecp), name))
{
if (crecp->flags & (F_HOSTS | F_DHCP))
@@ -360,7 +371,12 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
int freed_all = flags & F_REVERSE;
int free_avail = 0;
log_query(flags | F_UPSTREAM, name, addr, NULL);
if(daemon->max_cache_ttl < ttl)
ttl = daemon->max_cache_ttl;
/* Don't log keys */
if (flags & (F_IPV4 | F_IPV6))
log_query(flags | F_UPSTREAM, name, addr, NULL);
/* if previous insertion failed give up now. */
if (insert_error)
@@ -452,9 +468,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
if (addr)
new->addr.addr = *addr;
else
new->addr.cname.cache = NULL;
new->ttd = now + (time_t)ttl;
new->next = new_chain;
new_chain = new;
@@ -634,13 +648,29 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
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,
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));
int i, nameexists = 0;
struct cname *a;
unsigned int j;
/* Remove duplicates in hosts files. */
@@ -691,16 +721,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. */
if (!nameexists)
for (a = daemon->cnames; a; a = a->next)
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);
}
add_hosts_cname(cache);
}
static int eatspace(FILE *f)
@@ -992,13 +1013,41 @@ void cache_unhash_dhcp(void)
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,
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;
int in_hosts = 0;
struct cname *a;
size_t addrlen = sizeof(struct in_addr);
#ifdef HAVE_IPV6
@@ -1009,29 +1058,21 @@ void cache_add_dhcp_entry(char *host_name, int prot,
}
#endif
inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
{
/* check all addresses associated with name */
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)
my_syslog(MS_DHCP | LOG_WARNING,
_("%s is a CNAME, not giving it to the DHCP lease of %s"),
host_name, daemon->addrbuff);
else if (memcmp(&crec->addr.addr, host_address, addrlen) != 0)
{
inet_ntop(prot, &crec->addr.addr, daemon->namebuff, MAXDNAME);
my_syslog(MS_DHCP | LOG_WARNING,
_("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 (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
in_hosts = 1;
else
fail_crec = crec;
}
else if (!(crec->flags & F_DHCP))
{
@@ -1041,21 +1082,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;
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))
/* Name in hosts, address doesn't match */
if (fail_crec)
{
inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
my_syslog(MS_DHCP | LOG_WARNING,
_("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(fail_crec->uid), daemon->namebuff);
return;
}
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;
else /* need new one */
crec = whine_malloc(sizeof(struct crec));
@@ -1072,27 +1126,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
crec->uid = uid++;
cache_hash(crec);
for (a = daemon->cnames; a; a = a->next)
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);
}
}
add_dhcp_cname(crec, ttd);
}
}
#endif
@@ -1150,22 +1184,35 @@ void dump_cache(time_t now)
if (!is_outdated_cname_pointer(cache))
a = cache_get_name(cache->addr.cname.cache);
}
#ifdef HAVE_IPV6
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DNSKEY)
{
a = daemon->addrbuff;
sprintf(a, "%3u %u", cache->addr.key.algo, cache->uid);
}
else if (cache->flags & F_DS)
{
a = daemon->addrbuff;
sprintf(a, "%5u %3u %3u %u", cache->addr.key.flags_or_keyid,
cache->addr.key.algo, cache->addr.key.digest, cache->uid);
}
#endif
else
{
a = daemon->addrbuff;
if (cache->flags & F_IPV4)
inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
#ifdef HAVE_IPV6
else if (cache->flags & F_IPV6)
inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
}
#else
else
a = inet_ntoa(cache->addr.addr.addr.addr4);
#endif
p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a,
}
p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s%s%s%s%s ", a,
cache->flags & F_IPV4 ? "4" : "",
cache->flags & F_IPV6 ? "6" : "",
cache->flags & F_DNSKEY ? "K" : "",
cache->flags & F_DS ? "S" : "",
cache->flags & F_CNAME ? "C" : "",
cache->flags & F_FORWARD ? "F" : " ",
cache->flags & F_REVERSE ? "R" : " ",
@@ -1173,7 +1220,8 @@ void dump_cache(time_t now)
cache->flags & F_DHCP ? "D" : " ",
cache->flags & F_NEG ? "N" : " ",
cache->flags & F_NXDOMAIN ? "X" : " ",
cache->flags & F_HOSTS ? "H" : " ");
cache->flags & F_HOSTS ? "H" : " ",
cache->flags & F_DNSSECOK ? "V" : " ");
#ifdef HAVE_BROKEN_RTC
p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
#else
@@ -1287,3 +1335,50 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
}
#ifdef HAVE_DNSSEC
struct keydata *keydata_alloc(char *data, size_t len)
{
struct keydata *block, *ret = NULL;
struct keydata **prev = &ret;
while (len > 0)
{
if (keyblock_free)
{
block = keyblock_free;
keyblock_free = block->next;
}
else
block = whine_malloc(sizeof(struct keydata));
if (!block)
{
/* failed to alloc, free partial chain */
keydata_free(ret);
return NULL;
}
memcpy(block->key, data, len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len);
data += KEYBLOCK_LEN;
len -= KEYBLOCK_LEN;
*prev = block;
prev = &block->next;
block->next = NULL;
}
return ret;
}
void keydata_free(struct keydata *blocks)
{
struct keydata *tmp;
if (blocks)
{
for (tmp = blocks; tmp->next; tmp = tmp->next);
tmp->next = keyblock_free;
keyblock_free = blocks;
}
}
#endif

View File

@@ -18,6 +18,7 @@
#define MAX_PROCS 20 /* max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
#define KEYBLOCK_LEN 140 /* choose to mininise fragmentation when storing DNSSEC keys */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define FORWARD_TEST 50 /* try all servers every 50 queries */
#define FORWARD_TIME 20 /* or 20 seconds */
@@ -32,7 +33,6 @@
#define SMALLDNAME 40 /* most domain names are smaller than this */
#define HOSTSFILE "/etc/hosts"
#define ETHERSFILE "/etc/ethers"
#define RUNFILE "/var/run/dnsmasq.pid"
#define DEFLEASE 3600 /* default lease time, 1 hour */
#define CHUSER "nobody"
#define CHGRP "dip"
@@ -40,7 +40,7 @@
#define LOG_MAX 5 /* log-queue length */
#define RANDFILE "/dev/urandom"
#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"
/* compile-time options: uncomment below to enable or do eg.
@@ -157,7 +157,13 @@ RESOLVFILE
# 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
@@ -167,7 +173,7 @@ HAVE_SOLARIS_NETWORK
define exactly one of these to alter interaction with kernel networking.
HAVE_GETOPT_LONG
defined when GNU-sty;e getopt_long available.
defined when GNU-style getopt_long available.
HAVE_ARC4RANDOM
defined if arc4random() available to get better security from DNS spoofs

View File

@@ -20,7 +20,7 @@
#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"
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
"<node name=\"" DNSMASQ_PATH "\">\n"
@@ -29,7 +29,7 @@ const char* introspection_xml =
" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
" </method>\n"
" </interface>\n"
" <interface name=\"" DNSMASQ_SERVICE "\">\n"
" <interface name=\"%s\">\n"
" <method name=\"ClearCache\">\n"
" </method>\n"
" <method name=\"GetVersion\">\n"
@@ -38,6 +38,12 @@ const char* introspection_xml =
" <method name=\"SetServers\">\n"
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\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"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"hwaddr\" type=\"s\"/>\n"
@@ -56,6 +62,8 @@ const char* introspection_xml =
" </interface>\n"
"</node>\n";
static char *introspection_xml = NULL;
struct watch {
DBusWatch *watch;
struct watch *next;
@@ -97,20 +105,118 @@ static void remove_watch(DBusWatch *watch, void *data)
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;
/* 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;
union mysockaddr addr, source_addr;
char *domain;
dbus_message_iter_init(message, &iter);
/* mark everything from DBUS */
for (serv = daemon->servers; serv; serv = serv->next)
if (serv->flags & SERV_FROM_DBUS)
serv->flags |= SERV_MARK;
mark_dbus();
while (1)
{
int skip = 0;
@@ -169,6 +275,7 @@ static void dbus_read_servers(DBusMessage *message)
/* At the end */
break;
/* process each domain */
do {
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
{
@@ -179,83 +286,183 @@ static void dbus_read_servers(DBusMessage *message)
domain = NULL;
if (!skip)
{
/* See if this is already there, and unmark */
for (serv = daemon->servers; serv; serv = serv->next)
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);
add_update_server(&addr, &source_addr, NULL, domain);
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
}
/* 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;
if (serv->flags & SERV_MARK)
{
server_gone(serv);
*up = serv->next;
free(serv);
}
else
up = &serv->next;
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
}
/* 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,
@@ -263,23 +470,27 @@ DBusHandlerResult message_handler(DBusConnection *connection,
void *user_data)
{
char *method = (char *)dbus_message_get_member(message);
DBusMessage *reply = NULL;
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
{
DBusMessage *reply = dbus_message_new_method_return(message);
dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
dbus_connection_send (connection, reply, NULL);
dbus_message_unref (reply);
/* string length: "%s" provides space for termination zero */
if (!introspection_xml &&
(introspection_xml = whine_malloc(strlen(introspection_xml_template) + strlen(daemon->dbus_name))))
sprintf(introspection_xml, introspection_xml_template, daemon->dbus_name);
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)
{
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_connection_send (connection, reply, NULL);
dbus_message_unref (reply);
}
else if (strcmp(method, "SetServers") == 0)
{
@@ -287,6 +498,16 @@ DBusHandlerResult message_handler(DBusConnection *connection,
dbus_read_servers(message);
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)
clear_cache_and_reload(dnsmasq_time());
else
@@ -294,8 +515,17 @@ DBusHandlerResult message_handler(DBusConnection *connection,
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);
}
@@ -315,7 +545,7 @@ char *dbus_init(void)
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
NULL, NULL, NULL);
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))
return (char *)dbus_error.message;
@@ -325,7 +555,7 @@ char *dbus_init(void)
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_message_unref(message);
@@ -430,7 +660,7 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
else
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;
dbus_message_iter_init_append(message, &args);

View File

@@ -111,6 +111,13 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
last_tag->next = tags;
tagif = run_tag_if(context_tags);
/* reset stuff with tag:!<tag> which now matches. */
for (opt = opts; opt; opt = opt->next)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
(opt->flags & DHOPT_TAGOK) &&
!match_netid(opt->netid, tagif, 0))
opt->flags &= ~DHOPT_TAGOK;
for (opt = opts; opt; opt = opt->next)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) &&
match_netid(opt->netid, tagif, 0))
@@ -239,40 +246,6 @@ int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
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)
{
/* Some people like to keep all static IP addresses in /etc/hosts.
@@ -282,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,
restore the status-quo ante first. */
struct dhcp_config *config;
struct dhcp_config *config, *conf_tmp;
struct crec *crec;
int prot = AF_INET;
@@ -324,7 +297,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
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->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
@@ -332,7 +306,8 @@ void dhcp_update_configs(struct dhcp_config *configs)
}
#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);
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
@@ -365,7 +340,6 @@ static int join_multicast_worker(struct in6_addr *local, int prefix,
char ifrn_name[IFNAMSIZ];
struct ipv6_mreq mreq;
int fd, i, max = *((int *)vparam);
struct dhcp_context *context;
struct iname *tmp;
(void)prefix;
@@ -399,14 +373,6 @@ static int join_multicast_worker(struct in6_addr *local, int prefix,
if (tmp->name && (strcmp(tmp->name, ifrn_name) == 0))
return 1;
/* weird libvirt-inspired access control */
for (context = 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);
@@ -444,6 +410,41 @@ void join_multicast(void)
}
#endif
#ifdef HAVE_LINUX_NETWORK
void bindtodevice(int fd)
{
/* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
to that device. This is for the use case of (eg) OpenStack, which runs a new
dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE,
individual processes don't always see the packets they should.
SO_BINDTODEVICE is only available Linux. */
struct irec *iface, *found;
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
if (iface->dhcp_ok)
{
if (!found)
found = iface;
else if (strcmp(found->name, iface->name) != 0)
{
/* more than one. */
found = NULL;
break;
}
}
if (found)
{
struct ifreq ifr;
strcpy(ifr.ifr_name, found->name);
/* only allowed by root. */
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
errno != EPERM)
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
}
}
#endif
static const struct opttab_t {
char *name;
@@ -488,15 +489,15 @@ static const struct opttab_t {
{ "x-windows-fs", 48, OT_ADDR_LIST },
{ "x-windows-dm", 49, 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 },
{ "message-type", 53, OT_INTERNAL | OT_DEC },
{ "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
{ "parameter-request", 55, OT_INTERNAL },
{ "message", 56, OT_INTERNAL },
{ "max-message-size", 57, OT_INTERNAL },
{ "T1", 58, OT_INTERNAL | OT_DEC},
{ "T2", 59, OT_INTERNAL | OT_DEC},
{ "T1", 58, OT_INTERNAL | OT_TIME},
{ "T2", 59, OT_INTERNAL | OT_TIME},
{ "vendor-class", 60, 0 },
{ "client-id", 61, OT_INTERNAL },
{ "nis+-domain", 64, OT_NAME },
@@ -547,6 +548,7 @@ static const struct opttab_t opttab6[] = {
{ "nis-domain", 29, OT_RFC1035_NAME },
{ "nis+-domain", 30, OT_RFC1035_NAME },
{ "sntp-server", 31, OT_ADDR_LIST },
{ "information-refresh-time", 32, OT_TIME },
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
{ "ntp-server", 56, OT_ADDR_LIST },
{ "bootfile-url", 59, OT_NAME },
@@ -711,14 +713,17 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
}
}
#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;
for (i = 0; i < opt_len; 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
nodecode = 1;

View File

@@ -66,7 +66,7 @@ static int make_fd(int port)
/* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 67. 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))
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
{
#ifdef SO_REUSEPORT
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
@@ -116,9 +116,7 @@ void dhcp_init(void)
/* Make BPF raw send socket */
init_bpf();
#endif
check_dhcp_hosts(1);
#endif
}
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))
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 */
for (context = daemon->dhcp; context; context = context->next)
context->current = context;
@@ -277,7 +267,7 @@ void dhcp_packet(time_t now, int pxe_fd)
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
for a secondary */
struct match_param match;
match.matched = 0;
match.ind = iface_index;

View File

@@ -54,6 +54,7 @@
#define OPTION6_RECONFIGURE_MSG 19
#define OPTION6_RECONF_ACCEPT 20
#define OPTION6_DNS_SERVER 23
#define OPTION6_DOMAIN_SEARCH 24
#define OPTION6_REMOTE_ID 37
#define OPTION6_SUBSCRIBER_ID 38
#define OPTION6_FQDN 39

View File

@@ -21,7 +21,7 @@
struct iface_param {
struct dhcp_context *current;
struct in6_addr fallback;
int ind;
int ind, addr_match;
};
static int complete_context6(struct in6_addr *local, int prefix,
@@ -33,18 +33,34 @@ void dhcp6_init(void)
{
int fd;
struct sockaddr_in6 saddr;
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
int class = IPTOS_CLASS_CS6;
#endif
int oneopt = 1;
if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 ||
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
#endif
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &oneopt, sizeof(oneopt)) == -1 ||
!fix_fd(fd) ||
!set_ipv6pktinfo(fd))
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));
#ifdef HAVE_SOCKADDR_SA_LEN
saddr.sin6_len = sizeof(struct sockaddr_in6);
@@ -71,7 +87,6 @@ void dhcp6_packet(time_t now)
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
} control_u;
struct sockaddr_in6 from;
struct all_addr dest;
ssize_t sz;
struct ifreq ifr;
struct iname *tmp;
@@ -98,41 +113,52 @@ void dhcp6_packet(time_t now)
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi6_ifindex;
dest.addr.addr6 = p.p->ipi6_addr;
}
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
return;
if (!iface_check(AF_INET6, (struct all_addr *)&dest, ifr.ifr_name))
return;
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
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.ind = if_index;
parm.addr_match = 0;
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))
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 */
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
@@ -159,15 +185,23 @@ static int complete_context6(struct in6_addr *local, int prefix,
{
struct dhcp_context *context;
struct iface_param *param = vparam;
struct iname *tmp;
(void)scope; /* warning */
(void)dad;
if (if_index == param->ind &&
!IN6_IS_ADDR_LOOPBACK(local) &&
!IN6_IS_ADDR_LINKLOCAL(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
if we have no matching dhcp-context, because we're only
allocating on remote subnets via relays. This
@@ -229,7 +263,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current)
if (c->flags & (CONTEXT_STATIC | CONTEXT_RA_STATELESS))
if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS))
continue;
else if (!match_netid(c->filter, netids, pass))
continue;
@@ -282,9 +316,9 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
start = addr6part(&tmp->start6);
end = addr6part(&tmp->end6);
if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) &&
is_same_net6(&context->start6, taddr, context->prefix) &&
is_same_net6(&context->end6, taddr, context->prefix) &&
if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_RA_STATELESS)) &&
is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
is_same_net6(&tmp->end6, taddr, tmp->prefix) &&
addr >= start &&
addr <= end &&
match_netid(tmp->filter, netids, 1))
@@ -331,14 +365,21 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
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() */
return 1;
if (!(config->flags & CONFIG_ADDR6))
if (!(config->flags & CONFIG_ADDR6) || is_addr_in_context6(context, &config->addr6))
return 1;
return 0;
}
int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr)
{
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 0;
@@ -358,7 +399,7 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
{
if (config->clid_len == duid_len &&
memcmp(config->clid, duid, duid_len) == 0 &&
is_addr_in_context6(context, config))
is_config_in_context6(context, config))
return config;
}
@@ -366,7 +407,7 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_NAME) &&
hostname_isequal(config->hostname, hostname) &&
is_addr_in_context6(context, config))
is_config_in_context6(context, config))
return config;
return NULL;

View File

@@ -114,10 +114,18 @@ int main (int argc, char **argv)
set_option_bool(OPT_NOWILD);
}
# endif
/* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
if (option_bool(OPT_CLEVERBIND))
{
bind_fallback = 1;
set_option_bool(OPT_NOWILD);
reset_option_bool(OPT_CLEVERBIND);
}
#endif
#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);
#endif
@@ -185,6 +193,9 @@ int main (int argc, char **argv)
#ifdef HAVE_LINUX_NETWORK
/* After lease_init */
netlink_init();
if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
#endif
#ifdef HAVE_DHCP6
@@ -202,13 +213,29 @@ int main (int argc, char **argv)
if (!enumerate_interfaces())
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
if (option_bool(OPT_NOWILD))
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
{
create_bound_listeners(1);
if (!option_bool(OPT_CLEVERBIND))
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
/* after enumerate_interfaces() */
if (daemon->dhcp)
{
bindtodevice(daemon->dhcpfd);
if (daemon->enable_pxe)
bindtodevice(daemon->pxefd);
}
#endif
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
if (daemon->dhcp6)
bindtodevice(daemon->dhcp6fd);
#endif
}
else
create_wildcard_listeners();
@@ -356,15 +383,48 @@ int main (int argc, char **argv)
/* write pidfile _after_ forking ! */
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 ((pidfile = fopen(daemon->runfile, "w")))
if ((fd = open(daemon->runfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1)
{
fprintf(pidfile, "%d\n", (int) getpid());
fclose(pidfile);
/* only complain if started as root */
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);
_exit(0);
@@ -410,8 +470,9 @@ int main (int argc, char **argv)
#if defined(HAVE_LINUX_NETWORK)
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
ports because of DAD, we need CAP_NET_BIND_SERVICE too. */
if (is_dad_listeners())
ports because of DAD, or we're doing it dynamically,
we need CAP_NET_BIND_SERVICE too. */
if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
data->effective = data->permitted = data->inheritable =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
(1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
@@ -459,7 +520,7 @@ int main (int argc, char **argv)
}
#ifdef HAVE_LINUX_NETWORK
if (is_dad_listeners())
if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
data->effective = data->permitted =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
else
@@ -483,6 +544,34 @@ int main (int argc, char **argv)
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif
#ifdef HAVE_TFTP
if (option_bool(OPT_TFTP))
{
DIR *dir;
struct tftp_prefix *p;
if (daemon->tftp_prefix)
{
if (!((dir = opendir(daemon->tftp_prefix))))
{
send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
_exit(0);
}
closedir(dir);
}
for (p = daemon->if_prefix; p; p = p->next)
{
if (!((dir = opendir(p->prefix))))
{
send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
_exit(0);
}
closedir(dir);
}
}
#endif
if (daemon->port == 0)
my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
else if (daemon->cachesize != 0)
@@ -530,7 +619,7 @@ int main (int argc, char **argv)
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
#ifdef HAVE_DHCP
if (daemon->dhcp || daemon->dhcp6)
if (daemon->dhcp || daemon->dhcp6 || daemon->ra_contexts)
{
struct dhcp_context *dhcp_tmp;
int family = AF_INET;
@@ -543,7 +632,7 @@ int main (int argc, char **argv)
{
void *start = &dhcp_tmp->start;
void *end = &dhcp_tmp->end;
#ifdef HAVE_DHCP6
if (family == AF_INET6)
{
@@ -555,24 +644,43 @@ int main (int argc, char **argv)
}
#endif
prettyprint_time(daemon->namebuff, dhcp_tmp->lease_time);
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);
}
inet_ntop(family, start, daemon->dhcp_buff, 256);
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_STATIC) ?
_("DHCP, static leases only on %.0s%s, lease time %s") :
(dhcp_tmp->flags & CONTEXT_RA_STATELESS) ?
_("SLAAC and stateless DHCPv6 on %.0s%s%.0s") :
_("%s stateless on %s%.0s%.0s") :
(dhcp_tmp->flags & CONTEXT_STATIC) ?
_("%s, static leases only on %.0s%s, %s") :
(dhcp_tmp->flags & CONTEXT_PROXY) ?
_("DHCP, proxy on subnet %.0s%s%.0s") :
_("DHCP, IP range %s -- %s, lease time %s"),
_("%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);
if (dhcp_tmp->flags & CONTEXT_RA_NAME)
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC and DHCPv4-derived names on %s"), daemon->dhcp_buff2);
if (dhcp_tmp->flags & CONTEXT_RA_ONLY)
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC on %s"), daemon->dhcp_buff2);
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s"),
daemon->dhcp_buff2);
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->dhcp_buff2, daemon->namebuff);
}
}
#ifdef HAVE_DHCP6
@@ -592,7 +700,7 @@ int main (int argc, char **argv)
#ifdef HAVE_TFTP
if (daemon->tftp_unlimited || daemon->tftp_interfaces)
if (option_bool(OPT_TFTP))
{
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
@@ -814,14 +922,11 @@ int main (int argc, char **argv)
}
#ifdef HAVE_DHCP6
if (daemon->dhcp6)
{
if (FD_ISSET(daemon->dhcp6fd, &rset))
dhcp6_packet(now);
if (daemon->dhcp6 && FD_ISSET(daemon->dhcp6fd, &rset))
dhcp6_packet(now);
if (daemon->ra_contexts && FD_ISSET(daemon->icmp6fd, &rset))
icmp6_packet();
}
if (daemon->ra_contexts && FD_ISSET(daemon->icmp6fd, &rset))
icmp6_packet();
#endif
# ifdef HAVE_SCRIPT
@@ -963,6 +1068,9 @@ static void fatal_event(struct event_desc *ev, char *msg)
case EVENT_LUA_ERR:
die(_("failed to load Lua script: %s"), msg, EC_MISC);
case EVENT_TFTP_ERR:
die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
}
}
@@ -1167,20 +1275,15 @@ void clear_cache_and_reload(time_t now)
dhcp_read_ethers();
reread_dhcp();
dhcp_update_configs(daemon->dhcp_conf);
check_dhcp_hosts(0);
lease_update_from_configs();
lease_update_file(now);
lease_update_dns(1);
}
#ifdef HAVE_DHCP6
else if (daemon->ra_contexts)
{
/* Not doing DHCP, so no lease system, manage
alarms for ra only */
time_t next_event = periodic_ra(now);
if (next_event != 0)
alarm((unsigned)difftime(next_event, now));
}
/* Not doing DHCP, so no lease system, manage
alarms for ra only */
send_alarm(periodic_ra(now), now);
#endif
#endif
}
@@ -1293,7 +1396,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
continue;
if (option_bool(OPT_NOWILD))
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */
else
{
@@ -1310,7 +1413,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
break;
}
if (!iface && !option_bool(OPT_NOWILD))
if (!iface && !(option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND)))
{
shutdown(confd, SHUT_RDWR);
close(confd);

View File

@@ -159,6 +159,7 @@ struct event_desc {
#define EVENT_LOG_ERR 17
#define EVENT_FORK_ERR 18
#define EVENT_LUA_ERR 19
#define EVENT_TFTP_ERR 20
/* Exit codes. */
#define EC_GOOD 0
@@ -217,7 +218,10 @@ struct event_desc {
#define OPT_CONNTRACK 35
#define OPT_FQDN_UPDATE 36
#define OPT_RA 37
#define OPT_LAST 38
#define OPT_TFTP_LC 38
#define OPT_CLEVERBIND 39
#define OPT_TFTP 40
#define OPT_LAST 41
/* 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. */
@@ -297,17 +301,30 @@ union bigname {
union bigname *next; /* freelist */
};
struct keydata {
struct keydata *next;
unsigned char key[KEYBLOCK_LEN];
};
struct crec {
struct crec *next, *prev, *hash_next;
time_t ttd; /* time to die */
int uid;
/* union is 16 bytes when doing IPv6, 8 bytes on 32 bit machines without IPv6 */
union {
struct all_addr addr;
struct {
struct crec *cache;
int uid;
} cname;
struct {
struct keydata *keydata;
unsigned char algo;
unsigned char digest; /* DS only */
unsigned short flags_or_keyid; /* flags for DNSKEY, keyid for DS */
} key;
} addr;
time_t ttd; /* time to die */
/* used as keylen if F_DS or F_DNSKEY, index to source for F_HOSTS */
int uid;
unsigned short flags;
union {
char sname[SMALLDNAME];
@@ -328,14 +345,21 @@ struct crec {
#define F_BIGNAME (1u<<9)
#define F_NXDOMAIN (1u<<10)
#define F_CNAME (1u<<11)
#define F_NOERR (1u<<12)
#define F_DNSKEY (1u<<12)
#define F_CONFIG (1u<<13)
#define F_DS (1u<<14)
#define F_DNSSECOK (1u<<15)
/* below here are only valid as args to log_query: cache
entries are limited to 16 bits */
#define F_UPSTREAM (1u<<16)
#define F_RRNAME (1u<<17)
#define F_SERVER (1u<<18)
#define F_QUERY (1u<<19)
#define F_NOERR (1u<<20)
/* composites */
#define F_TYPE (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS) /* Only one may be set */
/* struct sockaddr is not large enough to hold any address,
@@ -388,7 +412,7 @@ struct server {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, mtu, done, dad;
int tftp_ok, dhcp_ok, mtu, done, dad;
char *name;
struct irec *next;
};
@@ -403,7 +427,7 @@ struct listener {
struct iname {
char *name;
union mysockaddr addr;
int isloop, used;
int used;
struct iname *next;
};
@@ -451,7 +475,7 @@ struct frec {
#define OT_NAME 0x1000
#define OT_CSTRING 0x0800
#define OT_DEC 0x0400
#define OT_TIME 0x0200
/* actions in the daemon->helper RPC */
#define ACTION_DEL 1
@@ -641,7 +665,6 @@ struct dhcp_context {
time_t ra_time;
#endif
int flags;
char *interface;
struct dhcp_netid netid, *filter;
struct dhcp_context *next, *current;
};
@@ -655,6 +678,7 @@ struct dhcp_context {
#define CONTEXT_RA_NAME 64
#define CONTEXT_RA_STATELESS 128
#define CONTEXT_DHCP 256
#define CONTEXT_DEPRECATE 512
struct ping_result {
struct in_addr addr;
@@ -688,11 +712,6 @@ struct addr_list {
struct addr_list *next;
};
struct interface_list {
char *interface;
struct interface_list *next;
};
struct tftp_prefix {
char *interface;
char *prefix;
@@ -710,7 +729,7 @@ extern struct daemon {
time_t last_resolv;
struct mx_srv_record *mxnames;
struct naptr *naptr;
struct txt_record *txt;
struct txt_record *txt, *rr;
struct ptr_record *ptr;
struct host_record *host_records, *host_records_tail;
struct cname *cnames;
@@ -732,7 +751,7 @@ extern struct daemon {
int max_logs; /* queue limit */
int cachesize, ftabsize;
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;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp, *dhcp6, *ra_contexts;
struct dhcp_config *dhcp_conf;
@@ -756,10 +775,9 @@ extern struct daemon {
unsigned short edns_pktsz;
char *tftp_prefix;
struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
int tftp_unlimited;
unsigned int duid_enterprise, duid_config_len;
unsigned char *duid_config;
char *dbus_name;
/* globally used stuff for DNS */
char *packet; /* packet buffer */
@@ -837,6 +855,10 @@ char *get_domain(struct in_addr addr);
#ifdef HAVE_IPV6
char *get_domain6(struct in6_addr *addr);
#endif
#ifdef HAVE_DNSSEC
struct keydata *keydata_alloc(char *data, size_t len);
void keydata_free(struct keydata *blocks);
#endif
/* rfc1035.c */
unsigned int extract_request(struct dns_header *header, size_t qlen,
@@ -869,7 +891,7 @@ void safe_pipe(int *fd, int read_noblock);
void *whine_malloc(size_t size);
int sa_len(union mysockaddr *addr);
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);
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
#ifdef HAVE_IPV6
@@ -904,7 +926,10 @@ char *option_string(int prot, unsigned int opt, unsigned char *val,
int opt_len, char *buf, int buf_len);
void reread_dhcp(void);
void set_option_bool(unsigned int opt);
void reset_option_bool(unsigned int opt);
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 */
void reply_query(int fd, int family, time_t now);
@@ -915,7 +940,7 @@ void server_gone(struct server *server);
struct frec *get_new_frec(time_t now, int *wait);
int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source,
unsigned int iface, int *errp);
unsigned int iface);
/* network.c */
int indextoname(int fd, int index, char *name);
@@ -969,12 +994,13 @@ 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_find(unsigned char *clid, int clid_len,
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);
u64 lease_find_max_addr6(struct dhcp_context *context);
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
#endif
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);
unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain);
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now);
@@ -1068,6 +1094,7 @@ void dhcp6_init(void);
void dhcp6_packet(time_t now);
int address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
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 in6_addr *taddr,
struct dhcp_netid *netids);
@@ -1101,12 +1128,14 @@ char *strip_hostname(char *hostname);
void log_tags(struct dhcp_netid *netid, u32 xid);
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
void dhcp_update_configs(struct dhcp_config *configs);
void check_dhcp_hosts(int fatal);
void display_opts(void);
u16 lookup_dhcp_opt(int prot, char *name);
u16 lookup_dhcp_len(int prot, u16 val);
char *option_string(int prot, unsigned int opt, unsigned char *val,
int opt_len, char *buf, int buf_len);
#ifdef HAVE_LINUX_NETWORK
void bindtodevice(int fd);
#endif
# ifdef HAVE_DHCP6
void display_opts6(void);
void join_multicast(void);
@@ -1137,7 +1166,7 @@ void ra_start_unsolicted(time_t now, struct dhcp_context *context);
/* slaac.c */
#ifdef HAVE_DHCP6
void build_subnet_map(void);
void slaac_add_addrs(struct dhcp_lease *lease, time_t now);
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force);
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 schedule_subnet_map(void);

View File

@@ -28,7 +28,7 @@ static struct randfd *allocate_rfd(int family);
unless nowild is true, when we just send it with the kernel default */
int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, struct all_addr *source,
unsigned int iface, int *errp)
unsigned int iface)
{
struct msghdr msg;
struct iovec iov[1];
@@ -95,29 +95,19 @@ int send_from(int fd, int nowild, char *packet, size_t len,
#endif
}
retry:
if (sendmsg(fd, &msg, 0) == -1)
while (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())
goto retry;
continue;
if (errp)
*errp = errno;
else
my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
/* 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));
return 0;
}
return 1;
}
@@ -439,7 +429,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (udpfd != -1)
{
plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
send_from(udpfd, option_bool(OPT_NOWILD), (char *)header, plen, udpaddr, dst_addr, dst_iface, NULL);
send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
}
return 0;
@@ -627,8 +617,8 @@ void reply_query(int fd, int family, time_t now)
{
header->id = htons(forward->orig_id);
header->hb4 |= HB4_RA; /* recursion if available */
send_from(forward->fd, option_bool(OPT_NOWILD), daemon->packet, nn,
&forward->source, &forward->dest, forward->iface, NULL);
send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
&forward->source, &forward->dest, forward->iface);
}
free_frec(forward); /* cancel */
}
@@ -822,8 +812,8 @@ void receive_query(struct listener *listen, time_t now)
dst_addr_4, netmask, now);
if (m >= 1)
{
send_from(listen->fd, option_bool(OPT_NOWILD), (char *)header,
m, &source_addr, &dst_addr, if_index, NULL);
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,

View File

@@ -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);
#ifdef HAVE_LUASCRIPT
#define LUA_COMPAT_ALL
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#ifndef lua_open
#define lua_open() luaL_newstate()
#endif
lua_State *lua;
static unsigned char *grab_extradata_lua(unsigned char *buf, unsigned char *end, char *field);

View File

@@ -98,7 +98,7 @@ void lease_init(time_t now)
hw_type = ARPHRD_ETHER;
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
hw_len, hw_type, clid_len, now);
hw_len, hw_type, clid_len, now, 0);
if (strcmp(daemon->dhcp_buff, "*") != 0)
lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
@@ -119,7 +119,7 @@ void lease_init(time_t now)
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
{
lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, hw_type, clid_len, now);
lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, hw_type, clid_len, now, 0);
if (strcmp(daemon->dhcp_buff, "*") != 0)
lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
@@ -310,12 +310,19 @@ void lease_update_file(time_t now)
/* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
if (daemon->ra_contexts)
{
time_t ra_event = periodic_slaac(now, leases);
time_t event;
next_event = periodic_ra(now);
if ((event = periodic_slaac(now, leases)) != 0)
{
if (next_event == 0 || difftime(next_event, event) > 0.0)
next_event = event;
}
if (next_event == 0 || difftime(next_event, ra_event) > 0.0)
next_event = ra_event;
if ((event = periodic_ra(now)) != 0)
{
if (next_event == 0 || difftime(next_event, event) > 0.0)
next_event = event;
}
}
#endif
@@ -373,7 +380,10 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface)
{
slaac_ping_reply(sender, packet, interface, leases);
/* We may be doing RA but not DHCPv4, in which case the lease
database may not exist and we have nothing to do anyway */
if (daemon->dhcp)
slaac_ping_reply(sender, packet, interface, leases);
}
#endif
@@ -552,18 +562,31 @@ struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
memcmp(clid, lease->clid, clid_len) != 0))
continue;
if (clid || addr)
{
lease->flags |= LEASE_USED;
return lease;
}
else
lease->flags &= ~LEASE_USED;
lease->flags |= LEASE_USED;
return lease;
}
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 *lease;
@@ -699,13 +722,16 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
}
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)
unsigned char *clid, int hw_len, int hw_type, int clid_len,
time_t now, int force)
{
#ifdef HAVE_DHCP6
int change = 0;
int change = force;
lease->flags |= LEASE_HAVE_HWADDR;
#endif
(void)force;
if (hw_len != lease->hwaddr_len ||
hw_type != lease->hwaddr_type ||
(hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
@@ -755,7 +781,7 @@ void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
#ifdef HAVE_DHCP6
if (change)
slaac_add_addrs(lease, now);
slaac_add_addrs(lease, now, force);
#endif
}
@@ -883,7 +909,7 @@ void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now)
lease->flags |= LEASE_CHANGED;
#ifdef HAVE_DHCP6
slaac_add_addrs(lease, now);
slaac_add_addrs(lease, now, 0);
#endif
}

View File

@@ -38,8 +38,7 @@
static struct iovec iov;
static u32 netlink_pid;
static void nl_err(struct nlmsghdr *h);
static void nl_routechange(struct nlmsghdr *h);
static int nl_async(struct nlmsghdr *h);
void netlink_init(void)
{
@@ -49,10 +48,13 @@ void netlink_init(void)
addr.nl_family = AF_NETLINK;
addr.nl_pad = 0;
addr.nl_pid = 0; /* autobind */
#ifdef HAVE_IPV6
addr.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
#else
addr.nl_groups = RTMGRP_IPV4_ROUTE;
if (option_bool(OPT_CLEVERBIND))
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
#ifdef HAVE_IPV6
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
if (daemon->ra_contexts || option_bool(OPT_CLEVERBIND))
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
#endif
/* May not be able to have permission to set multicast groups don't die in that case */
@@ -136,7 +138,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
struct nlmsghdr *h;
ssize_t len;
static unsigned int seq = 0;
int callback_ok = 1;
int callback_ok = 1, newaddr = 0;
struct {
struct nlmsghdr nlh;
@@ -182,12 +184,24 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid)
nl_routechange(h); /* May be multicast arriving async */
else if (h->nlmsg_type == NLMSG_ERROR)
nl_err(h);
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
{
/* May be multicast arriving async */
if (nl_async(h) && option_bool(OPT_CLEVERBIND))
newaddr = 1;
}
else if (h->nlmsg_type == NLMSG_DONE)
return callback_ok;
{
/* handle async new interface address arrivals, these have to be done
after we complete as we're not re-entrant */
if (newaddr)
{
enumerate_interfaces();
create_bound_listeners(0);
}
return callback_ok;
}
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
{
struct ifaddrmsg *ifa = NLMSG_DATA(h);
@@ -295,7 +309,7 @@ void netlink_multicast(void)
{
ssize_t len;
struct nlmsghdr *h;
int flags;
int flags, newaddr = 0;
/* don't risk blocking reading netlink messages here. */
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
@@ -303,44 +317,62 @@ void netlink_multicast(void)
return;
if ((len = netlink_recv()) != -1)
{
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
if (h->nlmsg_type == NLMSG_ERROR)
nl_err(h);
else
nl_routechange(h);
}
/* restore non-blocking status */
fcntl(daemon->netlinkfd, F_SETFL, flags);
}
static void nl_err(struct nlmsghdr *h)
{
struct nlmsgerr *err = NLMSG_DATA(h);
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))
newaddr = 1;
if (err->error != 0)
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
/* restore non-blocking status */
fcntl(daemon->netlinkfd, F_SETFL, flags);
if (newaddr)
{
enumerate_interfaces();
create_bound_listeners(0);
}
}
/* 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. Note that we only accept these messages from the kernel (pid == 0) */
static void nl_routechange(struct nlmsghdr *h)
static int nl_async(struct nlmsghdr *h)
{
if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
if (h->nlmsg_type == NLMSG_ERROR)
{
struct nlmsgerr *err = NLMSG_DATA(h);
if (err->error != 0)
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
return 0;
}
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
{
/* 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);
int fd;
if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_scope != RT_SCOPE_LINK)
return;
/* Force re-reading resolv file right now, for luck. */
daemon->last_resolv = 0;
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;
}
else if (h->nlmsg_type == RTM_NEWADDR)
{
#ifdef HAVE_DHCP6
/* force RAs to sync new network and pick up new interfaces. */
if (daemon->ra_contexts)
@@ -351,23 +383,13 @@ static void nl_routechange(struct nlmsghdr *h)
iface_enumerate and can't re-enter it now */
send_alarm(0, 0);
}
#endif
if (daemon->srv_save)
{
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;
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
}
}
#endif
return 1; /* clever bind mode - rescan */
}
return 0;
}
#endif

View File

@@ -117,18 +117,8 @@ int iface_check(int family, struct all_addr *addr, char *name)
if (daemon->if_names || daemon->if_addrs)
{
#ifdef HAVE_DHCP
struct dhcp_context *range;
#endif
ret = 0;
#ifdef HAVE_DHCP
for (range = daemon->dhcp; range; range = range->next)
if (range->interface && strcmp(range->interface, name) == 0)
ret = 1;
#endif
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
ret = tmp->used = 1;
@@ -161,11 +151,11 @@ static int iface_allowed(struct irec **irecp, int if_index,
struct irec *iface;
int fd, mtu = 0, loopback;
struct ifreq ifr;
int tftp_ok = daemon->tftp_unlimited;
int tftp_ok = !!option_bool(OPT_TFTP);
int dhcp_ok = 1;
#ifdef HAVE_DHCP
struct iname *tmp;
#endif
struct interface_list *ir = NULL;
/* check whether the interface IP has been added already
we call this routine multiple times. */
@@ -190,6 +180,9 @@ static int iface_allowed(struct irec **irecp, int if_index,
}
loopback = ifr.ifr_flags & IFF_LOOPBACK;
if (loopback)
dhcp_ok = 0;
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
@@ -203,50 +196,38 @@ static int iface_allowed(struct irec **irecp, int if_index,
struct iname *lo;
for (lo = daemon->if_names; lo; lo = lo->next)
if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
{
lo->isloop = 1;
break;
}
break;
if (!lo &&
(lo = whine_malloc(sizeof(struct iname))) &&
(lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
{
strcpy(lo->name, ifr.ifr_name);
lo->isloop = lo->used = 1;
lo->used = 1;
lo->next = daemon->if_names;
daemon->if_names = lo;
}
}
#ifdef HAVE_TFTP
/* implement wierd TFTP service rules */
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, ifr.ifr_name) == 0)
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 = 1;
break;
tftp_ok = 0;
dhcp_ok = 0;
}
#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;
#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;
if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
return 1;
#endif
}
/* add to list */
if ((iface = whine_malloc(sizeof(struct irec))))
@@ -254,14 +235,18 @@ static int iface_allowed(struct irec **irecp, int if_index,
iface->addr = *addr;
iface->netmask = netmask;
iface->tftp_ok = tftp_ok;
iface->dhcp_ok = dhcp_ok;
iface->mtu = mtu;
iface->dad = dad;
iface->done = 0;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
strcpy(iface->name, ifr.ifr_name);
iface->next = *irecp;
*irecp = iface;
return 1;
{
strcpy(iface->name, ifr.ifr_name);
iface->next = *irecp;
*irecp = iface;
return 1;
}
free(iface);
}
errno = ENOMEM;
@@ -339,6 +324,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if ((fd = socket(family, type, 0)) == -1)
{
int port;
char *s;
/* No error if the kernel just doesn't support this IP flavour */
if (errno == EPROTONOSUPPORT ||
@@ -347,18 +333,27 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
return -1;
err:
port = prettyprint_addr(addr, daemon->addrbuff);
if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
sprintf(daemon->addrbuff, "port %d", port);
s = _("failed to create listening socket for %s: %s");
if (fd != -1)
close (fd);
if (dienow)
{
port = prettyprint_addr(addr, daemon->namebuff);
if (!option_bool(OPT_NOWILD))
sprintf(daemon->namebuff, "port %d", port);
die(_("failed to create listening socket for %s: %s"),
daemon->namebuff, 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));
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
goto err;
@@ -476,8 +471,7 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
void create_wildcard_listeners(void)
{
union mysockaddr addr;
struct listener *l;
int tftp_enabled = daemon->tftp_unlimited || daemon->tftp_interfaces;
struct listener *l, *l6;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -487,7 +481,7 @@ void create_wildcard_listeners(void)
addr.in.sin_addr.s_addr = INADDR_ANY;
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
memset(&addr, 0, sizeof(addr));
@@ -497,11 +491,12 @@ void create_wildcard_listeners(void)
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(daemon->port);
l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
if (l)
l->next = create_listeners(&addr, tftp_enabled, 1);
l->next = l6;
else
l = create_listeners(&addr, tftp_enabled, 1);
l = l6;
#endif
daemon->listeners = l;
@@ -527,7 +522,8 @@ void create_bound_listeners(int dienow)
no interface with a matching address. These may be valid: eg it's possible
to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
If the address isn't valid the bind() will fail and we'll die().
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
handled by the DNS and TFTP code. It disables --localise-queries processing
@@ -535,7 +531,7 @@ void create_bound_listeners(int dienow)
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, 1, dienow)))
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
{
new->iface = NULL;
new->next = daemon->listeners;

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define ALL_HOSTS "FF02::1"
#define ALL_NODES "FF02::1"
#define ALL_ROUTERS "FF02::2"
struct ping_packet {
@@ -43,6 +43,7 @@ struct prefix_opt {
#define ICMP6_OPT_PREFIX 3
#define ICMP6_OPT_MTU 5
#define ICMP6_OPT_RDNSS 25
#define ICMP6_OPT_DNSSL 31

View File

@@ -29,6 +29,7 @@
struct ra_param {
int ind, managed, other, found_context, first;
char *if_name;
struct dhcp_netid *tags;
struct in6_addr link_local;
};
@@ -50,7 +51,7 @@ void ra_init(time_t now)
{
struct icmp6_filter filter;
int fd;
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
int class = IPTOS_CLASS_CS6;
#endif
int val = 255; /* radvd uses this value */
@@ -72,7 +73,7 @@ void ra_init(time_t now)
if ((fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1 ||
getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, &len) ||
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
#endif
!fix_fd(fd) ||
@@ -116,10 +117,8 @@ void icmp6_packet(void)
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
} control_u;
struct sockaddr_in6 from;
unsigned char *p;
char *mac = "";
unsigned char *packet;
struct iname *tmp;
struct dhcp_context *context;
/* Note: use outpacket for input buffer */
msg.msg_control = control_u.control6;
@@ -132,6 +131,8 @@ void icmp6_packet(void)
if ((sz = recv_dhcp_packet(daemon->icmp6fd, &msg)) == -1 || sz < 8)
return;
packet = (unsigned char *)daemon->outpacket.iov_base;
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
@@ -155,41 +156,26 @@ void icmp6_packet(void)
if (tmp->name && (strcmp(tmp->name, interface) == 0))
return;
/* weird libvirt-inspired access control */
for (context = daemon->dhcp6; context; context = context->next)
if (!context->interface || strcmp(context->interface, interface) == 0)
break;
if (!context)
if (packet[1] != 0)
return;
p = (unsigned char *)daemon->outpacket.iov_base;
if (p[1] != 0)
return;
if (p[0] == ICMP6_ECHO_REPLY)
if (packet[0] == ICMP6_ECHO_REPLY)
lease_ping_reply(&from.sin6_addr, packet, interface);
else if (packet[0] == ND_ROUTER_SOLICIT)
{
/* We may be doing RA but not DHCPv4, in which case the lease
database may not exist and we have nothing to do anyway */
if (daemon->dhcp)
lease_ping_reply(&from.sin6_addr, p, interface);
return;
char *mac = "";
/* look for link-layer address option for logging */
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
{
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
mac = daemon->namebuff;
}
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
/* 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);
}
if (p[0] != ND_ROUTER_SOLICIT)
return;
/* look for link-layer address option for logging */
if (sz >= 16 && p[8] == ICMP6_OPT_SOURCE_MAC && (p[9] * 8) + 8 <= sz)
{
print_mac(daemon->namebuff, &p[10], (p[9] * 8) - 2);
mac = daemon->namebuff;
}
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
send_ra(if_index, interface, &from.sin6_addr);
}
static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
@@ -199,7 +185,10 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
struct ifreq ifr;
struct sockaddr_in6 addr;
struct dhcp_context *context;
struct dhcp_netid iface_id;
struct dhcp_opt *opt_cfg;
int done_dns = 0;
save_counter(0);
ra = expand(sizeof(struct ra_packet));
@@ -218,9 +207,17 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
parm.if_name = iface_name;
parm.first = 1;
for (context = daemon->ra_contexts; context; context = context->next)
context->flags &= ~CONTEXT_RA_DONE;
/* set tag with name == interface */
iface_id.net = iface_name;
iface_id.next = NULL;
parm.tags = &iface_id;
for (context = daemon->ra_contexts; context; context = context->next)
{
context->flags &= ~CONTEXT_RA_DONE;
context->netid.next = &context->netid;
}
if (!iface_enumerate(AF_INET6, &parm, add_prefixes) ||
!parm.found_context)
return;
@@ -236,14 +233,63 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
}
iface_enumerate(AF_LOCAL, &iface, add_lla);
/* RDNSS, RFC 6106, use relevant DHCP6 options */
(void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
/* RDNSS, RFC 6106 */
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char(3);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(&parm.link_local, IN6ADDRSZ);
for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
{
int i;
/* netids match and not encapsulated? */
if (!(opt_cfg->flags & DHOPT_TAGOK))
continue;
if (opt_cfg->opt == OPTION6_DNS_SERVER)
{
struct in6_addr *a = (struct in6_addr *)opt_cfg->val;
done_dns = 1;
if (opt_cfg->len == 0)
continue;
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char((opt_cfg->len/8) + 1);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
/* zero means "self" */
for (i = 0; i < opt_cfg->len; i += IN6ADDRSZ, a++)
if (IN6_IS_ADDR_UNSPECIFIED(a))
put_opt6(&parm.link_local, IN6ADDRSZ);
else
put_opt6(a, IN6ADDRSZ);
}
if (opt_cfg->opt == OPTION6_DOMAIN_SEARCH && opt_cfg->len != 0)
{
int len = ((opt_cfg->len+7)/8);
put_opt6_char(ICMP6_OPT_DNSSL);
put_opt6_char(len + 1);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(opt_cfg->val, opt_cfg->len);
/* pad */
for (i = opt_cfg->len; i < len * 8; i++)
put_opt6_char(0);
}
}
if (!done_dns)
{
/* default == us. */
put_opt6_char(ICMP6_OPT_RDNSS);
put_opt6_char(3);
put_opt6_short(0);
put_opt6_long(1800); /* lifetime - twice RA retransmit */
put_opt6(&parm.link_local, IN6ADDRSZ);
}
/* set managed bits unless we're providing only RA on this link */
if (parm.managed)
@@ -266,19 +312,17 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
addr.sin6_scope_id = iface;
}
else
inet_pton(AF_INET6, ALL_HOSTS, &addr.sin6_addr);
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
send_from(daemon->icmp6fd, 0, daemon->outpacket.iov_base, save_counter(0),
(union mysockaddr *)&addr, (struct all_addr *)&parm.link_local, iface, NULL);
(union mysockaddr *)&addr, (struct all_addr *)&parm.link_local, iface);
}
static int add_prefixes(struct in6_addr *local, int prefix,
int scope, int if_index, int dad, void *vparam)
{
struct dhcp_context *context, *tmp;
struct ra_param *param = vparam;
struct prefix_opt *opt;
(void)scope; /* warning */
(void)dad;
@@ -291,19 +335,27 @@ static int add_prefixes(struct in6_addr *local, int prefix,
!IN6_IS_ADDR_LINKLOCAL(local) &&
!IN6_IS_ADDR_MULTICAST(local))
{
int do_prefix = 0;
int do_slaac = 0;
int deprecate = 0;
unsigned int time = 0xffffffff;
struct dhcp_context *context;
for (context = daemon->ra_contexts; context; context = context->next)
if (prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
{
int do_slaac = 0;
if ((context->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
{
do_slaac = 1;
if (context->flags & CONTEXT_RA_STATELESS)
param->other = 1;
if (context->flags & CONTEXT_DHCP)
{
param->other = 1;
if (!(context->flags & CONTEXT_RA_STATELESS))
param->managed = 1;
}
}
else
{
@@ -314,68 +366,63 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param->other = 1;
}
if (context->flags & CONTEXT_RA_DONE)
continue;
/* find floor time */
if (time > context->lease_time)
time = context->lease_time;
/* subsequent prefixes on the same interface don't need timers */
if (!param->first)
context->ra_time = 0;
param->first = 0;
param->found_context = 1;
context->flags |= CONTEXT_RA_DONE;
if (context->flags & CONTEXT_DEPRECATE)
deprecate = 1;
/* mark this subnet and duplicates: as done. */
for (tmp = context->next; tmp; tmp = tmp->next)
if (tmp->prefix == prefix &&
is_same_net6(local, &tmp->start6, prefix) &&
is_same_net6(local, &tmp->end6, prefix))
{
tmp->flags |= CONTEXT_RA_DONE;
context->ra_time = 0;
/* if any dhcp-range with ra-only on this subnet
set the "do_slaac" bit */
if (tmp->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS))
{
do_slaac = 1;
if (context->flags & CONTEXT_RA_STATELESS)
param->other = 1;
}
else
{
/* don't do RA for non-ra-only unless --enable-ra is set */
if (!option_bool(OPT_RA))
continue;
param->managed = 1;
param->other = 1;
}
}
if ((opt = expand(sizeof(struct prefix_opt))))
/* collect dhcp-range tags */
if (context->netid.next == &context->netid && context->netid.net)
{
u64 addrpart = addr6part(&context->start6);
u64 mask = (prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU;
unsigned int time = context->lease_time;
/* lifetimes must be min 2 hrs, by RFC 2462 */
if (time < 7200)
time = 7200;
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = prefix;
/* autonomous only is we're not doing dhcp */
opt->flags = do_slaac ? 0x40 : 0x00;
opt->valid_lifetime = opt->preferred_lifetime = htonl(time);
opt->reserved = 0;
opt->prefix = context->start6;
setaddr6part(&opt->prefix, addrpart & ~mask);
inet_ntop(AF_INET6, &opt->prefix, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff);
context->netid.next = param->tags;
param->tags = &context->netid;
}
/* subsequent prefixes on the same interface
and subsequent instances of this prefix don't need timers.
Be careful not to find the same prefix twice with different
addresses. */
if (!(context->flags & CONTEXT_RA_DONE))
{
if (!param->first)
context->ra_time = 0;
context->flags |= CONTEXT_RA_DONE;
do_prefix = 1;
}
param->first = 0;
param->found_context = 1;
}
if (do_prefix)
{
struct prefix_opt *opt;
if ((opt = expand(sizeof(struct prefix_opt))))
{
/* zero net part of address */
setaddr6part(local, addr6part(local) & ~((prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU));
/* lifetimes must be min 2 hrs, by RFC 2462 */
if (time < 7200)
time = 7200;
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80;
opt->valid_lifetime = htonl(time);
opt->preferred_lifetime = htonl(deprecate ? 0 : time);
opt->reserved = 0;
opt->prefix = *local;
inet_ntop(AF_INET6, local, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s", param->if_name, daemon->addrbuff);
}
}
}
}
return 1;
@@ -410,6 +457,7 @@ time_t periodic_ra(time_t now)
char interface[IF_NAMESIZE+1];
param.now = now;
param.iface = 0;
while (1)
{
@@ -435,13 +483,21 @@ time_t periodic_ra(time_t now)
ever be able to send ra's and satistfy it. */
if (iface_enumerate(AF_INET6, &param, iface_search))
context->ra_time = 0;
else if (indextoname(daemon->icmp6fd, param.iface, interface))
send_ra(param.iface, interface, NULL);
}
else if (param.iface != 0 &&
indextoname(daemon->icmp6fd, param.iface, interface) &&
iface_check(AF_LOCAL, NULL, interface))
{
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(param.iface, interface, NULL);
}
}
return next_event;
}
static int iface_search(struct in6_addr *local, int prefix,
int scope, int if_index, int dad, void *vparam)
{
@@ -458,9 +514,11 @@ static int iface_search(struct in6_addr *local, int prefix,
if (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
so they don't timeout independently .*/
param->iface = if_index;
timeout value and arrange for RA to be sent unless interface is
still doing DAD.*/
if (!dad)
param->iface = if_index;
if (difftime(param->now, ra_short_period_start) < 60.0)
/* range 5 - 20 */
@@ -469,6 +527,14 @@ static int iface_search(struct in6_addr *local, int prefix,
/* range 450 - 600 */
context->ra_time = param->now + 450 + (rand16()/440);
/* 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 */
}

View File

@@ -699,15 +699,17 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
unsigned char *p2 = p1;
/* make counted string zero-term and sanitise */
for (i = 0; i < len; i++)
if (isprint(*(p2+1)))
{
*p2 = *(p2+1);
p2++;
}
{
if (!isprint((int)*(p2+1)))
break;
*p2 = *(p2+1);
p2++;
}
*p2 = 0;
my_syslog(LOG_INFO, "reply %s is %s", name, p1);
/* restore */
memmove(p1 + 1, p1, len);
memmove(p1 + 1, p1, i);
*p1 = len;
p1 += len+1;
}
@@ -936,10 +938,14 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
if (!cname_count--)
return 0; /* looped CNAMES */
newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
if (newc && cpp)
if (newc)
{
cpp->addr.cname.cache = newc;
cpp->addr.cname.uid = newc->uid;
newc->addr.cname.cache = NULL;
if (cpp)
{
cpp->addr.cname.cache = newc;
cpp->addr.cname.uid = newc->uid;
}
}
cpp = newc;
@@ -1003,10 +1009,16 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
}
}
/* Don't put stuff from a truncated packet into the cache,
also don't cache replies where DNSSEC validation was turned off, either
the upstream server told us so, or the original query specified it. */
if (!(header->hb3 & HB3_TC) && !(header->hb4 & HB4_CD) && !checking_disabled)
/* Don't put stuff from a truncated packet into the cache.
Don't cache replies where DNSSEC validation was turned off, either
the upstream server told us so, or the original query specified it.
Don't cache replies from non-recursive nameservers, since we may get a
reply containing a CNAME but not its target, even though the target
does exist. */
if (!(header->hb3 & HB3_TC) &&
!(header->hb4 & HB4_CD) &&
(header->hb4 & HB4_RA) &&
!checking_disabled)
cache_end_insert();
return 0;
@@ -1238,7 +1250,8 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
case 't':
usval = va_arg(ap, int);
sval = va_arg(ap, char *);
memcpy(p, sval, usval);
if (usval != 0)
memcpy(p, sval, usval);
p += usval;
break;
@@ -1381,6 +1394,22 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (qclass == C_IN)
{
struct txt_record *t;
for (t = daemon->rr; t; t = t->next)
if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
{
ans = 1;
if (!dryrun)
{
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
t->class, C_IN, "t", t->len, t->txt))
anscount ++;
}
}
if (qtype == T_PTR || qtype == T_ANY)
{
/* see if it's w.z.y.z.in-addr.arpa format */
@@ -1633,6 +1662,23 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
} while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
}
}
if (qtype == T_CNAME || qtype == T_ANY)
{
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP))))
{
ans = 1;
if (!dryrun)
{
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), &nameoffset,
T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
anscount++;
}
}
}
if (qtype == T_MX || qtype == T_ANY)
{

View File

@@ -483,7 +483,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
logaddr = &mess->yiaddr;
lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now);
lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now, 1);
if (hostname)
lease_set_hostname(lease, hostname, 1, get_domain(lease->addr), domain);
/* infinite lease unless nailed in dhcp-host line. */
@@ -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);
clear_packet(mess, end);
match_vendor_opts(NULL, daemon->dhcp_opts); /* clear flags */
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;
pp = op;
/* Always force update, since the client has no way to do it itself. */
if (!option_bool(OPT_FQDN_UPDATE) && !(fqdn_flags & 0x01))
fqdn_flags |= 0x03;
fqdn_flags &= ~0x08;
/* NB, the following always sets at least one bit */
if (option_bool(OPT_FQDN_UPDATE))
{
if (fqdn_flags & 0x01)
{
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)
while (*op != 0 && ((op + (*op) + 1) - pp) < len)
@@ -1222,51 +1234,56 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
log_tags(tagif_netid, ntohl(mess->xid));
#ifdef HAVE_SCRIPT
if (do_classes && daemon->lease_change_command)
if (do_classes)
{
struct dhcp_netid *n;
if (mess->giaddr.s_addr)
lease->giaddr = mess->giaddr;
/* pick up INIT-REBOOT events. */
lease->flags |= LEASE_CHANGED;
free(lease->extradata);
lease->extradata = NULL;
lease->extradata_size = lease->extradata_len = 0;
add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
add_extradata_opt(lease, oui);
add_extradata_opt(lease, serial);
add_extradata_opt(lease, class);
/* space-concat tag set */
if (!tagif_netid)
add_extradata_opt(lease, NULL);
else
for (n = tagif_netid; n; n = n->next)
{
struct dhcp_netid *n1;
/* kill dupes */
for (n1 = n->next; n1; n1 = n1->next)
if (strcmp(n->net, n1->net) == 0)
break;
if (!n1)
lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
}
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
#ifdef HAVE_SCRIPT
if (daemon->lease_change_command)
{
int len = option_len(opt);
unsigned char *ucp = option_ptr(opt, 0);
/* If the user-class option started as counted strings, the first byte will be zero. */
if (len != 0 && ucp[0] == 0)
ucp++, len--;
lease_add_extradata(lease, ucp, len, 0);
struct dhcp_netid *n;
if (mess->giaddr.s_addr)
lease->giaddr = mess->giaddr;
free(lease->extradata);
lease->extradata = NULL;
lease->extradata_size = lease->extradata_len = 0;
add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
add_extradata_opt(lease, oui);
add_extradata_opt(lease, serial);
add_extradata_opt(lease, class);
/* space-concat tag set */
if (!tagif_netid)
add_extradata_opt(lease, NULL);
else
for (n = tagif_netid; n; n = n->next)
{
struct dhcp_netid *n1;
/* kill dupes */
for (n1 = n->next; n1; n1 = n1->next)
if (strcmp(n->net, n1->net) == 0)
break;
if (!n1)
lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
}
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
{
int len = option_len(opt);
unsigned char *ucp = option_ptr(opt, 0);
/* If the user-class option started as counted strings, the first byte will be zero. */
if (len != 0 && ucp[0] == 0)
ucp++, len--;
lease_add_extradata(lease, ucp, len, 0);
}
}
}
#endif
}
if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
{
@@ -1276,7 +1293,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now);
lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now, do_classes);
/* if all the netids in the ignore_name list are present, ignore client-supplied name */
if (!hostname_auth)
@@ -1370,6 +1387,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (lease)
{
lease_set_interface(lease, int_index, now);
if (override.s_addr != 0)
lease->override = override;
else
@@ -1380,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_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),
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
@@ -2256,7 +2264,7 @@ static void do_options(struct dhcp_context *context,
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;

View File

@@ -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 *domain = NULL, *send_domain = 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;
unsigned char *outmsgtypep;
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;
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 */
outmsgtypep = put_opt6(inbuff, 4);
start_opts = save_counter(-1);
@@ -349,28 +354,28 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (len != 0 && len < 255)
{
unsigned char *pp, *op = opt6_ptr(opt, 1);
char *pq = daemon->dhcp_buff;
pp = op;
while (*op != 0 && ((op + (*op) + 1) - pp) < len)
{
memcpy(pq, op+1, *op);
pq += *op;
op += (*op)+1;
*(pq++) = '.';
}
if (pq != daemon->dhcp_buff)
pq--;
*pq = 0;
if (legal_hostname(daemon->dhcp_buff))
{
client_hostname = daemon->dhcp_buff;
if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), xid, client_hostname);
}
unsigned char *pp, *op = opt6_ptr(opt, 1);
char *pq = daemon->dhcp_buff;
pp = op;
while (*op != 0 && ((op + (*op)) - pp) < len)
{
memcpy(pq, op+1, *op);
pq += *op;
op += (*op)+1;
*(pq++) = '.';
}
if (pq != daemon->dhcp_buff)
pq--;
*pq = 0;
if (legal_hostname(daemon->dhcp_buff))
{
client_hostname = daemon->dhcp_buff;
if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), xid, client_hostname);
}
}
}
@@ -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);
/* 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);
put_opt6_long(iaid);
@@ -513,13 +518,13 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
while (1)
{
struct in6_addr alloced_addr, *addrp = NULL;
u32 preferred_time = 0;
u32 requested_time = 0;
struct dhcp_lease *lease = NULL;
if (ia_option)
{
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
preferred_time = opt6_uint(ia_option, 16, 4);
requested_time = opt6_uint(ia_option, 16, 4);
if (!address6_available(context, req_addr, tags) &&
(!have_config(config, CONFIG_ADDR6) || memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0))
@@ -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"),
daemon->addrbuff);
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 */
if (!addrp &&
(lease = lease6_find(clid, clid_len,
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))
addrp = (struct in6_addr *)&lease->hwaddr;
@@ -621,10 +630,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (ia_option)
{
if (preferred_time < 120u )
preferred_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (preferred_time != 0xffffffff && preferred_time < lease_time))
lease_time = preferred_time;
if (requested_time < 120u )
requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = requested_time;
}
if (lease_time < min_time)
@@ -637,7 +646,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (lease)
{
lease_set_expires(lease, lease_time, now);
lease_set_hwaddr(lease, NULL, clid, 0, iaid, clid_len, now);
lease_set_hwaddr(lease, NULL, clid, 0, iaid, clid_len, now, 0);
lease_set_interface(lease, interface, now);
if (hostname && ia_type == OPTION6_IA_NA)
{
@@ -730,8 +739,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(addrp, sizeof(*addrp));
put_opt6_long(lease_time);
put_opt6_long(lease_time);
/* preferred lifetime */
put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
put_opt6_long(lease_time); /* valid lifetime */
end_opt6(o1);
log6_packet( make_lease ? "DHCPREPLY" : "DHCPADVERTISE",
@@ -831,7 +841,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
iacntr = save_counter(-1);
/* 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_end = opt6_ptr(opt, opt6_len(opt));
@@ -842,7 +852,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
{
struct dhcp_lease *lease = NULL;
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
u32 preferred_time = opt6_uint(ia_option, 16, 4);
u32 requested_time = opt6_uint(ia_option, 16, 4);
unsigned int lease_time;
struct dhcp_context *this_context;
struct dhcp_config *valid_config = config;
@@ -873,7 +883,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if (!address6_available(context, req_addr, tagif) ||
!(this_context = narrow_context6(context, req_addr, tagif)))
lease_time = 0;
{
lease_time = 0;
this_context = NULL;
}
else
{
/* get tags from context if we've not used it before */
@@ -895,10 +908,10 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
lease_time = have_config(valid_config, CONFIG_TIME) ? valid_config->lease_time : this_context->lease_time;
if (preferred_time < 120u )
preferred_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (preferred_time != 0xffffffff && preferred_time < lease_time))
lease_time = preferred_time;
if (requested_time < 120u )
requested_time = 120u; /* sanity */
if (lease_time == 0xffffffff || (requested_time != 0xffffffff && requested_time < lease_time))
lease_time = requested_time;
lease_set_expires(lease, lease_time, now);
if (ia_type == OPTION6_IA_NA && hostname)
@@ -917,8 +930,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(req_addr, sizeof(*req_addr));
put_opt6_long(lease_time);
put_opt6_long(lease_time);
/* preferred lifetime */
put_opt6_long(this_context && (this_context->flags & CONTEXT_DEPRECATE) ? 0 : lease_time);
put_opt6_long(lease_time); /* valid lifetime */
end_opt6(o1);
}
@@ -996,10 +1010,17 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
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)
return 0;
*outmsgtypep = DHCP6REPLY;
log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, hostname);
break;
}
@@ -1031,7 +1052,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);
/* 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);
ia_option;
@@ -1110,7 +1131,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);
/* 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);
ia_option;

View File

@@ -23,12 +23,14 @@
static int map_rebuild = 0;
static int ping_id = 0;
void slaac_add_addrs(struct dhcp_lease *lease, time_t now)
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
{
struct slaac_address *slaac, *old, **up;
struct dhcp_context *context;
int dns_dirty = 0;
if (!(lease->flags & LEASE_HAVE_HWADDR) ||
(lease->flags & (LEASE_TA | LEASE_NA)) ||
lease->last_interface == 0 ||
!lease->hostname)
return ;
@@ -72,6 +74,13 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now)
if (IN6_ARE_ADDR_EQUAL(&addr, &slaac->addr))
{
*up = slaac->next;
/* recheck when DHCPv4 goes through init-reboot */
if (force)
{
slaac->ping_time = now;
slaac->backoff = 1;
dns_dirty = 1;
}
break;
}
up = &slaac->next;
@@ -95,6 +104,9 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now)
}
}
if (old || dns_dirty)
lease_update_dns(1);
/* Free any no reused */
for (; old; old = slaac)
{
@@ -108,8 +120,8 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
{
struct dhcp_context *context;
struct dhcp_lease *lease;
struct slaac_address *slaac;
time_t next_event = 0;
struct slaac_address *slaac;
time_t next_event = 0;
for (context = daemon->ra_contexts; context; context = context->next)
if ((context->flags & CONTEXT_RA_NAME))
@@ -139,8 +151,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
{
struct ping_packet *ping;
struct sockaddr_in6 addr;
int err;
save_counter(0);
ping = expand(sizeof(struct ping_packet));
ping->type = ICMP6_ECHO_REQUEST;
@@ -156,9 +167,11 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = slaac->addr;
if (send_from(daemon->icmp6fd, 0, daemon->outpacket.iov_base, save_counter(0),
(union mysockaddr *)&addr, (struct all_addr *)&slaac->local,
lease->last_interface, &err))
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
(struct sockaddr *)&addr, sizeof(addr)) == -1 &&
errno == EHOSTUNREACH)
slaac->ping_time = 0; /* Give up */
else
{
slaac->ping_time += (1 << (slaac->backoff - 1)) + (rand16()/21785); /* 0 - 3 */
if (slaac->backoff > 4)
@@ -166,8 +179,6 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
if (slaac->backoff < 12)
slaac->backoff++;
}
else if (err == EHOSTUNREACH)
slaac->ping_time = 0; /* Give up */
}
if (slaac->ping_time != 0 &&

View File

@@ -18,12 +18,13 @@
#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 ssize_t tftp_err(int err, char *packet, char *mess, char *file);
static ssize_t tftp_err_oops(char *packet, char *file);
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
static char *next(char **p, char *end);
static void sanitise(char *buf);
#define OP_RRQ 1
#define OP_WRQ 2
@@ -47,7 +48,7 @@ void tftp_request(struct listener *listen, time_t now)
struct msghdr msg;
struct iovec iov;
struct ifreq ifr;
int is_err = 1, if_index = 0, mtu = 0, special = 0;
int is_err = 1, if_index = 0, mtu = 0;
#ifdef HAVE_DHCP
struct iname *tmp;
#endif
@@ -60,7 +61,6 @@ void tftp_request(struct listener *listen, time_t now)
char *name = NULL;
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct interface_list *ir;
union {
struct cmsghdr align; /* this ensures alignment */
@@ -113,8 +113,6 @@ void tftp_request(struct listener *listen, time_t now)
else
{
struct cmsghdr *cmptr;
int check;
struct interface_list *ir;
if (msg.msg_controllen < sizeof(struct cmsghdr))
return;
@@ -194,29 +192,22 @@ void tftp_request(struct listener *listen, time_t now)
#ifdef HAVE_IPV6
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))
return;
}
else
#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))
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
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
return;
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0))
return;
#endif
}
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
mtu = ifr.ifr_mtu;
@@ -227,12 +218,7 @@ void tftp_request(struct listener *listen, time_t now)
/* check for per-interface prefix */
for (pref = daemon->if_prefix; pref; pref = pref->next)
if (strcmp(pref->interface, name) == 0)
prefix = pref->prefix;
/* wierd TFTP interfaces disable special options. */
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
if (strcmp(ir->interface, name) == 0)
special = 1;
prefix = pref->prefix;
}
if (listen->family == AF_INET)
@@ -311,7 +297,10 @@ void tftp_request(struct listener *listen, time_t now)
!(filename = next(&p, end)) ||
!(mode = next(&p, end)) ||
(strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff);
{
len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff);
is_err = 1;
}
else
{
if (strcasecmp(mode, "netascii") == 0)
@@ -321,8 +310,7 @@ void tftp_request(struct listener *listen, time_t now)
{
if (strcasecmp(opt, "blksize") == 0)
{
if ((opt = next(&p, end)) &&
(special || !option_bool(OPT_TFTP_NOBLOCK)))
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
{
transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1)
@@ -344,9 +332,12 @@ void tftp_request(struct listener *listen, time_t now)
}
/* cope with backslashes from windows boxen. */
while ((p = strchr(filename, '\\')))
*p = '/';
for (p = filename; *p; p++)
if (*p == '\\')
*p = '/';
else if (option_bool(OPT_TFTP_LC))
*p = tolower(*p);
strcpy(daemon->namebuff, "/");
if (prefix)
{
@@ -356,7 +347,7 @@ void tftp_request(struct listener *listen, time_t now)
if (prefix[strlen(prefix)-1] != '/')
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);
struct stat statbuf;
@@ -383,7 +374,7 @@ void tftp_request(struct listener *listen, time_t now)
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
/* check permissions and open file */
if ((transfer->file = check_tftp_fileperm(&len, prefix, special)))
if ((transfer->file = check_tftp_fileperm(&len, prefix)))
{
if ((len = get_block(packet, transfer)) == -1)
len = tftp_err_oops(packet, daemon->namebuff);
@@ -393,7 +384,7 @@ void tftp_request(struct listener *listen, time_t now)
}
while (sendto(transfer->sockfd, packet, len, 0,
(struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR);
(struct sockaddr *)&peer, sa_len(&peer)) == -1 && errno == EINTR);
if (is_err)
free_transfer(transfer);
@@ -404,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;
struct tftp_file *file;
@@ -441,7 +432,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int spe
goto perm;
}
/* 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;
/* If we're doing many tranfers from the same file, only
@@ -501,12 +492,12 @@ void check_tftp_listeners(fd_set *rset, time_t now)
{
tmp = transfer->next;
prettyprint_addr(&transfer->peer, daemon->addrbuff);
if (FD_ISSET(transfer->sockfd, rset))
{
/* we overwrote the buffer... */
daemon->srv_save = NULL;
prettyprint_addr(&transfer->peer, daemon->addrbuff);
if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
{
@@ -528,14 +519,8 @@ void check_tftp_listeners(fd_set *rset, time_t now)
if (!err)
err = "";
else
{
unsigned char *q, *r;
for (q = r = (unsigned char *)err; *r; r++)
if (isprint(*r))
*(q++) = *r;
*q = 0;
}
sanitise(err);
my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
(int)ntohs(mess->block), err,
daemon->addrbuff);
@@ -562,32 +547,33 @@ void check_tftp_listeners(fd_set *rset, time_t now)
len = tftp_err_oops(daemon->packet, transfer->file->filename);
endcon = 1;
}
else if (++transfer->backoff > 5)
/* don't complain about timeout when we're awaiting the last
ACK, some clients never send it */
else if (++transfer->backoff > 5 && len != 0)
{
/* don't complain about timeout when we're awaiting the last
ACK, some clients never send it */
if (len != 0)
{
my_syslog(MS_TFTP | LOG_ERR, _("failed sending %s to %s"),
transfer->file->filename, daemon->addrbuff);
len = 0;
endcon = 1;
}
endcon = 1;
len = 0;
}
if (len != 0)
while(sendto(transfer->sockfd, daemon->packet, len, 0,
(struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR);
(struct sockaddr *)&transfer->peer, sa_len(&transfer->peer)) == -1 && errno == EINTR);
if (endcon || len == 0)
{
if (!endcon)
my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, daemon->addrbuff);
strcpy(daemon->namebuff, transfer->file->filename);
sanitise(daemon->namebuff);
my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
/* unlink */
*up = tmp;
/* put on queue to be sent to script and deleted */
transfer->next = daemon->tftp_done_trans;
daemon->tftp_done_trans = transfer;
if (endcon)
free_transfer(transfer);
else
{
/* put on queue to be sent to script and deleted */
transfer->next = daemon->tftp_done_trans;
daemon->tftp_done_trans = transfer;
}
continue;
}
}
@@ -621,6 +607,16 @@ static char *next(char **p, char *end)
return ret;
}
static void sanitise(char *buf)
{
unsigned char *q, *r;
for (q = r = (unsigned char *)buf; *r; r++)
if (isprint((int)*r))
*(q++) = *r;
*q = 0;
}
static ssize_t tftp_err(int err, char *packet, char *message, char *file)
{
struct errmess {
@@ -629,7 +625,9 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
} *mess = (struct errmess *)packet;
ssize_t ret = 4;
char *errstr = strerror(errno);
sanitise(file);
mess->op = htons(OP_ERR);
mess->err = htons(err);
ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
@@ -640,7 +638,9 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
static ssize_t tftp_err_oops(char *packet, char *file)
{
return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file);
/* May have >1 refs to file, so potentially mangle a copy of the name */
strcpy(daemon->namebuff, file);
return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff);
}
/* return -1 for error, zero for done. */

View File

@@ -280,7 +280,7 @@ int sa_len(union mysockaddr *addr)
}
/* 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;
@@ -330,7 +330,7 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
return 0;
if (pfbits == 0 ||
(a->s6_addr[pfbytes] >> (8 - pfbits) != b->s6_addr[pfbytes] >> (8 - pfbits)))
(a->s6_addr[pfbytes] >> (8 - pfbits) == b->s6_addr[pfbytes] >> (8 - pfbits)))
return 1;
return 0;
@@ -426,7 +426,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
while (maxlen == -1 || i < maxlen)
{
for (r = in; *r != 0 && *r != ':' && *r != '-'; r++)
for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
if (*r != '*' && !isxdigit((unsigned char)*r))
return -1;
@@ -444,12 +444,29 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
else
{
*r = 0;
mask = mask << 1;
if (strcmp(in, "*") == 0)
mask |= 1;
{
mask = (mask << 1) | 1;
i++;
}
else
out[i] = strtol(in, NULL, 16);
i++;
{
int j, bytes = (1 + (r - in))/2;
for (j = 0; j < bytes; j++)
{
char sav;
if (j < bytes - 1)
{
sav = in[(j+1)*2];
in[(j+1)*2] = 0;
}
out[i] = strtol(&in[j*2], NULL, 16);
mask = mask << 1;
i++;
if (j < bytes - 1)
in[(j+1)*2] = sav;
}
}
}
}
in = r+1;