iPXE
dns.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * Portions copyright (C) 2004 Anselm M. Hoffmeister
5  * <stockholm@users.sourceforge.net>.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA.
21  *
22  * You can also choose to distribute this program under the terms of
23  * the Unmodified Binary Distribution Licence (as given in the file
24  * COPYING.UBDL), provided that you have satisfied its requirements.
25  */
26 
27 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
28 
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <byteswap.h>
36 #include <ipxe/refcnt.h>
37 #include <ipxe/iobuf.h>
38 #include <ipxe/xfer.h>
39 #include <ipxe/open.h>
40 #include <ipxe/resolv.h>
41 #include <ipxe/retry.h>
42 #include <ipxe/tcpip.h>
43 #include <ipxe/settings.h>
44 #include <ipxe/features.h>
45 #include <ipxe/job.h>
46 #include <ipxe/dhcp.h>
47 #include <ipxe/dhcpv6.h>
48 #include <ipxe/dns.h>
49 
50 /** @file
51  *
52  * DNS protocol
53  *
54  */
55 
57 
58 /* Disambiguate the various error causes */
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" )
65 
66 /** A DNS server list */
67 struct dns_server {
68  /** Server list */
69  union {
70  /** IPv4 addresses */
71  struct in_addr *in;
72  /** IPv6 addresses */
73  struct in6_addr *in6;
74  /** Raw data */
75  void *data;
76  };
77  /** Number of servers */
78  unsigned int count;
79 };
80 
81 /** IPv4 DNS server list */
82 static struct dns_server dns4;
83 
84 /** IPv6 DNS server list */
85 static struct dns_server dns6;
86 
87 /** Total number of DNS servers */
88 static unsigned int dns_count;
89 
90 /** The DNS search list */
91 static struct dns_name dns_search;
92 
93 /**
94  * Encode a DNS name using RFC1035 encoding
95  *
96  * @v string DNS name as a string
97  * @v name DNS name to fill in
98  * @ret len Length of DNS name, or negative error
99  */
100 int dns_encode ( const char *string, struct dns_name *name ) {
101  uint8_t *start = ( name->data + name->offset );
102  uint8_t *end = ( name->data + name->len );
103  uint8_t *dst = start;
104  size_t len = 0;
105  char c;
106 
107  /* Encode name */
108  while ( ( c = *(string++) ) ) {
109 
110  /* Handle '.' separators */
111  if ( c == '.' ) {
112 
113  /* Reject consecutive '.' */
114  if ( ( len == 0 ) && ( dst != start ) )
115  return -EINVAL;
116 
117  /* Terminate if this is the trailing '.' */
118  if ( *string == '\0' )
119  break;
120 
121  /* Reject initial non-terminating '.' */
122  if ( len == 0 )
123  return -EINVAL;
124 
125  /* Reset length */
126  len = 0;
127 
128  } else {
129 
130  /* Increment length */
131  len++;
132 
133  /* Check for overflow */
134  if ( len > DNS_MAX_LABEL_LEN )
135  return -EINVAL;
136  }
137 
138  /* Copy byte, update length */
139  if ( ++dst < end ) {
140  *dst = c;
141  dst[-len] = len;
142  }
143  }
144 
145  /* Add terminating root marker */
146  if ( len )
147  dst++;
148  if ( dst < end )
149  *dst = '\0';
150  dst++;
151 
152  return ( dst - start );
153 }
154 
155 /**
156  * Find start of valid label within an RFC1035-encoded DNS name
157  *
158  * @v name DNS name
159  * @v offset Current offset
160  * @ret offset Offset of label, or negative error
161  */
162 static int dns_label ( struct dns_name *name, size_t offset ) {
163  const uint8_t *byte;
164  const uint16_t *word;
165  size_t len;
166  size_t ptr;
167 
168  while ( 1 ) {
169 
170  /* Fail if we have overrun the DNS name */
171  if ( ( offset + sizeof ( *byte) ) > name->len )
172  return -EINVAL;
173  byte = ( name->data + offset );
174 
175  /* Follow compression pointer, if applicable */
176  if ( DNS_IS_COMPRESSED ( *byte ) ) {
177 
178  /* Fail if we have overrun the DNS name */
179  if ( ( offset + sizeof ( *word ) ) > name->len )
180  return -EINVAL;
181  word = ( name->data + offset );
182 
183  /* Extract pointer to new offset */
184  ptr = DNS_COMPRESSED_OFFSET ( ntohs ( *word ) );
185 
186  /* Fail if pointer does not point backwards.
187  * (This guarantees termination of the
188  * function.)
189  */
190  if ( ptr >= offset )
191  return -EINVAL;
192 
193  /* Continue from new offset */
194  offset = ptr;
195  continue;
196  }
197 
198  /* Fail if we have overrun the DNS name */
199  len = *byte;
200  if ( ( offset + sizeof ( *byte ) + len ) > name->len )
201  return -EINVAL;
202 
203  /* We have a valid label */
204  return offset;
205  }
206 }
207 
208 /**
209  * Decode RFC1035-encoded DNS name
210  *
211  * @v name DNS name
212  * @v data Output buffer
213  * @v len Length of output buffer
214  * @ret len Length of decoded DNS name, or negative error
215  */
216 int dns_decode ( struct dns_name *name, char *data, size_t len ) {
217  unsigned int recursion_limit = name->len; /* Generous upper bound */
218  int offset = name->offset;
219  const uint8_t *label;
220  size_t decoded_len = 0;
221  size_t label_len;
222  size_t copy_len;
223 
224  while ( recursion_limit-- ) {
225 
226  /* Find valid DNS label */
227  offset = dns_label ( name, offset );
228  if ( offset < 0 )
229  return offset;
230 
231  /* Terminate if we have reached the root */
232  label = ( name->data + offset );
233  label_len = *(label++);
234  if ( label_len == 0 ) {
235  if ( decoded_len < len )
236  *data = '\0';
237  return decoded_len;
238  }
239 
240  /* Prepend '.' if applicable */
241  if ( decoded_len && ( decoded_len++ < len ) )
242  *(data++) = '.';
243 
244  /* Copy label to output buffer */
245  copy_len = ( ( decoded_len < len ) ? ( len - decoded_len ) : 0);
246  if ( copy_len > label_len )
247  copy_len = label_len;
248  memcpy ( data, label, copy_len );
249  data += copy_len;
250  decoded_len += label_len;
251 
252  /* Move to next label */
253  offset += ( sizeof ( *label ) + label_len );
254  }
255 
256  /* Recursion limit exceeded */
257  return -EINVAL;
258 }
259 
260 /**
261  * Compare DNS names for equality
262  *
263  * @v first First DNS name
264  * @v second Second DNS name
265  * @ret rc Return status code
266  */
267 int dns_compare ( struct dns_name *first, struct dns_name *second ) {
268  unsigned int recursion_limit = first->len; /* Generous upper bound */
269  int first_offset = first->offset;
270  int second_offset = second->offset;
271  const uint8_t *first_label;
272  const uint8_t *second_label;
273  size_t label_len;
274  size_t len;
275 
276  while ( recursion_limit-- ) {
277 
278  /* Find valid DNS labels */
279  first_offset = dns_label ( first, first_offset );
280  if ( first_offset < 0 )
281  return first_offset;
282  second_offset = dns_label ( second, second_offset );
283  if ( second_offset < 0 )
284  return second_offset;
285 
286  /* Compare label lengths */
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++) )
291  return -ENOENT;
292  len = ( sizeof ( *first_label ) + label_len );
293 
294  /* Terminate if we have reached the root */
295  if ( label_len == 0 )
296  return 0;
297 
298  /* Compare label contents (case-insensitively) */
299  while ( label_len-- ) {
300  if ( tolower ( *(first_label++) ) !=
301  tolower ( *(second_label++) ) )
302  return -ENOENT;
303  }
304 
305  /* Move to next labels */
306  first_offset += len;
307  second_offset += len;
308  }
309 
310  /* Recursion limit exceeded */
311  return -EINVAL;
312 }
313 
314 /**
315  * Copy a DNS name
316  *
317  * @v src Source DNS name
318  * @v dst Destination DNS name
319  * @ret len Length of copied DNS name, or negative error
320  */
321 int dns_copy ( struct dns_name *src, struct dns_name *dst ) {
322  unsigned int recursion_limit = src->len; /* Generous upper bound */
323  int src_offset = src->offset;
324  size_t dst_offset = dst->offset;
325  const uint8_t *label;
326  size_t label_len;
327  size_t copy_len;
328  size_t len;
329 
330  while ( recursion_limit-- ) {
331 
332  /* Find valid DNS label */
333  src_offset = dns_label ( src, src_offset );
334  if ( src_offset < 0 )
335  return src_offset;
336 
337  /* Copy as an uncompressed label */
338  label = ( src->data + src_offset );
339  label_len = *label;
340  len = ( sizeof ( *label ) + label_len );
341  copy_len = ( ( dst_offset < dst->len ) ?
342  ( dst->len - dst_offset ) : 0 );
343  if ( copy_len > len )
344  copy_len = len;
345  memcpy ( ( dst->data + dst_offset ), label, copy_len );
346  src_offset += len;
347  dst_offset += len;
348 
349  /* Terminate if we have reached the root */
350  if ( label_len == 0 )
351  return ( dst_offset - dst->offset );
352  }
353 
354  /* Recursion limit exceeded */
355  return -EINVAL;
356 }
357 
358 /**
359  * Skip RFC1035-encoded DNS name
360  *
361  * @v name DNS name
362  * @ret offset Offset to next name, or negative error
363  */
364 int dns_skip ( struct dns_name *name ) {
365  unsigned int recursion_limit = name->len; /* Generous upper bound */
366  int offset = name->offset;
367  int prev_offset;
368  const uint8_t *label;
369  size_t label_len;
370 
371  while ( recursion_limit-- ) {
372 
373  /* Find valid DNS label */
374  prev_offset = offset;
375  offset = dns_label ( name, prev_offset );
376  if ( offset < 0 )
377  return offset;
378 
379  /* Terminate if we have reached a compression pointer */
380  if ( offset != prev_offset )
381  return ( prev_offset + sizeof ( uint16_t ) );
382 
383  /* Skip this label */
384  label = ( name->data + offset );
385  label_len = *label;
386  offset += ( sizeof ( *label ) + label_len );
387 
388  /* Terminate if we have reached the root */
389  if ( label_len == 0 )
390  return offset;
391  }
392 
393  /* Recursion limit exceeded */
394  return -EINVAL;
395 }
396 
397 /**
398  * Skip RFC1035-encoded DNS name in search list
399  *
400  * @v name DNS name
401  * @ret offset Offset to next non-empty name, or negative error
402  */
403 static int dns_skip_search ( struct dns_name *name ) {
404  int offset;
405 
406  /* Find next name */
407  offset = dns_skip ( name );
408  if ( offset < 0 )
409  return offset;
410 
411  /* Skip over any subsequent empty names (e.g. due to padding
412  * bytes used in the NDP DNSSL option).
413  */
414  while ( ( offset < ( ( int ) name->len ) ) &&
415  ( *( ( uint8_t * ) ( name->data + offset ) ) == 0 ) ) {
416  offset++;
417  }
418 
419  return offset;
420 }
421 
422 /**
423  * Transcribe DNS name (for debugging)
424  *
425  * @v name DNS name
426  * @ret string Transcribed DNS name
427  */
428 static const char * dns_name ( struct dns_name *name ) {
429  static char buf[256];
430  int len;
431 
432  len = dns_decode ( name, buf, ( sizeof ( buf ) - 1 /* NUL */ ) );
433  return ( ( len < 0 ) ? "<INVALID>" : buf );
434 }
435 
436 /**
437  * Name a DNS query type (for debugging)
438  *
439  * @v type Query type (in network byte order)
440  * @ret name Type name
441  */
442 static const char * dns_type ( uint16_t type ) {
443  switch ( type ) {
444  case htons ( DNS_TYPE_A ): return "A";
445  case htons ( DNS_TYPE_AAAA ): return "AAAA";
446  case htons ( DNS_TYPE_CNAME ): return "CNAME";
447  default: return "<UNKNOWN>";
448  }
449 }
450 
451 /** A DNS request */
452 struct dns_request {
453  /** Reference counter */
454  struct refcnt refcnt;
455  /** Name resolution interface */
457  /** Data transfer interface */
459  /** Retry timer */
461 
462  /** Socket address to fill in with resolved address */
463  union {
464  struct sockaddr sa;
465  struct sockaddr_in sin;
467  } address;
468  /** Initial query type */
470  /** Buffer for current query */
471  struct {
472  /** Query header */
474  /** Name buffer */
476  /** Space for question */
478  } __attribute__ (( packed )) buf;
479  /** Current query name */
480  struct dns_name name;
481  /** Question within current query */
483  /** Length of current query */
484  size_t len;
485  /** Offset of search suffix within current query */
486  size_t offset;
487  /** Search list */
488  struct dns_name search;
489  /** Server index */
490  unsigned int index;
491  /** Recursion counter */
492  unsigned int recursion;
493 };
494 
495 /**
496  * Mark DNS request as complete
497  *
498  * @v dns DNS request
499  * @v rc Return status code
500  */
501 static void dns_done ( struct dns_request *dns, int rc ) {
502 
503  /* Stop the retry timer */
504  stop_timer ( &dns->timer );
505 
506  /* Shut down interfaces */
507  intf_shutdown ( &dns->socket, rc );
508  intf_shutdown ( &dns->resolv, rc );
509 }
510 
511 /**
512  * Mark DNS request as resolved and complete
513  *
514  * @v dns DNS request
515  * @v rc Return status code
516  */
517 static void dns_resolved ( struct dns_request *dns ) {
518 
519  DBGC ( dns, "DNS %p found address %s\n",
520  dns, sock_ntoa ( &dns->address.sa ) );
521 
522  /* Return resolved address */
523  resolv_done ( &dns->resolv, &dns->address.sa );
524 
525  /* Mark operation as complete */
526  dns_done ( dns, 0 );
527 }
528 
529 /**
530  * Construct DNS question
531  *
532  * @v dns DNS request
533  * @ret rc Return status code
534  */
535 static int dns_question ( struct dns_request *dns ) {
536  static struct dns_name search_root = {
537  .data = "",
538  .len = 1,
539  };
540  struct dns_name *search = &dns->search;
541  int len;
542  size_t offset;
543 
544  /* Use root suffix if search list is empty */
545  if ( search->offset == search->len )
546  search = &search_root;
547 
548  /* Overwrite current suffix */
549  dns->name.offset = dns->offset;
550  len = dns_copy ( search, &dns->name );
551  if ( len < 0 )
552  return len;
553 
554  /* Sanity check */
555  offset = ( dns->name.offset + len );
556  if ( offset > dns->name.len ) {
557  DBGC ( dns, "DNS %p name is too long\n", dns );
558  return -EINVAL;
559  }
560 
561  /* Construct question */
562  dns->question = ( ( ( void * ) &dns->buf ) + offset );
563  dns->question->qtype = dns->qtype;
564  dns->question->qclass = htons ( DNS_CLASS_IN );
565 
566  /* Store length */
567  dns->len = ( offset + sizeof ( *(dns->question) ) );
568 
569  /* Restore name */
570  dns->name.offset = offsetof ( typeof ( dns->buf ), name );
571 
572  /* Reset query ID */
573  dns->buf.query.id = 0;
574 
575  DBGC2 ( dns, "DNS %p question is %s type %s\n", dns,
576  dns_name ( &dns->name ), dns_type ( dns->question->qtype ) );
577 
578  return 0;
579 }
580 
581 /**
582  * Send DNS query
583  *
584  * @v dns DNS request
585  * @ret rc Return status code
586  */
587 static int dns_send_packet ( struct dns_request *dns ) {
588  struct dns_header *query = &dns->buf.query;
589  union {
590  struct sockaddr sa;
591  struct sockaddr_tcpip st;
592  struct sockaddr_in sin;
593  struct sockaddr_in6 sin6;
594  } nameserver;
595  struct xfer_metadata meta;
596  unsigned int index;
597 
598  /* Start retransmission timer */
599  start_timer ( &dns->timer );
600 
601  /* Construct DNS server address */
602  memset ( &nameserver, 0, sizeof ( nameserver ) );
603  nameserver.st.st_port = htons ( DNS_PORT );
604  if ( ! dns_count ) {
605  DBGC ( dns, "DNS %p lost DNS servers mid query\n", dns );
606  return -EINVAL;
607  }
608  index = ( dns->index % dns_count );
609  if ( index < dns6.count ) {
610  nameserver.sin6.sin6_family = AF_INET6;
611  memcpy ( &nameserver.sin6.sin6_addr, &dns6.in6[index],
612  sizeof ( nameserver.sin6.sin6_addr ) );
613  } else {
614  nameserver.sin.sin_family = AF_INET;
615  nameserver.sin.sin_addr = dns4.in[index - dns6.count];
616  }
617 
618  /* Construct metadata */
619  memset ( &meta, 0, sizeof ( meta ) );
620  meta.dest = &nameserver.sa;
621 
622  /* Generate query identifier if applicable */
623  if ( ! query->id )
624  query->id = random();
625 
626  /* Send query */
627  DBGC ( dns, "DNS %p sending %s query ID %#04x for %s type %s\n", dns,
628  sock_ntoa ( &nameserver.sa ), ntohs ( query->id ),
629  dns_name ( &dns->name ), dns_type ( dns->question->qtype ) );
630 
631  /* Send the data */
632  return xfer_deliver_raw_meta ( &dns->socket, query, dns->len, &meta );
633 }
634 
635 /**
636  * Handle DNS (re)transmission timer expiry
637  *
638  * @v timer Retry timer
639  * @v fail Failure indicator
640  */
641 static void dns_timer_expired ( struct retry_timer *timer, int fail ) {
642  struct dns_request *dns =
643  container_of ( timer, struct dns_request, timer );
644 
645  /* Terminate DNS request on failure */
646  if ( fail ) {
647  dns_done ( dns, -ETIMEDOUT );
648  return;
649  }
650 
651  /* Move to next DNS server if this is a retransmission */
652  if ( dns->buf.query.id )
653  dns->index++;
654 
655  /* Send DNS query */
656  dns_send_packet ( dns );
657 }
658 
659 /**
660  * Receive new data
661  *
662  * @v dns DNS request
663  * @v iobuf I/O buffer
664  * @v meta Data transfer metadata
665  * @ret rc Return status code
666  */
667 static int dns_xfer_deliver ( struct dns_request *dns,
668  struct io_buffer *iobuf,
669  struct xfer_metadata *meta __unused ) {
670  struct dns_header *response = iobuf->data;
671  struct dns_header *query = &dns->buf.query;
672  unsigned int qtype = dns->question->qtype;
673  struct dns_name buf;
674  union dns_rr *rr;
675  int offset;
676  size_t answer_offset;
677  size_t next_offset;
678  size_t rdlength;
679  size_t name_len;
680  int rc;
681 
682  /* Sanity check */
683  if ( iob_len ( iobuf ) < sizeof ( *response ) ) {
684  DBGC ( dns, "DNS %p received underlength packet length %zd\n",
685  dns, iob_len ( iobuf ) );
686  rc = -EINVAL;
687  goto done;
688  }
689 
690  /* Check response ID matches query ID */
691  if ( response->id != query->id ) {
692  DBGC ( dns, "DNS %p received unexpected response ID %#04x "
693  "(wanted %d)\n", dns, ntohs ( response->id ),
694  ntohs ( query->id ) );
695  rc = -EINVAL;
696  goto done;
697  }
698  DBGC ( dns, "DNS %p received response ID %#04x\n",
699  dns, ntohs ( response->id ) );
700 
701  /* Check that we have exactly one question */
702  if ( response->qdcount != htons ( 1 ) ) {
703  DBGC ( dns, "DNS %p received response with %d questions\n",
704  dns, ntohs ( response->qdcount ) );
705  rc = -EINVAL;
706  goto done;
707  }
708 
709  /* Skip question section */
710  buf.data = iobuf->data;
711  buf.offset = sizeof ( *response );
712  buf.len = iob_len ( iobuf );
713  offset = dns_skip ( &buf );
714  if ( offset < 0 ) {
715  rc = offset;
716  DBGC ( dns, "DNS %p received response with malformed "
717  "question: %s\n", dns, strerror ( rc ) );
718  goto done;
719  }
720  answer_offset = ( offset + sizeof ( struct dns_question ) );
721 
722  /* Search through response for useful answers. Do this
723  * multiple times, to take advantage of useful nameservers
724  * which send us e.g. the CNAME *and* the A record for the
725  * pointed-to name.
726  */
727  for ( buf.offset = answer_offset ; buf.offset != buf.len ;
728  buf.offset = next_offset ) {
729 
730  /* Check for valid name */
731  offset = dns_skip ( &buf );
732  if ( offset < 0 ) {
733  rc = offset;
734  DBGC ( dns, "DNS %p received response with malformed "
735  "answer: %s\n", dns, strerror ( rc ) );
736  goto done;
737  }
738 
739  /* Check for sufficient space for resource record */
740  rr = ( buf.data + offset );
741  if ( ( offset + sizeof ( rr->common ) ) > buf.len ) {
742  DBGC ( dns, "DNS %p received response with underlength "
743  "RR\n", dns );
744  rc = -EINVAL;
745  goto done;
746  }
747  rdlength = ntohs ( rr->common.rdlength );
748  next_offset = ( offset + sizeof ( rr->common ) + rdlength );
749  if ( next_offset > buf.len ) {
750  DBGC ( dns, "DNS %p received response with underlength "
751  "RR\n", dns );
752  rc = -EINVAL;
753  goto done;
754  }
755 
756  /* Skip non-matching names */
757  if ( dns_compare ( &buf, &dns->name ) != 0 ) {
758  DBGC2 ( dns, "DNS %p ignoring response for %s type "
759  "%s\n", dns, dns_name ( &buf ),
760  dns_type ( rr->common.type ) );
761  continue;
762  }
763 
764  /* Handle answer */
765  switch ( rr->common.type ) {
766 
767  case htons ( DNS_TYPE_AAAA ):
768 
769  /* Found the target AAAA record */
770  if ( rdlength < sizeof ( dns->address.sin6.sin6_addr )){
771  DBGC ( dns, "DNS %p received response with "
772  "underlength AAAA\n", dns );
773  rc = -EINVAL;
774  goto done;
775  }
777  memcpy ( &dns->address.sin6.sin6_addr,
778  &rr->aaaa.in6_addr,
779  sizeof ( dns->address.sin6.sin6_addr ) );
780  dns_resolved ( dns );
781  rc = 0;
782  goto done;
783 
784  case htons ( DNS_TYPE_A ):
785 
786  /* Found the target A record */
787  if ( rdlength < sizeof ( dns->address.sin.sin_addr ) ) {
788  DBGC ( dns, "DNS %p received response with "
789  "underlength A\n", dns );
790  rc = -EINVAL;
791  goto done;
792  }
793  dns->address.sin.sin_family = AF_INET;
794  dns->address.sin.sin_addr = rr->a.in_addr;
795  dns_resolved ( dns );
796  rc = 0;
797  goto done;
798 
799  case htons ( DNS_TYPE_CNAME ):
800 
801  /* Terminate the operation if we recurse too far */
802  if ( ++dns->recursion > DNS_MAX_CNAME_RECURSION ) {
803  DBGC ( dns, "DNS %p recursion exceeded\n",
804  dns );
805  rc = -ELOOP;
806  dns_done ( dns, rc );
807  goto done;
808  }
809 
810  /* Found a CNAME record; update query and recurse */
811  buf.offset = ( offset + sizeof ( rr->cname ) );
812  DBGC ( dns, "DNS %p found CNAME %s\n",
813  dns, dns_name ( &buf ) );
814  dns->search.offset = dns->search.len;
815  name_len = dns_copy ( &buf, &dns->name );
816  dns->offset = ( offsetof ( typeof ( dns->buf ), name ) +
817  name_len - 1 /* Strip root label */ );
818  if ( ( rc = dns_question ( dns ) ) != 0 ) {
819  dns_done ( dns, rc );
820  goto done;
821  }
822  next_offset = answer_offset;
823  break;
824 
825  default:
826  DBGC ( dns, "DNS %p got unknown record type %d\n",
827  dns, ntohs ( rr->common.type ) );
828  break;
829  }
830  }
831 
832  /* Stop the retry timer. After this point, each code path
833  * must either restart the timer by calling dns_send_packet(),
834  * or mark the DNS operation as complete by calling
835  * dns_done()
836  */
837  stop_timer ( &dns->timer );
838 
839  /* Determine what to do next based on the type of query we
840  * issued and the response we received
841  */
842  switch ( qtype ) {
843 
844  case htons ( DNS_TYPE_AAAA ):
845  /* We asked for an AAAA record and got nothing; try
846  * the A.
847  */
848  DBGC ( dns, "DNS %p found no AAAA record; trying A\n", dns );
849  dns->question->qtype = htons ( DNS_TYPE_A );
850  dns_send_packet ( dns );
851  rc = 0;
852  goto done;
853 
854  case htons ( DNS_TYPE_A ):
855  /* We asked for an A record and got nothing;
856  * try the CNAME.
857  */
858  DBGC ( dns, "DNS %p found no A record; trying CNAME\n", dns );
859  dns->question->qtype = htons ( DNS_TYPE_CNAME );
860  dns_send_packet ( dns );
861  rc = 0;
862  goto done;
863 
864  case htons ( DNS_TYPE_CNAME ):
865  /* We asked for a CNAME record. If we got a response
866  * (i.e. if the next AAAA/A query is already set up),
867  * then issue it.
868  */
869  if ( qtype == dns->qtype ) {
870  dns_send_packet ( dns );
871  rc = 0;
872  goto done;
873  }
874 
875  /* If we have already reached the end of the search list,
876  * then terminate lookup.
877  */
878  if ( dns->search.offset == dns->search.len ) {
879  DBGC ( dns, "DNS %p found no CNAME record\n", dns );
880  rc = -ENXIO_NO_RECORD;
881  dns_done ( dns, rc );
882  goto done;
883  }
884 
885  /* Move to next entry in search list. This can never fail,
886  * since we have already used this entry.
887  */
888  DBGC ( dns, "DNS %p found no CNAME record; trying next "
889  "suffix\n", dns );
890  dns->search.offset = dns_skip_search ( &dns->search );
891  if ( ( rc = dns_question ( dns ) ) != 0 ) {
892  dns_done ( dns, rc );
893  goto done;
894  }
895  dns_send_packet ( dns );
896  goto done;
897 
898  default:
899  assert ( 0 );
900  rc = -EINVAL;
901  dns_done ( dns, rc );
902  goto done;
903  }
904 
905  done:
906  /* Free I/O buffer */
907  free_iob ( iobuf );
908  return rc;
909 }
910 
911 /**
912  * Receive new data
913  *
914  * @v dns DNS request
915  * @v rc Reason for close
916  */
917 static void dns_xfer_close ( struct dns_request *dns, int rc ) {
918 
919  if ( ! rc )
920  rc = -ECONNABORTED;
921 
922  dns_done ( dns, rc );
923 }
924 
925 /**
926  * Report job progress
927  *
928  * @v dns DNS request
929  * @v progress Progress report to fill in
930  * @ret ongoing_rc Ongoing job status code (if known)
931  */
932 static int dns_progress ( struct dns_request *dns,
933  struct job_progress *progress ) {
934  int len;
935 
936  /* Show current question as progress message */
937  len = dns_decode ( &dns->name, progress->message,
938  ( sizeof ( progress->message ) - 1 /* NUL */ ) );
939  if ( len < 0 ) {
940  /* Ignore undecodable names */
941  progress->message[0] = '\0';
942  }
943 
944  return 0;
945 }
946 
947 /** DNS socket interface operations */
951 };
952 
953 /** DNS socket interface descriptor */
955  INTF_DESC ( struct dns_request, socket, dns_socket_operations );
956 
957 /** DNS resolver interface operations */
960  INTF_OP ( intf_close, struct dns_request *, dns_done ),
961 };
962 
963 /** DNS resolver interface descriptor */
966 
967 /**
968  * Resolve name using DNS
969  *
970  * @v resolv Name resolution interface
971  * @v name Name to resolve
972  * @v sa Socket address to fill in
973  * @ret rc Return status code
974  */
975 static int dns_resolv ( struct interface *resolv,
976  const char *name, struct sockaddr *sa ) {
977  struct dns_request *dns;
978  struct dns_header *query;
979  size_t search_len;
980  int name_len;
981  int rc;
982 
983  /* Fail immediately if no DNS servers */
984  if ( dns_count == 0 ) {
985  DBG ( "DNS not attempting to resolve \"%s\": "
986  "no DNS servers\n", name );
988  goto err_no_nameserver;
989  }
990 
991  /* Determine whether or not to use search list */
992  search_len = ( strchr ( name, '.' ) ? 0 : dns_search.len );
993 
994  /* Allocate DNS structure */
995  dns = zalloc ( sizeof ( *dns ) + search_len );
996  if ( ! dns ) {
997  rc = -ENOMEM;
998  goto err_alloc_dns;
999  }
1000  ref_init ( &dns->refcnt, NULL );
1001  intf_init ( &dns->resolv, &dns_resolv_desc, &dns->refcnt );
1002  intf_init ( &dns->socket, &dns_socket_desc, &dns->refcnt );
1003  timer_init ( &dns->timer, dns_timer_expired, &dns->refcnt );
1004  memcpy ( &dns->address.sa, sa, sizeof ( dns->address.sa ) );
1005  dns->search.data = ( ( ( void * ) dns ) + sizeof ( *dns ) );
1006  dns->search.len = search_len;
1007  memcpy ( dns->search.data, dns_search.data, search_len );
1008 
1009  /* Determine initial query type */
1010  dns->qtype = ( ( dns6.count != 0 ) ?
1011  htons ( DNS_TYPE_AAAA ) : htons ( DNS_TYPE_A ) );
1012 
1013  /* Construct query */
1014  query = &dns->buf.query;
1015  query->flags = htons ( DNS_FLAG_RD );
1016  query->qdcount = htons ( 1 );
1017  dns->name.data = &dns->buf;
1018  dns->name.offset = offsetof ( typeof ( dns->buf ), name );
1019  dns->name.len = offsetof ( typeof ( dns->buf ), padding );
1020  name_len = dns_encode ( name, &dns->name );
1021  if ( name_len < 0 ) {
1022  rc = name_len;
1023  goto err_encode;
1024  }
1025  dns->offset = ( offsetof ( typeof ( dns->buf ), name ) +
1026  name_len - 1 /* Strip root label */ );
1027  if ( ( rc = dns_question ( dns ) ) != 0 )
1028  goto err_question;
1029 
1030  /* Open UDP connection */
1031  if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM,
1032  NULL, NULL ) ) != 0 ) {
1033  DBGC ( dns, "DNS %p could not open socket: %s\n",
1034  dns, strerror ( rc ) );
1035  goto err_open_socket;
1036  }
1037 
1038  /* Start timer to trigger first packet */
1039  start_timer_nodelay ( &dns->timer );
1040 
1041  /* Attach parent interface, mortalise self, and return */
1042  intf_plug_plug ( &dns->resolv, resolv );
1043  ref_put ( &dns->refcnt );
1044  return 0;
1045 
1046  err_open_socket:
1047  err_question:
1048  err_encode:
1049  ref_put ( &dns->refcnt );
1050  err_alloc_dns:
1051  err_no_nameserver:
1052  return rc;
1053 }
1054 
1055 /** DNS name resolver */
1056 struct resolver dns_resolver __resolver ( RESOLV_NORMAL ) = {
1057  .name = "DNS",
1058  .resolv = dns_resolv,
1059 };
1060 
1061 /******************************************************************************
1062  *
1063  * Settings
1064  *
1065  ******************************************************************************
1066  */
1067 
1068 /**
1069  * Format DNS search list setting
1070  *
1071  * @v type Setting type
1072  * @v raw Raw setting value
1073  * @v raw_len Length of raw setting value
1074  * @v buf Buffer to contain formatted value
1075  * @v len Length of buffer
1076  * @ret len Length of formatted value, or negative error
1077  */
1078 static int format_dnssl_setting ( const struct setting_type *type __unused,
1079  const void *raw, size_t raw_len,
1080  char *buf, size_t len ) {
1081  struct dns_name name = {
1082  .data = ( ( void * ) raw ),
1083  .len = raw_len,
1084  };
1085  size_t remaining = len;
1086  size_t total = 0;
1087  int name_len;
1088 
1089  while ( name.offset < raw_len ) {
1090 
1091  /* Decode name */
1092  remaining = ( ( total < len ) ? ( len - total ) : 0 );
1093  name_len = dns_decode ( &name, ( buf + total ), remaining );
1094  if ( name_len < 0 )
1095  return name_len;
1096  total += name_len;
1097 
1098  /* Move to next name */
1099  name.offset = dns_skip_search ( &name );
1100 
1101  /* Add separator if applicable */
1102  if ( name.offset != raw_len ) {
1103  if ( total < len )
1104  buf[total] = ' ';
1105  total++;
1106  }
1107  }
1108 
1109  return total;
1110 }
1111 
1112 /** A DNS search list setting type */
1113 const struct setting_type setting_type_dnssl __setting_type = {
1114  .name = "dnssl",
1115  .format = format_dnssl_setting,
1116 };
1117 
1118 /** IPv4 DNS server setting */
1119 const struct setting dns_setting __setting ( SETTING_IP4_EXTRA, dns ) = {
1120  .name = "dns",
1121  .description = "DNS server",
1122  .tag = DHCP_DNS_SERVERS,
1123  .type = &setting_type_ipv4,
1124 };
1125 
1126 /** IPv6 DNS server setting */
1127 const struct setting dns6_setting __setting ( SETTING_IP6_EXTRA, dns6 ) = {
1128  .name = "dns6",
1129  .description = "DNS server",
1130  .tag = DHCPV6_DNS_SERVERS,
1131  .type = &setting_type_ipv6,
1132  .scope = &dhcpv6_scope,
1133 };
1134 
1135 /** DNS search list */
1136 const struct setting dnssl_setting __setting ( SETTING_IP_EXTRA, dnssl ) = {
1137  .name = "dnssl",
1138  .description = "DNS search list",
1139  .tag = DHCP_DOMAIN_SEARCH,
1140  .type = &setting_type_dnssl,
1141 };
1142 
1143 /**
1144  * Apply DNS server addresses
1145  *
1146  */
1147 static void apply_dns_servers ( void ) {
1148  int len;
1149 
1150  /* Free existing server addresses */
1151  free ( dns4.data );
1152  free ( dns6.data );
1153  dns4.data = NULL;
1154  dns6.data = NULL;
1155  dns4.count = 0;
1156  dns6.count = 0;
1157 
1158  /* Fetch DNS server addresses */
1159  len = fetch_raw_setting_copy ( NULL, &dns_setting, &dns4.data );
1160  if ( len >= 0 )
1161  dns4.count = ( len / sizeof ( dns4.in[0] ) );
1162  len = fetch_raw_setting_copy ( NULL, &dns6_setting, &dns6.data );
1163  if ( len >= 0 )
1164  dns6.count = ( len / sizeof ( dns6.in6[0] ) );
1165  dns_count = ( dns4.count + dns6.count );
1166 }
1167 
1168 /**
1169  * Apply DNS search list
1170  *
1171  */
1172 static void apply_dns_search ( void ) {
1173  char *localdomain;
1174  int len;
1175 
1176  /* Free existing search list */
1177  free ( dns_search.data );
1178  memset ( &dns_search, 0, sizeof ( dns_search ) );
1179 
1180  /* Fetch DNS search list */
1181  len = fetch_raw_setting_copy ( NULL, &dnssl_setting, &dns_search.data );
1182  if ( len >= 0 ) {
1183  dns_search.len = len;
1184  return;
1185  }
1186 
1187  /* If no DNS search list exists, try to fetch the local domain */
1188  fetch_string_setting_copy ( NULL, &domain_setting, &localdomain );
1189  if ( localdomain ) {
1190  len = dns_encode ( localdomain, &dns_search );
1191  if ( len >= 0 ) {
1192  dns_search.data = malloc ( len );
1193  if ( dns_search.data ) {
1194  dns_search.len = len;
1195  dns_encode ( localdomain, &dns_search );
1196  }
1197  }
1198  free ( localdomain );
1199  return;
1200  }
1201 }
1202 
1203 /**
1204  * Apply DNS settings
1205  *
1206  * @ret rc Return status code
1207  */
1208 static int apply_dns_settings ( void ) {
1209  void *dbgcol = &dns_count;
1210 
1211  /* Fetch DNS server address */
1213  if ( DBG_EXTRA && ( dns_count != 0 ) ) {
1214  union {
1215  struct sockaddr sa;
1216  struct sockaddr_in sin;
1217  struct sockaddr_in6 sin6;
1218  } u;
1219  unsigned int i;
1220 
1221  DBGC2 ( dbgcol, "DNS servers:" );
1222  for ( i = 0 ; i < dns6.count ; i++ ) {
1223  u.sin6.sin6_family = AF_INET6;
1224  memcpy ( &u.sin6.sin6_addr, &dns6.in6[i],
1225  sizeof ( u.sin6.sin6_addr ) );
1226  DBGC2 ( dbgcol, " %s", sock_ntoa ( &u.sa ) );
1227  }
1228  for ( i = 0 ; i < dns4.count ; i++ ) {
1229  u.sin.sin_family = AF_INET;
1230  u.sin.sin_addr = dns4.in[i];
1231  DBGC2 ( dbgcol, " %s", sock_ntoa ( &u.sa ) );
1232  }
1233  DBGC2 ( dbgcol, "\n" );
1234  }
1235 
1236  /* Fetch DNS search list */
1237  apply_dns_search();
1238  if ( DBG_EXTRA && ( dns_search.len != 0 ) ) {
1239  struct dns_name name;
1240  int offset;
1241 
1242  DBGC2 ( dbgcol, "DNS search list:" );
1243  memcpy ( &name, &dns_search, sizeof ( name ) );
1244  while ( name.offset != name.len ) {
1245  DBGC2 ( dbgcol, " %s", dns_name ( &name ) );
1246  offset = dns_skip_search ( &name );
1247  if ( offset < 0 )
1248  break;
1249  name.offset = offset;
1250  }
1251  DBGC2 ( dbgcol, "\n" );
1252  }
1253 
1254  return 0;
1255 }
1256 
1257 /** DNS settings applicator */
1260 };
struct dns_rr_common common
Common fields.
Definition: dns.h:140
uint32_t c
Definition: md4.c:30
#define __attribute__(x)
Definition: compiler.h:10
#define EINVAL
Invalid argument.
Definition: errno.h:428
An object interface operation.
Definition: interface.h:17
#define SETTING_IP_EXTRA
IPv4 additional settings.
Definition: settings.h:70
#define DNS_TYPE_CNAME
Type of a DNS "NAME" record.
Definition: dns.h:129
TCP/IP socket address.
Definition: tcpip.h:75
size_t offset
Offset of search suffix within current query.
Definition: dns.c:486
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1984
unsigned short uint16_t
Definition: stdint.h:11
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
uint16_t qdcount
Number of question records.
Definition: dns.h:71
#define ENXIO_NO_NAMESERVER
Definition: dns.c:62
#define DNS_MAX_LABEL_LEN
Maximum length of a single DNS label.
Definition: dns.h:53
Dynamic Host Configuration Protocol.
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
#define AF_INET6
IPv6 Internet addresses.
Definition: socket.h:64
struct dns_question * question
Question within current query.
Definition: dns.c:482
int dns_skip(struct dns_name *name)
Skip RFC1035-encoded DNS name.
Definition: dns.c:364
#define DHCP_EB_FEATURE_DNS
DNS protocol.
Definition: features.h:43
static void apply_dns_servers(void)
Apply DNS server addresses.
Definition: dns.c:1147
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition: retry.h:99
static void dns_done(struct dns_request *dns, int rc)
Mark DNS request as complete.
Definition: dns.c:501
const struct settings_scope dhcpv6_scope
IPv6 settings scope.
Definition: settings.c:1792
#define DNS_COMPRESSED_OFFSET(word)
Extract DNS compression pointer.
Definition: dns.h:42
A DNS packet header.
Definition: dns.h:65
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:267
#define FEATURE_PROTOCOL
Network protocols.
Definition: features.h:21
#define DNS_FLAG_RD
Recursion desired flag.
Definition: dns.h:81
static struct dns_server dns4
IPv4 DNS server list.
Definition: dns.c:82
static int dns_question(struct dns_request *dns)
Construct DNS question.
Definition: dns.c:535
int fetch_raw_setting_copy(struct settings *settings, const struct setting *setting, void **data)
Fetch value of setting.
Definition: settings.c:821
void resolv_done(struct interface *intf, struct sockaddr *sa)
Name resolved.
Definition: resolv.c:55
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition: open.c:142
uint16_t type
Type.
Definition: dns.h:97
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
static void dns_timer_expired(struct retry_timer *timer, int fail)
Handle DNS (re)transmission timer expiry.
Definition: dns.c:641
Name resolution.
static __always_inline int off_t userptr_t second
Definition: efi_uaccess.h:80
uint32_t type
Operating system type.
Definition: ena.h:12
#define SOCK_DGRAM
Definition: socket.h:29
Retry timers.
static struct interface_operation dns_socket_operations[]
DNS socket interface operations.
Definition: dns.c:948
struct in_addr * in
IPv4 addresses.
Definition: dns.c:71
#define DBGC(...)
Definition: compiler.h:505
unsigned int index
Server index.
Definition: dns.c:490
struct sockaddr_in6 sin6
Definition: syslog.c:58
A retry timer.
Definition: retry.h:21
#define ENOENT
No such file or directory.
Definition: errno.h:514
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:107
static void dns_xfer_close(struct dns_request *dns, int rc)
Receive new data.
Definition: dns.c:917
struct in6_addr in6_addr
IPv6 address.
Definition: dns.h:125
A settings applicator.
Definition: settings.h:251
struct in_addr in_addr
IPv4 address.
Definition: dns.h:114
IPv4 socket address.
Definition: in.h:82
#define ntohs(value)
Definition: byteswap.h:136
unsigned int recursion
Recursion counter.
Definition: dns.c:492
static const char * dns_name(struct dns_name *name)
Transcribe DNS name (for debugging)
Definition: dns.c:428
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
Character types.
void * data
Start of data.
Definition: dns.h:21
unsigned int count
Number of servers.
Definition: dns.c:78
sa_family_t sin_family
Socket address family (part of struct sockaddr)
Definition: in.h:87
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define DNS_PORT
DNS server port.
Definition: dns.h:16
static unsigned int dns_count
Total number of DNS servers.
Definition: dns.c:88
#define ELOOP
Too many levels of symbolic links.
Definition: errno.h:448
static const char * dns_type(uint16_t type)
Name a DNS query type (for debugging)
Definition: dns.c:442
Data transfer interfaces.
A reference counter.
Definition: refcnt.h:26
A timer.
Definition: timer.h:28
const char * name
Name.
Definition: settings.h:28
struct sockaddr_tcpip st
Definition: syslog.c:56
void * data
Raw data.
Definition: dns.c:75
uint32_t start
Starting offset.
Definition: netvsc.h:12
struct refcnt refcnt
Reference counter.
Definition: dns.c:454
static int dns_xfer_deliver(struct dns_request *dns, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive new data.
Definition: dns.c:667
#define DNS_TYPE_A
Type of a DNS "A" record.
Definition: dns.h:107
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
A DNS resource record.
Definition: dns.h:138
static int dns_progress(struct dns_request *dns, struct job_progress *progress)
Report job progress.
Definition: dns.c:932
const struct setting_type setting_type_dnssl __setting_type
A DNS search list setting type.
Definition: dns.c:1113
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static struct dns_name dns_search
The DNS search list.
Definition: dns.c:91
#define SETTING_IP4_EXTRA
IPv4 additional settings.
Definition: settings.h:66
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
uint16_t qtype
Query type.
Definition: dns.h:86
An object interface.
Definition: interface.h:124
An RFC1035-encoded DNS name.
Definition: dns.h:19
struct dns_request::@5 buf
Buffer for current query.
size_t len
Length of current query.
Definition: dns.c:484
struct sockaddr_in6 sin6
Definition: dns.c:466
static int tolower(int character)
Convert character to lower case.
Definition: ctype.h:97
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
struct sockaddr sa
Definition: syslog.c:55
Transport-network layer interface.
Feature list.
static int dns_send_packet(struct dns_request *dns)
Send DNS query.
Definition: dns.c:587
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition: settings.c:873
IP6 address structure.
Definition: in.h:48
struct sockaddr sa
Definition: dns.c:464
size_t offset
Offset of name within data.
Definition: dns.h:23
#define DNS_TYPE_AAAA
Type of a DNS "AAAA" record.
Definition: dns.h:118
#define DHCP_DOMAIN_SEARCH
DNS domain search list.
Definition: dhcp.h:324
struct interface resolv
Name resolution interface.
Definition: dns.c:456
static __always_inline void off_t userptr_t src
Definition: efi_uaccess.h:66
int meta(WINDOW *, bool)
Configuration settings.
static size_t raw_len
Definition: base16.h:50
Generalized socket address structure.
Definition: socket.h:96
An object interface descriptor.
Definition: interface.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
IP address structure.
Definition: in.h:39
uint16_t flags
Flags.
Definition: dns.h:69
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:271
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
struct dns_header query
Query header.
Definition: dns.c:473
Job progress.
Definition: job.h:15
int dns_copy(struct dns_name *src, struct dns_name *dst)
Copy a DNS name.
Definition: dns.c:321
#define ECONNABORTED
Connection aborted.
Definition: errno.h:353
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:30
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:193
int dns_encode(const char *string, struct dns_name *name)
Encode a DNS name using RFC1035 encoding.
Definition: dns.c:100
#define DHCPV6_DNS_SERVERS
DHCPv6 DNS recursive name server option.
Definition: dhcpv6.h:164
#define DNS_MAX_CNAME_RECURSION
Maximum depth of CNAME recursion.
Definition: dns.h:62
unsigned char uint8_t
Definition: stdint.h:10
struct dns_rr_a a
"A" record
Definition: dns.h:142
Data transfer interface opening.
#define ENXIO_NO_RECORD
Definition: dns.c:59
static int dns_resolv(struct interface *resolv, const char *name, struct sockaddr *sa)
Resolve name using DNS.
Definition: dns.c:975
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
unsigned char byte
Definition: smc9000.h:38
A DNS request.
Definition: dns.c:452
A setting.
Definition: settings.h:23
Job control interfaces.
static void apply_dns_search(void)
Apply DNS search list.
Definition: dns.c:1172
char message[32]
Message (optional)
Definition: job.h:32
void start_timer(struct retry_timer *timer)
Start timer.
Definition: retry.c:93
#define DNS_MAX_NAME_LEN
Maximum length of a DNS name (mandated by RFC1035 section 2.3.4)
Definition: dns.h:56
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
char name[DNS_MAX_NAME_LEN]
Name buffer.
Definition: dns.c:475
struct in_addr sin_addr
IPv4 address.
Definition: in.h:98
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
#define DNS_IS_COMPRESSED(byte)
Test for a DNS compression pointer.
Definition: dns.h:34
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
struct interface socket
Data transfer interface.
Definition: dns.c:458
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition: socket.c:42
A DNS question.
Definition: dns.h:84
uint16_t qclass
Query class.
Definition: dns.h:88
struct dns_rr_aaaa aaaa
"AAAA" record
Definition: dns.h:144
static struct interface_descriptor dns_socket_desc
DNS socket interface descriptor.
Definition: dns.c:954
A DNS server list.
Definition: dns.c:67
uint16_t id
Query identifier.
Definition: dns.h:67
static struct interface_operation dns_resolv_op[]
DNS resolver interface operations.
Definition: dns.c:958
uint32_t len
Length.
Definition: ena.h:14
#define DBGC2(...)
Definition: compiler.h:522
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:1078
#define SETTING_IP6_EXTRA
IPv6 additional settings.
Definition: settings.h:68
A name resolver.
Definition: resolv.h:18
static int dns_skip_search(struct dns_name *name)
Skip RFC1035-encoded DNS name in search list.
Definition: dns.c:403
void * data
Start of data.
Definition: iobuf.h:48
struct dns_name search
Search list.
Definition: dns.c:488
#define DNS_CLASS_IN
DNS class "IN".
Definition: dns.h:92
struct retry_timer timer
Retry timer.
Definition: dns.c:460
struct resolver dns_resolver __resolver(RESOLV_NORMAL)
DNS name resolver.
uint16_t qtype
Initial query type.
Definition: dns.c:469
const char * name
Name.
Definition: settings.h:196
unsigned short word
Definition: smc9000.h:39
static int apply_dns_settings(void)
Apply DNS settings.
Definition: dns.c:1208
union @17 u
Reference counting.
uint32_t end
Ending offset.
Definition: netvsc.h:18
int dns_compare(struct dns_name *first, struct dns_name *second)
Compare DNS names for equality.
Definition: dns.c:267
const char * name
Name of this resolver (e.g.
Definition: resolv.h:20
#define DHCP_DNS_SERVERS
DNS servers.
Definition: dhcp.h:72
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:162
__be32 raw[7]
Definition: CIB_PRM.h:28
struct settings_applicator dns_applicator __settings_applicator
DNS settings applicator.
Definition: dns.c:1258
static struct interface_descriptor dns_resolv_desc
DNS resolver interface descriptor.
Definition: dns.c:964
IPv6 socket address.
Definition: in.h:115
int(* apply)(void)
Apply updated settings.
Definition: settings.h:256
int resolv(struct interface *resolv, const char *name, struct sockaddr *sa)
Start name resolution.
Definition: resolv.c:257
int dns_decode(struct dns_name *name, char *data, size_t len)
Decode RFC1035-encoded DNS name.
Definition: dns.c:216
sa_family_t sin6_family
Socket address family (part of struct sockaddr)
Definition: in.h:120
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition: acpi.c:45
#define DBG_EXTRA
Definition: compiler.h:319
struct sockaddr_in sin
Definition: syslog.c:57
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
FEATURE(FEATURE_PROTOCOL, "DNS", DHCP_EB_FEATURE_DNS, 1)
uint64_t index
Index of the first segment within the content.
Definition: pccrc.h:21
size_t len
Total length of data.
Definition: dns.h:25
struct sockaddr_in sin
Definition: dns.c:465
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:190
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct in6_addr * in6
IPv6 addresses.
Definition: dns.c:73
const struct setting dns_setting __setting(SETTING_IP4_EXTRA, dns)
IPv4 DNS server setting.
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:669
String functions.
union dns_request::@4 address
Socket address to fill in with resolved address.
uint16_t rdlength
Resource data length.
Definition: dns.h:103
#define htons(value)
Definition: byteswap.h:135
struct bofm_section_header done
Definition: bofm_test.c:46
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:23
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63
A setting type.
Definition: settings.h:191
struct in6_addr sin6_addr
IPv6 address.
Definition: in.h:132
struct dns_question padding
Space for question.
Definition: dns.c:477
DNS protocol.
static struct dns_server dns6
IPv6 DNS server list.
Definition: dns.c:85
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
Dynamic Host Configuration Protocol for IPv6.
struct dns_rr_cname cname
"CNAME" record
Definition: dns.h:146
void * memset(void *dest, int character, size_t len) __nonnull
#define RESOLV_NORMAL
Normal resolver priority.
Definition: resolv.h:36
A persistent I/O buffer.
Definition: iobuf.h:33
static void dns_resolved(struct dns_request *dns)
Mark DNS request as resolved and complete.
Definition: dns.c:517