59 #define ENXIO_NO_RECORD __einfo_error ( EINFO_ENXIO_NO_RECORD ) 60 #define EINFO_ENXIO_NO_RECORD \ 61 __einfo_uniqify ( EINFO_ENXIO, 0x01, "DNS name does not exist" ) 62 #define ENXIO_NO_NAMESERVER __einfo_error ( EINFO_ENXIO_NO_NAMESERVER ) 63 #define EINFO_ENXIO_NO_NAMESERVER \ 64 __einfo_uniqify ( EINFO_ENXIO, 0x02, "No DNS servers available" ) 108 while ( (
c = *(
string++) ) ) {
114 if ( (
len == 0 ) && ( dst !=
start ) )
118 if ( *
string ==
'\0' )
152 return ( dst -
start );
171 if ( (
offset +
sizeof ( *
byte) ) >
name->len )
217 unsigned int recursion_limit =
name->len;
220 size_t decoded_len = 0;
224 while ( recursion_limit-- ) {
233 label_len = *(
label++);
234 if ( label_len == 0 ) {
235 if ( decoded_len <
len )
241 if ( decoded_len && ( decoded_len++ <
len ) )
245 copy_len = ( ( decoded_len <
len ) ? (
len - decoded_len ) : 0);
246 if ( copy_len > label_len )
247 copy_len = label_len;
250 decoded_len += label_len;
253 offset += (
sizeof ( *label ) + label_len );
268 unsigned int recursion_limit =
first->len;
269 int first_offset =
first->offset;
270 int second_offset =
second->offset;
276 while ( recursion_limit-- ) {
280 if ( first_offset < 0 )
283 if ( second_offset < 0 )
284 return second_offset;
287 first_label = (
first->data + first_offset );
288 second_label = (
second->data + second_offset );
289 label_len = *(first_label++);
290 if ( label_len != *(second_label++) )
292 len = (
sizeof ( *first_label ) + label_len );
295 if ( label_len == 0 )
299 while ( label_len-- ) {
300 if (
tolower ( *(first_label++) ) !=
301 tolower ( *(second_label++) ) )
307 second_offset +=
len;
322 unsigned int recursion_limit =
src->len;
323 int src_offset =
src->offset;
324 size_t dst_offset = dst->
offset;
330 while ( recursion_limit-- ) {
334 if ( src_offset < 0 )
340 len = (
sizeof ( *label ) + label_len );
341 copy_len = ( ( dst_offset < dst->
len ) ?
342 ( dst->
len - dst_offset ) : 0 );
343 if ( copy_len >
len )
350 if ( label_len == 0 )
351 return ( dst_offset - dst->
offset );
365 unsigned int recursion_limit =
name->len;
371 while ( recursion_limit-- ) {
380 if (
offset != prev_offset )
381 return ( prev_offset +
sizeof (
uint16_t ) );
386 offset += (
sizeof ( *label ) + label_len );
389 if ( label_len == 0 )
429 static char buf[256];
433 return ( (
len < 0 ) ?
"<INVALID>" : buf );
447 default:
return "<UNKNOWN>";
519 DBGC ( dns,
"DNS %p found address %s\n",
536 static struct dns_name search_root = {
546 search = &search_root;
557 DBGC ( dns,
"DNS %p name is too long\n", dns );
575 DBGC2 ( dns,
"DNS %p question is %s type %s\n", dns,
602 memset ( &nameserver, 0,
sizeof ( nameserver ) );
605 DBGC ( dns,
"DNS %p lost DNS servers mid query\n", dns );
610 nameserver.sin6.sin6_family =
AF_INET6;
612 sizeof ( nameserver.sin6.sin6_addr ) );
614 nameserver.sin.sin_family =
AF_INET;
620 meta.dest = &nameserver.sa;
627 DBGC ( dns,
"DNS %p sending %s query ID %#04x for %s type %s\n", dns,
676 size_t answer_offset;
683 if (
iob_len ( iobuf ) <
sizeof ( *response ) ) {
684 DBGC ( dns,
"DNS %p received underlength packet length %zd\n",
691 if ( response->
id != query->
id ) {
692 DBGC ( dns,
"DNS %p received unexpected response ID %#04x " 693 "(wanted %d)\n", dns,
ntohs ( response->
id ),
698 DBGC ( dns,
"DNS %p received response ID %#04x\n",
703 DBGC ( dns,
"DNS %p received response with %d questions\n",
711 buf.
offset =
sizeof ( *response );
716 DBGC ( dns,
"DNS %p received response with malformed " 728 buf.
offset = next_offset ) {
734 DBGC ( dns,
"DNS %p received response with malformed " 742 DBGC ( dns,
"DNS %p received response with underlength " 748 next_offset = (
offset +
sizeof ( rr->
common ) + rdlength );
749 if ( next_offset > buf.
len ) {
750 DBGC ( dns,
"DNS %p received response with underlength " 758 DBGC2 ( dns,
"DNS %p ignoring response for %s type " 771 DBGC ( dns,
"DNS %p received response with " 772 "underlength AAAA\n", dns );
788 DBGC ( dns,
"DNS %p received response with " 789 "underlength A\n", dns );
803 DBGC ( dns,
"DNS %p recursion exceeded\n",
812 DBGC ( dns,
"DNS %p found CNAME %s\n",
822 next_offset = answer_offset;
826 DBGC ( dns,
"DNS %p got unknown record type %d\n",
848 DBGC ( dns,
"DNS %p found no AAAA record; trying A\n", dns );
858 DBGC ( dns,
"DNS %p found no A record; trying CNAME\n", dns );
879 DBGC ( dns,
"DNS %p found no CNAME record\n", dns );
888 DBGC ( dns,
"DNS %p found no CNAME record; trying next " 938 ( sizeof ( progress->
message ) - 1 ) );
985 DBG (
"DNS not attempting to resolve \"%s\": " 986 "no DNS servers\n",
name );
988 goto err_no_nameserver;
995 dns =
zalloc (
sizeof ( *dns ) + search_len );
1005 dns->
search.
data = ( ( (
void * ) dns ) +
sizeof ( *dns ) );
1021 if ( name_len < 0 ) {
1033 DBGC ( dns,
"DNS %p could not open socket: %s\n",
1035 goto err_open_socket;
1080 char *buf,
size_t len ) {
1082 .data = ( (
void * )
raw ),
1085 size_t remaining =
len;
1092 remaining = ( ( total <
len ) ? (
len - total ) : 0 );
1121 .description =
"DNS server",
1123 .type = &setting_type_ipv4,
1129 .description =
"DNS server",
1131 .type = &setting_type_ipv6,
1138 .description =
"DNS search list",
1140 .type = &setting_type_dnssl,
1189 if ( localdomain ) {
1198 free ( localdomain );
1221 DBGC2 ( dbgcol,
"DNS servers:" );
1225 sizeof (
u.sin6.sin6_addr ) );
1233 DBGC2 ( dbgcol,
"\n" );
1242 DBGC2 ( dbgcol,
"DNS search list:" );
1244 while (
name.offset !=
name.len ) {
1251 DBGC2 ( dbgcol,
"\n" );
struct dns_rr_common common
Common fields.
#define EINVAL
Invalid argument.
An object interface operation.
#define SETTING_IP_EXTRA
IPv4 additional settings.
#define DNS_TYPE_CNAME
Type of a DNS "NAME" record.
size_t offset
Offset of search suffix within current query.
struct arbelprm_rc_send_wqe rc
void intf_close(struct interface *intf, int rc)
Close an object interface.
#define ENXIO_NO_NAMESERVER
#define DNS_MAX_LABEL_LEN
Maximum length of a single DNS label.
static __always_inline void off_t int c
Dynamic Host Configuration Protocol.
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
#define AF_INET6
IPv6 Internet addresses.
struct dns_question * question
Question within current query.
int dns_skip(struct dns_name *name)
Skip RFC1035-encoded DNS name.
#define DHCP_EB_FEATURE_DNS
DNS protocol.
static void apply_dns_servers(void)
Apply DNS server addresses.
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
static void dns_done(struct dns_request *dns, int rc)
Mark DNS request as complete.
const struct settings_scope dhcpv6_scope
IPv6 settings scope.
#define DNS_COMPRESSED_OFFSET(word)
Extract DNS compression pointer.
int xfer_deliver_raw_meta(struct interface *intf, const void *data, size_t len, struct xfer_metadata *meta)
Deliver datagram as raw data.
#define FEATURE_PROTOCOL
Network protocols.
#define DNS_FLAG_RD
Recursion desired flag.
static struct dns_server dns4
IPv4 DNS server list.
static int dns_question(struct dns_request *dns)
Construct DNS question.
int fetch_raw_setting_copy(struct settings *settings, const struct setting *setting, void **data)
Fetch value of setting.
void resolv_done(struct interface *intf, struct sockaddr *sa)
Name resolved.
uint32_t first
First block in range.
#define ref_init(refcnt, free)
Initialise a reference counter.
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
static void dns_timer_expired(struct retry_timer *timer, int fail)
Handle DNS (re)transmission timer expiry.
uint32_t type
Operating system type.
static struct interface_operation dns_socket_operations[]
DNS socket interface operations.
struct in_addr * in
IPv4 addresses.
unsigned int index
Server index.
#define ENOENT
No such file or directory.
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
static void dns_xfer_close(struct dns_request *dns, int rc)
Receive new data.
struct in6_addr in6_addr
IPv6 address.
struct in_addr in_addr
IPv4 address.
unsigned int recursion
Recursion counter.
static const char * dns_name(struct dns_name *name)
Transcribe DNS name (for debugging)
#define offsetof(type, field)
Get offset of a field within a structure.
void * data
Start of data.
unsigned int count
Number of servers.
sa_family_t sin_family
Socket address family (part of struct sockaddr)
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define DNS_PORT
DNS server port.
static unsigned int dns_count
Total number of DNS servers.
#define ELOOP
Too many levels of symbolic links.
static const char * dns_type(uint16_t type)
Name a DNS query type (for debugging)
Data transfer interfaces.
uint32_t start
Starting offset.
struct refcnt refcnt
Reference counter.
static int dns_xfer_deliver(struct dns_request *dns, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive new data.
#define DNS_TYPE_A
Type of a DNS "A" record.
#define ENOMEM
Not enough space.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int dns_progress(struct dns_request *dns, struct job_progress *progress)
Report job progress.
const struct setting_type setting_type_dnssl __setting_type
A DNS search list setting type.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static struct dns_name dns_search
The DNS search list.
#define SETTING_IP4_EXTRA
IPv4 additional settings.
#define container_of(ptr, type, field)
Get containing structure.
uint16_t qtype
Query type.
An RFC1035-encoded DNS name.
struct dns_request::@5 buf
Buffer for current query.
size_t len
Length of current query.
#define __unused
Declare a variable or data structure as unused.
static int tolower(int character)
Convert character to lower case.
Transport-network layer interface.
static int dns_send_packet(struct dns_request *dns)
Send DNS query.
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
size_t offset
Offset of name within data.
#define DNS_TYPE_AAAA
Type of a DNS "AAAA" record.
#define DHCP_DOMAIN_SEARCH
DNS domain search list.
struct interface resolv
Name resolution interface.
Generalized socket address structure.
An object interface descriptor.
char * strerror(int errno)
Retrieve string representation of error number.
static void(* free)(struct refcnt *refcnt))
void * zalloc(size_t size)
Allocate cleared memory.
char * strchr(const char *src, int character)
Find character within a string.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
struct dns_header query
Query header.
int dns_copy(struct dns_name *src, struct dns_name *dst)
Copy a DNS name.
#define ECONNABORTED
Connection aborted.
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
int dns_encode(const char *string, struct dns_name *name)
Encode a DNS name using RFC1035 encoding.
#define DHCPV6_DNS_SERVERS
DHCPv6 DNS recursive name server option.
#define DNS_MAX_CNAME_RECURSION
Maximum depth of CNAME recursion.
struct dns_rr_a a
"A" record
Data transfer interface opening.
static int dns_resolv(struct interface *resolv, const char *name, struct sockaddr *sa)
Resolve name using DNS.
void * malloc(size_t size)
Allocate memory.
static void apply_dns_search(void)
Apply DNS search list.
char message[32]
Message (optional)
void start_timer(struct retry_timer *timer)
Start timer.
#define DNS_MAX_NAME_LEN
Maximum length of a DNS name (mandated by RFC1035 section 2.3.4)
char name[DNS_MAX_NAME_LEN]
Name buffer.
struct in_addr sin_addr
IPv4 address.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
#define DNS_IS_COMPRESSED(byte)
Test for a DNS compression pointer.
void stop_timer(struct retry_timer *timer)
Stop timer.
struct interface socket
Data transfer interface.
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
uint16_t qclass
Query class.
struct dns_rr_aaaa aaaa
"AAAA" record
static struct interface_descriptor dns_socket_desc
DNS socket interface descriptor.
static struct interface_operation dns_resolv_op[]
DNS resolver interface operations.
static int format_dnssl_setting(const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len)
Format DNS search list setting.
#define SETTING_IP6_EXTRA
IPv6 additional settings.
static int dns_skip_search(struct dns_name *name)
Skip RFC1035-encoded DNS name in search list.
void * data
Start of data.
struct dns_name search
Search list.
#define DNS_CLASS_IN
DNS class "IN".
struct retry_timer timer
Retry timer.
struct resolver dns_resolver __resolver(RESOLV_NORMAL)
DNS name resolver.
uint16_t qtype
Initial query type.
static int apply_dns_settings(void)
Apply DNS settings.
uint32_t end
Ending offset.
uint8_t data[48]
Additional event data.
int dns_compare(struct dns_name *first, struct dns_name *second)
Compare DNS names for equality.
const char * name
Name of this resolver (e.g.
#define DHCP_DNS_SERVERS
DNS servers.
static int dns_label(struct dns_name *name, size_t offset)
Find start of valid label within an RFC1035-encoded DNS name.
struct settings_applicator dns_applicator __settings_applicator
DNS settings applicator.
static struct interface_descriptor dns_resolv_desc
DNS resolver interface descriptor.
int(* apply)(void)
Apply updated settings.
int resolv(struct interface *resolv, const char *name, struct sockaddr *sa)
Start name resolution.
int dns_decode(struct dns_name *name, char *data, size_t len)
Decode RFC1035-encoded DNS name.
uint16_t offset
Offset to command line.
sa_family_t sin6_family
Socket address family (part of struct sockaddr)
typeof(acpi_finder=acpi_find)
ACPI table finder.
FEATURE(FEATURE_PROTOCOL, "DNS", DHCP_EB_FEATURE_DNS, 1)
size_t len
Total length of data.
#define DBG(...)
Print a debugging message.
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
#define NULL
NULL pointer (VOID *)
struct in6_addr * in6
IPv6 addresses.
const struct setting dns_setting __setting(SETTING_IP4_EXTRA, dns)
IPv4 DNS server setting.
#define ETIMEDOUT
Connection timed out.
static __always_inline int off_t userptr_t second
union dns_request::@4 address
Socket address to fill in with resolved address.
uint16_t rdlength
Resource data length.
struct bofm_section_header done
#define AF_INET
IPv4 Internet addresses.
struct in6_addr sin6_addr
IPv6 address.
struct dns_question padding
Space for question.
static struct dns_server dns6
IPv6 DNS server list.
#define ref_put(refcnt)
Drop reference to object.
Dynamic Host Configuration Protocol for IPv6.
struct dns_rr_cname cname
"CNAME" record
void * memset(void *dest, int character, size_t len) __nonnull
#define RESOLV_NORMAL
Normal resolver priority.
static void dns_resolved(struct dns_request *dns)
Mark DNS request as resolved and complete.