nxt.c 4.87 KB
Newer Older
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
1
/*
Bob Halley's avatar
Bob Halley committed
2
 * Copyright (C) 1999, 2000  Internet Software Consortium.
3
 *
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
4
5
6
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
7
 *
8
9
10
11
12
13
14
15
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
16
17
 */

18
/* $Id: nxt.c,v 1.25 2000/10/28 01:25:14 bwelling Exp $ */
David Lawrence's avatar
David Lawrence committed
19

Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
20
21
#include <config.h>

22
#include <isc/string.h>
Bob Halley's avatar
Bob Halley committed
23
#include <isc/util.h>
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
24
25

#include <dns/db.h>
26
#include <dns/nxt.h>
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
27
#include <dns/rdata.h>
28
#include <dns/rdatalist.h>
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
29
30
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
31
#include <dns/rdatastruct.h>
32
#include <dns/result.h>
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
33

34
35
36
37
#define RETERR(x) do { \
	result = (x); \
	if (result != ISC_R_SUCCESS) \
		goto failure; \
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
38
39
40
41
	} while (0)

static void
set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
David Lawrence's avatar
David Lawrence committed
42
43
	unsigned int shift, mask;

Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
44
45
46
	shift = 7 - (index % 8);
	mask = 1 << shift;

David Lawrence's avatar
David Lawrence committed
47
	if (bit != 0)
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
48
49
50
51
52
53
54
55
		array[index / 8] |= mask;
	else
		array[index / 8] &= (~mask & 0xFF);
}

static unsigned int
bit_isset(unsigned char *array, unsigned int index) {
	unsigned int byte, shift, mask;
David Lawrence's avatar
David Lawrence committed
56

Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
57
58
59
	byte = array[index / 8];
	shift = 7 - (index % 8);
	mask = 1 << shift;
David Lawrence's avatar
David Lawrence committed
60
61

	return ((byte & mask) != 0);
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
62
63
}

64
isc_result_t
65
66
67
dns_nxt_buildrdata(dns_db_t *db, dns_dbversion_t *version,
		   dns_dbnode_t *node, dns_name_t *target,
		   unsigned char *buffer, dns_rdata_t *rdata)
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
{
	isc_result_t result;
	dns_rdataset_t rdataset;
	isc_region_t r;
	int i;

	unsigned char *nxt_bits;
	unsigned int max_type;
	dns_rdatasetiter_t *rdsiter;

	memset(buffer, 0, DNS_NXT_BUFFERSIZE);
	dns_name_toregion(target, &r);
	memcpy(buffer, r.base, r.length);
	r.base = buffer;
	nxt_bits = r.base + r.length;
	set_bit(nxt_bits, dns_rdatatype_nxt, 1);
	max_type = dns_rdatatype_nxt;
	dns_rdataset_init(&rdataset);
	rdsiter = NULL;
	result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
88
	if (result != ISC_R_SUCCESS)
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
89
90
91
92
93
94
95
		return (result);
	for (result = dns_rdatasetiter_first(rdsiter);
	     result == ISC_R_SUCCESS;
	     result = dns_rdatasetiter_next(rdsiter))
	{
		dns_rdatasetiter_current(rdsiter, &rdataset);
		if (rdataset.type > 127)
David Lawrence's avatar
David Lawrence committed
96
97
			/* XXX "rdataset type too large" */
			return (ISC_R_RANGE);
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
98
99
100
101
102
103
104
105
		if (rdataset.type != dns_rdatatype_nxt) {
			if (rdataset.type > max_type)
				max_type = rdataset.type;
			set_bit(nxt_bits, rdataset.type, 1);
		}
		dns_rdataset_disassociate(&rdataset);
	}

David Lawrence's avatar
David Lawrence committed
106
107
108
	/*
	 * At zone cuts, deny the existence of glue in the parent zone.
	 */
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
109
110
111
112
	if (bit_isset(nxt_bits, dns_rdatatype_ns) &&
	    ! bit_isset(nxt_bits, dns_rdatatype_soa)) {
		for (i = 0; i < 128; i++) {
			if (bit_isset(nxt_bits, i) &&
113
			    ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
114
115
116
117
118
				set_bit(nxt_bits, i, 0);
		}
	}

	dns_rdatasetiter_destroy(&rdsiter);
119
	if (result != ISC_R_NOMORE)
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
120
121
122
123
		return (result);

	r.length += ((max_type + 7) / 8);
	INSIST(r.length <= DNS_NXT_BUFFERSIZE);
124
	dns_rdata_fromregion(rdata,
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
125
126
127
128
			     dns_db_class(db),
			     dns_rdatatype_nxt,
			     &r);

129
	return (ISC_R_SUCCESS);
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
130
131
132
}


133
isc_result_t
134
135
dns_nxt_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
	      dns_name_t *target, dns_ttl_t ttl)
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
136
{
137
	isc_result_t result;
138
	dns_rdata_t rdata = DNS_RDATA_INIT;
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
139
140
141
	unsigned char data[DNS_NXT_BUFFERSIZE];
	dns_rdatalist_t rdatalist;
	dns_rdataset_t rdataset;
142

Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
143
	dns_rdataset_init(&rdataset);
144
	dns_rdata_init(&rdata);
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
145

146
	RETERR(dns_nxt_buildrdata(db, version, node, target, data, &rdata));
147

148
	rdatalist.rdclass = dns_db_class(db);
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
149
150
	rdatalist.type = dns_rdatatype_nxt;
	rdatalist.covers = 0;
151
	rdatalist.ttl = ttl;
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
152
153
	ISC_LIST_INIT(rdatalist.rdata);
	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
154
	RETERR(dns_rdatalist_tordataset(&rdatalist, &rdataset));
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
155
	result = dns_db_addrdataset(db, node, version, 0, &rdataset,
156
				    0, NULL);
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
157
158
	if (result == DNS_R_UNCHANGED)
		result = ISC_R_SUCCESS;
159
	RETERR(result);
Andreas Gustafsson's avatar
created    
Andreas Gustafsson committed
160
161
162
163
164
 failure:
	if (dns_rdataset_isassociated(&rdataset))
		dns_rdataset_disassociate(&rdataset);
	return (result);
}
Brian Wellington's avatar
Brian Wellington committed
165
166
167

isc_boolean_t
dns_nxt_typepresent(dns_rdata_t *nxt, dns_rdatatype_t type) {
168
169
170
	dns_rdata_nxt_t nxtstruct;
	isc_result_t result;
	isc_boolean_t present;
Brian Wellington's avatar
Brian Wellington committed
171
172
173
174
175

	REQUIRE(nxt != NULL);
	REQUIRE(nxt->type == dns_rdatatype_nxt);
	REQUIRE(type < 128);

176
177
178
179
180
181
	/* This should never fail */
	result = dns_rdata_tostruct(nxt, &nxtstruct, NULL);
	INSIST(result == ISC_R_SUCCESS);
	
	if (type >= nxtstruct.len * 8)
		present = ISC_FALSE;
Brian Wellington's avatar
Brian Wellington committed
182
	else
183
184
185
		present = ISC_TF(bit_isset(nxtstruct.typebits, type));
	dns_rdata_freestruct(&nxt);
	return (present);
Brian Wellington's avatar
Brian Wellington committed
186
}