Commit e1ff419c authored by Simon Kelley's avatar Simon Kelley

Complete AXFR support

parent ee86ce68
...@@ -84,7 +84,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -84,7 +84,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
struct auth_zone *zone = NULL; struct auth_zone *zone = NULL;
struct subnet *subnet = NULL; struct subnet *subnet = NULL;
char *cut; char *cut;
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;
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY ) if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
return 0; return 0;
...@@ -99,13 +105,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -99,13 +105,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{ {
unsigned short flag = 0; unsigned short flag = 0;
int found = 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 */ /* save pointer to name for copying into answers */
nameoffset = p - (unsigned char *)header; nameoffset = p - (unsigned char *)header;
...@@ -345,30 +345,33 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -345,30 +345,33 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
flag = F_IPV6; flag = F_IPV6;
#endif #endif
if (qtype == T_SOA && !cut) if (!cut)
{ {
soa = 1; /* inhibits auth section */ nxdomain = 0;
found = 1;
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>"); if (qtype == T_SOA)
} {
soa = 1; /* inhibits auth section */
if (qtype == T_AXFR && !cut) found = 1;
{ log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
soa = 1; /* inhibits auth section */ }
axfr = 1; else if (qtype == T_AXFR)
found = 1; {
axfroffset = nameoffset; soa = 1; /* inhibits auth section */
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>"); ns = 1; /* ensure we include NS records! */
} axfr = 1;
found = 1;
if (qtype == T_NS && !cut) axfroffset = nameoffset;
{ log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
ns = 1; /* inhibits auth section */ }
found = 1; else if (qtype == T_NS)
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>"); {
ns = 1; /* inhibits auth section */
found = 1;
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
}
} }
if (!option_bool(OPT_DHCP_FQDN) && cut) if (!option_bool(OPT_DHCP_FQDN) && cut)
{ {
*cut = 0; /* remove domain part */ *cut = 0; /* remove domain part */
...@@ -423,7 +426,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -423,7 +426,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (auth) if (auth)
{ {
char *authname; char *authname;
int newoffset, offset = 0;
if (!subnet) if (!subnet)
authname = zone->domain; authname = zone->domain;
else else
...@@ -464,17 +468,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -464,17 +468,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} }
/* handle NS and SOA in auth section or for explicit queries */ /* handle NS and SOA in auth section or for explicit queries */
if ((anscount != 0 || ns) && newoffset = ansp - (unsigned char *)header;
add_resource_record(header, limit, &trunc, 0, &ansp, if (((anscount == 0 && !ns) || soa) &&
daemon->auth_ttl, NULL, T_NS, C_IN, "d", authname, daemon->authserver))
{
if (ns)
anscount++;
else
authcount++;
}
if ((anscount == 0 || soa) &&
add_resource_record(header, limit, &trunc, 0, &ansp, add_resource_record(header, limit, &trunc, 0, &ansp,
daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll", daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
authname, daemon->authserver, daemon->hostmaster, authname, daemon->authserver, daemon->hostmaster,
...@@ -482,14 +477,149 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -482,14 +477,149 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
daemon->soa_retry, daemon->soa_expiry, daemon->soa_retry, daemon->soa_expiry,
daemon->auth_ttl)) daemon->auth_ttl))
{ {
offset = newoffset;
if (soa) if (soa)
anscount++; anscount++;
else else
authcount++; authcount++;
} }
if (anscount != 0 || ns)
{
struct name_list *secondary;
newoffset = ansp - (unsigned char *)header;
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
{
if (offset == 0)
offset = newoffset;
if (ns)
anscount++;
else
authcount++;
}
if (!subnet)
for (secondary = daemon->secondary_forward_server; secondary; secondary = secondary->next)
if (add_resource_record(header, limit, &trunc, offset, &ansp,
daemon->auth_ttl, NULL, T_NS, C_IN, "d", secondary->name))
{
if (ns)
anscount++;
else
authcount++;
}
}
if (axfr) if (axfr)
{ {
for (rec = daemon->mxnames; rec; rec = rec->next)
if (in_zone(zone, rec->name, &cut))
{
if (cut)
*cut = 0;
if (rec->issrv)
{
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
NULL, T_SRV, C_IN, "sssd", cut ? rec->name : NULL,
rec->priority, rec->weight, rec->srvport, rec->target))
anscount++;
}
else
{
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
NULL, T_MX, C_IN, "sd", cut ? rec->name : NULL, rec->weight, rec->target))
anscount++;
}
/* restore config data */
if (cut)
*cut = '.';
}
for (txt = daemon->rr; txt; txt = txt->next)
if (in_zone(zone, txt->name, &cut))
{
if (cut)
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
NULL, txt->class, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
anscount++;
/* restore config data */
if (cut)
*cut = '.';
}
for (txt = daemon->txt; txt; txt = txt->next)
if (txt->class == C_IN && in_zone(zone, txt->name, &cut))
{
if (cut)
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
NULL, T_TXT, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
anscount++;
/* restore config data */
if (cut)
*cut = '.';
}
for (na = daemon->naptr; na; na = na->next)
if (in_zone(zone, na->name, &cut))
{
if (cut)
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
NULL, T_NAPTR, C_IN, "sszzzd", cut ? na->name : NULL,
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
anscount++;
/* restore config data */
if (cut)
*cut = '.';
}
for (intr = daemon->int_names; intr; intr = intr->next)
if (in_zone(zone, intr->name, &cut) && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
{
if (cut)
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addr))
anscount++;
/* restore config data */
if (cut)
*cut = '.';
}
for (a = daemon->cnames; a; a = a->next)
if (in_zone(zone, a->alias, &cut))
{
strcpy(name, a->target);
if (!strchr(name, '.'))
{
strcat(name, ".");
strcat(name, zone->domain);
}
if (cut)
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL,
T_CNAME, C_IN, "d", cut ? a->alias : NULL, name))
anscount++;
}
cache_enumerate(1); cache_enumerate(1);
while ((crecp = cache_enumerate(0))) while ((crecp = cache_enumerate(0)))
{ {
...@@ -525,20 +655,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -525,20 +655,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
qtype = T_AAAA; qtype = T_AAAA;
#endif #endif
if (cut) if (cut)
{ *cut = 0;
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN, daemon->auth_ttl, NULL, qtype, C_IN,
(crecp->flags & F_IPV4) ? "4" : "6", name, &crecp->addr)) (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
anscount++; anscount++;
}
else
{
if (add_resource_record(header, limit, &trunc, axfroffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
(crecp->flags & F_IPV4) ? "4" : "6", &crecp->addr))
anscount++;
}
} }
} }
} }
...@@ -555,7 +677,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n ...@@ -555,7 +677,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} }
} }
/* done all questions, set up header and return length of result */ /* done all questions, set up header and return length of result */
/* clear authoritative and truncated flags, set QR flag */ /* clear authoritative and truncated flags, set QR flag */
......
...@@ -756,6 +756,7 @@ extern struct daemon { ...@@ -756,6 +756,7 @@ extern struct daemon {
char *username, *groupname, *scriptuser; char *username, *groupname, *scriptuser;
char *luascript; char *luascript;
char *authserver, *authinterface, *hostmaster; char *authserver, *authinterface, *hostmaster;
struct name_list *secondary_forward_server;
int group_set, osport; int group_set, osport;
char *domain_suffix; char *domain_suffix;
struct cond_domain *cond_domain; struct cond_domain *cond_domain;
...@@ -901,7 +902,7 @@ size_t resize_packet(struct dns_header *header, size_t plen, ...@@ -901,7 +902,7 @@ size_t resize_packet(struct dns_header *header, size_t plen,
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, int add_resource_record(struct dns_header *header, char *limit, int *truncp,
int nameoffset, unsigned char **pp, unsigned long ttl, int nameoffset, unsigned char **pp, unsigned long ttl,
unsigned int *offset, unsigned short type, unsigned short class, char *format, ...); int *offset, unsigned short type, unsigned short class, char *format, ...);
unsigned char *skip_questions(struct dns_header *header, size_t plen); unsigned char *skip_questions(struct dns_header *header, size_t plen);
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);
......
...@@ -420,6 +420,9 @@ void lease_update_dns(int force) ...@@ -420,6 +420,9 @@ void lease_update_dns(int force)
if (daemon->port != 0 && (dns_dirty || force)) if (daemon->port != 0 && (dns_dirty || force))
{ {
/* force transfer to authoritative secondaries */
daemon->soa_sn++;
cache_unhash_dhcp(); cache_unhash_dhcp();
for (lease = leases; lease; lease = lease->next) for (lease = leases; lease; lease = lease->next)
......
...@@ -123,8 +123,9 @@ struct myoption { ...@@ -123,8 +123,9 @@ struct myoption {
#define LOPT_MAXCTTL 312 #define LOPT_MAXCTTL 312
#define LOPT_AUTHZONE 313 #define LOPT_AUTHZONE 313
#define LOPT_AUTHSERV 314 #define LOPT_AUTHSERV 314
#define LOPT_AUTHTTL 315 #define LOPT_AUTHTTL 315
#define LOPT_AUTHSOA 316 #define LOPT_AUTHSOA 316
#define LOPT_AUTHSFS 317
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
...@@ -255,6 +256,7 @@ static const struct myoption opts[] = ...@@ -255,6 +256,7 @@ static const struct myoption opts[] =
{ "auth-server", 1, 0, LOPT_AUTHSERV }, { "auth-server", 1, 0, LOPT_AUTHSERV },
{ "auth-ttl", 1, 0, LOPT_AUTHTTL }, { "auth-ttl", 1, 0, LOPT_AUTHTTL },
{ "auth-soa", 1, 0, LOPT_AUTHSOA }, { "auth-soa", 1, 0, LOPT_AUTHSOA },
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
...@@ -391,6 +393,7 @@ static struct { ...@@ -391,6 +393,7 @@ static struct {
{ LOPT_AUTHZONE, ARG_DUP, "<domain>,<subnet>[,<subnet>]", gettext_noop("Domain to export 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_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL }, { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
{ LOPT_AUTHSFS, ARG_ONE, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
...@@ -1525,7 +1528,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -1525,7 +1528,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->next = daemon->dhcp_hosts_file; new->next = daemon->dhcp_hosts_file;
daemon->dhcp_hosts_file = new; daemon->dhcp_hosts_file = new;
} }
else if (option == LOPT_DHCP_OPTS) else if (option == LOPT_DHCP_OPTS)
{ {
new->next = daemon->dhcp_opts_file; new->next = daemon->dhcp_opts_file;
daemon->dhcp_opts_file = new; daemon->dhcp_opts_file = new;
...@@ -1541,7 +1544,22 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -1541,7 +1544,22 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->authinterface = opt_string_alloc(comma); daemon->authinterface = opt_string_alloc(comma);
break; break;
case LOPT_AUTHSFS: /* --auth-sec-servers */
{
struct name_list *new;
do {
comma = split(arg);
new = safe_malloc(sizeof(struct name_list));
new->name = opt_string_alloc(arg);
new->next = daemon->secondary_forward_server;
daemon->secondary_forward_server = new;
arg = comma;
} while (arg);
break;
}
case LOPT_AUTHZONE: /* --auth-zone */ case LOPT_AUTHZONE: /* --auth-zone */
{ {
struct auth_zone *new; struct auth_zone *new;
......
...@@ -1186,7 +1186,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, ...@@ -1186,7 +1186,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
} }
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp, int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...) unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
{ {
va_list ap; va_list ap;
unsigned char *sav, *p = *pp; unsigned char *sav, *p = *pp;
...@@ -1206,7 +1206,9 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int ...@@ -1206,7 +1206,9 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
} }
else else
{ {
p = do_rfc1035_name(p, va_arg(ap, char *)); char *name = va_arg(ap, char *);
if (name)
p = do_rfc1035_name(p, name);
if (nameoffset < 0) if (nameoffset < 0)
{ {
PUTSHORT(-nameoffset | 0xc000, p); PUTSHORT(-nameoffset | 0xc000, p);
...@@ -1699,7 +1701,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1699,7 +1701,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
ans = found = 1; ans = found = 1;
if (!dryrun) if (!dryrun)
{ {
unsigned int offset; int offset;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>"); log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
&offset, T_MX, C_IN, "sd", rec->weight, rec->target)) &offset, T_MX, C_IN, "sd", rec->weight, rec->target))
...@@ -1737,7 +1739,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1737,7 +1739,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
found = ans = 1; found = ans = 1;
if (!dryrun) if (!dryrun)
{ {
unsigned int offset; int offset;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>"); log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
&offset, T_SRV, C_IN, "sssd", &offset, T_SRV, C_IN, "sssd",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment