]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/sillyrecords.cc
289cdb18cb63feba7815964d6ec98a0c0dcc22a7
11 #include "dnsrecords.hh"
13 static unsigned int poweroften
[10] = {1, 10, 100, 1000, 10000, 100000,
14 1000000,10000000,100000000,1000000000};
16 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/
17 static uint8_t precsize_aton(const char **strptr
)
19 unsigned int mval
= 0, cmval
= 0;
28 mval
= mval
* 10 + (*cp
++ - '0');
30 if (*cp
== '.') { /* centimeters */
33 cmval
= (*cp
++ - '0') * 10;
35 cmval
+= (*cp
++ - '0');
39 cmval
= (mval
* 100) + cmval
;
41 for (exponent
= 0; exponent
< 9; exponent
++)
42 if (cmval
< poweroften
[exponent
+1])
45 mantissa
= cmval
/ poweroften
[exponent
];
49 retval
= (mantissa
<< 4) | exponent
;
56 /* converts ascii lat/lon to unsigned encoded 32-bit number.
59 latlon2ul(const char **latlonstrptr
, int *which
)
63 int deg
= 0, min
= 0, secs
= 0, secsfrac
= 0;
68 deg
= deg
* 10 + (*cp
++ - '0');
77 min
= min
* 10 + (*cp
++ - '0');
82 if (*cp
&& !(isdigit(*cp
)))
86 secs
= secs
* 10 + (*cp
++ - '0');
88 if (*cp
== '.') { /* decimal seconds */
91 secsfrac
= (*cp
++ - '0') * 100;
93 secsfrac
+= (*cp
++ - '0') * 10;
95 secsfrac
+= (*cp
++ - '0');
101 while (*cp
&& !isspace(*cp
)) /* if any trailing garbage */
111 retval
= ((unsigned)1<<31)
112 + (((((deg
* 60) + min
) * 60) + secs
) * 1000)
117 retval
= ((unsigned)1<<31)
118 - (((((deg
* 60) + min
) * 60) + secs
) * 1000)
122 retval
= 0; /* invalid value -- indicates error */
129 *which
= 1; /* latitude */
133 *which
= 2; /* longitude */
136 *which
= 0; /* error */
143 cp
++; /* skip the hemisphere */
145 while (*cp
&& !isspace(*cp
)) /* if any trailing garbage */
148 while (isspace(*cp
)) /* move to next field */
156 void LOCRecordContent::report(void)
158 regist(1, QType::LOC
, &make
, &make
, "LOC");
159 regist(254, QType::LOC
, &make
, &make
, "LOC");
162 DNSRecordContent
* LOCRecordContent::make(const string
& content
)
164 return new LOCRecordContent(content
);
168 void LOCRecordContent::toPacket(DNSPacketWriter
& pw
)
170 pw
.xfr8BitInt(d_version
);
171 pw
.xfr8BitInt(d_size
);
172 pw
.xfr8BitInt(d_horizpre
);
173 pw
.xfr8BitInt(d_vertpre
);
175 pw
.xfr32BitInt(d_latitude
);
176 pw
.xfr32BitInt(d_longitude
);
177 pw
.xfr32BitInt(d_altitude
);
180 LOCRecordContent::DNSRecordContent
* LOCRecordContent::make(const DNSRecord
&dr
, PacketReader
& pr
)
182 LOCRecordContent
* ret
=new LOCRecordContent();
183 pr
.xfr8BitInt(ret
->d_version
);
184 pr
.xfr8BitInt(ret
->d_size
);
185 pr
.xfr8BitInt(ret
->d_horizpre
);
186 pr
.xfr8BitInt(ret
->d_vertpre
);
188 pr
.xfr32BitInt(ret
->d_latitude
);
189 pr
.xfr32BitInt(ret
->d_longitude
);
190 pr
.xfr32BitInt(ret
->d_altitude
);
195 LOCRecordContent::LOCRecordContent(const string
& content
, const string
& zone
)
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
201 const char *cp
, *maxcp
;
203 uint32_t lltemp1
= 0, lltemp2
= 0;
204 int altmeters
= 0, altfrac
= 0, altsign
= 1;
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 */
208 int which1
= 0, which2
= 0;
210 cp
= content
.c_str();
211 maxcp
= cp
+ strlen(content
.c_str());
213 lltemp1
= latlon2ul(&cp
, &which1
);
214 lltemp2
= latlon2ul(&cp
, &which2
);
216 switch (which1
+ which2
) {
217 case 3: /* 1 + 2, the only valid combination */
218 if ((which1
== 1) && (which2
== 2)) { /* normal case */
219 d_latitude
= lltemp1
;
220 d_longitude
= lltemp2
;
221 } else if ((which1
== 2) && (which2
== 1)) {/*reversed*/
222 d_latitude
= lltemp1
;
223 d_longitude
= lltemp2
;
224 } else { /* some kind of brokenness */
228 default: /* we didn't get one of each */
229 throw MOADNSException("Error decoding LOC content");
242 altmeters
= altmeters
* 10 + (*cp
++ - '0');
244 if (*cp
== '.') { /* decimal meters */
247 altfrac
= (*cp
++ - '0') * 10;
249 altfrac
+= (*cp
++ - '0');
254 d_altitude
= (10000000 + (altsign
* (altmeters
* 100 + altfrac
)));
256 while (!isspace(*cp
) && (cp
< maxcp
))
257 /* if trailing garbage or m */
260 while (isspace(*cp
) && (cp
< maxcp
))
267 d_size
= precsize_aton(&cp
);
269 while (!isspace(*cp
) && (cp
< maxcp
))/*if trailing garbage or m*/
272 while (isspace(*cp
) && (cp
< maxcp
))
278 d_horizpre
= precsize_aton(&cp
);
280 while (!isspace(*cp
) && (cp
< maxcp
))/*if trailing garbage or m*/
283 while (isspace(*cp
) && (cp
< maxcp
))
289 d_vertpre
= precsize_aton(&cp
);
296 string
LOCRecordContent::getZoneRepresentation(bool noDot
) const
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
301 double latitude
= ((int32_t)d_latitude
- (1<<31))/3600000.0;
302 double longitude
=((int32_t)d_longitude
- (1<<31))/3600000.0;
303 double altitude
= ((int32_t)d_altitude
)/100.0 - 100000;
305 double size
=0.01*((d_size
>>4)&0xf);
306 int count
=d_size
& 0xf;
310 double horizpre
=0.01*((d_horizpre
>>4) & 0xf);
311 count
=d_horizpre
&0xf;
315 double vertpre
=0.01*((d_vertpre
>>4)&0xf);
320 double remlat
=60.0*(latitude
-(int)latitude
);
321 double remlong
=60.0*(longitude
-(int)longitude
);
323 snprintf(ret
,sizeof(ret
)-1,"%d %d %2.03f %c %d %d %2.03f %c %.2fm %.2fm %.2fm %.2fm",
324 abs((int)latitude
), abs((int) ((latitude
-(int)latitude
)*60)),
325 fabs((double)((remlat
-(int)remlat
)*60.0)),
326 latitude
>0 ? 'N' : 'S',
327 abs((int)longitude
), abs((int) ((longitude
-(int)longitude
)*60)),
328 fabs((double)((remlong
-(int)remlong
)*60.0)),
329 longitude
>0 ? 'E' : 'W',
330 altitude
, size
, horizpre
, vertpre
);