mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
import of dnsmasq-2.15.tar.gz
This commit is contained in:
24
CHANGELOG
24
CHANGELOG
@@ -1190,3 +1190,27 @@ version 2.14
|
|||||||
|
|
||||||
Added "keep-in-foreground" option. Thanks to Sean
|
Added "keep-in-foreground" option. Thanks to Sean
|
||||||
MacLennan for the patch.
|
MacLennan for the patch.
|
||||||
|
|
||||||
|
version 2.15
|
||||||
|
Fixed NXDOMAIN/NODATA confusion for locally known
|
||||||
|
names. We now return a NODATA reponse for names which are
|
||||||
|
locally known. Now a query for (eg AAAA or MX) for a name
|
||||||
|
with an IPv4 address in /etc/hosts which fails upstream
|
||||||
|
will generate a NODATA response. Note that the query
|
||||||
|
is still tried upstream, but a NXDOMAIN reply gets
|
||||||
|
converted to NODATA. Thanks to Eric de Thouars, Eric
|
||||||
|
Spakman and Mike Mestnik for bug reports/testing.
|
||||||
|
|
||||||
|
Allow multiple dhcp-ranges within the same network. The
|
||||||
|
original intention was that there would be a dhcp-range
|
||||||
|
option for each network served, but there's no real reason
|
||||||
|
not to allow discontinuous ranges within a network so this
|
||||||
|
release adds support for that.
|
||||||
|
|
||||||
|
Check for dhcp-ranges which are inconsistent with their
|
||||||
|
netmask, and generate errors or warnings.
|
||||||
|
|
||||||
|
Improve error messages when there are problems with
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.14
|
Version: 2.15
|
||||||
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.14
|
Version: 2.15
|
||||||
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.14"
|
#define VERSION "2.15"
|
||||||
|
|
||||||
#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 */
|
||||||
|
|||||||
111
src/dhcp.c
111
src/dhcp.c
@@ -209,9 +209,19 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
|||||||
iface_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
iface_netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||||
|
|
||||||
if (iface_netmask.s_addr &&
|
if (iface_netmask.s_addr &&
|
||||||
is_same_net(iface_addr, context->start, iface_netmask) &&
|
(is_same_net(iface_addr, context->start, iface_netmask) ||
|
||||||
is_same_net(iface_addr, context->end, iface_netmask))
|
is_same_net(iface_addr, context->end, iface_netmask)))
|
||||||
context->netmask = iface_netmask;
|
{
|
||||||
|
context->netmask = iface_netmask;
|
||||||
|
if (!(is_same_net(iface_addr, context->start, iface_netmask) &&
|
||||||
|
is_same_net(iface_addr, context->end, iface_netmask)))
|
||||||
|
{
|
||||||
|
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
|
||||||
|
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
|
||||||
|
syslog(LOG_WARNING, "DHCP range %s -- %s is not consistent with netmask %s",
|
||||||
|
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(iface_netmask));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine "default" default routes. These are to this server or the relay agent.
|
/* Determine "default" default routes. These are to this server or the relay agent.
|
||||||
@@ -226,7 +236,8 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
|||||||
{
|
{
|
||||||
if (!iface_broadcast.s_addr && ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) != -1)
|
if (!iface_broadcast.s_addr && ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) != -1)
|
||||||
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
iface_broadcast = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||||
if (iface_broadcast.s_addr)
|
if (iface_broadcast.s_addr &&
|
||||||
|
is_same_net(iface_broadcast, context->start, context->netmask))
|
||||||
context->broadcast = iface_broadcast;
|
context->broadcast = iface_broadcast;
|
||||||
else
|
else
|
||||||
context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
|
context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
|
||||||
@@ -361,26 +372,23 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
|||||||
|
|
||||||
int address_available(struct dhcp_context *context, struct in_addr taddr)
|
int address_available(struct dhcp_context *context, struct in_addr taddr)
|
||||||
{
|
{
|
||||||
/* Check is an address is OK for this network, ie
|
/* Check is an address is OK for this network, check all
|
||||||
within allowable range and not in an existing lease */
|
possible ranges. */
|
||||||
|
|
||||||
unsigned int addr, start, end;
|
unsigned int start, end, addr = ntohl(taddr.s_addr);
|
||||||
|
|
||||||
/* static leases only. */
|
for (; context; context = context->current)
|
||||||
if (context->static_only)
|
{
|
||||||
return 0;
|
start = ntohl(context->start.s_addr);
|
||||||
|
end = ntohl(context->end.s_addr);
|
||||||
|
|
||||||
addr = ntohl(taddr.s_addr);
|
if (!context->static_only &&
|
||||||
start = ntohl(context->start.s_addr);
|
addr >= start &&
|
||||||
end = ntohl(context->end.s_addr);
|
addr <= end)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (addr < start)
|
return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (addr > end)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@@ -402,41 +410,40 @@ int address_allocate(struct dhcp_context *context, struct daemon *daemon,
|
|||||||
|
|
||||||
struct in_addr start, addr ;
|
struct in_addr start, addr ;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
/* check if no dynamic leases. */
|
|
||||||
if (context->static_only)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* pick a seed based on hwaddr then iterate until we find a free address. */
|
for (; context; context = context->current)
|
||||||
for (j = context->addr_epoch, i = 0; i < ETHER_ADDR_LEN; i++)
|
if (!context->static_only)
|
||||||
j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
|
|
||||||
|
|
||||||
start.s_addr = addr.s_addr =
|
|
||||||
htonl(ntohl(context->start.s_addr) +
|
|
||||||
(j % (1 + ntohl(context->end.s_addr) - ntohl(context->start.s_addr))));
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (!lease_find_by_addr(addr) &&
|
|
||||||
!config_find_by_address(daemon->dhcp_conf, addr))
|
|
||||||
{
|
{
|
||||||
if (icmp_ping(daemon, addr))
|
/* pick a seed based on hwaddr then iterate until we find a free address. */
|
||||||
/* perturb address selection so that we are
|
for (j = context->addr_epoch, i = 0; i < ETHER_ADDR_LEN; i++)
|
||||||
less likely to try this address again. */
|
j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16);
|
||||||
context->addr_epoch++;
|
|
||||||
else
|
start.s_addr = addr.s_addr =
|
||||||
{
|
htonl(ntohl(context->start.s_addr) +
|
||||||
*addrp = addr;
|
(j % (1 + ntohl(context->end.s_addr) - ntohl(context->start.s_addr))));
|
||||||
return 1;
|
|
||||||
}
|
do {
|
||||||
}
|
if (!lease_find_by_addr(addr) &&
|
||||||
|
!config_find_by_address(daemon->dhcp_conf, addr))
|
||||||
|
{
|
||||||
|
if (icmp_ping(daemon, addr))
|
||||||
|
/* perturb address selection so that we are
|
||||||
|
less likely to try this address again. */
|
||||||
|
context->addr_epoch++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*addrp = addr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
|
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
|
||||||
|
|
||||||
if (addr.s_addr == htonl(ntohl(context->end.s_addr) + 1))
|
if (addr.s_addr == htonl(ntohl(context->end.s_addr) + 1))
|
||||||
addr = context->start;
|
addr = context->start;
|
||||||
|
|
||||||
} while (addr.s_addr != start.s_addr);
|
} while (addr.s_addr != start.s_addr);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ struct dhcp_context {
|
|||||||
struct in_addr start, end; /* range of available addresses */
|
struct in_addr start, end; /* range of available addresses */
|
||||||
int static_only;
|
int static_only;
|
||||||
struct dhcp_netid netid;
|
struct dhcp_netid netid;
|
||||||
struct dhcp_context *next;
|
struct dhcp_context *next, *current;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef unsigned char u8;
|
typedef unsigned char u8;
|
||||||
@@ -393,11 +393,15 @@ int setup_reply(HEADER *header, unsigned int qlen,
|
|||||||
unsigned long local_ttl);
|
unsigned long local_ttl);
|
||||||
void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff,
|
void extract_addresses(HEADER *header, unsigned int qlen, char *namebuff,
|
||||||
time_t now, struct doctor *doctors);
|
time_t now, struct doctor *doctors);
|
||||||
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *namebuff, time_t now);
|
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *namebuff, time_t now, unsigned short flags);
|
||||||
int answer_request(HEADER *header, char *limit, unsigned int qlen, struct daemon *daemon, time_t now);
|
int answer_request(HEADER *header, char *limit, unsigned int qlen, struct daemon *daemon, time_t now);
|
||||||
int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name,
|
int check_for_bogus_wildcard(HEADER *header, unsigned int qlen, char *name,
|
||||||
struct bogus_addr *addr, time_t now);
|
struct bogus_addr *addr, time_t now);
|
||||||
unsigned char *find_pseudoheader(HEADER *header, unsigned int plen);
|
unsigned char *find_pseudoheader(HEADER *header, unsigned int plen,
|
||||||
|
unsigned int *len, unsigned char **p);
|
||||||
|
int check_for_local_domain(char *name, time_t now, struct mx_record *mx);
|
||||||
|
int resize_packet(HEADER *header, unsigned int plen,
|
||||||
|
unsigned char *pheader, unsigned int hlen);
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
unsigned short rand16(void);
|
unsigned short rand16(void);
|
||||||
|
|||||||
124
src/forward.c
124
src/forward.c
@@ -114,8 +114,8 @@ static void send_from(int fd, int nowild, char *packet, int len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short search_servers(struct daemon *daemon, struct all_addr **addrpp,
|
static unsigned short search_servers(struct daemon *daemon, time_t now, struct all_addr **addrpp,
|
||||||
unsigned short qtype, char *qdomain, int *type, char **domain)
|
unsigned short qtype, char *qdomain, int *type, char **domain)
|
||||||
|
|
||||||
{
|
{
|
||||||
/* If the query ends in the domain in one of our servers, set
|
/* If the query ends in the domain in one of our servers, set
|
||||||
@@ -133,19 +133,23 @@ unsigned short search_servers(struct daemon *daemon, struct all_addr **addrpp,
|
|||||||
{
|
{
|
||||||
unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
|
unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
|
||||||
*type = SERV_FOR_NODOTS;
|
*type = SERV_FOR_NODOTS;
|
||||||
flags = 0;
|
|
||||||
if (serv->flags & SERV_NO_ADDR)
|
if (serv->flags & SERV_NO_ADDR)
|
||||||
flags = F_NXDOMAIN;
|
flags = F_NXDOMAIN;
|
||||||
else if ((serv->flags & SERV_LITERAL_ADDRESS) && (sflag & qtype))
|
else if (serv->flags & SERV_LITERAL_ADDRESS)
|
||||||
{
|
{
|
||||||
flags = sflag;
|
if (sflag & qtype)
|
||||||
if (serv->addr.sa.sa_family == AF_INET)
|
{
|
||||||
*addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
|
flags = sflag;
|
||||||
|
if (serv->addr.sa.sa_family == AF_INET)
|
||||||
|
*addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
else
|
||||||
*addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
|
*addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else if (!flags)
|
||||||
|
flags = F_NOERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (serv->flags & SERV_HAS_DOMAIN)
|
else if (serv->flags & SERV_HAS_DOMAIN)
|
||||||
{
|
{
|
||||||
@@ -158,23 +162,27 @@ unsigned short search_servers(struct daemon *daemon, struct all_addr **addrpp,
|
|||||||
*type = SERV_HAS_DOMAIN;
|
*type = SERV_HAS_DOMAIN;
|
||||||
*domain = serv->domain;
|
*domain = serv->domain;
|
||||||
matchlen = domainlen;
|
matchlen = domainlen;
|
||||||
flags = 0;
|
|
||||||
if (serv->flags & SERV_NO_ADDR)
|
if (serv->flags & SERV_NO_ADDR)
|
||||||
flags = F_NXDOMAIN;
|
flags = F_NXDOMAIN;
|
||||||
else if ((serv->flags & SERV_LITERAL_ADDRESS) && ((sflag | F_QUERY ) & qtype))
|
else if (serv->flags & SERV_LITERAL_ADDRESS)
|
||||||
{
|
{
|
||||||
flags = qtype;
|
if ((sflag | F_QUERY ) & qtype)
|
||||||
if (serv->addr.sa.sa_family == AF_INET)
|
{
|
||||||
*addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
|
flags = qtype;
|
||||||
|
if (serv->addr.sa.sa_family == AF_INET)
|
||||||
|
*addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
else
|
||||||
*addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
|
*addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
else if (!flags)
|
||||||
|
flags = F_NOERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & ~F_NXDOMAIN) /* flags set here means a literal found */
|
if (flags & ~(F_NOERR | F_NXDOMAIN)) /* flags set here means a literal found */
|
||||||
{
|
{
|
||||||
if (flags & F_QUERY)
|
if (flags & F_QUERY)
|
||||||
log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL, 0);
|
log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL, 0);
|
||||||
@@ -182,9 +190,12 @@ unsigned short search_servers(struct daemon *daemon, struct all_addr **addrpp,
|
|||||||
log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0);
|
log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0);
|
||||||
}
|
}
|
||||||
else if (qtype && (daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.'))
|
else if (qtype && (daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.'))
|
||||||
|
flags = F_NXDOMAIN;
|
||||||
|
|
||||||
|
if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now, daemon->mxnames))
|
||||||
flags = F_NOERR;
|
flags = F_NOERR;
|
||||||
|
|
||||||
if (flags & (F_NOERR | F_NXDOMAIN))
|
if (flags == F_NXDOMAIN || flags == F_NOERR)
|
||||||
log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL, 0);
|
log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL, 0);
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
@@ -223,7 +234,7 @@ static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *ud
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (gotname)
|
if (gotname)
|
||||||
flags = search_servers(daemon, &addrp, gotname, daemon->namebuff, &type, &domain);
|
flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
|
||||||
|
|
||||||
if (!flags && !(forward = get_new_frec(now)))
|
if (!flags && !(forward = get_new_frec(now)))
|
||||||
/* table full - server failure. */
|
/* table full - server failure. */
|
||||||
@@ -316,20 +327,21 @@ static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *ud
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int process_reply(struct daemon *daemon, HEADER *header, time_t now,
|
static int process_reply(struct daemon *daemon, HEADER *header, time_t now,
|
||||||
union mysockaddr *serveraddr, int n)
|
union mysockaddr *serveraddr, unsigned int n)
|
||||||
{
|
{
|
||||||
unsigned char *pheader;
|
unsigned char *pheader, *sizep;
|
||||||
|
unsigned int plen;
|
||||||
|
|
||||||
/* If upstream is advertising a larger UDP packet size
|
/* If upstream is advertising a larger UDP packet size
|
||||||
than we allow, trim it so that we don't get overlarge
|
than we allow, trim it so that we don't get overlarge
|
||||||
requests for the client. */
|
requests for the client. */
|
||||||
|
|
||||||
if ((pheader = find_pseudoheader(header, n)))
|
if ((pheader = find_pseudoheader(header, n, &plen, &sizep)))
|
||||||
{
|
{
|
||||||
unsigned short udpsz;
|
unsigned short udpsz;
|
||||||
unsigned char *psave = pheader;
|
unsigned char *psave = sizep;
|
||||||
|
|
||||||
GETSHORT(udpsz, pheader);
|
GETSHORT(udpsz, sizep);
|
||||||
if (udpsz > daemon->edns_pktsz)
|
if (udpsz > daemon->edns_pktsz)
|
||||||
PUTSHORT(daemon->edns_pktsz, psave);
|
PUTSHORT(daemon->edns_pktsz, psave);
|
||||||
}
|
}
|
||||||
@@ -350,20 +362,52 @@ static int process_reply(struct daemon *daemon, HEADER *header, time_t now,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((header->rcode == NOERROR || header->rcode == NXDOMAIN) && header->opcode == QUERY)
|
if (header->opcode != QUERY || (header->rcode != NOERROR && header->rcode != NXDOMAIN))
|
||||||
|
return n;
|
||||||
|
|
||||||
|
if (header->rcode == NOERROR && ntohs(header->ancount) != 0)
|
||||||
{
|
{
|
||||||
if (!(daemon->bogus_addr &&
|
if (!(daemon->bogus_addr &&
|
||||||
header->rcode == NOERROR &&
|
check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now)))
|
||||||
check_for_bogus_wildcard(header, (unsigned int)n, daemon->namebuff, daemon->bogus_addr, now)))
|
extract_addresses(header, n, daemon->namebuff, now, daemon->doctors);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned short flags = F_NEG;
|
||||||
|
int munged = 0;
|
||||||
|
|
||||||
|
if (header->rcode == NXDOMAIN)
|
||||||
{
|
{
|
||||||
if (header->rcode == NOERROR && ntohs(header->ancount) != 0)
|
/* if we forwarded a query for a locally known name (because it was for
|
||||||
extract_addresses(header, (unsigned int)n, daemon->namebuff, now, daemon->doctors);
|
an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
|
||||||
else if (!(daemon->options & OPT_NO_NEG))
|
since we know that the domain exists, even if upstream doesn't */
|
||||||
extract_neg_addrs(header, (unsigned int)n, daemon->namebuff, now);
|
if (extract_request(header, n, daemon->namebuff, NULL) &&
|
||||||
|
check_for_local_domain(daemon->namebuff, now, daemon->mxnames))
|
||||||
|
{
|
||||||
|
munged = 1;
|
||||||
|
header->rcode = NOERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
flags |= F_NXDOMAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(daemon->options & OPT_NO_NEG))
|
||||||
|
extract_neg_addrs(header, n, daemon->namebuff, now, flags);
|
||||||
|
|
||||||
|
/* do this after extract_neg_addrs. Ensure NODATA reply and remove
|
||||||
|
nameserver info. */
|
||||||
|
if (munged)
|
||||||
|
{
|
||||||
|
header->ancount = htons(0);
|
||||||
|
header->nscount = htons(0);
|
||||||
|
header->arcount = htons(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
/* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
|
||||||
|
sections of the packet. Find the new length here and put back pseudoheader
|
||||||
|
if it was removed. */
|
||||||
|
return resize_packet(header, n, pheader, plen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sets new last_server */
|
/* sets new last_server */
|
||||||
@@ -401,7 +445,7 @@ void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process_reply(daemon, header, now, &serveraddr, n))
|
if ((n = process_reply(daemon, header, now, &serveraddr, (unsigned int)n)))
|
||||||
{
|
{
|
||||||
header->id = htons(forward->orig_id);
|
header->id = htons(forward->orig_id);
|
||||||
send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, n,
|
send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, n,
|
||||||
@@ -654,7 +698,7 @@ char *tcp_request(struct daemon *daemon, int confd, time_t now)
|
|||||||
char *domain = NULL;
|
char *domain = NULL;
|
||||||
|
|
||||||
if (gotname)
|
if (gotname)
|
||||||
flags = search_servers(daemon, &addrp, gotname, daemon->namebuff, &type, &domain);
|
flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain);
|
||||||
|
|
||||||
if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server)
|
if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server)
|
||||||
last_server = daemon->servers;
|
last_server = daemon->servers;
|
||||||
@@ -729,7 +773,7 @@ char *tcp_request(struct daemon *daemon, int confd, time_t now)
|
|||||||
/* There's no point in updating the cache, since this process will exit and
|
/* There's no point in updating the cache, since this process will exit and
|
||||||
lose the information after one query. We make this call for the alias and
|
lose the information after one query. We make this call for the alias and
|
||||||
bogus-nxdomain side-effects. */
|
bogus-nxdomain side-effects. */
|
||||||
process_reply(daemon, header, now, &last_server->addr, m);
|
m = process_reply(daemon, header, now, &last_server->addr, (unsigned int)m);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
57
src/option.c
57
src/option.c
@@ -161,7 +161,7 @@ static char *usage =
|
|||||||
struct daemon *read_opts (int argc, char **argv)
|
struct daemon *read_opts (int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct daemon *daemon = safe_malloc(sizeof(struct daemon));
|
struct daemon *daemon = safe_malloc(sizeof(struct daemon));
|
||||||
char *buff = safe_malloc(MAXDNAME);
|
char *problem = NULL, *buff = safe_malloc(MAXDNAME);
|
||||||
int option = 0, i;
|
int option = 0, i;
|
||||||
FILE *file_save = NULL, *f = NULL;
|
FILE *file_save = NULL, *f = NULL;
|
||||||
char *file_name_save = NULL, *conffile = CONFFILE;
|
char *file_name_save = NULL, *conffile = CONFFILE;
|
||||||
@@ -187,6 +187,8 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
problem = NULL;
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
option = getopt_long(argc, argv, OPTSTRING, (struct option *)opts, NULL);
|
option = getopt_long(argc, argv, OPTSTRING, (struct option *)opts, NULL);
|
||||||
@@ -302,7 +304,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
complain(buff, NULL);
|
complain(buff, NULL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case 'C':
|
case 'C':
|
||||||
@@ -366,7 +368,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
if (comma)
|
if (comma)
|
||||||
*(comma++) = 0;
|
*(comma++) = 0;
|
||||||
if (!canonicalise(optarg) || (comma && !canonicalise(comma)))
|
if (!canonicalise(optarg) || (comma && !canonicalise(comma)))
|
||||||
option = '?';
|
{
|
||||||
|
option = '?';
|
||||||
|
problem = "bad MX name";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct mx_record *new = safe_malloc(sizeof(struct mx_record));
|
struct mx_record *new = safe_malloc(sizeof(struct mx_record));
|
||||||
@@ -380,7 +385,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (!canonicalise(optarg))
|
if (!canonicalise(optarg))
|
||||||
option = '?';
|
{
|
||||||
|
option = '?';
|
||||||
|
problem = "bad MX target";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
daemon->mxtarget = safe_string_alloc(optarg);
|
daemon->mxtarget = safe_string_alloc(optarg);
|
||||||
break;
|
break;
|
||||||
@@ -391,7 +399,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
case 'H':
|
case 'H':
|
||||||
if (daemon->addn_hosts)
|
if (daemon->addn_hosts)
|
||||||
option = '?';
|
{
|
||||||
|
option = '?';
|
||||||
|
problem = "only one addn hosts file allowed";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
daemon->addn_hosts = safe_string_alloc(optarg);
|
daemon->addn_hosts = safe_string_alloc(optarg);
|
||||||
break;
|
break;
|
||||||
@@ -563,7 +574,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
*portno = 0;
|
*portno = 0;
|
||||||
if (!atoi_check(portno+1, &source_port))
|
if (!atoi_check(portno+1, &source_port))
|
||||||
option = '?';
|
{
|
||||||
|
option = '?';
|
||||||
|
problem = "bad port";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,7 +585,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
*portno = 0;
|
*portno = 0;
|
||||||
if (!atoi_check(portno+1, &serv_port))
|
if (!atoi_check(portno+1, &serv_port))
|
||||||
option = '?';
|
{
|
||||||
|
option = '?';
|
||||||
|
problem = "bad port";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -717,6 +734,8 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
new->netid.net = NULL;
|
new->netid.net = NULL;
|
||||||
new->static_only = 0;
|
new->static_only = 0;
|
||||||
|
|
||||||
|
problem = "bad dhcp-range";
|
||||||
|
|
||||||
for (cp = optarg; *cp; cp++)
|
for (cp = optarg; *cp; cp++)
|
||||||
if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9')))
|
if (!(*cp == ' ' || *cp == '.' || (*cp >='0' && *cp <= '9')))
|
||||||
break;
|
break;
|
||||||
@@ -755,6 +774,17 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
new->end = tmp;
|
new->end = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (option != '?' && k >= 3 && strchr(a[2], '.') &&
|
||||||
|
((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
|
||||||
|
{
|
||||||
|
leasepos = 3;
|
||||||
|
if (!is_same_net(new->start, new->end, new->netmask))
|
||||||
|
{
|
||||||
|
problem = "inconsistent DHCP range";
|
||||||
|
option = '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (option == '?')
|
if (option == '?')
|
||||||
{
|
{
|
||||||
free(new);
|
free(new);
|
||||||
@@ -762,11 +792,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
daemon->dhcp = new;
|
daemon->dhcp = new;
|
||||||
|
|
||||||
if (k >= 3 && strchr(a[2], '.') &&
|
|
||||||
((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
|
|
||||||
leasepos = 3;
|
|
||||||
|
|
||||||
if (k >= 4 && strchr(a[3], '.') &&
|
if (k >= 4 && strchr(a[3], '.') &&
|
||||||
((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
|
((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
|
||||||
leasepos = 4;
|
leasepos = 4;
|
||||||
@@ -955,6 +981,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
|
|
||||||
if (option == '?')
|
if (option == '?')
|
||||||
{
|
{
|
||||||
|
problem = "bad dhcp-host";
|
||||||
if (new->flags & CONFIG_NAME)
|
if (new->flags & CONFIG_NAME)
|
||||||
free(new->hostname);
|
free(new->hostname);
|
||||||
if (new->flags & CONFIG_CLID)
|
if (new->flags & CONFIG_CLID)
|
||||||
@@ -1003,6 +1030,7 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
if ((new->opt = atoi(optarg)) == 0)
|
if ((new->opt = atoi(optarg)) == 0)
|
||||||
{
|
{
|
||||||
option = '?';
|
option = '?';
|
||||||
|
problem = "bad dhcp-opt";
|
||||||
if (new->netid)
|
if (new->netid)
|
||||||
free(new->netid);
|
free(new->netid);
|
||||||
free(new);
|
free(new);
|
||||||
@@ -1203,11 +1231,12 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
sprintf(buff, "error at line %d of %s ", lineno, conffile);
|
sprintf(buff, "%s at line %d of %s ",
|
||||||
|
problem ? problem : "error", lineno, conffile);
|
||||||
complain(buff, NULL);
|
complain(buff, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
die("bad command line options: try --help.", NULL);
|
die("bad command line options: %s.", problem ? problem : "try --help");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -306,9 +306,44 @@ static unsigned char *skip_questions(HEADER *header, unsigned int plen)
|
|||||||
return ansp;
|
return ansp;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *find_pseudoheader(HEADER *header, unsigned int plen)
|
int resize_packet(HEADER *header, unsigned int plen, unsigned char *pheader, unsigned int hlen)
|
||||||
{
|
{
|
||||||
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. */
|
int i;
|
||||||
|
unsigned char *ansp = skip_questions(header, plen);
|
||||||
|
unsigned short rdlen;
|
||||||
|
|
||||||
|
if (!ansp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
i < (ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount));
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
if (!(ansp = skip_name(ansp, header, plen)))
|
||||||
|
return 0;
|
||||||
|
ansp += 8; /* type, class, TTL */
|
||||||
|
GETSHORT(rdlen, ansp);
|
||||||
|
if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
|
||||||
|
return 0;
|
||||||
|
ansp += rdlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore pseudoheader */
|
||||||
|
if (pheader && ntohs(header->arcount) == 0)
|
||||||
|
{
|
||||||
|
/* must use memmove, may overlap */
|
||||||
|
memmove(ansp, pheader, hlen);
|
||||||
|
header->arcount = htons(1);
|
||||||
|
ansp += hlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ansp - (unsigned char *)header;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *find_pseudoheader(HEADER *header, unsigned int plen, unsigned int *len, unsigned char **p)
|
||||||
|
{
|
||||||
|
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
|
||||||
|
also return length of pseudoheader in *len and pointer to the UDP size in *p */
|
||||||
|
|
||||||
int i, arcount = ntohs(header->arcount);
|
int i, arcount = ntohs(header->arcount);
|
||||||
unsigned char *ansp;
|
unsigned char *ansp;
|
||||||
@@ -330,7 +365,7 @@ unsigned char *find_pseudoheader(HEADER *header, unsigned int plen)
|
|||||||
|
|
||||||
for (i = 0; i < arcount; i++)
|
for (i = 0; i < arcount; i++)
|
||||||
{
|
{
|
||||||
unsigned char *save;
|
unsigned char *save, *start = ansp;
|
||||||
if (!(ansp = skip_name(ansp, header, plen)))
|
if (!(ansp = skip_name(ansp, header, plen)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -340,9 +375,15 @@ unsigned char *find_pseudoheader(HEADER *header, unsigned int plen)
|
|||||||
GETSHORT(rdlen, ansp);
|
GETSHORT(rdlen, ansp);
|
||||||
if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
|
if ((unsigned int)(ansp + rdlen - (unsigned char *)header) > plen)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (type == T_OPT)
|
ansp += rdlen;
|
||||||
return save;
|
if (type == T_OPT)
|
||||||
ansp += rdlen;
|
{
|
||||||
|
if (len)
|
||||||
|
*len = ansp - start;
|
||||||
|
if (p)
|
||||||
|
*p = save;
|
||||||
|
return start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -397,17 +438,13 @@ static unsigned char *add_text_record(unsigned int nameoffset, unsigned char *p,
|
|||||||
|
|
||||||
/* On receiving an NXDOMAIN or NODATA reply, determine which names are known
|
/* On receiving an NXDOMAIN or NODATA reply, determine which names are known
|
||||||
not to exist for negative caching. name if a working buffer passed in. */
|
not to exist for negative caching. name if a working buffer passed in. */
|
||||||
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now)
|
void extract_neg_addrs(HEADER *header, unsigned int qlen, char *name, time_t now, unsigned short flags)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
int i, found_soa = 0;
|
int i, found_soa = 0;
|
||||||
int qtype, qclass, rdlen;
|
int qtype, qclass, rdlen;
|
||||||
unsigned long ttl, minttl = 0;
|
unsigned long ttl, minttl = 0;
|
||||||
unsigned short flags = F_NEG;
|
|
||||||
|
|
||||||
if (header->rcode == NXDOMAIN)
|
|
||||||
flags |= F_NXDOMAIN;
|
|
||||||
|
|
||||||
/* there may be more than one question with some questions
|
/* there may be more than one question with some questions
|
||||||
answered. We don't generate negative entries from those. */
|
answered. We don't generate negative entries from those. */
|
||||||
if (ntohs(header->ancount) != 0)
|
if (ntohs(header->ancount) != 0)
|
||||||
@@ -555,7 +592,7 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *name,
|
|||||||
#endif
|
#endif
|
||||||
else if (qtype == T_PTR)
|
else if (qtype == T_PTR)
|
||||||
{
|
{
|
||||||
/* PTR record */
|
/* PTR record */
|
||||||
struct all_addr addr;
|
struct all_addr addr;
|
||||||
int name_encoding = in_arpa_name_2_addr(name, &addr);
|
int name_encoding = in_arpa_name_2_addr(name, &addr);
|
||||||
if (name_encoding)
|
if (name_encoding)
|
||||||
@@ -735,7 +772,22 @@ int setup_reply(HEADER *header, unsigned int qlen,
|
|||||||
|
|
||||||
return p - (unsigned char *)header;
|
return p - (unsigned char *)header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
|
||||||
|
int check_for_local_domain(char *name, time_t now, struct mx_record *mx)
|
||||||
|
{
|
||||||
|
struct crec *crecp;
|
||||||
|
|
||||||
|
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4|F_IPV6)) &&
|
||||||
|
(crecp->flags & (F_HOSTS | F_DHCP)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (; mx; mx = mx->next)
|
||||||
|
if (hostname_isequal(name, mx->mxname))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is the packet a reply with the answer address equal to addr?
|
/* Is the packet a reply with the answer address equal to addr?
|
||||||
If so mung is into an NXDOMAIN reply and also put that information
|
If so mung is into an NXDOMAIN reply and also put that information
|
||||||
@@ -811,7 +863,7 @@ int answer_request(HEADER *header, char *limit, unsigned int qlen, struct daemon
|
|||||||
forward rather than answering from the cache, which doesn't include
|
forward rather than answering from the cache, which doesn't include
|
||||||
security information. */
|
security information. */
|
||||||
|
|
||||||
if ((pheader = find_pseudoheader(header, qlen)))
|
if (find_pseudoheader(header, qlen, NULL, &pheader))
|
||||||
{
|
{
|
||||||
unsigned short udpsz, ext_rcode, flags;
|
unsigned short udpsz, ext_rcode, flags;
|
||||||
unsigned char *psave = pheader;
|
unsigned char *psave = pheader;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ static int have_config(struct dhcp_config *config, unsigned int mask)
|
|||||||
|
|
||||||
int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_name, unsigned int sz, time_t now)
|
int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_name, unsigned int sz, time_t now)
|
||||||
{
|
{
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context, *context_tmp;
|
||||||
unsigned char *opt, *clid;
|
unsigned char *opt, *clid;
|
||||||
struct dhcp_lease *lease, *ltmp;
|
struct dhcp_lease *lease, *ltmp;
|
||||||
struct dhcp_vendor *vendor;
|
struct dhcp_vendor *vendor;
|
||||||
@@ -148,12 +148,25 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
subnet_addr.s_addr ? subnet_addr :
|
subnet_addr.s_addr ? subnet_addr :
|
||||||
(mess->giaddr.s_addr ? mess->giaddr :
|
(mess->giaddr.s_addr ? mess->giaddr :
|
||||||
(mess->ciaddr.s_addr ? mess->ciaddr : iface_addr));
|
(mess->ciaddr.s_addr ? mess->ciaddr : iface_addr));
|
||||||
|
|
||||||
for (context = daemon->dhcp; context; context = context->next)
|
/* More than one context may match, we build a chain of them all on ->current
|
||||||
if (context->netmask.s_addr &&
|
Note that if netmasks, netid or lease times don't match, odd things may happen. */
|
||||||
is_same_net(addr, context->start, context->netmask) &&
|
|
||||||
is_same_net(addr, context->end, context->netmask))
|
for (context = NULL, context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
|
||||||
break;
|
if (context_tmp->netmask.s_addr &&
|
||||||
|
is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
|
||||||
|
is_same_net(addr, context_tmp->end, context_tmp->netmask))
|
||||||
|
{
|
||||||
|
context_tmp->current = context;
|
||||||
|
context = context_tmp;
|
||||||
|
|
||||||
|
/* start to build netid chain */
|
||||||
|
if (context_tmp->netid.net)
|
||||||
|
{
|
||||||
|
context_tmp->netid.next = netid;
|
||||||
|
netid = &context_tmp->netid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
{
|
{
|
||||||
@@ -164,14 +177,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
mess->op = BOOTREPLY;
|
mess->op = BOOTREPLY;
|
||||||
|
|
||||||
/* start to build netid chain */
|
|
||||||
if (context->netid.net)
|
|
||||||
{
|
|
||||||
context->netid.next = netid;
|
|
||||||
netid = &context->netid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mess_type == 0)
|
if (mess_type == 0)
|
||||||
{
|
{
|
||||||
/* BOOTP request */
|
/* BOOTP request */
|
||||||
@@ -268,14 +274,12 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def_time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
|
||||||
|
|
||||||
if (have_config(config, CONFIG_NETID))
|
if (have_config(config, CONFIG_NETID))
|
||||||
{
|
{
|
||||||
config->netid.next = netid;
|
config->netid.next = netid;
|
||||||
netid = &config->netid;
|
netid = &config->netid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Theres a chance that carefully chosen data could match the same
|
/* Theres a chance that carefully chosen data could match the same
|
||||||
vendor/user option twice and make a loop in the netid chain. */
|
vendor/user option twice and make a loop in the netid chain. */
|
||||||
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
||||||
@@ -326,10 +330,12 @@ 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);
|
||||||
|
|
||||||
|
def_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)))
|
||||||
{
|
{
|
||||||
unsigned int req_time = option_uint(opt, 4);
|
unsigned int req_time = option_uint(opt, 4);
|
||||||
|
|
||||||
if (def_time == 0xffffffff ||
|
if (def_time == 0xffffffff ||
|
||||||
(req_time != 0xffffffff && req_time < def_time))
|
(req_time != 0xffffffff && req_time < def_time))
|
||||||
expires_time = renewal_time = req_time;
|
expires_time = renewal_time = req_time;
|
||||||
@@ -392,7 +398,8 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* make sure this host gets a different address next time. */
|
/* make sure this host gets a different address next time. */
|
||||||
context->addr_epoch++;
|
for (; context; context = context->current)
|
||||||
|
context->addr_epoch++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user