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

proftpd / proftpd / 15763543944

19 Jun 2025 05:45PM UTC coverage: 92.984% (-0.005%) from 92.989%
15763543944

push

github

51411 of 55290 relevant lines covered (92.98%)

221.09 hits per line

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

80.96
/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-2025 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, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
20
 *
21
 * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
22
 * and other respective copyright holders give permission to link this program
23
 * with OpenSSL, and distribute the resulting executable, without including
24
 * the source code for OpenSSL in the source distribution.
25
 */
26

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

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

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

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

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

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

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

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

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

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

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

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

77
  (void) p;
15✔
78

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

187
  res->use_nodelay = c->use_nodelay;
6✔
188

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

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

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

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

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

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

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

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

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

229
  if (bind_addr != NULL) {
70✔
230
    addr_family = pr_netaddr_get_family(bind_addr);
6✔
231

232
  } else if (inet_family) {
64✔
233
    addr_family = inet_family;
234

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

393
    if (bind_addr != NULL) {
65✔
394
      pr_netaddr_set_sockaddr(&na, pr_netaddr_get_sockaddr(bind_addr));
6✔
395

396
    } else {
397
      pr_netaddr_set_sockaddr_any(&na);
59✔
398
    }
399

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

504
      pr_timer_sleep(1);
×
505

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

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

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

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

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

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

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

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

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

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

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

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

564
      if (c->local_addr == NULL) {
65✔
565
        c->local_addr = local_addr;
65✔
566
      }
567

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

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

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

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

586
  return c;
70✔
587
}
588

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

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

598
  return c;
70✔
599
}
600

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

605
  flags = PR_INET_CREATE_CONN_FL_LOG_ERRORS;
64✔
606
  if (retry_bind == TRUE) {
64✔
607
    flags |= PR_INET_CREATE_CONN_FL_RETRY_BIND;
×
608
  }
609

610
  return pr_inet_create_conn2(p, fd, bind_addr, port, flags);
64✔
611
}
612

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

623
  if (low_port < 0 ||
3✔
624
      high_port < 0) {
3✔
625
    errno = EINVAL;
1✔
626
    return NULL;
1✔
627
  }
628

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

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

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

644
  i = range_len;
1✔
645
  while (i--) {
16,384✔
646
    range[i] = low_port + i;
16,383✔
647
  }
648

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

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

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

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

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

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

684
  errno = xerrno;
1✔
685
  return c;
1✔
686
}
687

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

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

700
  if (c->pool != NULL) {
47✔
701
    destroy_pool(c->pool);
47✔
702
  }
703
}
704

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

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

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

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

724
  c->outstrm = NULL;
14✔
725
  c->instrm = NULL;
14✔
726

727
  destroy_pool(c->pool);
14✔
728
}
729

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

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

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

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

753
  c->instrm = NULL;
9✔
754
  c->outstrm = NULL;
9✔
755

756
  destroy_pool(c->pool);
9✔
757
}
758

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

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

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

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

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

786
  return res;
19✔
787
}
788

789
int pr_inet_set_proto_nodelay(pool *p, conn_t *conn, int nodelay) {
9✔
790

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

799
  if (conn == NULL) {
9✔
800
    errno = EINVAL;
1✔
801
    return -1;
1✔
802
  }
803

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

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

826
  return 0;
827
}
828

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

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

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

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

854
  if (c == NULL) {
18✔
855
    errno = EINVAL;
1✔
856
    return -1;
1✔
857
  }
858

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

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

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

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

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

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

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

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

949
  return 0;
950
}
951

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

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

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

968
  keepalive = tcp_keepalive->keepalive_enabled;
14✔
969

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

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

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

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

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

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

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

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

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

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

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

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

1061
  return 0;
1062
}
1063

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

1068
  if (c == NULL) {
21✔
1069
    errno = EINVAL;
2✔
1070
    return -1;
2✔
1071
  }
1072

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

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

1084
    (void) pr_inet_set_proto_keepalive(p, c, tcp_keepalive);
17✔
1085

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

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

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

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

1115
    c->sndbuf = (sndbuf ? sndbuf : csndbuf);
17✔
1116

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

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

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

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

1146
    c->rcvbuf = (rcvbuf ? rcvbuf : crcvbuf);
17✔
1147
  }
1148

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

1163
  return 0;
1164
}
1165

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

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

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

1181
#if defined(SO_REUSEPORT)
1182
  res = setsockopt(c->listen_fd, SOL_SOCKET, SO_REUSEPORT, (void *) &reuse_port,
50✔
1183
    sizeof(reuse_port));
1184
  if (res < 0) {
50✔
1185
    pr_log_pri(PR_LOG_NOTICE,
39✔
1186
      "error setting SO_REUSEPORT on fd %d: %s", c->listen_fd,
1187
      strerror(errno));
39✔
1188
  }
1189
#else
1190
  errno = ENOSYS;
1191
#endif /* SO_REUSEPORT */
1192

1193
  return res;
1194
}
1195

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

1208
#ifdef F_SETOWN
1209
static void set_socket_owner(int fd) {
12✔
1210
  if (fd >= 0) {
12✔
1211
    pid_t pid;
6✔
1212

1213
    pid = session.pid ? session.pid : getpid();
6✔
1214
    if (fcntl(fd, F_SETOWN, pid) < 0) {
6✔
1215
      pr_trace_msg(trace_channel, 3,
3✔
1216
        "failed to SETOWN PID %lu on socket fd %d: %s", (unsigned long) pid,
1217
        fd, strerror(errno));
3✔
1218
    }
1219
  }
1220
}
12✔
1221
#endif
1222

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

1232
#ifdef SO_OOBINLINE
1233
  pr_trace_msg(trace_channel, 7,
4✔
1234
    "setting SO_OOBINLINE for listening socket fd %d", c->listen_fd);
1235
  set_oobinline(c->listen_fd);
4✔
1236

1237
  pr_trace_msg(trace_channel, 7,
4✔
1238
    "setting SO_OOBINLINE for reading socket fd %d", c->rfd);
1239
  set_oobinline(c->rfd);
4✔
1240

1241
  pr_trace_msg(trace_channel, 7,
4✔
1242
    "setting SO_OOBINLINE for writing socket fd %d", c->wfd);
1243
  set_oobinline(c->wfd);
4✔
1244
#endif
1245

1246
#ifdef F_SETOWN
1247
  set_socket_owner(c->listen_fd);
4✔
1248
  set_socket_owner(c->rfd);
4✔
1249
  set_socket_owner(c->wfd);
4✔
1250
#endif
1251

1252
  return 0;
4✔
1253
}
1254

1255
/* Put a socket in nonblocking mode.
1256
 */
1257
int pr_inet_set_nonblock(pool *p, conn_t *c) {
8✔
1258
  int flags;
8✔
1259
  int res = -1;
8✔
1260

1261
  (void) p;
8✔
1262

1263
  if (c == NULL) {
8✔
1264
    errno = EINVAL;
1✔
1265
    return -1;
1✔
1266
  }
1267

1268
  errno = EBADF;                /* Default */
7✔
1269

1270
  if (c->mode == CM_LISTEN ||
7✔
1271
      c->mode == CM_CONNECT) {
1272
    flags = fcntl(c->listen_fd, F_GETFL);
4✔
1273
    if (flags >= 0) {
4✔
1274
      res = fcntl(c->listen_fd, F_SETFL, flags|O_NONBLOCK);
4✔
1275

1276
    } else {
1277
      res = flags;
1278
    }
1279

1280
  } else {
1281
    if (c->rfd != -1) {
3✔
1282
      flags = fcntl(c->rfd, F_GETFL);
1✔
1283
      if (flags >= 0) {
1✔
1284
        res = fcntl(c->rfd, F_SETFL, flags|O_NONBLOCK);
1✔
1285

1286
      } else {
1287
        res = flags;
1288
      }
1289
    }
1290

1291
    if (c->wfd != -1) {
3✔
1292
      flags = fcntl(c->wfd, F_GETFL);
1✔
1293
      if (flags >= 0) {
1✔
1294
        res = fcntl(c->wfd, F_SETFL, flags|O_NONBLOCK);
1✔
1295

1296
      } else {
1297
        res = flags;
1298
      }
1299
    }
1300
  }
1301

1302
  return res;
1303
}
1304

1305
int pr_inet_set_block(pool *p, conn_t *c) {
44✔
1306
  int flags;
44✔
1307
  int res = -1;
44✔
1308

1309
  (void) p;
44✔
1310

1311
  if (c == NULL) {
44✔
1312
    errno = EINVAL;
1✔
1313
    return -1;
1✔
1314
  }
1315

1316
  errno = EBADF;                /* Default */
43✔
1317

1318
  if (c->mode == CM_LISTEN ||
43✔
1319
      c->mode == CM_CONNECT) {
1320
    flags = fcntl(c->listen_fd, F_GETFL);
16✔
1321
    if (flags >= 0) {
16✔
1322
      res = fcntl(c->listen_fd, F_SETFL, flags & (U32BITS ^ O_NONBLOCK));
15✔
1323

1324
    } else {
1325
      res = flags;
1326
    }
1327

1328
  } else {
1329
    if (c->rfd != -1) {
27✔
1330
      flags = fcntl(c->rfd, F_GETFL);
1✔
1331
      if (flags >= 0) {
1✔
1332
        res = fcntl(c->rfd, F_SETFL, flags & (U32BITS ^ O_NONBLOCK));
1✔
1333

1334
      } else {
1335
        res = flags;
1336
      }
1337
    }
1338

1339
    if (c->wfd != -1) {
27✔
1340
      flags = fcntl(c->wfd, F_GETFL);
1✔
1341
      if (flags >= 0) {
1✔
1342
        res = fcntl(c->wfd, F_SETFL, flags & (U32BITS ^ O_NONBLOCK));
1✔
1343

1344
      } else {
1345
        res = flags;
1346
      }
1347
    }
1348
  }
1349

1350
  return res;
1351
}
1352

1353
/* Put a connection in listen mode */
1354
int pr_inet_listen(pool *p, conn_t *c, int backlog, int flags) {
4✔
1355
  if (c == NULL) {
4✔
1356
    errno = EINVAL;
1✔
1357
    return -1;
1✔
1358
  }
1359

1360
  if (c->mode == CM_LISTEN) {
3✔
1361
    errno = EPERM;
1✔
1362
    return -1;
1✔
1363
  }
1364

1365
  while (TRUE) {
2✔
1366
    if (listen(c->listen_fd, backlog) < 0) {
2✔
1367
      int xerrno = errno;
1✔
1368

1369
      if (xerrno == EINTR) {
1✔
1370
        pr_signals_handle();
×
1371
        continue;
×
1372
      }
1373

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

1377
      if (flags & PR_INET_LISTEN_FL_FATAL_ON_ERROR) {
1✔
1378
        pr_session_disconnect(NULL, PR_SESS_DISCONNECT_BY_APPLICATION, NULL);
×
1379
      }
1380

1381
      errno = xerrno;
1✔
1382
      return -1;
1✔
1383
    }
1384

1385
    break;
1✔
1386
  }
1387

1388
  c->mode = CM_LISTEN;
1✔
1389
  return 0;
1✔
1390
}
1391

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

1401
  c->mode = CM_LISTEN;
2✔
1402
  if (pr_inet_set_block(c->pool, c) < 0) {
2✔
1403
    c->xerrno = errno;
1✔
1404
    return -1;
1✔
1405
  }
1406

1407
  return 0;
1408
}
1409

1410
int pr_inet_connect(pool *p, conn_t *c, const pr_netaddr_t *addr, int port) {
16✔
1411
  pr_netaddr_t remote_na;
16✔
1412
  int res = 0;
16✔
1413

1414
  if (c == NULL ||
16✔
1415
      addr == NULL) {
16✔
1416
    errno = EINVAL;
2✔
1417
    return -1;
2✔
1418
  }
1419

1420
  c->mode = CM_CONNECT;
14✔
1421
  if (pr_inet_set_block(p, c) < 0) {
14✔
1422
    c->mode = CM_ERROR;
×
1423
    c->xerrno = errno;
×
1424
    return -1;
×
1425
  }
1426

1427
  /* No need to initialize the remote_na netaddr here, as we're directly
1428
   * copying the data from the given netaddr into that memory area.
1429
   */
1430

1431
  memcpy(&remote_na, addr, sizeof(remote_na));
14✔
1432
  pr_netaddr_set_port(&remote_na, htons(port));
14✔
1433

1434
  while (TRUE) {
14✔
1435
    res = connect(c->listen_fd, pr_netaddr_get_sockaddr(&remote_na),
14✔
1436
      pr_netaddr_get_sockaddr_len(&remote_na));
14✔
1437
    if (res < 0 &&
14✔
1438
        errno == EINTR) {
12✔
1439
      pr_signals_handle();
×
1440
      continue;
×
1441
    }
1442

1443
    break;
14✔
1444
  }
1445

1446
  if (res < 0) {
14✔
1447
    c->mode = CM_ERROR;
12✔
1448
    c->xerrno = errno;
12✔
1449
    return -1;
12✔
1450
  }
1451

1452
  c->mode = CM_OPEN;
2✔
1453

1454
  if (pr_inet_get_conn_info(c, c->listen_fd) < 0) {
2✔
1455
    c->mode = CM_ERROR;
×
1456
    c->xerrno = errno;
×
1457
    return -1;
×
1458
  }
1459

1460
  return 1;
1461
}
1462

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

1471
  if (c == NULL ||
4✔
1472
      addr == NULL) {
4✔
1473
    errno = EINVAL;
2✔
1474
    return -1;
2✔
1475
  }
1476

1477
  c->mode = CM_CONNECT;
2✔
1478
  if (pr_inet_set_nonblock(p, c) < 0) {
2✔
1479
    c->mode = CM_ERROR;
×
1480
    c->xerrno = errno;
×
1481
    return -1;
×
1482
  }
1483

1484
  /* No need to initialize the remote_na netaddr here, as we're directly
1485
   * copying the data from the given netaddr into that memory area.
1486
   */
1487

1488
  memcpy(&remote_na, addr, sizeof(remote_na));
2✔
1489
  pr_netaddr_set_port(&remote_na, htons(port));
2✔
1490

1491
  if (connect(c->listen_fd, pr_netaddr_get_sockaddr(&remote_na),
2✔
1492
      pr_netaddr_get_sockaddr_len(&remote_na)) == -1) {
2✔
1493
    if (errno != EINPROGRESS &&
2✔
1494
        errno != EALREADY) {
1495
      c->mode = CM_ERROR;
1✔
1496
      c->xerrno = errno;
1✔
1497

1498
      (void) pr_inet_set_block(c->pool, c);
1✔
1499

1500
      errno = c->xerrno;
1✔
1501
      return -1;
1✔
1502
    }
1503

1504
    return 0;
1505
  }
1506

1507
  c->mode = CM_OPEN;
×
1508

1509
  if (pr_inet_get_conn_info(c, c->listen_fd) < 0) {
×
1510
    c->xerrno = errno;
×
1511

1512
    (void) pr_inet_set_block(c->pool, c);
×
1513
    errno = c->xerrno;
×
1514
    return -1;
×
1515
  }
1516

1517
  if (pr_inet_set_block(c->pool, c) < 0) {
×
1518
    c->xerrno = errno;
×
1519
    return -1;
×
1520
  }
1521

1522
  return 1;
1523
}
1524

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

1534
  if (c == NULL) {
3✔
1535
    errno = EINVAL;
1✔
1536
    return -1;
1✔
1537
  }
1538

1539
  if (c->mode == CM_LISTEN) {
2✔
1540
    if (pr_inet_set_nonblock(c->pool, c) < 0) {
1✔
1541
      if (errno != EBADF) {
×
1542
        pr_trace_msg(trace_channel, 3,
×
1543
          "error making connection nonblocking: %s", strerror(errno));
1544
      }
1545
    }
1546
  }
1547

1548
  /* A directive could enforce only IPv4 or IPv6 connections here, by
1549
   * actually using a sockaddr argument to accept(2), and checking the
1550
   * family of the connecting entity.
1551
   */
1552

1553
  c->mode = CM_ACCEPT;
2✔
1554
  while (TRUE) {
2✔
1555
    pr_signals_handle();
2✔
1556
    fd = accept(c->listen_fd, NULL, NULL);
2✔
1557

1558
    if (fd == -1) {
2✔
1559
      if (errno == EINTR) {
2✔
1560
        continue;
×
1561
      }
1562

1563
      if (errno != EWOULDBLOCK) {
2✔
1564
        c->mode = CM_ERROR;
2✔
1565
        c->xerrno = errno;
2✔
1566
        return -1;
2✔
1567
      }
1568

1569
      c->mode = CM_LISTEN;
×
1570
      c->xerrno = 0;
×
1571
      return -1;
×
1572
    }
1573

1574
    break;
×
1575
  }
1576

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

1587
  return fd;
1588
}
1589

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

1601
  if (c == NULL ||
4✔
1602
      d == NULL) {
4✔
1603
    errno = EINVAL;
1✔
1604
    return NULL;
1✔
1605
  }
1606

1607
  /* Initialize the netaddr. */
1608
  pr_netaddr_clear(&na);
3✔
1609

1610
  pr_netaddr_set_family(&na, pr_netaddr_get_family(c->remote_addr));
3✔
1611
  nalen = pr_netaddr_get_sockaddr_len(&na);
3✔
1612

1613
  allow_foreign_addr_config = find_config(TOPLEVEL_CONF, CONF_PARAM,
3✔
1614
    "AllowForeignAddress", FALSE);
1615
  d->mode = CM_ACCEPT;
3✔
1616

1617
  /* A directive could enforce only IPv4 or IPv6 connections here, by
1618
   * actually using a sockaddr argument to accept(2), and checking the
1619
   * family of the connecting entity.
1620
   */
1621

1622
  while (TRUE) {
3✔
1623
    pr_signals_handle();
3✔
1624

1625
    fd = accept(d->listen_fd, pr_netaddr_get_sockaddr(&na), &nalen);
3✔
1626
    if (fd < 0) {
3✔
1627
      if (errno == EINTR) {
3✔
1628
        continue;
×
1629
      }
1630

1631
      d->mode = CM_ERROR;
3✔
1632
      d->xerrno = errno;
3✔
1633
      break;
3✔
1634
    }
1635

1636
    if (allow_foreign_addr_config != NULL) {
×
1637
      int allowed;
×
1638

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

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

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

1663
            (void) close(fd);
×
1664
            d->mode = CM_ERROR;
×
1665
            d->xerrno = EACCES;
×
1666

1667
            return NULL;
×
1668
          }
1669

1670
        } else {
1671
          char *class_name;
×
1672

1673
          /* Check the data connection remote address against BOTH the
1674
           * control connection remote address AND the configured <Class>.
1675
           */
1676
          class_name = allow_foreign_addr_config->argv[1];
×
1677

1678
          if (pr_netaddr_cmp(&na, c->remote_addr) != 0) {
×
1679
            const pr_class_t *cls;
×
1680

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

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

1692
                (void) close(fd);
×
1693
                d->mode = CM_ERROR;
×
1694
                d->xerrno = EACCES;
×
1695
                return NULL;
×
1696
              }
1697

1698
            } else {
1699
              pr_log_debug(DEBUG8, "<Class> '%s' not found for filtering "
×
1700
                "AllowForeignAddress", class_name);
1701
            }
1702

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

1712
    d->mode = CM_OPEN;
×
1713
    res = pr_inet_openrw(p, d, NULL, PR_NETIO_STRM_DATA, fd, rfd, wfd,
×
1714
      resolve);
1715

1716
    break;
×
1717
  }
1718

1719
  return res;
1720
}
1721

1722
int pr_inet_get_conn_info(conn_t *c, int fd) {
9✔
1723
  pr_netaddr_t na;
9✔
1724
  socklen_t nalen;
9✔
1725

1726
  if (c == NULL) {
9✔
1727
    errno = EINVAL;
1✔
1728
    return -1;
1✔
1729
  }
1730

1731
  if (fd < 0) {
8✔
1732
    errno = EBADF;
4✔
1733
    return -1;
4✔
1734
  }
1735

1736
  /* Initialize the netaddr. */
1737
  pr_netaddr_clear(&na);
4✔
1738

1739
#ifdef PR_USE_IPV6
1740
  if (pr_netaddr_use_ipv6()) {
4✔
1741
    pr_netaddr_set_family(&na, AF_INET6);
4✔
1742

1743
  } else {
1744
    pr_netaddr_set_family(&na, AF_INET);
×
1745
  }
1746
#else
1747
  pr_netaddr_set_family(&na, AF_INET);
1748
#endif /* PR_USE_IPV6 */
1749
  nalen = pr_netaddr_get_sockaddr_len(&na);
4✔
1750

1751
  if (getsockname(fd, pr_netaddr_get_sockaddr(&na), &nalen) == 0) {
4✔
1752
    pr_netaddr_t *local_addr;
2✔
1753

1754
    if (c->local_addr != NULL) {
2✔
1755
      local_addr = (pr_netaddr_t *) c->local_addr;
1756

1757
    } else {
1758
      local_addr = pr_netaddr_alloc(c->pool);
×
1759
    }
1760

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

1770
    if (c->local_addr == NULL) {
2✔
1771
      c->local_addr = local_addr;
×
1772
    }
1773

1774
  } else {
1775
    int xerrno = errno;
2✔
1776

1777
    pr_trace_msg(trace_channel, 3,
2✔
1778
      "getsockname(2) error on fd %d: %s", fd, strerror(xerrno));
1779

1780
    errno = xerrno;
2✔
1781
    return -1;
2✔
1782
  }
1783

1784
  /* "Reset" the pr_netaddr_t struct for the getpeername(2) call. */
1785
#ifdef PR_USE_IPV6
1786
  if (pr_netaddr_use_ipv6()) {
2✔
1787
    pr_netaddr_set_family(&na, AF_INET6);
2✔
1788

1789
  } else {
1790
    pr_netaddr_set_family(&na, AF_INET);
×
1791
  }
1792
#else
1793
  pr_netaddr_set_family(&na, AF_INET);
1794
#endif /* PR_USE_IPV6 */
1795
  nalen = pr_netaddr_get_sockaddr_len(&na);
2✔
1796

1797
  if (getpeername(fd, pr_netaddr_get_sockaddr(&na), &nalen) == 0) {
2✔
1798
    /* Handle IPv4-mapped IPv6 peers as IPv4 peers (Bug#2196). */
1799
    if (pr_netaddr_is_v4mappedv6(&na) == TRUE) {
2✔
1800
      c->remote_addr = pr_netaddr_v6tov4(c->pool, &na);
×
1801

1802
    } else {
1803
      pr_netaddr_t *remote_addr;
2✔
1804

1805
      remote_addr = pr_netaddr_alloc(c->pool);
2✔
1806

1807
      pr_netaddr_set_family(remote_addr,
4✔
1808
        pr_netaddr_get_sockaddr(&na)->sa_family);
2✔
1809
      pr_netaddr_set_sockaddr(remote_addr, pr_netaddr_get_sockaddr(&na));
2✔
1810

1811
      c->remote_addr = remote_addr;
2✔
1812
    }
1813

1814
    c->remote_port = ntohs(pr_netaddr_get_port(&na));
2✔
1815

1816
  } else {
1817
    int xerrno = errno;
×
1818

1819
    pr_trace_msg(trace_channel, 3,
×
1820
      "getpeername(2) error on fd %d: %s", fd, strerror(xerrno));
1821

1822
    errno = xerrno;
×
1823
    return -1;
×
1824
  }
1825

1826
  return 0;
2✔
1827
}
1828

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

1849
  res = pr_inet_copy_conn(p, c);
5✔
1850
  if (res == NULL) {
5✔
1851
    int xerrno = errno;
1✔
1852

1853
    pr_trace_msg(trace_channel, 3,
1✔
1854
      "error copying connection: %s", strerror(xerrno));
1855

1856
    errno = xerrno;
1✔
1857
    return NULL;
1✔
1858
  }
1859

1860
  res->listen_fd = -1;
4✔
1861

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

1871
    pr_trace_msg(trace_channel, 3,
1✔
1872
      "error getting info for connection on fd %d: %s", fd, strerror(xerrno));
1873

1874
    errno = xerrno;
1✔
1875
    return NULL;
1✔
1876
  }
1877

1878
  if (addr != NULL) {
3✔
1879
    if (res->remote_addr == NULL) {
2✔
1880
      res->remote_addr = pr_netaddr_dup(res->pool, addr);
2✔
1881
    }
1882
  }
1883

1884
  if (resolve == TRUE &&
3✔
1885
      res->remote_addr != NULL) {
1✔
1886
    res->remote_name = pr_netaddr_get_dnsstr(res->remote_addr);
1✔
1887
  }
1888

1889
  if (res->remote_name == NULL) {
3✔
1890
    res->remote_name = pr_netaddr_get_ipstr(res->remote_addr);
2✔
1891
    if (res->remote_name == NULL) {
2✔
1892
      int xerrno = errno;
1✔
1893

1894
      /* If we can't even get the IP address as a string, then something
1895
       * is very wrong, and we should not continue to handle this connection.
1896
       */
1897

1898
      pr_trace_msg(trace_channel, 3,
1✔
1899
        "error getting IP address for client: %s", strerror(xerrno));
1900

1901
      errno = xerrno;
1✔
1902
      return NULL;
1✔
1903
    }
1904
  }
1905

1906
  if (fd == -1 &&
2✔
1907
      c->listen_fd != -1) {
2✔
1908
    fd = c->listen_fd;
2✔
1909
  }
1910

1911
  if (rfd > -1) {
2✔
1912
    if (fd != rfd) {
×
1913
      dup2(fd, rfd);
×
1914

1915
    } else {
1916
      close_fd = FALSE;
1917
    }
1918

1919
  } else {
1920
    /* dup(2) cannot take a negative value. */
1921
    if (fd >= 0) {
2✔
1922
      rfd = dup(fd);
2✔
1923
    }
1924
  }
1925

1926
  if (wfd > -1) {
2✔
1927
    if (fd != wfd) {
×
1928
      if (wfd == STDOUT_FILENO) {
×
1929
        fflush(stdout);
×
1930
      }
1931

1932
      dup2(fd, wfd);
×
1933

1934
    } else {
1935
      close_fd = FALSE;
1936
    }
1937

1938
  } else {
1939
    /* dup(2) cannot take a negative value. */
1940
    if (fd >= 0) {
2✔
1941
      wfd = dup(fd);
2✔
1942
    }
1943
  }
1944

1945
  /* Now discard the original socket */
1946
  if (rfd > -1 &&
2✔
1947
      wfd > -1 &&
2✔
1948
      close_fd) {
1949
    (void) close(fd);
1✔
1950
  }
1951

1952
  res->rfd = rfd;
2✔
1953
  res->wfd = wfd;
2✔
1954

1955
  res->instrm = pr_netio_open(res->pool, strm_type, res->rfd, PR_NETIO_IO_RD);
2✔
1956
  res->outstrm = pr_netio_open(res->pool, strm_type, res->wfd, PR_NETIO_IO_WR);
2✔
1957

1958
  /* Set options on the sockets. */
1959
  pr_inet_set_socket_opts(res->pool, res, 0, 0, NULL);
2✔
1960
  (void) pr_inet_set_block(res->pool, res);
2✔
1961

1962
  res->mode = CM_OPEN;
2✔
1963

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

1976
    pr_log_pri(PR_LOG_WARNING, "error calling ioctl(RPROTDIS): %s",
1977
      strerror(errno));
1978
    break;
1979
  }
1980
#endif
1981

1982
  return res;
2✔
1983
}
1984

1985
int pr_inet_generate_socket_event(const char *event, server_rec *s,
9✔
1986
    const pr_netaddr_t *addr, int fd) {
1987
  pool *p;
9✔
1988
  struct socket_ctx *sc;
9✔
1989

1990
  if (event == NULL ||
9✔
1991
      s == NULL ||
9✔
1992
      addr == NULL) {
1993
    errno = EINVAL;
3✔
1994
    return -1;
3✔
1995
  }
1996

1997
  p = make_sub_pool(permanent_pool);
6✔
1998
  sc = pcalloc(p, sizeof(struct socket_ctx));
6✔
1999
  sc->server = s;
6✔
2000
  sc->addr = addr;
6✔
2001
  sc->sockfd = fd;
6✔
2002
  pr_event_generate(event, sc);
6✔
2003
  destroy_pool(p);
6✔
2004

2005
  return 0;
6✔
2006
}
2007

2008
void init_inet(void) {
48✔
2009
  struct protoent *pr = NULL;
48✔
2010

2011
#ifdef HAVE_SETPROTOENT
2012
  setprotoent(FALSE);
48✔
2013
#endif
2014

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

2030
#if defined(PR_USE_IPV6)
2031
  pr = getprotobyname("ipv6");
48✔
2032
  if (pr != NULL) {
48✔
2033
    ipv6_proto = pr->p_proto;
48✔
2034
  }
2035
#endif /* PR_USE_IPV6 */
2036

2037
  pr = getprotobyname("tcp");
48✔
2038
  if (pr != NULL) {
48✔
2039
    tcp_proto = pr->p_proto;
48✔
2040
  }
2041

2042
#ifdef HAVE_ENDPROTOENT
2043
  endprotoent();
48✔
2044
#endif
2045

2046
  if (inet_pool != NULL) {
48✔
2047
    destroy_pool(inet_pool);
×
2048
  }
2049

2050
  inet_pool = make_sub_pool(permanent_pool);
48✔
2051
  pr_pool_tag(inet_pool, "Inet Pool");
48✔
2052
}
48✔
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