Merge from vendor branch SENDMAIL:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / rdata / generic / opt_41.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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: opt_41.c,v 1.25.2.1 2004/03/09 06:11:32 marka Exp $ */
19
20 /* Reviewed: Thu Mar 16 14:06:44 PST 2000 by gson */
21
22 /* RFC 2671 */
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(downcase);
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 length;
97         unsigned int total;
98
99         REQUIRE(type == 41);
100
101         UNUSED(type);
102         UNUSED(rdclass);
103         UNUSED(dctx);
104         UNUSED(downcase);
105
106         isc_buffer_activeregion(source, &sregion);
107         total = 0;
108         while (sregion.length != 0) {
109                 if (sregion.length < 4)
110                         return (ISC_R_UNEXPECTEDEND);
111                 /*
112                  * Eat the 16bit option code.  There is nothing to
113                  * be done with it currently.
114                  */
115                 isc_region_consume(&sregion, 2);
116                 length = uint16_fromregion(&sregion);
117                 isc_region_consume(&sregion, 2);
118                 total += 4;
119                 if (sregion.length < length)
120                         return (ISC_R_UNEXPECTEDEND);
121                 isc_region_consume(&sregion, length);
122                 total += length;
123         }
124
125         isc_buffer_activeregion(source, &sregion);
126         isc_buffer_availableregion(target, &tregion);
127         if (tregion.length < total)
128                 return (ISC_R_NOSPACE);
129         memcpy(tregion.base, sregion.base, total);
130         isc_buffer_forward(source, total);
131         isc_buffer_add(target, total);
132
133         return (ISC_R_SUCCESS);
134 }
135
136 static inline isc_result_t
137 towire_opt(ARGS_TOWIRE) {
138
139         REQUIRE(rdata->type == 41);
140
141         UNUSED(cctx);
142
143         return (mem_tobuffer(target, rdata->data, rdata->length));
144 }
145
146 static inline int
147 compare_opt(ARGS_COMPARE) {
148         isc_region_t r1;
149         isc_region_t r2;
150
151         REQUIRE(rdata1->type == rdata2->type);
152         REQUIRE(rdata1->rdclass == rdata2->rdclass);
153         REQUIRE(rdata1->type == 41);
154
155         dns_rdata_toregion(rdata1, &r1);
156         dns_rdata_toregion(rdata2, &r2);
157         return (compare_region(&r1, &r2));
158 }
159
160 static inline isc_result_t
161 fromstruct_opt(ARGS_FROMSTRUCT) {
162         dns_rdata_opt_t *opt = source;
163         isc_region_t region;
164         isc_uint16_t length;
165
166         REQUIRE(type == 41);
167         REQUIRE(source != NULL);
168         REQUIRE(opt->common.rdtype == type);
169         REQUIRE(opt->common.rdclass == rdclass);
170         REQUIRE(opt->options != NULL || opt->length == 0);
171
172         UNUSED(type);
173         UNUSED(rdclass);
174
175         region.base = opt->options;
176         region.length = opt->length;
177         while (region.length >= 4) {
178                 isc_region_consume(&region, 2); /* opt */
179                 length = uint16_fromregion(&region);
180                 isc_region_consume(&region, 2);
181                 if (region.length < length)
182                         return (ISC_R_UNEXPECTEDEND);
183                 isc_region_consume(&region, length);
184         }
185         if (region.length != 0)
186                 return (ISC_R_UNEXPECTEDEND);
187
188         return (mem_tobuffer(target, opt->options, opt->length));
189 }
190
191 static inline isc_result_t
192 tostruct_opt(ARGS_TOSTRUCT) {
193         dns_rdata_opt_t *opt = target;
194         isc_region_t r;
195
196         REQUIRE(rdata->type == 41);
197         REQUIRE(target != NULL);
198
199         opt->common.rdclass = rdata->rdclass;
200         opt->common.rdtype = rdata->type;
201         ISC_LINK_INIT(&opt->common, link);
202
203         dns_rdata_toregion(rdata, &r);
204         opt->length = r.length;
205         opt->options = mem_maybedup(mctx, r.base, r.length);
206         if (opt->options == NULL)
207                 return (ISC_R_NOMEMORY);
208
209         opt->offset = 0;
210         opt->mctx = mctx;
211         return (ISC_R_SUCCESS);
212 }
213
214 static inline void
215 freestruct_opt(ARGS_FREESTRUCT) {
216         dns_rdata_opt_t *opt = source;
217
218         REQUIRE(source != NULL);
219         REQUIRE(opt->common.rdtype == 41);
220
221         if (opt->mctx == NULL)
222                 return;
223
224         if (opt->options != NULL)
225                 isc_mem_free(opt->mctx, opt->options);
226         opt->mctx = NULL;
227 }
228
229 static inline isc_result_t
230 additionaldata_opt(ARGS_ADDLDATA) {
231         REQUIRE(rdata->type == 41);
232
233         UNUSED(rdata);
234         UNUSED(add);
235         UNUSED(arg);
236
237         return (ISC_R_SUCCESS);
238 }
239
240 static inline isc_result_t
241 digest_opt(ARGS_DIGEST) {
242
243         /*
244          * OPT records are not digested.
245          */
246
247         REQUIRE(rdata->type == 41);
248
249         UNUSED(rdata);
250         UNUSED(digest);
251         UNUSED(arg);
252
253         return (ISC_R_NOTIMPLEMENTED);
254 }
255
256 #endif  /* RDATA_GENERIC_OPT_41_C */