xref: /netbsd-src/external/mpl/bind/dist/lib/dns/private.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1*bcda20f6Schristos /*	$NetBSD: private.c,v 1.10 2025/01/26 16:25:24 christos Exp $	*/
2d68c78b8Schristos 
3d68c78b8Schristos /*
4d68c78b8Schristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5d68c78b8Schristos  *
68596601aSchristos  * SPDX-License-Identifier: MPL-2.0
78596601aSchristos  *
8d68c78b8Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
9d68c78b8Schristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
10fce770bdSchristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11d68c78b8Schristos  *
12d68c78b8Schristos  * See the COPYRIGHT file distributed with this work for additional
13d68c78b8Schristos  * information regarding copyright ownership.
14d68c78b8Schristos  */
15d68c78b8Schristos 
16d4a20c3eSchristos #include <stdbool.h>
17d68c78b8Schristos 
18d68c78b8Schristos #include <isc/base64.h>
19d68c78b8Schristos #include <isc/result.h>
20d68c78b8Schristos #include <isc/string.h>
21d68c78b8Schristos #include <isc/types.h>
22d68c78b8Schristos #include <isc/util.h>
23d68c78b8Schristos 
24d68c78b8Schristos #include <dns/nsec3.h>
25d68c78b8Schristos #include <dns/private.h>
26d68c78b8Schristos 
27d68c78b8Schristos /*
28d68c78b8Schristos  * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
29d68c78b8Schristos  * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
30d68c78b8Schristos  *
31d68c78b8Schristos  * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
32d68c78b8Schristos  * if all the NSEC3PARAM records (and associated chains) are slated for
33d68c78b8Schristos  * destruction and we have not been told to NOT build the NSEC chain.
34d68c78b8Schristos  *
35d68c78b8Schristos  * If the NSEC set exist then check to see if there is a request to create
36d68c78b8Schristos  * a NSEC3 chain.
37d68c78b8Schristos  *
38d68c78b8Schristos  * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
39d68c78b8Schristos  * type exists then we need to examine it to determine if NSEC3 chain has
40d68c78b8Schristos  * been requested to be built otherwise a NSEC chain needs to be built.
41d68c78b8Schristos  */
42d68c78b8Schristos 
43d68c78b8Schristos #define REMOVE(x)  (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
44d68c78b8Schristos #define CREATE(x)  (((x) & DNS_NSEC3FLAG_CREATE) != 0)
45d68c78b8Schristos #define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
46d68c78b8Schristos #define NONSEC(x)  (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
47d68c78b8Schristos 
485606745fSchristos #define CHECK(x)                             \
495606745fSchristos 	do {                                 \
50d68c78b8Schristos 		result = (x);                \
51d68c78b8Schristos 		if (result != ISC_R_SUCCESS) \
52d68c78b8Schristos 			goto failure;        \
5353cc4e50Srillig 	} while (0)
54d68c78b8Schristos 
55d68c78b8Schristos /*
56d68c78b8Schristos  * Work out if 'param' should be ignored or not (i.e. it is in the process
57d68c78b8Schristos  * of being removed).
58d68c78b8Schristos  *
59d68c78b8Schristos  * Note: we 'belt-and-braces' here by also checking for a CREATE private
60d68c78b8Schristos  * record and keep the param record in this case.
61d68c78b8Schristos  */
62d68c78b8Schristos 
63d4a20c3eSchristos static bool
64d68c78b8Schristos ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
65d68c78b8Schristos 	isc_result_t result;
66d68c78b8Schristos 
675606745fSchristos 	for (result = dns_rdataset_first(privateset); result == ISC_R_SUCCESS;
685606745fSchristos 	     result = dns_rdataset_next(privateset))
695606745fSchristos 	{
70d68c78b8Schristos 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
71d68c78b8Schristos 		dns_rdata_t private = DNS_RDATA_INIT;
72d68c78b8Schristos 		dns_rdata_t rdata = DNS_RDATA_INIT;
73d68c78b8Schristos 
74d68c78b8Schristos 		dns_rdataset_current(privateset, &private);
755606745fSchristos 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
76903adeddSchristos 						sizeof(buf)))
77903adeddSchristos 		{
78d68c78b8Schristos 			continue;
795606745fSchristos 		}
80d68c78b8Schristos 		/*
81d68c78b8Schristos 		 * We are going to create a new NSEC3 chain so it
82d68c78b8Schristos 		 * doesn't matter if we are removing this one.
83d68c78b8Schristos 		 */
845606745fSchristos 		if (CREATE(rdata.data[1])) {
85*bcda20f6Schristos 			return false;
865606745fSchristos 		}
87d68c78b8Schristos 		if (rdata.data[0] != param->data[0] ||
88d68c78b8Schristos 		    rdata.data[2] != param->data[2] ||
89d68c78b8Schristos 		    rdata.data[3] != param->data[3] ||
90d68c78b8Schristos 		    rdata.data[4] != param->data[4] ||
91d68c78b8Schristos 		    memcmp(&rdata.data[5], &param->data[5], param->data[4]))
925606745fSchristos 		{
93d68c78b8Schristos 			continue;
945606745fSchristos 		}
95d68c78b8Schristos 		/*
96d68c78b8Schristos 		 * The removal of this NSEC3 chain does NOT cause a
97d68c78b8Schristos 		 * NSEC chain to be created so we don't need to tell
98d68c78b8Schristos 		 * the caller that it will be removed.
99d68c78b8Schristos 		 */
1005606745fSchristos 		if (NONSEC(rdata.data[1])) {
101*bcda20f6Schristos 			return false;
1025606745fSchristos 		}
103*bcda20f6Schristos 		return true;
104d68c78b8Schristos 	}
105*bcda20f6Schristos 	return false;
106d68c78b8Schristos }
107d68c78b8Schristos 
108d68c78b8Schristos isc_result_t
109d68c78b8Schristos dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
1105606745fSchristos 		   dns_rdatatype_t privatetype, bool *build_nsec,
1115606745fSchristos 		   bool *build_nsec3) {
112d68c78b8Schristos 	dns_dbnode_t *node;
113d68c78b8Schristos 	dns_rdataset_t nsecset, nsec3paramset, privateset;
114d4a20c3eSchristos 	bool nsec3chain;
115d4a20c3eSchristos 	bool signing;
116d68c78b8Schristos 	isc_result_t result;
117d68c78b8Schristos 	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
118d68c78b8Schristos 	unsigned int count;
119d68c78b8Schristos 
120d68c78b8Schristos 	node = NULL;
121d68c78b8Schristos 	dns_rdataset_init(&nsecset);
122d68c78b8Schristos 	dns_rdataset_init(&nsec3paramset);
123d68c78b8Schristos 	dns_rdataset_init(&privateset);
124d68c78b8Schristos 
125d68c78b8Schristos 	CHECK(dns_db_getoriginnode(db, &node));
126d68c78b8Schristos 
1275606745fSchristos 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0,
1285606745fSchristos 				     (isc_stdtime_t)0, &nsecset, NULL);
129d68c78b8Schristos 
1305606745fSchristos 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
131d68c78b8Schristos 		goto failure;
1325606745fSchristos 	}
133d68c78b8Schristos 
1345606745fSchristos 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
1355606745fSchristos 				     (isc_stdtime_t)0, &nsec3paramset, NULL);
1365606745fSchristos 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
137d68c78b8Schristos 		goto failure;
1385606745fSchristos 	}
139d68c78b8Schristos 
140d68c78b8Schristos 	if (dns_rdataset_isassociated(&nsecset) &&
1415606745fSchristos 	    dns_rdataset_isassociated(&nsec3paramset))
1425606745fSchristos 	{
1435606745fSchristos 		if (build_nsec != NULL) {
144d4a20c3eSchristos 			*build_nsec = true;
1455606745fSchristos 		}
1465606745fSchristos 		if (build_nsec3 != NULL) {
147d4a20c3eSchristos 			*build_nsec3 = true;
1485606745fSchristos 		}
149d68c78b8Schristos 		goto success;
150d68c78b8Schristos 	}
151d68c78b8Schristos 
152d68c78b8Schristos 	if (privatetype != (dns_rdatatype_t)0) {
1535606745fSchristos 		result = dns_db_findrdataset(db, node, ver, privatetype, 0,
1545606745fSchristos 					     (isc_stdtime_t)0, &privateset,
1555606745fSchristos 					     NULL);
1565606745fSchristos 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
157d68c78b8Schristos 			goto failure;
158d68c78b8Schristos 		}
1595606745fSchristos 	}
160d68c78b8Schristos 
161d68c78b8Schristos 	/*
162d68c78b8Schristos 	 * Look to see if we also need to be creating a NSEC3 chain.
163d68c78b8Schristos 	 */
164d68c78b8Schristos 	if (dns_rdataset_isassociated(&nsecset)) {
1655606745fSchristos 		if (build_nsec != NULL) {
166d4a20c3eSchristos 			*build_nsec = true;
1675606745fSchristos 		}
1685606745fSchristos 		if (build_nsec3 != NULL) {
169d4a20c3eSchristos 			*build_nsec3 = false;
1705606745fSchristos 		}
1715606745fSchristos 		if (!dns_rdataset_isassociated(&privateset)) {
172d68c78b8Schristos 			goto success;
1735606745fSchristos 		}
174d68c78b8Schristos 		for (result = dns_rdataset_first(&privateset);
175d68c78b8Schristos 		     result == ISC_R_SUCCESS;
1765606745fSchristos 		     result = dns_rdataset_next(&privateset))
1775606745fSchristos 		{
178d68c78b8Schristos 			dns_rdata_t private = DNS_RDATA_INIT;
179d68c78b8Schristos 			dns_rdata_t rdata = DNS_RDATA_INIT;
180d68c78b8Schristos 
181d68c78b8Schristos 			dns_rdataset_current(&privateset, &private);
1825606745fSchristos 			if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
183903adeddSchristos 							sizeof(buf)))
184903adeddSchristos 			{
185d68c78b8Schristos 				continue;
1865606745fSchristos 			}
1875606745fSchristos 			if (REMOVE(rdata.data[1])) {
188d68c78b8Schristos 				continue;
1895606745fSchristos 			}
1905606745fSchristos 			if (build_nsec3 != NULL) {
191d4a20c3eSchristos 				*build_nsec3 = true;
1925606745fSchristos 			}
193d68c78b8Schristos 			break;
194d68c78b8Schristos 		}
195d68c78b8Schristos 		goto success;
196d68c78b8Schristos 	}
197d68c78b8Schristos 
198d68c78b8Schristos 	if (dns_rdataset_isassociated(&nsec3paramset)) {
1995606745fSchristos 		if (build_nsec3 != NULL) {
200d4a20c3eSchristos 			*build_nsec3 = true;
2015606745fSchristos 		}
2025606745fSchristos 		if (build_nsec != NULL) {
203d4a20c3eSchristos 			*build_nsec = false;
2045606745fSchristos 		}
2055606745fSchristos 		if (!dns_rdataset_isassociated(&privateset)) {
206d68c78b8Schristos 			goto success;
2075606745fSchristos 		}
208d68c78b8Schristos 		/*
209d68c78b8Schristos 		 * If we are in the process of building a new NSEC3 chain
210d68c78b8Schristos 		 * then we don't need to build a NSEC chain.
211d68c78b8Schristos 		 */
212d68c78b8Schristos 		for (result = dns_rdataset_first(&privateset);
213d68c78b8Schristos 		     result == ISC_R_SUCCESS;
2145606745fSchristos 		     result = dns_rdataset_next(&privateset))
2155606745fSchristos 		{
216d68c78b8Schristos 			dns_rdata_t private = DNS_RDATA_INIT;
217d68c78b8Schristos 			dns_rdata_t rdata = DNS_RDATA_INIT;
218d68c78b8Schristos 
219d68c78b8Schristos 			dns_rdataset_current(&privateset, &private);
2205606745fSchristos 			if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
221903adeddSchristos 							sizeof(buf)))
222903adeddSchristos 			{
223d68c78b8Schristos 				continue;
2245606745fSchristos 			}
2255606745fSchristos 			if (CREATE(rdata.data[1])) {
226d68c78b8Schristos 				goto success;
227d68c78b8Schristos 			}
2285606745fSchristos 		}
229d68c78b8Schristos 
230d68c78b8Schristos 		/*
231d68c78b8Schristos 		 * Check to see if there will be a active NSEC3CHAIN once
232d68c78b8Schristos 		 * the changes queued complete.
233d68c78b8Schristos 		 */
234d68c78b8Schristos 		count = 0;
235d68c78b8Schristos 		for (result = dns_rdataset_first(&nsec3paramset);
236d68c78b8Schristos 		     result == ISC_R_SUCCESS;
2375606745fSchristos 		     result = dns_rdataset_next(&nsec3paramset))
2385606745fSchristos 		{
239d68c78b8Schristos 			dns_rdata_t rdata = DNS_RDATA_INIT;
240d68c78b8Schristos 
241d68c78b8Schristos 			/*
242d68c78b8Schristos 			 * If there is more that one NSEC3 chain present then
243d68c78b8Schristos 			 * we don't need to construct a NSEC chain.
244d68c78b8Schristos 			 */
2455606745fSchristos 			if (++count > 1) {
246d68c78b8Schristos 				goto success;
2475606745fSchristos 			}
248d68c78b8Schristos 			dns_rdataset_current(&nsec3paramset, &rdata);
2495606745fSchristos 			if (ignore(&rdata, &privateset)) {
250d68c78b8Schristos 				continue;
2515606745fSchristos 			}
252d68c78b8Schristos 			/*
253d68c78b8Schristos 			 * We still have a good NSEC3 chain or we are
254d68c78b8Schristos 			 * not creating a NSEC chain as NONSEC is set.
255d68c78b8Schristos 			 */
256d68c78b8Schristos 			goto success;
257d68c78b8Schristos 		}
258d68c78b8Schristos 
259d68c78b8Schristos 		/*
260d68c78b8Schristos 		 * The last NSEC3 chain is being removed and does not have
261d68c78b8Schristos 		 * have NONSEC set.
262d68c78b8Schristos 		 */
2635606745fSchristos 		if (build_nsec != NULL) {
264d4a20c3eSchristos 			*build_nsec = true;
2655606745fSchristos 		}
266d68c78b8Schristos 		goto success;
267d68c78b8Schristos 	}
268d68c78b8Schristos 
2695606745fSchristos 	if (build_nsec != NULL) {
270d4a20c3eSchristos 		*build_nsec = false;
2715606745fSchristos 	}
2725606745fSchristos 	if (build_nsec3 != NULL) {
273d4a20c3eSchristos 		*build_nsec3 = false;
2745606745fSchristos 	}
2755606745fSchristos 	if (!dns_rdataset_isassociated(&privateset)) {
276d68c78b8Schristos 		goto success;
2775606745fSchristos 	}
278d68c78b8Schristos 
279d4a20c3eSchristos 	signing = false;
280d4a20c3eSchristos 	nsec3chain = false;
281d68c78b8Schristos 
2825606745fSchristos 	for (result = dns_rdataset_first(&privateset); result == ISC_R_SUCCESS;
2835606745fSchristos 	     result = dns_rdataset_next(&privateset))
2845606745fSchristos 	{
285d68c78b8Schristos 		dns_rdata_t rdata = DNS_RDATA_INIT;
286d68c78b8Schristos 		dns_rdata_t private = DNS_RDATA_INIT;
287d68c78b8Schristos 
288d68c78b8Schristos 		dns_rdataset_current(&privateset, &private);
2895606745fSchristos 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
290903adeddSchristos 						sizeof(buf)))
291903adeddSchristos 		{
292d68c78b8Schristos 			/*
293d68c78b8Schristos 			 * Look for record that says we are signing the
294d68c78b8Schristos 			 * zone with a key.
295d68c78b8Schristos 			 */
296d68c78b8Schristos 			if (private.length == 5 && private.data[0] != 0 &&
297d68c78b8Schristos 			    private.data[3] == 0 && private.data[4] == 0)
2985606745fSchristos 			{
299d4a20c3eSchristos 				signing = true;
3005606745fSchristos 			}
301d68c78b8Schristos 		} else {
3025606745fSchristos 			if (CREATE(rdata.data[1])) {
303d4a20c3eSchristos 				nsec3chain = true;
304d68c78b8Schristos 			}
305d68c78b8Schristos 		}
3065606745fSchristos 	}
307d68c78b8Schristos 
308d68c78b8Schristos 	if (signing) {
309d68c78b8Schristos 		if (nsec3chain) {
3105606745fSchristos 			if (build_nsec3 != NULL) {
311d4a20c3eSchristos 				*build_nsec3 = true;
3125606745fSchristos 			}
313d68c78b8Schristos 		} else {
3145606745fSchristos 			if (build_nsec != NULL) {
315d4a20c3eSchristos 				*build_nsec = true;
316d68c78b8Schristos 			}
317d68c78b8Schristos 		}
3185606745fSchristos 	}
319d68c78b8Schristos 
320d68c78b8Schristos success:
321d68c78b8Schristos 	result = ISC_R_SUCCESS;
322d68c78b8Schristos failure:
3235606745fSchristos 	if (dns_rdataset_isassociated(&nsecset)) {
324d68c78b8Schristos 		dns_rdataset_disassociate(&nsecset);
3255606745fSchristos 	}
3265606745fSchristos 	if (dns_rdataset_isassociated(&nsec3paramset)) {
327d68c78b8Schristos 		dns_rdataset_disassociate(&nsec3paramset);
3285606745fSchristos 	}
3295606745fSchristos 	if (dns_rdataset_isassociated(&privateset)) {
330d68c78b8Schristos 		dns_rdataset_disassociate(&privateset);
3315606745fSchristos 	}
3325606745fSchristos 	if (node != NULL) {
333d68c78b8Schristos 		dns_db_detachnode(db, &node);
3345606745fSchristos 	}
335*bcda20f6Schristos 	return result;
336d68c78b8Schristos }
337d68c78b8Schristos 
338d68c78b8Schristos isc_result_t
339d68c78b8Schristos dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
340d68c78b8Schristos 	isc_result_t result;
341d68c78b8Schristos 
3425606745fSchristos 	if (private->length < 5) {
343*bcda20f6Schristos 		return ISC_R_NOTFOUND;
3445606745fSchristos 	}
345d68c78b8Schristos 
346d68c78b8Schristos 	if (private->data[0] == 0) {
347d68c78b8Schristos 		unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
348d68c78b8Schristos 		unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
349d68c78b8Schristos 		dns_rdata_t rdata = DNS_RDATA_INIT;
350d68c78b8Schristos 		dns_rdata_nsec3param_t nsec3param;
351d4a20c3eSchristos 		bool del, init, nonsec;
352d68c78b8Schristos 		isc_buffer_t b;
353d68c78b8Schristos 
354d68c78b8Schristos 		if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
355903adeddSchristos 						sizeof(nsec3buf)))
356903adeddSchristos 		{
357d68c78b8Schristos 			CHECK(ISC_R_FAILURE);
3585606745fSchristos 		}
359d68c78b8Schristos 
360d68c78b8Schristos 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
361d68c78b8Schristos 
362d4a20c3eSchristos 		del = ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
363d4a20c3eSchristos 		init = ((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
364d4a20c3eSchristos 		nonsec = ((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
365d68c78b8Schristos 
3665606745fSchristos 		nsec3param.flags &=
3675606745fSchristos 			~(DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_REMOVE |
3685606745fSchristos 			  DNS_NSEC3FLAG_INITIAL | DNS_NSEC3FLAG_NONSEC);
369d68c78b8Schristos 
3705606745fSchristos 		if (init) {
371d68c78b8Schristos 			isc_buffer_putstr(buf, "Pending NSEC3 chain ");
3725606745fSchristos 		} else if (del) {
373d68c78b8Schristos 			isc_buffer_putstr(buf, "Removing NSEC3 chain ");
3745606745fSchristos 		} else {
375d68c78b8Schristos 			isc_buffer_putstr(buf, "Creating NSEC3 chain ");
3765606745fSchristos 		}
377d68c78b8Schristos 
378d68c78b8Schristos 		dns_rdata_reset(&rdata);
379d68c78b8Schristos 		isc_buffer_init(&b, newbuf, sizeof(newbuf));
380d68c78b8Schristos 		CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
381d68c78b8Schristos 					   dns_rdatatype_nsec3param,
382d68c78b8Schristos 					   &nsec3param, &b));
383d68c78b8Schristos 
384d68c78b8Schristos 		CHECK(dns_rdata_totext(&rdata, NULL, buf));
385d68c78b8Schristos 
3865606745fSchristos 		if (del && !nonsec) {
387d68c78b8Schristos 			isc_buffer_putstr(buf, " / creating NSEC chain");
3885606745fSchristos 		}
389d68c78b8Schristos 	} else if (private->length == 5) {
390d68c78b8Schristos 		unsigned char alg = private->data[0];
391d68c78b8Schristos 		dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
3928596601aSchristos 		char keybuf[DNS_SECALG_FORMATSIZE + BUFSIZ],
3938596601aSchristos 			algbuf[DNS_SECALG_FORMATSIZE];
394d4a20c3eSchristos 		bool del = private->data[3];
395d4a20c3eSchristos 		bool complete = private->data[4];
396d68c78b8Schristos 
3975606745fSchristos 		if (del && complete) {
398d68c78b8Schristos 			isc_buffer_putstr(buf, "Done removing signatures for ");
3995606745fSchristos 		} else if (del) {
400d68c78b8Schristos 			isc_buffer_putstr(buf, "Removing signatures for ");
4015606745fSchristos 		} else if (complete) {
402d68c78b8Schristos 			isc_buffer_putstr(buf, "Done signing with ");
4035606745fSchristos 		} else {
404d68c78b8Schristos 			isc_buffer_putstr(buf, "Signing with ");
4055606745fSchristos 		}
406d68c78b8Schristos 
407d68c78b8Schristos 		dns_secalg_format(alg, algbuf, sizeof(algbuf));
408d68c78b8Schristos 		snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
409d68c78b8Schristos 		isc_buffer_putstr(buf, keybuf);
4105606745fSchristos 	} else {
411*bcda20f6Schristos 		return ISC_R_NOTFOUND;
4125606745fSchristos 	}
413d68c78b8Schristos 
414d68c78b8Schristos 	isc_buffer_putuint8(buf, 0);
415d68c78b8Schristos 	result = ISC_R_SUCCESS;
416d68c78b8Schristos failure:
417*bcda20f6Schristos 	return result;
418d68c78b8Schristos }
419