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

proftpd / proftpd / 28259826111

26 Jun 2026 07:20PM UTC coverage: 93.032% (+0.6%) from 92.469%
28259826111

push

github

51363 of 55210 relevant lines covered (93.03%)

200.05 hits per line

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

80.8
/src/inet.c
1
/*
2
 * ProFTPD - FTP server daemon
3
 * Copyright (c) 1997, 1998 Public Flood Software
4
 * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
5
 * Copyright (c) 2001-2026 The ProFTPD Project team
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19
 *
20
 * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
21
 * and other respective copyright holders give permission to link this program
22
 * with OpenSSL, and distribute the resulting executable, without including
23
 * the source code for OpenSSL in the source distribution.
24
 */
25

26
/* Inet support functions, many wrappers for netdb functions */
27

28
#include "conf.h"
29
#include "privs.h"
30

31
extern unsigned char is_master;
32
extern server_rec *main_server;
33

34
/* A private work pool for all pr_inet_* functions to use. */
35
static pool *inet_pool = NULL;
36

37
static int ip_proto = IPPROTO_IP;
38
#ifdef PR_USE_IPV6
39
static int ipv6_proto = IPPROTO_IPV6;
40
#endif /* PR_USE_IPV6 */
41
static int tcp_proto = IPPROTO_TCP;
42

43
static int inet_errno = 0;                /* Holds errno */
44

45
/* The default address family to use when creating a socket, if a pr_netaddr_t
46
 * is not given.  This is mainly for the benefit of init_conn().
47
 */
48
static int inet_family = 0;
49

50
static const char *trace_channel = "inet";
51

52
/* Called by others after running a number of pr_inet_* functions in order
53
 * to free up memory.
54
 */
55
void pr_inet_clear(void) {
56
  destroy_pool(inet_pool);
34✔
57
  inet_pool = NULL;
34✔
58
}
34✔
59

34✔
60
/* All inet_ interface functions take a pool as the first arg, which
61
 * is where any returned allocated memory is taken from.  For purposes
62
 * of uniformity the pool is included in all calls, even those that
63
 * don't need to return allocated memory.
64
 */
65

66
int pr_inet_set_default_family(pool *p, int family) {
67
  int old_family = inet_family;
59✔
68
  inet_family = family;
59✔
69
  return old_family;
59✔
70
}
59✔
71

72
/* Find a service and return its port number. */
73
int pr_inet_getservport(pool *p, const char *serv, const char *proto) {
74
  struct servent *servent;
15✔
75

15✔
76
  (void) p;
77

15✔
78
  if (serv == NULL) {
79
    errno = EINVAL;
15✔
80
    return -1;
1✔
81
  }
1✔
82

83
  servent = getservbyname(serv, proto);
84
  if (servent == NULL) {
14✔
85
    return -1;
14✔
86
  }
87

88
  /* getservbyname returns the port in network byte order. */
89
  return ntohs(servent->s_port);
90
}
13✔
91

92
static void conn_cleanup_cb(void *cv) {
93
  conn_t *c = (conn_t *) cv;
76✔
94

76✔
95
  /* XXX These closes' return values should be checked, ideally. Do
96
   * we really care if they fail, though?
97
   */
98

99
  if (c->instrm != NULL) {
100
    pr_netio_close(c->instrm);
76✔
101
  }
17✔
102

103
  if (c->outstrm != NULL &&
104
      c->outstrm != c->instrm) {
76✔
105
    pr_netio_close(c->outstrm);
16✔
106
  }
16✔
107

108
  /* Set these to NULL only AFTER comparing them with each other, and closing
109
   * them.  Otherwise, we may try to close the same stream twice.
110
   */
111
  c->instrm = c->outstrm = NULL;
112

76✔
113
  if (c->listen_fd != -1) {
114
    (void) close(c->listen_fd);
76✔
115
    c->listen_fd = -1;
71✔
116
  }
71✔
117

118
  if (c->rfd != -1) {
119
    (void) close(c->rfd);
76✔
120
    c->rfd = -1;
2✔
121
  }
2✔
122

123
  if (c->wfd != -1) {
124
    (void) close(c->wfd);
76✔
125
    c->wfd = -1;
1✔
126
  }
1✔
127
}
128

76✔
129
/* Copy a connection structure, also creates a sub pool for the new
130
 * connection.
131
 */
132
conn_t *pr_inet_copy_conn(pool *p, conn_t *c) {
133
  conn_t *res = NULL;
9✔
134
  pool *sub_pool = NULL;
9✔
135

9✔
136
  if (p == NULL ||
137
      c == NULL) {
9✔
138
    errno = EINVAL;
9✔
139
    return NULL;
3✔
140
  }
3✔
141

142
  sub_pool = make_sub_pool(p);
143
  pr_pool_tag(sub_pool, "inet_copy_conn pool");
6✔
144

6✔
145
  res = (conn_t *) pcalloc(sub_pool, sizeof(conn_t));
146

6✔
147
  memcpy(res, c, sizeof(conn_t));
148
  res->pool = sub_pool;
6✔
149
  res->instrm = res->outstrm = NULL;
6✔
150

6✔
151
  if (c->local_addr != NULL) {
152
    pr_netaddr_t *local_addr;
6✔
153

6✔
154
    local_addr = pr_netaddr_alloc(res->pool);
155

6✔
156
    if (pr_netaddr_set_family(local_addr,
157
        pr_netaddr_get_family(c->local_addr)) < 0) {
6✔
158
      destroy_pool(res->pool);
159
      return NULL;
×
160
    }
×
161

162
    pr_netaddr_set_sockaddr(local_addr, pr_netaddr_get_sockaddr(c->local_addr));
163
    res->local_addr = local_addr;
6✔
164
  }
6✔
165

166
  if (c->remote_addr != NULL) {
167
    pr_netaddr_t *remote_addr;
6✔
168

1✔
169
    remote_addr = pr_netaddr_alloc(res->pool);
170

1✔
171
    if (pr_netaddr_set_family(remote_addr,
172
        pr_netaddr_get_family(c->remote_addr)) < 0) {
1✔
173
      destroy_pool(res->pool);
174
      return NULL;
×
175
    }
×
176

177
    pr_netaddr_set_sockaddr(remote_addr,
178
      pr_netaddr_get_sockaddr(c->remote_addr));
1✔
179
    res->remote_addr = remote_addr;
180
  }
1✔
181

182
  if (c->remote_name != NULL) {
183
    res->remote_name = pstrdup(res->pool, c->remote_name);
6✔
184
  }
1✔
185

186
  res->use_nodelay = c->use_nodelay;
187

6✔
188
  register_cleanup2(res->pool, (void *) res, conn_cleanup_cb);
6✔
189
  return res;
190
}
191

192
/* Initialize a new connection record, also creates a new subpool just for the
193
 * new connection.
194
 */
71✔
195
static conn_t *init_conn(pool *p, int fd, const pr_netaddr_t *bind_addr,
196
    int port, int flags) {
71✔
197
  pool *sub_pool = NULL;
71✔
198
  conn_t *c;
71✔
199
  pr_netaddr_t na;
71✔
200
  int addr_family;
71✔
201
  int res = 0, on = 1, off = 0, hold_errno;
202

71✔
203
  if (p == NULL) {
1✔
204
    errno = inet_errno = EINVAL;
1✔
205
    return NULL;
206
  }
207

70✔
208
  if (inet_pool == NULL) {
16✔
209
    inet_pool = make_sub_pool(permanent_pool);
16✔
210
    pr_pool_tag(inet_pool, "Inet Pool");
211
  }
212

213
  /* Initialize the netaddr. */
70✔
214
  pr_netaddr_clear(&na);
215

70✔
216
  sub_pool = make_sub_pool(p);
70✔
217
  pr_pool_tag(sub_pool, "init_conn pool");
218

70✔
219
  c = (conn_t *) pcalloc(sub_pool, sizeof(conn_t));
70✔
220
  c->pool = sub_pool;
221

70✔
222
  c->local_port = port;
70✔
223
  c->rfd = c->wfd = -1;
224

70✔
225
  /* Disable use of Nagle (i.e. enable TCP_NODELAY) by default. */
6✔
226
  c->use_nodelay = TRUE;
227

64✔
228
  if (bind_addr != NULL) {
229
    addr_family = pr_netaddr_get_family(bind_addr);
230

231
  } else if (inet_family) {
232
    addr_family = inet_family;
233

234
  } else {
235
    /* If no default family has been set, then default to IPv6 (if IPv6
236
     * support is enabled), otherwise use IPv4.
39✔
237
     */
238
#if defined(PR_USE_IPV6)
239
    if (pr_netaddr_use_ipv6()) {
240
      addr_family = AF_INET6;
×
241

242
    } else {
243
      addr_family = AF_INET;
244
    }
245
#else
246
    addr_family = AF_INET;
247
#endif /* PR_USE_IPV6 */
248
  }
249

70✔
250
  /* If fd == -1, there is no currently open socket, so create one.
65✔
251
   */
65✔
252
  if (fd == -1) {
253
    socklen_t salen;
254
    register unsigned int i = 0;
255

256
    /* Certain versions of Solaris apparently require us to be root
257
     * in order to create a socket inside a chroot.
258
     *
259
     * FreeBSD 2.2.6 (possibly other versions as well), has a security
260
     * "feature" which disallows SO_REUSEADDR from working if the socket
261
     * owners don't match.  The easiest thing to do is simply make sure
262
     * the socket is created as root.  (Note: this "feature" seems to apply
263
     * to _all_ BSDs.)
65✔
264
     */
265

266
    if (port != INPORT_ANY) {
267
#if defined(SOLARIS2) || defined(FREEBSD2) || defined(FREEBSD3) || \
268
    defined(FREEBSD4) || defined(FREEBSD5) || defined(FREEBSD6) || \
269
    defined(FREEBSD7) || defined(FREEBSD8) || defined(FREEBSD9) || \
270
    defined(FREEBSD10) || defined(FREEBSD11) || defined(FREEBSD12) || \
271
    defined(FREEBSD13) || defined(FREEBSD14) || \
272
    defined(__OpenBSD__) || defined(__NetBSD__) || \
273
    defined(DARWIN6) || defined(DARWIN7) || defined(DARWIN8) || \
274
    defined(DARWIN9) || defined(DARWIN10) || defined(DARWIN11) || \
275
    defined(DARWIN12) || defined(DARWIN13) || defined(DARWIN14) || \
276
    defined(DARWIN15) || defined(DARWIN16) || defined(DARWIN17) || \
277
    defined(DARWIN18) || \
278
    defined(SCO3) || defined(CYGWIN) || defined(SYSV4_2MP) || \
279
    defined(SYSV5SCO_SV6) || defined(SYSV5UNIXWARE7)
280
# ifdef SOLARIS2
281
      if (port < 1024) {
282
# endif
283
        pr_signals_block();
284
        PRIVS_ROOT
285
# ifdef SOLARIS2
286
      }
65✔
287
# endif
288
#endif
65✔
289
    }
65✔
290

291
    fd = socket(addr_family, SOCK_STREAM, tcp_proto);
65✔
292
    inet_errno = errno;
293

294
    if (port != INPORT_ANY) {
295
#if defined(SOLARIS2) || defined(FREEBSD2) || defined(FREEBSD3) || \
296
    defined(FREEBSD4) || defined(FREEBSD5) || defined(FREEBSD6) || \
297
    defined(FREEBSD7) || defined(FREEBSD8) || defined(FREEBSD9) || \
298
    defined(FREEBSD10) || defined(FREEBSD11) || defined(FREEBSD12) || \
299
    defined(FREEBSD13) || defined(FREEBSD14) || \
300
    defined(__OpenBSD__) || defined(__NetBSD__) || \
301
    defined(DARWIN6) || defined(DARWIN7) || defined(DARWIN8) || \
302
    defined(DARWIN9) || defined(DARWIN10) || defined(DARWIN11) || \
303
    defined(DARWIN12) || defined(DARWIN13) || defined(DARWIN14) || \
304
    defined(DARWIN15) || defined(DARWIN16) || defined(DARWIN17) || \
305
    defined(DARWIN18) || \
306
    defined(SCO3) || defined(CYGWIN) || defined(SYSV4_2MP) || \
307
    defined(SYSV5SCO_SV6) || defined(SYSV5UNIXWARE7)
308
# ifdef SOLARIS2
309
      if (port < 1024) {
310
# endif
311
        PRIVS_RELINQUISH
312
        pr_signals_unblock();
313
# ifdef SOLARIS2
314
      }
65✔
315
# endif
316
#endif
65✔
317
    }
318

×
319
    if (fd == -1) {
×
320
      /* On failure, destroy the connection and return NULL. */
321
      if (flags & PR_INET_CREATE_CONN_FL_LOG_ERRORS) {
322
        pr_log_pri(PR_LOG_WARNING,
323
          "socket() failed in connection initialization: %s",
324
          strerror(inet_errno));
×
325
      }
×
326

×
327
      destroy_pool(c->pool);
328
      errno = inet_errno;
329
      return NULL;
330
    }
65✔
331

332
    /* Allow address reuse. */
×
333
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &on,
334
        sizeof(on)) < 0) {
335
      pr_log_pri(PR_LOG_NOTICE, "error setting SO_REUSEADDR: %s",
336
        strerror(errno));
337
    }
65✔
338

39✔
339
    /* Allow port reuse, if requested. */
36✔
340
    if (main_server != NULL &&
36✔
341
        main_server->tcp_reuse_port != -1) {
36✔
342
      res = pr_inet_set_reuse_port(p, c, main_server->tcp_reuse_port);
343
      if (res < 0) {
36✔
344
        pr_trace_msg(trace_channel, 8,
345
          "error setting socket fd %d reuseport = %d: %s", fd,
346
          main_server->tcp_reuse_port,
347
        strerror(errno));
×
348

×
349
      } else {
350
        pr_trace_msg(trace_channel, 8, "set socket fd %d reuseport = %d",
351
          fd, main_server->tcp_reuse_port);
352
      }
353
    }
354

355
    /* Allow socket keepalive messages by default.  However, if
356
     * "SocketOptions keepalive off" is in effect, then explicitly
65✔
357
     * disable keepalives.
39✔
358
     */
39✔
359
    if (main_server != NULL &&
×
360
        main_server->tcp_keepalive != NULL &&
361
        main_server->tcp_keepalive->keepalive_enabled == FALSE) {
×
362
      pr_trace_msg(trace_channel, 17, "disabling SO_KEEPALIVE on socket fd %d",
363
        fd);
364
      res = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *) &off,
365
        sizeof(off));
65✔
366

367
    } else {
65✔
368
      pr_trace_msg(trace_channel, 17, "enabling SO_KEEPALIVE on socket fd %d",
369
        fd);
370
      res = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *) &on, sizeof(on));
65✔
371
    }
×
372

373
    if (res < 0) {
374
      pr_log_pri(PR_LOG_NOTICE,
375
        "error setting SO_KEEPALIVE on socket fd %d: %s", fd, strerror(errno));
376
    }
377

65✔
378
#if defined(IP_FREEBIND)
379
    /* Allow binding to an as-yet-nonexistent address. */
×
380
    if (setsockopt(fd, SOL_IP, IP_FREEBIND, (void *) &on,
×
381
        sizeof(on)) < 0) {
382
      if (errno != ENOSYS) {
383
        pr_log_pri(PR_LOG_INFO, "error setting IP_FREEBIND: %s",
384
          strerror(errno));
385
      }
386
    }
65✔
387
#endif /* IP_FREEBIND */
65✔
388

389
    memset(&na, 0, sizeof(na));
65✔
390
    pr_netaddr_set_family(&na, addr_family);
6✔
391

392
    if (bind_addr != NULL) {
393
      pr_netaddr_set_sockaddr(&na, pr_netaddr_get_sockaddr(bind_addr));
59✔
394

395
    } else {
396
      pr_netaddr_set_sockaddr_any(&na);
397
    }
65✔
398

399
#if defined(PR_USE_IPV6) && defined(IPV6_V6ONLY)
38✔
400
    if (pr_netaddr_use_ipv6() &&
38✔
401
        addr_family == AF_INET6) {
402
      int level = ipv6_proto;
403
      socklen_t len = sizeof(off);
404

405
      /* If creating a wildcard socket IPv6 socket, make sure that it
406
       * will accept IPv4 connections as well.  This is the default on
407
       * Linux and Solaris; BSD usually defaults to allowing only IPv6
408
       * (depending on the net.inet6.ip6.v6only sysctl value).
409
       *
410
       * Ideally, this setsockopt() call would be configurable via the
411
       * SocketOptions directive.
38✔
412
       */
38✔
413

×
414
      if (getsockopt(fd, level, IPV6_V6ONLY, (void *) &off, &len) >= 0) {
415
        if (off != 0) {
×
416
          off = 0;
417

418
          pr_trace_msg(trace_channel, 5,
×
419
            "disabling IPV6_V6ONLY on server socket fd %d", fd);
420

421
          res = setsockopt(fd, level, IPV6_V6ONLY, (void *) &off, len);
422

423
          /* Bug#3237 shows that some systems do NOT like setting the V6ONLY
424
           * option on an IPv4-mapped IPv6 address.  However, other systems
425
           * (e.g. FreeBSD) require that this be done in order for EPSV
426
           * to work properly.  Portability strikes again!
×
427
           */
428

×
429
          if (res < 0
430
#ifdef ENOPROTOOPT
431
              && errno != ENOPROTOOPT
×
432
#endif /* !ENOPROTOOPT */
433
              ) {
434
            pr_log_pri(PR_LOG_NOTICE, "error setting IPV6_V6ONLY: %s",
435
              strerror(errno));
436
          }
437
        }
×
438

439
      } else {
440
        pr_trace_msg(trace_channel, 3,
441
          "error getting IPV6_V6ONLY setting on socket fd %d: %s", fd,
442
          strerror(errno));
443
      }
444
    }
65✔
445
#endif /* PR_USE_IPV6 and IPV6_V6ONLY */
446

65✔
447
    pr_netaddr_set_port(&na, htons(port));
65✔
448

×
449
    if (port != INPORT_ANY &&
×
450
        port < 1024) {
451
      pr_signals_block();
452
      PRIVS_ROOT
65✔
453
    }
×
454

455
    if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
456
      pr_log_pri(PR_LOG_WARNING, "unable to set CLOEXEC on socket fd %d: %s",
457
        fd, strerror(errno));
458
    }
459

460
    /* According to one expert, the very nature of the FTP protocol, and it's
461
     * multiple data-connections creates problems with "rapid-fire" connections
462
     * (transferring lots of files) causing an eventual "Address already in use"
463
     * error.  As a result, this nasty kludge retries ten times (once per
65✔
464
     * second) if the port being bound to is INPORT_ANY.
65✔
465
     */
65✔
466
    for (i = 10; i > 0; i--) {
65✔
467
      pr_trace_msg(trace_channel, 19,
468
        "attempting to bind to %s#%d (%u %s remaining)",
65✔
469
        pr_netaddr_get_ipstr(&na), port, i, i != 1 ? "attempts" : "attempt");
65✔
470
      res = bind(fd, pr_netaddr_get_sockaddr(&na),
×
471
        pr_netaddr_get_sockaddr_len(&na));
×
472
      hold_errno = errno;
×
473

474
      if (res == -1 &&
475
          hold_errno == EINTR) {
65✔
476
        pr_signals_handle();
477
        i++;
478
        continue;
479
      }
480

481
      if (res != -1 ||
482
        /* Note that on Solaris, bind(2) might fail with EACCES if the
483
         * randomly selected port for e.g. passive transfers is used by
484
         * NFS.  Thus, for Solaris only, we treat EACCES as the same as
65✔
485
         * EADDRINUSE.  Silly Solaris.
486
         */
×
487
#ifdef SOLARIS2
488
          (hold_errno != EADDRINUSE && hold_errno != EACCES) ||
489
#else
490
          hold_errno != EADDRINUSE ||
×
491
#endif /* SOLARIS2 */
492
          (port != INPORT_ANY &&
×
493
           !(flags & PR_INET_CREATE_CONN_FL_RETRY_BIND))) {
×
494
        break;
495
      }
496

×
497
      if (port != INPORT_ANY &&
498
          port < 1024) {
×
499
        PRIVS_RELINQUISH
500
        pr_signals_unblock();
×
501
      }
×
502

503
      pr_timer_sleep(1);
504

505
      if (port != INPORT_ANY &&
65✔
506
          port < 1024) {
×
507
        pr_signals_block();
508
        PRIVS_ROOT
×
509
      }
×
510
    }
511

512
    if (res == -1) {
×
513
      if (port != INPORT_ANY &&
×
514
          port < 1024) {
515
        PRIVS_RELINQUISH
×
516
        pr_signals_unblock();
517
      }
×
518

519
      pr_log_pri(PR_LOG_ERR, "Failed binding to %s, port %d: %s",
520
        pr_netaddr_get_ipstr(&na), port, strerror(hold_errno));
521

522
      if (flags & PR_INET_CREATE_CONN_FL_LOG_ERRORS) {
×
523
        pr_log_pri(PR_LOG_ERR, "Check the ServerType directive to ensure "
×
524
          "you are configured correctly");
×
525
        pr_log_pri(PR_LOG_ERR, "Check to see if inetd/xinetd, or another "
526
          "proftpd instance, is already using %s, port %d",
×
527
          pr_netaddr_get_ipstr(&na), port);
×
528
      }
529

530
      inet_errno = hold_errno;
65✔
531
      destroy_pool(c->pool);
532
      (void) close(fd);
×
533

×
534
      errno = inet_errno;
535
      return NULL;
536
    }
537

538
    if (port != INPORT_ANY &&
539
        port < 1024) {
540
      PRIVS_RELINQUISH
65✔
541
      pr_signals_unblock();
65✔
542
    }
65✔
543

544
    /* We use getsockname here because the caller might be binding to
65✔
545
     * INPORT_ANY (0), in which case our port number will be dynamic.
546
     */
547

548
    salen = pr_netaddr_get_sockaddr_len(&na);
65✔
549
    if (getsockname(fd, pr_netaddr_get_sockaddr(&na), &salen) == 0) {
550
      pr_netaddr_t *local_addr;
551

65✔
552
      if (c->local_addr != NULL) {
65✔
553
        local_addr = (pr_netaddr_t *) c->local_addr;
65✔
554

555
      } else {
65✔
556
        local_addr = pr_netaddr_alloc(c->pool);
65✔
557
      }
558

559
      pr_netaddr_set_family(local_addr, pr_netaddr_get_family(&na));
560
      pr_netaddr_set_sockaddr(local_addr, pr_netaddr_get_sockaddr(&na));
×
561
      c->local_port = ntohs(pr_netaddr_get_port(&na));
562

563
      if (c->local_addr == NULL) {
564
        c->local_addr = local_addr;
565
      }
566

5✔
567
    } else {
5✔
568
      pr_log_debug(DEBUG3, "getsockname error on socket fd %d: %s", fd,
569
        strerror(errno));
570
    }
571

70✔
572
  } else {
70✔
573
    /* Make sure the netaddr has its address family set. */
574
    if (pr_netaddr_get_family(&na) == 0) {
70✔
575
      pr_netaddr_set_family(&na, addr_family);
576
    }
577
  }
70✔
578

579
  c->listen_fd = fd;
580
  register_cleanup2(c->pool, (void *) c, conn_cleanup_cb);
70✔
581

582
  pr_trace_msg("binding", 4, "bound address %s, port %d to socket fd %d",
70✔
583
    pr_netaddr_get_ipstr(&na), c->local_port, fd);
584

70✔
585
  return c;
70✔
586
}
1✔
587

588
conn_t *pr_inet_create_conn2(pool *p, int fd, const pr_netaddr_t *bind_addr,
589
    int port, int flags) {
70✔
590
  conn_t *c = NULL;
591

592
  c = init_conn(p, fd, bind_addr, port, flags);
593
  if (c == NULL) {
594
    errno = inet_errno;
595
  }
3✔
596

597
  return c;
3✔
598
}
3✔
599

3✔
600
conn_t *pr_inet_create_conn(pool *p, int fd, const pr_netaddr_t *bind_addr,
3✔
601
    int port, int retry_bind) {
602
  int flags = 0;
3✔
603

3✔
604
  flags = PR_INET_CREATE_CONN_FL_LOG_ERRORS;
1✔
605
  if (retry_bind == TRUE) {
1✔
606
    flags |= PR_INET_CREATE_CONN_FL_RETRY_BIND;
607
  }
608

2✔
609
  return pr_inet_create_conn2(p, fd, bind_addr, port, flags);
1✔
610
}
1✔
611

612
/* Attempt to create a connection bound to a given port range, returns NULL
613
 * if unable to bind to any port in the range.
614
 */
1✔
615
conn_t *pr_inet_create_conn_portrange(pool *p, const pr_netaddr_t *bind_addr,
×
616
    int low_port, int high_port) {
×
617
  int range_len, i;
618
  int *range, *ports;
619
  int attempt, random_index, xerrno = 0;
1✔
620
  conn_t *c = NULL;
1✔
621

1✔
622
  if (low_port < 0 ||
623
      high_port < 0) {
1✔
624
    errno = EINVAL;
16,384✔
625
    return NULL;
16,383✔
626
  }
627

628
  if (low_port >= high_port) {
2✔
629
    errno = EPERM;
2✔
630
    return NULL;
1✔
631
  }
632

633
  /* Make sure the temporary inet work pool exists. */
634
  if (inet_pool == NULL) {
635
    inet_pool = make_sub_pool(permanent_pool);
1✔
636
    pr_pool_tag(inet_pool, "Inet Pool");
637
  }
1✔
638

639
  range_len = high_port - low_port + 1;
640
  range = (int *) pcalloc(inet_pool, range_len * sizeof(int));
641
  ports = (int *) pcalloc(inet_pool, range_len * sizeof(int));
642

1✔
643
  i = range_len;
644
  while (i--) {
645
    range[i] = low_port + i;
646
  }
647

2,620✔
648
  for (attempt = 3; attempt > 0 && c == NULL; attempt--) {
2,619✔
649
    for (i = range_len - 1; i >= 0 && c == NULL; i--) {
650
      pr_signals_handle();
651

652
      /* If this is the first attempt through the range, randomize
1✔
653
       * the order of the port numbers used.
1✔
654
       */
655
      if (attempt == 3) {
656
        /* Obtain a random index into the port array range. */
657
        random_index = (int) ((1.0 * i * rand()) / (RAND_MAX+1.0));
658

659
        /* Copy the port at that index into the array from which port
660
         * numbers will be selected when calling init_conn().
661
         */
662
        ports[i] = range[random_index];
×
663

664
        /* Move non-selected numbers down so that the next randomly chosen
×
665
         * port will be from the range of as-yet untried ports.
666
         */
×
667
        while (++random_index <= i) {
668
          range[random_index-1] = range[random_index];
669
        }
670
      }
671

672
      c = init_conn(p, -1, bind_addr, ports[i], 0);
673
      xerrno = errno;
674

49✔
675
      if (c == NULL) {
49✔
676
        pr_trace_msg(trace_channel, 19, "unable to bind to %s:%d: %s",
677
          bind_addr != NULL ? pr_netaddr_get_ipstr(bind_addr) : "0.0.0.0",
678
          ports[i], strerror(xerrno));
679
      }
680
    }
681
  }
682

683
  errno = xerrno;
684
  return c;
685
}
686

47✔
687
void pr_inet_close(pool *p, conn_t *c) {
47✔
688
  if (c == NULL) {
689
    return;
690
  }
691

692
  /* It is not necessary to close the fds or schedule netio streams for
15✔
693
   * removal, because the creator of the connection (either
15✔
694
   * pr_inet_create_conn() or pr_inet_copy_conn() will have registered a pool
695
   * cleanup handler (conn_cleanup_cb()) which will do all this for us.
696
   * Simply destroy the pool and all the dirty work gets done.
697
   */
14✔
698

699
  if (c->pool != NULL) {
14✔
700
    destroy_pool(c->pool);
1✔
701
  }
702
}
703

704
/* Perform shutdown/read on streams */
705
void pr_inet_lingering_close(pool *p, conn_t *c, long linger) {
706
  if (c == NULL) {
14✔
707
    return;
1✔
708
  }
709

710
  (void) pr_inet_set_block(p, c);
14✔
711

14✔
712
  if (c->outstrm != NULL) {
713
    pr_netio_lingering_close(c->outstrm, linger);
14✔
714
  }
715

716
  /* Only close the input stream if it is actually a different stream than
717
   * the output stream.
10✔
718
   */
10✔
719
  if (c->instrm != c->outstrm) {
720
    pr_netio_close(c->instrm);
721
  }
722

9✔
723
  c->outstrm = NULL;
724
  c->instrm = NULL;
9✔
725

1✔
726
  destroy_pool(c->pool);
727
}
728

729
/* Similar to a lingering close, perform a lingering abort. */
730
void pr_inet_lingering_abort(pool *p, conn_t *c, long linger) {
731
  if (c == NULL) {
732
    return;
733
  }
734

735
  (void) pr_inet_set_block(p, c);
9✔
736

1✔
737
  if (c->instrm != NULL) {
738
    pr_netio_lingering_abort(c->instrm, linger);
739
  }
9✔
740

9✔
741
  /* Only close the output stream if it is actually a different stream
742
   * than the input stream.
9✔
743
   *
744
   * Note: we do not call pr_netio_lingering_abort() on the input stream
745
   * since doing so would result in two 426 responses sent; we only
19✔
746
   * want and need one.
19✔
747
   */
748
  if (c->outstrm != c->instrm) {
749
    pr_netio_close(c->outstrm);
750
  }
751

752
  c->instrm = NULL;
753
  c->outstrm = NULL;
754

755
  destroy_pool(c->pool);
756
}
757

758
int pr_inet_set_proto_cork(int sockfd, int cork) {
759
  int res = 0;
19✔
760

761
  /* Linux defines TCP_CORK; BSD-derived systems (including Mac OSX) use
762
   * TCP_NOPUSH.
763
   *
764
   * Both options work by "corking" the socket, only sending TCP packets
765
   * if there's enough data for a full packet, otherwise buffering the data
766
   * to be written.  "Uncorking" the socket should flush out the buffered
2✔
767
   * data.
768
   */
769

770
#if defined(TCP_CORK) || defined(TCP_NOPUSH)
771
# ifdef SOL_TCP
772
  int tcp_level = SOL_TCP;
19✔
773
# else
774
  int tcp_level = tcp_proto;
775
# endif /* SOL_TCP */
9✔
776
#endif /* TCP_CORK or TCP_NOPUSH */
777

778
#if defined(TCP_CORK)
9✔
779
  res = setsockopt(sockfd, tcp_level, TCP_CORK, (void *) &cork, sizeof(cork));
780

9✔
781
#elif defined(TCP_NOPUSH)
782
  res = setsockopt(sockfd, tcp_level, TCP_NOPUSH, (void *) &cork, sizeof(cork));
783
#endif
784

785
  return res;
9✔
786
}
1✔
787

1✔
788
int pr_inet_set_proto_nodelay(pool *p, conn_t *conn, int nodelay) {
789

790
#if defined(TCP_NODELAY)
8✔
791
  int res = 0;
3✔
792
# ifdef SOL_TCP
793
  int tcp_level = SOL_TCP;
3✔
794
# else
3✔
795
  int tcp_level = tcp_proto;
1✔
796
# endif /* SOL_TCP */
797

798
  if (conn == NULL) {
799
    errno = EINVAL;
800
    return -1;
8✔
801
  }
3✔
802

803
  if (conn->rfd != -1) {
3✔
804
    res = setsockopt(conn->rfd, tcp_level, TCP_NODELAY, (void *) &nodelay,
3✔
805
      sizeof(nodelay));
806
    if (res < 0 &&
1✔
807
        errno != EBADF) {
808
      pr_log_pri(PR_LOG_NOTICE, "error setting read fd %d TCP_NODELAY %d: %s",
809
       conn->rfd, nodelay, strerror(errno));
810
    }
811
  }
812

813
  if (conn->wfd != -1) {
814
    res = setsockopt(conn->wfd, tcp_level, TCP_NODELAY, (void *) &nodelay,
815
      sizeof(nodelay));
18✔
816
    if (res < 0 &&
817
        errno != EBADF &&
818
        errno != EINVAL) {
819
      pr_log_pri(PR_LOG_NOTICE, "error setting write fd %d TCP_NODELAY %d: %s",
820
       conn->wfd, nodelay, strerror(errno));
821
    }
822
  }
823
#endif
824

825
  return 0;
18✔
826
}
827

828
int pr_inet_set_proto_opts(pool *p, conn_t *c, int mss, int nodelay,
829
    int tos, int nopush) {
830

831
  /* More portability fun.  Traditional BSD-style sockets want the value from
18✔
832
   * getprotobyname() in the setsockopt(2) call; Linux wants SOL_TCP for
833
   * these options.  Also, *BSD want IPPROTO_IP for IP_TOS options, Linux
834
   * wants SOL_IP.  How many other platforms will have variations?  Will
835
   * networking code always be this fragmented?
18✔
836
   */
837
#ifdef SOL_IP
838
  int ip_level = SOL_IP;
839
#else
840
  int ip_level = ip_proto;
841
#endif /* SOL_IP */
18✔
842

1✔
843
#ifdef SOL_TCP
1✔
844
  int tcp_level = SOL_TCP;
845
#else
846
  int tcp_level = tcp_proto;
847
#endif /* SOL_TCP */
848

849
  /* Some of these setsockopt() calls may fail when they operate on IPv6
17✔
850
   * sockets, rather than on IPv4 sockets.
6✔
851
   */
852

853
  if (c == NULL) {
6✔
854
    errno = EINVAL;
×
855
    return -1;
17✔
856
  }
7✔
857

858
#if defined(TCP_NODELAY)
7✔
859
  if (c->rfd != -1) {
5✔
860
    if (setsockopt(c->rfd, tcp_level, TCP_NODELAY, (void *) &nodelay,
861
        sizeof(nodelay)) < 0) {
862
      if (errno != EBADF) {
863
        pr_log_pri(PR_LOG_NOTICE,
864
          "error setting read fd %d TCP_NODELAY=%d: %s", c->rfd, nodelay,
865
          strerror(errno));
17✔
866
      }
3✔
867
    }
868
  }
3✔
869

1✔
870
  if (c->wfd != -1) {
871
    if (setsockopt(c->wfd, tcp_level, TCP_NODELAY, (void *) &nodelay,
872
        sizeof(nodelay)) < 0) {
873
      if (errno != EBADF) {
874
        pr_log_pri(PR_LOG_NOTICE,
875
          "error setting write fd %d TCP_NODELAY=%d: %s", c->wfd, nodelay,
17✔
876
          strerror(errno));
17✔
877
      }
878
    }
3✔
879
  }
1✔
880

881
  if (c->listen_fd != -1) {
882
    if (setsockopt(c->listen_fd, tcp_level, TCP_NODELAY, (void *) &nodelay,
883
        sizeof(nodelay)) < 0) {
884
      if (errno != EBADF) {
885
        pr_log_pri(PR_LOG_NOTICE,
886
          "error setting listen fd %d TCP_NODELAY=%d: %s",
887
          c->listen_fd, nodelay, strerror(errno));
888
      }
889
    }
17✔
890
  }
17✔
891
#endif /* TCP_NODELAY */
11✔
892

893
#if defined(TCP_MAXSEG)
11✔
894
  if (c->listen_fd != -1 &&
11✔
895
      mss > 0) {
896
    if (setsockopt(c->listen_fd, tcp_level, TCP_MAXSEG, &mss,
897
        sizeof(mss)) < 0) {
898
      pr_log_pri(PR_LOG_NOTICE, "error setting listen fd TCP_MAXSEG(%d): %s",
899
        mss, strerror(errno));
900
    }
901
  }
17✔
902
#endif /* TCP_MAXSEG */
13✔
903

13✔
904
#if defined(IP_TOS)
905
  /* Only set TOS flags on IPv4 sockets; IPv6 sockets use TCLASS. */
2✔
906
  if (pr_netaddr_get_family(c->local_addr) == AF_INET) {
2✔
907
    if (c->listen_fd != -1) {
908
      if (setsockopt(c->listen_fd, ip_level, IP_TOS, (void *) &tos,
909
          sizeof(tos)) < 0) {
910
        pr_log_pri(PR_LOG_NOTICE, "error setting listen fd IP_TOS: %s",
911
          strerror(errno));
912
      }
913
    }
17✔
914
  }
915
#endif /* IP_TOS */
17✔
916

4✔
917
#if defined(PR_USE_IPV6) && defined(IPV6_TCLASS)
4✔
918
  if (pr_netaddr_use_ipv6()) {
919
    /* Only set TCLASS flags on IPv6 sockets; IPv4 sockets use TOS. */
4✔
920
    if (pr_netaddr_get_family(c->local_addr) == AF_INET6) {
4✔
921
      if (c->listen_fd != -1) {
922
        int level, res;
4✔
923

1✔
924
        level = ipv6_proto;
925
        res = setsockopt(c->listen_fd, level, IPV6_TCLASS, (void *) &tos,
1✔
926
          sizeof(tos));
927
        if (res < 0
928
            && errno != EINVAL
1✔
929
#ifdef ENOPROTOOPT
930
            && errno != ENOPROTOOPT
931
#endif /* !ENOPROTOOPT */
932
          ) {
933
          pr_log_pri(PR_LOG_NOTICE, "error setting listen fd IPV6_TCLASS: %s",
934
            strerror(errno));
935
        }
936
      }
17✔
937
    }
17✔
938
  }
3✔
939
#endif /* IPV6_TCLASS */
3✔
940

941
  if (c->listen_fd != -1) {
942
    if (pr_inet_set_proto_cork(c->listen_fd, nopush) < 0) {
943
      pr_log_pri(PR_LOG_NOTICE, "error corking listen fd %d: %s", c->listen_fd,
944
        strerror(errno));
945
    }
946
  }
22✔
947

948
  return 0;
22✔
949
}
950

22✔
951
int pr_inet_set_proto_keepalive(pool *p, conn_t *c,
22✔
952
    struct tcp_keepalive *tcp_keepalive) {
953
  int keepalive = 1, val = -1;
7✔
954

7✔
955
  if (p == NULL ||
956
      c == NULL ||
957
      tcp_keepalive == NULL) {
15✔
958
    errno = EINVAL;
1✔
959
    return -1;
1✔
960
  }
961

962
  if (c->listen_fd < 0) {
14✔
963
    errno = EINVAL;
964
    return -1;
14✔
965
  }
966

14✔
967
  keepalive = tcp_keepalive->keepalive_enabled;
968

10✔
969
  pr_trace_msg(trace_channel, 17, "%s SO_KEEPALIVE on socket fd %d",
5✔
970
    keepalive ? "enabling" : "disabling", c->listen_fd);
5✔
971
  if (setsockopt(c->listen_fd, SOL_SOCKET, SO_KEEPALIVE, (void *) &keepalive,
972
      sizeof(int)) < 0) {
973
    pr_log_pri(PR_LOG_NOTICE, "error setting listen fd SO_KEEPALIVE: %s",
9✔
974
      strerror(errno));
975
    return 0;
976
  }
977

978
  if (keepalive == 0) {
979
    return 0;
980
  }
9✔
981

982
  /* We only try to set the TCP keepalive specifics if SO_KEEPALIVE was
983
   * enabled successfully.
984
   */
985
  pr_trace_msg(trace_channel, 15, "enabled SO_KEEPALIVE on socket fd %d",
986
    c->listen_fd);
987

9✔
988
  /* On Mac OS, the socket option is TCP_KEEPALIVE rather than
9✔
989
   * TCP_KEEPIDLE.
2✔
990
   */
991
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE)
992
  val = tcp_keepalive->keepalive_idle;
993
  if (val != -1) {
994
    int option_name;
2✔
995

996
# if defined(TCP_KEEPALIVE)
997
    option_name = TCP_KEEPALIVE;
998
# else
999
    option_name = TCP_KEEPIDLE;
1000
# endif /* TCP_KEEPALIVE or TCP_KEEPIDLE */
1001

2✔
1002
# ifdef __DragonFly__
1003
    /* DragonFly BSD uses millsecs as the KEEPIDLE unit. */
×
1004
    val *= 1000;
1005
# endif /* DragonFly BSD */
×
1006
    if (setsockopt(c->listen_fd, IPPROTO_TCP, option_name, (void *) &val,
1007
        sizeof(int)) < 0) {
1008
      pr_log_pri(PR_LOG_NOTICE,
2✔
1009
        "error setting TCP_KEEPIDLE %d on fd %d: %s", val, c->listen_fd,
1010
       strerror(errno));
1011

1012
    } else {
1013
      pr_trace_msg(trace_channel, 15,
1014
        "enabled TCP_KEEPIDLE %d on socket fd %d", val, c->listen_fd);
1015
    }
9✔
1016
  }
9✔
1017
#endif /* TCP_KEEPIDLE */
2✔
1018

1019
#if defined(TCP_KEEPCNT)
×
1020
  val = tcp_keepalive->keepalive_count;
1021
  if (val != -1) {
×
1022
    if (setsockopt(c->listen_fd, IPPROTO_TCP, TCP_KEEPCNT, (void *) &val,
1023
        sizeof(int)) < 0) {
1024
      pr_log_pri(PR_LOG_NOTICE,
2✔
1025
        "error setting TCP_KEEPCNT %d on fd %d: %s", val, c->listen_fd,
1026
        strerror(errno));
1027

1028
    } else {
1029
      pr_trace_msg(trace_channel, 15,
1030
        "enabled TCP_KEEPCNT %d on socket fd %d", val, c->listen_fd);
1031
    }
9✔
1032
  }
9✔
1033
#endif /* TCP_KEEPCNT */
1034

1035
#if defined(TCP_KEEPINTVL)
1036
  val = tcp_keepalive->keepalive_intvl;
1037
  if (val != -1) {
2✔
1038
# ifdef __DragonFly__
1039
    /* DragonFly BSD uses millsecs as the KEEPINTVL unit. */
×
1040
    val *= 1000;
1041
# endif /* DragonFly BSD */
×
1042
    if (setsockopt(c->listen_fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *) &val,
1043
        sizeof(int)) < 0) {
1044
      pr_log_pri(PR_LOG_NOTICE,
2✔
1045
        "error setting TCP_KEEPINTVL %d on fd %d: %s", val, c->listen_fd,
1046
        strerror(errno));
1047

1048
    } else {
1049
      pr_trace_msg(trace_channel, 15,
1050
        "enabled TCP_KEEPINTVL %d on socket fd %d", val, c->listen_fd);
1051
    }
1052
  }
1053
#endif /* TCP_KEEPINTVL */
1054

1055
  /* Avoid compiler warnings on platforms which do not support any
1056
   * of the above TCP keepalive macros.
1057
   */
1058
  (void) val;
1059

21✔
1060
  return 0;
1061
}
1062

21✔
1063
/* Set socket options on a connection.  */
2✔
1064
int pr_inet_set_socket_opts2(pool *p, conn_t *c, int rcvbuf, int sndbuf,
2✔
1065
    struct tcp_keepalive *tcp_keepalive, int reuse_port) {
1066

1067
  if (c == NULL) {
1068
    errno = EINVAL;
1069
    return -1;
1070
  }
1071

1072
  /* Linux and "most" newer networking OSes probably use a highly adaptive
1073
   * window size system, which generally wouldn't require user-space
1074
   * modification at all.  Thus, check the current sndbuf and rcvbuf sizes
19✔
1075
   * before changing them, and only change them if we are making them larger
17✔
1076
   * than their current size.
17✔
1077
   */
1078

17✔
1079
  if (c->listen_fd != -1) {
1080
    int crcvbuf = 0, csndbuf = 0;
17✔
1081
    socklen_t len;
8✔
1082

8✔
1083
    (void) pr_inet_set_proto_keepalive(p, c, tcp_keepalive);
1084

6✔
1085
    if (sndbuf > 0) {
2✔
1086
      len = sizeof(csndbuf);
1087
      if (getsockopt(c->listen_fd, SOL_SOCKET, SO_SNDBUF, (void *) &csndbuf,
×
1088
          &len) == 0) {
×
1089
        if (sndbuf > csndbuf) {
1090
          if (setsockopt(c->listen_fd, SOL_SOCKET, SO_SNDBUF, (void *) &sndbuf,
1091
              sizeof(sndbuf)) < 0) {
2✔
1092
            pr_log_pri(PR_LOG_NOTICE, "error setting listen fd SO_SNDBUF: %s",
1093
              strerror(errno));
1094

1095
          } else {
1096
            pr_trace_msg("data", 8,
4✔
1097
              "set socket sndbuf of %lu bytes", (unsigned long) sndbuf);
1098
          }
1099

1100
        } else {
1101
          pr_trace_msg("data", 8,
1102
            "socket fd %d has sndbuf of %lu bytes, ignoring "
1103
            "requested %lu bytes sndbuf", c->listen_fd, (unsigned long) csndbuf,
2✔
1104
            (unsigned long) sndbuf);
1105
        }
2✔
1106

1107
      } else {
1108
        pr_trace_msg("data", 3,
1109
          "error getting SO_SNDBUF on listen fd %d: %s", c->listen_fd,
17✔
1110
          strerror(errno));
1111
      }
17✔
1112
    }
8✔
1113

8✔
1114
    c->sndbuf = (sndbuf ? sndbuf : csndbuf);
1115

6✔
1116
    if (rcvbuf > 0) {
2✔
1117
      len = sizeof(crcvbuf);
1118
      if (getsockopt(c->listen_fd, SOL_SOCKET, SO_RCVBUF, (void *) &crcvbuf,
×
1119
          &len) == 0) {
×
1120
        if (rcvbuf > crcvbuf) {
1121
          if (setsockopt(c->listen_fd, SOL_SOCKET, SO_RCVBUF, (void *) &rcvbuf,
1122
              sizeof(rcvbuf)) < 0) {
2✔
1123
            pr_log_pri(PR_LOG_NOTICE, "error setting listen fd SO_RCVFBUF: %s",
1124
              strerror(errno));
1125

1126
          } else {
1127
            pr_trace_msg("data", 8,
4✔
1128
              "set socket rcvbuf of %lu bytes", (unsigned long) rcvbuf);
1129
          }
1130

1131
        } else {
1132
          pr_trace_msg("data", 8,
1133
           "socket fd %d has rcvbuf of %lu bytes, ignoring "
1134
            "requested %lu bytes rcvbuf", c->listen_fd, (unsigned long) crcvbuf,
2✔
1135
            (unsigned long) rcvbuf);
1136
        }
2✔
1137

1138
      } else {
1139
        pr_trace_msg("data", 3,
1140
          "error getting SO_RCVBUF on listen fd %d: %s", c->listen_fd,
17✔
1141
          strerror(errno));
1142
      }
1143
    }
19✔
1144

1145
    c->rcvbuf = (rcvbuf ? rcvbuf : crcvbuf);
1146
  }
1147

1148
  if (reuse_port != -1) {
1149
    /* Note that we only want to use this socket option if we are NOT the
12✔
1150
     * master/parent daemon.  Otherwise, we would allow multiple daemon
12✔
1151
     * processes to bind to the same socket, causing unexpected terror
9✔
1152
     * and madness (see Issue #622).
1153
     */
1154
    if (!is_master) {
1155
      if (pr_inet_set_reuse_port(p, c, reuse_port) == 0) {
1156
        pr_trace_msg("data", 8,
1157
          "set socket fd %d reuseport = %d", c->listen_fd, reuse_port);
1158
      }
1159
    }
1160
  }
7✔
1161

1162
  return 0;
5✔
1163
}
1164

1165
int pr_inet_set_socket_opts(pool *p, conn_t *c, int rcvbuf, int sndbuf,
52✔
1166
    struct tcp_keepalive *tcp_keepalive) {
52✔
1167
  return pr_inet_set_socket_opts2(p, c, rcvbuf, sndbuf, tcp_keepalive, -1);
1168
}
52✔
1169

52✔
1170
int pr_inet_set_reuse_port(pool *p, conn_t *c, int reuse_port) {
51✔
1171
  int res = -1;
2✔
1172

2✔
1173
  if (p == NULL ||
1174
      c == NULL ||
1175
      reuse_port < 0) {
1176
    errno = EINVAL;
50✔
1177
    return -1;
1178
  }
50✔
1179

39✔
1180
  if (c->listen_fd < 0) {
1181
    errno = EBADF;
39✔
1182
    return -1;
1183
  }
1184

1185
#if defined(SO_REUSEPORT)
1186
  res = setsockopt(c->listen_fd, SOL_SOCKET, SO_REUSEPORT, (void *) &reuse_port,
1187
    sizeof(reuse_port));
1188
  if (res < 0) {
1189
    pr_log_pri(PR_LOG_NOTICE,
1190
      "error setting SO_REUSEPORT on fd %d: %s", c->listen_fd,
1191
      strerror(errno));
12✔
1192
  }
12✔
1193
#else
12✔
1194
  errno = ENOSYS;
6✔
1195
#endif /* SO_REUSEPORT */
3✔
1196

3✔
1197
  return res;
1198
}
1199

12✔
1200
#ifdef SO_OOBINLINE
1201
static void set_oobinline(int fd) {
1202
  int on = 1;
1203
  if (fd >= 0) {
12✔
1204
    if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (void*)&on, sizeof(on)) < 0) {
12✔
1205
      pr_log_pri(PR_LOG_NOTICE, "error setting SO_OOBINLINE: %s",
6✔
1206
        strerror(errno));
1207
    }
6✔
1208
  }
6✔
1209
}
3✔
1210
#endif
1211

3✔
1212
#ifdef F_SETOWN
1213
static void set_socket_owner(int fd) {
1214
  if (fd >= 0) {
12✔
1215
    pid_t pid;
1216

1217
    pid = session.pid ? session.pid : getpid();
1218
    if (fcntl(fd, F_SETOWN, pid) < 0) {
1219
      pr_trace_msg(trace_channel, 3,
5✔
1220
        "failed to SETOWN PID %lu on socket fd %d: %s", (unsigned long) pid,
5✔
1221
        fd, strerror(errno));
5✔
1222
    }
1✔
1223
  }
1✔
1224
}
1225
#endif
1226

1227
/* Put a socket in async mode (so SIGURG is raised on OOB)
4✔
1228
 */
1229
int pr_inet_set_async(pool *p, conn_t *c) {
4✔
1230
  if (p == NULL ||
1231
      c == NULL) {
4✔
1232
    errno = EINVAL;
1233
    return -1;
4✔
1234
  }
1235

4✔
1236
#ifdef SO_OOBINLINE
1237
  pr_trace_msg(trace_channel, 7,
4✔
1238
    "setting SO_OOBINLINE for listening socket fd %d", c->listen_fd);
1239
  set_oobinline(c->listen_fd);
1240

1241
  pr_trace_msg(trace_channel, 7,
4✔
1242
    "setting SO_OOBINLINE for reading socket fd %d", c->rfd);
4✔
1243
  set_oobinline(c->rfd);
4✔
1244

1245
  pr_trace_msg(trace_channel, 7,
1246
    "setting SO_OOBINLINE for writing socket fd %d", c->wfd);
4✔
1247
  set_oobinline(c->wfd);
1248
#endif
1249

1250
#ifdef F_SETOWN
1251
  set_socket_owner(c->listen_fd);
8✔
1252
  set_socket_owner(c->rfd);
8✔
1253
  set_socket_owner(c->wfd);
8✔
1254
#endif
1255

8✔
1256
  return 0;
1257
}
8✔
1258

1✔
1259
/* Put a socket in nonblocking mode.
1✔
1260
 */
1261
int pr_inet_set_nonblock(pool *p, conn_t *c) {
1262
  int flags;
7✔
1263
  int res = -1;
1264

7✔
1265
  (void) p;
1266

4✔
1267
  if (c == NULL) {
4✔
1268
    errno = EINVAL;
4✔
1269
    return -1;
1270
  }
1271

1272
  errno = EBADF;                /* Default */
1273

1274
  if (c->mode == CM_LISTEN ||
1275
      c->mode == CM_CONNECT) {
3✔
1276
    flags = fcntl(c->listen_fd, F_GETFL);
1✔
1277
    if (flags >= 0) {
1✔
1278
      res = fcntl(c->listen_fd, F_SETFL, flags|O_NONBLOCK);
1✔
1279

1280
    } else {
1281
      res = flags;
1282
    }
1283

1284
  } else {
1285
    if (c->rfd != -1) {
3✔
1286
      flags = fcntl(c->rfd, F_GETFL);
1✔
1287
      if (flags >= 0) {
1✔
1288
        res = fcntl(c->rfd, F_SETFL, flags|O_NONBLOCK);
1✔
1289

1290
      } else {
1291
        res = flags;
1292
      }
1293
    }
1294

1295
    if (c->wfd != -1) {
1296
      flags = fcntl(c->wfd, F_GETFL);
1297
      if (flags >= 0) {
1298
        res = fcntl(c->wfd, F_SETFL, flags|O_NONBLOCK);
1299

44✔
1300
      } else {
44✔
1301
        res = flags;
44✔
1302
      }
1303
    }
44✔
1304
  }
1305

44✔
1306
  return res;
1✔
1307
}
1✔
1308

1309
int pr_inet_set_block(pool *p, conn_t *c) {
1310
  int flags;
43✔
1311
  int res = -1;
1312

43✔
1313
  (void) p;
1314

16✔
1315
  if (c == NULL) {
16✔
1316
    errno = EINVAL;
15✔
1317
    return -1;
1318
  }
1319

1320
  errno = EBADF;                /* Default */
1321

1322
  if (c->mode == CM_LISTEN ||
1323
      c->mode == CM_CONNECT) {
27✔
1324
    flags = fcntl(c->listen_fd, F_GETFL);
1✔
1325
    if (flags >= 0) {
1✔
1326
      res = fcntl(c->listen_fd, F_SETFL, flags & (U32BITS ^ O_NONBLOCK));
1✔
1327

1328
    } else {
1329
      res = flags;
1330
    }
1331

1332
  } else {
1333
    if (c->rfd != -1) {
27✔
1334
      flags = fcntl(c->rfd, F_GETFL);
1✔
1335
      if (flags >= 0) {
1✔
1336
        res = fcntl(c->rfd, F_SETFL, flags & (U32BITS ^ O_NONBLOCK));
1✔
1337

1338
      } else {
1339
        res = flags;
1340
      }
1341
    }
1342

1343
    if (c->wfd != -1) {
1344
      flags = fcntl(c->wfd, F_GETFL);
1345
      if (flags >= 0) {
1346
        res = fcntl(c->wfd, F_SETFL, flags & (U32BITS ^ O_NONBLOCK));
1347

1348
      } else {
4✔
1349
        res = flags;
4✔
1350
      }
1✔
1351
    }
1✔
1352
  }
1353

1354
  return res;
3✔
1355
}
1✔
1356

1✔
1357
/* Put a connection in listen mode */
1358
int pr_inet_listen(pool *p, conn_t *c, int backlog, int flags) {
1359
  if (c == NULL) {
2✔
1360
    errno = EINVAL;
2✔
1361
    return -1;
1✔
1362
  }
1363

1✔
1364
  if (c->mode == CM_LISTEN) {
×
1365
    errno = EPERM;
×
1366
    return -1;
1367
  }
1368

1✔
1369
  while (TRUE) {
1370
    if (listen(c->listen_fd, backlog) < 0) {
1371
      int xerrno = errno;
1✔
1372

×
1373
      if (xerrno == EINTR) {
1374
        pr_signals_handle();
1375
        continue;
1✔
1376
      }
1✔
1377

1378
      pr_log_pri(PR_LOG_ERR, "unable to listen on %s#%u: %s",
1379
        pr_netaddr_get_ipstr(c->local_addr), c->local_port, strerror(xerrno));
1✔
1380

1381
      if (flags & PR_INET_LISTEN_FL_FATAL_ON_ERROR) {
1382
        pr_session_disconnect(NULL, PR_SESS_DISCONNECT_BY_APPLICATION, NULL);
1✔
1383
      }
1✔
1384

1385
      errno = xerrno;
1386
      return -1;
1387
    }
1388

1389
    break;
3✔
1390
  }
3✔
1391

1✔
1392
  c->mode = CM_LISTEN;
1✔
1393
  return 0;
1394
}
1395

2✔
1396
/* Reset a connection back to listen mode.  Enables blocking mode
2✔
1397
 * for safety.
1✔
1398
 */
1✔
1399
int pr_inet_resetlisten(pool *p, conn_t *c) {
1400
  if (c == NULL) {
1401
    errno = EINVAL;
1402
    return -1;
1403
  }
1404

16✔
1405
  c->mode = CM_LISTEN;
16✔
1406
  if (pr_inet_set_block(c->pool, c) < 0) {
16✔
1407
    c->xerrno = errno;
1408
    return -1;
16✔
1409
  }
16✔
1410

2✔
1411
  return 0;
2✔
1412
}
1413

1414
int pr_inet_connect(pool *p, conn_t *c, const pr_netaddr_t *addr, int port) {
14✔
1415
  pr_netaddr_t remote_na;
14✔
1416
  int res = 0;
×
1417

×
1418
  if (c == NULL ||
×
1419
      addr == NULL) {
1420
    errno = EINVAL;
1421
    return -1;
1422
  }
1423

1424
  c->mode = CM_CONNECT;
1425
  if (pr_inet_set_block(p, c) < 0) {
14✔
1426
    c->mode = CM_ERROR;
14✔
1427
    c->xerrno = errno;
1428
    return -1;
14✔
1429
  }
14✔
1430

14✔
1431
  /* No need to initialize the remote_na netaddr here, as we're directly
14✔
1432
   * copying the data from the given netaddr into that memory area.
12✔
1433
   */
×
1434

×
1435
  memcpy(&remote_na, addr, sizeof(remote_na));
1436
  pr_netaddr_set_port(&remote_na, htons(port));
1437

14✔
1438
  while (TRUE) {
1439
    res = connect(c->listen_fd, pr_netaddr_get_sockaddr(&remote_na),
1440
      pr_netaddr_get_sockaddr_len(&remote_na));
14✔
1441
    if (res < 0 &&
12✔
1442
        errno == EINTR) {
12✔
1443
      pr_signals_handle();
12✔
1444
      continue;
1445
    }
1446

2✔
1447
    break;
1448
  }
2✔
1449

×
1450
  if (res < 0) {
×
1451
    c->mode = CM_ERROR;
×
1452
    c->xerrno = errno;
1453
    return -1;
1454
  }
1455

1456
  c->mode = CM_OPEN;
1457

1458
  if (pr_inet_get_conn_info(c, c->listen_fd) < 0) {
1459
    c->mode = CM_ERROR;
1460
    c->xerrno = errno;
1461
    return -1;
4✔
1462
  }
1463

4✔
1464
  return 1;
1465
}
4✔
1466

4✔
1467
/* Attempt to connect a connection, returning immediately with 1 if connected,
2✔
1468
 * 0 if not connected, or -1 if error.  Only needs to be called once, and can
2✔
1469
 * then be selected for writing.
1470
 */
1471
int pr_inet_connect_nowait(pool *p, conn_t *c, const pr_netaddr_t *addr,
2✔
1472
    int port) {
2✔
1473
  pr_netaddr_t remote_na;
×
1474

×
1475
  if (c == NULL ||
×
1476
      addr == NULL) {
1477
    errno = EINVAL;
1478
    return -1;
1479
  }
1480

1481
  c->mode = CM_CONNECT;
1482
  if (pr_inet_set_nonblock(p, c) < 0) {
2✔
1483
    c->mode = CM_ERROR;
2✔
1484
    c->xerrno = errno;
1485
    return -1;
2✔
1486
  }
2✔
1487

2✔
1488
  /* No need to initialize the remote_na netaddr here, as we're directly
1489
   * copying the data from the given netaddr into that memory area.
1✔
1490
   */
1✔
1491

1492
  memcpy(&remote_na, addr, sizeof(remote_na));
1✔
1493
  pr_netaddr_set_port(&remote_na, htons(port));
1494

1✔
1495
  if (connect(c->listen_fd, pr_netaddr_get_sockaddr(&remote_na),
1✔
1496
      pr_netaddr_get_sockaddr_len(&remote_na)) == -1) {
1497
    if (errno != EINPROGRESS &&
1498
        errno != EALREADY) {
1499
      c->mode = CM_ERROR;
1500
      c->xerrno = errno;
1501

×
1502
      (void) pr_inet_set_block(c->pool, c);
1503

×
1504
      errno = c->xerrno;
×
1505
      return -1;
1506
    }
×
1507

×
1508
    return 0;
×
1509
  }
1510

1511
  c->mode = CM_OPEN;
×
1512

×
1513
  if (pr_inet_get_conn_info(c, c->listen_fd) < 0) {
×
1514
    c->xerrno = errno;
1515

1516
    (void) pr_inet_set_block(c->pool, c);
1517
    errno = c->xerrno;
1518
    return -1;
1519
  }
1520

1521
  if (pr_inet_set_block(c->pool, c) < 0) {
1522
    c->xerrno = errno;
1523
    return -1;
1524
  }
1525

3✔
1526
  return 1;
3✔
1527
}
1528

3✔
1529
/* Accepts a new connection, returning immediately with -1 if no connection is
1✔
1530
 * available.  If a connection is accepted, creating a new conn_t and potential
1✔
1531
 * resolving is deferred, and a normal socket fd is returned for the new
1532
 * connection, which can later be used in pr_inet_openrw() to fully open and
1533
 * resolve addresses.
2✔
1534
 */
1✔
1535
int pr_inet_accept_nowait(pool *p, conn_t *c) {
×
1536
  int fd;
×
1537

1538
  if (c == NULL) {
1539
    errno = EINVAL;
1540
    return -1;
1541
  }
1542

1543
  if (c->mode == CM_LISTEN) {
1544
    if (pr_inet_set_nonblock(c->pool, c) < 0) {
1545
      if (errno != EBADF) {
1546
        pr_trace_msg(trace_channel, 3,
1547
          "error making connection nonblocking: %s", strerror(errno));
2✔
1548
      }
2✔
1549
    }
2✔
1550
  }
2✔
1551

1552
  /* A directive could enforce only IPv4 or IPv6 connections here, by
2✔
1553
   * actually using a sockaddr argument to accept(2), and checking the
2✔
1554
   * family of the connecting entity.
×
1555
   */
1556

1557
  c->mode = CM_ACCEPT;
2✔
1558
  while (TRUE) {
2✔
1559
    pr_signals_handle();
2✔
1560
    fd = accept(c->listen_fd, NULL, NULL);
2✔
1561

1562
    if (fd == -1) {
1563
      if (errno == EINTR) {
×
1564
        continue;
×
1565
      }
×
1566

1567
      if (errno != EWOULDBLOCK) {
1568
        c->mode = CM_ERROR;
×
1569
        c->xerrno = errno;
1570
        return -1;
1571
      }
1572

1573
      c->mode = CM_LISTEN;
1574
      c->xerrno = 0;
×
1575
      return -1;
×
1576
    }
×
1577

1578
    break;
1579
  }
1580

1581
  /* Leave the connection in CM_ACCEPT mode, so others can see
1582
   * our state.  Re-enable blocking mode, however.
1583
   */
1584
  if (pr_inet_set_block(c->pool, c) < 0) {
1585
    if (errno != EBADF) {
1586
      pr_trace_msg(trace_channel, 3,
1587
        "error making connection blocking: %s", strerror(errno));
4✔
1588
    }
1589
  }
4✔
1590

4✔
1591
  return fd;
4✔
1592
}
4✔
1593

4✔
1594
/* Accepts a new connection, cloning the existing conn_t and returning
1595
 * it, or NULL upon error.
4✔
1596
 */
4✔
1597
conn_t *pr_inet_accept(pool *p, conn_t *d, conn_t *c, int rfd, int wfd,
1✔
1598
    unsigned char resolve) {
1✔
1599
  config_rec *allow_foreign_addr_config = NULL;
1600
  conn_t *res = NULL;
1601
  int fd = -1;
1602
  pr_netaddr_t na;
3✔
1603
  socklen_t nalen;
1604

3✔
1605
  if (c == NULL ||
3✔
1606
      d == NULL) {
1607
    errno = EINVAL;
3✔
1608
    return NULL;
1609
  }
3✔
1610

1611
  /* Initialize the netaddr. */
1612
  pr_netaddr_clear(&na);
1613

1614
  pr_netaddr_set_family(&na, pr_netaddr_get_family(c->remote_addr));
1615
  nalen = pr_netaddr_get_sockaddr_len(&na);
1616

3✔
1617
  allow_foreign_addr_config = find_config(TOPLEVEL_CONF, CONF_PARAM,
3✔
1618
    "AllowForeignAddress", FALSE);
1619
  d->mode = CM_ACCEPT;
3✔
1620

3✔
1621
  /* A directive could enforce only IPv4 or IPv6 connections here, by
3✔
1622
   * actually using a sockaddr argument to accept(2), and checking the
×
1623
   * family of the connecting entity.
1624
   */
1625

3✔
1626
  while (TRUE) {
3✔
1627
    pr_signals_handle();
3✔
1628

1629
    fd = accept(d->listen_fd, pr_netaddr_get_sockaddr(&na), &nalen);
1630
    if (fd < 0) {
×
1631
      if (errno == EINTR) {
×
1632
        continue;
1633
      }
×
1634

×
1635
      d->mode = CM_ERROR;
1636
      d->xerrno = errno;
1637
      break;
1638
    }
1639

1640
    if (allow_foreign_addr_config != NULL) {
×
1641
      int allowed;
1642

1643
      allowed = *((int *) allow_foreign_addr_config->argv[0]);
1644
      if (allowed != TRUE) {
×
1645
        /* If foreign addresses (i.e. IP addresses that do not match the
×
1646
         * control connection's remote IP address) are not allowed, we
×
1647
         * need to see just what our remote address IS.
×
1648
         */
1649

1650
        if (getpeername(fd, pr_netaddr_get_sockaddr(&na), &nalen) < 0) {
×
1651
          /* If getpeername(2) fails, should we still allow this connection?
×
1652
           * Caution (and the AllowForeignAddress setting) say "no".
×
1653
           */
1654
          pr_log_pri(PR_LOG_DEBUG, "rejecting passive connection; "
1655
            "failed to get address of remote peer: %s", strerror(errno));
1656
          (void) close(fd);
1657
          continue;
×
1658
        }
×
1659

×
1660
        if (allowed == FALSE) {
1661
          if (pr_netaddr_cmp(&na, c->remote_addr) != 0) {
×
1662
            pr_log_pri(PR_LOG_NOTICE, "SECURITY VIOLATION: Passive connection "
1663
              "from foreign IP address %s rejected (does not match client "
1664
              "IP address %s).", pr_netaddr_get_ipstr(&na),
1665
              pr_netaddr_get_ipstr(c->remote_addr));
×
1666

1667
            (void) close(fd);
1668
            d->mode = CM_ERROR;
1669
            d->xerrno = EACCES;
1670

×
1671
            return NULL;
1672
          }
×
1673

×
1674
        } else {
1675
          char *class_name;
×
1676

×
1677
          /* Check the data connection remote address against BOTH the
×
1678
           * control connection remote address AND the configured <Class>.
×
1679
           */
1680
          class_name = allow_foreign_addr_config->argv[1];
1681

×
1682
          if (pr_netaddr_cmp(&na, c->remote_addr) != 0) {
1683
            const pr_class_t *cls;
1684

1685
            cls = pr_class_find(class_name);
1686
            if (cls != NULL) {
×
1687
              if (pr_class_satisfied(p, cls, &na) != TRUE) {
×
1688
                pr_log_debug(DEBUG8, "<Class> '%s' not satisfied by foreign "
×
1689
                  "address '%s'", class_name, pr_netaddr_get_ipstr(&na));
×
1690

1691
                pr_log_pri(PR_LOG_NOTICE,
1692
                  "SECURITY VIOLATION: Passive connection from foreign IP "
1693
                  "address %s rejected (does not match <Class %s>).",
×
1694
                  pr_netaddr_get_ipstr(&na), class_name);
1695

1696
                (void) close(fd);
1697
                d->mode = CM_ERROR;
1698
                d->xerrno = EACCES;
×
1699
                return NULL;
1700
              }
1701

1702
            } else {
1703
              pr_log_debug(DEBUG8, "<Class> '%s' not found for filtering "
1704
                "AllowForeignAddress", class_name);
1705
            }
1706

×
1707
          } else {
×
1708
            pr_log_debug(DEBUG9, "Passive connection from IP address '%s' "
1709
              "matches control connection address; skipping <Class> '%s'",
1710
              pr_netaddr_get_ipstr(&na), class_name);
×
1711
          }
1712
        }
1713
      }
1714
    }
1715

1716
    d->mode = CM_OPEN;
9✔
1717
    res = pr_inet_openrw(p, d, NULL, PR_NETIO_STRM_DATA, fd, rfd, wfd,
9✔
1718
      resolve);
9✔
1719

1720
    break;
9✔
1721
  }
1✔
1722

1✔
1723
  return res;
1724
}
1725

8✔
1726
int pr_inet_get_conn_info(conn_t *c, int fd) {
4✔
1727
  pr_netaddr_t na;
4✔
1728
  socklen_t nalen;
1729

1730
  if (c == NULL) {
1731
    errno = EINVAL;
4✔
1732
    return -1;
1733
  }
1734

4✔
1735
  if (fd < 0) {
4✔
1736
    errno = EBADF;
1737
    return -1;
1738
  }
×
1739

1740
  /* Initialize the netaddr. */
1741
  pr_netaddr_clear(&na);
1742

1743
#ifdef PR_USE_IPV6
4✔
1744
  if (pr_netaddr_use_ipv6()) {
1745
    pr_netaddr_set_family(&na, AF_INET6);
4✔
1746

2✔
1747
  } else {
1748
    pr_netaddr_set_family(&na, AF_INET);
2✔
1749
  }
1750
#else
1751
  pr_netaddr_set_family(&na, AF_INET);
1752
#endif /* PR_USE_IPV6 */
×
1753
  nalen = pr_netaddr_get_sockaddr_len(&na);
1754

1755
  if (getsockname(fd, pr_netaddr_get_sockaddr(&na), &nalen) == 0) {
1756
    pr_netaddr_t *local_addr;
1757

1758
    if (c->local_addr != NULL) {
1759
      local_addr = (pr_netaddr_t *) c->local_addr;
1760

2✔
1761
    } else {
2✔
1762
      local_addr = pr_netaddr_alloc(c->pool);
2✔
1763
    }
1764

2✔
1765
    /* getsockname(2) will read the local socket information into the struct
×
1766
     * sockaddr * given.  Which means that the address family of the local
1767
     * socket can be found in struct sockaddr *->sa_family, and not (yet)
1768
     * via pr_netaddr_get_family().
1769
     */
2✔
1770
    pr_netaddr_set_family(local_addr, pr_netaddr_get_sockaddr(&na)->sa_family);
1771
    pr_netaddr_set_sockaddr(local_addr, pr_netaddr_get_sockaddr(&na));
2✔
1772
    c->local_port = ntohs(pr_netaddr_get_port(&na));
1773

1774
    if (c->local_addr == NULL) {
2✔
1775
      c->local_addr = local_addr;
2✔
1776
    }
1777

1778
  } else {
1779
    int xerrno = errno;
1780

2✔
1781
    pr_trace_msg(trace_channel, 3,
2✔
1782
      "getsockname(2) error on fd %d: %s", fd, strerror(xerrno));
1783

1784
    errno = xerrno;
×
1785
    return -1;
1786
  }
1787

1788
  /* "Reset" the pr_netaddr_t struct for the getpeername(2) call. */
1789
#ifdef PR_USE_IPV6
2✔
1790
  if (pr_netaddr_use_ipv6()) {
1791
    pr_netaddr_set_family(&na, AF_INET6);
2✔
1792

1793
  } else {
2✔
1794
    pr_netaddr_set_family(&na, AF_INET);
×
1795
  }
1796
#else
1797
  pr_netaddr_set_family(&na, AF_INET);
2✔
1798
#endif /* PR_USE_IPV6 */
1799
  nalen = pr_netaddr_get_sockaddr_len(&na);
2✔
1800

1801
  if (getpeername(fd, pr_netaddr_get_sockaddr(&na), &nalen) == 0) {
4✔
1802
    /* Handle IPv4-mapped IPv6 peers as IPv4 peers (Bug#2196). */
2✔
1803
    if (pr_netaddr_is_v4mappedv6(&na) == TRUE) {
2✔
1804
      c->remote_addr = pr_netaddr_v6tov4(c->pool, &na);
1805

2✔
1806
    } else {
1807
      pr_netaddr_t *remote_addr;
1808

2✔
1809
      remote_addr = pr_netaddr_alloc(c->pool);
1810

1811
      pr_netaddr_set_family(remote_addr,
×
1812
        pr_netaddr_get_sockaddr(&na)->sa_family);
1813
      pr_netaddr_set_sockaddr(remote_addr, pr_netaddr_get_sockaddr(&na));
×
1814

1815
      c->remote_addr = remote_addr;
1816
    }
×
1817

×
1818
    c->remote_port = ntohs(pr_netaddr_get_port(&na));
1819

1820
  } else {
2✔
1821
    int xerrno = errno;
1822

1823
    pr_trace_msg(trace_channel, 3,
1824
      "getpeername(2) error on fd %d: %s", fd, strerror(xerrno));
1825

1826
    errno = xerrno;
1827
    return -1;
1828
  }
1829

1830
  return 0;
1831
}
1832

1833
/* Open streams for a new socket. If rfd and wfd != -1, two new fds are duped
1834
 * to the respective read/write fds. If the fds specified correspond to the
1835
 * normal stdin and stdout, the streams opened will be assigned to stdin and
1836
 * stdout in an intuitive fashion (so that they may be later be used by
1837
 * printf/fgets type libc functions).  If inaddr is non-NULL, the address is
1838
 * assigned to the connection (as the *source* of the connection).  If it is
5✔
1839
 * NULL, remote address discovery will be attempted.  The connection structure
1840
 * appropriate fields are filled in, including the *destination* address.
5✔
1841
 * Finally, if resolve is non-zero, this function will attempt to reverse
5✔
1842
 * resolve the remote address.  A new connection structure is created in the
1843
 * specified pool.
5✔
1844
 *
5✔
1845
 * Important, do not call any log_* functions from inside of pr_inet_openrw()
1✔
1846
 * or any functions it calls, as the possibility for fd overwriting occurs.
1847
 */
1✔
1848
conn_t *pr_inet_openrw(pool *p, conn_t *c, const pr_netaddr_t *addr,
1849
    int strm_type, int fd, int rfd, int wfd, int resolve) {
1850
  conn_t *res = NULL;
1✔
1851
  int close_fd = TRUE;
1✔
1852

1853
  res = pr_inet_copy_conn(p, c);
1854
  if (res == NULL) {
4✔
1855
    int xerrno = errno;
1856

1857
    pr_trace_msg(trace_channel, 3,
1858
      "error copying connection: %s", strerror(xerrno));
1859

1860
    errno = xerrno;
1861
    return NULL;
4✔
1862
  }
4✔
1863

1✔
1864
  res->listen_fd = -1;
1865

1✔
1866
  /* Note: there are some cases where the given file descriptor will
1867
   * intentionally be bad (e.g. in get_ident() lookups).  In this case,
1868
   * errno will have a value of EBADF; this is an "acceptable" error.  Any
1✔
1869
   * other errno value constitutes an unacceptable error.
1✔
1870
   */
1871
  if (pr_inet_get_conn_info(res, fd) < 0 &&
1872
      errno != EBADF) {
3✔
1873
    int xerrno = errno;
2✔
1874

2✔
1875
    pr_trace_msg(trace_channel, 3,
1876
      "error getting info for connection on fd %d: %s", fd, strerror(xerrno));
1877

1878
    errno = xerrno;
3✔
1879
    return NULL;
1✔
1880
  }
1✔
1881

1882
  if (addr != NULL) {
1883
    if (res->remote_addr == NULL) {
3✔
1884
      res->remote_addr = pr_netaddr_dup(res->pool, addr);
2✔
1885
    }
2✔
1886
  }
1✔
1887

1888
  if (resolve == TRUE &&
1889
      res->remote_addr != NULL) {
1890
    res->remote_name = pr_netaddr_get_dnsstr(res->remote_addr);
1891
  }
1892

1✔
1893
  if (res->remote_name == NULL) {
1894
    res->remote_name = pr_netaddr_get_ipstr(res->remote_addr);
1895
    if (res->remote_name == NULL) {
1✔
1896
      int xerrno = errno;
1✔
1897

1898
      /* If we can't even get the IP address as a string, then something
1899
       * is very wrong, and we should not continue to handle this connection.
1900
       */
2✔
1901

2✔
1902
      pr_trace_msg(trace_channel, 3,
2✔
1903
        "error getting IP address for client: %s", strerror(xerrno));
1904

1905
      errno = xerrno;
2✔
1906
      return NULL;
×
1907
    }
×
1908
  }
1909

1910
  if (fd == -1 &&
1911
      c->listen_fd != -1) {
1912
    fd = c->listen_fd;
1913
  }
1914

1915
  if (rfd > -1) {
2✔
1916
    if (fd != rfd) {
2✔
1917
      dup2(fd, rfd);
1918

1919
    } else {
1920
      close_fd = FALSE;
2✔
1921
    }
×
1922

×
1923
  } else {
×
1924
    /* dup(2) cannot take a negative value. */
1925
    if (fd >= 0) {
1926
      rfd = dup(fd);
×
1927
    }
1928
  }
1929

1930
  if (wfd > -1) {
1931
    if (fd != wfd) {
1932
      if (wfd == STDOUT_FILENO) {
1933
        fflush(stdout);
1934
      }
2✔
1935

2✔
1936
      dup2(fd, wfd);
1937

1938
    } else {
1939
      close_fd = FALSE;
1940
    }
2✔
1941

2✔
1942
  } else {
1943
    /* dup(2) cannot take a negative value. */
1✔
1944
    if (fd >= 0) {
1945
      wfd = dup(fd);
1946
    }
2✔
1947
  }
2✔
1948

1949
  /* Now discard the original socket */
2✔
1950
  if (rfd > -1 &&
2✔
1951
      wfd > -1 &&
1952
      close_fd) {
1953
    (void) close(fd);
2✔
1954
  }
2✔
1955

1956
  res->rfd = rfd;
2✔
1957
  res->wfd = wfd;
1958

1959
  res->instrm = pr_netio_open(res->pool, strm_type, res->rfd, PR_NETIO_IO_RD);
1960
  res->outstrm = pr_netio_open(res->pool, strm_type, res->wfd, PR_NETIO_IO_WR);
1961

1962
  /* Set options on the sockets. */
1963
  pr_inet_set_socket_opts(res->pool, res, 0, 0, NULL);
1964
  (void) pr_inet_set_block(res->pool, res);
1965

1966
  res->mode = CM_OPEN;
1967

1968
#if defined(HAVE_STROPTS_H) && defined(I_SRDOPT) && defined(RPROTDIS) && \
1969
    (defined(SOLARIS2_9) || defined(SOLARIS2_10))
1970
  /* This is needed to work around control messages in STREAMS devices
1971
   * (as on Solaris 9/NFS).  The underlying issue is reported to be fixed
1972
   * in Solaris 11.
1973
   */
1974
  while (ioctl(res->rfd, I_SRDOPT, RPROTDIS) < 0) {
1975
    if (errno == EINTR) {
1976
      pr_signals_handle();
2✔
1977
      continue;
1978
    }
1979

9✔
1980
    pr_log_pri(PR_LOG_WARNING, "error calling ioctl(RPROTDIS): %s",
1981
      strerror(errno));
9✔
1982
    break;
9✔
1983
  }
1984
#endif
9✔
1985

9✔
1986
  return res;
1987
}
3✔
1988

3✔
1989
int pr_inet_generate_socket_event(const char *event, server_rec *s,
1990
    const pr_netaddr_t *addr, int fd) {
1991
  pool *p;
6✔
1992
  struct socket_ctx *sc;
6✔
1993

6✔
1994
  if (event == NULL ||
6✔
1995
      s == NULL ||
6✔
1996
      addr == NULL) {
6✔
1997
    errno = EINVAL;
6✔
1998
    return -1;
1999
  }
6✔
2000

2001
  p = make_sub_pool(permanent_pool);
2002
  sc = pcalloc(p, sizeof(struct socket_ctx));
48✔
2003
  sc->server = s;
48✔
2004
  sc->addr = addr;
2005
  sc->sockfd = fd;
2006
  pr_event_generate(event, sc);
48✔
2007
  destroy_pool(p);
2008

2009
  return 0;
2010
}
2011

2012
void init_inet(void) {
2013
  struct protoent *pr = NULL;
2014

2015
#ifdef HAVE_SETPROTOENT
2016
  setprotoent(FALSE);
2017
#endif
2018

48✔
2019
  /* AIX ships with a broken /etc/protocols file; the entry for 'ip' in that
48✔
2020
   * file defines a value of 252, which is unacceptable to the AIX
48✔
2021
   * setsockopt(2) system call (Bug#3780).
2022
   *
2023
   * To work around this, do not perform the /etc/protocols lookup for AIX;
2024
   * instead, keep the default IP_PROTO value defined in its other system
2025
   * headers.
48✔
2026
   */
48✔
2027
#ifndef _AIX
48✔
2028
  pr = getprotobyname("ip");
2029
  if (pr != NULL) {
2030
    ip_proto = pr->p_proto;
2031
  }
48✔
2032
#endif /* AIX */
48✔
2033

48✔
2034
#if defined(PR_USE_IPV6)
2035
  pr = getprotobyname("ipv6");
2036
  if (pr != NULL) {
2037
    ipv6_proto = pr->p_proto;
48✔
2038
  }
2039
#endif /* PR_USE_IPV6 */
2040

48✔
2041
  pr = getprotobyname("tcp");
×
2042
  if (pr != NULL) {
2043
    tcp_proto = pr->p_proto;
2044
  }
48✔
2045

48✔
2046
#ifdef HAVE_ENDPROTOENT
48✔
2047
  endprotoent();
2048
#endif
2049

2050
  if (inet_pool != NULL) {
2051
    destroy_pool(inet_pool);
2052
  }
2053

2054
  inet_pool = make_sub_pool(permanent_pool);
2055
  pr_pool_tag(inet_pool, "Inet Pool");
2056
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc