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