import of dnsmasq-2.1.tar.gz

This commit is contained in:
Simon Kelley
2004-01-29 16:48:35 +00:00
parent 9e4abcb5ac
commit 1ab84e2f35
18 changed files with 356 additions and 106 deletions

View File

@@ -666,4 +666,50 @@ release 2.0
domains and IPv6 queries. Thanks to Roy Marples for
helping to track that one down.
release 2.1
Tweak include files to allow compilation on FreeBSD 5
Fix unaligned access warnings on BSD/Alpha.
Allow empty DHCP options, like so: dhpc-option=44
Allow single-byte DHCP options like so: dhcp-option=20,1
Allow comments on the same line as options in
/etc/dnsmasq.conf
Don't complain when the same name and address is
allocated to a host using DHCP and /etc/hosts.
Added to the example configuration the dnsmasq equivalent
of the ISC dhcpd settings given in
http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
Fixed long-existing strangeness in Linux IPv6 interface
discovery code. The flags field in /proc/net/if_inet6 is
_not_ the interface flags.
Fail gracefully when getting an ENODEV error when trying
to bind an IPv6 socket, rather than bailing out.
Allow the name->address mapping for static DHCP leases to
be set by /etc/hosts. It's now possible to have
dhcp-host=<mac addr>,wibble
or even
dhcp-host=wibble
and in /etc/hosts have
wibble 1.2.3.4
and for the correct thing to happen. Note that some sort
of dhcp-host line is still needed, it's not possible for
random host to claim an address in /etc/hosts without
some explicit configuration.
Make 0.0.0.0 in a dhcp-option to mean "the machine
running dnsmasq".
Fix lease time spec when specified in dhcp-range and not
in dhcp-host, previously this was always one hour.
Fix problem with setting domains as "local only".
Added support for max message size DHCP option.

28
FAQ
View File

@@ -154,6 +154,34 @@ A: [note: this was written in September 2003, things may well change.]
registries pull the same stunt; there is a list of them all, and
the addresses to block, at http://winware.org/bogus-domains.txt
Q: This new DHCP server is well and good, but it doesn't work for me.
What's the problem?
A: There are a couple of configuration gotchas which have been
encountered by people moving from the ISC dhcpd to the dnsmasq
integrated DHCP daemon. Both are related to differences in
in the way the two daemons bypass the IP stack to do "ground up"
IP configuration and can lead to the dnsmasq daemon failing
whilst the ISC one works.
The first thing to check is the broadcast address set for the
ethernet interface. This is normally the adddress on the connected
network with all ones in the host part. For instance if the
address of the ethernet interface is 192.168.55.7 and the netmask
is 255.255.255.0 then the broadcast address should be
192.168.55.255. Having a broadcast address which is not on the
network to which the interface is connected kills things stone
dead.
The second potential problem relates to firewall rules: since the ISC
daemon in some configurations bypasses the kernel firewall rules
entirely, the ability to run the ISC daemon does not indicate
that the current configuration is OK for the dnsmasq daemon.
For the dnsmasq daemon to operate it's vital that UDP packets to
and from ports 67 and 68 and broadcast packets with source
address 0.0.0.0 and destination address 255.255.255.255 are not
dropped by iptables/ipchains.

View File

@@ -40,7 +40,7 @@ to store its leases it is necessary to remove the configuration line in
To enable DHCP, simply add a line like this to /etc/dnsmasq.conf
dhcp-range=192.168.0.100,192,168.0.200,12h
dhcp-range=192.168.0.100,192.168.0.200,12h
which tells dnsmasq to us the addresses 192.168.0.100 to 192.168.0.200
for dynamic IP addresses, and to issue twelve hour leases.
@@ -60,6 +60,8 @@ Windows use winipcfg.exe
For more complex DHCP configuration, refer to the doc/setup.html, the
dnsmasq manpage and the annotated example configuration file.
dnsmasq manpage and the annotated example configuration file. Also
note that for some ISC dhcpd to dnsmasq DHCP upgrades there may be
firewall issues: see the FAQ for details of this.

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.0
Version: 2.1
Release: 1
Copyright: GPL
Group: System Environment/Daemons

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.0
Version: 2.1
Release: 1
Copyright: GPL
Group: System Environment/Daemons

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.0
Version: 2.1
Release: 1
Copyright: GPL
Group: Productivity/Networking/DNS/Servers
@@ -100,7 +100,7 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0 rpm/README.susefirewall
%config /etc/init.d/dnsmasq
%config /etc/dnsmasq.conf
/usr/sbin/rcdnsmasq

View File

@@ -251,7 +251,7 @@ an infinite DHCP lease.
.B --dhcp-host=lap,192.168.0.199
tells
dnsmasq to always allocate the machine lap the IP address
192.168.0.199. Addresses allocated like this are not contrained to be
192.168.0.199. Addresses allocated like this are not constrained to be
in the range given by the --dhcp-range option, but they must be on the
network being served by the DHCP server. It is allowed to use client identifiers rather than
hardware addresses to identify hosts by prefixing with 'id:'. Thus:
@@ -259,8 +259,12 @@ hardware addresses to identify hosts by prefixing with 'id:'. Thus:
refers to the host with client identifier 01:02:03:04. It is also
allowed to specify the client ID as text, like this:
.B --dhcp-host=id:clientidastext,.....
If a name appears in /etc/hosts, the associated address can be
allocated to a DHCP lease, but only if a
.B --dhcp-host
option specifying the name also exists.
.TP
.B \-O, --dhcp-option=<opt>,<value>[,<value>]
.B \-O, --dhcp-option=<opt>,[<value>[,<value>]]
Specfify different or extra options to DHCP clients. By default,
dnsmasq sends some standard options to DHCP clients, the netmask and
broadcast address are set to the same as the host running dnsmasq, and
@@ -273,6 +277,8 @@ specfied in RFC2132. For example, to set the default route option to
.B --dhcp-option=3,192.168.4.4
and to set the time-server address to 192.168.0.4, do
.B dhcp-option=42,192.168.0.4
The special address 0.0.0.0 is taken to mean "the address of the
machine running dnsmasq".
Be careful: no checking is done that the correct type of data for the
option number is sent, and there are option numbers for which it is not
possible to generate the correct data type; it is quite possible to

View File

@@ -31,6 +31,13 @@ filterwin2k
# somewhere other that /etc/resolv.conf
#resolv-file=
# By default, dnsmasq will send queries to any of the upstream
# servers it knows about and tries to favour servers to are known
# to be up. Uncommenting this forces dnsmasq to try each query
# with each server strictly in the order they appear in
# /etc/resolv.conf
#strict-order
# If you don't want dnsmasq to read /etc/resolv.conf or any other
# file, getting its servers for this file instead (see below), then
# uncomment this
@@ -88,9 +95,10 @@ filterwin2k
#dhcp-range=192.168.0.50,192.168.0.150,12h
# Supply parameters for specified hosts using DHCP. There are lots
# of valid alternatives, do 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
# need to be on the same network.
# need to be on the same network. The order of the parameters in these
# do not matter, it's permissble to give name,adddress and MAC in any order
# Always allocate the host with ethernet address 11:22:33:44:55:66
# The IP address 192.168.0.60
@@ -116,15 +124,54 @@ filterwin2k
# the IP address 192.168.0.60
#dhcp-host=id:marjorie,192.168.0.60
# Enable the address given for "judge" in /etc/hosts
# to be given to a machine presenting the name "judge" when
# it asks for a DHCP lease.
#dhcp-host=judge
# Send options to hosts which ask for a DHCP lease.
# See RFC 2132 for details of available options.
# Note that all the common settings, such as netmask and
# broadcast address, DNS server and default route, are given
# sane defaults by dnsmasq. You very likely will not need any
# any dhcp-options. If you use Windows clients and Samba, there
# are some options which are recommended, they are detailed at the
# end of this section.
# For reference, the common options are:
# subnet mask - 1
# default router - 3
# DNS server - 6
# broadcast address - 28
# Set the NTP time server addresses to 192.168.0.4 and 10.10.0.5
#dhcp-option=42,192.168.0.4,10.10.0.5
# Set the NTP time server address to be the same machine as
# is running dnsmasq
#dhcp-option=42,0.0.0.0
# Set the NIS domain name to "welly"
#dhcp-option=40,welly
# Set the default time-to-live to 50
#dhcp-option=23,50
# Set the "all subnets are local" flag
#dhcp-option=27,1
# The following DHCP options set up dnsmasq in the same way as is specified
# for the ISC dhcpcd in
# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
# adapted for a typical dnsmasq installation where the host running
# dnsmasq is also the host running samba.
# you may want to uncomment them if you use Windows clients and Samba.
#dhcp-option=19,0 # option ip-forwarding off
#dhcp-option=44,0.0.0.0 # set netbios-over-TCP/IP nameserver(s) aka WINS server(s)
#dhcp-option=45,0.0.0.0 # netbios datagram distribution server
#dhcp-option=46,8 # netbios node type
#dhcp-option=47 # empty netbios scope.
# Set the boot filename and tftpd server name and address
# for BOOTP. You will only need this is you want to
# boot machines over the network.
@@ -133,14 +180,10 @@ filterwin2k
# The DHCP server needs somewhere on disk to keep its lease database.
# This defaults to a sane location, but if you want to change it, use
# the line below.
#dhcp-leasefile=/var/lib/dnsmasq/leases
# Override the default route (which is normally automagically set
# to be the machine running dnsmasq
#dhcp-option=2,192,168.4.4
#dhcp-leasefile=/var/lib/misc/dnsmasq.leases
# Set the cachesize here.
#cache-size=600
#cache-size=150
# If you want to disable negative caching, uncomment this.
#no-negcache

27
rpm/README.susefirewall Normal file
View File

@@ -0,0 +1,27 @@
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
It fixes the depancy from the dns daemon name 'named'
After appending the patch, the SuSEfirewall is again able to autodetect
the dnsmasq named service.
This is a very old bug in the SuSEfirewall script.
The SuSE people think the name of the dns server will allways 'named'
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100
+++ /sbin/SuSEfirewall2 2004-01-23 13:31:56.000000000 +0100
@@ -764,7 +764,7 @@
echo 'FW_ALLOW_INCOMING_HIGHPORTS_UDP should be set to yes, if you are running a DNS server!'
test "$FW_SERVICE_AUTODETECT" = yes -o "$FW_SERVICE_AUTODETECT" = dmz -o "$FW_SERVICE_AUTODETECT" = ext && {
- test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv named && {
+ test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv dnsmasq && {
echo -e 'Warning: detected activated named, enabling FW_SERVICE_DNS!
You still have to allow tcp/udp port 53 on internal, dmz and/or external.'
FW_SERVICE_DNS=$FW_SERVICE_AUTODETECT
@@ -878,7 +878,7 @@
test -e /etc/resolv.conf || echo "Warning: /etc/resolv.conf not found"
# Get ports/IP bindings of NAMED/SQUID
test "$FW_SERVICE_DNS" = yes -o "$FW_SERVICE_DNS" = dmz -o "$FW_SERVICE_DNS" = ext -o "$START_NAMED" = yes && DNS_PORT=`$LSOF -i -n -P | \
- $AWK -F: '/^named .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
+ $AWK -F: '/^dnsmasq .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
test "$FW_SERVICE_SQUID" = yes -o "$FW_SERVICE_SQUID" = dmz -o "$FW_SERVICE_SQUID" = ext -o "$START_SQUID" = yes && SQUID_PORT=`$LSOF -i -n -P | \
$AWK -F: '/^squid .* UDP/ {print $2}'| $SORT -un`

View File

@@ -639,7 +639,10 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
if ((crec = cache_find_by_name(NULL, host_name, 0, F_IPV4)))
{
if (crec->flags & F_HOSTS)
syslog(LOG_WARNING, "Ignoring DHCP lease for %s because it clashes with an /etc/hosts entry.", host_name);
{
if (crec->addr.addr.addr4.s_addr != host_address->s_addr)
syslog(LOG_WARNING, "Not naming DHCP lease for %s because it clashes with an /etc/hosts entry.", host_name);
}
else if (!(crec->flags & F_DHCP))
{
if (crec->flags & F_NEG)
@@ -650,7 +653,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
goto newrec;
}
else
syslog(LOG_WARNING, "Ignoring DHCP lease for %s because it clashes with a cached name.", cache_get_name(crec));
syslog(LOG_WARNING, "Not naming DHCP lease for %s because it clashes with a cached name.", cache_get_name(crec));
}
return;
}
@@ -671,7 +674,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
crec->flags |= F_IMMORTAL;
else
crec->ttd = ttd;
memcpy(&crec->addr, host_address, INADDRSZ);
crec->addr.addr.addr4 = *host_address;
crec->name.namep = host_name;
crec->prev = dhcp_inuse;
dhcp_inuse = crec;

View File

@@ -12,7 +12,7 @@
/* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.0"
#define VERSION "2.1"
#define FTABSIZ 150 /* max number of outstanding requests */
#define TIMEOUT 40 /* drop queries after TIMEOUT seconds */

View File

@@ -269,5 +269,18 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
return NULL;
}
void set_configs_from_cache(struct dhcp_config *configs)
/* Some people like to keep all static IP addresses in /etc/hosts.
This goes through /etc/hosts and sets static addresses for any DHCP config
records which don't have an address and whose name matches. */
{
struct dhcp_config *config;
struct crec *crec;
for (config = configs; config; config = config->next)
if (config->addr.s_addr == 0 && config->hostname &&
(crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
(crec->flags & F_HOSTS))
config->addr = crec->addr.addr.addr4;
}

View File

@@ -158,6 +158,7 @@ int main (int argc, char **argv)
if (!dhcp_tmp->iface)
die("No suitable interface for DHCP service at address %s", inet_ntoa(dhcp_tmp->start));
set_configs_from_cache(dhcp_configs);
leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, time(NULL), dhcp_configs);
lease_update_dns(1); /* must follow cache_init and lease_init */
}
@@ -270,6 +271,7 @@ int main (int argc, char **argv)
if (sighup)
{
cache_reload(options, dnamebuff, domain_suffix, addn_hosts);
set_configs_from_cache(dhcp_configs);
lease_update_dns(1);
if (resolv && (options & OPT_NO_POLL))
servers = last_server =

View File

@@ -16,6 +16,8 @@
#define _XOPEN_SOURCE 600
/* but then DNS headers don't compile without.... */
#define _BSD_SOURCE
/* and also, on FreeBSD 5.0 ..... */
#define __BSD_VISIBLE 1
/* get these before config.h for IPv6 stuff... */
#include <sys/types.h>
@@ -26,7 +28,6 @@
#include "config.h"
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <sys/stat.h>
@@ -229,8 +230,7 @@ struct dhcp_config {
};
struct dhcp_opt {
unsigned char opt;
unsigned char len;
int opt, len, is_addr;
unsigned char *val;
struct dhcp_opt *next;
};
@@ -360,6 +360,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
unsigned char *clid, int clid_len,
unsigned char *hwaddr, char *hostname);
void set_configs_from_cache(struct dhcp_config *configs);
/* lease.c */
void lease_update_dns(int force_dns);
int lease_init(char *lease_file, char *domain, char *buff,

View File

@@ -132,6 +132,7 @@ struct server *forward_query(int udpfd, union mysockaddr *udpaddr, HEADER *heade
flags = 0; /* may be better match from previous literal */
domain = serv->domain;
matchlen = domainlen;
type = SERV_HAS_DOMAIN;
}
}
}

View File

@@ -76,12 +76,14 @@ static char *add_iface(struct irec **list, unsigned int flags,
specific addresses even if BIND is running and has bound *:53 */
opt = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
bind(fd, &addr->sa, sa_len(addr)))
bind(fd, &addr->sa, sa_len(addr)) == -1)
{
int errsave = errno;
close(fd);
errno = errsave;
return "failed to bind socket: %s";
/* IPv6 interfaces sometimes return ENODEV to bind() for unknown
(to me) reasons. Don't treat that as fatal. */
return errno == ENODEV ? NULL : "failed to bind socket: %s";
}
/* If OK, add it to the head of the list */
@@ -119,6 +121,7 @@ char *enumerate_interfaces(struct irec **interfacep,
struct irec *iface, *prev;
char *buf, *ptr, *err = NULL;
struct ifconf ifc;
struct ifreq *ifr = NULL;
int fd = socket(PF_INET, SOCK_DGRAM, 0);
int rawfd = -1;
@@ -158,12 +161,22 @@ char *enumerate_interfaces(struct irec **interfacep,
for (ptr = buf; ptr < buf + ifc.ifc_len; )
{
struct ifreq *ifr = (struct ifreq *) ptr;
union mysockaddr addr;
#ifdef HAVE_SOCKADDR_SA_LEN
ptr += ifr->ifr_addr.sa_len + IF_NAMESIZE;
/* subsequent entries may not be aligned, so copy into
an aligned buffer to avoid nasty complaints about
unaligned accesses. */
int ifr_len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
if (!(ifr = realloc(ifr, ifr_len)))
{
err = "cannot allocate buffer";
goto end;
}
memcpy(ifr, ptr, ifr_len);
ptr += ifr_len;
#else
ifr = (struct ifreq *)ptr;
ptr += sizeof(struct ifreq);
#endif
@@ -198,6 +211,54 @@ char *enumerate_interfaces(struct irec **interfacep,
&addr, names, addrs, except)))
goto end;
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
/* This code snarfed from net-tools 1.60 and certainly linux specific, though
it shouldn't break on other Unices, and their SIOGIFCONF might work. */
{
FILE *f = fopen(IP6INTERFACES, "r");
int found = 0;
if (f)
{
unsigned int plen, scope, flags, if_idx;
char devname[20], addrstring[32];
while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
{
if (strcmp(devname, ifr->ifr_name) == 0)
{
int i;
unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr;
memset(&addr, 0, sizeof(addr));
addr.sa.sa_family = AF_INET6;
for (i=0; i<16; i++)
{
unsigned int byte;
sscanf(addrstring+i+i, "%02x", &byte);
addr6p[i] = byte;
}
addr.in6.sin6_port = htons(port);
addr.in6.sin6_flowinfo = htonl(0);
addr.in6.sin6_scope_id = htonl(scope);
found = 1;
break;
}
}
fclose(f);
}
if (found &&
(err = add_iface(interfacep, ifr->ifr_flags, ifr->ifr_name,
&addr, names, addrs, except)))
goto end;
}
#endif /* LINUX */
/* dhcp is non-null only on the first call: set up the relevant
interface-related DHCP stuff here. DHCP is IPv4 only.
Because errors here are ultimately fatal we can return directly and not bother
@@ -289,32 +350,48 @@ char *enumerate_interfaces(struct irec **interfacep,
}
}
}
}
#ifdef HAVE_BPF
/* now go through the interfaces again, looking for AF_LINK records
to get hardware addresses from */
for (ptr = buf; ptr < buf + ifc.ifc_len; )
{
struct ifreq *ifr = (struct ifreq *) ptr;
struct dhcp_context *context;
#ifdef HAVE_SOCKADDR_SA_LEN
ptr += ifr->ifr_addr.sa_len + IF_NAMESIZE;
/* subsequent entries may not be aligned, so copy into
an aligned buffer to avoid nasty complaints about
unaligned accesses. */
int ifr_len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
if (!(ifr = realloc(ifr, ifr_len)))
{
err = "cannot allocate buffer";
goto end;
}
memcpy(ifr, ptr, ifr_len);
ptr += ifr_len;
#else
ifr = (struct ifreq *)ptr;
ptr += sizeof(struct ifreq);
#endif
if (ifr->ifr_addr.sa_family == AF_LINK)
for (context = dhcp; context; context = context->next)
if (context->iface && strcmp(context->iface, ifr->ifr_name) == 0)
memcpy(context->hwaddr, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
}
#endif
end:
errsave = errno; /* since errno gets overwritten by close */
if (buf)
free(buf);
#ifdef HAVE_SOCKADDR_SA_LEN
if (ifr)
free(ifr);
#endif
close(fd);
if (err)
{
@@ -322,54 +399,6 @@ char *enumerate_interfaces(struct irec **interfacep,
return err;
}
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
/* This code snarfed from net-tools 1.60 and certainly linux specific, though
it shouldn't break on other Unices, and their SIOGIFCONF might work. */
{
FILE *f = fopen(IP6INTERFACES, "r");
if (f)
{
union mysockaddr addr;
unsigned int plen, scope, flags, if_idx;
char devname[20], addrstring[32];
while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
{
int i;
unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr;
memset(&addr, 0, sizeof(addr));
addr.sa.sa_family = AF_INET6;
for (i=0; i<16; i++)
{
unsigned int byte;
sscanf(addrstring+i+i, "%02x", &byte);
addr6p[i] = byte;
}
#ifdef HAVE_SOCKADDR_SA_LEN
/* For completeness - should never be defined on Linux. */
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
addr.in6.sin6_port = htons(port);
addr.in6.sin6_flowinfo = htonl(0);
addr.in6.sin6_scope_id = htonl(scope);
if ((err = add_iface(interfacep, flags, devname, &addr, names, addrs, except)))
{
errsave = errno;
fclose(f);
errno = errsave;
return err;
}
}
fclose(f);
}
}
#endif /* LINUX */
/* now remove interfaces which were not found on this scan */
for(prev = NULL, iface = *interfacep; iface; )
{

View File

@@ -175,14 +175,18 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
else
{
char *p;
/* dump comments */
for (p = buff; *p; p++)
if (*p == '#')
*p = 0;
/* fgets gets end of line char too. */
while (strlen(buff) > 0 &&
(buff[strlen(buff)-1] == '\n' ||
buff[strlen(buff)-1] == ' ' ||
buff[strlen(buff)-1] == '\t'))
buff[strlen(buff)-1] = 0;
if (*buff == '#' || *buff == 0)
continue; /* comment */
if (*buff == 0)
continue;
if ((p=strchr(buff, '=')))
{
optarg = p+1;
@@ -639,7 +643,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
new->clid = NULL;
new->hostname = NULL;
new->addr.s_addr = 0;
new->lease_time = DEFLEASE;
new->lease_time = 0;
a[0] = optarg;
for (k = 1; k < 4; k++)
@@ -706,8 +710,8 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
{
case 'h':
case 'H':
fac *= 60;
/* fall through */
fac *= 60;
/* fall through */
case 'm':
case 'M':
fac *= 60;
@@ -717,7 +721,7 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
}
for (cp = a[j]; *cp; cp++)
if (!isdigit(*cp))
if (!isdigit(*cp) && *cp != ' ')
break;
if (*cp)
@@ -739,24 +743,33 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
{
struct dhcp_opt *new = safe_malloc(sizeof(struct dhcp_opt));
char *cp, *comma = strchr(optarg, ',');
int addrs;
int addrs, is_addr;
new->next = *dhcp_opts;
new->len = 0;
new->is_addr = 0;
*dhcp_opts = new;
if (!comma || (*comma = 0) || (new->opt = atoi(optarg)) == 0)
if ((new->opt = atoi(optarg)) == 0)
{
option = '?';
break;
}
if (!comma)
break;
*comma = 0;
/* check for non-address list characters */
for (addrs = 1, cp = comma+1; *cp; cp++)
for (addrs = 1, is_addr = 0, cp = comma+1; *cp; cp++)
if (*cp == ',')
addrs++;
else if (!(*cp == '.' || *cp == ' ' || (*cp >='0' && *cp <= '9')))
break;
else if (*cp == '.')
is_addr = 1;
if (*cp)
{
/* text arg */
@@ -768,17 +781,28 @@ unsigned int read_opts (int argc, char **argv, char *buff, struct resolvc **reso
{
struct in_addr in;
unsigned char *op;
new->len = INADDRSZ * addrs;
new->val = op = safe_malloc(new->len);
while (addrs--)
if (addrs == 1 && !is_addr)
{
cp = comma;
if (cp && (comma = strchr(cp+1, ',')))
*comma = 0;
if (cp && (in.s_addr = inet_addr(cp+1)) == (in_addr_t)-1)
option = '?';
memcpy(op, &in, INADDRSZ);
op += INADDRSZ;
new->len = 1;
new->val = safe_malloc(1);
*(new->val) = atoi(comma+1);
}
else
{
new->len = INADDRSZ * addrs;
new->val = op = safe_malloc(new->len);
new->is_addr = 1;
while (addrs--)
{
cp = comma;
if (cp && (comma = strchr(cp+1, ',')))
*comma = 0;
if (cp && (in.s_addr = inet_addr(cp+1)) == (in_addr_t)-1)
option = '?';
memcpy(op, &in, INADDRSZ);
op += INADDRSZ;
}
}
}
break;

View File

@@ -139,7 +139,7 @@ int dhcp_reply(struct dhcp_context *context, struct dhcp_packet *mess,
/* search again now we have a hostname */
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
def_time = config ? config->lease_time : context->lease_time;
def_time = config && config->lease_time ? config->lease_time : context->lease_time;
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
{
@@ -444,6 +444,9 @@ static unsigned char *do_req_options(struct dhcp_context *context,
if (!req_options)
return p;
if (in_list(req_options, OPTION_MAXMESSAGE))
p = option_put(p, end, OPTION_MAXMESSAGE, 2, sizeof(struct udp_dhcp_packet));
if (in_list(req_options, OPTION_NETMASK) &&
!option_find2(config_opts, OPTION_NETMASK))
p = option_put(p, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
@@ -484,12 +487,34 @@ static unsigned char *do_req_options(struct dhcp_context *context,
for (i = 0; req_options[i] != OPTION_END; i++)
{
struct dhcp_opt *opt = option_find2(config_opts, req_options[i]);
if (req_options[i] != OPTION_HOSTNAME && opt && (p + opt->len + 2 < end))
if (req_options[i] != OPTION_HOSTNAME &&
req_options[i] != OPTION_MAXMESSAGE &&
opt && (p + opt->len + 2 < end))
{
*(p++) = opt->opt;
*(p++) = opt->len;
memcpy(p, opt->val, opt->len);
p += opt->len;
if (opt->len != 0)
{
if (opt->is_addr)
{
int j;
struct in_addr *a = (struct in_addr *)opt->val;
for (j = 0; j < opt->len; j+=INADDRSZ, a++)
{
/* zero means "self" */
if (a->s_addr == 0)
memcpy(p, &context->serv_addr, INADDRSZ);
else
memcpy(p, a, INADDRSZ);
p += INADDRSZ;
}
}
else
{
memcpy(p, opt->val, opt->len);
p += opt->len;
}
}
}
}