X-Git-Url: https://git.exim.org/users/heiko/exim.git/blobdiff_plain/4d4c2a9bc67a4cb368703cc26fbc520e7428a428..846430d945e9056842ad7f12f85d43435d78baf0:/test/src/fakens.c diff --git a/test/src/fakens.c b/test/src/fakens.c index ec7588cc8..1228c70f9 100644 --- a/test/src/fakens.c +++ b/test/src/fakens.c @@ -50,6 +50,9 @@ line in the zone file contains exactly this: and the domain is not found. It converts the the result to PASS_ON instead of HOST_NOT_FOUND. +Any DNS record line in a zone file can be prefixed with "DELAY=" and +a number of milliseconds (followed by whitespace). + 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. */ @@ -57,11 +60,13 @@ as such then the response will have the "AD" bit set. */ #include #include #include +#include #include #include #include #include #include +#include #include #define FALSE 0 @@ -99,21 +104,25 @@ not defined, assume we are in this state. A really old system might not even know about AAAA and SRV at all. */ #ifndef ns_t_a -#define ns_t_a T_A -#define ns_t_ns T_NS -#define ns_t_cname T_CNAME -#define ns_t_soa T_SOA -#define ns_t_ptr T_PTR -#define ns_t_mx T_MX -#define ns_t_txt T_TXT -#define ns_t_aaaa T_AAAA -#define ns_t_srv T_SRV -#ifndef T_AAAA -#define T_AAAA 28 -#endif -#ifndef T_SRV -#define T_SRV 33 -#endif +# define ns_t_a T_A +# define ns_t_ns T_NS +# define ns_t_cname T_CNAME +# define ns_t_soa T_SOA +# define ns_t_ptr T_PTR +# define ns_t_mx T_MX +# define ns_t_txt T_TXT +# define ns_t_aaaa T_AAAA +# define ns_t_srv T_SRV +# define ns_t_tlsa T_TLSA +# ifndef T_AAAA +# define T_AAAA 28 +# endif +# ifndef T_SRV +# define T_SRV 33 +# endif +# ifndef T_TLSA +# define T_TLSA 52 +# endif #endif static tlist type_list[] = { @@ -126,6 +135,7 @@ static tlist type_list[] = { { US"TXT", ns_t_txt }, { US"AAAA", ns_t_aaaa }, { US"SRV", ns_t_srv }, + { US"TLSA", ns_t_tlsa }, { NULL, 0 } }; @@ -151,7 +161,7 @@ uschar *yield; char buffer[256]; va_list ap; va_start(ap, format); -vsprintf(buffer, format, ap); +vsprintf(buffer, CS format, ap); va_end(ap); yield = (uschar *)malloc(Ustrlen(buffer) + 1); Ustrcpy(yield, buffer); @@ -189,6 +199,65 @@ while (*name != 0) return pk; } +uschar * +bytefield(uschar ** pp, uschar * pk) +{ +unsigned value = 0; +uschar * p = *pp; + +while (isdigit(*p)) value = value*10 + *p++ - '0'; +while (isspace(*p)) p++; +*pp = p; +*pk++ = value & 255; +return pk; +} + +uschar * +shortfield(uschar ** pp, uschar * pk) +{ +unsigned value = 0; +uschar * p = *pp; + +while (isdigit(*p)) value = value*10 + *p++ - '0'; +while (isspace(*p)) p++; +*pp = p; +*pk++ = (value >> 8) & 255; +*pk++ = value & 255; +return pk; +} + + + +/*************************************************/ + +static void +milliwait(struct itimerval *itval) +{ +sigset_t sigmask; +sigset_t old_sigmask; + +if (itval->it_value.tv_usec < 100 && itval->it_value.tv_sec == 0) + return; +(void)sigemptyset(&sigmask); /* Empty mask */ +(void)sigaddset(&sigmask, SIGALRM); /* Add SIGALRM */ +(void)sigprocmask(SIG_BLOCK, &sigmask, &old_sigmask); /* Block SIGALRM */ +(void)setitimer(ITIMER_REAL, itval, NULL); /* Start timer */ +(void)sigfillset(&sigmask); /* All signals */ +(void)sigdelset(&sigmask, SIGALRM); /* Remove SIGALRM */ +(void)sigsuspend(&sigmask); /* Until SIGALRM */ +(void)sigprocmask(SIG_SETMASK, &old_sigmask, NULL); /* Restore mask */ +} + +static void +millisleep(int msec) +{ +struct itimerval itval; +itval.it_interval.tv_sec = 0; +itval.it_interval.tv_usec = 0; +itval.it_value.tv_sec = msec/1000; +itval.it_value.tv_usec = (msec % 1000) * 1000; +milliwait(&itval); +} /************************************************* @@ -237,7 +306,7 @@ if (typeptr->name == NULL) rrdomain[0] = 0; /* No previous domain */ (void)fseek(f, 0, SEEK_SET); /* Start again at the beginning */ -*dnssec = TRUE; /* cancelled by first nonsecure rec found */ +*dnssec = TRUE; /* cancelled by first nonsecure rec found */ /* Scan for RRs */ @@ -250,6 +319,7 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) int tvalue = typeptr->value; int qtlen = qtypelen; BOOL rr_sec = FALSE; + int delay = 0; p = buffer; while (isspace(*p)) p++; @@ -266,11 +336,22 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) *ep = 0; p = buffer; - if (Ustrncmp(p, US"DNSSEC ", 7) == 0) /* tagged as secure */ - { - rr_sec = TRUE; - p += 7; - } + 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 (!isspace(*p)) { @@ -324,6 +405,9 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) /* Found a relevant record */ + if (delay) + millisleep(delay); + if (!rr_sec) *dnssec = FALSE; /* cancel AD return */ @@ -387,12 +471,8 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) break; case ns_t_mx: - value = 0; - while (isdigit(*p)) value = value*10 + *p++ - '0'; - while (isspace(*p)) p++; - *pk++ = (value >> 8) & 255; - *pk++ = value & 255; - if (ep[-1] != '.') sprintf(ep, "%s.", zone); + pk = shortfield(&p, pk); + if (ep[-1] != '.') sprintf(CS ep, "%s.", zone); pk = packname(p, pk); plen = Ustrlen(p); break; @@ -404,6 +484,23 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) *pp = pk - pp - 1; break; + case ns_t_tlsa: + pk = bytefield(&p, pk); /* usage */ + pk = bytefield(&p, pk); /* selector */ + pk = bytefield(&p, pk); /* match type */ + while (isxdigit(*p)) + { + value = toupper(*p) - (isdigit(*p) ? '0' : '7') << 4; + if (isxdigit(*++p)) + { + value |= toupper(*p) - (isdigit(*p) ? '0' : '7'); + p++; + } + *pk++ = value & 255; + } + + break; + case ns_t_srv: for (i = 0; i < 3; i++) { @@ -419,7 +516,7 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) case ns_t_cname: case ns_t_ns: case ns_t_ptr: - if (ep[-1] != '.') sprintf(ep, "%s.", zone); + if (ep[-1] != '.') sprintf(CS ep, "%s.", zone); pk = packname(p, pk); plen = Ustrlen(p); break; @@ -436,6 +533,10 @@ return (yield == HOST_NOT_FOUND && pass_on_not_found)? PASS_ON : yield; } +static void +alarmfn(int sig) +{ +} /************************************************* * Entry point and main program * @@ -462,6 +563,8 @@ uschar packet[512]; uschar *pk = packet; BOOL dnssec; +signal(SIGALRM, alarmfn); + if (argc != 4) { fprintf(stderr, "fakens: expected 3 arguments, received %d\n", argc-1); @@ -470,7 +573,7 @@ if (argc != 4) /* Find the zones */ -(void)sprintf(buffer, "%s/../dnszones", argv[1]); +(void)sprintf(CS buffer, "%s/../dnszones", argv[1]); d = opendir(CCS buffer); if (d == NULL) @@ -482,20 +585,20 @@ if (d == NULL) while ((de = readdir(d)) != NULL) { - uschar *name = de->d_name; + uschar *name = US de->d_name; if (Ustrncmp(name, "qualify.", 8) == 0) { - qualify = fcopystring("%s", name + 7); + qualify = fcopystring(US "%s", name + 7); continue; } if (Ustrncmp(name, "db.", 3) != 0) continue; if (Ustrncmp(name + 3, "ip4.", 4) == 0) - zones[zonecount].zone = fcopystring("%s.in-addr.arpa", name + 6); + zones[zonecount].zone = fcopystring(US "%s.in-addr.arpa", name + 6); else if (Ustrncmp(name + 3, "ip6.", 4) == 0) - zones[zonecount].zone = fcopystring("%s.ip6.arpa", name + 6); + zones[zonecount].zone = fcopystring(US "%s.ip6.arpa", name + 6); else - zones[zonecount].zone = fcopystring("%s", name + 2); - zones[zonecount++].zonefile = fcopystring("%s", name); + zones[zonecount].zone = fcopystring(US "%s", name + 2); + zones[zonecount++].zonefile = fcopystring(US "%s", name); } (void)closedir(d); @@ -541,7 +644,7 @@ if (zonefile == NULL) return PASS_ON; } -(void)sprintf(buffer, "%s/../dnszones/%s", argv[1], zonefile); +(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 @@ -552,7 +655,7 @@ pk += 12; /* Open the zone file. */ -f = fopen(buffer, "r"); +f = fopen(CS buffer, "r"); if (f == NULL) { fprintf(stderr, "fakens: failed to open %s: %s\n", buffer, strerror(errno));