import of dnsmasq-2.32.tar.gz

This commit is contained in:
Simon Kelley committed 2012-01-05 17:31:12 +00:00
1 parent 7cebd20fe7
commit 849a8357ba
24 files changed
+6621 -4429

No files matched your search

+70 -66
View File
@@ -26,17 +26,6 @@ static struct iovec ifreq = {
.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)
{
int i = 0;
@@ -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
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;
struct iovec iov[2];
struct iovec iov[4];
/* Only know how to do ethernet on *BSD */
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,
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, ifr) < 0)
return;
memcpy(header.ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
header.ether.ether_type = htons(ETHERTYPE_IP);
memcpy(ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
ether.ether_type = htons(ETHERTYPE_IP);
if (ntohs(mess->flags) & 0x8000)
{
memset(header.ether.ether_dhost, 255, ETHER_ADDR_LEN);
header.ip.ip_dst.s_addr = INADDR_BROADCAST;
memset(ether.ether_dhost, 255, ETHER_ADDR_LEN);
ip.ip_dst.s_addr = INADDR_BROADCAST;
}
else
{
memcpy(header.ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN);
header.ip.ip_dst.s_addr = mess->yiaddr.s_addr;
memcpy(ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN);
ip.ip_dst.s_addr = mess->yiaddr.s_addr;
}
header.ip.ip_p = IPPROTO_UDP;
header.ip.ip_src.s_addr = iface_addr.s_addr;
header.ip.ip_len = htons(sizeof(struct ip) +
sizeof(struct udphdr) +
len) ;
header.ip.ip_hl = sizeof(struct ip) / 4;
header.ip.ip_v = IPVERSION;
header.ip.ip_tos = 0;
header.ip.ip_id = htons(0);
header.ip.ip_off = htons(0x4000); /* don't fragment */
header.ip.ip_ttl = IPDEFTTL;
header.ip.ip_sum = 0;
ip.ip_p = IPPROTO_UDP;
ip.ip_src.s_addr = iface_addr.s_addr;
ip.ip_len = htons(sizeof(struct ip) +
sizeof(struct udphdr) +
len) ;
ip.ip_hl = sizeof(struct ip) / 4;
ip.ip_v = IPVERSION;
ip.ip_tos = 0;
ip.ip_id = htons(0);
ip.ip_off = htons(0x4000); /* don't fragment */
ip.ip_ttl = IPDEFTTL;
ip.ip_sum = 0;
for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
sum += ((u16 *)&header.ip)[i];
sum += ((u16 *)&ip)[i];
while (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);
header.udp.uh_dport = htons(DHCP_CLIENT_PORT);
udp.uh_sport = htons(DHCP_SERVER_PORT);
udp.uh_dport = htons(DHCP_CLIENT_PORT);
if (len & 1)
((char *)mess)[len] = 0; /* for checksum, in case length is odd. */
header.udp.uh_sum = 0;
header.udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len);
udp.uh_sum = 0;
udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len);
sum += htons(IPPROTO_UDP);
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++)
sum += ((u16 *)&header.udp)[i];
sum += ((u16 *)&udp)[i];
for (i = 0; i < (len + 1) / 2; i++)
sum += ((u16 *)mess)[i];
while (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);
iov[0].iov_base = &header;
iov[0].iov_len = sizeof(struct header);
iov[1].iov_base = mess;
iov[1].iov_len = len;
while (writev(daemon->dhcp_raw_fd, iov, 2) == -1 && retry_send());
iov[0].iov_base = &ether;
iov[0].iov_len = sizeof(ether);
iov[1].iov_base = &ip;
iov[1].iov_len = sizeof(ip);
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)())
@@ -150,31 +152,33 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
struct ifconf ifc;
int fd, errsav, ret = 0;
int lastlen = 0;
size_t len;
size_t len = 0;
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0;
for (len = 0; ; len += 10*sizeof(struct ifreq))
while(1)
{
if (!expand_buf(&ifconf, len))
goto err;
ifc.ifc_len = len;
ifc.ifc_buf = ifconf.iov_base;
if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
{
if (errno != EINVAL || lastlen != 0)
goto err;
}
else
{
if (ifc.ifc_len == lastlen)
break; /* got a big enough buffer now */
lastlen = ifc.ifc_len;
}
}
len += 10*sizeof(struct ifreq);
if (!expand_buf(&ifconf, len))
goto err;
ifc.ifc_len = len;
ifc.ifc_buf = ifconf.iov_base;
if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
{
if (errno != EINVAL || lastlen != 0)
goto err;
}
else
{
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 )
{
+2 -15
View File
@@ -10,7 +10,7 @@
GNU General Public License for more details.
*/
#define VERSION "2.31"
#define VERSION "2.32"
#define FTABSIZ 150 /* max number of outstanding requests */
#define MAX_PROCS 20 /* max no children for TCP requests */
@@ -23,6 +23,7 @@
#define MAXLEASES 150 /* maximum number of DHCP leases */
#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 DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
#define SMALLDNAME 40 /* most domain names are smaller than this */
#define HOSTSFILE "/etc/hosts"
@@ -53,20 +54,6 @@
#define DNSMASQ_SERVICE "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 */
#ifndef T_SRV
+40 -20
View File
@@ -47,6 +47,7 @@ void dhcp_init(struct daemon *daemon)
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)) == -1)
die(_("failed to set SO_REUSEADDR on DHCP socket: %s"), NULL);
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(DHCP_SERVER_PORT);
saddr.sin_addr.s_addr = INADDR_ANY;
@@ -237,9 +238,10 @@ void dhcp_packet(struct daemon *daemon, time_t now)
dest.sin_port = htons(DHCP_CLIENT_PORT);
}
#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;
msg.msg_control = control_u.control;
msg.msg_controllen = sizeof(control_u);
@@ -255,21 +257,17 @@ void dhcp_packet(struct daemon *daemon, time_t now)
}
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_port = htons(DHCP_CLIENT_PORT);
if (mess->hlen != 0 && mess->hlen <= 14 && mess->htype != 0)
{
/* inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
struct arpreq req;
*((struct sockaddr_in *)&req.arp_pa) = dest;
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);
}
*((struct sockaddr_in *)&req.arp_pa) = dest;
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
@@ -366,7 +364,7 @@ struct dhcp_context *address_available(struct dhcp_context *context, struct in_a
struct dhcp_context *tmp;
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;
for (tmp = context; tmp; tmp = tmp->current)
@@ -481,7 +479,7 @@ int address_allocate(struct dhcp_context *context, struct daemon *daemon,
do {
/* eliminate addresses in use by the server. */
for (d = context; d; d = d->current)
if (addr.s_addr == d->local.s_addr)
if (addr.s_addr == d->router.s_addr)
break;
if (!d &&
@@ -622,6 +620,7 @@ void dhcp_read_ethers(struct daemon *daemon)
char *ip, *cp;
struct in_addr addr;
unsigned char hwaddr[ETHER_ADDR_LEN];
struct dhcp_config **up, *tmp;
struct dhcp_config *config, *configs = daemon->dhcp_conf;
int count = 0, lineno = 0;
@@ -633,6 +632,22 @@ void dhcp_read_ethers(struct daemon *daemon)
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))
{
lineno++;
@@ -700,7 +715,7 @@ void dhcp_read_ethers(struct daemon *daemon)
{
if (!(config = malloc(sizeof(struct dhcp_config))))
continue;
config->flags = 0;
config->flags = CONFIG_FROM_ETHERS;
config->wildcard_mask = 0;
config->next = configs;
configs = config;
@@ -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
records which don't have an address and whose name matches.
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 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)
if (!(config->flags & CONFIG_ADDR) &&
@@ -757,7 +777,7 @@ void dhcp_update_configs(struct dhcp_config *configs)
else
{
config->addr = crec->addr.addr.addr.addr4;
config->flags |= CONFIG_ADDR;
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
}
}
}
+39 -31
View File
@@ -128,7 +128,6 @@ int main (int argc, char **argv)
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port)))
die(_("failed to create listening socket: %s"), NULL);
forward_init(1);
cache_init(daemon->cachesize, daemon->options & OPT_LOG);
now = dnsmasq_time();
@@ -167,6 +166,7 @@ int main (int argc, char **argv)
if (daemon->query_port)
{
union mysockaddr addr;
memset(&addr, 0, sizeof(addr));
addr.in.sin_family = AF_INET;
addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = htons(daemon->query_port);
@@ -175,11 +175,10 @@ int main (int argc, char **argv)
#endif
allocate_sfd(&addr, &daemon->sfds);
#ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(daemon->query_port);
addr.in6.sin6_flowinfo = 0;
addr.in6.sin6_scope_id = 0;
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
@@ -197,7 +196,19 @@ int main (int argc, char **argv)
sig = SIGHUP;
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;
struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
@@ -322,16 +333,10 @@ int main (int argc, char **argv)
capset(hdr, data);
#endif
}
}
#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));
openlog("dnsmasq", LOG_PID, daemon->log_fac);
}
if (daemon->cachesize != 0)
syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
else
@@ -444,7 +449,7 @@ int main (int argc, char **argv)
/* Check for changes to resolv files once per second max. */
/* 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;
@@ -472,14 +477,11 @@ int main (int argc, char **argv)
else
{
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;
if (difftime(res->mtime, last_change) > 0.0)
{
last_change = res->mtime;
latest = res;
}
last_change = statbuf.st_mtime;
latest = res;
}
}
res = res->next;
@@ -487,8 +489,19 @@ int main (int argc, char **argv)
if (latest)
{
reload_servers(latest->name, daemon);
check_servers(daemon);
static int warned = 0;
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)
/* Knock all our children on the head. */
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGQUIT);
kill(daemon->tcp_pids[i], SIGALRM);
if (daemon->dhcp)
{
if (daemon->script_pid != 0)
kill(daemon->script_pid, SIGQUIT);
/* close this carefully */
fclose(daemon->lease_stream);
}
fclose(daemon->lease_stream);
exit(0);
}
+9 -4
View File
@@ -16,8 +16,6 @@
#include <sys/types.h>
#include <netinet/in.h>
/* get this before config.h too. */
#include <syslog.h>
#ifdef __APPLE__
/* need this before arpa/nameser.h */
# define BIND_8_COMPAT
@@ -69,6 +67,8 @@
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/uio.h>
#include <syslog.h>
#include <dirent.h>
#ifndef HAVE_LINUX_NETWORK
# include <net/if_dl.h>
#endif
@@ -319,6 +319,7 @@ struct dhcp_config {
char *hostname;
struct dhcp_netid netid;
struct in_addr addr;
time_t decline_time;
unsigned int lease_time, wildcard_mask;
struct dhcp_config *next;
};
@@ -331,6 +332,9 @@ struct dhcp_config {
#define CONFIG_ADDR 32
#define CONFIG_NETID 64
#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 {
int opt, len, flags;
@@ -417,6 +421,7 @@ struct daemon {
struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
struct bogus_addr *bogus_addr;
struct server *servers;
int log_fac; /* log facility */
int cachesize;
int port, query_port;
unsigned long local_ttl;
@@ -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);
/* forward.c */
void forward_init(int first);
void reply_query(struct serverfd *sfd, 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,
struct in_addr local_addr, struct in_addr netmask);
void server_gone(struct daemon *daemon, struct server *server);
/* network.c */
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);
int enumerate_interfaces(struct daemon *daemon);
struct listener *create_wildcard_listeners(int port);
+16 -11
View File
@@ -12,7 +12,7 @@
#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 *lookup_frec(unsigned short id);
@@ -21,16 +21,6 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
unsigned int crc);
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"
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,
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 */
static unsigned short get_id(void)
+2 -3
View File
@@ -18,7 +18,6 @@ static int dns_dirty, file_dirty, leases_left;
void lease_init(struct daemon *daemon, time_t now)
{
unsigned long ei;
unsigned char hwaddr[DHCP_CHADDR_MAX];
struct in_addr addr;
struct dhcp_lease *lease;
int flags, clid_len, hw_len, hw_type;
@@ -43,7 +42,7 @@ void lease_init(struct daemon *daemon, time_t now)
&ei, daemon->dhcp_buff2, daemon->namebuff,
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. */
if (hw_type == 0 && hw_len != 0)
hw_type = ARPHRD_ETHER;
@@ -72,7 +71,7 @@ void lease_init(struct daemon *daemon, time_t now)
lease->expires = (time_t)ei;
#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)
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
+85 -88
View File
@@ -141,6 +141,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local,
netmask.s_addr = 0;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(addr.in6);
#endif
@@ -148,8 +149,7 @@ static int iface_allowed_v6(struct daemon *daemon, struct in6_addr *local,
addr.in6.sin6_addr = *local;
addr.in6.sin6_port = htons(daemon->port);
addr.in6.sin6_scope_id = scope;
addr.in6.sin6_flowinfo = 0;
return iface_allowed(daemon, (struct irec **)vparam, if_index, &addr, netmask);
}
#endif
@@ -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)
{
union mysockaddr addr;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(addr.in);
#endif
@@ -202,11 +203,10 @@ static int create_ipv6_listener(struct listener **link, int port)
struct listener *l;
int opt = 1;
memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(port);
addr.in6.sin6_flowinfo = 0;
addr.in6.sin6_scope_id = 0;
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(addr.in6);
#endif
@@ -254,6 +254,7 @@ struct listener *create_wildcard_listeners(int port)
struct listener *l, *l6 = NULL;
int tcpfd, fd;
memset(&addr, 0, sizeof(addr));
addr.in.sin_family = AF_INET;
addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = htons(port);
@@ -394,11 +395,6 @@ void check_servers(struct daemon *daemon)
struct server *new, *tmp, *ret = NULL;
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)
{
tmp = new->next;
@@ -450,25 +446,37 @@ void check_servers(struct daemon *daemon)
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;
char *line;
struct server *old_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
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. */
while (serv)
for (serv = daemon->servers; serv;)
{
struct server *tmp = serv->next;
if (serv->flags & SERV_FROM_RESOLV)
{
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
{
@@ -477,82 +485,68 @@ void reload_servers(char *fname, struct daemon *daemon)
}
serv = tmp;
}
/* buff happens to be NAXDNAME long... */
f = fopen(fname, "r");
if (!f)
{
syslog(LOG_ERR, _("failed to read %s: %m"), fname);
}
else
{
syslog(LOG_INFO, _("reading %s"), fname);
while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
{
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
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
#endif
source_addr.in.sin_family = addr.in.sin_family = AF_INET;
addr.in.sin_port = htons(NAMESERVER_PORT);
source_addr.in.sin_addr.s_addr = INADDR_ANY;
source_addr.in.sin_port = htons(daemon->query_port);
}
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
{
#ifdef HAVE_SOCKADDR_SA_LEN
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
#endif
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_port = htons(NAMESERVER_PORT);
source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
source_addr.in6.sin6_scope_id = addr.in6.sin6_scope_id = 0;
source_addr.in6.sin6_addr = in6addr_any;
source_addr.in6.sin6_port = htons(daemon->query_port);
}
#endif /* IPV6 */
else
continue;
if (old_servers)
{
serv = old_servers;
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;
}
fclose(f);
}
while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
{
union mysockaddr addr, source_addr;
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)
{
#ifdef HAVE_SOCKADDR_SA_LEN
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
#endif
source_addr.in.sin_family = addr.in.sin_family = AF_INET;
addr.in.sin_port = htons(NAMESERVER_PORT);
source_addr.in.sin_addr.s_addr = INADDR_ANY;
source_addr.in.sin_port = htons(daemon->query_port);
}
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
{
#ifdef HAVE_SOCKADDR_SA_LEN
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
#endif
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_port = htons(NAMESERVER_PORT);
source_addr.in6.sin6_addr = in6addr_any;
source_addr.in6.sin6_port = htons(daemon->query_port);
}
#endif /* IPV6 */
else
continue;
if (old_servers)
{
serv = old_servers;
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;
gotone = 1;
}
/* Free any memory not used. */
while(old_servers)
while (old_servers)
{
struct server *tmp = old_servers->next;
free(old_servers);
@@ -560,6 +554,9 @@ void reload_servers(char *fname, struct daemon *daemon)
}
daemon->servers = new_servers;
fclose(f);
return gotone;
}
+1637 -1557
View File
File diff suppressed because it is too large. Load diff
+19 -10
View File
@@ -109,9 +109,10 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
unsigned short fuzz = 0;
unsigned int mess_type = 0;
unsigned char fqdn_flags = 0;
subnet_addr.s_addr = 0;
unsigned char *agent_id = NULL;
subnet_addr.s_addr = 0;
if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
return 0;
@@ -524,13 +525,12 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
*q++ = c;
}
*q++ = 0; /* add terminator */
message = daemon->dhcp_buff;
}
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
return 0;
log_packet(daemon, "DECLINE", option_ptr(opt), mess, iface_name, message);
log_packet(daemon, "DECLINE", option_ptr(opt), mess, iface_name, daemon->dhcp_buff);
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
lease_prune(lease, now);
@@ -538,8 +538,11 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
if (have_config(config, CONFIG_ADDR) &&
config->addr.s_addr == option_addr(opt).s_addr)
{
syslog(LOG_WARNING, _("disabling DHCP static address %s"), inet_ntoa(config->addr));
config->flags &= ~CONFIG_ADDR ;
prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
syslog(LOG_WARNING, _("disabling DHCP static address %s for %s"),
inet_ntoa(config->addr), daemon->dhcp_buff);
config->flags |= CONFIG_DECLINED;
config->decline_time = now;
}
else
/* make sure this host gets a different address next time. */
@@ -578,18 +581,22 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
conf.s_addr = 0;
if (have_config(config, CONFIG_ADDR))
{
char *addrs = inet_ntoa(config->addr);
if ((ltmp = lease_find_by_addr(config->addr)) && ltmp != lease)
syslog(LOG_WARNING, _("not using configured address %s because it is leased to %s"),
inet_ntoa(config->addr), print_mac(daemon, ltmp->hwaddr, ltmp->hwaddr_len));
addrs, print_mac(daemon, ltmp->hwaddr, ltmp->hwaddr_len));
else
{
struct dhcp_context *tmp;
for (tmp = context; tmp; tmp = tmp->current)
if (context->local.s_addr == config->addr.s_addr)
if (context->router.s_addr == config->addr.s_addr)
break;
if (tmp)
syslog(LOG_WARNING, _("not using configured address %s because it is in use by the server"),
inet_ntoa(config->addr));
syslog(LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
else if (have_config(config, CONFIG_DECLINED) &&
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
syslog(LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
else
conf = config->addr;
}
@@ -699,7 +706,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
if (have_config(config, CONFIG_ADDR))
for (tmp = context; tmp; tmp = tmp->current)
if (context->local.s_addr == config->addr.s_addr)
if (context->router.s_addr == config->addr.s_addr)
break;
if (!(context = narrow_context(context, mess->yiaddr)))
@@ -720,6 +727,8 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
an endless protocol loop will ensue. */
else if (!tmp &&
have_config(config, CONFIG_ADDR) &&
(!have_config(config, CONFIG_DECLINED) ||
difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
config->addr.s_addr != mess->yiaddr.s_addr &&
(!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
message = _("static lease available");