You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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