60 #define ENXIO_NO_RECORD __einfo_error ( EINFO_ENXIO_NO_RECORD ) 61 #define EINFO_ENXIO_NO_RECORD \ 62 __einfo_uniqify ( EINFO_ENXIO, 0x01, "DNS name does not exist" ) 63 #define ENXIO_NO_NAMESERVER __einfo_error ( EINFO_ENXIO_NO_NAMESERVER ) 64 #define EINFO_ENXIO_NO_NAMESERVER \ 65 __einfo_uniqify ( EINFO_ENXIO, 0x02, "No DNS servers available" ) 109 while ( ( c = *(
string++) ) ) {
115 if ( (
len == 0 ) && ( dst !=
start ) )
119 if ( *
string ==
'\0' )
153 return ( dst -
start );
172 if ( (
offset +
sizeof ( *
byte) ) >
name->len )
218 unsigned int recursion_limit =
name->len;
221 size_t decoded_len = 0;
225 while ( recursion_limit-- ) {
234 label_len = *(
label++);
235 if ( label_len == 0 ) {
236 if ( decoded_len <
len )
242 if ( decoded_len && ( decoded_len++ <
len ) )
246 copy_len = ( ( decoded_len <
len ) ? (
len - decoded_len ) : 0);
247 if ( copy_len > label_len )
248 copy_len = label_len;
251 decoded_len += label_len;
254 offset += (
sizeof ( *label ) + label_len );
269 unsigned int recursion_limit =
first->len;
270 int first_offset =
first->offset;
271 int second_offset = second->
offset;
277 while ( recursion_limit-- ) {
281 if ( first_offset < 0 )
283 second_offset =
dns_label ( second, second_offset );
284 if ( second_offset < 0 )
285 return second_offset;
288 first_label = (
first->data + first_offset );
289 second_label = ( second->
data + second_offset );
290 label_len = *(first_label++);
291 if ( label_len != *(second_label++) )
293 len = (
sizeof ( *first_label ) + label_len );
296 if ( label_len == 0 )
300 while ( label_len-- ) {
301 if (
tolower ( *(first_label++) ) !=
302 tolower ( *(second_label++) ) )
308 second_offset +=
len;
323 unsigned int recursion_limit =
src->len;
324 int src_offset =
src->offset;
325 size_t dst_offset = dst->
offset;
331 while ( recursion_limit-- ) {
335 if ( src_offset < 0 )
341 len = (
sizeof ( *label ) + label_len );
342 copy_len = ( ( dst_offset < dst->
len ) ?
343 ( dst->
len - dst_offset ) : 0 );
344 if ( copy_len >
len )
351 if ( label_len == 0 )
352 return ( dst_offset - dst->
offset );
366 unsigned int recursion_limit =
name->len;
372 while ( recursion_limit-- ) {
381 if (
offset != prev_offset )
382 return ( prev_offset +
sizeof (
uint16_t ) );
387 offset += (
sizeof ( *label ) + label_len );
390 if ( label_len == 0 )
430 static char buf[256];
434 return ( (
len < 0 ) ?
"<INVALID>" : buf );
448 default:
return "<UNKNOWN>";
520 DBGC ( dns,
"DNS %p found address %s\n",
537 static struct dns_name search_root = {
547 search = &search_root;
558 DBGC ( dns,
"DNS %p name is too long\n", dns );
576 DBGC2 ( dns,
"DNS %p question is %s type %s\n", dns,
603 memset ( &nameserver, 0,
sizeof ( nameserver ) );
606 DBGC ( dns,
"DNS %p lost DNS servers mid query\n", dns );
611 nameserver.sin6.sin6_family =
AF_INET6;
613 sizeof ( nameserver.sin6.sin6_addr ) );
615 nameserver.sin.sin_family =
AF_INET;
621 meta.dest = &nameserver.sa;
628 DBGC ( dns,
"DNS %p sending %s query ID %#04x for %s type %s\n", dns,
677 size_t answer_offset;
684 if (
iob_len ( iobuf ) <
sizeof ( *response ) ) {
685 DBGC ( dns,
"DNS %p received underlength packet length %zd\n",
692 if ( response->
id != query->
id ) {
693 DBGC ( dns,
"DNS %p received unexpected response ID %#04x " 694 "(wanted %d)\n", dns,
ntohs ( response->
id ),
699 DBGC ( dns,
"DNS %p received response ID %#04x\n",
704 DBGC ( dns,
"DNS %p received response with %d questions\n",
712 buf.
offset =
sizeof ( *response );
717 DBGC ( dns,
"DNS %p received response with malformed " 729 buf.
offset = next_offset ) {
735 DBGC ( dns,
"DNS %p received response with malformed " 743 DBGC ( dns,
"DNS %p received response with underlength " 749 next_offset = (
offset +
sizeof ( rr->
common ) + rdlength );
750 if ( next_offset > buf.
len ) {
751 DBGC ( dns,
"DNS %p received response with underlength " 759 DBGC2 ( dns,
"DNS %p ignoring response for %s type " 772 DBGC ( dns,
"DNS %p received response with " 773 "underlength AAAA\n", dns );
789 DBGC ( dns,
"DNS %p received response with " 790 "underlength A\n", dns );
804 DBGC ( dns,
"DNS %p recursion exceeded\n",
813 DBGC ( dns,
"DNS %p found CNAME %s\n",
823 next_offset = answer_offset;
827 DBGC ( dns,
"DNS %p got unknown record type %d\n",
849 DBGC ( dns,
"DNS %p found no AAAA record; trying A\n", dns );
859 DBGC ( dns,
"DNS %p found no A record; trying CNAME\n", dns );
880 DBGC ( dns,
"DNS %p found no CNAME record\n", dns );
889 DBGC ( dns,
"DNS %p found no CNAME record; trying next " 939 ( sizeof ( progress->
message ) - 1 ) );
986 DBG (
"DNS not attempting to resolve \"%s\": " 987 "no DNS servers\n",
name );
989 goto err_no_nameserver;
996 dns =
zalloc (
sizeof ( *dns ) + search_len );
1006 dns->
search.
data = ( ( (
void * ) dns ) +
sizeof ( *dns ) );
1022 if ( name_len < 0 ) {
1034 DBGC ( dns,
"DNS %p could not open socket: %s\n",
1036 goto err_open_socket;
1081 char *buf,
size_t len ) {
1083 .data = ( (
void * )
raw ),
1086 size_t remaining =
len;
1093 remaining = ( ( total <
len ) ? (
len - total ) : 0 );
1122 .description =
"DNS server",
1124 .type = &setting_type_ipv4,
1130 .description =
"DNS server",
1132 .type = &setting_type_ipv6,
1139 .description =
"DNS search list",
1141 .type = &setting_type_dnssl,
1190 if ( localdomain ) {
1199 free ( localdomain );
1222 DBGC2 ( dbgcol,
"DNS servers:" );
1226 sizeof (
u.sin6.sin6_addr ) );
1234 DBGC2 ( dbgcol,
"\n" );
1243 DBGC2 ( dbgcol,
"DNS search list:" );
1245 while (
name.offset !=
name.len ) {
1252 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.
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.
sa_family_t sin6_family
Socket address family (part of struct sockaddr)
typeof(acpi_finder=acpi_find)
ACPI table finder.
uint16_t offset
Offset to command line.
uint8_t meta
Metadata flags.
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.
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.