struct auth_zone *zone = NULL;
struct subnet *subnet = NULL;
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 )
return 0;
{
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;
flag = F_IPV6;
#endif
- if (qtype == T_SOA && !cut)
+ if (!cut)
{
- soa = 1; /* inhibits auth section */
- found = 1;
- log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
- }
-
- if (qtype == T_AXFR && !cut)
- {
- soa = 1; /* inhibits auth section */
- axfr = 1;
- found = 1;
- axfroffset = nameoffset;
- log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
- }
-
- if (qtype == T_NS && !cut)
- {
- ns = 1; /* inhibits auth section */
- found = 1;
- log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
+ nxdomain = 0;
+
+ if (qtype == T_SOA)
+ {
+ soa = 1; /* inhibits auth section */
+ found = 1;
+ log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
+ }
+ else if (qtype == T_AXFR)
+ {
+ soa = 1; /* inhibits auth section */
+ ns = 1; /* ensure we include NS records! */
+ axfr = 1;
+ found = 1;
+ axfroffset = nameoffset;
+ log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
+ }
+ else if (qtype == T_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)
{
*cut = 0; /* remove domain part */
if (auth)
{
char *authname;
-
+ int newoffset, offset = 0;
+
if (!subnet)
authname = zone->domain;
else
}
/* 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", authname, daemon->authserver))
- {
- if (ns)
- anscount++;
- else
- authcount++;
- }
-
- if ((anscount == 0 || soa) &&
+ newoffset = ansp - (unsigned char *)header;
+ if (((anscount == 0 && !ns) || soa) &&
add_resource_record(header, limit, &trunc, 0, &ansp,
daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
authname, daemon->authserver, daemon->hostmaster,
daemon->soa_retry, daemon->soa_expiry,
daemon->auth_ttl))
{
+ offset = newoffset;
if (soa)
anscount++;
else
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)
{
+ 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);
while ((crecp = cache_enumerate(0)))
{
qtype = T_AAAA;
#endif
if (cut)
- {
- *cut = 0;
- if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
- daemon->auth_ttl, NULL, qtype, C_IN,
- (crecp->flags & F_IPV4) ? "4" : "6", name, &crecp->addr))
- 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++;
- }
+ *cut = 0;
+
+ if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
+ daemon->auth_ttl, NULL, qtype, C_IN,
+ (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
+ anscount++;
}
}
}
}
- }
+}
/* done all questions, set up header and return length of result */
/* clear authoritative and truncated flags, set QR flag */
#define LOPT_MAXCTTL 312
#define LOPT_AUTHZONE 313
#define LOPT_AUTHSERV 314
-#define LOPT_AUTHTTL 315
+#define LOPT_AUTHTTL 315
#define LOPT_AUTHSOA 316
+#define LOPT_AUTHSFS 317
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
{ "auth-server", 1, 0, LOPT_AUTHSERV },
{ "auth-ttl", 1, 0, LOPT_AUTHTTL },
{ "auth-soa", 1, 0, LOPT_AUTHSOA },
+ { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
{ NULL, 0, 0, 0 }
};
{ 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 },
+ { LOPT_AUTHSFS, ARG_ONE, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ 0, 0, NULL, NULL, NULL }
};
new->next = daemon->dhcp_hosts_file;
daemon->dhcp_hosts_file = new;
}
- else if (option == LOPT_DHCP_OPTS)
+ else if (option == LOPT_DHCP_OPTS)
{
new->next = daemon->dhcp_opts_file;
daemon->dhcp_opts_file = new;
daemon->authinterface = opt_string_alloc(comma);
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 */
{
struct auth_zone *new;