xref: /minix/external/bsd/bind/dist/bin/named/notify.c (revision 00b67f09)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: notify.c,v 1.4 2014/12/10 04:37:51 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: notify.c,v 1.37 2007/06/19 23:46:59 tbox Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <isc/log.h>
25*00b67f09SDavid van Moolenbroek #include <isc/print.h>
26*00b67f09SDavid van Moolenbroek 
27*00b67f09SDavid van Moolenbroek #include <dns/message.h>
28*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
29*00b67f09SDavid van Moolenbroek #include <dns/result.h>
30*00b67f09SDavid van Moolenbroek #include <dns/tsig.h>
31*00b67f09SDavid van Moolenbroek #include <dns/view.h>
32*00b67f09SDavid van Moolenbroek #include <dns/zone.h>
33*00b67f09SDavid van Moolenbroek #include <dns/zt.h>
34*00b67f09SDavid van Moolenbroek 
35*00b67f09SDavid van Moolenbroek #include <named/log.h>
36*00b67f09SDavid van Moolenbroek #include <named/notify.h>
37*00b67f09SDavid van Moolenbroek 
38*00b67f09SDavid van Moolenbroek /*! \file
39*00b67f09SDavid van Moolenbroek  * \brief
40*00b67f09SDavid van Moolenbroek  * This module implements notify as in RFC1996.
41*00b67f09SDavid van Moolenbroek  */
42*00b67f09SDavid van Moolenbroek 
43*00b67f09SDavid van Moolenbroek static void
notify_log(ns_client_t * client,int level,const char * fmt,...)44*00b67f09SDavid van Moolenbroek notify_log(ns_client_t *client, int level, const char *fmt, ...) {
45*00b67f09SDavid van Moolenbroek 	va_list ap;
46*00b67f09SDavid van Moolenbroek 
47*00b67f09SDavid van Moolenbroek 	va_start(ap, fmt);
48*00b67f09SDavid van Moolenbroek 	ns_client_logv(client, DNS_LOGCATEGORY_NOTIFY, NS_LOGMODULE_NOTIFY,
49*00b67f09SDavid van Moolenbroek 		       level, fmt, ap);
50*00b67f09SDavid van Moolenbroek 	va_end(ap);
51*00b67f09SDavid van Moolenbroek }
52*00b67f09SDavid van Moolenbroek 
53*00b67f09SDavid van Moolenbroek static void
respond(ns_client_t * client,isc_result_t result)54*00b67f09SDavid van Moolenbroek respond(ns_client_t *client, isc_result_t result) {
55*00b67f09SDavid van Moolenbroek 	dns_rcode_t rcode;
56*00b67f09SDavid van Moolenbroek 	dns_message_t *message;
57*00b67f09SDavid van Moolenbroek 	isc_result_t msg_result;
58*00b67f09SDavid van Moolenbroek 
59*00b67f09SDavid van Moolenbroek 	message = client->message;
60*00b67f09SDavid van Moolenbroek 	rcode = dns_result_torcode(result);
61*00b67f09SDavid van Moolenbroek 
62*00b67f09SDavid van Moolenbroek 	msg_result = dns_message_reply(message, ISC_TRUE);
63*00b67f09SDavid van Moolenbroek 	if (msg_result != ISC_R_SUCCESS)
64*00b67f09SDavid van Moolenbroek 		msg_result = dns_message_reply(message, ISC_FALSE);
65*00b67f09SDavid van Moolenbroek 	if (msg_result != ISC_R_SUCCESS) {
66*00b67f09SDavid van Moolenbroek 		ns_client_next(client, msg_result);
67*00b67f09SDavid van Moolenbroek 		return;
68*00b67f09SDavid van Moolenbroek 	}
69*00b67f09SDavid van Moolenbroek 	message->rcode = rcode;
70*00b67f09SDavid van Moolenbroek 	if (rcode == dns_rcode_noerror)
71*00b67f09SDavid van Moolenbroek 		message->flags |= DNS_MESSAGEFLAG_AA;
72*00b67f09SDavid van Moolenbroek 	else
73*00b67f09SDavid van Moolenbroek 		message->flags &= ~DNS_MESSAGEFLAG_AA;
74*00b67f09SDavid van Moolenbroek 	ns_client_send(client);
75*00b67f09SDavid van Moolenbroek }
76*00b67f09SDavid van Moolenbroek 
77*00b67f09SDavid van Moolenbroek void
ns_notify_start(ns_client_t * client)78*00b67f09SDavid van Moolenbroek ns_notify_start(ns_client_t *client) {
79*00b67f09SDavid van Moolenbroek 	dns_message_t *request = client->message;
80*00b67f09SDavid van Moolenbroek 	isc_result_t result;
81*00b67f09SDavid van Moolenbroek 	dns_name_t *zonename;
82*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *zone_rdataset;
83*00b67f09SDavid van Moolenbroek 	dns_zone_t *zone = NULL;
84*00b67f09SDavid van Moolenbroek 	char namebuf[DNS_NAME_FORMATSIZE];
85*00b67f09SDavid van Moolenbroek 	char tsigbuf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
86*00b67f09SDavid van Moolenbroek 	dns_tsigkey_t *tsigkey;
87*00b67f09SDavid van Moolenbroek 
88*00b67f09SDavid van Moolenbroek 	/*
89*00b67f09SDavid van Moolenbroek 	 * Interpret the question section.
90*00b67f09SDavid van Moolenbroek 	 */
91*00b67f09SDavid van Moolenbroek 	result = dns_message_firstname(request, DNS_SECTION_QUESTION);
92*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
93*00b67f09SDavid van Moolenbroek 		notify_log(client, ISC_LOG_NOTICE,
94*00b67f09SDavid van Moolenbroek 			   "notify question section empty");
95*00b67f09SDavid van Moolenbroek 		goto formerr;
96*00b67f09SDavid van Moolenbroek 	}
97*00b67f09SDavid van Moolenbroek 
98*00b67f09SDavid van Moolenbroek 	/*
99*00b67f09SDavid van Moolenbroek 	 * The question section must contain exactly one question.
100*00b67f09SDavid van Moolenbroek 	 */
101*00b67f09SDavid van Moolenbroek 	zonename = NULL;
102*00b67f09SDavid van Moolenbroek 	dns_message_currentname(request, DNS_SECTION_QUESTION, &zonename);
103*00b67f09SDavid van Moolenbroek 	zone_rdataset = ISC_LIST_HEAD(zonename->list);
104*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) {
105*00b67f09SDavid van Moolenbroek 		notify_log(client, ISC_LOG_NOTICE,
106*00b67f09SDavid van Moolenbroek 			   "notify question section contains multiple RRs");
107*00b67f09SDavid van Moolenbroek 		goto formerr;
108*00b67f09SDavid van Moolenbroek 	}
109*00b67f09SDavid van Moolenbroek 
110*00b67f09SDavid van Moolenbroek 	/* The zone section must have exactly one name. */
111*00b67f09SDavid van Moolenbroek 	result = dns_message_nextname(request, DNS_SECTION_ZONE);
112*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_NOMORE) {
113*00b67f09SDavid van Moolenbroek 		notify_log(client, ISC_LOG_NOTICE,
114*00b67f09SDavid van Moolenbroek 			   "notify question section contains multiple RRs");
115*00b67f09SDavid van Moolenbroek 		goto formerr;
116*00b67f09SDavid van Moolenbroek 	}
117*00b67f09SDavid van Moolenbroek 
118*00b67f09SDavid van Moolenbroek 	/* The one rdataset must be an SOA. */
119*00b67f09SDavid van Moolenbroek 	if (zone_rdataset->type != dns_rdatatype_soa) {
120*00b67f09SDavid van Moolenbroek 		notify_log(client, ISC_LOG_NOTICE,
121*00b67f09SDavid van Moolenbroek 			   "notify question section contains no SOA");
122*00b67f09SDavid van Moolenbroek 		goto formerr;
123*00b67f09SDavid van Moolenbroek 	}
124*00b67f09SDavid van Moolenbroek 
125*00b67f09SDavid van Moolenbroek 	tsigkey = dns_message_gettsigkey(request);
126*00b67f09SDavid van Moolenbroek 	if (tsigkey != NULL) {
127*00b67f09SDavid van Moolenbroek 		dns_name_format(&tsigkey->name, namebuf, sizeof(namebuf));
128*00b67f09SDavid van Moolenbroek 
129*00b67f09SDavid van Moolenbroek 		if (tsigkey->generated) {
130*00b67f09SDavid van Moolenbroek 			char cnamebuf[DNS_NAME_FORMATSIZE];
131*00b67f09SDavid van Moolenbroek 			dns_name_format(tsigkey->creator, cnamebuf,
132*00b67f09SDavid van Moolenbroek 					sizeof(cnamebuf));
133*00b67f09SDavid van Moolenbroek 			snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s' (%s)",
134*00b67f09SDavid van Moolenbroek 				 namebuf, cnamebuf);
135*00b67f09SDavid van Moolenbroek 		} else {
136*00b67f09SDavid van Moolenbroek 			snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'",
137*00b67f09SDavid van Moolenbroek 				 namebuf);
138*00b67f09SDavid van Moolenbroek 		}
139*00b67f09SDavid van Moolenbroek 	} else
140*00b67f09SDavid van Moolenbroek 		tsigbuf[0] = '\0';
141*00b67f09SDavid van Moolenbroek 	dns_name_format(zonename, namebuf, sizeof(namebuf));
142*00b67f09SDavid van Moolenbroek 	result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,
143*00b67f09SDavid van Moolenbroek 			     &zone);
144*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
145*00b67f09SDavid van Moolenbroek 		goto notauth;
146*00b67f09SDavid van Moolenbroek 
147*00b67f09SDavid van Moolenbroek 	switch (dns_zone_gettype(zone)) {
148*00b67f09SDavid van Moolenbroek 	case dns_zone_master:
149*00b67f09SDavid van Moolenbroek 	case dns_zone_slave:
150*00b67f09SDavid van Moolenbroek 	case dns_zone_stub:	/* Allow dialup passive to work. */
151*00b67f09SDavid van Moolenbroek 		notify_log(client, ISC_LOG_INFO,
152*00b67f09SDavid van Moolenbroek 			   "received notify for zone '%s'%s", namebuf, tsigbuf);
153*00b67f09SDavid van Moolenbroek 		respond(client, dns_zone_notifyreceive(zone,
154*00b67f09SDavid van Moolenbroek 			ns_client_getsockaddr(client), request));
155*00b67f09SDavid van Moolenbroek 		break;
156*00b67f09SDavid van Moolenbroek 	default:
157*00b67f09SDavid van Moolenbroek 		goto notauth;
158*00b67f09SDavid van Moolenbroek 	}
159*00b67f09SDavid van Moolenbroek 	dns_zone_detach(&zone);
160*00b67f09SDavid van Moolenbroek 	return;
161*00b67f09SDavid van Moolenbroek 
162*00b67f09SDavid van Moolenbroek  notauth:
163*00b67f09SDavid van Moolenbroek 	notify_log(client, ISC_LOG_NOTICE,
164*00b67f09SDavid van Moolenbroek 		   "received notify for zone '%s'%s: not authoritative",
165*00b67f09SDavid van Moolenbroek 		   namebuf, tsigbuf);
166*00b67f09SDavid van Moolenbroek 	result = DNS_R_NOTAUTH;
167*00b67f09SDavid van Moolenbroek 	goto failure;
168*00b67f09SDavid van Moolenbroek 
169*00b67f09SDavid van Moolenbroek  formerr:
170*00b67f09SDavid van Moolenbroek 	result = DNS_R_FORMERR;
171*00b67f09SDavid van Moolenbroek 
172*00b67f09SDavid van Moolenbroek  failure:
173*00b67f09SDavid van Moolenbroek 	if (zone != NULL)
174*00b67f09SDavid van Moolenbroek 		dns_zone_detach(&zone);
175*00b67f09SDavid van Moolenbroek 	respond(client, result);
176*00b67f09SDavid van Moolenbroek }
177