Coverage Report

Created: 2023-06-07 06:23

/src/bind9/lib/dns/rdata/generic/loc_29.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
/* RFC1876 */
15
16
#ifndef RDATA_GENERIC_LOC_29_C
17
#define RDATA_GENERIC_LOC_29_C
18
19
28.9k
#define RRTYPE_LOC_ATTRIBUTES (0)
20
21
static isc_result_t
22
loc_getdecimal(const char *str, unsigned long max, size_t precision, char units,
23
55.3k
         unsigned long *valuep) {
24
55.3k
  bool ok;
25
55.3k
  char *e;
26
55.3k
  size_t i;
27
55.3k
  long tmp;
28
55.3k
  unsigned long value;
29
30
55.3k
  value = strtoul(str, &e, 10);
31
55.3k
  if (*e != 0 && *e != '.' && *e != units) {
32
54
    return (DNS_R_SYNTAX);
33
54
  }
34
55.2k
  if (value > max) {
35
146
    return (ISC_R_RANGE);
36
146
  }
37
55.1k
  ok = e != str;
38
55.1k
  if (*e == '.') {
39
34.2k
    e++;
40
36.9k
    for (i = 0; i < precision; i++) {
41
35.8k
      if (*e == 0 || *e == units) {
42
33.1k
        break;
43
33.1k
      }
44
2.77k
      if ((tmp = decvalue(*e++)) < 0) {
45
11
        return (DNS_R_SYNTAX);
46
11
      }
47
2.76k
      ok = true;
48
2.76k
      value *= 10;
49
2.76k
      value += tmp;
50
2.76k
    }
51
100k
    for (; i < precision; i++) {
52
66.2k
      value *= 10;
53
66.2k
    }
54
34.1k
  } else {
55
64.9k
    for (i = 0; i < precision; i++) {
56
44.0k
      value *= 10;
57
44.0k
    }
58
20.9k
  }
59
55.0k
  if (*e != 0 && *e == units) {
60
9.62k
    e++;
61
9.62k
  }
62
55.0k
  if (!ok || *e != 0) {
63
27
    return (DNS_R_SYNTAX);
64
27
  }
65
55.0k
  *valuep = value;
66
55.0k
  return (ISC_R_SUCCESS);
67
55.0k
}
68
69
static isc_result_t
70
7.94k
loc_getprecision(const char *str, unsigned char *valuep) {
71
7.94k
  unsigned long poweroften[8] = { 1,     10,     100, 1000,
72
7.94k
          10000, 100000, 1000000, 10000000 };
73
7.94k
  unsigned long m, cm;
74
7.94k
  bool ok;
75
7.94k
  char *e;
76
7.94k
  size_t i;
77
7.94k
  long tmp;
78
7.94k
  int man;
79
7.94k
  int exp;
80
81
7.94k
  m = strtoul(str, &e, 10);
82
7.94k
  if (*e != 0 && *e != '.' && *e != 'm') {
83
18
    return (DNS_R_SYNTAX);
84
18
  }
85
7.92k
  if (m > 90000000) {
86
109
    return (ISC_R_RANGE);
87
109
  }
88
7.81k
  cm = 0;
89
7.81k
  ok = e != str;
90
7.81k
  if (*e == '.') {
91
3.58k
    e++;
92
6.63k
    for (i = 0; i < 2; i++) {
93
5.25k
      if (*e == 0 || *e == 'm') {
94
2.19k
        break;
95
2.19k
      }
96
3.05k
      if ((tmp = decvalue(*e++)) < 0) {
97
6
        return (DNS_R_SYNTAX);
98
6
      }
99
3.04k
      ok = true;
100
3.04k
      cm *= 10;
101
3.04k
      cm += tmp;
102
3.04k
    }
103
7.70k
    for (; i < 2; i++) {
104
4.11k
      cm *= 10;
105
4.11k
    }
106
3.58k
  }
107
7.80k
  if (*e == 'm') {
108
2.27k
    e++;
109
2.27k
  }
110
7.80k
  if (!ok || *e != 0) {
111
29
    return (DNS_R_SYNTAX);
112
29
  }
113
114
  /*
115
   * We don't just multiply out as we will overflow.
116
   */
117
7.77k
  if (m > 0) {
118
24.9k
    for (exp = 0; exp < 7; exp++) {
119
22.4k
      if (m < poweroften[exp + 1]) {
120
2.41k
        break;
121
2.41k
      }
122
22.4k
    }
123
4.94k
    man = m / poweroften[exp];
124
4.94k
    exp += 2;
125
4.94k
  } else if (cm >= 10) {
126
1.20k
    man = cm / 10;
127
1.20k
    exp = 1;
128
1.62k
  } else {
129
1.62k
    man = cm;
130
1.62k
    exp = 0;
131
1.62k
  }
132
7.77k
  *valuep = (man << 4) + exp;
133
7.77k
  return (ISC_R_SUCCESS);
134
7.80k
}
135
136
static isc_result_t
137
105k
get_degrees(isc_lex_t *lexer, isc_token_t *token, unsigned long *d) {
138
105k
  RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_number,
139
105k
              false));
140
105k
  *d = token->value.as_ulong;
141
142
105k
  return (ISC_R_SUCCESS);
143
105k
}
144
145
static isc_result_t
146
check_coordinate(unsigned long d, unsigned long m, unsigned long s,
147
111k
     unsigned long maxd) {
148
111k
  if (d > maxd || m > 59U) {
149
105
    return (ISC_R_RANGE);
150
105
  }
151
111k
  if (d == maxd && (m != 0 || s != 0)) {
152
16
    return (ISC_R_RANGE);
153
16
  }
154
155
111k
  return (ISC_R_SUCCESS);
156
111k
}
157
158
static isc_result_t
159
3.40k
get_minutes(isc_lex_t *lexer, isc_token_t *token, unsigned long *m) {
160
3.40k
  RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_number,
161
3.40k
              false));
162
163
3.35k
  *m = token->value.as_ulong;
164
165
3.35k
  return (ISC_R_SUCCESS);
166
3.40k
}
167
168
static isc_result_t
169
3.00k
get_seconds(isc_lex_t *lexer, isc_token_t *token, unsigned long *s) {
170
3.00k
  RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_string,
171
3.00k
              false));
172
3.00k
  RETERR(loc_getdecimal(DNS_AS_STR(*token), 59, 3, '\0', s));
173
174
2.78k
  return (ISC_R_SUCCESS);
175
3.00k
}
176
177
static isc_result_t
178
get_direction(isc_lex_t *lexer, isc_token_t *token, const char *directions,
179
111k
        int *direction) {
180
111k
  RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_string,
181
111k
              false));
182
111k
  if (DNS_AS_STR(*token)[0] == directions[1] &&
183
111k
      DNS_AS_STR(*token)[1] == 0)
184
53.5k
  {
185
53.5k
    *direction = DNS_AS_STR(*token)[0];
186
53.5k
    return (ISC_R_SUCCESS);
187
53.5k
  }
188
189
57.5k
  if (DNS_AS_STR(*token)[0] == directions[0] &&
190
57.5k
      DNS_AS_STR(*token)[1] == 0)
191
51.1k
  {
192
51.1k
    *direction = DNS_AS_STR(*token)[0];
193
51.1k
    return (ISC_R_SUCCESS);
194
51.1k
  }
195
196
6.41k
  *direction = 0;
197
6.41k
  isc_lex_ungettoken(lexer, token);
198
6.41k
  return (ISC_R_SUCCESS);
199
57.5k
}
200
201
static isc_result_t
202
loc_getcoordinate(isc_lex_t *lexer, unsigned long *dp, unsigned long *mp,
203
      unsigned long *sp, const char *directions, int *directionp,
204
105k
      unsigned long maxd) {
205
105k
  isc_result_t result = ISC_R_SUCCESS;
206
105k
  isc_token_t token;
207
105k
  unsigned long d, m, s;
208
105k
  int direction = 0;
209
210
105k
  m = 0;
211
105k
  s = 0;
212
213
  /*
214
   * Degrees.
215
   */
216
105k
  RETERR(get_degrees(lexer, &token, &d));
217
105k
  RETTOK(check_coordinate(d, m, s, maxd));
218
219
  /*
220
   * Minutes.
221
   */
222
105k
  RETERR(get_direction(lexer, &token, directions, &direction));
223
105k
  if (direction > 0) {
224
101k
    goto done;
225
101k
  }
226
227
3.40k
  RETERR(get_minutes(lexer, &token, &m));
228
3.35k
  RETTOK(check_coordinate(d, m, s, maxd));
229
230
  /*
231
   * Seconds.
232
   */
233
3.33k
  RETERR(get_direction(lexer, &token, directions, &direction));
234
3.30k
  if (direction > 0) {
235
298
    goto done;
236
298
  }
237
238
3.00k
  result = get_seconds(lexer, &token, &s);
239
3.00k
  if (result == ISC_R_RANGE || result == DNS_R_SYNTAX) {
240
221
    RETTOK(result);
241
221
  }
242
2.78k
  RETERR(result);
243
2.78k
  RETTOK(check_coordinate(d, m, s, maxd));
244
245
  /*
246
   * Direction.
247
   */
248
2.77k
  RETERR(get_direction(lexer, &token, directions, &direction));
249
2.75k
  if (direction == 0) {
250
9
    RETERR(DNS_R_SYNTAX);
251
9
  }
252
104k
done:
253
254
104k
  *directionp = direction;
255
104k
  *dp = d;
256
104k
  *mp = m;
257
104k
  *sp = s;
258
259
104k
  return (ISC_R_SUCCESS);
260
2.75k
}
261
262
static isc_result_t
263
52.7k
loc_getlatitude(isc_lex_t *lexer, unsigned long *latitude) {
264
52.7k
  unsigned long d1 = 0, m1 = 0, s1 = 0;
265
52.7k
  int direction = 0;
266
267
52.7k
  RETERR(loc_getcoordinate(lexer, &d1, &m1, &s1, "SN", &direction, 90U));
268
269
52.3k
  switch (direction) {
270
10.6k
  case 'N':
271
10.6k
    *latitude = 0x80000000 + (d1 * 3600 + m1 * 60) * 1000 + s1;
272
10.6k
    break;
273
41.6k
  case 'S':
274
41.6k
    *latitude = 0x80000000 - (d1 * 3600 + m1 * 60) * 1000 - s1;
275
41.6k
    break;
276
0
  default:
277
0
    UNREACHABLE();
278
52.3k
  }
279
280
52.3k
  return (ISC_R_SUCCESS);
281
52.3k
}
282
283
static isc_result_t
284
52.3k
loc_getlongitude(isc_lex_t *lexer, unsigned long *longitude) {
285
52.3k
  unsigned long d2 = 0, m2 = 0, s2 = 0;
286
52.3k
  int direction = 0;
287
288
52.3k
  RETERR(loc_getcoordinate(lexer, &d2, &m2, &s2, "WE", &direction, 180U));
289
290
52.3k
  switch (direction) {
291
42.8k
  case 'E':
292
42.8k
    *longitude = 0x80000000 + (d2 * 3600 + m2 * 60) * 1000 + s2;
293
42.8k
    break;
294
9.43k
  case 'W':
295
9.43k
    *longitude = 0x80000000 - (d2 * 3600 + m2 * 60) * 1000 - s2;
296
9.43k
    break;
297
0
  default:
298
0
    UNREACHABLE();
299
52.3k
  }
300
301
52.3k
  return (ISC_R_SUCCESS);
302
52.3k
}
303
304
static isc_result_t
305
52.3k
loc_getaltitude(isc_lex_t *lexer, unsigned long *altitude) {
306
52.3k
  isc_token_t token;
307
52.3k
  unsigned long cm;
308
52.3k
  const char *str;
309
310
52.3k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
311
52.3k
              false));
312
52.3k
  str = DNS_AS_STR(token);
313
52.3k
  if (DNS_AS_STR(token)[0] == '-') {
314
269
    RETTOK(loc_getdecimal(str + 1, 100000, 2, 'm', &cm));
315
266
    if (cm > 10000000UL) {
316
1
      RETTOK(ISC_R_RANGE);
317
1
    }
318
265
    *altitude = 10000000 - cm;
319
52.0k
  } else {
320
52.0k
    RETTOK(loc_getdecimal(str, 42849672, 2, 'm', &cm));
321
52.0k
    if (cm > 4284967295UL) {
322
2
      RETTOK(ISC_R_RANGE);
323
2
    }
324
52.0k
    *altitude = 10000000 + cm;
325
52.0k
  }
326
327
52.2k
  return (ISC_R_SUCCESS);
328
52.3k
}
329
330
static isc_result_t
331
59.6k
loc_getoptionalprecision(isc_lex_t *lexer, unsigned char *valuep) {
332
59.6k
  isc_token_t token;
333
334
59.6k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
335
59.6k
              true));
336
59.4k
  if (token.type == isc_tokentype_eol || token.type == isc_tokentype_eof)
337
51.5k
  {
338
51.5k
    isc_lex_ungettoken(lexer, &token);
339
51.5k
    return (ISC_R_NOMORE);
340
51.5k
  }
341
7.94k
  RETTOK(loc_getprecision(DNS_AS_STR(token), valuep));
342
343
7.77k
  return (ISC_R_SUCCESS);
344
7.94k
}
345
346
static isc_result_t
347
52.2k
loc_getsize(isc_lex_t *lexer, unsigned char *sizep) {
348
52.2k
  return (loc_getoptionalprecision(lexer, sizep));
349
52.2k
}
350
351
static isc_result_t
352
6.57k
loc_gethorizontalprecision(isc_lex_t *lexer, unsigned char *hpp) {
353
6.57k
  return (loc_getoptionalprecision(lexer, hpp));
354
6.57k
}
355
356
static isc_result_t
357
765
loc_getverticalprecision(isc_lex_t *lexer, unsigned char *vpp) {
358
765
  return (loc_getoptionalprecision(lexer, vpp));
359
765
}
360
361
/* The LOC record is expressed in a master file in the following format:
362
 *
363
 * <owner> <TTL> <class> LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]]
364
 *                             {"E"|"W"} alt["m"] [siz["m"] [hp["m"]
365
 *                             [vp["m"]]]] )
366
 *
367
 * (The parentheses are used for multi-line data as specified in [RFC
368
 * 1035] section 5.1.)
369
 *
370
 * where:
371
 *
372
 *     d1:     [0 .. 90]            (degrees latitude)
373
 *     d2:     [0 .. 180]           (degrees longitude)
374
 *     m1, m2: [0 .. 59]            (minutes latitude/longitude)
375
 *     s1, s2: [0 .. 59.999]        (seconds latitude/longitude)
376
 *     alt:    [-100000.00 .. 42849672.95] BY .01 (altitude in meters)
377
 *     siz, hp, vp: [0 .. 90000000.00] (size/precision in meters)
378
 *
379
 * If omitted, minutes and seconds default to zero, size defaults to 1m,
380
 * horizontal precision defaults to 10000m, and vertical precision
381
 * defaults to 10m.  These defaults are chosen to represent typical
382
 * ZIP/postal code area sizes, since it is often easy to find
383
 * approximate geographical location by ZIP/postal code.
384
 */
385
static isc_result_t
386
52.7k
fromtext_loc(ARGS_FROMTEXT) {
387
52.7k
  isc_result_t result = ISC_R_SUCCESS;
388
52.7k
  unsigned long latitude = 0;
389
52.7k
  unsigned long longitude = 0;
390
52.7k
  unsigned long altitude = 0;
391
52.7k
  unsigned char size = 0x12; /* Default: 1.00m */
392
52.7k
  unsigned char hp = 0x16;   /* Default: 10000.00 m */
393
52.7k
  unsigned char vp = 0x13;   /* Default: 10.00 m */
394
52.7k
  unsigned char version = 0;
395
396
52.7k
  REQUIRE(type == dns_rdatatype_loc);
397
398
52.7k
  UNUSED(type);
399
52.7k
  UNUSED(rdclass);
400
52.7k
  UNUSED(origin);
401
52.7k
  UNUSED(options);
402
52.7k
  UNUSED(callbacks);
403
404
52.7k
  RETERR(loc_getlatitude(lexer, &latitude));
405
52.3k
  RETERR(loc_getlongitude(lexer, &longitude));
406
52.3k
  RETERR(loc_getaltitude(lexer, &altitude));
407
52.2k
  result = loc_getsize(lexer, &size);
408
52.2k
  if (result == ISC_R_NOMORE) {
409
45.5k
    result = ISC_R_SUCCESS;
410
45.5k
    goto encode;
411
45.5k
  }
412
6.78k
  RETERR(result);
413
6.57k
  result = loc_gethorizontalprecision(lexer, &hp);
414
6.57k
  if (result == ISC_R_NOMORE) {
415
5.75k
    result = ISC_R_SUCCESS;
416
5.75k
    goto encode;
417
5.75k
  }
418
824
  RETERR(result);
419
765
  result = loc_getverticalprecision(lexer, &vp);
420
765
  if (result == ISC_R_NOMORE) {
421
308
    result = ISC_R_SUCCESS;
422
308
    goto encode;
423
308
  }
424
457
  RETERR(result);
425
51.9k
encode:
426
51.9k
  RETERR(mem_tobuffer(target, &version, 1));
427
51.9k
  RETERR(mem_tobuffer(target, &size, 1));
428
51.9k
  RETERR(mem_tobuffer(target, &hp, 1));
429
51.9k
  RETERR(mem_tobuffer(target, &vp, 1));
430
431
51.9k
  RETERR(uint32_tobuffer(latitude, target));
432
51.9k
  RETERR(uint32_tobuffer(longitude, target));
433
51.9k
  RETERR(uint32_tobuffer(altitude, target));
434
435
51.9k
  return (result);
436
51.9k
}
437
438
static isc_result_t
439
4.99k
totext_loc(ARGS_TOTEXT) {
440
4.99k
  int d1, m1, s1, fs1;
441
4.99k
  int d2, m2, s2, fs2;
442
4.99k
  unsigned long latitude;
443
4.99k
  unsigned long longitude;
444
4.99k
  unsigned long altitude;
445
4.99k
  bool north;
446
4.99k
  bool east;
447
4.99k
  bool below;
448
4.99k
  isc_region_t sr;
449
4.99k
  char sbuf[sizeof("90000000m")];
450
4.99k
  char hbuf[sizeof("90000000m")];
451
4.99k
  char vbuf[sizeof("90000000m")];
452
  /* "89 59 59.999 N 179 59 59.999 E " */
453
  /* "-42849672.95m 90000000m 90000000m 90000000m"; */
454
4.99k
  char buf[8 * 6 + 12 * 1 + 2 * 10 + sizeof(sbuf) + sizeof(hbuf) +
455
4.99k
     sizeof(vbuf)];
456
4.99k
  unsigned char size, hp, vp;
457
4.99k
  unsigned long poweroften[8] = { 1,     10,     100, 1000,
458
4.99k
          10000, 100000, 1000000, 10000000 };
459
460
4.99k
  UNUSED(tctx);
461
462
4.99k
  REQUIRE(rdata->type == dns_rdatatype_loc);
463
4.99k
  REQUIRE(rdata->length != 0);
464
465
4.99k
  dns_rdata_toregion(rdata, &sr);
466
467
4.99k
  if (sr.base[0] != 0) {
468
1.58k
    return (ISC_R_NOTIMPLEMENTED);
469
1.58k
  }
470
471
3.40k
  REQUIRE(rdata->length == 16);
472
473
3.40k
  size = sr.base[1];
474
3.40k
  INSIST((size & 0x0f) < 10 && (size >> 4) < 10);
475
3.40k
  if ((size & 0x0f) > 1) {
476
2.38k
    snprintf(sbuf, sizeof(sbuf), "%lum",
477
2.38k
       (size >> 4) * poweroften[(size & 0x0f) - 2]);
478
2.38k
  } else {
479
1.02k
    snprintf(sbuf, sizeof(sbuf), "0.%02lum",
480
1.02k
       (size >> 4) * poweroften[(size & 0x0f)]);
481
1.02k
  }
482
3.40k
  hp = sr.base[2];
483
3.40k
  INSIST((hp & 0x0f) < 10 && (hp >> 4) < 10);
484
3.40k
  if ((hp & 0x0f) > 1) {
485
1.29k
    snprintf(hbuf, sizeof(hbuf), "%lum",
486
1.29k
       (hp >> 4) * poweroften[(hp & 0x0f) - 2]);
487
2.11k
  } else {
488
2.11k
    snprintf(hbuf, sizeof(hbuf), "0.%02lum",
489
2.11k
       (hp >> 4) * poweroften[(hp & 0x0f)]);
490
2.11k
  }
491
3.40k
  vp = sr.base[3];
492
3.40k
  INSIST((vp & 0x0f) < 10 && (vp >> 4) < 10);
493
3.40k
  if ((vp & 0x0f) > 1) {
494
733
    snprintf(vbuf, sizeof(vbuf), "%lum",
495
733
       (vp >> 4) * poweroften[(vp & 0x0f) - 2]);
496
2.67k
  } else {
497
2.67k
    snprintf(vbuf, sizeof(vbuf), "0.%02lum",
498
2.67k
       (vp >> 4) * poweroften[(vp & 0x0f)]);
499
2.67k
  }
500
3.40k
  isc_region_consume(&sr, 4);
501
502
3.40k
  latitude = uint32_fromregion(&sr);
503
3.40k
  isc_region_consume(&sr, 4);
504
3.40k
  if (latitude >= 0x80000000) {
505
699
    north = true;
506
699
    latitude -= 0x80000000;
507
2.71k
  } else {
508
2.71k
    north = false;
509
2.71k
    latitude = 0x80000000 - latitude;
510
2.71k
  }
511
3.40k
  fs1 = (int)(latitude % 1000);
512
3.40k
  latitude /= 1000;
513
3.40k
  s1 = (int)(latitude % 60);
514
3.40k
  latitude /= 60;
515
3.40k
  m1 = (int)(latitude % 60);
516
3.40k
  latitude /= 60;
517
3.40k
  d1 = (int)latitude;
518
3.40k
  INSIST(latitude <= 90U);
519
520
3.40k
  longitude = uint32_fromregion(&sr);
521
3.40k
  isc_region_consume(&sr, 4);
522
3.40k
  if (longitude >= 0x80000000) {
523
1.25k
    east = true;
524
1.25k
    longitude -= 0x80000000;
525
2.15k
  } else {
526
2.15k
    east = false;
527
2.15k
    longitude = 0x80000000 - longitude;
528
2.15k
  }
529
3.40k
  fs2 = (int)(longitude % 1000);
530
3.40k
  longitude /= 1000;
531
3.40k
  s2 = (int)(longitude % 60);
532
3.40k
  longitude /= 60;
533
3.40k
  m2 = (int)(longitude % 60);
534
3.40k
  longitude /= 60;
535
3.40k
  d2 = (int)longitude;
536
3.40k
  INSIST(longitude <= 180U);
537
538
3.40k
  altitude = uint32_fromregion(&sr);
539
3.40k
  isc_region_consume(&sr, 4);
540
3.40k
  if (altitude < 10000000U) {
541
850
    below = true;
542
850
    altitude = 10000000 - altitude;
543
2.55k
  } else {
544
2.55k
    below = false;
545
2.55k
    altitude -= 10000000;
546
2.55k
  }
547
548
3.40k
  snprintf(buf, sizeof(buf),
549
3.40k
     "%d %d %d.%03d %s %d %d %d.%03d %s %s%lu.%02lum %s %s %s", d1,
550
3.40k
     m1, s1, fs1, north ? "N" : "S", d2, m2, s2, fs2,
551
3.40k
     east ? "E" : "W", below ? "-" : "", altitude / 100,
552
3.40k
     altitude % 100, sbuf, hbuf, vbuf);
553
554
3.40k
  return (str_totext(buf, target));
555
4.99k
}
556
557
static isc_result_t
558
6.77k
fromwire_loc(ARGS_FROMWIRE) {
559
6.77k
  isc_region_t sr;
560
6.77k
  unsigned char c;
561
6.77k
  unsigned long latitude;
562
6.77k
  unsigned long longitude;
563
564
6.77k
  REQUIRE(type == dns_rdatatype_loc);
565
566
6.77k
  UNUSED(type);
567
6.77k
  UNUSED(rdclass);
568
6.77k
  UNUSED(dctx);
569
570
6.77k
  isc_buffer_activeregion(source, &sr);
571
6.77k
  if (sr.length < 1) {
572
5
    return (ISC_R_UNEXPECTEDEND);
573
5
  }
574
6.76k
  if (sr.base[0] != 0) {
575
    /* Treat as unknown. */
576
3.03k
    isc_buffer_forward(source, sr.length);
577
3.03k
    return (mem_tobuffer(target, sr.base, sr.length));
578
3.03k
  }
579
3.73k
  if (sr.length < 16) {
580
20
    return (ISC_R_UNEXPECTEDEND);
581
20
  }
582
583
  /*
584
   * Size.
585
   */
586
3.71k
  c = sr.base[1];
587
3.71k
  if (c != 0) {
588
2.80k
    if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 ||
589
2.80k
        ((c >> 4) & 0xf) == 0)
590
17
    {
591
17
      return (ISC_R_RANGE);
592
593
      /*
594
       * Horizontal precision.
595
       */
596
17
    }
597
2.80k
  }
598
599
  /*
600
   * Horizontal precision.
601
   */
602
3.69k
  c = sr.base[2];
603
3.69k
  if (c != 0) {
604
1.94k
    if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 ||
605
1.94k
        ((c >> 4) & 0xf) == 0)
606
13
    {
607
13
      return (ISC_R_RANGE);
608
609
      /*
610
       * Vertical precision.
611
       */
612
13
    }
613
1.94k
  }
614
615
  /*
616
   * Vertical precision.
617
   */
618
3.68k
  c = sr.base[3];
619
3.68k
  if (c != 0) {
620
3.28k
    if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 ||
621
3.28k
        ((c >> 4) & 0xf) == 0)
622
14
    {
623
14
      return (ISC_R_RANGE);
624
14
    }
625
3.28k
  }
626
3.66k
  isc_region_consume(&sr, 4);
627
628
  /*
629
   * Latitude.
630
   */
631
3.66k
  latitude = uint32_fromregion(&sr);
632
3.66k
  if (latitude < (0x80000000UL - 90 * 3600000) ||
633
3.66k
      latitude > (0x80000000UL + 90 * 3600000))
634
118
  {
635
118
    return (ISC_R_RANGE);
636
118
  }
637
3.55k
  isc_region_consume(&sr, 4);
638
639
  /*
640
   * Longitude.
641
   */
642
3.55k
  longitude = uint32_fromregion(&sr);
643
3.55k
  if (longitude < (0x80000000UL - 180 * 3600000) ||
644
3.55k
      longitude > (0x80000000UL + 180 * 3600000))
645
149
  {
646
149
    return (ISC_R_RANGE);
647
149
  }
648
649
  /*
650
   * Altitude.
651
   * All values possible.
652
   */
653
654
3.40k
  isc_buffer_activeregion(source, &sr);
655
3.40k
  isc_buffer_forward(source, 16);
656
3.40k
  return (mem_tobuffer(target, sr.base, 16));
657
3.55k
}
658
659
static isc_result_t
660
2.52k
towire_loc(ARGS_TOWIRE) {
661
2.52k
  UNUSED(cctx);
662
663
2.52k
  REQUIRE(rdata->type == dns_rdatatype_loc);
664
2.52k
  REQUIRE(rdata->length != 0);
665
666
2.52k
  return (mem_tobuffer(target, rdata->data, rdata->length));
667
2.52k
}
668
669
static int
670
3.31M
compare_loc(ARGS_COMPARE) {
671
3.31M
  isc_region_t r1;
672
3.31M
  isc_region_t r2;
673
674
3.31M
  REQUIRE(rdata1->type == rdata2->type);
675
3.31M
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
676
3.31M
  REQUIRE(rdata1->type == dns_rdatatype_loc);
677
3.31M
  REQUIRE(rdata1->length != 0);
678
3.31M
  REQUIRE(rdata2->length != 0);
679
680
3.31M
  dns_rdata_toregion(rdata1, &r1);
681
3.31M
  dns_rdata_toregion(rdata2, &r2);
682
3.31M
  return (isc_region_compare(&r1, &r2));
683
3.31M
}
684
685
static isc_result_t
686
0
fromstruct_loc(ARGS_FROMSTRUCT) {
687
0
  dns_rdata_loc_t *loc = source;
688
0
  uint8_t c;
689
690
0
  REQUIRE(type == dns_rdatatype_loc);
691
0
  REQUIRE(loc != NULL);
692
0
  REQUIRE(loc->common.rdtype == type);
693
0
  REQUIRE(loc->common.rdclass == rdclass);
694
695
0
  UNUSED(type);
696
0
  UNUSED(rdclass);
697
698
0
  if (loc->v.v0.version != 0) {
699
0
    return (ISC_R_NOTIMPLEMENTED);
700
0
  }
701
0
  RETERR(uint8_tobuffer(loc->v.v0.version, target));
702
703
0
  c = loc->v.v0.size;
704
0
  if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 || ((c >> 4) & 0xf) == 0) {
705
0
    return (ISC_R_RANGE);
706
0
  }
707
0
  RETERR(uint8_tobuffer(loc->v.v0.size, target));
708
709
0
  c = loc->v.v0.horizontal;
710
0
  if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 || ((c >> 4) & 0xf) == 0) {
711
0
    return (ISC_R_RANGE);
712
0
  }
713
0
  RETERR(uint8_tobuffer(loc->v.v0.horizontal, target));
714
715
0
  c = loc->v.v0.vertical;
716
0
  if ((c & 0xf) > 9 || ((c >> 4) & 0xf) > 9 || ((c >> 4) & 0xf) == 0) {
717
0
    return (ISC_R_RANGE);
718
0
  }
719
0
  RETERR(uint8_tobuffer(loc->v.v0.vertical, target));
720
721
0
  if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) ||
722
0
      loc->v.v0.latitude > (0x80000000UL + 90 * 3600000))
723
0
  {
724
0
    return (ISC_R_RANGE);
725
0
  }
726
0
  RETERR(uint32_tobuffer(loc->v.v0.latitude, target));
727
728
0
  if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) ||
729
0
      loc->v.v0.longitude > (0x80000000UL + 180 * 3600000))
730
0
  {
731
0
    return (ISC_R_RANGE);
732
0
  }
733
0
  RETERR(uint32_tobuffer(loc->v.v0.longitude, target));
734
0
  return (uint32_tobuffer(loc->v.v0.altitude, target));
735
0
}
736
737
static isc_result_t
738
0
tostruct_loc(ARGS_TOSTRUCT) {
739
0
  dns_rdata_loc_t *loc = target;
740
0
  isc_region_t r;
741
0
  uint8_t version;
742
743
0
  REQUIRE(rdata->type == dns_rdatatype_loc);
744
0
  REQUIRE(loc != NULL);
745
0
  REQUIRE(rdata->length != 0);
746
747
0
  UNUSED(mctx);
748
749
0
  dns_rdata_toregion(rdata, &r);
750
0
  version = uint8_fromregion(&r);
751
0
  if (version != 0) {
752
0
    return (ISC_R_NOTIMPLEMENTED);
753
0
  }
754
755
0
  loc->common.rdclass = rdata->rdclass;
756
0
  loc->common.rdtype = rdata->type;
757
0
  ISC_LINK_INIT(&loc->common, link);
758
759
0
  loc->v.v0.version = version;
760
0
  isc_region_consume(&r, 1);
761
0
  loc->v.v0.size = uint8_fromregion(&r);
762
0
  isc_region_consume(&r, 1);
763
0
  loc->v.v0.horizontal = uint8_fromregion(&r);
764
0
  isc_region_consume(&r, 1);
765
0
  loc->v.v0.vertical = uint8_fromregion(&r);
766
0
  isc_region_consume(&r, 1);
767
0
  loc->v.v0.latitude = uint32_fromregion(&r);
768
0
  isc_region_consume(&r, 4);
769
0
  loc->v.v0.longitude = uint32_fromregion(&r);
770
0
  isc_region_consume(&r, 4);
771
0
  loc->v.v0.altitude = uint32_fromregion(&r);
772
0
  isc_region_consume(&r, 4);
773
0
  return (ISC_R_SUCCESS);
774
0
}
775
776
static void
777
0
freestruct_loc(ARGS_FREESTRUCT) {
778
0
  dns_rdata_loc_t *loc = source;
779
780
0
  REQUIRE(loc != NULL);
781
0
  REQUIRE(loc->common.rdtype == dns_rdatatype_loc);
782
783
0
  UNUSED(source);
784
0
  UNUSED(loc);
785
0
}
786
787
static isc_result_t
788
0
additionaldata_loc(ARGS_ADDLDATA) {
789
0
  REQUIRE(rdata->type == dns_rdatatype_loc);
790
791
0
  UNUSED(rdata);
792
0
  UNUSED(owner);
793
0
  UNUSED(add);
794
0
  UNUSED(arg);
795
796
0
  return (ISC_R_SUCCESS);
797
0
}
798
799
static isc_result_t
800
0
digest_loc(ARGS_DIGEST) {
801
0
  isc_region_t r;
802
803
0
  REQUIRE(rdata->type == dns_rdatatype_loc);
804
805
0
  dns_rdata_toregion(rdata, &r);
806
807
0
  return ((digest)(arg, &r));
808
0
}
809
810
static bool
811
0
checkowner_loc(ARGS_CHECKOWNER) {
812
0
  REQUIRE(type == dns_rdatatype_loc);
813
814
0
  UNUSED(name);
815
0
  UNUSED(type);
816
0
  UNUSED(rdclass);
817
0
  UNUSED(wildcard);
818
819
0
  return (true);
820
0
}
821
822
static bool
823
0
checknames_loc(ARGS_CHECKNAMES) {
824
0
  REQUIRE(rdata->type == dns_rdatatype_loc);
825
826
0
  UNUSED(rdata);
827
0
  UNUSED(owner);
828
0
  UNUSED(bad);
829
830
0
  return (true);
831
0
}
832
833
static int
834
0
casecompare_loc(ARGS_COMPARE) {
835
0
  return (compare_loc(rdata1, rdata2));
836
0
}
837
838
#endif /* RDATA_GENERIC_LOC_29_C */