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 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 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 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