1/* 2 * Copyright (C) 2004, 2005, 2007, 2009, 2012 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 31static inline isc_result_t 32fromtext_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 50static inline isc_result_t 51totext_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 92static inline isc_result_t 93fromwire_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(options); 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 136static inline isc_result_t 137towire_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 146static inline int 147compare_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 (isc_region_compare(&r1, &r2)); 158} 159 160static inline isc_result_t 161fromstruct_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(®ion, 2); /* opt */ 179 length = uint16_fromregion(®ion); 180 isc_region_consume(®ion, 2); 181 if (region.length < length) 182 return (ISC_R_UNEXPECTEDEND); 183 isc_region_consume(®ion, length); 184 } 185 if (region.length != 0) 186 return (ISC_R_UNEXPECTEDEND); 187 188 return (mem_tobuffer(target, opt->options, opt->length)); 189} 190 191static inline isc_result_t 192tostruct_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 214static inline void 215freestruct_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 229static inline isc_result_t 230additionaldata_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 240static inline isc_result_t 241digest_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 256static inline isc_boolean_t 257checkowner_opt(ARGS_CHECKOWNER) { 258 259 REQUIRE(type == 41); 260 261 UNUSED(type); 262 UNUSED(rdclass); 263 UNUSED(wildcard); 264 265 return (dns_name_equal(name, dns_rootname)); 266} 267 268static inline isc_boolean_t 269checknames_opt(ARGS_CHECKNAMES) { 270 271 REQUIRE(rdata->type == 41); 272 273 UNUSED(rdata); 274 UNUSED(owner); 275 UNUSED(bad); 276 277 return (ISC_TRUE); 278} 279 280static inline int 281casecompare_opt(ARGS_COMPARE) { 282 return (compare_opt(rdata1, rdata2)); 283} 284 285#endif /* RDATA_GENERIC_OPT_41_C */ 286