]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/rdata/generic/opt_41.c
MFC: r253983-253984
[FreeBSD/stable/8.git] / contrib / bind9 / lib / dns / rdata / generic / opt_41.c
1 /*
2  * Copyright (C) 2004, 2005, 2007, 2009, 2012-2014  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2002  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
18 /* $Id$ */
19
20 /* Reviewed: Thu Mar 16 14:06:44 PST 2000 by gson */
21
22 /* RFC2671 */
23
24 #ifndef RDATA_GENERIC_OPT_41_C
25 #define RDATA_GENERIC_OPT_41_C
26
27 #define RRTYPE_OPT_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON | \
28                                DNS_RDATATYPEATTR_META | \
29                                DNS_RDATATYPEATTR_NOTQUESTION)
30
31 static inline isc_result_t
32 fromtext_opt(ARGS_FROMTEXT) {
33         /*
34          * OPT records do not have a text format.
35          */
36
37         REQUIRE(type == 41);
38
39         UNUSED(type);
40         UNUSED(rdclass);
41         UNUSED(lexer);
42         UNUSED(origin);
43         UNUSED(options);
44         UNUSED(target);
45         UNUSED(callbacks);
46
47         return (ISC_R_NOTIMPLEMENTED);
48 }
49
50 static inline isc_result_t
51 totext_opt(ARGS_TOTEXT) {
52         isc_region_t r;
53         isc_region_t or;
54         isc_uint16_t option;
55         isc_uint16_t length;
56         char buf[sizeof("64000 64000")];
57
58         /*
59          * OPT records do not have a text format.
60          */
61
62         REQUIRE(rdata->type == 41);
63
64         dns_rdata_toregion(rdata, &r);
65         while (r.length > 0) {
66                 option = uint16_fromregion(&r);
67                 isc_region_consume(&r, 2);
68                 length = uint16_fromregion(&r);
69                 isc_region_consume(&r, 2);
70                 sprintf(buf, "%u %u", option, length);
71                 RETERR(str_totext(buf, target));
72                 INSIST(r.length >= length);
73                 if (length > 0) {
74                         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
75                                 RETERR(str_totext(" (", target));
76                         RETERR(str_totext(tctx->linebreak, target));
77                         or = r;
78                         or.length = length;
79                         RETERR(isc_base64_totext(&or, tctx->width - 2,
80                                                  tctx->linebreak, target));
81                         isc_region_consume(&r, length);
82                         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
83                                 RETERR(str_totext(" )", target));
84                 }
85                 if (r.length > 0)
86                         RETERR(str_totext(" ", target));
87         }
88
89         return (ISC_R_SUCCESS);
90 }
91
92 static inline isc_result_t
93 fromwire_opt(ARGS_FROMWIRE) {
94         isc_region_t sregion;
95         isc_region_t tregion;
96         isc_uint16_t opt;
97         isc_uint16_t length;
98         unsigned int total;
99
100         REQUIRE(type == 41);
101
102         UNUSED(type);
103         UNUSED(rdclass);
104         UNUSED(dctx);
105         UNUSED(options);
106
107         isc_buffer_activeregion(source, &sregion);
108         total = 0;
109         while (sregion.length != 0) {
110                 if (sregion.length < 4)
111                         return (ISC_R_UNEXPECTEDEND);
112                 opt = uint16_fromregion(&sregion);
113                 isc_region_consume(&sregion, 2);
114                 length = uint16_fromregion(&sregion);
115                 isc_region_consume(&sregion, 2);
116                 total += 4;
117                 if (sregion.length < length)
118                         return (ISC_R_UNEXPECTEDEND);
119                 switch (opt) {
120                 case DNS_OPT_CLIENT_SUBNET: {
121                         isc_uint16_t family;
122                         isc_uint8_t addrlen;
123                         isc_uint8_t scope;
124                         isc_uint8_t addrbytes;
125
126                         if (length < 4)
127                                 return (DNS_R_FORMERR);
128                         family = uint16_fromregion(&sregion);
129                         isc_region_consume(&sregion, 2);
130                         addrlen = uint8_fromregion(&sregion);
131                         isc_region_consume(&sregion, 1);
132                         scope = uint8_fromregion(&sregion);
133                         isc_region_consume(&sregion, 1);
134                         switch (family) {
135                         case 1:
136                                 if (addrlen > 32U || scope > 32U)
137                                         return (DNS_R_FORMERR);
138                                 break;
139                         case 2:
140                                 if (addrlen > 128U || scope > 128U)
141                                         return (DNS_R_FORMERR);
142                                 break;
143                         }
144                         addrbytes = (addrlen + 7) / 8;
145                         if (addrbytes + 4 != length)
146                                 return (DNS_R_FORMERR);
147                         isc_region_consume(&sregion, addrbytes);
148                         break;
149                 }
150                 default:
151                         isc_region_consume(&sregion, length);
152                         break;
153                 }
154                 total += length;
155         }
156
157         isc_buffer_activeregion(source, &sregion);
158         isc_buffer_availableregion(target, &tregion);
159         if (tregion.length < total)
160                 return (ISC_R_NOSPACE);
161         memmove(tregion.base, sregion.base, total);
162         isc_buffer_forward(source, total);
163         isc_buffer_add(target, total);
164
165         return (ISC_R_SUCCESS);
166 }
167
168 static inline isc_result_t
169 towire_opt(ARGS_TOWIRE) {
170
171         REQUIRE(rdata->type == 41);
172
173         UNUSED(cctx);
174
175         return (mem_tobuffer(target, rdata->data, rdata->length));
176 }
177
178 static inline int
179 compare_opt(ARGS_COMPARE) {
180         isc_region_t r1;
181         isc_region_t r2;
182
183         REQUIRE(rdata1->type == rdata2->type);
184         REQUIRE(rdata1->rdclass == rdata2->rdclass);
185         REQUIRE(rdata1->type == 41);
186
187         dns_rdata_toregion(rdata1, &r1);
188         dns_rdata_toregion(rdata2, &r2);
189         return (isc_region_compare(&r1, &r2));
190 }
191
192 static inline isc_result_t
193 fromstruct_opt(ARGS_FROMSTRUCT) {
194         dns_rdata_opt_t *opt = source;
195         isc_region_t region;
196         isc_uint16_t length;
197
198         REQUIRE(type == 41);
199         REQUIRE(source != NULL);
200         REQUIRE(opt->common.rdtype == type);
201         REQUIRE(opt->common.rdclass == rdclass);
202         REQUIRE(opt->options != NULL || opt->length == 0);
203
204         UNUSED(type);
205         UNUSED(rdclass);
206
207         region.base = opt->options;
208         region.length = opt->length;
209         while (region.length >= 4) {
210                 isc_region_consume(&region, 2); /* opt */
211                 length = uint16_fromregion(&region);
212                 isc_region_consume(&region, 2);
213                 if (region.length < length)
214                         return (ISC_R_UNEXPECTEDEND);
215                 isc_region_consume(&region, length);
216         }
217         if (region.length != 0)
218                 return (ISC_R_UNEXPECTEDEND);
219
220         return (mem_tobuffer(target, opt->options, opt->length));
221 }
222
223 static inline isc_result_t
224 tostruct_opt(ARGS_TOSTRUCT) {
225         dns_rdata_opt_t *opt = target;
226         isc_region_t r;
227
228         REQUIRE(rdata->type == 41);
229         REQUIRE(target != NULL);
230
231         opt->common.rdclass = rdata->rdclass;
232         opt->common.rdtype = rdata->type;
233         ISC_LINK_INIT(&opt->common, link);
234
235         dns_rdata_toregion(rdata, &r);
236         opt->length = r.length;
237         opt->options = mem_maybedup(mctx, r.base, r.length);
238         if (opt->options == NULL)
239                 return (ISC_R_NOMEMORY);
240
241         opt->offset = 0;
242         opt->mctx = mctx;
243         return (ISC_R_SUCCESS);
244 }
245
246 static inline void
247 freestruct_opt(ARGS_FREESTRUCT) {
248         dns_rdata_opt_t *opt = source;
249
250         REQUIRE(source != NULL);
251         REQUIRE(opt->common.rdtype == 41);
252
253         if (opt->mctx == NULL)
254                 return;
255
256         if (opt->options != NULL)
257                 isc_mem_free(opt->mctx, opt->options);
258         opt->mctx = NULL;
259 }
260
261 static inline isc_result_t
262 additionaldata_opt(ARGS_ADDLDATA) {
263         REQUIRE(rdata->type == 41);
264
265         UNUSED(rdata);
266         UNUSED(add);
267         UNUSED(arg);
268
269         return (ISC_R_SUCCESS);
270 }
271
272 static inline isc_result_t
273 digest_opt(ARGS_DIGEST) {
274
275         /*
276          * OPT records are not digested.
277          */
278
279         REQUIRE(rdata->type == 41);
280
281         UNUSED(rdata);
282         UNUSED(digest);
283         UNUSED(arg);
284
285         return (ISC_R_NOTIMPLEMENTED);
286 }
287
288 static inline isc_boolean_t
289 checkowner_opt(ARGS_CHECKOWNER) {
290
291         REQUIRE(type == 41);
292
293         UNUSED(type);
294         UNUSED(rdclass);
295         UNUSED(wildcard);
296
297         return (dns_name_equal(name, dns_rootname));
298 }
299
300 static inline isc_boolean_t
301 checknames_opt(ARGS_CHECKNAMES) {
302
303         REQUIRE(rdata->type == 41);
304
305         UNUSED(rdata);
306         UNUSED(owner);
307         UNUSED(bad);
308
309         return (ISC_TRUE);
310 }
311
312 static inline int
313 casecompare_opt(ARGS_COMPARE) {
314         return (compare_opt(rdata1, rdata2));
315 }
316
317 #endif  /* RDATA_GENERIC_OPT_41_C */