1 /* $NetBSD: atma_34.c,v 1.9 2025/01/26 16:25:34 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /* http://www.broadband-forum.org/ftp/pub/approved-specs/af-dans-0152.000.pdf */ 17 18 #ifndef RDATA_IN_1_ATMA_22_C 19 #define RDATA_IN_1_ATMA_22_C 20 21 #define RRTYPE_ATMA_ATTRIBUTES (0) 22 23 static isc_result_t 24 fromtext_in_atma(ARGS_FROMTEXT) { 25 isc_token_t token; 26 isc_textregion_t *sr; 27 int n; 28 bool valid = false; 29 bool lastwasperiod = true; /* leading periods not allowed */ 30 int digits = 0; 31 unsigned char c = 0; 32 33 REQUIRE(type == dns_rdatatype_atma); 34 REQUIRE(rdclass == dns_rdataclass_in); 35 36 UNUSED(type); 37 UNUSED(origin); 38 UNUSED(options); 39 UNUSED(rdclass); 40 UNUSED(callbacks); 41 42 /* ATM End System Address (AESA) format or E.164 */ 43 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 44 false)); 45 sr = &token.value.as_textregion; 46 if (sr->length < 1) { 47 RETTOK(ISC_R_UNEXPECTEDEND); 48 } 49 50 if (sr->base[0] != '+') { 51 /* 52 * Format 0: ATM End System Address (AESA) format. 53 */ 54 c = 0; 55 RETERR(mem_tobuffer(target, &c, 1)); 56 while (sr->length > 0) { 57 if (sr->base[0] == '.') { 58 if (lastwasperiod) { 59 RETTOK(DNS_R_SYNTAX); 60 } 61 isc_textregion_consume(sr, 1); 62 lastwasperiod = true; 63 continue; 64 } 65 if ((n = hexvalue(sr->base[0])) == -1) { 66 RETTOK(DNS_R_SYNTAX); 67 } 68 c <<= 4; 69 c += n; 70 if (++digits == 2) { 71 RETERR(mem_tobuffer(target, &c, 1)); 72 valid = true; 73 digits = 0; 74 c = 0; 75 } 76 isc_textregion_consume(sr, 1); 77 lastwasperiod = false; 78 } 79 if (digits != 0 || !valid || lastwasperiod) { 80 RETTOK(ISC_R_UNEXPECTEDEND); 81 } 82 } else { 83 /* 84 * Format 1: E.164. 85 */ 86 c = 1; 87 RETERR(mem_tobuffer(target, &c, 1)); 88 isc_textregion_consume(sr, 1); 89 while (sr->length > 0) { 90 if (sr->base[0] == '.') { 91 if (lastwasperiod) { 92 RETTOK(DNS_R_SYNTAX); 93 } 94 isc_textregion_consume(sr, 1); 95 lastwasperiod = true; 96 continue; 97 } 98 if (!isdigit((unsigned char)sr->base[0])) { 99 RETTOK(DNS_R_SYNTAX); 100 } 101 RETERR(mem_tobuffer(target, sr->base, 1)); 102 isc_textregion_consume(sr, 1); 103 lastwasperiod = false; 104 } 105 if (lastwasperiod) { 106 RETTOK(ISC_R_UNEXPECTEDEND); 107 } 108 } 109 return ISC_R_SUCCESS; 110 } 111 112 static isc_result_t 113 totext_in_atma(ARGS_TOTEXT) { 114 isc_region_t region; 115 char buf[sizeof("xx")]; 116 117 REQUIRE(rdata->type == dns_rdatatype_atma); 118 REQUIRE(rdata->rdclass == dns_rdataclass_in); 119 REQUIRE(rdata->length != 0); 120 121 UNUSED(tctx); 122 123 dns_rdata_toregion(rdata, ®ion); 124 INSIST(region.length > 1); 125 switch (region.base[0]) { 126 case 0: 127 isc_region_consume(®ion, 1); 128 while (region.length != 0) { 129 snprintf(buf, sizeof(buf), "%02x", region.base[0]); 130 isc_region_consume(®ion, 1); 131 RETERR(str_totext(buf, target)); 132 } 133 break; 134 case 1: 135 RETERR(str_totext("+", target)); 136 isc_region_consume(®ion, 1); 137 RETERR(mem_tobuffer(target, region.base, region.length)); 138 break; 139 default: 140 return ISC_R_NOTIMPLEMENTED; 141 } 142 return ISC_R_SUCCESS; 143 } 144 145 static isc_result_t 146 fromwire_in_atma(ARGS_FROMWIRE) { 147 isc_region_t region; 148 149 REQUIRE(type == dns_rdatatype_atma); 150 REQUIRE(rdclass == dns_rdataclass_in); 151 152 UNUSED(type); 153 UNUSED(dctx); 154 UNUSED(rdclass); 155 156 isc_buffer_activeregion(source, ®ion); 157 if (region.length < 2) { 158 return ISC_R_UNEXPECTEDEND; 159 } 160 if (region.base[0] == 1) { 161 unsigned int i; 162 for (i = 1; i < region.length; i++) { 163 if (!isdigit((unsigned char)region.base[i])) { 164 return DNS_R_FORMERR; 165 } 166 } 167 } 168 RETERR(mem_tobuffer(target, region.base, region.length)); 169 isc_buffer_forward(source, region.length); 170 return ISC_R_SUCCESS; 171 } 172 173 static isc_result_t 174 towire_in_atma(ARGS_TOWIRE) { 175 REQUIRE(rdata->type == dns_rdatatype_atma); 176 REQUIRE(rdata->rdclass == dns_rdataclass_in); 177 REQUIRE(rdata->length != 0); 178 179 UNUSED(cctx); 180 181 return mem_tobuffer(target, rdata->data, rdata->length); 182 } 183 184 static int 185 compare_in_atma(ARGS_COMPARE) { 186 isc_region_t r1; 187 isc_region_t r2; 188 189 REQUIRE(rdata1->type == rdata2->type); 190 REQUIRE(rdata1->rdclass == rdata2->rdclass); 191 REQUIRE(rdata1->type == dns_rdatatype_atma); 192 REQUIRE(rdata1->rdclass == dns_rdataclass_in); 193 REQUIRE(rdata1->length != 0); 194 REQUIRE(rdata2->length != 0); 195 196 dns_rdata_toregion(rdata1, &r1); 197 dns_rdata_toregion(rdata2, &r2); 198 return isc_region_compare(&r1, &r2); 199 } 200 201 static isc_result_t 202 fromstruct_in_atma(ARGS_FROMSTRUCT) { 203 dns_rdata_in_atma_t *atma = source; 204 205 REQUIRE(type == dns_rdatatype_atma); 206 REQUIRE(rdclass == dns_rdataclass_in); 207 REQUIRE(atma != NULL); 208 REQUIRE(atma->common.rdtype == type); 209 REQUIRE(atma->common.rdclass == rdclass); 210 REQUIRE(atma->atma != NULL || atma->atma_len == 0); 211 212 UNUSED(type); 213 UNUSED(rdclass); 214 215 RETERR(mem_tobuffer(target, &atma->format, 1)); 216 return mem_tobuffer(target, atma->atma, atma->atma_len); 217 } 218 219 static isc_result_t 220 tostruct_in_atma(ARGS_TOSTRUCT) { 221 dns_rdata_in_atma_t *atma = target; 222 isc_region_t r; 223 224 REQUIRE(rdata->type == dns_rdatatype_atma); 225 REQUIRE(rdata->rdclass == dns_rdataclass_in); 226 REQUIRE(atma != NULL); 227 REQUIRE(rdata->length != 0); 228 229 atma->common.rdclass = rdata->rdclass; 230 atma->common.rdtype = rdata->type; 231 ISC_LINK_INIT(&atma->common, link); 232 233 dns_rdata_toregion(rdata, &r); 234 atma->format = r.base[0]; 235 isc_region_consume(&r, 1); 236 atma->atma_len = r.length; 237 atma->atma = mem_maybedup(mctx, r.base, r.length); 238 atma->mctx = mctx; 239 return ISC_R_SUCCESS; 240 } 241 242 static void 243 freestruct_in_atma(ARGS_FREESTRUCT) { 244 dns_rdata_in_atma_t *atma = source; 245 246 REQUIRE(atma != NULL); 247 REQUIRE(atma->common.rdclass == dns_rdataclass_in); 248 REQUIRE(atma->common.rdtype == dns_rdatatype_atma); 249 250 if (atma->mctx == NULL) { 251 return; 252 } 253 254 if (atma->atma != NULL) { 255 isc_mem_free(atma->mctx, atma->atma); 256 } 257 atma->mctx = NULL; 258 } 259 260 static isc_result_t 261 additionaldata_in_atma(ARGS_ADDLDATA) { 262 REQUIRE(rdata->type == dns_rdatatype_atma); 263 REQUIRE(rdata->rdclass == dns_rdataclass_in); 264 265 UNUSED(rdata); 266 UNUSED(owner); 267 UNUSED(add); 268 UNUSED(arg); 269 270 return ISC_R_SUCCESS; 271 } 272 273 static isc_result_t 274 digest_in_atma(ARGS_DIGEST) { 275 isc_region_t r; 276 277 REQUIRE(rdata->type == dns_rdatatype_atma); 278 REQUIRE(rdata->rdclass == dns_rdataclass_in); 279 280 dns_rdata_toregion(rdata, &r); 281 282 return (digest)(arg, &r); 283 } 284 285 static bool 286 checkowner_in_atma(ARGS_CHECKOWNER) { 287 REQUIRE(type == dns_rdatatype_atma); 288 REQUIRE(rdclass == dns_rdataclass_in); 289 290 UNUSED(name); 291 UNUSED(type); 292 UNUSED(rdclass); 293 UNUSED(wildcard); 294 295 return true; 296 } 297 298 static bool 299 checknames_in_atma(ARGS_CHECKNAMES) { 300 REQUIRE(rdata->type == dns_rdatatype_atma); 301 REQUIRE(rdata->rdclass == dns_rdataclass_in); 302 303 UNUSED(rdata); 304 UNUSED(owner); 305 UNUSED(bad); 306 307 return true; 308 } 309 310 static int 311 casecompare_in_atma(ARGS_COMPARE) { 312 return compare_in_atma(rdata1, rdata2); 313 } 314 315 #endif /* RDATA_IN_1_atma_22_C */ 316