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

proftpd / proftpd / 14526507026

17 Apr 2025 11:25PM UTC coverage: 93.03% (+0.4%) from 92.667%
14526507026

push

github

51358 of 55206 relevant lines covered (93.03%)

234.02 hits per line

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

80.91
/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

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

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

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

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

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

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

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

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

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

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

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

235
  } else {
39✔
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()) {
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 */
70✔
249
  }
65✔
250

65✔
251
  /* If fd == -1, there is no currently open socket, so create one.
252
   */
253
  if (fd == -1) {
254
    socklen_t salen;
255
    register unsigned int i = 0;
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
65✔
263
     * the socket is created as root.  (Note: this "feature" seems to apply
264
     * to _all_ BSDs.)
265
     */
266

267
    if (port != INPORT_ANY) {
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
65✔
286
# ifdef SOLARIS2
287
      }
65✔
288
# endif
65✔
289
#endif
290
    }
65✔
291

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

295
    if (port != INPORT_ANY) {
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();
65✔
314
# ifdef SOLARIS2
315
      }
65✔
316
# endif
317
#endif
×
318
    }
×
319

320
    if (fd == -1) {
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;
65✔
330
      return NULL;
331
    }
×
332

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

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

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

374
    if (res < 0) {
375
      pr_log_pri(PR_LOG_NOTICE,
376
        "error setting SO_KEEPALIVE on socket fd %d: %s", fd, strerror(errno));
65✔
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,
382
        sizeof(on)) < 0) {
383
      if (errno != ENOSYS) {
384
        pr_log_pri(PR_LOG_INFO, "error setting IP_FREEBIND: %s",
385
          strerror(errno));
65✔
386
      }
65✔
387
    }
388
#endif /* IP_FREEBIND */
65✔
389

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

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

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

38✔
400
#if defined(PR_USE_IPV6) && defined(IPV6_V6ONLY)
401
    if (pr_netaddr_use_ipv6() &&
402
        addr_family == AF_INET6) {
403
      int level = ipv6_proto;
404
      socklen_t len = sizeof(off);
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
       *
38✔
411
       * Ideally, this setsockopt() call would be configurable via the
38✔
412
       * SocketOptions directive.
×
413
       */
414

×
415
      if (getsockopt(fd, level, IPV6_V6ONLY, (void *) &off, &len) >= 0) {
416
        if (off != 0) {
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));
65✔
444
      }
445
    }
65✔
446
#endif /* PR_USE_IPV6 and IPV6_V6ONLY */
65✔
447

×
448
    pr_netaddr_set_port(&na, htons(port));
×
449

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

456
    if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
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
65✔
463
     * (transferring lots of files) causing an eventual "Address already in use"
65✔
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
     */
65✔
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");
65✔
471
      res = bind(fd, pr_netaddr_get_sockaddr(&na),
65✔
472
        pr_netaddr_get_sockaddr_len(&na));
×
473
      hold_errno = errno;
×
474

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

482
      if (res != -1 ||
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.
65✔
487
         */
488
#ifdef SOLARIS2
×
489
          (hold_errno != EADDRINUSE && hold_errno != EACCES) ||
×
490
#else
491
          hold_errno != EADDRINUSE ||
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();
65✔
509
        PRIVS_ROOT
×
510
      }
511
    }
×
512

×
513
    if (res == -1) {
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

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

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

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

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

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

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

65✔
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));
562
      c->local_port = ntohs(pr_netaddr_get_port(&na));
563

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

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

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

580
  c->listen_fd = fd;
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",
584
    pr_netaddr_get_ipstr(&na), c->local_port, fd);
70✔
585

586
  return c;
70✔
587
}
588

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

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

598
  return c;
64✔
599
}
600

64✔
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;
604

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

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

613
/* Attempt to create a connection bound to a given port range, returns NULL
3✔
614
 * if unable to bind to any port in the range.
3✔
615
 */
3✔
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;
1✔
621
  conn_t *c = NULL;
1✔
622

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

629
  if (low_port >= high_port) {
630
    errno = EPERM;
1✔
631
    return NULL;
×
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);
1✔
637
    pr_pool_tag(inet_pool, "Inet Pool");
1✔
638
  }
639

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

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

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

653
      /* If this is the first attempt through the range, randomize
1✔
654
       * the order of the port numbers used.
655
       */
656
      if (attempt == 3) {
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];
2,620✔
664

2,619✔
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) {
1✔
669
          range[random_index-1] = range[random_index];
1✔
670
        }
671
      }
1✔
672

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

676
      if (c == NULL) {
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));
1✔
680
      }
1✔
681
    }
682
  }
683

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

688
void pr_inet_close(pool *p, conn_t *c) {
689
  if (c == NULL) {
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
47✔
696
   * cleanup handler (conn_cleanup_cb()) which will do all this for us.
47✔
697
   * Simply destroy the pool and all the dirty work gets done.
698
   */
699

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

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

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

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

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

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

10✔
727
  destroy_pool(c->pool);
10✔
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) {
9✔
732
  if (c == NULL) {
733
    return;
9✔
734
  }
1✔
735

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

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

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

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

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

759
int pr_inet_set_proto_cork(int sockfd, int cork) {
760
  int res = 0;
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.
19✔
769
   */
770

771
#if defined(TCP_CORK) || defined(TCP_NOPUSH)
772
# ifdef SOL_TCP
773
  int tcp_level = SOL_TCP;
774
# else
775
  int tcp_level = tcp_proto;
2✔
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));
781

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

786
  return res;
787
}
9✔
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;
793
# ifdef SOL_TCP
794
  int tcp_level = SOL_TCP;
9✔
795
# else
1✔
796
  int tcp_level = tcp_proto;
1✔
797
# endif /* SOL_TCP */
798

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

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

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

826
  return 0;
827
}
828

829
int pr_inet_set_proto_opts(pool *p, conn_t *c, int mss, int nodelay,
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
18✔
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;
840
#else
18✔
841
  int ip_level = ip_proto;
842
#endif /* SOL_IP */
843

844
#ifdef SOL_TCP
18✔
845
  int tcp_level = SOL_TCP;
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
18✔
851
   * sockets, rather than on IPv4 sockets.
1✔
852
   */
1✔
853

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

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

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

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

894
#if defined(TCP_MAXSEG)
895
  if (c->listen_fd != -1 &&
896
      mss > 0) {
897
    if (setsockopt(c->listen_fd, tcp_level, TCP_MAXSEG, &mss,
898
        sizeof(mss)) < 0) {
17✔
899
      pr_log_pri(PR_LOG_NOTICE, "error setting listen fd TCP_MAXSEG(%d): %s",
17✔
900
        mss, strerror(errno));
11✔
901
    }
902
  }
11✔
903
#endif /* TCP_MAXSEG */
11✔
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) {
908
    if (c->listen_fd != -1) {
909
      if (setsockopt(c->listen_fd, ip_level, IP_TOS, (void *) &tos,
910
          sizeof(tos)) < 0) {
17✔
911
        pr_log_pri(PR_LOG_NOTICE, "error setting listen fd IP_TOS: %s",
13✔
912
          strerror(errno));
13✔
913
      }
914
    }
2✔
915
  }
2✔
916
#endif /* IP_TOS */
917

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

17✔
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
4✔
930
#ifdef ENOPROTOOPT
931
            && errno != ENOPROTOOPT
4✔
932
#endif /* !ENOPROTOOPT */
1✔
933
          ) {
934
          pr_log_pri(PR_LOG_NOTICE, "error setting listen fd IPV6_TCLASS: %s",
1✔
935
            strerror(errno));
936
        }
937
      }
1✔
938
    }
939
  }
940
#endif /* IPV6_TCLASS */
941

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

3✔
949
  return 0;
950
}
951

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

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

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

1✔
968
  keepalive = tcp_keepalive->keepalive_enabled;
1✔
969

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

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

9✔
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",
987
    c->listen_fd);
988

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

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

1003
# ifdef __DragonFly__
2✔
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,
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,
2✔
1011
       strerror(errno));
1012

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

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

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

1036
#if defined(TCP_KEEPINTVL)
1037
  val = tcp_keepalive->keepalive_intvl;
1038
  if (val != -1) {
1039
# ifdef __DragonFly__
1040
    /* DragonFly BSD uses millsecs as the KEEPINTVL unit. */
9✔
1041
    val *= 1000;
9✔
1042
# endif /* DragonFly BSD */
1043
    if (setsockopt(c->listen_fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *) &val,
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,
2✔
1047
        strerror(errno));
1048

×
1049
    } else {
1050
      pr_trace_msg(trace_channel, 15,
×
1051
        "enabled TCP_KEEPINTVL %d on socket fd %d", val, c->listen_fd);
1052
    }
1053
  }
2✔
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,
1066
    struct tcp_keepalive *tcp_keepalive, int reuse_port) {
1067

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

2✔
1073
  /* Linux and "most" newer networking OSes probably use a highly adaptive
2✔
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) {
1081
    int crcvbuf = 0, csndbuf = 0;
1082
    socklen_t len;
1083

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

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

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

2✔
1101
        } else {
1102
          pr_trace_msg("data", 8,
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);
4✔
1106
        }
1107

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

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

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

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

2✔
1132
        } else {
1133
          pr_trace_msg("data", 8,
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);
4✔
1137
        }
1138

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

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

1149
  if (reuse_port != -1) {
17✔
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
19✔
1153
     * and madness (see Issue #622).
1154
     */
1155
    if (!is_master) {
1156
      if (pr_inet_set_reuse_port(p, c, reuse_port) == 0) {
1157
        pr_trace_msg("data", 8,
1158
          "set socket fd %d reuseport = %d", c->listen_fd, reuse_port);
12✔
1159
      }
12✔
1160
    }
9✔
1161
  }
1162

1163
  return 0;
1164
}
1165

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

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

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

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

1193
  return res;
1194
}
1195

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

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

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

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

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

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

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

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

4✔
1252
  return 0;
4✔
1253
}
1254

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

8✔
1261
  (void) p;
8✔
1262

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

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

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

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

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

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

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

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

1302
  return res;
1303
}
1304

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

44✔
1309
  (void) p;
44✔
1310

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

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

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

16✔
1324
    } else {
16✔
1325
      res = flags;
15✔
1326
    }
1327

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

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

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

1✔
1344
      } else {
1✔
1345
        res = flags;
1✔
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) {
1355
  if (c == NULL) {
1356
    errno = EINVAL;
1357
    return -1;
4✔
1358
  }
4✔
1359

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

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

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

×
1374
      pr_log_pri(PR_LOG_ERR, "unable to listen on %s#%u: %s",
×
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

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

1✔
1385
    break;
1✔
1386
  }
1387

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

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

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

1✔
1407
  return 0;
1✔
1408
}
1409

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

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

2✔
1420
  c->mode = CM_CONNECT;
2✔
1421
  if (pr_inet_set_block(p, c) < 0) {
1422
    c->mode = CM_ERROR;
1423
    c->xerrno = errno;
14✔
1424
    return -1;
14✔
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));
1432
  pr_netaddr_set_port(&remote_na, htons(port));
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));
1437
    if (res < 0 &&
14✔
1438
        errno == EINTR) {
14✔
1439
      pr_signals_handle();
14✔
1440
      continue;
14✔
1441
    }
12✔
1442

×
1443
    break;
×
1444
  }
1445

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

12✔
1452
  c->mode = CM_OPEN;
12✔
1453

1454
  if (pr_inet_get_conn_info(c, c->listen_fd) < 0) {
1455
    c->mode = CM_ERROR;
2✔
1456
    c->xerrno = errno;
1457
    return -1;
2✔
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,
1468
    int port) {
1469
  pr_netaddr_t remote_na;
1470

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

2✔
1477
  c->mode = CM_CONNECT;
2✔
1478
  if (pr_inet_set_nonblock(p, c) < 0) {
1479
    c->mode = CM_ERROR;
1480
    c->xerrno = errno;
2✔
1481
    return -1;
2✔
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));
1489
  pr_netaddr_set_port(&remote_na, htons(port));
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 &&
1494
        errno != EALREADY) {
2✔
1495
      c->mode = CM_ERROR;
2✔
1496
      c->xerrno = errno;
2✔
1497

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

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

1✔
1504
    return 0;
1✔
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) {
1532
  int fd;
1533

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

1✔
1539
  if (c->mode == CM_LISTEN) {
1✔
1540
    if (pr_inet_set_nonblock(c->pool, c) < 0) {
1541
      if (errno != EBADF) {
1542
        pr_trace_msg(trace_channel, 3,
2✔
1543
          "error making connection nonblocking: %s", strerror(errno));
1✔
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;
1554
  while (TRUE) {
1555
    pr_signals_handle();
1556
    fd = accept(c->listen_fd, NULL, NULL);
2✔
1557

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

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

2✔
1569
      c->mode = CM_LISTEN;
2✔
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,
1594
    unsigned char resolve) {
1595
  config_rec *allow_foreign_addr_config = NULL;
1596
  conn_t *res = NULL;
4✔
1597
  int fd = -1;
1598
  pr_netaddr_t na;
4✔
1599
  socklen_t nalen;
4✔
1600

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

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

1610
  pr_netaddr_set_family(&na, pr_netaddr_get_family(c->remote_addr));
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);
3✔
1615
  d->mode = CM_ACCEPT;
1616

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

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

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

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

3✔
1636
    if (allow_foreign_addr_config != NULL) {
3✔
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) {
1723
  pr_netaddr_t na;
1724
  socklen_t nalen;
1725

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

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

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

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

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

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

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

1757
    } else {
2✔
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);
1767
    pr_netaddr_set_sockaddr(local_addr, pr_netaddr_get_sockaddr(&na));
1768
    c->local_port = ntohs(pr_netaddr_get_port(&na));
1769

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

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

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

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

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

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

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

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

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

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

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

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

1816
  } else {
1817
    int xerrno = errno;
2✔
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;
×
1827
}
1828

1829
/* Open streams for a new socket. If rfd and wfd != -1, two new fds are duped
2✔
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,
1845
    int strm_type, int fd, int rfd, int wfd, int resolve) {
1846
  conn_t *res = NULL;
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;
1852

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

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

1✔
1860
  res->listen_fd = -1;
1✔
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,
4✔
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 &&
1868
      errno != EBADF) {
1869
    int xerrno = errno;
1870

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

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

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

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

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

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

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

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

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

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

2✔
1915
    } else {
×
1916
      close_fd = FALSE;
×
1917
    }
1918

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

2✔
1926
  if (wfd > -1) {
1927
    if (fd != wfd) {
1928
      if (wfd == STDOUT_FILENO) {
1929
        fflush(stdout);
2✔
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) {
1941
      wfd = dup(fd);
1942
    }
1943
  }
2✔
1944

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

1952
  res->rfd = rfd;
1✔
1953
  res->wfd = wfd;
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. */
2✔
1959
  pr_inet_set_socket_opts(res->pool, res, 0, 0, NULL);
2✔
1960
  (void) pr_inet_set_block(res->pool, res);
1961

1962
  res->mode = CM_OPEN;
2✔
1963

2✔
1964
#if defined(HAVE_STROPTS_H) && defined(I_SRDOPT) && defined(RPROTDIS) && \
1965
    (defined(SOLARIS2_9) || defined(SOLARIS2_10))
2✔
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;
1983
}
1984

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

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

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

6✔
2005
  return 0;
6✔
2006
}
6✔
2007

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

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

2015
  /* AIX ships with a broken /etc/protocols file; the entry for 'ip' in that
48✔
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");
2025
  if (pr != NULL) {
2026
    ip_proto = pr->p_proto;
2027
  }
48✔
2028
#endif /* AIX */
48✔
2029

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

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

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

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

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