• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

proftpd / proftpd / 20282775287

16 Dec 2025 09:13PM UTC coverage: 92.995% (-0.002%) from 92.997%
20282775287

push

github

51430 of 55304 relevant lines covered (93.0%)

222.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.08
/src/netaddr.c
1
/*
2
 * ProFTPD - FTP server daemon
3
 * Copyright (c) 2003-2025 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, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18
 *
19
 * As a special exemption, The ProFTPD Project team and other respective
20
 * copyright holders give permission to link this program with OpenSSL, and
21
 * distribute the resulting executable, without including the source code for
22
 * OpenSSL in the source distribution.
23
 */
24

25
/* Network address routines */
26

27
#include "conf.h"
28

29
#if HAVE_NET_IF_H
30
# include <net/if.h>
31
#endif
32
#if HAVE_IFADDRS_H
33
# include <ifaddrs.h>
34
#endif
35

36
/* Define an IPv4 equivalent of the IN6_IS_ADDR_LOOPBACK macro. */
37
#undef IN_IS_ADDR_LOOPBACK
38
#define IN_IS_ADDR_LOOPBACK(a) \
39
  ((((unsigned long int) ntohl((a)->s_addr)) & 0xff000000) == 0x7f000000)
40

41
static pr_netaddr_t sess_local_addr;
42
static int have_sess_local_addr = FALSE;
43

44
static pr_netaddr_t sess_remote_addr;
45
static char sess_remote_name[PR_TUNABLE_BUFFER_SIZE];
46
static int have_sess_remote_addr = FALSE;
47

48
/* Do reverse DNS lookups? */
49
static int reverse_dns = 1;
50

51
/* Use IPv6? */
52
#ifdef PR_USE_IPV6
53
static int use_ipv6 = TRUE;
54
#else
55
static int use_ipv6 = FALSE;
56
#endif /* PR_USE_IPV6 */
57

58
static char localaddr_str[PR_TUNABLE_BUFFER_SIZE];
59
static int have_localaddr_str = FALSE;
60

61
static pool *netaddr_pool = NULL;
62
static pr_table_t *netaddr_iptab = NULL;
63
static pr_table_t *netaddr_dnstab = NULL;
64

65
static const char *trace_channel = "dns";
66

67
/* Netaddr cache management */
68
static array_header *netaddr_dnscache_get(pool *p, const char *ip_str) {
24✔
69
  array_header *res = NULL;
24✔
70

71
  if (netaddr_dnstab != NULL) {
24✔
72
    const void *v;
24✔
73

74
    v = pr_table_get(netaddr_dnstab, ip_str, NULL);
24✔
75
    if (v != NULL) {
24✔
76
      res = (array_header *) v;
15✔
77

78
      pr_trace_msg(trace_channel, 4,
15✔
79
        "using %d DNS %s from netaddr DNS cache for IP address '%s'",
80
        res->nelts, res->nelts != 1 ? "names" : "name", ip_str);
15✔
81

82
      if (p) {
15✔
83
        /* If the caller provided a pool, return a copy of the array. */
84
        return copy_array_str(p, res);
1✔
85
      }
86

87
      return res;
88
    }
89
  }
90

91
  pr_trace_msg(trace_channel, 12,
9✔
92
    "no DNS names found in netaddr DNS cache for IP address '%s'", ip_str);
93
  errno = ENOENT;
9✔
94
  return NULL;
9✔
95
}
96

97
static void netaddr_dnscache_set(const char *ip_str, const char *dns_name) {
22✔
98
  if (netaddr_dnstab != NULL) {
22✔
99
    void *v = NULL;
22✔
100
    array_header *res = NULL;
22✔
101
    int add_list = FALSE;
22✔
102

103
    res = netaddr_dnscache_get(NULL, ip_str);
22✔
104
    if (res == NULL) {
22✔
105
      /* No existing entries for this IP address yet. */
106
      res = make_array(netaddr_pool, 1, sizeof(char *));
8✔
107
      add_list = TRUE;
8✔
108

109
    } else {
110
      register unsigned int i;
14✔
111
      char **names;
14✔
112

113
      /* Check for duplicates. */
114
      names = res->elts;
14✔
115
      for (i = 0; i < res->nelts; i++) {
35✔
116
        if (names[i] != NULL) {
21✔
117
          if (strcmp(names[i], dns_name) == 0) {
21✔
118
            pr_trace_msg(trace_channel, 5,
×
119
              "DNS name '%s' for IP address '%s' already stashed in the "
120
              "netaddr DNS cache", dns_name, ip_str);
121
            return;
×
122
          }
123
        }
124
      }
125
    }
126

127
    *((char **) push_array(res)) = pstrdup(netaddr_pool, dns_name);
22✔
128
    v = res;
22✔
129

130
    if (add_list == TRUE) {
22✔
131
      if (pr_table_add(netaddr_dnstab, pstrdup(netaddr_pool, ip_str), v,
8✔
132
          sizeof(array_header *)) < 0) {
133
        pr_trace_msg(trace_channel, 3,
×
134
          "error adding DNS name '%s' for IP address '%s' to the netaddr "
135
          "DNS cache: %s", dns_name, ip_str, strerror(errno));
×
136

137
      } else {
138
        pr_trace_msg(trace_channel, 5,
8✔
139
          "stashed DNS name '%s' for IP address '%s' in the netaddr DNS cache",
140
          dns_name, ip_str);
141
      }
142

143
    } else {
144
      pr_trace_msg(trace_channel, 5,
14✔
145
        "stashed DNS name '%s' for IP address '%s' in the netaddr DNS cache",
146
        dns_name, ip_str);
147
    }
148
  }
149
}
150

151
static pr_netaddr_t *netaddr_ipcache_get(pool *p, const char *name) {
173✔
152
  pr_netaddr_t *res = NULL;
173✔
153

154
  if (netaddr_iptab != NULL) {
173✔
155
    const void *v;
167✔
156

157
    v = pr_table_get(netaddr_iptab, name, NULL);
167✔
158
    if (v != NULL) {
167✔
159
      res = (pr_netaddr_t *) v;
78✔
160
      pr_trace_msg(trace_channel, 4,
78✔
161
        "using IP address '%s' from netaddr IP cache for name '%s'",
162
        pr_netaddr_get_ipstr(res), name);
163

164
      /* We return a copy of the cache's netaddr_t, if the caller provided
165
       * a pool for duplication.
166
       */
167
      if (p != NULL) {
78✔
168
        pr_netaddr_t *dup_res = NULL;
40✔
169

170
        dup_res = pr_netaddr_dup(p, res);
40✔
171
        if (dup_res == NULL) {
40✔
172
          pr_log_debug(DEBUG0, "error duplicating address for name '%s' "
×
173
            "from cache: %s", name, strerror(errno));
×
174
        }
175

176
        return dup_res;
40✔
177
      }
178

179
      return res;
180
    }
181
  }
182

183
  pr_trace_msg(trace_channel, 2,
95✔
184
    "no IP address found in netaddr IP cache for name '%s'", name);
185
  errno = ENOENT;
95✔
186
  return NULL;
95✔
187
}
188

189
static int netaddr_ipcache_set(const char *name, const pr_netaddr_t *na) {
169✔
190
  if (netaddr_iptab != NULL) {
169✔
191
    int count = 0;
163✔
192
    void *v = NULL;
163✔
193

194
    /* We store an internal copy of the netaddr_t in the cache. */
195
    v = pr_netaddr_dup(netaddr_pool, na);
163✔
196
    if (v == NULL) {
163✔
197
      return -1;
198
    }
199

200
    count = pr_table_exists(netaddr_iptab, name);
159✔
201
    if (count <= 0) {
159✔
202
      if (pr_table_add(netaddr_iptab, pstrdup(netaddr_pool, name), v,
108✔
203
          sizeof(pr_netaddr_t *)) < 0) {
204
        pr_trace_msg(trace_channel, 3,
×
205
          "error adding IP address '%s' for name '%s' to the netaddr "
206
          "IP cache: %s", pr_netaddr_get_ipstr(na), name,
207
          strerror(errno));
×
208

209
      } else {
210
        pr_trace_msg(trace_channel, 5,
108✔
211
          "stashed IP address '%s' for name '%s' in the netaddr IP cache",
212
          pr_netaddr_get_ipstr(v), name);
213
      }
214

215
    } else {
216
      if (pr_table_set(netaddr_iptab, pstrdup(netaddr_pool, name), v,
51✔
217
          sizeof(pr_netaddr_t *)) < 0) {
218
        pr_trace_msg(trace_channel, 3,
×
219
          "error setting IP address '%s' for name '%s' in the netaddr "
220
          "IP cache: %s", pr_netaddr_get_ipstr(na), name, strerror(errno));
×
221
      }
222
    }
223
  }
224

225
  return 0;
226
}
227

228
/* Provide replacements for needed functions. */
229

230
#if !defined(HAVE_GETNAMEINFO) || defined(PR_USE_GETNAMEINFO)
231
int pr_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
232
    size_t hostlen, char *serv, size_t servlen, int flags) {
233

234
  struct sockaddr_in *sai = (struct sockaddr_in *) sa;
235

236
  if (!sai || sai->sin_family != AF_INET)
237
    return EAI_FAMILY;
238

239
  if (serv != NULL && servlen > (size_t) 1)
240
    pr_snprintf(serv, servlen, "%lu", (unsigned long) ntohs(sai->sin_port));
241

242
  if (host != NULL && hostlen > (size_t) 1) {
243
    struct hostent *he = NULL;
244

245
    if ((flags & NI_NUMERICHOST) == 0 &&
246
        (he = gethostbyaddr((const char *) &(sai->sin_addr),
247
          sizeof(sai->sin_addr), AF_INET)) != NULL &&
248
        he->h_name != NULL &&
249
        *he->h_name != 0) {
250

251
      if (strlen(he->h_name) >= hostlen)
252
          goto handle_numeric_ip;
253
      sstrncpy(host, he->h_name, hostlen);
254

255
    } else {
256
      char *ipstr = NULL;
257

258
      handle_numeric_ip:
259
      ipstr = inet_ntoa(sai->sin_addr);
260
      if (ipstr == NULL)
261
        return EAI_SYSTEM;
262

263
      if (strlen(ipstr) >= hostlen)
264
        return EAI_FAIL;
265

266
      sstrncpy(host, ipstr, hostlen);
267
    }
268
  }
269

270
  return 0;
271
}
272
#endif /* HAVE_GETNAMEINFO or PR_USE_GETNAMEINFO */
273

274
#if !defined(HAVE_GETADDRINFO) || defined(PR_USE_GETADDRINFO)
275
int pr_getaddrinfo(const char *node, const char *service,
276
    const struct addrinfo *hints, struct addrinfo **res) {
277
  struct addrinfo *ans = NULL;
278
  struct sockaddr_in *saddr = NULL;
279
  const char *proto_name = "tcp";
280
  int socktype = SOCK_STREAM;
281
  unsigned short port = 0;
282

283
  if (res == NULL) {
284
    return EAI_FAIL;
285
  }
286

287
  *res = NULL;
288

289
  ans = malloc(sizeof(struct addrinfo));
290
  if (ans == NULL) {
291
    return EAI_MEMORY;
292
  }
293

294
  saddr = malloc(sizeof(struct sockaddr_in));
295
  if (saddr == NULL) {
296
    free(ans);
297
    return EAI_MEMORY;
298
  }
299

300
  ans->ai_family = AF_INET;
301
  ans->ai_addrlen = sizeof *saddr;
302
  ans->ai_addr = (struct sockaddr *) saddr;
303
  ans->ai_next = NULL;
304
  memset(saddr, 0, sizeof(*saddr));
305
  saddr->sin_family = AF_INET;
306

307
  if (hints != NULL) {
308
    struct protoent *pe = NULL;
309

310
    if ((pe = getprotobynumber(hints->ai_protocol)) != NULL &&
311
         pe->p_name != NULL &&
312
         *pe->p_name != 0)
313
      proto_name = pe->p_name;
314

315
    if (hints->ai_socktype != 0) {
316
      socktype = hints->ai_socktype;
317

318
    } else if (strncasecmp(proto_name, "udp", 4) == 0) {
319
      socktype = SOCK_DGRAM;
320
    }
321
  }
322

323
  if (service != NULL) {
324
    struct servent *se = NULL;
325

326
    if ((se = getservbyname(service, proto_name)) != NULL &&
327
        se->s_port > 0) {
328
      port = se->s_port;
329

330
    } else if ((port = (unsigned short) strtoul(service, NULL, 0)) <= 0 ||
331
        port > 65535) {
332
      port = 0;
333
    }
334
  }
335

336
  if (hints != NULL &&
337
      (hints->ai_flags & AI_PASSIVE) != 0)
338
    saddr->sin_addr.s_addr = htonl(INADDR_ANY);
339

340
  if (node != NULL) {
341
    struct hostent *he = NULL;
342

343
    if ((he = gethostbyname(node)) != NULL &&
344
         he->h_addr_list != NULL &&
345
         he->h_addr_list[0] != NULL &&
346
         he->h_length > 0 &&
347
         he->h_length <= (int) sizeof(saddr->sin_addr))
348
      memcpy(&saddr->sin_addr, he->h_addr_list[0], he->h_length);
349
  }
350

351
  ans->ai_socktype = socktype;
352
  saddr->sin_port = htons(port);
353
  *res = ans;
354

355
  return 0;
356
}
357

358
void pr_freeaddrinfo(struct addrinfo *ai) {
359
  if (ai == NULL) {
360
    return;
361
  }
362

363
  if (ai->ai_addr != NULL) {
364
    free(ai->ai_addr);
365
    ai->ai_addr = NULL;
366
  }
367

368
  free(ai);
369
}
370
#endif /* HAVE_GETADDRINFO or PR_USE_GETADDRINFO */
371

372
#if !defined(HAVE_INET_NTOP)
373
const char *pr_inet_ntop(int af, const void *src, char *dst, size_t len) {
374
  char *res;
375

376
  if (af != AF_INET) {
377
    errno = EAFNOSUPPORT;
378
    return NULL;
379
  }
380

381
  res = inet_ntoa(*((struct in_addr *) src));
382
  if (res == NULL)
383
    return NULL;
384

385
  memcpy(dst, res, len);
386
  return dst;
387
}
388
#endif /* !HAVE_INET_NTOP */
389

390
#if !defined(HAVE_INET_PTON)
391
int pr_inet_pton(int af, const char *src, void *dst) {
392
  unsigned long res;
393

394
  if (af != AF_INET) {
395
    errno = EAFNOSUPPORT;
396
    return -1;
397
  }
398

399
  /* inet_aton(3) would be better. However, it is not ubiquitous.  */
400
  res = inet_addr(src);
401
  if (res == INADDR_NONE ||
402
      res == 0)
403
    return 0;
404

405
  memcpy(dst, &res, sizeof(res));
406
  return 1;
407
}
408
#endif /* !HAVE_INET_PTON */
409

410
static void *get_v4inaddr(const pr_netaddr_t *na) {
9✔
411

412
  /* This function is specifically for IPv4 clients (when gethostbyname2(2) is
413
   * present) that have an IPv4-mapped IPv6 address, when performing reverse
414
   * DNS checks.  This function is called iff the given netaddr object is
415
   * indeed an IPv4-mapped IPv6 address.  IPv6 address have 128 bits in their
416
   * sin6_addr field.  For IPv4-mapped IPv6 addresses, the relevant 32 bits
417
   * are the last of those 128 bits (or, alternatively, the last 4 bytes of
418
   * those 16 bytes); hence the read of 12 bytes after the start of the
419
   * sin6_addr pointer.
420
   */
421

422
  return (((char *) pr_netaddr_get_inaddr(na)) + 12);
18✔
423
}
424

425
/* Validate anything returned from the 'outside', since it's untrusted
426
 * information.
427
 */
428
char *pr_netaddr_validate_dns_str(char *buf) {
14✔
429
  char *p;
14✔
430

431
  if (buf == NULL) {
14✔
432
    errno = EINVAL;
1✔
433
    return NULL;
1✔
434
  }
435

436
  /* Validate anything returned from a DNS. */
437
  for (p = buf; p && *p; p++) {
124✔
438

439
    /* Per RFC requirements, these are all that are valid from a DNS. */
440
    if (!PR_ISALNUM(*p) &&
111✔
441
        *p != '.' &&
442
        *p != '-'
443
#ifdef PR_USE_IPV6
444
        && *p != ':'
445
#endif /* PR_USE_IPV6 */
446
        ) {
447

448
      /* We set it to _ because we know that's an invalid, yet safe, option
449
       * for a DNS entry.
450
       */
451
      *p = '_';
2✔
452
    }
453
  }
454

455
  return buf;
456
}
457

458
int pr_netaddr_set_reverse_dns(int enable) {
20✔
459
  int old_enable = reverse_dns;
20✔
460
  reverse_dns = enable;
20✔
461
  return old_enable;
20✔
462
}
463

464
pr_netaddr_t *pr_netaddr_alloc(pool *p) {
306✔
465
  if (p == NULL) {
306✔
466
    errno = EINVAL;
1✔
467
    return NULL;
1✔
468
  }
469

470
  return pcalloc(p, sizeof(pr_netaddr_t));
305✔
471
}
472

473
void pr_netaddr_clear(pr_netaddr_t *na) {
82✔
474
  if (na == NULL) {
82✔
475
    return;
476
  }
477

478
  memset(na, 0, sizeof(pr_netaddr_t));
81✔
479
}
480

481
pr_netaddr_t *pr_netaddr_dup(pool *p, const pr_netaddr_t *na) {
209✔
482
  pr_netaddr_t *dup_na;
209✔
483

484
  if (p == NULL ||
209✔
485
      na == NULL) {
209✔
486
    errno = EINVAL;
3✔
487
    return NULL;
3✔
488
  }
489

490
  dup_na = pr_netaddr_alloc(p);
206✔
491

492
  if (pr_netaddr_set_family(dup_na, pr_netaddr_get_family(na)) < 0) {
206✔
493
    return NULL;
494
  }
495

496
  pr_netaddr_set_sockaddr(dup_na, pr_netaddr_get_sockaddr(na));
202✔
497

498
  if (na->na_have_ipstr) {
202✔
499
    sstrncpy(dup_na->na_ipstr, na->na_ipstr, sizeof(dup_na->na_ipstr));
201✔
500
    dup_na->na_have_ipstr = 1;
201✔
501
  }
502

503
  if (na->na_have_dnsstr) {
202✔
504
    sstrncpy(dup_na->na_dnsstr, na->na_dnsstr, sizeof(dup_na->na_dnsstr));
30✔
505
    dup_na->na_have_dnsstr = 1;
30✔
506
  }
507

508
  return dup_na;
509
}
510

511
static pr_netaddr_t *get_addr_by_ip(pool *p, const char *name,
98✔
512
    array_header **addrs, unsigned int flags) {
513
  struct sockaddr_in v4;
98✔
514
  pr_netaddr_t *na = NULL;
98✔
515
  int res;
98✔
516

517
#ifdef PR_USE_IPV6
518
  if (use_ipv6 == TRUE) {
98✔
519
    struct sockaddr_in6 v6;
98✔
520
    memset(&v6, 0, sizeof(v6));
98✔
521
    v6.sin6_family = AF_INET6;
98✔
522

523
# ifdef SIN6_LEN
524
    v6.sin6_len = sizeof(struct sockaddr_in6);
525
# endif /* SIN6_LEN */
526

527
    res = pr_inet_pton(AF_INET6, name, &v6.sin6_addr);
98✔
528
    if (res > 0) {
98✔
529
      na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
30✔
530
      pr_netaddr_set_family(na, AF_INET6);
30✔
531
      pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v6);
30✔
532
      if (addrs != NULL) {
30✔
533
        *addrs = NULL;
1✔
534
      }
535

536
      pr_trace_msg(trace_channel, 7, "'%s' resolved to IPv6 address %s", name,
30✔
537
        pr_netaddr_get_ipstr(na));
538

539
      if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_CACHE)) {
30✔
540
        if (netaddr_ipcache_set(name, na) < 0) {
30✔
541
          pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
×
542
            name, strerror(errno));
×
543
        }
544

545
        if (netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na) < 0) {
30✔
546
          pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
×
547
            pr_netaddr_get_ipstr(na), strerror(errno));
×
548
        }
549
      }
550

551
      return na;
30✔
552
    }
553
  }
554
#endif /* PR_USE_IPV6 */
555

556
  memset(&v4, 0, sizeof(v4));
68✔
557
  v4.sin_family = AF_INET;
68✔
558

559
# ifdef SIN_LEN
560
  v4.sin_len = sizeof(struct sockaddr_in);
561
# endif /* SIN_LEN */
562

563
  res = pr_inet_pton(AF_INET, name, &v4.sin_addr);
68✔
564
  if (res > 0) {
68✔
565
    na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
47✔
566
    pr_netaddr_set_family(na, AF_INET);
47✔
567
    pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v4);
47✔
568
    if (addrs != NULL) {
47✔
569
      *addrs = NULL;
1✔
570
    }
571

572
    pr_trace_msg(trace_channel, 7, "'%s' resolved to IPv4 address %s", name,
47✔
573
      pr_netaddr_get_ipstr(na));
574

575
    if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_DNS)) {
47✔
576
      if (netaddr_ipcache_set(name, na) < 0) {
47✔
577
        pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s", name,
×
578
          strerror(errno));
×
579
      }
580

581
      /* Avoid duplicates. */
582
      if (strcmp(name, pr_netaddr_get_ipstr(na)) != 0) {
47✔
583
        if (netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na) < 0) {
×
584
          pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
×
585
            pr_netaddr_get_ipstr(na), strerror(errno));
×
586
        }
587
      }
588
    }
589

590
    return na;
47✔
591
  }
592

593
  return NULL;
594
}
595

596
static pr_netaddr_t *get_addr_by_name(pool *p, const char *name,
20✔
597
    array_header **addrs, unsigned int flags) {
598
  pr_netaddr_t *na = NULL;
20✔
599
  int res, xerrno;
20✔
600
  struct addrinfo hints, *info = NULL;
20✔
601

602
  memset(&hints, 0, sizeof(hints));
20✔
603
  hints.ai_family = AF_INET;
20✔
604
  hints.ai_socktype = SOCK_STREAM;
20✔
605
  hints.ai_protocol = IPPROTO_TCP;
20✔
606
  info = NULL;
20✔
607

608
  xerrno = errno;
20✔
609
  pr_trace_msg(trace_channel, 7,
20✔
610
    "attempting to resolve '%s' to IPv4 address via DNS", name);
611
  errno = xerrno;
20✔
612
  res = pr_getaddrinfo(name, NULL, &hints, &info);
20✔
613
  if (res != 0) {
20✔
614
    xerrno = errno;
8✔
615

616
    if (res != EAI_SYSTEM) {
8✔
617
#ifdef PR_USE_IPV6
618
      if (use_ipv6 == TRUE) {
8✔
619
        pr_trace_msg(trace_channel, 7,
8✔
620
          "unable to resolve '%s' to an IPv4 address: %s", name,
621
          pr_gai_strerror(res));
622

623
        memset(&hints, 0, sizeof(hints));
8✔
624
        hints.ai_family = AF_INET6;
8✔
625
        hints.ai_socktype = SOCK_STREAM;
8✔
626
        hints.ai_protocol = IPPROTO_TCP;
8✔
627
        info = NULL;
8✔
628

629
        pr_trace_msg(trace_channel, 7,
8✔
630
          "attempting to resolve '%s' to IPv6 address via DNS", name);
631
        errno = xerrno;
8✔
632
        res = pr_getaddrinfo(name, NULL, &hints, &info);
8✔
633
        xerrno = errno;
8✔
634

635
        if (res != 0) {
8✔
636
          if (res != EAI_SYSTEM) {
8✔
637
            pr_trace_msg(trace_channel, 5,
8✔
638
              "unable to resolve '%s' to an IPv6 address: %s", name,
639
              pr_gai_strerror(res));
640

641
            if (res == EAI_NODATA ||
8✔
642
                res == EAI_NONAME) {
8✔
643
              xerrno = ENOENT;
644
# if defined(EAFNOSUPPORT)
645
            } else if (res == EAI_FAMILY) {
3✔
646
              xerrno = EAFNOSUPPORT;
×
647
# endif /* EAFNOSUPPORT */
648
            }
649

650
          } else {
651
            pr_trace_msg(trace_channel, 1,
×
652
              "IPv6 getaddrinfo '%s' system error: [%d] %s", name,
653
              xerrno, strerror(xerrno));
654
          }
655
        }
656

657
      } else {
658
        const char *errstr;
×
659

660
        errstr = pr_gai_strerror(res);
×
661
        pr_trace_msg(trace_channel, 1, "IPv4 getaddrinfo '%s' error: %s",
×
662
          name, errstr);
663

664
        if (res == EAI_NODATA ||
×
665
            res == EAI_NONAME) {
×
666
          xerrno = ENOENT;
667
# if defined(EAFNOSUPPORT)
668
        } else if (res == EAI_FAMILY) {
×
669
          xerrno = EAFNOSUPPORT;
670
# endif /* EAFNOSUPPORT */
671
        } else {
672
          /* Note that this is a hack, to deal with GNU/Linux custom
673
           * gai_strerror(3) values which are not exported in the <netdb.h>
674
           * header by default.
675
           */
676
          if (strcmp(errstr, "Address family for hostname not supported") == 0) {
×
677
            xerrno = EAFNOSUPPORT;
×
678
          }
679
        }
680
      }
681
#else
682
      pr_trace_msg(trace_channel, 1, "IPv4 getaddrinfo '%s' error: %s",
683
        name, pr_gai_strerror(res));
684
      if (res == EAI_NODATA ||
685
          res == EAI_NONAME) {
686
        xerrno = ENOENT;
687
# if defined(EAFNOSUPPORT)
688
      } else if (res == EAI_FAMILY) {
689
        xerrno = EAFNOSUPPORT;
690
# endif /* EAFNOSUPPORT */
691
      }
692
#endif /* PR_USE_IPV6 */
693

694
    } else {
695
      pr_trace_msg(trace_channel, 1,
×
696
        "IPv4 getaddrinfo '%s' system error: [%d] %s", name,
697
        xerrno, strerror(xerrno));
698
    }
699

700
    if (res != 0) {
8✔
701
      errno = xerrno;
8✔
702
      return NULL;
8✔
703
    }
704
  }
705

706
  if (info != NULL) {
12✔
707
    na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
12✔
708

709
    /* Copy the first returned addr into na, as the return value. */
710
    pr_netaddr_set_family(na, info->ai_family);
12✔
711
    pr_netaddr_set_sockaddr(na, info->ai_addr);
12✔
712

713
    pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
24✔
714
      info->ai_family == AF_INET ? "IPv4" : "IPv6",
12✔
715
      pr_netaddr_get_ipstr(na));
716

717
    if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_DNS)) {
12✔
718
      if (netaddr_ipcache_set(name, na) < 0) {
12✔
719
        pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s", name,
×
720
          strerror(errno));
721
      }
722

723
      if (netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na) < 0) {
12✔
724
        pr_trace_msg(trace_channel, 2, "error setting '%s' in cache: %s",
×
725
          pr_netaddr_get_ipstr(na), strerror(errno));
726
      }
727
    }
728

729
    if (addrs != NULL) {
12✔
730
      struct addrinfo *next_info = NULL;
3✔
731

732
      /* Copy any other addrs into the list. */
733
      if (*addrs == NULL) {
3✔
734
        *addrs = make_array(p, 0, sizeof(pr_netaddr_t *));
2✔
735
      }
736

737
      next_info = info->ai_next;
3✔
738
      while (next_info != NULL) {
14✔
739
        pr_netaddr_t **elt;
11✔
740

741
        pr_signals_handle();
11✔
742
        elt = push_array(*addrs);
11✔
743

744
        *elt = pcalloc(p, sizeof(pr_netaddr_t));
11✔
745
        pr_netaddr_set_family(*elt, next_info->ai_family);
11✔
746
        pr_netaddr_set_sockaddr(*elt, next_info->ai_addr);
11✔
747

748
        pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
22✔
749
          next_info->ai_family == AF_INET ? "IPv4" : "IPv6",
11✔
750
          pr_netaddr_get_ipstr(*elt));
751

752
        next_info = next_info->ai_next;
11✔
753
      }
754
    }
755

756
    pr_freeaddrinfo(info);
12✔
757
  }
758

759
#ifdef PR_USE_IPV6
760
  if (use_ipv6 == TRUE &&
12✔
761
      addrs != NULL) {
762
    /* Do the call again, this time for IPv6 addresses.
763
     *
764
     * We make two separate getaddrinfo(3) calls, rather than one
765
     * with a hint of AF_UNSPEC, because of certain bugs where the use
766
     * of AF_UNSPEC does not function as advertised.  (I suspect this
767
     * bug was caused by proftpd's calling pattern, but as I could
768
     * not track it down, and as there are reports of AF_UNSPEC not
769
     * being as fast as AF_INET/AF_INET6, it just seemed easier to
770
     * do it this way.)
771
     */
772

773
    memset(&hints, 0, sizeof(hints));
3✔
774
    hints.ai_family = AF_INET6;
3✔
775
    hints.ai_socktype = SOCK_STREAM;
3✔
776
    hints.ai_protocol = IPPROTO_TCP;
3✔
777
    info = NULL;
3✔
778

779
    pr_trace_msg(trace_channel, 7,
3✔
780
      "attempting to resolve '%s' to IPv6 address via DNS", name);
781
    res = pr_getaddrinfo(name, NULL, &hints, &info);
3✔
782
    xerrno = errno;
3✔
783

784
    if (res != 0) {
3✔
785
      if (res != EAI_SYSTEM) {
×
786
        pr_trace_msg(trace_channel, 1, "IPv6 getaddrinfo '%s' error: %s",
×
787
          name, pr_gai_strerror(res));
788

789
      } else {
790
        pr_trace_msg(trace_channel, 1,
×
791
          "IPv6 getaddrinfo '%s' system error: [%d] %s", name,
792
          xerrno, strerror(xerrno));
793
      }
794

795
    } else {
796
      /* We may have already looked up an IPv6 address as the first
797
       * address; we don't want to have duplicate addresses in the
798
       * returned list of additional addresses.
799
       */
800
      if (info != NULL) {
3✔
801
        struct addrinfo *next_info = NULL;
3✔
802

803
        /* Copy any other addrs into the list. */
804
        if (*addrs == NULL) {
3✔
805
          *addrs = make_array(p, 0, sizeof(pr_netaddr_t *));
×
806
        }
807

808
        /* Note that for this subsequent IPv6 lookup, we need to treat the
809
         * first struct addrinfo as an "additional" record, unlike our handling
810
         * of IPv4 results.  Failure to do so means we might miss some IPv6
811
         * addresses; see Bug#4428.
812
         */
813
        next_info = info;
3✔
814
        while (next_info != NULL) {
12✔
815
          pr_netaddr_t **elt;
9✔
816

817
          pr_signals_handle();
9✔
818
          elt = push_array(*addrs);
9✔
819

820
          *elt = pcalloc(p, sizeof(pr_netaddr_t));
9✔
821
          pr_netaddr_set_family(*elt, next_info->ai_family);
9✔
822
          pr_netaddr_set_sockaddr(*elt, next_info->ai_addr);
9✔
823

824
          pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
18✔
825
            next_info->ai_family == AF_INET ? "IPv4" : "IPv6",
9✔
826
            pr_netaddr_get_ipstr(*elt));
827

828
          next_info = next_info->ai_next;
9✔
829
        }
830

831
        pr_freeaddrinfo(info);
3✔
832
      }
833
    }
834
  }
835
#endif /* PR_USE_IPV6 */
836

837
  return na;
838
}
839

840
static pr_netaddr_t *get_addr_by_device(pool *p, const char *name,
3✔
841
    array_header **addrs, unsigned int flags) {
842
#ifdef HAVE_GETIFADDRS
843
  struct ifaddrs *ifaddr = NULL;
3✔
844
  pr_netaddr_t *na = NULL;
3✔
845
  int res, xerrno;
3✔
846

847
  /* Try to use the given name as a device/interface name, and see if we
848
   * can suss out the IP address(es) to use based on that.
849
   */
850

851
  res = getifaddrs(&ifaddr);
3✔
852
  if (res < 0) {
3✔
853
    xerrno = errno;
×
854

855
    pr_trace_msg(trace_channel, 1,
×
856
      "error retrieving interfaces via getifaddrs(3): %s", strerror(xerrno));
857

858
  } else {
859
    struct ifaddrs *ifa;
3✔
860
    int found_device = FALSE;
3✔
861

862
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
15✔
863
      pr_signals_handle();
13✔
864

865
      /* Watch out for null ifa_addr, as when a device does not have
866
       * an associated address (e.g. due to not be initialized).
867
       */
868
      if (ifa->ifa_addr == NULL) {
13✔
869
        continue;
×
870
      }
871

872
      /* We're only looking for addresses, not stats. */
873
      if (ifa->ifa_addr->sa_family != AF_INET
19✔
874
#ifdef PR_USE_IPV6
875
          && ifa->ifa_addr->sa_family != AF_INET6
13✔
876
#endif /* PR_USE_IPV6 */
877
         ) {
878
        continue;
6✔
879
      }
880

881
      if (strcmp(ifa->ifa_name, name) == 0) {
7✔
882
        if (found_device == FALSE) {
1✔
883
          na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));
1✔
884

885
          pr_netaddr_set_family(na, ifa->ifa_addr->sa_family);
1✔
886
          pr_netaddr_set_sockaddr(na, ifa->ifa_addr);
1✔
887

888
          pr_trace_msg(trace_channel, 7,
2✔
889
            "resolved '%s' to interface with %s address %s", name,
890
            ifa->ifa_addr->sa_family == AF_INET ? "IPv4" : "IPv6",
1✔
891
            pr_netaddr_get_ipstr(na));
892

893
          found_device = TRUE;
1✔
894

895
          /* If the caller did not request additional addresses, then
896
           * return now.  Otherwise, we keep looking for the other
897
           * addresses bound to this interface.
898
           */
899
          if (addrs == NULL) {
1✔
900
            break;
901
          }
902

903
        } else {
904
          pr_netaddr_t **elt;
×
905

906
          /* We've already found the first match; this block happens
907
           * if the caller wants all of the addresses for this interface.
908
           */
909

910
          *addrs = make_array(p, 0, sizeof(pr_netaddr_t *));
×
911
          elt = push_array(*addrs);
×
912

913
          *elt = pcalloc(p, sizeof(pr_netaddr_t));
×
914
          pr_netaddr_set_family(*elt, ifa->ifa_addr->sa_family);
×
915
          pr_netaddr_set_sockaddr(*elt, ifa->ifa_addr);
×
916

917
          pr_trace_msg(trace_channel, 7,
×
918
            "resolved '%s' to interface with %s address %s", name,
919
            ifa->ifa_addr->sa_family == AF_INET ? "IPv4" : "IPv6",
×
920
            pr_netaddr_get_ipstr(*elt));
921
        }
922
      }
923
    }
924

925
    if (ifaddr != NULL) {
3✔
926
      freeifaddrs(ifaddr);
3✔
927
    }
928

929
    if (found_device) {
3✔
930
      return na;
931
    }
932
  }
933

934
  errno = ENOENT;
2✔
935
#else
936
  errno = ENOSYS;
937
#endif /* HAVE_GETIFADDRS */
938

939
  return NULL;
2✔
940
}
941

942
const pr_netaddr_t *pr_netaddr_get_addr2(pool *p, const char *name,
141✔
943
    array_header **addrs, unsigned int flags) {
944
  pr_netaddr_t *na = NULL;
141✔
945
  int xerrno = ENOENT;
141✔
946

947
  if (p == NULL ||
141✔
948
      name == NULL) {
141✔
949
    errno = EINVAL;
3✔
950
    return NULL;
3✔
951
  }
952

953
  pr_trace_msg(trace_channel, 10, "resolving name '%s' to IP address",
138✔
954
    name);
955

956
  /* First, check our cache to see if this name has already been
957
   * resolved.  We only want to use the cache, though, if the caller did not
958
   * provide the `addrs' pointer, indicating that the caller wants to know
959
   * about any additional addresses for the given name.  The netaddr cache
960
   * is a simple cache, hidden from callers, and thus is unable to populate
961
   * that `addrs' pointer if the name is in the cache.
962
   */
963
  if (addrs == NULL) {
138✔
964
    na = netaddr_ipcache_get(p, name);
133✔
965
    if (na != NULL) {
133✔
966
      return na;
967
    }
968
  }
969

970
  /* Attempt to translate the given name into a pr_netaddr_t using
971
   * pr_inet_pton() first.
972
   *
973
   * First, if IPv6 support is enabled, we try to translate the name using
974
   * pr_inet_pton(AF_INET6) on the hopes that the given string is a valid
975
   * representation of an IPv6 address.  If that fails, or if IPv6 support
976
   * is not enabled, we try with pr_inet_pton(AF_INET).  If that fails, we
977
   * assume that the given name is a DNS name, and we call pr_getaddrinfo().
978
   */
979

980
  na = get_addr_by_ip(p, name, addrs, flags);
98✔
981
  xerrno = errno;
98✔
982

983
  if (na != NULL) {
98✔
984
    return na;
985
  }
986

987
  /* If get_addr_by_ip() returns NULL, it means that name does not represent a
988
   * valid network address in the specified address family.  Usually,
989
   * this means that name is actually a DNS name, not an IP address
990
   * string.  So we treat it as a DNS name, and use getaddrinfo(3) to
991
   * resolve that name to its IP address(es) -- unless the EXCL_DNS flag
992
   * has been used, indicating that the caller does not want us resolving
993
   * DNS names.
994
   */
995

996
  if (!(flags & PR_NETADDR_GET_ADDR_FL_EXCL_DNS)) {
21✔
997
    na = get_addr_by_name(p, name, addrs, flags);
20✔
998
    xerrno = errno;
20✔
999

1000
    if (na != NULL) {
20✔
1001
      return na;
1002
    }
1003
  }
1004

1005
  if (flags & PR_NETADDR_GET_ADDR_FL_INCL_DEVICE) {
9✔
1006
    na = get_addr_by_device(p, name, addrs, flags);
3✔
1007
    xerrno = errno;
3✔
1008

1009
    if (na != NULL) {
3✔
1010
      return na;
1011
    }
1012
  }
1013

1014
  pr_trace_msg(trace_channel, 8, "failed to resolve '%s' to an IP address",
8✔
1015
    name);
1016
  errno = xerrno;
8✔
1017
  return NULL;
8✔
1018
}
1019

1020
const pr_netaddr_t *pr_netaddr_get_addr(pool *p, const char *name,
136✔
1021
    array_header **addrs) {
1022
  return pr_netaddr_get_addr2(p, name, addrs, 0);
135✔
1023
}
1024

1025
int pr_netaddr_get_family(const pr_netaddr_t *na) {
2,111✔
1026
  if (na == NULL) {
185✔
1027
    errno = EINVAL;
2✔
1028
    return -1;
2✔
1029
  }
1030

1031
  return na->na_family;
443✔
1032
}
1033

1034
int pr_netaddr_set_family(pr_netaddr_t *na, int family) {
501✔
1035
  if (!na) {
501✔
1036
    errno = EINVAL;
1✔
1037
    return -1;
1✔
1038
  }
1039

1040
  /* Set the family member of the appropriate sockaddr struct. */
1041
  switch (family) {
500✔
1042
    case AF_INET:
295✔
1043
      na->na_addr.v4.sin_family = AF_INET;
295✔
1044
      break;
295✔
1045

1046
#ifdef PR_USE_IPV6
1047
    case AF_INET6:
199✔
1048
      if (use_ipv6 == TRUE) {
199✔
1049
        na->na_addr.v6.sin6_family = AF_INET6;
199✔
1050
        break;
199✔
1051
      }
1052
#endif /* PR_USE_IPV6 */
1053

1054
    default:
1055
#ifdef EAFNOSUPPORT
1056
      errno = EAFNOSUPPORT;
6✔
1057
#else
1058
      errno = EINVAL;
1059
#endif
1060
      return -1;
6✔
1061
  }
1062

1063
  na->na_family = family;
494✔
1064
  return 0;
494✔
1065
}
1066

1067
size_t pr_netaddr_get_sockaddr_len(const pr_netaddr_t *na) {
370✔
1068
  if (na == NULL) {
370✔
1069
    errno = EINVAL;
1✔
1070
    return -1;
1✔
1071
  }
1072

1073
  switch (pr_netaddr_get_family(na)) {
369✔
1074
    case AF_INET:
1075
      return sizeof(struct sockaddr_in);
1076

1077
#if defined(PR_USE_IPV6)
1078
    case AF_INET6:
170✔
1079
      if (use_ipv6 == TRUE) {
170✔
1080
        return sizeof(struct sockaddr_in6);
1081
      }
1082
#endif /* PR_USE_IPV6 */
1083
  }
1084

1085
  errno = EPERM;
14✔
1086
  return -1;
14✔
1087
}
1088

1089
size_t pr_netaddr_get_inaddr_len(const pr_netaddr_t *na) {
4✔
1090
  if (na == NULL) {
4✔
1091
    errno = EINVAL;
1✔
1092
    return -1;
1✔
1093
  }
1094

1095
  switch (pr_netaddr_get_family(na)) {
3✔
1096
    case AF_INET:
1097
      return sizeof(struct in_addr);
1098

1099
#ifdef PR_USE_IPV6
1100
    case AF_INET6:
1✔
1101
      return sizeof(struct in6_addr);
1✔
1102
#endif /* PR_USE_IPV6 */
1103
  }
1104

1105
  errno = EPERM;
1✔
1106
  return -1;
1✔
1107
}
1108

1109
struct sockaddr *pr_netaddr_get_sockaddr(const pr_netaddr_t *na) {
675✔
1110
  if (na == NULL) {
675✔
1111
    errno = EINVAL;
1✔
1112
    return NULL;
1✔
1113
  }
1114

1115
  switch (pr_netaddr_get_family(na)) {
674✔
1116
    case AF_INET:
371✔
1117
      return (struct sockaddr *) &na->na_addr.v4;
371✔
1118

1119
#if defined(PR_USE_IPV6)
1120
    case AF_INET6:
290✔
1121
      if (use_ipv6 == TRUE) {
290✔
1122
        return (struct sockaddr *) &na->na_addr.v6;
289✔
1123
      }
1124
#endif /* PR_USE_IPV6 */
1125
  }
1126

1127
  errno = EPERM;
14✔
1128
  return NULL;
14✔
1129
}
1130

1131
int pr_netaddr_set_sockaddr(pr_netaddr_t *na, struct sockaddr *addr) {
417✔
1132
  if (na == NULL ||
417✔
1133
      addr == NULL) {
417✔
1134
    errno = EINVAL;
2✔
1135
    return -1;
2✔
1136
  }
1137

1138
  memset(&na->na_addr, 0, sizeof(na->na_addr));
415✔
1139
  switch (na->na_family) {
415✔
1140
    case AF_INET:
261✔
1141
      memcpy(&(na->na_addr.v4), addr, sizeof(struct sockaddr_in));
261✔
1142
      return 0;
261✔
1143

1144
#if defined(PR_USE_IPV6)
1145
    case AF_INET6:
153✔
1146
      if (use_ipv6 == TRUE) {
153✔
1147
        memcpy(&(na->na_addr.v6), addr, sizeof(struct sockaddr_in6));
152✔
1148
        return 0;
152✔
1149
      }
1150
#endif /* PR_USE_IPV6 */
1151
  }
1152

1153
  errno = EPERM;
2✔
1154
  return -1;
2✔
1155
}
1156

1157
int pr_netaddr_set_sockaddr_any(pr_netaddr_t *na) {
64✔
1158
  if (na == NULL) {
64✔
1159
    errno = EINVAL;
1✔
1160
    return -1;
1✔
1161
  }
1162

1163
  switch (pr_netaddr_get_family(na)) {
63✔
1164
    case AF_INET: {
1165
      struct in_addr in4addr_any;
22✔
1166
      in4addr_any.s_addr = htonl(INADDR_ANY);
22✔
1167
      na->na_addr.v4.sin_family = AF_INET;
22✔
1168
#ifdef SIN_LEN
1169
      na->na_addr.v4.sin_len = sizeof(struct sockaddr_in);
1170
#endif /* SIN_LEN */
1171
      memcpy(&na->na_addr.v4.sin_addr, &in4addr_any, sizeof(struct in_addr));
22✔
1172
      if (na->na_have_ipstr) {
22✔
1173
        memset(na->na_ipstr, '\0', sizeof(na->na_ipstr));
1✔
1174
        sstrncpy(na->na_ipstr, "0.0.0.0", sizeof(na->na_ipstr));
1✔
1175
      }
1176
      return 0;
22✔
1177
    }
1178

1179
#ifdef PR_USE_IPV6
1180
    case AF_INET6:
40✔
1181
      if (use_ipv6 == TRUE) {
40✔
1182
        na->na_addr.v6.sin6_family = AF_INET6;
39✔
1183
#ifdef SIN6_LEN
1184
        na->na_addr.v6.sin6_len = sizeof(struct sockaddr_in6);
1185
#endif /* SIN6_LEN */
1186
        memcpy(&na->na_addr.v6.sin6_addr, &in6addr_any, sizeof(struct in6_addr));
39✔
1187
        if (na->na_have_ipstr) {
39✔
1188
          memset(na->na_ipstr, '\0', sizeof(na->na_ipstr));
1✔
1189
          sstrncpy(na->na_ipstr, "::", sizeof(na->na_ipstr));
1✔
1190
        }
1191
        return 0;
39✔
1192
      }
1193
#endif /* PR_USE_IPV6 */
1194
  }
1195

1196
  errno = EPERM;
2✔
1197
  return -1;
2✔
1198
}
1199

1200
void *pr_netaddr_get_inaddr(const pr_netaddr_t *na) {
79✔
1201
  if (na == NULL) {
79✔
1202
    errno = EINVAL;
1✔
1203
    return NULL;
1✔
1204
  }
1205

1206
  switch (pr_netaddr_get_family(na)) {
78✔
1207
    case AF_INET:
23✔
1208
      return (void *) &na->na_addr.v4.sin_addr;
23✔
1209

1210
#ifdef PR_USE_IPV6
1211
    case AF_INET6:
54✔
1212
      if (use_ipv6 == TRUE) {
54✔
1213
        return (void *) &na->na_addr.v6.sin6_addr;
53✔
1214
      }
1215
#endif /* PR_USE_IPV6 */
1216
  }
1217

1218
  errno = EPERM;
2✔
1219
  return NULL;
2✔
1220
}
1221

1222
unsigned int pr_netaddr_get_port(const pr_netaddr_t *na) {
87✔
1223
  if (na == NULL) {
87✔
1224
    errno = EINVAL;
1✔
1225
    return 0;
1✔
1226
  }
1227

1228
  switch (pr_netaddr_get_family(na)) {
86✔
1229
    case AF_INET:
34✔
1230
      return na->na_addr.v4.sin_port;
34✔
1231

1232
#ifdef PR_USE_IPV6
1233
    case AF_INET6:
51✔
1234
      if (use_ipv6 == TRUE) {
51✔
1235
        return na->na_addr.v6.sin6_port;
51✔
1236
      }
1237
#endif /* PR_USE_IPV6 */
1238
  }
1239

1240
  errno = EPERM;
1✔
1241
  return 0;
1✔
1242
}
1243

1244
int pr_netaddr_set_port(pr_netaddr_t *na, unsigned int port) {
97✔
1245
  if (!na) {
97✔
1246
    errno = EINVAL;
1✔
1247
    return -1;
1✔
1248
  }
1249

1250
  switch (pr_netaddr_get_family(na)) {
96✔
1251
    case AF_INET:
52✔
1252
      na->na_addr.v4.sin_port = port;
52✔
1253
      return 0;
52✔
1254

1255
#ifdef PR_USE_IPV6
1256
    case AF_INET6:
43✔
1257
      if (use_ipv6) {
43✔
1258
        na->na_addr.v6.sin6_port = port;
43✔
1259
        return 0;
43✔
1260
      }
1261
#endif /* PR_USE_IPV6 */
1262
  }
1263

1264
  errno = EPERM;
1✔
1265
  return -1;
1✔
1266
}
1267

1268
int pr_netaddr_set_port2(pr_netaddr_t *na, unsigned int port) {
3✔
1269
  return pr_netaddr_set_port(na, htons(port));
3✔
1270
}
1271

1272
int pr_netaddr_cmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2) {
20✔
1273
  pool *tmp_pool = NULL;
20✔
1274
  pr_netaddr_t *a, *b;
20✔
1275
  int res;
20✔
1276

1277
  if (na1 != NULL &&
20✔
1278
      na2 == NULL) {
20✔
1279
    return 1;
1280
  }
1281

1282
  if (na1 == NULL &&
19✔
1283
      na2 != NULL) {
19✔
1284
    return -1;
1285
  }
1286

1287
  if (na1 == NULL &&
18✔
1288
      na2 == NULL) {
1289
    return 0;
1290
  }
1291

1292
  if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {
51✔
1293

1294
    /* Cannot compare addresses from different families, unless one
1295
     * of the netaddrs has an AF_INET family, and the other has an
1296
     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
1297
     */
1298

1299
    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
7✔
1300
        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
3✔
1301
      errno = EINVAL;
2✔
1302
      return -1;
2✔
1303
    }
1304

1305
    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
2✔
1306
      tmp_pool = make_sub_pool(permanent_pool);
1✔
1307

1308
      pr_trace_msg(trace_channel, 5, "addr '%s' is an IPv4-mapped IPv6 address",
1✔
1309
        pr_netaddr_get_ipstr((pr_netaddr_t *) na1));
1310

1311
      /* This case means that na1 is an IPv4-mapped IPv6 address, and
1312
       * na2 is an IPv4 address.
1313
       */
1314
      a = pr_netaddr_v6tov4(tmp_pool, na1);
1✔
1315
      b = (pr_netaddr_t *) na2;
1✔
1316

1317
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
1✔
1318
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(b),
1319
        pr_netaddr_get_ipstr(a));
1320

1321
    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
1✔
1322
      tmp_pool = make_sub_pool(permanent_pool);
1✔
1323

1324
      pr_trace_msg(trace_channel, 5, "addr '%s' is an IPv4-mapped IPv6 address",
1✔
1325
        pr_netaddr_get_ipstr((pr_netaddr_t *) na2));
1326

1327
      /* This case means that na is an IPv4 address, and na2 is an
1328
       * IPv4-mapped IPv6 address.
1329
       */
1330
      a = (pr_netaddr_t *) na1;
1✔
1331
      b = pr_netaddr_v6tov4(tmp_pool, na2);
1✔
1332

1333
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
1✔
1334
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(a),
1335
        pr_netaddr_get_ipstr(b));
1336

1337
    } else {
1338
      a = (pr_netaddr_t *) na1;
1339
      b = (pr_netaddr_t *) na2;
1340
    }
1341

1342
  } else {
1343
    a = (pr_netaddr_t *) na1;
1344
    b = (pr_netaddr_t *) na2;
1345
  }
1346

1347
  switch (pr_netaddr_get_family(a)) {
15✔
1348
    case AF_INET:
15✔
1349
      res = memcmp(&a->na_addr.v4.sin_addr, &b->na_addr.v4.sin_addr,
15✔
1350
        sizeof(struct in_addr));
1351

1352
      if (res != 0) {
15✔
1353
        pr_trace_msg(trace_channel, 4, "addr %s does not match addr %s",
2✔
1354
          pr_netaddr_get_ipstr(a), pr_netaddr_get_ipstr(b));
1355
      }
1356

1357
      if (tmp_pool) {
15✔
1358
        destroy_pool(tmp_pool);
2✔
1359
        tmp_pool = NULL;
2✔
1360
      }
1361

1362
      return res;
1363

1364
#ifdef PR_USE_IPV6
1365
    case AF_INET6:
×
1366
      if (use_ipv6) {
×
1367
        res = memcmp(&a->na_addr.v6.sin6_addr, &b->na_addr.v6.sin6_addr,
×
1368
          sizeof(struct in6_addr));
1369

1370
        if (res != 0) {
×
1371
          pr_trace_msg(trace_channel, 4, "addr %s does not match addr %s",
×
1372
            pr_netaddr_get_ipstr(a), pr_netaddr_get_ipstr(b));
1373
        }
1374

1375
        if (tmp_pool != NULL) {
×
1376
          destroy_pool(tmp_pool);
×
1377
          tmp_pool = NULL;
×
1378
        }
1379

1380
        return res;
×
1381
      }
1382
#endif /* PR_USE_IPV6 */
1383
  }
1384

1385
  if (tmp_pool != NULL) {
×
1386
    destroy_pool(tmp_pool);
×
1387
  }
1388

1389
  errno = EPERM;
×
1390
  return -1;
×
1391
}
1392

1393
static int addr_ncmp(const unsigned char *aptr, const unsigned char *bptr,
15✔
1394
    unsigned int masklen) {
1395
  unsigned char nbits, nbytes;
15✔
1396
  int res;
15✔
1397

1398
  /* These null checks are unlikely to happen.  But be prepared, eh? */
1399

1400
  if (aptr != NULL &&
15✔
1401
      bptr == NULL) {
9✔
1402
    return 1;
1403
  }
1404

1405
  if (aptr == NULL &&
15✔
1406
      bptr != NULL) {
9✔
1407
    return -1;
1408
  }
1409

1410
  if (aptr == NULL &&
9✔
1411
      bptr == NULL) {
1412
    return 0;
1413
  }
1414

1415
  nbytes = masklen / 8;
15✔
1416
  nbits = masklen % 8;
15✔
1417

1418
  res = memcmp(aptr, bptr, nbytes);
15✔
1419
  if (res != 0) {
9✔
1420
    return -1;
1421
  }
1422

1423
  if (nbits > 0) {
7✔
1424
    unsigned char abyte, bbyte, mask;
1✔
1425

1426
    abyte = aptr[nbytes];
1✔
1427
    bbyte = bptr[nbytes];
1✔
1428

1429
    mask = (0xff << (8 - nbits)) & 0xff;
1✔
1430

1431
    if ((abyte & mask) > (bbyte & mask)) {
1✔
1432
      return 1;
1433
    }
1434

1435
    if ((abyte & mask) < (bbyte & mask)) {
1✔
1436
      return -1;
×
1437
    }
1438
  }
1439

1440
  return 0;
1441
}
1442

1443
int pr_netaddr_ncmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2,
13✔
1444
    unsigned int bitlen) {
1445
  pool *tmp_pool = NULL;
13✔
1446
  pr_netaddr_t *a, *b;
13✔
1447
  const unsigned char *in1, *in2;
13✔
1448
  int res;
13✔
1449

1450
  if (na1 != NULL &&
13✔
1451
      na2 == NULL) {
13✔
1452
    return 1;
1453
  }
1454

1455
  if (na1 == NULL &&
12✔
1456
      na2 != NULL) {
12✔
1457
    return -1;
1458
  }
1459

1460
  if (na1 == NULL &&
10✔
1461
      na2 == NULL) {
1462
    return 0;
1463
  }
1464

1465
  if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {
27✔
1466

1467
    /* Cannot compare addresses from different families, unless one
1468
     * of the netaddrs has an AF_INET family, and the other has an
1469
     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
1470
     */
1471

1472
    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
8✔
1473
        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
3✔
1474
      errno = EINVAL;
2✔
1475
      return -1;
2✔
1476
    }
1477

1478
    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
3✔
1479
      tmp_pool = make_sub_pool(permanent_pool);
2✔
1480

1481
      /* This case means that na1 is an IPv4-mapped IPv6 address, and
1482
       * na2 is an IPv4 address.
1483
       */
1484
      a = pr_netaddr_v6tov4(tmp_pool, na1);
2✔
1485
      b = (pr_netaddr_t *) na2;
2✔
1486

1487
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
2✔
1488
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(b),
1489
        pr_netaddr_get_ipstr(a));
1490

1491
    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
1✔
1492
      tmp_pool = make_sub_pool(permanent_pool);
1✔
1493

1494
      /* This case means that na is an IPv4 address, and na2 is an
1495
       * IPv4-mapped IPv6 address.
1496
       */
1497
      a = (pr_netaddr_t *) na1;
1✔
1498
      b = pr_netaddr_v6tov4(tmp_pool, na2);
1✔
1499

1500
      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
1✔
1501
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(a),
1502
        pr_netaddr_get_ipstr(b));
1503

1504
    } else {
1505
      a = (pr_netaddr_t *) na1;
1506
      b = (pr_netaddr_t *) na2;
1507
    }
1508

1509
  } else {
1510
    a = (pr_netaddr_t *) na1;
1511
    b = (pr_netaddr_t *) na2;
1512
  }
1513

1514
  switch (pr_netaddr_get_family(a)) {
7✔
1515
    case AF_INET: {
7✔
1516
      /* Make sure that the given number of bits is not more than supported
1517
       * for IPv4 addresses (32).
1518
       */
1519
      if (bitlen > 32) {
7✔
1520
        errno = EINVAL;
1✔
1521
        return -1;
1✔
1522
      }
1523

1524
      break;
1525
    }
1526

1527
#ifdef PR_USE_IPV6
1528
    case AF_INET6: {
×
1529
      if (use_ipv6) {
×
1530
        /* Make sure that the given number of bits is not more than supported
1531
         * for IPv6 addresses (128).
1532
         */
1533
        if (bitlen > 128) {
×
1534
          errno = EINVAL;
×
1535
          return -1;
×
1536
        }
1537

1538
        break;
1539
      }
1540
    }
1541
#endif /* PR_USE_IPV6 */
1542

1543
    default:
1544
      errno = EPERM;
×
1545
      return -1;
×
1546
  }
1547

1548
  /* Retrieve pointers to the contained in_addrs. */
1549
  in1 = (const unsigned char *) pr_netaddr_get_inaddr(a);
6✔
1550
  in2 = (const unsigned char *) pr_netaddr_get_inaddr(b);
6✔
1551

1552
  res = addr_ncmp(in1, in2, bitlen);
6✔
1553

1554
  if (tmp_pool) {
6✔
1555
    destroy_pool(tmp_pool);
3✔
1556
  }
1557

1558
  return res;
1559
}
1560

1561
int pr_netaddr_fnmatch(const pr_netaddr_t *na, const char *pattern, int flags) {
14✔
1562

1563
  /* Note: I'm still not sure why proftpd bundles an fnmatch(3)
1564
   * implementation rather than using the system library's implementation.
1565
   * Needs looking into.
1566
   *
1567
   * The FNM_CASEFOLD flag is a GNU extension; perhaps the bundled
1568
   * implementation was added to make that flag available on other platforms.
1569
   */
1570
  int match_flags = PR_FNM_NOESCAPE|PR_FNM_CASEFOLD;
14✔
1571

1572
  if (na == NULL ||
14✔
1573
      pattern == NULL) {
14✔
1574
    errno = EINVAL;
2✔
1575
    return -1;
2✔
1576
  }
1577

1578
  if (flags & PR_NETADDR_MATCH_DNS) {
12✔
1579
    const char *dnsstr;
5✔
1580

1581
    dnsstr = pr_netaddr_get_dnsstr(na);
5✔
1582
    if (pr_fnmatch(pattern, dnsstr, match_flags) == 0) {
5✔
1583
      pr_trace_msg(trace_channel, 6, "DNS name '%s' matches pattern '%s'",
3✔
1584
        dnsstr, pattern);
1585
      return TRUE;
3✔
1586
    }
1587
  }
1588

1589
  if (flags & PR_NETADDR_MATCH_IP) {
9✔
1590
    const char *ipstr;
7✔
1591

1592
    ipstr = pr_netaddr_get_ipstr(na);
7✔
1593
    if (pr_fnmatch(pattern, ipstr, match_flags) == 0) {
7✔
1594
      pr_trace_msg(trace_channel, 6, "IP address '%s' matches pattern '%s'",
3✔
1595
        ipstr, pattern);
1596
      return TRUE;
3✔
1597
    }
1598

1599
    /* If the address is an IPv4-mapped IPv6 address, get the IPv4 address
1600
     * and try to match that against the configured glob pattern.
1601
     */
1602
    if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
4✔
1603
      pool *tmp_pool;
2✔
1604
      pr_netaddr_t *a;
2✔
1605

1606
      pr_trace_msg(trace_channel, 5, "addr '%s' is an IPv4-mapped IPv6 address",
2✔
1607
        ipstr);
1608

1609
      tmp_pool = make_sub_pool(permanent_pool);
2✔
1610
      a = pr_netaddr_v6tov4(tmp_pool, na);
2✔
1611

1612
      ipstr = pr_netaddr_get_ipstr(a);
2✔
1613

1614
      if (pr_fnmatch(pattern, ipstr, match_flags) == 0) {
2✔
1615
        pr_trace_msg(trace_channel, 6, "IP address '%s' matches pattern '%s'",
1✔
1616
          ipstr, pattern);
1617

1618
        destroy_pool(tmp_pool);
1✔
1619
        return TRUE;
1✔
1620
      }
1621

1622
      destroy_pool(tmp_pool);
1✔
1623
    }
1624
  }
1625

1626
  pr_trace_msg(trace_channel, 4, "addr %s does not match pattern '%s'",
5✔
1627
    pr_netaddr_get_ipstr(na), pattern);
1628
  return FALSE;
5✔
1629
}
1630

1631
const char *pr_netaddr_get_ipstr(const pr_netaddr_t *na) {
730✔
1632
#if defined(PR_USE_IPV6)
1633
  char buf[INET6_ADDRSTRLEN];
730✔
1634
#else
1635
  char buf[INET_ADDRSTRLEN];
1636
#endif /* PR_USE_IPV6 */
1637
  int res = 0, xerrno;
730✔
1638
  pr_netaddr_t *addr;
730✔
1639

1640
  if (na == NULL) {
730✔
1641
    errno = EINVAL;
6✔
1642
    return NULL;
6✔
1643
  }
1644

1645
  /* If this pr_netaddr_t has already been resolved to an IP string, return the
1646
   * cached string.
1647
   */
1648
  if (na->na_have_ipstr) {
724✔
1649
    return na->na_ipstr;
524✔
1650
  }
1651

1652
  memset(buf, '\0', sizeof(buf));
200✔
1653
  res = pr_getnameinfo(pr_netaddr_get_sockaddr(na),
200✔
1654
    pr_netaddr_get_sockaddr_len(na), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
200✔
1655
  xerrno = errno;
200✔
1656

1657
  if (res != 0) {
200✔
1658
    if (res != EAI_SYSTEM) {
9✔
1659
      pr_log_pri(PR_LOG_WARNING, "getnameinfo error: %s", pr_gai_strerror(res));
9✔
1660
      errno = EIO;
9✔
1661

1662
    } else {
1663
      pr_log_pri(PR_LOG_WARNING, "getnameinfo system error: [%d] %s",
×
1664
        xerrno, strerror(xerrno));
1665
      errno = xerrno;
×
1666
    }
1667

1668
    return NULL;
9✔
1669
  }
1670

1671
#ifdef PR_USE_IPV6
1672
  if (use_ipv6 &&
191✔
1673
      pr_netaddr_get_family(na) == AF_INET6) {
191✔
1674
    /* The getnameinfo(3) implementation might append the zone ID to an IPv6
1675
     * name; we need to trim it off.
1676
     */
1677
    char *ptr;
81✔
1678

1679
    ptr = strrchr(buf, '%');
81✔
1680
    if (ptr != NULL) {
81✔
1681
      *ptr = '\0';
×
1682
    }
1683
  }
1684
#endif /* PR_USE_IPV6 */
1685

1686
  /* Copy the string into the pr_netaddr_t cache as well, so we only
1687
   * have to do this once for this pr_netaddr_t.  But to do this, we need
1688
   * let the compiler know that the pr_netaddr_t is not really const at this
1689
   * point.
1690
   */
1691
  addr = (pr_netaddr_t *) na;
191✔
1692
  memset(addr->na_ipstr, '\0', sizeof(addr->na_ipstr));
191✔
1693
  sstrncpy(addr->na_ipstr, buf, sizeof(addr->na_ipstr));
191✔
1694
  addr->na_have_ipstr = TRUE;
191✔
1695

1696
  return na->na_ipstr;
191✔
1697
}
1698

1699
#if defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME2)
1700
static int netaddr_get_dnsstr_getaddrinfo(const pr_netaddr_t *na,
1701
    const char *name) {
1702
  struct addrinfo hints, *info = NULL;
1703
  int family, flags = 0, res = 0, ok = FALSE;
1704
  void *inaddr = pr_netaddr_get_inaddr(na);
1705

1706
  family = pr_netaddr_get_family(na);
1707
  if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
1708
    family = AF_INET;
1709
    inaddr = get_v4inaddr(na);
1710
  }
1711

1712
#ifdef AI_CANONNAME
1713
  flags |= AI_CANONNAME;
1714
#endif
1715

1716
#ifdef AI_ALL
1717
  flags |= AI_ALL;
1718
#endif
1719

1720
#ifdef AI_V4MAPPED
1721
  flags |= AI_V4MAPPED;
1722
#endif
1723

1724
  memset(&hints, 0, sizeof(hints));
1725

1726
  hints.ai_family = family;
1727
  hints.ai_socktype = SOCK_STREAM;
1728
  hints.ai_protocol = IPPROTO_TCP;
1729
  hints.ai_flags = flags;
1730

1731
  res = pr_getaddrinfo(name, NULL, &hints, &info);
1732
  if (res != 0) {
1733
    int xerrno = errno;
1734

1735
    if (res != EAI_SYSTEM) {
1736
      pr_trace_msg(trace_channel, 1, "%s getaddrinfo '%s' error: %s",
1737
        hints.ai_family == AF_INET ? "IPv4" : "IPv6", name,
1738
        pr_gai_strerror(res));
1739

1740
    } else {
1741
      pr_trace_msg(trace_channel, 1,
1742
        "%s getaddrinfo '%s' system error: [%d] %s",
1743
        hints.ai_family == AF_INET ? "IPv4" : "IPv6", name, xerrno,
1744
        strerror(xerrno));
1745
    }
1746

1747
    errno = xerrno;
1748
    return -1;
1749
  }
1750

1751
  if (info != NULL) {
1752
#ifdef PR_USE_IPV6
1753
    char buf[INET6_ADDRSTRLEN];
1754
#else
1755
    char buf[INET_ADDRSTRLEN];
1756
#endif /* PR_USE_IPV6 */
1757
    struct addrinfo *ai;
1758
    int xerrno;
1759

1760
    memset(buf, '\0', sizeof(buf));
1761
    res = pr_getnameinfo(info->ai_addr, info->ai_addrlen, buf, sizeof(buf),
1762
      NULL, 0, NI_NAMEREQD);
1763
    xerrno = errno;
1764

1765
    if (res != 0) {
1766
      if (res != EAI_SYSTEM) {
1767
        pr_trace_msg(trace_channel, 1, "%s getnameinfo error: %s",
1768
          hints.ai_family == AF_INET ? "IPv4" : "IPv6", pr_gai_strerror(res));
1769

1770
      } else {
1771
        pr_trace_msg(trace_channel, 1,
1772
          "%s getnameinfo system error: [%d] %s",
1773
          hints.ai_family == AF_INET ? "IPv4" : "IPv6", xerrno,
1774
          strerror(xerrno));
1775
      }
1776

1777
      errno = xerrno;
1778
      return -1;
1779
    }
1780

1781
    netaddr_dnscache_set(pr_netaddr_get_ipstr(na), buf);
1782
    ok = TRUE;
1783

1784
    pr_trace_msg(trace_channel, 10,
1785
      "checking addresses associated with host '%s'", buf);
1786

1787
    for (ai = info->ai_next; ai; ai = ai->ai_next) {
1788
#ifdef PR_USE_IPV6
1789
      char alias[INET6_ADDRSTRLEN];
1790
#else
1791
      char alias[INET_ADDRSTRLEN];
1792
#endif /* PR_USE_IPV6 */
1793

1794
      switch (ai->ai_family) {
1795
        case AF_INET:
1796
          if (family == AF_INET) {
1797
            if (memcmp(ai->ai_addr, inaddr, ai->ai_addrlen) == 0) {
1798
              memset(alias, '\0', sizeof(alias));
1799
              res = pr_getnameinfo(ai->ai_addr, ai->ai_addrlen, alias,
1800
                sizeof(alias), NULL, 0, NI_NAMEREQD);
1801
              if (res == 0) {
1802
                pr_trace_msg(trace_channel, 10,
1803
                  "host '%s' has alias '%s'", buf, alias);
1804
                netaddr_ipcache_set(alias, na);
1805
                netaddr_dnscache_set(pr_netaddr_get_ipstr(na), alias);
1806
              }
1807
            }
1808
          }
1809
          break;
1810

1811
#ifdef PR_USE_IPV6
1812
        case AF_INET6:
1813
          if (use_ipv6 && family == AF_INET6) {
1814
            if (memcmp(ai->ai_addr, inaddr, ai->ai_addrlen) == 0) {
1815
              memset(alias, '\0', sizeof(alias));
1816
              res = pr_getnameinfo(ai->ai_addr, ai->ai_addrlen, alias,
1817
                sizeof(alias), NULL, 0, NI_NAMEREQD);
1818
              if (res == 0) {
1819
                pr_trace_msg(trace_channel, 10,
1820
                  "host '%s' has alias '%s'", buf, alias);
1821
                netaddr_ipcache_set(alias, na);
1822
                netaddr_dnscache_set(pr_netaddr_get_ipstr(na), alias);
1823
              }
1824
            }
1825
          }
1826
          break;
1827
#endif /* PR_USE_IPV6 */
1828
      }
1829
    }
1830

1831
    pr_freeaddrinfo(info);
1832
  }
1833

1834
  return (ok ? 0 : -1);
1835
}
1836
#endif /* HAVE_GETADDRINFO and not HAVE_GETHOSTBYNAME2 */
1837

1838
#ifdef HAVE_GETHOSTBYNAME2
1839
static int netaddr_get_dnsstr_gethostbyname(const pr_netaddr_t *na,
8✔
1840
    const char *name) {
1841
  struct hostent *hent = NULL;
8✔
1842
  int family, ok = FALSE;
8✔
1843
  void *inaddr;
8✔
1844

1845
  family = pr_netaddr_get_family(na);
8✔
1846
  if (family < 0) {
8✔
1847
    return -1;
×
1848
  }
1849

1850
  inaddr = pr_netaddr_get_inaddr(na);
8✔
1851

1852
  if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
8✔
1853
    family = AF_INET;
×
1854
    inaddr = get_v4inaddr(na);
×
1855
  }
1856

1857
  hent = gethostbyname2(name, family);
8✔
1858

1859
  if (hent != NULL) {
8✔
1860
    char **checkaddr;
8✔
1861

1862
    if (hent->h_name != NULL) {
8✔
1863
      netaddr_dnscache_set(pr_netaddr_get_ipstr(na), hent->h_name);
8✔
1864
    }
1865

1866
    pr_trace_msg(trace_channel, 10,
8✔
1867
      "checking addresses associated with host '%s'",
1868
      hent->h_name ? hent->h_name : "(null)");
8✔
1869

1870
    switch (hent->h_addrtype) {
8✔
1871
      case AF_INET:
7✔
1872
        if (family == AF_INET) {
7✔
1873
          for (checkaddr = hent->h_addr_list; *checkaddr; ++checkaddr) {
7✔
1874
            if (memcmp(*checkaddr, inaddr, hent->h_length) == 0) {
7✔
1875
              char **alias;
7✔
1876

1877
              for (alias = hent->h_aliases; *alias; ++alias) {
19✔
1878
                if (hent->h_name) {
12✔
1879
                  pr_trace_msg(trace_channel, 10,
12✔
1880
                    "host '%s' has alias '%s'", hent->h_name, *alias);
1881
                  netaddr_ipcache_set(*alias, na);
12✔
1882
                  netaddr_dnscache_set(pr_netaddr_get_ipstr(na), *alias);
12✔
1883
                }
1884
              }
1885

1886
              ok = TRUE;
1887
              break;
1888
            }
1889
          }
1890
        }
1891
        break;
1892

1893
# if defined(PR_USE_IPV6)
1894
      case AF_INET6:
1✔
1895
        if (use_ipv6 && family == AF_INET6) {
1✔
1896
          for (checkaddr = hent->h_addr_list; *checkaddr; ++checkaddr) {
1✔
1897
            if (memcmp(*checkaddr, inaddr, hent->h_length) == 0) {
1✔
1898
              char **alias;
1✔
1899

1900
              for (alias = hent->h_aliases; *alias; ++alias) {
3✔
1901
                if (hent->h_name) {
2✔
1902
                  pr_trace_msg(trace_channel, 10,
2✔
1903
                    "host '%s' has alias '%s'", hent->h_name, *alias);
1904
                  netaddr_ipcache_set(*alias, na);
2✔
1905
                  netaddr_dnscache_set(pr_netaddr_get_ipstr(na), *alias);
2✔
1906
                }
1907
              }
1908

1909
              ok = TRUE;
1910
              break;
1911
            }
1912
          }
1913
        }
1914
        break;
1915
# endif /* PR_USE_IPV6 */
1916
    }
1917

1918
  } else {
1919
    pr_log_debug(DEBUG1, "notice: unable to resolve '%s' as %s address: %s",
×
1920
      name, family != AF_INET ? "IPv6" : "IPv4", hstrerror(h_errno));
×
1921
  }
1922

1923
  return (ok ? 0 : -1);
8✔
1924
}
1925
#endif /* HAVE_GETHOSTBYNAME2 */
1926

1927
/* This differs from pr_netaddr_get_ipstr() in that pr_netaddr_get_ipstr()
1928
 * returns a string of the numeric form of the given network address, whereas
1929
 * this function returns a string of the DNS name (if present).
1930
 */
1931
const char *pr_netaddr_get_dnsstr(const pr_netaddr_t *na) {
44✔
1932
  char dns_buf[1024], *name = NULL;
44✔
1933
  pr_netaddr_t *addr = NULL, *cache = NULL;
44✔
1934

1935
  if (na == NULL) {
44✔
1936
    errno = EINVAL;
4✔
1937
    return NULL;
4✔
1938
  }
1939

1940
  cache = netaddr_ipcache_get(NULL, pr_netaddr_get_ipstr(na));
40✔
1941
  if (cache &&
40✔
1942
      cache->na_have_dnsstr) {
38✔
1943
    addr = (pr_netaddr_t *) na;
28✔
1944
    memset(addr->na_dnsstr, '\0', sizeof(addr->na_dnsstr));
28✔
1945
    sstrncpy(addr->na_dnsstr, cache->na_dnsstr, sizeof(addr->na_dnsstr));
28✔
1946
    addr->na_have_dnsstr = TRUE;
28✔
1947

1948
    return na->na_dnsstr;
28✔
1949
  }
1950

1951
  /* If this pr_netaddr_t has already been resolved to an DNS string, return the
1952
   * cached string.
1953
   */
1954
  if (na->na_have_dnsstr) {
12✔
1955
    return na->na_dnsstr;
×
1956
  }
1957

1958
  if (reverse_dns) {
12✔
1959
    int res = 0;
10✔
1960

1961
    pr_trace_msg(trace_channel, 3,
10✔
1962
      "verifying DNS name for IP address %s via reverse DNS lookup",
1963
      pr_netaddr_get_ipstr(na));
1964

1965
    memset(dns_buf, '\0', sizeof(dns_buf));
10✔
1966
    res = pr_getnameinfo(pr_netaddr_get_sockaddr(na),
10✔
1967
      pr_netaddr_get_sockaddr_len(na), dns_buf, sizeof(dns_buf), NULL, 0,
10✔
1968
      NI_NAMEREQD);
1969
    dns_buf[sizeof(dns_buf)-1] = '\0';
10✔
1970

1971
    if (res == 0) {
10✔
1972
      /* Some older glibc's getaddrinfo(3) does not appear to handle IPv6
1973
       * addresses properly; we thus prefer gethostbyname2(3) on systems
1974
       * which have it, for such older systems.
1975
       */
1976
#ifdef HAVE_GETHOSTBYNAME2
1977
      res = netaddr_get_dnsstr_gethostbyname(na, dns_buf);
8✔
1978
#else
1979
      res = netaddr_get_dnsstr_getaddrinfo(na, dns_buf);
1980
#endif /* HAVE_GETHOSTBYNAME2 */
1981
      if (res == 0) {
8✔
1982
        name = dns_buf;
8✔
1983
        pr_trace_msg(trace_channel, 8,
8✔
1984
          "using DNS name '%s' for IP address '%s'", name,
1985
          pr_netaddr_get_ipstr(na));
1986

1987
      } else {
1988
        name = NULL;
×
1989
        pr_trace_msg(trace_channel, 8,
×
1990
          "unable to verify any DNS names for IP address '%s'",
1991
          pr_netaddr_get_ipstr(na));
1992
      }
1993
    }
1994

1995
  } else {
1996
    pr_log_debug(DEBUG10,
2✔
1997
      "UseReverseDNS off, returning IP address instead of DNS name");
1998
  }
1999

2000
  if (name) {
2✔
2001
    name = pr_netaddr_validate_dns_str(name);
8✔
2002

2003
  } else {
2004
    name = (char *) pr_netaddr_get_ipstr(na);
4✔
2005
  }
2006

2007
  /* Copy the string into the pr_netaddr_t cache as well, so we only
2008
   * have to do this once for this pr_netaddr_t.  But to do this, we need
2009
   * let the compiler know that the pr_netaddr_t is not really const at this
2010
   * point.
2011
   */
2012
  addr = (pr_netaddr_t *) na;
12✔
2013
  memset(addr->na_dnsstr, '\0', sizeof(addr->na_dnsstr));
12✔
2014
  sstrncpy(addr->na_dnsstr, name, sizeof(addr->na_dnsstr));
12✔
2015
  addr->na_have_dnsstr = TRUE;
12✔
2016

2017
  /* Update the netaddr object in the cache with the resolved DNS names. */
2018
  netaddr_ipcache_set(name, na);
12✔
2019
  netaddr_ipcache_set(pr_netaddr_get_ipstr(na), na);
12✔
2020

2021
  return na->na_dnsstr;
12✔
2022
}
2023

2024
array_header *pr_netaddr_get_dnsstr_list(pool *p, const pr_netaddr_t *na) {
4✔
2025
  array_header *res;
4✔
2026

2027
  if (p == NULL ||
4✔
2028
      na == NULL) {
4✔
2029
    errno = EINVAL;
2✔
2030
    return NULL;
2✔
2031
  }
2032

2033
  if (!reverse_dns) {
2✔
2034
    /* If UseReverseDNS is off, then we won't have any names that we trust.
2035
     * So return an empty list.
2036
     */
2037
    return make_array(p, 0, sizeof(char *));
×
2038
  }
2039

2040
  res = netaddr_dnscache_get(p, pr_netaddr_get_ipstr(na));
2✔
2041
  if (res == NULL) {
2✔
2042
    res = make_array(p, 0, sizeof(char *));
1✔
2043
  }
2044

2045
  return res;
2046
}
2047

2048
/* Return the hostname (wrapper for gethostname(2), except returns FQDN). */
2049
const char *pr_netaddr_get_localaddr_str(pool *p) {
2✔
2050
  char buf[256];
2✔
2051
  int res, xerrno;
2✔
2052

2053
  if (p == NULL) {
2✔
2054
    errno = EINVAL;
1✔
2055
    return NULL;
1✔
2056
  }
2057

2058
  if (have_localaddr_str) {
1✔
2059
    return pr_netaddr_validate_dns_str(pstrdup(p, localaddr_str));
×
2060
  }
2061

2062
  memset(buf, '\0', sizeof(buf));
1✔
2063
  res = gethostname(buf, sizeof(buf)-1);
1✔
2064
  xerrno = errno;
1✔
2065

2066
  if (res >= 0) {
1✔
2067
    struct hostent *host;
1✔
2068

2069
    buf[sizeof(buf)-1] = '\0';
1✔
2070

2071
    /* Note: this may need to be gethostbyname2() on systems that provide
2072
     * that function, for it is possible that the configured hostname for
2073
     * a machine only resolves to an IPv6 address.
2074
     */
2075
#ifdef HAVE_GETHOSTBYNAME2
2076
    host = gethostbyname2(buf, AF_INET);
1✔
2077
    if (host == NULL &&
1✔
2078
        h_errno == HOST_NOT_FOUND) {
×
2079
# ifdef AF_INET6
2080
      host = gethostbyname2(buf, AF_INET6);
×
2081
# endif /* AF_INET6 */
2082
    }
2083
#else
2084
    host = gethostbyname(buf);
2085
#endif
2086
    if (host != NULL) {
1✔
2087
      return pr_netaddr_validate_dns_str(pstrdup(p, host->h_name));
1✔
2088
    }
2089

2090
    pr_trace_msg(trace_channel, 14,
×
2091
      "gethostbyname() failed for '%s': %s", buf, hstrerror(h_errno));
×
2092
    return pr_netaddr_validate_dns_str(pstrdup(p, buf));
×
2093
  }
2094

2095
  pr_trace_msg(trace_channel, 1, "gethostname(2) error: %s", strerror(xerrno));
×
2096
  errno = xerrno;
×
2097
  return NULL;
×
2098
}
2099

2100
int pr_netaddr_set_localaddr_str(const char *addr_str) {
×
2101
  if (addr_str == NULL) {
×
2102
    errno = EINVAL;
×
2103
    return -1;
×
2104
  }
2105

2106
  memset(localaddr_str, '\0', sizeof(localaddr_str));
×
2107
  sstrncpy(localaddr_str, addr_str, sizeof(localaddr_str));
×
2108
  have_localaddr_str = TRUE;
×
2109
  return 0;
×
2110
}
2111

2112
int pr_netaddr_is_loopback(const pr_netaddr_t *na) {
6✔
2113
  if (na == NULL) {
6✔
2114
    errno = EINVAL;
1✔
2115
    return -1;
1✔
2116
  }
2117

2118
  switch (pr_netaddr_get_family(na)) {
5✔
2119
    case AF_INET:
3✔
2120
      return IN_IS_ADDR_LOOPBACK(
3✔
2121
        (struct in_addr *) pr_netaddr_get_inaddr(na));
2122

2123
#ifdef PR_USE_IPV6
2124
    case AF_INET6:
2✔
2125
      if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
2✔
2126
        pool *tmp_pool;
1✔
2127
        pr_netaddr_t *v4na;
1✔
2128
        int res;
1✔
2129

2130
        tmp_pool = make_sub_pool(permanent_pool);
1✔
2131
        v4na = pr_netaddr_v6tov4(tmp_pool, na);
1✔
2132

2133
        res = pr_netaddr_is_loopback(v4na);
1✔
2134
        destroy_pool(tmp_pool);
1✔
2135

2136
        return res;
1✔
2137
      }
2138

2139
      /* XXX *sigh* Different platforms implement the IN6_IS_ADDR macros
2140
       * differently.  For example, on Linux, those macros expect to operate
2141
       * on s6_addr32, while on Solaris, the macros operate on struct in6_addr.
2142
       * Certain Drafts define the macros to work on struct in6_addr *, as
2143
       * Solaris does, so Linux may have it wrong.  Tentative research on
2144
       * Google shows some BSD netinet6/in6.h headers that define these
2145
       * macros in terms of struct in6_addr *, so I'll go with that for now.
2146
       * Joy. =P
2147
       */
2148
# ifndef LINUX
2149
      return IN6_IS_ADDR_LOOPBACK(
2150
        (struct in6_addr *) pr_netaddr_get_inaddr(na));
2151
# else
2152
      return IN6_IS_ADDR_LOOPBACK(
1✔
2153
        ((struct in6_addr *) pr_netaddr_get_inaddr(na))->s6_addr32);
2154
# endif
2155
#endif /* PR_USE_IPV6 */
2156
  }
2157

2158
  return FALSE;
2159
}
2160

2161
/* RFC 1918 addresses:
2162
 *
2163
 * 10.0.0.0 - 10.255.255.255 (10.0.0.0/8, 24-bit block)
2164
 * 172.16.0.0 - 172.31.255.255 (172.16.0.0/12, 20-bit block)
2165
 * 192.168.0.0 - 192.168.255.255 (192.168.0.0/16, 16-bit block)
2166
 *
2167
 */
2168

2169
static int is_10_xxx_addr(uint32_t addrno) {
2✔
2170
  uint32_t rfc1918_addrno;
2✔
2171

2172
  rfc1918_addrno = htonl(0x0a000000);
2✔
2173
  return addr_ncmp((const unsigned char *) &addrno,
2✔
2174
    (const unsigned char *) &rfc1918_addrno, 8);
2175
}
2176

2177
static int is_172_16_xx_addr(uint32_t addrno) {
3✔
2178
  uint32_t rfc1918_addrno;
3✔
2179

2180
  rfc1918_addrno = htonl(0xac100000);
3✔
2181
  return addr_ncmp((const unsigned char *) &addrno,
3✔
2182
    (const unsigned char *) &rfc1918_addrno, 12);
2183
}
2184

2185
static int is_192_168_xx_addr(uint32_t addrno) {
4✔
2186
  uint32_t rfc1918_addrno;
4✔
2187

2188
  rfc1918_addrno = htonl(0xc0a80000);
4✔
2189
  return addr_ncmp((const unsigned char *) &addrno,
4✔
2190
    (const unsigned char *) &rfc1918_addrno, 16);
2191
}
2192

2193
int pr_netaddr_is_rfc1918(const pr_netaddr_t *na) {
6✔
2194
  if (na == NULL) {
6✔
2195
    errno = EINVAL;
1✔
2196
    return -1;
1✔
2197
  }
2198

2199
  switch (pr_netaddr_get_family(na)) {
5✔
2200
    case AF_INET: {
4✔
2201
      uint32_t addrno;
4✔
2202

2203
      addrno = pr_netaddr_get_addrno(na);
4✔
2204
      if (is_192_168_xx_addr(addrno) == 0 ||
4✔
2205
          is_172_16_xx_addr(addrno) == 0 ||
3✔
2206
          is_10_xxx_addr(addrno) == 0) {
4✔
2207
          return TRUE;
3✔
2208
      }
2209
      break;
2210
    }
2211

2212
#ifdef PR_USE_IPV6
2213
    case AF_INET6:
1✔
2214
      if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
1✔
2215
        pool *tmp_pool;
×
2216
        pr_netaddr_t *v4na;
×
2217
        int res;
×
2218

2219
        tmp_pool = make_sub_pool(permanent_pool);
×
2220
        v4na = pr_netaddr_v6tov4(tmp_pool, na);
×
2221

2222
        res = pr_netaddr_is_rfc1918(v4na);
×
2223
        destroy_pool(tmp_pool);
×
2224

2225
        return res;
×
2226
      }
2227

2228
      /* By definition, an IPv6 address is not an RFC1918-defined address. */
2229
      return FALSE;
2230
#endif /* PR_USE_IPV6 */
2231
  }
2232

2233
  errno = EINVAL;
1✔
2234
  return FALSE;
1✔
2235
}
2236

2237
/* A slightly naughty function that should go away. It relies too much on
2238
 * knowledge of the internal structures of struct in_addr, struct in6_addr.
2239
 */
2240
uint32_t pr_netaddr_get_addrno(const pr_netaddr_t *na) {
4✔
2241
  if (na == NULL) {
4✔
2242
    errno = EINVAL;
×
2243
    return 0;
×
2244
  }
2245

2246
  switch (pr_netaddr_get_family(na)) {
4✔
2247
    case AF_INET:
4✔
2248
      return (uint32_t) na->na_addr.v4.sin_addr.s_addr;
4✔
2249

2250
#ifdef PR_USE_IPV6
2251
    case AF_INET6: {
×
2252

2253
      /* Linux defines s6_addr32 in its netinet/in.h header.
2254
       * FreeBSD defines s6_addr32 in KAME's netinet6/in6.h header.
2255
       * Solaris defines s6_addr32 in its netinet/in.h header, but only
2256
       * for kernel builds.
2257
       */
2258
#if 0
2259
      int *addrs = ((struct sockaddr_in6 *) pr_netaddr_get_inaddr(na))->s6_addr32;
2260
      return addrs[0];
2261
#else
2262
      errno = ENOENT;
×
2263
      return 0;
×
2264
#endif
2265
    }
2266
#endif /* PR_USE_IPV6 */
2267
  }
2268

2269
  errno = EPERM;
×
2270
  return 0;
×
2271
}
2272

2273
int pr_netaddr_is_v4(const char *name) {
4✔
2274
  int res;
4✔
2275
  struct sockaddr_in v4;
4✔
2276

2277
  if (name == NULL) {
4✔
2278
    errno = EINVAL;
1✔
2279
    return -1;
1✔
2280
  }
2281

2282
  memset(&v4, 0, sizeof(v4));
3✔
2283
  v4.sin_family = AF_INET;
3✔
2284

2285
# ifdef SIN_LEN
2286
  v4.sin_len = sizeof(struct sockaddr_in);
2287
# endif /* SIN_LEN */
2288

2289
  res = pr_inet_pton(AF_INET, name, &v4.sin_addr);
3✔
2290
  if (res > 0) {
3✔
2291
    return TRUE;
1✔
2292
  }
2293

2294
  return FALSE;
2295
}
2296

2297
int pr_netaddr_is_v6(const char *name) {
4✔
2298
  if (name == NULL) {
4✔
2299
    errno = EINVAL;
1✔
2300
    return -1;
1✔
2301
  }
2302

2303
#ifdef PR_USE_IPV6
2304
  if (use_ipv6) {
3✔
2305
    int res;
3✔
2306
    struct sockaddr_in6 v6;
3✔
2307

2308
    memset(&v6, 0, sizeof(v6));
3✔
2309
    v6.sin6_family = AF_INET6;
3✔
2310

2311
# ifdef SIN6_LEN
2312
    v6.sin6_len = sizeof(struct sockaddr_in6);
2313
# endif /* SIN6_LEN */
2314

2315
    res = pr_inet_pton(AF_INET6, name, &v6.sin6_addr);
3✔
2316
    if (res > 0) {
3✔
2317
      return TRUE;
1✔
2318
    }
2319
  }
2320

2321
  return FALSE;
2322
#else
2323
  return FALSE;
2324
#endif /* !PR_USE_IPV6 */
2325
}
2326

2327
int pr_netaddr_is_v4mappedv6(const pr_netaddr_t *na) {
61✔
2328
  if (!na) {
61✔
2329
    errno = EINVAL;
1✔
2330
    return -1;
1✔
2331
  }
2332

2333
  switch (pr_netaddr_get_family(na)) {
60✔
2334
    case AF_INET:
19✔
2335

2336
      /* This function tests only IPv6 addresses, not IPv4 addresses. */
2337
      errno = EINVAL;
19✔
2338
      return -1;
19✔
2339

2340
#ifdef PR_USE_IPV6
2341
    case AF_INET6: {
41✔
2342
      int res;
41✔
2343

2344
      if (!use_ipv6) {
41✔
2345
        errno = EINVAL;
×
2346
        return -1;
×
2347
      }
2348

2349
# ifndef LINUX
2350
      res = IN6_IS_ADDR_V4MAPPED(
2351
        (struct in6_addr *) pr_netaddr_get_inaddr(na));
2352
# else
2353
      res = IN6_IS_ADDR_V4MAPPED(
41✔
2354
        ((struct in6_addr *) pr_netaddr_get_inaddr(na))->s6_addr32);
2355
# endif
2356

2357
      if (res != TRUE) {
15✔
2358
        errno = EINVAL;
15✔
2359
      }
2360

2361
      return res;
2362
    }
2363
#endif /* PR_USE_IPV6 */
2364
  }
2365

2366
  errno = EPERM;
×
2367
  return -1;
×
2368
}
2369

2370
pr_netaddr_t *pr_netaddr_v6tov4(pool *p, const pr_netaddr_t *na) {
12✔
2371
  pr_netaddr_t *res;
12✔
2372

2373
  if (p == NULL ||
12✔
2374
      na == NULL) {
12✔
2375
    errno = EINVAL;
2✔
2376
    return NULL;
2✔
2377
  }
2378

2379
  if (pr_netaddr_is_v4mappedv6(na) != TRUE) {
10✔
2380
    errno = EPERM;
1✔
2381
    return NULL;
1✔
2382
  }
2383

2384
  res = pr_netaddr_alloc(p);
9✔
2385
  pr_netaddr_set_family(res, AF_INET);
9✔
2386
  pr_netaddr_set_port(res, pr_netaddr_get_port(na));
9✔
2387
  memcpy(&res->na_addr.v4.sin_addr, get_v4inaddr(na), sizeof(struct in_addr));
9✔
2388

2389
  return res;
9✔
2390
}
2391

2392
pr_netaddr_t *pr_netaddr_v4tov6(pool *p, const pr_netaddr_t *na) {
4✔
2393
  pr_netaddr_t *res;
4✔
2394

2395
  if (p == NULL ||
4✔
2396
      na == NULL) {
4✔
2397
    errno = EINVAL;
2✔
2398
    return NULL;
2✔
2399
  }
2400

2401
  if (pr_netaddr_get_family(na) != AF_INET) {
2✔
2402
    errno = EPERM;
1✔
2403
    return NULL;
1✔
2404
  }
2405

2406
#ifdef PR_USE_IPV6
2407
  res = (pr_netaddr_t *) pr_netaddr_get_addr(p,
2✔
2408
    pstrcat(p, "::ffff:", pr_netaddr_get_ipstr(na), NULL), NULL);
1✔
2409
  if (res != NULL) {
1✔
2410
    pr_netaddr_set_port(res, pr_netaddr_get_port(na));
1✔
2411
  }
2412

2413
#else
2414
  errno = EPERM;
2415
  res = NULL;
2416
#endif /* PR_USE_IPV6 */
2417

2418
  return res;
2419
}
2420

2421
const pr_netaddr_t *pr_netaddr_get_sess_local_addr(void) {
4✔
2422
  if (have_sess_local_addr) {
4✔
2423
    return &sess_local_addr;
2424
  }
2425

2426
  errno = ENOENT;
4✔
2427
  return NULL;
4✔
2428
}
2429

2430
const pr_netaddr_t *pr_netaddr_get_sess_remote_addr(void) {
6✔
2431
  if (have_sess_remote_addr) {
6✔
2432
    return &sess_remote_addr;
2433
  }
2434

2435
  errno = ENOENT;
5✔
2436
  return NULL;
5✔
2437
}
2438

2439
const char *pr_netaddr_get_sess_remote_name(void) {
2✔
2440
  if (have_sess_remote_addr) {
2✔
2441
    return sess_remote_name;
2442
  }
2443

2444
  errno = ENOENT;
2✔
2445
  return NULL;
2✔
2446
}
2447

2448
void pr_netaddr_set_sess_addrs(void) {
1✔
2449
  memset(&sess_local_addr, 0, sizeof(sess_local_addr));
1✔
2450
  pr_netaddr_set_family(&sess_local_addr,
1✔
2451
    pr_netaddr_get_family(session.c->local_addr));
1✔
2452
  pr_netaddr_set_sockaddr(&sess_local_addr,
1✔
2453
    pr_netaddr_get_sockaddr(session.c->local_addr));
1✔
2454
  have_sess_local_addr = TRUE;
1✔
2455

2456
  memset(&sess_remote_addr, 0, sizeof(sess_remote_addr));
1✔
2457
  pr_netaddr_set_family(&sess_remote_addr,
1✔
2458
    pr_netaddr_get_family(session.c->remote_addr));
1✔
2459
  pr_netaddr_set_sockaddr(&sess_remote_addr,
1✔
2460
    pr_netaddr_get_sockaddr(session.c->remote_addr));
1✔
2461

2462
  memset(sess_remote_name, '\0', sizeof(sess_remote_name));
1✔
2463
  sstrncpy(sess_remote_name, session.c->remote_name, sizeof(sess_remote_name));
1✔
2464
  have_sess_remote_addr = TRUE;
1✔
2465
}
1✔
2466

2467
unsigned char pr_netaddr_use_ipv6(void) {
201✔
2468
  if (use_ipv6 == TRUE) {
201✔
2469
    return TRUE;
200✔
2470
  }
2471

2472
  return FALSE;
2473
}
2474

2475
void pr_netaddr_disable_ipv6(void) {
6✔
2476
#if defined(PR_USE_IPV6)
2477
  use_ipv6 = FALSE;
6✔
2478
#endif /* PR_USE_IPV6 */
2479
}
6✔
2480

2481
void pr_netaddr_enable_ipv6(void) {
9✔
2482
#if defined(PR_USE_IPV6)
2483
  use_ipv6 = TRUE;
9✔
2484
#endif /* PR_USE_IPV6 */
2485
}
9✔
2486

2487
void pr_netaddr_clear_cache(void) {
1✔
2488
  if (netaddr_iptab != NULL) {
1✔
2489
    pr_trace_msg(trace_channel, 5, "emptying netaddr IP cache");
1✔
2490
    (void) pr_table_empty(netaddr_iptab);
1✔
2491
    (void) pr_table_free(netaddr_iptab);
1✔
2492

2493
    /* Allocate a fresh table. */
2494
    netaddr_iptab = pr_table_alloc(netaddr_pool, 0);
1✔
2495
  }
2496

2497
  if (netaddr_dnstab != NULL) {
1✔
2498
    pr_trace_msg(trace_channel, 5, "emptying netaddr DNS cache");
1✔
2499
    (void) pr_table_empty(netaddr_dnstab);
1✔
2500
    (void) pr_table_free(netaddr_dnstab);
1✔
2501

2502
    /* Allocate a fresh table. */
2503
    netaddr_dnstab = pr_table_alloc(netaddr_pool, 0);
1✔
2504
  }
2505
}
1✔
2506

2507
void pr_netaddr_clear_dnscache(const char *ip_str) {
×
2508
  if (netaddr_dnstab != NULL) {
×
2509
    (void) pr_table_remove(netaddr_dnstab, ip_str, NULL);
×
2510
  }
2511
}
×
2512

2513
void pr_netaddr_clear_ipcache(const char *name) {
2✔
2514
  if (netaddr_iptab != NULL) {
2✔
2515
    (void) pr_table_remove(netaddr_iptab, name, NULL);
2✔
2516
  }
2517
}
2✔
2518

2519
void init_netaddr(void) {
96✔
2520
  if (netaddr_pool != NULL) {
96✔
2521
    pr_netaddr_clear_cache();
×
2522
    destroy_pool(netaddr_pool);
×
2523
    netaddr_pool = NULL;
×
2524
  }
2525

2526
  netaddr_pool = make_sub_pool(permanent_pool);
96✔
2527
  pr_pool_tag(netaddr_pool, "Netaddr API");
96✔
2528

2529
  netaddr_iptab = pr_table_alloc(netaddr_pool, 0);
96✔
2530
  netaddr_dnstab = pr_table_alloc(netaddr_pool, 0);
96✔
2531
}
96✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc