mirror of
https://github.com/ipxe/ipxe
synced 2025-12-24 06:22:59 +03:00
[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:
@@ -290,6 +290,9 @@ struct dhcp_client_uuid {
|
||||
|
||||
#define DHCP_CLIENT_UUID_TYPE 0
|
||||
|
||||
/** DNS domain search list */
|
||||
#define DHCP_DOMAIN_SEARCH 119
|
||||
|
||||
/** Etherboot-specific encapsulated options
|
||||
*
|
||||
* This encapsulated options field is used to contain all options
|
||||
|
||||
@@ -12,88 +12,144 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <stdint.h>
|
||||
#include <ipxe/in.h>
|
||||
|
||||
/*
|
||||
* Constants
|
||||
/** DNS server port */
|
||||
#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
|
||||
#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
|
||||
/**
|
||||
* Extract DNS compression pointer
|
||||
*
|
||||
* @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 {
|
||||
uint16_t id;
|
||||
uint16_t flags;
|
||||
uint16_t qdcount;
|
||||
uint16_t ancount;
|
||||
uint16_t nscount;
|
||||
uint16_t arcount;
|
||||
/** Query identifier */
|
||||
uint16_t id;
|
||||
/** Flags */
|
||||
uint16_t flags;
|
||||
/** Number of question records */
|
||||
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 ));
|
||||
|
||||
struct dns_query_info {
|
||||
uint16_t qtype;
|
||||
uint16_t qclass;
|
||||
/** Recursion desired flag */
|
||||
#define DNS_FLAG_RD 0x0100
|
||||
|
||||
/** A DNS question */
|
||||
struct dns_question {
|
||||
/** Query type */
|
||||
uint16_t qtype;
|
||||
/** Query class */
|
||||
uint16_t qclass;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
struct dns_query {
|
||||
struct dns_header dns;
|
||||
char payload[ 256 + sizeof ( struct dns_query_info ) ];
|
||||
/** DNS class "IN" */
|
||||
#define DNS_CLASS_IN 1
|
||||
|
||||
/** 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 ));
|
||||
|
||||
struct dns_rr_info_common {
|
||||
uint16_t type;
|
||||
uint16_t class;
|
||||
uint32_t ttl;
|
||||
uint16_t rdlength;
|
||||
} __attribute__ (( packed ));
|
||||
/** Type of a DNS "A" record */
|
||||
#define DNS_TYPE_A 1
|
||||
|
||||
struct dns_rr_info_a {
|
||||
struct dns_rr_info_common common;
|
||||
/** A DNS "A" record */
|
||||
struct dns_rr_a {
|
||||
/** Common fields */
|
||||
struct dns_rr_common common;
|
||||
/** IPv4 address */
|
||||
struct in_addr in_addr;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
struct dns_rr_info_aaaa {
|
||||
struct dns_rr_info_common common;
|
||||
/** Type of a DNS "AAAA" record */
|
||||
#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;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
struct dns_rr_info_cname {
|
||||
struct dns_rr_info_common common;
|
||||
char cname[0];
|
||||
/** Type of a DNS "NAME" record */
|
||||
#define DNS_TYPE_CNAME 5
|
||||
|
||||
/** A DNS "CNAME" record */
|
||||
struct dns_rr_cname {
|
||||
/** Common fields */
|
||||
struct dns_rr_common common;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
union dns_rr_info {
|
||||
struct dns_rr_info_common common;
|
||||
struct dns_rr_info_a a;
|
||||
struct dns_rr_info_aaaa aaaa;
|
||||
struct dns_rr_info_cname cname;
|
||||
/** A DNS resource record */
|
||||
union dns_rr {
|
||||
/** Common fields */
|
||||
struct dns_rr_common common;
|
||||
/** "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 */
|
||||
|
||||
@@ -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_uuid __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
|
||||
ip_setting __setting ( SETTING_IP, ip );
|
||||
|
||||
Reference in New Issue
Block a user