mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.6.tar.gz
This commit is contained in:
64
CHANGELOG
64
CHANGELOG
@@ -860,4 +860,68 @@ release 2.5
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
35
FAQ
35
FAQ
@@ -181,7 +181,42 @@ A: There are a couple of configuration gotchas which have been
|
||||
and from ports 67 and 68 and broadcast packets with source
|
||||
address 0.0.0.0 and destination address 255.255.255.255 are not
|
||||
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,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
|
||||
have addresses allocated by DHCP to be included in the DNS.
|
||||
|
||||
Version 2.x of dnsmasq removes the ISC dhcpd integration and replaces
|
||||
it with a DHCP server integrated into dnsmasq. This is an incompatible
|
||||
change in dnsmasq but it has the following advantages:
|
||||
Version 2.x of dnsmasq replaces the ISC dhcpd integration with a DHCP
|
||||
server integrated into dnsmasq. Versions 2.0-2.5 removed the ISC
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
|
||||
DHCP configuration
|
||||
------------------
|
||||
|
||||
@@ -55,9 +56,9 @@ in the same way as before.
|
||||
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
|
||||
Linux, this is best done by killing-and-restarting the DHCP client
|
||||
daemon or taking the network interface down and then back up. For
|
||||
Windows use winipcfg.exe
|
||||
|
||||
daemon or taking the network interface down and then back up. For
|
||||
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
|
||||
dnsmasq manpage and the annotated example configuration file. Also
|
||||
|
||||
130
dnsmasq-mdk.spec
130
dnsmasq-mdk.spec
@@ -1,130 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# General mumbojumbo
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.5
|
||||
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
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.5
|
||||
Version: 2.6
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: System Environment/Daemons
|
||||
@@ -58,7 +58,6 @@ 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
|
||||
gzip $RPM_BUILD_ROOT/usr/share/man/man8/dnsmasq.8
|
||||
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(0664,root,root) /etc/dnsmasq.conf
|
||||
%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*
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.5
|
||||
Version: 2.6
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Productivity/Networking/DNS/Servers
|
||||
|
||||
44
dnsmasq.8
44
dnsmasq.8
@@ -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.
|
||||
.SH OPTIONS
|
||||
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
|
||||
.B \-h, --no-hosts
|
||||
Don't read the hostnames in /etc/hosts.
|
||||
@@ -271,9 +274,16 @@ given using the
|
||||
.B interface
|
||||
option. This limitation currently affects OpenBSD. The optional
|
||||
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
|
||||
.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
|
||||
with a particular hardware address to be always allocated the same
|
||||
hostname, IP address and lease time. A hostname specified like this
|
||||
@@ -299,7 +309,16 @@ allowed to specify the client ID as text, like this:
|
||||
If a name appears in /etc/hosts, the associated address can be
|
||||
allocated to a DHCP lease, but only if a
|
||||
.B --dhcp-host
|
||||
option specifying the name also exists.
|
||||
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
|
||||
.B \-Z, --read-ethers
|
||||
Read /etc/ethers for information about hosts for the DHCP server. The
|
||||
@@ -323,7 +342,9 @@ specfied in RFC2132. For example, to set the default route option to
|
||||
and to set the time-server address to 192.168.0.4, do
|
||||
.B dhcp-option=42,192.168.0.4
|
||||
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
|
||||
contains a matching network-id.
|
||||
Be careful: no checking is done that the correct type of data for the
|
||||
@@ -344,7 +365,12 @@ create thousands of leases and use lots of memory in the dnsmasq
|
||||
process.
|
||||
.TP
|
||||
.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
|
||||
.B \-s, --domain=<domain>
|
||||
Specifies the domain for the DHCP server. This has two effects;
|
||||
@@ -361,12 +387,14 @@ Add the domain-suffix to simple names (without a period) in /etc/hosts
|
||||
in the same way as for DHCP-derived names.
|
||||
.SH CONFIG FILE
|
||||
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
|
||||
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
|
||||
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
|
||||
When it receives a SIGHUP,
|
||||
.B dnsmasq
|
||||
|
||||
@@ -157,6 +157,14 @@ filterwin2k
|
||||
# it asks for a DHCP lease.
|
||||
#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
|
||||
|
||||
# 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
|
||||
# on the ethernet-address/IP pairs found there just as if they had
|
||||
# been given as --dhcp-host options. Useful if you keep
|
||||
@@ -193,6 +201,10 @@ filterwin2k
|
||||
# Set the "all subnets are local" flag
|
||||
#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
|
||||
# (see dhcp-range for the declaration of the "red" network)
|
||||
#dhcp-option=red,42,192.168.1.1
|
||||
@@ -250,13 +262,13 @@ filterwin2k
|
||||
# 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
|
||||
# dnsmasq.
|
||||
#log-queries
|
||||
|
||||
|
||||
# Include a another lot of configuration options.
|
||||
#conf-file=/etc/dnsmasq.more.conf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
CFLAGS?= -O2
|
||||
|
||||
OBJS = cache.o rfc1035.o util.o option.o forward.o \
|
||||
network.o dnsmasq.o dhcp.o lease.o rfc2131.o
|
||||
OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o \
|
||||
network.o dnsmasq.o dhcp.o lease.o rfc2131.o
|
||||
|
||||
.c.o: dnsmasq.h config.h
|
||||
$(CC) $(CFLAGS) $(RPM_OPT_FLAGS) -Wall -W -c $*.c
|
||||
|
||||
19
src/config.h
19
src/config.h
@@ -12,12 +12,13 @@
|
||||
|
||||
/* Author's email: simon@thekelleys.org.uk */
|
||||
|
||||
#define VERSION "2.5"
|
||||
#define VERSION "2.6"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */
|
||||
#define LOGRATE 120 /* log table overflows every LOGRATE seconds */
|
||||
#define CACHESIZ 150 /* default cache size */
|
||||
#define MAXTOK 50 /* token in DHCP leases */
|
||||
#define MAXLEASES 150 /* maximum number of DHCP leases */
|
||||
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
||||
#define HOSTSFILE "/etc/hosts"
|
||||
@@ -121,6 +122,10 @@ HAVE_BROKEN_RTC
|
||||
work on other systems by teaching dnsmasq_time() in utils.c how to
|
||||
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
|
||||
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. */
|
||||
#if defined(__uClinux__) || defined(__UCLIBC__)
|
||||
#undef HAVE_LINUX_IPV6_PROC
|
||||
@@ -255,6 +270,7 @@ typedef unsigned long in_addr_t;
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
#undef HAVE_PSELECT
|
||||
#define HAVE_BPF
|
||||
#define BIND_8_COMPAT
|
||||
/* Define before sys/socket.h is included so we get socklen_t */
|
||||
#define _BSD_SOCKLEN_T_
|
||||
/* The two below are not defined in Mac OS X arpa/nameserv.h */
|
||||
@@ -287,3 +303,4 @@ typedef unsigned long in_addr_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
143
src/dhcp.c
143
src/dhcp.c
@@ -362,6 +362,10 @@ int address_available(struct dhcp_context *context, struct in_addr taddr)
|
||||
start = ntohl(context->start.s_addr);
|
||||
end = ntohl(context->end.s_addr);
|
||||
|
||||
/* static leases only. */
|
||||
if (start == end)
|
||||
return 0;
|
||||
|
||||
if (addr < start)
|
||||
return 0;
|
||||
|
||||
@@ -382,7 +386,11 @@ int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
||||
|
||||
struct dhcp_config *config;
|
||||
struct in_addr start = context->last;
|
||||
|
||||
|
||||
/* start == end means no dynamic leases. */
|
||||
if (context->end.s_addr == context->start.s_addr)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
if (context->last.s_addr == context->end.s_addr)
|
||||
context->last = context->start;
|
||||
@@ -393,7 +401,7 @@ int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
|
||||
if (!lease_find_by_addr(context->last))
|
||||
{
|
||||
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 == context->last.s_addr)
|
||||
break;
|
||||
|
||||
if (!config)
|
||||
@@ -411,7 +419,7 @@ static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *
|
||||
{
|
||||
if (!context)
|
||||
return 1;
|
||||
if (config->addr.s_addr == 0)
|
||||
if (!(config->flags & CONFIG_ADDR))
|
||||
return 1;
|
||||
if ((config->addr.s_addr & context->netmask.s_addr) == (context->start.s_addr & context->netmask.s_addr))
|
||||
return 1;
|
||||
@@ -428,28 +436,31 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
|
||||
if (clid_len)
|
||||
for (config = configs; config; config = config->next)
|
||||
{
|
||||
if (config->clid_len == clid_len &&
|
||||
memcmp(config->clid, clid, clid_len) == 0 &&
|
||||
is_addr_in_context(context, config))
|
||||
return config;
|
||||
|
||||
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
|
||||
cope with that here */
|
||||
if (*clid == 0 && config->clid_len == clid_len-1 &&
|
||||
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
|
||||
is_addr_in_context(context, config))
|
||||
return config;
|
||||
}
|
||||
|
||||
if (config->flags & CONFIG_CLID)
|
||||
{
|
||||
if (config->clid_len == clid_len &&
|
||||
memcmp(config->clid, clid, clid_len) == 0 &&
|
||||
is_addr_in_context(context, config))
|
||||
return config;
|
||||
|
||||
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
|
||||
cope with that here */
|
||||
if (*clid == 0 && config->clid_len == clid_len-1 &&
|
||||
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
|
||||
is_addr_in_context(context, config))
|
||||
return config;
|
||||
}
|
||||
|
||||
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))
|
||||
return config;
|
||||
|
||||
if (hostname)
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->hostname && hostname_isequal(config->hostname, hostname) &&
|
||||
if ((config->flags & CONFIG_NAME) &&
|
||||
hostname_isequal(config->hostname, hostname) &&
|
||||
is_addr_in_context(context, config))
|
||||
return config;
|
||||
|
||||
@@ -459,28 +470,29 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
|
||||
{
|
||||
FILE *f = fopen(ETHERSFILE, "r");
|
||||
unsigned int e0, e1, e2, e3, e4, e5;
|
||||
char *ip, *cp, *name;
|
||||
unsigned int flags, e0, e1, e2, e3, e4, e5;
|
||||
char *ip, *cp;
|
||||
struct in_addr addr;
|
||||
unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||
struct dhcp_config *config;
|
||||
int count = 0;
|
||||
|
||||
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 (strlen(buff) > 0 &&
|
||||
(buff[strlen(buff)-1] == '\n' ||
|
||||
buff[strlen(buff)-1] == ' ' ||
|
||||
buff[strlen(buff)-1] == '\r' ||
|
||||
buff[strlen(buff)-1] == '\t'))
|
||||
while (strlen(buff) > 0 && isspace(buff[strlen(buff)-1]))
|
||||
buff[strlen(buff)-1] = 0;
|
||||
|
||||
if ((*buff == '#') || (*buff == '+'))
|
||||
continue;
|
||||
|
||||
for (ip = buff; *ip && *ip != ' ' && *ip != '\t'; ip++);
|
||||
for(; *ip && (*ip == ' ' || *ip == '\t'); ip++)
|
||||
for (ip = buff; *ip && !isspace(*ip); ip++);
|
||||
for(; *ip && isspace(*ip); ip++)
|
||||
*ip = 0;
|
||||
if (!*ip)
|
||||
continue;
|
||||
@@ -488,6 +500,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))
|
||||
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 */
|
||||
for (cp = ip; *cp; cp++)
|
||||
if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
|
||||
@@ -495,47 +514,64 @@ struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
|
||||
|
||||
if (!*cp)
|
||||
{
|
||||
name = NULL;
|
||||
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
|
||||
continue;
|
||||
flags = CONFIG_ADDR;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->addr.s_addr == addr.s_addr)
|
||||
if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!canonicalise(ip))
|
||||
continue;
|
||||
name = ip;
|
||||
addr.s_addr = 0;
|
||||
flags = CONFIG_NAME;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->hostname && hostname_isequal(config->hostname, name))
|
||||
if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, ip))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!config)
|
||||
{
|
||||
config = safe_malloc(sizeof(struct dhcp_config));
|
||||
config->clid_len = 0;
|
||||
config->clid = NULL;
|
||||
config->lease_time = 0;
|
||||
config->hostname = safe_string_alloc(name);
|
||||
config->addr = addr;
|
||||
config->next = configs;
|
||||
configs = config;
|
||||
for (config = configs; config; config = config->next)
|
||||
if ((config->flags & CONFIG_HWADDR) &&
|
||||
memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
|
||||
break;
|
||||
|
||||
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);
|
||||
|
||||
config->hwaddr[0] = e0;
|
||||
config->hwaddr[1] = e1;
|
||||
config->hwaddr[2] = e2;
|
||||
config->hwaddr[3] = e3;
|
||||
config->hwaddr[4] = e4;
|
||||
config->hwaddr[5] = e5;
|
||||
count++;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
syslog(LOG_INFO, "read " ETHERSFILE " - %d addresses", count);
|
||||
return configs;
|
||||
}
|
||||
|
||||
@@ -549,10 +585,13 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
||||
struct crec *crec;
|
||||
|
||||
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->flags & F_HOSTS))
|
||||
config->addr = crec->addr.addr.addr4;
|
||||
|
||||
{
|
||||
config->addr = crec->addr.addr.addr4;
|
||||
config->flags |= CONFIG_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ int main (int argc, char **argv)
|
||||
int leasefd = -1, dhcpfd = -1, dhcp_raw_fd = -1;
|
||||
struct sigaction sigact;
|
||||
sigset_t sigmask;
|
||||
|
||||
|
||||
sighup = 1; /* init cache the first time through */
|
||||
sigusr1 = 0; /* but don't dump */
|
||||
sigterm = 0; /* or die */
|
||||
@@ -120,17 +120,14 @@ int main (int argc, char **argv)
|
||||
#endif
|
||||
|
||||
if (!lease_file)
|
||||
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);
|
||||
}
|
||||
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
|
||||
|
||||
interfaces = enumerate_interfaces(if_names, if_addrs, if_except, port);
|
||||
if (options & OPT_NOWILD)
|
||||
@@ -152,11 +149,6 @@ int main (int argc, char **argv)
|
||||
{
|
||||
dhcp_init(&dhcpfd, &dhcp_raw_fd);
|
||||
leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, now, maxleases);
|
||||
if (options & OPT_ETHERS)
|
||||
dhcp_configs = dhcp_read_ethers(dhcp_configs, dnamebuff);
|
||||
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);
|
||||
@@ -248,7 +240,10 @@ int main (int argc, char **argv)
|
||||
sprintf(packet, "infinite");
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -271,6 +266,8 @@ int main (int argc, char **argv)
|
||||
cache_reload(options, dnamebuff, domain_suffix, addn_hosts);
|
||||
if (dhcp)
|
||||
{
|
||||
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);
|
||||
lease_update_file(0, now);
|
||||
@@ -350,11 +347,17 @@ int main (int argc, char **argv)
|
||||
if (last == 0 || difftime(now, last) > 1.0)
|
||||
{
|
||||
last = now;
|
||||
|
||||
#ifdef HAVE_ISC_READER
|
||||
if (lease_file && !dhcp)
|
||||
load_dhcp(lease_file, domain_suffix, now, dnamebuff);
|
||||
#endif
|
||||
|
||||
if (!(options & OPT_NO_POLL))
|
||||
{
|
||||
struct resolvc *res = resolv, *latest = NULL;
|
||||
time_t last_change = 0;
|
||||
struct stat statbuf;
|
||||
time_t last_change = 0;
|
||||
/* There may be more than one possible file.
|
||||
Go through and find the one which changed _last_.
|
||||
Warn of any which can't be read. */
|
||||
|
||||
@@ -238,15 +238,24 @@ struct dhcp_lease {
|
||||
};
|
||||
|
||||
struct dhcp_config {
|
||||
unsigned int flags;
|
||||
int clid_len; /* length of client identifier */
|
||||
unsigned char *clid; /* clientid */
|
||||
unsigned char hwaddr[ETHER_ADDR_LEN];
|
||||
char *hostname;
|
||||
char *hostname, *netid;
|
||||
struct in_addr addr;
|
||||
unsigned int lease_time;
|
||||
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
|
||||
|
||||
struct dhcp_opt {
|
||||
int opt, len, is_addr;
|
||||
unsigned char *val;
|
||||
@@ -406,3 +415,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
char *domain_suffix, char *dhcp_file, char *dhcp_sname,
|
||||
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
|
||||
|
||||
249
src/isc.c
Normal file
249
src/isc.c
Normal file
@@ -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
|
||||
|
||||
298
src/option.c
298
src/option.c
@@ -161,10 +161,10 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{
|
||||
int option = 0, i;
|
||||
unsigned int flags = 0;
|
||||
FILE *f = NULL;
|
||||
char *conffile = CONFFILE;
|
||||
FILE *file_save = NULL, *f = NULL;
|
||||
char *file_name_save = NULL, *conffile = CONFFILE;
|
||||
int conffile_set = 0;
|
||||
int lineno = 0;
|
||||
int line_save = 0, lineno = 0;
|
||||
opterr = 0;
|
||||
|
||||
*min_leasetime = UINT_MAX;
|
||||
@@ -179,26 +179,38 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
#endif
|
||||
else
|
||||
{ /* f non-NULL, reading from conffile. */
|
||||
reread:
|
||||
if (!fgets(buff, MAXDNAME, f))
|
||||
{
|
||||
/* At end of file, all done */
|
||||
fclose(f);
|
||||
if (file_save)
|
||||
{
|
||||
/* may be nested */
|
||||
conffile = file_name_save;
|
||||
f = file_save;
|
||||
file_save = NULL;
|
||||
lineno = line_save;
|
||||
goto reread;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *p;
|
||||
int white;
|
||||
lineno++;
|
||||
/* dump comments */
|
||||
for (p = buff; *p; p++)
|
||||
if (*p == '#')
|
||||
*p = 0;
|
||||
for (white = 1, p = buff; *p; p++)
|
||||
if (white && *p == '#')
|
||||
{
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
white = isspace(*p);
|
||||
/* fgets gets end of line char too. */
|
||||
while (strlen(buff) > 0 &&
|
||||
(buff[strlen(buff)-1] == '\n' ||
|
||||
buff[strlen(buff)-1] == ' ' ||
|
||||
buff[strlen(buff)-1] == '\r' ||
|
||||
buff[strlen(buff)-1] == '\t'))
|
||||
while (strlen(buff) > 0 && isspace(buff[strlen(buff)-1]))
|
||||
buff[strlen(buff)-1] = 0;
|
||||
if (*buff == 0)
|
||||
continue;
|
||||
@@ -227,6 +239,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{ /* end of command line args, start reading conffile. */
|
||||
if (!conffile)
|
||||
break; /* "confile=" option disables */
|
||||
fileopen:
|
||||
option = 0;
|
||||
if (!(f = fopen(conffile, "r")))
|
||||
{
|
||||
@@ -274,9 +287,27 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
switch (option)
|
||||
{
|
||||
case 'C':
|
||||
if (!f)
|
||||
{
|
||||
conffile = safe_string_alloc(optarg);
|
||||
conffile_set = 1;
|
||||
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;
|
||||
break;
|
||||
lineno = 0;
|
||||
goto fileopen;
|
||||
|
||||
case 'x':
|
||||
*runfile = safe_string_alloc(optarg);
|
||||
@@ -643,11 +674,15 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
*(a[k]++) = 0;
|
||||
}
|
||||
|
||||
if ((k < 2) ||
|
||||
((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
||||
((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
||||
if ((k < 2) || ((new->start.s_addr = inet_addr(a[0])) == (in_addr_t)-1))
|
||||
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 == '?')
|
||||
{
|
||||
option = '?';
|
||||
free(new);
|
||||
break;
|
||||
}
|
||||
@@ -700,22 +735,17 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
case 'G':
|
||||
{
|
||||
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;
|
||||
struct dhcp_config *new = safe_malloc(sizeof(struct dhcp_config));
|
||||
struct in_addr in;
|
||||
|
||||
new->next = *dhcp_conf;
|
||||
|
||||
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;
|
||||
new->flags = 0;
|
||||
|
||||
|
||||
a[0] = optarg;
|
||||
for (k = 1; k < 4; k++)
|
||||
for (k = 1; k < 6; k++)
|
||||
{
|
||||
if (!(a[k] = strchr(a[k-1], ',')))
|
||||
break;
|
||||
@@ -723,37 +753,60 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
}
|
||||
|
||||
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];
|
||||
if ((arg[0] == 'i' || arg[0] == 'I') &&
|
||||
(arg[1] == 'd' || arg[1] == 'D') &&
|
||||
arg[2] == ':')
|
||||
{
|
||||
int s, len;
|
||||
int len;
|
||||
arg += 3; /* dump id: */
|
||||
if (strchr(arg, ':'))
|
||||
{
|
||||
s = (strlen(arg)/3) + 1;
|
||||
/* decode in place */
|
||||
for (len = 0; len < s; len++)
|
||||
/* decode hex in place */
|
||||
char *p = arg, *q = arg, *r;
|
||||
while (*p)
|
||||
{
|
||||
if (arg[(len*3)+2] != ':')
|
||||
option = '?';
|
||||
arg[(len*3)+2] = 0;
|
||||
arg[len] = strtol(&arg[len*3], NULL, 16);
|
||||
for (r = p; *r && *r != ':'; r++);
|
||||
if (*r)
|
||||
{
|
||||
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
|
||||
len = strlen(arg);
|
||||
|
||||
new->flags |= CONFIG_CLID;
|
||||
new->clid_len = len;
|
||||
new->clid = safe_malloc(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",
|
||||
&e0, &e1, &e2, &e3, &e4, &e5) == 6)
|
||||
{
|
||||
new->flags |= CONFIG_HWADDR;
|
||||
new->hwaddr[0] = e0;
|
||||
new->hwaddr[1] = e1;
|
||||
new->hwaddr[2] = e2;
|
||||
@@ -765,7 +818,10 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
option = '?';
|
||||
}
|
||||
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
|
||||
{
|
||||
char *cp, *lastp = NULL, last = 0;
|
||||
@@ -800,19 +856,38 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
if (lastp)
|
||||
*lastp = last;
|
||||
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
|
||||
new->hostname = safe_string_alloc(a[j]);
|
||||
{
|
||||
new->hostname = safe_string_alloc(a[j]);
|
||||
new->flags |= CONFIG_NAME;
|
||||
}
|
||||
}
|
||||
else
|
||||
new->lease_time = atoi(a[j]) * fac;
|
||||
{
|
||||
new->lease_time = atoi(a[j]) * fac;
|
||||
new->flags |= CONFIG_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
if (option == '?')
|
||||
free(new);
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new->lease_time < *min_leasetime)
|
||||
if ((new->flags & CONFIG_TIME) && new->lease_time < *min_leasetime)
|
||||
*min_leasetime = new->lease_time;
|
||||
*dhcp_conf = new;
|
||||
}
|
||||
@@ -823,7 +898,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
{
|
||||
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
|
||||
char *cp, *comma;
|
||||
int addrs, is_addr;
|
||||
int addrs, digs, is_addr, is_hex, is_dec;
|
||||
|
||||
new->next = *dhcp_opts;
|
||||
new->len = 0;
|
||||
@@ -853,58 +928,113 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
|
||||
free(new);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
*dhcp_opts = new;
|
||||
|
||||
if (!comma)
|
||||
{
|
||||
*dhcp_opts = new;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check for non-address list characters */
|
||||
for (addrs = 1, is_addr = 0, cp = comma+1; *cp; cp++)
|
||||
break;
|
||||
|
||||
/* characterise the value */
|
||||
is_addr = is_hex = is_dec = 1;
|
||||
addrs = digs = 1;
|
||||
for (cp = comma+1; *cp; cp++)
|
||||
if (*cp == ',')
|
||||
addrs++;
|
||||
else if (!(*cp == '.' || *cp == ' ' || (*cp >='0' && *cp <= '9')))
|
||||
break;
|
||||
{
|
||||
addrs++;
|
||||
is_dec = is_hex = 0;
|
||||
}
|
||||
else if (*cp == ':')
|
||||
{
|
||||
digs++;
|
||||
is_dec = is_addr = 0;
|
||||
}
|
||||
else if (*cp == '.')
|
||||
is_addr = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (is_hex && digs > 1)
|
||||
{
|
||||
char *p = comma+1, *q, *r;
|
||||
new->len = digs;
|
||||
q = new->val = safe_malloc(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
|
||||
{
|
||||
if (*p)
|
||||
*(q++) = strtol(p, NULL, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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->val = safe_malloc(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
|
||||
{
|
||||
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->val = op = safe_malloc(new->len);
|
||||
new->is_addr = 1;
|
||||
while (addrs--)
|
||||
{
|
||||
cp = comma;
|
||||
if ((comma = strchr(cp+1, ',')))
|
||||
*comma = 0;
|
||||
in.s_addr = inet_addr(cp+1);
|
||||
memcpy(op, &in, INADDRSZ);
|
||||
op += INADDRSZ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* text arg */
|
||||
new->len = strlen(comma+1);
|
||||
new->val = safe_malloc(new->len);
|
||||
memcpy(new->val, comma+1, new->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct in_addr in;
|
||||
unsigned char *op;
|
||||
|
||||
if (addrs == 1 && !is_addr)
|
||||
{
|
||||
new->len = 1;
|
||||
new->val = safe_malloc(1);
|
||||
*(new->val) = atoi(comma+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
new->len = INADDRSZ * addrs;
|
||||
new->val = op = safe_malloc(new->len);
|
||||
new->is_addr = 1;
|
||||
while (addrs--)
|
||||
{
|
||||
cp = comma;
|
||||
if (cp && (comma = strchr(cp+1, ',')))
|
||||
*comma = 0;
|
||||
if (cp && (in.s_addr = inet_addr(cp+1)) == (in_addr_t)-1)
|
||||
option = '?';
|
||||
memcpy(op, &in, INADDRSZ);
|
||||
op += INADDRSZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dhcp_opts = new;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
152
src/rfc2131.c
152
src/rfc2131.c
@@ -63,8 +63,12 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
char *domainname, char *hostname,
|
||||
struct in_addr router,
|
||||
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,
|
||||
struct in_addr iface_addr,
|
||||
@@ -88,13 +92,27 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
char *message = NULL;
|
||||
unsigned int renewal_time, expires_time, def_time;
|
||||
struct dhcp_config *config;
|
||||
|
||||
char *netid;
|
||||
|
||||
if (mess->op != BOOTREQUEST ||
|
||||
mess->htype != ARPHRD_ETHER ||
|
||||
mess->hlen != ETHER_ADDR_LEN ||
|
||||
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;
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE)))
|
||||
@@ -130,9 +148,9 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
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)) &&
|
||||
config->hostname)
|
||||
have_config(config, CONFIG_NAME))
|
||||
hostname = config->hostname;
|
||||
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME)))
|
||||
{
|
||||
@@ -164,7 +182,8 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
|
||||
/* search again now we have a hostname */
|
||||
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
|
||||
def_time = config && config->lease_time ? config->lease_time : context->lease_time;
|
||||
def_time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||
netid = have_config(config, CONFIG_NETID) ? config->netid : context->netid;
|
||||
|
||||
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
||||
{
|
||||
@@ -219,11 +238,11 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||
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)
|
||||
{
|
||||
syslog(LOG_WARNING, "disabling DHCP static address %s", inet_ntoa(config->addr));
|
||||
config->addr.s_addr = 0;
|
||||
config->flags &= ~CONFIG_ADDR ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -244,9 +263,9 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
||||
mess->yiaddr = option_addr(opt);
|
||||
|
||||
log_packet("DISCOVER", opt ? &mess->yiaddr : NULL, mess->chaddr, iface_name, NULL);
|
||||
|
||||
if (config && config->addr.s_addr && !lease_find_by_addr(config->addr))
|
||||
if (have_config(config, CONFIG_DISABLE))
|
||||
message = "ignored";
|
||||
else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr))
|
||||
mess->yiaddr = config->addr;
|
||||
else if (lease &&
|
||||
((lease->addr.s_addr & context->netmask.s_addr) ==
|
||||
@@ -254,18 +273,19 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
mess->yiaddr = lease->addr;
|
||||
else if ((!opt || !address_available(context, mess->yiaddr)) &&
|
||||
!address_allocate(context, dhcp_configs, &mess->yiaddr))
|
||||
{
|
||||
syslog(LOG_WARNING, "address pool exhausted");
|
||||
return 0;
|
||||
}
|
||||
|
||||
message = "no address available";
|
||||
|
||||
log_packet("DISCOVER", opt ? &mess->yiaddr : NULL, mess->chaddr, iface_name, message);
|
||||
if (message)
|
||||
return 0;
|
||||
|
||||
bootp_option_put(mess, dhcp_file, dhcp_sname);
|
||||
mess->siaddr = dhcp_next_server;
|
||||
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_LEASE_TIME, 4, expires_time);
|
||||
p = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||
NULL, router, iface_addr, iface_mtu);
|
||||
NULL, router, iface_addr, iface_mtu, netid);
|
||||
p = option_put(p, end, OPTION_END, 0, 0);
|
||||
|
||||
log_packet("OFFER" , &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||
@@ -297,7 +317,7 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
if (!lease)
|
||||
{
|
||||
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";
|
||||
else if (!(lease = lease_allocate(clid, clid_len, mess->yiaddr)))
|
||||
message = "no leases left";
|
||||
@@ -319,6 +339,9 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
if ((mess->yiaddr.s_addr & context->netmask.s_addr) != (context->start.s_addr & context->netmask.s_addr))
|
||||
message = "wrong network";
|
||||
|
||||
if (have_config(config, CONFIG_DISABLE))
|
||||
message = "disabled";
|
||||
|
||||
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
|
||||
|
||||
if (message)
|
||||
@@ -354,17 +377,23 @@ int dhcp_reply(struct dhcp_context *context,
|
||||
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,
|
||||
hostname, router, iface_addr, iface_mtu);
|
||||
hostname, router, iface_addr, iface_mtu, netid);
|
||||
p = option_put(p, end, OPTION_END, 0, 0);
|
||||
return p - (unsigned char *)mess;
|
||||
|
||||
case DHCPINFORM:
|
||||
if (have_config(config, CONFIG_DISABLE))
|
||||
{
|
||||
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, "ignored");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_packet("INFORM", &mess->ciaddr, mess->chaddr, iface_name, NULL);
|
||||
|
||||
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 = do_req_options(context, p, end, req_options, dhcp_opts, domain_suffix,
|
||||
hostname, router, iface_addr, iface_mtu);
|
||||
hostname, router, iface_addr, iface_mtu, netid);
|
||||
p = option_put(p, end, OPTION_END, 0, 0);
|
||||
|
||||
log_packet("ACK", &mess->ciaddr, mess->chaddr, iface_name, hostname);
|
||||
@@ -524,11 +553,11 @@ static int in_list(unsigned char *list, int opt)
|
||||
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)
|
||||
if (opts->opt == opt &&
|
||||
(!opts->netid || (context->netid && strcmp(opts->netid, context->netid) == 0)))
|
||||
(!opts->netid || (netid && strcmp(opts->netid, netid) == 0)))
|
||||
return opts;
|
||||
return NULL;
|
||||
}
|
||||
@@ -540,7 +569,7 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
char *domainname, char *hostname,
|
||||
struct in_addr router,
|
||||
struct in_addr iface_addr,
|
||||
int iface_mtu)
|
||||
int iface_mtu, char *netid)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -553,24 +582,24 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
iface_mtu : DNSMASQ_PACKETSZ);
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
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,
|
||||
ntohl(router.s_addr));
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
/* Note that we ignore attempts to set the hostname using
|
||||
@@ -580,38 +609,49 @@ static unsigned char *do_req_options(struct dhcp_context *context,
|
||||
|
||||
for (i = 0; req_options[i] != OPTION_END; i++)
|
||||
{
|
||||
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))
|
||||
struct dhcp_opt *opt;
|
||||
|
||||
if (req_options[i] == OPTION_HOSTNAME ||
|
||||
req_options[i] == OPTION_MAXMESSAGE ||
|
||||
!(opt = option_find2(netid, config_opts, req_options[i])) ||
|
||||
(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->len;
|
||||
if (opt->len == 0)
|
||||
continue;
|
||||
|
||||
if (opt->is_addr)
|
||||
{
|
||||
*(p++) = opt->opt;
|
||||
*(p++) = opt->len;
|
||||
if (opt->len != 0)
|
||||
int j;
|
||||
struct in_addr *a = (struct in_addr *)opt->val;
|
||||
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
|
||||
{
|
||||
if (opt->is_addr)
|
||||
{
|
||||
int j;
|
||||
struct in_addr *a = (struct in_addr *)opt->val;
|
||||
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
|
||||
{
|
||||
/* zero means "self" */
|
||||
if (a->s_addr == 0)
|
||||
memcpy(p, &iface_addr, INADDRSZ);
|
||||
else
|
||||
memcpy(p, a, INADDRSZ);
|
||||
p += INADDRSZ;
|
||||
}
|
||||
}
|
||||
/* zero means "self" */
|
||||
if (a->s_addr == 0)
|
||||
memcpy(p, &iface_addr, INADDRSZ);
|
||||
else
|
||||
{
|
||||
memcpy(p, opt->val, opt->len);
|
||||
p += opt->len;
|
||||
}
|
||||
memcpy(p, a, INADDRSZ);
|
||||
p += INADDRSZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
memcpy(p, opt->val, opt->len);
|
||||
p += opt->len;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user