mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-13 17:00:49 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a84fa1d085 | ||
|
|
33820b7ed9 | ||
|
|
8a911ccc75 | ||
|
|
1cff166d37 |
No files matched your search
@@ -821,5 +821,144 @@ release 2.3
|
|||||||
embedded systems without a stable RTC. Oleg Vdovikin
|
embedded systems without a stable RTC. Oleg Vdovikin
|
||||||
helped work out how to make that work.
|
helped work out how to make that work.
|
||||||
|
|
||||||
|
release 2.4
|
||||||
|
Fixed inability to start when the lease file doesn't
|
||||||
|
already exist. Thanks to Dag Wieers for reporting that.
|
||||||
|
|
||||||
|
Fixed problem were dhcp-host configuration options did
|
||||||
|
not play well with entries in /etc/ethers for the same
|
||||||
|
host. Thanks again to Dag Wieers.
|
||||||
|
|
||||||
|
Tweaked DHCP code to favour moving to a newly-configured
|
||||||
|
static IP address rather than an old lease when doing
|
||||||
|
DHCP allocation.
|
||||||
|
|
||||||
|
Added --alias configuration option. This provides IPv4
|
||||||
|
rewrite facilities like Cisco "DNS doctoring". Suggested
|
||||||
|
by Chad Skeeters.
|
||||||
|
|
||||||
|
Fixed bug in /etc/ethers parsing code triggered by tab
|
||||||
|
characters. Qudos to Dag Wieers for hepling to nail that
|
||||||
|
one.
|
||||||
|
|
||||||
|
Added "bind-interfaces" option correctly.
|
||||||
|
|
||||||
|
release 2.5
|
||||||
|
Made "where are we allocating addresses?" code in DHCP
|
||||||
|
server cope with requests via a relay which is on a
|
||||||
|
directly connected network for which there is not a
|
||||||
|
configured netmask. This strange state of affairs occurs
|
||||||
|
with win4lin. Thanks to Alex Melt and Jim Horner for bug
|
||||||
|
reports and testing with this.
|
||||||
|
|
||||||
|
Fixed trivial-but-irritating missing #include which broke
|
||||||
|
compilation on *BSD.
|
||||||
|
|
||||||
|
Force --bind-interfaces if IP-aliased interface
|
||||||
|
specifications are used, since the sockets API provides
|
||||||
|
no other sane way to determine which alias of an
|
||||||
|
interface a packet was sent to. Thanks to Javier Kohen
|
||||||
|
for the bug report.
|
||||||
|
|
||||||
|
release 2.6
|
||||||
|
Support Token Ring DHCP. Thanks to Dag Wieers for help
|
||||||
|
testing. Note that Token ring support only works on Linux
|
||||||
|
currently.
|
||||||
|
|
||||||
|
Fix compilation on MacOS X. Thanks to Bernhard Ehlers for
|
||||||
|
the patch.
|
||||||
|
|
||||||
|
Added new "ignore" keyword for
|
||||||
|
dhcp-host. "dhcp-host=11:22:33:44:55:66,ignore" will
|
||||||
|
cause the DHCP server to ignore any host with the given
|
||||||
|
MAC address, leaving it to other servers on the
|
||||||
|
network. This also works with client-id and hostnames.
|
||||||
|
Suggestion by Alex Melt.
|
||||||
|
|
||||||
|
Fixed parsing of hex client IDs. Problem spotted by Peter
|
||||||
|
Fichtner.
|
||||||
|
|
||||||
|
Allow conf-file options in configuration file, to
|
||||||
|
provide an include function.
|
||||||
|
|
||||||
|
Re-read /etc/ethers on receipt of SIGHUP.
|
||||||
|
|
||||||
|
Added back the ability to read ISC dhcpd lease files, by
|
||||||
|
popular demand. Note that this is deprecated and for
|
||||||
|
backwards compatibility only. You can get back the 4K of
|
||||||
|
memory that the code occupies by undefining
|
||||||
|
"HAVE_ISC_READER" in src/config.h
|
||||||
|
|
||||||
|
Added ability to disable "pool" DHCP address allocation
|
||||||
|
whilst leaving static leases working. The syntax is
|
||||||
|
"dhcp-range=192.168.0.0,static"
|
||||||
|
Thanks to Grzegorz Nosek for the suggestion.
|
||||||
|
|
||||||
|
Generalized dnsmasq-rh.spec file to work on Mandrake too,
|
||||||
|
and removed dnsmasq-mdk.spec. Thanks to Doug Keller.
|
||||||
|
|
||||||
|
Allow DHCP options which are tied to specific static
|
||||||
|
leases in the same way as to specific networks.
|
||||||
|
|
||||||
|
Generalised the dhcp-option parser a bit to allow hex
|
||||||
|
strings as parameters. This is now legal:
|
||||||
|
dhcp-option=128,e4:45:74:68:00:00
|
||||||
|
Inspired by a patch from Joel Nordell.
|
||||||
|
|
||||||
|
Changed the semantics of argument-less dhcp-options for
|
||||||
|
the default-setting ones, ie 1, 3, 6 and 28. Now, doing
|
||||||
|
eg, dhcp-option=3 stops dnsmasq from sending a default
|
||||||
|
router option at all. Thanks to Scott Emmons for pointing
|
||||||
|
out that this is useful.
|
||||||
|
|
||||||
|
Fixed dnsmasq.conf parsing bug which interpreted port
|
||||||
|
numbers in server= lines as a comment. To start a
|
||||||
|
comment, a '#' character must now be a the start of a
|
||||||
|
line or preceded by whitespace. Thanks to Christian
|
||||||
|
Haggstrom for the bug report.
|
||||||
|
|
||||||
|
release 2.7
|
||||||
|
Allow the dhcp-host specification of id:* which makes
|
||||||
|
dnsmasq ignore any client-id. This is useful to ensure
|
||||||
|
that a dual-boot machine sees the same lease when one OS
|
||||||
|
gives a client-id and the other doesn't. It's also useful
|
||||||
|
when PXE boot DHCP does not use client IDs but the OS it boots
|
||||||
|
does. Thanks to Grzegorz Nosek for suggesting this enhancement.
|
||||||
|
|
||||||
|
No longer assume that ciaddr is zero in received DHCPDISCOVER
|
||||||
|
messages, just for security against broken clients.
|
||||||
|
|
||||||
|
Set default of siaddr field to the address of the machine running
|
||||||
|
dnsmasq when not explicitly set using dhcp-boot
|
||||||
|
option. This is the ISC dhcpd behaviour.
|
||||||
|
|
||||||
|
Send T1 and T2 options in DHCPOFFER packets. This is required
|
||||||
|
by the DHCP client in some JetDirect printers. Thanks
|
||||||
|
to Paul Mattal for work on this.
|
||||||
|
|
||||||
|
Fixed bug with DHCP on OpenBSD reported by Dominique Jacquel.
|
||||||
|
The code which added loopback interfaces to the list
|
||||||
|
was confusing the DHCP code, which expected one interface only.
|
||||||
|
Solved by adding loopback interfaces to address list instead.
|
||||||
|
|
||||||
|
Add dhcp-vendorclass option to allow options to be sent only
|
||||||
|
to certain classes of clients.
|
||||||
|
|
||||||
|
Tweaked option search code so that if a netid-qualified
|
||||||
|
option is used, any unqualified option is ignored.
|
||||||
|
|
||||||
|
Changed the method of picking new dynamic IP
|
||||||
|
addresses. This used to use the next consecutive
|
||||||
|
address as long it was free, now it uses a hash
|
||||||
|
from the client hardware address. This reduces the amount
|
||||||
|
of address movement for clients which let their lease
|
||||||
|
expire and allows consecutive DHCPOFFERS to the same host
|
||||||
|
to (almost always) be for the same address, without
|
||||||
|
storing state before a lease is granted.
|
||||||
|
|
||||||
|
Tweaked option handling code to return all possible
|
||||||
|
options rather than none when DHCP "requested options"
|
||||||
|
field is missing. This fixes interoperability with
|
||||||
|
ancient IBM LANMAN DHCP clients. Thanks to Jim Louvau for
|
||||||
|
help with this.
|
||||||
|
|
||||||
@@ -182,6 +182,41 @@ A: There are a couple of configuration gotchas which have been
|
|||||||
address 0.0.0.0 and destination address 255.255.255.255 are not
|
address 0.0.0.0 and destination address 255.255.255.255 are not
|
||||||
dropped by iptables/ipchains.
|
dropped by iptables/ipchains.
|
||||||
|
|
||||||
|
Q: I'm running Debian, and my machines get an address fine with DHCP,
|
||||||
|
but their names are not appearing in the DNS.
|
||||||
|
|
||||||
|
A: By default, none of the DHCP clients send the host-name when asking
|
||||||
|
for a lease. For most of the clients, you can set the host-name to
|
||||||
|
send with the "hostname" keyword in /etc/network/interfaces. (See
|
||||||
|
"man interfaces" for details.) That doesn't work for dhclient, were
|
||||||
|
you have to add something like "send host-name daisy" to
|
||||||
|
/etc/dhclient.conf
|
||||||
|
|
||||||
|
Q: I'm network booting my machines, and trying to give them static
|
||||||
|
DHCP-assigned addresses. The machine gets its correct address
|
||||||
|
whilst booting, but then the OS starts and it seems to get
|
||||||
|
allocated a different address.
|
||||||
|
|
||||||
|
A: What is happening is this: The boot process sends a DHCP
|
||||||
|
request and gets allocated the static address corresponding to its
|
||||||
|
MAC address. The boot loader does not send a client-id. Then the OS
|
||||||
|
starts and repeats the DHCP process, but it it does send a
|
||||||
|
client-id. Dnsmasq cannot assume that the two requests are from the
|
||||||
|
same machine (since the client ID's don't match) and even though
|
||||||
|
the MAC address has a static allocation, that address is still in
|
||||||
|
use by the first incarnation of the machine (the one from the boot,
|
||||||
|
without a client ID.) dnsmasq therefore has to give the machine a
|
||||||
|
dynamic address from its pool. There are two ways to solve this:
|
||||||
|
(1) persuade your DHCP client not to send a client ID, or (2) set up
|
||||||
|
the static assignment to the client ID, not the MAC address. The
|
||||||
|
default client-id will be 01:<MAC address>, so change the dhcp-host
|
||||||
|
line from "dhcp-host=11:22:33:44:55:66,1.2.3.4" to
|
||||||
|
"dhcp-host=id:01:11:22:33:44:55:66,1.2.3.4"
|
||||||
|
|
||||||
|
Q: What network types are supported by the DHCP server?
|
||||||
|
|
||||||
|
A: Ethernet (and 802.11 wireless) are supported on all platforms. On
|
||||||
|
Linux Token Ring is also supported.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -7,9 +7,11 @@ Version 1.x of dnsmasq includes a facility for reading the dhcp.leases
|
|||||||
file written by ISC dhcpd. This allows the names of machines which
|
file written by ISC dhcpd. This allows the names of machines which
|
||||||
have addresses allocated by DHCP to be included in the DNS.
|
have addresses allocated by DHCP to be included in the DNS.
|
||||||
|
|
||||||
Version 2.x of dnsmasq removes the ISC dhcpd integration and replaces
|
Version 2.x of dnsmasq replaces the ISC dhcpd integration with a DHCP
|
||||||
it with a DHCP server integrated into dnsmasq. This is an incompatible
|
server integrated into dnsmasq. Versions 2.0-2.5 removed the ISC
|
||||||
change in dnsmasq but it has the following advantages:
|
integration completely, but in version 2.6 it was re-enabled for
|
||||||
|
backwards compatibility purposes. The change to an integrated DHCP
|
||||||
|
server has the following advantages:
|
||||||
|
|
||||||
* Small. ISC dhcpd is a large and comprehensive DHCP solution. The
|
* Small. ISC dhcpd is a large and comprehensive DHCP solution. The
|
||||||
dnsmasq DHCP server adds about 15k to DNS-only dnsmasq and provides
|
dnsmasq DHCP server adds about 15k to DNS-only dnsmasq and provides
|
||||||
@@ -29,7 +31,6 @@ change in dnsmasq but it has the following advantages:
|
|||||||
with the dnsmasq DHCP server.
|
with the dnsmasq DHCP server.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DHCP configuration
|
DHCP configuration
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
@@ -56,8 +57,8 @@ Having started dnsmasq, tell any hosts on the network to renew their
|
|||||||
DHCP lease, so that dnsmasq's DHCP server becomes aware of them. For
|
DHCP lease, so that dnsmasq's DHCP server becomes aware of them. For
|
||||||
Linux, this is best done by killing-and-restarting the DHCP client
|
Linux, this is best done by killing-and-restarting the DHCP client
|
||||||
daemon or taking the network interface down and then back up. For
|
daemon or taking the network interface down and then back up. For
|
||||||
Windows use winipcfg.exe
|
Windows 9x/Me, use the graphical tool "winipcfg". For Windows
|
||||||
|
NT/2000/XP, use the command-line "ipconfig /renew"
|
||||||
|
|
||||||
For more complex DHCP configuration, refer to the doc/setup.html, the
|
For more complex DHCP configuration, refer to the doc/setup.html, the
|
||||||
dnsmasq manpage and the annotated example configuration file. Also
|
dnsmasq manpage and the annotated example configuration file. Also
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# General mumbojumbo
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Name: dnsmasq
|
|
||||||
Version: 2.3
|
|
||||||
Release: 1
|
|
||||||
Copyright: GPL
|
|
||||||
Group: System Environment/Daemons
|
|
||||||
Vendor: Simon Kelley
|
|
||||||
Packager: Simon Kelley
|
|
||||||
Distribution: Mandrake Linux
|
|
||||||
URL: http://www.thekelleys.org.uk/dnsmasq
|
|
||||||
Source0: %{name}-%{version}.tar.gz
|
|
||||||
Requires: chkconfig
|
|
||||||
BuildRoot: /var/tmp/%{name}-%{version}
|
|
||||||
Summary: A lightweight caching nameserver
|
|
||||||
|
|
||||||
%description
|
|
||||||
Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. It
|
|
||||||
is designed to provide DNS and, optionally, DHCP, to a small network. It can
|
|
||||||
serve the names of local machines which are not in the global DNS. The DHCP
|
|
||||||
server integrates with the DNS server and allows machines with DHCP-allocated
|
|
||||||
addresses to appear in the DNS with names configured either in each host or
|
|
||||||
in a central configuration file. Dnsmasq supports static and dynamic DHCP
|
|
||||||
leases and BOOTP for network booting of diskless machines.
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Build
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%setup -q
|
|
||||||
%build
|
|
||||||
make
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Install
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%install
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
|
|
||||||
mkdir -p -m 755 $RPM_BUILD_ROOT/usr/sbin
|
|
||||||
mkdir -p -m 755 $RPM_BUILD_ROOT/etc/rc.d/init.d
|
|
||||||
mkdir -p -m 755 $RPM_BUILD_ROOT/usr/share/man/man8
|
|
||||||
|
|
||||||
cp rpm/dnsmasq.rh $RPM_BUILD_ROOT/etc/rc.d/init.d/dnsmasq
|
|
||||||
strip src/dnsmasq
|
|
||||||
cp src/dnsmasq $RPM_BUILD_ROOT/usr/sbin
|
|
||||||
cp dnsmasq.8 $RPM_BUILD_ROOT/usr/share/man/man8
|
|
||||||
cp dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Clean up
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%clean
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Post-install scriptlet
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%post
|
|
||||||
/sbin/chkconfig --add dnsmasq
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Pre-uninstall scriptlet
|
|
||||||
#
|
|
||||||
# If there's a time when your package needs to have one last look around before
|
|
||||||
# the user erases it, the place to do it is in the %preun script. Anything that
|
|
||||||
# a package needs to do immediately prior to RPM taking any action to erase the
|
|
||||||
# package, can be done here.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%preun
|
|
||||||
if [ $1 = 0 ]; then # execute this only if we are NOT doing an upgrade
|
|
||||||
service dnsmasq stop >/dev/null 2>&1
|
|
||||||
/sbin/chkconfig --del dnsmasq
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Post-uninstall scriptlet
|
|
||||||
#
|
|
||||||
# The %postun script executes after the package has been removed. It is the
|
|
||||||
# last chance for a package to clean up after itself.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%postun
|
|
||||||
if [ "$1" -ge "1" ]; then
|
|
||||||
service dnsmasq restart >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# File list
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%files
|
|
||||||
%defattr(-,root,root)
|
|
||||||
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0
|
|
||||||
%attr(0755,root,root) /etc/rc.d/init.d/dnsmasq
|
|
||||||
%attr(0664,root,root) /etc/dnsmasq.conf
|
|
||||||
%config /etc/rc.d/init.d/dnsmasq
|
|
||||||
%config /etc/dnsmasq.conf
|
|
||||||
%attr(0755,root,root) /usr/sbin/dnsmasq
|
|
||||||
%attr(0644,root,root) /usr/share/man/man8/dnsmasq.8.bz2
|
|
||||||
|
|
||||||
|
|
||||||
+2
-3
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.3
|
Version: 2.7
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
@@ -58,7 +58,6 @@ cp rpm/dnsmasq.rh $RPM_BUILD_ROOT/etc/rc.d/init.d/dnsmasq
|
|||||||
strip src/dnsmasq
|
strip src/dnsmasq
|
||||||
cp src/dnsmasq $RPM_BUILD_ROOT/usr/sbin
|
cp src/dnsmasq $RPM_BUILD_ROOT/usr/sbin
|
||||||
cp dnsmasq.8 $RPM_BUILD_ROOT/usr/share/man/man8
|
cp dnsmasq.8 $RPM_BUILD_ROOT/usr/share/man/man8
|
||||||
gzip $RPM_BUILD_ROOT/usr/share/man/man8/dnsmasq.8
|
|
||||||
cp dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
|
cp dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -128,6 +127,6 @@ fi
|
|||||||
%attr(0755,root,root) /etc/rc.d/init.d/dnsmasq
|
%attr(0755,root,root) /etc/rc.d/init.d/dnsmasq
|
||||||
%attr(0664,root,root) /etc/dnsmasq.conf
|
%attr(0664,root,root) /etc/dnsmasq.conf
|
||||||
%attr(0755,root,root) /usr/sbin/dnsmasq
|
%attr(0755,root,root) /usr/sbin/dnsmasq
|
||||||
%attr(0644,root,root) /usr/share/man/man8/dnsmasq.8.gz
|
%attr(0644,root,root) /usr/share/man/man8/dnsmasq*
|
||||||
|
|
||||||
|
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.3
|
Version: 2.7
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: Productivity/Networking/DNS/Servers
|
Group: Productivity/Networking/DNS/Servers
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ is lightweight and easy to configure. It is intended as be run on
|
|||||||
small router/firewalls and provide a DNS (and optionally, DHCP) service to a LAN.
|
small router/firewalls and provide a DNS (and optionally, DHCP) service to a LAN.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
Note that in general missing parameters are allowed and switch off
|
Note that in general missing parameters are allowed and switch off
|
||||||
functions, for instance "--pid-file=" disables writing a PID file.
|
functions, for instance "--pid-file=" disables writing a PID file. On
|
||||||
|
BSD, unless the GNU getopt library is linked, the long form of the
|
||||||
|
options does not work on the command line; it is still recognised in
|
||||||
|
the configuration file.
|
||||||
.TP
|
.TP
|
||||||
.B \-h, --no-hosts
|
.B \-h, --no-hosts
|
||||||
Don't read the hostnames in /etc/hosts.
|
Don't read the hostnames in /etc/hosts.
|
||||||
@@ -82,7 +85,14 @@ flags are given, dnsmasq listens on all available interfaces unless overridden b
|
|||||||
.B \-a
|
.B \-a
|
||||||
or
|
or
|
||||||
.B \-I
|
.B \-I
|
||||||
flags.
|
flags. If IP alias interfaces (eg "eth1:0") are used with
|
||||||
|
.B --interface
|
||||||
|
or
|
||||||
|
.B --except-interface
|
||||||
|
options, then the
|
||||||
|
.B --bind-interfaces
|
||||||
|
option will be automatically set. This is required for deeply boring
|
||||||
|
sockets-API reasons.
|
||||||
.TP
|
.TP
|
||||||
.B \-I, --except-interface=<interface name>
|
.B \-I, --except-interface=<interface name>
|
||||||
Do not listen on the specified interface.
|
Do not listen on the specified interface.
|
||||||
@@ -108,12 +118,22 @@ requests that it shouldn't reply to. This has the advantage of
|
|||||||
working even when interfaces come and go and change address. This
|
working even when interfaces come and go and change address. This
|
||||||
option forces dnsmasq to really bind only the interfaces it is
|
option forces dnsmasq to really bind only the interfaces it is
|
||||||
listening on. About the only time when this is useful is when
|
listening on. About the only time when this is useful is when
|
||||||
running another nameserver on the same machine.
|
running another nameserver on the same machine or using IP
|
||||||
|
alias. Specifying interfaces with IP alias automatically turns this
|
||||||
|
option on.
|
||||||
.TP
|
.TP
|
||||||
.B \-b, --bogus-priv
|
.B \-b, --bogus-priv
|
||||||
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
|
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
|
||||||
which are not found in /etc/hosts or the DHCP leases file are resolved to the IP address in dotted-quad form.
|
which are not found in /etc/hosts or the DHCP leases file are resolved to the IP address in dotted-quad form.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-V, --alias=<old-ip>,<new-ip>[,<mask>]
|
||||||
|
Modify IPv4 addresses returned from upstream nameservers; old-ip is
|
||||||
|
replaced by new-ip. If the optional mask is given then any address
|
||||||
|
which matches the masked old-ip will be re-written. So, for instance
|
||||||
|
.B --alias=1.2.3.0,6.7.8.0,255.255.255.0
|
||||||
|
will map 1.2.3.56 to 6.7.8.56 and 1.2.3.67 to 6.7.8.67. This is what
|
||||||
|
Cisco PIX routers call "DNS doctoring".
|
||||||
|
.TP
|
||||||
.B \-B, --bogus-nxdomain=<ipaddr>
|
.B \-B, --bogus-nxdomain=<ipaddr>
|
||||||
Transform replies which contain the IP address given into "No such
|
Transform replies which contain the IP address given into "No such
|
||||||
domain" replies. This is intended to counteract a devious move made by
|
domain" replies. This is intended to counteract a devious move made by
|
||||||
@@ -254,9 +274,16 @@ given using the
|
|||||||
.B interface
|
.B interface
|
||||||
option. This limitation currently affects OpenBSD. The optional
|
option. This limitation currently affects OpenBSD. The optional
|
||||||
network-id is a alphanumeric label which marks this network so that
|
network-id is a alphanumeric label which marks this network so that
|
||||||
dhcp options may be specified on a per-network basis.
|
dhcp options may be specified on a per-network basis. The end address
|
||||||
|
may be replaced by the keyword
|
||||||
|
.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.
|
||||||
.TP
|
.TP
|
||||||
.B \-G, --dhcp-host=[[<hwaddr>]|[id:<client_id>]][,<ipaddr>][,<hostname>][,<lease_time>]
|
.B \-G, --dhcp-host=[[<hwaddr>]|[id:[<client_id>][*]]][net:<netid>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||||
Specify per host parameters for the DHCP server. This allows a machine
|
Specify per host parameters for the DHCP server. This allows a machine
|
||||||
with a particular hardware address to be always allocated the same
|
with a particular hardware address to be always allocated the same
|
||||||
hostname, IP address and lease time. A hostname specified like this
|
hostname, IP address and lease time. A hostname specified like this
|
||||||
@@ -279,10 +306,22 @@ hardware addresses to identify hosts by prefixing with 'id:'. Thus:
|
|||||||
refers to the host with client identifier 01:02:03:04. It is also
|
refers to the host with client identifier 01:02:03:04. It is also
|
||||||
allowed to specify the client ID as text, like this:
|
allowed to specify the client ID as text, like this:
|
||||||
.B --dhcp-host=id:clientidastext,.....
|
.B --dhcp-host=id:clientidastext,.....
|
||||||
|
The special option id:* means "ignore any client-id
|
||||||
|
and use MAC addresses only." This is useful when a client presents a client-id sometimes
|
||||||
|
but not others.
|
||||||
If a name appears in /etc/hosts, the associated address can be
|
If a name appears in /etc/hosts, the associated address can be
|
||||||
allocated to a DHCP lease, but only if a
|
allocated to a DHCP lease, but only if a
|
||||||
.B --dhcp-host
|
.B --dhcp-host
|
||||||
option specifying the name also exists.
|
option specifying the name also exists. The special keyword "ignore"
|
||||||
|
tells dnsmasq to never offer a DHCP lease to a machine. The machine
|
||||||
|
can be specified by hardware address, client ID or hostname, for
|
||||||
|
instance
|
||||||
|
.B --dhcp-host=00:20:e0:3b:13:af,ignore
|
||||||
|
This is
|
||||||
|
useful when there is another DHCP server on the network which should
|
||||||
|
be used by some machines. The net:<network-id> parameter enables DHCP options just
|
||||||
|
for this host in the same way as the the network-id in
|
||||||
|
.B dhcp-range.
|
||||||
.TP
|
.TP
|
||||||
.B \-Z, --read-ethers
|
.B \-Z, --read-ethers
|
||||||
Read /etc/ethers for information about hosts for the DHCP server. The
|
Read /etc/ethers for information about hosts for the DHCP server. The
|
||||||
@@ -304,9 +343,11 @@ specfied in RFC2132. For example, to set the default route option to
|
|||||||
192.168.4.4, do
|
192.168.4.4, do
|
||||||
.B --dhcp-option=3,192.168.4.4
|
.B --dhcp-option=3,192.168.4.4
|
||||||
and to set the time-server address to 192.168.0.4, do
|
and to set the time-server address to 192.168.0.4, do
|
||||||
.B dhcp-option=42,192.168.0.4
|
.B --dhcp-option=42,192.168.0.4
|
||||||
The special address 0.0.0.0 is taken to mean "the address of the
|
The special address 0.0.0.0 is taken to mean "the address of the
|
||||||
machine running dnsmasq". If the optional network-id is given then
|
machine running dnsmasq". Data types allowed are comma seperated
|
||||||
|
dotted-quad IP addresses, a decimal number, colon-seperated hex digits
|
||||||
|
and a text string. If the optional network-id is given then
|
||||||
this option is only sent to machines on the network whose dhcp-range
|
this option is only sent to machines on the network whose dhcp-range
|
||||||
contains a matching network-id.
|
contains a matching network-id.
|
||||||
Be careful: no checking is done that the correct type of data for the
|
Be careful: no checking is done that the correct type of data for the
|
||||||
@@ -315,6 +356,15 @@ possible to generate the correct data type; it is quite possible to
|
|||||||
persuade dnsmasq to generate illegal DHCP packets with injudicious use
|
persuade dnsmasq to generate illegal DHCP packets with injudicious use
|
||||||
of this flag.
|
of this flag.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-U, --dhcp-vendorclass=<network-id>,<vendor-class>
|
||||||
|
Map from a vendor-class string to a network id. Most DHCP clients provide a
|
||||||
|
"vendor class" which represents, in some sense, the type of host. This options
|
||||||
|
maps vendor classes to network ids, so that DHCP options may be selectively delivered
|
||||||
|
to different classes of hosts. For example
|
||||||
|
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
|
||||||
|
will allow options to be set only for HP printers like so:
|
||||||
|
.B --dhcp-option=printers,3,192.168.4.4
|
||||||
|
.TP
|
||||||
.B \-M, --dhcp-boot=<filename>,[<servername>[,<server address>]]
|
.B \-M, --dhcp-boot=<filename>,[<servername>[,<server address>]]
|
||||||
Set BOOTP options to be returned by the DHCP server. These are needed
|
Set BOOTP options to be returned by the DHCP server. These are needed
|
||||||
for machines which network boot, and tell the machine where to collect
|
for machines which network boot, and tell the machine where to collect
|
||||||
@@ -327,7 +377,12 @@ create thousands of leases and use lots of memory in the dnsmasq
|
|||||||
process.
|
process.
|
||||||
.TP
|
.TP
|
||||||
.B \-l, --dhcp-leasefile=<path>
|
.B \-l, --dhcp-leasefile=<path>
|
||||||
Use the specified file to store DHCP lease information.
|
Use the specified file to store DHCP lease information. If this option
|
||||||
|
is given but no dhcp-range option is given then dnsmasq version 1
|
||||||
|
behaviour is activated. The file given is assumed to be an ISC dhcpd
|
||||||
|
lease file and parsed for leases which are then added to the DNS
|
||||||
|
system if they have a hostname. This functionality may have been
|
||||||
|
excluded from dnsmasq at compile time, in which case an error will occur.
|
||||||
.TP
|
.TP
|
||||||
.B \-s, --domain=<domain>
|
.B \-s, --domain=<domain>
|
||||||
Specifies the domain for the DHCP server. This has two effects;
|
Specifies the domain for the DHCP server. This has two effects;
|
||||||
@@ -344,12 +399,14 @@ Add the domain-suffix to simple names (without a period) in /etc/hosts
|
|||||||
in the same way as for DHCP-derived names.
|
in the same way as for DHCP-derived names.
|
||||||
.SH CONFIG FILE
|
.SH CONFIG FILE
|
||||||
At startup, dnsmasq reads /etc/dnsmasq.conf, if it exists. (On
|
At startup, dnsmasq reads /etc/dnsmasq.conf, if it exists. (On
|
||||||
FreeBSD, the file is /usr/local/etc/dnsmasq.conf) The format of this
|
FreeBSD and OpenBSD, the file is /usr/local/etc/dnsmasq.conf) The format of this
|
||||||
file consists of one option per line, exactly as the long options detailed
|
file consists of one option per line, exactly as the long options detailed
|
||||||
in the OPTIONS section but without the leading "--". Lines starting with # are comments and ignored. For
|
in the OPTIONS section but without the leading "--". Lines starting with # are comments and ignored. For
|
||||||
options which may only be specified once, the configuration file overrides
|
options which may only be specified once, the configuration file overrides
|
||||||
the command line. Use the --conf-file option to specify a different
|
the command line. Use the --conf-file option to specify a different
|
||||||
configuration file.
|
configuration file. The conf-file option is also allowed in
|
||||||
|
configuration files, to include multiple configuration files. Only one
|
||||||
|
level of nesting is allowed.
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
When it receives a SIGHUP,
|
When it receives a SIGHUP,
|
||||||
.B dnsmasq
|
.B dnsmasq
|
||||||
|
|||||||
@@ -157,6 +157,20 @@ filterwin2k
|
|||||||
# it asks for a DHCP lease.
|
# it asks for a DHCP lease.
|
||||||
#dhcp-host=judge
|
#dhcp-host=judge
|
||||||
|
|
||||||
|
# Never offer DHCP service to a machine whose ethernet
|
||||||
|
# address is 11:22:33:44:55:66
|
||||||
|
#dhcp-host=11:22:33:44:55:66,ignore
|
||||||
|
|
||||||
|
# Ignore any client-id presented by the machine with ethernet
|
||||||
|
# address 11:22:33:44:55:66. This is useful to prevent a machine
|
||||||
|
# being treated differently when running under different OS's or
|
||||||
|
# between PXE boot and OS boot.
|
||||||
|
#dhcp-host=11:22:33:44:55:66,id:*
|
||||||
|
|
||||||
|
# Send extra options which are tagged as "red" to
|
||||||
|
# the machine with ethernet address 11:22:33:44:55:66
|
||||||
|
#dhcp-host=11:22:33:44:55:66,net:red
|
||||||
|
|
||||||
# If this line is uncommented, dnsmasq will read /etc/ethers and act
|
# If this line is uncommented, dnsmasq will read /etc/ethers and act
|
||||||
# on the ethernet-address/IP pairs found there just as if they had
|
# on the ethernet-address/IP pairs found there just as if they had
|
||||||
# been given as --dhcp-host options. Useful if you keep
|
# been given as --dhcp-host options. Useful if you keep
|
||||||
@@ -193,6 +207,10 @@ filterwin2k
|
|||||||
# Set the "all subnets are local" flag
|
# Set the "all subnets are local" flag
|
||||||
#dhcp-option=27,1
|
#dhcp-option=27,1
|
||||||
|
|
||||||
|
# Send the etherboot magic flag and then etherboot options (a string).
|
||||||
|
#dhcp-option=128,e4:45:74:68:00:00
|
||||||
|
#dhcp-option=129,NIC=eepro100
|
||||||
|
|
||||||
# Specify an option which will only be sent to the "red" network
|
# Specify an option which will only be sent to the "red" network
|
||||||
# (see dhcp-range for the declaration of the "red" network)
|
# (see dhcp-range for the declaration of the "red" network)
|
||||||
#dhcp-option=red,42,192.168.1.1
|
#dhcp-option=red,42,192.168.1.1
|
||||||
@@ -243,10 +261,19 @@ filterwin2k
|
|||||||
# registries which have implemented wildcard A records.
|
# registries which have implemented wildcard A records.
|
||||||
#bogus-nxdomain=64.94.110.11
|
#bogus-nxdomain=64.94.110.11
|
||||||
|
|
||||||
|
# If you want to fix up DNS results from upstream servers, use the
|
||||||
|
# alias option. This only works for IPv4.
|
||||||
|
# This alias makes a result of 1.2.3.4 appear as 5.6.7.8
|
||||||
|
#alias=1.2.3.4,5.6.7.8
|
||||||
|
# and this maps 1.2.3.x to 5.6.7.x
|
||||||
|
#alias=1.2.3.0,5.6.7.0,255.255.255.0
|
||||||
|
|
||||||
# For debugging purposes, log each DNS query as it passes through
|
# For debugging purposes, log each DNS query as it passes through
|
||||||
# dnsmasq.
|
# dnsmasq.
|
||||||
#log-queries
|
#log-queries
|
||||||
|
|
||||||
|
# Include a another lot of configuration options.
|
||||||
|
#conf-file=/etc/dnsmasq.more.conf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
CFLAGS?= -O2
|
CFLAGS?= -O2
|
||||||
|
|
||||||
OBJS = cache.o rfc1035.o util.o option.o forward.o \
|
OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o \
|
||||||
network.o dnsmasq.o dhcp.o lease.o rfc2131.o
|
network.o dnsmasq.o dhcp.o lease.o rfc2131.o
|
||||||
|
|
||||||
.c.o: dnsmasq.h config.h
|
.c.o: dnsmasq.h config.h
|
||||||
|
|||||||
+3
-3
@@ -641,7 +641,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
|
|||||||
if (crec->flags & F_HOSTS)
|
if (crec->flags & F_HOSTS)
|
||||||
{
|
{
|
||||||
if (crec->addr.addr.addr4.s_addr != host_address->s_addr)
|
if (crec->addr.addr.addr4.s_addr != host_address->s_addr)
|
||||||
syslog(LOG_WARNING, "Not naming DHCP lease for %s because it clashes with an /etc/hosts entry.", host_name);
|
syslog(LOG_WARNING, "not naming DHCP lease for %s because it clashes with an /etc/hosts entry.", host_name);
|
||||||
}
|
}
|
||||||
else if (!(crec->flags & F_DHCP))
|
else if (!(crec->flags & F_DHCP))
|
||||||
{
|
{
|
||||||
@@ -653,7 +653,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
|
|||||||
goto newrec;
|
goto newrec;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
syslog(LOG_WARNING, "Not naming DHCP lease for %s because it clashes with a cached name.", cache_get_name(crec));
|
syslog(LOG_WARNING, "not naming DHCP lease for %s because it clashes with a cached name.", cache_get_name(crec));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -686,7 +686,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
|
|||||||
|
|
||||||
void dump_cache(int debug, int cache_size)
|
void dump_cache(int debug, int cache_size)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Cache size %d, %d/%d cache insertions re-used unexpired cache entries.",
|
syslog(LOG_INFO, "cache size %d, %d/%d cache insertions re-used unexpired cache entries.",
|
||||||
cache_size, cache_live_freed, cache_inserted);
|
cache_size, cache_live_freed, cache_inserted);
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
|
|||||||
+18
-1
@@ -12,12 +12,13 @@
|
|||||||
|
|
||||||
/* Author's email: simon@thekelleys.org.uk */
|
/* Author's email: simon@thekelleys.org.uk */
|
||||||
|
|
||||||
#define VERSION "2.3"
|
#define VERSION "2.7"
|
||||||
|
|
||||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||||
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */
|
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */
|
||||||
#define LOGRATE 120 /* log table overflows every LOGRATE seconds */
|
#define LOGRATE 120 /* log table overflows every LOGRATE seconds */
|
||||||
#define CACHESIZ 150 /* default cache size */
|
#define CACHESIZ 150 /* default cache size */
|
||||||
|
#define MAXTOK 50 /* token in DHCP leases */
|
||||||
#define MAXLEASES 150 /* maximum number of DHCP leases */
|
#define MAXLEASES 150 /* maximum number of DHCP leases */
|
||||||
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
||||||
#define HOSTSFILE "/etc/hosts"
|
#define HOSTSFILE "/etc/hosts"
|
||||||
@@ -121,6 +122,10 @@ HAVE_BROKEN_RTC
|
|||||||
work on other systems by teaching dnsmasq_time() in utils.c how to
|
work on other systems by teaching dnsmasq_time() in utils.c how to
|
||||||
read the system uptime.
|
read the system uptime.
|
||||||
|
|
||||||
|
HAVE_ISC_READER
|
||||||
|
define this to include the old ISC dhcpcd integration. Note that you cannot
|
||||||
|
set both HAVE_ISC_READER and HAVE_BROKEN_RTC.
|
||||||
|
|
||||||
HAVE_GETOPT_LONG
|
HAVE_GETOPT_LONG
|
||||||
define this if you have GNU libc or GNU getopt.
|
define this if you have GNU libc or GNU getopt.
|
||||||
|
|
||||||
@@ -175,6 +180,16 @@ NOTES:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* platform independent options. */
|
||||||
|
#undef HAVE_BROKEN_RTC
|
||||||
|
#define HAVE_ISC_READER
|
||||||
|
|
||||||
|
#if defined(HAVE_BROKEN_RTC) && defined(HAVE_ISC_READER)
|
||||||
|
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* platform dependent options. */
|
||||||
|
|
||||||
/* Must preceed __linux__ since uClinux defines __linux__ too. */
|
/* Must preceed __linux__ since uClinux defines __linux__ too. */
|
||||||
#if defined(__uClinux__) || defined(__UCLIBC__)
|
#if defined(__uClinux__) || defined(__UCLIBC__)
|
||||||
#undef HAVE_LINUX_IPV6_PROC
|
#undef HAVE_LINUX_IPV6_PROC
|
||||||
@@ -255,6 +270,7 @@ typedef unsigned long in_addr_t;
|
|||||||
#define HAVE_SOCKADDR_SA_LEN
|
#define HAVE_SOCKADDR_SA_LEN
|
||||||
#undef HAVE_PSELECT
|
#undef HAVE_PSELECT
|
||||||
#define HAVE_BPF
|
#define HAVE_BPF
|
||||||
|
#define BIND_8_COMPAT
|
||||||
/* Define before sys/socket.h is included so we get socklen_t */
|
/* Define before sys/socket.h is included so we get socklen_t */
|
||||||
#define _BSD_SOCKLEN_T_
|
#define _BSD_SOCKLEN_T_
|
||||||
/* The two below are not defined in Mac OS X arpa/nameserv.h */
|
/* The two below are not defined in Mac OS X arpa/nameserv.h */
|
||||||
@@ -287,3 +303,4 @@ typedef unsigned long in_addr_t;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+148
-63
@@ -21,7 +21,7 @@ void dhcp_init(int *fdp, int* rfdp)
|
|||||||
int opt = 1;
|
int opt = 1;
|
||||||
|
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
die ("Cannot create DHCP socket : %s", NULL);
|
die ("cannot create DHCP socket : %s", NULL);
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
||||||
#if defined(IP_PKTINFO)
|
#if defined(IP_PKTINFO)
|
||||||
@@ -49,11 +49,11 @@ void dhcp_init(int *fdp, int* rfdp)
|
|||||||
if ((fd = open(filename, O_RDWR, 0)) != -1)
|
if ((fd = open(filename, O_RDWR, 0)) != -1)
|
||||||
break;
|
break;
|
||||||
if (errno != EBUSY)
|
if (errno != EBUSY)
|
||||||
die("Cannot create DHCP BPF socket: %s", NULL);
|
die("cannot create DHCP BPF socket: %s", NULL);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_IP))) == -1)
|
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_IP))) == -1)
|
||||||
die("Cannot create DHCP packet socket: %s", NULL);
|
die("cannot create DHCP packet socket: %s", NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*rfdp = fd;
|
*rfdp = fd;
|
||||||
@@ -61,6 +61,7 @@ void dhcp_init(int *fdp, int* rfdp)
|
|||||||
|
|
||||||
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
time_t now, char *namebuff, char *domain_suffix,
|
time_t now, char *namebuff, char *domain_suffix,
|
||||||
char *dhcp_file, char *dhcp_sname,
|
char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
||||||
@@ -75,7 +76,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
struct iovec iov[2];
|
struct iovec iov[2];
|
||||||
struct cmsghdr *cmptr;
|
struct cmsghdr *cmptr;
|
||||||
int sz, newlen, iface_index = 0;
|
int sz, newlen, iface_index = 0;
|
||||||
struct in_addr source, real_netmask, iface_addr, netmask_save, broadcast_save;
|
struct in_addr source, iface_netmask, iface_addr, iface_broadcast;
|
||||||
|
struct in_addr netmask_save, broadcast_save, router;
|
||||||
#ifdef HAVE_BPF
|
#ifdef HAVE_BPF
|
||||||
unsigned char iface_hwaddr[ETHER_ADDR_LEN];
|
unsigned char iface_hwaddr[ETHER_ADDR_LEN];
|
||||||
#endif
|
#endif
|
||||||
@@ -112,7 +114,8 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
|
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||||
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
|
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
|
||||||
|
|
||||||
if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name))
|
if (!(ifr.ifr_ifindex = iface_index) ||
|
||||||
|
ioctl(dhcp_fd, SIOCGIFNAME, &ifr) == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#elif defined(IP_RECVIF)
|
#elif defined(IP_RECVIF)
|
||||||
@@ -170,16 +173,29 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
else use the address of the interface is arrived on. */
|
else use the address of the interface is arrived on. */
|
||||||
source = mess->giaddr.s_addr ? mess->giaddr : iface_addr;
|
source = mess->giaddr.s_addr ? mess->giaddr : iface_addr;
|
||||||
|
|
||||||
|
iface_netmask.s_addr = 0;
|
||||||
|
iface_broadcast.s_addr = 0;
|
||||||
|
|
||||||
|
if (ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1)
|
||||||
|
{
|
||||||
|
iface_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||||
|
/* we can use the interface netmask if either the packet came direct,
|
||||||
|
or it came via a relay listening on the same network. This sounds unlikely,
|
||||||
|
but it happens with win4lin. */
|
||||||
|
if (!is_same_net(source, iface_addr, iface_netmask))
|
||||||
|
iface_netmask.s_addr = 0;
|
||||||
|
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
|
||||||
|
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for (context = contexts; context; context = context->next)
|
for (context = contexts; context; context = context->next)
|
||||||
{
|
{
|
||||||
if (!context->netmask.s_addr && !mess->giaddr.s_addr && ioctl(dhcp_fd, SIOCGIFNETMASK, &ifr) != -1)
|
struct in_addr netmask = context->netmask.s_addr ? context->netmask : iface_netmask;
|
||||||
real_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
|
||||||
else
|
|
||||||
real_netmask = context->netmask;
|
|
||||||
|
|
||||||
if (real_netmask.s_addr &&
|
if (netmask.s_addr &&
|
||||||
(source.s_addr & real_netmask.s_addr) == (context->start.s_addr & real_netmask.s_addr) &&
|
is_same_net(source, context->start, netmask) &&
|
||||||
(source.s_addr & real_netmask.s_addr) == (context->end.s_addr & real_netmask.s_addr))
|
is_same_net(source, context->end, netmask))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,26 +208,34 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
netmask_save = context->netmask;
|
netmask_save = context->netmask;
|
||||||
broadcast_save = context->broadcast;
|
broadcast_save = context->broadcast;
|
||||||
|
|
||||||
context->netmask = real_netmask;
|
if (!context->netmask.s_addr)
|
||||||
|
context->netmask = iface_netmask;
|
||||||
|
|
||||||
if (!context->broadcast.s_addr)
|
if (!context->broadcast.s_addr)
|
||||||
{
|
{
|
||||||
if (mess->giaddr.s_addr)
|
if (iface_broadcast.s_addr)
|
||||||
context->broadcast.s_addr = (mess->giaddr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr;
|
context->broadcast = iface_broadcast;
|
||||||
else if (ioctl(dhcp_fd, SIOCGIFBRDADDR, &ifr) != -1)
|
|
||||||
context->broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
|
||||||
else
|
else
|
||||||
context->broadcast.s_addr = (iface_addr.s_addr & real_netmask.s_addr) | ~real_netmask.s_addr;
|
context->broadcast.s_addr = (source.s_addr & context->netmask.s_addr) | ~context->netmask.s_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(dhcp_fd, SIOCGIFMTU, &ifr) == -1)
|
if (ioctl(dhcp_fd, SIOCGIFMTU, &ifr) == -1)
|
||||||
ifr.ifr_mtu = ETHERMTU;
|
ifr.ifr_mtu = ETHERMTU;
|
||||||
|
|
||||||
|
/* Normally, we set the default route to point to the machine which is getting the
|
||||||
|
DHCP broadcast, either this machine or a relay. In the special case that the relay
|
||||||
|
is on the same network as us, we set the default route to us, not the relay.
|
||||||
|
This is the win4lin scenario again. */
|
||||||
|
if (is_same_net(source, iface_addr, context->netmask))
|
||||||
|
router = iface_addr;
|
||||||
|
else
|
||||||
|
router = source;
|
||||||
|
|
||||||
lease_prune(NULL, now); /* lose any expired leases */
|
lease_prune(NULL, now); /* lose any expired leases */
|
||||||
newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu,
|
newlen = dhcp_reply(context, iface_addr, ifr.ifr_name, ifr.ifr_mtu,
|
||||||
rawpacket, sz, now, namebuff,
|
rawpacket, sz, now, namebuff,
|
||||||
dhcp_opts, dhcp_configs, domain_suffix, dhcp_file,
|
dhcp_opts, dhcp_configs, vendors, domain_suffix,
|
||||||
dhcp_sname, dhcp_next_server);
|
dhcp_file, dhcp_sname, dhcp_next_server, router);
|
||||||
lease_update_file(0, now);
|
lease_update_file(0, now);
|
||||||
lease_update_dns();
|
lease_update_dns();
|
||||||
|
|
||||||
@@ -327,7 +351,6 @@ void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int address_available(struct dhcp_context *context, struct in_addr taddr)
|
int address_available(struct dhcp_context *context, struct in_addr taddr)
|
||||||
{
|
{
|
||||||
/* Check is an address is OK for this network, ie
|
/* Check is an address is OK for this network, ie
|
||||||
@@ -339,6 +362,10 @@ int address_available(struct dhcp_context *context, struct in_addr taddr)
|
|||||||
start = ntohl(context->start.s_addr);
|
start = ntohl(context->start.s_addr);
|
||||||
end = ntohl(context->end.s_addr);
|
end = ntohl(context->end.s_addr);
|
||||||
|
|
||||||
|
/* static leases only. */
|
||||||
|
if (start == end)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (addr < start)
|
if (addr < start)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -352,34 +379,47 @@ int address_available(struct dhcp_context *context, struct in_addr taddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
||||||
struct in_addr *addrp)
|
struct in_addr *addrp, unsigned char *hwaddr)
|
||||||
{
|
{
|
||||||
/* Find a free address: exlude anything in use and anything allocated to
|
/* Find a free address: exlude anything in use and anything allocated to
|
||||||
a particular hwaddr/clientid/hostname in our configuration */
|
a particular hwaddr/clientid/hostname in our configuration */
|
||||||
|
|
||||||
struct dhcp_config *config;
|
struct dhcp_config *config;
|
||||||
struct in_addr start = context->last;
|
struct in_addr start, addr ;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/* start == end means no dynamic leases. */
|
||||||
|
if (context->end.s_addr == context->start.s_addr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* pick a seed based on hwaddr then iterate until we find a free address. */
|
||||||
|
for (j = 0, i = 0; i < ETHER_ADDR_LEN; i++)
|
||||||
|
j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
|
||||||
|
|
||||||
|
start.s_addr = addr.s_addr =
|
||||||
|
htonl(ntohl(context->start.s_addr) +
|
||||||
|
(j % (ntohl(context->end.s_addr) - ntohl(context->start.s_addr))));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (context->last.s_addr == context->end.s_addr)
|
if (addr.s_addr == context->end.s_addr)
|
||||||
context->last = context->start;
|
addr = context->start;
|
||||||
else
|
else
|
||||||
context->last.s_addr = htonl(ntohl(context->last.s_addr) + 1);
|
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
|
||||||
|
|
||||||
|
|
||||||
if (!lease_find_by_addr(context->last))
|
if (!lease_find_by_addr(addr))
|
||||||
{
|
{
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if (config->addr.s_addr == context->last.s_addr)
|
if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!config)
|
if (!config)
|
||||||
{
|
{
|
||||||
*addrp = context->last;
|
*addrp = addr;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (context->last.s_addr != start.s_addr);
|
} while (addr.s_addr != start.s_addr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -388,9 +428,9 @@ static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *
|
|||||||
{
|
{
|
||||||
if (!context)
|
if (!context)
|
||||||
return 1;
|
return 1;
|
||||||
if (config->addr.s_addr == 0)
|
if (!(config->flags & CONFIG_ADDR))
|
||||||
return 1;
|
return 1;
|
||||||
if ((config->addr.s_addr & context->netmask.s_addr) == (context->start.s_addr & context->netmask.s_addr))
|
if (is_same_net(config->addr, context->start, context->netmask))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -405,6 +445,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
|
|
||||||
if (clid_len)
|
if (clid_len)
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
|
if (config->flags & CONFIG_CLID)
|
||||||
{
|
{
|
||||||
if (config->clid_len == clid_len &&
|
if (config->clid_len == clid_len &&
|
||||||
memcmp(config->clid, clid, clid_len) == 0 &&
|
memcmp(config->clid, clid, clid_len) == 0 &&
|
||||||
@@ -420,13 +461,15 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if (memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0 &&
|
if ((config->flags & CONFIG_HWADDR) &&
|
||||||
|
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0 &&
|
||||||
is_addr_in_context(context, config))
|
is_addr_in_context(context, config))
|
||||||
return config;
|
return config;
|
||||||
|
|
||||||
if (hostname)
|
if (hostname)
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if (config->hostname && strcmp(config->hostname, hostname) == 0 &&
|
if ((config->flags & CONFIG_NAME) &&
|
||||||
|
hostname_isequal(config->hostname, hostname) &&
|
||||||
is_addr_in_context(context, config))
|
is_addr_in_context(context, config))
|
||||||
return config;
|
return config;
|
||||||
|
|
||||||
@@ -436,27 +479,29 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
|
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(ETHERSFILE, "r");
|
FILE *f = fopen(ETHERSFILE, "r");
|
||||||
unsigned int e0, e1, e2, e3, e4, e5;
|
unsigned int flags, e0, e1, e2, e3, e4, e5;
|
||||||
char *ip, *cp, *name;
|
char *ip, *cp;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
struct dhcp_config *new;
|
unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||||
|
struct dhcp_config *config;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
die("Failed to open " ETHERSFILE ":%s", NULL);
|
{
|
||||||
|
syslog(LOG_ERR, "failed to read " ETHERSFILE ":%m");
|
||||||
|
return configs;
|
||||||
|
}
|
||||||
|
|
||||||
while (fgets(buff, MAXDNAME, f))
|
while (fgets(buff, MAXDNAME, f))
|
||||||
{
|
{
|
||||||
while (strlen(buff) > 0 &&
|
while (strlen(buff) > 0 && isspace(buff[strlen(buff)-1]))
|
||||||
(buff[strlen(buff)-1] == '\n' ||
|
|
||||||
buff[strlen(buff)-1] == ' ' ||
|
|
||||||
buff[strlen(buff)-1] == '\t'))
|
|
||||||
buff[strlen(buff)-1] = 0;
|
buff[strlen(buff)-1] = 0;
|
||||||
|
|
||||||
if ((*buff == '#') || (*buff == '+'))
|
if ((*buff == '#') || (*buff == '+'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (ip = buff; *ip && *ip != ' '; ip++);
|
for (ip = buff; *ip && !isspace(*ip); ip++);
|
||||||
for(; *ip && *ip == ' '; ip++)
|
for(; *ip && isspace(*ip); ip++)
|
||||||
*ip = 0;
|
*ip = 0;
|
||||||
if (!*ip)
|
if (!*ip)
|
||||||
continue;
|
continue;
|
||||||
@@ -464,6 +509,13 @@ struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
|
|||||||
if (!sscanf(buff, "%x:%x:%x:%x:%x:%x", &e0, &e1, &e2, &e3, &e4, &e5))
|
if (!sscanf(buff, "%x:%x:%x:%x:%x:%x", &e0, &e1, &e2, &e3, &e4, &e5))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
hwaddr[0] = e0;
|
||||||
|
hwaddr[1] = e1;
|
||||||
|
hwaddr[2] = e2;
|
||||||
|
hwaddr[3] = e3;
|
||||||
|
hwaddr[4] = e4;
|
||||||
|
hwaddr[5] = e5;
|
||||||
|
|
||||||
/* check for name or dotted-quad */
|
/* check for name or dotted-quad */
|
||||||
for (cp = ip; *cp; cp++)
|
for (cp = ip; *cp; cp++)
|
||||||
if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
|
if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
|
||||||
@@ -471,34 +523,64 @@ struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
|
|||||||
|
|
||||||
if (!*cp)
|
if (!*cp)
|
||||||
{
|
{
|
||||||
name = NULL;
|
|
||||||
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
|
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
|
||||||
continue;
|
continue;
|
||||||
|
flags = CONFIG_ADDR;
|
||||||
|
|
||||||
|
for (config = configs; config; config = config->next)
|
||||||
|
if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
name = safe_string_alloc(ip);
|
if (!canonicalise(ip))
|
||||||
addr.s_addr = 0;
|
continue;
|
||||||
|
flags = CONFIG_NAME;
|
||||||
|
|
||||||
|
for (config = configs; config; config = config->next)
|
||||||
|
if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, ip))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = safe_malloc(sizeof(struct dhcp_config));
|
if (!config)
|
||||||
new->clid_len = 0;
|
{
|
||||||
new->clid = NULL;
|
for (config = configs; config; config = config->next)
|
||||||
new->hwaddr[0] = e0;
|
if ((config->flags & CONFIG_HWADDR) &&
|
||||||
new->hwaddr[1] = e1;
|
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
|
||||||
new->hwaddr[2] = e2;
|
break;
|
||||||
new->hwaddr[3] = e3;
|
|
||||||
new->hwaddr[4] = e4;
|
|
||||||
new->hwaddr[5] = e5;
|
|
||||||
new->hostname = name;
|
|
||||||
new->addr = addr;
|
|
||||||
new->lease_time = 0;
|
|
||||||
new->next = configs;
|
|
||||||
|
|
||||||
configs = new;
|
if (!config)
|
||||||
|
{
|
||||||
|
if (!(config = malloc(sizeof(struct dhcp_config))))
|
||||||
|
continue;
|
||||||
|
config->flags = 0;
|
||||||
|
config->next = configs;
|
||||||
|
configs = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
config->flags |= flags;
|
||||||
|
|
||||||
|
if (flags & CONFIG_NAME)
|
||||||
|
{
|
||||||
|
if ((config->hostname = malloc(strlen(ip)+1)))
|
||||||
|
strcpy(config->hostname, ip);
|
||||||
|
else
|
||||||
|
config->flags &= ~CONFIG_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CONFIG_ADDR)
|
||||||
|
config->addr = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
config->flags |= CONFIG_HWADDR;
|
||||||
|
memcpy(config->hwaddr, hwaddr, ETHER_ADDR_LEN);
|
||||||
|
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "read " ETHERSFILE " - %d addresses", count);
|
||||||
return configs;
|
return configs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,10 +594,13 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
struct crec *crec;
|
struct crec *crec;
|
||||||
|
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if (config->addr.s_addr == 0 && config->hostname &&
|
if (!(config->flags & CONFIG_ADDR) &&
|
||||||
|
(config->flags & CONFIG_NAME) &&
|
||||||
(crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
|
(crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
|
||||||
(crec->flags & F_HOSTS))
|
(crec->flags & F_HOSTS))
|
||||||
|
{
|
||||||
config->addr = crec->addr.addr.addr4;
|
config->addr = crec->addr.addr.addr4;
|
||||||
|
config->flags |= CONFIG_ADDR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+32
-27
@@ -44,6 +44,7 @@ int main (int argc, char **argv)
|
|||||||
time_t now, last = 0;
|
time_t now, last = 0;
|
||||||
struct irec *interfaces = NULL;
|
struct irec *interfaces = NULL;
|
||||||
struct listener *listener, *listeners;
|
struct listener *listener, *listeners;
|
||||||
|
struct doctor *doctors = NULL;
|
||||||
char *mxname = NULL;
|
char *mxname = NULL;
|
||||||
char *mxtarget = NULL;
|
char *mxtarget = NULL;
|
||||||
char *lease_file = NULL;
|
char *lease_file = NULL;
|
||||||
@@ -65,6 +66,7 @@ int main (int argc, char **argv)
|
|||||||
struct dhcp_context *dhcp_tmp, *dhcp = NULL;
|
struct dhcp_context *dhcp_tmp, *dhcp = NULL;
|
||||||
struct dhcp_config *dhcp_configs = NULL;
|
struct dhcp_config *dhcp_configs = NULL;
|
||||||
struct dhcp_opt *dhcp_options = NULL;
|
struct dhcp_opt *dhcp_options = NULL;
|
||||||
|
struct dhcp_vendor *dhcp_vendors = NULL;
|
||||||
char *dhcp_file = NULL, *dhcp_sname = NULL;
|
char *dhcp_file = NULL, *dhcp_sname = NULL;
|
||||||
struct in_addr dhcp_next_server;
|
struct in_addr dhcp_next_server;
|
||||||
int leasefd = -1, dhcpfd = -1, dhcp_raw_fd = -1;
|
int leasefd = -1, dhcpfd = -1, dhcp_raw_fd = -1;
|
||||||
@@ -108,29 +110,27 @@ int main (int argc, char **argv)
|
|||||||
&username, &groupname, &domain_suffix, &runfile,
|
&username, &groupname, &domain_suffix, &runfile,
|
||||||
&if_names, &if_addrs, &if_except, &bogus_addr,
|
&if_names, &if_addrs, &if_except, &bogus_addr,
|
||||||
&serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts,
|
&serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts,
|
||||||
&dhcp, &dhcp_configs, &dhcp_options,
|
&dhcp, &dhcp_configs, &dhcp_options, &dhcp_vendors,
|
||||||
&dhcp_file, &dhcp_sname, &dhcp_next_server, &maxleases, &min_leasetime);
|
&dhcp_file, &dhcp_sname, &dhcp_next_server, &maxleases, &min_leasetime,
|
||||||
|
&doctors);
|
||||||
|
|
||||||
|
if (!lease_file)
|
||||||
|
{
|
||||||
|
if (dhcp)
|
||||||
|
lease_file = LEASEFILE;
|
||||||
|
}
|
||||||
|
#ifndef HAVE_ISC_READER
|
||||||
|
else if (!dhcp)
|
||||||
|
die("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h", NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_UDP_SRC_DST
|
||||||
/* if we cannot support binding the wildcard address, set the "bind only
|
/* if we cannot support binding the wildcard address, set the "bind only
|
||||||
interfaces in use" option */
|
interfaces in use" option */
|
||||||
#ifndef HAVE_UDP_SRC_DST
|
|
||||||
options |= OPT_NOWILD;
|
options |= OPT_NOWILD;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!lease_file)
|
interfaces = enumerate_interfaces(&if_names, &if_addrs, if_except, port);
|
||||||
lease_file = LEASEFILE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!dhcp)
|
|
||||||
{
|
|
||||||
complain("********* dhcp-lease option set, but not dhcp-range.", NULL);
|
|
||||||
complain("********* Are you trying to use the obsolete ISC dhcpd integration?", NULL);
|
|
||||||
complain("********* Please configure the dnsmasq integrated DHCP server by using", NULL);
|
|
||||||
complain("********* the \"dhcp-range\" option, and remove any other DHCP server.", NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interfaces = enumerate_interfaces(if_names, if_addrs, if_except, port);
|
|
||||||
if (options & OPT_NOWILD)
|
if (options & OPT_NOWILD)
|
||||||
listeners = create_bound_listeners(interfaces);
|
listeners = create_bound_listeners(interfaces);
|
||||||
else
|
else
|
||||||
@@ -150,12 +150,6 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
dhcp_init(&dhcpfd, &dhcp_raw_fd);
|
dhcp_init(&dhcpfd, &dhcp_raw_fd);
|
||||||
leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, now, maxleases);
|
leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, now, maxleases);
|
||||||
if (options & OPT_ETHERS)
|
|
||||||
dhcp_configs = dhcp_read_ethers(dhcp_configs, dnamebuff);
|
|
||||||
dhcp_update_configs(dhcp_configs);
|
|
||||||
lease_update_from_configs(dhcp_configs, domain_suffix); /* must follow cache_init and lease_init */
|
|
||||||
lease_update_file(0, now);
|
|
||||||
lease_update_dns();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setbuf(stdout, NULL);
|
setbuf(stdout, NULL);
|
||||||
@@ -247,7 +241,10 @@ int main (int argc, char **argv)
|
|||||||
sprintf(packet, "infinite");
|
sprintf(packet, "infinite");
|
||||||
else
|
else
|
||||||
sprintf(packet, "%ds", (int)dhcp_tmp->lease_time);
|
sprintf(packet, "%ds", (int)dhcp_tmp->lease_time);
|
||||||
syslog(LOG_INFO, "DHCP, IP range %s -- %s, lease time %s",
|
syslog(LOG_INFO,
|
||||||
|
dhcp_tmp->start.s_addr == dhcp_tmp->end.s_addr ?
|
||||||
|
"DHCP, static leases only on %.0s%s, lease time %s" :
|
||||||
|
"DHCP, IP range %s -- %s, lease time %s",
|
||||||
dnamebuff, inet_ntoa(dhcp_tmp->end), packet);
|
dnamebuff, inet_ntoa(dhcp_tmp->end), packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +267,8 @@ int main (int argc, char **argv)
|
|||||||
cache_reload(options, dnamebuff, domain_suffix, addn_hosts);
|
cache_reload(options, dnamebuff, domain_suffix, addn_hosts);
|
||||||
if (dhcp)
|
if (dhcp)
|
||||||
{
|
{
|
||||||
|
if (options & OPT_ETHERS)
|
||||||
|
dhcp_configs = dhcp_read_ethers(dhcp_configs, dnamebuff);
|
||||||
dhcp_update_configs(dhcp_configs);
|
dhcp_update_configs(dhcp_configs);
|
||||||
lease_update_from_configs(dhcp_configs, domain_suffix);
|
lease_update_from_configs(dhcp_configs, domain_suffix);
|
||||||
lease_update_file(0, now);
|
lease_update_file(0, now);
|
||||||
@@ -349,11 +348,17 @@ int main (int argc, char **argv)
|
|||||||
if (last == 0 || difftime(now, last) > 1.0)
|
if (last == 0 || difftime(now, last) > 1.0)
|
||||||
{
|
{
|
||||||
last = now;
|
last = now;
|
||||||
|
|
||||||
|
#ifdef HAVE_ISC_READER
|
||||||
|
if (lease_file && !dhcp)
|
||||||
|
load_dhcp(lease_file, domain_suffix, now, dnamebuff);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!(options & OPT_NO_POLL))
|
if (!(options & OPT_NO_POLL))
|
||||||
{
|
{
|
||||||
struct resolvc *res = resolv, *latest = NULL;
|
struct resolvc *res = resolv, *latest = NULL;
|
||||||
time_t last_change = 0;
|
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
time_t last_change = 0;
|
||||||
/* There may be more than one possible file.
|
/* There may be more than one possible file.
|
||||||
Go through and find the one which changed _last_.
|
Go through and find the one which changed _last_.
|
||||||
Warn of any which can't be read. */
|
Warn of any which can't be read. */
|
||||||
@@ -390,10 +395,10 @@ int main (int argc, char **argv)
|
|||||||
for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next)
|
for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next)
|
||||||
if (FD_ISSET(serverfdp->fd, &rset))
|
if (FD_ISSET(serverfdp->fd, &rset))
|
||||||
last_server = reply_query(serverfdp->fd, options, packet, now,
|
last_server = reply_query(serverfdp->fd, options, packet, now,
|
||||||
dnamebuff, last_server, bogus_addr);
|
dnamebuff, last_server, bogus_addr, doctors);
|
||||||
|
|
||||||
if (dhcp && FD_ISSET(dhcpfd, &rset))
|
if (dhcp && FD_ISSET(dhcpfd, &rset))
|
||||||
dhcp_packet(dhcp, packet, dhcp_options, dhcp_configs,
|
dhcp_packet(dhcp, packet, dhcp_options, dhcp_configs, dhcp_vendors,
|
||||||
now, dnamebuff, domain_suffix, dhcp_file,
|
now, dnamebuff, domain_suffix, dhcp_file,
|
||||||
dhcp_sname, dhcp_next_server, dhcpfd, dhcp_raw_fd,
|
dhcp_sname, dhcp_next_server, dhcpfd, dhcp_raw_fd,
|
||||||
if_names, if_addrs, if_except);
|
if_names, if_addrs, if_except);
|
||||||
|
|||||||
+45
-10
@@ -40,6 +40,7 @@
|
|||||||
# include <sys/sockio.h>
|
# include <sys/sockio.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -105,6 +106,12 @@ struct bogus_addr {
|
|||||||
struct bogus_addr *next;
|
struct bogus_addr *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* dns doctor param */
|
||||||
|
struct doctor {
|
||||||
|
struct in_addr in, out, mask;
|
||||||
|
struct doctor *next;
|
||||||
|
};
|
||||||
|
|
||||||
union bigname {
|
union bigname {
|
||||||
char name[MAXDNAME];
|
char name[MAXDNAME];
|
||||||
union bigname *next; /* freelist */
|
union bigname *next; /* freelist */
|
||||||
@@ -231,15 +238,25 @@ struct dhcp_lease {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp_config {
|
struct dhcp_config {
|
||||||
|
unsigned int flags;
|
||||||
int clid_len; /* length of client identifier */
|
int clid_len; /* length of client identifier */
|
||||||
unsigned char *clid; /* clientid */
|
unsigned char *clid; /* clientid */
|
||||||
unsigned char hwaddr[ETHER_ADDR_LEN];
|
unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||||
char *hostname;
|
char *hostname, *netid;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
unsigned int lease_time;
|
unsigned int lease_time;
|
||||||
struct dhcp_config *next;
|
struct dhcp_config *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CONFIG_DISABLE 1
|
||||||
|
#define CONFIG_CLID 2
|
||||||
|
#define CONFIG_HWADDR 4
|
||||||
|
#define CONFIG_TIME 8
|
||||||
|
#define CONFIG_NAME 16
|
||||||
|
#define CONFIG_ADDR 32
|
||||||
|
#define CONFIG_NETID 64
|
||||||
|
#define CONFIG_NOCLID 128
|
||||||
|
|
||||||
struct dhcp_opt {
|
struct dhcp_opt {
|
||||||
int opt, len, is_addr;
|
int opt, len, is_addr;
|
||||||
unsigned char *val;
|
unsigned char *val;
|
||||||
@@ -247,10 +264,16 @@ struct dhcp_opt {
|
|||||||
struct dhcp_opt *next;
|
struct dhcp_opt *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dhcp_vendor {
|
||||||
|
int len;
|
||||||
|
char *data, *net;
|
||||||
|
struct dhcp_vendor *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct dhcp_context {
|
struct dhcp_context {
|
||||||
unsigned int lease_time;
|
unsigned int lease_time;
|
||||||
struct in_addr netmask, broadcast;
|
struct in_addr netmask, broadcast;
|
||||||
struct in_addr start, end, last; /* range of available addresses */
|
struct in_addr start, end; /* range of available addresses */
|
||||||
char *netid;
|
char *netid;
|
||||||
struct dhcp_context *next;
|
struct dhcp_context *next;
|
||||||
};
|
};
|
||||||
@@ -304,7 +327,8 @@ unsigned short extract_request(HEADER *header, unsigned int qlen, char *name);
|
|||||||
int setup_reply(HEADER *header, unsigned int qlen,
|
int setup_reply(HEADER *header, unsigned int qlen,
|
||||||
struct all_addr *addrp, unsigned short flags,
|
struct all_addr *addrp, unsigned short flags,
|
||||||
unsigned long local_ttl);
|
unsigned long local_ttl);
|
||||||
void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff, time_t now);
|
void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff,
|
||||||
|
time_t now, struct doctor *doctors);
|
||||||
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *namebuff, time_t now);
|
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *namebuff, time_t now);
|
||||||
int answer_request(HEADER *header, char *limit, unsigned int qlen, char *mxname,
|
int answer_request(HEADER *header, char *limit, unsigned int qlen, char *mxname,
|
||||||
char *mxtarget, unsigned int options, time_t now, unsigned long local_ttl,
|
char *mxtarget, unsigned int options, time_t now, unsigned long local_ttl,
|
||||||
@@ -324,6 +348,8 @@ int sa_len(union mysockaddr *addr);
|
|||||||
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
||||||
int hostname_isequal(unsigned char *a, unsigned char *b);
|
int hostname_isequal(unsigned char *a, unsigned char *b);
|
||||||
time_t dnsmasq_time(int fd);
|
time_t dnsmasq_time(int fd);
|
||||||
|
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||||
|
|
||||||
/* option.c */
|
/* option.c */
|
||||||
unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resolv_file,
|
unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resolv_file,
|
||||||
char **mxname, char **mxtarget, char **lease_file,
|
char **mxname, char **mxtarget, char **lease_file,
|
||||||
@@ -332,15 +358,16 @@ unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resol
|
|||||||
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
||||||
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize,
|
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize,
|
||||||
int *port, int *query_port, unsigned long *local_ttl, char **addn_hosts,
|
int *port, int *query_port, unsigned long *local_ttl, char **addn_hosts,
|
||||||
struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf, struct dhcp_opt **opts,
|
struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf,
|
||||||
|
struct dhcp_opt **opts, struct dhcp_vendor **dhcp_vendors,
|
||||||
char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server,
|
char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server,
|
||||||
int *maxleases, unsigned int *min_leasetime);
|
int *maxleases, unsigned int *min_leasetime, struct doctor **doctors);
|
||||||
|
|
||||||
/* forward.c */
|
/* forward.c */
|
||||||
void forward_init(int first);
|
void forward_init(int first);
|
||||||
struct server *reply_query(int fd, int options, char *packet, time_t now,
|
struct server *reply_query(int fd, int options, char *packet, time_t now,
|
||||||
char *dnamebuff, struct server *last_server,
|
char *dnamebuff, struct server *last_server,
|
||||||
struct bogus_addr *bogus_nxdomain);
|
struct bogus_addr *bogus_nxdomain, struct doctor *doctors);
|
||||||
|
|
||||||
struct server *receive_query(struct listener *listen, char *packet, char *mxname,
|
struct server *receive_query(struct listener *listen, char *packet, char *mxname,
|
||||||
char *mxtarget, unsigned int options, time_t now,
|
char *mxtarget, unsigned int options, time_t now,
|
||||||
@@ -350,8 +377,8 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
|
|||||||
/* network.c */
|
/* network.c */
|
||||||
struct server *reload_servers(char *fname, char *buff, struct server *servers, int query_port);
|
struct server *reload_servers(char *fname, char *buff, struct server *servers, int query_port);
|
||||||
struct server *check_servers(struct server *new, struct irec *interfaces, struct serverfd **sfds);
|
struct server *check_servers(struct server *new, struct irec *interfaces, struct serverfd **sfds);
|
||||||
struct irec *enumerate_interfaces(struct iname *names,
|
struct irec *enumerate_interfaces(struct iname **names,
|
||||||
struct iname *addrs,
|
struct iname **addrs,
|
||||||
struct iname *except,
|
struct iname *except,
|
||||||
int port);
|
int port);
|
||||||
struct listener *create_wildcard_listeners(int port);
|
struct listener *create_wildcard_listeners(int port);
|
||||||
@@ -360,13 +387,14 @@ struct listener *create_bound_listeners(struct irec *interfaces);
|
|||||||
void dhcp_init(int *fdp, int* rfdp);
|
void dhcp_init(int *fdp, int* rfdp);
|
||||||
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
void dhcp_packet(struct dhcp_context *contexts, char *packet,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
time_t now, char *namebuff, char *domain_suffix,
|
time_t now, char *namebuff, char *domain_suffix,
|
||||||
char *dhcp_file, char *dhcp_sname,
|
char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
struct in_addr dhcp_next_server, int dhcp_fd, int raw_fd,
|
||||||
struct iname *names, struct iname *addrs, struct iname *except);
|
struct iname *names, struct iname *addrs, struct iname *except);
|
||||||
int address_available(struct dhcp_context *context, struct in_addr addr);
|
int address_available(struct dhcp_context *context, struct in_addr addr);
|
||||||
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
||||||
struct in_addr *addrp);
|
struct in_addr *addrp, unsigned char *hwaddr);
|
||||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||||
struct dhcp_context *context,
|
struct dhcp_context *context,
|
||||||
unsigned char *clid, int clid_len,
|
unsigned char *clid, int clid_len,
|
||||||
@@ -374,6 +402,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
struct dhcp_config *read_ethers(struct dhcp_config *configs, char *buff);
|
struct dhcp_config *read_ethers(struct dhcp_config *configs, char *buff);
|
||||||
void dhcp_update_configs(struct dhcp_config *configs);
|
void dhcp_update_configs(struct dhcp_config *configs);
|
||||||
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff);
|
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff);
|
||||||
|
|
||||||
/* lease.c */
|
/* lease.c */
|
||||||
void lease_update_file(int force, time_t now);
|
void lease_update_file(int force, time_t now);
|
||||||
void lease_update_dns(void);
|
void lease_update_dns(void);
|
||||||
@@ -387,6 +416,7 @@ struct dhcp_lease *lease_find_by_client(unsigned char *clid, int clid_len);
|
|||||||
struct dhcp_lease *lease_find_by_addr(struct in_addr addr);
|
struct dhcp_lease *lease_find_by_addr(struct in_addr addr);
|
||||||
void lease_prune(struct dhcp_lease *target, time_t now);
|
void lease_prune(struct dhcp_lease *target, time_t now);
|
||||||
void lease_update_from_configs(struct dhcp_config *dhcp_configs, char *domain);
|
void lease_update_from_configs(struct dhcp_config *dhcp_configs, char *domain);
|
||||||
|
|
||||||
/* rfc2131.c */
|
/* rfc2131.c */
|
||||||
int dhcp_reply(struct dhcp_context *context,
|
int dhcp_reply(struct dhcp_context *context,
|
||||||
struct in_addr iface_addr,
|
struct in_addr iface_addr,
|
||||||
@@ -395,6 +425,11 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
struct udp_dhcp_packet *rawpacket,
|
struct udp_dhcp_packet *rawpacket,
|
||||||
unsigned int sz, time_t now, char *namebuff,
|
unsigned int sz, time_t now, char *namebuff,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server);
|
struct in_addr dhcp_next_server, struct in_addr router);
|
||||||
|
|
||||||
|
/* isc.c */
|
||||||
|
#ifdef HAVE_ISC_READER
|
||||||
|
void load_dhcp(char *file, char *suffix, time_t now, char *hostname);
|
||||||
|
#endif
|
||||||
+24
-16
@@ -104,7 +104,6 @@ static void send_from(int fd, int nowild, char *packet, int len,
|
|||||||
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||||
cmptr->cmsg_type = IPV6_PKTINFO;
|
cmptr->cmsg_type = IPV6_PKTINFO;
|
||||||
cmptr->cmsg_level = IPV6_LEVEL;
|
cmptr->cmsg_level = IPV6_LEVEL;
|
||||||
cmptr->cmsg_level = IPPROTO_IPV6;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -314,7 +313,8 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
|
|
||||||
/* returns new last_server */
|
/* returns new last_server */
|
||||||
struct server *reply_query(int fd, int options, char *packet, time_t now,
|
struct server *reply_query(int fd, int options, char *packet, time_t now,
|
||||||
char *dnamebuff, struct server *last_server, struct bogus_addr *bogus_nxdomain)
|
char *dnamebuff, struct server *last_server,
|
||||||
|
struct bogus_addr *bogus_nxdomain, struct doctor *doctors)
|
||||||
{
|
{
|
||||||
/* packet from peer server, extract data for cache, and send to
|
/* packet from peer server, extract data for cache, and send to
|
||||||
original requester */
|
original requester */
|
||||||
@@ -338,7 +338,7 @@ struct server *reply_query(int fd, int options, char *packet, time_t now,
|
|||||||
check_for_bogus_wildcard(header, (unsigned int)n, dnamebuff, bogus_nxdomain, now)))
|
check_for_bogus_wildcard(header, (unsigned int)n, dnamebuff, bogus_nxdomain, now)))
|
||||||
{
|
{
|
||||||
if (header->rcode == NOERROR && ntohs(header->ancount) != 0)
|
if (header->rcode == NOERROR && ntohs(header->ancount) != 0)
|
||||||
extract_addresses(header, (unsigned int)n, dnamebuff, now);
|
extract_addresses(header, (unsigned int)n, dnamebuff, now, doctors);
|
||||||
else if (!(options & OPT_NO_NEG))
|
else if (!(options & OPT_NO_NEG))
|
||||||
extract_neg_addrs(header, (unsigned int)n, dnamebuff, now);
|
extract_neg_addrs(header, (unsigned int)n, dnamebuff, now);
|
||||||
}
|
}
|
||||||
@@ -367,11 +367,10 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
|
|||||||
union mysockaddr source_addr;
|
union mysockaddr source_addr;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
struct all_addr dst_addr;
|
struct all_addr dst_addr;
|
||||||
int m, n, gotit = 0;
|
int m, n, if_index = 0;
|
||||||
struct iovec iov[1];
|
struct iovec iov[1];
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct cmsghdr *cmptr;
|
struct cmsghdr *cmptr;
|
||||||
char if_name[IF_NAMESIZE];
|
|
||||||
union {
|
union {
|
||||||
struct cmsghdr align; /* this ensures alignment */
|
struct cmsghdr align; /* this ensures alignment */
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -413,20 +412,16 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
|
|||||||
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
|
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||||
{
|
{
|
||||||
dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
|
dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst;
|
||||||
if_indextoname(((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex, if_name);
|
if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
|
||||||
gotit = 1;
|
|
||||||
}
|
}
|
||||||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
||||||
if (!(options & OPT_NOWILD) && listen->family == AF_INET)
|
if (!(options & OPT_NOWILD) && listen->family == AF_INET)
|
||||||
{
|
{
|
||||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
|
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
|
||||||
{
|
|
||||||
dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
|
dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr));
|
||||||
gotit = 1;
|
|
||||||
}
|
|
||||||
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
||||||
if_indextoname(((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index, if_name);
|
if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -437,8 +432,7 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
|
|||||||
if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
|
if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO)
|
||||||
{
|
{
|
||||||
dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
|
dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr;
|
||||||
if_indextoname(((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex, if_name);
|
if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex;
|
||||||
gotit = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -449,17 +443,31 @@ struct server *receive_query(struct listener *listen, char *packet, char *mxname
|
|||||||
/* enforce available interface configuration */
|
/* enforce available interface configuration */
|
||||||
if (!(options & OPT_NOWILD))
|
if (!(options & OPT_NOWILD))
|
||||||
{
|
{
|
||||||
if (!gotit)
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
if (if_index == 0)
|
||||||
return last_server;
|
return last_server;
|
||||||
|
|
||||||
|
if (except || names)
|
||||||
|
{
|
||||||
|
#ifdef SIOCGIFNAME
|
||||||
|
ifr.ifr_ifindex = if_index;
|
||||||
|
if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1)
|
||||||
|
return last_server;
|
||||||
|
#else
|
||||||
|
if (!if_indextoname(if_index, ifr.ifr_name))
|
||||||
|
return last_server;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
for (tmp = except; tmp; tmp = tmp->next)
|
for (tmp = except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, if_name) == 0))
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
return last_server;
|
return last_server;
|
||||||
|
|
||||||
if (names || addrs)
|
if (names || addrs)
|
||||||
{
|
{
|
||||||
for (tmp = names; tmp; tmp = tmp->next)
|
for (tmp = names; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, if_name) == 0))
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
break;
|
break;
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
for (tmp = addrs; tmp; tmp = tmp->next)
|
for (tmp = addrs; tmp; tmp = tmp->next)
|
||||||
|
|||||||
@@ -0,0 +1,249 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000 - 2004 by Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Code in this file is based on contributions by John Volpe. */
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_ISC_READER
|
||||||
|
|
||||||
|
struct isc_lease {
|
||||||
|
char *name, *fqdn;
|
||||||
|
time_t expires;
|
||||||
|
struct in_addr addr;
|
||||||
|
struct isc_lease *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct isc_lease *leases = NULL;
|
||||||
|
static off_t lease_file_size = (off_t)0;
|
||||||
|
static ino_t lease_file_inode = (ino_t)0;
|
||||||
|
static int logged_lease = 0;
|
||||||
|
|
||||||
|
static int next_token (char *token, int buffsize, FILE * fp)
|
||||||
|
{
|
||||||
|
int c, count = 0;
|
||||||
|
char *cp = token;
|
||||||
|
|
||||||
|
while((c = getc(fp)) != EOF)
|
||||||
|
{
|
||||||
|
if (c == '#')
|
||||||
|
do { c = getc(fp); } while (c != '\n' && c != EOF);
|
||||||
|
|
||||||
|
if (c == ' ' || c == '\t' || c == '\n' || c == ';')
|
||||||
|
{
|
||||||
|
if (count)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ((c != '"') && (count<buffsize-1))
|
||||||
|
{
|
||||||
|
*cp++ = c;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*cp = 0;
|
||||||
|
return count ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_dhcp(char *file, char *suffix, time_t now, char *hostname)
|
||||||
|
{
|
||||||
|
char token[MAXTOK], *dot;
|
||||||
|
struct in_addr host_address;
|
||||||
|
time_t ttd, tts;
|
||||||
|
FILE *fp;
|
||||||
|
struct isc_lease *lease, *tmp, **up;
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
if (stat(file, &statbuf) == -1)
|
||||||
|
{
|
||||||
|
if (!logged_lease)
|
||||||
|
syslog(LOG_WARNING, "failed to access %s: %m", file);
|
||||||
|
logged_lease = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logged_lease = 0;
|
||||||
|
|
||||||
|
if ((statbuf.st_size <= lease_file_size) &&
|
||||||
|
(statbuf.st_ino == lease_file_inode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
lease_file_size = statbuf.st_size;
|
||||||
|
lease_file_inode = statbuf.st_ino;
|
||||||
|
|
||||||
|
if (!(fp = fopen (file, "r")))
|
||||||
|
{
|
||||||
|
syslog (LOG_ERR, "failed to load %s: %m", file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
syslog (LOG_INFO, "reading %s", file);
|
||||||
|
|
||||||
|
while ((next_token(token, MAXTOK, fp)))
|
||||||
|
{
|
||||||
|
if (strcmp(token, "lease") == 0)
|
||||||
|
{
|
||||||
|
hostname[0] = '\0';
|
||||||
|
ttd = tts = (time_t)(-1);
|
||||||
|
if (next_token(token, MAXTOK, fp) &&
|
||||||
|
(host_address.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
||||||
|
{
|
||||||
|
if (next_token(token, MAXTOK, fp) && *token == '{')
|
||||||
|
{
|
||||||
|
while (next_token(token, MAXTOK, fp) && *token != '}')
|
||||||
|
{
|
||||||
|
if ((strcmp(token, "client-hostname") == 0) ||
|
||||||
|
(strcmp(token, "hostname") == 0))
|
||||||
|
{
|
||||||
|
if (next_token(hostname, MAXDNAME, fp))
|
||||||
|
if (!canonicalise(hostname))
|
||||||
|
{
|
||||||
|
*hostname = 0;
|
||||||
|
syslog(LOG_ERR, "bad name in %s", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((strcmp(token, "ends") == 0) ||
|
||||||
|
(strcmp(token, "starts") == 0))
|
||||||
|
{
|
||||||
|
struct tm lease_time;
|
||||||
|
int is_ends = (strcmp(token, "ends") == 0);
|
||||||
|
if (next_token(token, MAXTOK, fp) && /* skip weekday */
|
||||||
|
next_token(token, MAXTOK, fp) && /* Get date from lease file */
|
||||||
|
sscanf (token, "%d/%d/%d",
|
||||||
|
&lease_time.tm_year,
|
||||||
|
&lease_time.tm_mon,
|
||||||
|
&lease_time.tm_mday) == 3 &&
|
||||||
|
next_token(token, MAXTOK, fp) &&
|
||||||
|
sscanf (token, "%d:%d:%d:",
|
||||||
|
&lease_time.tm_hour,
|
||||||
|
&lease_time.tm_min,
|
||||||
|
&lease_time.tm_sec) == 3)
|
||||||
|
{
|
||||||
|
/* There doesn't seem to be a universally available library function
|
||||||
|
which converts broken-down _GMT_ time to seconds-in-epoch.
|
||||||
|
The following was borrowed from ISC dhcpd sources, where
|
||||||
|
it is noted that it might not be entirely accurate for odd seconds.
|
||||||
|
Since we're trying to get the same answer as dhcpd, that's just
|
||||||
|
fine here. */
|
||||||
|
static int months [11] = { 31, 59, 90, 120, 151, 181,
|
||||||
|
212, 243, 273, 304, 334 };
|
||||||
|
time_t time = ((((((365 * (lease_time.tm_year - 1970) + /* Days in years since '70 */
|
||||||
|
(lease_time.tm_year - 1969) / 4 + /* Leap days since '70 */
|
||||||
|
(lease_time.tm_mon > 1 /* Days in months this year */
|
||||||
|
? months [lease_time.tm_mon - 2]
|
||||||
|
: 0) +
|
||||||
|
(lease_time.tm_mon > 2 && /* Leap day this year */
|
||||||
|
!((lease_time.tm_year - 1972) & 3)) +
|
||||||
|
lease_time.tm_mday - 1) * 24) + /* Day of month */
|
||||||
|
lease_time.tm_hour) * 60) +
|
||||||
|
lease_time.tm_min) * 60) + lease_time.tm_sec;
|
||||||
|
if (is_ends)
|
||||||
|
ttd = time;
|
||||||
|
else
|
||||||
|
tts = time; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* missing info? */
|
||||||
|
if (!*hostname)
|
||||||
|
continue;
|
||||||
|
if (ttd == (time_t)(-1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* We use 0 as infinite in ttd */
|
||||||
|
if ((tts != -1) && (ttd == tts - 1))
|
||||||
|
ttd = (time_t)0;
|
||||||
|
else if (difftime(now, ttd) > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((dot = strchr(hostname, '.')))
|
||||||
|
{
|
||||||
|
if (!suffix || hostname_isequal(dot+1, suffix))
|
||||||
|
{
|
||||||
|
syslog(LOG_WARNING,
|
||||||
|
"Ignoring DHCP lease for %s because it has an illegal domain part",
|
||||||
|
hostname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*dot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (lease = leases; lease; lease = lease->next)
|
||||||
|
if (hostname_isequal(lease->name, hostname))
|
||||||
|
{
|
||||||
|
lease->expires = ttd;
|
||||||
|
lease->addr = host_address;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lease && (lease = malloc(sizeof(struct isc_lease))))
|
||||||
|
{
|
||||||
|
lease->expires = ttd;
|
||||||
|
lease->addr = host_address;
|
||||||
|
lease->fqdn = NULL;
|
||||||
|
lease->next = leases;
|
||||||
|
if (!(lease->name = malloc(strlen(hostname)+1)))
|
||||||
|
free(lease);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
leases = lease;
|
||||||
|
strcpy(lease->name, hostname);
|
||||||
|
if (suffix && (lease->fqdn = malloc(strlen(hostname) + strlen(suffix) + 2)))
|
||||||
|
{
|
||||||
|
strcpy(lease->fqdn, hostname);
|
||||||
|
strcat(lease->fqdn, ".");
|
||||||
|
strcat(lease->fqdn, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
/* prune expired leases */
|
||||||
|
for (lease = leases, up = &leases; lease; lease = tmp)
|
||||||
|
{
|
||||||
|
tmp = lease->next;
|
||||||
|
if (lease->expires != (time_t)0 && difftime(now, lease->expires) > 0)
|
||||||
|
{
|
||||||
|
*up = lease->next; /* unlink */
|
||||||
|
free(lease->name);
|
||||||
|
if (lease->fqdn)
|
||||||
|
free(lease->fqdn);
|
||||||
|
free(lease);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &lease->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* remove all existing DHCP cache entries */
|
||||||
|
cache_unhash_dhcp();
|
||||||
|
|
||||||
|
for (lease = leases; lease; lease = lease->next)
|
||||||
|
{
|
||||||
|
if (lease->fqdn)
|
||||||
|
{
|
||||||
|
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires, F_REVERSE);
|
||||||
|
cache_add_dhcp_entry(lease->name, &lease->addr, lease->expires, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cache_add_dhcp_entry(lease->name, &lease->addr, lease->expires, F_REVERSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
+5
-1
@@ -34,9 +34,13 @@ int lease_init(char *filename, char *domain, char *buff,
|
|||||||
leases = NULL;
|
leases = NULL;
|
||||||
leases_left = maxleases;
|
leases_left = maxleases;
|
||||||
|
|
||||||
if (!(lease_file = fopen(filename, "r+")))
|
/* NOTE: need a+ mode to create file if it doesn't exist */
|
||||||
|
if (!(lease_file = fopen(filename, "a+")))
|
||||||
die("cannot open or create leases file: %s", NULL);
|
die("cannot open or create leases file: %s", NULL);
|
||||||
|
|
||||||
|
/* a+ mode lease pointer at end. */
|
||||||
|
rewind(lease_file);
|
||||||
|
|
||||||
while (fscanf(lease_file, "%lu %x:%x:%x:%x:%x:%x %d.%d.%d.%d %256s %500s",
|
while (fscanf(lease_file, "%lu %x:%x:%x:%x:%x:%x %d.%d.%d.%d %256s %500s",
|
||||||
&ei, &e0, &e1, &e2, &e3, &e4, &e5, &a0, &a1, &a2, &a3, buff, buff2) == 13)
|
&ei, &e0, &e1, &e2, &e3, &e4, &e5, &a0, &a1, &a2, &a3, buff, buff2) == 13)
|
||||||
{
|
{
|
||||||
|
|||||||
+29
-28
@@ -25,7 +25,7 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a
|
|||||||
if (except)
|
if (except)
|
||||||
for (tmp = except; tmp; tmp = tmp->next)
|
for (tmp = except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && strcmp(tmp->name, name) == 0)
|
if (tmp->name && strcmp(tmp->name, name) == 0)
|
||||||
return NULL;
|
return list;
|
||||||
|
|
||||||
/* we may need to check the whitelist */
|
/* we may need to check the whitelist */
|
||||||
if (names || addrs)
|
if (names || addrs)
|
||||||
@@ -33,38 +33,36 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a
|
|||||||
for (tmp = names; tmp; tmp = tmp->next)
|
for (tmp = names; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||||
break;
|
break;
|
||||||
if (!tmp && !addrs)
|
if (!tmp)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (tmp = addrs; tmp; tmp = tmp->next)
|
for (tmp = addrs; tmp; tmp = tmp->next)
|
||||||
if (sockaddr_isequal(&tmp->addr, addr))
|
if (sockaddr_isequal(&tmp->addr, addr))
|
||||||
break;
|
break;
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return NULL;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check whether the interface IP has been added already
|
/* check whether the interface IP has been added already
|
||||||
it is possible to have multiple interfaces with the same address */
|
it is possible to have multiple interfaces with the same address */
|
||||||
for (; list; list = list->next)
|
for (iface = list; iface; iface = iface->next)
|
||||||
if (sockaddr_isequal(&list->addr, addr))
|
if (sockaddr_isequal(&iface->addr, addr))
|
||||||
break;
|
break;
|
||||||
if (list)
|
if (iface)
|
||||||
return NULL;
|
return list;
|
||||||
|
|
||||||
/* If OK, add it to the head of the list */
|
/* If OK, add it to the head of the list */
|
||||||
iface = safe_malloc(sizeof(struct irec));
|
iface = safe_malloc(sizeof(struct irec));
|
||||||
iface->addr = *addr;
|
iface->addr = *addr;
|
||||||
|
iface->next = list;
|
||||||
return iface;
|
return iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct irec *enumerate_interfaces(struct iname *names,
|
struct irec *enumerate_interfaces(struct iname **names,
|
||||||
struct iname *addrs,
|
struct iname **addrs,
|
||||||
struct iname *except,
|
struct iname *except,
|
||||||
int port)
|
int port)
|
||||||
{
|
{
|
||||||
struct irec *iface = NULL, *new;
|
struct irec *iface = NULL;
|
||||||
char *buf, *ptr;
|
char *buf, *ptr;
|
||||||
struct ifreq *ifr = NULL;
|
struct ifreq *ifr = NULL;
|
||||||
struct ifconf ifc;
|
struct ifconf ifc;
|
||||||
@@ -139,21 +137,18 @@ struct irec *enumerate_interfaces(struct iname *names,
|
|||||||
die("ioctl error getting interface flags: %m", NULL);
|
die("ioctl error getting interface flags: %m", NULL);
|
||||||
|
|
||||||
/* If we are restricting the set of interfaces to use, make
|
/* If we are restricting the set of interfaces to use, make
|
||||||
sure that loopback interfaces are in that set. */
|
sure that loopback interfaces are in that set. Note that
|
||||||
if (names && (ifr->ifr_flags & IFF_LOOPBACK))
|
this is done as addresses rather than interface names so
|
||||||
|
as not to confuse the no-IPRECVIF workaround on the DHCP code */
|
||||||
|
if (*names && (ifr->ifr_flags & IFF_LOOPBACK))
|
||||||
{
|
{
|
||||||
struct iname *lo = safe_malloc(sizeof(struct iname));
|
struct iname *lo = safe_malloc(sizeof(struct iname));
|
||||||
lo->name = safe_string_alloc(ifr->ifr_name);
|
lo->addr = addr;
|
||||||
lo->next = names->next;
|
lo->next = *addrs;
|
||||||
names->next = lo;
|
*addrs = lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((new = add_iface(iface, ifr->ifr_name,
|
iface = add_iface(iface, ifr->ifr_name, &addr, *names, *addrs, except);
|
||||||
&addr, names, addrs, except)))
|
|
||||||
{
|
|
||||||
new->next = iface;
|
|
||||||
iface = new;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
||||||
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
||||||
@@ -196,11 +191,17 @@ struct irec *enumerate_interfaces(struct iname *names,
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found && (new = add_iface(iface, ifr->ifr_name,
|
if (found)
|
||||||
&addr6, names, addrs, except)))
|
|
||||||
{
|
{
|
||||||
new->next = iface;
|
if (*names && (ifr->ifr_flags & IFF_LOOPBACK))
|
||||||
iface = new;
|
{
|
||||||
|
struct iname *lo = safe_malloc(sizeof(struct iname));
|
||||||
|
lo->addr = addr6;
|
||||||
|
lo->next = *addrs;
|
||||||
|
*addrs = lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = add_iface(iface, ifr->ifr_name, &addr6, *names, *addrs, except);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LINUX */
|
#endif /* LINUX */
|
||||||
|
|||||||
+269
-69
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000 - 2003 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000 - 2004 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,7 +21,7 @@ struct myoption {
|
|||||||
int val;
|
int val;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:"
|
#define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:"
|
||||||
|
|
||||||
static struct myoption opts[] = {
|
static struct myoption opts[] = {
|
||||||
{"version", 0, 0, 'v'},
|
{"version", 0, 0, 'v'},
|
||||||
@@ -67,7 +67,10 @@ static struct myoption opts[] = {
|
|||||||
{"except-interface", 1, 0, 'I'},
|
{"except-interface", 1, 0, 'I'},
|
||||||
{"domain-needed", 0, 0, 'D'},
|
{"domain-needed", 0, 0, 'D'},
|
||||||
{"dhcp-lease-max", 1, 0, 'X' },
|
{"dhcp-lease-max", 1, 0, 'X' },
|
||||||
|
{"bind-interfaces", 0, 0, 'z'},
|
||||||
{"read-ethers", 0, 0, 'Z' },
|
{"read-ethers", 0, 0, 'Z' },
|
||||||
|
{"alias", 1, 0, 'V' },
|
||||||
|
{"dhcp-vendorclass", 1, 0, 'U'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -137,7 +140,9 @@ static char *usage =
|
|||||||
"-t, --mx-target=host_name Specify the host in an MX reply.\n"
|
"-t, --mx-target=host_name Specify the host in an MX reply.\n"
|
||||||
"-T, --local-ttl=time Specify time-to-live in seconds for replies from /etc/hosts.\n"
|
"-T, --local-ttl=time Specify time-to-live in seconds for replies from /etc/hosts.\n"
|
||||||
"-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n"
|
"-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n"
|
||||||
|
"-U, --dhcp-vendorclass=<id>,<class> Map DHCP vendor class to option set.\n"
|
||||||
"-v, --version Display dnsmasq version.\n"
|
"-v, --version Display dnsmasq version.\n"
|
||||||
|
"-V, --alias=addr,addr,mask Translate IPv4 addresses from upstream servers.\n"
|
||||||
"-w, --help Display this message.\n"
|
"-w, --help Display this message.\n"
|
||||||
"-x, --pid-file=path Specify path of PID file. (defaults to " RUNFILE ").\n"
|
"-x, --pid-file=path Specify path of PID file. (defaults to " RUNFILE ").\n"
|
||||||
"-X, --dhcp-lease-max=number Specify maximum number of DHCP leases (defaults to %d).\n"
|
"-X, --dhcp-lease-max=number Specify maximum number of DHCP leases (defaults to %d).\n"
|
||||||
@@ -152,17 +157,16 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
struct iname **if_names, struct iname **if_addrs, struct iname **if_except,
|
||||||
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize, int *port,
|
struct bogus_addr **bogus_addr, struct server **serv_addrs, int *cachesize, int *port,
|
||||||
int *query_port, unsigned long *local_ttl, char **addn_hosts, struct dhcp_context **dhcp,
|
int *query_port, unsigned long *local_ttl, char **addn_hosts, struct dhcp_context **dhcp,
|
||||||
struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, char **dhcp_file,
|
struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, struct dhcp_vendor **dhcp_vendors, char **dhcp_file,
|
||||||
char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max,
|
char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max,
|
||||||
unsigned int *min_leasetime)
|
unsigned int *min_leasetime, struct doctor **doctors)
|
||||||
{
|
{
|
||||||
int option = 0, i;
|
int option = 0, i;
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
FILE *f = NULL;
|
FILE *file_save = NULL, *f = NULL;
|
||||||
char *conffile = CONFFILE;
|
char *file_name_save = NULL, *conffile = CONFFILE;
|
||||||
int conffile_set = 0;
|
int conffile_set = 0;
|
||||||
int lineno = 0;
|
int line_save = 0, lineno = 0;
|
||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
|
|
||||||
*min_leasetime = UINT_MAX;
|
*min_leasetime = UINT_MAX;
|
||||||
@@ -177,25 +181,38 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{ /* f non-NULL, reading from conffile. */
|
{ /* f non-NULL, reading from conffile. */
|
||||||
|
reread:
|
||||||
if (!fgets(buff, MAXDNAME, f))
|
if (!fgets(buff, MAXDNAME, f))
|
||||||
{
|
{
|
||||||
/* At end of file, all done */
|
/* At end of file, all done */
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
if (file_save)
|
||||||
|
{
|
||||||
|
/* may be nested */
|
||||||
|
conffile = file_name_save;
|
||||||
|
f = file_save;
|
||||||
|
file_save = NULL;
|
||||||
|
lineno = line_save;
|
||||||
|
goto reread;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
int white;
|
||||||
lineno++;
|
lineno++;
|
||||||
/* dump comments */
|
/* dump comments */
|
||||||
for (p = buff; *p; p++)
|
for (white = 1, p = buff; *p; p++)
|
||||||
if (*p == '#')
|
if (white && *p == '#')
|
||||||
|
{
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
white = isspace(*p);
|
||||||
/* fgets gets end of line char too. */
|
/* fgets gets end of line char too. */
|
||||||
while (strlen(buff) > 0 &&
|
while (strlen(buff) > 0 && isspace(buff[strlen(buff)-1]))
|
||||||
(buff[strlen(buff)-1] == '\n' ||
|
|
||||||
buff[strlen(buff)-1] == ' ' ||
|
|
||||||
buff[strlen(buff)-1] == '\t'))
|
|
||||||
buff[strlen(buff)-1] = 0;
|
buff[strlen(buff)-1] = 0;
|
||||||
if (*buff == 0)
|
if (*buff == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -224,6 +241,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
{ /* end of command line args, start reading conffile. */
|
{ /* end of command line args, start reading conffile. */
|
||||||
if (!conffile)
|
if (!conffile)
|
||||||
break; /* "confile=" option disables */
|
break; /* "confile=" option disables */
|
||||||
|
fileopen:
|
||||||
option = 0;
|
option = 0;
|
||||||
if (!(f = fopen(conffile, "r")))
|
if (!(f = fopen(conffile, "r")))
|
||||||
{
|
{
|
||||||
@@ -271,9 +289,27 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case 'C':
|
case 'C':
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
conffile = safe_string_alloc(optarg);
|
conffile = safe_string_alloc(optarg);
|
||||||
conffile_set = 1;
|
conffile_set = 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nest conffiles one deep */
|
||||||
|
if (file_save)
|
||||||
|
{
|
||||||
|
sprintf(buff, "nested includes not allowed at line %d of %s ", lineno, conffile);
|
||||||
|
complain(buff, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
file_name_save = conffile;
|
||||||
|
file_save = f;
|
||||||
|
line_save = lineno;
|
||||||
|
conffile = safe_string_alloc(optarg);
|
||||||
|
conffile_set = 1;
|
||||||
|
lineno = 0;
|
||||||
|
goto fileopen;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
*runfile = safe_string_alloc(optarg);
|
*runfile = safe_string_alloc(optarg);
|
||||||
@@ -355,6 +391,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
/* new->name may be NULL if someone does
|
/* new->name may be NULL if someone does
|
||||||
"interface=" to disable all interfaces except loop. */
|
"interface=" to disable all interfaces except loop. */
|
||||||
new->name = safe_string_alloc(optarg);
|
new->name = safe_string_alloc(optarg);
|
||||||
|
if (strchr(optarg, ':'))
|
||||||
|
flags |= OPT_NOWILD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,6 +402,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
new->next = *if_except;
|
new->next = *if_except;
|
||||||
*if_except = new;
|
*if_except = new;
|
||||||
new->name = safe_string_alloc(optarg);
|
new->name = safe_string_alloc(optarg);
|
||||||
|
if (strchr(optarg, ':'))
|
||||||
|
flags |= OPT_NOWILD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,11 +676,15 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
*(a[k]++) = 0;
|
*(a[k]++) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((k < 2) ||
|
if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
|
||||||
((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
|
||||||
((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
|
||||||
{
|
|
||||||
option = '?';
|
option = '?';
|
||||||
|
else if (strcmp(a[1], "static") == 0)
|
||||||
|
new->end = new->start;
|
||||||
|
else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
|
||||||
|
option = '?';
|
||||||
|
|
||||||
|
if (option == '?')
|
||||||
|
{
|
||||||
free(new);
|
free(new);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -680,36 +724,29 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
}
|
}
|
||||||
|
|
||||||
new->lease_time = atoi(a[leasepos]) * fac;
|
new->lease_time = atoi(a[leasepos]) * fac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (new->lease_time < *min_leasetime)
|
if (new->lease_time < *min_leasetime)
|
||||||
*min_leasetime = new->lease_time;
|
*min_leasetime = new->lease_time;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new->last = new->start;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'G':
|
case 'G':
|
||||||
{
|
{
|
||||||
int j, k;
|
int j, k;
|
||||||
char *a[4] = { NULL, NULL, NULL, NULL };
|
char *a[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
||||||
unsigned int e0, e1, e2, e3, e4, e5;
|
unsigned int e0, e1, e2, e3, e4, e5;
|
||||||
struct dhcp_config *new = safe_malloc(sizeof(struct dhcp_config));
|
struct dhcp_config *new = safe_malloc(sizeof(struct dhcp_config));
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
|
|
||||||
new->next = *dhcp_conf;
|
new->next = *dhcp_conf;
|
||||||
|
new->flags = 0;
|
||||||
|
|
||||||
memset(new->hwaddr, 0, ETHER_ADDR_LEN);
|
|
||||||
new->clid_len = 0;
|
|
||||||
new->clid = NULL;
|
|
||||||
new->hostname = NULL;
|
|
||||||
new->addr.s_addr = 0;
|
|
||||||
new->lease_time = 0;
|
|
||||||
|
|
||||||
a[0] = optarg;
|
a[0] = optarg;
|
||||||
for (k = 1; k < 4; k++)
|
for (k = 1; k < 6; k++)
|
||||||
{
|
{
|
||||||
if (!(a[k] = strchr(a[k-1], ',')))
|
if (!(a[k] = strchr(a[k-1], ',')))
|
||||||
break;
|
break;
|
||||||
@@ -717,37 +754,65 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(j = 0; j < k; j++)
|
for(j = 0; j < k; j++)
|
||||||
if (strchr(a[j], ':')) /* ethernet address or binary CLID */
|
if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
|
||||||
{
|
{
|
||||||
char *arg = a[j];
|
char *arg = a[j];
|
||||||
if ((arg[0] == 'i' || arg[0] == 'I') &&
|
if ((arg[0] == 'i' || arg[0] == 'I') &&
|
||||||
(arg[1] == 'd' || arg[1] == 'D') &&
|
(arg[1] == 'd' || arg[1] == 'D') &&
|
||||||
arg[2] == ':')
|
arg[2] == ':')
|
||||||
{
|
{
|
||||||
int s, len;
|
if (arg[3] == '*')
|
||||||
|
new->flags |= CONFIG_NOCLID;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int len;
|
||||||
arg += 3; /* dump id: */
|
arg += 3; /* dump id: */
|
||||||
if (strchr(arg, ':'))
|
if (strchr(arg, ':'))
|
||||||
{
|
{
|
||||||
s = (strlen(arg)/3) + 1;
|
/* decode hex in place */
|
||||||
/* decode in place */
|
char *p = arg, *q = arg, *r;
|
||||||
for (len = 0; len < s; len++)
|
while (*p)
|
||||||
{
|
{
|
||||||
if (arg[(len*3)+2] != ':')
|
for (r = p; *r && *r != ':'; r++);
|
||||||
option = '?';
|
if (*r)
|
||||||
arg[(len*3)+2] = 0;
|
{
|
||||||
arg[len] = strtol(&arg[len*3], NULL, 16);
|
if (r != p)
|
||||||
|
{
|
||||||
|
*r = 0;
|
||||||
|
*(q++) = strtol(p, NULL, 16);
|
||||||
}
|
}
|
||||||
|
p = r+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*p)
|
||||||
|
*(q++) = strtol(p, NULL, 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len = q - arg;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
len = strlen(arg);
|
len = strlen(arg);
|
||||||
|
|
||||||
|
new->flags |= CONFIG_CLID;
|
||||||
new->clid_len = len;
|
new->clid_len = len;
|
||||||
new->clid = safe_malloc(len);
|
new->clid = safe_malloc(len);
|
||||||
memcpy(new->clid, arg, len);
|
memcpy(new->clid, arg, len);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if ((arg[0] == 'n' || arg[0] == 'N') &&
|
||||||
|
(arg[1] == 'e' || arg[1] == 'E') &&
|
||||||
|
(arg[2] == 't' || arg[3] == 'T') &&
|
||||||
|
arg[3] == ':')
|
||||||
|
{
|
||||||
|
new->flags |= CONFIG_NETID;
|
||||||
|
new->netid = safe_string_alloc(arg+4);
|
||||||
|
}
|
||||||
else if (sscanf(a[j], "%x:%x:%x:%x:%x:%x",
|
else if (sscanf(a[j], "%x:%x:%x:%x:%x:%x",
|
||||||
&e0, &e1, &e2, &e3, &e4, &e5) == 6)
|
&e0, &e1, &e2, &e3, &e4, &e5) == 6)
|
||||||
{
|
{
|
||||||
|
new->flags |= CONFIG_HWADDR;
|
||||||
new->hwaddr[0] = e0;
|
new->hwaddr[0] = e0;
|
||||||
new->hwaddr[1] = e1;
|
new->hwaddr[1] = e1;
|
||||||
new->hwaddr[2] = e2;
|
new->hwaddr[2] = e2;
|
||||||
@@ -759,7 +824,10 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
option = '?';
|
option = '?';
|
||||||
}
|
}
|
||||||
else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
|
else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
|
||||||
|
{
|
||||||
new->addr = in;
|
new->addr = in;
|
||||||
|
new->flags |= CONFIG_ADDR;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *cp, *lastp = NULL, last = 0;
|
char *cp, *lastp = NULL, last = 0;
|
||||||
@@ -794,22 +862,41 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
if (lastp)
|
if (lastp)
|
||||||
*lastp = last;
|
*lastp = last;
|
||||||
if (strcmp(a[j], "infinite") == 0)
|
if (strcmp(a[j], "infinite") == 0)
|
||||||
|
{
|
||||||
new->lease_time = 0xffffffff;
|
new->lease_time = 0xffffffff;
|
||||||
|
new->flags |= CONFIG_TIME;
|
||||||
|
}
|
||||||
|
else if (strcmp(a[j], "ignore") == 0)
|
||||||
|
new->flags |= CONFIG_DISABLE;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
new->hostname = safe_string_alloc(a[j]);
|
new->hostname = safe_string_alloc(a[j]);
|
||||||
|
new->flags |= CONFIG_NAME;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new->lease_time = atoi(a[j]) * fac;
|
new->lease_time = atoi(a[j]) * fac;
|
||||||
if (new->lease_time < *min_leasetime)
|
new->flags |= CONFIG_TIME;
|
||||||
*min_leasetime = new->lease_time;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option == '?')
|
if (option == '?')
|
||||||
|
{
|
||||||
|
if (new->flags & CONFIG_NAME)
|
||||||
|
free(new->hostname);
|
||||||
|
if (new->flags & CONFIG_CLID)
|
||||||
|
free(new->clid);
|
||||||
|
if (new->flags & CONFIG_NETID)
|
||||||
|
free(new->netid);
|
||||||
free(new);
|
free(new);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if ((new->flags & CONFIG_TIME) && new->lease_time < *min_leasetime)
|
||||||
|
*min_leasetime = new->lease_time;
|
||||||
*dhcp_conf = new;
|
*dhcp_conf = new;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,7 +904,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
{
|
{
|
||||||
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
|
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
|
||||||
char *cp, *comma;
|
char *cp, *comma;
|
||||||
int addrs, is_addr;
|
int addrs, digs, is_addr, is_hex, is_dec;
|
||||||
|
|
||||||
new->next = *dhcp_opts;
|
new->next = *dhcp_opts;
|
||||||
new->len = 0;
|
new->len = 0;
|
||||||
@@ -848,57 +935,112 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!comma)
|
|
||||||
{
|
|
||||||
*dhcp_opts = new;
|
*dhcp_opts = new;
|
||||||
|
|
||||||
|
if (!comma)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* characterise the value */
|
||||||
|
is_addr = is_hex = is_dec = 1;
|
||||||
|
addrs = digs = 1;
|
||||||
|
for (cp = comma+1; *cp; cp++)
|
||||||
|
if (*cp == ',')
|
||||||
|
{
|
||||||
|
addrs++;
|
||||||
|
is_dec = is_hex = 0;
|
||||||
|
}
|
||||||
|
else if (*cp == ':')
|
||||||
|
{
|
||||||
|
digs++;
|
||||||
|
is_dec = is_addr = 0;
|
||||||
|
}
|
||||||
|
else if (*cp == '.')
|
||||||
|
is_dec = is_hex = 0;
|
||||||
|
else if (!(*cp >='0' && *cp <= '9'))
|
||||||
|
{
|
||||||
|
is_dec = is_addr = 0;
|
||||||
|
if (!((*cp >='A' && *cp <= 'F') ||
|
||||||
|
(*cp >='a' && *cp <= 'F')))
|
||||||
|
is_hex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for non-address list characters */
|
if (is_hex && digs > 1)
|
||||||
for (addrs = 1, is_addr = 0, cp = comma+1; *cp; cp++)
|
|
||||||
if (*cp == ',')
|
|
||||||
addrs++;
|
|
||||||
else if (!(*cp == '.' || *cp == ' ' || (*cp >='0' && *cp <= '9')))
|
|
||||||
break;
|
|
||||||
else if (*cp == '.')
|
|
||||||
is_addr = 1;
|
|
||||||
|
|
||||||
if (*cp)
|
|
||||||
{
|
{
|
||||||
/* text arg */
|
char *p = comma+1, *q, *r;
|
||||||
new->len = strlen(comma+1);
|
new->len = digs;
|
||||||
new->val = safe_malloc(new->len);
|
q = new->val = safe_malloc(new->len);
|
||||||
memcpy(new->val, comma+1, new->len);
|
while (*p)
|
||||||
|
{
|
||||||
|
for (r = p; *r && *r != ':'; r++);
|
||||||
|
if (*r)
|
||||||
|
{
|
||||||
|
if (r != p)
|
||||||
|
{
|
||||||
|
*r = 0;
|
||||||
|
*(q++) = strtol(p, NULL, 16);
|
||||||
|
}
|
||||||
|
p = r+1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct in_addr in;
|
if (*p)
|
||||||
unsigned char *op;
|
*(q++) = strtol(p, NULL, 16);
|
||||||
|
break;
|
||||||
if (addrs == 1 && !is_addr)
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_dec)
|
||||||
|
{
|
||||||
|
/* Given that we don't know the length,
|
||||||
|
this applaing hack is the best available */
|
||||||
|
unsigned int val = atoi(comma+1);
|
||||||
|
if (val < 256)
|
||||||
{
|
{
|
||||||
new->len = 1;
|
new->len = 1;
|
||||||
new->val = safe_malloc(1);
|
new->val = safe_malloc(1);
|
||||||
*(new->val) = atoi(comma+1);
|
*(new->val) = val;
|
||||||
|
}
|
||||||
|
else if (val < 65536)
|
||||||
|
{
|
||||||
|
new->len = 2;
|
||||||
|
new->val = safe_malloc(2);
|
||||||
|
*(new->val) = val>>8;
|
||||||
|
*(new->val+1) = val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
new->len = 4;
|
||||||
|
new->val = safe_malloc(4);
|
||||||
|
*(new->val) = val>>24;
|
||||||
|
*(new->val+1) = val>>16;
|
||||||
|
*(new->val+2) = val>>8;
|
||||||
|
*(new->val+3) = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_addr)
|
||||||
|
{
|
||||||
|
struct in_addr in;
|
||||||
|
unsigned char *op;
|
||||||
new->len = INADDRSZ * addrs;
|
new->len = INADDRSZ * addrs;
|
||||||
new->val = op = safe_malloc(new->len);
|
new->val = op = safe_malloc(new->len);
|
||||||
new->is_addr = 1;
|
new->is_addr = 1;
|
||||||
while (addrs--)
|
while (addrs--)
|
||||||
{
|
{
|
||||||
cp = comma;
|
cp = comma;
|
||||||
if (cp && (comma = strchr(cp+1, ',')))
|
if ((comma = strchr(cp+1, ',')))
|
||||||
*comma = 0;
|
*comma = 0;
|
||||||
if (cp && (in.s_addr = inet_addr(cp+1)) == (in_addr_t)-1)
|
in.s_addr = inet_addr(cp+1);
|
||||||
option = '?';
|
|
||||||
memcpy(op, &in, INADDRSZ);
|
memcpy(op, &in, INADDRSZ);
|
||||||
op += INADDRSZ;
|
op += INADDRSZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* text arg */
|
||||||
|
new->len = strlen(comma+1);
|
||||||
|
new->val = safe_malloc(new->len);
|
||||||
|
memcpy(new->val, comma+1, new->len);
|
||||||
}
|
}
|
||||||
*dhcp_opts = new;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,6 +1062,64 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'U':
|
||||||
|
{
|
||||||
|
char *comma;
|
||||||
|
|
||||||
|
if (!(comma = strchr(optarg, ',')))
|
||||||
|
option = '?';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct dhcp_vendor *new = safe_malloc(sizeof(struct dhcp_vendor));
|
||||||
|
*comma = 0;
|
||||||
|
new->net = safe_string_alloc(optarg);
|
||||||
|
new->len = strlen(comma+1);
|
||||||
|
new->data = safe_malloc(new->len);
|
||||||
|
memcpy(new->data, comma+1, new->len);
|
||||||
|
new->next = *dhcp_vendors;
|
||||||
|
*dhcp_vendors = new;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'V':
|
||||||
|
{
|
||||||
|
char *a[3] = { NULL, NULL, NULL };
|
||||||
|
int k;
|
||||||
|
struct in_addr in, out, mask;
|
||||||
|
struct doctor *new;
|
||||||
|
|
||||||
|
mask.s_addr = 0xffffffff;
|
||||||
|
|
||||||
|
a[0] = optarg;
|
||||||
|
for (k = 1; k < 4; k++)
|
||||||
|
{
|
||||||
|
if (!(a[k] = strchr(a[k-1], ',')))
|
||||||
|
break;
|
||||||
|
*(a[k]++) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((k < 2) ||
|
||||||
|
((in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
||||||
|
((out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
||||||
|
{
|
||||||
|
option = '?';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k == 3)
|
||||||
|
mask.s_addr = inet_addr(a[2]);
|
||||||
|
|
||||||
|
new = safe_malloc(sizeof(struct doctor));
|
||||||
|
new->in = in;
|
||||||
|
new->out = out;
|
||||||
|
new->mask = mask;
|
||||||
|
new->next = *doctors;
|
||||||
|
*doctors = new;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-1
@@ -440,7 +440,19 @@ void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now
|
|||||||
cache_end_insert();
|
cache_end_insert();
|
||||||
}
|
}
|
||||||
|
|
||||||
void extract_addresses(HEADER *header, unsigned int qlen, char *name, time_t now)
|
static void dns_doctor(struct doctor *doctor, struct in_addr *addr)
|
||||||
|
{
|
||||||
|
for (; doctor; doctor = doctor->next)
|
||||||
|
if (is_same_net(doctor->in, *addr, doctor->mask))
|
||||||
|
{
|
||||||
|
addr->s_addr &= ~doctor->mask.s_addr;
|
||||||
|
addr->s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void extract_addresses(HEADER *header, unsigned int qlen, char *name,
|
||||||
|
time_t now, struct doctor *doctors)
|
||||||
{
|
{
|
||||||
unsigned char *p, *psave, *endrr;
|
unsigned char *p, *psave, *endrr;
|
||||||
int qtype, qclass, rdlen;
|
int qtype, qclass, rdlen;
|
||||||
@@ -477,8 +489,11 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *name, time_t now
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == T_A) /* A record. */
|
if (qtype == T_A) /* A record. */
|
||||||
|
{
|
||||||
|
dns_doctor(doctors, (struct in_addr *)p);
|
||||||
cache_insert(name, (struct all_addr *)p, now,
|
cache_insert(name, (struct all_addr *)p, now,
|
||||||
ttl, F_IPV4 | F_FORWARD);
|
ttl, F_IPV4 | F_FORWARD);
|
||||||
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (qtype == T_AAAA) /* IPV6 address record. */
|
else if (qtype == T_AAAA) /* IPV6 address record. */
|
||||||
cache_insert(name, (struct all_addr *)p, now,
|
cache_insert(name, (struct all_addr *)p, now,
|
||||||
@@ -546,8 +561,11 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *name, time_t now
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (qtype == T_A) /* A record. */
|
if (qtype == T_A) /* A record. */
|
||||||
|
{
|
||||||
|
dns_doctor(doctors, (struct in_addr *)p);
|
||||||
cache_insert(name, (struct all_addr *)p, now,
|
cache_insert(name, (struct all_addr *)p, now,
|
||||||
cttl, F_IPV4 | F_FORWARD);
|
cttl, F_IPV4 | F_FORWARD);
|
||||||
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (qtype == T_AAAA) /* IPV6 address record. */
|
else if (qtype == T_AAAA) /* IPV6 address record. */
|
||||||
cache_insert(name, (struct all_addr *)p, now,
|
cache_insert(name, (struct all_addr *)p, now,
|
||||||
|
|||||||
+152
-77
@@ -35,6 +35,7 @@
|
|||||||
#define OPTION_MAXMESSAGE 57
|
#define OPTION_MAXMESSAGE 57
|
||||||
#define OPTION_T1 58
|
#define OPTION_T1 58
|
||||||
#define OPTION_T2 59
|
#define OPTION_T2 59
|
||||||
|
#define OPTION_VENDOR_ID 60
|
||||||
#define OPTION_CLIENT_ID 61
|
#define OPTION_CLIENT_ID 61
|
||||||
#define OPTION_END 255
|
#define OPTION_END 255
|
||||||
|
|
||||||
@@ -61,10 +62,14 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
unsigned char *req_options,
|
unsigned char *req_options,
|
||||||
struct dhcp_opt *config_opts,
|
struct dhcp_opt *config_opts,
|
||||||
char *domainname, char *hostname,
|
char *domainname, char *hostname,
|
||||||
struct in_addr relay,
|
struct in_addr router,
|
||||||
struct in_addr iface_addr,
|
struct in_addr iface_addr,
|
||||||
int iface_mtu);
|
int iface_mtu, char *netid);
|
||||||
|
|
||||||
|
static int have_config(struct dhcp_config *config, unsigned int mask)
|
||||||
|
{
|
||||||
|
return config && (config->flags & mask);
|
||||||
|
}
|
||||||
|
|
||||||
int dhcp_reply(struct dhcp_context *context,
|
int dhcp_reply(struct dhcp_context *context,
|
||||||
struct in_addr iface_addr,
|
struct in_addr iface_addr,
|
||||||
@@ -73,8 +78,9 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
struct udp_dhcp_packet *rawpacket,
|
struct udp_dhcp_packet *rawpacket,
|
||||||
unsigned int sz, time_t now, char *namebuff,
|
unsigned int sz, time_t now, char *namebuff,
|
||||||
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
|
||||||
|
struct dhcp_vendor *vendors,
|
||||||
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
||||||
struct in_addr dhcp_next_server)
|
struct in_addr dhcp_next_server, struct in_addr router)
|
||||||
{
|
{
|
||||||
unsigned char *opt, *clid;
|
unsigned char *opt, *clid;
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
@@ -88,13 +94,29 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
unsigned int renewal_time, expires_time, def_time;
|
unsigned int renewal_time, expires_time, def_time;
|
||||||
struct dhcp_config *config;
|
struct dhcp_config *config;
|
||||||
|
char *netid;
|
||||||
|
struct in_addr addr;
|
||||||
|
unsigned short fuzz = 0;
|
||||||
|
|
||||||
if (mess->op != BOOTREQUEST ||
|
if (mess->op != BOOTREQUEST ||
|
||||||
mess->htype != ARPHRD_ETHER ||
|
|
||||||
mess->hlen != ETHER_ADDR_LEN ||
|
mess->hlen != ETHER_ADDR_LEN ||
|
||||||
mess->cookie != htonl(DHCP_COOKIE))
|
mess->cookie != htonl(DHCP_COOKIE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* Token ring is supported when we have packet sockets
|
||||||
|
to make the HW headers for us. We don't have the code to build
|
||||||
|
token ring headers when using BPF. We rely on the fact that
|
||||||
|
token ring hwaddrs are the same size as ethernet hwaddrs. */
|
||||||
|
|
||||||
|
#ifdef HAVE_BPF
|
||||||
|
if (mess->htype != ARPHRD_ETHER)
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
if (mess->htype != ARPHRD_ETHER &&
|
||||||
|
mess->htype != ARPHRD_IEEE802)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
mess->op = BOOTREPLY;
|
mess->op = BOOTREPLY;
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE)))
|
if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE)))
|
||||||
@@ -120,19 +142,8 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
clid_len = 0;
|
clid_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do we have a lease in store? */
|
|
||||||
lease = lease_find_by_client(clid, clid_len);
|
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS)))
|
|
||||||
{
|
|
||||||
int len = option_len(opt);
|
|
||||||
req_options = namebuff;
|
|
||||||
memcpy(req_options, option_ptr(opt), len);
|
|
||||||
req_options[len] = OPTION_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, NULL)) &&
|
if ((config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, NULL)) &&
|
||||||
config->hostname)
|
have_config(config, CONFIG_NAME))
|
||||||
hostname = config->hostname;
|
hostname = config->hostname;
|
||||||
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME)))
|
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME)))
|
||||||
{
|
{
|
||||||
@@ -159,12 +170,34 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
else
|
else
|
||||||
*dot = 0; /* truncate */
|
*dot = 0; /* truncate */
|
||||||
}
|
}
|
||||||
|
/* search again now we have a hostname */
|
||||||
|
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search again now we have a hostname */
|
def_time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||||
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
|
|
||||||
def_time = config && config->lease_time ? config->lease_time : context->lease_time;
|
netid = context->netid;
|
||||||
|
if (have_config(config, CONFIG_NETID))
|
||||||
|
netid = config->netid;
|
||||||
|
else if ((opt = option_find(mess, sz, OPTION_VENDOR_ID)))
|
||||||
|
{
|
||||||
|
struct dhcp_vendor *vendor;
|
||||||
|
for (vendor = vendors; vendor; vendor = vendor->next)
|
||||||
|
if (vendor->len == option_len(opt) &&
|
||||||
|
memcmp(vendor->data, option_ptr(opt), vendor->len) == 0)
|
||||||
|
netid = vendor->net;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can have setting to ignore the client ID for a particular MAC address or hostname */
|
||||||
|
if (have_config(config, CONFIG_NOCLID))
|
||||||
|
{
|
||||||
|
clid = mess->chaddr;
|
||||||
|
clid_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do we have a lease in store? */
|
||||||
|
lease = lease_find_by_client(clid, clid_len);
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
||||||
{
|
{
|
||||||
@@ -185,10 +218,18 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
expires_time = def_time;
|
expires_time = def_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS)))
|
||||||
|
{
|
||||||
|
int len = option_len(opt);
|
||||||
|
req_options = namebuff;
|
||||||
|
memcpy(req_options, option_ptr(opt), len);
|
||||||
|
req_options[len] = OPTION_END;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(opt = option_find(mess, sz, OPTION_MESSAGE_TYPE)))
|
if (!(opt = option_find(mess, sz, OPTION_MESSAGE_TYPE)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (opt[2])
|
switch (option_uint(opt, 1))
|
||||||
{
|
{
|
||||||
case DHCPDECLINE:
|
case DHCPDECLINE:
|
||||||
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER)) ||
|
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER)) ||
|
||||||
@@ -219,11 +260,11 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||||
lease_prune(lease, now);
|
lease_prune(lease, now);
|
||||||
|
|
||||||
if (config && config->addr.s_addr &&
|
if (have_config(config, CONFIG_ADDR) &&
|
||||||
config->addr.s_addr == option_addr(opt).s_addr)
|
config->addr.s_addr == option_addr(opt).s_addr)
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "disabling DHCP static address %s", inet_ntoa(config->addr));
|
syslog(LOG_WARNING, "disabling DHCP static address %s", inet_ntoa(config->addr));
|
||||||
config->addr.s_addr = 0;
|
config->flags &= ~CONFIG_ADDR ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -242,37 +283,48 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
|
|
||||||
case DHCPDISCOVER:
|
case DHCPDISCOVER:
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
||||||
mess->yiaddr = option_addr(opt);
|
addr = option_addr(opt);
|
||||||
|
|
||||||
log_packet("DISCOVER", opt ? &mess->yiaddr : NULL, mess->chaddr, iface_name, NULL);
|
if (have_config(config, CONFIG_DISABLE))
|
||||||
|
message = "ignored";
|
||||||
if (lease &&
|
else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr))
|
||||||
((lease->addr.s_addr & context->netmask.s_addr) == (context->start.s_addr & context->netmask.s_addr)))
|
|
||||||
mess->yiaddr = lease->addr;
|
|
||||||
else if (config && config->addr.s_addr && !lease_find_by_addr(config->addr))
|
|
||||||
mess->yiaddr = config->addr;
|
mess->yiaddr = config->addr;
|
||||||
else if ((!opt || !address_available(context, mess->yiaddr)) &&
|
else if (lease && is_same_net(lease->addr, context->start, context->netmask))
|
||||||
!address_allocate(context, dhcp_configs, &mess->yiaddr))
|
mess->yiaddr = lease->addr;
|
||||||
{
|
else if (opt && address_available(context, addr))
|
||||||
syslog(LOG_WARNING, "address pool exhausted");
|
mess->yiaddr = addr;
|
||||||
return 0;
|
else if (!address_allocate(context, dhcp_configs, &mess->yiaddr, mess->chaddr))
|
||||||
}
|
message = "no address available";
|
||||||
|
|
||||||
|
log_packet("DISCOVER", opt ? &addr : NULL, mess->chaddr, iface_name, message);
|
||||||
|
|
||||||
|
if (message)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* ensure that we send the reply by steam even if a buggy client sets this. */
|
||||||
|
mess->ciaddr.s_addr = 0;
|
||||||
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
||||||
mess->siaddr = dhcp_next_server;
|
mess->siaddr = dhcp_next_server.s_addr ? dhcp_next_server : iface_addr;
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
||||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||||
p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time);
|
p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time);
|
||||||
|
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
||||||
|
if (expires_time != 0xffffffff)
|
||||||
|
{
|
||||||
|
p = option_put(p, end, OPTION_T1, 4, (expires_time/2));
|
||||||
|
p = option_put(p, end, OPTION_T2, 4, ((expires_time * 7)/8));
|
||||||
|
}
|
||||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||||
NULL, mess->giaddr, iface_addr, iface_mtu);
|
NULL, router, iface_addr, iface_mtu, netid);
|
||||||
p = option_put(p, end, OPTION_END, 0, 0);
|
p = option_put(p, end, OPTION_END, 0, 0);
|
||||||
|
|
||||||
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||||
return p - (unsigned char *)mess;
|
return p - (unsigned char *)mess;
|
||||||
|
|
||||||
|
|
||||||
case DHCPREQUEST:
|
case DHCPREQUEST:
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
if (have_config(config, CONFIG_DISABLE))
|
||||||
|
message = "disabled";
|
||||||
|
else if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
||||||
{
|
{
|
||||||
/* SELECTING or INIT_REBOOT */
|
/* SELECTING or INIT_REBOOT */
|
||||||
mess->yiaddr = option_addr(opt);
|
mess->yiaddr = option_addr(opt);
|
||||||
@@ -296,7 +348,7 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
if (!lease)
|
if (!lease)
|
||||||
{
|
{
|
||||||
if (!address_available(context, mess->yiaddr) &&
|
if (!address_available(context, mess->yiaddr) &&
|
||||||
(!config || config->addr.s_addr == 0 || config->addr.s_addr != mess->yiaddr.s_addr))
|
(!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
|
||||||
message = "address unavailable";
|
message = "address unavailable";
|
||||||
else if (!(lease = lease_allocate(clid, clid_len, mess->yiaddr)))
|
else if (!(lease = lease_allocate(clid, clid_len, mess->yiaddr)))
|
||||||
message = "no leases left";
|
message = "no leases left";
|
||||||
@@ -312,10 +364,15 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
mess->yiaddr = mess->ciaddr;
|
mess->yiaddr = mess->ciaddr;
|
||||||
if (!lease || mess->ciaddr.s_addr != lease->addr.s_addr)
|
if (!lease || mess->ciaddr.s_addr != lease->addr.s_addr)
|
||||||
message = "lease not found";
|
message = "lease not found";
|
||||||
|
|
||||||
|
/* desynchronise renewals */
|
||||||
|
fuzz = rand16();
|
||||||
|
while (fuzz > (renewal_time/16))
|
||||||
|
fuzz = fuzz/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a machine moves networks whilst it has a lease, we catch that here. */
|
/* If a machine moves networks whilst it has a lease, we catch that here. */
|
||||||
if ((mess->yiaddr.s_addr & context->netmask.s_addr) != (context->start.s_addr & context->netmask.s_addr))
|
if (!message && !is_same_net(mess->yiaddr, context->start, context->netmask))
|
||||||
message = "wrong network";
|
message = "wrong network";
|
||||||
|
|
||||||
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||||
@@ -340,30 +397,33 @@ int dhcp_reply(struct dhcp_context *context,
|
|||||||
lease_set_expires(lease, renewal_time == 0xffffffff ? 0 : now + (time_t)renewal_time);
|
lease_set_expires(lease, renewal_time == 0xffffffff ? 0 : now + (time_t)renewal_time);
|
||||||
|
|
||||||
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
||||||
mess->siaddr = dhcp_next_server;
|
mess->siaddr = dhcp_next_server.s_addr ? dhcp_next_server : iface_addr;
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||||
p = option_put(p, end, OPTION_LEASE_TIME, 4, renewal_time);
|
p = option_put(p, end, OPTION_LEASE_TIME, 4, renewal_time);
|
||||||
if (renewal_time != 0xffffffff)
|
if (renewal_time != 0xffffffff)
|
||||||
{
|
{
|
||||||
unsigned short fuzz = rand16();
|
|
||||||
while (fuzz > (renewal_time/16))
|
|
||||||
fuzz = fuzz/2;
|
|
||||||
p = option_put(p, end, OPTION_T1, 4, (renewal_time/2) - fuzz);
|
p = option_put(p, end, OPTION_T1, 4, (renewal_time/2) - fuzz);
|
||||||
p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz);
|
p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz);
|
||||||
}
|
}
|
||||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||||
hostname, mess->giaddr, iface_addr, iface_mtu);
|
hostname, router, iface_addr, iface_mtu, netid);
|
||||||
p = option_put(p, end, OPTION_END, 0, 0);
|
p = option_put(p, end, OPTION_END, 0, 0);
|
||||||
return p - (unsigned char *)mess;
|
return p - (unsigned char *)mess;
|
||||||
|
|
||||||
case DHCPINFORM:
|
case DHCPINFORM:
|
||||||
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, NULL);
|
if (have_config(config, CONFIG_DISABLE))
|
||||||
|
message = "ignored";
|
||||||
|
|
||||||
|
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, message);
|
||||||
|
|
||||||
|
if (message || mess->ciaddr.s_addr == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||||
hostname, mess->giaddr, iface_addr, iface_mtu);
|
hostname, router, iface_addr, iface_mtu, netid);
|
||||||
p = option_put(p, end, OPTION_END, 0, 0);
|
p = option_put(p, end, OPTION_END, 0, 0);
|
||||||
|
|
||||||
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
|
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
|
||||||
@@ -516,6 +576,10 @@ static int in_list(unsigned char *list, int opt)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* If no requested options, send everything, not nothing. */
|
||||||
|
if (!list)
|
||||||
|
return 1;
|
||||||
|
|
||||||
for (i = 0; list[i] != OPTION_END; i++)
|
for (i = 0; list[i] != OPTION_END; i++)
|
||||||
if (opt == list[i])
|
if (opt == list[i])
|
||||||
return 1;
|
return 1;
|
||||||
@@ -523,13 +587,17 @@ static int in_list(unsigned char *list, int opt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dhcp_opt *option_find2(struct dhcp_context *context, struct dhcp_opt *opts, int opt)
|
static struct dhcp_opt *option_find2(char *netid, struct dhcp_opt *opts, int opt)
|
||||||
{
|
{
|
||||||
for (; opts; opts = opts->next)
|
struct dhcp_opt *tmp;
|
||||||
if (opts->opt == opt &&
|
|
||||||
(!opts->netid || (context->netid && strcmp(opts->netid, context->netid) == 0)))
|
for (tmp = opts; tmp; tmp = tmp->next)
|
||||||
return opts;
|
if (tmp->opt == opt &&
|
||||||
return NULL;
|
((!netid && !tmp->netid) ||
|
||||||
|
(netid && tmp->netid && strcmp(tmp->netid, netid) == 0)))
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
return netid ? option_find2(NULL, opts, opt) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *do_req_options(struct dhcp_context *context,
|
static unsigned char *do_req_options(struct dhcp_context *context,
|
||||||
@@ -537,14 +605,11 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
unsigned char *req_options,
|
unsigned char *req_options,
|
||||||
struct dhcp_opt *config_opts,
|
struct dhcp_opt *config_opts,
|
||||||
char *domainname, char *hostname,
|
char *domainname, char *hostname,
|
||||||
struct in_addr relay,
|
struct in_addr router,
|
||||||
struct in_addr iface_addr,
|
struct in_addr iface_addr,
|
||||||
int iface_mtu)
|
int iface_mtu, char *netid)
|
||||||
{
|
{
|
||||||
int i;
|
struct dhcp_opt *opt;
|
||||||
|
|
||||||
if (!req_options)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
if (in_list(req_options, OPTION_MAXMESSAGE))
|
if (in_list(req_options, OPTION_MAXMESSAGE))
|
||||||
p = option_put(p, end, OPTION_MAXMESSAGE, 2,
|
p = option_put(p, end, OPTION_MAXMESSAGE, 2,
|
||||||
@@ -552,24 +617,24 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
iface_mtu : DNSMASQ_PACKETSZ);
|
iface_mtu : DNSMASQ_PACKETSZ);
|
||||||
|
|
||||||
if (in_list(req_options, OPTION_NETMASK) &&
|
if (in_list(req_options, OPTION_NETMASK) &&
|
||||||
!option_find2(context, config_opts, OPTION_NETMASK))
|
!option_find2(netid, config_opts, OPTION_NETMASK))
|
||||||
p = option_put(p, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
|
p = option_put(p, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
|
||||||
|
|
||||||
if (in_list(req_options, OPTION_BROADCAST) &&
|
if (in_list(req_options, OPTION_BROADCAST) &&
|
||||||
!option_find2(context, config_opts, OPTION_BROADCAST))
|
!option_find2(netid, config_opts, OPTION_BROADCAST))
|
||||||
p = option_put(p, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
|
p = option_put(p, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
|
||||||
|
|
||||||
if (in_list(req_options, OPTION_ROUTER) &&
|
if (in_list(req_options, OPTION_ROUTER) &&
|
||||||
!option_find2(context, config_opts, OPTION_ROUTER))
|
!option_find2(netid, config_opts, OPTION_ROUTER))
|
||||||
p = option_put(p, end, OPTION_ROUTER, INADDRSZ,
|
p = option_put(p, end, OPTION_ROUTER, INADDRSZ,
|
||||||
ntohl(relay.s_addr ? relay.s_addr : iface_addr.s_addr ));
|
ntohl(router.s_addr));
|
||||||
|
|
||||||
if (in_list(req_options, OPTION_DNSSERVER) &&
|
if (in_list(req_options, OPTION_DNSSERVER) &&
|
||||||
!option_find2(context, config_opts, OPTION_DNSSERVER))
|
!option_find2(netid, config_opts, OPTION_DNSSERVER))
|
||||||
p = option_put(p, end, OPTION_DNSSERVER, INADDRSZ, ntohl(iface_addr.s_addr));
|
p = option_put(p, end, OPTION_DNSSERVER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||||
|
|
||||||
if (domainname && in_list(req_options, OPTION_DOMAINNAME) &&
|
if (domainname && in_list(req_options, OPTION_DOMAINNAME) &&
|
||||||
!option_find2(context, config_opts, OPTION_DOMAINNAME))
|
!option_find2(netid, config_opts, OPTION_DOMAINNAME))
|
||||||
p = option_put_string(p, end, OPTION_DOMAINNAME, domainname);
|
p = option_put_string(p, end, OPTION_DOMAINNAME, domainname);
|
||||||
|
|
||||||
/* Note that we ignore attempts to set the hostname using
|
/* Note that we ignore attempts to set the hostname using
|
||||||
@@ -577,17 +642,30 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
if (hostname && in_list(req_options, OPTION_HOSTNAME))
|
if (hostname && in_list(req_options, OPTION_HOSTNAME))
|
||||||
p = option_put_string(p, end, OPTION_HOSTNAME, hostname);
|
p = option_put_string(p, end, OPTION_HOSTNAME, hostname);
|
||||||
|
|
||||||
for (i = 0; req_options[i] != OPTION_END; i++)
|
for (opt=config_opts; opt; opt = opt->next)
|
||||||
{
|
|
||||||
struct dhcp_opt *opt = option_find2(context, config_opts, req_options[i]);
|
|
||||||
if (req_options[i] != OPTION_HOSTNAME &&
|
|
||||||
req_options[i] != OPTION_MAXMESSAGE &&
|
|
||||||
opt && (p + opt->len + 3 < end))
|
|
||||||
{
|
{
|
||||||
|
if (opt->opt == OPTION_HOSTNAME ||
|
||||||
|
opt->opt == OPTION_MAXMESSAGE ||
|
||||||
|
!in_list(req_options, opt->opt) ||
|
||||||
|
opt != option_find2(netid, config_opts, opt->opt) ||
|
||||||
|
p + opt->len + 3 >= end)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* For the options we have default values on
|
||||||
|
dhc-option=<optionno> means "don't include this option"
|
||||||
|
not "include a zero-length option" */
|
||||||
|
if (opt->len == 0 &&
|
||||||
|
(opt->opt == OPTION_NETMASK ||
|
||||||
|
opt->opt == OPTION_BROADCAST ||
|
||||||
|
opt->opt == OPTION_ROUTER ||
|
||||||
|
opt->opt == OPTION_DNSSERVER))
|
||||||
|
continue;
|
||||||
|
|
||||||
*(p++) = opt->opt;
|
*(p++) = opt->opt;
|
||||||
*(p++) = opt->len;
|
*(p++) = opt->len;
|
||||||
if (opt->len != 0)
|
if (opt->len == 0)
|
||||||
{
|
continue;
|
||||||
|
|
||||||
if (opt->is_addr)
|
if (opt->is_addr)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
@@ -608,9 +686,6 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
|||||||
p += opt->len;
|
p += opt->len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -228,3 +228,8 @@ time_t dnsmasq_time(int fd)
|
|||||||
return time(NULL);
|
return time(NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
||||||
|
{
|
||||||
|
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user