1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /* $Id: apl_42.c,v 1.13 2020/02/26 18:47:59 florian Exp $ */ 18 19 /* RFC3123 */ 20 21 #ifndef RDATA_IN_1_APL_42_C 22 #define RDATA_IN_1_APL_42_C 23 24 static inline isc_result_t 25 totext_in_apl(ARGS_TOTEXT) { 26 isc_region_t sr; 27 isc_region_t ir; 28 uint16_t afi; 29 uint8_t prefix; 30 uint8_t len; 31 isc_boolean_t neg; 32 unsigned char buf[16]; 33 char txt[sizeof(" !64000:")]; 34 const char *sep = ""; 35 int n; 36 37 REQUIRE(rdata->type == dns_rdatatype_apl); 38 REQUIRE(rdata->rdclass == dns_rdataclass_in); 39 40 UNUSED(tctx); 41 42 dns_rdata_toregion(rdata, &sr); 43 ir.base = buf; 44 ir.length = sizeof(buf); 45 46 while (sr.length > 0) { 47 INSIST(sr.length >= 4); 48 afi = uint16_fromregion(&sr); 49 isc_region_consume(&sr, 2); 50 prefix = *sr.base; 51 isc_region_consume(&sr, 1); 52 len = (*sr.base & 0x7f); 53 neg = ISC_TF((*sr.base & 0x80) != 0); 54 isc_region_consume(&sr, 1); 55 INSIST(len <= sr.length); 56 n = snprintf(txt, sizeof(txt), "%s%s%u:", sep, 57 neg ? "!" : "", afi); 58 INSIST(n < (int)sizeof(txt)); 59 RETERR(isc_str_tobuffer(txt, target)); 60 switch (afi) { 61 case 1: 62 INSIST(len <= 4); 63 INSIST(prefix <= 32); 64 memset(buf, 0, sizeof(buf)); 65 memmove(buf, sr.base, len); 66 RETERR(inet_totext(AF_INET, &ir, target)); 67 break; 68 69 case 2: 70 INSIST(len <= 16); 71 INSIST(prefix <= 128); 72 memset(buf, 0, sizeof(buf)); 73 memmove(buf, sr.base, len); 74 RETERR(inet_totext(AF_INET6, &ir, target)); 75 break; 76 77 default: 78 return (ISC_R_NOTIMPLEMENTED); 79 } 80 n = snprintf(txt, sizeof(txt), "/%u", prefix); 81 INSIST(n < (int)sizeof(txt)); 82 RETERR(isc_str_tobuffer(txt, target)); 83 isc_region_consume(&sr, len); 84 sep = " "; 85 } 86 return (ISC_R_SUCCESS); 87 } 88 89 static inline isc_result_t 90 fromwire_in_apl(ARGS_FROMWIRE) { 91 isc_region_t sr, sr2; 92 isc_region_t tr; 93 uint16_t afi; 94 uint8_t prefix; 95 uint8_t len; 96 97 REQUIRE(type == dns_rdatatype_apl); 98 REQUIRE(rdclass == dns_rdataclass_in); 99 100 UNUSED(type); 101 UNUSED(dctx); 102 UNUSED(rdclass); 103 UNUSED(options); 104 105 isc_buffer_activeregion(source, &sr); 106 isc_buffer_availableregion(target, &tr); 107 if (sr.length > tr.length) 108 return (ISC_R_NOSPACE); 109 sr2 = sr; 110 111 /* Zero or more items */ 112 while (sr.length > 0) { 113 if (sr.length < 4) 114 return (ISC_R_UNEXPECTEDEND); 115 afi = uint16_fromregion(&sr); 116 isc_region_consume(&sr, 2); 117 prefix = *sr.base; 118 isc_region_consume(&sr, 1); 119 len = (*sr.base & 0x7f); 120 isc_region_consume(&sr, 1); 121 if (len > sr.length) 122 return (ISC_R_UNEXPECTEDEND); 123 switch (afi) { 124 case 1: 125 if (prefix > 32 || len > 4) 126 return (ISC_R_RANGE); 127 break; 128 case 2: 129 if (prefix > 128 || len > 16) 130 return (ISC_R_RANGE); 131 } 132 if (len > 0 && sr.base[len - 1] == 0) 133 return (DNS_R_FORMERR); 134 isc_region_consume(&sr, len); 135 } 136 isc_buffer_forward(source, sr2.length); 137 return (isc_mem_tobuffer(target, sr2.base, sr2.length)); 138 } 139 140 static inline isc_result_t 141 towire_in_apl(ARGS_TOWIRE) { 142 UNUSED(cctx); 143 144 REQUIRE(rdata->type == dns_rdatatype_apl); 145 REQUIRE(rdata->rdclass == dns_rdataclass_in); 146 147 return (isc_mem_tobuffer(target, rdata->data, rdata->length)); 148 } 149 150 #endif /* RDATA_IN_1_APL_42_C */ 151