d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews/*
a853d87fc422f5ade566a5e264bbb1a6914dbef6Tinderbox User * Copyright (C) 1999-2007, 2016, 2018 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
70e5a7403f0e0a3bd292b8287c5fed5772c15270Automatic Updater/* $Id: notify.c,v 1.37 2007/06/19 23:46:59 tbox Exp $ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <config.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington#include <isc/log.h>
16a68807e13caea3183a41a5292f1b3f48b81a26Mark Andrews#include <isc/print.h>
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <dns/message.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <dns/rdataset.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <dns/result.h>
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews#include <dns/tsig.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <dns/view.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <dns/zone.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <dns/zt.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <named/log.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#include <named/notify.h>
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \brief
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * This module implements notify as in RFC1996.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellingtonstatic void
8e40433e347bc487cd70f02487fc7ce947a2422aMark Andrewsnotify_log(ns_client_t *client, int level, const char *fmt, ...) {
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington va_list ap;
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington va_start(ap, fmt);
8e40433e347bc487cd70f02487fc7ce947a2422aMark Andrews ns_client_logv(client, DNS_LOGCATEGORY_NOTIFY, NS_LOGMODULE_NOTIFY,
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington level, fmt, ap);
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington va_end(ap);
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington}
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrewsstatic void
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffrespond(ns_client_t *client, isc_result_t result) {
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews dns_rcode_t rcode;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington dns_message_t *message;
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington isc_result_t msg_result;
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews message = client->message;
542189f21b3ea9b27b0fbc047d832a34dcaf75bcAndreas Gustafsson rcode = dns_result_torcode(result);
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews msg_result = dns_message_reply(message, ISC_TRUE);
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews if (msg_result != ISC_R_SUCCESS)
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews msg_result = dns_message_reply(message, ISC_FALSE);
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews if (msg_result != ISC_R_SUCCESS) {
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews ns_client_next(client, msg_result);
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews return;
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews }
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews message->rcode = rcode;
b03a619e1d426c52c5cf7a5778982074ac6515c8Mark Andrews if (rcode == dns_rcode_noerror)
b03a619e1d426c52c5cf7a5778982074ac6515c8Mark Andrews message->flags |= DNS_MESSAGEFLAG_AA;
b03a619e1d426c52c5cf7a5778982074ac6515c8Mark Andrews else
b03a619e1d426c52c5cf7a5778982074ac6515c8Mark Andrews message->flags &= ~DNS_MESSAGEFLAG_AA;
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews ns_client_send(client);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews}
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrewsvoid
f9aa0a668c059e0fda1b06882c68aaeb4e840e1bDavid Lawrencens_notify_start(ns_client_t *client) {
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews dns_message_t *request = client->message;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews dns_name_t *zonename;
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews dns_rdataset_t *zone_rdataset;
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews dns_zone_t *zone = NULL;
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews char namebuf[DNS_NAME_FORMATSIZE];
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews char tsigbuf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_tsigkey_t *tsigkey;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews /*
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * Interpret the question section.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews result = dns_message_firstname(request, DNS_SECTION_QUESTION);
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington if (result != ISC_R_SUCCESS) {
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews notify_log(client, ISC_LOG_NOTICE,
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews "notify question section empty");
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman result = DNS_R_FORMERR;
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman goto done;
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington }
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews /*
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * The question section must contain exactly one question.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews zonename = NULL;
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews dns_message_currentname(request, DNS_SECTION_QUESTION, &zonename);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews zone_rdataset = ISC_LIST_HEAD(zonename->list);
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) {
1431917c7cddbac7442cb910e83cb058fea59fb5Mark Andrews notify_log(client, ISC_LOG_NOTICE,
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington "notify question section contains multiple RRs");
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman result = DNS_R_FORMERR;
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman goto done;
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington }
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews /* The zone section must have exactly one name. */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews result = dns_message_nextname(request, DNS_SECTION_ZONE);
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington if (result != ISC_R_NOMORE) {
1431917c7cddbac7442cb910e83cb058fea59fb5Mark Andrews notify_log(client, ISC_LOG_NOTICE,
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington "notify question section contains multiple RRs");
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman result = DNS_R_FORMERR;
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman goto done;
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington }
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington /* The one rdataset must be an SOA. */
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington if (zone_rdataset->type != dns_rdatatype_soa) {
1431917c7cddbac7442cb910e83cb058fea59fb5Mark Andrews notify_log(client, ISC_LOG_NOTICE,
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington "notify question section contains no SOA");
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman result = DNS_R_FORMERR;
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman goto done;
eeb77542a8b85f04665b2cfe34496cdab844a1b1Brian Wellington }
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews tsigkey = dns_message_gettsigkey(request);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (tsigkey != NULL) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_name_format(&tsigkey->name, namebuf, sizeof(namebuf));
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (tsigkey->generated) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews char cnamebuf[DNS_NAME_FORMATSIZE];
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews dns_name_format(tsigkey->creator, cnamebuf,
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews sizeof(cnamebuf));
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s' (%s)",
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews namebuf, cnamebuf);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews } else {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'",
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews namebuf);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews }
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews } else
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews tsigbuf[0] = '\0';
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews dns_name_format(zonename, namebuf, sizeof(namebuf));
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, &zone);
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman if (result == ISC_R_SUCCESS) {
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman dns_zonetype_t zonetype = dns_zone_gettype(zone);
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman if ((zonetype == dns_zone_master) ||
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman (zonetype == dns_zone_slave) ||
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman (zonetype == dns_zone_stub))
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman {
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman isc_sockaddr_t *from = ns_client_getsockaddr(client);
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman isc_sockaddr_t *to = ns_client_getdestaddr(client);
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman notify_log(client, ISC_LOG_INFO,
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman "received notify for zone '%s'%s",
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman namebuf, tsigbuf);
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman result = dns_zone_notifyreceive2(zone, from, to,
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman request);
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman goto done;
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman }
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews notify_log(client, ISC_LOG_NOTICE,
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews "received notify for zone '%s'%s: not authoritative",
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews namebuf, tsigbuf);
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews result = DNS_R_NOTAUTH;
ee84964a7d29ae88769f67326a65256731769ea7Mark Andrews
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman done:
c6ce77b4dccb15297f78de9e0c00d40f40ce8aa4Mark Andrews if (zone != NULL)
c6ce77b4dccb15297f78de9e0c00d40f40ce8aa4Mark Andrews dns_zone_detach(&zone);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews respond(client, result);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews}