Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/libntp/ntp_rfc2553.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
/*
31
 * Copyright (c) 1982, 1986, 1990, 1993
32
 *  The Regents of the University of California.  All rights reserved.
33
 *
34
 * Redistribution and use in source and binary forms, with or without
35
 * modification, are permitted provided that the following conditions
36
 * are met:
37
 * 1. Redistributions of source code must retain the above copyright
38
 *    notice, this list of conditions and the following disclaimer.
39
 * 2. Redistributions in binary form must reproduce the above copyright
40
 *    notice, this list of conditions and the following disclaimer in the
41
 *    documentation and/or other materials provided with the distribution.
42
 * 3. All advertising materials mentioning features or use of this software
43
 *    must display the following acknowledgement:
44
 *  This product includes software developed by the University of
45
 *  California, Berkeley and its contributors.
46
 * 4. Neither the name of the University nor the names of its contributors
47
 *    may be used to endorse or promote products derived from this software
48
 *    without specific prior written permission.
49
 *
50
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60
 * SUCH DAMAGE.
61
 *
62
 */
63
64
/*
65
 * Compatability shims with the rfc2553 API to simplify ntp.
66
 */
67
68
#include <config.h>
69
70
#include <sys/types.h>
71
#include <ctype.h>
72
#ifdef HAVE_SYS_SOCKET_H
73
#include <sys/socket.h>
74
#endif
75
#include <isc/net.h>
76
#ifdef HAVE_NETINET_IN_H
77
#include <netinet/in.h>
78
#endif
79
#include "ntp_rfc2553.h"
80
81
#include "ntpd.h"
82
#include "ntp_malloc.h"
83
#include "ntp_string.h"
84
#include "ntp_debug.h"
85
86
87
/*
88
 * copy_addrinfo()  - copy a single addrinfo to malloc()'d block.
89
 * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block.
90
 *
91
 * Copies an addrinfo list and its associated data to a contiguous block
92
 * of storage from emalloc().  Callback routines invoked via
93
 * getaddrinfo_sometime() have access to the resulting addrinfo list
94
 * only until they return.  This routine provides an easy way to make a
95
 * persistent copy.  Although the list provided to gai_sometime_callback
96
 * routines is similarly contiguous, to keep this code usable in any
97
 * context where we might want to duplicate an addrinfo list, it does
98
 * not require the input list be contiguous.
99
 *
100
 * The returned list head pointer is passed to free() to release the
101
 * entire list.
102
 *
103
 * In keeping with the rest of the NTP distribution, sockaddr_u is used
104
 * in preference to struct sockaddr_storage, which is a member of the
105
 * former union and so compatible.
106
 *
107
 * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6
108
 * not being defined, copy_addrinfo_*() are exceptions.
109
 */
110
struct addrinfo * copy_addrinfo_common(const struct addrinfo *, int
111
#ifdef EREALLOC_CALLSITE
112
                   ,
113
               const char *, int
114
#endif
115
               );
116
117
118
struct addrinfo *
119
copy_addrinfo_impl(
120
  const struct addrinfo * src
121
#ifdef EREALLOC_CALLSITE
122
           ,
123
  const char *    caller_file,
124
  int     caller_line
125
#endif
126
  )
127
0
{
128
0
  return copy_addrinfo_common(src, TRUE
129
#ifdef EREALLOC_CALLSITE
130
                ,
131
            caller_file, caller_line
132
#endif
133
0
            );
134
0
}
135
136
137
struct addrinfo *
138
copy_addrinfo_list_impl(
139
  const struct addrinfo * src
140
#ifdef EREALLOC_CALLSITE
141
           ,
142
  const char *    caller_file,
143
  int     caller_line
144
#endif
145
  )
146
0
{
147
0
  return copy_addrinfo_common(src, FALSE
148
#ifdef EREALLOC_CALLSITE
149
                ,
150
            caller_file, caller_line
151
#endif
152
0
            );
153
0
}
154
155
156
struct addrinfo *
157
copy_addrinfo_common(
158
  const struct addrinfo * src,
159
  int     just_one
160
#ifdef EREALLOC_CALLSITE
161
          ,
162
  const char *    caller_file,
163
  int     caller_line
164
#endif
165
  )
166
0
{
167
0
  const struct addrinfo * ai_src;
168
0
  const struct addrinfo * ai_nxt;
169
0
  struct addrinfo * ai_cpy;
170
0
  struct addrinfo * dst;
171
0
  sockaddr_u *    psau;
172
0
  char *      pcanon;
173
0
  u_int     elements;
174
0
  size_t      octets;
175
0
  size_t      canons_octets;
176
0
  size_t      str_octets;
177
178
0
  elements = 0;
179
0
  canons_octets = 0;
180
181
0
  for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
182
0
    if (just_one)
183
0
      ai_nxt = NULL;
184
0
    else
185
0
      ai_nxt = ai_src->ai_next;
186
0
    ++elements;
187
0
    if (NULL != ai_src->ai_canonname)
188
0
      canons_octets += 1 + strlen(ai_src->ai_canonname);
189
0
  }
190
191
0
  octets = elements * (sizeof(*ai_cpy) + sizeof(*psau));
192
0
  octets += canons_octets;
193
194
0
  dst = erealloczsite(NULL, octets, 0, TRUE, caller_file,
195
0
          caller_line);
196
0
  ai_cpy = dst;
197
0
  psau = (void *)(ai_cpy + elements);
198
0
  pcanon = (void *)(psau + elements);
199
200
0
  for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
201
0
    if (just_one)
202
0
      ai_nxt = NULL;
203
0
    else
204
0
      ai_nxt = ai_src->ai_next;
205
0
    *ai_cpy = *ai_src;
206
0
    DEBUG_INSIST(ai_cpy->ai_canonname == ai_src->ai_canonname);
207
0
    INSIST(ai_src->ai_addrlen <= sizeof(sockaddr_u));
208
0
    memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
209
0
    ai_cpy->ai_addr = &psau->sa;
210
0
    ++psau;
211
0
    if (NULL != ai_src->ai_canonname) {
212
0
      ai_cpy->ai_canonname = pcanon;
213
0
      str_octets = 1 + strlen(ai_src->ai_canonname);
214
0
      memcpy(pcanon, ai_src->ai_canonname, str_octets);
215
0
      pcanon += str_octets;
216
0
    }
217
0
    if (NULL != ai_cpy->ai_next) {
218
0
      if (just_one)
219
0
        ai_cpy->ai_next = NULL;
220
0
      else
221
0
        ai_cpy->ai_next = ai_cpy + 1;
222
0
    }
223
0
    ++ai_cpy;
224
0
  }
225
0
  ENSURE(pcanon == ((char *)dst + octets));
226
227
0
  return dst;
228
0
}
229
230
231
#ifndef ISC_PLATFORM_HAVEIPV6
232
233
static char *ai_errlist[] = {
234
  "Success",
235
  "Address family for hostname not supported",  /* EAI_ADDRFAMILY */
236
  "Temporary failure in name resolution",   /* EAI_AGAIN      */
237
  "Invalid value for ai_flags",           /* EAI_BADFLAGS   */
238
  "Non-recoverable failure in name resolution",   /* EAI_FAIL       */
239
  "ai_family not supported",      /* EAI_FAMILY     */
240
  "Memory allocation failure",      /* EAI_MEMORY     */
241
  "No address associated with hostname",    /* EAI_NODATA     */
242
  "hostname nor servname provided, or not known", /* EAI_NONAME     */
243
  "servname not supported for ai_socktype", /* EAI_SERVICE    */
244
  "ai_socktype not supported",      /* EAI_SOCKTYPE   */
245
  "System error returned in errno",     /* EAI_SYSTEM     */
246
  "Invalid value for hints",      /* EAI_BADHINTS   */
247
  "Resolved protocol is unknown",     /* EAI_PROTOCOL   */
248
  "Unknown error",        /* EAI_MAX        */
249
};
250
251
/*
252
 * Local declaration
253
 */
254
int
255
DNSlookup_name(
256
  const char *name,
257
  int ai_family,
258
  struct hostent **Addresses
259
);
260
261
#ifndef SYS_WINNT
262
/*
263
 * Encapsulate gethostbyname to control the error code
264
 */
265
int
266
DNSlookup_name(
267
  const char *name,
268
  int ai_family,
269
  struct hostent **Addresses
270
)
271
{
272
  *Addresses = gethostbyname(name);
273
  return (h_errno);
274
}
275
#endif
276
277
static  int do_nodename (const char *nodename, struct addrinfo *ai,
278
    const struct addrinfo *hints);
279
280
int
281
getaddrinfo (const char *nodename, const char *servname,
282
  const struct addrinfo *hints, struct addrinfo **res)
283
{
284
  int rval;
285
  struct servent *sp;
286
  struct addrinfo *ai = NULL;
287
  int port;
288
  const char *proto = NULL;
289
  int family, socktype, flags, protocol;
290
291
292
  /*
293
   * If no name is provide just return an error
294
   */
295
  if (nodename == NULL && servname == NULL)
296
    return (EAI_NONAME);
297
  
298
  ai = calloc(sizeof(struct addrinfo), 1);
299
  if (ai == NULL)
300
    return (EAI_MEMORY);
301
302
  /*
303
   * Copy default values from hints, if available
304
   */
305
  if (hints != NULL) {
306
    ai->ai_flags = hints->ai_flags;
307
    ai->ai_family = hints->ai_family;
308
    ai->ai_socktype = hints->ai_socktype;
309
    ai->ai_protocol = hints->ai_protocol;
310
311
    family = hints->ai_family;
312
    socktype = hints->ai_socktype;
313
    protocol = hints->ai_protocol;
314
    flags = hints->ai_flags;
315
316
    switch (family) {
317
    case AF_UNSPEC:
318
      switch (hints->ai_socktype) {
319
      case SOCK_STREAM:
320
        proto = "tcp";
321
        break;
322
      case SOCK_DGRAM:
323
        proto = "udp";
324
        break;
325
      }
326
      break;
327
    case AF_INET:
328
    case AF_INET6:
329
      switch (hints->ai_socktype) {
330
      case 0:
331
        break;
332
      case SOCK_STREAM:
333
        proto = "tcp";
334
        break;
335
      case SOCK_DGRAM:
336
        proto = "udp";
337
        break;
338
      case SOCK_RAW:
339
        break;
340
      default:
341
        return (EAI_SOCKTYPE);
342
      }
343
      break;
344
#ifdef  AF_LOCAL
345
    case AF_LOCAL:
346
      switch (hints->ai_socktype) {
347
      case 0:
348
        break;
349
      case SOCK_STREAM:
350
        break;
351
      case SOCK_DGRAM:
352
        break;
353
      default:
354
        return (EAI_SOCKTYPE);
355
      }
356
      break;
357
#endif
358
    default:
359
      return (EAI_FAMILY);
360
    }
361
  } else {
362
    protocol = 0;
363
    family = 0;
364
    socktype = 0;
365
    flags = 0;
366
  }
367
368
  rval = do_nodename(nodename, ai, hints);
369
  if (rval != 0) {
370
    freeaddrinfo(ai);
371
    return (rval);
372
  }
373
374
  /*
375
   * First, look up the service name (port) if it was
376
   * requested.  If the socket type wasn't specified, then
377
   * try and figure it out.
378
   */
379
  if (servname != NULL) {
380
    char *e;
381
382
    port = strtol(servname, &e, 10);
383
    if (*e == '\0') {
384
      if (socktype == 0)
385
        return (EAI_SOCKTYPE);
386
      if (port < 0 || port > 65535)
387
        return (EAI_SERVICE);
388
      port = htons((unsigned short) port);
389
    } else {
390
      sp = getservbyname(servname, proto);
391
      if (sp == NULL)
392
        return (EAI_SERVICE);
393
      port = sp->s_port;
394
      if (socktype == 0) {
395
        if (strcmp(sp->s_proto, "tcp") == 0)
396
          socktype = SOCK_STREAM;
397
        else if (strcmp(sp->s_proto, "udp") == 0)
398
          socktype = SOCK_DGRAM;
399
      }
400
    }
401
  } else
402
    port = 0;
403
404
  /*
405
   *
406
   * Set up the port number
407
   */
408
  if (ai->ai_family == AF_INET)
409
    ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
410
  else if (ai->ai_family == AF_INET6)
411
    ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
412
  *res = ai;
413
  return (0);
414
}
415
416
void
417
freeaddrinfo(struct addrinfo *ai)
418
{
419
  if (ai->ai_canonname != NULL)
420
  {
421
    free(ai->ai_canonname);
422
    ai->ai_canonname = NULL;
423
  }
424
  if (ai->ai_addr != NULL)
425
  {
426
    free(ai->ai_addr);
427
    ai->ai_addr = NULL;
428
  }
429
  free(ai);
430
  ai = NULL;
431
}
432
433
int
434
getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
435
  size_t hostlen, char *serv, size_t servlen, int flags)
436
{
437
  struct hostent *hp;
438
439
  if (sa->sa_family != AF_INET)
440
    return (EAI_FAMILY);
441
  hp = gethostbyaddr(
442
      (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
443
      4, AF_INET);
444
  if (hp == NULL) {
445
    if (h_errno == TRY_AGAIN)
446
      return (EAI_AGAIN);
447
    else
448
      return (EAI_FAIL);
449
  }
450
  if (host != NULL && hostlen > 0)
451
    strlcpy(host, hp->h_name, hostlen);
452
  return (0);
453
}
454
455
char *
456
gai_strerror(int ecode)
457
{
458
  if (ecode < 0 || ecode > EAI_MAX)
459
    ecode = EAI_MAX;
460
  return ai_errlist[ecode];
461
}
462
463
static int
464
do_nodename(
465
  const char *nodename,
466
  struct addrinfo *ai,
467
  const struct addrinfo *hints)
468
{
469
  struct hostent *hp = NULL;
470
  struct sockaddr_in *sockin;
471
  struct sockaddr_in6 *sockin6;
472
  int errval;
473
474
  ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
475
  if (ai->ai_addr == NULL)
476
    return (EAI_MEMORY);
477
478
  /*
479
   * For an empty node name just use the wildcard.
480
   * NOTE: We need to assume that the address family is
481
   * set elsewhere so that we can set the appropriate wildcard
482
   */
483
  if (nodename == NULL) {
484
    if (ai->ai_family == AF_INET)
485
    {
486
      ai->ai_addrlen = sizeof(struct sockaddr_in);
487
      sockin = (struct sockaddr_in *)ai->ai_addr;
488
      sockin->sin_family = (short) ai->ai_family;
489
      sockin->sin_addr.s_addr = htonl(INADDR_ANY);
490
    }
491
    else
492
    {
493
      ai->ai_addrlen = sizeof(struct sockaddr_in6);
494
      sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
495
      sockin6->sin6_family = (short) ai->ai_family;
496
      /*
497
       * we have already zeroed out the address
498
       * so we don't actually need to do this
499
       * This assignment is causing problems so
500
       * we don't do what this would do.
501
       sockin6->sin6_addr = in6addr_any;
502
       */
503
    }
504
#ifdef ISC_PLATFORM_HAVESALEN
505
    ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
506
#endif
507
508
    return (0);
509
  }
510
511
  /*
512
   * See if we have an IPv6 address
513
   */
514
  if(strchr(nodename, ':') != NULL) {
515
    if (inet_pton(AF_INET6, nodename,
516
        &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
517
      ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
518
      ai->ai_family = AF_INET6;
519
      ai->ai_addrlen = sizeof(struct sockaddr_in6);
520
      return (0);
521
    }
522
  }
523
524
  /*
525
   * See if we have an IPv4 address
526
   */
527
  if (inet_pton(AF_INET, nodename,
528
      &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
529
    ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
530
    ai->ai_family = AF_INET;
531
    ai->ai_addrlen = sizeof(struct sockaddr_in);
532
    return (0);
533
  }
534
535
  /*
536
   * If the numeric host flag is set, don't attempt resolution
537
   */
538
  if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
539
    return (EAI_NONAME);
540
541
  /*
542
   * Look for a name
543
   */
544
545
  errval = DNSlookup_name(nodename, AF_INET, &hp);
546
547
  if (hp == NULL) {
548
    if (errval == TRY_AGAIN || errval == EAI_AGAIN)
549
      return (EAI_AGAIN);
550
    else if (errval == EAI_NONAME) {
551
      if (inet_pton(AF_INET, nodename,
552
          &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
553
        ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
554
        ai->ai_family = AF_INET;
555
        ai->ai_addrlen = sizeof(struct sockaddr_in);
556
        return (0);
557
      }
558
      return (errval);
559
    }
560
    else
561
    {
562
      return (errval);
563
    }
564
  }
565
  ai->ai_family = hp->h_addrtype;
566
  ai->ai_addrlen = sizeof(struct sockaddr);
567
  sockin = (struct sockaddr_in *)ai->ai_addr;
568
  memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
569
  ai->ai_addr->sa_family = hp->h_addrtype;
570
#ifdef ISC_PLATFORM_HAVESALEN
571
  ai->ai_addr->sa_len = sizeof(struct sockaddr);
572
#endif
573
  if (hints != NULL && (hints->ai_flags & AI_CANONNAME))
574
    ai->ai_canonname = estrdup(hp->h_name);
575
  return (0);
576
}
577
578
#endif /* !ISC_PLATFORM_HAVEIPV6 */