]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/sillyrecords.cc
Merge pull request #7908 from omoerbeek/rec-4.1.14-changelog
[thirdparty/pdns.git] / pdns / sillyrecords.cc
CommitLineData
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
13static 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 17static 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 58static uint32_t
a9e2e5ef
BH
59latlon2ul(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
156void 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 162std::shared_ptr<DNSRecordContent> LOCRecordContent::make(const string& content)
a9e2e5ef 163{
32122aab 164 return std::make_shared<LOCRecordContent>(content);
c6a60874
BH
165}
166
167
168void 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 180std::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 195LOCRecordContent::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 296string 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}