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 FILE_SECBOOT ( PERMITTED );
29 
30 #include <stdint.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <errno.h>
36 #include <byteswap.h>
37 #include <ipxe/refcnt.h>
38 #include <ipxe/iobuf.h>
39 #include <ipxe/xfer.h>
40 #include <ipxe/open.h>
41 #include <ipxe/resolv.h>
42 #include <ipxe/retry.h>
43 #include <ipxe/tcpip.h>
44 #include <ipxe/settings.h>
45 #include <ipxe/features.h>
46 #include <ipxe/job.h>
47 #include <ipxe/dhcp.h>
48 #include <ipxe/dhcpv6.h>
49 #include <ipxe/dns.h>
50 
51 /** @file
52  *
53  * DNS protocol
54  *
55  */
56 
58 
59 /* Disambiguate the various error causes */
60 #define ENXIO_NO_RECORD __einfo_error ( EINFO_ENXIO_NO_RECORD )
61 #define EINFO_ENXIO_NO_RECORD \
62  __einfo_uniqify ( EINFO_ENXIO, 0x01, "DNS name does not exist" )
63 #define ENXIO_NO_NAMESERVER __einfo_error ( EINFO_ENXIO_NO_NAMESERVER )
64 #define EINFO_ENXIO_NO_NAMESERVER \
65  __einfo_uniqify ( EINFO_ENXIO, 0x02, "No DNS servers available" )
66 
67 /** A DNS server list */
68 struct dns_server {
69  /** Server list */
70  union {
71  /** IPv4 addresses */
72  struct in_addr *in;
73  /** IPv6 addresses */
74  struct in6_addr *in6;
75  /** Raw data */
76  void *data;
77  };
78  /** Number of servers */
79  unsigned int count;
80 };
81 
82 /** IPv4 DNS server list */
83 static struct dns_server dns4;
84 
85 /** IPv6 DNS server list */
86 static struct dns_server dns6;
87 
88 /** Total number of DNS servers */
89 static unsigned int dns_count;
90 
91 /** The DNS search list */
92 static struct dns_name dns_search;
93 
94 /**
95  * Encode a DNS name using RFC1035 encoding
96  *
97  * @v string DNS name as a string
98  * @v name DNS name to fill in
99  * @ret len Length of DNS name, or negative error
100  */
101 int dns_encode ( const char *string, struct dns_name *name ) {
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 }
155 
156 /**
157  * Find start of valid label within an RFC1035-encoded DNS name
158  *
159  * @v name DNS name
160  * @v offset Current offset
161  * @ret offset Offset of label, or negative error
162  */
163 static int dns_label ( struct dns_name *name, size_t offset ) {
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 }
208 
209 /**
210  * Decode RFC1035-encoded DNS name
211  *
212  * @v name DNS name
213  * @v data Output buffer
214  * @v len Length of output buffer
215  * @ret len Length of decoded DNS name, or negative error
216  */
217 int dns_decode ( struct dns_name *name, char *data, size_t len ) {
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 */
228  offset = dns_label ( name, offset );
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 }
260 
261 /**
262  * Compare DNS names for equality
263  *
264  * @v first First DNS name
265  * @v second Second DNS name
266  * @ret rc Return status code
267  */
268 int dns_compare ( struct dns_name *first, struct dns_name *second ) {
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 }
314 
315 /**
316  * Copy a DNS name
317  *
318  * @v src Source DNS name
319  * @v dst Destination DNS name
320  * @ret len Length of copied DNS name, or negative error
321  */
322 int dns_copy ( struct dns_name *src, struct dns_name *dst ) {
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 }
358 
359 /**
360  * Skip RFC1035-encoded DNS name
361  *
362  * @v name DNS name
363  * @ret offset Offset to next name, or negative error
364  */
365 int dns_skip ( struct dns_name *name ) {
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 }
397 
398 /**
399  * Skip RFC1035-encoded DNS name in search list
400  *
401  * @v name DNS name
402  * @ret offset Offset to next non-empty name, or negative error
403  */
404 static int dns_skip_search ( struct dns_name *name ) {
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 }
422 
423 /**
424  * Transcribe DNS name (for debugging)
425  *
426  * @v name DNS name
427  * @ret string Transcribed DNS name
428  */
429 static const char * dns_name ( struct dns_name *name ) {
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 }
436 
437 /**
438  * Name a DNS query type (for debugging)
439  *
440  * @v type Query type (in network byte order)
441  * @ret name Type name
442  */
443 static const char * dns_type ( uint16_t type ) {
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 }
451 
452 /** A DNS request */
453 struct dns_request {
454  /** Reference counter */
455  struct refcnt refcnt;
456  /** Name resolution interface */
458  /** Data transfer interface */
460  /** Retry timer */
462 
463  /** Socket address to fill in with resolved address */
464  union {
465  struct sockaddr sa;
466  struct sockaddr_in sin;
468  } address;
469  /** Initial query type */
471  /** Buffer for current query */
472  struct {
473  /** Query header */
475  /** Name buffer */
477  /** Space for question */
479  } __attribute__ (( packed )) buf;
480  /** Current query name */
481  struct dns_name name;
482  /** Question within current query */
484  /** Length of current query */
485  size_t len;
486  /** Offset of search suffix within current query */
487  size_t offset;
488  /** Search list */
489  struct dns_name search;
490  /** Server index */
491  unsigned int index;
492  /** Recursion counter */
493  unsigned int recursion;
494 };
495 
496 /**
497  * Mark DNS request as complete
498  *
499  * @v dns DNS request
500  * @v rc Return status code
501  */
502 static void dns_done ( struct dns_request *dns, int rc ) {
503 
504  /* Stop the retry timer */
505  stop_timer ( &dns->timer );
506 
507  /* Shut down interfaces */
508  intf_shutdown ( &dns->socket, rc );
509  intf_shutdown ( &dns->resolv, rc );
510 }
511 
512 /**
513  * Mark DNS request as resolved and complete
514  *
515  * @v dns DNS request
516  * @v rc Return status code
517  */
518 static void dns_resolved ( struct dns_request *dns ) {
519 
520  DBGC ( dns, "DNS %p found address %s\n",
521  dns, sock_ntoa ( &dns->address.sa ) );
522 
523  /* Return resolved address */
524  resolv_done ( &dns->resolv, &dns->address.sa );
525 
526  /* Mark operation as complete */
527  dns_done ( dns, 0 );
528 }
529 
530 /**
531  * Construct DNS question
532  *
533  * @v dns DNS request
534  * @ret rc Return status code
535  */
536 static int dns_question ( struct dns_request *dns ) {
537  static struct dns_name search_root = {
538  .data = "",
539  .len = 1,
540  };
541  struct dns_name *search = &dns->search;
542  int len;
543  size_t offset;
544 
545  /* Use root suffix if search list is empty */
546  if ( search->offset == search->len )
547  search = &search_root;
548 
549  /* Overwrite current suffix */
550  dns->name.offset = dns->offset;
551  len = dns_copy ( search, &dns->name );
552  if ( len < 0 )
553  return len;
554 
555  /* Sanity check */
556  offset = ( dns->name.offset + len );
557  if ( offset > dns->name.len ) {
558  DBGC ( dns, "DNS %p name is too long\n", dns );
559  return -EINVAL;
560  }
561 
562  /* Construct question */
563  dns->question = ( ( ( void * ) &dns->buf ) + offset );
564  dns->question->qtype = dns->qtype;
565  dns->question->qclass = htons ( DNS_CLASS_IN );
566 
567  /* Store length */
568  dns->len = ( offset + sizeof ( *(dns->question) ) );
569 
570  /* Restore name */
571  dns->name.offset = offsetof ( typeof ( dns->buf ), name );
572 
573  /* Reset query ID */
574  dns->buf.query.id = 0;
575 
576  DBGC2 ( dns, "DNS %p question is %s type %s\n", dns,
577  dns_name ( &dns->name ), dns_type ( dns->question->qtype ) );
578 
579  return 0;
580 }
581 
582 /**
583  * Send DNS query
584  *
585  * @v dns DNS request
586  * @ret rc Return status code
587  */
588 static int dns_send_packet ( struct dns_request *dns ) {
589  struct dns_header *query = &dns->buf.query;
590  union {
591  struct sockaddr sa;
592  struct sockaddr_tcpip st;
593  struct sockaddr_in sin;
594  struct sockaddr_in6 sin6;
595  } nameserver;
596  struct xfer_metadata meta;
597  unsigned int index;
598 
599  /* Start retransmission timer */
600  start_timer ( &dns->timer );
601 
602  /* Construct DNS server address */
603  memset ( &nameserver, 0, sizeof ( nameserver ) );
604  nameserver.st.st_port = htons ( DNS_PORT );
605  if ( ! dns_count ) {
606  DBGC ( dns, "DNS %p lost DNS servers mid query\n", dns );
607  return -EINVAL;
608  }
609  index = ( dns->index % dns_count );
610  if ( index < dns6.count ) {
611  nameserver.sin6.sin6_family = AF_INET6;
612  memcpy ( &nameserver.sin6.sin6_addr, &dns6.in6[index],
613  sizeof ( nameserver.sin6.sin6_addr ) );
614  } else {
615  nameserver.sin.sin_family = AF_INET;
616  nameserver.sin.sin_addr = dns4.in[index - dns6.count];
617  }
618 
619  /* Construct metadata */
620  memset ( &meta, 0, sizeof ( meta ) );
621  meta.dest = &nameserver.sa;
622 
623  /* Generate query identifier if applicable */
624  if ( ! query->id )
625  query->id = random();
626 
627  /* Send query */
628  DBGC ( dns, "DNS %p sending %s query ID %#04x for %s type %s\n", dns,
629  sock_ntoa ( &nameserver.sa ), ntohs ( query->id ),
630  dns_name ( &dns->name ), dns_type ( dns->question->qtype ) );
631 
632  /* Send the data */
633  return xfer_deliver_raw_meta ( &dns->socket, query, dns->len, &meta );
634 }
635 
636 /**
637  * Handle DNS (re)transmission timer expiry
638  *
639  * @v timer Retry timer
640  * @v fail Failure indicator
641  */
642 static void dns_timer_expired ( struct retry_timer *timer, int fail ) {
643  struct dns_request *dns =
644  container_of ( timer, struct dns_request, timer );
645 
646  /* Terminate DNS request on failure */
647  if ( fail ) {
648  dns_done ( dns, -ETIMEDOUT );
649  return;
650  }
651 
652  /* Move to next DNS server if this is a retransmission */
653  if ( dns->buf.query.id )
654  dns->index++;
655 
656  /* Send DNS query */
657  dns_send_packet ( dns );
658 }
659 
660 /**
661  * Receive new data
662  *
663  * @v dns DNS request
664  * @v iobuf I/O buffer
665  * @v meta Data transfer metadata
666  * @ret rc Return status code
667  */
668 static int dns_xfer_deliver ( struct dns_request *dns,
669  struct io_buffer *iobuf,
670  struct xfer_metadata *meta __unused ) {
671  struct dns_header *response = iobuf->data;
672  struct dns_header *query = &dns->buf.query;
673  unsigned int qtype = dns->question->qtype;
674  struct dns_name buf;
675  union dns_rr *rr;
676  int offset;
677  size_t answer_offset;
678  size_t next_offset;
679  size_t rdlength;
680  size_t name_len;
681  int rc;
682 
683  /* Sanity check */
684  if ( iob_len ( iobuf ) < sizeof ( *response ) ) {
685  DBGC ( dns, "DNS %p received underlength packet length %zd\n",
686  dns, iob_len ( iobuf ) );
687  rc = -EINVAL;
688  goto done;
689  }
690 
691  /* Check response ID matches query ID */
692  if ( response->id != query->id ) {
693  DBGC ( dns, "DNS %p received unexpected response ID %#04x "
694  "(wanted %d)\n", dns, ntohs ( response->id ),
695  ntohs ( query->id ) );
696  rc = -EINVAL;
697  goto done;
698  }
699  DBGC ( dns, "DNS %p received response ID %#04x\n",
700  dns, ntohs ( response->id ) );
701 
702  /* Check that we have exactly one question */
703  if ( response->qdcount != htons ( 1 ) ) {
704  DBGC ( dns, "DNS %p received response with %d questions\n",
705  dns, ntohs ( response->qdcount ) );
706  rc = -EINVAL;
707  goto done;
708  }
709 
710  /* Skip question section */
711  buf.data = iobuf->data;
712  buf.offset = sizeof ( *response );
713  buf.len = iob_len ( iobuf );
714  offset = dns_skip ( &buf );
715  if ( offset < 0 ) {
716  rc = offset;
717  DBGC ( dns, "DNS %p received response with malformed "
718  "question: %s\n", dns, strerror ( rc ) );
719  goto done;
720  }
721  answer_offset = ( offset + sizeof ( struct dns_question ) );
722 
723  /* Search through response for useful answers. Do this
724  * multiple times, to take advantage of useful nameservers
725  * which send us e.g. the CNAME *and* the A record for the
726  * pointed-to name.
727  */
728  for ( buf.offset = answer_offset ; buf.offset != buf.len ;
729  buf.offset = next_offset ) {
730 
731  /* Check for valid name */
732  offset = dns_skip ( &buf );
733  if ( offset < 0 ) {
734  rc = offset;
735  DBGC ( dns, "DNS %p received response with malformed "
736  "answer: %s\n", dns, strerror ( rc ) );
737  goto done;
738  }
739 
740  /* Check for sufficient space for resource record */
741  rr = ( buf.data + offset );
742  if ( ( offset + sizeof ( rr->common ) ) > buf.len ) {
743  DBGC ( dns, "DNS %p received response with underlength "
744  "RR\n", dns );
745  rc = -EINVAL;
746  goto done;
747  }
748  rdlength = ntohs ( rr->common.rdlength );
749  next_offset = ( offset + sizeof ( rr->common ) + rdlength );
750  if ( next_offset > buf.len ) {
751  DBGC ( dns, "DNS %p received response with underlength "
752  "RR\n", dns );
753  rc = -EINVAL;
754  goto done;
755  }
756 
757  /* Skip non-matching names */
758  if ( dns_compare ( &buf, &dns->name ) != 0 ) {
759  DBGC2 ( dns, "DNS %p ignoring response for %s type "
760  "%s\n", dns, dns_name ( &buf ),
761  dns_type ( rr->common.type ) );
762  continue;
763  }
764 
765  /* Handle answer */
766  switch ( rr->common.type ) {
767 
768  case htons ( DNS_TYPE_AAAA ):
769 
770  /* Found the target AAAA record */
771  if ( rdlength < sizeof ( dns->address.sin6.sin6_addr )){
772  DBGC ( dns, "DNS %p received response with "
773  "underlength AAAA\n", dns );
774  rc = -EINVAL;
775  goto done;
776  }
778  memcpy ( &dns->address.sin6.sin6_addr,
779  &rr->aaaa.in6_addr,
780  sizeof ( dns->address.sin6.sin6_addr ) );
781  dns_resolved ( dns );
782  rc = 0;
783  goto done;
784 
785  case htons ( DNS_TYPE_A ):
786 
787  /* Found the target A record */
788  if ( rdlength < sizeof ( dns->address.sin.sin_addr ) ) {
789  DBGC ( dns, "DNS %p received response with "
790  "underlength A\n", dns );
791  rc = -EINVAL;
792  goto done;
793  }
794  dns->address.sin.sin_family = AF_INET;
795  dns->address.sin.sin_addr = rr->a.in_addr;
796  dns_resolved ( dns );
797  rc = 0;
798  goto done;
799 
800  case htons ( DNS_TYPE_CNAME ):
801 
802  /* Terminate the operation if we recurse too far */
803  if ( ++dns->recursion > DNS_MAX_CNAME_RECURSION ) {
804  DBGC ( dns, "DNS %p recursion exceeded\n",
805  dns );
806  rc = -ELOOP;
807  dns_done ( dns, rc );
808  goto done;
809  }
810 
811  /* Found a CNAME record; update query and recurse */
812  buf.offset = ( offset + sizeof ( rr->cname ) );
813  DBGC ( dns, "DNS %p found CNAME %s\n",
814  dns, dns_name ( &buf ) );
815  dns->search.offset = dns->search.len;
816  name_len = dns_copy ( &buf, &dns->name );
817  dns->offset = ( offsetof ( typeof ( dns->buf ), name ) +
818  name_len - 1 /* Strip root label */ );
819  if ( ( rc = dns_question ( dns ) ) != 0 ) {
820  dns_done ( dns, rc );
821  goto done;
822  }
823  next_offset = answer_offset;
824  break;
825 
826  default:
827  DBGC ( dns, "DNS %p got unknown record type %d\n",
828  dns, ntohs ( rr->common.type ) );
829  break;
830  }
831  }
832 
833  /* Stop the retry timer. After this point, each code path
834  * must either restart the timer by calling dns_send_packet(),
835  * or mark the DNS operation as complete by calling
836  * dns_done()
837  */
838  stop_timer ( &dns->timer );
839 
840  /* Determine what to do next based on the type of query we
841  * issued and the response we received
842  */
843  switch ( qtype ) {
844 
845  case htons ( DNS_TYPE_AAAA ):
846  /* We asked for an AAAA record and got nothing; try
847  * the A.
848  */
849  DBGC ( dns, "DNS %p found no AAAA record; trying A\n", dns );
850  dns->question->qtype = htons ( DNS_TYPE_A );
851  dns_send_packet ( dns );
852  rc = 0;
853  goto done;
854 
855  case htons ( DNS_TYPE_A ):
856  /* We asked for an A record and got nothing;
857  * try the CNAME.
858  */
859  DBGC ( dns, "DNS %p found no A record; trying CNAME\n", dns );
860  dns->question->qtype = htons ( DNS_TYPE_CNAME );
861  dns_send_packet ( dns );
862  rc = 0;
863  goto done;
864 
865  case htons ( DNS_TYPE_CNAME ):
866  /* We asked for a CNAME record. If we got a response
867  * (i.e. if the next AAAA/A query is already set up),
868  * then issue it.
869  */
870  if ( qtype == dns->qtype ) {
871  dns_send_packet ( dns );
872  rc = 0;
873  goto done;
874  }
875 
876  /* If we have already reached the end of the search list,
877  * then terminate lookup.
878  */
879  if ( dns->search.offset == dns->search.len ) {
880  DBGC ( dns, "DNS %p found no CNAME record\n", dns );
881  rc = -ENXIO_NO_RECORD;
882  dns_done ( dns, rc );
883  goto done;
884  }
885 
886  /* Move to next entry in search list. This can never fail,
887  * since we have already used this entry.
888  */
889  DBGC ( dns, "DNS %p found no CNAME record; trying next "
890  "suffix\n", dns );
891  dns->search.offset = dns_skip_search ( &dns->search );
892  if ( ( rc = dns_question ( dns ) ) != 0 ) {
893  dns_done ( dns, rc );
894  goto done;
895  }
896  dns_send_packet ( dns );
897  goto done;
898 
899  default:
900  assert ( 0 );
901  rc = -EINVAL;
902  dns_done ( dns, rc );
903  goto done;
904  }
905 
906  done:
907  /* Free I/O buffer */
908  free_iob ( iobuf );
909  return rc;
910 }
911 
912 /**
913  * Receive new data
914  *
915  * @v dns DNS request
916  * @v rc Reason for close
917  */
918 static void dns_xfer_close ( struct dns_request *dns, int rc ) {
919 
920  if ( ! rc )
921  rc = -ECONNABORTED;
922 
923  dns_done ( dns, rc );
924 }
925 
926 /**
927  * Report job progress
928  *
929  * @v dns DNS request
930  * @v progress Progress report to fill in
931  * @ret ongoing_rc Ongoing job status code (if known)
932  */
933 static int dns_progress ( struct dns_request *dns,
934  struct job_progress *progress ) {
935  int len;
936 
937  /* Show current question as progress message */
938  len = dns_decode ( &dns->name, progress->message,
939  ( sizeof ( progress->message ) - 1 /* NUL */ ) );
940  if ( len < 0 ) {
941  /* Ignore undecodable names */
942  progress->message[0] = '\0';
943  }
944 
945  return 0;
946 }
947 
948 /** DNS socket interface operations */
952 };
953 
954 /** DNS socket interface descriptor */
956  INTF_DESC ( struct dns_request, socket, dns_socket_operations );
957 
958 /** DNS resolver interface operations */
961  INTF_OP ( intf_close, struct dns_request *, dns_done ),
962 };
963 
964 /** DNS resolver interface descriptor */
967 
968 /**
969  * Resolve name using DNS
970  *
971  * @v resolv Name resolution interface
972  * @v name Name to resolve
973  * @v sa Socket address to fill in
974  * @ret rc Return status code
975  */
976 static int dns_resolv ( struct interface *resolv,
977  const char *name, struct sockaddr *sa ) {
978  struct dns_request *dns;
979  struct dns_header *query;
980  size_t search_len;
981  int name_len;
982  int rc;
983 
984  /* Fail immediately if no DNS servers */
985  if ( dns_count == 0 ) {
986  DBG ( "DNS not attempting to resolve \"%s\": "
987  "no DNS servers\n", name );
989  goto err_no_nameserver;
990  }
991 
992  /* Determine whether or not to use search list */
993  search_len = ( strchr ( name, '.' ) ? 0 : dns_search.len );
994 
995  /* Allocate DNS structure */
996  dns = zalloc ( sizeof ( *dns ) + search_len );
997  if ( ! dns ) {
998  rc = -ENOMEM;
999  goto err_alloc_dns;
1000  }
1001  ref_init ( &dns->refcnt, NULL );
1002  intf_init ( &dns->resolv, &dns_resolv_desc, &dns->refcnt );
1003  intf_init ( &dns->socket, &dns_socket_desc, &dns->refcnt );
1004  timer_init ( &dns->timer, dns_timer_expired, &dns->refcnt );
1005  memcpy ( &dns->address.sa, sa, sizeof ( dns->address.sa ) );
1006  dns->search.data = ( ( ( void * ) dns ) + sizeof ( *dns ) );
1007  dns->search.len = search_len;
1008  memcpy ( dns->search.data, dns_search.data, search_len );
1009 
1010  /* Determine initial query type */
1011  dns->qtype = ( ( dns6.count != 0 ) ?
1012  htons ( DNS_TYPE_AAAA ) : htons ( DNS_TYPE_A ) );
1013 
1014  /* Construct query */
1015  query = &dns->buf.query;
1016  query->flags = htons ( DNS_FLAG_RD );
1017  query->qdcount = htons ( 1 );
1018  dns->name.data = &dns->buf;
1019  dns->name.offset = offsetof ( typeof ( dns->buf ), name );
1020  dns->name.len = offsetof ( typeof ( dns->buf ), padding );
1021  name_len = dns_encode ( name, &dns->name );
1022  if ( name_len < 0 ) {
1023  rc = name_len;
1024  goto err_encode;
1025  }
1026  dns->offset = ( offsetof ( typeof ( dns->buf ), name ) +
1027  name_len - 1 /* Strip root label */ );
1028  if ( ( rc = dns_question ( dns ) ) != 0 )
1029  goto err_question;
1030 
1031  /* Open UDP connection */
1032  if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM,
1033  NULL, NULL ) ) != 0 ) {
1034  DBGC ( dns, "DNS %p could not open socket: %s\n",
1035  dns, strerror ( rc ) );
1036  goto err_open_socket;
1037  }
1038 
1039  /* Start timer to trigger first packet */
1040  start_timer_nodelay ( &dns->timer );
1041 
1042  /* Attach parent interface, mortalise self, and return */
1043  intf_plug_plug ( &dns->resolv, resolv );
1044  ref_put ( &dns->refcnt );
1045  return 0;
1046 
1047  err_open_socket:
1048  err_question:
1049  err_encode:
1050  ref_put ( &dns->refcnt );
1051  err_alloc_dns:
1052  err_no_nameserver:
1053  return rc;
1054 }
1055 
1056 /** DNS name resolver */
1057 struct resolver dns_resolver __resolver ( RESOLV_NORMAL ) = {
1058  .name = "DNS",
1059  .resolv = dns_resolv,
1060 };
1061 
1062 /******************************************************************************
1063  *
1064  * Settings
1065  *
1066  ******************************************************************************
1067  */
1068 
1069 /**
1070  * Format DNS search list setting
1071  *
1072  * @v type Setting type
1073  * @v raw Raw setting value
1074  * @v raw_len Length of raw setting value
1075  * @v buf Buffer to contain formatted value
1076  * @v len Length of buffer
1077  * @ret len Length of formatted value, or negative error
1078  */
1079 static int format_dnssl_setting ( const struct setting_type *type __unused,
1080  const void *raw, size_t raw_len,
1081  char *buf, size_t len ) {
1082  struct dns_name name = {
1083  .data = ( ( void * ) raw ),
1084  .len = raw_len,
1085  };
1086  size_t remaining = len;
1087  size_t total = 0;
1088  int name_len;
1089 
1090  while ( name.offset < raw_len ) {
1091 
1092  /* Decode name */
1093  remaining = ( ( total < len ) ? ( len - total ) : 0 );
1094  name_len = dns_decode ( &name, ( buf + total ), remaining );
1095  if ( name_len < 0 )
1096  return name_len;
1097  total += name_len;
1098 
1099  /* Move to next name */
1100  name.offset = dns_skip_search ( &name );
1101 
1102  /* Add separator if applicable */
1103  if ( name.offset != raw_len ) {
1104  if ( total < len )
1105  buf[total] = ' ';
1106  total++;
1107  }
1108  }
1109 
1110  return total;
1111 }
1112 
1113 /** A DNS search list setting type */
1114 const struct setting_type setting_type_dnssl __setting_type = {
1115  .name = "dnssl",
1116  .format = format_dnssl_setting,
1117 };
1118 
1119 /** IPv4 DNS server setting */
1120 const struct setting dns_setting __setting ( SETTING_IP4_EXTRA, dns ) = {
1121  .name = "dns",
1122  .description = "DNS server",
1123  .tag = DHCP_DNS_SERVERS,
1124  .type = &setting_type_ipv4,
1125 };
1126 
1127 /** IPv6 DNS server setting */
1128 const struct setting dns6_setting __setting ( SETTING_IP6_EXTRA, dns6 ) = {
1129  .name = "dns6",
1130  .description = "DNS server",
1131  .tag = DHCPV6_DNS_SERVERS,
1132  .type = &setting_type_ipv6,
1133  .scope = &dhcpv6_scope,
1134 };
1135 
1136 /** DNS search list */
1137 const struct setting dnssl_setting __setting ( SETTING_IP_EXTRA, dnssl ) = {
1138  .name = "dnssl",
1139  .description = "DNS search list",
1140  .tag = DHCP_DOMAIN_SEARCH,
1141  .type = &setting_type_dnssl,
1142 };
1143 
1144 /**
1145  * Apply DNS server addresses
1146  *
1147  */
1148 static void apply_dns_servers ( void ) {
1149  int len;
1150 
1151  /* Free existing server addresses */
1152  free ( dns4.data );
1153  free ( dns6.data );
1154  dns4.data = NULL;
1155  dns6.data = NULL;
1156  dns4.count = 0;
1157  dns6.count = 0;
1158 
1159  /* Fetch DNS server addresses */
1160  len = fetch_raw_setting_copy ( NULL, &dns_setting, &dns4.data );
1161  if ( len >= 0 )
1162  dns4.count = ( len / sizeof ( dns4.in[0] ) );
1163  len = fetch_raw_setting_copy ( NULL, &dns6_setting, &dns6.data );
1164  if ( len >= 0 )
1165  dns6.count = ( len / sizeof ( dns6.in6[0] ) );
1166  dns_count = ( dns4.count + dns6.count );
1167 }
1168 
1169 /**
1170  * Apply DNS search list
1171  *
1172  */
1173 static void apply_dns_search ( void ) {
1174  char *localdomain;
1175  int len;
1176 
1177  /* Free existing search list */
1178  free ( dns_search.data );
1179  memset ( &dns_search, 0, sizeof ( dns_search ) );
1180 
1181  /* Fetch DNS search list */
1182  len = fetch_raw_setting_copy ( NULL, &dnssl_setting, &dns_search.data );
1183  if ( len >= 0 ) {
1184  dns_search.len = len;
1185  return;
1186  }
1187 
1188  /* If no DNS search list exists, try to fetch the local domain */
1189  fetch_string_setting_copy ( NULL, &domain_setting, &localdomain );
1190  if ( localdomain ) {
1191  len = dns_encode ( localdomain, &dns_search );
1192  if ( len >= 0 ) {
1193  dns_search.data = malloc ( len );
1194  if ( dns_search.data ) {
1195  dns_search.len = len;
1196  dns_encode ( localdomain, &dns_search );
1197  }
1198  }
1199  free ( localdomain );
1200  return;
1201  }
1202 }
1203 
1204 /**
1205  * Apply DNS settings
1206  *
1207  * @ret rc Return status code
1208  */
1209 static int apply_dns_settings ( void ) {
1210  void *dbgcol = &dns_count;
1211 
1212  /* Fetch DNS server address */
1214  if ( DBG_EXTRA && ( dns_count != 0 ) ) {
1215  union {
1216  struct sockaddr sa;
1217  struct sockaddr_in sin;
1218  struct sockaddr_in6 sin6;
1219  } u;
1220  unsigned int i;
1221 
1222  DBGC2 ( dbgcol, "DNS servers:" );
1223  for ( i = 0 ; i < dns6.count ; i++ ) {
1224  u.sin6.sin6_family = AF_INET6;
1225  memcpy ( &u.sin6.sin6_addr, &dns6.in6[i],
1226  sizeof ( u.sin6.sin6_addr ) );
1227  DBGC2 ( dbgcol, " %s", sock_ntoa ( &u.sa ) );
1228  }
1229  for ( i = 0 ; i < dns4.count ; i++ ) {
1230  u.sin.sin_family = AF_INET;
1231  u.sin.sin_addr = dns4.in[i];
1232  DBGC2 ( dbgcol, " %s", sock_ntoa ( &u.sa ) );
1233  }
1234  DBGC2 ( dbgcol, "\n" );
1235  }
1236 
1237  /* Fetch DNS search list */
1238  apply_dns_search();
1239  if ( DBG_EXTRA && ( dns_search.len != 0 ) ) {
1240  struct dns_name name;
1241  int offset;
1242 
1243  DBGC2 ( dbgcol, "DNS search list:" );
1244  memcpy ( &name, &dns_search, sizeof ( name ) );
1245  while ( name.offset != name.len ) {
1246  DBGC2 ( dbgcol, " %s", dns_name ( &name ) );
1247  offset = dns_skip_search ( &name );
1248  if ( offset < 0 )
1249  break;
1250  name.offset = offset;
1251  }
1252  DBGC2 ( dbgcol, "\n" );
1253  }
1254 
1255  return 0;
1256 }
1257 
1258 /** DNS settings applicator */
1261 };
struct dns_rr_common common
Common fields.
Definition: dns.h:141
#define __attribute__(x)
Definition: compiler.h:10
#define EINVAL
Invalid argument.
Definition: errno.h:429
An object interface operation.
Definition: interface.h:18
#define SETTING_IP_EXTRA
IPv4 additional settings.
Definition: settings.h:71
#define DNS_TYPE_CNAME
Type of a DNS "NAME" record.
Definition: dns.h:130
TCP/IP socket address.
Definition: tcpip.h:76
size_t offset
Offset of search suffix within current query.
Definition: dns.c:487
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1986
unsigned short uint16_t
Definition: stdint.h:11
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:250
uint16_t qdcount
Number of question records.
Definition: dns.h:72
#define ENXIO_NO_NAMESERVER
Definition: dns.c:63
#define DNS_MAX_LABEL_LEN
Maximum length of a single DNS label.
Definition: dns.h:54
Dynamic Host Configuration Protocol.
A text label widget.
Definition: label.h:16
Data transfer metadata.
Definition: xfer.h:23
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:279
#define AF_INET6
IPv6 Internet addresses.
Definition: socket.h:65
struct dns_question * question
Question within current query.
Definition: dns.c:483
int dns_skip(struct dns_name *name)
Skip RFC1035-encoded DNS name.
Definition: dns.c:365
#define DHCP_EB_FEATURE_DNS
DNS protocol.
Definition: features.h:44
static void apply_dns_servers(void)
Apply DNS server addresses.
Definition: dns.c:1148
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition: retry.h:100
static void dns_done(struct dns_request *dns, int rc)
Mark DNS request as complete.
Definition: dns.c:502
const struct settings_scope dhcpv6_scope
IPv6 settings scope.
Definition: settings.c:1793
#define DNS_COMPRESSED_OFFSET(word)
Extract DNS compression pointer.
Definition: dns.h:43
A DNS packet header.
Definition: dns.h:66
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
#define FEATURE_PROTOCOL
Network protocols.
Definition: features.h:22
#define DNS_FLAG_RD
Recursion desired flag.
Definition: dns.h:82
static struct dns_server dns4
IPv4 DNS server list.
Definition: dns.c:83
static int dns_question(struct dns_request *dns)
Construct DNS question.
Definition: dns.c:536
int fetch_raw_setting_copy(struct settings *settings, const struct setting *setting, void **data)
Fetch value of setting.
Definition: settings.c:822
void resolv_done(struct interface *intf, struct sockaddr *sa)
Name resolved.
Definition: resolv.c:56
uint32_t first
First block in range.
Definition: pccrr.h:15
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
Error codes.
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition: open.c:143
uint16_t type
Type.
Definition: dns.h:98
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
static void dns_timer_expired(struct retry_timer *timer, int fail)
Handle DNS (re)transmission timer expiry.
Definition: dns.c:642
Name resolution.
uint32_t type
Operating system type.
Definition: ena.h:12
#define SOCK_DGRAM
Definition: socket.h:30
Retry timers.
static struct interface_operation dns_socket_operations[]
DNS socket interface operations.
Definition: dns.c:949
struct in_addr * in
IPv4 addresses.
Definition: dns.c:72
#define DBGC(...)
Definition: compiler.h:505
unsigned int index
Server index.
Definition: dns.c:491
struct sockaddr_in6 sin6
Definition: syslog.c:60
A retry timer.
Definition: retry.h:22
long index
Definition: bigint.h:65
#define ENOENT
No such file or directory.
Definition: errno.h:515
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:108
static void dns_xfer_close(struct dns_request *dns, int rc)
Receive new data.
Definition: dns.c:918
struct in6_addr in6_addr
IPv6 address.
Definition: dns.h:126
A settings applicator.
Definition: settings.h:252
struct in_addr in_addr
IPv4 address.
Definition: dns.h:115
IPv4 socket address.
Definition: in.h:85
#define ntohs(value)
Definition: byteswap.h:137
unsigned int recursion
Recursion counter.
Definition: dns.c:493
union @18 u
static const char * dns_name(struct dns_name *name)
Transcribe DNS name (for debugging)
Definition: dns.c:429
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:25
Character types.
void * data
Start of data.
Definition: dns.h:22
unsigned int count
Number of servers.
Definition: dns.c:79
sa_family_t sin_family
Socket address family (part of struct sockaddr)
Definition: in.h:90
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define DNS_PORT
DNS server port.
Definition: dns.h:17
static unsigned int dns_count
Total number of DNS servers.
Definition: dns.c:89
#define ELOOP
Too many levels of symbolic links.
Definition: errno.h:449
static const char * dns_type(uint16_t type)
Name a DNS query type (for debugging)
Definition: dns.c:443
Data transfer interfaces.
A reference counter.
Definition: refcnt.h:27
A timer.
Definition: timer.h:29
const char * name
Name.
Definition: settings.h:29
struct sockaddr_tcpip st
Definition: syslog.c:58
void * data
Raw data.
Definition: dns.c:76
uint32_t start
Starting offset.
Definition: netvsc.h:12
struct refcnt refcnt
Reference counter.
Definition: dns.c:455
static int dns_xfer_deliver(struct dns_request *dns, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive new data.
Definition: dns.c:668
#define DNS_TYPE_A
Type of a DNS "A" record.
Definition: dns.h:108
#define ENOMEM
Not enough space.
Definition: errno.h:535
void * memcpy(void *dest, const void *src, size_t len) __nonnull
A DNS resource record.
Definition: dns.h:139
static int dns_progress(struct dns_request *dns, struct job_progress *progress)
Report job progress.
Definition: dns.c:933
const struct setting_type setting_type_dnssl __setting_type
A DNS search list setting type.
Definition: dns.c:1114
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static struct dns_name dns_search
The DNS search list.
Definition: dns.c:92
#define SETTING_IP4_EXTRA
IPv4 additional settings.
Definition: settings.h:67
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
uint16_t qtype
Query type.
Definition: dns.h:87
An object interface.
Definition: interface.h:125
An RFC1035-encoded DNS name.
Definition: dns.h:20
static const void * src
Definition: string.h:48
struct dns_request::@5 buf
Buffer for current query.
size_t len
Length of current query.
Definition: dns.c:485
struct sockaddr_in6 sin6
Definition: dns.c:467
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
ring len
Length.
Definition: dwmac.h:231
static int tolower(int character)
Convert character to lower case.
Definition: ctype.h:109
struct sockaddr sa
Definition: syslog.c:57
Transport-network layer interface.
Feature list.
static int dns_send_packet(struct dns_request *dns)
Send DNS query.
Definition: dns.c:588
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition: settings.c:874
IP6 address structure.
Definition: in.h:51
struct sockaddr sa
Definition: dns.c:465
size_t offset
Offset of name within data.
Definition: dns.h:24
#define DNS_TYPE_AAAA
Type of a DNS "AAAA" record.
Definition: dns.h:119
#define DHCP_DOMAIN_SEARCH
DNS domain search list.
Definition: dhcp.h:346
struct interface resolv
Name resolution interface.
Definition: dns.c:457
Configuration settings.
static size_t raw_len
Definition: base16.h:54
Generalized socket address structure.
Definition: socket.h:97
An object interface descriptor.
Definition: interface.h:56
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
IP address structure.
Definition: in.h:42
uint16_t flags
Flags.
Definition: dns.h:70
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:272
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
struct dns_header query
Query header.
Definition: dns.c:474
Job progress.
Definition: job.h:16
int dns_copy(struct dns_name *src, struct dns_name *dst)
Copy a DNS name.
Definition: dns.c:322
#define ECONNABORTED
Connection aborted.
Definition: errno.h:354
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:32
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:195
int dns_encode(const char *string, struct dns_name *name)
Encode a DNS name using RFC1035 encoding.
Definition: dns.c:101
#define DHCPV6_DNS_SERVERS
DHCPv6 DNS recursive name server option.
Definition: dhcpv6.h:165
#define DNS_MAX_CNAME_RECURSION
Maximum depth of CNAME recursion.
Definition: dns.h:63
unsigned char uint8_t
Definition: stdint.h:10
struct dns_rr_a a
"A" record
Definition: dns.h:143
Data transfer interface opening.
#define ENXIO_NO_RECORD
Definition: dns.c:60
static int dns_resolv(struct interface *resolv, const char *name, struct sockaddr *sa)
Resolve name using DNS.
Definition: dns.c:976
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:621
unsigned char byte
Definition: smc9000.h:38
A DNS request.
Definition: dns.c:453
A setting.
Definition: settings.h:24
Job control interfaces.
static void apply_dns_search(void)
Apply DNS search list.
Definition: dns.c:1173
char message[32]
Message (optional)
Definition: job.h:33
void start_timer(struct retry_timer *timer)
Start timer.
Definition: retry.c:94
#define DNS_MAX_NAME_LEN
Maximum length of a DNS name (mandated by RFC1035 section 2.3.4)
Definition: dns.h:57
char name[DNS_MAX_NAME_LEN]
Name buffer.
Definition: dns.c:476
struct in_addr sin_addr
IPv4 address.
Definition: in.h:101
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:81
#define DNS_IS_COMPRESSED(byte)
Test for a DNS compression pointer.
Definition: dns.h:35
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:118
struct interface socket
Data transfer interface.
Definition: dns.c:459
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition: socket.c:43
A DNS question.
Definition: dns.h:85
uint16_t qclass
Query class.
Definition: dns.h:89
struct dns_rr_aaaa aaaa
"AAAA" record
Definition: dns.h:145
static struct interface_descriptor dns_socket_desc
DNS socket interface descriptor.
Definition: dns.c:955
A DNS server list.
Definition: dns.c:68
uint16_t id
Query identifier.
Definition: dns.h:68
static struct interface_operation dns_resolv_op[]
DNS resolver interface operations.
Definition: dns.c:959
#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:1079
#define SETTING_IP6_EXTRA
IPv6 additional settings.
Definition: settings.h:69
A name resolver.
Definition: resolv.h:19
static int dns_skip_search(struct dns_name *name)
Skip RFC1035-encoded DNS name in search list.
Definition: dns.c:404
void * data
Start of data.
Definition: iobuf.h:53
struct dns_name search
Search list.
Definition: dns.c:489
#define DNS_CLASS_IN
DNS class "IN".
Definition: dns.h:93
struct retry_timer timer
Retry timer.
Definition: dns.c:461
struct resolver dns_resolver __resolver(RESOLV_NORMAL)
DNS name resolver.
uint16_t qtype
Initial query type.
Definition: dns.c:470
const char * name
Name.
Definition: settings.h:197
unsigned short word
Definition: smc9000.h:39
static int apply_dns_settings(void)
Apply DNS settings.
Definition: dns.c:1209
Reference counting.
uint32_t end
Ending offset.
Definition: netvsc.h:18
uint8_t data[48]
Additional event data.
Definition: ena.h:22
int dns_compare(struct dns_name *first, struct dns_name *second)
Compare DNS names for equality.
Definition: dns.c:268
const char * name
Name of this resolver (e.g.
Definition: resolv.h:21
#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:163
__be32 raw[7]
Definition: CIB_PRM.h:28
struct settings_applicator dns_applicator __settings_applicator
DNS settings applicator.
Definition: dns.c:1259
static struct interface_descriptor dns_resolv_desc
DNS resolver interface descriptor.
Definition: dns.c:965
IPv6 socket address.
Definition: in.h:118
int(* apply)(void)
Apply updated settings.
Definition: settings.h:257
int resolv(struct interface *resolv, const char *name, struct sockaddr *sa)
Start name resolution.
Definition: resolv.c:258
int dns_decode(struct dns_name *name, char *data, size_t len)
Decode RFC1035-encoded DNS name.
Definition: dns.c:217
sa_family_t sin6_family
Socket address family (part of struct sockaddr)
Definition: in.h:123
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition: acpi.c:48
#define DBG_EXTRA
Definition: compiler.h:319
struct sockaddr_in sin
Definition: syslog.c:59
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
uint8_t meta
Metadata flags.
Definition: ena.h:14
FEATURE(FEATURE_PROTOCOL, "DNS", DHCP_EB_FEATURE_DNS, 1)
size_t len
Total length of data.
Definition: dns.h:26
struct sockaddr_in sin
Definition: dns.c:466
#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:204
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
struct in6_addr * in6
IPv6 addresses.
Definition: dns.c:74
const struct setting dns_setting __setting(SETTING_IP4_EXTRA, dns)
IPv4 DNS server setting.
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:670
String functions.
union dns_request::@4 address
Socket address to fill in with resolved address.
uint16_t rdlength
Resource data length.
Definition: dns.h:104
#define htons(value)
Definition: byteswap.h:136
struct bofm_section_header done
Definition: bofm_test.c:46
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:64
A setting type.
Definition: settings.h:192
struct in6_addr sin6_addr
IPv6 address.
Definition: in.h:135
struct dns_question padding
Space for question.
Definition: dns.c:478
DNS protocol.
static struct dns_server dns6
IPv6 DNS server list.
Definition: dns.c:86
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107
Dynamic Host Configuration Protocol for IPv6.
struct dns_rr_cname cname
"CNAME" record
Definition: dns.h:147
FILE_SECBOOT(PERMITTED)
void * memset(void *dest, int character, size_t len) __nonnull
#define RESOLV_NORMAL
Normal resolver priority.
Definition: resolv.h:37
A persistent I/O buffer.
Definition: iobuf.h:38
static void dns_resolved(struct dns_request *dns)
Mark DNS request as resolved and complete.
Definition: dns.c:518