]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/sillyrecords.cc
Merge pull request #11340 from norve/pdnustil-flush-prompt
[thirdparty/pdns.git] / pdns / sillyrecords.cc
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <boost/format.hpp>
6
7 #include "utility.hh"
8 #include <cstdio>
9 #include <math.h>
10 #include <cstdlib>
11 #include <sys/types.h>
12 #include <string>
13 #include <errno.h>
14 #include "dnsrecords.hh"
15
16 const static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
17 1000000,10000000,100000000,1000000000};
18
19 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/
20 static uint8_t precsize_aton(const char **strptr)
21 {
22 unsigned int mval = 0, cmval = 0;
23 uint8_t retval = 0;
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)) {
38 cmval += (*cp++ - '0');
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. */
61 static uint32_t
62 latlon2ul(const char **latlonstrptr, int *which)
63 {
64 const char *cp;
65 uint32_t retval;
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');
72
73 while (isspace(*cp))
74 cp++;
75
76 if (!(isdigit(*cp)))
77 goto fndhemi;
78
79 while (isdigit(*cp))
80 min = min * 10 + (*cp++ - '0');
81
82 while (isspace(*cp))
83 cp++;
84
85 if (*cp && !(isdigit(*cp)))
86 goto fndhemi;
87
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)) {
96 secsfrac += (*cp++ - '0') * 10;
97 if (isdigit(*cp)) {
98 secsfrac += (*cp++ - '0');
99 }
100 }
101 }
102 }
103
104 while (*cp && !isspace(*cp)) /* if any trailing garbage */
105 cp++;
106
107 while (isspace(*cp))
108 cp++;
109
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 }
128
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
143 if (!*cp)
144 return 0;
145
146 cp++; /* skip the hemisphere */
147
148 while (*cp && !isspace(*cp)) /* if any trailing garbage */
149 cp++;
150
151 while (isspace(*cp)) /* move to next field */
152 cp++;
153
154 *latlonstrptr = cp;
155
156 return (retval);
157 }
158
159 void LOCRecordContent::report()
160 {
161 regist(1, QType::LOC, &make, &make, "LOC");
162 regist(254, QType::LOC, &make, &make, "LOC");
163 }
164
165 std::shared_ptr<DNSRecordContent> LOCRecordContent::make(const string& content)
166 {
167 return std::make_shared<LOCRecordContent>(content);
168 }
169
170
171 void LOCRecordContent::toPacket(DNSPacketWriter& pw)
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
183 std::shared_ptr<LOCRecordContent::DNSRecordContent> LOCRecordContent::make(const DNSRecord &dr, PacketReader& pr)
184 {
185 auto ret=std::make_shared<LOCRecordContent>();
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);
194
195 return ret;
196 }
197
198 LOCRecordContent::LOCRecordContent(const string& content, const string& zone)
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
204 const char *cp, *maxcp;
205
206 uint32_t lltemp1 = 0, lltemp2 = 0;
207 int altmeters = 0, altfrac = 0, altsign = 1;
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 */
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);
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 */
222 d_latitude = lltemp1;
223 d_longitude = lltemp2;
224 } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/
225 d_latitude = lltemp1;
226 d_longitude = lltemp2;
227 } else { /* some kind of brokenness */
228 return;
229 }
230 break;
231 default: /* we didn't get one of each */
232 throw MOADNSException("Error decoding LOC content");
233 }
234
235 /* altitude */
236 if (*cp == '-') {
237 altsign = -1;
238 cp++;
239 }
240
241 if (*cp == '+')
242 cp++;
243
244 while (isdigit(*cp))
245 altmeters = altmeters * 10 + (*cp++ - '0');
246
247 if (*cp == '.') { /* decimal meters */
248 cp++;
249 if (isdigit(*cp)) {
250 altfrac = (*cp++ - '0') * 10;
251 if (isdigit(*cp)) {
252 altfrac += (*cp++ - '0');
253 }
254 }
255 }
256
257 d_altitude = (10000000 + (altsign * (altmeters * 100 + altfrac)));
258
259 while (!isspace(*cp) && (cp < maxcp))
260 /* if trailing garbage or m */
261 cp++;
262
263 while (isspace(*cp) && (cp < maxcp))
264 cp++;
265
266
267 if (cp >= maxcp)
268 goto defaults;
269
270 d_size = precsize_aton(&cp);
271
272 while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
273 cp++;
274
275 while (isspace(*cp) && (cp < maxcp))
276 cp++;
277
278 if (cp >= maxcp)
279 goto defaults;
280
281 d_horizpre = precsize_aton(&cp);
282
283 while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
284 cp++;
285
286 while (isspace(*cp) && (cp < maxcp))
287 cp++;
288
289 if (cp >= maxcp)
290 goto defaults;
291
292 d_vertpre = precsize_aton(&cp);
293
294 defaults:
295 ;
296 }
297
298
299 string LOCRecordContent::getZoneRepresentation(bool noDot) const
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
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;
306 double altitude= ((int32_t)d_altitude )/100.0 - 100000;
307
308 double size=0.01*((d_size>>4)&0xf);
309 int count=d_size & 0xf;
310 while(count--)
311 size*=10;
312
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);
325 static const boost::format fmt("%d %d %2.03f %c %d %d %2.03f %c %.2fm %.2fm %.2fm %.2fm");
326 std::string ret = boost::str(
327 boost::format(fmt)
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 );
335
336 return ret;
337 }