Commit 44a2a316 authored by Simon Kelley's avatar Simon Kelley

import of dnsmasq-2.3.tar.gz

parent b49644f3
...@@ -667,6 +667,9 @@ release 2.0 ...@@ -667,6 +667,9 @@ release 2.0
helping to track that one down. helping to track that one down.
release 2.1 release 2.1
Thanks to Matt Swift and Dag Wieers for many suggestions
which went into this release.
Tweak include files to allow compilation on FreeBSD 5 Tweak include files to allow compilation on FreeBSD 5
Fix unaligned access warnings on BSD/Alpha. Fix unaligned access warnings on BSD/Alpha.
...@@ -687,10 +690,11 @@ release 2.1 ...@@ -687,10 +690,11 @@ release 2.1
Fixed long-existing strangeness in Linux IPv6 interface Fixed long-existing strangeness in Linux IPv6 interface
discovery code. The flags field in /proc/net/if_inet6 is discovery code. The flags field in /proc/net/if_inet6 is
_not_ the interface flags. _not_ the interface flags.
Fail gracefully when getting an ENODEV error when trying Fail gracefully when getting an ENODEV error when trying
to bind an IPv6 socket, rather than bailing out. to bind an IPv6 socket, rather than bailing out. Thanks
to Jan Ischebeck for feedback on that.
Allow the name->address mapping for static DHCP leases to Allow the name->address mapping for static DHCP leases to
be set by /etc/hosts. It's now possible to have be set by /etc/hosts. It's now possible to have
...@@ -710,12 +714,112 @@ release 2.1 ...@@ -710,12 +714,112 @@ release 2.1
Fix lease time spec when specified in dhcp-range and not Fix lease time spec when specified in dhcp-range and not
in dhcp-host, previously this was always one hour. in dhcp-host, previously this was always one hour.
Fix problem with setting domains as "local only". Fix problem with setting domains as "local only". -
thanks to Chris Schank.
Added support for max message size DHCP option. Added support for max message size DHCP option.
release 2.2 release 2.2
Fix total lack for DHCP functionality on Fix total lack for DHCP functionality on
Linux systems with IPv6 enabled. Linux systems with IPv6 enabled. - thanks to
Jonathon Hudson for spotting that.
Move default config file under FreeBSD - patch from
Steven Honson
release 2.3
Fix "install" makefile target. (reported by Rob Stevens)
Ensure that "local=/domain/" flag is obeyed for all
queries on a domain, not just A and AAAA. (Reported by
Peter Fichtner.)
Handle DHCPDECLINE messages and provide an error message
in DHCPNAK messages.
Add "domain" setting example to
dnsmasq.conf.example. Thanks to K P Kirchdorfer for
spotting that it was missing.
Subtle change to the DHCPREQUEST handling code to work
around a bug in the DHCP client in HP Jetdirect printers.
Thanks to Marko Stolle for finding this problem.
Return DHCP T1 and T2 times, with "fuzz" to desychronise lease
renewals, as specified in the RFC.
Ensure that the END option is always present in DHCP
packets , even if the packet is too small to fit all
the requested options.
Handle larger-than-default DHCP packets if required, up
to the ethernet MTU.
Fix a couple of places where the return code from
malloc() was not checked.
Cope with a machine taking a DHCP lease and then moving
network so that the lease address is no longer valid.
The DHCP server will now work via a BOOTP relay - remote
networks are configured with the dhcp-range option the
same as directly connected ones, but they need an
additional netmask parameter. Eg
--dhcp-range=192.168.4.10,192.168.4.50,255.255,255.0
will enable DHCP service via a BOOTP relay on the
192.168.4.0 network.
Add a limit on the number of available DHCP leases,
otherwise the daemon could be DOSed by a malicious
host. The default is 150, but it can be changed by the
dhcp-lease-max option.
Fixed compilation on OpenBSD (thanks to Frederic Brodbeck
for help with that.)
Reworked the DHCP network handling code for two good
effects: (1) The limit of one network only for DHCP on
FreeBSD is now gone, (2) The DHCP server copes with
dynamically created interfaces. The one-interface
limitation remains for OpenBSD, which is missing
extensions to the socket API which have been in Linux
since version 2.2 and FreeBSD since version 4.8.
Reworked the DNS network code to also cope with
dynamically created interfaces. dnsmasq will now listen
to the wildcard address and port 53 by default, so if no
--interface or --address options are given it will handle
dynamically created interfaces. The old behaviour can be
restored with --bind-interfaces for people running BIND
on one interface and dnsmasq on another. Note that
--interface and --address options still work, but the
filtering is done by dnsmasq, rather then the kernel.
This works on Linux, and FreeBSD>=5.0. On systems which
don't support the required API extensions, the old
behaviour is used, just as if --bind-interfaces had been set.
Allow IPv6 support to be disabled at compile time. To do
that, add -DNO_IPV6 to the CFLAGS. Thanks to Oleg
I. Vdovikin for the suggestion to do that.
Add ability to set DHCP options per network. This is done
by giving a network an identifier like this:
dhcp-range=red-net,192.168.0.10,192.168.0.50
and then labeling options intended for that network only
like this:
dhcp-option=red-net,6,1.1.1.1
Thanks to Oleg Vdovikin for arguing that one through.
Made errors in the configuration file non-fatal: dnsmasq
will now complain bitterly, but continue.
Added --read-ethers option, to allow dnsmasq to pull
static DHCP information from that file.
Thanks to Andi Cambeis for that suggestion.
Added HAVE_BROKEN_RTC compilation option to support
embedded systems without a stable RTC. Oleg Vdovikin
helped work out how to make that work.
Move default config file under FreeBSD.
...@@ -12,7 +12,7 @@ all : ...@@ -12,7 +12,7 @@ all :
clean : clean :
rm -f *~ */*~ $(SRC)/*.o $(SRC)/dnsmasq core build rm -f *~ */*~ $(SRC)/*.o $(SRC)/dnsmasq core build
install : $(SRC)/dnsmasq install : all
install -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8 install -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8
install -m 644 dnsmasq.8 $(DESTDIR)$(MANDIR)/man8 install -m 644 dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
install -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR) install -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.2 Version: 2.3
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: System Environment/Daemons Group: System Environment/Daemons
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.2 Version: 2.3
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: System Environment/Daemons Group: System Environment/Daemons
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.2 Version: 2.3
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: Productivity/Networking/DNS/Servers Group: Productivity/Networking/DNS/Servers
......
...@@ -87,7 +87,7 @@ flags. ...@@ -87,7 +87,7 @@ flags.
.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.
.TP .TP
.B \-a, --listen-address .B \-a, --listen-address=<ipaddr>
Listen only on the given IP address. As with Listen only on the given IP address. As with
.B \-i .B \-i
more than one address may be specified. Unlike more than one address may be specified. Unlike
...@@ -101,6 +101,15 @@ or ...@@ -101,6 +101,15 @@ or
.B \-I .B \-I
flags. flags.
.TP .TP
.B \-z, --bind-interfaces
On systems which support it, dnsmasq binds the wildcard address,
even when it is listening on only some interfaces. It then discards
requests that it shouldn't reply to. This has the advantage of
working even when interfaces come and go and change address. This
option forces dnsmasq to really bind only the interfaces it is
listening on. About the only time when this is useful is when
running another nameserver on the same machine.
.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.
...@@ -226,15 +235,26 @@ Disable negative caching. Negative caching allows dnsmasq to remember ...@@ -226,15 +235,26 @@ Disable negative caching. Negative caching allows dnsmasq to remember
identical queries without forwarding them again. This flag disables identical queries without forwarding them again. This flag disables
negative caching. negative caching.
.TP .TP
.B \-F, --dhcp-range=<start-addr>,<end-addr>[,<default lease time>] .B \-F, --dhcp-range=[network-id,]<start-addr>,<end-addr>[[,<netmask>],<broadcast>][,<default lease time>]
Enable the DHCP server. Addresses will be given out from the range Enable the DHCP server. Addresses will be given out from the range
<start-addr> to <end-addr>, both of which must be on the network <start-addr> to <end-addr> and from statically defined addresses given
attached to a local interface. If the lease time is given, then leases in
.B dhcp-host
options. If the lease time is given, then leases
will be given for that length of time. The lease time is on seconds, will be given for that length of time. The lease time is on seconds,
or minutes (eg 45m) or hours (eg 1h) or the literal "infinite". This or minutes (eg 45m) or hours (eg 1h) or the literal "infinite". This
option may be repeated, with different addresses, to enable DHCP option may be repeated, with different addresses, to enable DHCP
service on more than one local interface. (Use of more than one service to more than one network. For directly connected networks (ie,
interface currently only works under Linux.) networks on which the machine running dnsmasq has an interface) the
netmask is optional. It is, however, required for networks which
recieve DHCP service via a relay agent. The broadcast address is
always optional. On some broken systems, dnsmasq can listen on only
one interface when using DHCP, and the name of that interface must be
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.
.TP .TP
.B \-G, --dhcp-host=[[<hwaddr>]|[id:<client_id>]][,<ipaddr>][,<hostname>][,<lease_time>] .B \-G, --dhcp-host=[[<hwaddr>]|[id:<client_id>]][,<ipaddr>][,<hostname>][,<lease_time>]
Specify per host parameters for the DHCP server. This allows a machine Specify per host parameters for the DHCP server. This allows a machine
...@@ -263,8 +283,16 @@ If a name appears in /etc/hosts, the associated address can be ...@@ -263,8 +283,16 @@ 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.
.TP
.B \-Z, --read-ethers
Read /etc/ethers for information about hosts for the DHCP server. The
format of /etc/ethers is a hardware address, followed by either a
hostname or dotted-quad IP address. When read by dnsmasq these lines
have exactly the same effect as
.B --dhcp-host
options containing the same information.
.TP .TP
.B \-O, --dhcp-option=<opt>,[<value>[,<value>]] .B \-O, --dhcp-option=[network-id,]<opt>,[<value>[,<value>]]
Specfify different or extra options to DHCP clients. By default, Specfify different or extra options to DHCP clients. By default,
dnsmasq sends some standard options to DHCP clients, the netmask and dnsmasq sends some standard options to DHCP clients, the netmask and
broadcast address are set to the same as the host running dnsmasq, and broadcast address are set to the same as the host running dnsmasq, and
...@@ -278,7 +306,9 @@ specfied in RFC2132. For example, to set the default route option to ...@@ -278,7 +306,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 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". machine running dnsmasq". 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 Be careful: no checking is done that the correct type of data for the
option number is sent, and there are option numbers for which it is not option number is sent, and there are option numbers for which it is not
possible to generate the correct data type; it is quite possible to possible to generate the correct data type; it is quite possible to
...@@ -290,6 +320,12 @@ Set BOOTP options to be returned by the DHCP server. These are needed ...@@ -290,6 +320,12 @@ 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
its initial configuration. its initial configuration.
.TP .TP
.B \-X, --dhcp-lease-max=<number>
Limits dnsmasq to the specified maximum number of DHCP leases. The
default is 150. This limit is to prevent DoS attacks from hosts which
create thousands of leases and use lots of memory in the dnsmasq
process.
.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.
.TP .TP
...@@ -332,14 +368,6 @@ of names that have been inserted into the cache. In ...@@ -332,14 +368,6 @@ of names that have been inserted into the cache. In
.B --no-daemon .B --no-daemon
mode or when full logging is enabled (-q), a complete dump of the contents of the cache is made. mode or when full logging is enabled (-q), a complete dump of the contents of the cache is made.
.PP .PP
When it receives a SIGUSR2,
.B dnsmasq
re-scans network interfaces. This is required if it is to listen for
queries on newly created interfaces or interfaces which have changed IP
address. For this facility to work, dnsmasq must be told to continue
running as user root, using
.B --user=root
.PP
Dnsmasq is a DNS query forwarder: it it not capable of recursively Dnsmasq is a DNS query forwarder: it it not capable of recursively
answering arbitrary queries starting from the root servers but answering arbitrary queries starting from the root servers but
forwards such queries to a fully recursive upstream DNS server which is forwards such queries to a fully recursive upstream DNS server which is
......
...@@ -76,6 +76,15 @@ filterwin2k ...@@ -76,6 +76,15 @@ filterwin2k
# you use this.) # you use this.)
#listen-address= #listen-address=
# On systems which support it, dnsmasq binds the wildcard address,
# even when it is listening on only some interfaces. It then discards
# requests that it shouldn't reply to. This has the advantage of
# working even when interfaces come and go and change address. If you
# want dnsmasq to really bind only the interfaces it is listening on,
# uncomment this option. About the only time you may need this is when
# running another nameserver on the same machine.
#bind-interfaces
# If you don't want dnsmasq to read /etc/hosts, uncomment the # If you don't want dnsmasq to read /etc/hosts, uncomment the
# following line. # following line.
#no-hosts #no-hosts
...@@ -87,13 +96,32 @@ filterwin2k ...@@ -87,13 +96,32 @@ filterwin2k
# automatically added to simple names in a hosts-file. # automatically added to simple names in a hosts-file.
#expand-hosts #expand-hosts
# Set the domain for dnsmasq. this is optional, but if it is set, it
# does the following things.
# 1) Allows DHCP hosts to have fully qualified domain names, as long
# as the domain part matches this setting.
# 2) Sets the "domain" DHCP option thereby potentially setting the
# domain of all systems configured by DHCP
# 3) Provides the domain part for "expand-hosts"
#domain=thekelleys.org.uk
# Uncomment this to enable the integrated DHCP server, you need # Uncomment this to enable the integrated DHCP server, you need
# to supply the range of addresses available for lease and optionally # to supply the range of addresses available for lease and optionally
# a lease time. If you have more than one interface, you will need to # a lease time. If you have more than one network, you will need to
# repeat this for each interface on which you want to supply DHCP # repeat this for each network on which you want to supply DHCP
# service. # service.
#dhcp-range=192.168.0.50,192.168.0.150,12h #dhcp-range=192.168.0.50,192.168.0.150,12h
# This is an example of a DHCP range where the netmask is given. This
# is needed for networks we reach the dnsmasq DHCP server via a relay
# agent. If you don't know what a DHCP relay agent is, you probably
# don't need to worry about this.
#dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h
# This is an example of a DHCP range with a network-id, so that
# some DHCP options may be set only for this network.
#dhcp-range=red,192.168.0.50,192.168.0.150
# Supply parameters for specified hosts using DHCP. There are lots # Supply parameters for specified hosts using DHCP. There are lots
# of valid alternatives, so we will give examples of each. Note that # of valid alternatives, so we will give examples of each. Note that
# IP addresses DO NOT have to be in the range given above, they just # IP addresses DO NOT have to be in the range given above, they just
...@@ -129,6 +157,12 @@ filterwin2k ...@@ -129,6 +157,12 @@ filterwin2k
# it asks for a DHCP lease. # it asks for a DHCP lease.
#dhcp-host=judge #dhcp-host=judge
# 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
# MAC-address/host mappings there for other purposes.
#read-ethers
# Send options to hosts which ask for a DHCP lease. # Send options to hosts which ask for a DHCP lease.
# See RFC 2132 for details of available options. # See RFC 2132 for details of available options.
# Note that all the common settings, such as netmask and # Note that all the common settings, such as netmask and
...@@ -159,6 +193,10 @@ filterwin2k ...@@ -159,6 +193,10 @@ filterwin2k
# Set the "all subnets are local" flag # Set the "all subnets are local" flag
#dhcp-option=27,1 #dhcp-option=27,1
# 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
# The following DHCP options set up dnsmasq in the same way as is specified # The following DHCP options set up dnsmasq in the same way as is specified
# for the ISC dhcpcd in # for the ISC dhcpcd in
# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt # http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
...@@ -177,6 +215,9 @@ filterwin2k ...@@ -177,6 +215,9 @@ filterwin2k
# boot machines over the network. # boot machines over the network.
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3 #dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3
# Set the limit on DHCP leases, the default is 150
#dhcp-lease-max=150
# The DHCP server needs somewhere on disk to keep its lease database. # The DHCP server needs somewhere on disk to keep its lease database.
# This defaults to a sane location, but if you want to change it, use # This defaults to a sane location, but if you want to change it, use
# the line below. # the line below.
......
...@@ -710,7 +710,12 @@ void dump_cache(int debug, int cache_size) ...@@ -710,7 +710,12 @@ void dump_cache(int debug, int cache_size)
else else
strcpy(addrbuff, inet_ntoa(cache->addr.addr.addr4)); strcpy(addrbuff, inet_ntoa(cache->addr.addr.addr4));
#endif #endif
syslog(LOG_DEBUG, "%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %s", syslog(LOG_DEBUG,
#ifdef HAVE_BROKEN_RTC
"%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %ld\n",
#else
"%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %s",
#endif
cache_get_name(cache), addrbuff, cache_get_name(cache), addrbuff,
cache->flags & F_IPV4 ? "4" : "", cache->flags & F_IPV4 ? "4" : "",
cache->flags & F_IPV6 ? "6" : "", cache->flags & F_IPV6 ? "6" : "",
...@@ -722,7 +727,11 @@ void dump_cache(int debug, int cache_size) ...@@ -722,7 +727,11 @@ void dump_cache(int debug, int cache_size)
cache->flags & F_NXDOMAIN ? "X" : " ", cache->flags & F_NXDOMAIN ? "X" : " ",
cache->flags & F_HOSTS ? "H" : " ", cache->flags & F_HOSTS ? "H" : " ",
cache->flags & F_ADDN ? "A" : " ", cache->flags & F_ADDN ? "A" : " ",
#ifdef HAVE_BROKEN_RTC
cache->flags & F_IMMORTAL ? 0: (unsigned long)cache->ttd) ;
#else
cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd))) ; cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd))) ;
#endif
} }
} }
...@@ -749,14 +758,14 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr) ...@@ -749,14 +758,14 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr)
#endif #endif
if (flags & F_NXDOMAIN) if (flags & F_NXDOMAIN)
strcpy(addrbuff, "<NXDOMAIN>-"); strcpy(addrbuff, "<NXDOMAIN>");
else else
strcpy(addrbuff, "<NODATA>-"); strcpy(addrbuff, "<NODATA>");
if (flags & F_IPV4) if (flags & F_IPV4)
strcat(addrbuff, "IPv4"); strcat(addrbuff, "-IPv4");
else else if (flags & F_IPV6)
strcat(addrbuff, "IPv6"); strcat(addrbuff, "-IPv6");
} }
else else
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
......
...@@ -12,21 +12,23 @@ ...@@ -12,21 +12,23 @@
/* Author's email: simon@thekelleys.org.uk */ /* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.2" #define VERSION "2.3"
#define FTABSIZ 150 /* max number of outstanding requests */ #define FTABSIZ 150 /* max number of outstanding requests */
#define TIMEOUT 40 /* 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 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"
#define ETHERSFILE "/etc/ethers"
#ifdef __uClinux__ #ifdef __uClinux__
# define RESOLVFILE "/etc/config/resolv.conf" # define RESOLVFILE "/etc/config/resolv.conf"
#else #else
# define RESOLVFILE "/etc/resolv.conf" # define RESOLVFILE "/etc/resolv.conf"
#endif #endif
#define RUNFILE "/var/run/dnsmasq.pid" #define RUNFILE "/var/run/dnsmasq.pid"
#ifdef __FreeBSD__ #if defined(__FreeBSD__) || defined (__OpenBSD__)
# define LEASEFILE "/var/db/dnsmasq.leases" # define LEASEFILE "/var/db/dnsmasq.leases"
# define CONFFILE "/usr/local/etc/dnsmasq.conf" # define CONFFILE "/usr/local/etc/dnsmasq.conf"
#else #else
...@@ -37,6 +39,7 @@ ...@@ -37,6 +39,7 @@
#define CHUSER "nobody" #define CHUSER "nobody"
#define CHGRP "dip" #define CHGRP "dip"
#define IP6INTERFACES "/proc/net/if_inet6" #define IP6INTERFACES "/proc/net/if_inet6"
#define UPTIME "/proc/uptime"
#define DHCP_SERVER_PORT 67 #define DHCP_SERVER_PORT 67
#define DHCP_CLIENT_PORT 68 #define DHCP_CLIENT_PORT 68
...@@ -55,13 +58,29 @@ ...@@ -55,13 +58,29 @@
#endif #endif
/* determine if we can find the destination address of recieved packets
and set the source address of sent ones. If so, we can use one socket
bound to INADDR_ANY and cope with dynamically created interfaces.
Linux does this differently to FreeBSD. */
#if defined(IP_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
# define HAVE_UDP_SRC_DST
#else
# undef HAVE_UDP_SRC_DST
#endif
/* Decide if we're going to support IPv6 */ /* Decide if we're going to support IPv6 */
/* We assume that systems which don't have IPv6 /* We assume that systems which don't have IPv6
headers don't have ntop and pton either */ headers don't have ntop and pton either */
#if defined(INET6_ADDRSTRLEN) #if defined(INET6_ADDRSTRLEN) && !defined(NO_IPV6)
# define HAVE_IPV6 # define HAVE_IPV6
# define ADDRSTRLEN INET6_ADDRSTRLEN # define ADDRSTRLEN INET6_ADDRSTRLEN
# if defined(SOL_IPV6)
# define IPV6_LEVEL SOL_IPV6
# else
# define IPV6_LEVEL IPPROTO_IPV6
# endif
#elif defined(INET_ADDRSTRLEN) #elif defined(INET_ADDRSTRLEN)
# undef HAVE_IPV6 # undef HAVE_IPV6
# define ADDRSTRLEN INET_ADDRSTRLEN # define ADDRSTRLEN INET_ADDRSTRLEN
...@@ -85,6 +104,23 @@ HAVE_LINUX_IPV6_PROC ...@@ -85,6 +104,23 @@ HAVE_LINUX_IPV6_PROC
define this to do IPv6 interface discovery using define this to do IPv6 interface discovery using
proc/net/if_inet6 ala LINUX. proc/net/if_inet6 ala LINUX.
HAVE_BROKEN_RTC
define this on embeded systems which don't have an RTC
which keeps time over reboots. Causes dnsmasq to use uptime()
for timing, and keep relative time values in its leases file.
Also enables "Flash disk mode". Normally, dnsmasq tries very hard to
keep the on-disk leases file up-to-date: rewriting it after every change.
When HAVE_BROKEN_RTC is in effect, a different regime is used:
The leases file is written when dnsmasq terminates, when it receives
SIGALRM, when a brand new lease is allocated, or every n seconds,
where n is one third of the smallest time configured for leases
in a --dhcp-range or --dhcp-host option.
NOTE: when enabling or disabling this, be sure to delete any old
leases file, otherwise dnsmasq may get very confused.
This configuration currently only works on Linux, but could be made to
work on other systems by teaching dnsmasq_time() in utils.c how to
read the system uptime.
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.
...@@ -111,9 +147,6 @@ HAVE_SOCKADDR_SA_LEN ...@@ -111,9 +147,6 @@ HAVE_SOCKADDR_SA_LEN
HAVE_PSELECT HAVE_PSELECT
If your C library implements pselect, define this. If your C library implements pselect, define this.
HAVE_PF_PACKET
If your OS implements packet sockets, define this.
HAVE_BPF HAVE_BPF
If your OS implements Berkeley PAcket filter, define this. If your OS implements Berkeley PAcket filter, define this.
...@@ -124,8 +157,7 @@ NOTES: ...@@ -124,8 +157,7 @@ NOTES:
HAVE_RANDOM HAVE_RANDOM
HAVE_DEV_RANDOM HAVE_DEV_RANDOM
HAVE_DEV_URANDOM HAVE_DEV_URANDOM
HAVE_PF_PACKET you should NOT define
you should NOT define
HAVE_ARC4RANDOM HAVE_ARC4RANDOM
HAVE_SOCKADDR_SA_LEN HAVE_SOCKADDR_SA_LEN
...@@ -151,7 +183,6 @@ NOTES: ...@@ -151,7 +183,6 @@ NOTES:
#define HAVE_RANDOM #define HAVE_RANDOM
#define HAVE_DEV_URANDOM #define HAVE_DEV_URANDOM
#define HAVE_DEV_RANDOM #define HAVE_DEV_RANDOM
#define HAVE_PF_PACKET
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
#undef HAVE_PSELECT #undef HAVE_PSELECT
/* Don't fork into background on uClinux */ /* Don't fork into background on uClinux */
...@@ -175,7 +206,6 @@ NOTES: ...@@ -175,7 +206,6 @@ NOTES:
#define HAVE_RANDOM #define HAVE_RANDOM
#define HAVE_DEV_URANDOM #define HAVE_DEV_URANDOM
#define HAVE_DEV_RANDOM #define HAVE_DEV_RANDOM
#undef HAVE_PF_PACKET
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
#undef HAVE_PSELECT #undef HAVE_PSELECT
/* Fix various misfeatures of libc5 headers */ /* Fix various misfeatures of libc5 headers */
...@@ -193,7 +223,6 @@ typedef size_t socklen_t; ...@@ -193,7 +223,6 @@ typedef size_t socklen_t;
#define HAVE_DEV_RANDOM #define HAVE_DEV_RANDOM
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
#define HAVE_PSELECT #define HAVE_PSELECT
#define HAVE_PF_PACKET
/* glibc < 2.2 has broken Sockaddr_in6 so we have to use our own. */ /* glibc < 2.2 has broken Sockaddr_in6 so we have to use our own. */
/* glibc < 2.2 doesn't define in_addr_t */ /* glibc < 2.2 doesn't define in_addr_t */
#if defined(__GLIBC__) && (__GLIBC__ == 2) && \ #if defined(__GLIBC__) && (__GLIBC__ == 2) && \
...@@ -204,6 +233,9 @@ typedef unsigned long in_addr_t; ...@@ -204,6 +233,9 @@ typedef unsigned long in_addr_t;
#endif #endif
#endif #endif
/* #elif defined(__OpenBSD__)
#error The sockets API in OpenBSD does not provide facilities required by dnsmasq
*/
#elif defined(__FreeBSD__) || defined(__OpenBSD__) #elif defined(__FreeBSD__) || defined(__OpenBSD__)
#undef HAVE_LINUX_IPV6_PROC #undef HAVE_LINUX_IPV6_PROC
#undef HAVE_GETOPT_LONG #undef HAVE_GETOPT_LONG
......
This diff is collapsed.
This diff is collapsed.
...@@ -11,23 +11,24 @@ ...@@ -11,23 +11,24 @@
*/ */
/* Author's email: simon@thekelleys.org.uk */ /* Author's email: simon@thekelleys.org.uk */
#ifdef __linux__
/* for pselect.... */ /* for pselect.... */
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE 600
/* but then DNS headers don't compile without.... */ /* but then DNS headers don't compile without.... */
#define _BSD_SOURCE #define _BSD_SOURCE
/* and also, on FreeBSD 5.0 ..... */ #endif
#define __BSD_VISIBLE 1
/* get these before config.h for IPv6 stuff... */ /* get these before config.h for IPv6 stuff... */
#include <sys/types.h> #include <sys/types.h>
#include <netinet/in.h> #include <netinet/in.h>
/* get this before config.h too. */ /* get this before config.h too. */
#include <syslog.h> #include <syslog.h>
#include "config.h" #include "config.h"
#include <arpa/nameser.h> #include <arpa/nameser.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -36,7 +37,7 @@ ...@@ -36,7 +37,7 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/select.h> #include <sys/select.h>
#if defined(__sun) || defined(__sun__) #if defined(__sun) || defined(__sun__)
#include <sys/sockio.h> # include <sys/sockio.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
#include <net/if.h> #include <net/if.h>
...@@ -54,19 +55,26 @@ ...@@ -54,19 +55,26 @@
#include <errno.h> #include <errno.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#include <net/ethernet.h> #if defined(__OpenBSD__)
# include <netinet/if_ether.h>
#else
# include <net/ethernet.h>
#endif
#include <net/if_arp.h> #include <net/if_arp.h>
#include <netinet/in_systm.h> #include <netinet/in_systm.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#ifdef HAVE_PF_PACKET
#include <netpacket/packet.h>
#endif
#ifdef HAVE_BPF #ifdef HAVE_BPF
#include <net/bpf.h> # include <net/bpf.h>
#include <net/if_dl.h> # include <net/if_dl.h>
#else
# include <netpacket/packet.h>
#endif #endif
#include <sys/uio.h> #include <sys/uio.h>
/* Size: we check after adding each record, so there must be
memory for the largest packet, and the largest record */
#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
#define OPT_BOGUSPRIV 1 #define OPT_BOGUSPRIV 1
#define OPT_FILTER 2 #define OPT_FILTER 2
#define OPT_LOG 4 #define OPT_LOG 4
...@@ -80,6 +88,8 @@ ...@@ -80,6 +88,8 @@
#define OPT_LOCALMX 1024 #define OPT_LOCALMX 1024
#define OPT_NO_NEG 2048 #define OPT_NO_NEG 2048
#define OPT_NODOTS_LOCAL 4096 #define OPT_NODOTS_LOCAL 4096
#define OPT_NOWILD 8192
#define OPT_ETHERS 16384
struct all_addr { struct all_addr {
union { union {
...@@ -175,20 +185,20 @@ struct server { ...@@ -175,20 +185,20 @@ struct server {
struct server *next; struct server *next;
}; };
/* linked list of all the interfaces in the system and
the sockets we have bound to each one. */
struct irec { struct irec {
union mysockaddr addr; union mysockaddr addr;
int fd;
int valid;
struct irec *next; struct irec *next;
}; };
struct listener {
int fd, family;
struct listener *next;
};
/* interface and address parms from command line. */ /* interface and address parms from command line. */
struct iname { struct iname {
char *name; char *name;
union mysockaddr addr; union mysockaddr addr;
int found;
struct iname *next; struct iname *next;
}; };
...@@ -202,6 +212,7 @@ struct resolvc { ...@@ -202,6 +212,7 @@ struct resolvc {
struct frec { struct frec {
union mysockaddr source; union mysockaddr source;
struct all_addr dest;
struct server *sentto; struct server *sentto;
unsigned short orig_id, new_id; unsigned short orig_id, new_id;
int fd; int fd;
...@@ -232,16 +243,15 @@ struct dhcp_config { ...@@ -232,16 +243,15 @@ struct dhcp_config {
struct dhcp_opt { struct dhcp_opt {
int opt, len, is_addr; int opt, len, is_addr;
unsigned char *val; unsigned char *val;
char *netid;
struct dhcp_opt *next; struct dhcp_opt *next;
}; };
struct dhcp_context { struct dhcp_context {
int fd, rawfd, ifindex;
char *iface;
unsigned char hwaddr[ETHER_ADDR_LEN];
unsigned int lease_time; unsigned int lease_time;
struct in_addr serv_addr, netmask, broadcast; struct in_addr netmask, broadcast;
struct in_addr start, end, last; /* range of available addresses */ struct in_addr start, end, last; /* range of available addresses */
char *netid;
struct dhcp_context *next; struct dhcp_context *next;
}; };
...@@ -313,7 +323,7 @@ char *safe_string_alloc(char *cp); ...@@ -313,7 +323,7 @@ char *safe_string_alloc(char *cp);
int sa_len(union mysockaddr *addr); int sa_len(union mysockaddr *addr);
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2); int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
int hostname_isequal(unsigned char *a, unsigned char *b); int hostname_isequal(unsigned char *a, unsigned char *b);
time_t dnsmasq_time(int fd);
/* 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,
...@@ -323,35 +333,37 @@ unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resol ...@@ -323,35 +333,37 @@ unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resol
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,
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);
/* forward.c */ /* forward.c */
void forward_init(int first); void forward_init(int first);
void reap_forward(int fd);
struct server *forward_query(int udpfd, union mysockaddr *udpaddr, HEADER *header,
int plen, unsigned int options, char *dnamebuff,
struct server *servers, struct server *last_server,
time_t now, unsigned long local_ttl);
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 server *receive_query(struct listener *listen, char *packet, char *mxname,
char *mxtarget, unsigned int options, time_t now,
unsigned long local_ttl, char *namebuff,
struct iname *names, struct iname *addrs, struct iname *except,
struct server *last_server, struct server *servers);
/* 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);
char *enumerate_interfaces(struct irec **interfaces, struct irec *enumerate_interfaces(struct iname *names,
struct iname *names, struct iname *addrs,
struct iname *addrs, struct iname *except,
struct iname *except, int port);
struct dhcp_context *dhcp, struct listener *create_wildcard_listeners(int port);
int port); struct listener *create_bound_listeners(struct irec *interfaces);
/* dhcp.c */ /* dhcp.c */
void dhcp_packet(struct dhcp_context *context, char *packet, void dhcp_init(int *fdp, int* rfdp);
struct dhcp_opt *dhcp_opts, void dhcp_packet(struct dhcp_context *contexts, char *packet,
struct dhcp_config *dhcp_configs, struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
time_t now, char *namebuff, char *domain_suffix, time_t now, char *namebuff, char *domain_suffix,
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 dhcp_fd, int raw_fd,
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);
...@@ -359,12 +371,14 @@ struct dhcp_config *find_config(struct dhcp_config *configs, ...@@ -359,12 +371,14 @@ 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,
unsigned char *hwaddr, char *hostname); unsigned char *hwaddr, char *hostname);
struct dhcp_config *read_ethers(struct dhcp_config *configs, char *buff);
void set_configs_from_cache(struct dhcp_config *configs); void dhcp_update_configs(struct dhcp_config *configs);
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff);
/* lease.c */ /* lease.c */
void lease_update_dns(int force_dns); void lease_update_file(int force, time_t now);
void lease_update_dns(void);
int lease_init(char *lease_file, char *domain, char *buff, int lease_init(char *lease_file, char *domain, char *buff,
char *buff2, time_t now, struct dhcp_config *dhcp_configs); char *buff2, time_t now, int maxleases);
struct dhcp_lease *lease_allocate(unsigned char *clid, int clid_len, struct in_addr addr); struct dhcp_lease *lease_allocate(unsigned char *clid, int clid_len, struct in_addr addr);
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr); void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr);
void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix); void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix);
...@@ -372,10 +386,15 @@ void lease_set_expires(struct dhcp_lease *lease, time_t exp); ...@@ -372,10 +386,15 @@ void lease_set_expires(struct dhcp_lease *lease, time_t exp);
struct dhcp_lease *lease_find_by_client(unsigned char *clid, int clid_len); 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);
/* rfc2131.c */ /* rfc2131.c */
int dhcp_reply(struct dhcp_context *context, struct dhcp_packet *mess, int dhcp_reply(struct dhcp_context *context,
struct in_addr iface_addr,
char *iface_name,
int iface_mtu,
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,
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);
This diff is collapsed.
...@@ -16,10 +16,11 @@ ...@@ -16,10 +16,11 @@
static struct dhcp_lease *leases; static struct dhcp_lease *leases;
FILE *lease_file; FILE *lease_file;
int dns_dirty, file_dirty; int dns_dirty, file_dirty, new_lease;
int leases_left;
int lease_init(char *filename, char *domain, char *buff, int lease_init(char *filename, char *domain, char *buff,
char *buff2, time_t now, struct dhcp_config *dhcp_configs) char *buff2, time_t now, int maxleases)
{ {
unsigned int e0, e1, e2, e3, e4, e5, a0, a1, a2, a3; unsigned int e0, e1, e2, e3, e4, e5, a0, a1, a2, a3;
unsigned long ei; unsigned long ei;
...@@ -27,20 +28,24 @@ int lease_init(char *filename, char *domain, char *buff, ...@@ -27,20 +28,24 @@ int lease_init(char *filename, char *domain, char *buff,
unsigned char hwaddr[ETHER_ADDR_LEN]; unsigned char hwaddr[ETHER_ADDR_LEN];
struct in_addr addr; struct in_addr addr;
struct dhcp_lease *lease; struct dhcp_lease *lease;
struct dhcp_config *config;
int clid_len = 0; int clid_len = 0;
int has_old = 0; int has_old = 0;
leases = NULL; leases = NULL;
leases_left = maxleases;
if (!(lease_file = fopen(filename, "a+")))
if (!(lease_file = fopen(filename, "r+")))
die("cannot open or create leases file: %s", NULL); die("cannot open or create leases file: %s", NULL);
rewind(lease_file); /* file opened with mode a+ which sets pointer at end. */
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)
{ {
#ifdef HAVE_BROKEN_RTC
if (ei)
expires = (time_t)ei + now;
else
expires = (time_t)0;
#else
/* strictly time_t is opaque, but this hack should work on all sane systems, /* strictly time_t is opaque, but this hack should work on all sane systems,
even when sizeof(time_t) == 8 */ even when sizeof(time_t) == 8 */
expires = (time_t)ei; expires = (time_t)ei;
...@@ -50,6 +55,7 @@ int lease_init(char *filename, char *domain, char *buff, ...@@ -50,6 +55,7 @@ int lease_init(char *filename, char *domain, char *buff,
has_old = 1; has_old = 1;
continue; /* expired */ continue; /* expired */
} }
#endif
hwaddr[0] = e0; hwaddr[0] = e0;
hwaddr[1] = e1; hwaddr[1] = e1;
...@@ -74,7 +80,7 @@ int lease_init(char *filename, char *domain, char *buff, ...@@ -74,7 +80,7 @@ int lease_init(char *filename, char *domain, char *buff,
} }
if (!(lease = lease_allocate(buff2, clid_len, addr))) if (!(lease = lease_allocate(buff2, clid_len, addr)))
die ("cannot get memory", NULL); die ("too many stored leases", NULL);
lease->expires = expires; lease->expires = expires;
memcpy(lease->hwaddr, hwaddr, ETHER_ADDR_LEN); memcpy(lease->hwaddr, hwaddr, ETHER_ADDR_LEN);
...@@ -85,32 +91,54 @@ int lease_init(char *filename, char *domain, char *buff, ...@@ -85,32 +91,54 @@ int lease_init(char *filename, char *domain, char *buff,
dns_dirty = 1; dns_dirty = 1;
file_dirty = has_old; file_dirty = has_old;
new_lease = 0;
return fileno(lease_file);
}
void lease_update_from_configs(struct dhcp_config *dhcp_configs, char *domain)
{
/* changes to the config may change current leases. */
struct dhcp_lease *lease;
struct dhcp_config *config;
/* Deal with edits to the config file which may have changed the hostname
associated with a hardware address. Do this after the main loop so that
changes get written back out */
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
if ((config = find_config(dhcp_configs, NULL, lease->clid, lease->clid_len, lease->hwaddr, NULL)) && if ((config = find_config(dhcp_configs, NULL, lease->clid, lease->clid_len, lease->hwaddr, NULL)) &&
(config->hostname)) (config->hostname))
lease_set_hostname(lease, config->hostname, domain); lease_set_hostname(lease, config->hostname, domain);
return fileno(lease_file);
} }
void lease_update_dns(int force_dns) void lease_update_file(int force, time_t now)
{ {
struct dhcp_lease *lease; struct dhcp_lease *lease;
int i; int i = force; /* avoid warning */
unsigned long expires;
#ifdef HAVE_BROKEN_RTC
if (force || new_lease)
{
lease_prune(NULL, now);
#else
if (file_dirty) if (file_dirty)
{ {
#endif
rewind(lease_file); rewind(lease_file);
ftruncate(fileno(lease_file), 0); ftruncate(fileno(lease_file), 0);
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
{ {
#ifdef HAVE_BROKEN_RTC
if (lease->expires)
expires = (unsigned long) difftime(lease->expires, now);
else
expires = 0;
#else
expires = now; /* eliminate warning */
expires = (unsigned long)lease->expires;
#endif
fprintf(lease_file, "%lu %.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %s ", fprintf(lease_file, "%lu %.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %s ",
(unsigned long)lease->expires, lease->hwaddr[0], lease->hwaddr[1], expires, lease->hwaddr[0], lease->hwaddr[1],
lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
lease->hwaddr[5], inet_ntoa(lease->addr), lease->hwaddr[5], inet_ntoa(lease->addr),
lease->hostname ? lease->hostname : "*"); lease->hostname ? lease->hostname : "*");
...@@ -129,13 +157,18 @@ void lease_update_dns(int force_dns) ...@@ -129,13 +157,18 @@ void lease_update_dns(int force_dns)
fflush(lease_file); fflush(lease_file);
fsync(fileno(lease_file)); fsync(fileno(lease_file));
file_dirty = 0; file_dirty = 0;
new_lease = 0;
} }
}
if (dns_dirty || force_dns) void lease_update_dns(void)
{
struct dhcp_lease *lease;
if (dns_dirty)
{ {
cache_unhash_dhcp(); cache_unhash_dhcp();
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
{ {
if (lease->fqdn) if (lease->fqdn)
...@@ -173,6 +206,7 @@ void lease_prune(struct dhcp_lease *target, time_t now) ...@@ -173,6 +206,7 @@ void lease_prune(struct dhcp_lease *target, time_t now)
if (lease->clid) if (lease->clid)
free(lease->clid); free(lease->clid);
free(lease); free(lease);
leases_left++;
} }
else else
up = &lease->next; up = &lease->next;
...@@ -220,7 +254,7 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr addr) ...@@ -220,7 +254,7 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
struct dhcp_lease *lease_allocate(unsigned char *clid, int clid_len, struct in_addr addr) struct dhcp_lease *lease_allocate(unsigned char *clid, int clid_len, struct in_addr addr)
{ {
struct dhcp_lease *lease; struct dhcp_lease *lease;
if (!(lease = malloc(sizeof(struct dhcp_lease)))) if (!leases_left || !(lease = malloc(sizeof(struct dhcp_lease))))
return NULL; return NULL;
lease->clid = NULL; lease->clid = NULL;
...@@ -245,6 +279,8 @@ struct dhcp_lease *lease_allocate(unsigned char *clid, int clid_len, struct in_a ...@@ -245,6 +279,8 @@ struct dhcp_lease *lease_allocate(unsigned char *clid, int clid_len, struct in_a
leases = lease; leases = lease;
file_dirty = 1; file_dirty = 1;
new_lease = 1;
leases_left--;
return lease; return lease;
} }
...@@ -294,14 +330,12 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix) ...@@ -294,14 +330,12 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix)
lease_tmp->fqdn = NULL; lease_tmp->fqdn = NULL;
} }
} }
if (!new_name)
{ if (!new_name && (new_name = malloc(strlen(name) + 1)))
new_name = malloc(strlen(name) + 1); strcpy(new_name, name);
strcpy(new_name, name);
} if (suffix && !new_fqdn && (new_fqdn = malloc(strlen(name) + strlen(suffix) + 2)))
if (suffix && !new_fqdn)
{ {
new_fqdn = malloc(strlen(name) + strlen(suffix) + 2);
strcpy(new_fqdn, name); strcpy(new_fqdn, name);
strcat(new_fqdn, "."); strcat(new_fqdn, ".");
strcat(new_fqdn, suffix); strcat(new_fqdn, suffix);
......
This diff is collapsed.
This diff is collapsed.
...@@ -620,7 +620,7 @@ int setup_reply(HEADER *header, unsigned int qlen, ...@@ -620,7 +620,7 @@ int setup_reply(HEADER *header, unsigned int qlen,
header->ancount = htons(0); /* no answers unless changed below*/ header->ancount = htons(0); /* no answers unless changed below*/
if (flags == F_NEG) if (flags == F_NEG)
header->rcode = SERVFAIL; /* couldn't get memory */ header->rcode = SERVFAIL; /* couldn't get memory */
else if (flags == F_NOERR) else if (flags == F_NOERR || flags == F_QUERY)
header->rcode = NOERROR; /* empty domain */ header->rcode = NOERROR; /* empty domain */
else if (flags == F_NXDOMAIN) else if (flags == F_NXDOMAIN)
header->rcode = NXDOMAIN; header->rcode = NXDOMAIN;
......
This diff is collapsed.
...@@ -61,17 +61,15 @@ unsigned short rand16(void) ...@@ -61,17 +61,15 @@ unsigned short rand16(void)
else else
{ {
s = (char *) &seed; s = (char *) &seed;
while ( (c < sizeof(seed)) && while ((c < sizeof(seed)) &&
((n = read(fd, sbuf, sizeof(seed)) > 0)) ) ((n = read(fd, sbuf, sizeof(seed)) > 0)))
{ {
memcpy(s, sbuf, n); memcpy(s, sbuf, n);
s += n; s += n;
c += n; c += n;
} }
if (n < 0) if (n < 0)
{ seed = badseed;
seed = badseed;
}
close(fd); close(fd);
} }
...@@ -215,3 +213,18 @@ int hostname_isequal(unsigned char *a, unsigned char *b) ...@@ -215,3 +213,18 @@ int hostname_isequal(unsigned char *a, unsigned char *b)
return 1; return 1;
} }
time_t dnsmasq_time(int fd)
{
#ifdef HAVE_BROKEN_RTC
/* we use uptime as a time-base, rather than epoch time
because epoch time can break when a machine contacts
a nameserver and updates it. */
char buf[30];
lseek(fd, 0, SEEK_SET);
read(fd, buf, 30);
return (time_t)atol(buf);
#else
fd = 0; /* stop warning */
return time(NULL);
#endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment