Commit 8ef5ada2 authored by Simon Kelley's avatar Simon Kelley

import of dnsmasq-2.53.tar.gz

parent 316e2730
version 2.53
Fix failure to compile on Debian/kFreeBSD. Thanks to
Axel Beckert and Petr Salinger.
Fix code to avoid scary strict-aliasing warnings
generated by gcc 4.4.
Added FAQ entry warning about DHCP failures with Vista
when firewalls block 255.255.255.255.
Fixed bug which caused bad things to happen if a
resolv.conf file which exists is subsequently removed.
Thanks to Nikolai Saoukh for the patch.
Rationalised the DHCP tag system. Every configuration item
which can set a tag does so by adding "set:<tag>" and
every configuration item which is conditional on a tag is
made so by "tag:<tag>". The NOT operator changes to '!',
which is a bit more intuitive too. Dhcp-host directives
can set more than one tag now. The old '#' NOT,
"net:" prefix and no-prefixes are still honoured, so
no existing config file needs to be changed, but
the documentation and new-style config files should be
much less confusing.
Added --tag-if to allow boolean operations on tags.
This allows complicated logic to be clearer and more
general. A great suggestion from Richard Voigt.
Add broadcast/unicast information to DHCP logging.
Allow --dhcp-broadcast to be unconditional.
Fixed incorrect behaviour with NOT <tag> conditionals in
dhcp-options. Thanks to Max Turkewitz for assistance
finding this.
If we send vendor-class encapsulated options based on the
vendor-class supplied by the client, and no explicit
vendor-class option is given, echo back the vendor-class
from the client.
Fix bug which stopped dnsmasq from matching both a
circuitid and a remoteid. Thanks to Ignacio Bravo for
finding this.
Add --dhcp-proxy, which makes it possible to configure
dnsmasq to use a DHCP relay agent as a full proxy, with
all DHCP messages passing through the proxy. This is
useful if the relay adds extra information to the packets
it forwards, but cannot be configured with the RFC 5107
server-override option.
Added interface:<iface name> part to dhcp-range. The
semantics of this are very odd at first sight, but it
allows a single line of the form
dhcp-range=interface:virt0,192.168.0.4,192.168.0.200
to be added to dnsmasq configuration which then supplies
DHCP and DNS services to that interface, without affecting
what services are supplied to other interfaces and
irrespective of the existance or lack of
interface=<interface>
lines elsewhere in the dnsmasq configuration. The idea is
that such a line can be added automatically by libvirt
or equivalent systems, without disturbing any manual
configuration.
Similarly to the above, allow --enable-tftp=<interface>
Allow a TFTP root to be set separately for requests via
different interfaces, --tftp-root=<path>,<interface>
Correctly handle and log clashes between CNAMES and
DNS names being given to DHCP leases. This fixes a bug
which caused nonsense IP addresses to be logged. Thanks to
Sergei Zhirikov for finding and analysing the problem.
Tweak flush_log so as to avoid leaving the log
file in non-blocking mode. O_NONBLOCK is a property of the
file, not the process/descriptor.
Fix contrib/Solaris10/create_package
(/usr/man -> /usr/share/man) Thanks to Vita Batrla.
Fix a problem where, if a client got a lease, then went
to another subnet and got another lease, then moved back,
it couldn't resume the old lease, but would instead get
a new address. Thanks to Leonardo Rodrigues for spotting
this and testing the fix.
Fix weird bug which sometimes omitted certain characters
from the start of quoted strings in dhcp-options. Thanks
to Dayton Turner for spotting the problem.
Add facility to redirect some domains to the standard
upstream servers: this allows something like
--server=/google.com/1.2.3.4 --server=/www.google.com/#
which will send queries for *.google.com to 1.2.3.4,
except *www.google.com which will be forwarded as usual.
Thanks to AJ Weber for prompting this addition.
Improve the hash-algorithm used to generate IP addresses
from MAC addresses during initial DHCP address
allocation. This improves performance when large numbers
of hosts with similar MAC addresses all try and get an IP
address at the same time. Thanks to Paul Smith for his
work on this.
Tweak DHCP code so that --bridge-interface can be used to
select which IP alias of an interface should be used for
DHCP purposes on Linux. If eth0 has an alias eth0:dhcp
then adding --bridge-interface=eth0:dhcp,eth0 will use
the address of eth0:dhcp to determine the correct subnet
for DHCP address allocation. Thanks to Pawel Golaszewski
for prompting this and Eric Cooper for further testing.
Add --dhcp-generate-names. Suggestion by Ferenc Wagner.
Tweak DNS server selection algorithm when there is more
than one server available for a domain, eg.
--server=/mydomain/1.1.1.1
--server=/mydomain/2.2.2.2
Thanks to Alberto Cuesta-Canada for spotting a weakness
here.
Add --max-ttl. Thanks to Fredrik Ringertz for the patch.
Allow --log-facility=- to force all logging to
stderr. Suggestion from Clemens Fischer.
Fix regression which caused configuration like
--address=/.domain.com/1.2.3.4 to be rejected. The dot to the
left of the domain has been implied and not required for a
long time, but it should be accepted for backward
compatibility. Thanks to Andrew Burcin for spotting this.
Add --rebind-domain-ok and --rebind-localhost-ok.
Suggestion from Clemens Fischer.
Log replies to queries of type TXT, when --log-queries
is set.
Fix compiler warnings when compiled with -DNO_DHCP. Thanks
to Shantanu Gadgil for the patch.
Updated French translation. Thanks to Gildas Le Nadan.
Updated Polish translation. Thanks to Jan Psota.
Updated German translation. Thanks to Matthias Andree.
Added contrib/static-arp, thanks to Darren Hoo.
Fix corruption of the domain when a name from /etc/hosts
overrides one supplied by a DHCP client. Thanks to Fedor
Kozhevnikov for spotting the problem.
Updated Spanish translation. Thanks to Chris Chatham.
version 2.52 version 2.52
Work around a Linux kernel bug which insists that the Work around a Linux kernel bug which insists that the
length of the option passed to setsockopt must be at least length of the option passed to setsockopt must be at least
...@@ -81,7 +241,7 @@ version 2.52 ...@@ -81,7 +241,7 @@ version 2.52
reconfigured using --edns-packet-max if needed. Thanks to reconfigured using --edns-packet-max if needed. Thanks to
Francis Dupont for pointing this out. Francis Dupont for pointing this out.
Rewrite query-ids even for DNSSEC signed packets, since Rewrite query-ids even for TSIG signed packets, since
this is allowed by RFC5625 section 4.5. this is allowed by RFC5625 section 4.5.
Use getopt_long by default on OS X. It has been supported Use getopt_long by default on OS X. It has been supported
...@@ -101,7 +261,12 @@ version 2.52 ...@@ -101,7 +261,12 @@ version 2.52
Updated Spanish translation. Thanks to Chris Chatham. Updated Spanish translation. Thanks to Chris Chatham.
Fixed confusion about domains, when looking up DHCP hosts
in /etc/hosts. This could cause spurious "Ignoring
domain..." messages. Thanks to Fedor Kozhevnikov for
finding and analysing the problem.
version 2.51 version 2.51
Add support for internationalised DNS. Non-ASCII characters Add support for internationalised DNS. Non-ASCII characters
in domain names found in /etc/hosts, /etc/ethers and in domain names found in /etc/hosts, /etc/ethers and
......
...@@ -456,6 +456,16 @@ A: In almost all cases: none. If you have the normal arrangement with ...@@ -456,6 +456,16 @@ A: In almost all cases: none. If you have the normal arrangement with
and turn on syslog-ng's dns-cache function. and turn on syslog-ng's dns-cache function.
Q: DHCP doesn't work with windows Vista, but everything else is fine.
A: The DHCP client on windows Vista (and possibly later versions)
demands that the DHCP server send replies as broadcasts. Most other
clients don't do this. The broadcasts are send to
255.255.255.255. A badly configured firewall which blocks such
packets will show exactly these symptoms (Vista fails, others
work).
......
Hi Simon,
I just wanted to let you know that I have built a Solaris .pkg install package of your dnsmasq utility for people to use. Feel free to point them in my direction if you have people who want this sort of thing.
http://ejesconsulting.wordpress.com/2010/05/12/gnu-dnsmasq-for-opensolaris-sparc/
Thanks
-evan
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# #
BIN_DIR="/usr/sbin" BIN_DIR="/usr/sbin"
CONF_DIR="/etc" CONF_DIR="/etc"
MAN_DIR="/usr/man/man8" MAN_DIR="/usr/share/man/man8"
PACKAGE_NAME="dnsmasq" PACKAGE_NAME="dnsmasq"
......
#!/bin/sh
# Contributed by Darren Hoo <darren.hoo@gmail.com>
# If you use dnsmasq as DHCP server on a router, you may have
# met with attackers trying ARP Poison Routing (APR) on your
# local area network. This script will setup a 'permanent' entry
# in the router's ARP table upon each DHCP transaction so as to
# make the attacker's efforts less successful.
# Usage:
# edit /etc/dnsmasq.conf and specify the path of this script
# to dhcp-script, for example:
# dhcp-script=/usr/sbin/static-arp
# if $1 is add or old, update the static arp table entry.
# if $1 is del, then delete the entry from the table
# if $1 is init which is called by dnsmasq at startup, it's ignored
ARP=/usr/sbin/arp
# Arguments.
# $1 is action (add, del, old)
# $2 is MAC
# $3 is address
# $4 is hostname (optional, may be unset)
if [ ${1} = del ] ; then
${ARP} -d $3
fi
if [ ${1} = old ] || [ ${1} = add ] ; then
${ARP} -s $3 $2
fi
...@@ -66,12 +66,12 @@ ...@@ -66,12 +66,12 @@
# You can control how dnsmasq talks to a server: this forces # You can control how dnsmasq talks to a server: this forces
# queries to 10.1.2.3 to be routed via eth1 # queries to 10.1.2.3 to be routed via eth1
# --server=10.1.2.3@eth1 # server=10.1.2.3@eth1
# and this sets the source (ie local) address used to talk to # and this sets the source (ie local) address used to talk to
# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that # 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
# IP on the machine, obviously). # IP on the machine, obviously).
# --server=10.1.2.3@192.168.1.1#55 # server=10.1.2.3@192.168.1.1#55
# If you want dnsmasq to change uid and gid to something other # If you want dnsmasq to change uid and gid to something other
# than the default, edit the following lines. # than the default, edit the following lines.
...@@ -141,10 +141,22 @@ ...@@ -141,10 +141,22 @@
# don't need to worry about this. # don't need to worry about this.
#dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h #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 # This is an example of a DHCP range which sets a tag, so that
# some DHCP options may be set only for this network. # some DHCP options may be set only for this network.
#dhcp-range=red,192.168.0.50,192.168.0.150 #dhcp-range=set:red,192.168.0.50,192.168.0.150
# Use this DHCP range only when the tag "green" is set.
#dhcp-range=tag:green,192.168.0.50,192.168.0.150,12h
# Specify a subnet which can't be used for dynamic address allocation,
# is available for hosts with matching --dhcp-host lines. Note that
# dhcp-host declarations will be ignored unless there is a dhcp-range
# of some type for the subnet in question.
# In this case the netmask is implied (it comes from the network
# configuration on the machine running dnsmasq) it is possible to give
# an explict netmask instead.
#dhcp-range=192.168.0.0,static
# 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
...@@ -200,29 +212,29 @@ ...@@ -200,29 +212,29 @@
# Send extra options which are tagged as "red" to # Send extra options which are tagged as "red" to
# the machine with ethernet address 11:22:33:44:55:66 # the machine with ethernet address 11:22:33:44:55:66
#dhcp-host=11:22:33:44:55:66,net:red #dhcp-host=11:22:33:44:55:66,set:red
# Send extra options which are tagged as "red" to # Send extra options which are tagged as "red" to
# any machine with ethernet address starting 11:22:33: # any machine with ethernet address starting 11:22:33:
#dhcp-host=11:22:33:*:*:*,net:red #dhcp-host=11:22:33:*:*:*,set:red
# Ignore any clients which are specified in dhcp-host lines # Ignore any clients which are specified in dhcp-host lines
# or /etc/ethers. Equivalent to ISC "deny unkown-clients". # or /etc/ethers. Equivalent to ISC "deny unkown-clients".
# This relies on the special "known" tag which is set when # This relies on the special "known" tag which is set when
# a host is matched. # a host is matched.
#dhcp-ignore=#known #dhcp-ignore=tag:!known
# Send extra options which are tagged as "red" to any machine whose # Send extra options which are tagged as "red" to any machine whose
# DHCP vendorclass string includes the substring "Linux" # DHCP vendorclass string includes the substring "Linux"
#dhcp-vendorclass=red,Linux #dhcp-vendorclass=set:red,Linux
# Send extra options which are tagged as "red" to any machine one # Send extra options which are tagged as "red" to any machine one
# of whose DHCP userclass strings includes the substring "accounts" # of whose DHCP userclass strings includes the substring "accounts"
#dhcp-userclass=red,accounts #dhcp-userclass=set:red,accounts
# Send extra options which are tagged as "red" to any machine whose # Send extra options which are tagged as "red" to any machine whose
# MAC address matches the pattern. # MAC address matches the pattern.
#dhcp-mac=red,00:60:8C:*:*:* #dhcp-mac=set:red,00:60:8C:*:*:*
# If this line is uncommented, dnsmasq will read /etc/ethers and act # If this line is uncommented, dnsmasq will read /etc/ethers and act
# on the ethernet-address/IP pairs found there just as if they had # on the ethernet-address/IP pairs found there just as if they had
...@@ -276,8 +288,8 @@ ...@@ -276,8 +288,8 @@
# Specify an option which will only be sent to the "red" network # Specify an option which will only be sent to the "red" network
# (see dhcp-range for the declaration of the "red" network) # (see dhcp-range for the declaration of the "red" network)
# Note that the net: part must precede the option: part. # Note that the tag: part must precede the option: part.
#dhcp-option = net:red, option:ntp-server, 192.168.1.1 #dhcp-option = tag:red, option:ntp-server, 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
...@@ -338,8 +350,8 @@ ...@@ -338,8 +350,8 @@
# Boot for Etherboot gPXE. The idea is to send two different # Boot for Etherboot gPXE. The idea is to send two different
# filenames, the first loads gPXE, and the second tells gPXE what to # filenames, the first loads gPXE, and the second tells gPXE what to
# load. The dhcp-match sets the gpxe tag for requests from gPXE. # load. The dhcp-match sets the gpxe tag for requests from gPXE.
#dhcp-match=gpxe,175 # gPXE sends a 175 option. #dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
#dhcp-boot=net:#gpxe,undionly.kpxe #dhcp-boot=tag:!gpxe,undionly.kpxe
#dhcp-boot=mybootimage #dhcp-boot=mybootimage
# Encapsulated options for Etherboot gPXE. All the options are # Encapsulated options for Etherboot gPXE. All the options are
...@@ -490,11 +502,11 @@ ...@@ -490,11 +502,11 @@
# set for this to work.) # set for this to work.)
# A SRV record sending LDAP for the example.com domain to # A SRV record sending LDAP for the example.com domain to
# ldapserver.example.com port 289 # ldapserver.example.com port 389
#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389 #srv-host=_ldap._tcp.example.com,ldapserver.example.com,389
# A SRV record sending LDAP for the example.com domain to # A SRV record sending LDAP for the example.com domain to
# ldapserver.example.com port 289 (using domain=) # ldapserver.example.com port 389 (using domain=)
#domain=example.com #domain=example.com
#srv-host=_ldap._tcp,ldapserver.example.com,389 #srv-host=_ldap._tcp,ldapserver.example.com,389
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1045,7 +1045,14 @@ void cache_add_dhcp_entry(char *host_name, ...@@ -1045,7 +1045,14 @@ void cache_add_dhcp_entry(char *host_name,
/* check all addresses associated with name */ /* check all addresses associated with name */
if (crec->flags & F_HOSTS) if (crec->flags & F_HOSTS)
{ {
if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr) /* if in hosts, don't need DHCP record */
in_hosts = 1;
if (crec->flags & F_CNAME)
my_syslog(LOG_WARNING,
_("%s is a CNAME, not giving it to the DHCP lease of %s"),
host_name, inet_ntoa(*host_address));
else if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
{ {
strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4)); strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
my_syslog(LOG_WARNING, my_syslog(LOG_WARNING,
...@@ -1053,11 +1060,7 @@ void cache_add_dhcp_entry(char *host_name, ...@@ -1053,11 +1060,7 @@ void cache_add_dhcp_entry(char *host_name,
"the name exists in %s with address %s"), "the name exists in %s with address %s"),
host_name, inet_ntoa(*host_address), host_name, inet_ntoa(*host_address),
record_source(crec->uid), daemon->namebuff); record_source(crec->uid), daemon->namebuff);
return; }
}
else
/* if in hosts, don't need DHCP record */
in_hosts = 1;
} }
else if (!(crec->flags & F_DHCP)) else if (!(crec->flags & F_DHCP))
{ {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define VERSION "2.52" #define VERSION "2.54"
#define FTABSIZ 150 /* max number of outstanding requests (default) */ #define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */ #define MAX_PROCS 20 /* max no children for TCP requests */
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */ #define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */ #define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define FORWARD_TEST 50 /* try all servers every 50 queries */ #define FORWARD_TEST 50 /* try all servers every 50 queries */
#define FORWARD_TIME 10 /* or 10 seconds */ #define FORWARD_TIME 20 /* or 10 seconds */
#define RANDOM_SOCKS 64 /* max simultaneous random ports */ #define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */ #define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */ #define CACHESIZ 150 /* default cache size */
...@@ -230,13 +230,13 @@ NOTES: ...@@ -230,13 +230,13 @@ NOTES:
#elif defined(__FreeBSD__) || \ #elif defined(__FreeBSD__) || \
defined(__OpenBSD__) || \ defined(__OpenBSD__) || \
defined(__DragonFly__) || \ defined(__DragonFly__) || \
defined (__FreeBSD_kernel__) defined(__FreeBSD_kernel__)
#define HAVE_BSD_NETWORK #define HAVE_BSD_NETWORK
/* Later verions of FreeBSD have getopt_long() */ /* Later verions of FreeBSD have getopt_long() */
#if defined(optional_argument) && defined(required_argument) #if defined(optional_argument) && defined(required_argument)
# define HAVE_GETOPT_LONG # define HAVE_GETOPT_LONG
#endif #endif
#if !defined (__FreeBSD_kernel__) #if !defined(__FreeBSD_kernel__)
# define HAVE_ARC4RANDOM # define HAVE_ARC4RANDOM
#endif #endif
#define HAVE_SOCKADDR_SA_LEN #define HAVE_SOCKADDR_SA_LEN
......
...@@ -127,7 +127,10 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -127,7 +127,10 @@ void dhcp_packet(time_t now, int pxe_fd)
int iface_index = 0, unicast_dest = 0, is_inform = 0; int iface_index = 0, unicast_dest = 0, is_inform = 0;
struct in_addr iface_addr, *addrp = NULL; struct in_addr iface_addr, *addrp = NULL;
struct iface_param parm; struct iface_param parm;
#ifdef HAVE_LINUX_NETWORK
struct arpreq arp_req;
#endif
union { union {
struct cmsghdr align; /* this ensures alignment */ struct cmsghdr align; /* this ensures alignment */
#if defined(HAVE_LINUX_NETWORK) #if defined(HAVE_LINUX_NETWORK)
...@@ -189,8 +192,13 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -189,8 +192,13 @@ void dhcp_packet(time_t now, int pxe_fd)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
{ {
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex; union {
if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST) unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
iface_index = p.p->ipi_ifindex;
if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
unicast_dest = 1; unicast_dest = 1;
} }
...@@ -198,20 +206,37 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -198,20 +206,37 @@ void dhcp_packet(time_t now, int pxe_fd)
if (msg.msg_controllen >= sizeof(struct cmsghdr)) if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index; {
union {
unsigned char *c;
struct sockaddr_dl *s;
} p;
p.c = CMSG_DATA(cmptr);
iface_index = p.s->sdl_index;
}
#elif defined(HAVE_SOLARIS_NETWORK) #elif defined(HAVE_SOLARIS_NETWORK)
if (msg.msg_controllen >= sizeof(struct cmsghdr)) if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
iface_index = *((unsigned int *)CMSG_DATA(cmptr)); {
union {
unsigned char *c;
unsigned int *i;
} p;
p.c = CMSG_DATA(cmptr);
iface_index = *(p.i);
}
#endif #endif
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name)) if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
return; return;
#ifdef HAVE_LINUX_NETWORK
/* ARP fiddling uses original interface even if we pretend to use a different one. */
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
#endif
#ifdef MSG_BCAST #ifdef MSG_BCAST
/* OpenBSD tells us when a packet was broadcast */ /* OpenBSD tells us when a packet was broadcast */
if (!(msg.msg_flags & MSG_BCAST)) if (!(msg.msg_flags & MSG_BCAST))
...@@ -231,18 +256,14 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -231,18 +256,14 @@ void dhcp_packet(time_t now, int pxe_fd)
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return; return;
/* interface may have been changed by alias in iface_check */ /* weird libvirt-inspired access control */
if (!addrp) for (context = daemon->dhcp; context; context = context->next)
{ if (!context->interface || strcmp(context->interface, ifr.ifr_name) == 0)
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1) break;
{
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name); if (!context)
return; return;
}
else
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
}
/* unlinked contexts are marked by context->current == context */ /* unlinked contexts are marked by context->current == context */
for (context = daemon->dhcp; context; context = context->next) for (context = daemon->dhcp; context; context = context->next)
...@@ -253,6 +274,27 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -253,6 +274,27 @@ void dhcp_packet(time_t now, int pxe_fd)
parm.current = NULL; parm.current = NULL;
parm.ind = iface_index; parm.ind = iface_index;
/* interface may have been changed by alias in iface_check, make sure it gets priority in case
there is more than one address on the interface in the same subnet */
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1)
{
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
return;
}
else
{
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
if (ioctl(daemon->dhcpfd, SIOCGIFNETMASK, &ifr) != -1)
{
struct in_addr netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
if (ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) != -1)
{
struct in_addr broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
complete_context(iface_addr, iface_index, netmask, broadcast, &parm);
}
}
}
if (!iface_enumerate(&parm, complete_context, NULL)) if (!iface_enumerate(&parm, complete_context, NULL))
return; return;
lease_prune(NULL, now); /* lose any expired leases */ lease_prune(NULL, now); /* lose any expired leases */
...@@ -324,15 +366,14 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -324,15 +366,14 @@ void dhcp_packet(time_t now, int pxe_fd)
{ {
/* unicast to unconfigured client. Inject mac address direct into ARP cache. /* unicast to unconfigured client. Inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */ struct sockaddr limits size to 14 bytes. */
struct arpreq req;
dest.sin_addr = mess->yiaddr; dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port); dest.sin_port = htons(daemon->dhcp_client_port);
*((struct sockaddr_in *)&req.arp_pa) = dest; memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
req.arp_ha.sa_family = mess->htype; arp_req.arp_ha.sa_family = mess->htype;
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen); memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
strncpy(req.arp_dev, ifr.ifr_name, 16); /* interface name already copied in */
req.arp_flags = ATF_COM; arp_req.arp_flags = ATF_COM;
ioctl(daemon->dhcpfd, SIOCSARP, &req); ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
} }
#elif defined(HAVE_SOLARIS_NETWORK) #elif defined(HAVE_SOLARIS_NETWORK)
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER) else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
...@@ -491,13 +532,15 @@ struct dhcp_context *narrow_context(struct dhcp_context *context, ...@@ -491,13 +532,15 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
if (!(tmp = address_available(context, taddr, netids))) if (!(tmp = address_available(context, taddr, netids)))
{ {
for (tmp = context; tmp; tmp = tmp->current) for (tmp = context; tmp; tmp = tmp->current)
if (is_same_net(taddr, tmp->start, tmp->netmask) && if (match_netid(tmp->filter, netids, 1) &&
is_same_net(taddr, tmp->start, tmp->netmask) &&
(tmp->flags & CONTEXT_STATIC)) (tmp->flags & CONTEXT_STATIC))
break; break;
if (!tmp) if (!tmp)
for (tmp = context; tmp; tmp = tmp->current) for (tmp = context; tmp; tmp = tmp->current)
if (is_same_net(taddr, tmp->start, tmp->netmask)) if (match_netid(tmp->filter, netids, 1) &&
is_same_net(taddr, tmp->start, tmp->netmask))
break; break;
} }
...@@ -530,7 +573,8 @@ int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotnee ...@@ -530,7 +573,8 @@ int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotnee
for (; check; check = check->next) for (; check; check = check->next)
{ {
if (check->net[0] != '#') /* '#' for not is for backwards compat. */
if (check->net[0] != '!' && check->net[0] != '#')
{ {
for (tmp1 = pool; tmp1; tmp1 = tmp1->next) for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
if (strcmp(check->net, tmp1->net) == 0) if (strcmp(check->net, tmp1->net) == 0)
...@@ -546,6 +590,22 @@ int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotnee ...@@ -546,6 +590,22 @@ int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotnee
return 1; return 1;
} }
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
{
struct tag_if *exprs;
struct dhcp_netid_list *list;
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
if (match_netid(exprs->tag, tags, 1))
for (list = exprs->set; list; list = list->next)
{
list->list->next = tags;
tags = list->list;
}
return tags;
}
int address_allocate(struct dhcp_context *context, int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len, struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now) struct dhcp_netid *netids, time_t now)
...@@ -559,9 +619,10 @@ int address_allocate(struct dhcp_context *context, ...@@ -559,9 +619,10 @@ int address_allocate(struct dhcp_context *context,
int i, pass; int i, pass;
unsigned int j; unsigned int j;
/* hash hwaddr */ /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
dispersal even with similarly-valued "strings". */
for (j = 0, i = 0; i < hw_len; i++) for (j = 0, i = 0; i < hw_len; i++)
j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16); j += hwaddr[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= 1; pass++) for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current) for (c = context; c; c = c->current)
...@@ -977,29 +1038,40 @@ void dhcp_update_configs(struct dhcp_config *configs) ...@@ -977,29 +1038,40 @@ void dhcp_update_configs(struct dhcp_config *configs)
/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
for this address. If it has a domain part, that must match the set domain and for this address. If it has a domain part, that must match the set domain and
it gets stripped. The set of legal domain names is bigger than the set of legal hostnames it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
so check here that the domain name is legal as a hostname. */ so check here that the domain name is legal as a hostname.
NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */
char *host_from_dns(struct in_addr addr) char *host_from_dns(struct in_addr addr)
{ {
struct crec *lookup; struct crec *lookup;
char *hostname = NULL;
char *d1, *d2;
if (daemon->port == 0) if (daemon->port == 0)
return NULL; /* DNS disabled. */ return NULL; /* DNS disabled. */
lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4); lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
if (lookup && (lookup->flags & F_HOSTS)) if (lookup && (lookup->flags & F_HOSTS))
{ {
hostname = daemon->dhcp_buff; char *dot, *hostname = cache_get_name(lookup);
strncpy(hostname, cache_get_name(lookup), 256); dot = strchr(hostname, '.');
hostname[255] = 0;
d1 = strip_hostname(hostname); if (dot && strlen(dot+1) != 0)
d2 = get_domain(addr); {
if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2)))) char *d2 = get_domain(addr);
hostname = NULL; if (!d2 || !hostname_isequal(dot+1, d2))
return NULL; /* wrong domain */
}
if (!legal_hostname(hostname))
return NULL;
strncpy(daemon->dhcp_buff, hostname, 256);
daemon->dhcp_buff[255] = 0;
strip_hostname(daemon->dhcp_buff);
return daemon->dhcp_buff;
} }
return hostname; return NULL;
} }
/* return domain or NULL if none. */ /* return domain or NULL if none. */
......
...@@ -63,7 +63,6 @@ static void check_dns_listeners(fd_set *set, time_t now); ...@@ -63,7 +63,6 @@ static void check_dns_listeners(fd_set *set, time_t now);
static void sig_handler(int sig); static void sig_handler(int sig);
static void async_event(int pipe, time_t now); static void async_event(int pipe, time_t now);
static void fatal_event(struct event_desc *ev); static void fatal_event(struct event_desc *ev);
static void poll_resolv(void);
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
...@@ -142,7 +141,7 @@ int main (int argc, char **argv) ...@@ -142,7 +141,7 @@ int main (int argc, char **argv)
#endif #endif
#ifndef HAVE_TFTP #ifndef HAVE_TFTP
if (daemon->options & OPT_TFTP) if (daemon->tftp_unlimited || daemon->tftp_interfaces)
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF); die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
#endif #endif
...@@ -184,7 +183,7 @@ int main (int argc, char **argv) ...@@ -184,7 +183,7 @@ int main (int argc, char **argv)
die(_("no interface with address %s"), daemon->namebuff, EC_BADNET); die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
} }
} }
else if ((daemon->port != 0 || (daemon->options & OPT_TFTP)) && else if ((daemon->port != 0 || daemon->tftp_interfaces || daemon->tftp_unlimited) &&
!(daemon->listeners = create_wildcard_listeners())) !(daemon->listeners = create_wildcard_listeners()))
die(_("failed to create listening socket: %s"), NULL, EC_BADNET); die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
...@@ -278,8 +277,6 @@ int main (int argc, char **argv) ...@@ -278,8 +277,6 @@ int main (int argc, char **argv)
if (!(daemon->options & OPT_DEBUG)) if (!(daemon->options & OPT_DEBUG))
{ {
int nullfd;
/* The following code "daemonizes" the process. /* The following code "daemonizes" the process.
See Stevens section 12.4 */ See Stevens section 12.4 */
...@@ -344,16 +341,19 @@ int main (int argc, char **argv) ...@@ -344,16 +341,19 @@ int main (int argc, char **argv)
_exit(0); _exit(0);
} }
} }
/* open stdout etc to /dev/null */
nullfd = open("/dev/null", O_RDWR);
dup2(nullfd, STDOUT_FILENO);
dup2(nullfd, STDERR_FILENO);
dup2(nullfd, STDIN_FILENO);
close(nullfd);
} }
log_err = log_start(ent_pw, err_pipe[1]); log_err = log_start(ent_pw, err_pipe[1]);
if (!(daemon->options & OPT_DEBUG))
{
/* open stdout etc to /dev/null */
int nullfd = open("/dev/null", O_RDWR);
dup2(nullfd, STDOUT_FILENO);
dup2(nullfd, STDERR_FILENO);
dup2(nullfd, STDIN_FILENO);
close(nullfd);
}
/* if we are to run scripts, we need to fork a helper before dropping root. */ /* if we are to run scripts, we need to fork a helper before dropping root. */
daemon->helperfd = -1; daemon->helperfd = -1;
...@@ -508,7 +508,7 @@ int main (int argc, char **argv) ...@@ -508,7 +508,7 @@ int main (int argc, char **argv)
#endif #endif
#ifdef HAVE_TFTP #ifdef HAVE_TFTP
if (daemon->options & OPT_TFTP) if (daemon->tftp_unlimited || daemon->tftp_interfaces)
{ {
#ifdef FD_SETSIZE #ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd) if (FD_SETSIZE < (unsigned)max_fd)
...@@ -647,10 +647,11 @@ int main (int argc, char **argv) ...@@ -647,10 +647,11 @@ int main (int argc, char **argv)
difftime(now, daemon->last_resolv) > 1.0 || difftime(now, daemon->last_resolv) > 1.0 ||
difftime(now, daemon->last_resolv) < -1.0) difftime(now, daemon->last_resolv) < -1.0)
{ {
daemon->last_resolv = now; /* poll_resolv doesn't need to reload first time through, since
that's queued anyway. */
if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL)) poll_resolv(0, daemon->last_resolv != 0, now);
poll_resolv(); daemon->last_resolv = now;
} }
if (FD_ISSET(piperead, &rset)) if (FD_ISSET(piperead, &rset))
...@@ -898,7 +899,7 @@ static void async_event(int pipe, time_t now) ...@@ -898,7 +899,7 @@ static void async_event(int pipe, time_t now)
} }
} }
static void poll_resolv() void poll_resolv(int force, int do_reload, time_t now)
{ {
struct resolvc *res, *latest; struct resolvc *res, *latest;
struct stat statbuf; struct stat statbuf;
...@@ -906,19 +907,37 @@ static void poll_resolv() ...@@ -906,19 +907,37 @@ static void poll_resolv()
/* There may be more than one possible file. /* There may be more than one possible file.
Go through and find the one which changed _last_. Go through and find the one which changed _last_.
Warn of any which can't be read. */ Warn of any which can't be read. */
if (daemon->port == 0 || (daemon->options & OPT_NO_POLL))
return;
for (latest = NULL, res = daemon->resolv_files; res; res = res->next) for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
if (stat(res->name, &statbuf) == -1) if (stat(res->name, &statbuf) == -1)
{ {
if (force)
{
res->mtime = 0;
continue;
}
if (!res->logged) if (!res->logged)
my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno)); my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
res->logged = 1; res->logged = 1;
if (res->mtime != 0)
{
/* existing file evaporated, force selection of the latest
file even if its mtime hasn't changed since we last looked */
poll_resolv(1, do_reload, now);
return;
}
} }
else else
{ {
res->logged = 0; res->logged = 0;
if (statbuf.st_mtime != res->mtime) if (force || (statbuf.st_mtime != res->mtime))
{ {
res->mtime = statbuf.st_mtime; res->mtime = statbuf.st_mtime;
if (difftime(statbuf.st_mtime, last_change) > 0.0) if (difftime(statbuf.st_mtime, last_change) > 0.0)
{ {
last_change = statbuf.st_mtime; last_change = statbuf.st_mtime;
...@@ -935,8 +954,8 @@ static void poll_resolv() ...@@ -935,8 +954,8 @@ static void poll_resolv()
my_syslog(LOG_INFO, _("reading %s"), latest->name); my_syslog(LOG_INFO, _("reading %s"), latest->name);
warned = 0; warned = 0;
check_servers(); check_servers();
if (daemon->options & OPT_RELOAD) if ((daemon->options & OPT_RELOAD) && do_reload)
cache_reload(); clear_cache_and_reload(now);
} }
else else
{ {
...@@ -1125,11 +1144,13 @@ static void check_dns_listeners(fd_set *set, time_t now) ...@@ -1125,11 +1144,13 @@ static void check_dns_listeners(fd_set *set, time_t now)
dst_addr_4.s_addr = 0; dst_addr_4.s_addr = 0;
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to #ifndef NO_FORK
terminate the process. */ /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
terminate the process. */
if (!(daemon->options & OPT_DEBUG)) if (!(daemon->options & OPT_DEBUG))
alarm(CHILD_LIFETIME); alarm(CHILD_LIFETIME);
#endif
/* start with no upstream connections. */ /* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next) for (s = daemon->servers; s; s = s->next)
s->tcpfd = -1; s->tcpfd = -1;
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
# define _FILE_OFFSET_BITS 64 # define _FILE_OFFSET_BITS 64
#endif #endif
/* Get linux C library versions. */ /* Get linux C library versions and define _GNU_SOURCE for kFreeBSD. */
#ifdef __linux__ #if defined(__linux__) || defined(__GLIBC__)
# define _GNU_SOURCE # define _GNU_SOURCE
# include <features.h> # include <features.h>
#endif #endif
...@@ -188,7 +188,7 @@ struct event_desc { ...@@ -188,7 +188,7 @@ struct event_desc {
#define OPT_LEASE_RO (1u<<22) #define OPT_LEASE_RO (1u<<22)
#define OPT_ALL_SERVERS (1u<<23) #define OPT_ALL_SERVERS (1u<<23)
#define OPT_RELOAD (1u<<24) #define OPT_RELOAD (1u<<24)
#define OPT_TFTP (1u<<25) #define OPT_LOCAL_REBIND (1u<<25)
#define OPT_TFTP_SECURE (1u<<26) #define OPT_TFTP_SECURE (1u<<26)
#define OPT_TFTP_NOBLOCK (1u<<27) #define OPT_TFTP_NOBLOCK (1u<<27)
#define OPT_LOG_OPTS (1u<<28) #define OPT_LOG_OPTS (1u<<28)
...@@ -319,6 +319,8 @@ union mysockaddr { ...@@ -319,6 +319,8 @@ union mysockaddr {
#define SERV_MARK 256 /* for mark-and-delete */ #define SERV_MARK 256 /* for mark-and-delete */
#define SERV_TYPE (SERV_HAS_DOMAIN | SERV_FOR_NODOTS) #define SERV_TYPE (SERV_HAS_DOMAIN | SERV_FOR_NODOTS)
#define SERV_COUNTED 512 /* workspace for log code */ #define SERV_COUNTED 512 /* workspace for log code */
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
struct serverfd { struct serverfd {
int fd; int fd;
...@@ -345,7 +347,8 @@ struct server { ...@@ -345,7 +347,8 @@ struct server {
struct irec { struct irec {
union mysockaddr addr; union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */ struct in_addr netmask; /* only valid for IPv4 */
int dhcp_ok, mtu; int tftp_ok, mtu;
char *name;
struct irec *next; struct irec *next;
}; };
...@@ -391,7 +394,7 @@ struct frec { ...@@ -391,7 +394,7 @@ struct frec {
#endif #endif
unsigned int iface; unsigned int iface;
unsigned short orig_id, new_id; unsigned short orig_id, new_id;
int fd, forwardall; int fd, forwardall, norebind;
unsigned int crc; unsigned int crc;
time_t time; time_t time;
struct frec *next; struct frec *next;
...@@ -437,6 +440,12 @@ struct dhcp_netid_list { ...@@ -437,6 +440,12 @@ struct dhcp_netid_list {
struct dhcp_netid_list *next; struct dhcp_netid_list *next;
}; };
struct tag_if {
struct dhcp_netid_list *set;
struct dhcp_netid *tag;
struct tag_if *next;
};
struct hwaddr_config { struct hwaddr_config {
int hwaddr_len, hwaddr_type; int hwaddr_len, hwaddr_type;
unsigned char hwaddr[DHCP_CHADDR_MAX]; unsigned char hwaddr[DHCP_CHADDR_MAX];
...@@ -449,7 +458,7 @@ struct dhcp_config { ...@@ -449,7 +458,7 @@ struct dhcp_config {
int clid_len; /* length of client identifier */ int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */ unsigned char *clid; /* clientid */
char *hostname, *domain; char *hostname, *domain;
struct dhcp_netid netid; struct dhcp_netid_list *netid;
struct in_addr addr; struct in_addr addr;
time_t decline_time; time_t decline_time;
unsigned int lease_time; unsigned int lease_time;
...@@ -462,7 +471,6 @@ struct dhcp_config { ...@@ -462,7 +471,6 @@ struct dhcp_config {
#define CONFIG_TIME 8 #define CONFIG_TIME 8
#define CONFIG_NAME 16 #define CONFIG_NAME 16
#define CONFIG_ADDR 32 #define CONFIG_ADDR 32
#define CONFIG_NETID 64
#define CONFIG_NOCLID 128 #define CONFIG_NOCLID 128
#define CONFIG_FROM_ETHERS 256 /* entry created by /etc/ethers */ #define CONFIG_FROM_ETHERS 256 /* entry created by /etc/ethers */
#define CONFIG_ADDR_HOSTS 512 /* address added by from /etc/hosts */ #define CONFIG_ADDR_HOSTS 512 /* address added by from /etc/hosts */
...@@ -548,6 +556,7 @@ struct dhcp_context { ...@@ -548,6 +556,7 @@ struct dhcp_context {
struct in_addr local, router; struct in_addr local, router;
struct in_addr start, end; /* range of available addresses */ struct in_addr start, end; /* range of available addresses */
int flags; int flags;
char *interface;
struct dhcp_netid netid, *filter; struct dhcp_netid netid, *filter;
struct dhcp_context *next, *current; struct dhcp_context *next, *current;
}; };
...@@ -598,6 +607,23 @@ struct tftp_transfer { ...@@ -598,6 +607,23 @@ struct tftp_transfer {
struct tftp_transfer *next; struct tftp_transfer *next;
}; };
struct addr_list {
struct in_addr addr;
struct addr_list *next;
};
struct interface_list {
char *interface;
struct interface_list *next;
};
struct tftp_prefix {
char *interface;
char *prefix;
struct tftp_prefix *next;
};
extern struct daemon { extern struct daemon {
/* datastuctures representing the command-line and /* datastuctures representing the command-line and
config file arguments. All set (including defaults) config file arguments. All set (including defaults)
...@@ -628,7 +654,7 @@ extern struct daemon { ...@@ -628,7 +654,7 @@ extern struct daemon {
int max_logs; /* queue limit */ int max_logs; /* queue limit */
int cachesize, ftabsize; int cachesize, ftabsize;
int port, query_port, min_port; int port, query_port, min_port;
unsigned long local_ttl, neg_ttl; unsigned long local_ttl, neg_ttl, max_ttl;
struct hostsfile *addn_hosts; struct hostsfile *addn_hosts;
struct dhcp_context *dhcp; struct dhcp_context *dhcp;
struct dhcp_config *dhcp_conf; struct dhcp_config *dhcp_conf;
...@@ -637,8 +663,12 @@ extern struct daemon { ...@@ -637,8 +663,12 @@ extern struct daemon {
struct dhcp_mac *dhcp_macs; struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config; struct dhcp_boot *boot_config;
struct pxe_service *pxe_services; struct pxe_service *pxe_services;
struct tag_if *tag_if;
struct addr_list *override_relays;
int override;
int enable_pxe; int enable_pxe;
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *force_broadcast, *bootp_dynamic; struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
char *dhcp_hosts_file, *dhcp_opts_file; char *dhcp_hosts_file, *dhcp_opts_file;
int dhcp_max, tftp_max; int dhcp_max, tftp_max;
int dhcp_server_port, dhcp_client_port; int dhcp_server_port, dhcp_client_port;
...@@ -647,6 +677,9 @@ extern struct daemon { ...@@ -647,6 +677,9 @@ extern struct daemon {
struct doctor *doctors; struct doctor *doctors;
unsigned short edns_pktsz; unsigned short edns_pktsz;
char *tftp_prefix; char *tftp_prefix;
struct tftp_prefix *if_prefix; /* per-interface TFTP prefixes */
struct interface_list *tftp_interfaces; /* interfaces for limited TFTP service */
int tftp_unlimited;
/* globally used stuff for DNS */ /* globally used stuff for DNS */
char *packet; /* packet buffer */ char *packet; /* packet buffer */
...@@ -675,7 +708,7 @@ extern struct daemon { ...@@ -675,7 +708,7 @@ extern struct daemon {
int dhcp_raw_fd, dhcp_icmp_fd; int dhcp_raw_fd, dhcp_icmp_fd;
#endif #endif
struct iovec dhcp_packet; struct iovec dhcp_packet;
char *dhcp_buff, *dhcp_buff2; char *dhcp_buff, *dhcp_buff2, *dhcp_buff3;
struct ping_result *ping_results; struct ping_result *ping_results;
FILE *lease_stream; FILE *lease_stream;
struct dhcp_bridge *bridges; struct dhcp_bridge *bridges;
...@@ -719,7 +752,8 @@ unsigned short extract_request(HEADER *header, size_t qlen, ...@@ -719,7 +752,8 @@ unsigned short extract_request(HEADER *header, size_t qlen,
size_t setup_reply(HEADER *header, size_t qlen, size_t setup_reply(HEADER *header, size_t qlen,
struct all_addr *addrp, unsigned short flags, struct all_addr *addrp, unsigned short flags,
unsigned long local_ttl); unsigned long local_ttl);
int extract_addresses(HEADER *header, size_t qlen, char *namebuff, time_t now); int extract_addresses(HEADER *header, size_t qlen, char *namebuff,
time_t now, int is_sign, int checkrebind);
size_t answer_request(HEADER *header, char *limit, size_t qlen, size_t answer_request(HEADER *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask, time_t now); struct in_addr local_addr, struct in_addr local_netmask, time_t now);
int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name, int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
...@@ -803,9 +837,11 @@ struct dhcp_context *address_available(struct dhcp_context *context, ...@@ -803,9 +837,11 @@ struct dhcp_context *address_available(struct dhcp_context *context,
struct dhcp_context *narrow_context(struct dhcp_context *context, struct dhcp_context *narrow_context(struct dhcp_context *context,
struct in_addr taddr, struct in_addr taddr,
struct dhcp_netid *netids); struct dhcp_netid *netids);
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);int address_allocate(struct dhcp_context *context, int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len, struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now); struct dhcp_netid *netids, time_t now);
struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type); int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
struct dhcp_config *find_config(struct dhcp_config *configs, struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context, struct dhcp_context *context,
...@@ -856,6 +892,7 @@ int icmp_ping(struct in_addr addr); ...@@ -856,6 +892,7 @@ int icmp_ping(struct in_addr addr);
#endif #endif
void send_event(int fd, int event, int data); void send_event(int fd, int event, int data);
void clear_cache_and_reload(time_t now); void clear_cache_and_reload(time_t now);
void poll_resolv(int force, int do_reload, time_t now);
/* netlink.c */ /* netlink.c */
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
......
This diff is collapsed.
...@@ -245,9 +245,12 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) ...@@ -245,9 +245,12 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
if (data.giaddr.s_addr != 0) if (data.giaddr.s_addr != 0)
my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err); my_setenv("DNSMASQ_RELAY_ADDRESS", inet_ntoa(data.giaddr), &err);
sprintf(daemon->dhcp_buff2, "%u", data.remaining_time); if (data.action != ACTION_DEL)
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err); {
sprintf(daemon->dhcp_buff2, "%u", data.remaining_time);
my_setenv("DNSMASQ_TIME_REMAINING", daemon->dhcp_buff2, &err);
}
if (data.action == ACTION_OLD_HOSTNAME && hostname) if (data.action == ACTION_OLD_HOSTNAME && hostname)
{ {
my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err); my_setenv("DNSMASQ_OLD_HOSTNAME", hostname, &err);
......
...@@ -29,11 +29,12 @@ void lease_init(time_t now) ...@@ -29,11 +29,12 @@ void lease_init(time_t now)
int clid_len, hw_len, hw_type; int clid_len, hw_len, hw_type;
FILE *leasestream; FILE *leasestream;
/* These two each hold a DHCP option max size 255 /* These each hold a DHCP option max size 255
and get a terminating zero added */ and get a terminating zero added */
daemon->dhcp_buff = safe_malloc(256); daemon->dhcp_buff = safe_malloc(256);
daemon->dhcp_buff2 = safe_malloc(256); daemon->dhcp_buff2 = safe_malloc(256);
daemon->dhcp_buff3 = safe_malloc(256);
leases_left = daemon->dhcp_max; leases_left = daemon->dhcp_max;
if (daemon->options & OPT_LEASE_RO) if (daemon->options & OPT_LEASE_RO)
......
This diff is collapsed.
...@@ -281,8 +281,8 @@ static void nl_routechange(struct nlmsghdr *h) ...@@ -281,8 +281,8 @@ static void nl_routechange(struct nlmsghdr *h)
return; return;
/* Force re-reading resolv file right now, for luck. */ /* Force re-reading resolv file right now, for luck. */
daemon->last_resolv = 0; poll_resolv(1, 1, dnsmasq_time());
if (daemon->srv_save) if (daemon->srv_save)
{ {
if (daemon->srv_save->sfd) if (daemon->srv_save->sfd)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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