/contrib/bind9/bin/named/notify.c

https://bitbucket.org/freebsd/freebsd-head/
C | 174 lines | 123 code | 22 blank | 29 comment | 23 complexity | c9e467869b13a18058e0b3374f9ab012 MD5 | raw file

✨ Summary
  1. /*
  2. * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-2003 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: notify.c,v 1.37 2007/06/19 23:46:59 tbox Exp $ */
  18. #include <config.h>
  19. #include <isc/log.h>
  20. #include <isc/print.h>
  21. #include <dns/message.h>
  22. #include <dns/rdataset.h>
  23. #include <dns/result.h>
  24. #include <dns/tsig.h>
  25. #include <dns/view.h>
  26. #include <dns/zone.h>
  27. #include <dns/zt.h>
  28. #include <named/log.h>
  29. #include <named/notify.h>
  30. /*! \file
  31. * \brief
  32. * This module implements notify as in RFC1996.
  33. */
  34. static void
  35. notify_log(ns_client_t *client, int level, const char *fmt, ...) {
  36. va_list ap;
  37. va_start(ap, fmt);
  38. ns_client_logv(client, DNS_LOGCATEGORY_NOTIFY, NS_LOGMODULE_NOTIFY,
  39. level, fmt, ap);
  40. va_end(ap);
  41. }
  42. static void
  43. respond(ns_client_t *client, isc_result_t result) {
  44. dns_rcode_t rcode;
  45. dns_message_t *message;
  46. isc_result_t msg_result;
  47. message = client->message;
  48. rcode = dns_result_torcode(result);
  49. msg_result = dns_message_reply(message, ISC_TRUE);
  50. if (msg_result != ISC_R_SUCCESS)
  51. msg_result = dns_message_reply(message, ISC_FALSE);
  52. if (msg_result != ISC_R_SUCCESS) {
  53. ns_client_next(client, msg_result);
  54. return;
  55. }
  56. message->rcode = rcode;
  57. if (rcode == dns_rcode_noerror)
  58. message->flags |= DNS_MESSAGEFLAG_AA;
  59. else
  60. message->flags &= ~DNS_MESSAGEFLAG_AA;
  61. ns_client_send(client);
  62. }
  63. void
  64. ns_notify_start(ns_client_t *client) {
  65. dns_message_t *request = client->message;
  66. isc_result_t result;
  67. dns_name_t *zonename;
  68. dns_rdataset_t *zone_rdataset;
  69. dns_zone_t *zone = NULL;
  70. char namebuf[DNS_NAME_FORMATSIZE];
  71. char tsigbuf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
  72. dns_tsigkey_t *tsigkey;
  73. /*
  74. * Interpret the question section.
  75. */
  76. result = dns_message_firstname(request, DNS_SECTION_QUESTION);
  77. if (result != ISC_R_SUCCESS) {
  78. notify_log(client, ISC_LOG_NOTICE,
  79. "notify question section empty");
  80. goto formerr;
  81. }
  82. /*
  83. * The question section must contain exactly one question.
  84. */
  85. zonename = NULL;
  86. dns_message_currentname(request, DNS_SECTION_QUESTION, &zonename);
  87. zone_rdataset = ISC_LIST_HEAD(zonename->list);
  88. if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) {
  89. notify_log(client, ISC_LOG_NOTICE,
  90. "notify question section contains multiple RRs");
  91. goto formerr;
  92. }
  93. /* The zone section must have exactly one name. */
  94. result = dns_message_nextname(request, DNS_SECTION_ZONE);
  95. if (result != ISC_R_NOMORE) {
  96. notify_log(client, ISC_LOG_NOTICE,
  97. "notify question section contains multiple RRs");
  98. goto formerr;
  99. }
  100. /* The one rdataset must be an SOA. */
  101. if (zone_rdataset->type != dns_rdatatype_soa) {
  102. notify_log(client, ISC_LOG_NOTICE,
  103. "notify question section contains no SOA");
  104. goto formerr;
  105. }
  106. tsigkey = dns_message_gettsigkey(request);
  107. if (tsigkey != NULL) {
  108. dns_name_format(&tsigkey->name, namebuf, sizeof(namebuf));
  109. if (tsigkey->generated) {
  110. char cnamebuf[DNS_NAME_FORMATSIZE];
  111. dns_name_format(tsigkey->creator, cnamebuf,
  112. sizeof(cnamebuf));
  113. snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s' (%s)",
  114. namebuf, cnamebuf);
  115. } else {
  116. snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'",
  117. namebuf);
  118. }
  119. } else
  120. tsigbuf[0] = '\0';
  121. dns_name_format(zonename, namebuf, sizeof(namebuf));
  122. result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,
  123. &zone);
  124. if (result != ISC_R_SUCCESS)
  125. goto notauth;
  126. switch (dns_zone_gettype(zone)) {
  127. case dns_zone_master:
  128. case dns_zone_slave:
  129. case dns_zone_stub: /* Allow dialup passive to work. */
  130. notify_log(client, ISC_LOG_INFO,
  131. "received notify for zone '%s'%s", namebuf, tsigbuf);
  132. respond(client, dns_zone_notifyreceive(zone,
  133. ns_client_getsockaddr(client), request));
  134. break;
  135. default:
  136. goto notauth;
  137. }
  138. dns_zone_detach(&zone);
  139. return;
  140. notauth:
  141. notify_log(client, ISC_LOG_NOTICE,
  142. "received notify for zone '%s'%s: not authoritative",
  143. namebuf, tsigbuf);
  144. result = DNS_R_NOTAUTH;
  145. goto failure;
  146. formerr:
  147. result = DNS_R_FORMERR;
  148. failure:
  149. if (zone != NULL)
  150. dns_zone_detach(&zone);
  151. respond(client, result);
  152. }