]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/sillyrecords.cc
Update rules-actions.rst
[thirdparty/pdns.git] / pdns / sillyrecords.cc
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include "utility.hh"
5 #include <cstdio>
6 #include <math.h>
7 #include <cstdlib>
8 #include <sys/types.h>
9 #include <string>
10 #include <errno.h>
11 #include "dnsrecords.hh"
12
13 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
14 1000000,10000000,100000000,1000000000};
15
16 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/
17 static uint8_t precsize_aton(const char **strptr)
18 {
19 unsigned int mval = 0, cmval = 0;
20 uint8_t retval = 0;
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)) {
35 cmval += (*cp++ - '0');
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. */
58 static uint32_t
59 latlon2ul(const char **latlonstrptr, int *which)
60 {
61 const char *cp;
62 uint32_t retval;
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');
78
79 while (isspace(*cp))
80 cp++;
81
82 if (*cp && !(isdigit(*cp)))
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)) {
93 secsfrac += (*cp++ - '0') * 10;
94 if (isdigit(*cp)) {
95 secsfrac += (*cp++ - '0');
96 }
97 }
98 }
99 }
100
101 while (*cp && !isspace(*cp)) /* if any trailing garbage */
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
140 if (!*cp)
141 return 0;
142
143 cp++; /* skip the hemisphere */
144
145 while (*cp && !isspace(*cp)) /* if any trailing garbage */
146 cp++;
147
148 while (isspace(*cp)) /* move to next field */
149 cp++;
150
151 *latlonstrptr = cp;
152
153 return (retval);
154 }
155
156 void LOCRecordContent::report(void)
157 {
158 regist(1, QType::LOC, &make, &make, "LOC");
159 regist(254, QType::LOC, &make, &make, "LOC");
160 }
161
162 std::shared_ptr<DNSRecordContent> LOCRecordContent::make(const string& content)
163 {
164 return std::make_shared<LOCRecordContent>(content);
165 }
166
167
168 void 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
180 std::shared_ptr<LOCRecordContent::DNSRecordContent> LOCRecordContent::make(const DNSRecord &dr, PacketReader& pr)
181 {
182 auto ret=std::make_shared<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);
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
195 LOCRecordContent::LOCRecordContent(const string& content, const string& zone)
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
201 const char *cp, *maxcp;
202
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;
209
210 cp = content.c_str();
211 maxcp = cp + strlen(content.c_str());
212
213 lltemp1 = latlon2ul(&cp, &which1);
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 */
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 */
225 return;
226 }
227 break;
228 default: /* we didn't get one of each */
229 throw MOADNSException("Error decoding LOC content");
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)) {
249 altfrac += (*cp++ - '0');
250 }
251 }
252 }
253
254 d_altitude = (10000000 + (altsign * (altmeters * 100 + altfrac)));
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
267 d_size = precsize_aton(&cp);
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
278 d_horizpre = precsize_aton(&cp);
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
289 d_vertpre = precsize_aton(&cp);
290
291 defaults:
292 ;
293 }
294
295
296 string LOCRecordContent::getZoneRepresentation(bool noDot) const
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;
303 double altitude= ((int32_t)d_altitude )/100.0 - 100000;
304
305 double size=0.01*((d_size>>4)&0xf);
306 int count=d_size & 0xf;
307 while(count--)
308 size*=10;
309
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);
322 static const boost::format fmt("%d %d %2.03f %c %d %d %2.03f %c %.2fm %.2fm %.2fm %.2fm");
323 std::string ret = boost::str(
324 boost::format(fmt)
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 );
332
333 return ret;
334 }