mirror of
https://github.com/curl/curl.git
synced 2026-04-14 22:01:41 +03:00
tests/dnsd: read config from file
Make the <dns> tag in a test case control what is stored there. Also documented. Make test 2102 and 2103 use the new tag. Lets the test case config the A and AAAA contents the server replies with. Initial work for the HTTPS RR exists, but does not yet work. Closes #17543
This commit is contained in:
parent
2cdc02f49f
commit
aed828cc51
8 changed files with 173 additions and 91 deletions
|
|
@ -383,6 +383,14 @@ issue.
|
|||
`writedelay: [secs]` delay this amount between reply packets (each packet
|
||||
being 512 bytes payload)
|
||||
|
||||
### `<dns>`
|
||||
|
||||
Commands for the test DNS server.
|
||||
|
||||
- `A: [dotted ipv4 address]` - set IPv4 address to return
|
||||
- `AAAA: [numerical IPv6 address]` - set IPv6 address to return, with or
|
||||
without `[]`
|
||||
|
||||
## `<client>`
|
||||
|
||||
### `<server>`
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ test2064 test2065 test2066 test2067 test2068 test2069 test2070 test2071 \
|
|||
test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 \
|
||||
test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 \
|
||||
test2088 test2089 \
|
||||
test2100 test2101 test2102 \
|
||||
test2100 test2101 test2102 test2103 \
|
||||
\
|
||||
test2200 test2201 test2202 test2203 test2204 test2205 \
|
||||
\
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ Funny-head: yesyes
|
|||
|
||||
-foo-
|
||||
</data>
|
||||
<dns>
|
||||
A: %HOSTIP
|
||||
AAAA: %HOST6IP
|
||||
</dns>
|
||||
</reply>
|
||||
|
||||
#
|
||||
|
|
|
|||
45
tests/data/test2103
Normal file
45
tests/data/test2103
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
DNS fail
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<dns>
|
||||
A: none
|
||||
AAAA: none
|
||||
</dns>
|
||||
</reply>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
dns
|
||||
</server>
|
||||
<features>
|
||||
override-dns
|
||||
</features>
|
||||
<name>
|
||||
HTTP GET with bad host name
|
||||
</name>
|
||||
<setenv>
|
||||
CURL_DNS_SERVER=127.0.0.1:%DNSPORT
|
||||
</setenv>
|
||||
<command>
|
||||
http://examplehost.example/%TESTNUMBER
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
# curl: (6) Could not resolve host: examplehost.example
|
||||
<errorcode>
|
||||
6
|
||||
</errorcode>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
|
@ -61,6 +61,7 @@ BEGIN {
|
|||
$run_duphandle
|
||||
$run_event_based
|
||||
$SERVERCMD
|
||||
$DNSCMD
|
||||
$SERVERIN
|
||||
$srcdir
|
||||
$TESTDIR
|
||||
|
|
@ -134,6 +135,7 @@ our $SERVERIN="server.input"; # what curl sent the server
|
|||
our $PROXYIN="proxy.input"; # what curl sent the proxy
|
||||
our $MEMDUMP="memdump"; # file that the memory debugging creates
|
||||
our $SERVERCMD="server.cmd"; # copy server instructions here
|
||||
our $DNSCMD="dnsd.cmd"; # write DNS instructions here
|
||||
|
||||
# other config variables
|
||||
our @protocols; # array of lowercase supported protocol servers
|
||||
|
|
|
|||
|
|
@ -750,11 +750,16 @@ sub singletest_prepare {
|
|||
unlink("$LOGDIR/$SERVERIN");
|
||||
unlink("$LOGDIR/$PROXYIN");
|
||||
|
||||
# if this section exists, it might be FTP server instructions:
|
||||
my @ftpservercmd = getpart("reply", "servercmd");
|
||||
push @ftpservercmd, "Testnum $testnum\n";
|
||||
# if this section exists, it might be server instructions:
|
||||
my @servercmd = getpart("reply", "servercmd");
|
||||
push @servercmd, "Testnum $testnum\n";
|
||||
# write the instructions to file
|
||||
writearray("$LOGDIR/$SERVERCMD", \@ftpservercmd);
|
||||
writearray("$LOGDIR/$SERVERCMD", \@servercmd);
|
||||
|
||||
# if this section exists, it might be DNS instructions:
|
||||
my @dnscmd = getpart("reply", "dns");
|
||||
# write the instructions to file
|
||||
writearray("$LOGDIR/$DNSCMD", \@dnscmd);
|
||||
|
||||
# provide an environment variable
|
||||
$ENV{'CURL_TESTNUM'} = $testnum;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ UTILS = getpart.c util.c
|
|||
CURLX_CFILES = \
|
||||
../../lib/curlx/base64.c \
|
||||
../../lib/curlx/inet_pton.c \
|
||||
../../lib/curlx/inet_ntop.c \
|
||||
../../lib/curlx/multibyte.c \
|
||||
../../lib/curlx/nonblock.c \
|
||||
../../lib/curlx/strparse.c \
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ static int qname(const unsigned char **pkt, size_t *size)
|
|||
|
||||
#define QTYPE_A 1
|
||||
#define QTYPE_AAAA 28
|
||||
#define QTYPE_HTTPS 0x41
|
||||
|
||||
/*
|
||||
* Handle initial connection protocol.
|
||||
|
|
@ -142,11 +143,13 @@ static int store_incoming(const unsigned char *data, size_t size,
|
|||
logmsg("Question for '%s' type %x", name, qd);
|
||||
|
||||
qd = get16bit(&data, &size);
|
||||
fprintf(server, "QCLASS: %04x\n", qd);
|
||||
logmsg("QCLASS: %04x\n", qd);
|
||||
|
||||
*qlen = qsize - size; /* total size of the query */
|
||||
memcpy(qbuf, qptr, *qlen);
|
||||
}
|
||||
else
|
||||
logmsg("Bad input qname");
|
||||
#if 0
|
||||
for(i = 0; i < size; i++) {
|
||||
fprintf(server, "%02d", (unsigned int)data[i]);
|
||||
|
|
@ -159,76 +162,6 @@ static int store_incoming(const unsigned char *data, size_t size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int send_response(curl_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
curl_socklen_t addrlen,
|
||||
unsigned short id)
|
||||
{
|
||||
ssize_t rc;
|
||||
unsigned char bytes[] = {
|
||||
0x80, 0xea, /* ID, overwrite */
|
||||
0x81, 0x80,
|
||||
/*
|
||||
Flags: 0x8180 Standard query response, No error
|
||||
1... .... .... .... = Response: Message is a response
|
||||
.000 0... .... .... = Opcode: Standard query (0)
|
||||
.... .0.. .... .... = Authoritative: Server is not an authority for
|
||||
domain
|
||||
.... ..0. .... .... = Truncated: Message is not truncated
|
||||
.... ...1 .... .... = Recursion desired: Do query recursively
|
||||
.... .... 1... .... = Recursion available: Server can do recursive
|
||||
queries
|
||||
.... .... .0.. .... = Z: reserved (0)
|
||||
.... .... ..0. .... = Answer authenticated: Answer/authority portion
|
||||
was not authenticated by the server
|
||||
.... .... ...0 .... = Non-authenticated data: Unacceptable
|
||||
.... .... .... 0000 = Reply code: No error (0)
|
||||
*/
|
||||
0x0, 0x1, /* QDCOUNT */
|
||||
0x0, 0x4, /* ANCOUNT */
|
||||
0x0, 0x0, /* NSCOUNT */
|
||||
0x0, 0x0, /* ARCOUNT */
|
||||
|
||||
/* here's the question */
|
||||
0x4, 0x63, 0x75, 0x72, 0x6c, 0x2, 0x73, 0x65, 0x0, /* curl.se */
|
||||
0x0, 0x1, /* QTYPE: A */
|
||||
0x0, 0x1, /* QCLASS: IN */
|
||||
|
||||
/* 4 answers */
|
||||
0xc0, 0xc, /* points to curl.se */
|
||||
0x0, 0x1, /* QTYPE A */
|
||||
0x0, 0x1, /* QCLASS IN */
|
||||
0x0, 0x0, 0xa, 0x14, /* Time to live: 2580 (43 minutes) */
|
||||
0x0, 0x4, /* data length */
|
||||
0x97, 0x65, 0x41, 0x5b, /* Address: 151.101.65.91 */
|
||||
|
||||
0xc0, 0xc, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0xa, 0x14,
|
||||
0x0, 0x4, 0x97, 0x65, 0x81, 0x5b, /* Address: 151.101.129.91 */
|
||||
0xc0, 0xc, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0xa, 0x14,
|
||||
0x0, 0x4, 0x97, 0x65, 0xc1, 0x5b, /* Address: 151.101.193.91 */
|
||||
0xc0, 0xc, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0xa, 0x14,
|
||||
0x0, 0x4, 0x97, 0x65, 0x1, 0x5b, /* Address: 151.101.1.91 */
|
||||
#if 0
|
||||
/* 1 additional record (ARCOUNT) */
|
||||
|
||||
0x0, 0x0, 0x29, 0x4, 0xd0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0
|
||||
#endif
|
||||
};
|
||||
size_t len = sizeof(bytes);
|
||||
|
||||
bytes[0] = (unsigned char)(id >> 8);
|
||||
bytes[1] = (unsigned char)(id & 0xff);
|
||||
|
||||
rc = sendto(sock, bytes, len, 0, addr, addrlen);
|
||||
if(rc != (ssize_t)len) {
|
||||
fprintf(stderr, "failed sending %d bytes\n", (int)len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void add_answer(unsigned char *bytes, size_t *w,
|
||||
const unsigned char *a, size_t alen,
|
||||
unsigned short qtype)
|
||||
|
|
@ -269,6 +202,17 @@ static void add_answer(unsigned char *bytes, size_t *w,
|
|||
#define SENDTO3 size_t
|
||||
#endif
|
||||
|
||||
#define INSTRUCTIONS "dnsd.cmd"
|
||||
|
||||
#define MAX_ALPN 5
|
||||
|
||||
static unsigned char ipv4_pref[4];
|
||||
static unsigned char ipv6_pref[16];
|
||||
static unsigned char alpn_pref[MAX_ALPN];
|
||||
static int alpn_count;
|
||||
static unsigned char ancount_a;
|
||||
static unsigned char ancount_aaaa;
|
||||
|
||||
/* this is an answer to a question */
|
||||
static int send_response(curl_socket_t sock,
|
||||
const struct sockaddr *addr, curl_socklen_t addrlen,
|
||||
|
|
@ -278,7 +222,7 @@ static int send_response(curl_socket_t sock,
|
|||
ssize_t rc;
|
||||
size_t i;
|
||||
int a;
|
||||
unsigned char ancount = 3;
|
||||
char addrbuf[128]; /* IP address buffer */
|
||||
unsigned char bytes[256] = {
|
||||
0x80, 0xea, /* ID, overwrite */
|
||||
0x81, 0x80,
|
||||
|
|
@ -303,14 +247,9 @@ static int send_response(curl_socket_t sock,
|
|||
0x0, 0x0, /* NSCOUNT */
|
||||
0x0, 0x0 /* ARCOUNT */
|
||||
};
|
||||
static const unsigned char ipv4_localhost[] = { 127, 0, 0, 1 };
|
||||
static const unsigned char ipv6_localhost[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
|
||||
};
|
||||
|
||||
bytes[0] = (unsigned char)(id >> 8);
|
||||
bytes[1] = (unsigned char)(id & 0xff);
|
||||
bytes[7] = ancount;
|
||||
|
||||
if(qlen > (sizeof(bytes) - 12))
|
||||
return -1;
|
||||
|
|
@ -320,16 +259,28 @@ static int send_response(curl_socket_t sock,
|
|||
|
||||
i = 12 + qlen;
|
||||
|
||||
for(a = 0; a < ancount; a++) {
|
||||
switch(qtype) {
|
||||
case QTYPE_A:
|
||||
add_answer(bytes, &i, ipv4_localhost, sizeof(ipv4_localhost), QTYPE_A);
|
||||
break;
|
||||
case QTYPE_AAAA:
|
||||
add_answer(bytes, &i, ipv6_localhost, sizeof(ipv6_localhost),
|
||||
QTYPE_AAAA);
|
||||
break;
|
||||
switch(qtype) {
|
||||
case QTYPE_A:
|
||||
bytes[7] = ancount_a;
|
||||
for(a = 0; a < ancount_a; a++) {
|
||||
const unsigned char *store = ipv4_pref;
|
||||
add_answer(bytes, &i, store, sizeof(ipv4_pref), QTYPE_A);
|
||||
logmsg("Sending back A (%x) '%s'", QTYPE_A,
|
||||
curlx_inet_ntop(AF_INET, store, addrbuf, sizeof(addrbuf)));
|
||||
}
|
||||
break;
|
||||
case QTYPE_AAAA:
|
||||
bytes[7] = ancount_aaaa;
|
||||
for(a = 0; a < ancount_aaaa; a++) {
|
||||
const unsigned char *store = ipv6_pref;
|
||||
add_answer(bytes, &i, store, sizeof(ipv6_pref), QTYPE_AAAA);
|
||||
logmsg("Sending back AAAA (%x) '%s'", QTYPE_AAAA,
|
||||
curlx_inet_ntop(AF_INET6, store, addrbuf, sizeof(addrbuf)));
|
||||
}
|
||||
break;
|
||||
case QTYPE_HTTPS:
|
||||
bytes[7] = 1; /* one answer */
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __AMIGA__
|
||||
|
|
@ -349,6 +300,68 @@ static int send_response(curl_socket_t sock,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void read_instructions(void)
|
||||
{
|
||||
char file[256];
|
||||
FILE *f;
|
||||
snprintf(file, sizeof(file), "%s/" INSTRUCTIONS, logdir);
|
||||
f = fopen(file, FOPEN_READTEXT);
|
||||
if(f) {
|
||||
char buf[256];
|
||||
ancount_aaaa = ancount_a = 0;
|
||||
alpn_count = 0;
|
||||
while(fgets(buf, sizeof(buf), f)) {
|
||||
char *p = strchr(buf, '\n');
|
||||
if(p) {
|
||||
int rc;
|
||||
*p = 0;
|
||||
if(!strncmp("A: ", buf, 3)) {
|
||||
rc = curlx_inet_pton(AF_INET, &buf[3], ipv4_pref);
|
||||
ancount_a = (rc == 1);
|
||||
}
|
||||
else if(!strncmp("AAAA: ", buf, 6)) {
|
||||
char *p6 = &buf[6];
|
||||
if(*p6 == '[') {
|
||||
char *pt = strchr(p6, ']');
|
||||
if(pt)
|
||||
*pt = 0;
|
||||
p6++;
|
||||
}
|
||||
rc = curlx_inet_pton(AF_INET6, p6, ipv6_pref);
|
||||
ancount_aaaa = (rc == 1);
|
||||
}
|
||||
else if(!strncmp("ALPN: ", buf, 6)) {
|
||||
char *ap = &buf[6];
|
||||
rc = 0;
|
||||
while(*ap) {
|
||||
if('h' == *ap) {
|
||||
ap++;
|
||||
if(*ap >= '1' && *ap <= '3') {
|
||||
if(alpn_count < MAX_ALPN)
|
||||
alpn_pref[alpn_count++] = *ap;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rc = 0;
|
||||
}
|
||||
if(rc != 1) {
|
||||
logmsg("Bad line in %s: '%s'\n", file, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
logmsg("Error opening file '%s'", file);
|
||||
}
|
||||
|
||||
static int test_dnsd(int argc, char **argv)
|
||||
{
|
||||
srvr_sockaddr_union_t me;
|
||||
|
|
@ -586,6 +599,10 @@ static int test_dnsd(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
|
||||
/* read once per incoming query, which is probably more than one
|
||||
per test case */
|
||||
read_instructions();
|
||||
|
||||
store_incoming(inbuffer, n, qbuf, &qlen, &qtype, &id);
|
||||
|
||||
set_advisor_read_lock(loglockfile);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue