Compare commits

...

3 Commits
v2.10 ... v2.13

Author SHA1 Message Date
Simon Kelley
9c74ec03ca import of dnsmasq-2.13.tar.gz 2012-01-05 17:31:10 +00:00
Simon Kelley
c1bb85048b import of dnsmasq-2.12.tar.gz 2012-01-05 17:31:10 +00:00
Simon Kelley
dfa666f24b import of dnsmasq-2.11.tar.gz 2012-01-05 17:31:10 +00:00
18 changed files with 275 additions and 133 deletions

View File

@@ -1123,4 +1123,40 @@ release 2.10
support was added. Thanks to Michael Hamilton for
assistance with this.
version 2.11
Fixed DHCP problem which could result in two leases in the
database with the same address. This looked much more
alarming then it was, since it could only happen when a
machine changes MAC address but kept the same name. The
old lease would persist until it timed out but things
would still work OK.
Check that IP addresses in all dhcp-host directives are
unique and die horribly if they are not, since otherwise
endless protocol loops can occur.
Use IPV6_RECVPKTINFO as socket option rather than
IPV6_PKTINFO where available. This keeps late-model FreeBSD
happy.
Set source interface when replying to IPv6 UDP
queries. This is needed to cope with link-local addresses.
version 2.12
Added extra checks to ensure that DHCP created DNS entries
cannot generate multiple DNS address->name entries. Thanks to
Stefan Monnier for finding the exact set of configuration
options which could create this.
Don't set the the filterwin2k option in the example config
file and add warnings that is breaks Kerberos. Thanks to
Simon Josefsson and Timothy Folks for pointing that out.
Log types of incoming queries as well as source and domain.
Log NODATA replies generated as a result of the
filterwin2k option.
version 2.13
Fixed crash with un-named DHCP hosts introduced in 2.12.
Thanks to Nicolo Wojewoda and Gregory Gathy for bug reports.

9
FAQ
View File

@@ -268,4 +268,13 @@ A: The DNS spec says that the reply to a DNS query must come from the
(address,port) pair when dnsmasq has bound (wildcard,port), hence
the ability to explicitly turn off wildcard binding.
Q: Why doesn't Kerberos work/why can't I get sensible answers to
queries for SRV records.
A: Probably because you have the "filterwin2k" option set. Note that
it was on by default in example configuration files included in
versions before 2.12, so you might have it set on without
realising.

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.10
Version: 2.13
Release: 1
Copyright: GPL
Group: System Environment/Daemons

View File

@@ -5,7 +5,7 @@
###############################################################################
Name: dnsmasq
Version: 2.10
Version: 2.13
Release: 1
Copyright: GPL
Group: Productivity/Networking/DNS/Servers
@@ -103,6 +103,7 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0 rpm/README.susefirewall
%doc contrib
%config /etc/init.d/dnsmasq
%config /etc/dnsmasq.conf
/usr/sbin/rcdnsmasq

View File

@@ -12,7 +12,7 @@
#selfmx
#localmx
# The following three options make you a better netizen, since they
# The following two options make you a better netizen, since they
# tell dnsmasq to filter out queries which the public DNS cannot
# answer, and which load the servers (especially the root servers)
# uneccessarily. If you have a dial-on-demand link they also stop
@@ -20,13 +20,16 @@
# Never forward plain names (with a dot or domain part)
domain-needed
# Reply to reverse queries for addresses in the non-routed address
# space with the dotted.quad address
# Never forward addresses in the non-routed address spaces.
bogus-priv
# Filter useless windows-originated DNS requests
filterwin2k
# Uncomment this to filter useless windows-originated DNS requests
# which can trigger dial-on-demand links needlessly.
# Note that (amongst other things) this blocks all SRV requests,
# so don't use it if you use eg Kerberos.
#filterwin2k
# Change this line if you want dns to get its upstream servers from
# somewhere other that /etc/resolv.conf
#resolv-file=

View File

@@ -112,7 +112,9 @@ bzip2 dnsmasq-zzz.tar
</PRE>
<H2>Links.</H2>
Ulrich Ivens has a nice HOWTO in German on installing dnsmasq at <A HREF="http://howto.linux-hardware-shop.de/dnsmasq.html">http://howto.linux-hardware-shop.de/dnsmasq.html</A>
Ulrich Ivens has a nice HOWTO in German on installing dnsmasq at <A
HREF="http://howto.linux-hardware-shop.de/dnsmasq.html">http://howto.linux-hardware-shop.de/dnsmasq.html</A>
and Damien Raude-Morvan has one in French at <A HREF="http://www.drazzib.com/docs-dnsmasq.html">http://www.drazzib.com/docs-dnsmasq.html</A>
<H2>License.</H2>
Dnsmasq is distributed under the GPL. See the file COPYING in the distribution

View File

@@ -1,5 +1,5 @@
--- dnsmasq.8 2004-06-21 21:55:47.000000000 +0200
+++ dnsmasq.8 2004-06-22 23:30:18.000000000 +0200
--- dnsmasq.8 2004-08-08 20:57:56.000000000 +0200
+++ dnsmasq.8 2004-08-12 00:40:01.000000000 +0200
@@ -63,7 +63,7 @@
.TP
.B \-g, --group=<groupname>
@@ -9,9 +9,9 @@
/etc/ppp/resolv.conf which is not normally world readable.
.TP
.B \-v, --version
--- dnsmasq.conf.example 2004-05-26 12:59:56.000000000 +0200
+++ dnsmasq.conf.example 2004-06-22 23:32:36.000000000 +0200
@@ -62,7 +62,7 @@
--- dnsmasq.conf.example 2004-08-08 21:18:26.000000000 +0200
+++ dnsmasq.conf.example 2004-08-12 00:40:01.000000000 +0200
@@ -65,7 +65,7 @@
# You no longer (as of version 1.7) need to set these to enable
# dnsmasq to read /etc/ppp/resolv.conf since dnsmasq now uses the
@@ -20,9 +20,9 @@
#user=
#group=
--- src/config.h 2004-06-22 21:14:50.000000000 +0200
+++ src/config.h 2004-06-22 23:31:46.000000000 +0200
@@ -38,7 +38,7 @@
--- src/config.h 2004-08-11 11:39:18.000000000 +0200
+++ src/config.h 2004-08-12 00:40:01.000000000 +0200
@@ -44,7 +44,7 @@
#endif
#define DEFLEASE 3600 /* default lease time, 1 hour */
#define CHUSER "nobody"
@@ -31,7 +31,7 @@
#define IP6INTERFACES "/proc/net/if_inet6"
#define UPTIME "/proc/uptime"
#define DHCP_SERVER_PORT 67
@@ -171,7 +171,7 @@
@@ -176,7 +176,7 @@
/* platform independent options. */
#undef HAVE_BROKEN_RTC

View File

@@ -226,7 +226,7 @@ void cache_insert(char *name, struct all_addr *addr,
union bigname *big_name = NULL;
int freed_all = flags & F_REVERSE;
log_query(flags | F_UPSTREAM, name, addr);
log_query(flags | F_UPSTREAM, name, addr, 0);
/* name is needed as workspace by log_query in this case */
if ((flags & F_NEG) && (flags & F_REVERSE))
@@ -633,36 +633,45 @@ void cache_unhash_dhcp(void)
dhcp_inuse = NULL;
}
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd, unsigned short flags)
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd)
{
struct crec *crec;
unsigned short flags = F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE;
if (!host_name)
return;
if ((crec = cache_find_by_name(NULL, host_name, 0, F_IPV4)))
{
if (crec->flags & F_HOSTS)
{
if (crec->addr.addr.addr4.s_addr != host_address->s_addr)
syslog(LOG_WARNING, "not naming DHCP lease for %s because it clashes with an /etc/hosts entry.", host_name);
return;
}
else if (!(crec->flags & F_DHCP))
{
if (crec->flags & F_NEG)
if (!(crec->flags & F_NEG))
{
/* name may have been searched for before being allocated to DHCP and
therefore got a negative cache entry. If so delete it and continue. */
cache_scan_free(host_name, NULL, 0, F_IPV4 | F_FORWARD);
goto newrec;
syslog(LOG_WARNING, "not naming DHCP lease for %s because it clashes with a cached name.", host_name);
return;
}
else
syslog(LOG_WARNING, "not naming DHCP lease for %s because it clashes with a cached name.", cache_get_name(crec));
/* name may have been searched for before being allocated to DHCP and
therefore got a negative cache entry. If so delete it and continue. */
cache_scan_free(host_name, NULL, 0, F_IPV4 | F_FORWARD);
}
return;
}
if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, F_IPV4)) && (crec->flags & F_NEG))
cache_scan_free(NULL, (struct all_addr *)host_address, 0, F_IPV4 | F_REVERSE);
newrec:
if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, F_IPV4)))
{
if (crec->flags & F_NEG)
cache_scan_free(NULL, (struct all_addr *)host_address, 0, F_IPV4 | F_REVERSE);
else
/* avoid multiple reverse mappings */
flags &= ~F_REVERSE;
}
if ((crec = dhcp_spare))
dhcp_spare = dhcp_spare->prev;
else /* need new one */
@@ -670,7 +679,7 @@ void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t
if (crec) /* malloc may fail */
{
crec->flags = F_DHCP | F_FORWARD | F_IPV4 | flags;
crec->flags = flags;
if (ttd == 0)
crec->flags |= F_IMMORTAL;
else
@@ -734,20 +743,23 @@ void dump_cache(int debug, int cache_size)
cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd))) ;
#endif
}
}
}
}
void log_query(unsigned short flags, char *name, struct all_addr *addr)
void log_query(unsigned short flags, char *name, struct all_addr *addr, unsigned short type)
{
char *source;
char *verb = "is";
char types[20];
char addrbuff[ADDRSTRLEN];
if (!log_queries)
return;
strcpy(types, " ");
if (flags & F_NEG)
{
if (flags & F_REVERSE)
@@ -796,6 +808,47 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr)
}
else if (flags & F_QUERY)
{
unsigned int i;
static struct {
unsigned int type;
char *name;
} typestr[] = {
{ 1, "A" },
{ 2, "NS" },
{ 5, "CNAME" },
{ 6, "SOA" },
{ 10, "NULL" },
{ 11, "WKS" },
{ 12, "PTR" },
{ 13, "HINFO" },
{ 15, "MX" },
{ 16, "TXT" },
{ 22, "NSAP" },
{ 23, "NSAP_PTR" },
{ 24, "SIG" },
{ 25, "KEY" },
{ 28, "AAAA" },
{ 33, "SRV" },
{ 36, "KX" },
{ 37, "CERT" },
{ 38, "A6" },
{ 39, "DNAME" },
{ 41, "OPT" },
{ 250, "TSIG" },
{ 251, "IXFR" },
{ 252, "AXFR" },
{ 253, "MAILB" },
{ 254, "MAILA" },
{ 255, "ANY" }
};
if (type != 0)
{
sprintf(types, "[type=%d] ", type);
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
if (typestr[i].type == type)
sprintf(types,"[%s] ", typestr[i].name);
}
source = "query";
verb = "from";
}
@@ -803,7 +856,7 @@ void log_query(unsigned short flags, char *name, struct all_addr *addr)
source = "cached";
if ((flags & F_FORWARD) | (flags & F_NEG))
syslog(LOG_DEBUG, "%s %s %s %s", source, name, verb, addrbuff);
syslog(LOG_DEBUG, "%s %s%s%s %s", source, name, types, verb, addrbuff);
else if (flags & F_REVERSE)
syslog(LOG_DEBUG, "%s %s is %s", source, addrbuff, name);
}

View File

@@ -12,7 +12,7 @@
/* Author's email: simon@thekelleys.org.uk */
#define VERSION "2.10"
#define VERSION "2.13"
#define FTABSIZ 150 /* max number of outstanding requests */
#define MAX_PROCS 20 /* max no children for TCP requests */

View File

@@ -14,12 +14,13 @@
#include "dnsmasq.h"
void dhcp_init(int *fdp, int* rfdp)
void dhcp_init(int *fdp, int* rfdp, struct dhcp_config *configs)
{
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in saddr;
int opt = 1;
struct dhcp_config *cp;
if (fd == -1)
die ("cannot create DHCP socket : %s", NULL);
@@ -57,6 +58,14 @@ void dhcp_init(int *fdp, int* rfdp)
#endif
*rfdp = fd;
/* If the same IP appears in more than one host config, then DISCOVER
for one of the hosts will get the address, but REQUEST will be NAKed,
since the address is reserved by the other one -> protocol loop. */
for (; configs; configs = configs->next)
for (cp = configs->next; cp; cp = cp->next)
if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
die("Duplicate IP address %s in dhcp-config directive.", inet_ntoa(cp->addr));
}
void dhcp_packet(struct dhcp_context *contexts, char *packet,
@@ -370,6 +379,17 @@ int address_available(struct dhcp_context *context, struct in_addr taddr)
return 1;
}
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
{
struct dhcp_config *config;
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
return config;
return NULL;
}
int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
struct in_addr *addrp, unsigned char *hwaddr)
@@ -377,7 +397,6 @@ int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration */
struct dhcp_config *config;
struct in_addr start, addr ;
unsigned int i, j;
@@ -400,17 +419,10 @@ int address_allocate(struct dhcp_context *context, struct dhcp_config *configs,
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
if (!lease_find_by_addr(addr))
if (!lease_find_by_addr(addr) && !config_find_by_address(configs, addr))
{
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
break;
if (!config)
{
*addrp = addr;
return 1;
}
*addrp = addr;
return 1;
}
} while (addr.s_addr != start.s_addr);

View File

@@ -206,7 +206,7 @@ int main (int argc, char **argv)
if (c != 1)
die("must set exactly one interface on broken systems without IP_RECVIF", NULL);
#endif
dhcp_init(&dhcpfd, &dhcp_raw_fd);
dhcp_init(&dhcpfd, &dhcp_raw_fd, dhcp_configs);
leasefd = lease_init(lease_file, domain_suffix, dnamebuff, packet, now, maxleases);
}

View File

@@ -230,6 +230,7 @@ struct frec {
union mysockaddr source;
struct all_addr dest;
struct server *sentto;
unsigned int iface;
unsigned short orig_id, new_id;
int fd;
time_t time;
@@ -321,7 +322,7 @@ struct udp_dhcp_packet {
/* cache.c */
void cache_init(int cachesize, int log);
void log_query(unsigned short flags, char *name, struct all_addr *addr);
void log_query(unsigned short flags, char *name, struct all_addr *addr, unsigned short type);
struct crec *cache_find_by_addr(struct crec *crecp,
struct all_addr *addr, time_t now,
unsigned short prot);
@@ -332,14 +333,14 @@ void cache_start_insert(void);
void cache_insert(char *name, struct all_addr *addr,
time_t now, unsigned long ttl, unsigned short flags);
void cache_reload(int opts, char *buff, char *domain_suffix, char *addn_hosts);
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address,
time_t ttd, unsigned short flags);
void cache_add_dhcp_entry(char *host_name, struct in_addr *host_address, time_t ttd);
void cache_unhash_dhcp(void);
void dump_cache(int debug, int size);
char *cache_get_name(struct crec *crecp);
/* rfc1035.c */
unsigned short extract_request(HEADER *header, unsigned int qlen, char *name);
unsigned short extract_request(HEADER *header, unsigned int qlen,
char *name, unsigned short *typep);
int setup_reply(HEADER *header, unsigned int qlen,
struct all_addr *addrp, unsigned short flags,
unsigned long local_ttl);
@@ -412,7 +413,7 @@ struct irec *enumerate_interfaces(struct iname **names,
struct listener *create_wildcard_listeners(int port);
struct listener *create_bound_listeners(struct irec *interfaces, int port);
/* dhcp.c */
void dhcp_init(int *fdp, int* rfdp);
void dhcp_init(int *fdp, int* rfdp, struct dhcp_config *configs);
void dhcp_packet(struct dhcp_context *contexts, char *packet,
struct dhcp_opt *dhcp_opts, struct dhcp_config *dhcp_configs,
struct dhcp_vendor *vendors,
@@ -430,7 +431,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_config *read_ethers(struct dhcp_config *configs, char *buff);
void dhcp_update_configs(struct dhcp_config *configs);
struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff);
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
/* lease.c */
void lease_update_file(int force, time_t now);
void lease_update_dns(void);

View File

@@ -36,7 +36,8 @@ void forward_init(int first)
/* 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 */
static void send_from(int fd, int nowild, char *packet, int len,
union mysockaddr *to, struct all_addr *source)
union mysockaddr *to, struct all_addr *source,
unsigned int iface)
{
struct msghdr msg;
struct iovec iov[1];
@@ -94,7 +95,7 @@ static void send_from(int fd, int nowild, char *packet, int len,
{
struct cmsghdr *cmptr = CMSG_FIRSTHDR(&msg);
struct in6_pktinfo *pkt = (struct in6_pktinfo *)CMSG_DATA(cmptr);
pkt->ipi6_ifindex = 0;
pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
pkt->ipi6_addr = source->addr.addr6;
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmptr->cmsg_type = IPV6_PKTINFO;
@@ -134,7 +135,7 @@ unsigned short search_servers(struct server *servers, unsigned int options, stru
*type = SERV_FOR_NODOTS;
flags = 0;
if (serv->flags & SERV_NO_ADDR)
flags = F_NOERR;
flags = F_NXDOMAIN;
else if ((serv->flags & SERV_LITERAL_ADDRESS) && (sflag & qtype))
{
flags = sflag;
@@ -159,7 +160,7 @@ unsigned short search_servers(struct server *servers, unsigned int options, stru
matchlen = domainlen;
flags = 0;
if (serv->flags & SERV_NO_ADDR)
flags = F_NOERR;
flags = F_NXDOMAIN;
else if ((serv->flags & SERV_LITERAL_ADDRESS) && ((sflag | F_QUERY ) & qtype))
{
flags = qtype;
@@ -173,26 +174,26 @@ unsigned short search_servers(struct server *servers, unsigned int options, stru
}
}
if (flags & ~F_NOERR) /* flags set here means a literal found */
if (flags & ~F_NXDOMAIN) /* flags set here means a literal found */
{
if (flags & F_QUERY)
log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL);
log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL, 0);
else
log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp);
log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0);
}
else if (qtype && (options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.'))
flags = F_NXDOMAIN;
flags = F_NOERR;
if (flags & (F_NOERR | F_NXDOMAIN))
log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL);
log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL, 0);
return flags;
}
/* returns new last_server */
static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
struct all_addr *dst_addr, HEADER *header,
int plen, unsigned int options, char *dnamebuff,
struct all_addr *dst_addr, unsigned int dst_iface,
HEADER *header, int plen, unsigned int options, char *dnamebuff,
struct server *servers, struct server *last_server,
time_t now, unsigned long local_ttl)
{
@@ -201,7 +202,7 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
int forwardall = 0, type = 0;
struct all_addr *addrp = NULL;
unsigned short flags = 0;
unsigned short gotname = extract_request(header, (unsigned int)plen, dnamebuff);
unsigned short gotname = extract_request(header, (unsigned int)plen, dnamebuff, NULL);
struct server *start = NULL;
/* may be recursion not speced or no servers available. */
@@ -246,6 +247,7 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
forward->source = *udpaddr;
forward->dest = *dst_addr;
forward->iface = dst_iface;
forward->new_id = get_id();
forward->fd = udpfd;
forward->orig_id = ntohs(header->id);
@@ -280,11 +282,11 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
strcpy(dnamebuff, "query");
if (start->addr.sa.sa_family == AF_INET)
log_query(F_SERVER | F_IPV4 | F_FORWARD, dnamebuff,
(struct all_addr *)&start->addr.in.sin_addr);
(struct all_addr *)&start->addr.in.sin_addr, 0);
#ifdef HAVE_IPV6
else
log_query(F_SERVER | F_IPV6 | F_FORWARD, dnamebuff,
(struct all_addr *)&start->addr.in6.sin6_addr);
(struct all_addr *)&start->addr.in6.sin6_addr, 0);
#endif
forwarded = 1;
forward->sentto = start;
@@ -310,7 +312,7 @@ static struct server *forward_query(int udpfd, union mysockaddr *udpaddr,
/* could not send on, return empty answer or address if known for whole domain */
plen = setup_reply(header, (unsigned int)plen, addrp, flags, local_ttl);
send_from(udpfd, options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr);
send_from(udpfd, options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr, dst_iface);
return last_server;
}
@@ -405,7 +407,7 @@ struct server *reply_query(struct serverfd *sfd, int options, char *packet, time
return NULL;
header->id = htons(forward->orig_id);
send_from(forward->fd, options & OPT_NOWILD, packet, n, &forward->source, &forward->dest);
send_from(forward->fd, options & OPT_NOWILD, packet, n, &forward->source, &forward->dest, forward->iface);
forward->new_id = 0; /* cancel */
}
@@ -420,6 +422,7 @@ struct server *receive_query(struct listener *listen, char *packet, struct mx_re
{
HEADER *header = (HEADER *)packet;
union mysockaddr source_addr;
unsigned short type;
struct iname *tmp;
struct all_addr dst_addr;
int check_dst = !(options & OPT_NOWILD);
@@ -549,24 +552,24 @@ struct server *receive_query(struct listener *listen, char *packet, struct mx_re
}
}
if (extract_request(header, (unsigned int)n, namebuff))
if (extract_request(header, (unsigned int)n, namebuff, &type))
{
if (listen->family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, namebuff,
(struct all_addr *)&source_addr.in.sin_addr);
(struct all_addr *)&source_addr.in.sin_addr, type);
#ifdef HAVE_IPV6
else
log_query(F_QUERY | F_IPV6 | F_FORWARD, namebuff,
(struct all_addr *)&source_addr.in6.sin6_addr);
(struct all_addr *)&source_addr.in6.sin6_addr, type);
#endif
}
m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n,
mxnames, mxtarget, options, now, local_ttl, namebuff, edns_pcktsz);
if (m >= 1)
send_from(listen->fd, options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr);
send_from(listen->fd, options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index);
else
last_server = forward_query(listen->fd, &source_addr, &dst_addr,
last_server = forward_query(listen->fd, &source_addr, &dst_addr, if_index,
header, n, options, namebuff, servers,
last_server, now, local_ttl);
return last_server;
@@ -617,6 +620,7 @@ char *tcp_request(int confd, struct mx_record *mxnames,
unsigned short edns_pktsz)
{
int size = 0, m;
unsigned short qtype, gotname;
unsigned char c1, c2;
/* Max TCP packet + slop */
char *packet = malloc(65536 + MAXDNAME + RRFIXEDSZ);
@@ -635,7 +639,7 @@ char *tcp_request(int confd, struct mx_record *mxnames,
header = (HEADER *)packet;
if (extract_request(header, (unsigned int)size, namebuff))
if ((gotname = extract_request(header, (unsigned int)size, namebuff, &qtype)))
{
union mysockaddr peer_addr;
socklen_t peer_len = sizeof(union mysockaddr);
@@ -644,11 +648,11 @@ char *tcp_request(int confd, struct mx_record *mxnames,
{
if (peer_addr.sa.sa_family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, namebuff,
(struct all_addr *)&peer_addr.in.sin_addr);
(struct all_addr *)&peer_addr.in.sin_addr, qtype);
#ifdef HAVE_IPV6
else
log_query(F_QUERY | F_IPV6 | F_FORWARD, namebuff,
(struct all_addr *)&peer_addr.in6.sin6_addr);
(struct all_addr *)&peer_addr.in6.sin6_addr, qtype);
#endif
}
}
@@ -660,7 +664,6 @@ char *tcp_request(int confd, struct mx_record *mxnames,
if (m == 0)
{
unsigned short flags = 0;
unsigned short gotname = extract_request(header, (unsigned int)size, namebuff);
struct all_addr *addrp = NULL;
int type = 0;
char *domain = NULL;
@@ -729,11 +732,11 @@ char *tcp_request(int confd, struct mx_record *mxnames,
strcpy(namebuff, "query");
if (last_server->addr.sa.sa_family == AF_INET)
log_query(F_SERVER | F_IPV4 | F_FORWARD, namebuff,
(struct all_addr *)&last_server->addr.in.sin_addr);
(struct all_addr *)&last_server->addr.in.sin_addr, 0);
#ifdef HAVE_IPV6
else
log_query(F_SERVER | F_IPV6 | F_FORWARD, namebuff,
(struct all_addr *)&last_server->addr.in6.sin6_addr);
(struct all_addr *)&last_server->addr.in6.sin6_addr, 0);
#endif
/* There's no point in updating the cache, since this process will exit and

View File

@@ -235,13 +235,8 @@ void load_dhcp(char *file, char *suffix, time_t now, char *hostname)
for (lease = leases; lease; lease = lease->next)
{
if (lease->fqdn)
{
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires, F_REVERSE);
cache_add_dhcp_entry(lease->name, &lease->addr, lease->expires, 0);
}
else
cache_add_dhcp_entry(lease->name, &lease->addr, lease->expires, F_REVERSE);
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
cache_add_dhcp_entry(lease->name, &lease->addr, lease->expires);
}
}

View File

@@ -175,13 +175,8 @@ void lease_update_dns(void)
for (lease = leases; lease; lease = lease->next)
{
if (lease->fqdn)
{
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires, F_REVERSE);
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires, 0);
}
else if (lease->hostname)
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires, F_REVERSE);
cache_add_dhcp_entry(lease->fqdn, &lease->addr, lease->expires);
cache_add_dhcp_entry(lease->hostname, &lease->addr, lease->expires);
}
dns_dirty = 0;

View File

@@ -263,7 +263,11 @@ static int create_ipv6_listener(struct listener **link, int port)
setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
(flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
#ifdef IPV6_RECVPKTINFO
setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
#else
setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
#endif
bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
listen(tcpfd, 5) == -1 ||
bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)

View File

@@ -650,11 +650,14 @@ void extract_addresses(HEADER *header, unsigned int qlen, char *name,
/* If the packet holds exactly one query
return 1 and leave the name from the query in name. */
unsigned short extract_request(HEADER *header,unsigned int qlen, char *name)
unsigned short extract_request(HEADER *header,unsigned int qlen, char *name, unsigned short *typep)
{
unsigned char *p = (unsigned char *)(header+1);
int qtype, qclass;
if (typep)
*typep = 0;
if (ntohs(header->qdcount) != 1 || header->opcode != QUERY)
return 0; /* must be exactly one query. */
@@ -666,6 +669,9 @@ unsigned short extract_request(HEADER *header,unsigned int qlen, char *name)
if (qclass == C_IN)
{
if (typep)
*typep = qtype;
if (qtype == T_A)
return F_IPV4;
if (qtype == T_AAAA)
@@ -885,7 +891,10 @@ int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_rec
{
if ((options & OPT_FILTER) &&
(qtype == T_SOA || qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
ans = 1;
{
ans = 1;
log_query(F_CONFIG | F_NEG, name, &addr, 0);
}
else
{
if (qtype == T_PTR || qtype == T_ANY)
@@ -898,7 +907,7 @@ int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_rec
ans = 1;
if (!dryrun)
{
log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, name, &addr);
log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, name, &addr, 0);
nxdomain = 1;
}
}
@@ -914,7 +923,7 @@ int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_rec
ans = 1;
if (!dryrun)
{
log_query(crecp->flags & ~F_FORWARD, name, &addr);
log_query(crecp->flags & ~F_FORWARD, name, &addr, 0);
auth = 0;
if (crecp->flags & F_NXDOMAIN)
nxdomain = 1;
@@ -939,7 +948,7 @@ int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_rec
ansp = add_text_record(nameoffset, ansp, ttl, 0, T_PTR,
cache_get_name(crecp));
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr);
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, 0);
anscount++;
/* if last answer exceeded packet size, give up */
@@ -981,7 +990,7 @@ int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_rec
ans = 1;
if (!dryrun)
{
log_query(crecp->flags, name, NULL);
log_query(crecp->flags, name, NULL, 0);
auth = 0;
if (crecp->flags & F_NXDOMAIN)
nxdomain = 1;
@@ -1001,7 +1010,7 @@ int answer_request(HEADER *header, char *limit, unsigned int qlen, struct mx_rec
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
auth = 0;
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr);
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr, 0);
/* copy question as first part of answer (use compression) */
PUTSHORT(nameoffset | 0xc000, ansp);

View File

@@ -89,7 +89,7 @@ int dhcp_reply(struct dhcp_context *context,
struct in_addr dhcp_next_server, struct in_addr router)
{
unsigned char *opt, *clid;
struct dhcp_lease *lease;
struct dhcp_lease *lease, *ltmp;
struct dhcp_vendor *vendor;
int clid_len;
struct dhcp_packet *mess = &rawpacket->data;
@@ -152,8 +152,9 @@ int dhcp_reply(struct dhcp_context *context,
clid_len = 0;
}
if ((config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, NULL)) &&
have_config(config, CONFIG_NAME))
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, NULL);
if (have_config(config, CONFIG_NAME))
hostname = config->hostname;
else if ((opt = option_find(mess, sz, OPTION_HOSTNAME)))
{
@@ -184,8 +185,16 @@ int dhcp_reply(struct dhcp_context *context,
hostname = NULL; /* nothing left */
}
}
/* search again now we have a hostname */
config = find_config(dhcp_configs, context, clid, clid_len, mess->chaddr, hostname);
/* Search again now we have a hostname.
Only accept configs without CLID and HWADDR here, (they won't match)
to avoid impersonation by name. */
if (!config)
{
struct dhcp_config *new = find_config(dhcp_configs, context, NULL, 0, mess->chaddr, hostname);
if (!have_config(new, CONFIG_CLID) && !have_config(new, CONFIG_HWADDR))
config = new;
}
}
}
@@ -343,11 +352,13 @@ int dhcp_reply(struct dhcp_context *context,
addr = option_addr(opt);
if (have_config(config, CONFIG_DISABLE))
message = "ignored";
else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr))
else if (have_config(config, CONFIG_ADDR) &&
(!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
mess->yiaddr = config->addr;
else if (lease && address_available(context, lease->addr))
mess->yiaddr = lease->addr;
else if (opt && address_available(context, addr) && !lease_find_by_addr(addr))
else if (opt && address_available(context, addr) && !lease_find_by_addr(addr) &&
!config_find_by_address(dhcp_configs, addr))
mess->yiaddr = addr;
else if (!address_allocate(context, dhcp_configs, &mess->yiaddr, mess->chaddr))
message = "no address available";
@@ -400,12 +411,11 @@ int dhcp_reply(struct dhcp_context *context,
if (!lease)
{
if ((!address_available(context, mess->yiaddr) || lease_find_by_addr(mess->yiaddr)) &&
(!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
message = "address unavailable";
if (lease_find_by_addr(mess->yiaddr))
message = "address in use";
else if (!(lease = lease_allocate(clid, clid_len, mess->yiaddr)))
message = "no leases left";
}
}
}
else
{
@@ -424,29 +434,38 @@ int dhcp_reply(struct dhcp_context *context,
fuzz = fuzz/2;
}
/* If a machine moves networks whilst it has a lease, we catch that here. */
if (!message && !is_same_net(mess->yiaddr, context->start, context->netmask))
message = "wrong network";
if (!message)
{
struct dhcp_config *addr_config;
/* If a machine moves networks whilst it has a lease, we catch that here. */
if (!is_same_net(mess->yiaddr, context->start, context->netmask))
message = "wrong network";
/* Check for renewal of a lease which is now outside the allowed range. */
if (!message && !address_available(context, mess->yiaddr) &&
(!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
message = "address no longer available";
/* Check for renewal of a lease which is now outside the allowed range. */
else if (!address_available(context, mess->yiaddr) &&
(!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
message = "address no longer available";
/* Check if a new static address has been configured. Be very sure that
when the client does DISCOVER, it will get the static address, otherwise
an endless protocol loop will ensue. */
else if (have_config(config, CONFIG_ADDR) && !lease_find_by_addr(config->addr))
message = "static lease available";
/* Check to see if the address is reserved as a static address for another host */
else if ((addr_config = config_find_by_address(dhcp_configs, mess->yiaddr)) && addr_config != config)
message ="address reserved";
}
/* Check if a new static address has been configured. Be very sure that
when the client does DISCOVER, it will get the static address, otherwise
an endless protocol loop will ensue. */
if (!message && have_config(config, CONFIG_ADDR) &&
!have_config(config, CONFIG_DISABLE) &&
!lease_find_by_addr(config->addr))
message = "static lease available";
log_packet("REQUEST", &mess->yiaddr, mess->chaddr, iface_name, NULL);
if (message)
{
log_packet("NAK", &mess->yiaddr, mess->chaddr, iface_name, message);
lease_prune(lease, now);
mess->siaddr.s_addr = mess->yiaddr.s_addr = mess->ciaddr.s_addr = 0;
bootp_option_put(mess, NULL, NULL);
p = option_put(p, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);