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.

nslookup.c 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (C) 2012 Patrick Plenefisch <phplenefisch@wpi.edu>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <ipxe/resolv.h>
  25. #include <ipxe/tcpip.h>
  26. #include <ipxe/monojob.h>
  27. #include <ipxe/settings.h>
  28. #include <usr/nslookup.h>
  29. /** @file
  30. *
  31. * Standalone name resolution
  32. *
  33. */
  34. /** A name resolution request */
  35. struct nslookup {
  36. /** Reference count for this object */
  37. struct refcnt refcnt;
  38. /** Job control interface */
  39. struct interface job;
  40. /** Data transfer interface */
  41. struct interface resolver;
  42. /** Setting name */
  43. char *setting_name;
  44. };
  45. /**
  46. * Terminate name resolution
  47. *
  48. * @v nslookup Name resolution request
  49. * @v rc Reason for termination
  50. */
  51. static void nslookup_close ( struct nslookup *nslookup, int rc ) {
  52. /* Shut down interfaces */
  53. intf_shutdown ( &nslookup->resolver, rc );
  54. intf_shutdown ( &nslookup->job, rc );
  55. }
  56. /**
  57. * Handle resolved name
  58. *
  59. * @v nslookup Name resolution request
  60. * @v sa Completed socket address
  61. */
  62. static void nslookup_resolv_done ( struct nslookup *nslookup,
  63. struct sockaddr *sa ) {
  64. struct sockaddr_in *sin;
  65. struct sockaddr_in6 *sin6;
  66. const struct setting_type *default_type;
  67. struct settings *settings;
  68. struct setting setting;
  69. void *data;
  70. size_t len;
  71. int rc;
  72. /* Extract address */
  73. switch ( sa->sa_family ) {
  74. case AF_INET:
  75. sin = ( ( struct sockaddr_in * ) sa );
  76. data = &sin->sin_addr;
  77. len = sizeof ( sin->sin_addr );
  78. default_type = &setting_type_ipv4;
  79. break;
  80. case AF_INET6:
  81. sin6 = ( ( struct sockaddr_in6 * ) sa );
  82. data = &sin6->sin6_addr;
  83. len = sizeof ( sin6->sin6_addr );
  84. default_type = &setting_type_ipv6;
  85. break;
  86. default:
  87. rc = -ENOTSUP;
  88. goto err;
  89. }
  90. /* Parse specified setting name */
  91. if ( ( rc = parse_setting_name ( nslookup->setting_name,
  92. autovivify_child_settings, &settings,
  93. &setting ) ) != 0 )
  94. goto err;
  95. /* Apply default type if necessary */
  96. if ( ! setting.type )
  97. setting.type = default_type;
  98. /* Store in specified setting */
  99. if ( ( rc = store_setting ( settings, &setting, data, len ) ) != 0 )
  100. goto err;
  101. err:
  102. /* Terminate name resolution */
  103. nslookup_close ( nslookup, rc );
  104. }
  105. /** Name resolution resolver interface operations */
  106. static struct interface_operation nslookup_resolver_operations[] = {
  107. INTF_OP ( resolv_done, struct nslookup *, nslookup_resolv_done ),
  108. INTF_OP ( intf_close, struct nslookup *, nslookup_close ),
  109. };
  110. /** Name resolution resolver interface descriptor */
  111. static struct interface_descriptor nslookup_resolver_desc =
  112. INTF_DESC_PASSTHRU ( struct nslookup, resolver,
  113. nslookup_resolver_operations, job );
  114. /** Name resolution job control interface operations */
  115. static struct interface_operation nslookup_job_operations[] = {
  116. INTF_OP ( intf_close, struct nslookup *, nslookup_close ),
  117. };
  118. /** Name resolution job control interface descriptor */
  119. static struct interface_descriptor nslookup_job_desc =
  120. INTF_DESC_PASSTHRU ( struct nslookup, job,
  121. nslookup_job_operations, resolver );
  122. /**
  123. * Initiate standalone name resolution
  124. *
  125. * @v job Parent interface
  126. * @v name Name to resolve
  127. * @v setting_name Setting name
  128. * @ret rc Return status code
  129. */
  130. static int resolv_setting ( struct interface *job, const char *name,
  131. const char *setting_name ) {
  132. struct nslookup *nslookup;
  133. struct sockaddr sa;
  134. char *setting_name_copy;
  135. int rc;
  136. /* Allocate and initialise structure */
  137. nslookup = zalloc ( sizeof ( *nslookup ) + strlen ( setting_name )
  138. + 1 /* NUL */ );
  139. if ( ! nslookup )
  140. return -ENOMEM;
  141. ref_init ( &nslookup->refcnt, NULL );
  142. intf_init ( &nslookup->job, &nslookup_job_desc, &nslookup->refcnt );
  143. intf_init ( &nslookup->resolver, &nslookup_resolver_desc,
  144. &nslookup->refcnt );
  145. setting_name_copy = ( ( void * ) ( nslookup + 1 ) );
  146. strcpy ( setting_name_copy, setting_name );
  147. nslookup->setting_name = setting_name_copy;
  148. /* Start name resolution */
  149. memset ( &sa, 0, sizeof ( sa ) );
  150. if ( ( rc = resolv ( &nslookup->resolver, name, &sa ) ) != 0 )
  151. goto err_resolv;
  152. /* Attach parent interface, mortalise self, and return */
  153. intf_plug_plug ( &nslookup->job, job );
  154. ref_put ( &nslookup->refcnt );
  155. return 0;
  156. err_resolv:
  157. ref_put ( &nslookup->refcnt );
  158. return rc;
  159. }
  160. /**
  161. * Perform (blocking) standalone name resolution
  162. *
  163. * @v name Name to resolve
  164. * @v setting_name Setting name
  165. * @ret rc Return status code
  166. */
  167. int nslookup ( const char *name, const char *setting_name ) {
  168. int rc;
  169. /* Perform name resolution */
  170. if ( ( rc = resolv_setting ( &monojob, name, setting_name ) ) == 0 )
  171. rc = monojob_wait ( NULL, 0 );
  172. if ( rc != 0 ) {
  173. printf ( "Could not resolve %s: %s\n", name, strerror ( rc ) );
  174. return rc;
  175. }
  176. return 0;
  177. }