mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Merge branch 'auth'
This commit is contained in:
2
Makefile
2
Makefile
@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
|||||||
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||||
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
||||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||||
dhcp-common.o outpacket.o radv.o slaac.o
|
dhcp-common.o outpacket.o radv.o slaac.o auth.o
|
||||||
|
|
||||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||||
dns-protocol.h radv-protocol.h
|
dns-protocol.h radv-protocol.h
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
|||||||
netlink.c network.c option.c rfc1035.c \
|
netlink.c network.c option.c rfc1035.c \
|
||||||
rfc2131.c tftp.c util.c conntrack.c \
|
rfc2131.c tftp.c util.c conntrack.c \
|
||||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||||
radv.c slaac.c
|
radv.c slaac.c auth.c
|
||||||
|
|
||||||
LOCAL_MODULE := dnsmasq
|
LOCAL_MODULE := dnsmasq
|
||||||
|
|
||||||
|
|||||||
499
src/auth.c
Normal file
499
src/auth.c
Normal file
@@ -0,0 +1,499 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||||
|
{
|
||||||
|
struct subnet *subnet;
|
||||||
|
|
||||||
|
for (subnet = zone->subnet; subnet; subnet = subnet->next)
|
||||||
|
{
|
||||||
|
if (subnet->is6 && (flag & F_IPV4))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!subnet->is6)
|
||||||
|
{
|
||||||
|
struct in_addr addr = addr_u->addr.addr4;
|
||||||
|
struct in_addr mask;
|
||||||
|
|
||||||
|
mask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
|
||||||
|
|
||||||
|
if (is_same_net(addr, subnet->addr4, mask))
|
||||||
|
return subnet;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr6, subnet->prefixlen))
|
||||||
|
return subnet;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now)
|
||||||
|
{
|
||||||
|
char *name = daemon->namebuff;
|
||||||
|
unsigned char *p, *ansp;
|
||||||
|
int qtype, qclass;
|
||||||
|
unsigned int nameoffset;
|
||||||
|
int q, anscount = 0, authcount = 0;
|
||||||
|
struct crec *crecp;
|
||||||
|
int auth = 1, trunc = 0, nxdomain = 1, soa = 0, ns = 0;
|
||||||
|
struct auth_zone *zone = NULL;
|
||||||
|
struct subnet *subnet = NULL;
|
||||||
|
|
||||||
|
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* determine end of question section (we put answers there) */
|
||||||
|
if (!(ansp = skip_questions(header, qlen)))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
/* now process each question, answers go in RRs after the question */
|
||||||
|
p = (unsigned char *)(header+1);
|
||||||
|
|
||||||
|
for (q = ntohs(header->qdcount); q != 0; q--)
|
||||||
|
{
|
||||||
|
size_t domainlen, namelen;
|
||||||
|
unsigned short flag = 0;
|
||||||
|
int found = 0;
|
||||||
|
struct mx_srv_record *rec, *move, **up;
|
||||||
|
struct txt_record *txt;
|
||||||
|
struct interface_name *intr;
|
||||||
|
struct naptr *na;
|
||||||
|
struct all_addr addr;
|
||||||
|
struct cname *a;
|
||||||
|
|
||||||
|
/* save pointer to name for copying into answers */
|
||||||
|
nameoffset = p - (unsigned char *)header;
|
||||||
|
|
||||||
|
/* now extract name as .-concatenated string into name */
|
||||||
|
if (!extract_name(header, qlen, &p, name, 1, 4))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
GETSHORT(qtype, p);
|
||||||
|
GETSHORT(qclass, p);
|
||||||
|
|
||||||
|
if (qclass != C_IN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (qtype == T_PTR)
|
||||||
|
{
|
||||||
|
if (!(flag = in_arpa_name_2_addr(name, &addr)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
|
if ((subnet = filter_zone(zone, flag, &addr)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!zone)
|
||||||
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
domainlen = strlen(zone->domain);
|
||||||
|
|
||||||
|
if (flag == F_IPV4)
|
||||||
|
{
|
||||||
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
|
{
|
||||||
|
if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||||
|
intr = intr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intr)
|
||||||
|
{
|
||||||
|
namelen = strlen(intr->name);
|
||||||
|
|
||||||
|
if (namelen >= domainlen && hostname_isequal(zone->domain, &intr->name[namelen - domainlen]) &&
|
||||||
|
(namelen == domainlen || intr->name[namelen - domainlen - 1] == '.'))
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", intr->name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
|
||||||
|
do {
|
||||||
|
strcpy(name, cache_get_name(crecp));
|
||||||
|
|
||||||
|
if (crecp->flags & F_DHCP && !option_bool(OPT_DHCP_FQDN))
|
||||||
|
{
|
||||||
|
char *p = strchr(name, '.');
|
||||||
|
if (p)
|
||||||
|
*p = 0; /* must be bare name */
|
||||||
|
|
||||||
|
/* add external domain */
|
||||||
|
strcat(name, ".");
|
||||||
|
strcat(name, zone->domain);
|
||||||
|
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
else if (crecp->flags & (F_DHCP | F_HOSTS))
|
||||||
|
{
|
||||||
|
namelen = strlen(name);
|
||||||
|
|
||||||
|
if (namelen > domainlen + 1 &&
|
||||||
|
name[namelen - domainlen - 1] != '.')
|
||||||
|
continue;
|
||||||
|
if (namelen < domainlen ||
|
||||||
|
!hostname_isequal(zone->domain, &name[namelen - domainlen]))
|
||||||
|
continue; /* wrong domain */
|
||||||
|
|
||||||
|
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | F_AUTH, NULL, &addr, NULL);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cname_restart:
|
||||||
|
namelen = strlen(name);
|
||||||
|
|
||||||
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
|
{
|
||||||
|
domainlen = strlen(zone->domain);
|
||||||
|
if (namelen >= domainlen &&
|
||||||
|
hostname_isequal(zone->domain, &name[namelen - domainlen]) &&
|
||||||
|
(namelen == domainlen || name[namelen - domainlen - 1] == '.'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!zone)
|
||||||
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
|
if (!rec->issrv && hostname_isequal(name, rec->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
|
||||||
|
if (qtype == T_MX)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
|
if (rec->issrv && hostname_isequal(name, rec->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
|
||||||
|
if (qtype == T_SRV)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_SRV, C_IN, "sssd",
|
||||||
|
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||||
|
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unlink first SRV record found */
|
||||||
|
if (!move)
|
||||||
|
{
|
||||||
|
move = rec;
|
||||||
|
*up = rec->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &rec->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &rec->next;
|
||||||
|
|
||||||
|
/* put first SRV record back at the end. */
|
||||||
|
if (move)
|
||||||
|
{
|
||||||
|
*up = move;
|
||||||
|
move->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (txt = daemon->rr; txt; txt = txt->next)
|
||||||
|
if (hostname_isequal(name, txt->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (txt->class == qtype)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (txt = daemon->txt; txt; txt = txt->next)
|
||||||
|
if (txt->class == C_IN && hostname_isequal(name, txt->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (qtype == T_TXT)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (na = daemon->naptr; na; na = na->next)
|
||||||
|
if (hostname_isequal(name, na->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (qtype == T_NAPTR)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
|
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||||
|
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
|
if (hostname_isequal(name, intr->name))
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if (qtype == T_A && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_A, C_IN, "4", &addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
|
if (hostname_isequal(name, a->alias) )
|
||||||
|
{
|
||||||
|
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
||||||
|
strcpy(name, a->target);
|
||||||
|
if (!strchr(name, '.'))
|
||||||
|
{
|
||||||
|
strcat(name, ".");
|
||||||
|
strcat(name, zone->domain);
|
||||||
|
}
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_CNAME, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
goto cname_restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype == T_A)
|
||||||
|
flag = F_IPV4;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (qtype == T_AAAA)
|
||||||
|
flag = F_IPV6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (qtype == T_SOA && namelen == domainlen)
|
||||||
|
{
|
||||||
|
soa = 1; /* inhibits auth section */
|
||||||
|
found = 1;
|
||||||
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype == T_NS && namelen == domainlen)
|
||||||
|
{
|
||||||
|
ns = 1; /* inhibits auth section */
|
||||||
|
found = 1;
|
||||||
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!option_bool(OPT_DHCP_FQDN) && namelen > domainlen + 1)
|
||||||
|
{
|
||||||
|
name[namelen - domainlen - 1] = 0; /* remove domain part */
|
||||||
|
|
||||||
|
if (!strchr(name, '.') && (crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
|
||||||
|
{
|
||||||
|
if (crecp->flags & F_DHCP)
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if ((crecp->flags & flag) && filter_zone(zone, flag, &(crecp->addr.addr)))
|
||||||
|
{
|
||||||
|
name[namelen - domainlen - 1] = '.'; /* restore domain part */
|
||||||
|
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||||
|
name[namelen - domainlen - 1] = 0; /* remove domain part */
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
|
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
|
||||||
|
}
|
||||||
|
|
||||||
|
name[namelen - domainlen - 1] = '.'; /* restore domain part */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
|
||||||
|
{
|
||||||
|
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nxdomain = 0;
|
||||||
|
if ((crecp->flags & flag) && filter_zone(zone, flag, &(crecp->addr.addr)))
|
||||||
|
{
|
||||||
|
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
|
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add auth section */
|
||||||
|
if (auth)
|
||||||
|
{
|
||||||
|
if (!subnet)
|
||||||
|
name = zone->domain;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* handle NS and SOA for PTR records */
|
||||||
|
if (!subnet->is6)
|
||||||
|
{
|
||||||
|
in_addr_t a = ntohl(subnet->addr4.s_addr) >> 8;
|
||||||
|
char *p = name;
|
||||||
|
|
||||||
|
if (subnet->prefixlen == 24)
|
||||||
|
p += sprintf(p, "%d.", a & 0xff);
|
||||||
|
a = a >> 8;
|
||||||
|
if (subnet->prefixlen != 8)
|
||||||
|
p += sprintf(p, "%d.", a & 0xff);
|
||||||
|
a = a >> 8;
|
||||||
|
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
|
||||||
|
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *p = name;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
|
||||||
|
{
|
||||||
|
int dig = ((unsigned char *)&subnet->addr6)[i>>3];
|
||||||
|
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
||||||
|
}
|
||||||
|
p += sprintf(p, "ip6.arpa");
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle NS and SOA in auth section or for explicit queries */
|
||||||
|
if ((anscount != 0 || ns) &&
|
||||||
|
add_resource_record(header, limit, &trunc, 0, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_NS, C_IN, "d", name, daemon->authserver))
|
||||||
|
{
|
||||||
|
if (ns)
|
||||||
|
anscount++;
|
||||||
|
else
|
||||||
|
authcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((anscount == 0 || soa) &&
|
||||||
|
add_resource_record(header, limit, &trunc, 0, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
|
||||||
|
name, daemon->authserver, daemon->hostmaster,
|
||||||
|
daemon->soa_sn, daemon->soa_refresh,
|
||||||
|
daemon->soa_retry, daemon->soa_expiry,
|
||||||
|
daemon->auth_ttl))
|
||||||
|
{
|
||||||
|
if (soa)
|
||||||
|
anscount++;
|
||||||
|
else
|
||||||
|
authcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* done all questions, set up header and return length of result */
|
||||||
|
/* clear authoritative and truncated flags, set QR flag */
|
||||||
|
header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
|
||||||
|
/* clear RA flag */
|
||||||
|
header->hb4 &= ~HB4_RA;
|
||||||
|
|
||||||
|
/* authoritive */
|
||||||
|
if (auth)
|
||||||
|
header->hb3 |= HB3_AA;
|
||||||
|
|
||||||
|
/* truncation */
|
||||||
|
if (trunc)
|
||||||
|
header->hb3 |= HB3_TC;
|
||||||
|
|
||||||
|
if (anscount == 0 && auth && nxdomain)
|
||||||
|
SET_RCODE(header, NXDOMAIN);
|
||||||
|
else
|
||||||
|
SET_RCODE(header, NOERROR); /* no error */
|
||||||
|
header->ancount = htons(anscount);
|
||||||
|
header->nscount = htons(authcount);
|
||||||
|
return ansp - (unsigned char *)header;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1248,14 +1248,14 @@ char *record_source(int index)
|
|||||||
return "<unknown>";
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void querystr(char *str, unsigned short type)
|
void querystr(char *desc, char *str, unsigned short type)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
sprintf(str, "query[type=%d]", type);
|
sprintf(str, "%s[type=%d]", desc, type);
|
||||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||||
if (typestr[i].type == type)
|
if (typestr[i].type == type)
|
||||||
sprintf(str,"query[%s]", typestr[i].name);
|
sprintf(str,"%s[%s]", desc, typestr[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
||||||
@@ -1316,6 +1316,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
|||||||
source = arg;
|
source = arg;
|
||||||
else if (flags & F_UPSTREAM)
|
else if (flags & F_UPSTREAM)
|
||||||
source = "reply";
|
source = "reply";
|
||||||
|
else if (flags & F_AUTH)
|
||||||
|
source = "auth";
|
||||||
else if (flags & F_SERVER)
|
else if (flags & F_SERVER)
|
||||||
{
|
{
|
||||||
source = "forwarded";
|
source = "forwarded";
|
||||||
|
|||||||
@@ -42,6 +42,10 @@
|
|||||||
#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
|
#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
|
||||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
|
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
|
||||||
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
||||||
|
#define AUTH_TTL 600 /* default TTL for auth DNS */
|
||||||
|
#define SOA_REFRESH 1200 /* SOA refresh default */
|
||||||
|
#define SOA_RETRY 180 /* SOA retry default */
|
||||||
|
#define SOA_EXPIRY 1209600 /* SOA expiry default */
|
||||||
|
|
||||||
/* compile-time options: uncomment below to enable or do eg.
|
/* compile-time options: uncomment below to enable or do eg.
|
||||||
make COPTS=-DHAVE_BROKEN_RTC
|
make COPTS=-DHAVE_BROKEN_RTC
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ static int join_multicast_worker(struct in6_addr *local, int prefix,
|
|||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
/* Are we doing DHCP on this interface? */
|
/* Are we doing DHCP on this interface? */
|
||||||
if (!iface_check(AF_INET6, (struct all_addr *)local, ifrn_name))
|
if (!iface_check(AF_INET6, (struct all_addr *)local, ifrn_name, NULL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
parm.current = NULL;
|
parm.current = NULL;
|
||||||
parm.ind = iface_index;
|
parm.ind = iface_index;
|
||||||
|
|
||||||
if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name))
|
if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
|
||||||
{
|
{
|
||||||
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
|
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
|
||||||
for a secondary */
|
for a secondary */
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (!daemon->lease_file)
|
if (!daemon->lease_file)
|
||||||
{
|
{
|
||||||
@@ -151,6 +152,14 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
|
/* Create a serial at startup is not configured. */
|
||||||
|
if (daemon->authinterface && daemon->soa_sn == 0)
|
||||||
|
#ifdef HAVE_BROKEN_RTC
|
||||||
|
die(_("zone serial must be configured in --auth-soa"));
|
||||||
|
#else
|
||||||
|
daemon->soa_sn = now;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
if (daemon->dhcp || daemon->dhcp6)
|
||||||
{
|
{
|
||||||
@@ -1440,11 +1449,18 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
struct server *s;
|
struct server *s;
|
||||||
int flags;
|
int flags;
|
||||||
struct in_addr netmask;
|
struct in_addr netmask;
|
||||||
|
int auth_dns;
|
||||||
|
|
||||||
if (iface)
|
if (iface)
|
||||||
|
{
|
||||||
netmask = iface->netmask;
|
netmask = iface->netmask;
|
||||||
|
auth_dns = iface->dns_auth;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
netmask.s_addr = 0;
|
netmask.s_addr = 0;
|
||||||
|
auth_dns = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NO_FORK
|
#ifndef NO_FORK
|
||||||
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
|
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
|
||||||
@@ -1463,7 +1479,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
|
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
|
||||||
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
|
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
|
||||||
|
|
||||||
buff = tcp_request(confd, now, &tcp_addr, netmask);
|
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
||||||
|
|
||||||
shutdown(confd, SHUT_RDWR);
|
shutdown(confd, SHUT_RDWR);
|
||||||
close(confd);
|
close(confd);
|
||||||
|
|||||||
@@ -278,6 +278,20 @@ struct cname {
|
|||||||
struct cname *next;
|
struct cname *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct auth_zone {
|
||||||
|
char *domain;
|
||||||
|
struct subnet {
|
||||||
|
int is6, prefixlen;
|
||||||
|
struct in_addr addr4;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
struct in6_addr addr6;
|
||||||
|
#endif
|
||||||
|
struct subnet *next;
|
||||||
|
} *subnet;
|
||||||
|
struct auth_zone *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct host_record {
|
struct host_record {
|
||||||
struct name_list {
|
struct name_list {
|
||||||
char *name;
|
char *name;
|
||||||
@@ -357,6 +371,8 @@ struct crec {
|
|||||||
#define F_SERVER (1u<<18)
|
#define F_SERVER (1u<<18)
|
||||||
#define F_QUERY (1u<<19)
|
#define F_QUERY (1u<<19)
|
||||||
#define F_NOERR (1u<<20)
|
#define F_NOERR (1u<<20)
|
||||||
|
#define F_AUTH (1u<<21)
|
||||||
|
|
||||||
/* composites */
|
/* composites */
|
||||||
#define F_TYPE (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS) /* Only one may be set */
|
#define F_TYPE (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS) /* Only one may be set */
|
||||||
|
|
||||||
@@ -412,7 +428,7 @@ struct server {
|
|||||||
struct irec {
|
struct irec {
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
struct in_addr netmask; /* only valid for IPv4 */
|
struct in_addr netmask; /* only valid for IPv4 */
|
||||||
int tftp_ok, dhcp_ok, mtu, done, dad;
|
int tftp_ok, dhcp_ok, mtu, done, dad, dns_auth;
|
||||||
char *name;
|
char *name;
|
||||||
struct irec *next;
|
struct irec *next;
|
||||||
};
|
};
|
||||||
@@ -733,11 +749,13 @@ extern struct daemon {
|
|||||||
struct ptr_record *ptr;
|
struct ptr_record *ptr;
|
||||||
struct host_record *host_records, *host_records_tail;
|
struct host_record *host_records, *host_records_tail;
|
||||||
struct cname *cnames;
|
struct cname *cnames;
|
||||||
|
struct auth_zone *auth_zones;
|
||||||
struct interface_name *int_names;
|
struct interface_name *int_names;
|
||||||
char *mxtarget;
|
char *mxtarget;
|
||||||
char *lease_file;
|
char *lease_file;
|
||||||
char *username, *groupname, *scriptuser;
|
char *username, *groupname, *scriptuser;
|
||||||
char *luascript;
|
char *luascript;
|
||||||
|
char *authserver, *authinterface, *hostmaster;
|
||||||
int group_set, osport;
|
int group_set, osport;
|
||||||
char *domain_suffix;
|
char *domain_suffix;
|
||||||
struct cond_domain *cond_domain;
|
struct cond_domain *cond_domain;
|
||||||
@@ -751,7 +769,7 @@ extern struct daemon {
|
|||||||
int max_logs; /* queue limit */
|
int max_logs; /* queue limit */
|
||||||
int cachesize, ftabsize;
|
int cachesize, ftabsize;
|
||||||
int port, query_port, min_port;
|
int port, query_port, min_port;
|
||||||
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl;
|
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
|
||||||
struct hostsfile *addn_hosts;
|
struct hostsfile *addn_hosts;
|
||||||
struct dhcp_context *dhcp, *dhcp6, *ra_contexts;
|
struct dhcp_context *dhcp, *dhcp6, *ra_contexts;
|
||||||
struct dhcp_config *dhcp_conf;
|
struct dhcp_config *dhcp_conf;
|
||||||
@@ -778,6 +796,7 @@ extern struct daemon {
|
|||||||
unsigned int duid_enterprise, duid_config_len;
|
unsigned int duid_enterprise, duid_config_len;
|
||||||
unsigned char *duid_config;
|
unsigned char *duid_config;
|
||||||
char *dbus_name;
|
char *dbus_name;
|
||||||
|
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
||||||
|
|
||||||
/* globally used stuff for DNS */
|
/* globally used stuff for DNS */
|
||||||
char *packet; /* packet buffer */
|
char *packet; /* packet buffer */
|
||||||
@@ -835,7 +854,7 @@ extern struct daemon {
|
|||||||
void cache_init(void);
|
void cache_init(void);
|
||||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
||||||
char *record_source(int index);
|
char *record_source(int index);
|
||||||
void querystr(char *str, unsigned short type);
|
void querystr(char *desc, char *str, unsigned short type);
|
||||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||||
struct all_addr *addr, time_t now,
|
struct all_addr *addr, time_t now,
|
||||||
unsigned short prot);
|
unsigned short prot);
|
||||||
@@ -879,6 +898,16 @@ unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
|
|||||||
size_t resize_packet(struct dns_header *header, size_t plen,
|
size_t resize_packet(struct dns_header *header, size_t plen,
|
||||||
unsigned char *pheader, size_t hlen);
|
unsigned char *pheader, size_t hlen);
|
||||||
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
|
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
|
||||||
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||||
|
unsigned int nameoffset, unsigned char **pp, unsigned long ttl,
|
||||||
|
unsigned int *offset, unsigned short type, unsigned short class, char *format, ...);
|
||||||
|
unsigned char *skip_questions(struct dns_header *header, size_t plen);
|
||||||
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
|
char *name, int isExtract, int extrabytes);
|
||||||
|
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
||||||
|
|
||||||
|
/* auth.c */
|
||||||
|
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now);
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
void rand_init(void);
|
void rand_init(void);
|
||||||
@@ -935,7 +964,7 @@ char *parse_server(char *arg, union mysockaddr *addr,
|
|||||||
void reply_query(int fd, int family, time_t now);
|
void reply_query(int fd, int family, time_t now);
|
||||||
void receive_query(struct listener *listen, time_t now);
|
void receive_query(struct listener *listen, time_t now);
|
||||||
unsigned char *tcp_request(int confd, time_t now,
|
unsigned char *tcp_request(int confd, time_t now,
|
||||||
union mysockaddr *local_addr, struct in_addr netmask);
|
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns);
|
||||||
void server_gone(struct server *server);
|
void server_gone(struct server *server);
|
||||||
struct frec *get_new_frec(time_t now, int *wait);
|
struct frec *get_new_frec(time_t now, int *wait);
|
||||||
int send_from(int fd, int nowild, char *packet, size_t len,
|
int send_from(int fd, int nowild, char *packet, size_t len,
|
||||||
@@ -953,7 +982,7 @@ int enumerate_interfaces();
|
|||||||
void create_wildcard_listeners(void);
|
void create_wildcard_listeners(void);
|
||||||
void create_bound_listeners(int die);
|
void create_bound_listeners(int die);
|
||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
int iface_check(int family, struct all_addr *addr, char *name);
|
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
||||||
int fix_fd(int fd);
|
int fix_fd(int fd);
|
||||||
struct in_addr get_ifaddr(char *intr);
|
struct in_addr get_ifaddr(char *intr);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|||||||
@@ -635,6 +635,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
size_t m;
|
size_t m;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int if_index = 0;
|
int if_index = 0;
|
||||||
|
int auth_dns = 0;
|
||||||
struct iovec iov[1];
|
struct iovec iov[1];
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct cmsghdr *cmptr;
|
struct cmsghdr *cmptr;
|
||||||
@@ -657,15 +658,18 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
/* packet buffer overwritten */
|
/* packet buffer overwritten */
|
||||||
daemon->srv_save = NULL;
|
daemon->srv_save = NULL;
|
||||||
|
|
||||||
if (listen->iface && listen->family == AF_INET && option_bool(OPT_NOWILD))
|
dst_addr_4.s_addr = 0;
|
||||||
|
netmask.s_addr = 0;
|
||||||
|
|
||||||
|
if (listen->iface && option_bool(OPT_NOWILD))
|
||||||
|
{
|
||||||
|
auth_dns = listen->iface->dns_auth;
|
||||||
|
|
||||||
|
if (listen->family == AF_INET)
|
||||||
{
|
{
|
||||||
dst_addr_4 = listen->iface->addr.in.sin_addr;
|
dst_addr_4 = listen->iface->addr.in.sin_addr;
|
||||||
netmask = listen->iface->netmask;
|
netmask = listen->iface->netmask;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
dst_addr_4.s_addr = 0;
|
|
||||||
netmask.s_addr = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iov[0].iov_base = daemon->packet;
|
iov[0].iov_base = daemon->packet;
|
||||||
@@ -760,7 +764,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
/* enforce available interface configuration */
|
/* enforce available interface configuration */
|
||||||
|
|
||||||
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
|
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
|
||||||
!iface_check(listen->family, &dst_addr, ifr.ifr_name))
|
!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
|
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
|
||||||
@@ -796,7 +800,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
char types[20];
|
char types[20];
|
||||||
|
|
||||||
querystr(types, type);
|
querystr(auth_dns ? "auth" : "query", types, type);
|
||||||
|
|
||||||
if (listen->family == AF_INET)
|
if (listen->family == AF_INET)
|
||||||
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||||
@@ -808,8 +812,18 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auth_dns)
|
||||||
|
{
|
||||||
|
m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now);
|
||||||
|
if (m >= 1)
|
||||||
|
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||||
|
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n,
|
m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n,
|
||||||
dst_addr_4, netmask, now);
|
dst_addr_4, netmask, now);
|
||||||
|
|
||||||
if (m >= 1)
|
if (m >= 1)
|
||||||
{
|
{
|
||||||
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||||
@@ -822,13 +836,14 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
else
|
else
|
||||||
daemon->local_answer++;
|
daemon->local_answer++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The daemon forks before calling this: it should deal with one connection,
|
/* The daemon forks before calling this: it should deal with one connection,
|
||||||
blocking as neccessary, and then return. Note, need to be a bit careful
|
blocking as neccessary, and then return. Note, need to be a bit careful
|
||||||
about resources for debug mode, when the fork is suppressed: that's
|
about resources for debug mode, when the fork is suppressed: that's
|
||||||
done by the caller. */
|
done by the caller. */
|
||||||
unsigned char *tcp_request(int confd, time_t now,
|
unsigned char *tcp_request(int confd, time_t now,
|
||||||
union mysockaddr *local_addr, struct in_addr netmask)
|
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
int norebind = 0;
|
int norebind = 0;
|
||||||
@@ -870,7 +885,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
{
|
{
|
||||||
char types[20];
|
char types[20];
|
||||||
|
|
||||||
querystr(types, qtype);
|
querystr(auth_dns ? "auth" : "query", types, qtype);
|
||||||
|
|
||||||
if (peer_addr.sa.sa_family == AF_INET)
|
if (peer_addr.sa.sa_family == AF_INET)
|
||||||
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
|
||||||
@@ -887,8 +902,12 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
else
|
else
|
||||||
dst_addr_4.s_addr = 0;
|
dst_addr_4.s_addr = 0;
|
||||||
|
|
||||||
|
if (auth_dns)
|
||||||
|
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now);
|
||||||
|
else
|
||||||
|
{
|
||||||
/* m > 0 if answered from cache */
|
/* m > 0 if answered from cache */
|
||||||
m = answer_request(header, ((char *) header) + 65536, (unsigned int)size,
|
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
||||||
dst_addr_4, netmask, now);
|
dst_addr_4, netmask, now);
|
||||||
|
|
||||||
/* Do this by steam now we're not in the select() loop */
|
/* Do this by steam now we're not in the select() loop */
|
||||||
@@ -1017,6 +1036,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
if (m == 0)
|
if (m == 0)
|
||||||
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
|
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
check_log_writer(NULL);
|
check_log_writer(NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ int indextoname(int fd, int index, char *name)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int iface_check(int family, struct all_addr *addr, char *name)
|
int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
||||||
{
|
{
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
@@ -115,6 +115,17 @@ int iface_check(int family, struct all_addr *addr, char *name)
|
|||||||
/* Note: have to check all and not bail out early, so that we set the
|
/* Note: have to check all and not bail out early, so that we set the
|
||||||
"used" flags. */
|
"used" flags. */
|
||||||
|
|
||||||
|
if (auth)
|
||||||
|
{
|
||||||
|
if (daemon->authinterface && strcmp(daemon->authinterface, name) == 0)
|
||||||
|
{
|
||||||
|
*auth = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*auth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (daemon->if_names || daemon->if_addrs)
|
if (daemon->if_names || daemon->if_addrs)
|
||||||
{
|
{
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -153,6 +164,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int tftp_ok = !!option_bool(OPT_TFTP);
|
int tftp_ok = !!option_bool(OPT_TFTP);
|
||||||
int dhcp_ok = 1;
|
int dhcp_ok = 1;
|
||||||
|
int auth_dns = 0;
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
#endif
|
#endif
|
||||||
@@ -210,10 +222,23 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET &&
|
if (addr->sa.sa_family == AF_INET &&
|
||||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name))
|
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, &auth_dns))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (addr->sa.sa_family == AF_INET6 &&
|
||||||
|
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &auth_dns))
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
|
/* No DHCP where we're doing auth DNS. */
|
||||||
|
if (auth_dns)
|
||||||
|
{
|
||||||
|
tftp_ok = 0;
|
||||||
|
dhcp_ok = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
{
|
{
|
||||||
@@ -222,13 +247,6 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr->sa.sa_family == AF_INET6 &&
|
|
||||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* add to list */
|
/* add to list */
|
||||||
if ((iface = whine_malloc(sizeof(struct irec))))
|
if ((iface = whine_malloc(sizeof(struct irec))))
|
||||||
{
|
{
|
||||||
@@ -236,6 +254,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
iface->netmask = netmask;
|
iface->netmask = netmask;
|
||||||
iface->tftp_ok = tftp_ok;
|
iface->tftp_ok = tftp_ok;
|
||||||
iface->dhcp_ok = dhcp_ok;
|
iface->dhcp_ok = dhcp_ok;
|
||||||
|
iface->dns_auth = auth_dns;
|
||||||
iface->mtu = mtu;
|
iface->mtu = mtu;
|
||||||
iface->dad = dad;
|
iface->dad = dad;
|
||||||
iface->done = 0;
|
iface->done = 0;
|
||||||
|
|||||||
120
src/option.c
120
src/option.c
@@ -121,6 +121,10 @@ struct myoption {
|
|||||||
#define LOPT_RR 310
|
#define LOPT_RR 310
|
||||||
#define LOPT_CLVERBIND 311
|
#define LOPT_CLVERBIND 311
|
||||||
#define LOPT_MAXCTTL 312
|
#define LOPT_MAXCTTL 312
|
||||||
|
#define LOPT_AUTHZONE 313
|
||||||
|
#define LOPT_AUTHSERV 314
|
||||||
|
#define LOPT_AUTHTTL 315
|
||||||
|
#define LOPT_AUTHSOA 316
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
static const struct option opts[] =
|
static const struct option opts[] =
|
||||||
@@ -247,6 +251,10 @@ static const struct myoption opts[] =
|
|||||||
{ "dhcp-duid", 1, 0, LOPT_DUID },
|
{ "dhcp-duid", 1, 0, LOPT_DUID },
|
||||||
{ "host-record", 1, 0, LOPT_HOST_REC },
|
{ "host-record", 1, 0, LOPT_HOST_REC },
|
||||||
{ "bind-dynamic", 0, 0, LOPT_CLVERBIND },
|
{ "bind-dynamic", 0, 0, LOPT_CLVERBIND },
|
||||||
|
{ "auth-zone", 1, 0, LOPT_AUTHZONE },
|
||||||
|
{ "auth-server", 1, 0, LOPT_AUTHSERV },
|
||||||
|
{ "auth-ttl", 1, 0, LOPT_AUTHTTL },
|
||||||
|
{ "auth-soa", 1, 0, LOPT_AUTHSOA },
|
||||||
{ NULL, 0, 0, 0 }
|
{ NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -379,6 +387,10 @@ static struct {
|
|||||||
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
|
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
|
||||||
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
|
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
|
||||||
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
|
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
|
||||||
|
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
|
||||||
|
{ LOPT_AUTHZONE, ARG_DUP, "<domain>,<subnet>[,<subnet>]", gettext_noop("Domain to export to global DNS"), NULL },
|
||||||
|
{ LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
|
||||||
|
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
|
||||||
{ 0, 0, NULL, NULL, NULL }
|
{ 0, 0, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1521,6 +1533,99 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LOPT_AUTHSERV: /* --auth-server */
|
||||||
|
if (!(comma = split(arg)))
|
||||||
|
ret_err(gen_err);
|
||||||
|
|
||||||
|
daemon->authserver = opt_string_alloc(arg);
|
||||||
|
daemon->authinterface = opt_string_alloc(comma);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOPT_AUTHZONE: /* --auth-zone */
|
||||||
|
{
|
||||||
|
struct auth_zone *new;
|
||||||
|
|
||||||
|
comma = split(arg);
|
||||||
|
if (!comma)
|
||||||
|
ret_err(gen_err);
|
||||||
|
|
||||||
|
new = safe_malloc(sizeof(struct auth_zone));
|
||||||
|
new->domain = opt_string_alloc(arg);
|
||||||
|
new->subnet = NULL;
|
||||||
|
new->next = daemon->auth_zones;
|
||||||
|
daemon->auth_zones = new;
|
||||||
|
|
||||||
|
while ((arg = comma))
|
||||||
|
{
|
||||||
|
int prefixlen = 0;
|
||||||
|
char *prefix;
|
||||||
|
struct subnet *subnet = safe_malloc(sizeof(struct subnet));
|
||||||
|
|
||||||
|
subnet->next = new->subnet;
|
||||||
|
new->subnet = subnet;
|
||||||
|
|
||||||
|
comma = split(arg);
|
||||||
|
prefix = split_chr(arg, '/');
|
||||||
|
|
||||||
|
if (prefix && !atoi_check(prefix, &prefixlen))
|
||||||
|
ret_err(gen_err);
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, arg, &subnet->addr4))
|
||||||
|
{
|
||||||
|
if ((prefixlen & 0x07) != 0 || prefixlen > 24)
|
||||||
|
ret_err(_("bad prefix"));
|
||||||
|
subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
|
||||||
|
subnet->is6 = 0;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (inet_pton(AF_INET6, arg, &subnet->addr6))
|
||||||
|
{
|
||||||
|
subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
|
||||||
|
subnet->is6 = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
ret_err(gen_err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LOPT_AUTHSOA: /* --auth-soa */
|
||||||
|
comma = split(arg);
|
||||||
|
atoi_check(arg, (int *)&daemon->soa_sn);
|
||||||
|
if (comma)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
arg = comma;
|
||||||
|
comma = split(arg);
|
||||||
|
daemon->hostmaster = opt_string_alloc(arg);
|
||||||
|
for (cp = daemon->hostmaster; *cp; cp++)
|
||||||
|
if (*cp == '@')
|
||||||
|
*cp = '.';
|
||||||
|
|
||||||
|
if (comma)
|
||||||
|
{
|
||||||
|
arg = comma;
|
||||||
|
comma = split(arg);
|
||||||
|
atoi_check(arg, (int *)&daemon->soa_refresh);
|
||||||
|
if (comma)
|
||||||
|
{
|
||||||
|
arg = comma;
|
||||||
|
comma = split(arg);
|
||||||
|
atoi_check(arg, (int *)&daemon->soa_retry);
|
||||||
|
if (comma)
|
||||||
|
{
|
||||||
|
arg = comma;
|
||||||
|
comma = split(arg);
|
||||||
|
atoi_check(arg, (int *)&daemon->soa_expiry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case 's': /* --domain */
|
case 's': /* --domain */
|
||||||
if (strcmp (arg, "#") == 0)
|
if (strcmp (arg, "#") == 0)
|
||||||
set_option_bool(OPT_RESOLV_DOMAIN);
|
set_option_bool(OPT_RESOLV_DOMAIN);
|
||||||
@@ -1933,6 +2038,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case LOPT_NEGTTL: /* --neg-ttl */
|
case LOPT_NEGTTL: /* --neg-ttl */
|
||||||
case LOPT_MAXTTL: /* --max-ttl */
|
case LOPT_MAXTTL: /* --max-ttl */
|
||||||
case LOPT_MAXCTTL: /* --max-cache-ttl */
|
case LOPT_MAXCTTL: /* --max-cache-ttl */
|
||||||
|
case LOPT_AUTHTTL: /* --auth-ttl */
|
||||||
{
|
{
|
||||||
int ttl;
|
int ttl;
|
||||||
if (!atoi_check(arg, &ttl))
|
if (!atoi_check(arg, &ttl))
|
||||||
@@ -1943,6 +2049,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
daemon->max_ttl = (unsigned long)ttl;
|
daemon->max_ttl = (unsigned long)ttl;
|
||||||
else if (option == LOPT_MAXCTTL)
|
else if (option == LOPT_MAXCTTL)
|
||||||
daemon->max_cache_ttl = (unsigned long)ttl;
|
daemon->max_cache_ttl = (unsigned long)ttl;
|
||||||
|
else if (option == LOPT_AUTHTTL)
|
||||||
|
daemon->auth_ttl = (unsigned long)ttl;
|
||||||
else
|
else
|
||||||
daemon->local_ttl = (unsigned long)ttl;
|
daemon->local_ttl = (unsigned long)ttl;
|
||||||
break;
|
break;
|
||||||
@@ -3613,6 +3721,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
daemon->tftp_max = TFTP_MAX_CONNECTIONS;
|
daemon->tftp_max = TFTP_MAX_CONNECTIONS;
|
||||||
daemon->edns_pktsz = EDNS_PKTSZ;
|
daemon->edns_pktsz = EDNS_PKTSZ;
|
||||||
daemon->log_fac = -1;
|
daemon->log_fac = -1;
|
||||||
|
daemon->auth_ttl = AUTH_TTL;
|
||||||
|
daemon->soa_refresh = SOA_REFRESH;
|
||||||
|
daemon->soa_retry = SOA_RETRY;
|
||||||
|
daemon->soa_expiry = SOA_EXPIRY;
|
||||||
add_txt("version.bind", "dnsmasq-" VERSION );
|
add_txt("version.bind", "dnsmasq-" VERSION );
|
||||||
add_txt("authors.bind", "Simon Kelley");
|
add_txt("authors.bind", "Simon Kelley");
|
||||||
add_txt("copyright.bind", COPYRIGHT);
|
add_txt("copyright.bind", COPYRIGHT);
|
||||||
@@ -3721,6 +3833,14 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
#endif /* IPv6 */
|
#endif /* IPv6 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create default, if not specified */
|
||||||
|
if (daemon->authserver && !daemon->hostmaster)
|
||||||
|
{
|
||||||
|
strcpy(buff, "hostmaster.");
|
||||||
|
strcat(buff, daemon->authserver);
|
||||||
|
daemon->hostmaster = opt_string_alloc(buff);
|
||||||
|
}
|
||||||
|
|
||||||
/* only one of these need be specified: the other defaults to the host-name */
|
/* only one of these need be specified: the other defaults to the host-name */
|
||||||
if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
|
if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ void icmp6_packet(void)
|
|||||||
if (!indextoname(daemon->icmp6fd, if_index, interface))
|
if (!indextoname(daemon->icmp6fd, if_index, interface))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!iface_check(AF_LOCAL, NULL, interface))
|
if (!iface_check(AF_LOCAL, NULL, interface, NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
|
|||||||
@@ -16,10 +16,6 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
static int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
|
||||||
unsigned int nameoffset, unsigned char **pp,
|
|
||||||
unsigned long ttl, unsigned int *offset, unsigned short type,
|
|
||||||
unsigned short class, char *format, ...);
|
|
||||||
|
|
||||||
#define CHECK_LEN(header, pp, plen, len) \
|
#define CHECK_LEN(header, pp, plen, len) \
|
||||||
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
|
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
|
||||||
@@ -27,7 +23,7 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
|
|||||||
#define ADD_RDLEN(header, pp, plen, len) \
|
#define ADD_RDLEN(header, pp, plen, len) \
|
||||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
||||||
|
|
||||||
static int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
char *name, int isExtract, int extrabytes)
|
char *name, int isExtract, int extrabytes)
|
||||||
{
|
{
|
||||||
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||||
@@ -173,7 +169,7 @@ static int extract_name(struct dns_header *header, size_t plen, unsigned char **
|
|||||||
|
|
||||||
/* Max size of input string (for IPv6) is 75 chars.) */
|
/* Max size of input string (for IPv6) is 75 chars.) */
|
||||||
#define MAXARPANAME 75
|
#define MAXARPANAME 75
|
||||||
static int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
char name[MAXARPANAME+1], *cp1;
|
char name[MAXARPANAME+1], *cp1;
|
||||||
@@ -333,7 +329,7 @@ static unsigned char *skip_name(unsigned char *ansp, struct dns_header *header,
|
|||||||
return ansp;
|
return ansp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *skip_questions(struct dns_header *header, size_t plen)
|
unsigned char *skip_questions(struct dns_header *header, size_t plen)
|
||||||
{
|
{
|
||||||
int q;
|
int q;
|
||||||
unsigned char *ansp = (unsigned char *)(header+1);
|
unsigned char *ansp = (unsigned char *)(header+1);
|
||||||
@@ -1189,7 +1185,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp,
|
||||||
unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...)
|
unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -1202,7 +1198,18 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
|
|||||||
if (truncp && *truncp)
|
if (truncp && *truncp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
va_start(ap, format); /* make ap point to 1st unamed argument */
|
||||||
|
|
||||||
|
if (nameoffset != 0)
|
||||||
|
{
|
||||||
PUTSHORT(nameoffset | 0xc000, p);
|
PUTSHORT(nameoffset | 0xc000, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = do_rfc1035_name(p, va_arg(ap, char *));
|
||||||
|
*p++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
PUTSHORT(type, p);
|
PUTSHORT(type, p);
|
||||||
PUTSHORT(class, p);
|
PUTSHORT(class, p);
|
||||||
PUTLONG(ttl, p); /* TTL */
|
PUTLONG(ttl, p); /* TTL */
|
||||||
@@ -1210,8 +1217,6 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
|
|||||||
sav = p; /* Save pointer to RDLength field */
|
sav = p; /* Save pointer to RDLength field */
|
||||||
PUTSHORT(0, p); /* Placeholder RDLength */
|
PUTSHORT(0, p); /* Placeholder RDLength */
|
||||||
|
|
||||||
va_start(ap, format); /* make ap point to 1st unamed argument */
|
|
||||||
|
|
||||||
for (; *format; format++)
|
for (; *format; format++)
|
||||||
switch (*format)
|
switch (*format)
|
||||||
{
|
{
|
||||||
@@ -1857,7 +1862,3 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
return ansp - (unsigned char *)header;
|
return ansp - (unsigned char *)header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -193,12 +193,12 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (listen->family == AF_INET6)
|
if (listen->family == AF_INET6)
|
||||||
{
|
{
|
||||||
if (!iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name))
|
if (!iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name, NULL))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (!iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name))
|
if (!iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name, NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
|
|||||||
Reference in New Issue
Block a user