Commit feba5c1d authored by Simon Kelley's avatar Simon Kelley

import of dnsmasq-2.10.tar.gz

parent de37951c
...@@ -1056,3 +1056,71 @@ release 2.9 ...@@ -1056,3 +1056,71 @@ release 2.9
Allow # as the argument to --domain, meaning "read the Allow # as the argument to --domain, meaning "read the
domain from the first search directive in domain from the first search directive in
/etc.resolv.conf". Feature suggested by Evan Jones. /etc.resolv.conf". Feature suggested by Evan Jones.
release 2.10
Allow --query-port to be set to a low port by creating and
binding the socket before dropping root. (Suggestion from
Jamie Lokier)
Support TCP queries. It turned out to be possible to do
this with a couple of hundred lines of code, once I knew
how. The executable size went up by a few K on i386.
There are a few limitations: data obtained via TCP is not
cached, and dynamically-created interfaces may break under
certain circumstances. Source-address or query-port
specifications are ignored for TCP.
NAK attempts to renew a DHCP lease where the DHCP range
has changed and the lease is no longer in the allowed
range. Jamie Lokier pointed out this bug.
NAK attempts to renew a pool DHCP lease when a statically
allocated address has become available, forcing a host to
move to it's allocated address. Lots of people have
suggested this change and been rebuffed (they know who
they are) the straws that broke the camel's back were Tim
Cutts and Jamie Lokier.
Remove any nameserver records from answers which are
modified by --alias flags. If the answer is modified, it
cannot any longer be authoritative.
Change behaviour of "bogus-priv" option to return NXDOMAIN
rather than a PTR record with the dotted-quad address as
name. The new behaviour doesn't provoke tcpwrappers like
the old behavior did.
Added a patch for the Suse rpm. That changes the default
group to one suitable for Suse and disables inclusion of
the ISC lease-file reader code. Thanks to Andy Cambeis for
his ongoing work on Suse packaging.
Support forwarding of EDNS.0 The maximum UDP packet size
defaults to 1280, but may be changed with the
--edns-packet-max option. Detect queries with the do bit
set and always forward them, since DNSSEC records are
not cached. This behaviour is required to make
DNSSECbis work properly though dnsmasq. Thanks to Simon
Josefsson for help with this.
Move default config file location under OpenBSD from
/usr/local/etc/dnsmasq.conf to /etc/dnsmasq.conf. Bug
report from Jonathan Weiss.
Use a lease with matching MAC address for a host which
doesn't present a client-id, even if there was a client ID
at some point in the past. This reduces surprises when
changing DHCP clients, adding id:* to a host, and from the
semantics change of /etc/ethers in 2.9. Thanks to Bernard
Sammer for finding that.
Added a "contrib" directory and in it the dnslist utility,
from Thomas Tuttle.
Fixed "fail to start up" problems under Linux with IPv6
enabled. It's not clear that these were an issue in
released versions, but they manifested themselves when TCP
support was added. Thanks to Michael Hamilton for
assistance with this.
...@@ -20,12 +20,10 @@ A: The high ports that dnsmasq opens is for replies from the upstream ...@@ -20,12 +20,10 @@ A: The high ports that dnsmasq opens is for replies from the upstream
Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify
that? that?
A: Yes, they do, so technically dnsmasq is not RFC-compliant. In practice, the A: Update: from version 2.10, it does. There are a few limitations:
sorts of queries which dnsmasq is used for are always sent via UDP. Adding data obtained via TCP is not cached, and dynamically-created
TCP support would make dnsmasq much more heavyweight for no practical interfaces may break under certain circumstances. Source-address
benefit. If you really want to do zone transfers, forward port 53 TCP or query-port specifications are ignored for TCP.
using in-kernel port-forwarding or a port-fowarder like rinetd.
Q: When I send SIGUSR1 to dump the contents of the cache, some entries have Q: When I send SIGUSR1 to dump the contents of the cache, some entries have
no IP address and are for names like mymachine.mydomain.com.mydomain.com. no IP address and are for names like mymachine.mydomain.com.mydomain.com.
...@@ -74,6 +72,8 @@ A: Use the standard DNS convention of <reversed address>.in-addr.arpa. ...@@ -74,6 +72,8 @@ A: Use the standard DNS convention of <reversed address>.in-addr.arpa.
For instance to send reverse queries on the range 192.168.0.0 to For instance to send reverse queries on the range 192.168.0.0 to
192.168.0.255 to a nameserver at 10.0.0.1 do 192.168.0.255 to a nameserver at 10.0.0.1 do
server=/0.168.192.in-addr.arpa/10.0.0.1 server=/0.168.192.in-addr.arpa/10.0.0.1
Note that the "bogus-priv" option take priority over this option,
so the above will not work when the bogus-priv option is set.
Q: Dnsmasq fails to start with an error like this: "dnsmasq: bind Q: Dnsmasq fails to start with an error like this: "dnsmasq: bind
failed: Cannot assign requested address". What's the problem? failed: Cannot assign requested address". What's the problem?
......
...@@ -10,7 +10,7 @@ all : ...@@ -10,7 +10,7 @@ all :
@cd $(SRC); $(MAKE) dnsmasq @cd $(SRC); $(MAKE) dnsmasq
clean : clean :
rm -f *~ */*~ $(SRC)/*.o $(SRC)/dnsmasq core build rm -f *~ contrib/*/*~ */*~ $(SRC)/*.o $(SRC)/dnsmasq core build
install : all install : all
install -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8 install -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8
......
body
{
font-family: sans-serif;
color: #000;
}
h1
{
font-size: medium;
font-weight: bold;
}
h1 .updated
{
color: #999;
}
table
{
border-collapse: collapse;
border-bottom: 2px solid #000;
}
th
{
background: #DDD;
border-top: 2px solid #000;
text-align: left;
font-weight: bold;
}
/* Any row */
tr
{
border-top: 2px solid #000;
}
/* Any row but the first or second (overrides above rule) */
tr + tr + tr
{
border-top: 2px solid #999;
}
tr.offline td.hostname
{
color: #999;
}
.hostname { width: 10em; }
.ip_addr { width: 10em; background: #DDD; }
.ether_addr { width: 15em; }
.client_id { width: 15em; background: #DDD; }
.status { width: 5em; }
.since { width: 10em; background: #DDD; }
.lease { width: 10em; }
This diff is collapsed.
<html>
<head>
<title>DHCP Clients</title>
<link rel="stylesheet" href="dhcp.css"/>
<meta http-equiv="Refresh" content="2"/>
</head>
<body>
<h1>DHCP Clients <span class="updated">(updated [% updated %])</span></h1>
<table cols="7">
<tr>
<th class="hostname">Hostname</th>
<th class="ip_addr">IP Address</th>
<th class="ether_addr">Ethernet Address</th>
<th class="client_id">DHCP Client ID</th>
<th class="status">Status</th>
<th class="since">Since</th>
<th class="lease">Lease Expires</th>
</tr>
[% FOREACH host IN hosts %]
<tr class="[% IF host.online %]online[% ELSE %]offline[% END %]">
<td class="hostname">[% host.hostname %]</td>
<td class="ip_addr">[% host.ip_addr %]</td>
<td class="ether_addr">[% host.ether_addr %]</td>
<td class="client_id">[% host.text_client_id %] ([% host.raw_client_id %])</td>
<td class="status">[% IF host.online %]Online[% ELSE %]Offline[% END %]</td>
<td class="since">[% host.since %]</td>
<td class="lease">[% host.text_lease %]</td>
</tr>
[% END %]
</table>
</body>
</html>
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.9 Version: 2.10
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.9 Version: 2.10
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: Productivity/Networking/DNS/Servers Group: Productivity/Networking/DNS/Servers
...@@ -16,7 +16,7 @@ Provides: dns_daemon ...@@ -16,7 +16,7 @@ Provides: dns_daemon
Conflicts: bind bind8 bind9 Conflicts: bind bind8 bind9
PreReq: %fillup_prereq %insserv_prereq PreReq: %fillup_prereq %insserv_prereq
Autoreqprov: on Autoreqprov: on
Source0: %{name}-%{version}.tar.gz Source0: %{name}-%{version}.tar.bz2
BuildRoot: /var/tmp/%{name}-%{version} BuildRoot: /var/tmp/%{name}-%{version}
Summary: A lightweight caching nameserver Summary: A lightweight caching nameserver
...@@ -39,6 +39,8 @@ leases and BOOTP for network booting of diskless machines. ...@@ -39,6 +39,8 @@ leases and BOOTP for network booting of diskless machines.
%prep %prep
%setup -q %setup -q
patch -p0 <rpm/%{name}-SuSE.patch
%build %build
%{?suse_update_config:%{suse_update_config -f}} %{?suse_update_config:%{suse_update_config -f}}
make make
......
...@@ -73,19 +73,29 @@ Print the version number. ...@@ -73,19 +73,29 @@ Print the version number.
Listen on <port> instead of the standard DNS port (53). Useful mainly for Listen on <port> instead of the standard DNS port (53). Useful mainly for
debugging. debugging.
.TP .TP
.B \-P, --edns-packet-max=<size>
Specify the largest EDNS.0 UDP packet which is supported by the DNS
forwarder. Defaults to 1280, which is the RFC2671-recommended maximum
for ethernet.
.TP
.B \-Q, --query-port=<query_port> .B \-Q, --query-port=<query_port>
Send outbound DNS queries from, and listen for their replies on, the specific UDP port <query_port> instead of using one chosen at runtime. Useful to simplify your Send outbound DNS queries from, and listen for their replies on, the specific UDP port <query_port> instead of using one chosen at runtime. Useful to simplify your
firewall rules; without this, your firewall would have to allow connections from outside DNS servers to a range of UDP ports, or dynamically adapt to the firewall rules; without this, your firewall would have to allow connections from outside DNS servers to a range of UDP ports, or dynamically adapt to the
port being used by the current dnsmasq instance. port being used by the current dnsmasq instance.
.TP .TP
.B \-i, --interface=<interface name> .B \-i, --interface=<interface name>
Listen only on the specified interface. More than one interface may be specified. Dnsmasq always listens on the loopback (local) interface. If no Listen only on the specified interface(s). Dnsmasq automatically adds
.B \-i the loopback (local) interface to the list of interfaces to use when
flags are given, dnsmasq listens on all available interfaces unless overridden by the
.B \-a .B \--interface
option is used. If no
.B \--interface
or or
.B \-I .B \--listen-address
flags. If IP alias interfaces (eg "eth1:0") are used with options are given dnsmasq listens on all available interfaces except any
given in
.B \--except-interface
options. If IP alias interfaces (eg "eth1:0") are used with
.B --interface .B --interface
or or
.B --except-interface .B --except-interface
...@@ -95,21 +105,30 @@ option will be automatically set. This is required for deeply boring ...@@ -95,21 +105,30 @@ option will be automatically set. This is required for deeply boring
sockets-API reasons. sockets-API reasons.
.TP .TP
.B \-I, --except-interface=<interface name> .B \-I, --except-interface=<interface name>
Do not listen on the specified interface. Do not listen on the specified interface. Note that the order of
.B \--listen-address
.B --interface
and
.B --except-interface
options does not matter and that
.B --except-interface
options always override the others.
.TP .TP
.B \-a, --listen-address=<ipaddr> .B \-a, --listen-address=<ipaddr>
Listen only on the given IP address. As with Listen on the given IP address(es). Both
.B \-i .B \--interface
more than one address may be specified. Unlike and
.B \-i .B \--listen-address
the loopback interface is not special: if dnsmasq is to listen on the loopback interface, options may be given, in which case the set of both interfaces and
it's IP, 127.0.0.1, must be explicitly given. If no addresses is used. Note that if no
.B \-a .B \--interface
flags are given, dnsmasq listens on all available interfaces unless overridden by option is given, but
.B \-i .B \--listen-address
or is, dnsmasq will not automatically listen on the loopback
.B \-I interface. To achieve this, its IP address, 127.0.0.1, must be
flags. explicitly given as a
.B \--listen-address
option.
.TP .TP
.B \-z, --bind-interfaces .B \-z, --bind-interfaces
On systems which support it, dnsmasq binds the wildcard address, On systems which support it, dnsmasq binds the wildcard address,
...@@ -126,7 +145,8 @@ broadcast packets. ...@@ -126,7 +145,8 @@ broadcast packets.
.TP .TP
.B \-b, --bogus-priv .B \-b, --bogus-priv
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc) Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
which are not found in /etc/hosts or the DHCP leases file are resolved to the IP address in dotted-quad form. which are not found in /etc/hosts or the DHCP leases file are answered
with "no such domain" rather than being forwarded upstream.
.TP .TP
.B \-V, --alias=<old-ip>,<new-ip>[,<mask>] .B \-V, --alias=<old-ip>,<new-ip>[,<mask>]
Modify IPv4 addresses returned from upstream nameservers; old-ip is Modify IPv4 addresses returned from upstream nameservers; old-ip is
......
...@@ -18,9 +18,11 @@ connected to the internet via a modem, cable-modem or ADSL ...@@ -18,9 +18,11 @@ connected to the internet via a modem, cable-modem or ADSL
connection but would be a good choice for any small network where low connection but would be a good choice for any small network where low
resource use and ease of configuration are important. resource use and ease of configuration are important.
<P> <P>
Supported platforms include Linux (with glibc and uclibc), *BSD and
Mac OS X.
Dnsmasq is included in at least the following Linux distributions: Dnsmasq is included in at least the following Linux distributions:
Gentoo, Debian, Slackware, Suse, Gentoo, Debian, Slackware, Suse,
Smoothwall, IP-Cop, floppyfw, Firebox, Freesco, CoyoteLinux and Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, CoyoteLinux and
Clarkconnect. It is also available as a FreeBSD port and is used in Linksys wireless routers. Clarkconnect. It is also available as a FreeBSD port and is used in Linksys wireless routers.
<P> <P>
Dnsmasq provides the following features: Dnsmasq provides the following features:
......
--- dnsmasq.8 2004-06-21 21:55:47.000000000 +0200
+++ dnsmasq.8 2004-06-22 23:30:18.000000000 +0200
@@ -63,7 +63,7 @@
.TP
.B \-g, --group=<groupname>
Specify the group which dnsmasq will run
-as. The defaults to "dip", if available, to facilitate access to
+as. The defaults to "dialout", if available, to facilitate access to
/etc/ppp/resolv.conf which is not normally world readable.
.TP
.B \-v, --version
--- dnsmasq.conf.example 2004-05-26 12:59:56.000000000 +0200
+++ dnsmasq.conf.example 2004-06-22 23:32:36.000000000 +0200
@@ -62,7 +62,7 @@
# You no longer (as of version 1.7) need to set these to enable
# dnsmasq to read /etc/ppp/resolv.conf since dnsmasq now uses the
-# "dip" group to achieve this.
+# "dialout" group to achieve this.
#user=
#group=
--- src/config.h 2004-06-22 21:14:50.000000000 +0200
+++ src/config.h 2004-06-22 23:31:46.000000000 +0200
@@ -38,7 +38,7 @@
#endif
#define DEFLEASE 3600 /* default lease time, 1 hour */
#define CHUSER "nobody"
-#define CHGRP "dip"
+#define CHGRP "dialout"
#define IP6INTERFACES "/proc/net/if_inet6"
#define UPTIME "/proc/uptime"
#define DHCP_SERVER_PORT 67
@@ -171,7 +171,7 @@
/* platform independent options. */
#undef HAVE_BROKEN_RTC
-#define HAVE_ISC_READER
+#undef HAVE_ISC_READER
#if defined(HAVE_BROKEN_RTC) && defined(HAVE_ISC_READER)
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
...@@ -12,10 +12,13 @@ ...@@ -12,10 +12,13 @@
/* Author's email: simon@thekelleys.org.uk */ /* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.9" #define VERSION "2.10"
#define FTABSIZ 150 /* max number of outstanding requests */ #define FTABSIZ 150 /* max number of outstanding requests */
#define TIMEOUT 20 /* drop queries after TIMEOUT seconds */ #define MAX_PROCS 20 /* max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define EDNS_PKTSZ 1280 /* default max EDNS.0 UDP packet from RFC2671 */
#define TIMEOUT 20 /* drop UDP queries after TIMEOUT seconds */
#define LOGRATE 120 /* log table overflows every LOGRATE seconds */ #define LOGRATE 120 /* log table overflows every LOGRATE seconds */
#define CACHESIZ 150 /* default cache size */ #define CACHESIZ 150 /* default cache size */
#define MAXTOK 50 /* token in DHCP leases */ #define MAXTOK 50 /* token in DHCP leases */
...@@ -31,9 +34,12 @@ ...@@ -31,9 +34,12 @@
#define RUNFILE "/var/run/dnsmasq.pid" #define RUNFILE "/var/run/dnsmasq.pid"
#if defined(__FreeBSD__) || defined (__OpenBSD__) #if defined(__FreeBSD__) || defined (__OpenBSD__)
# define LEASEFILE "/var/db/dnsmasq.leases" # define LEASEFILE "/var/db/dnsmasq.leases"
# define CONFFILE "/usr/local/etc/dnsmasq.conf"
#else #else
# define LEASEFILE "/var/lib/misc/dnsmasq.leases" # define LEASEFILE "/var/lib/misc/dnsmasq.leases"
#endif
#if defined(__FreeBSD__)
# define CONFFILE "/usr/local/etc/dnsmasq.conf"
#else
# define CONFFILE "/etc/dnsmasq.conf" # define CONFFILE "/etc/dnsmasq.conf"
#endif #endif
#define DEFLEASE 3600 /* default lease time, 1 hour */ #define DEFLEASE 3600 /* default lease time, 1 hour */
...@@ -63,7 +69,7 @@ ...@@ -63,7 +69,7 @@
/* 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) && !defined(NO_IPV6) #if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) && !defined(NO_IPV6)
# define HAVE_IPV6 # define HAVE_IPV6
# define ADDRSTRLEN INET6_ADDRSTRLEN # define ADDRSTRLEN INET6_ADDRSTRLEN
# if defined(SOL_IPV6) # if defined(SOL_IPV6)
...@@ -89,7 +95,6 @@ ...@@ -89,7 +95,6 @@
new system, you may want to edit these. new system, you may want to edit these.
May replace this with Autoconf one day. May replace this with Autoconf one day.
HAVE_LINUX_IPV6_PROC 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.
......
...@@ -368,28 +368,25 @@ int address_available(struct dhcp_context *context, struct in_addr taddr) ...@@ -368,28 +368,25 @@ int address_available(struct dhcp_context *context, struct in_addr taddr)
if (addr > end) if (addr > end)
return 0; return 0;
if (lease_find_by_addr(taddr))
return 0;
return 1; return 1;
} }
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, unsigned char *hwaddr) struct in_addr *addrp, unsigned char *hwaddr)
{ {
/* Find a free address: exlude anything in use and anything allocated to /* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration */ a particular hwaddr/clientid/hostname in our configuration */
struct dhcp_config *config; struct dhcp_config *config;
struct in_addr start, addr ; struct in_addr start, addr ;
int i, j; unsigned int i, j;
/* start == end means no dynamic leases. */ /* start == end means no dynamic leases. */
if (context->end.s_addr == context->start.s_addr) if (context->end.s_addr == context->start.s_addr)
return 0; return 0;
/* pick a seed based on hwaddr then iterate until we find a free address. */ /* pick a seed based on hwaddr then iterate until we find a free address. */
for (j = 0, i = 0; i < ETHER_ADDR_LEN; i++) for (j = context->addr_epoch, i = 0; i < ETHER_ADDR_LEN; i++)
j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16); j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
start.s_addr = addr.s_addr = start.s_addr = addr.s_addr =
......
This diff is collapsed.
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
*/ */
/* Author's email: simon@thekelleys.org.uk */ /* Author's email: simon@thekelleys.org.uk */
#define COPYRIGHT "Copyright (C) 2000-2004 Simon Kelley"
#ifdef __linux__ #ifdef __linux__
/* for pselect.... */ /* for pselect.... */
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/wait.h>
#if defined(__sun) || defined(__sun__) #if defined(__sun) || defined(__sun__)
# include <sys/sockio.h> # include <sys/sockio.h>
#endif #endif
...@@ -194,7 +196,7 @@ struct server { ...@@ -194,7 +196,7 @@ struct server {
struct serverfd *sfd; /* non-NULL if this server has its own fd bound to struct serverfd *sfd; /* non-NULL if this server has its own fd bound to
a source port */ a source port */
char *domain; /* set if this server only handles a domain. */ char *domain; /* set if this server only handles a domain. */
int flags; int flags, tcpfd;
struct server *next; struct server *next;
}; };
...@@ -204,7 +206,7 @@ struct irec { ...@@ -204,7 +206,7 @@ struct irec {
}; };
struct listener { struct listener {
int fd, family; int fd, tcpfd, family;
struct listener *next; struct listener *next;
}; };
...@@ -285,7 +287,7 @@ struct dhcp_vendor { ...@@ -285,7 +287,7 @@ struct dhcp_vendor {
}; };
struct dhcp_context { struct dhcp_context {
unsigned int lease_time; unsigned int lease_time, addr_epoch;
struct in_addr netmask, broadcast; struct in_addr netmask, broadcast;
struct in_addr start, end; /* range of available addresses */ struct in_addr start, end; /* range of available addresses */
struct dhcp_netid netid; struct dhcp_netid netid;
...@@ -346,9 +348,10 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff, ...@@ -346,9 +348,10 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff,
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *namebuff, time_t now); void extract_neg_addrs(HEADER *header, unsigned int qlen, char *namebuff, time_t now);
int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_record *mxnames, int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_record *mxnames,
char *mxtarget, unsigned int options, time_t now, unsigned long local_ttl, char *mxtarget, unsigned int options, time_t now, unsigned long local_ttl,
char *namebuff); char *namebuff, unsigned short edns_pcktsz);
int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name, int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name,
struct bogus_addr *addr, time_t now); struct bogus_addr *addr, time_t now);
unsigned char *find_pseudoheader(HEADER *header, unsigned int plen);
/* util.c */ /* util.c */
unsigned short rand16(void); unsigned short rand16(void);
...@@ -376,20 +379,30 @@ unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resol ...@@ -376,20 +379,30 @@ unsigned int read_opts(int argc, char **argv, char *buff, struct resolvc **resol
struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf, struct dhcp_context **dhcp, struct dhcp_config **dhcp_conf,
struct dhcp_opt **opts, struct dhcp_vendor **dhcp_vendors, struct dhcp_opt **opts, struct dhcp_vendor **dhcp_vendors,
char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server, char **dhcp_file, char **dhcp_sname, struct in_addr *dhcp_next_server,
int *maxleases, unsigned int *min_leasetime, struct doctor **doctors); int *maxleases, unsigned int *min_leasetime, struct doctor **doctors,
unsigned short *edns_pktsz);
/* forward.c */ /* forward.c */
void forward_init(int first); void forward_init(int first);
struct server *reply_query(struct serverfd *sfd, int options, char *packet, time_t now, struct server *reply_query(struct serverfd *sfd, int options, char *packet, time_t now,
char *dnamebuff, struct server *servers, struct server *last_server, char *dnamebuff, struct server *servers, struct server *last_server,
struct bogus_addr *bogus_nxdomain, struct doctor *doctors); struct bogus_addr *bogus_nxdomain,
struct doctor *doctors, unsigned short edns_pcktsz);
struct server *receive_query(struct listener *listen, char *packet, struct mx_record *mxnames, struct server *receive_query(struct listener *listen, char *packet, struct mx_record *mxnames,
char *mxtarget, unsigned int options, time_t now, char *mxtarget, unsigned int options, time_t now,
unsigned long local_ttl, char *namebuff, unsigned long local_ttl, char *namebuff,
struct iname *names, struct iname *addrs, struct iname *except, struct iname *names, struct iname *addrs, struct iname *except,
struct server *last_server, struct server *servers); struct server *last_server, struct server *servers, unsigned short edns_pcktsz);
char *tcp_request(int confd, struct mx_record *mxnames,
char *mxtarget, unsigned int options, time_t now,
unsigned long local_ttl, char *namebuff,
struct server *last_server, struct server *servers,
struct bogus_addr *bogus_nxdomain, struct doctor *doctors,
unsigned short edns_pcktsz);
/* network.c */ /* network.c */
struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds);
struct server *reload_servers(char *fname, char *buff, struct server *servers, int query_port); struct server *reload_servers(char *fname, char *buff, struct server *servers, int query_port);
struct server *check_servers(struct server *new, struct irec *interfaces, struct serverfd **sfds); struct server *check_servers(struct server *new, struct irec *interfaces, struct serverfd **sfds);
struct irec *enumerate_interfaces(struct iname **names, struct irec *enumerate_interfaces(struct iname **names,
...@@ -397,7 +410,7 @@ struct irec *enumerate_interfaces(struct iname **names, ...@@ -397,7 +410,7 @@ struct irec *enumerate_interfaces(struct iname **names,
struct iname *except, struct iname *except,
int port); int port);
struct listener *create_wildcard_listeners(int port); struct listener *create_wildcard_listeners(int port);
struct listener *create_bound_listeners(struct irec *interfaces); struct listener *create_bound_listeners(struct irec *interfaces, int port);
/* dhcp.c */ /* dhcp.c */
void dhcp_init(int *fdp, int* rfdp); void dhcp_init(int *fdp, int* rfdp);
void dhcp_packet(struct dhcp_context *contexts, char *packet, void dhcp_packet(struct dhcp_context *contexts, char *packet,
...@@ -448,3 +461,4 @@ int dhcp_reply(struct dhcp_context *context, ...@@ -448,3 +461,4 @@ int dhcp_reply(struct dhcp_context *context,
#ifdef HAVE_ISC_READER #ifdef HAVE_ISC_READER
void load_dhcp(char *file, char *suffix, time_t now, char *hostname); void load_dhcp(char *file, char *suffix, time_t now, char *hostname);
#endif #endif
This diff is collapsed.
...@@ -220,9 +220,6 @@ void lease_prune(struct dhcp_lease *target, time_t now) ...@@ -220,9 +220,6 @@ void lease_prune(struct dhcp_lease *target, time_t now)
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)
{ {
/* zero length means clid from hwaddr: never match am option clid to
a hardware-address derived clid */
struct dhcp_lease *lease; struct dhcp_lease *lease;
if (clid_len) if (clid_len)
...@@ -235,8 +232,7 @@ struct dhcp_lease *lease_find_by_client(unsigned char *clid, int clid_len) ...@@ -235,8 +232,7 @@ struct dhcp_lease *lease_find_by_client(unsigned char *clid, int clid_len)
else else
{ {
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
if (!lease->clid && if (memcmp(clid, lease->hwaddr, ETHER_ADDR_LEN) == 0)
memcmp(clid, lease->hwaddr, ETHER_ADDR_LEN) == 0)
return lease; return lease;
} }
......
...@@ -25,8 +25,12 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a ...@@ -25,8 +25,12 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a
if (except) if (except)
for (tmp = except; tmp; tmp = tmp->next) for (tmp = except; tmp; tmp = tmp->next)
if (tmp->name && strcmp(tmp->name, name) == 0) if (tmp->name && strcmp(tmp->name, name) == 0)
return list; {
/* record address of named interfaces, for TCP access control */
tmp->addr = *addr;
return list;
}
/* we may need to check the whitelist */ /* we may need to check the whitelist */
if (names || addrs) if (names || addrs)
{ {
...@@ -34,8 +38,11 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a ...@@ -34,8 +38,11 @@ static struct irec *add_iface(struct irec *list, char *name, union mysockaddr *a
for (tmp = names; tmp; tmp = tmp->next) for (tmp = names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, name) == 0)) if (tmp->name && (strcmp(tmp->name, name) == 0))
found = tmp->used = 1; {
tmp->addr = *addr;
found = tmp->used = 1;
}
for (tmp = addrs; tmp; tmp = tmp->next) for (tmp = addrs; tmp; tmp = tmp->next)
if (sockaddr_isequal(&tmp->addr, addr)) if (sockaddr_isequal(&tmp->addr, addr))
found = tmp->used = 1; found = tmp->used = 1;
...@@ -220,6 +227,65 @@ struct irec *enumerate_interfaces(struct iname **names, ...@@ -220,6 +227,65 @@ struct irec *enumerate_interfaces(struct iname **names,
return iface; return iface;
} }
#ifdef HAVE_IPV6
static int create_ipv6_listener(struct listener **link, int port)
{
union mysockaddr addr;
int tcpfd, fd, flags, save;
struct listener *l;
int opt = 1;
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(port);
addr.in6.sin6_flowinfo = htonl(0);
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
/* No error of the kernel doesn't support IPv6 */
if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
return (errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT ||
errno == EINVAL);
if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
{
save = errno;
close(fd);
errno = save;
return 0;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
(flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
listen(tcpfd, 5) == -1 ||
bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
{
save = errno;
close(fd);
close(tcpfd);
errno = save;
return 0;
}
l = safe_malloc(sizeof(struct listener));
l->fd = fd;
l->tcpfd = tcpfd;
l->family = AF_INET6;
l->next = NULL;
*link = l;
return 1;
}
#endif
struct listener *create_wildcard_listeners(int port) struct listener *create_wildcard_listeners(int port)
{ {
#if !(defined(IP_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))) #if !(defined(IP_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)))
...@@ -227,10 +293,9 @@ struct listener *create_wildcard_listeners(int port) ...@@ -227,10 +293,9 @@ struct listener *create_wildcard_listeners(int port)
#else #else
union mysockaddr addr; union mysockaddr addr;
int opt = 1; int opt = 1;
struct listener *listen; struct listener *l, *l6 = NULL;
#ifdef HAVE_IPV6 int flags;
int fd; int tcpfd, fd;
#endif
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
addr.in.sin_addr.s_addr = INADDR_ANY; addr.in.sin_addr.s_addr = INADDR_ANY;
...@@ -238,94 +303,87 @@ struct listener *create_wildcard_listeners(int port) ...@@ -238,94 +303,87 @@ struct listener *create_wildcard_listeners(int port)
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(struct sockaddr_in); addr.in.sin_len = sizeof(struct sockaddr_in);
#endif #endif
listen = safe_malloc(sizeof(struct listener));
if ((listen->fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
return NULL;
if ((tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{ {
free(listen); close (fd);
return NULL; return NULL;
} }
if (setsockopt(listen->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
listen(tcpfd, 5) == -1 ||
(flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
#ifdef HAVE_IPV6
!create_ipv6_listener(&l6, port) ||
#endif
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
#if defined(IP_PKTINFO) #if defined(IP_PKTINFO)
setsockopt(listen->fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 || setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
setsockopt(listen->fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 || setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(listen->fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 || setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
#endif #endif
bind(listen->fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1) bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
{ {
close(listen->fd); close(fd);
free(listen); close(tcpfd);
return NULL; return NULL;
} }
listen->next = NULL;
listen->family = AF_INET;
#ifdef HAVE_IPV6
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(port);
addr.in6.sin6_flowinfo = htonl(0);
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
{
if (errno != EPROTONOSUPPORT &&
errno != EAFNOSUPPORT &&
errno != EINVAL)
{
close(listen->fd);
free(listen);
return NULL;
}
}
else
{
listen->next = safe_malloc(sizeof(struct listener));
listen->next->fd = fd;
listen->next->family = AF_INET6;
listen->next->next = NULL;
if (setsockopt(listen->next->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(listen->next->fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
bind(listen->next->fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
{
close(listen->next->fd);
free(listen->next);
close(listen->fd);
free(listen);
return NULL;
}
}
#endif
return listen;
l = safe_malloc(sizeof(struct listener));
l->family = AF_INET;
l->fd = fd;
l->tcpfd = tcpfd;
l->next = l6;
return l;
#endif #endif
} }
struct listener *create_bound_listeners(struct irec *interfaces) struct listener *create_bound_listeners(struct irec *interfaces, int port)
{ {
struct listener *listeners = NULL; struct listener *listeners = NULL;
struct irec *iface; struct irec *iface;
int opt = 1; int flags = port, opt = 1;
/* Create bound listeners only for IPv4, IPv6 always binds the wildcard */
for (iface = interfaces ;iface; iface = iface->next) #ifdef HAVE_IPV6
{ if (!create_ipv6_listener(&listeners, port))
struct listener *new = safe_malloc(sizeof(struct listener)); die("failed to to create listening socket: %s", NULL);
new->family = iface->addr.sa.sa_family; #endif
new->next = listeners;
listeners = new;
if ((new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1)
die("failed to create socket: %s", NULL);
if (setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
die("failed to bind socket: %s", NULL);
}
for (iface = interfaces ;iface; iface = iface->next)
if (iface->addr.sa.sa_family == AF_INET)
{
struct listener *new = safe_malloc(sizeof(struct listener));
new->family = iface->addr.sa.sa_family;
new->next = listeners;
listeners = new;
if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
(new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
/* See Stevens 16.6 */
(flags = fcntl(new->tcpfd, F_GETFL, 0)) == -1 ||
fcntl(new->tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
listen(new->tcpfd, 5) == -1)
die("failed to to create listening socket: %s", NULL);
}
return listeners; return listeners;
} }
static struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds) struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
{ {
struct serverfd *sfd; struct serverfd *sfd;
......
...@@ -21,7 +21,7 @@ struct myoption { ...@@ -21,7 +21,7 @@ struct myoption {
int val; int val;
}; };
#define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:" #define OPTSTRING "ZDNLERzowefnbvhdqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:"
static struct myoption opts[] = { static struct myoption opts[] = {
{"version", 0, 0, 'v'}, {"version", 0, 0, 'v'},
...@@ -72,6 +72,7 @@ static struct myoption opts[] = { ...@@ -72,6 +72,7 @@ static struct myoption opts[] = {
{"alias", 1, 0, 'V' }, {"alias", 1, 0, 'V' },
{"dhcp-vendorclass", 1, 0, 'U'}, {"dhcp-vendorclass", 1, 0, 'U'},
{"dhcp-userclass", 1, 0, 'j'}, {"dhcp-userclass", 1, 0, 'j'},
{"edns-packet-max", 1, 0, 'P'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
...@@ -132,6 +133,7 @@ static char *usage = ...@@ -132,6 +133,7 @@ static char *usage =
"-o, --strict-order Use nameservers strictly in the order given in " RESOLVFILE ".\n" "-o, --strict-order Use nameservers strictly in the order given in " RESOLVFILE ".\n"
"-O, --dhcp-option=<optspec> Set extra options to be set to DHCP clients.\n" "-O, --dhcp-option=<optspec> Set extra options to be set to DHCP clients.\n"
"-p, --port=number Specify port to listen for DNS requests on (defaults to 53).\n" "-p, --port=number Specify port to listen for DNS requests on (defaults to 53).\n"
"-P, --edns-packet-max=<size> Maximum supported UDP packet size for EDNS.0 (defaults to %d).\n"
"-q, --log-queries Log queries.\n" "-q, --log-queries Log queries.\n"
"-Q, --query-port=number Force the originating port for upstream queries.\n" "-Q, --query-port=number Force the originating port for upstream queries.\n"
"-R, --no-resolv Do NOT read resolv.conf.\n" "-R, --no-resolv Do NOT read resolv.conf.\n"
...@@ -143,7 +145,7 @@ static char *usage = ...@@ -143,7 +145,7 @@ static char *usage =
"-T, --local-ttl=time Specify time-to-live in seconds for replies from /etc/hosts.\n" "-T, --local-ttl=time Specify time-to-live in seconds for replies from /etc/hosts.\n"
"-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n" "-u, --user=username Change to this user after startup. (defaults to " CHUSER ").\n"
"-U, --dhcp-vendorclass=<id>,<class> Map DHCP vendor class to option set.\n" "-U, --dhcp-vendorclass=<id>,<class> Map DHCP vendor class to option set.\n"
"-v, --version Display dnsmasq version.\n" "-v, --version Display dnsmasq version and copyright information.\n"
"-V, --alias=addr,addr,mask Translate IPv4 addresses from upstream servers.\n" "-V, --alias=addr,addr,mask Translate IPv4 addresses from upstream servers.\n"
"-w, --help Display this message.\n" "-w, --help Display this message.\n"
"-x, --pid-file=path Specify path of PID file. (defaults to " RUNFILE ").\n" "-x, --pid-file=path Specify path of PID file. (defaults to " RUNFILE ").\n"
...@@ -161,7 +163,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso ...@@ -161,7 +163,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
int *query_port, unsigned long *local_ttl, char **addn_hosts, struct dhcp_context **dhcp, int *query_port, unsigned long *local_ttl, char **addn_hosts, struct dhcp_context **dhcp,
struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, struct dhcp_vendor **dhcp_vendors, char **dhcp_file, struct dhcp_config **dhcp_conf, struct dhcp_opt **dhcp_opts, struct dhcp_vendor **dhcp_vendors, char **dhcp_file,
char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max, char **dhcp_sname, struct in_addr *dhcp_next_server, int *dhcp_max,
unsigned int *min_leasetime, struct doctor **doctors) unsigned int *min_leasetime, struct doctor **doctors, unsigned short *edns_pktsz)
{ {
int option = 0, i; int option = 0, i;
unsigned int flags = 0; unsigned int flags = 0;
...@@ -256,13 +258,16 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso ...@@ -256,13 +258,16 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
if (!f && option == 'w') if (!f && option == 'w')
{ {
fprintf (stderr, usage, CACHESIZ, MAXLEASES); fprintf (stderr, usage, CACHESIZ, EDNS_PKTSZ, MAXLEASES);
exit(0); exit(0);
} }
if (!f && option == 'v') if (!f && option == 'v')
{ {
fprintf(stderr, "dnsmasq version %s\n", VERSION); fprintf(stderr, "Dnsmasq version %s %s\n\n", VERSION, COPYRIGHT);
fprintf(stderr, "This software comes with ABSOLUTELY NO WARRANTY.\n");
fprintf(stderr, "Dnsmasq is free software, and you are welcome to redistribute it\n");
fprintf(stderr, "under the terms of the GNU General Public License, version 2.\n");
exit(0); exit(0);
} }
...@@ -658,6 +663,15 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso ...@@ -658,6 +663,15 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
option = '?'; option = '?';
break; break;
case 'P':
{
int i;
if (!atoi_check(optarg, &i))
option = '?';
*edns_pktsz = (unsigned short)i;
break;
}
case 'Q': case 'Q':
if (!atoi_check(optarg, query_port)) if (!atoi_check(optarg, query_port))
option = '?'; option = '?';
...@@ -685,7 +699,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso ...@@ -685,7 +699,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
struct dhcp_context *new = safe_malloc(sizeof(struct dhcp_context)); struct dhcp_context *new = safe_malloc(sizeof(struct dhcp_context));
new->next = *dhcp; new->next = *dhcp;
new->lease_time = DEFLEASE; new->lease_time = DEFLEASE;
new->addr_epoch = 0;
new->netmask.s_addr = 0; new->netmask.s_addr = 0;
new->broadcast.s_addr = 0; new->broadcast.s_addr = 0;
new->netid.net = NULL; new->netid.net = NULL;
......
This diff is collapsed.
...@@ -105,9 +105,7 @@ int dhcp_reply(struct dhcp_context *context, ...@@ -105,9 +105,7 @@ int dhcp_reply(struct dhcp_context *context,
struct in_addr addr; struct in_addr addr;
unsigned short fuzz = 0; unsigned short fuzz = 0;
if (mess->op != BOOTREQUEST || if (mess->op != BOOTREQUEST || mess->cookie != htonl(DHCP_COOKIE))
mess->hlen != ETHER_ADDR_LEN ||
mess->cookie != htonl(DHCP_COOKIE))
return 0; return 0;
/* Token ring is supported when we have packet sockets /* Token ring is supported when we have packet sockets
...@@ -116,14 +114,19 @@ int dhcp_reply(struct dhcp_context *context, ...@@ -116,14 +114,19 @@ int dhcp_reply(struct dhcp_context *context,
token ring hwaddrs are the same size as ethernet hwaddrs. */ token ring hwaddrs are the same size as ethernet hwaddrs. */
#ifdef HAVE_BPF #ifdef HAVE_BPF
if (mess->htype != ARPHRD_ETHER) if (mess->htype != ARPHRD_ETHER)
return 0;
#else #else
if (mess->htype != ARPHRD_ETHER && if (mess->htype != ARPHRD_ETHER && mess->htype != ARPHRD_IEEE802)
mess->htype != ARPHRD_IEEE802)
return 0;
#endif #endif
{
syslog(LOG_WARNING, "DHCP request for unsupported hardware type (%d) recieved on %s",
mess->htype, iface_name);
return 0;
}
if (mess->hlen != ETHER_ADDR_LEN)
return 0;
mess->op = BOOTREPLY; mess->op = BOOTREPLY;
if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE))) if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE)))
...@@ -317,6 +320,9 @@ int dhcp_reply(struct dhcp_context *context, ...@@ -317,6 +320,9 @@ int dhcp_reply(struct dhcp_context *context,
syslog(LOG_WARNING, "disabling DHCP static address %s", inet_ntoa(config->addr)); syslog(LOG_WARNING, "disabling DHCP static address %s", inet_ntoa(config->addr));
config->flags &= ~CONFIG_ADDR ; config->flags &= ~CONFIG_ADDR ;
} }
else
/* make sure this host gets a different address next time. */
context->addr_epoch++;
return 0; return 0;
...@@ -335,18 +341,16 @@ int dhcp_reply(struct dhcp_context *context, ...@@ -335,18 +341,16 @@ int dhcp_reply(struct dhcp_context *context,
case DHCPDISCOVER: case DHCPDISCOVER:
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP))) if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
addr = option_addr(opt); addr = option_addr(opt);
if (have_config(config, CONFIG_DISABLE)) if (have_config(config, CONFIG_DISABLE))
message = "ignored"; message = "ignored";
else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr)) else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr))
mess->yiaddr = config->addr; mess->yiaddr = config->addr;
else if (lease && is_same_net(lease->addr, context->start, context->netmask)) else if (lease && address_available(context, lease->addr))
mess->yiaddr = lease->addr; mess->yiaddr = lease->addr;
else if (opt && address_available(context, addr)) else if (opt && address_available(context, addr) && !lease_find_by_addr(addr))
mess->yiaddr = addr; mess->yiaddr = addr;
else if (!address_allocate(context, dhcp_configs, &mess->yiaddr, mess->chaddr)) else if (!address_allocate(context, dhcp_configs, &mess->yiaddr, mess->chaddr))
message = "no address available"; message = "no address available";
log_packet("DISCOVER", opt ? &addr : NULL, mess->chaddr, iface_name, message); log_packet("DISCOVER", opt ? &addr : NULL, mess->chaddr, iface_name, message);
if (message) if (message)
...@@ -393,12 +397,10 @@ int dhcp_reply(struct dhcp_context *context, ...@@ -393,12 +397,10 @@ int dhcp_reply(struct dhcp_context *context,
lease_prune(lease, now); lease_prune(lease, now);
lease = NULL; lease = NULL;
} }
/* accept addresses in the dynamic range or ones allocated statically to
particular hosts or an address which the host already has. */
if (!lease) if (!lease)
{ {
if (!address_available(context, mess->yiaddr) && if ((!address_available(context, mess->yiaddr) || lease_find_by_addr(mess->yiaddr)) &&
(!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr)) (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
message = "address unavailable"; message = "address unavailable";
else if (!(lease = lease_allocate(clid, clid_len, mess->yiaddr))) else if (!(lease = lease_allocate(clid, clid_len, mess->yiaddr)))
...@@ -425,7 +427,20 @@ int dhcp_reply(struct dhcp_context *context, ...@@ -425,7 +427,20 @@ int dhcp_reply(struct dhcp_context *context,
/* If a machine moves networks whilst it has a lease, we catch that here. */ /* If a machine moves networks whilst it has a lease, we catch that here. */
if (!message && !is_same_net(mess->yiaddr, context->start, context->netmask)) if (!message && !is_same_net(mess->yiaddr, context->start, context->netmask))
message = "wrong network"; message = "wrong network";
/* Check for renewal of a lease which is now outside the allowed range. */
if (!message && !address_available(context, mess->yiaddr) &&
(!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
message = "address no longer available";
/* Check if a new static address has been configured. Be very sure that
when the client does DISCOVER, it will get the static address, otherwise
an endless protocol loop will ensue. */
if (!message && have_config(config, CONFIG_ADDR) &&
!have_config(config, CONFIG_DISABLE) &&
!lease_find_by_addr(config->addr))
message = "static lease available";
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL); log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
if (message) if (message)
......
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