david/ipxe
Archived
1
0

[dns] Support DNS search lists

Update the DNS resolver to support DNS search lists (as provided by
DHCP option 119, DHCPv6 option 24, or NDP option 31).

Add validation code to ensure that parsing of DNS packets does not
overrun the input, get stuck in infinite loops, or (worse) write
beyond the end of allocated buffers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2014-01-31 18:16:42 +00:00
parent 3fa7a3b136
commit d4c0226a6c
9 changed files with 1457 additions and 333 deletions

View File

@ -290,6 +290,9 @@ struct dhcp_client_uuid {
#define DHCP_CLIENT_UUID_TYPE 0 #define DHCP_CLIENT_UUID_TYPE 0
/** DNS domain search list */
#define DHCP_DOMAIN_SEARCH 119
/** Etherboot-specific encapsulated options /** Etherboot-specific encapsulated options
* *
* This encapsulated options field is used to contain all options * This encapsulated options field is used to contain all options

View File

@ -12,88 +12,144 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h> #include <stdint.h>
#include <ipxe/in.h> #include <ipxe/in.h>
/* /** DNS server port */
* Constants #define DNS_PORT 53
/** An RFC1035-encoded DNS name */
struct dns_name {
/** Start of data */
void *data;
/** Offset of name within data */
size_t offset;
/** Total length of data */
size_t len;
};
/**
* Test for a DNS compression pointer
* *
* @v byte Initial byte
* @ret is_compressed Is a compression pointer
*/ */
#define DNS_IS_COMPRESSED( byte ) ( (byte) & 0xc0 )
#define DNS_TYPE_A 1 /**
#define DNS_TYPE_CNAME 5 * Extract DNS compression pointer
#define DNS_TYPE_AAAA 28
#define DNS_TYPE_ANY 255
#define DNS_CLASS_IN 1
#define DNS_CLASS_CS 2
#define DNS_CLASS_CH 3
#define DNS_CLASS_HS 4
#define DNS_FLAG_QUERY ( 0x00 << 15 )
#define DNS_FLAG_RESPONSE ( 0x01 << 15 )
#define DNS_FLAG_QR(flags) ( (flags) & ( 0x01 << 15 ) )
#define DNS_FLAG_OPCODE_QUERY ( 0x00 << 11 )
#define DNS_FLAG_OPCODE_IQUERY ( 0x01 << 11 )
#define DNS_FLAG_OPCODE_STATUS ( 0x02 << 11 )
#define DNS_FLAG_OPCODE(flags) ( (flags) & ( 0x0f << 11 ) )
#define DNS_FLAG_RD ( 0x01 << 8 )
#define DNS_FLAG_RA ( 0x01 << 7 )
#define DNS_FLAG_RCODE_OK ( 0x00 << 0 )
#define DNS_FLAG_RCODE_NX ( 0x03 << 0 )
#define DNS_FLAG_RCODE(flags) ( (flags) & ( 0x0f << 0 ) )
#define DNS_PORT 53
#define DNS_MAX_RETRIES 3
#define DNS_MAX_CNAME_RECURSION 0x30
/*
* DNS protocol structures
* *
* @v word Initial word
* @ret offset Offset
*/ */
#define DNS_COMPRESSED_OFFSET( word ) ( (word) & ~0xc000 )
/**
* Extract DNS label length
*
* @v byte Initial byte
* @ret len Label length
*/
#define DNS_LABEL_LEN( byte ) ( (byte) & ~0xc0 )
/** Maximum length of a single DNS label */
#define DNS_MAX_LABEL_LEN 0x3f
/** Maximum length of a DNS name (mandated by RFC1035 section 2.3.4) */
#define DNS_MAX_NAME_LEN 255
/** Maximum depth of CNAME recursion
*
* This is a policy decision.
*/
#define DNS_MAX_CNAME_RECURSION 32
/** A DNS packet header */
struct dns_header { struct dns_header {
uint16_t id; /** Query identifier */
uint16_t flags; uint16_t id;
uint16_t qdcount; /** Flags */
uint16_t ancount; uint16_t flags;
uint16_t nscount; /** Number of question records */
uint16_t arcount; uint16_t qdcount;
/** Number of answer records */
uint16_t ancount;
/** Number of name server records */
uint16_t nscount;
/** Number of additional records */
uint16_t arcount;
} __attribute__ (( packed )); } __attribute__ (( packed ));
struct dns_query_info { /** Recursion desired flag */
uint16_t qtype; #define DNS_FLAG_RD 0x0100
uint16_t qclass;
/** A DNS question */
struct dns_question {
/** Query type */
uint16_t qtype;
/** Query class */
uint16_t qclass;
} __attribute__ (( packed )); } __attribute__ (( packed ));
struct dns_query { /** DNS class "IN" */
struct dns_header dns; #define DNS_CLASS_IN 1
char payload[ 256 + sizeof ( struct dns_query_info ) ];
/** A DNS resource record */
struct dns_rr_common {
/** Type */
uint16_t type;
/** Class */
uint16_t class;
/** Time to live */
uint32_t ttl;
/** Resource data length */
uint16_t rdlength;
} __attribute__ (( packed )); } __attribute__ (( packed ));
struct dns_rr_info_common { /** Type of a DNS "A" record */
uint16_t type; #define DNS_TYPE_A 1
uint16_t class;
uint32_t ttl;
uint16_t rdlength;
} __attribute__ (( packed ));
struct dns_rr_info_a { /** A DNS "A" record */
struct dns_rr_info_common common; struct dns_rr_a {
/** Common fields */
struct dns_rr_common common;
/** IPv4 address */
struct in_addr in_addr; struct in_addr in_addr;
} __attribute__ (( packed )); } __attribute__ (( packed ));
struct dns_rr_info_aaaa { /** Type of a DNS "AAAA" record */
struct dns_rr_info_common common; #define DNS_TYPE_AAAA 28
/** A DNS "AAAA" record */
struct dns_rr_aaaa {
/** Common fields */
struct dns_rr_common common;
/** IPv6 address */
struct in6_addr in6_addr; struct in6_addr in6_addr;
} __attribute__ (( packed )); } __attribute__ (( packed ));
struct dns_rr_info_cname { /** Type of a DNS "NAME" record */
struct dns_rr_info_common common; #define DNS_TYPE_CNAME 5
char cname[0];
/** A DNS "CNAME" record */
struct dns_rr_cname {
/** Common fields */
struct dns_rr_common common;
} __attribute__ (( packed )); } __attribute__ (( packed ));
union dns_rr_info { /** A DNS resource record */
struct dns_rr_info_common common; union dns_rr {
struct dns_rr_info_a a; /** Common fields */
struct dns_rr_info_aaaa aaaa; struct dns_rr_common common;
struct dns_rr_info_cname cname; /** "A" record */
struct dns_rr_a a;
/** "AAAA" record */
struct dns_rr_aaaa aaaa;
/** "CNAME" record */
struct dns_rr_cname cname;
}; };
extern int dns_encode ( const char *string, struct dns_name *name );
extern int dns_decode ( struct dns_name *name, char *data, size_t len );
extern int dns_compare ( struct dns_name *first, struct dns_name *second );
extern int dns_copy ( struct dns_name *src, struct dns_name *dst );
extern int dns_skip ( struct dns_name *name );
#endif /* _IPXE_DNS_H */ #endif /* _IPXE_DNS_H */

View File

@ -417,6 +417,7 @@ extern const struct setting_type setting_type_hexhyp __setting_type;
extern const struct setting_type setting_type_hexraw __setting_type; extern const struct setting_type setting_type_hexraw __setting_type;
extern const struct setting_type setting_type_uuid __setting_type; extern const struct setting_type setting_type_uuid __setting_type;
extern const struct setting_type setting_type_busdevfn __setting_type; extern const struct setting_type setting_type_busdevfn __setting_type;
extern const struct setting_type setting_type_dnssl __setting_type;
extern const struct setting extern const struct setting
ip_setting __setting ( SETTING_IP, ip ); ip_setting __setting ( SETTING_IP, ip );

View File

@ -786,6 +786,16 @@ const struct setting ndp_dns6_setting __setting ( SETTING_IP_EXTRA, dns6 ) = {
.scope = &ndp_settings_scope, .scope = &ndp_settings_scope,
}; };
/** DNS search list setting */
const struct setting ndp_dnssl_setting __setting ( SETTING_IP_EXTRA, dnssl ) = {
.name = "dnssl",
.description = "DNS search list",
.tag = NDP_TAG ( NDP_OPT_DNSSL,
offsetof ( struct ndp_dnssl_option, names ) ),
.type = &setting_type_dnssl,
.scope = &ndp_settings_scope,
};
/**************************************************************************** /****************************************************************************
* *
* IPv6 autoconfiguration * IPv6 autoconfiguration

View File

@ -86,6 +86,7 @@ static uint8_t dhcp_request_options_data[] = {
DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME, DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME,
DHCP_ROOT_PATH, DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID, DHCP_ROOT_PATH, DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID,
DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME, DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME,
DHCP_DOMAIN_SEARCH,
128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */ 128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */
DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ), DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ),
DHCP_END DHCP_END

View File

@ -979,3 +979,12 @@ const struct setting filename6_setting __setting ( SETTING_BOOT, filename ) = {
.type = &setting_type_string, .type = &setting_type_string,
.scope = &ipv6_scope, .scope = &ipv6_scope,
}; };
/** DNS search list setting */
const struct setting dnssl6_setting __setting ( SETTING_IP_EXTRA, dnssl ) = {
.name = "dnssl",
.description = "DNS search list",
.tag = DHCPV6_DOMAIN_LIST,
.type = &setting_type_dnssl,
.scope = &ipv6_scope,
};

File diff suppressed because it is too large Load Diff

605
src/tests/dns_test.c Normal file
View File

@ -0,0 +1,605 @@
/*
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** @file
*
* DNS self-tests
*
*/
/* Forcibly enable assertions */
#undef NDEBUG
#include <string.h>
#include <assert.h>
#include <ipxe/dns.h>
#include <ipxe/test.h>
/** Define inline data */
#define DATA(...) { __VA_ARGS__ }
/** A DNS encoding test */
struct dns_encode_test {
/** String */
const char *string;
/** Encoded string */
const void *data;
/** Length of encoded string */
int len;
};
/**
* Define a DNS encoding test
*
* @v _name Test name
* @v _string Test string
* @v _data Expected encoded data
* @ret test DNS encoding test
*/
#define DNS_ENCODE( _name, _string, _data ) \
static const uint8_t _name ## __data[] = _data; \
static struct dns_encode_test _name = { \
.string = _string, \
.data = _name ## __data, \
.len = sizeof ( _name ## __data ), \
}
/**
* Report DNS encoding test result
*
* @v test DNS encoding test
* @v file Test code file
* @v line Test code line
*/
static void dns_encode_okx ( struct dns_encode_test *test, const char *file,
unsigned int line ) {
uint8_t data[ test->len ];
struct dns_name name;
int len;
/* Check ability to determine length with no buffer */
memset ( &name, 0, sizeof ( name ) );
len = dns_encode ( test->string, &name );
okx ( len >= 0, file, line );
okx ( len == test->len, file, line );
/* Check encoded name */
name.data = data;
name.len = sizeof ( data );
len = dns_encode ( test->string, &name );
okx ( len >= 0, file, line );
if ( len >= 0 ) {
okx ( len == test->len, file, line );
okx ( memcmp ( data, test->data, test->len ) == 0, file, line );
DBGC ( test, "DNS encoded \"%s\" to:\n", test->string );
DBGC_HDA ( test, 0, data, len );
}
}
#define dns_encode_ok( test ) dns_encode_okx ( test, __FILE__, __LINE__ )
/**
* Report DNS encoding failure test result
*
* @v test DNS encoding test
* @v file Test code file
* @v line Test code line
*/
static void dns_encode_fail_okx ( struct dns_encode_test *test,
const char *file, unsigned int line ) {
struct dns_name name = { .data = NULL, .len = 0 };
int len;
len = dns_encode ( test->string, &name );
okx ( len < 0, file, line );
}
#define dns_encode_fail_ok( test ) \
dns_encode_fail_okx ( test, __FILE__, __LINE__ )
/** A DNS decoding test */
struct dns_decode_test {
/** Name */
struct dns_name name;
/** Expected string */
const char *string;
};
/**
* Define a DNS decoding test
*
* @v _name Test name
* @v _data RFC1035-encoded data
* @v _offset Starting offset within encoded data
* @v _string Expected decoded string
* @ret test DNS decoding test
*/
#define DNS_DECODE( _name, _data, _offset, _string ) \
static uint8_t _name ## __data[] = _data; \
static struct dns_decode_test _name = { \
.name = { \
.data = _name ## __data, \
.offset = _offset, \
.len = sizeof ( _name ## __data ), \
}, \
.string = _string, \
}
/**
* Report DNS decoding test result
*
* @v test DNS decoding test
* @v file Test code file
* @v line Test code line
*/
static void dns_decode_okx ( struct dns_decode_test *test, const char *file,
unsigned int line ) {
char string[ strlen ( test->string ) + 1 /* NUL */ ];
int len;
/* Check ability to determine length with no buffer */
len = dns_decode ( &test->name, NULL, 0 );
okx ( len >= 0, file, line );
okx ( len == ( ( int ) strlen ( test->string ) ), file, line );
/* Check decoded string */
len = dns_decode ( &test->name, string, sizeof ( string ) );
okx ( len >= 0, file, line );
if ( len >= 0 ) {
okx ( strcmp ( string, test->string ) == 0, file, line );
DBGC ( test, "DNS decoded \"%s\" from offset %#zx in:\n",
string, test->name.offset );
DBGC_HDA ( test, 0, test->name.data, test->name.len );
}
}
#define dns_decode_ok( test ) dns_decode_okx ( test, __FILE__, __LINE__ )
/**
* Report DNS decoding failure test result
*
* @v test DNS decoding test
* @v file Test code file
* @v line Test code line
*/
static void dns_decode_fail_okx ( struct dns_decode_test *test,
const char *file, unsigned int line ) {
int len;
len = dns_decode ( &test->name, NULL, 0 );
okx ( len < 0, file, line );
}
#define dns_decode_fail_ok( test ) \
dns_decode_fail_okx ( test, __FILE__, __LINE__ )
/** A DNS comparison test */
struct dns_compare_test {
/** First name */
struct dns_name first;
/** Second name */
struct dns_name second;
};
/**
* Define a DNS comparison test
*
* @v _name Test name
* @v _first_data First RFC1035-encoded data
* @v _first_offset Starting offset within first encoded data
* @v _second_data Second RFC1035-encoded data
* @v _second_offset Starting offset within second encoded data
* @ret test DNS comparison test
*/
#define DNS_COMPARE( _name, _first_data, _first_offset, _second_data, \
_second_offset ) \
static uint8_t _name ## __first_data[] = _first_data; \
static uint8_t _name ## __second_data[] = _second_data; \
static struct dns_compare_test _name = { \
.first = { \
.data = _name ## __first_data, \
.offset = _first_offset, \
.len = sizeof ( _name ## __first_data ), \
}, \
.second = { \
.data = _name ## __second_data, \
.offset = _second_offset, \
.len = sizeof ( _name ## __second_data ), \
}, \
}
/**
* Report DNS comparison test result
*
* @v test DNS comparison test
* @v file Test code file
* @v line Test code line
*/
static void dns_compare_okx ( struct dns_compare_test *test, const char *file,
unsigned int line ) {
okx ( dns_compare ( &test->first, &test->second ) == 0, file, line );
}
#define dns_compare_ok( test ) dns_compare_okx ( test, __FILE__, __LINE__ )
/**
* Report DNS comparison test failure result
*
* @v test DNS comparison test
* @v file Test code file
* @v line Test code line
*/
static void dns_compare_fail_okx ( struct dns_compare_test *test,
const char *file, unsigned int line ) {
okx ( dns_compare ( &test->first, &test->second ) != 0, file, line );
}
#define dns_compare_fail_ok( test ) \
dns_compare_fail_okx ( test, __FILE__, __LINE__ )
/** A DNS copying test */
struct dns_copy_test {
/** Source name */
struct dns_name src;
/** Expected copied name */
struct dns_name dst;
};
/**
* Define a DNS copying test
*
* @v _name Test name
* @v _src_data Source RFC1035-encoded data
* @v _src_offset Starting offset within source encoded data
* @v _dst_data Expected copied RFC1035-encoded data
* @v _dst_offset Starting offset withint copied encoded data
* @ret test DNS copying test
*/
#define DNS_COPY( _name, _src_data, _src_offset, _dst_data, \
_dst_offset ) \
static uint8_t _name ## __src_data[] = _src_data; \
static uint8_t _name ## __dst_data[] = _dst_data; \
static struct dns_copy_test _name = { \
.src = { \
.data = _name ## __src_data, \
.offset = _src_offset, \
.len = sizeof ( _name ## __src_data ), \
}, \
.dst = { \
.data = _name ## __dst_data, \
.offset = _dst_offset, \
.len = sizeof ( _name ## __dst_data ), \
}, \
}
/**
* Report a DNS copying test result
*
* @v test DNS copying test
* @v file Test code file
* @v line Test code line
*/
static void dns_copy_okx ( struct dns_copy_test *test,
const char *file, unsigned int line ) {
uint8_t data[ test->dst.len ];
struct dns_name dst;
int len;
/* Check ability to determine length with no buffer */
memset ( &dst, 0, sizeof ( dst ) );
len = dns_copy ( &test->src, &dst );
okx ( len >= 0, file, line );
okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ),
file, line );
/* Check copied name */
dst.data = data;
dst.offset = test->dst.offset;
dst.len = sizeof ( data );
memcpy ( dst.data, test->dst.data, test->dst.offset );
len = dns_copy ( &test->src, &dst );
okx ( len >= 0, file, line );
okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ),
file, line );
okx ( memcmp ( data, test->dst.data, sizeof ( data ) ) == 0,
file, line );
DBGC ( test, "DNS copied:\n" );
DBGC_HDA ( test, 0, test->src.data, test->src.len );
DBGC_HDA ( test, 0, data, ( test->dst.offset + len ) );
}
#define dns_copy_ok( test ) dns_copy_okx ( test, __FILE__, __LINE__ )
/**
* Report a DNS copying failure test result
*
* @v test DNS copying test
* @v file Test code file
* @v line Test code line
*/
static void dns_copy_fail_okx ( struct dns_copy_test *test,
const char *file, unsigned int line ) {
struct dns_name dst;
int len;
memset ( &dst, 0, sizeof ( dst ) );
len = dns_copy ( &test->src, &dst );
okx ( len < 0, file, line );
}
#define dns_copy_fail_ok( test ) dns_copy_fail_okx ( test, __FILE__, __LINE__ )
/** A DNS search list test */
struct dns_list_test {
/** Search list */
struct dns_name list;
/** Expected decoded search list */
const char **strings;
/** Number of expected decoded string */
unsigned int count;
};
/**
* Define a DNS search list test
*
* @v _name Test name
* @v _list RFC1035-encoded data
* @v _strings Expected decoded strings
* @ret test DNS search list test
*/
#define DNS_LIST( _name, _list, _strings ) \
static uint8_t _name ## __list[] = _list; \
static const char * _name ## __strings[] = _strings; \
static struct dns_list_test _name = { \
.list = { \
.data = _name ## __list, \
.offset = 0, \
.len = sizeof ( _name ## __list ), \
}, \
.strings = _name ## __strings, \
.count = ( sizeof ( _name ## __strings ) / \
sizeof ( _name ## __strings[0] ) ), \
}
/**
* Report DNS search list test result
*
* @v test DNS search list test
* @v file Test code file
* @v line Test code line
*/
static void dns_list_okx ( struct dns_list_test *test, const char *file,
unsigned int line ) {
struct dns_name name;
unsigned int i;
DBGC ( test, "DNS search list:\n" );
DBGC_HDA ( test, 0, test->list.data, test->list.len );
memcpy ( &name, &test->list, sizeof ( name ) );
for ( i = 0 ; i < test->count ; i++ ) {
char buf[ strlen ( test->strings[i] ) + 1 /* NUL */ ];
int len;
int offset;
/* Decode this name */
len = dns_decode ( &name, buf, sizeof ( buf ) );
okx ( len >= 0, file, line );
if ( len >= 0 ) {
okx ( len == ( ( int ) strlen ( test->strings[i] ) ),
file, line );
okx ( strcmp ( buf, test->strings[i] ) == 0,
file, line );
DBGC ( test, "DNS search list found \"%s\" at offset "
"%#zx\n", buf, name.offset );
}
/* Skip to next name */
offset = dns_skip ( &name );
okx ( offset >= 0, file, line );
name.offset = offset;
}
/* Check that we have consumed the whole search list */
okx ( name.offset == name.len, file, line );
}
#define dns_list_ok( test ) dns_list_okx ( test, __FILE__, __LINE__ )
/* Simple encoding test */
DNS_ENCODE ( encode_simple, "ipxe.org",
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ) );
/* Single-word encoding test */
DNS_ENCODE ( encode_single, "foo", DATA ( 3, 'f', 'o', 'o', 0 ) );
/* Absolute encoding test */
DNS_ENCODE ( encode_absolute, "git.ipxe.org.",
DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
0 ) );
/* Empty string encoding test */
DNS_ENCODE ( encode_empty, "", DATA ( 0 ) );
/* Root domain encoding test */
DNS_ENCODE ( encode_root, ".", DATA ( 0 ) );
/* Invalid initial dot encoding test */
DNS_ENCODE ( encode_initial_dot, ".foo", DATA() );
/* Invalid double dot encoding test */
DNS_ENCODE ( encode_double_dot, "ipxe..org", DATA() );
/* Invalid solo double dot encoding test */
DNS_ENCODE ( encode_solo_double_dot, "..", DATA() );
/* Invalid trailing double dot encoding test */
DNS_ENCODE ( encode_trailing_double_dot, "ipxe.org..", DATA() );
/* Invalid overlength label encoding test */
DNS_ENCODE ( encode_overlength,
"this-label-is-maliciously-long-in-an-attempt-to-overflow-the-"
"length-field-and-generate-a-length-which-looks-like-a-"
"compression-pointer", DATA() );
/* Simple decoding test */
DNS_DECODE ( decode_simple,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
"ipxe.org" );
/* Compression pointer decoding test */
DNS_DECODE ( decode_ptr,
DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x',
'e', 0xc0, 0x00 ), 5,
"git.ipxe.org" );
/* Root decoding test */
DNS_DECODE ( decode_root,
DATA ( 0 ), 0, "" );
/* Incomplete name decoding test */
DNS_DECODE ( decode_incomplete_name,
DATA ( 4, 'i', 'p', 'x', 'e' ), 0, NULL );
/* Incomplete label decoding test */
DNS_DECODE ( decode_incomplete_label,
DATA ( 4, 'i', 'p', 'x' ), 0, NULL );
/* Incomplete compression pointer decoding test */
DNS_DECODE ( decode_incomplete_ptr,
DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e', 0xc0 ), 5,
NULL );
/* Forward reference decoding test */
DNS_DECODE ( decode_forward,
DATA ( 0xc0, 0x02, 3, 'f', 'o', 'o', 0 ), 0, NULL );
/* Infinite loop decoding test */
DNS_DECODE ( decode_infinite,
DATA ( 4, 'i', 'p', 'x', 'e', 0xc0, 0x00 ), 0, NULL );
/* Empty decoding test */
DNS_DECODE ( decode_empty,
DATA (), 0, NULL );
/* Simple comparison test */
DNS_COMPARE ( compare_simple,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
/* Compression pointer comparison test */
DNS_COMPARE ( compare_ptr,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e',
0xc0, 0x00 ), 5 );
/* Case insensitive comparison test */
DNS_COMPARE ( compare_case,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'O', 'R', 'G', 0 ), 0 );
/* Mismatch comparison test */
DNS_COMPARE ( compare_mismatch,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
DATA ( 4, 'g', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
/* Infinite loop comparison test */
DNS_COMPARE ( compare_infinite,
DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0,
DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0 );
/* Simple copying test */
DNS_COPY ( copy_simple,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 );
/* Simple copying test with offset */
DNS_COPY ( copy_offset,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0,
DATA ( 'f', 'o', 'o', 0, 4, 'i', 'p', 'x', 'e',
3, 'o', 'r', 'g', 0 ), 4 );
/* Compression pointer copying test */
DNS_COPY ( copy_ptr,
DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e',
0xc0, 0x00 ), 5,
DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g',
0 ), 0 );
/* Infinite loop copying test */
DNS_COPY ( copy_infinite,
DATA ( 4, 'l', 'o', 'o', 'p', 7, 'f', 'o', 'r', 'e', 'v', 'e', 'r',
0xc0, 0x05 ), 0,
DATA (), 0 );
/* DNS search list test */
DNS_LIST ( search,
DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0,
4, 'b', 'o', 'o', 't', 0xc0, 0x00,
3, 'd', 'e', 'v', 0xc0, 0x0a,
11, 'n', 'e', 't', 'w', 'o', 'r', 'k', 'b', 'o', 'o', 't',
0xc0, 0x05 ),
DATA ( "ipxe.org", "boot.ipxe.org", "dev.boot.ipxe.org",
"networkboot.org" ) );
/**
* Perform DNS self-test
*
*/
static void dns_test_exec ( void ) {
/* Encoding tests */
dns_encode_ok ( &encode_simple );
dns_encode_ok ( &encode_single );
dns_encode_ok ( &encode_absolute );
dns_encode_ok ( &encode_empty );
dns_encode_ok ( &encode_root );
dns_encode_fail_ok ( &encode_initial_dot );
dns_encode_fail_ok ( &encode_double_dot );
dns_encode_fail_ok ( &encode_solo_double_dot );
dns_encode_fail_ok ( &encode_trailing_double_dot );
dns_encode_fail_ok ( &encode_overlength );
/* Decoding tests */
dns_decode_ok ( &decode_simple );
dns_decode_ok ( &decode_ptr );
dns_decode_ok ( &decode_root );
dns_decode_fail_ok ( &decode_incomplete_name );
dns_decode_fail_ok ( &decode_incomplete_label );
dns_decode_fail_ok ( &decode_incomplete_ptr );
dns_decode_fail_ok ( &decode_forward );
dns_decode_fail_ok ( &decode_infinite );
dns_decode_fail_ok ( &decode_empty );
/* Comparison tests */
dns_compare_ok ( &compare_simple );
dns_compare_ok ( &compare_ptr );
dns_compare_ok ( &compare_case );
dns_compare_fail_ok ( &compare_mismatch );
dns_compare_fail_ok ( &compare_infinite );
/* Copying tests */
dns_copy_ok ( &copy_simple );
dns_copy_ok ( &copy_offset );
dns_copy_ok ( &copy_ptr );
dns_copy_fail_ok ( &copy_infinite );
/* Search list tets */
dns_list_ok ( &search );
}
/** DNS self-test */
struct self_test dns_test __self_test = {
.name = "dns",
.exec = dns_test_exec,
};

View File

@ -52,3 +52,4 @@ REQUIRE_OBJECT ( cms_test );
REQUIRE_OBJECT ( pnm_test ); REQUIRE_OBJECT ( pnm_test );
REQUIRE_OBJECT ( deflate_test ); REQUIRE_OBJECT ( deflate_test );
REQUIRE_OBJECT ( png_test ); REQUIRE_OBJECT ( png_test );
REQUIRE_OBJECT ( dns_test );