]>
Commit | Line | Data |
---|---|---|
870a0fe4 AT |
1 | #ifdef HAVE_CONFIG_H |
2 | #include "config.h" | |
3 | #endif | |
a9e2e5ef BH |
4 | #include "utility.hh" |
5 | #include <cstdio> | |
c6a60874 | 6 | #include <math.h> |
a9e2e5ef BH |
7 | #include <cstdlib> |
8 | #include <sys/types.h> | |
a9e2e5ef BH |
9 | #include <string> |
10 | #include <errno.h> | |
c6a60874 | 11 | #include "dnsrecords.hh" |
20177d1d | 12 | |
a9e2e5ef BH |
13 | static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, |
14 | 1000000,10000000,100000000,1000000000}; | |
15 | ||
a9e2e5ef | 16 | /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/ |
49a06471 | 17 | static uint8_t precsize_aton(const char **strptr) |
a9e2e5ef BH |
18 | { |
19 | unsigned int mval = 0, cmval = 0; | |
49a06471 | 20 | uint8_t retval = 0; |
a9e2e5ef BH |
21 | const char *cp; |
22 | int exponent; | |
23 | int mantissa; | |
24 | ||
25 | cp = *strptr; | |
26 | ||
27 | while (isdigit(*cp)) | |
28 | mval = mval * 10 + (*cp++ - '0'); | |
29 | ||
30 | if (*cp == '.') { /* centimeters */ | |
31 | cp++; | |
32 | if (isdigit(*cp)) { | |
33 | cmval = (*cp++ - '0') * 10; | |
34 | if (isdigit(*cp)) { | |
4957a608 | 35 | cmval += (*cp++ - '0'); |
a9e2e5ef BH |
36 | } |
37 | } | |
38 | } | |
39 | cmval = (mval * 100) + cmval; | |
40 | ||
41 | for (exponent = 0; exponent < 9; exponent++) | |
42 | if (cmval < poweroften[exponent+1]) | |
43 | break; | |
44 | ||
45 | mantissa = cmval / poweroften[exponent]; | |
46 | if (mantissa > 9) | |
47 | mantissa = 9; | |
48 | ||
49 | retval = (mantissa << 4) | exponent; | |
50 | ||
51 | *strptr = cp; | |
52 | ||
53 | return (retval); | |
54 | } | |
55 | ||
56 | /* converts ascii lat/lon to unsigned encoded 32-bit number. | |
57 | * moves pointer. */ | |
092f210a | 58 | static uint32_t |
a9e2e5ef BH |
59 | latlon2ul(const char **latlonstrptr, int *which) |
60 | { | |
61 | const char *cp; | |
092f210a | 62 | uint32_t retval; |
a9e2e5ef BH |
63 | int deg = 0, min = 0, secs = 0, secsfrac = 0; |
64 | ||
65 | cp = *latlonstrptr; | |
66 | ||
67 | while (isdigit(*cp)) | |
68 | deg = deg * 10 + (*cp++ - '0'); | |
69 | ||
70 | while (isspace(*cp)) | |
71 | cp++; | |
72 | ||
73 | if (!(isdigit(*cp))) | |
74 | goto fndhemi; | |
75 | ||
76 | while (isdigit(*cp)) | |
77 | min = min * 10 + (*cp++ - '0'); | |
c6a60874 | 78 | |
a9e2e5ef BH |
79 | while (isspace(*cp)) |
80 | cp++; | |
81 | ||
4eec51b6 | 82 | if (*cp && !(isdigit(*cp))) |
a9e2e5ef BH |
83 | goto fndhemi; |
84 | ||
85 | while (isdigit(*cp)) | |
86 | secs = secs * 10 + (*cp++ - '0'); | |
87 | ||
88 | if (*cp == '.') { /* decimal seconds */ | |
89 | cp++; | |
90 | if (isdigit(*cp)) { | |
91 | secsfrac = (*cp++ - '0') * 100; | |
92 | if (isdigit(*cp)) { | |
4957a608 BH |
93 | secsfrac += (*cp++ - '0') * 10; |
94 | if (isdigit(*cp)) { | |
95 | secsfrac += (*cp++ - '0'); | |
96 | } | |
a9e2e5ef BH |
97 | } |
98 | } | |
99 | } | |
100 | ||
4eec51b6 | 101 | while (*cp && !isspace(*cp)) /* if any trailing garbage */ |
a9e2e5ef BH |
102 | cp++; |
103 | ||
104 | while (isspace(*cp)) | |
105 | cp++; | |
106 | ||
107 | fndhemi: | |
108 | switch (*cp) { | |
109 | case 'N': case 'n': | |
110 | case 'E': case 'e': | |
111 | retval = ((unsigned)1<<31) | |
112 | + (((((deg * 60) + min) * 60) + secs) * 1000) | |
113 | + secsfrac; | |
114 | break; | |
115 | case 'S': case 's': | |
116 | case 'W': case 'w': | |
117 | retval = ((unsigned)1<<31) | |
118 | - (((((deg * 60) + min) * 60) + secs) * 1000) | |
119 | - secsfrac; | |
120 | break; | |
121 | default: | |
122 | retval = 0; /* invalid value -- indicates error */ | |
123 | break; | |
124 | } | |
125 | ||
126 | switch (*cp) { | |
127 | case 'N': case 'n': | |
128 | case 'S': case 's': | |
129 | *which = 1; /* latitude */ | |
130 | break; | |
131 | case 'E': case 'e': | |
132 | case 'W': case 'w': | |
133 | *which = 2; /* longitude */ | |
134 | break; | |
135 | default: | |
136 | *which = 0; /* error */ | |
137 | break; | |
138 | } | |
139 | ||
79b45a37 RG |
140 | if (!*cp) |
141 | return 0; | |
142 | ||
a9e2e5ef BH |
143 | cp++; /* skip the hemisphere */ |
144 | ||
4eec51b6 | 145 | while (*cp && !isspace(*cp)) /* if any trailing garbage */ |
a9e2e5ef BH |
146 | cp++; |
147 | ||
148 | while (isspace(*cp)) /* move to next field */ | |
149 | cp++; | |
150 | ||
151 | *latlonstrptr = cp; | |
152 | ||
153 | return (retval); | |
154 | } | |
155 | ||
c6a60874 BH |
156 | void LOCRecordContent::report(void) |
157 | { | |
3bb50daa | 158 | regist(1, QType::LOC, &make, &make, "LOC"); |
159 | regist(254, QType::LOC, &make, &make, "LOC"); | |
c6a60874 BH |
160 | } |
161 | ||
32122aab | 162 | std::shared_ptr<DNSRecordContent> LOCRecordContent::make(const string& content) |
a9e2e5ef | 163 | { |
32122aab | 164 | return std::make_shared<LOCRecordContent>(content); |
c6a60874 BH |
165 | } |
166 | ||
167 | ||
168 | void LOCRecordContent::toPacket(DNSPacketWriter& pw) | |
169 | { | |
170 | pw.xfr8BitInt(d_version); | |
171 | pw.xfr8BitInt(d_size); | |
172 | pw.xfr8BitInt(d_horizpre); | |
173 | pw.xfr8BitInt(d_vertpre); | |
174 | ||
175 | pw.xfr32BitInt(d_latitude); | |
176 | pw.xfr32BitInt(d_longitude); | |
177 | pw.xfr32BitInt(d_altitude); | |
178 | } | |
179 | ||
32122aab | 180 | std::shared_ptr<LOCRecordContent::DNSRecordContent> LOCRecordContent::make(const DNSRecord &dr, PacketReader& pr) |
c6a60874 | 181 | { |
32122aab | 182 | auto ret=std::make_shared<LOCRecordContent>(); |
c6a60874 BH |
183 | pr.xfr8BitInt(ret->d_version); |
184 | pr.xfr8BitInt(ret->d_size); | |
185 | pr.xfr8BitInt(ret->d_horizpre); | |
186 | pr.xfr8BitInt(ret->d_vertpre); | |
187 | ||
188 | pr.xfr32BitInt(ret->d_latitude); | |
189 | pr.xfr32BitInt(ret->d_longitude); | |
190 | pr.xfr32BitInt(ret->d_altitude); | |
191 | ||
192 | return ret; | |
193 | } | |
194 | ||
5a1f298f | 195 | LOCRecordContent::LOCRecordContent(const string& content, const string& zone) |
c6a60874 BH |
196 | { |
197 | // 51 59 00.000 N 5 55 00.000 E 4.00m 1.00m 10000.00m 10.00m | |
198 | // convert this to d_version, d_size, d_horiz/vertpre, d_latitude, d_longitude, d_altitude | |
199 | d_version = 0; | |
200 | ||
a9e2e5ef | 201 | const char *cp, *maxcp; |
a9e2e5ef | 202 | |
092f210a | 203 | uint32_t lltemp1 = 0, lltemp2 = 0; |
a9e2e5ef | 204 | int altmeters = 0, altfrac = 0, altsign = 1; |
c6a60874 BH |
205 | d_horizpre = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ |
206 | d_vertpre = 0x13; /* default = 1e3 cm = 10.00m */ | |
207 | d_size = 0x12; /* default = 1e2 cm = 1.00m */ | |
a9e2e5ef BH |
208 | int which1 = 0, which2 = 0; |
209 | ||
210 | cp = content.c_str(); | |
211 | maxcp = cp + strlen(content.c_str()); | |
212 | ||
213 | lltemp1 = latlon2ul(&cp, &which1); | |
a9e2e5ef BH |
214 | lltemp2 = latlon2ul(&cp, &which2); |
215 | ||
216 | switch (which1 + which2) { | |
217 | case 3: /* 1 + 2, the only valid combination */ | |
218 | if ((which1 == 1) && (which2 == 2)) { /* normal case */ | |
c6a60874 BH |
219 | d_latitude = lltemp1; |
220 | d_longitude = lltemp2; | |
a9e2e5ef | 221 | } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/ |
c6a60874 BH |
222 | d_latitude = lltemp1; |
223 | d_longitude = lltemp2; | |
a9e2e5ef BH |
224 | } else { /* some kind of brokenness */ |
225 | return; | |
226 | } | |
227 | break; | |
228 | default: /* we didn't get one of each */ | |
bea513c7 | 229 | throw MOADNSException("Error decoding LOC content"); |
a9e2e5ef BH |
230 | } |
231 | ||
232 | /* altitude */ | |
233 | if (*cp == '-') { | |
234 | altsign = -1; | |
235 | cp++; | |
236 | } | |
237 | ||
238 | if (*cp == '+') | |
239 | cp++; | |
240 | ||
241 | while (isdigit(*cp)) | |
242 | altmeters = altmeters * 10 + (*cp++ - '0'); | |
243 | ||
244 | if (*cp == '.') { /* decimal meters */ | |
245 | cp++; | |
246 | if (isdigit(*cp)) { | |
247 | altfrac = (*cp++ - '0') * 10; | |
248 | if (isdigit(*cp)) { | |
4957a608 | 249 | altfrac += (*cp++ - '0'); |
a9e2e5ef BH |
250 | } |
251 | } | |
252 | } | |
253 | ||
c6a60874 | 254 | d_altitude = (10000000 + (altsign * (altmeters * 100 + altfrac))); |
a9e2e5ef BH |
255 | |
256 | while (!isspace(*cp) && (cp < maxcp)) | |
257 | /* if trailing garbage or m */ | |
258 | cp++; | |
259 | ||
260 | while (isspace(*cp) && (cp < maxcp)) | |
261 | cp++; | |
262 | ||
263 | ||
264 | if (cp >= maxcp) | |
265 | goto defaults; | |
266 | ||
c6a60874 | 267 | d_size = precsize_aton(&cp); |
a9e2e5ef BH |
268 | |
269 | while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ | |
270 | cp++; | |
271 | ||
272 | while (isspace(*cp) && (cp < maxcp)) | |
273 | cp++; | |
274 | ||
275 | if (cp >= maxcp) | |
276 | goto defaults; | |
277 | ||
c6a60874 | 278 | d_horizpre = precsize_aton(&cp); |
a9e2e5ef BH |
279 | |
280 | while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ | |
281 | cp++; | |
282 | ||
283 | while (isspace(*cp) && (cp < maxcp)) | |
284 | cp++; | |
285 | ||
286 | if (cp >= maxcp) | |
287 | goto defaults; | |
288 | ||
c6a60874 | 289 | d_vertpre = precsize_aton(&cp); |
a9e2e5ef BH |
290 | |
291 | defaults: | |
c6a60874 BH |
292 | ; |
293 | } | |
294 | ||
295 | ||
f21fc0aa | 296 | string LOCRecordContent::getZoneRepresentation(bool noDot) const |
c6a60874 BH |
297 | { |
298 | // convert d_version, d_size, d_horiz/vertpre, d_latitude, d_longitude, d_altitude to: | |
299 | // 51 59 00.000 N 5 55 00.000 E 4.00m 1.00m 10000.00m 10.00m | |
300 | ||
301 | double latitude= ((int32_t)d_latitude - (1<<31))/3600000.0; | |
302 | double longitude=((int32_t)d_longitude - (1<<31))/3600000.0; | |
5e843b4e | 303 | double altitude= ((int32_t)d_altitude )/100.0 - 100000; |
c6a60874 BH |
304 | |
305 | double size=0.01*((d_size>>4)&0xf); | |
306 | int count=d_size & 0xf; | |
307 | while(count--) | |
308 | size*=10; | |
a9e2e5ef | 309 | |
c6a60874 BH |
310 | double horizpre=0.01*((d_horizpre>>4) & 0xf); |
311 | count=d_horizpre&0xf; | |
312 | while(count--) | |
313 | horizpre*=10; | |
314 | ||
315 | double vertpre=0.01*((d_vertpre>>4)&0xf); | |
316 | count=d_vertpre&0xf; | |
317 | while(count--) | |
318 | vertpre*=10; | |
319 | ||
320 | double remlat=60.0*(latitude-(int)latitude); | |
321 | double remlong=60.0*(longitude-(int)longitude); | |
3cbe2773 | 322 | static const boost::format fmt("%d %d %2.03f %c %d %d %2.03f %c %.2fm %.2fm %.2fm %.2fm"); |
0e12635d | 323 | std::string ret = boost::str( |
3cbe2773 | 324 | boost::format(fmt) |
0e12635d CHB |
325 | % abs((int)latitude) % abs((int) ((latitude-(int)latitude)*60)) |
326 | % fabs((double)((remlat-(int)remlat)*60.0)) % (latitude>0 ? 'N' : 'S') | |
327 | % abs((int)longitude) % abs((int) ((longitude-(int)longitude)*60)) | |
328 | % fabs((double)((remlong-(int)remlong)*60.0)) % (longitude>0 ? 'E' : 'W') | |
329 | % altitude % size | |
330 | % horizpre % vertpre | |
331 | ); | |
c6a60874 BH |
332 | |
333 | return ret; | |
a9e2e5ef | 334 | } |