/contrib/bind9/bin/named/lwdgnba.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 270 lines · 183 code · 45 blank · 42 comment · 49 complexity · b24d8f8cc09fd144e3e401b0d977a75e MD5 · raw file

  1. /*
  2. * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2000-2002 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id: lwdgnba.c,v 1.22 2008/01/14 23:46:56 tbox Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <isc/socket.h>
  21. #include <isc/string.h> /* Required for HP/UX (and others?) */
  22. #include <isc/util.h>
  23. #include <dns/adb.h>
  24. #include <dns/byaddr.h>
  25. #include <dns/result.h>
  26. #include <named/types.h>
  27. #include <named/lwdclient.h>
  28. static void start_byaddr(ns_lwdclient_t *);
  29. static void
  30. byaddr_done(isc_task_t *task, isc_event_t *event) {
  31. ns_lwdclient_t *client;
  32. ns_lwdclientmgr_t *cm;
  33. dns_byaddrevent_t *bevent;
  34. int lwres;
  35. lwres_buffer_t lwb;
  36. dns_name_t *name;
  37. isc_result_t result;
  38. lwres_result_t lwresult;
  39. isc_region_t r;
  40. isc_buffer_t b;
  41. lwres_gnbaresponse_t *gnba;
  42. isc_uint16_t naliases;
  43. UNUSED(task);
  44. lwb.base = NULL;
  45. client = event->ev_arg;
  46. cm = client->clientmgr;
  47. INSIST(client->byaddr == (dns_byaddr_t *)event->ev_sender);
  48. bevent = (dns_byaddrevent_t *)event;
  49. gnba = &client->gnba;
  50. ns_lwdclient_log(50, "byaddr event result = %s",
  51. isc_result_totext(bevent->result));
  52. result = bevent->result;
  53. if (result != ISC_R_SUCCESS) {
  54. dns_byaddr_destroy(&client->byaddr);
  55. isc_event_free(&event);
  56. bevent = NULL;
  57. if (client->na.family != AF_INET6 ||
  58. (client->options & DNS_BYADDROPT_IPV6INT) != 0) {
  59. if (result == DNS_R_NCACHENXDOMAIN ||
  60. result == DNS_R_NCACHENXRRSET ||
  61. result == DNS_R_NXDOMAIN ||
  62. result == DNS_R_NXRRSET)
  63. lwresult = LWRES_R_NOTFOUND;
  64. else
  65. lwresult = LWRES_R_FAILURE;
  66. ns_lwdclient_errorpktsend(client, lwresult);
  67. return;
  68. }
  69. /*
  70. * Fall back to ip6.int reverse if the default ip6.arpa
  71. * fails.
  72. */
  73. client->options |= DNS_BYADDROPT_IPV6INT;
  74. start_byaddr(client);
  75. return;
  76. }
  77. for (name = ISC_LIST_HEAD(bevent->names);
  78. name != NULL;
  79. name = ISC_LIST_NEXT(name, link))
  80. {
  81. b = client->recv_buffer;
  82. result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer);
  83. if (result != ISC_R_SUCCESS)
  84. goto out;
  85. ns_lwdclient_log(50, "found name '%.*s'",
  86. (int)(client->recv_buffer.used - b.used),
  87. (char *)(b.base) + b.used);
  88. if (gnba->realname == NULL) {
  89. gnba->realname = (char *)(b.base) + b.used;
  90. gnba->realnamelen = client->recv_buffer.used - b.used;
  91. } else {
  92. naliases = gnba->naliases;
  93. if (naliases >= LWRES_MAX_ALIASES)
  94. break;
  95. gnba->aliases[naliases] = (char *)(b.base) + b.used;
  96. gnba->aliaslen[naliases] =
  97. client->recv_buffer.used - b.used;
  98. gnba->naliases++;
  99. }
  100. }
  101. dns_byaddr_destroy(&client->byaddr);
  102. isc_event_free(&event);
  103. /*
  104. * Render the packet.
  105. */
  106. client->pkt.recvlength = LWRES_RECVLENGTH;
  107. client->pkt.authtype = 0; /* XXXMLG */
  108. client->pkt.authlength = 0;
  109. client->pkt.result = LWRES_R_SUCCESS;
  110. lwres = lwres_gnbaresponse_render(cm->lwctx,
  111. gnba, &client->pkt, &lwb);
  112. if (lwres != LWRES_R_SUCCESS)
  113. goto out;
  114. r.base = lwb.base;
  115. r.length = lwb.used;
  116. client->sendbuf = r.base;
  117. client->sendlength = r.length;
  118. result = ns_lwdclient_sendreply(client, &r);
  119. if (result != ISC_R_SUCCESS)
  120. goto out;
  121. NS_LWDCLIENT_SETSEND(client);
  122. return;
  123. out:
  124. if (client->byaddr != NULL)
  125. dns_byaddr_destroy(&client->byaddr);
  126. if (lwb.base != NULL)
  127. lwres_context_freemem(cm->lwctx,
  128. lwb.base, lwb.length);
  129. if (event != NULL)
  130. isc_event_free(&event);
  131. }
  132. static void
  133. start_byaddr(ns_lwdclient_t *client) {
  134. isc_result_t result;
  135. ns_lwdclientmgr_t *cm;
  136. cm = client->clientmgr;
  137. INSIST(client->byaddr == NULL);
  138. result = dns_byaddr_create(cm->mctx, &client->na, cm->view,
  139. client->options, cm->task, byaddr_done,
  140. client, &client->byaddr);
  141. if (result != ISC_R_SUCCESS) {
  142. ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
  143. return;
  144. }
  145. }
  146. static void
  147. init_gnba(ns_lwdclient_t *client) {
  148. int i;
  149. /*
  150. * Initialize the real name and alias arrays in the reply we're
  151. * going to build up.
  152. */
  153. for (i = 0; i < LWRES_MAX_ALIASES; i++) {
  154. client->aliases[i] = NULL;
  155. client->aliaslen[i] = 0;
  156. }
  157. for (i = 0; i < LWRES_MAX_ADDRS; i++) {
  158. client->addrs[i].family = 0;
  159. client->addrs[i].length = 0;
  160. memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
  161. LWRES_LINK_INIT(&client->addrs[i], link);
  162. }
  163. client->gnba.naliases = 0;
  164. client->gnba.realname = NULL;
  165. client->gnba.aliases = client->aliases;
  166. client->gnba.realnamelen = 0;
  167. client->gnba.aliaslen = client->aliaslen;
  168. client->gnba.base = NULL;
  169. client->gnba.baselen = 0;
  170. isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
  171. }
  172. void
  173. ns_lwdclient_processgnba(ns_lwdclient_t *client, lwres_buffer_t *b) {
  174. lwres_gnbarequest_t *req;
  175. isc_result_t result;
  176. isc_sockaddr_t sa;
  177. ns_lwdclientmgr_t *cm;
  178. REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
  179. INSIST(client->byaddr == NULL);
  180. cm = client->clientmgr;
  181. req = NULL;
  182. result = lwres_gnbarequest_parse(cm->lwctx,
  183. b, &client->pkt, &req);
  184. if (result != LWRES_R_SUCCESS)
  185. goto out;
  186. client->options = 0;
  187. if (req->addr.family == LWRES_ADDRTYPE_V4) {
  188. client->na.family = AF_INET;
  189. if (req->addr.length != 4)
  190. goto out;
  191. memcpy(&client->na.type.in, req->addr.address, 4);
  192. } else if (req->addr.family == LWRES_ADDRTYPE_V6) {
  193. client->na.family = AF_INET6;
  194. if (req->addr.length != 16)
  195. goto out;
  196. memcpy(&client->na.type.in6, req->addr.address, 16);
  197. } else {
  198. goto out;
  199. }
  200. isc_sockaddr_fromnetaddr(&sa, &client->na, 53);
  201. ns_lwdclient_log(50, "client %p looking for addrtype %08x",
  202. client, req->addr.family);
  203. /*
  204. * We no longer need to keep this around.
  205. */
  206. lwres_gnbarequest_free(cm->lwctx, &req);
  207. /*
  208. * Initialize the real name and alias arrays in the reply we're
  209. * going to build up.
  210. */
  211. init_gnba(client);
  212. client->options = 0;
  213. /*
  214. * Start the find.
  215. */
  216. start_byaddr(client);
  217. return;
  218. /*
  219. * We're screwed. Return an error packet to our caller.
  220. */
  221. out:
  222. if (req != NULL)
  223. lwres_gnbarequest_free(cm->lwctx, &req);
  224. ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
  225. }