mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.18.tar.gz
This commit is contained in:
22
CHANGELOG
22
CHANGELOG
@@ -1288,9 +1288,29 @@ version 2.17
|
|||||||
clients. Credit to Cedric Duval for spotting this.
|
clients. Credit to Cedric Duval for spotting this.
|
||||||
|
|
||||||
Fix rare crash associated with long DNS names and CNAME
|
Fix rare crash associated with long DNS names and CNAME
|
||||||
records. Thanks to Holger_Hoffstatte and especially Steve
|
records. Thanks to Holger Hoffstatte and especially Steve
|
||||||
Grecni for help chasing that one down.
|
Grecni for help chasing that one down.
|
||||||
|
|
||||||
|
version 2.18
|
||||||
|
Reworked the Linux interface discovery code (again) to
|
||||||
|
cope with interfaces which have only IPv6 addresses and
|
||||||
|
interfaces with more than one IPv6 address. Thanks to
|
||||||
|
Martin Pels for help with that.
|
||||||
|
|
||||||
|
Fix problems which occured when more than one dhcp-range
|
||||||
|
was specified in the same subnet: sometimes parameters
|
||||||
|
(lease time, network-id tag) from the wrong one would be
|
||||||
|
used. Thanks to Rory Campbell-Lange for the bug report.
|
||||||
|
|
||||||
|
Reset cache statistics when clearing the cache.
|
||||||
|
|
||||||
|
Enable long command line options on FreeBSD when the
|
||||||
|
C library supports them.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Name: dnsmasq
|
Name: dnsmasq
|
||||||
Version: 2.17
|
Version: 2.18
|
||||||
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.17
|
Version: 2.18
|
||||||
Release: 1
|
Release: 1
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: Productivity/Networking/DNS/Servers
|
Group: Productivity/Networking/DNS/Servers
|
||||||
|
|||||||
@@ -602,6 +602,8 @@ void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *a
|
|||||||
struct crec *cache, **up, *tmp;
|
struct crec *cache, **up, *tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
cache_inserted = cache_live_freed = 0;
|
||||||
|
|
||||||
for (i=0; i<hash_size; i++)
|
for (i=0; i<hash_size; i++)
|
||||||
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
|
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
|
||||||
{
|
{
|
||||||
|
|||||||
17
src/config.h
17
src/config.h
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2004 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/* Author's email: simon@thekelleys.org.uk */
|
/* Author's email: simon@thekelleys.org.uk */
|
||||||
|
|
||||||
#define VERSION "2.17"
|
#define VERSION "2.18"
|
||||||
|
|
||||||
#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 */
|
||||||
@@ -180,7 +180,7 @@ NOTES:
|
|||||||
HAVE_DEV_URANDOM - OpenBSD and FreeBSD and NetBSD
|
HAVE_DEV_URANDOM - OpenBSD and FreeBSD and NetBSD
|
||||||
HAVE_DEV_RANDOM - FreeBSD and NetBSD
|
HAVE_DEV_RANDOM - FreeBSD and NetBSD
|
||||||
(OpenBSD with hardware random number generator)
|
(OpenBSD with hardware random number generator)
|
||||||
HAVE_GETOPT_LONG - NetBSD
|
HAVE_GETOPT_LONG - NetBSD, later FreeBSD
|
||||||
(FreeBSD and OpenBSD only if you link GNU getopt)
|
(FreeBSD and OpenBSD only if you link GNU getopt)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -205,8 +205,10 @@ NOTES:
|
|||||||
#define HAVE_DEV_RANDOM
|
#define HAVE_DEV_RANDOM
|
||||||
#undef HAVE_SOCKADDR_SA_LEN
|
#undef HAVE_SOCKADDR_SA_LEN
|
||||||
#undef HAVE_PSELECT
|
#undef HAVE_PSELECT
|
||||||
/* Don't fork into background on uClinux */
|
|
||||||
#if defined(__uClinux__)
|
#if defined(__uClinux__)
|
||||||
|
/* Never use fork() on uClinux. Note that this is subtly different from the
|
||||||
|
--keep-in-foreground option, since it also suppresses forking new
|
||||||
|
processes for TCP connections. It's intended for use on MMU-less kernels. */
|
||||||
# define NO_FORK
|
# define NO_FORK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -254,7 +256,12 @@ typedef unsigned long in_addr_t;
|
|||||||
|
|
||||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||||
#undef HAVE_LINUX_IPV6_PROC
|
#undef HAVE_LINUX_IPV6_PROC
|
||||||
#undef HAVE_GETOPT_LONG
|
/* Later verions of FreeBSD have getopt_long() */
|
||||||
|
#if defined(optional_argument) && defined(required_argument)
|
||||||
|
# define HAVE_GETOPT_LONG
|
||||||
|
#else
|
||||||
|
# undef HAVE_GETOPT_LONG
|
||||||
|
#endif
|
||||||
#define HAVE_ARC4RANDOM
|
#define HAVE_ARC4RANDOM
|
||||||
#define HAVE_RANDOM
|
#define HAVE_RANDOM
|
||||||
#define HAVE_DEV_URANDOM
|
#define HAVE_DEV_URANDOM
|
||||||
|
|||||||
28
src/dhcp.c
28
src/dhcp.c
@@ -375,7 +375,7 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int address_available(struct dhcp_context *context, struct in_addr taddr)
|
struct dhcp_context *address_available(struct dhcp_context *context, struct in_addr taddr)
|
||||||
{
|
{
|
||||||
/* Check is an address is OK for this network, check all
|
/* Check is an address is OK for this network, check all
|
||||||
possible ranges. */
|
possible ranges. */
|
||||||
@@ -390,10 +390,32 @@ int address_available(struct dhcp_context *context, struct in_addr taddr)
|
|||||||
if (!context->static_only &&
|
if (!context->static_only &&
|
||||||
addr >= start &&
|
addr >= start &&
|
||||||
addr <= end)
|
addr <= end)
|
||||||
return 1;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dhcp_context *narrow_context(struct dhcp_context *context, struct in_addr taddr)
|
||||||
|
{
|
||||||
|
/* We start of with a set of possible contexts, all on the current subnet.
|
||||||
|
These are chained on ->current.
|
||||||
|
Here we have an address, and return the actual context correponding to that
|
||||||
|
address. Note that none may fit, if the address came a dhcp-host and is outside
|
||||||
|
any dhcp-range. In that case we return a static range is possible, or failing that,
|
||||||
|
any context on the subnet. (If there's more than one, this is a dodgy configuration:
|
||||||
|
maybe there should be a warning.) */
|
||||||
|
|
||||||
|
struct dhcp_context *tmp = address_available(context, taddr);
|
||||||
|
|
||||||
|
if (tmp)
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
for (tmp = context; tmp; tmp = tmp->current)
|
||||||
|
if (tmp->static_only)
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -549,11 +549,13 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
|
|||||||
|
|
||||||
if (!match || (num_kids >= MAX_PROCS))
|
if (!match || (num_kids >= MAX_PROCS))
|
||||||
close(confd);
|
close(confd);
|
||||||
|
#ifndef NO_FORK
|
||||||
else if (!(daemon->options & OPT_DEBUG) && fork())
|
else if (!(daemon->options & OPT_DEBUG) && fork())
|
||||||
{
|
{
|
||||||
num_kids++;
|
num_kids++;
|
||||||
close(confd);
|
close(confd);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *buff;
|
char *buff;
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
|
|
||||||
|
/* and this. */
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
@@ -50,9 +53,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#ifdef HAVE_GETOPT_LONG
|
|
||||||
# include <getopt.h>
|
|
||||||
#endif
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@@ -467,7 +467,8 @@ struct listener *create_bound_listeners(struct irec *interfaces, int port);
|
|||||||
void dhcp_init(struct daemon *daemon);
|
void dhcp_init(struct daemon *daemon);
|
||||||
void dhcp_packet(struct daemon *daemon, time_t now);
|
void dhcp_packet(struct daemon *daemon, time_t now);
|
||||||
|
|
||||||
int address_available(struct dhcp_context *context, struct in_addr addr);
|
struct dhcp_context *address_available(struct dhcp_context *context, struct in_addr addr);
|
||||||
|
struct dhcp_context *narrow_context(struct dhcp_context *context, struct in_addr taddr);
|
||||||
int address_allocate(struct dhcp_context *context, struct daemon *daemon,
|
int address_allocate(struct dhcp_context *context, struct daemon *daemon,
|
||||||
struct in_addr *addrp, unsigned char *hwaddr);
|
struct in_addr *addrp, unsigned char *hwaddr);
|
||||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||||
|
|||||||
149
src/network.c
149
src/network.c
@@ -14,11 +14,33 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
static struct irec *add_iface(struct daemon *daemon, struct irec *list, char *name, union mysockaddr *addr)
|
static struct irec *add_iface(struct daemon *daemon, struct irec *list,
|
||||||
|
char *name, int is_loopback, union mysockaddr *addr)
|
||||||
{
|
{
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
|
|
||||||
|
/* If we are restricting the set of interfaces to use, make
|
||||||
|
sure that loopback interfaces are in that set. */
|
||||||
|
if (daemon->if_names && is_loopback)
|
||||||
|
{
|
||||||
|
struct iname *lo;
|
||||||
|
for (lo = daemon->if_names; lo; lo = lo->next)
|
||||||
|
if (lo->name && strcmp(lo->name, name) == 0)
|
||||||
|
{
|
||||||
|
lo->isloop = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!lo)
|
||||||
|
{
|
||||||
|
lo = safe_malloc(sizeof(struct iname));
|
||||||
|
lo->name = safe_string_alloc(name);
|
||||||
|
lo->isloop = lo->used = 1;
|
||||||
|
lo->next = daemon->if_names;
|
||||||
|
daemon->if_names = lo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* check blacklist */
|
/* check blacklist */
|
||||||
if (daemon->if_except)
|
if (daemon->if_except)
|
||||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||||
@@ -67,6 +89,10 @@ static struct irec *add_iface(struct daemon *daemon, struct irec *list, char *na
|
|||||||
|
|
||||||
struct irec *enumerate_interfaces(struct daemon *daemon)
|
struct irec *enumerate_interfaces(struct daemon *daemon)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
||||||
|
FILE *f;
|
||||||
|
#endif
|
||||||
|
union mysockaddr addr;
|
||||||
struct irec *iface = NULL;
|
struct irec *iface = NULL;
|
||||||
char *buf, *ptr;
|
char *buf, *ptr;
|
||||||
struct ifreq *ifr = NULL;
|
struct ifreq *ifr = NULL;
|
||||||
@@ -99,9 +125,8 @@ struct irec *enumerate_interfaces(struct daemon *daemon)
|
|||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ptr = buf; ptr < buf + len; )
|
for (ptr = buf; ptr < buf + ifc.ifc_len; )
|
||||||
{
|
{
|
||||||
union mysockaddr addr;
|
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
/* subsequent entries may not be aligned, so copy into
|
/* subsequent entries may not be aligned, so copy into
|
||||||
an aligned buffer to avoid nasty complaints about
|
an aligned buffer to avoid nasty complaints about
|
||||||
@@ -141,75 +166,46 @@ struct irec *enumerate_interfaces(struct daemon *daemon)
|
|||||||
if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
|
if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
|
||||||
die("ioctl error getting interface flags: %m", NULL);
|
die("ioctl error getting interface flags: %m", NULL);
|
||||||
|
|
||||||
/* If we are restricting the set of interfaces to use, make
|
iface = add_iface(daemon, iface, ifr->ifr_name, ifr->ifr_flags & IFF_LOOPBACK, &addr);
|
||||||
sure that loopback interfaces are in that set. */
|
}
|
||||||
if (daemon->if_names && (ifr->ifr_flags & IFF_LOOPBACK))
|
|
||||||
{
|
|
||||||
struct iname *lo;
|
|
||||||
for (lo = daemon->if_names; lo; lo = lo->next)
|
|
||||||
if (lo->name && strcmp(lo->name, ifr->ifr_name) == 0)
|
|
||||||
{
|
|
||||||
lo->isloop = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!lo)
|
|
||||||
{
|
|
||||||
lo = safe_malloc(sizeof(struct iname));
|
|
||||||
lo->name = safe_string_alloc(ifr->ifr_name);
|
|
||||||
lo->isloop = lo->used = 1;
|
|
||||||
lo->next = daemon->if_names;
|
|
||||||
daemon->if_names = lo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iface = add_iface(daemon, iface, ifr->ifr_name, &addr);
|
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
|
||||||
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
/* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
|
||||||
/* This code snarfed from net-tools 1.60 and certainly linux specific, though
|
/* 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. */
|
it shouldn't break on other Unices, and their SIOGIFCONF might work. */
|
||||||
{
|
if ((f = fopen(IP6INTERFACES, "r")))
|
||||||
FILE *f = fopen(IP6INTERFACES, "r");
|
{
|
||||||
int found = 0;
|
unsigned int plen, scope, flags, if_idx;
|
||||||
union mysockaddr addr6;
|
char devname[20], addrstring[32];
|
||||||
|
|
||||||
if (f)
|
while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
|
||||||
{
|
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
|
||||||
unsigned int plen, scope, flags, if_idx;
|
{
|
||||||
char devname[20], addrstring[32];
|
int i;
|
||||||
|
struct ifreq sifr;
|
||||||
|
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(daemon->port);
|
||||||
|
addr.in6.sin6_flowinfo = htonl(0);
|
||||||
|
addr.in6.sin6_scope_id = htonl(scope);
|
||||||
|
|
||||||
while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
|
strncpy(sifr.ifr_name, devname, IF_NAMESIZE);
|
||||||
addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
|
if (ioctl(fd, SIOCGIFFLAGS, &sifr) < 0)
|
||||||
{
|
die("ioctl error getting interface flags: %m", NULL);
|
||||||
if (strcmp(devname, ifr->ifr_name) == 0)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned char *addr6p = (unsigned char *) &addr6.in6.sin6_addr;
|
|
||||||
memset(&addr6, 0, sizeof(addr6));
|
|
||||||
addr6.sa.sa_family = AF_INET6;
|
|
||||||
for (i=0; i<16; i++)
|
|
||||||
{
|
|
||||||
unsigned int byte;
|
|
||||||
sscanf(addrstring+i+i, "%02x", &byte);
|
|
||||||
addr6p[i] = byte;
|
|
||||||
}
|
|
||||||
addr6.in6.sin6_port = htons(daemon->port);
|
|
||||||
addr6.in6.sin6_flowinfo = htonl(0);
|
|
||||||
addr6.in6.sin6_scope_id = htonl(scope);
|
|
||||||
|
|
||||||
found = 1;
|
iface = add_iface(daemon, iface, sifr.ifr_name, sifr.ifr_flags & IFF_LOOPBACK, &addr);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
}
|
||||||
}
|
fclose(f);
|
||||||
|
|
||||||
if (found)
|
|
||||||
iface = add_iface(daemon, iface, ifr->ifr_name, &addr6);
|
|
||||||
}
|
|
||||||
#endif /* LINUX */
|
|
||||||
}
|
}
|
||||||
|
#endif /* LINUX */
|
||||||
|
|
||||||
if (buf)
|
if (buf)
|
||||||
free(buf);
|
free(buf);
|
||||||
@@ -361,7 +357,6 @@ struct listener *create_bound_listeners(struct irec *interfaces, int port)
|
|||||||
struct listener *new = safe_malloc(sizeof(struct listener));
|
struct listener *new = safe_malloc(sizeof(struct listener));
|
||||||
new->family = iface->addr.sa.sa_family;
|
new->family = iface->addr.sa.sa_family;
|
||||||
new->next = listeners;
|
new->next = listeners;
|
||||||
listeners = new;
|
|
||||||
if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
|
if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
|
||||||
(new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
|
(new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
|
||||||
setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
||||||
@@ -383,9 +378,25 @@ struct listener *create_bound_listeners(struct irec *interfaces, int port)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
|
if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
|
||||||
bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
|
bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
|
||||||
listen(new->tcpfd, 5) == -1)
|
{
|
||||||
die("failed to bind listening socket: %s", NULL);
|
#ifdef HAVE_IPV6
|
||||||
|
if (iface->addr.sa.sa_family == AF_INET6 && errno == ENODEV)
|
||||||
|
{
|
||||||
|
close(new->tcpfd);
|
||||||
|
close(new->fd);
|
||||||
|
free(new);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
die("failed to bind listening socket: %s", NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listeners = new;
|
||||||
|
if (listen(new->tcpfd, 5) == -1)
|
||||||
|
die("failed to listen on socket: %s", NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return listeners;
|
return listeners;
|
||||||
|
|||||||
14
src/option.c
14
src/option.c
@@ -478,8 +478,10 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
{
|
do {
|
||||||
struct iname *new = safe_malloc(sizeof(struct iname));
|
struct iname *new = safe_malloc(sizeof(struct iname));
|
||||||
|
if ((comma = strchr(optarg, ',')))
|
||||||
|
*comma++ = 0;
|
||||||
new->next = daemon->if_addrs;
|
new->next = daemon->if_addrs;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (inet_pton(AF_INET, optarg, &new->addr.in.sin_addr))
|
if (inet_pton(AF_INET, optarg, &new->addr.in.sin_addr))
|
||||||
@@ -510,13 +512,13 @@ struct daemon *read_opts (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
option = '?'; /* error */
|
option = '?'; /* error */
|
||||||
free(new);
|
free(new);
|
||||||
new = NULL;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new)
|
daemon->if_addrs = new;
|
||||||
daemon->if_addrs = new;
|
optarg = comma;
|
||||||
break;
|
} while (optarg);
|
||||||
}
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'A':
|
case 'A':
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
char *hostname = NULL;
|
char *hostname = NULL;
|
||||||
char *req_options = NULL;
|
char *req_options = NULL;
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
unsigned int renewal_time, expires_time, def_time;
|
unsigned int time;
|
||||||
struct dhcp_config *config;
|
struct dhcp_config *config;
|
||||||
struct dhcp_netid *netid = NULL;
|
struct dhcp_netid *netid = NULL;
|
||||||
struct in_addr addr, subnet_addr;
|
struct in_addr addr, subnet_addr;
|
||||||
@@ -171,13 +171,6 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
{
|
{
|
||||||
context_tmp->current = context;
|
context_tmp->current = context;
|
||||||
context = context_tmp;
|
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)
|
||||||
@@ -205,6 +198,7 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
mess->yiaddr = config->addr;
|
mess->yiaddr = config->addr;
|
||||||
if (lease_find_by_addr(config->addr))
|
if (lease_find_by_addr(config->addr))
|
||||||
message = "address in use";
|
message = "address in use";
|
||||||
|
context = narrow_context(context, config->addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
message = "no address configured";
|
message = "no address configured";
|
||||||
@@ -217,6 +211,12 @@ 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;
|
||||||
|
|
||||||
|
if (context->netid.net)
|
||||||
|
{
|
||||||
|
context->netid.next = netid;
|
||||||
|
netid = &context->netid;
|
||||||
|
}
|
||||||
|
|
||||||
if (have_config(config, CONFIG_NETID))
|
if (have_config(config, CONFIG_NETID))
|
||||||
{
|
{
|
||||||
config->netid.next = netid;
|
config->netid.next = netid;
|
||||||
@@ -348,27 +348,6 @@ 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)))
|
|
||||||
{
|
|
||||||
unsigned int req_time = option_uint(opt, 4);
|
|
||||||
|
|
||||||
if (def_time == 0xffffffff ||
|
|
||||||
(req_time != 0xffffffff && req_time < def_time))
|
|
||||||
expires_time = renewal_time = req_time;
|
|
||||||
else
|
|
||||||
expires_time = renewal_time = def_time;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
renewal_time = def_time;
|
|
||||||
if (lease)
|
|
||||||
expires_time = (unsigned int)difftime(lease->expires, now);
|
|
||||||
else
|
|
||||||
expires_time = def_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS)))
|
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS)))
|
||||||
{
|
{
|
||||||
int len = option_len(opt);
|
int len = option_len(opt);
|
||||||
@@ -455,16 +434,33 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
if (message)
|
if (message)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
context = narrow_context(context, mess->yiaddr);
|
||||||
|
if (context->netid.net)
|
||||||
|
{
|
||||||
|
context->netid.next = netid;
|
||||||
|
netid = &context->netid;
|
||||||
|
}
|
||||||
|
|
||||||
|
time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||||
|
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
||||||
|
{
|
||||||
|
unsigned int req_time = option_uint(opt, 4);
|
||||||
|
if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
|
||||||
|
time = req_time;
|
||||||
|
}
|
||||||
|
else if (lease && lease->expires != 0)
|
||||||
|
time = (unsigned int)difftime(lease->expires, now);
|
||||||
|
|
||||||
mess->siaddr = iface_addr;
|
mess->siaddr = iface_addr;
|
||||||
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, DHCPOFFER);
|
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
|
||||||
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));
|
||||||
p = option_put(p, end, OPTION_LEASE_TIME, 4, expires_time);
|
p = option_put(p, end, OPTION_LEASE_TIME, 4, time);
|
||||||
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
||||||
if (expires_time != 0xffffffff)
|
if (time != 0xffffffff)
|
||||||
{
|
{
|
||||||
p = option_put(p, end, OPTION_T1, 4, (expires_time/2));
|
p = option_put(p, end, OPTION_T1, 4, (time/2));
|
||||||
p = option_put(p, end, OPTION_T2, 4, ((expires_time * 7)/8));
|
p = option_put(p, end, OPTION_T2, 4, (time*7)/8);
|
||||||
}
|
}
|
||||||
p = do_req_options(context, p, end, req_options, daemon,
|
p = do_req_options(context, p, end, req_options, daemon,
|
||||||
NULL, iface_addr, netid, subnet_addr);
|
NULL, iface_addr, netid, subnet_addr);
|
||||||
@@ -513,9 +509,6 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
|
|
||||||
/* desynchronise renewals */
|
/* desynchronise renewals */
|
||||||
fuzz = rand16();
|
fuzz = rand16();
|
||||||
while (fuzz > (renewal_time/16))
|
|
||||||
fuzz = fuzz/2;
|
|
||||||
|
|
||||||
mess->yiaddr = mess->ciaddr;
|
mess->yiaddr = mess->ciaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,20 +561,37 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
{
|
{
|
||||||
log_packet("ACK", &mess->yiaddr, mess->chaddr, iface_name, hostname);
|
log_packet("ACK", &mess->yiaddr, mess->chaddr, iface_name, hostname);
|
||||||
|
|
||||||
|
context = narrow_context(context, mess->yiaddr);
|
||||||
|
if (context->netid.net)
|
||||||
|
{
|
||||||
|
context->netid.next = netid;
|
||||||
|
netid = &context->netid;
|
||||||
|
}
|
||||||
|
|
||||||
|
time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
|
||||||
|
if ((opt = option_find(mess, sz, OPTION_LEASE_TIME)))
|
||||||
|
{
|
||||||
|
unsigned int req_time = option_uint(opt, 4);
|
||||||
|
if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
|
||||||
|
time = req_time;
|
||||||
|
}
|
||||||
|
|
||||||
lease_set_hwaddr(lease, mess->chaddr);
|
lease_set_hwaddr(lease, mess->chaddr);
|
||||||
if (hostname)
|
if (hostname)
|
||||||
lease_set_hostname(lease, hostname, daemon->domain_suffix);
|
lease_set_hostname(lease, hostname, daemon->domain_suffix);
|
||||||
lease_set_expires(lease, renewal_time == 0xffffffff ? 0 : now + (time_t)renewal_time);
|
lease_set_expires(lease, time == 0xffffffff ? 0 : now + (time_t)time);
|
||||||
|
|
||||||
mess->siaddr = iface_addr;
|
mess->siaddr = iface_addr;
|
||||||
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));
|
||||||
p = option_put(p, end, OPTION_LEASE_TIME, 4, renewal_time);
|
p = option_put(p, end, OPTION_LEASE_TIME, 4, time);
|
||||||
if (renewal_time != 0xffffffff)
|
if (time != 0xffffffff)
|
||||||
{
|
{
|
||||||
p = option_put(p, end, OPTION_T1, 4, (renewal_time/2) - fuzz);
|
while (fuzz > (time/16))
|
||||||
p = option_put(p, end, OPTION_T2, 4, ((renewal_time * 7)/8) - fuzz);
|
fuzz = fuzz/2;
|
||||||
|
p = option_put(p, end, OPTION_T1, 4, (time/2) - fuzz);
|
||||||
|
p = option_put(p, end, OPTION_T2, 4, ((time * 7)/8) - fuzz);
|
||||||
}
|
}
|
||||||
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);
|
||||||
@@ -599,6 +609,13 @@ int dhcp_reply(struct daemon *daemon, struct in_addr iface_addr, char *iface_nam
|
|||||||
if (message || mess->ciaddr.s_addr == 0)
|
if (message || mess->ciaddr.s_addr == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
context = narrow_context(context, mess->ciaddr);
|
||||||
|
if (context->netid.net)
|
||||||
|
{
|
||||||
|
context->netid.next = netid;
|
||||||
|
netid = &context->netid;
|
||||||
|
}
|
||||||
|
|
||||||
mess->siaddr = iface_addr;
|
mess->siaddr = iface_addr;
|
||||||
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user