Coverage Report

Created: 2024-11-12 06:21

/src/pdns/pdns/sillyrecords.cc
Line
Count
Source (jump to first uncovered line)
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 <cerrno>
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
0
{
22
0
  unsigned int mval = 0, cmval = 0;
23
0
  uint8_t retval = 0;
24
0
  const char *cp;
25
0
  int exponent;
26
0
  int mantissa;
27
28
0
  cp = *strptr;
29
30
0
  while (isdigit(*cp))
31
0
    mval = mval * 10 + (*cp++ - '0');
32
33
0
  if (*cp == '.') {               /* centimeters */
34
0
    cp++;
35
0
    if (isdigit(*cp)) {
36
0
      cmval = (*cp++ - '0') * 10;
37
0
      if (isdigit(*cp)) {
38
0
        cmval += (*cp++ - '0');
39
0
      }
40
0
    }
41
0
  }
42
0
  cmval = (mval * 100) + cmval;
43
44
0
  for (exponent = 0; exponent < 9; exponent++)
45
0
    if (cmval < poweroften[exponent+1])
46
0
      break;
47
48
0
  mantissa = cmval / poweroften[exponent];
49
0
  if (mantissa > 9)
50
0
    mantissa = 9;
51
52
0
  retval = (mantissa << 4) | exponent;
53
54
0
  *strptr = cp;
55
56
0
  return (retval);
57
0
}
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
0
{
64
0
  const char *cp;
65
0
  uint32_t retval;
66
0
  int deg = 0, min = 0, secs = 0, secsfrac = 0;
67
68
0
  cp = *latlonstrptr;
69
70
0
  while (isdigit(*cp))
71
0
    deg = deg * 10 + (*cp++ - '0');
72
73
0
  while (isspace(*cp))
74
0
    cp++;
75
76
0
  if (!(isdigit(*cp)))
77
0
    goto fndhemi;
78
79
0
  while (isdigit(*cp))
80
0
    min = min * 10 + (*cp++ - '0');
81
82
0
  while (isspace(*cp))
83
0
    cp++;
84
85
0
  if (*cp && !(isdigit(*cp)))
86
0
    goto fndhemi;
87
88
0
  while (isdigit(*cp))
89
0
    secs = secs * 10 + (*cp++ - '0');
90
91
0
  if (*cp == '.') {               /* decimal seconds */
92
0
    cp++;
93
0
    if (isdigit(*cp)) {
94
0
      secsfrac = (*cp++ - '0') * 100;
95
0
      if (isdigit(*cp)) {
96
0
        secsfrac += (*cp++ - '0') * 10;
97
0
        if (isdigit(*cp)) {
98
0
          secsfrac += (*cp++ - '0');
99
0
        }
100
0
      }
101
0
    }
102
0
  }
103
104
0
  while (*cp && !isspace(*cp))   /* if any trailing garbage */
105
0
    cp++;
106
107
0
  while (isspace(*cp))
108
0
    cp++;
109
110
0
 fndhemi:
111
0
  switch (*cp) {
112
0
  case 'N': case 'n':
113
0
  case 'E': case 'e':
114
0
    retval = ((unsigned)1<<31)
115
0
      + (((((deg * 60) + min) * 60) + secs) * 1000)
116
0
      + secsfrac;
117
0
    break;
118
0
  case 'S': case 's':
119
0
  case 'W': case 'w':
120
0
    retval = ((unsigned)1<<31)
121
0
      - (((((deg * 60) + min) * 60) + secs) * 1000)
122
0
      - secsfrac;
123
0
    break;
124
0
  default:
125
0
    retval = 0;     /* invalid value -- indicates error */
126
0
    break;
127
0
  }
128
129
0
  switch (*cp) {
130
0
  case 'N': case 'n':
131
0
  case 'S': case 's':
132
0
    *which = 1;     /* latitude */
133
0
    break;
134
0
  case 'E': case 'e':
135
0
  case 'W': case 'w':
136
0
    *which = 2;     /* longitude */
137
0
    break;
138
0
  default:
139
0
    *which = 0;     /* error */
140
0
    break;
141
0
  }
142
143
0
  if (!*cp)
144
0
    return 0;
145
146
0
  cp++;                   /* skip the hemisphere */
147
148
0
  while (*cp && !isspace(*cp))   /* if any trailing garbage */
149
0
    cp++;
150
151
0
  while (isspace(*cp))    /* move to next field */
152
0
    cp++;
153
154
0
  *latlonstrptr = cp;
155
156
0
  return (retval);
157
0
}
158
159
void LOCRecordContent::report()
160
2
{
161
2
  regist(1, QType::LOC, &make, &make, "LOC");
162
2
  regist(254, QType::LOC, &make, &make, "LOC");
163
2
}
164
165
std::shared_ptr<DNSRecordContent> LOCRecordContent::make(const string& content)
166
0
{
167
0
  return std::make_shared<LOCRecordContent>(content);
168
0
}
169
170
171
void LOCRecordContent::toPacket(DNSPacketWriter& pw) const
172
0
{
173
0
  pw.xfr8BitInt(d_version);
174
0
  pw.xfr8BitInt(d_size);
175
0
  pw.xfr8BitInt(d_horizpre);
176
0
  pw.xfr8BitInt(d_vertpre);
177
178
0
  pw.xfr32BitInt(d_latitude);
179
0
  pw.xfr32BitInt(d_longitude);
180
0
  pw.xfr32BitInt(d_altitude);
181
0
}
182
183
std::shared_ptr<LOCRecordContent::DNSRecordContent> LOCRecordContent::make(const DNSRecord& /* dr */, PacketReader& pr)
184
1.93k
{
185
1.93k
  auto ret=std::make_shared<LOCRecordContent>();
186
1.93k
  pr.xfr8BitInt(ret->d_version);
187
1.93k
  pr.xfr8BitInt(ret->d_size);
188
1.93k
  pr.xfr8BitInt(ret->d_horizpre);
189
1.93k
  pr.xfr8BitInt(ret->d_vertpre);
190
191
1.93k
  pr.xfr32BitInt(ret->d_latitude);
192
1.93k
  pr.xfr32BitInt(ret->d_longitude);
193
1.93k
  pr.xfr32BitInt(ret->d_altitude);
194
195
1.93k
  return ret;
196
1.93k
}
197
198
LOCRecordContent::LOCRecordContent(const string& content, const string& /* zone */)
199
0
{
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
0
  d_version = 0;
203
204
0
  const char *cp, *maxcp;
205
206
0
  uint32_t lltemp1 = 0, lltemp2 = 0;
207
0
  int altmeters = 0, altfrac = 0, altsign = 1;
208
0
  d_horizpre = 0x16;    /* default = 1e6 cm = 10000.00m = 10km */
209
0
  d_vertpre = 0x13;    /* default = 1e3 cm = 10.00m */
210
0
  d_size = 0x12;   /* default = 1e2 cm = 1.00m */
211
0
  int which1 = 0, which2 = 0;
212
213
0
  cp = content.c_str();
214
0
  maxcp = cp + strlen(content.c_str());
215
216
0
  lltemp1 = latlon2ul(&cp, &which1);
217
0
  lltemp2 = latlon2ul(&cp, &which2);
218
219
0
  switch (which1 + which2) {
220
0
  case 3:                 /* 1 + 2, the only valid combination */
221
0
    if ((which1 == 1) && (which2 == 2)) { /* normal case */
222
0
      d_latitude = lltemp1;
223
0
      d_longitude = lltemp2;
224
0
    } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/
225
0
      d_latitude = lltemp1;
226
0
      d_longitude = lltemp2;
227
0
    } else {        /* some kind of brokenness */
228
0
      return;
229
0
    }
230
0
    break;
231
0
  default:                /* we didn't get one of each */
232
0
    throw MOADNSException("Error decoding LOC content");
233
0
  }
234
235
  /* altitude */
236
0
  if (*cp == '-') {
237
0
    altsign = -1;
238
0
    cp++;
239
0
  }
240
241
0
  if (*cp == '+')
242
0
    cp++;
243
244
0
  while (isdigit(*cp))
245
0
    altmeters = altmeters * 10 + (*cp++ - '0');
246
247
0
  if (*cp == '.') {               /* decimal meters */
248
0
    cp++;
249
0
    if (isdigit(*cp)) {
250
0
      altfrac = (*cp++ - '0') * 10;
251
0
      if (isdigit(*cp)) {
252
0
        altfrac += (*cp++ - '0');
253
0
      }
254
0
    }
255
0
  }
256
257
0
  d_altitude = (10000000 + (altsign * (altmeters * 100 + altfrac)));
258
259
0
  while (!isspace(*cp) && (cp < maxcp))
260
    /* if trailing garbage or m */
261
0
    cp++;
262
263
0
  while (isspace(*cp) && (cp < maxcp))
264
0
    cp++;
265
266
267
0
  if (cp >= maxcp)
268
0
    goto defaults;
269
270
0
  d_size = precsize_aton(&cp);
271
272
0
  while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
273
0
    cp++;
274
275
0
  while (isspace(*cp) && (cp < maxcp))
276
0
    cp++;
277
278
0
  if (cp >= maxcp)
279
0
    goto defaults;
280
281
0
  d_horizpre = precsize_aton(&cp);
282
283
0
  while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
284
0
    cp++;
285
286
0
  while (isspace(*cp) && (cp < maxcp))
287
0
    cp++;
288
289
0
  if (cp >= maxcp)
290
0
    goto defaults;
291
292
0
  d_vertpre = precsize_aton(&cp);
293
294
0
 defaults:
295
0
  ;
296
0
}
297
298
299
string LOCRecordContent::getZoneRepresentation(bool /* noDot */) const
300
0
{
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
0
  double latitude= ((int32_t)((uint32_t)d_latitude  - ((uint32_t)1<<31)))/3600000.0;
305
0
  double longitude=((int32_t)((uint32_t)d_longitude - ((uint32_t)1<<31)))/3600000.0;
306
0
  double altitude= ((int32_t)d_altitude           )/100.0 - 100000;
307
308
0
  double size=0.01*((d_size>>4)&0xf);
309
0
  int count=d_size & 0xf;
310
0
  while(count--)
311
0
    size*=10;
312
313
0
  double horizpre=0.01*((d_horizpre>>4) & 0xf);
314
0
  count=d_horizpre&0xf;
315
0
  while(count--)
316
0
    horizpre*=10;
317
318
0
  double vertpre=0.01*((d_vertpre>>4)&0xf);
319
0
  count=d_vertpre&0xf;
320
0
  while(count--)
321
0
    vertpre*=10;
322
323
0
  double remlat=60.0*(latitude-(int)latitude);
324
0
  double remlong=60.0*(longitude-(int)longitude);
325
0
  static const boost::format fmt("%d %d %2.03f %c %d %d %2.03f %c %.2fm %.2fm %.2fm %.2fm");
326
0
  std::string ret = boost::str(
327
0
    boost::format(fmt)
328
0
    % abs((int)latitude) % abs((int) ((latitude-(int)latitude)*60))
329
0
    % fabs((double)((remlat-(int)remlat)*60.0)) % (latitude>0 ? 'N' : 'S')
330
0
    % abs((int)longitude) % abs((int) ((longitude-(int)longitude)*60))
331
0
    % fabs((double)((remlong-(int)remlong)*60.0)) % (longitude>0 ? 'E' : 'W')
332
0
    % altitude % size
333
0
    % horizpre % vertpre
334
0
    );
335
336
0
  return ret;
337
0
}