Coverage Report

Created: 2023-06-07 06:22

/src/bind9/lib/isc/netaddr.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
/*! \file */
15
16
#include <inttypes.h>
17
#include <stdbool.h>
18
#include <stdio.h>
19
20
#include <isc/buffer.h>
21
#include <isc/net.h>
22
#include <isc/netaddr.h>
23
#include <isc/sockaddr.h>
24
#include <isc/string.h>
25
#include <isc/util.h>
26
27
bool
28
0
isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
29
0
  REQUIRE(a != NULL && b != NULL);
30
31
0
  if (a->family != b->family) {
32
0
    return (false);
33
0
  }
34
35
0
  if (a->zone != b->zone) {
36
0
    return (false);
37
0
  }
38
39
0
  switch (a->family) {
40
0
  case AF_INET:
41
0
    if (a->type.in.s_addr != b->type.in.s_addr) {
42
0
      return (false);
43
0
    }
44
0
    break;
45
0
  case AF_INET6:
46
0
    if (memcmp(&a->type.in6, &b->type.in6, sizeof(a->type.in6)) !=
47
0
          0 ||
48
0
        a->zone != b->zone)
49
0
    {
50
0
      return (false);
51
0
    }
52
0
    break;
53
0
  case AF_UNIX:
54
0
    if (strcmp(a->type.un, b->type.un) != 0) {
55
0
      return (false);
56
0
    }
57
0
    break;
58
0
  default:
59
0
    return (false);
60
0
  }
61
0
  return (true);
62
0
}
63
64
bool
65
isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
66
0
         unsigned int prefixlen) {
67
0
  const unsigned char *pa = NULL, *pb = NULL;
68
0
  unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
69
0
  unsigned int nbytes;     /* Number of significant whole bytes */
70
0
  unsigned int nbits;    /* Number of significant leftover bits */
71
72
0
  REQUIRE(a != NULL && b != NULL);
73
74
0
  if (a->family != b->family) {
75
0
    return (false);
76
0
  }
77
78
0
  if (a->zone != b->zone && b->zone != 0) {
79
0
    return (false);
80
0
  }
81
82
0
  switch (a->family) {
83
0
  case AF_INET:
84
0
    pa = (const unsigned char *)&a->type.in;
85
0
    pb = (const unsigned char *)&b->type.in;
86
0
    ipabytes = 4;
87
0
    break;
88
0
  case AF_INET6:
89
0
    pa = (const unsigned char *)&a->type.in6;
90
0
    pb = (const unsigned char *)&b->type.in6;
91
0
    ipabytes = 16;
92
0
    break;
93
0
  default:
94
0
    return (false);
95
0
  }
96
97
  /*
98
   * Don't crash if we get a pattern like 10.0.0.1/9999999.
99
   */
100
0
  if (prefixlen > ipabytes * 8) {
101
0
    prefixlen = ipabytes * 8;
102
0
  }
103
104
0
  nbytes = prefixlen / 8;
105
0
  nbits = prefixlen % 8;
106
107
0
  if (nbytes > 0) {
108
0
    if (memcmp(pa, pb, nbytes) != 0) {
109
0
      return (false);
110
0
    }
111
0
  }
112
0
  if (nbits > 0) {
113
0
    unsigned int bytea, byteb, mask;
114
0
    INSIST(nbytes < ipabytes);
115
0
    INSIST(nbits < 8);
116
0
    bytea = pa[nbytes];
117
0
    byteb = pb[nbytes];
118
0
    mask = (0xFF << (8 - nbits)) & 0xFF;
119
0
    if ((bytea & mask) != (byteb & mask)) {
120
0
      return (false);
121
0
    }
122
0
  }
123
0
  return (true);
124
0
}
125
126
isc_result_t
127
0
isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
128
0
  char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
129
0
  char zbuf[sizeof("%4294967295")];
130
0
  unsigned int alen;
131
0
  int zlen;
132
0
  const char *r;
133
0
  const void *type;
134
135
0
  REQUIRE(netaddr != NULL);
136
137
0
  switch (netaddr->family) {
138
0
  case AF_INET:
139
0
    type = &netaddr->type.in;
140
0
    break;
141
0
  case AF_INET6:
142
0
    type = &netaddr->type.in6;
143
0
    break;
144
0
  case AF_UNIX:
145
0
    alen = strlen(netaddr->type.un);
146
0
    if (alen > isc_buffer_availablelength(target)) {
147
0
      return (ISC_R_NOSPACE);
148
0
    }
149
0
    isc_buffer_putmem(target,
150
0
          (const unsigned char *)(netaddr->type.un),
151
0
          alen);
152
0
    return (ISC_R_SUCCESS);
153
0
  default:
154
0
    return (ISC_R_FAILURE);
155
0
  }
156
0
  r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
157
0
  if (r == NULL) {
158
0
    return (ISC_R_FAILURE);
159
0
  }
160
161
0
  alen = strlen(abuf);
162
0
  INSIST(alen < sizeof(abuf));
163
164
0
  zlen = 0;
165
0
  if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
166
0
    zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
167
0
    if (zlen < 0) {
168
0
      return (ISC_R_FAILURE);
169
0
    }
170
0
    INSIST((unsigned int)zlen < sizeof(zbuf));
171
0
  }
172
173
0
  if (alen + zlen > isc_buffer_availablelength(target)) {
174
0
    return (ISC_R_NOSPACE);
175
0
  }
176
177
0
  isc_buffer_putmem(target, (unsigned char *)abuf, alen);
178
0
  isc_buffer_putmem(target, (unsigned char *)zbuf, (unsigned int)zlen);
179
180
0
  return (ISC_R_SUCCESS);
181
0
}
182
183
void
184
0
isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
185
0
  isc_result_t result;
186
0
  isc_buffer_t buf;
187
188
0
  isc_buffer_init(&buf, array, size);
189
0
  result = isc_netaddr_totext(na, &buf);
190
191
0
  if (size == 0) {
192
0
    return;
193
0
  }
194
195
  /*
196
   * Null terminate.
197
   */
198
0
  if (result == ISC_R_SUCCESS) {
199
0
    if (isc_buffer_availablelength(&buf) >= 1) {
200
0
      isc_buffer_putuint8(&buf, 0);
201
0
    } else {
202
0
      result = ISC_R_NOSPACE;
203
0
    }
204
0
  }
205
206
0
  if (result != ISC_R_SUCCESS) {
207
0
    snprintf(array, size, "<unknown address, family %u>",
208
0
       na->family);
209
0
    array[size - 1] = '\0';
210
0
  }
211
0
}
212
213
isc_result_t
214
0
isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
215
0
  static const unsigned char zeros[16];
216
0
  unsigned int nbits, nbytes, ipbytes = 0;
217
0
  const unsigned char *p;
218
219
0
  switch (na->family) {
220
0
  case AF_INET:
221
0
    p = (const unsigned char *)&na->type.in;
222
0
    ipbytes = 4;
223
0
    if (prefixlen > 32) {
224
0
      return (ISC_R_RANGE);
225
0
    }
226
0
    break;
227
0
  case AF_INET6:
228
0
    p = (const unsigned char *)&na->type.in6;
229
0
    ipbytes = 16;
230
0
    if (prefixlen > 128) {
231
0
      return (ISC_R_RANGE);
232
0
    }
233
0
    break;
234
0
  default:
235
0
    return (ISC_R_NOTIMPLEMENTED);
236
0
  }
237
0
  nbytes = prefixlen / 8;
238
0
  nbits = prefixlen % 8;
239
0
  if (nbits != 0) {
240
0
    INSIST(nbytes < ipbytes);
241
0
    if ((p[nbytes] & (0xff >> nbits)) != 0U) {
242
0
      return (ISC_R_FAILURE);
243
0
    }
244
0
    nbytes++;
245
0
  }
246
0
  if (nbytes < ipbytes &&
247
0
      memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
248
0
  {
249
0
    return (ISC_R_FAILURE);
250
0
  }
251
0
  return (ISC_R_SUCCESS);
252
0
}
253
254
isc_result_t
255
0
isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
256
0
  unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
257
0
  const unsigned char *p;
258
259
0
  switch (s->family) {
260
0
  case AF_INET:
261
0
    p = (const unsigned char *)&s->type.in;
262
0
    ipbytes = 4;
263
0
    break;
264
0
  case AF_INET6:
265
0
    p = (const unsigned char *)&s->type.in6;
266
0
    ipbytes = 16;
267
0
    break;
268
0
  default:
269
0
    return (ISC_R_NOTIMPLEMENTED);
270
0
  }
271
0
  for (i = 0; i < ipbytes; i++) {
272
0
    if (p[i] != 0xFF) {
273
0
      break;
274
0
    }
275
0
  }
276
0
  nbytes = i;
277
0
  if (i < ipbytes) {
278
0
    unsigned int c = p[nbytes];
279
0
    while ((c & 0x80) != 0 && nbits < 8) {
280
0
      c <<= 1;
281
0
      nbits++;
282
0
    }
283
0
    if ((c & 0xFF) != 0) {
284
0
      return (ISC_R_MASKNONCONTIG);
285
0
    }
286
0
    i++;
287
0
  }
288
0
  for (; i < ipbytes; i++) {
289
0
    if (p[i] != 0) {
290
0
      return (ISC_R_MASKNONCONTIG);
291
0
    }
292
0
  }
293
0
  *lenp = nbytes * 8 + nbits;
294
0
  return (ISC_R_SUCCESS);
295
0
}
296
297
void
298
0
isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
299
0
  memset(netaddr, 0, sizeof(*netaddr));
300
0
  netaddr->family = AF_INET;
301
0
  netaddr->type.in = *ina;
302
0
}
303
304
void
305
0
isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
306
0
  memset(netaddr, 0, sizeof(*netaddr));
307
0
  netaddr->family = AF_INET6;
308
0
  netaddr->type.in6 = *ina6;
309
0
}
310
311
isc_result_t
312
0
isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
313
0
  if (strlen(path) > sizeof(netaddr->type.un) - 1) {
314
0
    return (ISC_R_NOSPACE);
315
0
  }
316
317
0
  memset(netaddr, 0, sizeof(*netaddr));
318
0
  netaddr->family = AF_UNIX;
319
0
  strlcpy(netaddr->type.un, path, sizeof(netaddr->type.un));
320
0
  netaddr->zone = 0;
321
0
  return (ISC_R_SUCCESS);
322
0
}
323
324
void
325
0
isc_netaddr_setzone(isc_netaddr_t *netaddr, uint32_t zone) {
326
  /* we currently only support AF_INET6. */
327
0
  REQUIRE(netaddr->family == AF_INET6);
328
329
0
  netaddr->zone = zone;
330
0
}
331
332
uint32_t
333
0
isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
334
0
  return (netaddr->zone);
335
0
}
336
337
void
338
0
isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
339
0
  int family = s->type.sa.sa_family;
340
0
  t->family = family;
341
0
  switch (family) {
342
0
  case AF_INET:
343
0
    t->type.in = s->type.sin.sin_addr;
344
0
    t->zone = 0;
345
0
    break;
346
0
  case AF_INET6:
347
0
    memmove(&t->type.in6, &s->type.sin6.sin6_addr, 16);
348
0
    t->zone = s->type.sin6.sin6_scope_id;
349
0
    break;
350
0
  case AF_UNIX:
351
0
    memmove(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
352
0
    t->zone = 0;
353
0
    break;
354
0
  default:
355
0
    UNREACHABLE();
356
0
  }
357
0
}
358
359
void
360
0
isc_netaddr_any(isc_netaddr_t *netaddr) {
361
0
  memset(netaddr, 0, sizeof(*netaddr));
362
0
  netaddr->family = AF_INET;
363
0
  netaddr->type.in.s_addr = INADDR_ANY;
364
0
}
365
366
void
367
0
isc_netaddr_any6(isc_netaddr_t *netaddr) {
368
0
  memset(netaddr, 0, sizeof(*netaddr));
369
0
  netaddr->family = AF_INET6;
370
0
  netaddr->type.in6 = in6addr_any;
371
0
}
372
373
void
374
0
isc_netaddr_unspec(isc_netaddr_t *netaddr) {
375
0
  memset(netaddr, 0, sizeof(*netaddr));
376
0
  netaddr->family = AF_UNSPEC;
377
0
}
378
379
bool
380
0
isc_netaddr_ismulticast(const isc_netaddr_t *na) {
381
0
  switch (na->family) {
382
0
  case AF_INET:
383
0
    return (ISC_IPADDR_ISMULTICAST(na->type.in.s_addr));
384
0
  case AF_INET6:
385
0
    return (IN6_IS_ADDR_MULTICAST(&na->type.in6));
386
0
  default:
387
0
    return (false); /* XXXMLG ? */
388
0
  }
389
0
}
390
391
bool
392
0
isc_netaddr_isexperimental(const isc_netaddr_t *na) {
393
0
  switch (na->family) {
394
0
  case AF_INET:
395
0
    return (ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr));
396
0
  default:
397
0
    return (false); /* XXXMLG ? */
398
0
  }
399
0
}
400
401
bool
402
0
isc_netaddr_islinklocal(const isc_netaddr_t *na) {
403
0
  switch (na->family) {
404
0
  case AF_INET:
405
0
    return (false);
406
0
  case AF_INET6:
407
0
    return (IN6_IS_ADDR_LINKLOCAL(&na->type.in6));
408
0
  default:
409
0
    return (false);
410
0
  }
411
0
}
412
413
bool
414
0
isc_netaddr_issitelocal(const isc_netaddr_t *na) {
415
0
  switch (na->family) {
416
0
  case AF_INET:
417
0
    return (false);
418
0
  case AF_INET6:
419
0
    return (IN6_IS_ADDR_SITELOCAL(&na->type.in6));
420
0
  default:
421
0
    return (false);
422
0
  }
423
0
}
424
425
#define ISC_IPADDR_ISNETZERO(i) \
426
0
  (((uint32_t)(i)&ISC__IPADDR(0xff000000)) == ISC__IPADDR(0x00000000))
427
428
bool
429
0
isc_netaddr_isnetzero(const isc_netaddr_t *na) {
430
0
  switch (na->family) {
431
0
  case AF_INET:
432
0
    return (ISC_IPADDR_ISNETZERO(na->type.in.s_addr));
433
0
  case AF_INET6:
434
0
    return (false);
435
0
  default:
436
0
    return (false);
437
0
  }
438
0
}
439
440
void
441
0
isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
442
0
  isc_netaddr_t *src = UNCONST(s); /* Must come before
443
              IN6_IS_ADDR_V4MAPPED. */
444
445
0
  REQUIRE(s->family == AF_INET6);
446
0
  REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
447
448
0
  memset(t, 0, sizeof(*t));
449
0
  t->family = AF_INET;
450
0
  memmove(&t->type.in, (char *)&src->type.in6 + 12, 4);
451
0
  return;
452
0
}
453
454
bool
455
0
isc_netaddr_isloopback(const isc_netaddr_t *na) {
456
0
  switch (na->family) {
457
0
  case AF_INET:
458
0
    return (((ntohl(na->type.in.s_addr) & 0xff000000U) ==
459
0
       0x7f000000U));
460
0
  case AF_INET6:
461
0
    return (IN6_IS_ADDR_LOOPBACK(&na->type.in6));
462
0
  default:
463
0
    return (false);
464
0
  }
465
0
}