1/*	$NetBSD: gpos_27.c,v 1.8 2024/02/21 22:52:12 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/* RFC1712 */
17
18#ifndef RDATA_GENERIC_GPOS_27_C
19#define RDATA_GENERIC_GPOS_27_C
20
21#define RRTYPE_GPOS_ATTRIBUTES (0)
22
23static isc_result_t
24fromtext_gpos(ARGS_FROMTEXT) {
25	isc_token_t token;
26	int i;
27
28	REQUIRE(type == dns_rdatatype_gpos);
29
30	UNUSED(type);
31	UNUSED(rdclass);
32	UNUSED(origin);
33	UNUSED(options);
34	UNUSED(callbacks);
35
36	for (i = 0; i < 3; i++) {
37		RETERR(isc_lex_getmastertoken(lexer, &token,
38					      isc_tokentype_qstring, false));
39		RETTOK(txt_fromtext(&token.value.as_textregion, target));
40	}
41	return (ISC_R_SUCCESS);
42}
43
44static isc_result_t
45totext_gpos(ARGS_TOTEXT) {
46	isc_region_t region;
47	int i;
48
49	REQUIRE(rdata->type == dns_rdatatype_gpos);
50	REQUIRE(rdata->length != 0);
51
52	UNUSED(tctx);
53
54	dns_rdata_toregion(rdata, &region);
55
56	for (i = 0; i < 3; i++) {
57		RETERR(txt_totext(&region, true, target));
58		if (i != 2) {
59			RETERR(str_totext(" ", target));
60		}
61	}
62
63	return (ISC_R_SUCCESS);
64}
65
66static isc_result_t
67fromwire_gpos(ARGS_FROMWIRE) {
68	int i;
69
70	REQUIRE(type == dns_rdatatype_gpos);
71
72	UNUSED(type);
73	UNUSED(dctx);
74	UNUSED(rdclass);
75	UNUSED(options);
76
77	for (i = 0; i < 3; i++) {
78		RETERR(txt_fromwire(source, target));
79	}
80	return (ISC_R_SUCCESS);
81}
82
83static isc_result_t
84towire_gpos(ARGS_TOWIRE) {
85	REQUIRE(rdata->type == dns_rdatatype_gpos);
86	REQUIRE(rdata->length != 0);
87
88	UNUSED(cctx);
89
90	return (mem_tobuffer(target, rdata->data, rdata->length));
91}
92
93static int
94compare_gpos(ARGS_COMPARE) {
95	isc_region_t r1;
96	isc_region_t r2;
97
98	REQUIRE(rdata1->type == rdata2->type);
99	REQUIRE(rdata1->rdclass == rdata2->rdclass);
100	REQUIRE(rdata1->type == dns_rdatatype_gpos);
101	REQUIRE(rdata1->length != 0);
102	REQUIRE(rdata2->length != 0);
103
104	dns_rdata_toregion(rdata1, &r1);
105	dns_rdata_toregion(rdata2, &r2);
106	return (isc_region_compare(&r1, &r2));
107}
108
109static isc_result_t
110fromstruct_gpos(ARGS_FROMSTRUCT) {
111	dns_rdata_gpos_t *gpos = source;
112
113	REQUIRE(type == dns_rdatatype_gpos);
114	REQUIRE(gpos != NULL);
115	REQUIRE(gpos->common.rdtype == type);
116	REQUIRE(gpos->common.rdclass == rdclass);
117
118	UNUSED(type);
119	UNUSED(rdclass);
120
121	RETERR(uint8_tobuffer(gpos->long_len, target));
122	RETERR(mem_tobuffer(target, gpos->longitude, gpos->long_len));
123	RETERR(uint8_tobuffer(gpos->lat_len, target));
124	RETERR(mem_tobuffer(target, gpos->latitude, gpos->lat_len));
125	RETERR(uint8_tobuffer(gpos->alt_len, target));
126	return (mem_tobuffer(target, gpos->altitude, gpos->alt_len));
127}
128
129static isc_result_t
130tostruct_gpos(ARGS_TOSTRUCT) {
131	dns_rdata_gpos_t *gpos = target;
132	isc_region_t region;
133
134	REQUIRE(rdata->type == dns_rdatatype_gpos);
135	REQUIRE(gpos != NULL);
136	REQUIRE(rdata->length != 0);
137
138	gpos->common.rdclass = rdata->rdclass;
139	gpos->common.rdtype = rdata->type;
140	ISC_LINK_INIT(&gpos->common, link);
141
142	dns_rdata_toregion(rdata, &region);
143	gpos->long_len = uint8_fromregion(&region);
144	isc_region_consume(&region, 1);
145	gpos->longitude = mem_maybedup(mctx, region.base, gpos->long_len);
146	if (gpos->longitude == NULL) {
147		return (ISC_R_NOMEMORY);
148	}
149	isc_region_consume(&region, gpos->long_len);
150
151	gpos->lat_len = uint8_fromregion(&region);
152	isc_region_consume(&region, 1);
153	gpos->latitude = mem_maybedup(mctx, region.base, gpos->lat_len);
154	if (gpos->latitude == NULL) {
155		goto cleanup_longitude;
156	}
157	isc_region_consume(&region, gpos->lat_len);
158
159	gpos->alt_len = uint8_fromregion(&region);
160	isc_region_consume(&region, 1);
161	if (gpos->lat_len > 0) {
162		gpos->altitude = mem_maybedup(mctx, region.base, gpos->alt_len);
163		if (gpos->altitude == NULL) {
164			goto cleanup_latitude;
165		}
166	} else {
167		gpos->altitude = NULL;
168	}
169
170	gpos->mctx = mctx;
171	return (ISC_R_SUCCESS);
172
173cleanup_latitude:
174	if (mctx != NULL && gpos->longitude != NULL) {
175		isc_mem_free(mctx, gpos->longitude);
176	}
177
178cleanup_longitude:
179	if (mctx != NULL && gpos->latitude != NULL) {
180		isc_mem_free(mctx, gpos->latitude);
181	}
182	return (ISC_R_NOMEMORY);
183}
184
185static void
186freestruct_gpos(ARGS_FREESTRUCT) {
187	dns_rdata_gpos_t *gpos = source;
188
189	REQUIRE(gpos != NULL);
190	REQUIRE(gpos->common.rdtype == dns_rdatatype_gpos);
191
192	if (gpos->mctx == NULL) {
193		return;
194	}
195
196	if (gpos->longitude != NULL) {
197		isc_mem_free(gpos->mctx, gpos->longitude);
198	}
199	if (gpos->latitude != NULL) {
200		isc_mem_free(gpos->mctx, gpos->latitude);
201	}
202	if (gpos->altitude != NULL) {
203		isc_mem_free(gpos->mctx, gpos->altitude);
204	}
205	gpos->mctx = NULL;
206}
207
208static isc_result_t
209additionaldata_gpos(ARGS_ADDLDATA) {
210	REQUIRE(rdata->type == dns_rdatatype_gpos);
211
212	UNUSED(rdata);
213	UNUSED(owner);
214	UNUSED(add);
215	UNUSED(arg);
216
217	return (ISC_R_SUCCESS);
218}
219
220static isc_result_t
221digest_gpos(ARGS_DIGEST) {
222	isc_region_t r;
223
224	REQUIRE(rdata->type == dns_rdatatype_gpos);
225
226	dns_rdata_toregion(rdata, &r);
227
228	return ((digest)(arg, &r));
229}
230
231static bool
232checkowner_gpos(ARGS_CHECKOWNER) {
233	REQUIRE(type == dns_rdatatype_gpos);
234
235	UNUSED(name);
236	UNUSED(type);
237	UNUSED(rdclass);
238	UNUSED(wildcard);
239
240	return (true);
241}
242
243static bool
244checknames_gpos(ARGS_CHECKNAMES) {
245	REQUIRE(rdata->type == dns_rdatatype_gpos);
246
247	UNUSED(rdata);
248	UNUSED(owner);
249	UNUSED(bad);
250
251	return (true);
252}
253
254static int
255casecompare_gpos(ARGS_COMPARE) {
256	return (compare_gpos(rdata1, rdata2));
257}
258
259#endif /* RDATA_GENERIC_GPOS_27_C */
260