HOST_NOT_FOUND.
Any DNS record line in a zone file can be prefixed with "DELAY=" and
-a number of milliseconds (followed by whitespace).
+a number of milliseconds (followed by one space).
-Any DNS record line in a zone file can be prefixed with "DNSSEC" and
-at least one space; if all the records found by a lookup are marked
-as such then the response will have the "AD" bit set. */
+Any DNS record line in a zone file can be prefixed with "DNSSEC ";
+if all the records found by a lookup are marked
+as such then the response will have the "AD" bit set.
+
+Any DNS record line in a zone file can be prefixed with "AA "
+if all the records found by a lookup are marked
+as such then the response will have the "AA" bit set.
+
+*/
#include <ctype.h>
#include <stdarg.h>
qtypelen the length of qtype
pkptr points to the output buffer pointer; this is updated
countptr points to the record count; this is updated
+ dnssec points to the AD flag indicator; this updated
+ aa points to the AA flag indicator; this updated
Returns: 0 on success, else HOST_NOT_FOUND or NO_DATA or NO_RECOVERY or
PASS_ON - the latter if a "PASS ON NOT FOUND" line is seen
static int
find_records(FILE *f, uschar *zone, uschar *domain, uschar *qtype,
- int qtypelen, uschar **pkptr, int *countptr, BOOL * dnssec)
+ int qtypelen, uschar **pkptr, int *countptr, BOOL * dnssec, BOOL * aa)
{
int yield = HOST_NOT_FOUND;
int domainlen = Ustrlen(domain);
(void)fseek(f, 0, SEEK_SET); /* Start again at the beginning */
*dnssec = TRUE; /* cancelled by first nonsecure rec found */
+*aa = TRUE; /* cancelled by first non-authoritive record */
/* Scan for RRs */
int tvalue = typeptr->value;
int qtlen = qtypelen;
BOOL rr_sec = FALSE;
+ BOOL rr_aa = FALSE;
int delay = 0;
p = buffer;
p = buffer;
for (;;)
- {
- if (Ustrncmp(p, US"DNSSEC ", 7) == 0) /* tagged as secure */
- {
- rr_sec = TRUE;
- p += 7;
- }
- else if (Ustrncmp(p, US"DELAY=", 6) == 0) /* delay beforee response */
- {
- for (p += 6; *p >= '0' && *p <= '9'; p++)
- delay = delay*10 + *p - '0';
- while (isspace(*p)) p++;
- }
- else
- break;
- }
+ {
+ if (Ustrncmp(p, US"DNSSEC ", 7) == 0) /* tagged as secure */
+ {
+ rr_sec = TRUE;
+ p += 7;
+ }
+ else if (Ustrncmp(p, US"AA ", 3) == 0) /* tagged as authoritive */
+ {
+ rr_aa = TRUE;
+ p += 3;
+ }
+ else if (Ustrncmp(p, US"DELAY=", 6) == 0) /* delay before response */
+ {
+ for (p += 6; *p >= '0' && *p <= '9'; p++) delay = delay*10 + *p - '0';
+ if (isspace(*p)) p++;
+ }
+ else
+ break;
+ }
- if (!isspace(*p))
+ if (!isspace(*p)) /* new domain name */
{
uschar *pp = rrdomain;
uschar *PP = RRdomain;
pp[-1] = 0;
PP[-1] = 0;
}
- }
+ } /* else use previous line's domain name */
/* Compare domain names; first check for a wildcard */
if (!rr_sec)
*dnssec = FALSE; /* cancel AD return */
+ if (!rr_aa)
+ *aa = FALSE; /* cancel AA return */
+
yield = 0;
*countptr = *countptr + 1;
{
}
+
+/*************************************************
+* Special-purpose domains *
+*************************************************/
+
+static int
+special_manyhome(uschar * packet, uschar * domain)
+{
+uschar *pk = packet + 12;
+uschar *rdlptr;
+int i, j;
+
+memset(packet, 0, 12);
+
+for (i = 104; i <= 111; i++) for (j = 0; j <= 255; j++)
+ {
+ pk = packname(domain, pk);
+ *pk++ = (ns_t_a >> 8) & 255;
+ *pk++ = (ns_t_a) & 255;
+ *pk++ = 0;
+ *pk++ = 1; /* class = IN */
+ pk += 4; /* TTL field; don't care */
+ rdlptr = pk; /* remember rdlength field */
+ pk += 2;
+
+ *pk++ = 10; *pk++ = 250; *pk++ = i; *pk++ = j;
+
+ rdlptr[0] = ((pk - rdlptr - 2) >> 8) & 255;
+ rdlptr[1] = (pk - rdlptr - 2) & 255;
+ }
+
+packet[6] = (2048 >> 8) & 255;
+packet[7] = 2048 & 255;
+packet[10] = 0;
+packet[11] = 0;
+
+(void)fwrite(packet, 1, pk - packet, stdout);
+return 0;
+}
+
+static int
+special_again(uschar * packet, uschar * domain)
+{
+int delay = atoi(CCS domain); /* digits at the start of the name */
+if (delay > 0) sleep(delay);
+return TRY_AGAIN;
+}
+
+
/*************************************************
* Entry point and main program *
*************************************************/
uschar domain[256];
uschar buffer[256];
uschar qtype[12];
-uschar packet[512];
+uschar packet[2048 * 32 + 32];
uschar *pk = packet;
BOOL dnssec;
+BOOL aa;
signal(SIGALRM, alarmfn);
qtypelen = Ustrlen(qtype);
for (p = qtype; *p != 0; p++) *p = toupper(*p);
-/* Find the domain, lower case it, check that it is in a zone that we handle,
+/* Find the domain, lower case it, deal with any specials,
+check that it is in a zone that we handle,
and set up the zone file name. The zone names in the table all start with a
dot. */
domain[domlen] = 0;
for (i = 0; i < domlen; i++) domain[i] = tolower(domain[i]);
+if (Ustrcmp(domain, "manyhome.test.ex") == 0 && Ustrcmp(qtype, "A") == 0)
+ return special_manyhome(packet, domain);
+else if (domlen >= 14 && Ustrcmp(domain + domlen - 14, "test.again.dns") == 0)
+ return special_again(packet, domain);
+else if (domlen >= 13 && Ustrcmp(domain + domlen - 13, "test.fail.dns") == 0)
+ return NO_RECOVERY;
+
+
if (Ustrchr(domain, '.') == NULL && qualify != NULL &&
Ustrcmp(domain, "dontqualify") != 0)
{
/* Find the records we want, and add them to the result. */
count = 0;
-yield = find_records(f, zone, domain, qtype, qtypelen, &pk, &count, &dnssec);
+yield = find_records(f, zone, domain, qtype, qtypelen, &pk, &count, &dnssec, &aa);
if (yield == NO_RECOVERY) goto END_OFF;
packet[6] = (count >> 8) & 255;
if (dnssec)
((HEADER *)packet)->ad = 1;
+if (aa)
+ ((HEADER *)packet)->aa = 1;
+
/* Close the zone file, write the result, and return. */
END_OFF:
return yield;
}
-/* vi: aw ai sw=2
+/* vi: aw ai sw=2 sts=2 ts=8 et
*/
/* End of fakens.c */