X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/fd8184e3bed43669b09f463ae610eff772e9ab65..9300a61f79604940f3b0c6fbc4b72f1a3c882caf:/test/src/fakens.c diff --git a/test/src/fakens.c b/test/src/fakens.c index 00f1f7d46..6d8a99df5 100644 --- a/test/src/fakens.c +++ b/test/src/fakens.c @@ -25,7 +25,7 @@ The arguments to the program are: the DNS record type that is being sought The output from the program is written to stdout. It is supposed to be in -exactly the same format as a traditional namserver response (see RFC 1035) so +exactly the same format as a traditional nameserver response (see RFC 1035) so that Exim can process it as normal. At present, no compression is used. Error messages are written to stderr. @@ -53,11 +53,15 @@ HOST_NOT_FOUND. Any DNS record line in a zone file can be prefixed with "DELAY=" and a number of milliseconds (followed by one space). -Any DNS record line in a zone file can be prefixed with "DNSSEC "; +Any DNS record line 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 " +Any DNS record line can be prefixed with "NXDOMAIN "; +The record will be ignored (but the prefix set still applied); +This lets us return a DNSSEC NXDOMAIN (=> HOST_NOT_FOUND). + +Any DNS record line 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. @@ -80,6 +84,9 @@ a number of seconds (followed by one space). #include #include #include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif #define FALSE 0 #define TRUE 1 @@ -99,6 +106,7 @@ typedef unsigned char uschar; #define Ustrlen(s) (int)strlen(CCS(s)) #define Ustrncmp(s,t,n) strncmp(CCS(s),CCS(t),n) #define Ustrncpy(s,t,n) strncpy(CS(s),CCS(t),n) +#define Ustrtok(s,t) (uschar*)strtok(CS(s),CCS(t)) typedef struct zoneitem { uschar *zone; @@ -338,9 +346,6 @@ if (typeptr->name == NULL) rrdomain[0] = 0; /* No previous domain */ (void)fseek(f, 0, SEEK_SET); /* Start again at the beginning */ -if (dnssec) *dnssec = TRUE; /* cancelled by first nonsecure rec found */ -if (aa) *aa = TRUE; /* cancelled by first non-aa rec found */ - /* Scan for RRs */ while (fgets(CS buffer, sizeof(buffer), f) != NULL) @@ -353,6 +358,7 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) int qtlen = qtypelen; BOOL rr_sec = FALSE; BOOL rr_aa = FALSE; + BOOL rr_ignore = FALSE; int delay = 0; uint ttl = DEFAULT_TTL; @@ -378,7 +384,12 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) rr_sec = TRUE; p += 7; } - else if (Ustrncmp(p, US"AA ", 3) == 0) /* tagged as authoritive */ + if (Ustrncmp(p, US"NXDOMAIN ", 9) == 0) /* ignore record content */ + { + rr_ignore = TRUE; + p += 9; + } + else if (Ustrncmp(p, US"AA ", 3) == 0) /* tagged as authoritative */ { rr_aa = TRUE; p += 3; @@ -434,7 +445,12 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) /* The domain matches */ - if (yield == HOST_NOT_FOUND) yield = NO_DATA; + if (yield == HOST_NOT_FOUND) + { + yield = NO_DATA; + if (dnssec) *dnssec = TRUE; /* cancelled by first nonsecure rec found */ + if (aa) *aa = TRUE; /* cancelled by first non-aa rec found */ + } /* Compare RR types; a CNAME record is always returned */ @@ -458,6 +474,8 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) if (aa && !rr_aa) *aa = FALSE; /* cancel AA return */ + if (rr_ignore) continue; + yield = 0; *countptr = *countptr + 1; @@ -486,13 +504,13 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) switch (tvalue) { case ns_t_soa: - p = strtok(p, " "); - ep = p + strlen(p); + p = Ustrtok(p, " "); + ep = p + Ustrlen(p); if (ep[-1] != '.') sprintf(CS ep, "%s.", zone); pk = packname(p, pk); /* primary ns */ - p = strtok(NULL, " "); + p = Ustrtok(NULL, " "); pk = packname(p , pk); /* responsible mailbox */ - *(p += strlen(p)) = ' '; + *(p += Ustrlen(p)) = ' '; while (isspace(*p)) p++; pk = longfield(&p, pk); /* serial */ pk = longfield(&p, pk); /* refresh */ @@ -502,12 +520,12 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) break; case ns_t_a: - inet_pton(AF_INET, p, pk); /* FIXME: error checking */ + inet_pton(AF_INET, CCS p, pk); /* FIXME: error checking */ pk += 4; break; case ns_t_aaaa: - inet_pton(AF_INET6, p, pk); /* FIXME: error checking */ + inet_pton(AF_INET6, CCS p, pk); /* FIXME: error checking */ pk += 16; break; @@ -745,22 +763,23 @@ if (zonefile == NULL) (void)sprintf(CS buffer, "%s/dnszones/%s", argv[1], zonefile); -/* Initialize the start of the response packet. We don't have to fake up -everything, because we know that Exim will look only at the answer and -additional section parts. */ +/* Initialize the start of the response packet. */ memset(packet, 0, 12); pk += 12; /* Open the zone file. */ -f = fopen(CS buffer, "r"); -if (f == NULL) +if (!(f = fopen(CS buffer, "r"))) { fprintf(stderr, "fakens: failed to open %s: %s\n", buffer, strerror(errno)); return NO_RECOVERY; } +header->qr = 1; /* query */ +header->opcode = QUERY; /* standard query */ +header->tc = 0; /* no trucation */ + /* Find the records we want, and add them to the result. */ count = 0; @@ -769,14 +788,16 @@ if (yield == NO_RECOVERY) goto END_OFF; header->ancount = htons(count); /* If the AA bit should be set (as indicated by the AA prefix in the zone file), -we are expected to return some records in the authortive section. Bind9: If -there is data in the answer section, the authoritive section contains the NS -records, otherwise it contains the SOA record. Currently we mimic this -behaviour for the first case (there is some answer record). +we are expected to return some records in the authoritative section. Bind9: If +there is data in the answer section, the authoritative section contains the NS +records, otherwise it contains the SOA record. Mimic that. */ -if (aa) - find_records(f, zone, zone[0] == '.' ? zone+1 : zone, US"NS", 2, &pk, &count, NULL, NULL); +if (strcmp(qtype, "SOA") != 0 && strcmp(qtype, "NS") != 0) + if (count) + find_records(f, zone, zone[0] == '.' ? zone+1 : zone, US"NS", 2, &pk, &count, NULL, NULL); + else + find_records(f, zone, zone[0] == '.' ? zone+1 : zone, US"SOA", 3, &pk, &count, NULL, NULL); header->nscount = htons(count - ntohs(header->ancount)); /* There is no need to return any additional records because Exim no longer