]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/sillyrecords.cc
5 #include <boost/format.hpp>
11 #include <sys/types.h>
14 #include "dnsrecords.hh"
16 const static unsigned int poweroften
[10] = {1, 10, 100, 1000, 10000, 100000,
17 1000000,10000000,100000000,1000000000};
19 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/
20 static uint8_t precsize_aton(const char **strptr
)
22 unsigned int mval
= 0, cmval
= 0;
31 mval
= mval
* 10 + (*cp
++ - '0');
33 if (*cp
== '.') { /* centimeters */
36 cmval
= (*cp
++ - '0') * 10;
38 cmval
+= (*cp
++ - '0');
42 cmval
= (mval
* 100) + cmval
;
44 for (exponent
= 0; exponent
< 9; exponent
++)
45 if (cmval
< poweroften
[exponent
+1])
48 mantissa
= cmval
/ poweroften
[exponent
];
52 retval
= (mantissa
<< 4) | exponent
;
59 /* converts ascii lat/lon to unsigned encoded 32-bit number.
62 latlon2ul(const char **latlonstrptr
, int *which
)
66 int deg
= 0, min
= 0, secs
= 0, secsfrac
= 0;
71 deg
= deg
* 10 + (*cp
++ - '0');
80 min
= min
* 10 + (*cp
++ - '0');
85 if (*cp
&& !(isdigit(*cp
)))
89 secs
= secs
* 10 + (*cp
++ - '0');
91 if (*cp
== '.') { /* decimal seconds */
94 secsfrac
= (*cp
++ - '0') * 100;
96 secsfrac
+= (*cp
++ - '0') * 10;
98 secsfrac
+= (*cp
++ - '0');
104 while (*cp
&& !isspace(*cp
)) /* if any trailing garbage */
114 retval
= ((unsigned)1<<31)
115 + (((((deg
* 60) + min
) * 60) + secs
) * 1000)
120 retval
= ((unsigned)1<<31)
121 - (((((deg
* 60) + min
) * 60) + secs
) * 1000)
125 retval
= 0; /* invalid value -- indicates error */
132 *which
= 1; /* latitude */
136 *which
= 2; /* longitude */
139 *which
= 0; /* error */
146 cp
++; /* skip the hemisphere */
148 while (*cp
&& !isspace(*cp
)) /* if any trailing garbage */
151 while (isspace(*cp
)) /* move to next field */
159 void LOCRecordContent::report()
161 regist(1, QType::LOC
, &make
, &make
, "LOC");
162 regist(254, QType::LOC
, &make
, &make
, "LOC");
165 std::shared_ptr
<DNSRecordContent
> LOCRecordContent::make(const string
& content
)
167 return std::make_shared
<LOCRecordContent
>(content
);
171 void LOCRecordContent::toPacket(DNSPacketWriter
& pw
)
173 pw
.xfr8BitInt(d_version
);
174 pw
.xfr8BitInt(d_size
);
175 pw
.xfr8BitInt(d_horizpre
);
176 pw
.xfr8BitInt(d_vertpre
);
178 pw
.xfr32BitInt(d_latitude
);
179 pw
.xfr32BitInt(d_longitude
);
180 pw
.xfr32BitInt(d_altitude
);
183 std::shared_ptr
<LOCRecordContent::DNSRecordContent
> LOCRecordContent::make(const DNSRecord
&dr
, PacketReader
& pr
)
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
);
191 pr
.xfr32BitInt(ret
->d_latitude
);
192 pr
.xfr32BitInt(ret
->d_longitude
);
193 pr
.xfr32BitInt(ret
->d_altitude
);
198 LOCRecordContent::LOCRecordContent(const string
& content
, const string
& zone
)
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
204 const char *cp
, *maxcp
;
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;
213 cp
= content
.c_str();
214 maxcp
= cp
+ strlen(content
.c_str());
216 lltemp1
= latlon2ul(&cp
, &which1
);
217 lltemp2
= latlon2ul(&cp
, &which2
);
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 */
231 default: /* we didn't get one of each */
232 throw MOADNSException("Error decoding LOC content");
245 altmeters
= altmeters
* 10 + (*cp
++ - '0');
247 if (*cp
== '.') { /* decimal meters */
250 altfrac
= (*cp
++ - '0') * 10;
252 altfrac
+= (*cp
++ - '0');
257 d_altitude
= (10000000 + (altsign
* (altmeters
* 100 + altfrac
)));
259 while (!isspace(*cp
) && (cp
< maxcp
))
260 /* if trailing garbage or m */
263 while (isspace(*cp
) && (cp
< maxcp
))
270 d_size
= precsize_aton(&cp
);
272 while (!isspace(*cp
) && (cp
< maxcp
))/*if trailing garbage or m*/
275 while (isspace(*cp
) && (cp
< maxcp
))
281 d_horizpre
= precsize_aton(&cp
);
283 while (!isspace(*cp
) && (cp
< maxcp
))/*if trailing garbage or m*/
286 while (isspace(*cp
) && (cp
< maxcp
))
292 d_vertpre
= precsize_aton(&cp
);
299 string
LOCRecordContent::getZoneRepresentation(bool noDot
) const
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
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;
308 double size
=0.01*((d_size
>>4)&0xf);
309 int count
=d_size
& 0xf;
313 double horizpre
=0.01*((d_horizpre
>>4) & 0xf);
314 count
=d_horizpre
&0xf;
318 double vertpre
=0.01*((d_vertpre
>>4)&0xf);
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(
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')