iPXE
dns.c File Reference

DNS protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/refcnt.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/resolv.h>
#include <ipxe/retry.h>
#include <ipxe/tcpip.h>
#include <ipxe/settings.h>
#include <ipxe/features.h>
#include <ipxe/job.h>
#include <ipxe/dhcp.h>
#include <ipxe/dhcpv6.h>
#include <ipxe/dns.h>

Go to the source code of this file.

Data Structures

struct  dns_server
 A DNS server list. More...
struct  dns_request
 A DNS request. More...

Macros

#define ENXIO_NO_RECORD   __einfo_error ( EINFO_ENXIO_NO_RECORD )
#define EINFO_ENXIO_NO_RECORD   __einfo_uniqify ( EINFO_ENXIO, 0x01, "DNS name does not exist" )
#define ENXIO_NO_NAMESERVER   __einfo_error ( EINFO_ENXIO_NO_NAMESERVER )
#define EINFO_ENXIO_NO_NAMESERVER   __einfo_uniqify ( EINFO_ENXIO, 0x02, "No DNS servers available" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
 FEATURE (FEATURE_PROTOCOL, "DNS", DHCP_EB_FEATURE_DNS, 1)
int dns_encode (const char *string, struct dns_name *name)
 Encode a DNS name using RFC1035 encoding.
static int dns_label (struct dns_name *name, size_t offset)
 Find start of valid label within an RFC1035-encoded DNS name.
int dns_decode (struct dns_name *name, char *data, size_t len)
 Decode RFC1035-encoded DNS name.
int dns_compare (struct dns_name *first, struct dns_name *second)
 Compare DNS names for equality.
int dns_copy (struct dns_name *src, struct dns_name *dst)
 Copy a DNS name.
int dns_skip (struct dns_name *name)
 Skip RFC1035-encoded DNS name.
static int dns_skip_search (struct dns_name *name)
 Skip RFC1035-encoded DNS name in search list.
static const char * dns_name (struct dns_name *name)
 Transcribe DNS name (for debugging).
static const char * dns_type (uint16_t type)
 Name a DNS query type (for debugging).
static void dns_done (struct dns_request *dns, int rc)
 Mark DNS request as complete.
static void dns_resolved (struct dns_request *dns)
 Mark DNS request as resolved and complete.
static int dns_question (struct dns_request *dns)
 Construct DNS question.
static int dns_send_packet (struct dns_request *dns)
 Send DNS query.
static void dns_timer_expired (struct retry_timer *timer, int fail)
 Handle DNS (re)transmission timer expiry.
static int dns_xfer_deliver (struct dns_request *dns, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Receive new data.
static void dns_xfer_close (struct dns_request *dns, int rc)
 Receive new data.
static int dns_progress (struct dns_request *dns, struct job_progress *progress)
 Report job progress.
static int dns_resolv (struct interface *resolv, const char *name, struct sockaddr *sa)
 Resolve name using DNS.
struct resolver dns_resolver __resolver (RESOLV_NORMAL)
 DNS name resolver.
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.
const struct setting dns_setting __setting (SETTING_IP4_EXTRA, dns)
 IPv4 DNS server setting.
const struct setting dns6_setting __setting (SETTING_IP6_EXTRA, dns6)
 IPv6 DNS server setting.
const struct setting dnssl_setting __setting (SETTING_IP_EXTRA, dnssl)
 DNS search list.
static void apply_dns_servers (void)
 Apply DNS server addresses.
static void apply_dns_search (void)
 Apply DNS search list.
static int apply_dns_settings (void)
 Apply DNS settings.

Variables

static struct dns_server dns4
 IPv4 DNS server list.
static struct dns_server dns6
 IPv6 DNS server list.
static unsigned int dns_count
 Total number of DNS servers.
static struct dns_name dns_search
 The DNS search list.
static struct interface_operation dns_socket_operations []
 DNS socket interface operations.
static struct interface_descriptor dns_socket_desc
 DNS socket interface descriptor.
static struct interface_operation dns_resolv_op []
 DNS resolver interface operations.
static struct interface_descriptor dns_resolv_desc
 DNS resolver interface descriptor.
const struct setting_type setting_type_dnssl __setting_type
 A DNS search list setting type.
struct settings_applicator dns_applicator __settings_applicator
 DNS settings applicator.

Detailed Description

DNS protocol.

Definition in file dns.c.

Macro Definition Documentation

◆ ENXIO_NO_RECORD

#define ENXIO_NO_RECORD   __einfo_error ( EINFO_ENXIO_NO_RECORD )

Definition at line 60 of file dns.c.

◆ EINFO_ENXIO_NO_RECORD

#define EINFO_ENXIO_NO_RECORD   __einfo_uniqify ( EINFO_ENXIO, 0x01, "DNS name does not exist" )

Definition at line 61 of file dns.c.

61#define EINFO_ENXIO_NO_RECORD \
62 __einfo_uniqify ( EINFO_ENXIO, 0x01, "DNS name does not exist" )

◆ ENXIO_NO_NAMESERVER

#define ENXIO_NO_NAMESERVER   __einfo_error ( EINFO_ENXIO_NO_NAMESERVER )

Definition at line 63 of file dns.c.

Referenced by dns_resolv().

◆ EINFO_ENXIO_NO_NAMESERVER

#define EINFO_ENXIO_NO_NAMESERVER   __einfo_uniqify ( EINFO_ENXIO, 0x02, "No DNS servers available" )

Definition at line 64 of file dns.c.

64#define EINFO_ENXIO_NO_NAMESERVER \
65 __einfo_uniqify ( EINFO_ENXIO, 0x02, "No DNS servers available" )

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ FEATURE()

FEATURE ( FEATURE_PROTOCOL ,
"DNS" ,
DHCP_EB_FEATURE_DNS ,
1  )

◆ dns_encode()

int dns_encode ( const char * string,
struct dns_name * name )

Encode a DNS name using RFC1035 encoding.

Parameters
stringDNS name as a string
nameDNS name to fill in
Return values
lenLength of DNS name, or negative error

Definition at line 101 of file dns.c.

101 {
102 uint8_t *start = ( name->data + name->offset );
103 uint8_t *end = ( name->data + name->len );
104 uint8_t *dst = start;
105 size_t len = 0;
106 char c;
107
108 /* Encode name */
109 while ( ( c = *(string++) ) ) {
110
111 /* Handle '.' separators */
112 if ( c == '.' ) {
113
114 /* Reject consecutive '.' */
115 if ( ( len == 0 ) && ( dst != start ) )
116 return -EINVAL;
117
118 /* Terminate if this is the trailing '.' */
119 if ( *string == '\0' )
120 break;
121
122 /* Reject initial non-terminating '.' */
123 if ( len == 0 )
124 return -EINVAL;
125
126 /* Reset length */
127 len = 0;
128
129 } else {
130
131 /* Increment length */
132 len++;
133
134 /* Check for overflow */
135 if ( len > DNS_MAX_LABEL_LEN )
136 return -EINVAL;
137 }
138
139 /* Copy byte, update length */
140 if ( ++dst < end ) {
141 *dst = c;
142 dst[-len] = len;
143 }
144 }
145
146 /* Add terminating root marker */
147 if ( len )
148 dst++;
149 if ( dst < end )
150 *dst = '\0';
151 dst++;
152
153 return ( dst - start );
154}
unsigned char uint8_t
Definition stdint.h:10
const char * name
Definition ath9k_hw.c:1986
#define DNS_MAX_LABEL_LEN
Maximum length of a single DNS label.
Definition dns.h:54
ring len
Length.
Definition dwmac.h:226
uint32_t start
Starting offset.
Definition netvsc.h:1
#define EINVAL
Invalid argument.
Definition errno.h:472
uint32_t end
Ending offset.
Definition netvsc.h:7

References DNS_MAX_LABEL_LEN, EINVAL, end, len, name, and start.

Referenced by apply_dns_search(), dns_encode_fail_okx(), dns_encode_okx(), and dns_resolv().

◆ dns_label()

int dns_label ( struct dns_name * name,
size_t offset )
static

Find start of valid label within an RFC1035-encoded DNS name.

Parameters
nameDNS name
offsetCurrent offset
Return values
offsetOffset of label, or negative error

Definition at line 163 of file dns.c.

163 {
164 const uint8_t *byte;
165 const uint16_t *word;
166 size_t len;
167 size_t ptr;
168
169 while ( 1 ) {
170
171 /* Fail if we have overrun the DNS name */
172 if ( ( offset + sizeof ( *byte) ) > name->len )
173 return -EINVAL;
174 byte = ( name->data + offset );
175
176 /* Follow compression pointer, if applicable */
177 if ( DNS_IS_COMPRESSED ( *byte ) ) {
178
179 /* Fail if we have overrun the DNS name */
180 if ( ( offset + sizeof ( *word ) ) > name->len )
181 return -EINVAL;
182 word = ( name->data + offset );
183
184 /* Extract pointer to new offset */
185 ptr = DNS_COMPRESSED_OFFSET ( ntohs ( *word ) );
186
187 /* Fail if pointer does not point backwards.
188 * (This guarantees termination of the
189 * function.)
190 */
191 if ( ptr >= offset )
192 return -EINVAL;
193
194 /* Continue from new offset */
195 offset = ptr;
196 continue;
197 }
198
199 /* Fail if we have overrun the DNS name */
200 len = *byte;
201 if ( ( offset + sizeof ( *byte ) + len ) > name->len )
202 return -EINVAL;
203
204 /* We have a valid label */
205 return offset;
206 }
207}
unsigned short uint16_t
Definition stdint.h:11
uint16_t offset
Offset to command line.
Definition bzimage.h:3
#define DNS_COMPRESSED_OFFSET(word)
Extract DNS compression pointer.
Definition dns.h:43
#define DNS_IS_COMPRESSED(byte)
Test for a DNS compression pointer.
Definition dns.h:35
#define ntohs(value)
Definition byteswap.h:137
unsigned char byte
Definition smc9000.h:38
unsigned short word
Definition smc9000.h:39

References DNS_COMPRESSED_OFFSET, DNS_IS_COMPRESSED, EINVAL, len, name, ntohs, and offset.

Referenced by dns_compare(), dns_copy(), dns_decode(), and dns_skip().

◆ dns_decode()

int dns_decode ( struct dns_name * name,
char * data,
size_t len )

Decode RFC1035-encoded DNS name.

Parameters
nameDNS name
dataOutput buffer
lenLength of output buffer
Return values
lenLength of decoded DNS name, or negative error

Definition at line 217 of file dns.c.

217 {
218 unsigned int recursion_limit = name->len; /* Generous upper bound */
219 int offset = name->offset;
220 const uint8_t *label;
221 size_t decoded_len = 0;
222 size_t label_len;
223 size_t copy_len;
224
225 while ( recursion_limit-- ) {
226
227 /* Find valid DNS label */
229 if ( offset < 0 )
230 return offset;
231
232 /* Terminate if we have reached the root */
233 label = ( name->data + offset );
234 label_len = *(label++);
235 if ( label_len == 0 ) {
236 if ( decoded_len < len )
237 *data = '\0';
238 return decoded_len;
239 }
240
241 /* Prepend '.' if applicable */
242 if ( decoded_len && ( decoded_len++ < len ) )
243 *(data++) = '.';
244
245 /* Copy label to output buffer */
246 copy_len = ( ( decoded_len < len ) ? ( len - decoded_len ) : 0);
247 if ( copy_len > label_len )
248 copy_len = label_len;
249 memcpy ( data, label, copy_len );
250 data += copy_len;
251 decoded_len += label_len;
252
253 /* Move to next label */
254 offset += ( sizeof ( *label ) + label_len );
255 }
256
257 /* Recursion limit exceeded */
258 return -EINVAL;
259}
static int dns_label(struct dns_name *name, size_t offset)
Find start of valid label within an RFC1035-encoded DNS name.
Definition dns.c:163
uint8_t data[48]
Additional event data.
Definition ena.h:11
void * memcpy(void *dest, const void *src, size_t len) __nonnull
A text label widget.
Definition label.h:16

References data, dns_label(), EINVAL, len, memcpy(), name, and offset.

Referenced by dns_decode_fail_okx(), dns_decode_okx(), dns_list_okx(), dns_name(), dns_progress(), and format_dnssl_setting().

◆ dns_compare()

int dns_compare ( struct dns_name * first,
struct dns_name * second )

Compare DNS names for equality.

Parameters
firstFirst DNS name
secondSecond DNS name
Return values
rcReturn status code

Definition at line 268 of file dns.c.

268 {
269 unsigned int recursion_limit = first->len; /* Generous upper bound */
270 int first_offset = first->offset;
271 int second_offset = second->offset;
272 const uint8_t *first_label;
273 const uint8_t *second_label;
274 size_t label_len;
275 size_t len;
276
277 while ( recursion_limit-- ) {
278
279 /* Find valid DNS labels */
280 first_offset = dns_label ( first, first_offset );
281 if ( first_offset < 0 )
282 return first_offset;
283 second_offset = dns_label ( second, second_offset );
284 if ( second_offset < 0 )
285 return second_offset;
286
287 /* Compare label lengths */
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++) )
292 return -ENOENT;
293 len = ( sizeof ( *first_label ) + label_len );
294
295 /* Terminate if we have reached the root */
296 if ( label_len == 0 )
297 return 0;
298
299 /* Compare label contents (case-insensitively) */
300 while ( label_len-- ) {
301 if ( tolower ( *(first_label++) ) !=
302 tolower ( *(second_label++) ) )
303 return -ENOENT;
304 }
305
306 /* Move to next labels */
307 first_offset += len;
308 second_offset += len;
309 }
310
311 /* Recursion limit exceeded */
312 return -EINVAL;
313}
static int tolower(int character)
Convert character to lower case.
Definition ctype.h:109
#define ENOENT
No such file or directory.
Definition errno.h:558
uint32_t first
First block in range.
Definition pccrr.h:1
size_t offset
Offset of name within data.
Definition dns.h:24
void * data
Start of data.
Definition dns.h:22

References dns_name::data, dns_label(), EINVAL, ENOENT, first, len, dns_name::offset, and tolower().

Referenced by dns_compare_fail_okx(), dns_compare_okx(), and dns_xfer_deliver().

◆ dns_copy()

int dns_copy ( struct dns_name * src,
struct dns_name * dst )

Copy a DNS name.

Parameters
srcSource DNS name
dstDestination DNS name
Return values
lenLength of copied DNS name, or negative error

Definition at line 322 of file dns.c.

322 {
323 unsigned int recursion_limit = src->len; /* Generous upper bound */
324 int src_offset = src->offset;
325 size_t dst_offset = dst->offset;
326 const uint8_t *label;
327 size_t label_len;
328 size_t copy_len;
329 size_t len;
330
331 while ( recursion_limit-- ) {
332
333 /* Find valid DNS label */
334 src_offset = dns_label ( src, src_offset );
335 if ( src_offset < 0 )
336 return src_offset;
337
338 /* Copy as an uncompressed label */
339 label = ( src->data + src_offset );
340 label_len = *label;
341 len = ( sizeof ( *label ) + label_len );
342 copy_len = ( ( dst_offset < dst->len ) ?
343 ( dst->len - dst_offset ) : 0 );
344 if ( copy_len > len )
345 copy_len = len;
346 memcpy ( ( dst->data + dst_offset ), label, copy_len );
347 src_offset += len;
348 dst_offset += len;
349
350 /* Terminate if we have reached the root */
351 if ( label_len == 0 )
352 return ( dst_offset - dst->offset );
353 }
354
355 /* Recursion limit exceeded */
356 return -EINVAL;
357}
static const void * src
Definition string.h:48
size_t len
Total length of data.
Definition dns.h:26

References dns_name::data, dns_label(), EINVAL, dns_name::len, len, memcpy(), dns_name::offset, and src.

Referenced by dns_copy_fail_okx(), dns_copy_okx(), dns_question(), and dns_xfer_deliver().

◆ dns_skip()

int dns_skip ( struct dns_name * name)

Skip RFC1035-encoded DNS name.

Parameters
nameDNS name
Return values
offsetOffset to next name, or negative error

Definition at line 365 of file dns.c.

365 {
366 unsigned int recursion_limit = name->len; /* Generous upper bound */
367 int offset = name->offset;
368 int prev_offset;
369 const uint8_t *label;
370 size_t label_len;
371
372 while ( recursion_limit-- ) {
373
374 /* Find valid DNS label */
375 prev_offset = offset;
376 offset = dns_label ( name, prev_offset );
377 if ( offset < 0 )
378 return offset;
379
380 /* Terminate if we have reached a compression pointer */
381 if ( offset != prev_offset )
382 return ( prev_offset + sizeof ( uint16_t ) );
383
384 /* Skip this label */
385 label = ( name->data + offset );
386 label_len = *label;
387 offset += ( sizeof ( *label ) + label_len );
388
389 /* Terminate if we have reached the root */
390 if ( label_len == 0 )
391 return offset;
392 }
393
394 /* Recursion limit exceeded */
395 return -EINVAL;
396}

References dns_label(), EINVAL, name, and offset.

Referenced by dns_list_okx(), dns_skip_search(), and dns_xfer_deliver().

◆ dns_skip_search()

int dns_skip_search ( struct dns_name * name)
static

Skip RFC1035-encoded DNS name in search list.

Parameters
nameDNS name
Return values
offsetOffset to next non-empty name, or negative error

Definition at line 404 of file dns.c.

404 {
405 int offset;
406
407 /* Find next name */
408 offset = dns_skip ( name );
409 if ( offset < 0 )
410 return offset;
411
412 /* Skip over any subsequent empty names (e.g. due to padding
413 * bytes used in the NDP DNSSL option).
414 */
415 while ( ( offset < ( ( int ) name->len ) ) &&
416 ( *( ( uint8_t * ) ( name->data + offset ) ) == 0 ) ) {
417 offset++;
418 }
419
420 return offset;
421}
int dns_skip(struct dns_name *name)
Skip RFC1035-encoded DNS name.
Definition dns.c:365

References dns_skip(), name, and offset.

Referenced by apply_dns_settings(), and format_dnssl_setting().

◆ dns_name()

const char * dns_name ( struct dns_name * name)
static

Transcribe DNS name (for debugging).

Parameters
nameDNS name
Return values
stringTranscribed DNS name

Definition at line 429 of file dns.c.

429 {
430 static char buf[256];
431 int len;
432
433 len = dns_decode ( name, buf, ( sizeof ( buf ) - 1 /* NUL */ ) );
434 return ( ( len < 0 ) ? "<INVALID>" : buf );
435}
int dns_decode(struct dns_name *name, char *data, size_t len)
Decode RFC1035-encoded DNS name.
Definition dns.c:217

References dns_decode(), len, and name.

◆ dns_type()

const char * dns_type ( uint16_t type)
static

Name a DNS query type (for debugging).

Parameters
typeQuery type (in network byte order)
Return values
nameType name

Definition at line 443 of file dns.c.

443 {
444 switch ( type ) {
445 case htons ( DNS_TYPE_A ): return "A";
446 case htons ( DNS_TYPE_AAAA ): return "AAAA";
447 case htons ( DNS_TYPE_CNAME ): return "CNAME";
448 default: return "<UNKNOWN>";
449 }
450}
#define DNS_TYPE_CNAME
Type of a DNS "NAME" record.
Definition dns.h:130
#define DNS_TYPE_AAAA
Type of a DNS "AAAA" record.
Definition dns.h:119
#define DNS_TYPE_A
Type of a DNS "A" record.
Definition dns.h:108
uint32_t type
Operating system type.
Definition ena.h:1
#define htons(value)
Definition byteswap.h:136
return
Definition natsemi.h:326

References DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_CNAME, htons, and type.

Referenced by dns_question(), and dns_send_packet().

◆ dns_done()

void dns_done ( struct dns_request * dns,
int rc )
static

Mark DNS request as complete.

Parameters
dnsDNS request
rcReturn status code

Definition at line 509 of file dns.c.

509 {
510
511 /* Stop the retry timer */
512 stop_timer ( &dns->timer );
513
514 /* Shut down interfaces */
515 intf_shutdown ( &dns->socket, rc );
516 intf_shutdown ( &dns->resolv, rc );
517}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
struct retry_timer timer
Retry timer.
Definition dns.c:461
struct interface resolv
Name resolution interface.
Definition dns.c:457
struct interface socket
Data transfer interface.
Definition dns.c:459

References intf_shutdown(), rc, dns_request::resolv, dns_request::socket, stop_timer(), and dns_request::timer.

Referenced by dns_resolved(), dns_timer_expired(), dns_xfer_close(), and dns_xfer_deliver().

◆ dns_resolved()

void dns_resolved ( struct dns_request * dns)
static

Mark DNS request as resolved and complete.

Parameters
dnsDNS request
rcReturn status code

Definition at line 525 of file dns.c.

525 {
526
527 DBGC ( dns, "DNS %p found address %s\n",
528 dns, sock_ntoa ( &dns->address.sa ) );
529
530 /* Return resolved address */
531 resolv_done ( &dns->resolv, &dns->address.sa );
532
533 /* Mark operation as complete */
534 dns_done ( dns, 0 );
535}
static void dns_done(struct dns_request *dns, int rc)
Mark DNS request as complete.
Definition dns.c:509
#define DBGC(...)
Definition compiler.h:530
void resolv_done(struct interface *intf, struct sockaddr *sa)
Name resolved.
Definition resolv.c:56
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition socket.c:43
struct sockaddr sa
Definition dns.c:465
union dns_request::@312034134017066265334376202135341175127303247071 address
Socket address to fill in with resolved address.

References dns_request::address, DBGC, dns_done(), dns_request::resolv, resolv_done(), dns_request::sa, and sock_ntoa().

Referenced by dns_xfer_deliver().

◆ dns_question()

int dns_question ( struct dns_request * dns)
static

Construct DNS question.

Parameters
dnsDNS request
Return values
rcReturn status code

Definition at line 543 of file dns.c.

543 {
544 static struct dns_name search_root = {
545 .data = "",
546 .len = 1,
547 };
548 struct dns_name *search = &dns->search;
549 int len;
550 size_t offset;
551
552 /* Use root suffix if search list is empty */
553 if ( search->offset == search->len )
554 search = &search_root;
555
556 /* Overwrite current suffix */
557 dns->name.offset = dns->offset;
558 len = dns_copy ( search, &dns->name );
559 if ( len < 0 )
560 return len;
561
562 /* Sanity check */
563 offset = ( dns->name.offset + len );
564 if ( offset > dns->name.len ) {
565 DBGC ( dns, "DNS %p name is too long\n", dns );
566 return -EINVAL;
567 }
568
569 /* Construct question */
570 dns->question = ( ( ( void * ) &dns->buf ) + offset );
571 dns->question->qtype = dns->qtype;
572 dns->question->qclass = htons ( DNS_CLASS_IN );
573
574 /* Store length */
575 dns->len = ( offset + sizeof ( *(dns->question) ) );
576
577 /* Restore name */
578 dns->name.offset = offsetof ( typeof ( dns->buf ), name );
579
580 /* Reset query ID */
581 dns->buf.query.id = 0;
582
583 DBGC2 ( dns, "DNS %p question is %s type %s\n", dns,
584 dns_name ( &dns->name ), dns_type ( dns->question->qtype ) );
585
586 return 0;
587}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
static const char * dns_type(uint16_t type)
Name a DNS query type (for debugging).
Definition dns.c:443
int dns_copy(struct dns_name *src, struct dns_name *dst)
Copy a DNS name.
Definition dns.c:322
#define DNS_CLASS_IN
DNS class "IN".
Definition dns.h:93
#define DBGC2(...)
Definition compiler.h:547
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
uint16_t id
Query identifier.
Definition dns.h:68
An RFC1035-encoded DNS name.
Definition dns.h:20
uint16_t qtype
Query type.
Definition dns.h:87
uint16_t qclass
Query class.
Definition dns.h:89
struct dns_name search
Search list.
Definition dns.c:496
uint16_t qtype
Initial query type.
Definition dns.c:477
struct dns_request::@271067130201152012154144344366021327072122275232 buf
Buffer for current query.
size_t offset
Offset of search suffix within current query.
Definition dns.c:494
struct dns_question * question
Question within current query.
Definition dns.c:490
struct dns_header query
Query header.
Definition dns.c:481
size_t len
Length of current query.
Definition dns.c:492
char name[DNS_MAX_NAME_LEN]
Name buffer.
Definition dns.c:483

References dns_request::buf, DBGC, DBGC2, DNS_CLASS_IN, dns_copy(), dns_type(), EINVAL, htons, dns_header::id, dns_name::len, dns_request::len, len, dns_request::name, name, dns_name::offset, dns_request::offset, offset, offsetof, dns_question::qclass, dns_question::qtype, dns_request::qtype, dns_request::query, dns_request::question, dns_request::search, and typeof().

◆ dns_send_packet()

int dns_send_packet ( struct dns_request * dns)
static

Send DNS query.

Parameters
dnsDNS request
Return values
rcReturn status code

Definition at line 595 of file dns.c.

595 {
596 struct dns_header *query = &dns->buf.query;
597 struct xfer_metadata meta;
598 unsigned int index;
599
600 /* Start retransmission timer */
601 start_timer ( &dns->timer );
602
603 /* Construct DNS server address */
604 memset ( &dns->nameserver, 0, sizeof ( dns->nameserver ) );
606 if ( ! dns_count ) {
607 DBGC ( dns, "DNS %p lost DNS servers mid query\n", dns );
608 return -EINVAL;
609 }
610 index = ( dns->index % dns_count );
611 if ( index < dns6.count ) {
613 memcpy ( &dns->nameserver.sin6.sin6_addr, &dns6.in6[index],
614 sizeof ( dns->nameserver.sin6.sin6_addr ) );
615 } else {
617 dns->nameserver.sin.sin_addr = dns4.in[index - dns6.count];
618 }
619
620 /* Construct metadata */
621 memset ( &meta, 0, sizeof ( meta ) );
622 meta.dest = &dns->nameserver.sa;
623
624 /* Generate query identifier if applicable */
625 if ( ! query->id )
626 query->id = random();
627
628 /* Send query */
629 DBGC ( dns, "DNS %p sending %s query ID %#04x for %s type %s\n", dns,
630 sock_ntoa ( &dns->nameserver.sa ), ntohs ( query->id ),
631 dns_name ( &dns->name ), dns_type ( dns->question->qtype ) );
632
633 /* Send the data */
634 return xfer_deliver_raw_meta ( &dns->socket, query, dns->len, &meta );
635}
long index
Definition bigint.h:30
static unsigned int dns_count
Total number of DNS servers.
Definition dns.c:89
static struct dns_server dns6
IPv6 DNS server list.
Definition dns.c:86
static struct dns_server dns4
IPv4 DNS server list.
Definition dns.c:83
#define DNS_PORT
DNS server port.
Definition dns.h:17
uint8_t meta
Metadata flags.
Definition ena.h:3
#define AF_INET
IPv4 Internet addresses.
Definition socket.h:64
#define AF_INET6
IPv6 Internet addresses.
Definition socket.h:65
void * memset(void *dest, int character, size_t len) __nonnull
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
void start_timer(struct retry_timer *timer)
Start timer.
Definition retry.c:94
A DNS packet header.
Definition dns.h:66
struct sockaddr_in sin
Definition dns.c:466
struct sockaddr_tcpip st
Definition dns.c:472
struct sockaddr_in6 sin6
Definition dns.c:467
unsigned int index
Server index.
Definition dns.c:498
union dns_request::@313264154177366216076030311163113224373276371112 nameserver
Current name server address.
struct in6_addr sin6_addr
IPv6 address.
Definition in.h:135
sa_family_t sin6_family
Socket address family (part of struct sockaddr).
Definition in.h:123
struct in_addr sin_addr
IPv4 address.
Definition in.h:101
sa_family_t sin_family
Socket address family (part of struct sockaddr).
Definition in.h:90
uint16_t st_port
TCP/IP port.
Definition tcpip.h:82
Data transfer metadata.
Definition xfer.h:23
int xfer_deliver_raw_meta(struct interface *intf, const void *data, size_t len, struct xfer_metadata *meta)
Deliver datagram as raw data.
Definition xfer.c:269

References AF_INET, AF_INET6, dns_request::buf, DBGC, dns4, dns6, dns_count, DNS_PORT, dns_type(), EINVAL, htons, dns_header::id, dns_request::index, index, dns_request::len, memcpy(), memset(), meta, dns_request::name, dns_request::nameserver, ntohs, dns_question::qtype, dns_request::query, dns_request::question, random(), dns_request::sa, dns_request::sin, dns_request::sin6, sockaddr_in6::sin6_addr, sockaddr_in6::sin6_family, sockaddr_in::sin_addr, sockaddr_in::sin_family, sock_ntoa(), dns_request::socket, dns_request::st, sockaddr_tcpip::st_port, start_timer(), dns_request::timer, and xfer_deliver_raw_meta().

Referenced by dns_timer_expired().

◆ dns_timer_expired()

void dns_timer_expired ( struct retry_timer * timer,
int fail )
static

Handle DNS (re)transmission timer expiry.

Parameters
timerRetry timer
failFailure indicator

Definition at line 643 of file dns.c.

643 {
644 struct dns_request *dns =
645 container_of ( timer, struct dns_request, timer );
646
647 /* Terminate DNS request on failure */
648 if ( fail ) {
649 dns_done ( dns, -ETIMEDOUT );
650 return;
651 }
652
653 /* Move to next DNS server if this is a retransmission */
654 if ( dns->buf.query.id )
655 dns->index++;
656
657 /* Send DNS query */
658 dns_send_packet ( dns );
659}
static int dns_send_packet(struct dns_request *dns)
Send DNS query.
Definition dns.c:595
#define ETIMEDOUT
Connection timed out.
Definition errno.h:713
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A DNS request.
Definition dns.c:453
A timer.
Definition timer.h:29

References dns_request::buf, container_of, dns_done(), dns_send_packet(), ETIMEDOUT, dns_header::id, dns_request::index, and dns_request::query.

Referenced by dns_resolv().

◆ dns_xfer_deliver()

int dns_xfer_deliver ( struct dns_request * dns,
struct io_buffer * iobuf,
struct xfer_metadata *meta __unused )
static

Receive new data.

Parameters
dnsDNS request
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 669 of file dns.c.

671 {
672 struct dns_header *query = &dns->buf.query;
673 unsigned int qtype = dns->question->qtype;
674 struct dns_header *response;
675 struct dns_name buf;
676 union dns_rr *rr;
677 int offset;
678 size_t answer_offset;
679 size_t next_offset;
680 size_t rdlength;
681 int name_len;
682 int rc;
683
684 /* Sanity check */
685 if ( iob_len ( iobuf ) < sizeof ( *response ) ) {
686 DBGC ( dns, "DNS %p received underlength packet length %zd\n",
687 dns, iob_len ( iobuf ) );
688 rc = -EINVAL;
689 goto done;
690 }
691 response = iobuf->data;
692
693 /* Check response ID matches query ID */
694 if ( response->id != query->id ) {
695 DBGC ( dns, "DNS %p received unexpected response ID %#04x "
696 "(wanted %d)\n", dns, ntohs ( response->id ),
697 ntohs ( query->id ) );
698 rc = -EINVAL;
699 goto done;
700 }
701 DBGC ( dns, "DNS %p received response ID %#04x\n",
702 dns, ntohs ( response->id ) );
703
704 /* Check that we have exactly one question */
705 if ( response->qdcount != htons ( 1 ) ) {
706 DBGC ( dns, "DNS %p received response with %d questions\n",
707 dns, ntohs ( response->qdcount ) );
708 rc = -EINVAL;
709 goto done;
710 }
711
712 /* Skip question section */
713 buf.data = iobuf->data;
714 buf.offset = sizeof ( *response );
715 buf.len = iob_len ( iobuf );
716 offset = dns_skip ( &buf );
717 if ( offset < 0 ) {
718 rc = offset;
719 DBGC ( dns, "DNS %p received response with malformed "
720 "question: %s\n", dns, strerror ( rc ) );
721 goto done;
722 }
723 answer_offset = ( offset + sizeof ( struct dns_question ) );
724
725 /* Search through response for useful answers. Do this
726 * multiple times, to take advantage of useful nameservers
727 * which send us e.g. the CNAME *and* the A record for the
728 * pointed-to name.
729 */
730 for ( buf.offset = answer_offset ; buf.offset != buf.len ;
731 buf.offset = next_offset ) {
732
733 /* Check for valid name */
734 offset = dns_skip ( &buf );
735 if ( offset < 0 ) {
736 rc = offset;
737 DBGC ( dns, "DNS %p received response with malformed "
738 "answer: %s\n", dns, strerror ( rc ) );
739 goto done;
740 }
741
742 /* Check for sufficient space for resource record */
743 rr = ( buf.data + offset );
744 if ( ( offset + sizeof ( rr->common ) ) > buf.len ) {
745 DBGC ( dns, "DNS %p received response with underlength "
746 "RR\n", dns );
747 rc = -EINVAL;
748 goto done;
749 }
750 rdlength = ntohs ( rr->common.rdlength );
751 next_offset = ( offset + sizeof ( rr->common ) + rdlength );
752 if ( next_offset > buf.len ) {
753 DBGC ( dns, "DNS %p received response with underlength "
754 "RR\n", dns );
755 rc = -EINVAL;
756 goto done;
757 }
758
759 /* Skip non-matching names */
760 if ( dns_compare ( &buf, &dns->name ) != 0 ) {
761 DBGC2 ( dns, "DNS %p ignoring response for %s type "
762 "%s\n", dns, dns_name ( &buf ),
763 dns_type ( rr->common.type ) );
764 continue;
765 }
766
767 /* Handle answer */
768 switch ( rr->common.type ) {
769
770 case htons ( DNS_TYPE_AAAA ):
771
772 /* Found the target AAAA record */
773 if ( rdlength < sizeof ( dns->address.sin6.sin6_addr )){
774 DBGC ( dns, "DNS %p received response with "
775 "underlength AAAA\n", dns );
776 rc = -EINVAL;
777 goto done;
778 }
781 &rr->aaaa.in6_addr,
782 sizeof ( dns->address.sin6.sin6_addr ) );
783 dns_resolved ( dns );
784 rc = 0;
785 goto done;
786
787 case htons ( DNS_TYPE_A ):
788
789 /* Found the target A record */
790 if ( rdlength < sizeof ( dns->address.sin.sin_addr ) ) {
791 DBGC ( dns, "DNS %p received response with "
792 "underlength A\n", dns );
793 rc = -EINVAL;
794 goto done;
795 }
797 dns->address.sin.sin_addr = rr->a.in_addr;
798 dns_resolved ( dns );
799 rc = 0;
800 goto done;
801
802 case htons ( DNS_TYPE_CNAME ):
803
804 /* Terminate the operation if we recurse too far */
805 if ( ++dns->recursion > DNS_MAX_CNAME_RECURSION ) {
806 DBGC ( dns, "DNS %p recursion exceeded\n",
807 dns );
808 rc = -ELOOP;
809 dns_done ( dns, rc );
810 goto done;
811 }
812
813 /* Found a CNAME record; update query and recurse */
814 buf.offset = ( offset + sizeof ( rr->cname ) );
815 DBGC ( dns, "DNS %p found CNAME %s\n",
816 dns, dns_name ( &buf ) );
817 dns->search.offset = dns->search.len;
818 name_len = dns_copy ( &buf, &dns->name );
819 if ( name_len < 0 ) {
820 rc = name_len;
821 dns_done ( dns, rc );
822 goto done;
823 }
824 dns->offset = ( offsetof ( typeof ( dns->buf ), name ) +
825 name_len - 1 /* Strip root label */ );
826 if ( ( rc = dns_question ( dns ) ) != 0 ) {
827 dns_done ( dns, rc );
828 goto done;
829 }
830 next_offset = answer_offset;
831 break;
832
833 default:
834 DBGC ( dns, "DNS %p got unknown record type %d\n",
835 dns, ntohs ( rr->common.type ) );
836 break;
837 }
838 }
839
840 /* Stop the retry timer. After this point, each code path
841 * must either restart the timer by calling dns_send_packet(),
842 * or mark the DNS operation as complete by calling
843 * dns_done()
844 */
845 stop_timer ( &dns->timer );
846
847 /* Determine what to do next based on the type of query we
848 * issued and the response we received
849 */
850 switch ( qtype ) {
851
852 case htons ( DNS_TYPE_AAAA ):
853 /* We asked for an AAAA record and got nothing; try
854 * the A.
855 */
856 DBGC ( dns, "DNS %p found no AAAA record; trying A\n", dns );
857 dns->question->qtype = htons ( DNS_TYPE_A );
858 dns_send_packet ( dns );
859 rc = 0;
860 goto done;
861
862 case htons ( DNS_TYPE_A ):
863 /* We asked for an A record and got nothing;
864 * try the CNAME.
865 */
866 DBGC ( dns, "DNS %p found no A record; trying CNAME\n", dns );
868 dns_send_packet ( dns );
869 rc = 0;
870 goto done;
871
872 case htons ( DNS_TYPE_CNAME ):
873 /* We asked for a CNAME record. If we got a response
874 * (i.e. if the next AAAA/A query is already set up),
875 * then issue it.
876 */
877 if ( qtype == dns->qtype ) {
878 dns_send_packet ( dns );
879 rc = 0;
880 goto done;
881 }
882
883 /* If we have already reached the end of the search list,
884 * then terminate lookup.
885 */
886 if ( dns->search.offset == dns->search.len ) {
887 DBGC ( dns, "DNS %p found no CNAME record\n", dns );
889 dns_done ( dns, rc );
890 goto done;
891 }
892
893 /* Move to next entry in search list. This can never fail,
894 * since we have already used this entry.
895 */
896 DBGC ( dns, "DNS %p found no CNAME record; trying next "
897 "suffix\n", dns );
898 dns->search.offset = dns_skip_search ( &dns->search );
899 if ( ( rc = dns_question ( dns ) ) != 0 ) {
900 dns_done ( dns, rc );
901 goto done;
902 }
903 dns_send_packet ( dns );
904 goto done;
905
906 default:
907 assert ( 0 );
908 rc = -EINVAL;
909 dns_done ( dns, rc );
910 goto done;
911 }
912
913 done:
914 /* Free I/O buffer */
915 free_iob ( iobuf );
916 return rc;
917}
switch(len)
Definition string.h:62
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
struct bofm_section_header done
Definition bofm_test.c:46
static int dns_skip_search(struct dns_name *name)
Skip RFC1035-encoded DNS name in search list.
Definition dns.c:404
#define ENXIO_NO_RECORD
Definition dns.c:60
int dns_compare(struct dns_name *first, struct dns_name *second)
Compare DNS names for equality.
Definition dns.c:268
static void dns_resolved(struct dns_request *dns)
Mark DNS request as resolved and complete.
Definition dns.c:525
#define DNS_MAX_CNAME_RECURSION
Maximum depth of CNAME recursion.
Definition dns.h:63
uint64_t address
Base address.
Definition ena.h:13
#define ELOOP
Too many levels of symbolic links.
Definition errno.h:492
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
if(natsemi->flags &NATSEMI_64BIT) return 1
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
uint16_t qdcount
Number of question records.
Definition dns.h:72
A DNS question.
Definition dns.h:85
struct in_addr in_addr
IPv4 address.
Definition dns.h:115
struct in6_addr in6_addr
IPv6 address.
Definition dns.h:126
uint16_t type
Type.
Definition dns.h:98
uint16_t rdlength
Resource data length.
Definition dns.h:104
void * data
Start of data.
Definition iobuf.h:113
struct sockaddr_in sin
Definition syslog.c:59
A DNS resource record.
Definition dns.h:139
struct dns_rr_aaaa aaaa
"AAAA" record
Definition dns.h:145
struct dns_rr_cname cname
"CNAME" record
Definition dns.h:147
struct dns_rr_common common
Common fields.
Definition dns.h:141
struct dns_rr_a a
"A" record
Definition dns.h:143

References __unused, dns_rr::a, dns_rr::aaaa, dns_request::address, AF_INET, AF_INET6, dns_request::buf, dns_rr::cname, dns_rr::common, dns_name::data, io_buffer::data, DBGC, dns_compare(), dns_copy(), dns_done(), DNS_MAX_CNAME_RECURSION, dns_resolved(), dns_skip(), DNS_TYPE_A, DNS_TYPE_CNAME, done, EINVAL, ELOOP, htons, dns_header::id, if(), dns_rr_aaaa::in6_addr, dns_rr_a::in_addr, iob_len(), dns_name::len, memcpy(), meta, dns_request::name, name, ntohs, dns_name::offset, dns_request::offset, offset, offsetof, dns_header::qdcount, dns_question::qtype, dns_request::query, dns_request::question, rc, dns_rr_common::rdlength, dns_request::recursion, dns_request::search, dns_request::sin, dns_request::sin6, sockaddr_in6::sin6_addr, sockaddr_in6::sin6_family, sockaddr_in::sin_addr, sockaddr_in::sin_family, strerror(), switch(), dns_rr_common::type, and typeof().

◆ dns_xfer_close()

void dns_xfer_close ( struct dns_request * dns,
int rc )
static

Receive new data.

Parameters
dnsDNS request
rcReason for close

Definition at line 925 of file dns.c.

925 {
926
927 if ( ! rc )
928 rc = -ECONNABORTED;
929
930 dns_done ( dns, rc );
931}
#define ECONNABORTED
Connection aborted.
Definition errno.h:397

References dns_done(), ECONNABORTED, and rc.

◆ dns_progress()

int dns_progress ( struct dns_request * dns,
struct job_progress * progress )
static

Report job progress.

Parameters
dnsDNS request
progressProgress report to fill in
Return values
ongoing_rcOngoing job status code (if known)

Definition at line 940 of file dns.c.

941 {
942 int len;
943
944 /* Show current question as progress message */
945 len = dns_decode ( &dns->name, progress->message,
946 ( sizeof ( progress->message ) - 1 /* NUL */ ) );
947 if ( len < 0 ) {
948 /* Ignore undecodable names */
949 progress->message[0] = '\0';
950 }
951
952 return 0;
953}
char message[32]
Message (optional).
Definition job.h:33

References dns_decode(), len, job_progress::message, and dns_request::name.

◆ dns_resolv()

int dns_resolv ( struct interface * resolv,
const char * name,
struct sockaddr * sa )
static

Resolve name using DNS.

Parameters
resolvName resolution interface
nameName to resolve
saSocket address to fill in
Return values
rcReturn status code

Definition at line 983 of file dns.c.

984 {
985 struct dns_request *dns;
986 struct dns_header *query;
987 size_t search_len;
988 int name_len;
989 int rc;
990
991 /* Fail immediately if no DNS servers */
992 if ( dns_count == 0 ) {
993 DBG ( "DNS not attempting to resolve \"%s\": "
994 "no DNS servers\n", name );
996 goto err_no_nameserver;
997 }
998
999 /* Determine whether or not to use search list */
1000 search_len = ( strchr ( name, '.' ) ? 0 : dns_search.len );
1001
1002 /* Allocate DNS structure */
1003 dns = zalloc ( sizeof ( *dns ) + search_len );
1004 if ( ! dns ) {
1005 rc = -ENOMEM;
1006 goto err_alloc_dns;
1007 }
1008 ref_init ( &dns->refcnt, NULL );
1009 intf_init ( &dns->resolv, &dns_resolv_desc, &dns->refcnt );
1010 intf_init ( &dns->socket, &dns_socket_desc, &dns->refcnt );
1011 timer_init ( &dns->timer, dns_timer_expired, &dns->refcnt );
1012 memcpy ( &dns->address.sa, sa, sizeof ( dns->address.sa ) );
1013 dns->search.data = ( ( ( void * ) dns ) + sizeof ( *dns ) );
1014 dns->search.len = search_len;
1015 memcpy ( dns->search.data, dns_search.data, search_len );
1016
1017 /* Determine initial query type */
1018 dns->qtype = ( ( dns6.count != 0 ) ?
1019 htons ( DNS_TYPE_AAAA ) : htons ( DNS_TYPE_A ) );
1020
1021 /* Construct query */
1022 query = &dns->buf.query;
1023 query->flags = htons ( DNS_FLAG_RD );
1024 query->qdcount = htons ( 1 );
1025 dns->name.data = &dns->buf;
1026 dns->name.offset = offsetof ( typeof ( dns->buf ), name );
1027 dns->name.len = offsetof ( typeof ( dns->buf ), padding );
1028 name_len = dns_encode ( name, &dns->name );
1029 if ( name_len < 0 ) {
1030 rc = name_len;
1031 goto err_encode;
1032 }
1033 dns->offset = ( offsetof ( typeof ( dns->buf ), name ) +
1034 name_len - 1 /* Strip root label */ );
1035 if ( ( rc = dns_question ( dns ) ) != 0 )
1036 goto err_question;
1037
1038 /* Open UDP connection */
1039 if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM,
1040 &dns->nameserver.sa, NULL ) ) != 0 ) {
1041 DBGC ( dns, "DNS %p could not open socket: %s\n",
1042 dns, strerror ( rc ) );
1043 goto err_open_socket;
1044 }
1045
1046 /* Start timer to trigger first packet */
1047 start_timer_nodelay ( &dns->timer );
1048
1049 /* Attach parent interface, mortalise self, and return */
1050 intf_plug_plug ( &dns->resolv, resolv );
1051 ref_put ( &dns->refcnt );
1052 return 0;
1053
1054 err_open_socket:
1055 err_question:
1056 err_encode:
1057 ref_put ( &dns->refcnt );
1058 err_alloc_dns:
1059 err_no_nameserver:
1060 return rc;
1061}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
static struct interface_descriptor dns_resolv_desc
DNS resolver interface descriptor.
Definition dns.c:972
int dns_encode(const char *string, struct dns_name *name)
Encode a DNS name using RFC1035 encoding.
Definition dns.c:101
static void dns_timer_expired(struct retry_timer *timer, int fail)
Handle DNS (re)transmission timer expiry.
Definition dns.c:643
#define ENXIO_NO_NAMESERVER
Definition dns.c:63
static struct dns_name dns_search
The DNS search list.
Definition dns.c:92
static struct interface_descriptor dns_socket_desc
DNS socket interface descriptor.
Definition dns.c:962
#define DNS_FLAG_RD
Recursion desired flag.
Definition dns.h:82
#define SOCK_DGRAM
Definition socket.h:30
#define DBG(...)
Print a debugging message.
Definition compiler.h:523
#define ENOMEM
Not enough space.
Definition errno.h:578
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition open.c:152
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int resolv(struct interface *resolv, const char *name, struct sockaddr *sa)
Start name resolution.
Definition resolv.c:258
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
char * strchr(const char *src, int character)
Find character within a string.
Definition string.c:288
uint16_t flags
Flags.
Definition dns.h:70
struct refcnt refcnt
Reference counter.
Definition dns.c:455
struct sockaddr sa
Definition syslog.c:57

References dns_request::address, dns_request::buf, dns_name::data, DBG, DBGC, dns6, dns_count, dns_encode(), DNS_FLAG_RD, dns_resolv_desc, dns_search, dns_socket_desc, dns_timer_expired(), DNS_TYPE_A, DNS_TYPE_AAAA, ENOMEM, ENXIO_NO_NAMESERVER, dns_header::flags, htons, intf_init(), intf_plug_plug(), dns_name::len, memcpy(), dns_request::name, name, dns_request::nameserver, NULL, dns_request::offset, offsetof, dns_header::qdcount, dns_request::qtype, dns_request::query, rc, ref_init, ref_put, dns_request::refcnt, dns_request::resolv, resolv(), dns_request::sa, sa, dns_request::search, SOCK_DGRAM, dns_request::socket, start_timer_nodelay(), strchr(), strerror(), dns_request::timer, typeof(), xfer_open_socket(), and zalloc().

Referenced by __resolver().

◆ __resolver()

struct resolver dns_resolver __resolver ( RESOLV_NORMAL )

DNS name resolver.

References __resolver, dns_resolv(), and RESOLV_NORMAL.

◆ format_dnssl_setting()

int format_dnssl_setting ( const struct setting_type *type __unused,
const void * raw,
size_t raw_len,
char * buf,
size_t len )
static

Format DNS search list setting.

Parameters
typeSetting type
rawRaw setting value
raw_lenLength of raw setting value
bufBuffer to contain formatted value
lenLength of buffer
Return values
lenLength of formatted value, or negative error

Definition at line 1086 of file dns.c.

1088 {
1089 struct dns_name name = {
1090 .data = ( ( void * ) raw ),
1091 .len = raw_len,
1092 };
1093 size_t remaining = len;
1094 size_t total = 0;
1095 int name_len;
1096
1097 while ( name.offset < raw_len ) {
1098
1099 /* Decode name */
1100 remaining = ( ( total < len ) ? ( len - total ) : 0 );
1101 name_len = dns_decode ( &name, ( buf + total ), remaining );
1102 if ( name_len < 0 )
1103 return name_len;
1104 total += name_len;
1105
1106 /* Move to next name */
1107 name.offset = dns_skip_search ( &name );
1108
1109 /* Add separator if applicable */
1110 if ( name.offset != raw_len ) {
1111 if ( total < len )
1112 buf[total] = ' ';
1113 total++;
1114 }
1115 }
1116
1117 return total;
1118}
__be32 raw[7]
Definition CIB_PRM.h:0
static size_t raw_len
Definition base16.h:54

References __unused, dns_decode(), dns_skip_search(), len, name, raw, raw_len, and type.

◆ __setting() [1/3]

const struct setting dns_setting __setting ( SETTING_IP4_EXTRA ,
dns  )

IPv4 DNS server setting.

References __setting, DHCP_DNS_SERVERS, dns_setting, and SETTING_IP4_EXTRA.

◆ __setting() [2/3]

const struct setting dns6_setting __setting ( SETTING_IP6_EXTRA ,
dns6  )

IPv6 DNS server setting.

References __setting, DHCPV6_DNS_SERVERS, dhcpv6_scope, dns6, dns6_setting, and SETTING_IP6_EXTRA.

◆ __setting() [3/3]

const struct setting dnssl_setting __setting ( SETTING_IP_EXTRA ,
dnssl  )

DNS search list.

References __setting, DHCP_DOMAIN_SEARCH, and SETTING_IP_EXTRA.

◆ apply_dns_servers()

void apply_dns_servers ( void )
static

Apply DNS server addresses.

Definition at line 1155 of file dns.c.

1155 {
1156 int len;
1157
1158 /* Free existing server addresses */
1159 free ( dns4.data );
1160 free ( dns6.data );
1161 dns4.data = NULL;
1162 dns6.data = NULL;
1163 dns4.count = 0;
1164 dns6.count = 0;
1165
1166 /* Fetch DNS server addresses */
1168 if ( len >= 0 )
1169 dns4.count = ( len / sizeof ( dns4.in[0] ) );
1171 if ( len >= 0 )
1172 dns6.count = ( len / sizeof ( dns6.in6[0] ) );
1173 dns_count = ( dns4.count + dns6.count );
1174}
const struct setting dns_setting
const struct setting dns6_setting
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
int fetch_raw_setting_copy(struct settings *settings, const struct setting *setting, void **data)
Fetch value of setting.
Definition settings.c:822

References dns4, dns6, dns6_setting, dns_count, dns_setting, fetch_raw_setting_copy(), free, len, and NULL.

Referenced by apply_dns_settings().

◆ apply_dns_search()

void apply_dns_search ( void )
static

Apply DNS search list.

Definition at line 1180 of file dns.c.

1180 {
1181 char *localdomain;
1182 int len;
1183
1184 /* Free existing search list */
1185 free ( dns_search.data );
1186 memset ( &dns_search, 0, sizeof ( dns_search ) );
1187
1188 /* Fetch DNS search list */
1189 len = fetch_raw_setting_copy ( NULL, &dnssl_setting, &dns_search.data );
1190 if ( len >= 0 ) {
1191 dns_search.len = len;
1192 return;
1193 }
1194
1195 /* If no DNS search list exists, try to fetch the local domain */
1196 fetch_string_setting_copy ( NULL, &domain_setting, &localdomain );
1197 if ( localdomain ) {
1198 len = dns_encode ( localdomain, &dns_search );
1199 if ( len >= 0 ) {
1200 dns_search.data = malloc ( len );
1201 if ( dns_search.data ) {
1202 dns_search.len = len;
1203 dns_encode ( localdomain, &dns_search );
1204 }
1205 }
1206 free ( localdomain );
1207 return;
1208 }
1209}
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:677
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition settings.c:874

References dns_encode(), dns_search, fetch_raw_setting_copy(), fetch_string_setting_copy(), free, len, malloc(), memset(), and NULL.

Referenced by apply_dns_settings().

◆ apply_dns_settings()

int apply_dns_settings ( void )
static

Apply DNS settings.

Return values
rcReturn status code

Definition at line 1216 of file dns.c.

1216 {
1217 void *dbgcol = &dns_count;
1218
1219 /* Fetch DNS server address */
1221 if ( DBG_EXTRA && ( dns_count != 0 ) ) {
1222 union {
1223 struct sockaddr sa;
1224 struct sockaddr_in sin;
1225 struct sockaddr_in6 sin6;
1226 } u;
1227 unsigned int i;
1228
1229 DBGC2 ( dbgcol, "DNS servers:" );
1230 for ( i = 0 ; i < dns6.count ; i++ ) {
1231 u.sin6.sin6_family = AF_INET6;
1232 memcpy ( &u.sin6.sin6_addr, &dns6.in6[i],
1233 sizeof ( u.sin6.sin6_addr ) );
1234 DBGC2 ( dbgcol, " %s", sock_ntoa ( &u.sa ) );
1235 }
1236 for ( i = 0 ; i < dns4.count ; i++ ) {
1237 u.sin.sin_family = AF_INET;
1238 u.sin.sin_addr = dns4.in[i];
1239 DBGC2 ( dbgcol, " %s", sock_ntoa ( &u.sa ) );
1240 }
1241 DBGC2 ( dbgcol, "\n" );
1242 }
1243
1244 /* Fetch DNS search list */
1246 if ( DBG_EXTRA && ( dns_search.len != 0 ) ) {
1247 struct dns_name name;
1248 int offset;
1249
1250 DBGC2 ( dbgcol, "DNS search list:" );
1251 memcpy ( &name, &dns_search, sizeof ( name ) );
1252 while ( name.offset != name.len ) {
1253 DBGC2 ( dbgcol, " %s", dns_name ( &name ) );
1255 if ( offset < 0 )
1256 break;
1257 name.offset = offset;
1258 }
1259 DBGC2 ( dbgcol, "\n" );
1260 }
1261
1262 return 0;
1263}
union @104331263140136355135267063077374276003064103115 u
static void apply_dns_servers(void)
Apply DNS server addresses.
Definition dns.c:1155
static void apply_dns_search(void)
Apply DNS search list.
Definition dns.c:1180
#define DBG_EXTRA
Definition compiler.h:344
IPv6 socket address.
Definition in.h:118
IPv4 socket address.
Definition in.h:85
Generalized socket address structure.
Definition socket.h:97
struct sockaddr_in6 sin6
Definition syslog.c:60

References AF_INET, AF_INET6, apply_dns_search(), apply_dns_servers(), DBG_EXTRA, DBGC2, dns4, dns6, dns_count, dns_search, dns_skip_search(), memcpy(), name, offset, sa, sin, sin6, sock_ntoa(), and u.

Variable Documentation

◆ dns4

struct dns_server dns4
static

IPv4 DNS server list.

Definition at line 83 of file dns.c.

Referenced by apply_dns_servers(), apply_dns_settings(), and dns_send_packet().

◆ dns6

struct dns_server dns6
static

IPv6 DNS server list.

Definition at line 86 of file dns.c.

Referenced by __setting(), apply_dns_servers(), apply_dns_settings(), dns_resolv(), and dns_send_packet().

◆ dns_count

unsigned int dns_count
static

Total number of DNS servers.

Definition at line 89 of file dns.c.

Referenced by apply_dns_servers(), apply_dns_settings(), dns_resolv(), and dns_send_packet().

◆ dns_search

struct dns_name dns_search
static

The DNS search list.

Definition at line 92 of file dns.c.

Referenced by apply_dns_search(), apply_dns_settings(), and dns_resolv().

◆ dns_socket_operations

struct interface_operation dns_socket_operations[]
static
Initial value:
= {
}
static void dns_xfer_close(struct dns_request *dns, int rc)
Receive new data.
Definition dns.c:925
static int dns_xfer_deliver(struct dns_request *dns, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive new data.
Definition dns.c:669
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195

DNS socket interface operations.

Definition at line 956 of file dns.c.

956 {
959};

◆ dns_socket_desc

struct interface_descriptor dns_socket_desc
static
Initial value:
=
static struct interface_operation dns_socket_operations[]
DNS socket interface operations.
Definition dns.c:956
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81

DNS socket interface descriptor.

Definition at line 962 of file dns.c.

Referenced by dns_resolv().

◆ dns_resolv_op

struct interface_operation dns_resolv_op[]
static
Initial value:
= {
}
static int dns_progress(struct dns_request *dns, struct job_progress *progress)
Report job progress.
Definition dns.c:940
Job progress.
Definition job.h:16

DNS resolver interface operations.

Definition at line 966 of file dns.c.

966 {
968 INTF_OP ( intf_close, struct dns_request *, dns_done ),
969};

◆ dns_resolv_desc

struct interface_descriptor dns_resolv_desc
static
Initial value:
=
static struct interface_operation dns_resolv_op[]
DNS resolver interface operations.
Definition dns.c:966

DNS resolver interface descriptor.

Definition at line 972 of file dns.c.

Referenced by dns_resolv().

◆ __setting_type

const struct setting_type setting_type_dnssl __setting_type
Initial value:
= {
.name = "dnssl",
}
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.
Definition dns.c:1086

A DNS search list setting type.

A string setting type.

Definition at line 1121 of file dns.c.

1121 {
1122 .name = "dnssl",
1123 .format = format_dnssl_setting,
1124};

◆ __settings_applicator

struct settings_applicator dns_applicator __settings_applicator
Initial value:
= {
}
static int apply_dns_settings(void)
Apply DNS settings.
Definition dns.c:1216

DNS settings applicator.

Definition at line 1266 of file dns.c.

1266 {
1267 .apply = apply_dns_settings,
1268};