Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/lib/isc/netaddr.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2004, 2005, 2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
3
 * Copyright (C) 1999-2002  Internet Software Consortium.
4
 *
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
 * PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
/* $Id$ */
19
20
/*! \file */
21
22
#include <config.h>
23
24
#include <stdio.h>
25
26
#include <isc/buffer.h>
27
#include <isc/msgs.h>
28
#include <isc/net.h>
29
#include <isc/netaddr.h>
30
#include <isc/print.h>
31
#include <isc/sockaddr.h>
32
#include <isc/string.h>
33
#include <isc/util.h>
34
#include "ntp_stdlib.h"   /* NTP change for strlcpy, strlcat */
35
36
isc_boolean_t
37
0
isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
38
0
  REQUIRE(a != NULL && b != NULL);
39
40
0
  if (a->family != b->family)
41
0
    return (ISC_FALSE);
42
43
0
  if (a->zone != b->zone)
44
0
    return (ISC_FALSE);
45
46
0
  switch (a->family) {
47
0
  case AF_INET:
48
0
    if (a->type.in.s_addr != b->type.in.s_addr)
49
0
      return (ISC_FALSE);
50
0
    break;
51
0
  case AF_INET6:
52
0
    if (memcmp(&a->type.in6, &b->type.in6,
53
0
         sizeof(a->type.in6)) != 0 ||
54
0
        a->zone != b->zone)
55
0
      return (ISC_FALSE);
56
0
    break;
57
#ifdef ISC_PLATFORM_HAVESYSUNH
58
  case AF_UNIX:
59
    if (strcmp(a->type.un, b->type.un) != 0)
60
      return (ISC_FALSE);
61
    break;
62
#endif
63
0
  default:
64
0
    return (ISC_FALSE);
65
0
  }
66
0
  return (ISC_TRUE);
67
0
}
68
69
isc_boolean_t
70
isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
71
         unsigned int prefixlen)
72
0
{
73
0
  const unsigned char *pa = NULL, *pb = NULL;
74
0
  unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
75
0
  unsigned int nbytes;       /* Number of significant whole bytes */
76
0
  unsigned int nbits;        /* Number of significant leftover bits */
77
78
0
  REQUIRE(a != NULL && b != NULL);
79
80
0
  if (a->family != b->family)
81
0
    return (ISC_FALSE);
82
83
0
  if (a->zone != b->zone && b->zone != 0)
84
0
    return (ISC_FALSE);
85
86
0
  switch (a->family) {
87
0
  case AF_INET:
88
0
    pa = (const unsigned char *) &a->type.in;
89
0
    pb = (const unsigned char *) &b->type.in;
90
0
    ipabytes = 4;
91
0
    break;
92
0
  case AF_INET6:
93
0
    pa = (const unsigned char *) &a->type.in6;
94
0
    pb = (const unsigned char *) &b->type.in6;
95
0
    ipabytes = 16;
96
0
    break;
97
0
  default:
98
0
    return (ISC_FALSE);
99
0
  }
100
101
  /*
102
   * Don't crash if we get a pattern like 10.0.0.1/9999999.
103
   */
104
0
  if (prefixlen > ipabytes * 8)
105
0
    prefixlen = ipabytes * 8;
106
107
0
  nbytes = prefixlen / 8;
108
0
  nbits = prefixlen % 8;
109
110
0
  if (nbytes > 0) {
111
0
    if (memcmp(pa, pb, nbytes) != 0)
112
0
      return (ISC_FALSE);
113
0
  }
114
0
  if (nbits > 0) {
115
0
    unsigned int bytea, byteb, mask;
116
0
    INSIST(nbytes < ipabytes);
117
0
    INSIST(nbits < 8);
118
0
    bytea = pa[nbytes];
119
0
    byteb = pb[nbytes];
120
0
    mask = (0xFF << (8-nbits)) & 0xFF;
121
0
    if ((bytea & mask) != (byteb & mask))
122
0
      return (ISC_FALSE);
123
0
  }
124
0
  return (ISC_TRUE);
125
0
}
126
127
isc_result_t
128
0
isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
129
0
  char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
130
0
  char zbuf[sizeof("%4294967295")];
131
0
  unsigned int alen;
132
0
  int zlen;
133
0
  const char *r;
134
0
  const void *type;
135
136
0
  REQUIRE(netaddr != NULL);
137
138
0
  switch (netaddr->family) {
139
0
  case AF_INET:
140
0
    type = &netaddr->type.in;
141
0
    break;
142
0
  case AF_INET6:
143
0
    type = &netaddr->type.in6;
144
0
    break;
145
#ifdef ISC_PLATFORM_HAVESYSUNH
146
  case AF_UNIX:
147
    alen = strlen(netaddr->type.un);
148
    if (alen > isc_buffer_availablelength(target))
149
      return (ISC_R_NOSPACE);
150
    isc_buffer_putmem(target,
151
          (const unsigned char *)(netaddr->type.un),
152
          alen);
153
    return (ISC_R_SUCCESS);
154
#endif
155
0
  default:
156
0
    return (ISC_R_FAILURE);
157
0
  }
158
0
  r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
159
0
  if (r == NULL)
160
0
    return (ISC_R_FAILURE);
161
162
0
  alen = (unsigned int)strlen(abuf); /* no overflow possible */
163
0
  INSIST(alen < sizeof(abuf));
164
165
0
  zlen = 0;
166
0
  if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
167
0
    zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
168
0
    if (zlen < 0)
169
0
      return (ISC_R_FAILURE);
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
176
0
  isc_buffer_putmem(target, (unsigned char *)abuf, alen);
177
0
  isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
178
179
0
  return (ISC_R_SUCCESS);
180
0
}
181
182
void
183
0
isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
184
0
  isc_result_t result;
185
0
  isc_buffer_t buf;
186
187
0
  isc_buffer_init(&buf, array, size);
188
0
  result = isc_netaddr_totext(na, &buf);
189
190
0
  if (size == 0)
191
0
    return;
192
193
  /*
194
   * Null terminate.
195
   */
196
0
  if (result == ISC_R_SUCCESS) {
197
0
    if (isc_buffer_availablelength(&buf) >= 1)
198
0
      isc_buffer_putuint8(&buf, 0);
199
0
    else
200
0
      result = ISC_R_NOSPACE;
201
0
  }
202
203
0
  if (result != ISC_R_SUCCESS) {
204
0
    snprintf(array, size,
205
0
       "<%s %u>",
206
0
       isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
207
0
          ISC_MSG_UNKNOWNADDR,
208
0
          "unknown address, family"),
209
0
       na->family);
210
0
    array[size - 1] = '\0';
211
0
  }
212
0
}
213
214
215
isc_result_t
216
0
isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
217
0
  static const unsigned char zeros[16] = { 0 };
218
0
  unsigned int nbits, nbytes, ipbytes = 0;
219
0
  const unsigned char *p;
220
221
0
  switch (na->family) {
222
0
  case AF_INET:
223
0
    p = (const unsigned char *) &na->type.in;
224
0
    ipbytes = 4;
225
0
    if (prefixlen > 32)
226
0
      return (ISC_R_RANGE);
227
0
    break;
228
0
  case AF_INET6:
229
0
    p = (const unsigned char *) &na->type.in6;
230
0
    ipbytes = 16;
231
0
    if (prefixlen > 128)
232
0
      return (ISC_R_RANGE);
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
    if ((p[nbytes] & (0xff>>nbits)) != 0U)
241
0
      return (ISC_R_FAILURE);
242
0
    nbytes++;
243
0
  }
244
0
  if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
245
0
    return (ISC_R_FAILURE);
246
0
  return (ISC_R_SUCCESS);
247
0
}
248
249
isc_result_t
250
0
isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
251
0
  unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
252
0
  const unsigned char *p;
253
254
0
  switch (s->family) {
255
0
  case AF_INET:
256
0
    p = (const unsigned char *) &s->type.in;
257
0
    ipbytes = 4;
258
0
    break;
259
0
  case AF_INET6:
260
0
    p = (const unsigned char *) &s->type.in6;
261
0
    ipbytes = 16;
262
0
    break;
263
0
  default:
264
0
    return (ISC_R_NOTIMPLEMENTED);
265
0
  }
266
0
  for (i = 0; i < ipbytes; i++) {
267
0
    if (p[i] != 0xFF)
268
0
      break;
269
0
  }
270
0
  nbytes = i;
271
0
  if (i < ipbytes) {
272
0
    unsigned int c = p[nbytes];
273
0
    while ((c & 0x80) != 0 && nbits < 8) {
274
0
      c <<= 1; nbits++;
275
0
    }
276
0
    if ((c & 0xFF) != 0)
277
0
      return (ISC_R_MASKNONCONTIG);
278
0
    i++;
279
0
  }
280
0
  for (; i < ipbytes; i++) {
281
0
    if (p[i] != 0)
282
0
      return (ISC_R_MASKNONCONTIG);
283
0
  }
284
0
  *lenp = nbytes * 8 + nbits;
285
0
  return (ISC_R_SUCCESS);
286
0
}
287
288
void
289
0
isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
290
0
  memset(netaddr, 0, sizeof(*netaddr));
291
0
  netaddr->family = AF_INET;
292
0
  netaddr->type.in = *ina;
293
0
}
294
295
void
296
0
isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
297
0
  memset(netaddr, 0, sizeof(*netaddr));
298
0
  netaddr->family = AF_INET6;
299
0
  netaddr->type.in6 = *ina6;
300
0
}
301
302
isc_result_t
303
0
isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
304
#ifdef ISC_PLATFORM_HAVESYSUNH
305
  if (strlen(path) > sizeof(netaddr->type.un) - 1)
306
    return (ISC_R_NOSPACE);
307
308
        memset(netaddr, 0, sizeof(*netaddr));
309
        netaddr->family = AF_UNIX;
310
  strlcpy(netaddr->type.un, path, sizeof(netaddr->type.un));
311
        netaddr->zone = 0;
312
        return (ISC_R_SUCCESS);
313
#else 
314
0
  UNUSED(netaddr);
315
0
  UNUSED(path);
316
0
  return (ISC_R_NOTIMPLEMENTED);
317
0
#endif
318
0
}
319
320
321
void
322
0
isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
323
  /* we currently only support AF_INET6. */
324
0
  REQUIRE(netaddr->family == AF_INET6);
325
326
0
  netaddr->zone = zone;
327
0
}
328
329
isc_uint32_t
330
0
isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
331
0
  return (netaddr->zone);
332
0
}
333
334
void
335
0
isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
336
0
  int family = s->type.sa.sa_family;
337
0
  t->family = family;
338
0
  switch (family) {
339
0
  case AF_INET:
340
0
    t->type.in = s->type.sin.sin_addr;
341
0
    t->zone = 0;
342
0
    break;
343
0
  case AF_INET6:
344
0
    memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
345
0
#ifdef ISC_PLATFORM_HAVESCOPEID
346
0
    t->zone = s->type.sin6.sin6_scope_id;
347
#else
348
    t->zone = 0;
349
#endif
350
0
    break;
351
#ifdef ISC_PLATFORM_HAVESYSUNH
352
  case AF_UNIX:
353
    memcpy(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
354
    t->zone = 0;
355
    break;
356
#endif
357
0
  default:
358
0
    INSIST(0);
359
0
  }
360
0
}
361
362
void
363
0
isc_netaddr_any(isc_netaddr_t *netaddr) {
364
0
  memset(netaddr, 0, sizeof(*netaddr));
365
0
  netaddr->family = AF_INET;
366
0
  netaddr->type.in.s_addr = INADDR_ANY;
367
0
}
368
369
void
370
0
isc_netaddr_any6(isc_netaddr_t *netaddr) {
371
0
  memset(netaddr, 0, sizeof(*netaddr));
372
0
  netaddr->family = AF_INET6;
373
0
  netaddr->type.in6 = in6addr_any;
374
0
}
375
376
isc_boolean_t
377
0
isc_netaddr_ismulticast(isc_netaddr_t *na) {
378
0
  switch (na->family) {
379
0
  case AF_INET:
380
0
    return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
381
0
  case AF_INET6:
382
0
    return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
383
0
  default:
384
0
    return (ISC_FALSE);  /* XXXMLG ? */
385
0
  }
386
0
}
387
388
isc_boolean_t
389
0
isc_netaddr_isexperimental(isc_netaddr_t *na) {
390
0
  switch (na->family) {
391
0
  case AF_INET:
392
0
    return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
393
0
  default:
394
0
    return (ISC_FALSE);  /* XXXMLG ? */
395
0
  }
396
0
}
397
398
isc_boolean_t
399
0
isc_netaddr_islinklocal(isc_netaddr_t *na) {
400
0
  switch (na->family) {
401
0
  case AF_INET:
402
0
    return (ISC_FALSE);
403
0
  case AF_INET6:
404
0
    return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
405
0
  default:
406
0
    return (ISC_FALSE);
407
0
  }
408
0
}
409
410
isc_boolean_t
411
0
isc_netaddr_issitelocal(isc_netaddr_t *na) {
412
0
  switch (na->family) {
413
0
  case AF_INET:
414
0
    return (ISC_FALSE);
415
0
  case AF_INET6:
416
0
    return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
417
0
  default:
418
0
    return (ISC_FALSE);
419
0
  }
420
0
}
421
422
void
423
0
isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
424
0
  isc_netaddr_t *src;
425
426
0
  DE_CONST(s, src); /* Must come before IN6_IS_ADDR_V4MAPPED. */
427
428
0
  REQUIRE(s->family == AF_INET6);
429
0
  REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
430
431
0
  memset(t, 0, sizeof(*t));
432
0
  t->family = AF_INET;
433
0
  memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4);
434
0
  return;
435
0
}