xref: /openbsd/usr.bin/dig/lib/dns/rdata/in_1/apl_42.c (revision 3cab2bb3)
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