Commit 849a8357 authored by Simon Kelley's avatar Simon Kelley

import of dnsmasq-2.32.tar.gz

parent 7cebd20f
...@@ -1833,6 +1833,57 @@ version 2.31 ...@@ -1833,6 +1833,57 @@ version 2.31
Tweaked config.h logic for uclibc build. It will now pick Tweaked config.h logic for uclibc build. It will now pick
up MMU and IPV6 status correctly on every system I tested. up MMU and IPV6 status correctly on every system I tested.
version 2.32
Attempt a better job of replacing previous configuration
when re-reading /etc/hosts and /etc/ethers. SIGHUP is
still not identical to a restart under all circumstances,
but it is for the common case of name->MAC address in
/etc/ethers and name->IP address in /etc/hosts.
Fall back to broadcast for DHCP to an unconfigured client
when the MAC address size is greater than 14 bytes.
Fix problem in 2.28-onwards releases which breaks DNS on
Mac OS X. Thanks to Doug Fields for the bug report and
testing.
Added fix to allow compilation on c89-only compilers.
Thanks to John Mastwijk for the patch.
Tweak resolv file polling code to work better if there is
a race between updating the mtime and file contents. This
is not normally a problem, but it can be on systems which
replace nameservers whilst active. The code now continues
to read resolv.conf until it gets at least one usable
server. Thanks to Holger Mauermann for help with this.
If a client DECLINEs an address which is allocated to it
via dhcp-host or /etc/hosts, lock that address out of use
for ten minutes, instead of forever, and log when it's not
being used because of the lock-out. This should provide
less surprising behaviour when a configured address can't be
used. Thanks to Peter Surda and Heinz Deinhart for input
on this.
Fixed *BSD DHCP breakage with only some
arches/compilers, depending on structure padding rules.
Thanks to Jeb Campbell and Tom Hensel for help with this.
Added --conf-dir option. Suggestion from Aaron Tygart.
Applied patch from Brent Cook which allows netids in
dhcp-option configuration lines to be prefixed by
"net:". This is not required by the syntax, but it is
consistent with other configuration items.
Added --log-facility option. Suggestion from Fabio Muzzi.
Major update to Spanish translation. Many thanks to Chris
Chatham.
Fixed gcc-4.1 strict-alias compilation warning.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.31 Version: 2.32
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: Productivity/Networking/DNS/Servers Group: Productivity/Networking/DNS/Servers
......
...@@ -60,6 +60,10 @@ to handle TCP queries. ...@@ -60,6 +60,10 @@ to handle TCP queries.
.B \-q, --log-queries .B \-q, --log-queries
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
.TP .TP
.B \-8, --log-facility=<facility>
Set the facility to which dnsmasq will send syslog entries, this
defaults to DAEMON, and to LOCAL0 when debug mode is in operation.
.TP
.B \-x, --pid-file=<path> .B \-x, --pid-file=<path>
Specify an alternate path for dnsmasq to record its process-id in. Normally /var/run/dnsmasq.pid. Specify an alternate path for dnsmasq to record its process-id in. Normally /var/run/dnsmasq.pid.
.TP .TP
...@@ -580,8 +584,13 @@ in the same way as for DHCP-derived names. ...@@ -580,8 +584,13 @@ in the same way as for DHCP-derived names.
.TP .TP
.B \-C, --conf-file=<file> .B \-C, --conf-file=<file>
Specify a different configuration file. The conf-file option is also allowed in Specify a different configuration file. The conf-file option is also allowed in
configuration files, to include multiple configuration files. Only one configuration files, to include multiple configuration files.
level of nesting is allowed. .TP
.B \-7, --conf-dir=<directory>
Read all the files in the given directory as configuration
files. Files whose names end in ~ or start with . or start and end
with # are skipped. This flag may be given on the command
line or in a configuration file.
.SH CONFIG FILE .SH CONFIG FILE
At startup, dnsmasq reads At startup, dnsmasq reads
.I /etc/dnsmasq.conf, .I /etc/dnsmasq.conf,
...@@ -590,7 +599,9 @@ FreeBSD, the file is ...@@ -590,7 +599,9 @@ FreeBSD, the file is
.I /usr/local/etc/dnsmasq.conf .I /usr/local/etc/dnsmasq.conf
) (but see the ) (but see the
.B \-C .B \-C
option.) The format of this and
.B \-7
options.) The format of this
file consists of one option per line, exactly as the long options detailed file consists of one option per line, exactly as the long options detailed
in the OPTIONS section but without the leading "--". Lines starting with # are comments and ignored. For in the OPTIONS section but without the leading "--". Lines starting with # are comments and ignored. For
options which may only be specified once, the configuration file overrides options which may only be specified once, the configuration file overrides
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -26,17 +26,6 @@ static struct iovec ifreq = { ...@@ -26,17 +26,6 @@ static struct iovec ifreq = {
.iov_len = 0 .iov_len = 0
}; };
struct header {
struct ether_header ether;
struct ip ip;
struct udphdr {
u16 uh_sport; /* source port */
u16 uh_dport; /* destination port */
u16 uh_ulen; /* udp length */
u16 uh_sum; /* udp checksum */
} udp;
};
void init_bpf(struct daemon *daemon) void init_bpf(struct daemon *daemon)
{ {
int i = 0; int i = 0;
...@@ -69,9 +58,17 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len, ...@@ -69,9 +58,17 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len,
Build the packet by steam, and send directly, bypassing Build the packet by steam, and send directly, bypassing
the kernel IP stack */ the kernel IP stack */
struct header header; struct ether_header ether;
struct ip ip;
struct udphdr {
u16 uh_sport; /* source port */
u16 uh_dport; /* destination port */
u16 uh_ulen; /* udp length */
u16 uh_sum; /* udp checksum */
} udp;
u32 i, sum; u32 i, sum;
struct iovec iov[2]; struct iovec iov[4];
/* Only know how to do ethernet on *BSD */ /* Only know how to do ethernet on *BSD */
if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN) if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN)
...@@ -85,62 +82,67 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len, ...@@ -85,62 +82,67 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len,
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, ifr) < 0) if (ioctl(daemon->dhcpfd, SIOCGIFADDR, ifr) < 0)
return; return;
memcpy(header.ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN); memcpy(ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
header.ether.ether_type = htons(ETHERTYPE_IP); ether.ether_type = htons(ETHERTYPE_IP);
if (ntohs(mess->flags) & 0x8000) if (ntohs(mess->flags) & 0x8000)
{ {
memset(header.ether.ether_dhost, 255, ETHER_ADDR_LEN); memset(ether.ether_dhost, 255, ETHER_ADDR_LEN);
header.ip.ip_dst.s_addr = INADDR_BROADCAST; ip.ip_dst.s_addr = INADDR_BROADCAST;
} }
else else
{ {
memcpy(header.ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN); memcpy(ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN);
header.ip.ip_dst.s_addr = mess->yiaddr.s_addr; ip.ip_dst.s_addr = mess->yiaddr.s_addr;
} }
header.ip.ip_p = IPPROTO_UDP; ip.ip_p = IPPROTO_UDP;
header.ip.ip_src.s_addr = iface_addr.s_addr; ip.ip_src.s_addr = iface_addr.s_addr;
header.ip.ip_len = htons(sizeof(struct ip) + ip.ip_len = htons(sizeof(struct ip) +
sizeof(struct udphdr) + sizeof(struct udphdr) +
len) ; len) ;
header.ip.ip_hl = sizeof(struct ip) / 4; ip.ip_hl = sizeof(struct ip) / 4;
header.ip.ip_v = IPVERSION; ip.ip_v = IPVERSION;
header.ip.ip_tos = 0; ip.ip_tos = 0;
header.ip.ip_id = htons(0); ip.ip_id = htons(0);
header.ip.ip_off = htons(0x4000); /* don't fragment */ ip.ip_off = htons(0x4000); /* don't fragment */
header.ip.ip_ttl = IPDEFTTL; ip.ip_ttl = IPDEFTTL;
header.ip.ip_sum = 0; ip.ip_sum = 0;
for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++) for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
sum += ((u16 *)&header.ip)[i]; sum += ((u16 *)&ip)[i];
while (sum>>16) while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16); sum = (sum & 0xffff) + (sum >> 16);
header.ip.ip_sum = (sum == 0xffff) ? sum : ~sum; ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
header.udp.uh_sport = htons(DHCP_SERVER_PORT); udp.uh_sport = htons(DHCP_SERVER_PORT);
header.udp.uh_dport = htons(DHCP_CLIENT_PORT); udp.uh_dport = htons(DHCP_CLIENT_PORT);
if (len & 1) if (len & 1)
((char *)mess)[len] = 0; /* for checksum, in case length is odd. */ ((char *)mess)[len] = 0; /* for checksum, in case length is odd. */
header.udp.uh_sum = 0; udp.uh_sum = 0;
header.udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len); udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len);
sum += htons(IPPROTO_UDP); sum += htons(IPPROTO_UDP);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
sum += ((u16 *)&header.ip.ip_src)[i]; sum += ((u16 *)&ip.ip_src)[i];
for (i = 0; i < sizeof(struct udphdr)/2; i++) for (i = 0; i < sizeof(struct udphdr)/2; i++)
sum += ((u16 *)&header.udp)[i]; sum += ((u16 *)&udp)[i];
for (i = 0; i < (len + 1) / 2; i++) for (i = 0; i < (len + 1) / 2; i++)
sum += ((u16 *)mess)[i]; sum += ((u16 *)mess)[i];
while (sum>>16) while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16); sum = (sum & 0xffff) + (sum >> 16);
header.udp.uh_sum = (sum == 0xffff) ? sum : ~sum; udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
ioctl(daemon->dhcp_raw_fd, BIOCSETIF, ifr); ioctl(daemon->dhcp_raw_fd, BIOCSETIF, ifr);
iov[0].iov_base = &header; iov[0].iov_base = &ether;
iov[0].iov_len = sizeof(struct header); iov[0].iov_len = sizeof(ether);
iov[1].iov_base = mess; iov[1].iov_base = &ip;
iov[1].iov_len = len; iov[1].iov_len = sizeof(ip);
while (writev(daemon->dhcp_raw_fd, iov, 2) == -1 && retry_send()); iov[2].iov_base = &udp;
iov[2].iov_len = sizeof(udp);
iov[3].iov_base = mess;
iov[3].iov_len = len;
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
} }
int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), int (*ipv6_callback)()) int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
...@@ -150,31 +152,33 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i ...@@ -150,31 +152,33 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
struct ifconf ifc; struct ifconf ifc;
int fd, errsav, ret = 0; int fd, errsav, ret = 0;
int lastlen = 0; int lastlen = 0;
size_t len; size_t len = 0;
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0; return 0;
for (len = 0; ; len += 10*sizeof(struct ifreq)) while(1)
{ {
if (!expand_buf(&ifconf, len)) len += 10*sizeof(struct ifreq);
goto err;
if (!expand_buf(&ifconf, len))
ifc.ifc_len = len; goto err;
ifc.ifc_buf = ifconf.iov_base;
ifc.ifc_len = len;
if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) ifc.ifc_buf = ifconf.iov_base;
{
if (errno != EINVAL || lastlen != 0) if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
goto err; {
} if (errno != EINVAL || lastlen != 0)
else goto err;
{ }
if (ifc.ifc_len == lastlen) else
break; /* got a big enough buffer now */ {
lastlen = ifc.ifc_len; if (ifc.ifc_len == lastlen)
} break; /* got a big enough buffer now */
} lastlen = ifc.ifc_len;
}
}
for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len; ptr += len ) for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len; ptr += len )
{ {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#define VERSION "2.31" #define VERSION "2.32"
#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 */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define MAXLEASES 150 /* maximum number of DHCP leases */ #define MAXLEASES 150 /* maximum number of DHCP leases */
#define PING_WAIT 3 /* wait for ping address-in-use test */ #define PING_WAIT 3 /* wait for ping address-in-use test */
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */ #define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */ #define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
#define SMALLDNAME 40 /* most domain names are smaller than this */ #define SMALLDNAME 40 /* most domain names are smaller than this */
#define HOSTSFILE "/etc/hosts" #define HOSTSFILE "/etc/hosts"
...@@ -53,20 +54,6 @@ ...@@ -53,20 +54,6 @@
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" #define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq" #define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
/* Logfile stuff - change this to change the options and facility */
/* debug is true if the --no-daemon flag is given */
#ifdef LOG_PERROR
# define DNSMASQ_LOG_OPT(debug) (debug) ? LOG_PERROR : LOG_PID
#else
# define DNSMASQ_LOG_OPT(debug) (debug) ? 0 : LOG_PID
#endif
#ifdef LOG_LOCAL0
# define DNSMASQ_LOG_FAC(debug) (debug) ? LOG_LOCAL0 : LOG_DAEMON
#else
# define DNSMASQ_LOG_FAC(debug) LOG_DAEMON
#endif
/* A small collection of RR-types which are missing on some platforms */ /* A small collection of RR-types which are missing on some platforms */
#ifndef T_SRV #ifndef T_SRV
......
...@@ -47,6 +47,7 @@ void dhcp_init(struct daemon *daemon) ...@@ -47,6 +47,7 @@ void dhcp_init(struct daemon *daemon)
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)) == -1) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)) == -1)
die(_("failed to set SO_REUSEADDR on DHCP socket: %s"), NULL); die(_("failed to set SO_REUSEADDR on DHCP socket: %s"), NULL);
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(DHCP_SERVER_PORT); saddr.sin_port = htons(DHCP_SERVER_PORT);
saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_addr.s_addr = INADDR_ANY;
...@@ -237,9 +238,10 @@ void dhcp_packet(struct daemon *daemon, time_t now) ...@@ -237,9 +238,10 @@ void dhcp_packet(struct daemon *daemon, time_t now)
dest.sin_port = htons(DHCP_CLIENT_PORT); dest.sin_port = htons(DHCP_CLIENT_PORT);
} }
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
else if (ntohs(mess->flags) & 0x8000) else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
{ {
/* broadcast to 255.255.255.255 */ /* broadcast to 255.255.255.255 (or mac address invalid) */
struct in_pktinfo *pkt; struct in_pktinfo *pkt;
msg.msg_control = control_u.control; msg.msg_control = control_u.control;
msg.msg_controllen = sizeof(control_u); msg.msg_controllen = sizeof(control_u);
...@@ -255,21 +257,17 @@ void dhcp_packet(struct daemon *daemon, time_t now) ...@@ -255,21 +257,17 @@ void dhcp_packet(struct daemon *daemon, time_t now)
} }
else else
{ {
/* unicast to unconfigured client */ /* unicast to unconfigured client. Inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
struct arpreq req;
dest.sin_addr = mess->yiaddr; dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(DHCP_CLIENT_PORT); dest.sin_port = htons(DHCP_CLIENT_PORT);
if (mess->hlen != 0 && mess->hlen <= 14 && mess->htype != 0) *((struct sockaddr_in *)&req.arp_pa) = dest;
{ req.arp_ha.sa_family = mess->htype;
/* inject mac address direct into ARP cache. memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
struct sockaddr limits size to 14 bytes. */ strncpy(req.arp_dev, ifr.ifr_name, 16);
struct arpreq req; req.arp_flags = ATF_COM;
*((struct sockaddr_in *)&req.arp_pa) = dest; ioctl(daemon->dhcpfd, SIOCSARP, &req);
req.arp_ha.sa_family = mess->htype;
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
strncpy(req.arp_dev, ifr.ifr_name, 16);
req.arp_flags = ATF_COM;
ioctl(daemon->dhcpfd, SIOCSARP, &req);
}
} }
#else #else
else else
...@@ -366,7 +364,7 @@ struct dhcp_context *address_available(struct dhcp_context *context, struct in_a ...@@ -366,7 +364,7 @@ struct dhcp_context *address_available(struct dhcp_context *context, struct in_a
struct dhcp_context *tmp; struct dhcp_context *tmp;
for (tmp = context; tmp; tmp = tmp->current) for (tmp = context; tmp; tmp = tmp->current)
if (taddr.s_addr == context->local.s_addr) if (taddr.s_addr == context->router.s_addr)
return NULL; return NULL;
for (tmp = context; tmp; tmp = tmp->current) for (tmp = context; tmp; tmp = tmp->current)
...@@ -481,7 +479,7 @@ int address_allocate(struct dhcp_context *context, struct daemon *daemon, ...@@ -481,7 +479,7 @@ int address_allocate(struct dhcp_context *context, struct daemon *daemon,
do { do {
/* eliminate addresses in use by the server. */ /* eliminate addresses in use by the server. */
for (d = context; d; d = d->current) for (d = context; d; d = d->current)
if (addr.s_addr == d->local.s_addr) if (addr.s_addr == d->router.s_addr)
break; break;
if (!d && if (!d &&
...@@ -622,6 +620,7 @@ void dhcp_read_ethers(struct daemon *daemon) ...@@ -622,6 +620,7 @@ void dhcp_read_ethers(struct daemon *daemon)
char *ip, *cp; char *ip, *cp;
struct in_addr addr; struct in_addr addr;
unsigned char hwaddr[ETHER_ADDR_LEN]; unsigned char hwaddr[ETHER_ADDR_LEN];
struct dhcp_config **up, *tmp;
struct dhcp_config *config, *configs = daemon->dhcp_conf; struct dhcp_config *config, *configs = daemon->dhcp_conf;
int count = 0, lineno = 0; int count = 0, lineno = 0;
...@@ -633,6 +632,22 @@ void dhcp_read_ethers(struct daemon *daemon) ...@@ -633,6 +632,22 @@ void dhcp_read_ethers(struct daemon *daemon)
return; return;
} }
/* This can be called again on SIGHUP, so remove entries created last time round. */
for (up = &daemon->dhcp_conf, config = configs; config; config = tmp)
{
tmp = config->next;
if (config->flags & CONFIG_FROM_ETHERS)
{
*up = tmp;
/* cannot have a clid */
if (config->flags & CONFIG_NAME)
free(config->hostname);
free(config);
}
else
up = &config->next;
}
while (fgets(buff, MAXDNAME, f)) while (fgets(buff, MAXDNAME, f))
{ {
lineno++; lineno++;
...@@ -700,7 +715,7 @@ void dhcp_read_ethers(struct daemon *daemon) ...@@ -700,7 +715,7 @@ void dhcp_read_ethers(struct daemon *daemon)
{ {
if (!(config = malloc(sizeof(struct dhcp_config)))) if (!(config = malloc(sizeof(struct dhcp_config))))
continue; continue;
config->flags = 0; config->flags = CONFIG_FROM_ETHERS;
config->wildcard_mask = 0; config->wildcard_mask = 0;
config->next = configs; config->next = configs;
configs = config; configs = config;
...@@ -740,10 +755,15 @@ void dhcp_update_configs(struct dhcp_config *configs) ...@@ -740,10 +755,15 @@ void dhcp_update_configs(struct dhcp_config *configs)
This goes through /etc/hosts and sets static addresses for any DHCP config This goes through /etc/hosts and sets static addresses for any DHCP config
records which don't have an address and whose name matches. records which don't have an address and whose name matches.
We take care to maintain the invariant that any IP address can appear We take care to maintain the invariant that any IP address can appear
in at most one dhcp-host. */ in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
restore the status-quo ante first. */
struct dhcp_config *config; struct dhcp_config *config;
struct crec *crec; struct crec *crec;
for (config = configs; config; config = config->next)
if (config->flags & CONFIG_ADDR_HOSTS)
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
for (config = configs; config; config = config->next) for (config = configs; config; config = config->next)
if (!(config->flags & CONFIG_ADDR) && if (!(config->flags & CONFIG_ADDR) &&
...@@ -757,7 +777,7 @@ void dhcp_update_configs(struct dhcp_config *configs) ...@@ -757,7 +777,7 @@ void dhcp_update_configs(struct dhcp_config *configs)
else else
{ {
config->addr = crec->addr.addr.addr.addr4; config->addr = crec->addr.addr.addr.addr4;
config->flags |= CONFIG_ADDR; config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
} }
} }
} }
......
...@@ -128,7 +128,6 @@ int main (int argc, char **argv) ...@@ -128,7 +128,6 @@ int main (int argc, char **argv)
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port))) else if (!(daemon->listeners = create_wildcard_listeners(daemon->port)))
die(_("failed to create listening socket: %s"), NULL); die(_("failed to create listening socket: %s"), NULL);
forward_init(1);
cache_init(daemon->cachesize, daemon->options & OPT_LOG); cache_init(daemon->cachesize, daemon->options & OPT_LOG);
now = dnsmasq_time(); now = dnsmasq_time();
...@@ -167,6 +166,7 @@ int main (int argc, char **argv) ...@@ -167,6 +166,7 @@ int main (int argc, char **argv)
if (daemon->query_port) if (daemon->query_port)
{ {
union mysockaddr addr; union mysockaddr addr;
memset(&addr, 0, sizeof(addr));
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
addr.in.sin_addr.s_addr = INADDR_ANY; addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = htons(daemon->query_port); addr.in.sin_port = htons(daemon->query_port);
...@@ -175,11 +175,10 @@ int main (int argc, char **argv) ...@@ -175,11 +175,10 @@ int main (int argc, char **argv)
#endif #endif
allocate_sfd(&addr, &daemon->sfds); allocate_sfd(&addr, &daemon->sfds);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6; addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any; addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(daemon->query_port); addr.in6.sin6_port = htons(daemon->query_port);
addr.in6.sin6_flowinfo = 0;
addr.in6.sin6_scope_id = 0;
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6); addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif #endif
...@@ -197,7 +196,19 @@ int main (int argc, char **argv) ...@@ -197,7 +196,19 @@ int main (int argc, char **argv)
sig = SIGHUP; sig = SIGHUP;
write(pipewrite, &sig, 1); write(pipewrite, &sig, 1);
if (!(daemon->options & OPT_DEBUG)) if (daemon->options & OPT_DEBUG)
{
#ifdef LOG_PERROR
openlog("dnsmasq", LOG_PERROR, daemon->log_fac);
#else
openlog("dnsmasq", 0, daemon->log_fac);
#endif
#ifdef HAVE_LINUX_NETWORK
prctl(PR_SET_DUMPABLE, 1);
#endif
}
else
{ {
FILE *pidfile; FILE *pidfile;
struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL; struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
...@@ -322,16 +333,10 @@ int main (int argc, char **argv) ...@@ -322,16 +333,10 @@ int main (int argc, char **argv)
capset(hdr, data); capset(hdr, data);
#endif #endif
} }
openlog("dnsmasq", LOG_PID, daemon->log_fac);
} }
#ifdef HAVE_LINUX_NETWORK
else
prctl(PR_SET_DUMPABLE, 1);
#endif
openlog("dnsmasq",
DNSMASQ_LOG_OPT(daemon->options & OPT_DEBUG),
DNSMASQ_LOG_FAC(daemon->options & OPT_DEBUG));
if (daemon->cachesize != 0) if (daemon->cachesize != 0)
syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize); syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
else else
...@@ -444,7 +449,7 @@ int main (int argc, char **argv) ...@@ -444,7 +449,7 @@ int main (int argc, char **argv)
/* Check for changes to resolv files once per second max. */ /* Check for changes to resolv files once per second max. */
/* Don't go silent for long periods if the clock goes backwards. */ /* Don't go silent for long periods if the clock goes backwards. */
if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < 1.0) if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < -1.0)
{ {
last = now; last = now;
...@@ -472,14 +477,11 @@ int main (int argc, char **argv) ...@@ -472,14 +477,11 @@ int main (int argc, char **argv)
else else
{ {
res->logged = 0; res->logged = 0;
if (statbuf.st_mtime != res->mtime) if (statbuf.st_mtime != res->mtime &&
difftime(statbuf.st_mtime, last_change) > 0.0)
{ {
res->mtime = statbuf.st_mtime; last_change = statbuf.st_mtime;
if (difftime(res->mtime, last_change) > 0.0) latest = res;
{
last_change = res->mtime;
latest = res;
}
} }
} }
res = res->next; res = res->next;
...@@ -487,8 +489,19 @@ int main (int argc, char **argv) ...@@ -487,8 +489,19 @@ int main (int argc, char **argv)
if (latest) if (latest)
{ {
reload_servers(latest->name, daemon); static int warned = 0;
check_servers(daemon); if (reload_servers(latest->name, daemon))
{
syslog(LOG_INFO, _("reading %s"), latest->name);
latest->mtime = last_change;
warned = 0;
check_servers(daemon);
}
else if (!warned)
{
syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
warned = 1;
}
} }
} }
} }
...@@ -529,16 +542,11 @@ int main (int argc, char **argv) ...@@ -529,16 +542,11 @@ int main (int argc, char **argv)
/* Knock all our children on the head. */ /* Knock all our children on the head. */
for (i = 0; i < MAX_PROCS; i++) for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] != 0) if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGQUIT); kill(daemon->tcp_pids[i], SIGALRM);
if (daemon->dhcp) if (daemon->dhcp)
{ fclose(daemon->lease_stream);
if (daemon->script_pid != 0)
kill(daemon->script_pid, SIGQUIT);
/* close this carefully */
fclose(daemon->lease_stream);
}
exit(0); exit(0);
} }
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <netinet/in.h> #include <netinet/in.h>
/* get this before config.h too. */
#include <syslog.h>
#ifdef __APPLE__ #ifdef __APPLE__
/* need this before arpa/nameser.h */ /* need this before arpa/nameser.h */
# define BIND_8_COMPAT # define BIND_8_COMPAT
...@@ -69,6 +67,8 @@ ...@@ -69,6 +67,8 @@
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/ip_icmp.h> #include <netinet/ip_icmp.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <syslog.h>
#include <dirent.h>
#ifndef HAVE_LINUX_NETWORK #ifndef HAVE_LINUX_NETWORK
# include <net/if_dl.h> # include <net/if_dl.h>
#endif #endif
...@@ -319,6 +319,7 @@ struct dhcp_config { ...@@ -319,6 +319,7 @@ struct dhcp_config {
char *hostname; char *hostname;
struct dhcp_netid netid; struct dhcp_netid netid;
struct in_addr addr; struct in_addr addr;
time_t decline_time;
unsigned int lease_time, wildcard_mask; unsigned int lease_time, wildcard_mask;
struct dhcp_config *next; struct dhcp_config *next;
}; };
...@@ -331,6 +332,9 @@ struct dhcp_config { ...@@ -331,6 +332,9 @@ struct dhcp_config {
#define CONFIG_ADDR 32 #define CONFIG_ADDR 32
#define CONFIG_NETID 64 #define CONFIG_NETID 64
#define CONFIG_NOCLID 128 #define CONFIG_NOCLID 128
#define CONFIG_FROM_ETHERS 256 /* entry created by /etc/ethers */
#define CONFIG_ADDR_HOSTS 512 /* address added by from /etc/hosts */
#define CONFIG_DECLINED 1024 /* address declined by client */
struct dhcp_opt { struct dhcp_opt {
int opt, len, flags; int opt, len, flags;
...@@ -417,6 +421,7 @@ struct daemon { ...@@ -417,6 +421,7 @@ struct daemon {
struct iname *if_names, *if_addrs, *if_except, *dhcp_except; struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
struct bogus_addr *bogus_addr; struct bogus_addr *bogus_addr;
struct server *servers; struct server *servers;
int log_fac; /* log facility */
int cachesize; int cachesize;
int port, query_port; int port, query_port;
unsigned long local_ttl; unsigned long local_ttl;
...@@ -532,15 +537,15 @@ char *print_mac(struct daemon *daemon, unsigned char *mac, int len); ...@@ -532,15 +537,15 @@ char *print_mac(struct daemon *daemon, unsigned char *mac, int len);
struct daemon *read_opts (int argc, char **argv, char *compile_opts); struct daemon *read_opts (int argc, char **argv, char *compile_opts);
/* forward.c */ /* forward.c */
void forward_init(int first);
void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now); void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now);
void receive_query(struct listener *listen, struct daemon *daemon, time_t now); void receive_query(struct listener *listen, struct daemon *daemon, time_t now);
unsigned char *tcp_request(struct daemon *daemon, int confd, time_t now, unsigned char *tcp_request(struct daemon *daemon, int confd, time_t now,
struct in_addr local_addr, struct in_addr netmask); struct in_addr local_addr, struct in_addr netmask);
void server_gone(struct daemon *daemon, struct server *server);
/* network.c */ /* network.c */
struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds); struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds);
void reload_servers(char *fname, struct daemon *daemon); int reload_servers(char *fname, struct daemon *daemon);
void check_servers(struct daemon *daemon); void check_servers(struct daemon *daemon);
int enumerate_interfaces(struct daemon *daemon); int enumerate_interfaces(struct daemon *daemon);
struct listener *create_wildcard_listeners(int port); struct listener *create_wildcard_listeners(int port);
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "dnsmasq.h" #include "dnsmasq.h"
static struct frec *frec_list; static struct frec *frec_list = NULL;
static struct frec *get_new_frec(time_t now); static struct frec *get_new_frec(time_t now);
static struct frec *lookup_frec(unsigned short id); static struct frec *lookup_frec(unsigned short id);
...@@ -21,16 +21,6 @@ static struct frec *lookup_frec_by_sender(unsigned short id, ...@@ -21,16 +21,6 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
unsigned int crc); unsigned int crc);
static unsigned short get_id(void); static unsigned short get_id(void);
/* May be called more than once. */
void forward_init(int first)
{
struct frec *f;
if (first)
frec_list = NULL;
for (f = frec_list; f; f = f->next)
f->new_id = 0;
}
/* Send a UDP packet with it's source address set as "source" /* Send a UDP packet with it's source address set as "source"
unless nowild is true, when we just send it with the kernel default */ unless nowild is true, when we just send it with the kernel default */
...@@ -927,6 +917,21 @@ static struct frec *lookup_frec_by_sender(unsigned short id, ...@@ -927,6 +917,21 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
return NULL; return NULL;
} }
/* A server record is going away, remove references to it */
void server_gone(struct daemon *daemon, struct server *server)
{
struct frec *f;
for (f = frec_list; f; f = f->next)
if (f->new_id != 0 && f->sentto == server)
f->new_id = 0;
if (daemon->last_server == server)
daemon->last_server = NULL;
if (daemon->srv_save == server)
daemon->srv_save = NULL;
}
/* return unique random ids between 1 and 65535 */ /* return unique random ids between 1 and 65535 */
static unsigned short get_id(void) static unsigned short get_id(void)
......
...@@ -18,7 +18,6 @@ static int dns_dirty, file_dirty, leases_left; ...@@ -18,7 +18,6 @@ static int dns_dirty, file_dirty, leases_left;
void lease_init(struct daemon *daemon, time_t now) void lease_init(struct daemon *daemon, time_t now)
{ {
unsigned long ei; unsigned long ei;
unsigned char hwaddr[DHCP_CHADDR_MAX];
struct in_addr addr; struct in_addr addr;
struct dhcp_lease *lease; struct dhcp_lease *lease;
int flags, clid_len, hw_len, hw_type; int flags, clid_len, hw_len, hw_type;
...@@ -43,7 +42,7 @@ void lease_init(struct daemon *daemon, time_t now) ...@@ -43,7 +42,7 @@ void lease_init(struct daemon *daemon, time_t now)
&ei, daemon->dhcp_buff2, daemon->namebuff, &ei, daemon->dhcp_buff2, daemon->namebuff,
daemon->dhcp_buff, daemon->packet) == 5) daemon->dhcp_buff, daemon->packet) == 5)
{ {
hw_len = parse_hex(daemon->dhcp_buff2, hwaddr, DHCP_CHADDR_MAX, NULL, &hw_type); hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
/* For backwards compatibility, no explict MAC address type means ether. */ /* For backwards compatibility, no explict MAC address type means ether. */
if (hw_type == 0 && hw_len != 0) if (hw_type == 0 && hw_len != 0)
hw_type = ARPHRD_ETHER; hw_type = ARPHRD_ETHER;
...@@ -72,7 +71,7 @@ void lease_init(struct daemon *daemon, time_t now) ...@@ -72,7 +71,7 @@ void lease_init(struct daemon *daemon, time_t now)
lease->expires = (time_t)ei; lease->expires = (time_t)ei;
#endif #endif
lease_set_hwaddr(lease, hwaddr, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len); lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
if (strcmp(daemon->dhcp_buff, "*") != 0) if (strcmp(daemon->dhcp_buff, "*") != 0)
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0); lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
......
...@@ -141,6 +141,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local, ...@@ -141,6 +141,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local,
netmask.s_addr = 0; netmask.s_addr = 0;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(addr.in6); addr.in6.sin6_len = sizeof(addr.in6);
#endif #endif
...@@ -148,8 +149,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local, ...@@ -148,8 +149,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local,
addr.in6.sin6_addr = *local; addr.in6.sin6_addr = *local;
addr.in6.sin6_port = htons(daemon->port); addr.in6.sin6_port = htons(daemon->port);
addr.in6.sin6_scope_id = scope; addr.in6.sin6_scope_id = scope;
addr.in6.sin6_flowinfo = 0;
return iface_allowed(daemon, (struct irec **)vparam, if_index, &addr, netmask); return iface_allowed(daemon, (struct irec **)vparam, if_index, &addr, netmask);
} }
#endif #endif
...@@ -158,7 +158,8 @@ static int iface_allowed_v4(struct daemon *daemon, struct in_addr local, int if_ ...@@ -158,7 +158,8 @@ static int iface_allowed_v4(struct daemon *daemon, struct in_addr local, int if_
struct in_addr netmask, struct in_addr broadcast, void *vparam) struct in_addr netmask, struct in_addr broadcast, void *vparam)
{ {
union mysockaddr addr; union mysockaddr addr;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(addr.in); addr.in.sin_len = sizeof(addr.in);
#endif #endif
...@@ -202,11 +203,10 @@ static int create_ipv6_listener(struct listener **link, int port) ...@@ -202,11 +203,10 @@ static int create_ipv6_listener(struct listener **link, int port)
struct listener *l; struct listener *l;
int opt = 1; int opt = 1;
memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6; addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any; addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(port); addr.in6.sin6_port = htons(port);
addr.in6.sin6_flowinfo = 0;
addr.in6.sin6_scope_id = 0;
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(addr.in6); addr.in6.sin6_len = sizeof(addr.in6);
#endif #endif
...@@ -254,6 +254,7 @@ struct listener *create_wildcard_listeners(int port) ...@@ -254,6 +254,7 @@ struct listener *create_wildcard_listeners(int port)
struct listener *l, *l6 = NULL; struct listener *l, *l6 = NULL;
int tcpfd, fd; int tcpfd, fd;
memset(&addr, 0, sizeof(addr));
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
addr.in.sin_addr.s_addr = INADDR_ANY; addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = htons(port); addr.in.sin_port = htons(port);
...@@ -394,11 +395,6 @@ void check_servers(struct daemon *daemon) ...@@ -394,11 +395,6 @@ void check_servers(struct daemon *daemon)
struct server *new, *tmp, *ret = NULL; struct server *new, *tmp, *ret = NULL;
int port = 0; int port = 0;
/* forward table rules reference servers, so have to blow them away */
forward_init(0);
daemon->last_server = daemon->srv_save = NULL;
for (new = daemon->servers; new; new = tmp) for (new = daemon->servers; new; new = tmp)
{ {
tmp = new->next; tmp = new->next;
...@@ -450,25 +446,37 @@ void check_servers(struct daemon *daemon) ...@@ -450,25 +446,37 @@ void check_servers(struct daemon *daemon)
daemon->servers = ret; daemon->servers = ret;
} }
void reload_servers(char *fname, struct daemon *daemon) /* Return zero if no servers found, in that case we keep polling.
This is a protection against an update-time/write race on resolv.conf */
int reload_servers(char *fname, struct daemon *daemon)
{ {
FILE *f; FILE *f;
char *line; char *line;
struct server *old_servers = NULL; struct server *old_servers = NULL;
struct server *new_servers = NULL; struct server *new_servers = NULL;
struct server *serv = daemon->servers; struct server *serv;
int gotone = 0;
/* buff happens to be MAXDNAME long... */
if (!(f = fopen(fname, "r")))
{
syslog(LOG_ERR, _("failed to read %s: %m"), fname);
return 0;
}
/* move old servers to free list - we can reuse the memory /* move old servers to free list - we can reuse the memory
and not risk malloc if there are the same or fewer new servers. and not risk malloc if there are the same or fewer new servers.
Servers which were specced on the command line go to the new list. */ Servers which were specced on the command line go to the new list. */
while (serv) for (serv = daemon->servers; serv;)
{ {
struct server *tmp = serv->next; struct server *tmp = serv->next;
if (serv->flags & SERV_FROM_RESOLV) if (serv->flags & SERV_FROM_RESOLV)
{ {
serv->next = old_servers; serv->next = old_servers;
old_servers = serv; old_servers = serv;
/* forward table rules reference servers, so have to blow them away */
server_gone(daemon, serv);
} }
else else
{ {
...@@ -477,82 +485,68 @@ void reload_servers(char *fname, struct daemon *daemon) ...@@ -477,82 +485,68 @@ void reload_servers(char *fname, struct daemon *daemon)
} }
serv = tmp; serv = tmp;
} }
/* buff happens to be NAXDNAME long... */ while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
f = fopen(fname, "r");
if (!f)
{
syslog(LOG_ERR, _("failed to read %s: %m"), fname);
}
else
{ {
syslog(LOG_INFO, _("reading %s"), fname); union mysockaddr addr, source_addr;
while ((line = fgets(daemon->namebuff, MAXDNAME, f))) char *token = strtok(line, " \t\n\r");
if (!token || strcmp(token, "nameserver") != 0)
continue;
if (!(token = strtok(NULL, " \t\n\r")))
continue;
memset(&addr, 0, sizeof(addr));
memset(&source_addr, 0, sizeof(source_addr));
if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
{ {
union mysockaddr addr, source_addr;
char *token = strtok(line, " \t\n\r");
struct server *serv;
if (!token || strcmp(token, "nameserver") != 0)
continue;
if (!(token = strtok(NULL, " \t\n\r")))
continue;
#ifdef HAVE_IPV6
if (inet_pton(AF_INET, token, &addr.in.sin_addr) > 0)
#else
if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
#endif
{
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
#endif #endif
source_addr.in.sin_family = addr.in.sin_family = AF_INET; source_addr.in.sin_family = addr.in.sin_family = AF_INET;
addr.in.sin_port = htons(NAMESERVER_PORT); addr.in.sin_port = htons(NAMESERVER_PORT);
source_addr.in.sin_addr.s_addr = INADDR_ANY; source_addr.in.sin_addr.s_addr = INADDR_ANY;
source_addr.in.sin_port = htons(daemon->query_port); source_addr.in.sin_port = htons(daemon->query_port);
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0) else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
{ {
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6); source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
#endif #endif
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6; source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_port = htons(NAMESERVER_PORT); addr.in6.sin6_port = htons(NAMESERVER_PORT);
source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0; source_addr.in6.sin6_addr = in6addr_any;
source_addr.in6.sin6_scope_id = addr.in6.sin6_scope_id = 0; source_addr.in6.sin6_port = htons(daemon->query_port);
source_addr.in6.sin6_addr = in6addr_any; }
source_addr.in6.sin6_port = htons(daemon->query_port);
}
#endif /* IPV6 */ #endif /* IPV6 */
else else
continue; continue;
if (old_servers) if (old_servers)
{ {
serv = old_servers; serv = old_servers;
old_servers = old_servers->next; old_servers = old_servers->next;
}
else if (!(serv = malloc(sizeof (struct server))))
continue;
/* this list is reverse ordered:
it gets reversed again in check_servers */
serv->next = new_servers;
new_servers = serv;
serv->addr = addr;
serv->source_addr = source_addr;
serv->domain = NULL;
serv->sfd = NULL;
serv->flags = SERV_FROM_RESOLV;
} }
else if (!(serv = malloc(sizeof (struct server))))
fclose(f); continue;
/* this list is reverse ordered:
it gets reversed again in check_servers */
serv->next = new_servers;
new_servers = serv;
serv->addr = addr;
serv->source_addr = source_addr;
serv->domain = NULL;
serv->sfd = NULL;
serv->flags = SERV_FROM_RESOLV;
gotone = 1;
} }
/* Free any memory not used. */ /* Free any memory not used. */
while(old_servers) while (old_servers)
{ {
struct server *tmp = old_servers->next; struct server *tmp = old_servers->next;
free(old_servers); free(old_servers);
...@@ -560,6 +554,9 @@ void reload_servers(char *fname, struct daemon *daemon) ...@@ -560,6 +554,9 @@ void reload_servers(char *fname, struct daemon *daemon)
} }
daemon->servers = new_servers; daemon->servers = new_servers;
fclose(f);
return gotone;
} }
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment