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