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