Coverage Report

Created: 2026-05-14 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/proftpd/src/netaddr.c
Line
Count
Source
1
/*
2
 * ProFTPD - FTP server daemon
3
 * Copyright (c) 2003-2026 The ProFTPD Project team
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
17
 *
18
 * As a special exemption, The ProFTPD Project team and other respective
19
 * copyright holders give permission to link this program with OpenSSL, and
20
 * distribute the resulting executable, without including the source code for
21
 * OpenSSL in the source distribution.
22
 */
23
24
/* Network address routines */
25
26
#include "conf.h"
27
28
#if HAVE_NET_IF_H
29
# include <net/if.h>
30
#endif
31
#if HAVE_IFADDRS_H
32
# include <ifaddrs.h>
33
#endif
34
35
/* Define an IPv4 equivalent of the IN6_IS_ADDR_LOOPBACK macro. */
36
#undef IN_IS_ADDR_LOOPBACK
37
#define IN_IS_ADDR_LOOPBACK(a) \
38
0
  ((((unsigned long int) ntohl((a)->s_addr)) & 0xff000000) == 0x7f000000)
39
40
static pr_netaddr_t sess_local_addr;
41
static int have_sess_local_addr = FALSE;
42
43
static pr_netaddr_t sess_remote_addr;
44
static char sess_remote_name[PR_TUNABLE_BUFFER_SIZE];
45
static int have_sess_remote_addr = FALSE;
46
47
/* Do reverse DNS lookups? */
48
static int reverse_dns = 1;
49
50
/* Use IPv6? */
51
#ifdef PR_USE_IPV6
52
static int use_ipv6 = TRUE;
53
#else
54
static int use_ipv6 = FALSE;
55
#endif /* PR_USE_IPV6 */
56
57
static char localaddr_str[PR_TUNABLE_BUFFER_SIZE];
58
static int have_localaddr_str = FALSE;
59
60
static pool *netaddr_pool = NULL;
61
static pr_table_t *netaddr_iptab = NULL;
62
static pr_table_t *netaddr_dnstab = NULL;
63
64
static const char *trace_channel = "dns";
65
66
/* Netaddr cache management */
67
0
static array_header *netaddr_dnscache_get(pool *p, const char *ip_str) {
68
0
  array_header *res = NULL;
69
70
0
  if (netaddr_dnstab != NULL) {
71
0
    const void *v;
72
73
0
    v = pr_table_get(netaddr_dnstab, ip_str, NULL);
74
0
    if (v != NULL) {
75
0
      res = (array_header *) v;
76
77
0
      pr_trace_msg(trace_channel, 4,
78
0
        "using %d DNS %s from netaddr DNS cache for IP address '%s'",
79
0
        res->nelts, res->nelts != 1 ? "names" : "name", ip_str);
80
81
0
      if (p) {
82
        /* If the caller provided a pool, return a copy of the array. */
83
0
        return copy_array_str(p, res);
84
0
      }
85
86
0
      return res;
87
0
    }
88
0
  }
89
90
0
  pr_trace_msg(trace_channel, 12,
91
0
    "no DNS names found in netaddr DNS cache for IP address '%s'", ip_str);
92
0
  errno = ENOENT;
93
0
  return NULL;
94
0
}
95
96
0
static void netaddr_dnscache_set(const char *ip_str, const char *dns_name) {
97
0
  if (netaddr_dnstab != NULL) {
98
0
    void *v = NULL;
99
0
    array_header *res = NULL;
100
0
    int add_list = FALSE;
101
102
0
    res = netaddr_dnscache_get(NULL, ip_str);
103
0
    if (res == NULL) {
104
      /* No existing entries for this IP address yet. */
105
0
      res = make_array(netaddr_pool, 1, sizeof(char *));
106
0
      add_list = TRUE;
107
108
0
    } else {
109
0
      register unsigned int i;
110
0
      char **names;
111
112
      /* Check for duplicates. */
113
0
      names = res->elts;
114
0
      for (i = 0; i < res->nelts; i++) {
115
0
        if (names[i] != NULL) {
116
0
          if (strcmp(names[i], dns_name) == 0) {
117
0
            pr_trace_msg(trace_channel, 5,
118
0
              "DNS name '%s' for IP address '%s' already stashed in the "
119
0
              "netaddr DNS cache", dns_name, ip_str);
120
0
            return;
121
0
          }
122
0
        }
123
0
      }
124
0
    }
125
126
0
    *((char **) push_array(res)) = pstrdup(netaddr_pool, dns_name);
127
0
    v = res;
128
129
0
    if (add_list == TRUE) {
130
0
      if (pr_table_add(netaddr_dnstab, pstrdup(netaddr_pool, ip_str), v,
131
0
          sizeof(array_header *)) < 0) {
132
0
        pr_trace_msg(trace_channel, 3,
133
0
          "error adding DNS name '%s' for IP address '%s' to the netaddr "
134
0
          "DNS cache: %s", dns_name, ip_str, strerror(errno));
135
136
0
      } else {
137
0
        pr_trace_msg(trace_channel, 5,
138
0
          "stashed DNS name '%s' for IP address '%s' in the netaddr DNS cache",
139
0
          dns_name, ip_str);
140
0
      }
141
142
0
    } else {
143
0
      pr_trace_msg(trace_channel, 5,
144
0
        "stashed DNS name '%s' for IP address '%s' in the netaddr DNS cache",
145
0
        dns_name, ip_str);
146
0
    }
147
0
  }
148
0
}
149
150
0
static pr_netaddr_t *netaddr_ipcache_get(pool *p, const char *name) {
151
0
  pr_netaddr_t *res = NULL;
152
153
0
  if (netaddr_iptab != NULL) {
154
0
    const void *v;
155
156
0
    v = pr_table_get(netaddr_iptab, name, NULL);
157
0
    if (v != NULL) {
158
0
      res = (pr_netaddr_t *) v;
159
0
      pr_trace_msg(trace_channel, 4,
160
0
        "using IP address '%s' from netaddr IP cache for name '%s'",
161
0
        pr_netaddr_get_ipstr(res), name);
162
163
      /* We return a copy of the cache's netaddr_t, if the caller provided
164
       * a pool for duplication.
165
       */
166
0
      if (p != NULL) {
167
0
        pr_netaddr_t *dup_res = NULL;
168
169
0
        dup_res = pr_netaddr_dup(p, res);
170
0
        if (dup_res == NULL) {
171
0
          pr_log_debug(DEBUG0, "error duplicating address for name '%s' "
172
0
            "from cache: %s", name, strerror(errno));
173
0
        }
174
175
0
        return dup_res;
176
0
      }
177
178
0
      return res;
179
0
    }
180
0
  }
181
182
0
  pr_trace_msg(trace_channel, 2,
183
0
    "no IP address found in netaddr IP cache for name '%s'", name);
184
0
  errno = ENOENT;
185
0
  return NULL;
186
0
}
187
188
0
static int netaddr_ipcache_set(const char *name, const pr_netaddr_t *na) {
189
0
  if (netaddr_iptab != NULL) {
190
0
    int count = 0;
191
0
    void *v = NULL;
192
193
    /* We store an internal copy of the netaddr_t in the cache. */
194
0
    v = pr_netaddr_dup(netaddr_pool, na);
195
0
    if (v == NULL) {
196
0
      return -1;
197
0
    }
198
199
0
    count = pr_table_exists(netaddr_iptab, name);
200
0
    if (count <= 0) {
201
0
      if (pr_table_add(netaddr_iptab, pstrdup(netaddr_pool, name), v,
202
0
          sizeof(pr_netaddr_t *)) < 0) {
203
0
        pr_trace_msg(trace_channel, 3,
204
0
          "error adding IP address '%s' for name '%s' to the netaddr "
205
0
          "IP cache: %s", pr_netaddr_get_ipstr(na), name,
206
0
          strerror(errno));
207
208
0
      } else {
209
0
        pr_trace_msg(trace_channel, 5,
210
0
          "stashed IP address '%s' for name '%s' in the netaddr IP cache",
211
0
          pr_netaddr_get_ipstr(v), name);
212
0
      }
213
214
0
    } else {
215
0
      if (pr_table_set(netaddr_iptab, pstrdup(netaddr_pool, name), v,
216
0
          sizeof(pr_netaddr_t *)) < 0) {
217
0
        pr_trace_msg(trace_channel, 3,
218
0
          "error setting IP address '%s' for name '%s' in the netaddr "
219
0
          "IP cache: %s", pr_netaddr_get_ipstr(na), name, strerror(errno));
220
0
      }
221
0
    }
222
0
  }
223
224
0
  return 0;
225
0
}
226
227
/* Provide replacements for needed functions. */
228
229
#if !defined(HAVE_GETNAMEINFO) || defined(PR_USE_GETNAMEINFO)
230
int pr_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
231
    size_t hostlen, char *serv, size_t servlen, int flags) {
232
233
  struct sockaddr_in *sai = (struct sockaddr_in *) sa;
234
235
  if (!sai || sai->sin_family != AF_INET)
236
    return EAI_FAMILY;
237
238
  if (serv != NULL && servlen > (size_t) 1)
239
    pr_snprintf(serv, servlen, "%lu", (unsigned long) ntohs(sai->sin_port));
240
241
  if (host != NULL && hostlen > (size_t) 1) {
242
    struct hostent *he = NULL;
243
244
    if ((flags & NI_NUMERICHOST) == 0 &&
245
        (he = gethostbyaddr((const char *) &(sai->sin_addr),
246
          sizeof(sai->sin_addr), AF_INET)) != NULL &&
247
        he->h_name != NULL &&
248
        *he->h_name != 0) {
249
250
      if (strlen(he->h_name) >= hostlen)
251
          goto handle_numeric_ip;
252
      sstrncpy(host, he->h_name, hostlen);
253
254
    } else {
255
      char *ipstr = NULL;
256
257
      handle_numeric_ip:
258
      ipstr = inet_ntoa(sai->sin_addr);
259
      if (ipstr == NULL)
260
        return EAI_SYSTEM;
261
262
      if (strlen(ipstr) >= hostlen)
263
        return EAI_FAIL;
264
265
      sstrncpy(host, ipstr, hostlen);
266
    }
267
  }
268
269
  return 0;
270
}
271
#endif /* HAVE_GETNAMEINFO or PR_USE_GETNAMEINFO */
272
273
#if !defined(HAVE_GETADDRINFO) || defined(PR_USE_GETADDRINFO)
274
int pr_getaddrinfo(const char *node, const char *service,
275
    const struct addrinfo *hints, struct addrinfo **res) {
276
  struct addrinfo *ans = NULL;
277
  struct sockaddr_in *saddr = NULL;
278
  const char *proto_name = "tcp";
279
  int socktype = SOCK_STREAM;
280
  unsigned short port = 0;
281
282
  if (res == NULL) {
283
    return EAI_FAIL;
284
  }
285
286
  *res = NULL;
287
288
  ans = malloc(sizeof(struct addrinfo));
289
  if (ans == NULL) {
290
    return EAI_MEMORY;
291
  }
292
293
  saddr = malloc(sizeof(struct sockaddr_in));
294
  if (saddr == NULL) {
295
    free(ans);
296
    return EAI_MEMORY;
297
  }
298
299
  ans->ai_family = AF_INET;
300
  ans->ai_addrlen = sizeof *saddr;
301
  ans->ai_addr = (struct sockaddr *) saddr;
302
  ans->ai_next = NULL;
303
  memset(saddr, 0, sizeof(*saddr));
304
  saddr->sin_family = AF_INET;
305
306
  if (hints != NULL) {
307
    struct protoent *pe = NULL;
308
309
    if ((pe = getprotobynumber(hints->ai_protocol)) != NULL &&
310
         pe->p_name != NULL &&
311
         *pe->p_name != 0)
312
      proto_name = pe->p_name;
313
314
    if (hints->ai_socktype != 0) {
315
      socktype = hints->ai_socktype;
316
317
    } else if (strncasecmp(proto_name, "udp", 4) == 0) {
318
      socktype = SOCK_DGRAM;
319
    }
320
  }
321
322
  if (service != NULL) {
323
    struct servent *se = NULL;
324
325
    if ((se = getservbyname(service, proto_name)) != NULL &&
326
        se->s_port > 0) {
327
      port = se->s_port;
328
329
    } else if ((port = (unsigned short) strtoul(service, NULL, 0)) <= 0 ||
330
        port > 65535) {
331
      port = 0;
332
    }
333
  }
334
335
  if (hints != NULL &&
336
      (hints->ai_flags & AI_PASSIVE) != 0)
337
    saddr->sin_addr.s_addr = htonl(INADDR_ANY);
338
339
  if (node != NULL) {
340
    struct hostent *he = NULL;
341
342
    if ((he = gethostbyname(node)) != NULL &&
343
         he->h_addr_list != NULL &&
344
         he->h_addr_list[0] != NULL &&
345
         he->h_length > 0 &&
346
         he->h_length <= (int) sizeof(saddr->sin_addr))
347
      memcpy(&saddr->sin_addr, he->h_addr_list[0], he->h_length);
348
  }
349
350
  ans->ai_socktype = socktype;
351
  saddr->sin_port = htons(port);
352
  *res = ans;
353
354
  return 0;
355
}
356
357
void pr_freeaddrinfo(struct addrinfo *ai) {
358
  if (ai == NULL) {
359
    return;
360
  }
361
362
  if (ai->ai_addr != NULL) {
363
    free(ai->ai_addr);
364
    ai->ai_addr = NULL;
365
  }
366
367
  free(ai);
368
}
369
#endif /* HAVE_GETADDRINFO or PR_USE_GETADDRINFO */
370
371
#if !defined(HAVE_INET_NTOP)
372
const char *pr_inet_ntop(int af, const void *src, char *dst, size_t len) {
373
  char *res;
374
375
  if (af != AF_INET) {
376
    errno = EAFNOSUPPORT;
377
    return NULL;
378
  }
379
380
  res = inet_ntoa(*((struct in_addr *) src));
381
  if (res == NULL)
382
    return NULL;
383
384
  memcpy(dst, res, len);
385
  return dst;
386
}
387
#endif /* !HAVE_INET_NTOP */
388
389
#if !defined(HAVE_INET_PTON)
390
int pr_inet_pton(int af, const char *src, void *dst) {
391
  unsigned long res;
392
393
  if (af != AF_INET) {
394
    errno = EAFNOSUPPORT;
395
    return -1;
396
  }
397
398
  /* inet_aton(3) would be better. However, it is not ubiquitous.  */
399
  res = inet_addr(src);
400
  if (res == INADDR_NONE ||
401
      res == 0)
402
    return 0;
403
404
  memcpy(dst, &res, sizeof(res));
405
  return 1;
406
}
407
#endif /* !HAVE_INET_PTON */
408
409
0
static void *get_v4inaddr(const pr_netaddr_t *na) {
410
411
  /* This function is specifically for IPv4 clients (when gethostbyname2(2) is
412
   * present) that have an IPv4-mapped IPv6 address, when performing reverse
413
   * DNS checks.  This function is called iff the given netaddr object is
414
   * indeed an IPv4-mapped IPv6 address.  IPv6 address have 128 bits in their
415
   * sin6_addr field.  For IPv4-mapped IPv6 addresses, the relevant 32 bits
416
   * are the last of those 128 bits (or, alternatively, the last 4 bytes of
417
   * those 16 bytes); hence the read of 12 bytes after the start of the
418
   * sin6_addr pointer.
419
   */
420
421
0
  return (((char *) pr_netaddr_get_inaddr(na)) + 12);
422
0
}
423
424
/* Validate anything returned from the 'outside', since it's untrusted
425
 * information.
426
 */
427
0
char *pr_netaddr_validate_dns_str(char *buf) {
428
0
  char *p;
429
430
0
  if (buf == NULL) {
431
0
    errno = EINVAL;
432
0
    return NULL;
433
0
  }
434
435
  /* Validate anything returned from a DNS. */
436
0
  for (p = buf; p && *p; p++) {
437
438
    /* Per RFC requirements, these are all that are valid from a DNS. */
439
0
    if (!PR_ISALNUM(*p) &&
440
0
        *p != '.' &&
441
0
        *p != '-'
442
0
#ifdef PR_USE_IPV6
443
0
        && *p != ':'
444
0
#endif /* PR_USE_IPV6 */
445
0
        ) {
446
447
      /* We set it to _ because we know that's an invalid, yet safe, option
448
       * for a DNS entry.
449
       */
450
0
      *p = '_';
451
0
    }
452
0
  }
453
454
0
  return buf;
455
0
}
456
457
0
int pr_netaddr_set_reverse_dns(int enable) {
458
0
  int old_enable = reverse_dns;
459
0
  reverse_dns = enable;
460
0
  return old_enable;
461
0
}
462
463
0
pr_netaddr_t *pr_netaddr_alloc(pool *p) {
464
0
  if (p == NULL) {
465
0
    errno = EINVAL;
466
0
    return NULL;
467
0
  }
468
469
0
  return pcalloc(p, sizeof(pr_netaddr_t));
470
0
}
471
472
0
void pr_netaddr_clear(pr_netaddr_t *na) {
473
0
  if (na == NULL) {
474
0
    return;
475
0
  }
476
477
0
  memset(na, 0, sizeof(pr_netaddr_t));
478
0
}
479
480
0
pr_netaddr_t *pr_netaddr_dup(pool *p, const pr_netaddr_t *na) {
481
0
  pr_netaddr_t *dup_na;
482
483
0
  if (p == NULL ||
484
0
      na == NULL) {
485
0
    errno = EINVAL;
486
0
    return NULL;
487
0
  }
488
489
0
  dup_na = pr_netaddr_alloc(p);
490
491
0
  if (pr_netaddr_set_family(dup_na, pr_netaddr_get_family(na)) < 0) {
492
0
    return NULL;
493
0
  }
494
495
0
  pr_netaddr_set_sockaddr(dup_na, pr_netaddr_get_sockaddr(na));
496
497
0
  if (na->na_have_ipstr) {
498
0
    sstrncpy(dup_na->na_ipstr, na->na_ipstr, sizeof(dup_na->na_ipstr));
499
0
    dup_na->na_have_ipstr = 1;
500
0
  }
501
502
0
  if (na->na_have_dnsstr) {
503
0
    sstrncpy(dup_na->na_dnsstr, na->na_dnsstr, sizeof(dup_na->na_dnsstr));
504
0
    dup_na->na_have_dnsstr = 1;
505
0
  }
506
507
0
  return dup_na;
508
0
}
509
510
static pr_netaddr_t *get_addr_by_ip(pool *p, const char *name,
511
0
    array_header **addrs, unsigned int flags) {
512
0
  struct sockaddr_in v4;
513
0
  pr_netaddr_t *na = NULL;
514
0
  int res;
515
516
0
#ifdef PR_USE_IPV6
517
0
  if (use_ipv6 == TRUE) {
518
0
    struct sockaddr_in6 v6;
519
0
    memset(&v6, 0, sizeof(v6));
520
0
    v6.sin6_family = AF_INET6;
521
522
# ifdef SIN6_LEN
523
    v6.sin6_len = sizeof(struct sockaddr_in6);
524
# endif /* SIN6_LEN */
525
526
0
    res = pr_inet_pton(AF_INET6, name, &v6.sin6_addr);
527
0
    if (res > 0) {
528
0
      na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
529
0
      pr_netaddr_set_family(na, AF_INET6);
530
0
      pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v6);
531
0
      if (addrs != NULL) {
532
0
        *addrs = NULL;
533
0
      }
534
535
0
      pr_trace_msg(trace_channel, 7, "'%s' resolved to IPv6 address %s", name,
536
0
        pr_netaddr_get_ipstr(na));
537
538
0
      if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_CACHE)) {
539
0
        if (netaddr_ipcache_set(name, na) < 0) {
540
0
          pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
541
0
            name, strerror(errno));
542
0
        }
543
544
0
        if (netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na) < 0) {
545
0
          pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
546
0
            pr_netaddr_get_ipstr(na), strerror(errno));
547
0
        }
548
0
      }
549
550
0
      return na;
551
0
    }
552
0
  }
553
0
#endif /* PR_USE_IPV6 */
554
555
0
  memset(&v4, 0, sizeof(v4));
556
0
  v4.sin_family = AF_INET;
557
558
# ifdef SIN_LEN
559
  v4.sin_len = sizeof(struct sockaddr_in);
560
# endif /* SIN_LEN */
561
562
0
  res = pr_inet_pton(AF_INET, name, &v4.sin_addr);
563
0
  if (res > 0) {
564
0
    na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
565
0
    pr_netaddr_set_family(na, AF_INET);
566
0
    pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v4);
567
0
    if (addrs != NULL) {
568
0
      *addrs = NULL;
569
0
    }
570
571
0
    pr_trace_msg(trace_channel, 7, "'%s' resolved to IPv4 address %s", name,
572
0
      pr_netaddr_get_ipstr(na));
573
574
0
    if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_DNS)) {
575
0
      if (netaddr_ipcache_set(name, na) < 0) {
576
0
        pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s", name,
577
0
          strerror(errno));
578
0
      }
579
580
      /* Avoid duplicates. */
581
0
      if (strcmp(name, pr_netaddr_get_ipstr(na)) != 0) {
582
0
        if (netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na) < 0) {
583
0
          pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
584
0
            pr_netaddr_get_ipstr(na), strerror(errno));
585
0
        }
586
0
      }
587
0
    }
588
589
0
    return na;
590
0
  }
591
592
0
  return NULL;
593
0
}
594
595
static pr_netaddr_t *get_addr_by_name(pool *p, const char *name,
596
0
    array_header **addrs, unsigned int flags) {
597
0
  pr_netaddr_t *na = NULL;
598
0
  int res, xerrno;
599
0
  struct addrinfo hints, *info = NULL;
600
601
0
  memset(&hints, 0, sizeof(hints));
602
0
  hints.ai_family = AF_INET;
603
0
  hints.ai_socktype = SOCK_STREAM;
604
0
  hints.ai_protocol = IPPROTO_TCP;
605
0
  info = NULL;
606
607
0
  xerrno = errno;
608
0
  pr_trace_msg(trace_channel, 7,
609
0
    "attempting to resolve '%s' to IPv4 address via DNS", name);
610
0
  errno = xerrno;
611
0
  res = pr_getaddrinfo(name, NULL, &hints, &info);
612
0
  if (res != 0) {
613
0
    xerrno = errno;
614
615
0
    if (res != EAI_SYSTEM) {
616
0
#ifdef PR_USE_IPV6
617
0
      if (use_ipv6 == TRUE) {
618
0
        pr_trace_msg(trace_channel, 7,
619
0
          "unable to resolve '%s' to an IPv4 address: %s", name,
620
0
          pr_gai_strerror(res));
621
622
0
        memset(&hints, 0, sizeof(hints));
623
0
        hints.ai_family = AF_INET6;
624
0
        hints.ai_socktype = SOCK_STREAM;
625
0
        hints.ai_protocol = IPPROTO_TCP;
626
0
        info = NULL;
627
628
0
        pr_trace_msg(trace_channel, 7,
629
0
          "attempting to resolve '%s' to IPv6 address via DNS", name);
630
0
        errno = xerrno;
631
0
        res = pr_getaddrinfo(name, NULL, &hints, &info);
632
0
        xerrno = errno;
633
634
0
        if (res != 0) {
635
0
          if (res != EAI_SYSTEM) {
636
0
            pr_trace_msg(trace_channel, 5,
637
0
              "unable to resolve '%s' to an IPv6 address: %s", name,
638
0
              pr_gai_strerror(res));
639
640
0
            if (res == EAI_NODATA ||
641
0
                res == EAI_NONAME) {
642
0
              xerrno = ENOENT;
643
0
# if defined(EAFNOSUPPORT)
644
0
            } else if (res == EAI_FAMILY) {
645
0
              xerrno = EAFNOSUPPORT;
646
0
# endif /* EAFNOSUPPORT */
647
0
            }
648
649
0
          } else {
650
0
            pr_trace_msg(trace_channel, 1,
651
0
              "IPv6 getaddrinfo '%s' system error: [%d] %s", name,
652
0
              xerrno, strerror(xerrno));
653
0
          }
654
0
        }
655
656
0
      } else {
657
0
        const char *errstr;
658
659
0
        errstr = pr_gai_strerror(res);
660
0
        pr_trace_msg(trace_channel, 1, "IPv4 getaddrinfo '%s' error: %s",
661
0
          name, errstr);
662
663
0
        if (res == EAI_NODATA ||
664
0
            res == EAI_NONAME) {
665
0
          xerrno = ENOENT;
666
0
# if defined(EAFNOSUPPORT)
667
0
        } else if (res == EAI_FAMILY) {
668
0
          xerrno = EAFNOSUPPORT;
669
0
# endif /* EAFNOSUPPORT */
670
0
        } else {
671
          /* Note that this is a hack, to deal with GNU/Linux custom
672
           * gai_strerror(3) values which are not exported in the <netdb.h>
673
           * header by default.
674
           */
675
0
          if (strcmp(errstr, "Address family for hostname not supported") == 0) {
676
0
            xerrno = EAFNOSUPPORT;
677
0
          }
678
0
        }
679
0
      }
680
#else
681
      pr_trace_msg(trace_channel, 1, "IPv4 getaddrinfo '%s' error: %s",
682
        name, pr_gai_strerror(res));
683
      if (res == EAI_NODATA ||
684
          res == EAI_NONAME) {
685
        xerrno = ENOENT;
686
# if defined(EAFNOSUPPORT)
687
      } else if (res == EAI_FAMILY) {
688
        xerrno = EAFNOSUPPORT;
689
# endif /* EAFNOSUPPORT */
690
      }
691
#endif /* PR_USE_IPV6 */
692
693
0
    } else {
694
0
      pr_trace_msg(trace_channel, 1,
695
0
        "IPv4 getaddrinfo '%s' system error: [%d] %s", name,
696
0
        xerrno, strerror(xerrno));
697
0
    }
698
699
0
    if (res != 0) {
700
0
      errno = xerrno;
701
0
      return NULL;
702
0
    }
703
0
  }
704
705
0
  if (info != NULL) {
706
0
    na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
707
708
    /* Copy the first returned addr into na, as the return value. */
709
0
    pr_netaddr_set_family(na, info->ai_family);
710
0
    pr_netaddr_set_sockaddr(na, info->ai_addr);
711
712
0
    pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
713
0
      info->ai_family == AF_INET ? "IPv4" : "IPv6",
714
0
      pr_netaddr_get_ipstr(na));
715
716
0
    if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_DNS)) {
717
0
      if (netaddr_ipcache_set(name, na) < 0) {
718
0
        pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s", name,
719
0
          strerror(errno));
720
0
      }
721
722
0
      if (netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na) < 0) {
723
0
        pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
724
0
          pr_netaddr_get_ipstr(na), strerror(errno));
725
0
      }
726
0
    }
727
728
0
    if (addrs != NULL) {
729
0
      struct addrinfo *next_info = NULL;
730
731
      /* Copy any other addrs into the list. */
732
0
      if (*addrs == NULL) {
733
0
        *addrs = make_array(p, 0, sizeof(pr_netaddr_t *));
734
0
      }
735
736
0
      next_info = info->ai_next;
737
0
      while (next_info != NULL) {
738
0
        pr_netaddr_t **elt;
739
740
0
        pr_signals_handle();
741
0
        elt = push_array(*addrs);
742
743
0
        *elt = pcalloc(p, sizeof(pr_netaddr_t));
744
0
        pr_netaddr_set_family(*elt, next_info->ai_family);
745
0
        pr_netaddr_set_sockaddr(*elt, next_info->ai_addr);
746
747
0
        pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
748
0
          next_info->ai_family == AF_INET ? "IPv4" : "IPv6",
749
0
          pr_netaddr_get_ipstr(*elt));
750
751
0
        next_info = next_info->ai_next;
752
0
      }
753
0
    }
754
755
0
    pr_freeaddrinfo(info);
756
0
  }
757
758
0
#ifdef PR_USE_IPV6
759
0
  if (use_ipv6 == TRUE &&
760
0
      addrs != NULL) {
761
    /* Do the call again, this time for IPv6 addresses.
762
     *
763
     * We make two separate getaddrinfo(3) calls, rather than one
764
     * with a hint of AF_UNSPEC, because of certain bugs where the use
765
     * of AF_UNSPEC does not function as advertised.  (I suspect this
766
     * bug was caused by proftpd's calling pattern, but as I could
767
     * not track it down, and as there are reports of AF_UNSPEC not
768
     * being as fast as AF_INET/AF_INET6, it just seemed easier to
769
     * do it this way.)
770
     */
771
772
0
    memset(&hints, 0, sizeof(hints));
773
0
    hints.ai_family = AF_INET6;
774
0
    hints.ai_socktype = SOCK_STREAM;
775
0
    hints.ai_protocol = IPPROTO_TCP;
776
0
    info = NULL;
777
778
0
    pr_trace_msg(trace_channel, 7,
779
0
      "attempting to resolve '%s' to IPv6 address via DNS", name);
780
0
    res = pr_getaddrinfo(name, NULL, &hints, &info);
781
0
    xerrno = errno;
782
783
0
    if (res != 0) {
784
0
      if (res != EAI_SYSTEM) {
785
0
        pr_trace_msg(trace_channel, 1, "IPv6 getaddrinfo '%s' error: %s",
786
0
          name, pr_gai_strerror(res));
787
788
0
      } else {
789
0
        pr_trace_msg(trace_channel, 1,
790
0
          "IPv6 getaddrinfo '%s' system error: [%d] %s", name,
791
0
          xerrno, strerror(xerrno));
792
0
      }
793
794
0
    } else {
795
      /* We may have already looked up an IPv6 address as the first
796
       * address; we don't want to have duplicate addresses in the
797
       * returned list of additional addresses.
798
       */
799
0
      if (info != NULL) {
800
0
        struct addrinfo *next_info = NULL;
801
802
        /* Copy any other addrs into the list. */
803
0
        if (*addrs == NULL) {
804
0
          *addrs = make_array(p, 0, sizeof(pr_netaddr_t *));
805
0
        }
806
807
        /* Note that for this subsequent IPv6 lookup, we need to treat the
808
         * first struct addrinfo as an "additional" record, unlike our handling
809
         * of IPv4 results.  Failure to do so means we might miss some IPv6
810
         * addresses; see Bug#4428.
811
         */
812
0
        next_info = info;
813
0
        while (next_info != NULL) {
814
0
          pr_netaddr_t **elt;
815
816
0
          pr_signals_handle();
817
0
          elt = push_array(*addrs);
818
819
0
          *elt = pcalloc(p, sizeof(pr_netaddr_t));
820
0
          pr_netaddr_set_family(*elt, next_info->ai_family);
821
0
          pr_netaddr_set_sockaddr(*elt, next_info->ai_addr);
822
823
0
          pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
824
0
            next_info->ai_family == AF_INET ? "IPv4" : "IPv6",
825
0
            pr_netaddr_get_ipstr(*elt));
826
827
0
          next_info = next_info->ai_next;
828
0
        }
829
830
0
        pr_freeaddrinfo(info);
831
0
      }
832
0
    }
833
0
  }
834
0
#endif /* PR_USE_IPV6 */
835
836
0
  return na;
837
0
}
838
839
static pr_netaddr_t *get_addr_by_device(pool *p, const char *name,
840
0
    array_header **addrs, unsigned int flags) {
841
0
#ifdef HAVE_GETIFADDRS
842
0
  struct ifaddrs *ifaddr = NULL;
843
0
  pr_netaddr_t *na = NULL;
844
0
  int res, xerrno;
845
846
  /* Try to use the given name as a device/interface name, and see if we
847
   * can suss out the IP address(es) to use based on that.
848
   */
849
850
0
  res = getifaddrs(&ifaddr);
851
0
  if (res < 0) {
852
0
    xerrno = errno;
853
854
0
    pr_trace_msg(trace_channel, 1,
855
0
      "error retrieving interfaces via getifaddrs(3): %s", strerror(xerrno));
856
857
0
  } else {
858
0
    struct ifaddrs *ifa;
859
0
    int found_device = FALSE;
860
861
0
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
862
0
      pr_signals_handle();
863
864
      /* Watch out for null ifa_addr, as when a device does not have
865
       * an associated address (e.g. due to not be initialized).
866
       */
867
0
      if (ifa->ifa_addr == NULL) {
868
0
        continue;
869
0
      }
870
871
      /* We're only looking for addresses, not stats. */
872
0
      if (ifa->ifa_addr->sa_family != AF_INET
873
0
#ifdef PR_USE_IPV6
874
0
          && ifa->ifa_addr->sa_family != AF_INET6
875
0
#endif /* PR_USE_IPV6 */
876
0
         ) {
877
0
        continue;
878
0
      }
879
880
0
      if (strcmp(ifa->ifa_name, name) == 0) {
881
0
        if (found_device == FALSE) {
882
0
          na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
883
884
0
          pr_netaddr_set_family(na, ifa->ifa_addr->sa_family);
885
0
          pr_netaddr_set_sockaddr(na, ifa->ifa_addr);
886
887
0
          pr_trace_msg(trace_channel, 7,
888
0
            "resolved '%s' to interface with %s address %s", name,
889
0
            ifa->ifa_addr->sa_family == AF_INET ? "IPv4" : "IPv6",
890
0
            pr_netaddr_get_ipstr(na));
891
892
0
          found_device = TRUE;
893
894
          /* If the caller did not request additional addresses, then
895
           * return now.  Otherwise, we keep looking for the other
896
           * addresses bound to this interface.
897
           */
898
0
          if (addrs == NULL) {
899
0
            break;
900
0
          }
901
902
0
        } else {
903
0
          pr_netaddr_t **elt;
904
905
          /* We've already found the first match; this block happens
906
           * if the caller wants all of the addresses for this interface.
907
           */
908
909
0
          *addrs = make_array(p, 0, sizeof(pr_netaddr_t *));
910
0
          elt = push_array(*addrs);
911
912
0
          *elt = pcalloc(p, sizeof(pr_netaddr_t));
913
0
          pr_netaddr_set_family(*elt, ifa->ifa_addr->sa_family);
914
0
          pr_netaddr_set_sockaddr(*elt, ifa->ifa_addr);
915
916
0
          pr_trace_msg(trace_channel, 7,
917
0
            "resolved '%s' to interface with %s address %s", name,
918
0
            ifa->ifa_addr->sa_family == AF_INET ? "IPv4" : "IPv6",
919
0
            pr_netaddr_get_ipstr(*elt));
920
0
        }
921
0
      }
922
0
    }
923
924
0
    if (ifaddr != NULL) {
925
0
      freeifaddrs(ifaddr);
926
0
    }
927
928
0
    if (found_device) {
929
0
      return na;
930
0
    }
931
0
  }
932
933
0
  errno = ENOENT;
934
#else
935
  errno = ENOSYS;
936
#endif /* HAVE_GETIFADDRS */
937
938
0
  return NULL;
939
0
}
940
941
const pr_netaddr_t *pr_netaddr_get_addr2(pool *p, const char *name,
942
0
    array_header **addrs, unsigned int flags) {
943
0
  pr_netaddr_t *na = NULL;
944
0
  int xerrno = ENOENT;
945
946
0
  if (p == NULL ||
947
0
      name == NULL) {
948
0
    errno = EINVAL;
949
0
    return NULL;
950
0
  }
951
952
0
  pr_trace_msg(trace_channel, 10, "resolving name '%s' to IP address",
953
0
    name);
954
955
  /* First, check our cache to see if this name has already been
956
   * resolved.  We only want to use the cache, though, if the caller did not
957
   * provide the `addrs' pointer, indicating that the caller wants to know
958
   * about any additional addresses for the given name.  The netaddr cache
959
   * is a simple cache, hidden from callers, and thus is unable to populate
960
   * that `addrs' pointer if the name is in the cache.
961
   */
962
0
  if (addrs == NULL) {
963
0
    na = netaddr_ipcache_get(p, name);
964
0
    if (na != NULL) {
965
0
      return na;
966
0
    }
967
0
  }
968
969
  /* Attempt to translate the given name into a pr_netaddr_t using
970
   * pr_inet_pton() first.
971
   *
972
   * First, if IPv6 support is enabled, we try to translate the name using
973
   * pr_inet_pton(AF_INET6) on the hopes that the given string is a valid
974
   * representation of an IPv6 address.  If that fails, or if IPv6 support
975
   * is not enabled, we try with pr_inet_pton(AF_INET).  If that fails, we
976
   * assume that the given name is a DNS name, and we call pr_getaddrinfo().
977
   */
978
979
0
  na = get_addr_by_ip(p, name, addrs, flags);
980
0
  xerrno = errno;
981
982
0
  if (na != NULL) {
983
0
    return na;
984
0
  }
985
986
  /* If get_addr_by_ip() returns NULL, it means that name does not represent a
987
   * valid network address in the specified address family.  Usually,
988
   * this means that name is actually a DNS name, not an IP address
989
   * string.  So we treat it as a DNS name, and use getaddrinfo(3) to
990
   * resolve that name to its IP address(es) -- unless the EXCL_DNS flag
991
   * has been used, indicating that the caller does not want us resolving
992
   * DNS names.
993
   */
994
995
0
  if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_DNS)) {
996
0
    na = get_addr_by_name(p, name, addrs, flags);
997
0
    xerrno = errno;
998
999
0
    if (na != NULL) {
1000
0
      return na;
1001
0
    }
1002
0
  }
1003
1004
0
  if (flags & PR_NETADDR_GET_ADDR_FL_INCL_DEVICE) {
1005
0
    na = get_addr_by_device(p, name, addrs, flags);
1006
0
    xerrno = errno;
1007
1008
0
    if (na != NULL) {
1009
0
      return na;
1010
0
    }
1011
0
  }
1012
1013
0
  pr_trace_msg(trace_channel, 8, "failed to resolve '%s' to an IP address",
1014
0
    name);
1015
0
  errno = xerrno;
1016
0
  return NULL;
1017
0
}
1018
1019
const pr_netaddr_t *pr_netaddr_get_addr(pool *p, const char *name,
1020
0
    array_header **addrs) {
1021
0
  return pr_netaddr_get_addr2(p, name, addrs, 0);
1022
0
}
1023
1024
0
int pr_netaddr_get_family(const pr_netaddr_t *na) {
1025
0
  if (na == NULL) {
1026
0
    errno = EINVAL;
1027
0
    return -1;
1028
0
  }
1029
1030
0
  return na->na_family;
1031
0
}
1032
1033
0
int pr_netaddr_set_family(pr_netaddr_t *na, int family) {
1034
0
  if (!na) {
1035
0
    errno = EINVAL;
1036
0
    return -1;
1037
0
  }
1038
1039
  /* Set the family member of the appropriate sockaddr struct. */
1040
0
  switch (family) {
1041
0
    case AF_INET:
1042
0
      na->na_addr.v4.sin_family = AF_INET;
1043
0
      break;
1044
1045
0
#ifdef PR_USE_IPV6
1046
0
    case AF_INET6:
1047
0
      if (use_ipv6 == TRUE) {
1048
0
        na->na_addr.v6.sin6_family = AF_INET6;
1049
0
        break;
1050
0
      }
1051
0
#endif /* PR_USE_IPV6 */
1052
1053
0
    default:
1054
0
#ifdef EAFNOSUPPORT
1055
0
      errno = EAFNOSUPPORT;
1056
#else
1057
      errno = EINVAL;
1058
#endif
1059
0
      return -1;
1060
0
  }
1061
1062
0
  na->na_family = family;
1063
0
  return 0;
1064
0
}
1065
1066
0
size_t pr_netaddr_get_sockaddr_len(const pr_netaddr_t *na) {
1067
0
  if (na == NULL) {
1068
0
    errno = EINVAL;
1069
0
    return -1;
1070
0
  }
1071
1072
0
  switch (pr_netaddr_get_family(na)) {
1073
0
    case AF_INET:
1074
0
      return sizeof(struct sockaddr_in);
1075
1076
0
#if defined(PR_USE_IPV6)
1077
0
    case AF_INET6:
1078
0
      if (use_ipv6 == TRUE) {
1079
0
        return sizeof(struct sockaddr_in6);
1080
0
      }
1081
0
#endif /* PR_USE_IPV6 */
1082
0
  }
1083
1084
0
  errno = EPERM;
1085
0
  return -1;
1086
0
}
1087
1088
0
size_t pr_netaddr_get_inaddr_len(const pr_netaddr_t *na) {
1089
0
  if (na == NULL) {
1090
0
    errno = EINVAL;
1091
0
    return -1;
1092
0
  }
1093
1094
0
  switch (pr_netaddr_get_family(na)) {
1095
0
    case AF_INET:
1096
0
      return sizeof(struct in_addr);
1097
1098
0
#ifdef PR_USE_IPV6
1099
0
    case AF_INET6:
1100
0
      return sizeof(struct in6_addr);
1101
0
#endif /* PR_USE_IPV6 */
1102
0
  }
1103
1104
0
  errno = EPERM;
1105
0
  return -1;
1106
0
}
1107
1108
0
struct sockaddr *pr_netaddr_get_sockaddr(const pr_netaddr_t *na) {
1109
0
  if (na == NULL) {
1110
0
    errno = EINVAL;
1111
0
    return NULL;
1112
0
  }
1113
1114
0
  switch (pr_netaddr_get_family(na)) {
1115
0
    case AF_INET:
1116
0
      return (struct sockaddr *) &na->na_addr.v4;
1117
1118
0
#if defined(PR_USE_IPV6)
1119
0
    case AF_INET6:
1120
0
      if (use_ipv6 == TRUE) {
1121
0
        return (struct sockaddr *) &na->na_addr.v6;
1122
0
      }
1123
0
#endif /* PR_USE_IPV6 */
1124
0
  }
1125
1126
0
  errno = EPERM;
1127
0
  return NULL;
1128
0
}
1129
1130
0
int pr_netaddr_set_sockaddr(pr_netaddr_t *na, struct sockaddr *addr) {
1131
0
  if (na == NULL ||
1132
0
      addr == NULL) {
1133
0
    errno = EINVAL;
1134
0
    return -1;
1135
0
  }
1136
1137
0
  memset(&na->na_addr, 0, sizeof(na->na_addr));
1138
0
  switch (na->na_family) {
1139
0
    case AF_INET:
1140
0
      memcpy(&(na->na_addr.v4), addr, sizeof(struct sockaddr_in));
1141
0
      return 0;
1142
1143
0
#if defined(PR_USE_IPV6)
1144
0
    case AF_INET6:
1145
0
      if (use_ipv6 == TRUE) {
1146
0
        memcpy(&(na->na_addr.v6), addr, sizeof(struct sockaddr_in6));
1147
0
        return 0;
1148
0
      }
1149
0
#endif /* PR_USE_IPV6 */
1150
0
  }
1151
1152
0
  errno = EPERM;
1153
0
  return -1;
1154
0
}
1155
1156
0
int pr_netaddr_set_sockaddr_any(pr_netaddr_t *na) {
1157
0
  if (na == NULL) {
1158
0
    errno = EINVAL;
1159
0
    return -1;
1160
0
  }
1161
1162
0
  switch (pr_netaddr_get_family(na)) {
1163
0
    case AF_INET: {
1164
0
      struct in_addr in4addr_any;
1165
0
      in4addr_any.s_addr = htonl(INADDR_ANY);
1166
0
      na->na_addr.v4.sin_family = AF_INET;
1167
#ifdef SIN_LEN
1168
      na->na_addr.v4.sin_len = sizeof(struct sockaddr_in);
1169
#endif /* SIN_LEN */
1170
0
      memcpy(&na->na_addr.v4.sin_addr, &in4addr_any, sizeof(struct in_addr));
1171
0
      if (na->na_have_ipstr) {
1172
0
        memset(na->na_ipstr, '\0', sizeof(na->na_ipstr));
1173
0
        sstrncpy(na->na_ipstr, "0.0.0.0", sizeof(na->na_ipstr));
1174
0
      }
1175
0
      return 0;
1176
0
    }
1177
1178
0
#ifdef PR_USE_IPV6
1179
0
    case AF_INET6:
1180
0
      if (use_ipv6 == TRUE) {
1181
0
        na->na_addr.v6.sin6_family = AF_INET6;
1182
#ifdef SIN6_LEN
1183
        na->na_addr.v6.sin6_len = sizeof(struct sockaddr_in6);
1184
#endif /* SIN6_LEN */
1185
0
        memcpy(&na->na_addr.v6.sin6_addr, &in6addr_any, sizeof(struct in6_addr));
1186
0
        if (na->na_have_ipstr) {
1187
0
          memset(na->na_ipstr, '\0', sizeof(na->na_ipstr));
1188
0
          sstrncpy(na->na_ipstr, "::", sizeof(na->na_ipstr));
1189
0
        }
1190
0
        return 0;
1191
0
      }
1192
0
#endif /* PR_USE_IPV6 */
1193
0
  }
1194
1195
0
  errno = EPERM;
1196
0
  return -1;
1197
0
}
1198
1199
0
void *pr_netaddr_get_inaddr(const pr_netaddr_t *na) {
1200
0
  if (na == NULL) {
1201
0
    errno = EINVAL;
1202
0
    return NULL;
1203
0
  }
1204
1205
0
  switch (pr_netaddr_get_family(na)) {
1206
0
    case AF_INET:
1207
0
      return (void *) &na->na_addr.v4.sin_addr;
1208
1209
0
#ifdef PR_USE_IPV6
1210
0
    case AF_INET6:
1211
0
      if (use_ipv6 == TRUE) {
1212
0
        return (void *) &na->na_addr.v6.sin6_addr;
1213
0
      }
1214
0
#endif /* PR_USE_IPV6 */
1215
0
  }
1216
1217
0
  errno = EPERM;
1218
0
  return NULL;
1219
0
}
1220
1221
0
unsigned int pr_netaddr_get_port(const pr_netaddr_t *na) {
1222
0
  if (na == NULL) {
1223
0
    errno = EINVAL;
1224
0
    return 0;
1225
0
  }
1226
1227
0
  switch (pr_netaddr_get_family(na)) {
1228
0
    case AF_INET:
1229
0
      return na->na_addr.v4.sin_port;
1230
1231
0
#ifdef PR_USE_IPV6
1232
0
    case AF_INET6:
1233
0
      if (use_ipv6 == TRUE) {
1234
0
        return na->na_addr.v6.sin6_port;
1235
0
      }
1236
0
#endif /* PR_USE_IPV6 */
1237
0
  }
1238
1239
0
  errno = EPERM;
1240
0
  return 0;
1241
0
}
1242
1243
0
int pr_netaddr_set_port(pr_netaddr_t *na, unsigned int port) {
1244
0
  if (!na) {
1245
0
    errno = EINVAL;
1246
0
    return -1;
1247
0
  }
1248
1249
0
  switch (pr_netaddr_get_family(na)) {
1250
0
    case AF_INET:
1251
0
      na->na_addr.v4.sin_port = port;
1252
0
      return 0;
1253
1254
0
#ifdef PR_USE_IPV6
1255
0
    case AF_INET6:
1256
0
      if (use_ipv6) {
1257
0
        na->na_addr.v6.sin6_port = port;
1258
0
        return 0;
1259
0
      }
1260
0
#endif /* PR_USE_IPV6 */
1261
0
  }
1262
1263
0
  errno = EPERM;
1264
0
  return -1;
1265
0
}
1266
1267
0
int pr_netaddr_set_port2(pr_netaddr_t *na, unsigned int port) {
1268
0
  return pr_netaddr_set_port(na, htons(port));
1269
0
}
1270
1271
0
int pr_netaddr_cmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2) {
1272
0
  pool *tmp_pool = NULL;
1273
0
  pr_netaddr_t *a, *b;
1274
0
  int res;
1275
1276
0
  if (na1 != NULL &&
1277
0
      na2 == NULL) {
1278
0
    return 1;
1279
0
  }
1280
1281
0
  if (na1 == NULL &&
1282
0
      na2 != NULL) {
1283
0
    return -1;
1284
0
  }
1285
1286
0
  if (na1 == NULL &&
1287
0
      na2 == NULL) {
1288
0
    return 0;
1289
0
  }
1290
1291
0
  if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {
1292
1293
    /* Cannot compare addresses from different families, unless one
1294
     * of the netaddrs has an AF_INET family, and the other has an
1295
     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
1296
     */
1297
1298
0
    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
1299
0
        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
1300
0
      errno = EINVAL;
1301
0
      return -1;
1302
0
    }
1303
1304
0
    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
1305
0
      tmp_pool = make_sub_pool(permanent_pool);
1306
1307
0
      pr_trace_msg(trace_channel, 5, "addr '%s' is an IPv4-mapped IPv6 address",
1308
0
        pr_netaddr_get_ipstr((pr_netaddr_t *) na1));
1309
1310
      /* This case means that na1 is an IPv4-mapped IPv6 address, and
1311
       * na2 is an IPv4 address.
1312
       */
1313
0
      a = pr_netaddr_v6tov4(tmp_pool, na1);
1314
0
      b = (pr_netaddr_t *) na2;
1315
1316
0
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
1317
0
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(b),
1318
0
        pr_netaddr_get_ipstr(a));
1319
1320
0
    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
1321
0
      tmp_pool = make_sub_pool(permanent_pool);
1322
1323
0
      pr_trace_msg(trace_channel, 5, "addr '%s' is an IPv4-mapped IPv6 address",
1324
0
        pr_netaddr_get_ipstr((pr_netaddr_t *) na2));
1325
1326
      /* This case means that na is an IPv4 address, and na2 is an
1327
       * IPv4-mapped IPv6 address.
1328
       */
1329
0
      a = (pr_netaddr_t *) na1;
1330
0
      b = pr_netaddr_v6tov4(tmp_pool, na2);
1331
1332
0
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
1333
0
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(a),
1334
0
        pr_netaddr_get_ipstr(b));
1335
1336
0
    } else {
1337
0
      a = (pr_netaddr_t *) na1;
1338
0
      b = (pr_netaddr_t *) na2;
1339
0
    }
1340
1341
0
  } else {
1342
0
    a = (pr_netaddr_t *) na1;
1343
0
    b = (pr_netaddr_t *) na2;
1344
0
  }
1345
1346
0
  switch (pr_netaddr_get_family(a)) {
1347
0
    case AF_INET:
1348
0
      res = memcmp(&a->na_addr.v4.sin_addr, &b->na_addr.v4.sin_addr,
1349
0
        sizeof(struct in_addr));
1350
1351
0
      if (res != 0) {
1352
0
        pr_trace_msg(trace_channel, 4, "addr %s does not match addr %s",
1353
0
          pr_netaddr_get_ipstr(a), pr_netaddr_get_ipstr(b));
1354
0
      }
1355
1356
0
      if (tmp_pool) {
1357
0
        destroy_pool(tmp_pool);
1358
0
        tmp_pool = NULL;
1359
0
      }
1360
1361
0
      return res;
1362
1363
0
#ifdef PR_USE_IPV6
1364
0
    case AF_INET6:
1365
0
      if (use_ipv6) {
1366
0
        res = memcmp(&a->na_addr.v6.sin6_addr, &b->na_addr.v6.sin6_addr,
1367
0
          sizeof(struct in6_addr));
1368
1369
0
        if (res != 0) {
1370
0
          pr_trace_msg(trace_channel, 4, "addr %s does not match addr %s",
1371
0
            pr_netaddr_get_ipstr(a), pr_netaddr_get_ipstr(b));
1372
0
        }
1373
1374
0
        if (tmp_pool != NULL) {
1375
0
          destroy_pool(tmp_pool);
1376
0
          tmp_pool = NULL;
1377
0
        }
1378
1379
0
        return res;
1380
0
      }
1381
0
#endif /* PR_USE_IPV6 */
1382
0
  }
1383
1384
0
  if (tmp_pool != NULL) {
1385
0
    destroy_pool(tmp_pool);
1386
0
  }
1387
1388
0
  errno = EPERM;
1389
0
  return -1;
1390
0
}
1391
1392
static int addr_ncmp(const unsigned char *aptr, const unsigned char *bptr,
1393
0
    unsigned int masklen) {
1394
0
  unsigned char nbits, nbytes;
1395
0
  int res;
1396
1397
  /* These null checks are unlikely to happen.  But be prepared, eh? */
1398
1399
0
  if (aptr != NULL &&
1400
0
      bptr == NULL) {
1401
0
    return 1;
1402
0
  }
1403
1404
0
  if (aptr == NULL &&
1405
0
      bptr != NULL) {
1406
0
    return -1;
1407
0
  }
1408
1409
0
  if (aptr == NULL &&
1410
0
      bptr == NULL) {
1411
0
    return 0;
1412
0
  }
1413
1414
0
  nbytes = masklen / 8;
1415
0
  nbits = masklen % 8;
1416
1417
0
  res = memcmp(aptr, bptr, nbytes);
1418
0
  if (res != 0) {
1419
0
    return -1;
1420
0
  }
1421
1422
0
  if (nbits > 0) {
1423
0
    unsigned char abyte, bbyte, mask;
1424
1425
0
    abyte = aptr[nbytes];
1426
0
    bbyte = bptr[nbytes];
1427
1428
0
    mask = (0xff << (8 - nbits)) & 0xff;
1429
1430
0
    if ((abyte & mask) > (bbyte & mask)) {
1431
0
      return 1;
1432
0
    }
1433
1434
0
    if ((abyte & mask) < (bbyte & mask)) {
1435
0
      return -1;
1436
0
    }
1437
0
  }
1438
1439
0
  return 0;
1440
0
}
1441
1442
int pr_netaddr_ncmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2,
1443
0
    unsigned int bitlen) {
1444
0
  pool *tmp_pool = NULL;
1445
0
  pr_netaddr_t *a, *b;
1446
0
  const unsigned char *in1, *in2;
1447
0
  int res;
1448
1449
0
  if (na1 != NULL &&
1450
0
      na2 == NULL) {
1451
0
    return 1;
1452
0
  }
1453
1454
0
  if (na1 == NULL &&
1455
0
      na2 != NULL) {
1456
0
    return -1;
1457
0
  }
1458
1459
0
  if (na1 == NULL &&
1460
0
      na2 == NULL) {
1461
0
    return 0;
1462
0
  }
1463
1464
0
  if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {
1465
1466
    /* Cannot compare addresses from different families, unless one
1467
     * of the netaddrs has an AF_INET family, and the other has an
1468
     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
1469
     */
1470
1471
0
    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
1472
0
        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
1473
0
      errno = EINVAL;
1474
0
      return -1;
1475
0
    }
1476
1477
0
    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
1478
0
      tmp_pool = make_sub_pool(permanent_pool);
1479
1480
      /* This case means that na1 is an IPv4-mapped IPv6 address, and
1481
       * na2 is an IPv4 address.
1482
       */
1483
0
      a = pr_netaddr_v6tov4(tmp_pool, na1);
1484
0
      b = (pr_netaddr_t *) na2;
1485
1486
0
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
1487
0
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(b),
1488
0
        pr_netaddr_get_ipstr(a));
1489
1490
0
    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
1491
0
      tmp_pool = make_sub_pool(permanent_pool);
1492
1493
      /* This case means that na is an IPv4 address, and na2 is an
1494
       * IPv4-mapped IPv6 address.
1495
       */
1496
0
      a = (pr_netaddr_t *) na1;
1497
0
      b = pr_netaddr_v6tov4(tmp_pool, na2);
1498
1499
0
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
1500
0
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(a),
1501
0
        pr_netaddr_get_ipstr(b));
1502
1503
0
    } else {
1504
0
      a = (pr_netaddr_t *) na1;
1505
0
      b = (pr_netaddr_t *) na2;
1506
0
    }
1507
1508
0
  } else {
1509
0
    a = (pr_netaddr_t *) na1;
1510
0
    b = (pr_netaddr_t *) na2;
1511
0
  }
1512
1513
0
  switch (pr_netaddr_get_family(a)) {
1514
0
    case AF_INET: {
1515
      /* Make sure that the given number of bits is not more than supported
1516
       * for IPv4 addresses (32).
1517
       */
1518
0
      if (bitlen > 32) {
1519
0
        errno = EINVAL;
1520
0
        return -1;
1521
0
      }
1522
1523
0
      break;
1524
0
    }
1525
1526
0
#ifdef PR_USE_IPV6
1527
0
    case AF_INET6: {
1528
0
      if (use_ipv6) {
1529
        /* Make sure that the given number of bits is not more than supported
1530
         * for IPv6 addresses (128).
1531
         */
1532
0
        if (bitlen > 128) {
1533
0
          errno = EINVAL;
1534
0
          return -1;
1535
0
        }
1536
1537
0
        break;
1538
0
      }
1539
0
    }
1540
0
#endif /* PR_USE_IPV6 */
1541
1542
0
    default:
1543
0
      errno = EPERM;
1544
0
      return -1;
1545
0
  }
1546
1547
  /* Retrieve pointers to the contained in_addrs. */
1548
0
  in1 = (const unsigned char *) pr_netaddr_get_inaddr(a);
1549
0
  in2 = (const unsigned char *) pr_netaddr_get_inaddr(b);
1550
1551
0
  res = addr_ncmp(in1, in2, bitlen);
1552
1553
0
  if (tmp_pool) {
1554
0
    destroy_pool(tmp_pool);
1555
0
  }
1556
1557
0
  return res;
1558
0
}
1559
1560
0
int pr_netaddr_fnmatch(const pr_netaddr_t *na, const char *pattern, int flags) {
1561
1562
  /* Note: I'm still not sure why proftpd bundles an fnmatch(3)
1563
   * implementation rather than using the system library's implementation.
1564
   * Needs looking into.
1565
   *
1566
   * The FNM_CASEFOLD flag is a GNU extension; perhaps the bundled
1567
   * implementation was added to make that flag available on other platforms.
1568
   */
1569
0
  int match_flags = PR_FNM_NOESCAPE|PR_FNM_CASEFOLD;
1570
1571
0
  if (na == NULL ||
1572
0
      pattern == NULL) {
1573
0
    errno = EINVAL;
1574
0
    return -1;
1575
0
  }
1576
1577
0
  if (flags & PR_NETADDR_MATCH_DNS) {
1578
0
    const char *dnsstr;
1579
1580
0
    dnsstr = pr_netaddr_get_dnsstr(na);
1581
0
    if (pr_fnmatch(pattern, dnsstr, match_flags) == 0) {
1582
0
      pr_trace_msg(trace_channel, 6, "DNS name '%s' matches pattern '%s'",
1583
0
        dnsstr, pattern);
1584
0
      return TRUE;
1585
0
    }
1586
0
  }
1587
1588
0
  if (flags & PR_NETADDR_MATCH_IP) {
1589
0
    const char *ipstr;
1590
1591
0
    ipstr = pr_netaddr_get_ipstr(na);
1592
0
    if (pr_fnmatch(pattern, ipstr, match_flags) == 0) {
1593
0
      pr_trace_msg(trace_channel, 6, "IP address '%s' matches pattern '%s'",
1594
0
        ipstr, pattern);
1595
0
      return TRUE;
1596
0
    }
1597
1598
    /* If the address is an IPv4-mapped IPv6 address, get the IPv4 address
1599
     * and try to match that against the configured glob pattern.
1600
     */
1601
0
    if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
1602
0
      pool *tmp_pool;
1603
0
      pr_netaddr_t *a;
1604
1605
0
      pr_trace_msg(trace_channel, 5, "addr '%s' is an IPv4-mapped IPv6 address",
1606
0
        ipstr);
1607
1608
0
      tmp_pool = make_sub_pool(permanent_pool);
1609
0
      a = pr_netaddr_v6tov4(tmp_pool, na);
1610
1611
0
      ipstr = pr_netaddr_get_ipstr(a);
1612
1613
0
      if (pr_fnmatch(pattern, ipstr, match_flags) == 0) {
1614
0
        pr_trace_msg(trace_channel, 6, "IP address '%s' matches pattern '%s'",
1615
0
          ipstr, pattern);
1616
1617
0
        destroy_pool(tmp_pool);
1618
0
        return TRUE;
1619
0
      }
1620
1621
0
      destroy_pool(tmp_pool);
1622
0
    }
1623
0
  }
1624
1625
0
  pr_trace_msg(trace_channel, 4, "addr %s does not match pattern '%s'",
1626
0
    pr_netaddr_get_ipstr(na), pattern);
1627
0
  return FALSE;
1628
0
}
1629
1630
0
const char *pr_netaddr_get_ipstr(const pr_netaddr_t *na) {
1631
0
#if defined(PR_USE_IPV6)
1632
0
  char buf[INET6_ADDRSTRLEN];
1633
#else
1634
  char buf[INET_ADDRSTRLEN];
1635
#endif /* PR_USE_IPV6 */
1636
0
  int res = 0, xerrno;
1637
0
  pr_netaddr_t *addr;
1638
1639
0
  if (na == NULL) {
1640
0
    errno = EINVAL;
1641
0
    return NULL;
1642
0
  }
1643
1644
  /* If this pr_netaddr_t has already been resolved to an IP string, return the
1645
   * cached string.
1646
   */
1647
0
  if (na->na_have_ipstr) {
1648
0
    return na->na_ipstr;
1649
0
  }
1650
1651
0
  memset(buf, '\0', sizeof(buf));
1652
0
  res = pr_getnameinfo(pr_netaddr_get_sockaddr(na),
1653
0
    pr_netaddr_get_sockaddr_len(na), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
1654
0
  xerrno = errno;
1655
1656
0
  if (res != 0) {
1657
0
    if (res != EAI_SYSTEM) {
1658
0
      pr_log_pri(PR_LOG_WARNING, "getnameinfo error: %s", pr_gai_strerror(res));
1659
0
      errno = EIO;
1660
1661
0
    } else {
1662
0
      pr_log_pri(PR_LOG_WARNING, "getnameinfo system error: [%d] %s",
1663
0
        xerrno, strerror(xerrno));
1664
0
      errno = xerrno;
1665
0
    }
1666
1667
0
    return NULL;
1668
0
  }
1669
1670
0
#ifdef PR_USE_IPV6
1671
0
  if (use_ipv6 &&
1672
0
      pr_netaddr_get_family(na) == AF_INET6) {
1673
    /* The getnameinfo(3) implementation might append the zone ID to an IPv6
1674
     * name; we need to trim it off.
1675
     */
1676
0
    char *ptr;
1677
1678
0
    ptr = strrchr(buf, '%');
1679
0
    if (ptr != NULL) {
1680
0
      *ptr = '\0';
1681
0
    }
1682
0
  }
1683
0
#endif /* PR_USE_IPV6 */
1684
1685
  /* Copy the string into the pr_netaddr_t cache as well, so we only
1686
   * have to do this once for this pr_netaddr_t.  But to do this, we need
1687
   * let the compiler know that the pr_netaddr_t is not really const at this
1688
   * point.
1689
   */
1690
0
  addr = (pr_netaddr_t *) na;
1691
0
  memset(addr->na_ipstr, '\0', sizeof(addr->na_ipstr));
1692
0
  sstrncpy(addr->na_ipstr, buf, sizeof(addr->na_ipstr));
1693
0
  addr->na_have_ipstr = TRUE;
1694
1695
0
  return na->na_ipstr;
1696
0
}
1697
1698
#if defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME2)
1699
static int netaddr_get_dnsstr_getaddrinfo(const pr_netaddr_t *na,
1700
    const char *name) {
1701
  struct addrinfo hints, *info = NULL;
1702
  int family, flags = 0, res = 0, ok = FALSE;
1703
  void *inaddr = pr_netaddr_get_inaddr(na);
1704
1705
  family = pr_netaddr_get_family(na);
1706
  if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
1707
    family = AF_INET;
1708
    inaddr = get_v4inaddr(na);
1709
  }
1710
1711
#ifdef AI_CANONNAME
1712
  flags |= AI_CANONNAME;
1713
#endif
1714
1715
#ifdef AI_ALL
1716
  flags |= AI_ALL;
1717
#endif
1718
1719
#ifdef AI_V4MAPPED
1720
  flags |= AI_V4MAPPED;
1721
#endif
1722
1723
  memset(&hints, 0, sizeof(hints));
1724
1725
  hints.ai_family = family;
1726
  hints.ai_socktype = SOCK_STREAM;
1727
  hints.ai_protocol = IPPROTO_TCP;
1728
  hints.ai_flags = flags;
1729
1730
  res = pr_getaddrinfo(name, NULL, &hints, &info);
1731
  if (res != 0) {
1732
    int xerrno = errno;
1733
1734
    if (res != EAI_SYSTEM) {
1735
      pr_trace_msg(trace_channel, 1, "%s getaddrinfo '%s' error: %s",
1736
        hints.ai_family == AF_INET ? "IPv4" : "IPv6", name,
1737
        pr_gai_strerror(res));
1738
1739
    } else {
1740
      pr_trace_msg(trace_channel, 1,
1741
        "%s getaddrinfo '%s' system error: [%d] %s",
1742
        hints.ai_family == AF_INET ? "IPv4" : "IPv6", name, xerrno,
1743
        strerror(xerrno));
1744
    }
1745
1746
    errno = xerrno;
1747
    return -1;
1748
  }
1749
1750
  if (info != NULL) {
1751
#ifdef PR_USE_IPV6
1752
    char buf[INET6_ADDRSTRLEN];
1753
#else
1754
    char buf[INET_ADDRSTRLEN];
1755
#endif /* PR_USE_IPV6 */
1756
    struct addrinfo *ai;
1757
    int xerrno;
1758
1759
    memset(buf, '\0', sizeof(buf));
1760
    res = pr_getnameinfo(info->ai_addr, info->ai_addrlen, buf, sizeof(buf),
1761
      NULL, 0, NI_NAMEREQD);
1762
    xerrno = errno;
1763
1764
    if (res != 0) {
1765
      if (res != EAI_SYSTEM) {
1766
        pr_trace_msg(trace_channel, 1, "%s getnameinfo error: %s",
1767
          hints.ai_family == AF_INET ? "IPv4" : "IPv6", pr_gai_strerror(res));
1768
1769
      } else {
1770
        pr_trace_msg(trace_channel, 1,
1771
          "%s getnameinfo system error: [%d] %s",
1772
          hints.ai_family == AF_INET ? "IPv4" : "IPv6", xerrno,
1773
          strerror(xerrno));
1774
      }
1775
1776
      errno = xerrno;
1777
      return -1;
1778
    }
1779
1780
    netaddr_dnscache_set(pr_netaddr_get_ipstr(na), buf);
1781
    ok = TRUE;
1782
1783
    pr_trace_msg(trace_channel, 10,
1784
      "checking addresses associated with host '%s'", buf);
1785
1786
    for (ai = info->ai_next; ai; ai = ai->ai_next) {
1787
#ifdef PR_USE_IPV6
1788
      char alias[INET6_ADDRSTRLEN];
1789
#else
1790
      char alias[INET_ADDRSTRLEN];
1791
#endif /* PR_USE_IPV6 */
1792
1793
      switch (ai->ai_family) {
1794
        case AF_INET:
1795
          if (family == AF_INET) {
1796
            if (memcmp(ai->ai_addr, inaddr, ai->ai_addrlen) == 0) {
1797
              memset(alias, '\0', sizeof(alias));
1798
              res = pr_getnameinfo(ai->ai_addr, ai->ai_addrlen, alias,
1799
                sizeof(alias), NULL, 0, NI_NAMEREQD);
1800
              if (res == 0) {
1801
                pr_trace_msg(trace_channel, 10,
1802
                  "host '%s' has alias '%s'", buf, alias);
1803
                netaddr_ipcache_set(alias, na);
1804
                netaddr_dnscache_set(pr_netaddr_get_ipstr(na), alias);
1805
              }
1806
            }
1807
          }
1808
          break;
1809
1810
#ifdef PR_USE_IPV6
1811
        case AF_INET6:
1812
          if (use_ipv6 && family == AF_INET6) {
1813
            if (memcmp(ai->ai_addr, inaddr, ai->ai_addrlen) == 0) {
1814
              memset(alias, '\0', sizeof(alias));
1815
              res = pr_getnameinfo(ai->ai_addr, ai->ai_addrlen, alias,
1816
                sizeof(alias), NULL, 0, NI_NAMEREQD);
1817
              if (res == 0) {
1818
                pr_trace_msg(trace_channel, 10,
1819
                  "host '%s' has alias '%s'", buf, alias);
1820
                netaddr_ipcache_set(alias, na);
1821
                netaddr_dnscache_set(pr_netaddr_get_ipstr(na), alias);
1822
              }
1823
            }
1824
          }
1825
          break;
1826
#endif /* PR_USE_IPV6 */
1827
      }
1828
    }
1829
1830
    pr_freeaddrinfo(info);
1831
  }
1832
1833
  return (ok ? 0 : -1);
1834
}
1835
#endif /* HAVE_GETADDRINFO and not HAVE_GETHOSTBYNAME2 */
1836
1837
#ifdef HAVE_GETHOSTBYNAME2
1838
static int netaddr_get_dnsstr_gethostbyname(const pr_netaddr_t *na,
1839
0
    const char *name) {
1840
0
  struct hostent *hent = NULL;
1841
0
  int family, ok = FALSE;
1842
0
  void *inaddr;
1843
1844
0
  family = pr_netaddr_get_family(na);
1845
0
  if (family < 0) {
1846
0
    return -1;
1847
0
  }
1848
1849
0
  inaddr = pr_netaddr_get_inaddr(na);
1850
1851
0
  if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
1852
0
    family = AF_INET;
1853
0
    inaddr = get_v4inaddr(na);
1854
0
  }
1855
1856
0
  hent = gethostbyname2(name, family);
1857
1858
0
  if (hent != NULL) {
1859
0
    char **checkaddr;
1860
1861
0
    if (hent->h_name != NULL) {
1862
0
      netaddr_dnscache_set(pr_netaddr_get_ipstr(na), hent->h_name);
1863
0
    }
1864
1865
0
    pr_trace_msg(trace_channel, 10,
1866
0
      "checking addresses associated with host '%s'",
1867
0
      hent->h_name ? hent->h_name : "(null)");
1868
1869
0
    switch (hent->h_addrtype) {
1870
0
      case AF_INET:
1871
0
        if (family == AF_INET) {
1872
0
          for (checkaddr = hent->h_addr_list; *checkaddr; ++checkaddr) {
1873
0
            if (memcmp(*checkaddr, inaddr, hent->h_length) == 0) {
1874
0
              char **alias;
1875
1876
0
              for (alias = hent->h_aliases; *alias; ++alias) {
1877
0
                if (hent->h_name) {
1878
0
                  pr_trace_msg(trace_channel, 10,
1879
0
                    "host '%s' has alias '%s'", hent->h_name, *alias);
1880
0
                  netaddr_ipcache_set(*alias, na);
1881
0
                  netaddr_dnscache_set(pr_netaddr_get_ipstr(na), *alias);
1882
0
                }
1883
0
              }
1884
1885
0
              ok = TRUE;
1886
0
              break;
1887
0
            }
1888
0
          }
1889
0
        }
1890
0
        break;
1891
1892
0
# if defined(PR_USE_IPV6)
1893
0
      case AF_INET6:
1894
0
        if (use_ipv6 && family == AF_INET6) {
1895
0
          for (checkaddr = hent->h_addr_list; *checkaddr; ++checkaddr) {
1896
0
            if (memcmp(*checkaddr, inaddr, hent->h_length) == 0) {
1897
0
              char **alias;
1898
1899
0
              for (alias = hent->h_aliases; *alias; ++alias) {
1900
0
                if (hent->h_name) {
1901
0
                  pr_trace_msg(trace_channel, 10,
1902
0
                    "host '%s' has alias '%s'", hent->h_name, *alias);
1903
0
                  netaddr_ipcache_set(*alias, na);
1904
0
                  netaddr_dnscache_set(pr_netaddr_get_ipstr(na), *alias);
1905
0
                }
1906
0
              }
1907
1908
0
              ok = TRUE;
1909
0
              break;
1910
0
            }
1911
0
          }
1912
0
        }
1913
0
        break;
1914
0
# endif /* PR_USE_IPV6 */
1915
0
    }
1916
1917
0
  } else {
1918
0
    pr_log_debug(DEBUG1, "notice: unable to resolve '%s' as %s address: %s",
1919
0
      name, family != AF_INET ? "IPv6" : "IPv4", hstrerror(h_errno));
1920
0
  }
1921
1922
0
  return (ok ? 0 : -1);
1923
0
}
1924
#endif /* HAVE_GETHOSTBYNAME2 */
1925
1926
/* This differs from pr_netaddr_get_ipstr() in that pr_netaddr_get_ipstr()
1927
 * returns a string of the numeric form of the given network address, whereas
1928
 * this function returns a string of the DNS name (if present).
1929
 */
1930
0
const char *pr_netaddr_get_dnsstr(const pr_netaddr_t *na) {
1931
0
  char dns_buf[1024], *name = NULL;
1932
0
  pr_netaddr_t *addr = NULL, *cache = NULL;
1933
1934
0
  if (na == NULL) {
1935
0
    errno = EINVAL;
1936
0
    return NULL;
1937
0
  }
1938
1939
0
  cache = netaddr_ipcache_get(NULL, pr_netaddr_get_ipstr(na));
1940
0
  if (cache &&
1941
0
      cache->na_have_dnsstr) {
1942
0
    addr = (pr_netaddr_t *) na;
1943
0
    memset(addr->na_dnsstr, '\0', sizeof(addr->na_dnsstr));
1944
0
    sstrncpy(addr->na_dnsstr, cache->na_dnsstr, sizeof(addr->na_dnsstr));
1945
0
    addr->na_have_dnsstr = TRUE;
1946
1947
0
    return na->na_dnsstr;
1948
0
  }
1949
1950
  /* If this pr_netaddr_t has already been resolved to an DNS string, return the
1951
   * cached string.
1952
   */
1953
0
  if (na->na_have_dnsstr) {
1954
0
    return na->na_dnsstr;
1955
0
  }
1956
1957
0
  if (reverse_dns) {
1958
0
    int res = 0;
1959
1960
0
    pr_trace_msg(trace_channel, 3,
1961
0
      "verifying DNS name for IP address %s via reverse DNS lookup",
1962
0
      pr_netaddr_get_ipstr(na));
1963
1964
0
    memset(dns_buf, '\0', sizeof(dns_buf));
1965
0
    res = pr_getnameinfo(pr_netaddr_get_sockaddr(na),
1966
0
      pr_netaddr_get_sockaddr_len(na), dns_buf, sizeof(dns_buf), NULL, 0,
1967
0
      NI_NAMEREQD);
1968
0
    dns_buf[sizeof(dns_buf)-1] = '\0';
1969
1970
0
    if (res == 0) {
1971
      /* Some older glibc's getaddrinfo(3) does not appear to handle IPv6
1972
       * addresses properly; we thus prefer gethostbyname2(3) on systems
1973
       * which have it, for such older systems.
1974
       */
1975
0
#ifdef HAVE_GETHOSTBYNAME2
1976
0
      res = netaddr_get_dnsstr_gethostbyname(na, dns_buf);
1977
#else
1978
      res = netaddr_get_dnsstr_getaddrinfo(na, dns_buf);
1979
#endif /* HAVE_GETHOSTBYNAME2 */
1980
0
      if (res == 0) {
1981
0
        name = dns_buf;
1982
0
        pr_trace_msg(trace_channel, 8,
1983
0
          "using DNS name '%s' for IP address '%s'", name,
1984
0
          pr_netaddr_get_ipstr(na));
1985
1986
0
      } else {
1987
0
        name = NULL;
1988
0
        pr_trace_msg(trace_channel, 8,
1989
0
          "unable to verify any DNS names for IP address '%s'",
1990
0
          pr_netaddr_get_ipstr(na));
1991
0
      }
1992
0
    }
1993
1994
0
  } else {
1995
0
    pr_log_debug(DEBUG10,
1996
0
      "UseReverseDNS off, returning IP address instead of DNS name");
1997
0
  }
1998
1999
0
  if (name) {
2000
0
    name = pr_netaddr_validate_dns_str(name);
2001
2002
0
  } else {
2003
0
    name = (char *) pr_netaddr_get_ipstr(na);
2004
0
  }
2005
2006
  /* Copy the string into the pr_netaddr_t cache as well, so we only
2007
   * have to do this once for this pr_netaddr_t.  But to do this, we need
2008
   * let the compiler know that the pr_netaddr_t is not really const at this
2009
   * point.
2010
   */
2011
0
  addr = (pr_netaddr_t *) na;
2012
0
  memset(addr->na_dnsstr, '\0', sizeof(addr->na_dnsstr));
2013
0
  sstrncpy(addr->na_dnsstr, name, sizeof(addr->na_dnsstr));
2014
0
  addr->na_have_dnsstr = TRUE;
2015
2016
  /* Update the netaddr object in the cache with the resolved DNS names. */
2017
0
  netaddr_ipcache_set(name, na);
2018
0
  netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na);
2019
2020
0
  return na->na_dnsstr;
2021
0
}
2022
2023
0
array_header *pr_netaddr_get_dnsstr_list(pool *p, const pr_netaddr_t *na) {
2024
0
  array_header *res;
2025
2026
0
  if (p == NULL ||
2027
0
      na == NULL) {
2028
0
    errno = EINVAL;
2029
0
    return NULL;
2030
0
  }
2031
2032
0
  if (!reverse_dns) {
2033
    /* If UseReverseDNS is off, then we won't have any names that we trust.
2034
     * So return an empty list.
2035
     */
2036
0
    return make_array(p, 0, sizeof(char *));
2037
0
  }
2038
2039
0
  res = netaddr_dnscache_get(p, pr_netaddr_get_ipstr(na));
2040
0
  if (res == NULL) {
2041
0
    res = make_array(p, 0, sizeof(char *));
2042
0
  }
2043
2044
0
  return res;
2045
0
}
2046
2047
/* Return the hostname (wrapper for gethostname(2), except returns FQDN). */
2048
0
const char *pr_netaddr_get_localaddr_str(pool *p) {
2049
0
  char buf[256];
2050
0
  int res, xerrno;
2051
2052
0
  if (p == NULL) {
2053
0
    errno = EINVAL;
2054
0
    return NULL;
2055
0
  }
2056
2057
0
  if (have_localaddr_str) {
2058
0
    return pr_netaddr_validate_dns_str(pstrdup(p, localaddr_str));
2059
0
  }
2060
2061
0
  memset(buf, '\0', sizeof(buf));
2062
0
  res = gethostname(buf, sizeof(buf)-1);
2063
0
  xerrno = errno;
2064
2065
0
  if (res >= 0) {
2066
0
    struct hostent *host;
2067
2068
0
    buf[sizeof(buf)-1] = '\0';
2069
2070
    /* Note: this may need to be gethostbyname2() on systems that provide
2071
     * that function, for it is possible that the configured hostname for
2072
     * a machine only resolves to an IPv6 address.
2073
     */
2074
0
#ifdef HAVE_GETHOSTBYNAME2
2075
0
    host = gethostbyname2(buf, AF_INET);
2076
0
    if (host == NULL &&
2077
0
        h_errno == HOST_NOT_FOUND) {
2078
0
# ifdef AF_INET6
2079
0
      host = gethostbyname2(buf, AF_INET6);
2080
0
# endif /* AF_INET6 */
2081
0
    }
2082
#else
2083
    host = gethostbyname(buf);
2084
#endif
2085
0
    if (host != NULL) {
2086
0
      return pr_netaddr_validate_dns_str(pstrdup(p, host->h_name));
2087
0
    }
2088
2089
0
    pr_trace_msg(trace_channel, 14,
2090
0
      "gethostbyname() failed for '%s': %s", buf, hstrerror(h_errno));
2091
0
    return pr_netaddr_validate_dns_str(pstrdup(p, buf));
2092
0
  }
2093
2094
0
  pr_trace_msg(trace_channel, 1, "gethostname(2) error: %s", strerror(xerrno));
2095
0
  errno = xerrno;
2096
0
  return NULL;
2097
0
}
2098
2099
0
int pr_netaddr_set_localaddr_str(const char *addr_str) {
2100
0
  if (addr_str == NULL) {
2101
0
    errno = EINVAL;
2102
0
    return -1;
2103
0
  }
2104
2105
0
  memset(localaddr_str, '\0', sizeof(localaddr_str));
2106
0
  sstrncpy(localaddr_str, addr_str, sizeof(localaddr_str));
2107
0
  have_localaddr_str = TRUE;
2108
0
  return 0;
2109
0
}
2110
2111
0
int pr_netaddr_is_loopback(const pr_netaddr_t *na) {
2112
0
  if (na == NULL) {
2113
0
    errno = EINVAL;
2114
0
    return -1;
2115
0
  }
2116
2117
0
  switch (pr_netaddr_get_family(na)) {
2118
0
    case AF_INET:
2119
0
      return IN_IS_ADDR_LOOPBACK(
2120
0
        (struct in_addr *) pr_netaddr_get_inaddr(na));
2121
2122
0
#ifdef PR_USE_IPV6
2123
0
    case AF_INET6:
2124
0
      if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
2125
0
        pool *tmp_pool;
2126
0
        pr_netaddr_t *v4na;
2127
0
        int res;
2128
2129
0
        tmp_pool = make_sub_pool(permanent_pool);
2130
0
        v4na = pr_netaddr_v6tov4(tmp_pool, na);
2131
2132
0
        res = pr_netaddr_is_loopback(v4na);
2133
0
        destroy_pool(tmp_pool);
2134
2135
0
        return res;
2136
0
      }
2137
2138
      /* XXX *sigh* Different platforms implement the IN6_IS_ADDR macros
2139
       * differently.  For example, on Linux, those macros expect to operate
2140
       * on s6_addr32, while on Solaris, the macros operate on struct in6_addr.
2141
       * Certain Drafts define the macros to work on struct in6_addr *, as
2142
       * Solaris does, so Linux may have it wrong.  Tentative research on
2143
       * Google shows some BSD netinet6/in6.h headers that define these
2144
       * macros in terms of struct in6_addr *, so I'll go with that for now.
2145
       * Joy. =P
2146
       */
2147
# ifndef LINUX
2148
      return IN6_IS_ADDR_LOOPBACK(
2149
        (struct in6_addr *) pr_netaddr_get_inaddr(na));
2150
# else
2151
0
      return IN6_IS_ADDR_LOOPBACK(
2152
0
        ((struct in6_addr *) pr_netaddr_get_inaddr(na))->s6_addr32);
2153
0
# endif
2154
0
#endif /* PR_USE_IPV6 */
2155
0
  }
2156
2157
0
  return FALSE;
2158
0
}
2159
2160
/* RFC 1918 addresses:
2161
 *
2162
 * 10.0.0.0 - 10.255.255.255 (10.0.0.0/8, 24-bit block)
2163
 * 172.16.0.0 - 172.31.255.255 (172.16.0.0/12, 20-bit block)
2164
 * 192.168.0.0 - 192.168.255.255 (192.168.0.0/16, 16-bit block)
2165
 *
2166
 */
2167
2168
0
static int is_10_xxx_addr(uint32_t addrno) {
2169
0
  uint32_t rfc1918_addrno;
2170
2171
0
  rfc1918_addrno = htonl(0x0a000000);
2172
0
  return addr_ncmp((const unsigned char *) &addrno,
2173
0
    (const unsigned char *) &rfc1918_addrno, 8);
2174
0
}
2175
2176
0
static int is_172_16_xx_addr(uint32_t addrno) {
2177
0
  uint32_t rfc1918_addrno;
2178
2179
0
  rfc1918_addrno = htonl(0xac100000);
2180
0
  return addr_ncmp((const unsigned char *) &addrno,
2181
0
    (const unsigned char *) &rfc1918_addrno, 12);
2182
0
}
2183
2184
0
static int is_192_168_xx_addr(uint32_t addrno) {
2185
0
  uint32_t rfc1918_addrno;
2186
2187
0
  rfc1918_addrno = htonl(0xc0a80000);
2188
0
  return addr_ncmp((const unsigned char *) &addrno,
2189
0
    (const unsigned char *) &rfc1918_addrno, 16);
2190
0
}
2191
2192
0
int pr_netaddr_is_rfc1918(const pr_netaddr_t *na) {
2193
0
  if (na == NULL) {
2194
0
    errno = EINVAL;
2195
0
    return -1;
2196
0
  }
2197
2198
0
  switch (pr_netaddr_get_family(na)) {
2199
0
    case AF_INET: {
2200
0
      uint32_t addrno;
2201
2202
0
      addrno = pr_netaddr_get_addrno(na);
2203
0
      if (is_192_168_xx_addr(addrno) == 0 ||
2204
0
          is_172_16_xx_addr(addrno) == 0 ||
2205
0
          is_10_xxx_addr(addrno) == 0) {
2206
0
          return TRUE;
2207
0
      }
2208
0
      break;
2209
0
    }
2210
2211
0
#ifdef PR_USE_IPV6
2212
0
    case AF_INET6:
2213
0
      if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
2214
0
        pool *tmp_pool;
2215
0
        pr_netaddr_t *v4na;
2216
0
        int res;
2217
2218
0
        tmp_pool = make_sub_pool(permanent_pool);
2219
0
        v4na = pr_netaddr_v6tov4(tmp_pool, na);
2220
2221
0
        res = pr_netaddr_is_rfc1918(v4na);
2222
0
        destroy_pool(tmp_pool);
2223
2224
0
        return res;
2225
0
      }
2226
2227
      /* By definition, an IPv6 address is not an RFC1918-defined address. */
2228
0
      return FALSE;
2229
0
#endif /* PR_USE_IPV6 */
2230
0
  }
2231
2232
0
  errno = EINVAL;
2233
0
  return FALSE;
2234
0
}
2235
2236
/* A slightly naughty function that should go away. It relies too much on
2237
 * knowledge of the internal structures of struct in_addr, struct in6_addr.
2238
 */
2239
0
uint32_t pr_netaddr_get_addrno(const pr_netaddr_t *na) {
2240
0
  if (na == NULL) {
2241
0
    errno = EINVAL;
2242
0
    return 0;
2243
0
  }
2244
2245
0
  switch (pr_netaddr_get_family(na)) {
2246
0
    case AF_INET:
2247
0
      return (uint32_t) na->na_addr.v4.sin_addr.s_addr;
2248
2249
0
#ifdef PR_USE_IPV6
2250
0
    case AF_INET6: {
2251
2252
      /* Linux defines s6_addr32 in its netinet/in.h header.
2253
       * FreeBSD defines s6_addr32 in KAME's netinet6/in6.h header.
2254
       * Solaris defines s6_addr32 in its netinet/in.h header, but only
2255
       * for kernel builds.
2256
       */
2257
#if 0
2258
      int *addrs = ((struct sockaddr_in6 *) pr_netaddr_get_inaddr(na))->s6_addr32;
2259
      return addrs[0];
2260
#else
2261
0
      errno = ENOENT;
2262
0
      return 0;
2263
0
#endif
2264
0
    }
2265
0
#endif /* PR_USE_IPV6 */
2266
0
  }
2267
2268
0
  errno = EPERM;
2269
0
  return 0;
2270
0
}
2271
2272
0
int pr_netaddr_is_v4(const char *name) {
2273
0
  int res;
2274
0
  struct sockaddr_in v4;
2275
2276
0
  if (name == NULL) {
2277
0
    errno = EINVAL;
2278
0
    return -1;
2279
0
  }
2280
2281
0
  memset(&v4, 0, sizeof(v4));
2282
0
  v4.sin_family = AF_INET;
2283
2284
# ifdef SIN_LEN
2285
  v4.sin_len = sizeof(struct sockaddr_in);
2286
# endif /* SIN_LEN */
2287
2288
0
  res = pr_inet_pton(AF_INET, name, &v4.sin_addr);
2289
0
  if (res > 0) {
2290
0
    return TRUE;
2291
0
  }
2292
2293
0
  return FALSE;
2294
0
}
2295
2296
0
int pr_netaddr_is_v6(const char *name) {
2297
0
  if (name == NULL) {
2298
0
    errno = EINVAL;
2299
0
    return -1;
2300
0
  }
2301
2302
0
#ifdef PR_USE_IPV6
2303
0
  if (use_ipv6) {
2304
0
    int res;
2305
0
    struct sockaddr_in6 v6;
2306
2307
0
    memset(&v6, 0, sizeof(v6));
2308
0
    v6.sin6_family = AF_INET6;
2309
2310
# ifdef SIN6_LEN
2311
    v6.sin6_len = sizeof(struct sockaddr_in6);
2312
# endif /* SIN6_LEN */
2313
2314
0
    res = pr_inet_pton(AF_INET6, name, &v6.sin6_addr);
2315
0
    if (res > 0) {
2316
0
      return TRUE;
2317
0
    }
2318
0
  }
2319
2320
0
  return FALSE;
2321
#else
2322
  return FALSE;
2323
#endif /* !PR_USE_IPV6 */
2324
0
}
2325
2326
0
int pr_netaddr_is_v4mappedv6(const pr_netaddr_t *na) {
2327
0
  if (!na) {
2328
0
    errno = EINVAL;
2329
0
    return -1;
2330
0
  }
2331
2332
0
  switch (pr_netaddr_get_family(na)) {
2333
0
    case AF_INET:
2334
2335
      /* This function tests only IPv6 addresses, not IPv4 addresses. */
2336
0
      errno = EINVAL;
2337
0
      return -1;
2338
2339
0
#ifdef PR_USE_IPV6
2340
0
    case AF_INET6: {
2341
0
      int res;
2342
2343
0
      if (!use_ipv6) {
2344
0
        errno = EINVAL;
2345
0
        return -1;
2346
0
      }
2347
2348
# ifndef LINUX
2349
      res = IN6_IS_ADDR_V4MAPPED(
2350
        (struct in6_addr *) pr_netaddr_get_inaddr(na));
2351
# else
2352
0
      res = IN6_IS_ADDR_V4MAPPED(
2353
0
        ((struct in6_addr *) pr_netaddr_get_inaddr(na))->s6_addr32);
2354
0
# endif
2355
2356
0
      if (res != TRUE) {
2357
0
        errno = EINVAL;
2358
0
      }
2359
2360
0
      return res;
2361
0
    }
2362
0
#endif /* PR_USE_IPV6 */
2363
0
  }
2364
2365
0
  errno = EPERM;
2366
0
  return -1;
2367
0
}
2368
2369
0
pr_netaddr_t *pr_netaddr_v6tov4(pool *p, const pr_netaddr_t *na) {
2370
0
  pr_netaddr_t *res;
2371
2372
0
  if (p == NULL ||
2373
0
      na == NULL) {
2374
0
    errno = EINVAL;
2375
0
    return NULL;
2376
0
  }
2377
2378
0
  if (pr_netaddr_is_v4mappedv6(na) != TRUE) {
2379
0
    errno = EPERM;
2380
0
    return NULL;
2381
0
  }
2382
2383
0
  res = pr_netaddr_alloc(p);
2384
0
  pr_netaddr_set_family(res, AF_INET);
2385
0
  pr_netaddr_set_port(res, pr_netaddr_get_port(na));
2386
0
  memcpy(&res->na_addr.v4.sin_addr, get_v4inaddr(na), sizeof(struct in_addr));
2387
2388
0
  return res;
2389
0
}
2390
2391
0
pr_netaddr_t *pr_netaddr_v4tov6(pool *p, const pr_netaddr_t *na) {
2392
0
  pr_netaddr_t *res;
2393
2394
0
  if (p == NULL ||
2395
0
      na == NULL) {
2396
0
    errno = EINVAL;
2397
0
    return NULL;
2398
0
  }
2399
2400
0
  if (pr_netaddr_get_family(na) != AF_INET) {
2401
0
    errno = EPERM;
2402
0
    return NULL;
2403
0
  }
2404
2405
0
#ifdef PR_USE_IPV6
2406
0
  res = (pr_netaddr_t *) pr_netaddr_get_addr(p,
2407
0
    pstrcat(p, "::ffff:", pr_netaddr_get_ipstr(na), NULL), NULL);
2408
0
  if (res != NULL) {
2409
0
    pr_netaddr_set_port(res, pr_netaddr_get_port(na));
2410
0
  }
2411
2412
#else
2413
  errno = EPERM;
2414
  res = NULL;
2415
#endif /* PR_USE_IPV6 */
2416
2417
0
  return res;
2418
0
}
2419
2420
0
const pr_netaddr_t *pr_netaddr_get_sess_local_addr(void) {
2421
0
  if (have_sess_local_addr) {
2422
0
    return &sess_local_addr;
2423
0
  }
2424
2425
0
  errno = ENOENT;
2426
0
  return NULL;
2427
0
}
2428
2429
0
const pr_netaddr_t *pr_netaddr_get_sess_remote_addr(void) {
2430
0
  if (have_sess_remote_addr) {
2431
0
    return &sess_remote_addr;
2432
0
  }
2433
2434
0
  errno = ENOENT;
2435
0
  return NULL;
2436
0
}
2437
2438
0
const char *pr_netaddr_get_sess_remote_name(void) {
2439
0
  if (have_sess_remote_addr) {
2440
0
    return sess_remote_name;
2441
0
  }
2442
2443
0
  errno = ENOENT;
2444
0
  return NULL;
2445
0
}
2446
2447
0
void pr_netaddr_set_sess_addrs(void) {
2448
0
  memset(&sess_local_addr, 0, sizeof(sess_local_addr));
2449
0
  pr_netaddr_set_family(&sess_local_addr,
2450
0
    pr_netaddr_get_family(session.c->local_addr));
2451
0
  pr_netaddr_set_sockaddr(&sess_local_addr,
2452
0
    pr_netaddr_get_sockaddr(session.c->local_addr));
2453
0
  have_sess_local_addr = TRUE;
2454
2455
0
  memset(&sess_remote_addr, 0, sizeof(sess_remote_addr));
2456
0
  pr_netaddr_set_family(&sess_remote_addr,
2457
0
    pr_netaddr_get_family(session.c->remote_addr));
2458
0
  pr_netaddr_set_sockaddr(&sess_remote_addr,
2459
0
    pr_netaddr_get_sockaddr(session.c->remote_addr));
2460
2461
0
  memset(sess_remote_name, '\0', sizeof(sess_remote_name));
2462
0
  sstrncpy(sess_remote_name, session.c->remote_name, sizeof(sess_remote_name));
2463
0
  have_sess_remote_addr = TRUE;
2464
0
}
2465
2466
0
unsigned char pr_netaddr_use_ipv6(void) {
2467
0
  if (use_ipv6 == TRUE) {
2468
0
    return TRUE;
2469
0
  }
2470
2471
0
  return FALSE;
2472
0
}
2473
2474
0
void pr_netaddr_disable_ipv6(void) {
2475
0
#if defined(PR_USE_IPV6)
2476
0
  use_ipv6 = FALSE;
2477
0
#endif /* PR_USE_IPV6 */
2478
0
}
2479
2480
0
void pr_netaddr_enable_ipv6(void) {
2481
0
#if defined(PR_USE_IPV6)
2482
0
  use_ipv6 = TRUE;
2483
0
#endif /* PR_USE_IPV6 */
2484
0
}
2485
2486
0
void pr_netaddr_clear_cache(void) {
2487
0
  if (netaddr_iptab != NULL) {
2488
0
    pr_trace_msg(trace_channel, 5, "emptying netaddr IP cache");
2489
0
    (void) pr_table_empty(netaddr_iptab);
2490
0
    (void) pr_table_free(netaddr_iptab);
2491
2492
    /* Allocate a fresh table. */
2493
0
    netaddr_iptab = pr_table_alloc(netaddr_pool, 0);
2494
0
  }
2495
2496
0
  if (netaddr_dnstab != NULL) {
2497
0
    pr_trace_msg(trace_channel, 5, "emptying netaddr DNS cache");
2498
0
    (void) pr_table_empty(netaddr_dnstab);
2499
0
    (void) pr_table_free(netaddr_dnstab);
2500
2501
    /* Allocate a fresh table. */
2502
0
    netaddr_dnstab = pr_table_alloc(netaddr_pool, 0);
2503
0
  }
2504
0
}
2505
2506
0
void pr_netaddr_clear_dnscache(const char *ip_str) {
2507
0
  if (netaddr_dnstab != NULL) {
2508
0
    (void) pr_table_remove(netaddr_dnstab, ip_str, NULL);
2509
0
  }
2510
0
}
2511
2512
0
void pr_netaddr_clear_ipcache(const char *name) {
2513
0
  if (netaddr_iptab != NULL) {
2514
0
    (void) pr_table_remove(netaddr_iptab, name, NULL);
2515
0
  }
2516
0
}
2517
2518
0
void init_netaddr(void) {
2519
0
  if (netaddr_pool != NULL) {
2520
0
    pr_netaddr_clear_cache();
2521
0
    destroy_pool(netaddr_pool);
2522
0
    netaddr_pool = NULL;
2523
0
  }
2524
2525
0
  netaddr_pool = make_sub_pool(permanent_pool);
2526
0
  pr_pool_tag(netaddr_pool, "Netaddr API");
2527
2528
0
  netaddr_iptab = pr_table_alloc(netaddr_pool, 0);
2529
0
  netaddr_dnstab = pr_table_alloc(netaddr_pool, 0);
2530
0
}