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: loc_29.c,v 1.13 2020/09/14 08:40:43 florian Exp $ */
18
19 /* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
20
21 /* RFC1876 */
22
23 #ifndef RDATA_GENERIC_LOC_29_C
24 #define RDATA_GENERIC_LOC_29_C
25
26 static inline isc_result_t
totext_loc(ARGS_TOTEXT)27 totext_loc(ARGS_TOTEXT) {
28 int d1, m1, s1, fs1;
29 int d2, m2, s2, fs2;
30 unsigned long latitude;
31 unsigned long longitude;
32 unsigned long altitude;
33 int north;
34 int east;
35 int below;
36 isc_region_t sr;
37 char buf[sizeof("89 59 59.999 N 179 59 59.999 E "
38 "42849672.95m 90000000m 90000000m 90000000m")];
39 char sbuf[sizeof("90000000m")];
40 char hbuf[sizeof("90000000m")];
41 char vbuf[sizeof("90000000m")];
42 unsigned char size, hp, vp;
43 unsigned long poweroften[8] = { 1, 10, 100, 1000,
44 10000, 100000, 1000000, 10000000 };
45
46 UNUSED(tctx);
47
48 REQUIRE(rdata->type == dns_rdatatype_loc);
49 REQUIRE(rdata->length != 0);
50
51 dns_rdata_toregion(rdata, &sr);
52
53 if (sr.base[0] != 0)
54 return (ISC_R_NOTIMPLEMENTED);
55
56 REQUIRE(rdata->length == 16);
57
58 size = sr.base[1];
59 INSIST((size&0x0f) < 10 && (size>>4) < 10);
60 if ((size&0x0f)> 1) {
61 snprintf(sbuf, sizeof(sbuf),
62 "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
63 } else {
64 snprintf(sbuf, sizeof(sbuf),
65 "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
66 }
67 hp = sr.base[2];
68 INSIST((hp&0x0f) < 10 && (hp>>4) < 10);
69 if ((hp&0x0f)> 1) {
70 snprintf(hbuf, sizeof(hbuf),
71 "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
72 } else {
73 snprintf(hbuf, sizeof(hbuf),
74 "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
75 }
76 vp = sr.base[3];
77 INSIST((vp&0x0f) < 10 && (vp>>4) < 10);
78 if ((vp&0x0f)> 1) {
79 snprintf(vbuf, sizeof(vbuf),
80 "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
81 } else {
82 snprintf(vbuf, sizeof(vbuf),
83 "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]);
84 }
85 isc_region_consume(&sr, 4);
86
87 latitude = uint32_fromregion(&sr);
88 isc_region_consume(&sr, 4);
89 if (latitude >= 0x80000000) {
90 north = 1;
91 latitude -= 0x80000000;
92 } else {
93 north = 0;
94 latitude = 0x80000000 - latitude;
95 }
96 fs1 = (int)(latitude % 1000);
97 latitude /= 1000;
98 s1 = (int)(latitude % 60);
99 latitude /= 60;
100 m1 = (int)(latitude % 60);
101 latitude /= 60;
102 d1 = (int)latitude;
103 INSIST(latitude <= 90U);
104
105 longitude = uint32_fromregion(&sr);
106 isc_region_consume(&sr, 4);
107 if (longitude >= 0x80000000) {
108 east = 1;
109 longitude -= 0x80000000;
110 } else {
111 east = 0;
112 longitude = 0x80000000 - longitude;
113 }
114 fs2 = (int)(longitude % 1000);
115 longitude /= 1000;
116 s2 = (int)(longitude % 60);
117 longitude /= 60;
118 m2 = (int)(longitude % 60);
119 longitude /= 60;
120 d2 = (int)longitude;
121 INSIST(longitude <= 180U);
122
123 altitude = uint32_fromregion(&sr);
124 isc_region_consume(&sr, 4);
125 if (altitude < 10000000U) {
126 below = 1;
127 altitude = 10000000 - altitude;
128 } else {
129 below =0;
130 altitude -= 10000000;
131 }
132
133 snprintf(buf, sizeof(buf),
134 "%d %d %d.%03d %s %d %d %d.%03d %s %s%lu.%02lum %s %s %s",
135 d1, m1, s1, fs1, north ? "N" : "S",
136 d2, m2, s2, fs2, east ? "E" : "W",
137 below ? "-" : "", altitude/100, altitude % 100,
138 sbuf, hbuf, vbuf);
139
140 return (isc_str_tobuffer(buf, target));
141 }
142
143 static inline isc_result_t
fromwire_loc(ARGS_FROMWIRE)144 fromwire_loc(ARGS_FROMWIRE) {
145 isc_region_t sr;
146 unsigned char c;
147 unsigned long latitude;
148 unsigned long longitude;
149
150 REQUIRE(type == dns_rdatatype_loc);
151
152 UNUSED(type);
153 UNUSED(rdclass);
154 UNUSED(dctx);
155 UNUSED(options);
156
157 isc_buffer_activeregion(source, &sr);
158 if (sr.length < 1)
159 return (ISC_R_UNEXPECTEDEND);
160 if (sr.base[0] != 0) {
161 /* Treat as unknown. */
162 isc_buffer_forward(source, sr.length);
163 return (isc_mem_tobuffer(target, sr.base, sr.length));
164 }
165 if (sr.length < 16)
166 return (ISC_R_UNEXPECTEDEND);
167
168 /*
169 * Size.
170 */
171 c = sr.base[1];
172 if (c != 0)
173 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
174 return (ISC_R_RANGE);
175
176 /*
177 * Horizontal precision.
178 */
179 c = sr.base[2];
180 if (c != 0)
181 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
182 return (ISC_R_RANGE);
183
184 /*
185 * Vertical precision.
186 */
187 c = sr.base[3];
188 if (c != 0)
189 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
190 return (ISC_R_RANGE);
191 isc_region_consume(&sr, 4);
192
193 /*
194 * Latitude.
195 */
196 latitude = uint32_fromregion(&sr);
197 if (latitude < (0x80000000UL - 90 * 3600000) ||
198 latitude > (0x80000000UL + 90 * 3600000))
199 return (ISC_R_RANGE);
200 isc_region_consume(&sr, 4);
201
202 /*
203 * Longitude.
204 */
205 longitude = uint32_fromregion(&sr);
206 if (longitude < (0x80000000UL - 180 * 3600000) ||
207 longitude > (0x80000000UL + 180 * 3600000))
208 return (ISC_R_RANGE);
209
210 /*
211 * Altitude.
212 * All values possible.
213 */
214
215 isc_buffer_activeregion(source, &sr);
216 isc_buffer_forward(source, 16);
217 return (isc_mem_tobuffer(target, sr.base, 16));
218 }
219
220 static inline isc_result_t
towire_loc(ARGS_TOWIRE)221 towire_loc(ARGS_TOWIRE) {
222 UNUSED(cctx);
223
224 REQUIRE(rdata->type == dns_rdatatype_loc);
225 REQUIRE(rdata->length != 0);
226
227 return (isc_mem_tobuffer(target, rdata->data, rdata->length));
228 }
229
230 #endif /* RDATA_GENERIC_LOC_29_C */
231