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

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

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

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

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

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

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

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

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

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

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

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

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

15✔
76
  (void) p;
77

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

503
      pr_timer_sleep(1);
×
504

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

70✔
585
  return c;
586
}
70✔
587

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

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

64✔
597
  return c;
598
}
64✔
599

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

9✔
785
  return res;
786
}
787

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

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

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

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

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

18✔
825
  return 0;
826
}
827

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

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

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

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

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

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

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

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

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

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

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

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

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

3✔
948
  return 0;
3✔
949
}
950

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

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

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

15✔
967
  keepalive = tcp_keepalive->keepalive_enabled;
1✔
968

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

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

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

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

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

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

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

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

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

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

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

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

1060
  return 0;
1061
}
1062

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1162
  return 0;
1163
}
1164

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

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

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

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

1192
  return res;
1193
}
1194

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

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

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

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

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

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

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

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

4✔
1251
  return 0;
4✔
1252
}
4✔
1253

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

1260
  (void) p;
8✔
1261

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

8✔
1267
  errno = EBADF;                /* Default */
1✔
1268

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

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

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

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

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

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

1301
  return res;
1302
}
1303

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

1308
  (void) p;
44✔
1309

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

44✔
1315
  errno = EBADF;                /* Default */
1✔
1316

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

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

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

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

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

27✔
1343
      } else {
1✔
1344
        res = flags;
1✔
1345
      }
1✔
1346
    }
1347
  }
1348

1349
  return res;
1350
}
1351

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

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

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

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

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

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

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

1384
    break;
1✔
1385
  }
1✔
1386

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

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

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

2✔
1406
  return 0;
1✔
1407
}
1✔
1408

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

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

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

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

1430
  memcpy(&remote_na, addr, sizeof(remote_na));
1431
  pr_netaddr_set_port(&remote_na, htons(port));
1432

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

12✔
1442
    break;
×
1443
  }
×
1444

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

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

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

×
1459
  return 1;
×
1460
}
×
1461

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

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

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

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

1487
  memcpy(&remote_na, addr, sizeof(remote_na));
1488
  pr_netaddr_set_port(&remote_na, htons(port));
1489

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

2✔
1497
      (void) pr_inet_set_block(c->pool, c);
1498

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

1503
    return 0;
1✔
1504
  }
1✔
1505

1506
  c->mode = CM_OPEN;
1507

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

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

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

×
1521
  return 1;
×
1522
}
×
1523

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

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

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

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

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

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

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

2✔
1568
      c->mode = CM_LISTEN;
2✔
1569
      c->xerrno = 0;
2✔
1570
      return -1;
1571
    }
1572

×
1573
    break;
×
1574
  }
×
1575

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

×
1586
  return fd;
1587
}
1588

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

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

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

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

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

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

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

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

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

3✔
1635
    if (allow_foreign_addr_config != NULL) {
3✔
1636
      int allowed;
3✔
1637

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

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

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

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

1666
            return NULL;
×
1667
          }
×
1668

×
1669
        } else {
1670
          char *class_name;
×
1671

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

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

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

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

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

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

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

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

1715
    break;
×
1716
  }
×
1717

1718
  return res;
1719
}
×
1720

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

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

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

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

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

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

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

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

2✔
1756
    } else {
1757
      local_addr = pr_netaddr_alloc(c->pool);
2✔
1758
    }
1759

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

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

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

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

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

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

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

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

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

×
1804
      remote_addr = pr_netaddr_alloc(c->pool);
1805

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

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

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

2✔
1815
  } else {
1816
    int xerrno = errno;
1817

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

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

1825
  return 0;
×
1826
}
×
1827

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

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

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

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

1859
  res->listen_fd = -1;
1✔
1860

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

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

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

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

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

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

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

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

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

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

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

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

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

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

×
1931
      dup2(fd, wfd);
×
1932

×
1933
    } else {
1934
      close_fd = FALSE;
1935
    }
×
1936

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

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

2✔
1951
  res->rfd = rfd;
1952
  res->wfd = wfd;
1✔
1953

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

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

1961
  res->mode = CM_OPEN;
1962

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

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

1981
  return res;
1982
}
1983

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

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

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

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

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

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

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

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

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

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

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

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