mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.19.tar.gz
This commit is contained in:
18
CHANGELOG
18
CHANGELOG
@@ -1307,8 +1307,22 @@ version 2.18
|
|||||||
Enable long command line options on FreeBSD when the
|
Enable long command line options on FreeBSD when the
|
||||||
C library supports them.
|
C library supports them.
|
||||||
|
|
||||||
|
version 2.19
|
||||||
|
Tweaked the Linux-only interface discovery code to cope
|
||||||
|
with interface-indexes larger than 8 bits in
|
||||||
|
/proc/net/if_inet6. This only affects Linux, obviously.
|
||||||
|
Thanks to Richard Atterer for the bug report.
|
||||||
|
|
||||||
|
Check for under-length option fields in DHCP packets, a
|
||||||
|
zero length client-id, in particluar, could seriously
|
||||||
|
confuse dnsmasq 'till now. Thanks to Will Murname for help
|
||||||
|
with that.
|
||||||
|
|
||||||
|
If a DHCP-allocated address has an associated name in
|
||||||
|
/etc/hosts, and the client does not provide a hostname
|
||||||
|
parameter and there is no hostname in a matching dhcp-host
|
||||||
|
option, send the /etc/hosts name as the hostname in
|
||||||
|
the DHCP lease. Thanks to Will Murname for the suggestion.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
19
FAQ
19
FAQ
@@ -115,7 +115,7 @@ A: Resolver code sometime does strange things when given names without
|
|||||||
--expand-hosts and --domain-suffix options.
|
--expand-hosts and --domain-suffix options.
|
||||||
|
|
||||||
Q: Can I get dnsmasq to save the contents of its cache to disk when
|
Q: Can I get dnsmasq to save the contents of its cache to disk when
|
||||||
I shut my machine down and re-load when it starts again.
|
I shut my machine down and re-load when it starts again?
|
||||||
|
|
||||||
A: No, that facility is not provided. Very few names in the DNS have
|
A: No, that facility is not provided. Very few names in the DNS have
|
||||||
their time-to-live set for longer than a few hours so most of the
|
their time-to-live set for longer than a few hours so most of the
|
||||||
@@ -299,7 +299,22 @@ A: Because when a Gentoo box shuts down, it releases its lease with
|
|||||||
dnsmasq ignores it until is times out and restarts the process.
|
dnsmasq ignores it until is times out and restarts the process.
|
||||||
To fix this, set the dhcp-authoritative flag in dnsmasq.
|
To fix this, set the dhcp-authoritative flag in dnsmasq.
|
||||||
|
|
||||||
|
Q: My laptop has two network interfaces, a wired one and a wireless
|
||||||
|
one. I never use both interfaces at the same time, and I'd like the
|
||||||
|
same IP and configuration to be used irrespcetive of which
|
||||||
|
interface is in use. How can I do that.
|
||||||
|
|
||||||
|
A: By default, the identity of a machine is determined by using the
|
||||||
|
MAC address, which is associated with interface hardware. Once an
|
||||||
|
IP is bound to the MAC address of one interface, it cannot be
|
||||||
|
associated with another MAC address until after the DHCP lease
|
||||||
|
expires. The solution to this is to use a client-id as the machine
|
||||||
|
identity rather than the MAC address. If you arrange for the same
|
||||||
|
client-id to sent when either interface is in use, the DHCP server
|
||||||
|
will recognise the same machine, and use the same address. The
|
||||||
|
method for setting the client-id varies with DHCP client software,
|
||||||
|
dhcpcd uses the "-I" flag. Windows uses a registry setting,
|
||||||
|
see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.18
|
Version: 2.19
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.18
|
Version: 2.19
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: Productivity/Networking/DNS/Servers
|
Group: Productivity/Networking/DNS/Servers
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/* Author's email: simon@thekelleys.org.uk */
|
/* Author's email: simon@thekelleys.org.uk */
|
||||||
|
|
||||||
#define VERSION "2.18"
|
#define VERSION "2.19"
|
||||||
|
|
||||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||||
|
|||||||
38
src/dhcp.c
38
src/dhcp.c
@@ -656,3 +656,41 @@ 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
|
||||||
|
for this address. If it has a domain part, that must match the set domain and
|
||||||
|
it gets stripped. */
|
||||||
|
char *host_from_dns(struct daemon *daemon, struct in_addr addr)
|
||||||
|
{
|
||||||
|
struct crec *lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
|
||||||
|
char *hostname = NULL;
|
||||||
|
|
||||||
|
if (lookup && (lookup->flags & F_HOSTS))
|
||||||
|
{
|
||||||
|
hostname = daemon->dhcp_buff;
|
||||||
|
hostname[256] = 0;
|
||||||
|
strncpy(hostname, cache_get_name(lookup), 256);
|
||||||
|
hostname = strip_hostname(daemon, hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strip_hostname(struct daemon *daemon, char *hostname)
|
||||||
|
{
|
||||||
|
char *dot = strchr(hostname, '.');
|
||||||
|
if (dot)
|
||||||
|
{
|
||||||
|
if (!daemon->domain_suffix || !hostname_isequal(dot+1, daemon->domain_suffix))
|
||||||
|
{
|
||||||
|
syslog(LOG_WARNING, "Ignoring DHCP host name %s because it has an illegal domain part", hostname);
|
||||||
|
hostname = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*dot = 0; /* truncate */
|
||||||
|
if (strlen(hostname) == 0)
|
||||||
|
hostname = NULL; /* nothing left */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|||||||
@@ -478,6 +478,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
void dhcp_update_configs(struct dhcp_config *configs);
|
void dhcp_update_configs(struct dhcp_config *configs);
|
||||||
void dhcp_read_ethers(struct daemon *daemon);
|
void dhcp_read_ethers(struct daemon *daemon);
|
||||||
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
|
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
|
||||||
|
char *strip_hostname(struct daemon *daemon, char *hostname);
|
||||||
|
char *host_from_dns(struct daemon *daemon, struct in_addr addr);
|
||||||
|
|
||||||
/* lease.c */
|
/* lease.c */
|
||||||
void lease_update_file(int force, time_t now);
|
void lease_update_file(int force, time_t now);
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ struct irec *enumerate_interfaces(struct daemon *daemon)
|
|||||||
unsigned int plen, scope, flags, if_idx;
|
unsigned int plen, scope, flags, if_idx;
|
||||||
char devname[20], addrstring[32];
|
char devname[20], addrstring[32];
|
||||||
|
|
||||||
while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
|
while (fscanf(f, "%32s %x %x %x %x %20s\n",
|
||||||
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
|
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -199,9 +199,7 @@ struct irec *enumerate_interfaces(struct daemon *daemon)
|
|||||||
strncpy(sifr.ifr_name, devname, IF_NAMESIZE);
|
strncpy(sifr.ifr_name, devname, IF_NAMESIZE);
|
||||||
if (ioctl(fd, SIOCGIFFLAGS, &sifr) < 0)
|
if (ioctl(fd, SIOCGIFFLAGS, &sifr) < 0)
|
||||||
die("ioctl error getting interface flags: %m", NULL);
|
die("ioctl error getting interface flags: %m", NULL);
|
||||||
|
|
||||||
iface = add_iface(daemon, iface, sifr.ifr_name, sifr.ifr_flags & IFF_LOOPBACK, &addr);
|
iface = add_iface(daemon, iface, sifr.ifr_name, sifr.ifr_flags & IFF_LOOPBACK, &addr);
|
||||||
|
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ static unsigned char *option_end(unsigned char *p, unsigned char *end, struct dh
|
|||||||
static unsigned char *option_put_string(unsigned char *p, unsigned char *end, int opt, char *string);
|
static unsigned char *option_put_string(unsigned char *p, unsigned char *end, int opt, char *string);
|
||||||
static void bootp_option_put(struct dhcp_packet *mess,
|
static void bootp_option_put(struct dhcp_packet *mess,
|
||||||
struct dhcp_boot *boot_opts, struct dhcp_netid *netids);
|
struct dhcp_boot *boot_opts, struct dhcp_netid *netids);
|
||||||
static int option_len(unsigned char *opt);
|
static unsigned int option_len(unsigned char *opt);
|
||||||
static void *option_ptr(unsigned char *opt);
|
static void *option_ptr(unsigned char *opt);
|
||||||
static struct in_addr option_addr(unsigned char *opt);
|
static struct in_addr option_addr(unsigned char *opt);
|
||||||
static unsigned int option_uint(unsigned char *opt, int size);
|
static unsigned int option_uint(unsigned char *opt, int size);
|
||||||
static void log_packet(char *type, struct in_addr *addr, unsigned char *hwaddr, char *interface, char *string);
|
static void log_packet(char *type, struct in_addr *addr, unsigned char *hwaddr, char *interface, char *string);
|
||||||
static int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool);
|
static int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool);
|
||||||
static unsigned char *option_find(struct dhcp_packet *mess, int size, int opt_type);
|
static unsigned char *option_find(struct dhcp_packet *mess, int size, int opt_type, unsigned int minsize);
|
||||||
static unsigned char *do_req_options(struct dhcp_context *context,
|
static unsigned char *do_req_options(struct dhcp_context *context,
|
||||||
unsigned char *p, unsigned char *end,
|
unsigned char *p, unsigned char *end,
|
||||||
unsigned char *req_options,
|
unsigned char *req_options,
|
||||||
@@ -126,7 +126,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* check for DHCP rather than BOOTP */
|
/* check for DHCP rather than BOOTP */
|
||||||
if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE)))
|
if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
|
||||||
{
|
{
|
||||||
mess_type = option_uint(opt, 1);
|
mess_type = option_uint(opt, 1);
|
||||||
|
|
||||||
@@ -136,18 +136,18 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
|
|
||||||
/* Some buggy clients set ciaddr when they shouldn't, so clear that here since
|
/* Some buggy clients set ciaddr when they shouldn't, so clear that here since
|
||||||
it can affect the context-determination code. */
|
it can affect the context-determination code. */
|
||||||
if ((option_find(mess, sz, OPTION_REQUESTED_IP) || mess_type == DHCPDISCOVER))
|
if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
|
||||||
mess->ciaddr.s_addr = 0;
|
mess->ciaddr.s_addr = 0;
|
||||||
|
|
||||||
/* Check for RFC3011 subnet selector */
|
/* Check for RFC3011 subnet selector */
|
||||||
if ((opt = option_find(mess, sz, OPTION_SUBNET_SELECT)))
|
if ((opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
|
||||||
subnet_addr = option_addr(opt);
|
subnet_addr = option_addr(opt);
|
||||||
|
|
||||||
/* If there is no client identifier option, use the hardware address */
|
/* If there is no client identifier option, use the hardware address */
|
||||||
if ((opt = option_find(mess, sz, OPTION_CLIENT_ID)))
|
if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
|
||||||
{
|
{
|
||||||
clid = option_ptr(opt);
|
|
||||||
clid_len = option_len(opt);
|
clid_len = option_len(opt);
|
||||||
|
clid = option_ptr(opt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
clid = mess->chaddr;
|
clid = mess->chaddr;
|
||||||
@@ -253,9 +253,9 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
|
|
||||||
if (have_config(config, CONFIG_NAME))
|
if (have_config(config, CONFIG_NAME))
|
||||||
hostname = config->hostname;
|
hostname = config->hostname;
|
||||||
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME)))
|
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
|
||||||
{
|
{
|
||||||
int len = option_len(opt);
|
unsigned int len = option_len(opt);
|
||||||
hostname = daemon->dhcp_buff;
|
hostname = daemon->dhcp_buff;
|
||||||
memcpy(hostname, option_ptr(opt), len);
|
memcpy(hostname, option_ptr(opt), len);
|
||||||
/* May not be zero terminated */
|
/* May not be zero terminated */
|
||||||
@@ -263,33 +263,14 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
/* ensure there are no strange chars in there */
|
/* ensure there are no strange chars in there */
|
||||||
if (!canonicalise(hostname))
|
if (!canonicalise(hostname))
|
||||||
hostname = NULL;
|
hostname = NULL;
|
||||||
else
|
else if ((hostname = strip_hostname(daemon, hostname)) && !config)
|
||||||
{
|
{
|
||||||
char *dot = strchr(hostname, '.');
|
|
||||||
if (dot)
|
|
||||||
{
|
|
||||||
if (!daemon->domain_suffix || !hostname_isequal(dot+1, daemon->domain_suffix))
|
|
||||||
{
|
|
||||||
syslog(LOG_WARNING, "Ignoring DHCP host name %s because it has an illegal domain part", hostname);
|
|
||||||
hostname = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*dot = 0; /* truncate */
|
|
||||||
if (strlen(hostname) == 0)
|
|
||||||
hostname = NULL; /* nothing left */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search again now we have a hostname.
|
/* Search again now we have a hostname.
|
||||||
Only accept configs without CLID and HWADDR here, (they won't match)
|
Only accept configs without CLID and HWADDR here, (they won't match)
|
||||||
to avoid impersonation by name. */
|
to avoid impersonation by name. */
|
||||||
if (!config)
|
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0, mess->chaddr, hostname);
|
||||||
{
|
if (!have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
|
||||||
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0, mess->chaddr, hostname);
|
config = new;
|
||||||
if (!have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
|
|
||||||
config = new;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,10 +288,10 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
assume that the option is a single string and non RFC3004 compliant
|
assume that the option is a single string and non RFC3004 compliant
|
||||||
and just do the substring match. dhclient provides these broken options. */
|
and just do the substring match. dhclient provides these broken options. */
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_USER_CLASS)))
|
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
|
||||||
{
|
{
|
||||||
unsigned char *ucp = option_ptr(opt);
|
unsigned char *ucp = option_ptr(opt);
|
||||||
int tmp, j;
|
unsigned int tmp, j;
|
||||||
for (j = 0; j < option_len(opt); j += ucp[j] + 1);
|
for (j = 0; j < option_len(opt); j += ucp[j] + 1);
|
||||||
if (j == option_len(opt))
|
if (j == option_len(opt))
|
||||||
for (j = 0; j < option_len(opt); j = tmp)
|
for (j = 0; j < option_len(opt); j = tmp)
|
||||||
@@ -321,9 +302,9 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
||||||
if ((opt = option_find(mess, sz, vendor->is_vendor ? OPTION_VENDOR_ID : OPTION_USER_CLASS)))
|
if ((opt = option_find(mess, sz, vendor->is_vendor ? OPTION_VENDOR_ID : OPTION_USER_CLASS, 1)))
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i;
|
||||||
for (i = 0; i <= (option_len(opt) - vendor->len); i++)
|
for (i = 0; i <= (option_len(opt) - vendor->len); i++)
|
||||||
if (memcmp(vendor->data, option_ptr(opt)+i, vendor->len) == 0)
|
if (memcmp(vendor->data, option_ptr(opt)+i, vendor->len) == 0)
|
||||||
{
|
{
|
||||||
@@ -348,23 +329,22 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
/* do we have a lease in store? */
|
/* do we have a lease in store? */
|
||||||
lease = lease_find_by_client(clid, clid_len);
|
lease = lease_find_by_client(clid, clid_len);
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS)))
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
|
||||||
{
|
{
|
||||||
int len = option_len(opt);
|
|
||||||
req_options = daemon->dhcp_buff2;
|
req_options = daemon->dhcp_buff2;
|
||||||
memcpy(req_options, option_ptr(opt), len);
|
memcpy(req_options, option_ptr(opt), option_len(opt));
|
||||||
req_options[len] = OPTION_END;
|
req_options[option_len(opt)] = OPTION_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mess_type)
|
switch (mess_type)
|
||||||
{
|
{
|
||||||
case DHCPDECLINE:
|
case DHCPDECLINE:
|
||||||
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER)) ||
|
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||||
(iface_addr.s_addr != option_addr(opt).s_addr))
|
(iface_addr.s_addr != option_addr(opt).s_addr))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* sanitise any message. Paranoid? Moi? */
|
/* sanitise any message. Paranoid? Moi? */
|
||||||
if ((opt = option_find(mess, sz, OPTION_MESSAGE)))
|
if ((opt = option_find(mess, sz, OPTION_MESSAGE, 1)))
|
||||||
{
|
{
|
||||||
char *p = option_ptr(opt), *q = daemon->dhcp_buff;
|
char *p = option_ptr(opt), *q = daemon->dhcp_buff;
|
||||||
int i;
|
int i;
|
||||||
@@ -379,7 +359,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
message = daemon->dhcp_buff;
|
message = daemon->dhcp_buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
log_packet("DECLINE", option_ptr(opt), mess->chaddr, iface_name, message);
|
log_packet("DECLINE", option_ptr(opt), mess->chaddr, iface_name, message);
|
||||||
@@ -401,7 +381,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case DHCPRELEASE:
|
case DHCPRELEASE:
|
||||||
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER)) ||
|
if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
|
||||||
(iface_addr.s_addr != option_addr(opt).s_addr))
|
(iface_addr.s_addr != option_addr(opt).s_addr))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -415,7 +395,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case DHCPDISCOVER:
|
case DHCPDISCOVER:
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||||
addr = option_addr(opt);
|
addr = option_addr(opt);
|
||||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||||
message = "ignored";
|
message = "ignored";
|
||||||
@@ -442,7 +422,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||||
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME, 4)))
|
||||||
{
|
{
|
||||||
unsigned int req_time = option_uint(opt, 4);
|
unsigned int req_time = option_uint(opt, 4);
|
||||||
if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
|
if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
|
||||||
@@ -472,12 +452,12 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
case DHCPREQUEST:
|
case DHCPREQUEST:
|
||||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||||
return 0;
|
return 0;
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP)))
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||||
{
|
{
|
||||||
/* SELECTING or INIT_REBOOT */
|
/* SELECTING or INIT_REBOOT */
|
||||||
mess->yiaddr = option_addr(opt);
|
mess->yiaddr = option_addr(opt);
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER)))
|
if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
|
||||||
{
|
{
|
||||||
/* SELECTING */
|
/* SELECTING */
|
||||||
if (iface_addr.s_addr != option_addr(opt).s_addr)
|
if (iface_addr.s_addr != option_addr(opt).s_addr)
|
||||||
@@ -569,7 +549,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||||
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME, 4)))
|
||||||
{
|
{
|
||||||
unsigned int req_time = option_uint(opt, 4);
|
unsigned int req_time = option_uint(opt, 4);
|
||||||
if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
|
if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
|
||||||
@@ -577,6 +557,8 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
lease_set_hwaddr(lease, mess->chaddr);
|
lease_set_hwaddr(lease, mess->chaddr);
|
||||||
|
if (!hostname)
|
||||||
|
hostname = host_from_dns(daemon, mess->yiaddr);
|
||||||
if (hostname)
|
if (hostname)
|
||||||
lease_set_hostname(lease, hostname, daemon->domain_suffix);
|
lease_set_hostname(lease, hostname, daemon->domain_suffix);
|
||||||
lease_set_expires(lease, time == 0xffffffff ? 0 : now + (time_t)time);
|
lease_set_expires(lease, time == 0xffffffff ? 0 : now + (time_t)time);
|
||||||
@@ -620,6 +602,8 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
bootp_option_put(mess, daemon->boot_config, netid);
|
bootp_option_put(mess, daemon->boot_config, netid);
|
||||||
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
p = option_put(p, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(iface_addr.s_addr));
|
||||||
|
if (!hostname)
|
||||||
|
hostname = host_from_dns(daemon, mess->yiaddr);
|
||||||
p = do_req_options(context, p, end, req_options, daemon,
|
p = do_req_options(context, p, end, req_options, daemon,
|
||||||
hostname, iface_addr, netid, subnet_addr);
|
hostname, iface_addr, netid, subnet_addr);
|
||||||
p = option_end(p, end, mess);
|
p = option_end(p, end, mess);
|
||||||
@@ -644,7 +628,7 @@ static void log_packet(char *type, struct in_addr *addr, unsigned char *hwaddr,
|
|||||||
string ? string : "");
|
string ? string : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int option_len(unsigned char *opt)
|
static unsigned int option_len(unsigned char *opt)
|
||||||
{
|
{
|
||||||
return opt[1];
|
return opt[1];
|
||||||
}
|
}
|
||||||
@@ -756,13 +740,13 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
|||||||
|
|
||||||
while (*p != OPTION_END)
|
while (*p != OPTION_END)
|
||||||
{
|
{
|
||||||
if (end && (p >= end))
|
if (p >= end)
|
||||||
return 0; /* malformed packet */
|
return 0; /* malformed packet */
|
||||||
else if (*p == OPTION_PAD)
|
else if (*p == OPTION_PAD)
|
||||||
p++;
|
p++;
|
||||||
else if (*p == OPTION_OVERLOAD)
|
else if (*p == OPTION_OVERLOAD)
|
||||||
{
|
{
|
||||||
if (end && (p >= end - 3))
|
if (p >= end - 3)
|
||||||
return 0; /* malformed packet */
|
return 0; /* malformed packet */
|
||||||
if (overload)
|
if (overload)
|
||||||
*overload = *(p+2);
|
*overload = *(p+2);
|
||||||
@@ -771,10 +755,10 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int opt_len;;
|
int opt_len;;
|
||||||
if (end && (p >= end - 2))
|
if (p >= end - 2)
|
||||||
return 0; /* malformed packet */
|
return 0; /* malformed packet */
|
||||||
opt_len = option_len(p);
|
opt_len = option_len(p);
|
||||||
if (end && (p >= end - (2 + opt_len)))
|
if (p >= end - (2 + opt_len))
|
||||||
return 0; /* malformed packet */
|
return 0; /* malformed packet */
|
||||||
if (*p == opt)
|
if (*p == opt)
|
||||||
return p;
|
return p;
|
||||||
@@ -785,7 +769,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *option_find(struct dhcp_packet *mess, int size, int opt_type)
|
static unsigned char *option_find(struct dhcp_packet *mess, int size, int opt_type, unsigned int minsize)
|
||||||
{
|
{
|
||||||
int overload = 0;
|
int overload = 0;
|
||||||
unsigned char *ret;
|
unsigned char *ret;
|
||||||
@@ -799,6 +783,10 @@ static unsigned char *option_find(struct dhcp_packet *mess, int size, int opt_ty
|
|||||||
if (!ret && (overload & 2))
|
if (!ret && (overload & 2))
|
||||||
ret = option_find1(&mess->sname[0], &mess->file[64], opt_type, &overload);
|
ret = option_find1(&mess->sname[0], &mess->file[64], opt_type, &overload);
|
||||||
|
|
||||||
|
/* Check the option field is big enough */
|
||||||
|
if (ret && (option_len(ret) < minsize))
|
||||||
|
ret = NULL;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user