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

proftpd / proftpd / 14136377169

28 Mar 2025 07:21PM UTC coverage: 92.663% (-0.4%) from 93.027%
14136377169

push

github

Castaglia
To aid in debugging of unexpectedly malfunctioning authorized SSH keys, add trace logging of any lines of text which are not formatted as expected.

47143 of 50876 relevant lines covered (92.66%)

237.38 hits per line

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

72.88
/src/data.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-2023 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
/* Data connection management functions */
28

29
#include "conf.h"
30

31
#ifdef HAVE_SYS_SENDFILE_H
32
#include <sys/sendfile.h>
33
#endif /* HAVE_SYS_SENDFILE_H */
34

35
#ifdef HAVE_SYS_UIO_H
36
#include <sys/uio.h>
37
#endif /* HAVE_SYS_UIO_H */
38

39
static const char *trace_channel = "data";
40
static const char *timing_channel = "timing";
41

42
#define PR_DATA_OPT_IGNORE_ASCII        0x0001
43
static unsigned long data_opts = 0UL;
44
static uint64_t data_start_ms = 0L;
45
static int data_first_byte_read = FALSE;
46
static int data_first_byte_written = FALSE;
47

48
/* local macro */
49

50
#define MODE_STRING        (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE) ? \
51
                         "ASCII" : "BINARY")
52

53
/* Internal usage: pointer to current data connection stream in use (may be
54
 * in either read or write mode)
55
 */
56
static pr_netio_stream_t *nstrm = NULL;
57

58
static long timeout_linger = PR_TUNABLE_TIMEOUTLINGER;
59

60
static int timeout_idle = PR_TUNABLE_TIMEOUTIDLE;
61
static int timeout_noxfer = PR_TUNABLE_TIMEOUTNOXFER;
62
static int timeout_stalled = PR_TUNABLE_TIMEOUTSTALLED;
63

64
/* Called if the "Stalled" timer goes off
65
 */
66
static int stalled_timeout_cb(CALLBACK_FRAME) {
×
67
  pr_event_generate("core.timeout-stalled", NULL);
×
68
  pr_log_pri(PR_LOG_NOTICE, "Data transfer stall timeout: %d %s",
×
69
    timeout_stalled, timeout_stalled != 1 ? "seconds" : "second");
×
70
  pr_session_disconnect(NULL, PR_SESS_DISCONNECT_TIMEOUT,
×
71
    "TimeoutStalled during data transfer");
72

73
  /* Prevent compiler warning. */
74
  return 0;
×
75
}
76

77
/* This signal is raised if we get OOB data on the control connection, and
78
 * a data transfer is in progress.
79
 */
80
static RETSIGTYPE data_urgent(int signo) {
×
81
  if (session.sf_flags & SF_XFER) {
×
82
    pr_trace_msg(trace_channel, 5, "received SIGURG signal (signal %d), "
×
83
      "setting 'aborted' session flag", signo);
84
    session.sf_flags |= SF_ABORT;
×
85

86
    if (nstrm) {
×
87
      pr_netio_abort(nstrm);
×
88
    }
89
  }
90

91
  signal(SIGURG, data_urgent);
×
92
}
×
93

94
static void data_new_xfer(char *filename, int direction) {
7✔
95
  pr_data_clear_xfer_pool();
7✔
96

97
  session.xfer.p = make_sub_pool(session.pool);
7✔
98
  pr_pool_tag(session.xfer.p, "Data Transfer pool");
7✔
99

100
  session.xfer.filename = pstrdup(session.xfer.p, filename);
7✔
101
  session.xfer.direction = direction;
7✔
102
  session.xfer.bufsize = pr_config_get_server_xfer_bufsz(direction);
7✔
103
  session.xfer.buf = pcalloc(session.xfer.p, session.xfer.bufsize + 1);
7✔
104
  pr_trace_msg(trace_channel, 8, "allocated data transfer buffer of %lu bytes",
7✔
105
    (unsigned long) session.xfer.bufsize);
7✔
106
  session.xfer.buf++;        /* leave room for ascii translation */
7✔
107
  session.xfer.buflen = 0;
7✔
108
}
7✔
109

110
static int data_passive_open(const char *reason, off_t size) {
3✔
111
  conn_t *c;
112
  int rev, xerrno = 0;
3✔
113

114
  if (reason == NULL &&
6✔
115
      session.xfer.filename != NULL) {
3✔
116
    reason = session.xfer.filename;
×
117
  }
118

119
  /* Set the "stalled" timer, if any, to prevent the connection
120
   * open from taking too long
121
   */
122
  if (timeout_stalled) {
3✔
123
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
3✔
124
      "TimeoutStalled");
125
  }
126

127
  /* We save the state of our current disposition for doing reverse
128
   * lookups, and then set it to what the configuration wants it to
129
   * be.
130
   */
131
  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
3✔
132

133
  /* Protocol and socket options should be set before handshaking. */
134

135
  if (session.xfer.direction == PR_NETIO_IO_RD) {
3✔
136
    pr_inet_set_socket_opts2(session.d->pool, session.d,
4✔
137
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
2✔
138
      main_server->tcp_keepalive, 0);
2✔
139

140
  } else {
141
    pr_inet_set_socket_opts2(session.d->pool, session.d,
2✔
142
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
1✔
143
      main_server->tcp_keepalive, 0);
1✔
144
  }
145

146
  c = pr_inet_accept(session.pool, session.d, session.c, -1, -1, TRUE);
3✔
147
  pr_netaddr_set_reverse_dns(rev);
3✔
148

149
  if (c && c->mode != CM_ERROR) {
3✔
150
    pr_inet_close(session.pool, session.d);
×
151
    (void) pr_inet_set_nonblock(session.pool, c);
×
152
    session.d = c;
×
153

154
    pr_log_debug(DEBUG4, "passive data connection opened - local  : %s:%d",
×
155
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
156
    pr_log_debug(DEBUG4, "passive data connection opened - remote : %s:%d",
×
157
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);
×
158

159
    if (session.xfer.xfer_type != STOR_UNIQUE) {
×
160
      if (size) {
×
161
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
×
162
          "(%" PR_LU " %s)"), MODE_STRING, reason, (pr_off_t) size,
×
163
          size != 1 ? "bytes" : "byte");
164

165
      } else {
166
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
×
167
          MODE_STRING, reason);
×
168
      }
169

170
    } else {
171

172
      /* Format of 150 responses for STOU is explicitly dictated by
173
       * RFC 1123:
174
       *
175
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
176
       *
177
       *    The STOU command stores into a uniquely named file.  When it
178
       *    receives an STOU command, a Server-FTP MUST return the
179
       *    actual file name in the "125 Transfer Starting" or the "150
180
       *    Opening Data Connection" message that precedes the transfer
181
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
182
       *    exact format of these messages is hereby defined to be as
183
       *    follows:
184
       *
185
       *        125 FILE: pppp
186
       *        150 FILE: pppp
187
       *
188
       *    where pppp represents the unique pathname of the file that
189
       *    will be written.
190
       */
191
      pr_response_send(R_150, "FILE: %s", reason);
×
192
    }
193

194
    return 0;
195
  }
196

197
  /* Check for error conditions. */
198
  if (c != NULL &&
3✔
199
      c->mode == CM_ERROR) {
×
200
    pr_log_pri(PR_LOG_ERR, "error: unable to accept an incoming data "
×
201
      "connection: %s", strerror(c->xerrno));
202
  }
203

204
  xerrno = session.d->xerrno;
3✔
205
  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
3✔
206
    strerror(xerrno));
207
  pr_data_close2();
3✔
208

209
  errno = xerrno;
3✔
210
  return -1;
3✔
211
}
212

213
static int data_active_open(const char *reason, off_t size) {
8✔
214
  conn_t *c;
215
  int bind_port, rev, *root_revoke = NULL, xerrno;
8✔
216
  const pr_netaddr_t *bind_addr = NULL;
8✔
217

218
  if (session.c->remote_addr == NULL) {
8✔
219
    /* An opened but unconnected connection? */
220
    errno = EINVAL;
1✔
221
    return -1;
1✔
222
  }
223

224
  if (reason == NULL &&
14✔
225
      session.xfer.filename != NULL) {
7✔
226
    reason = session.xfer.filename;
4✔
227
  }
228

229
  if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(session.c->remote_addr)) {
7✔
230
    bind_addr = session.c->local_addr;
7✔
231

232
  } else {
233
    /* In this scenario, the server has an IPv6 socket, but the remote client
234
     * is an IPv4 (or IPv4-mapped IPv6) peer.
235
     */
236
    bind_addr = pr_netaddr_v6tov4(session.xfer.p, session.c->local_addr);
×
237
  }
238

239
  /* Default source port to which to bind for the active transfer, as
240
   * per RFC959.
241
   */
242
  bind_port = session.c->local_port-1;
7✔
243

244
  root_revoke = get_param_ptr(TOPLEVEL_CONF, "RootRevoke", FALSE);
7✔
245
  if (root_revoke == NULL) {
7✔
246
    /* In the absence of any explicit RootRevoke, the default behavior is to
247
     * change the source port.  This means we are technically noncompliant,
248
     * but most clients do not enforce this behavior.
249
     */
250
    bind_port = INPORT_ANY;
251

252
  } else {
253
    /* A RootRevoke value of 0 indicates 'false', 1 indicates 'true', and
254
     * 2 indicates 'NonCompliantActiveTransfer'.  We change the source port for
255
     * a RootRevoke value of 2, and for a value of 1, we make sure that
256
     * that the port is not a privileged port.
257
     */
258
    switch (*root_revoke) {
4✔
259
      case 1:
2✔
260
        if (bind_port < 1024) {
2✔
261
          pr_log_debug(DEBUG0, "RootRevoke in effect, unable to bind to local "
1✔
262
            "port %d for active transfer", bind_port);
263
          errno = EPERM;
1✔
264
          return -1;
1✔
265
        }
266
        break;
267

268
      case 2:
1✔
269
        bind_port = INPORT_ANY;
1✔
270
        break;
1✔
271

272
      default:
273
        break;
274
    }
275
  }
276

277
  session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);
6✔
278
  if (session.d == NULL) {
6✔
279
    xerrno = errno;
×
280

281
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
282
      strerror(xerrno));
283

284
    errno = xerrno;
×
285
    return -1;
×
286
  }
287

288
  /* Default remote address to which to connect for an active transfer,
289
   * if the client has not specified a different address via PORT/EPRT,
290
   * as per RFC 959.
291
   */
292
  if (pr_netaddr_get_family(&session.data_addr) == AF_UNSPEC) {
6✔
293
    pr_log_debug(DEBUG6, "Client has not sent previous PORT/EPRT command, "
2✔
294
      "defaulting to %s#%u for active transfer",
295
      pr_netaddr_get_ipstr(session.c->remote_addr), session.c->remote_port);
2✔
296

297
    pr_netaddr_set_family(&session.data_addr, pr_netaddr_get_family(session.c->remote_addr));
2✔
298
    pr_netaddr_set_sockaddr(&session.data_addr, pr_netaddr_get_sockaddr(session.c->remote_addr));
2✔
299
  }
300

301
  /* Set the "stalled" timer, if any, to prevent the connection
302
   * open from taking too long
303
   */
304
  if (timeout_stalled) {
6✔
305
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
6✔
306
      "TimeoutStalled");
307
  }
308

309
  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
6✔
310

311
  /* Protocol and socket options should be set before handshaking. */
312

313
  if (session.xfer.direction == PR_NETIO_IO_RD) {
6✔
314
    pr_inet_set_socket_opts2(session.d->pool, session.d,
8✔
315
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
4✔
316
      main_server->tcp_keepalive, 1);
4✔
317

318
  } else {
319
    pr_inet_set_socket_opts2(session.d->pool, session.d,
4✔
320
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
2✔
321
      main_server->tcp_keepalive, 1);
2✔
322
  }
323

324
  /* Make sure that the necessary socket options are set on the socket prior
325
   * to the call to connect(2).
326
   */
327
  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
6✔
328
    IPTOS_THROUGHPUT, 1);
329
  pr_inet_generate_socket_event("core.data-connect", main_server,
6✔
330
    session.d->local_addr, session.d->listen_fd);
6✔
331

332
  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
6✔
333
      session.data_port) < 0) {
6✔
334
    xerrno = session.d->xerrno;
6✔
335

336
    pr_log_debug(DEBUG6,
12✔
337
      "Error connecting to %s#%u for active data transfer: %s",
338
      pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
6✔
339
      strerror(xerrno));
340
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
6✔
341
      strerror(xerrno));
342
    pr_data_close2();
6✔
343

344
    errno = xerrno;
6✔
345
    return -1;
6✔
346
  }
347

348
  c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
×
349
    session.d->listen_fd, -1, -1, TRUE);
×
350

351
  pr_netaddr_set_reverse_dns(rev);
×
352

353
  if (c) {
×
354
    pr_log_debug(DEBUG4, "active data connection opened - local  : %s:%d",
×
355
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
×
356
    pr_log_debug(DEBUG4, "active data connection opened - remote : %s:%d",
×
357
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);
×
358

359
    if (session.xfer.xfer_type != STOR_UNIQUE) {
×
360
      if (size) {
×
361
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
×
362
          "(%" PR_LU " %s)"), MODE_STRING, reason, (pr_off_t) size,
×
363
          size != 1 ? "bytes" : "byte");
364

365
      } else {
366
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
×
367
          MODE_STRING, reason);
×
368
      }
369

370
    } else {
371

372
      /* Format of 150 responses for STOU is explicitly dictated by
373
       * RFC 1123:
374
       *
375
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
376
       *
377
       *    The STOU command stores into a uniquely named file.  When it
378
       *    receives an STOU command, a Server-FTP MUST return the
379
       *    actual file name in the "125 Transfer Starting" or the "150
380
       *    Opening Data Connection" message that precedes the transfer
381
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
382
       *    exact format of these messages is hereby defined to be as
383
       *    follows:
384
       *
385
       *        125 FILE: pppp
386
       *        150 FILE: pppp
387
       *
388
       *    where pppp represents the unique pathname of the file that
389
       *    will be written.
390
       */
391
      pr_response_send(R_150, "FILE: %s", reason);
×
392
    }
393

394
    pr_inet_close(session.pool, session.d);
×
395
    (void) pr_inet_set_nonblock(session.pool, session.d);
×
396
    session.d = c;
×
397
    return 0;
×
398
  }
399

400
  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
401
    strerror(session.d->xerrno));
×
402
  xerrno = session.d->xerrno;
×
403
  pr_data_close2();
×
404

405
  errno = xerrno;
×
406
  return -1;
×
407
}
408

409
void pr_data_set_linger(long linger) {
1✔
410
  timeout_linger = linger;
1✔
411
}
1✔
412

413
int pr_data_get_timeout(int id) {
7✔
414
  switch (id) {
7✔
415
    case PR_DATA_TIMEOUT_IDLE:
2✔
416
      return timeout_idle;
2✔
417

418
    case PR_DATA_TIMEOUT_NO_TRANSFER:
2✔
419
      return timeout_noxfer;
2✔
420

421
    case PR_DATA_TIMEOUT_STALLED:
2✔
422
      return timeout_stalled;
2✔
423
  }
424

425
  errno = EINVAL;
1✔
426
  return -1;
1✔
427
}
428

429
void pr_data_set_timeout(int id, int timeout) {
3✔
430
  switch (id) {
3✔
431
    case PR_DATA_TIMEOUT_IDLE:
1✔
432
      timeout_idle = timeout;
1✔
433
      break;
1✔
434

435
    case PR_DATA_TIMEOUT_NO_TRANSFER:
1✔
436
      timeout_noxfer = timeout;
1✔
437
      break;
1✔
438

439
    case PR_DATA_TIMEOUT_STALLED:
1✔
440
      timeout_stalled = timeout;
1✔
441
      break;
1✔
442
  }
443
}
3✔
444

445
void pr_data_clear_xfer_pool(void) {
19✔
446
  int xfer_type;
447

448
  if (session.xfer.p != NULL) {
19✔
449
    destroy_pool(session.xfer.p);
2✔
450
  }
451

452
  /* Note that session.xfer.xfer_type may have been set already, e.g.
453
   * for STOR_UNIQUE uploads.  To support this, we need to preserve that
454
   * value.
455
   */
456
  xfer_type = session.xfer.xfer_type;
19✔
457

458
  memset(&session.xfer, 0, sizeof(session.xfer));
19✔
459
  session.xfer.xfer_type = xfer_type;
19✔
460
}
19✔
461

462
void pr_data_reset(void) {
9✔
463
  /* Clear any leftover state from previous transfers. */
464
  pr_ascii_ftp_reset();
9✔
465

466
  if (session.d != NULL &&
10✔
467
      session.d->pool != NULL) {
1✔
468
    destroy_pool(session.d->pool);
1✔
469
  }
470

471
  session.d = NULL;
9✔
472
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_POST_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE|SF_EPSV_ALL));
9✔
473
}
9✔
474

475
int pr_data_ignore_ascii(int ignore_ascii) {
5✔
476
  int res;
477

478
  if (ignore_ascii != TRUE &&
5✔
479
      ignore_ascii != FALSE) {
480
    errno = EINVAL;
1✔
481
    return -1;
1✔
482
  }
483

484
  if (data_opts & PR_DATA_OPT_IGNORE_ASCII) {
4✔
485
    if (!ignore_ascii) {
2✔
486
      data_opts &= ~PR_DATA_OPT_IGNORE_ASCII;
1✔
487
    }
488

489
    res = TRUE;
490

491
  } else {
492
    if (ignore_ascii) {
2✔
493
      data_opts |= PR_DATA_OPT_IGNORE_ASCII;
1✔
494
    }
495

496
    res = FALSE;
497
  }
498

499
  return res;
500
}
501

502
void pr_data_init(char *filename, int direction) {
3✔
503
  if (session.xfer.p == NULL) {
3✔
504
    data_new_xfer(filename, direction);
2✔
505

506
  } else {
507
    if (!(session.sf_flags & SF_PASSIVE)) {
1✔
508
      pr_log_debug(DEBUG5,
1✔
509
        "data_init oddity: session.xfer exists in non-PASV mode");
510
    }
511

512
    session.xfer.direction = direction;
1✔
513
  }
514

515
  /* Clear any leftover state from previous transfers. */
516
  pr_ascii_ftp_reset();
3✔
517
}
3✔
518

519
int pr_data_open(char *filename, char *reason, int direction, off_t size) {
15✔
520
  int res = 0;
15✔
521
  struct sigaction act;
522

523
  if (session.c == NULL) {
15✔
524
    errno = EINVAL;
2✔
525
    return -1;
2✔
526
  }
527

528
  if ((session.sf_flags & SF_PASSIVE) ||
22✔
529
      (session.sf_flags & SF_EPSV_ALL)) {
9✔
530
    /* For passive transfers, we expect there to already be an existing
531
     * data connection...
532
     */
533
    if (session.d == NULL) {
4✔
534
      errno = EINVAL;
1✔
535
      return -1;
1✔
536
    }
537

538
  } else {
539
    /* ...but for active transfers, we expect there to NOT be an existing
540
     * data connection.
541
     */
542
    if (session.d != NULL) {
9✔
543
      errno = session.d->xerrno = EINVAL;
1✔
544
      return -1;
1✔
545
    }
546
  }
547

548
  /* Make sure that any abort flags have been cleared. */
549
  session.sf_flags &= ~(SF_ABORT|SF_POST_ABORT);
11✔
550

551
  if (session.xfer.p == NULL) {
11✔
552
    data_new_xfer(filename, direction);
5✔
553

554
  } else {
555
    session.xfer.direction = direction;
6✔
556
  }
557

558
  if (reason == NULL) {
11✔
559
    reason = filename;
11✔
560
  }
561

562
  /* Passive data transfers... */
563
  if ((session.sf_flags & SF_PASSIVE) ||
19✔
564
      (session.sf_flags & SF_EPSV_ALL)) {
8✔
565
    res = data_passive_open(reason, size);
3✔
566

567
  /* Active data transfers... */
568
  } else {
569
    res = data_active_open(reason, size);
8✔
570
  }
571

572
  if (res < 0) {
11✔
573
    return res;
574
  }
575

576
  if (pr_netio_postopen(session.d->instrm) < 0) {
×
577
    int xerrno;
578

579
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
580
      strerror(session.d->xerrno));
×
581
    xerrno = session.d->xerrno;
×
582
    pr_data_close2();
×
583

584
    errno = xerrno;
×
585
    return -1;
×
586
  }
587

588
  if (pr_netio_postopen(session.d->outstrm) < 0) {
×
589
    int xerrno;
590

591
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
592
      strerror(session.d->xerrno));
×
593
    xerrno = session.d->xerrno;
×
594
    pr_data_close2();
×
595

596
    errno = xerrno;
×
597
    return -1;
×
598
  }
599

600
  memset(&session.xfer.start_time, '\0', sizeof(session.xfer.start_time));
×
601
  gettimeofday(&session.xfer.start_time, NULL);
×
602

603
  if (session.xfer.direction == PR_NETIO_IO_RD) {
×
604
    nstrm = session.d->instrm;
×
605

606
  } else {
607
    nstrm = session.d->outstrm;
×
608
  }
609

610
  session.sf_flags |= SF_XFER;
×
611

612
  if (timeout_noxfer) {
×
613
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
×
614
  }
615

616
  /* Allow aborts -- set the current NetIO stream to allow interrupted
617
   * syscalls, so our SIGURG handler can interrupt it
618
   */
619
  pr_netio_set_poll_interval(nstrm, 1);
×
620

621
  /* PORTABILITY: sigaction is used here to allow us to indicate
622
   * (w/ POSIX at least) that we want SIGURG to interrupt syscalls.  Put
623
   * in whatever is necessary for your arch here; probably not necessary
624
   * as the only _important_ interrupted syscall is select(), which on
625
   * any sensible system is interrupted.
626
   */
627

628
  act.sa_handler = data_urgent;
×
629
  sigemptyset(&act.sa_mask);
×
630
  act.sa_flags = 0;
631
#ifdef SA_INTERRUPT
632
  act.sa_flags |= SA_INTERRUPT;
×
633
#endif
634

635
  if (sigaction(SIGURG, &act, NULL) < 0) {
×
636
    pr_log_pri(PR_LOG_WARNING,
×
637
      "warning: unable to set SIGURG signal handler: %s", strerror(errno));
×
638
  }
639

640
#ifdef HAVE_SIGINTERRUPT
641
  /* This is the BSD way of ensuring interruption.
642
   * Linux uses it too (??)
643
   */
644
  if (siginterrupt(SIGURG, 1) < 0) {
×
645
    pr_log_pri(PR_LOG_WARNING,
×
646
      "warning: unable to make SIGURG interrupt system calls: %s",
647
      strerror(errno));
×
648
  }
649
#endif
650

651
  /* Reset all of the timing-related variables for data transfers. */
652
  pr_gettimeofday_millis(&data_start_ms);
×
653
  data_first_byte_read = FALSE;
×
654
  data_first_byte_written = FALSE;
×
655

656
  return res;
×
657
}
658

659
void pr_data_close2(void) {
12✔
660
  nstrm = NULL;
12✔
661

662
  if (session.d != NULL) {
12✔
663
    pr_inet_lingering_close(session.pool, session.d, timeout_linger);
10✔
664
    session.d = NULL;
10✔
665
  }
666

667
  /* Aborts no longer necessary */
668
  signal(SIGURG, SIG_IGN);
12✔
669

670
  if (timeout_noxfer) {
12✔
671
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
12✔
672
  }
673

674
  if (timeout_stalled) {
12✔
675
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
12✔
676
  }
677

678
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
12✔
679
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
12✔
680
  pr_session_set_idle();
12✔
681
}
12✔
682

683
/* close == successful transfer */
684
void pr_data_close(int quiet) {
3✔
685
  pr_data_close2();
3✔
686

687
  if (quiet == FALSE) {
3✔
688
    pr_response_add(R_226, _("Transfer complete"));
1✔
689
  }
690
}
3✔
691

692
/* Note: true_abort may be false in real abort situations, because
693
 * some ftp clients close the data connection at the same time as they
694
 * send the OOB byte (which results in a broken pipe on our
695
 * end).  Thus, it's a race between the OOB data and the tcp close
696
 * finishing.  Either way, it's ok (client will see either "Broken pipe"
697
 * error or "Aborted").  xfer_abor() in mod_xfer cleans up the session
698
 * flags in any case.  session flags will end up have SF_POST_ABORT
699
 * set if the OOB byte won the race.
700
 */
701
void pr_data_cleanup(void) {
2✔
702
  /* sanity check */
703
  if (session.d != NULL) {
2✔
704
    pr_inet_lingering_close(session.pool, session.d, timeout_linger);
1✔
705
    session.d = NULL;
1✔
706
  }
707

708
  pr_data_clear_xfer_pool();
2✔
709

710
  /* Clear/restore the default data transfer type. Otherwise, things like
711
   * APPEs or STOUs will be preserved for the next upload erroneously
712
   * (see Bug#3612).
713
   */
714
  session.xfer.xfer_type = STOR_DEFAULT;
2✔
715
}
2✔
716

717
/* In order to avoid clearing the transfer counters in session.xfer, we don't
718
 * clear session.xfer here, it should be handled by the appropriate
719
 * LOG_CMD/LOG_CMD_ERR handler calling pr_data_cleanup().
720
 */
721
void pr_data_abort(int err, int quiet) {
11✔
722
  int true_abort = XFER_ABORTED;
11✔
723
  nstrm = NULL;
11✔
724

725
  pr_trace_msg(trace_channel, 9,
11✔
726
    "aborting data transfer (errno = %s (%d), quiet = %s, true abort = %s)",
727
    strerror(err), err, quiet ? "true" : "false",
728
    true_abort ? "true" : "false");
729

730
  if (session.d != NULL) {
11✔
731
    if (true_abort) {
9✔
732
      /* For "true" aborts, we also asynchronously send a 426 response
733
       * message via the "lingering abort" functions.
734
       */
735
      pr_inet_lingering_abort(session.pool, session.d, timeout_linger);
8✔
736

737
    } else {
738
      pr_inet_lingering_close(session.pool, session.d, timeout_linger);
1✔
739
    }
740

741
    session.d = NULL;
9✔
742
  }
743

744
  if (timeout_noxfer) {
11✔
745
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
11✔
746
  }
747

748
  if (timeout_stalled) {
11✔
749
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
11✔
750
  }
751

752
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
11✔
753
  session.sf_flags &= (SF_ALL^(SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
11✔
754
  pr_session_set_idle();
11✔
755

756
  if (!quiet) {
11✔
757
    char *respcode = R_426;
10✔
758
    char *msg = NULL;
10✔
759
    char msgbuf[64];
760

761
    switch (err) {
10✔
762

763
    case 0:
2✔
764
#ifdef ECONNABORTED
765
    case ECONNABORTED:        /* FALLTHROUGH */
766
#endif
767
#ifdef ECONNRESET
768
    case ECONNRESET:        /* FALLTHROUGH */
769
#endif
770
#ifdef EPIPE
771
    case EPIPE:
772
#endif
773
      respcode = R_426;
2✔
774
      msg = _("Data connection closed");
2✔
775
      break;
2✔
776

777
#ifdef ENXIO
778
    case ENXIO:
1✔
779
      respcode = R_451;
1✔
780
      msg = _("Unexpected streams hangup");
1✔
781
      break;
1✔
782
#endif
783

784
#ifdef EAGAIN
785
    case EAGAIN:                /* FALLTHROUGH */
1✔
786
#endif
787
#ifdef ENOMEM
788
    case ENOMEM:
789
#endif
790
#if defined(EAGAIN) || defined(ENOMEM)
791
      respcode = R_451;
1✔
792
      msg = _("Insufficient memory or file locked");
1✔
793
      break;
1✔
794
#endif
795

796
#ifdef ETXTBSY
797
    case ETXTBSY:                /* FALLTHROUGH */
798
#endif
799
#ifdef EBUSY
800
    case EBUSY:
801
#endif
802
#if defined(ETXTBSY) || defined(EBUSY)
803
      respcode = R_451;
804
      break;
805
#endif
806

807
#ifdef ENOSPC
808
    case ENOSPC:
809
      respcode = R_452;
810
      break;
811
#endif
812

813
#ifdef EDQUOT
814
    case EDQUOT:                /* FALLTHROUGH */
815
#endif
816
#ifdef EFBIG
817
    case EFBIG:
818
#endif
819
#if defined(EDQUOT) || defined(EFBIG)
820
      respcode = R_552;
821
      break;
822
#endif
823

824
#ifdef ECOMM
825
    case ECOMM:                /* FALLTHROUGH */
826
#endif
827
#ifdef EDEADLK
828
    case EDEADLK:                /* FALLTHROUGH */
829
#endif
830
#ifdef EDEADLOCK
831
# if !defined(EDEADLK) || (EDEADLOCK != EDEADLK)
832
    case EDEADLOCK:                /* FALLTHROUGH */
833
# endif
834
#endif
835
#ifdef EXFULL
836
    case EXFULL:                /* FALLTHROUGH */
837
#endif
838
#ifdef ENOSR
839
    case ENOSR:                /* FALLTHROUGH */
840
#endif
841
#ifdef EPROTO
842
    case EPROTO:                /* FALLTHROUGH */
843
#endif
844
#ifdef ETIME
845
    case ETIME:                /* FALLTHROUGH */
846
#endif
847
#ifdef EIO
848
    case EIO:                /* FALLTHROUGH */
849
#endif
850
#ifdef EFAULT
851
    case EFAULT:                /* FALLTHROUGH */
852
#endif
853
#ifdef ESPIPE
854
    case ESPIPE:                /* FALLTHROUGH */
855
#endif
856
#if defined(ECOMM) || defined(EDEADLK) ||  defined(EDEADLOCK) || \
857
    defined(EXFULL) || defined(ENOSR) || defined(EPROTO) || \
858
    defined(ETIME) || defined(EIO) || defined(EFAULT) || \
859
    defined(ESPIPE) || defined(EPIPE)
860
      respcode = R_451;
861
      break;
862
#endif
863

864
#ifdef EREMCHG
865
    case EREMCHG:                /* FALLTHROUGH */
×
866
#endif
867
#ifdef ESRMNT
868
    case ESRMNT:                /* FALLTHROUGH */
869
#endif
870
#ifdef ESTALE
871
    case ESTALE:                /* FALLTHROUGH */
872
#endif
873
#ifdef ENOLINK
874
    case ENOLINK:                /* FALLTHROUGH */
875
#endif
876
#ifdef ENOLCK
877
    case ENOLCK:                /* FALLTHROUGH */
878
#endif
879
#ifdef ENETRESET
880
    case ENETRESET:                /* FALLTHROUGH */
881
#endif
882
#ifdef ETIMEDOUT
883
    case ETIMEDOUT:
884
#endif
885
#if defined(EREMCHG) || defined(ESRMNT) ||  defined(ESTALE) || \
886
    defined(ENOLINK) || defined(ENOLCK) || defined(ENETRESET) || \
887
    defined(ECONNABORTED) || defined(ECONNRESET) || defined(ETIMEDOUT)
888
      respcode = R_450;
×
889
      msg = _("Link to file server lost");
×
890
      break;
×
891
#endif
892
    }
893

894
    if (msg == NULL &&
4✔
895
        (msg = strerror(err)) == NULL) {
896

897
      if (pr_snprintf(msgbuf, sizeof(msgbuf),
×
898
          _("Unknown or out of range errno [%d]"), err) > 0) {
×
899
        msg = msgbuf;
×
900
      }
901
    }
902

903
    pr_log_pri(PR_LOG_NOTICE, "notice: user %s: aborting transfer: %s",
10✔
904
      session.user ? session.user : "(unknown)", msg);
10✔
905

906
    /* If we are aborting, then a 426 response has already been sent via
907
     * pr_inet_lingering_abort(), and we don't want to add another to the
908
     * error queue.
909
     */
910
    if (true_abort == FALSE) {
10✔
911
      pr_response_add_err(respcode, _("Transfer aborted. %s"), msg ? msg : "");
2✔
912
    }
913

914
    /* Forcibly clear the data-transfer instigating command pool from the
915
     * Response API.
916
     */
917
    pr_response_set_pool(session.pool);
10✔
918
  }
919

920
  if (true_abort) {
11✔
921
    session.sf_flags |= SF_POST_ABORT;
8✔
922
  }
923
}
11✔
924

925
/* From response.c.  XXX Need to provide these symbols another way. */
926
extern pr_response_t *resp_list, *resp_err_list;
927

928
static int peek_is_abor_cmd(void) {
14✔
929
  int fd, res;
930
  fd_set rfds;
931
  struct timeval tv;
932
  ssize_t len;
933
  char buf[5];
934

935
  tv.tv_sec = 1;
14✔
936
  tv.tv_usec = 0;
14✔
937

938
  fd = PR_NETIO_FD(session.c->instrm);
14✔
939
  pr_trace_msg(trace_channel, 20, "peeking at next data for fd %d", fd);
14✔
940

941
  FD_ZERO(&rfds);
14✔
942
  FD_SET(fd, &rfds);
14✔
943

944
  res = select(fd + 1, &rfds, NULL, NULL, &tv);
14✔
945
  while (res < 0) {
14✔
946
    int xerrno = errno;
×
947

948
    if (xerrno == EINTR) {
×
949
      pr_signals_handle();
×
950
      res = select(fd + 1, &rfds, NULL, NULL, &tv);
×
951
      continue;
×
952
    }
953

954
    pr_trace_msg(trace_channel, 20,
×
955
      "error waiting for next data on fd %d: %s", fd, strerror(xerrno));
956
    return FALSE;
×
957
  }
958

959
  if (res == 0) {
14✔
960
    /* Timed out. */
961
    pr_trace_msg(trace_channel, 20, "timed out peeking for data on fd %d", fd);
13✔
962
    return FALSE;
13✔
963
  }
964

965
  /* If we reach here, the peer must have sent something.  Let's see what it
966
   * might be.  Chances are that we received at least 5 bytes, but to be
967
   * defensive, we use MSG_WAITALL anyway.  TCP allows for sending one byte
968
   * at time, if need be.  The shortest FTP command is 5 bytes, e.g. "CCC\r\n".
969
   * ABOR would be 6 bytes, but we do not want to block until we see 6 bytes;
970
   * we're peeking opportunistically, and optimistically.
971
   */
972
  memset(&buf, 0, sizeof(buf));
1✔
973
  len = recv(fd, buf, sizeof(buf), MSG_PEEK|MSG_WAITALL);
1✔
974
  while (len < 0) {
1✔
975
    int xerrno = errno;
1✔
976

977
    if (xerrno == EINTR) {
1✔
978
      pr_signals_handle();
×
979
      len = recv(fd, &buf, sizeof(buf), MSG_PEEK|MSG_WAITALL);
×
980
      continue;
×
981
    }
982

983
    pr_trace_msg(trace_channel, 20,
1✔
984
      "error peeking at next data: %s", strerror(xerrno));
985
    return FALSE;
1✔
986
  }
987

988
  pr_trace_msg(trace_channel, 20, "peeking at %ld bytes of next data",
×
989
    (long) len);
990
  if (strncasecmp(buf, "ABOR\r", len) == 0) {
×
991
    pr_trace_msg(trace_channel, 20, "peeked data probably 'ABOR' command");
×
992
    return TRUE;
×
993
  }
994

995
  pr_trace_msg(trace_channel, 20, "peeked data '%.*s' not ABOR command",
×
996
    (int) len, buf);
997
  return FALSE;
×
998
}
999

1000
static void poll_ctrl(void) {
26✔
1001
  int res;
1002

1003
  if (session.c == NULL) {
26✔
1004
    return;
1005
  }
1006

1007
  pr_trace_msg(trace_channel, 4, "polling for commands on control channel");
14✔
1008
  pr_netio_set_poll_interval(session.c->instrm, 0);
14✔
1009
  res = pr_netio_poll(session.c->instrm);
14✔
1010
  pr_netio_reset_poll_interval(session.c->instrm);
14✔
1011

1012
  if (res == 0 &&
28✔
1013
      !(session.sf_flags & SF_ABORT)) {
14✔
1014

1015
    /* First, we peek at the data, to see if it is an ABOR command.  Why?
1016
     *
1017
     * Consider the case where a client uses the TCP OOB mechanism and
1018
     * marks the ABOR command with the marker.  In that case, a SIGURG signal
1019
     * will have been raised, and the SF_ABORT flag set.  The actual "ABOR"
1020
     * data on the control connection will be read only AFTER the data transfer
1021
     * has been failed.  This leads the proper ordering of multiple responses
1022
     * (first for failed transfer, second for successful ABOR) in such cases.
1023
     *
1024
     * Now consider the case where a client does NOT use the TCP OOB mechanism,
1025
     * and only sends the ABOR command.  We want the same behavior in this case
1026
     * as for the TCP OOB case, BUT now, the SF_ABORT flag has NOT been set at
1027
     * this point in the flow.  Which means that we might read that "ABOR" text
1028
     * from the control connection _in the middle_ of the data transfer, which
1029
     * leads to different behavior, different ordering of responses.
1030
     *
1031
     * Thus we cheat here, and only peek at the control connection data.  IFF
1032
     * it is the "ABOR\r\n" text, then we set the SF_ABORT flag ourselves
1033
     * here, and preserve the expected semantics (Bug #4402).
1034
     */
1035
    if (peek_is_abor_cmd() == TRUE) {
14✔
1036
      pr_trace_msg(trace_channel, 5, "client sent 'ABOR' command during data "
×
1037
        "transfer, setting 'aborted' session flag");
1038

1039
      session.sf_flags |= SF_ABORT;
×
1040

1041
      if (nstrm != NULL) {
×
1042
        pr_netio_abort(nstrm);
×
1043
        errno = 0;
×
1044
      }
1045
    }
1046
  }
1047

1048
  if (res == 0 &&
28✔
1049
      !(session.sf_flags & SF_ABORT)) {
14✔
1050
    cmd_rec *cmd = NULL;
14✔
1051

1052
    pr_trace_msg(trace_channel, 1,
14✔
1053
      "data available for reading on control channel during data transfer, "
1054
      "reading control data");
1055
    res = pr_cmd_read(&cmd);
14✔
1056
    if (res < 0) {
14✔
1057
      int xerrno;
1058

1059
#if defined(ECONNABORTED)
1060
      xerrno = ECONNABORTED;
×
1061
#elif defined(ENOTCONN)
1062
      xerrno = ENOTCONN;
1063
#else
1064
      xerrno = EIO;
1065
#endif
1066

1067
      pr_trace_msg(trace_channel, 1,
×
1068
        "unable to read control command during data transfer: %s",
1069
        strerror(xerrno));
1070
      errno = xerrno;
×
1071

1072
#ifndef PR_DEVEL_NO_DAEMON
1073
      /* Otherwise, EOF */
1074
      pr_session_disconnect(NULL, PR_SESS_DISCONNECT_CLIENT_EOF, NULL);
×
1075
#else
1076
      return;
1077
#endif /* PR_DEVEL_NO_DAEMON */
1078

1079
    } else if (cmd != NULL) {
14✔
1080
      char *ch;
1081

1082
      for (ch = cmd->argv[0]; *ch; ch++) {
35✔
1083
        *ch = toupper((int) *ch);
56✔
1084
      }
1085

1086
      cmd->cmd_id = pr_cmd_get_id(cmd->argv[0]);
7✔
1087

1088
      /* Only handle commands which do not involve data transfers; we
1089
       * already have a data transfer in progress.  For any data transfer
1090
       * command, send a 450 ("busy") reply.  Looks like almost all of the
1091
       * data transfer commands accept that response, as per RFC959.
1092
       *
1093
       * We also prevent the EPRT, EPSV, PASV, and PORT commands, since
1094
       * they will also interfere with the current data transfer.  In doing
1095
       * so, we break RFC compliance a little; RFC959 does not allow a
1096
       * response code of 450 for those commands (although it should).
1097
       */
1098
      if (pr_cmd_cmp(cmd, PR_CMD_APPE_ID) == 0 ||
14✔
1099
          pr_cmd_cmp(cmd, PR_CMD_LIST_ID) == 0 ||
14✔
1100
          pr_cmd_cmp(cmd, PR_CMD_MLSD_ID) == 0 ||
14✔
1101
          pr_cmd_cmp(cmd, PR_CMD_NLST_ID) == 0 ||
14✔
1102
          pr_cmd_cmp(cmd, PR_CMD_RETR_ID) == 0 ||
14✔
1103
          pr_cmd_cmp(cmd, PR_CMD_STOR_ID) == 0 ||
14✔
1104
          pr_cmd_cmp(cmd, PR_CMD_STOU_ID) == 0 ||
14✔
1105
          pr_cmd_cmp(cmd, PR_CMD_RNFR_ID) == 0 ||
14✔
1106
          pr_cmd_cmp(cmd, PR_CMD_RNTO_ID) == 0 ||
14✔
1107
          pr_cmd_cmp(cmd, PR_CMD_PORT_ID) == 0 ||
14✔
1108
          pr_cmd_cmp(cmd, PR_CMD_EPRT_ID) == 0 ||
14✔
1109
          pr_cmd_cmp(cmd, PR_CMD_PASV_ID) == 0 ||
12✔
1110
          pr_cmd_cmp(cmd, PR_CMD_EPSV_ID) == 0) {
7✔
1111
        pool *resp_pool;
1112

1113
        pr_trace_msg(trace_channel, 5,
2✔
1114
          "client sent '%s' command during data transfer, denying",
1115
          (char *) cmd->argv[0]);
2✔
1116

1117
        resp_list = resp_err_list = NULL;
2✔
1118
        resp_pool = pr_response_get_pool();
2✔
1119

1120
        pr_response_set_pool(cmd->pool);
2✔
1121

1122
        pr_response_add_err(R_450, _("%s: data transfer in progress"),
2✔
1123
          (char *) cmd->argv[0]);
2✔
1124

1125
        pr_response_flush(&resp_err_list);
2✔
1126

1127
        pr_response_set_pool(resp_pool);
2✔
1128
        destroy_pool(cmd->pool);
2✔
1129

1130
      /* We don't want to actually dispatch the NOOP command, since that
1131
       * would overwrite the scoreboard with the NOOP state; admins probably
1132
       * want to see the command that caused the data transfer.  And since
1133
       * NOOP doesn't take a 450 response (as per RFC959), we will simply
1134
       * return 200.
1135
       */
1136
      } else if (pr_cmd_cmp(cmd, PR_CMD_NOOP_ID) == 0) {
5✔
1137
        pool *resp_pool;
1138

1139
        pr_trace_msg(trace_channel, 5,
2✔
1140
          "client sent '%s' command during data transfer, ignoring",
1141
          (char *) cmd->argv[0]);
2✔
1142

1143
        resp_list = resp_err_list = NULL;
2✔
1144
        resp_pool = pr_response_get_pool();
2✔
1145

1146
        pr_response_set_pool(cmd->pool);
2✔
1147

1148
        pr_response_add(R_200, _("%s: data transfer in progress"),
2✔
1149
          (char *) cmd->argv[0]);
2✔
1150

1151
        pr_response_flush(&resp_list);
2✔
1152

1153
        pr_response_set_pool(resp_pool);
2✔
1154
        destroy_pool(cmd->pool);
2✔
1155

1156
      } else {
1157
        char *title_buf = NULL;
3✔
1158
        int curr_cmd_id = 0, title_len = -1;
3✔
1159
        const char *curr_cmd = NULL, *sce_cmd = NULL, *sce_cmd_arg = NULL;
3✔
1160
        cmd_rec *curr_cmd_rec = NULL;
3✔
1161
        pool *resp_pool;
1162

1163
        pr_trace_msg(trace_channel, 5,
3✔
1164
          "client sent '%s' command during data transfer, dispatching",
1165
          (char *) cmd->argv[0]);
3✔
1166

1167
        title_len = pr_proctitle_get(NULL, 0);
3✔
1168
        if (title_len > 0) {
3✔
1169
          title_buf = pcalloc(cmd->pool, title_len + 1);
×
1170
          pr_proctitle_get(title_buf, title_len + 1);
×
1171
        }
1172

1173
        curr_cmd = session.curr_cmd;
3✔
1174
        curr_cmd_id = session.curr_cmd_id;
3✔
1175
        curr_cmd_rec = session.curr_cmd_rec;
3✔
1176
        sce_cmd = pr_scoreboard_entry_get(PR_SCORE_CMD);
3✔
1177
        sce_cmd_arg = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG);
3✔
1178

1179
        resp_list = resp_err_list = NULL;
3✔
1180
        resp_pool = pr_response_get_pool();
3✔
1181

1182
        pr_response_set_pool(cmd->pool);
3✔
1183
        pr_cmd_dispatch(cmd);
3✔
1184

1185
        pr_scoreboard_entry_update(session.pid,
3✔
1186
          PR_SCORE_CMD, "%s", sce_cmd, NULL, NULL);
1187
        pr_scoreboard_entry_update(session.pid,
3✔
1188
          PR_SCORE_CMD_ARG, "%s", sce_cmd_arg, NULL, NULL);
1189

1190
        if (title_len > 0) {
3✔
1191
          pr_proctitle_set_str(title_buf);
×
1192
        }
1193

1194
        pr_response_flush(&resp_list);
3✔
1195
        pr_response_set_pool(resp_pool);
3✔
1196
        destroy_pool(cmd->pool);
3✔
1197

1198
        session.curr_cmd = curr_cmd;
3✔
1199
        session.curr_cmd_id = curr_cmd_id;
3✔
1200
        session.curr_cmd_rec = curr_cmd_rec;
3✔
1201
      }
1202

1203
    } else {
1204
      pr_trace_msg(trace_channel, 3,
7✔
1205
        "invalid command sent, sending error response");
1206
      pr_response_send(R_500, _("Invalid command: try being more creative"));
7✔
1207
    }
1208
  }
1209
}
1210

1211
/* pr_data_xfer() actually transfers the data on the data connection.  ASCII
1212
 * translation is performed if necessary.  `direction' is set when the data
1213
 * connection was opened.
1214
 *
1215
 * We determine if the client buffer is read from or written to.  Returns 0 if
1216
 * reading and data connection closes, or -1 if error (with errno set).
1217
 */
1218
int pr_data_xfer(char *cl_buf, size_t cl_size) {
34✔
1219
  int len = 0;
34✔
1220
  int total = 0;
34✔
1221
  int res = 0;
34✔
1222
  pool *tmp_pool = NULL;
34✔
1223

1224
  if (cl_buf == NULL ||
68✔
1225
      cl_size == 0) {
34✔
1226
    errno = EINVAL;
8✔
1227
    return -1;
8✔
1228
  }
1229

1230
  /* Poll the control channel for any commands we should handle, like
1231
   * QUIT or ABOR.
1232
   */
1233
  poll_ctrl();
26✔
1234

1235
  /* If we don't have a data connection here (e.g. might have been closed
1236
   * by an ABOR), then return zero (no data transferred).
1237
   */
1238
  if (session.d == NULL) {
26✔
1239
    int xerrno;
1240

1241
#if defined(ECONNABORTED)
1242
    xerrno = ECONNABORTED;
4✔
1243
#elif defined(ENOTCONN)
1244
    xerrno = ENOTCONN;
1245
#else
1246
    xerrno = EIO;
1247
#endif
1248

1249
    pr_trace_msg(trace_channel, 1,
4✔
1250
      "data connection is null prior to data transfer (possibly from "
1251
      "aborted transfer), returning '%s' error", strerror(xerrno));
1252
    pr_log_debug(DEBUG5,
4✔
1253
      "data connection is null prior to data transfer (possibly from "
1254
       "aborted transfer), returning '%s' error", strerror(xerrno));
1255

1256
    errno = xerrno;
4✔
1257
    return -1;
4✔
1258
  }
1259

1260
  if (session.xfer.direction == PR_NETIO_IO_RD) {
22✔
1261
    char *buf;
1262

1263
    buf = session.xfer.buf;
12✔
1264

1265
    /* We use ASCII translation if:
1266
     *
1267
     * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
1268
     */
1269
    if (((session.sf_flags & SF_ASCII) &&
19✔
1270
        !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
7✔
1271
      int adjlen, buflen;
1272

1273
      do {
1274
        buflen = session.xfer.buflen;        /* how much remains in buf */
7✔
1275
        adjlen = 0;
7✔
1276

1277
        pr_signals_handle();
7✔
1278

1279
        len = pr_netio_read(session.d->instrm, buf + buflen,
7✔
1280
          session.xfer.bufsize - buflen, 1);
7✔
1281
        while (len < 0) {
7✔
1282
          int xerrno = errno;
1✔
1283

1284
          if (xerrno == EAGAIN || xerrno == EINTR) {
1✔
1285
            /* Since our socket is in non-blocking mode, read(2) can return
1286
             * EAGAIN if there is no data yet for us.  Handle this by
1287
             * delaying temporarily, then trying again.
1288
             */
1289
            errno = EINTR;
×
1290
            pr_signals_handle();
×
1291

1292
            len = pr_netio_read(session.d->instrm, buf + buflen,
×
1293
              session.xfer.bufsize - buflen, 1);
×
1294
            continue;
×
1295
          }
1296

1297
          destroy_pool(tmp_pool);
1✔
1298
          errno = xerrno;
1✔
1299
          return -1;
1✔
1300
        }
1301

1302
        if (len > 0 &&
12✔
1303
            data_first_byte_read == FALSE) {
6✔
1304
          if (pr_trace_get_level(timing_channel)) {
2✔
1305
            unsigned long elapsed_ms;
1306
            uint64_t read_ms;
1307

1308
            pr_gettimeofday_millis(&read_ms);
2✔
1309
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
2✔
1310

1311
            pr_trace_msg(timing_channel, 7,
2✔
1312
              "Time for first data byte read: %lu ms", elapsed_ms);
1313
          }
1314

1315
          data_first_byte_read = TRUE;
2✔
1316
        }
1317

1318
        if (len > 0) {
6✔
1319
          pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
6✔
1320
            len != 1 ? "bytes" : "byte");
1321

1322
          buflen += len;
6✔
1323

1324
          if (timeout_stalled) {
6✔
1325
            pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
6✔
1326
          }
1327
        }
1328

1329
        /* If buflen > 0, data remains in the buffer to be copied. */
1330
        if (len >= 0 &&
6✔
1331
            buflen > 0) {
6✔
1332

1333
          /* Perform ASCII translation:
1334
           *
1335
           * buflen: is returned as the modified buffer length after
1336
           *         translation
1337
           * res:    is returned as the number of characters unprocessed in
1338
           *         the buffer (to be dealt with later)
1339
           *
1340
           * We skip the call to pr_ascii_ftp_from_crlf() in one case:
1341
           * when we have one character in the buffer and have reached
1342
           * end of data, this is so that pr_ascii_ftp_from_crlf() won't sit
1343
           * forever waiting for the next character after a final '\r'.
1344
           */
1345
          if (len > 0 ||
12✔
1346
              buflen > 1) {
6✔
1347
            size_t outlen = 0;
6✔
1348

1349
            if (tmp_pool == NULL) {
6✔
1350
              tmp_pool = make_sub_pool(session.xfer.p);
6✔
1351
              pr_pool_tag(tmp_pool, "ASCII upload");
6✔
1352
            }
1353

1354
            res = pr_ascii_ftp_from_crlf(tmp_pool, buf, buflen, &buf, &outlen);
6✔
1355
            if (res < 0) {
6✔
1356
              pr_trace_msg(trace_channel, 3, "error reading ASCII data: %s",
×
1357
                strerror(errno));
×
1358

1359
            } else {
1360
              adjlen += res;
6✔
1361
              buflen = (int) outlen;
6✔
1362
            }
1363
          }
1364

1365
          /* Now copy everything we can into cl_buf */
1366
          if ((size_t) buflen > cl_size) {
6✔
1367
            /* Because we have to cut our buffer short, make sure this
1368
             * is made up for later by increasing adjlen.
1369
             */
1370
            adjlen += (buflen - cl_size);
×
1371
            buflen = cl_size;
×
1372
          }
1373

1374
          memcpy(cl_buf, buf, buflen);
12✔
1375

1376
          /* Copy whatever remains at the end of session.xfer.buf to the
1377
           * head of the buffer and adjust buf accordingly.
1378
           *
1379
           * adjlen is now the total bytes still waiting in buf, if
1380
           * anything remains, copy it to the start of the buffer.
1381
           */
1382

1383
          if (adjlen > 0) {
6✔
1384
            memcpy(buf, buf + buflen, adjlen);
1✔
1385
          }
1386

1387
          /* Store everything back in session.xfer. */
1388
          session.xfer.buflen = adjlen;
6✔
1389
          total += buflen;
6✔
1390
        }
1391
        
1392
        /* Restart if data was returned by pr_netio_read() (len > 0) but no
1393
         * data was copied to the client buffer (buflen = 0).  This indicates
1394
         * that pr_ascii_ftp_from_crlf() needs more data in order to
1395
         * translate, so we need to call pr_netio_read() again.
1396
         */
1397
      } while (len > 0 && buflen == 0);
6✔
1398

1399
      /* Return how much data we actually copied into the client buffer. */
1400
      len = buflen;
1401

1402
    } else {
1403
      len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
5✔
1404
      while (len < 0) {
10✔
1405
        int xerrno = errno;
1✔
1406

1407
        if (xerrno == EAGAIN || xerrno == EINTR) {
1✔
1408
          /* Since our socket is in non-blocking mode, read(2) can return
1409
           * EAGAIN if there is no data yet for us.  Handle this by
1410
           * delaying temporarily, then trying again.
1411
           */
1412
          errno = EINTR;
×
1413
          pr_signals_handle();
×
1414

1415
          len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
×
1416
          continue;
×
1417
        }
1418

1419
        break;
1420
      }
1421

1422
      if (len > 0) {
5✔
1423
        pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
4✔
1424
          len != 1 ? "bytes" : "byte");
1425

1426
        if (data_first_byte_read == FALSE) {
4✔
1427
          if (pr_trace_get_level(timing_channel)) {
2✔
1428
            unsigned long elapsed_ms;
1429
            uint64_t read_ms;
1430

1431
            pr_gettimeofday_millis(&read_ms);
2✔
1432
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
2✔
1433

1434
            pr_trace_msg(timing_channel, 7,
2✔
1435
              "Time for first data byte read: %lu ms", elapsed_ms);
1436
          }
1437

1438
          data_first_byte_read = TRUE;
2✔
1439
        }
1440

1441
        /* Non-ASCII mode doesn't need to use session.xfer.buf */
1442
        if (timeout_stalled) {
4✔
1443
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
4✔
1444
        }
1445

1446
        total += len;
1447
      }
1448
    }
1449

1450
  } else { /* PR_NETIO_IO_WR */
1451

1452
    while (cl_size) {
18✔
1453
      int bwrote = 0;
10✔
1454
      int buflen = cl_size;
10✔
1455
      unsigned int xferbuflen;
1456
      char *xferbuf = NULL, *ascii_buf = NULL;
10✔
1457

1458
      pr_signals_handle();
10✔
1459

1460
      if (buflen > pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR)) {
10✔
1461
        buflen = pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR);
×
1462
      }
1463

1464
      xferbuf = cl_buf;
10✔
1465
      xferbuflen = buflen;
10✔
1466

1467
      /* We use ASCII translation if:
1468
       *
1469
       * - SF_ASCII_OVERRIDE session flag is set (e.g. for LIST/NLST)
1470
       * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
1471
       */
1472
      if ((session.sf_flags & SF_ASCII_OVERRIDE) ||
14✔
1473
          ((session.sf_flags & SF_ASCII) &&
5✔
1474
           !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
1✔
1475
        char *out = NULL;
7✔
1476
        size_t outlen = 0;
7✔
1477

1478
        if (tmp_pool == NULL) {
7✔
1479
          tmp_pool = make_sub_pool(session.xfer.p);
7✔
1480
          pr_pool_tag(tmp_pool, "ASCII download");
7✔
1481
        }
1482

1483
        /* Fill up our internal buffer. */
1484
        memcpy(session.xfer.buf, cl_buf, buflen);
14✔
1485

1486
        /* Scan the internal buffer, looking for LFs with no preceding CRs.
1487
         * Add CRs (and expand the internal buffer) as necessary. xferbuflen
1488
         * will be adjusted so that it contains the length of data in
1489
         * the internal buffer, including any added CRs.
1490
         */
1491
        res = pr_ascii_ftp_to_crlf(tmp_pool, session.xfer.buf, xferbuflen,
7✔
1492
          &out, &outlen);
1493
        if (res < 0) {
7✔
1494
          pr_trace_msg(trace_channel, 1, "error writing ASCII data: %s",
×
1495
            strerror(errno));
×
1496

1497
        } else {
1498
          ascii_buf = session.xfer.buf;
7✔
1499
          session.xfer.buf = out;
7✔
1500
          session.xfer.buflen = xferbuflen = outlen;
7✔
1501
        }
1502

1503
        xferbuf = session.xfer.buf;
7✔
1504
      }
1505

1506
      bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
10✔
1507
      while (bwrote < 0) {
10✔
1508
        int xerrno = errno;
4✔
1509

1510
        if (xerrno == EAGAIN ||
8✔
1511
            xerrno == EINTR) {
4✔
1512
          /* Since our socket may be in non-blocking mode, write(2) can return
1513
           * EAGAIN if there is not enough from for our data yet.  Handle
1514
           * this by delaying temporarily, then trying again.
1515
           */
1516
          errno = EINTR;
2✔
1517
          pr_signals_handle();
2✔
1518

1519
          bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
2✔
1520
          continue;
2✔
1521
        }
1522

1523
        destroy_pool(tmp_pool);
2✔
1524
        if (ascii_buf != NULL) {
2✔
1525
          /* Free up the malloc'd memory. */
1526
          free(session.xfer.buf);
1✔
1527
          session.xfer.buf = ascii_buf;
1✔
1528
        }
1529

1530
        errno = xerrno;
2✔
1531
        return -1;
2✔
1532
      }
1533

1534
      if (bwrote > 0) {
8✔
1535
        pr_trace_msg(trace_channel, 19, "wrote %d %s to network", bwrote,
8✔
1536
          bwrote != 1 ? "bytes" : "byte");
1537

1538
        if (data_first_byte_written == FALSE) {
8✔
1539
          if (pr_trace_get_level(timing_channel)) {
3✔
1540
            unsigned long elapsed_ms;
1541
            uint64_t write_ms;
1542

1543
            pr_gettimeofday_millis(&write_ms);
3✔
1544
            elapsed_ms = (unsigned long) (write_ms - data_start_ms);
3✔
1545

1546
            pr_trace_msg(timing_channel, 7,
3✔
1547
              "Time for first data byte written: %lu ms", elapsed_ms);
1548
          }
1549

1550
          data_first_byte_written = TRUE;
3✔
1551
        }
1552

1553
        if (timeout_stalled) {
8✔
1554
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
8✔
1555
        }
1556

1557
        cl_size -= buflen;
8✔
1558
        cl_buf += buflen;
8✔
1559
        total += buflen;
8✔
1560
      }
1561

1562
      if (ascii_buf != NULL) {
8✔
1563
        /* Yes, we are using malloc et al here, rather than the memory pools.
1564
         * See Bug#4352 for details.
1565
         */
1566
        free(session.xfer.buf);
6✔
1567
        session.xfer.buf = ascii_buf;
6✔
1568
      }
1569
    }
1570

1571
    len = total;
1572
  }
1573

1574
  if (total &&
19✔
1575
      timeout_idle) {
1576
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
18✔
1577
  }
1578

1579
  session.xfer.total_bytes += total;
19✔
1580
  session.total_bytes += total;
19✔
1581
  if (session.xfer.direction == PR_NETIO_IO_RD) {
19✔
1582
    session.total_bytes_in += total;
11✔
1583

1584
  } else {
1585
    session.total_bytes_out += total;
8✔
1586
  }
1587

1588
  destroy_pool(tmp_pool);
19✔
1589
  return (len < 0 ? -1 : len);
19✔
1590
}
1591

1592
#if defined(HAVE_SENDFILE)
1593
/* pr_data_sendfile() actually transfers the data on the data connection.
1594
 * ASCII translation is not performed.
1595
 * return 0 if reading and data connection closes, or -1 if error
1596
 */
1597
pr_sendfile_t pr_data_sendfile(int retr_fd, off_t *offset, off_t count) {
7✔
1598
  int flags, error;
1599
  pr_sendfile_t len = 0, total = 0;
7✔
1600
# if defined(HAVE_AIX_SENDFILE)
1601
  struct sf_parms parms;
1602
  int rc;
1603
# endif /* HAVE_AIX_SENDFILE */
1604

1605
  if (offset == NULL ||
14✔
1606
      count == 0) {
7✔
1607
    errno = EINVAL;
3✔
1608
    return -1;
3✔
1609
  }
1610

1611
  if (session.xfer.direction == PR_NETIO_IO_RD) {
4✔
1612
    errno = EPERM;
1✔
1613
    return -1;
1✔
1614
  }
1615

1616
  if (session.d == NULL) {
3✔
1617
    errno = EPERM;
1✔
1618
    return -1;
1✔
1619
  }
1620

1621
  flags = fcntl(PR_NETIO_FD(session.d->outstrm), F_GETFL);
2✔
1622
  if (flags < 0) {
2✔
1623
    return -1;
1624
  }
1625

1626
  /* Set fd to blocking-mode for sendfile() */
1627
  if (flags & O_NONBLOCK) {
2✔
1628
    if (fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags^O_NONBLOCK) < 0) {
×
1629
      return -1;
1630
    }
1631
  }
1632

1633
  for (;;) {
1634
# if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_SOLARIS_SENDFILE)
1635
    off_t orig_offset = *offset;
2✔
1636

1637
    /* Linux semantics are fairly straightforward in a glibc 2.x world:
1638
     *
1639
     *   #include <sys/sendfile.h>
1640
     *
1641
     *   ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
1642
     *
1643
     * Unfortunately, this API does not allow for an off_t number of bytes
1644
     * to be sent, only a size_t.  This means we need to make sure that
1645
     * the given count does not exceed the maximum value for a size_t.  Even
1646
     * worse, the return value is a ssize_t, not a size_t, which means
1647
     * the maximum value used can only be of the maximum _signed_ value,
1648
     * not the maximum unsigned value.  This means calling sendfile() more
1649
     * times.  How annoying.
1650
     */
1651

1652
#  if defined(HAVE_LINUX_SENDFILE)
1653
    if (count > INT_MAX) {
2✔
1654
      count = INT_MAX;
×
1655
    }
1656
#  elif defined(HAVE_SOLARIS_SENDFILE)
1657
#   if SIZEOF_SIZE_T == SIZEOF_INT
1658
    if (count > INT_MAX) {
1659
      count = INT_MAX;
1660
    }
1661
#   elif SIZEOF_SIZE_T == SIZEOF_LONG
1662
    if (count > LONG_MAX) {
1663
      count = LONG_MAX;
1664
    }
1665
#   elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
1666
    if (count > LLONG_MAX) {
1667
      count = LLONG_MAX;
1668
    }
1669
#   endif
1670
#  endif /* !HAVE_SOLARIS_SENDFILE */
1671

1672
    errno = 0;
2✔
1673
    len = sendfile(PR_NETIO_FD(session.d->outstrm), retr_fd, offset, count);
2✔
1674

1675
    /* If no data could be written (e.g. the file was truncated), we're
1676
     * done (Bug#4318).
1677
     */
1678
    if (len == 0) {
2✔
1679
      if (errno != EINTR &&
×
1680
          errno != EAGAIN) {
1681
        break;
1682
      }
1683

1684
      /* Handle our interrupting signal, and continue. */
1685
      pr_signals_handle();
×
1686
    }
1687

1688
    if (len != -1 &&
4✔
1689
        len < count) {
2✔
1690
      /* Under Linux semantics, this occurs when a signal has interrupted
1691
       * sendfile().
1692
       */
1693
      if (XFER_ABORTED) {
×
1694
        errno = EINTR;
×
1695

1696
        session.xfer.total_bytes += len;
×
1697
        session.total_bytes += len;
×
1698
        session.total_bytes_out += len;
×
1699
        session.total_raw_out += len;
×
1700

1701
        return -1;
×
1702
      }
1703

1704
      count -= len;
×
1705

1706
      /* Only reset the timers if data have actually been written out. */
1707
      if (len > 0) {
×
1708
        if (timeout_stalled) {
×
1709
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
×
1710
        }
1711

1712
        if (timeout_idle) {
×
1713
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
×
1714
        }
1715
      }
1716

1717
      session.xfer.total_bytes += len;
×
1718
      session.total_bytes += len;
×
1719
      session.total_bytes_out += len;
×
1720
      session.total_raw_out += len;
×
1721
      total += len;
×
1722

1723
      pr_signals_handle();
×
1724
      continue;
×
1725
    }
1726

1727
    if (len == -1) {
2✔
1728
      /* Linux updates offset on error, not len like BSD, fix up so
1729
       * BSD-based code works.
1730
       */
1731
      len = *offset - orig_offset;
1✔
1732
      *offset = orig_offset;
1✔
1733

1734
# elif defined(HAVE_BSD_SENDFILE)
1735
    /* BSD semantics for sendfile are flexible...it'd be nice if we could
1736
     * standardize on something like it.  The semantics are:
1737
     *
1738
     *   #include <sys/types.h>
1739
     *   #include <sys/socket.h>
1740
     *   #include <sys/uio.h>
1741
     *
1742
     *   int sendfile(int in_fd, int out_fd, off_t offset, size_t count,
1743
     *                struct sf_hdtr *hdtr, off_t *len, int flags)
1744
     *
1745
     *  The comments above, about size_t versus off_t, apply here as
1746
     *  well.  Except that BSD's sendfile() uses an off_t * for returning
1747
     *  the number of bytes sent, so we can use the maximum unsigned
1748
     *  value.
1749
     */
1750

1751
#  if SIZEOF_SIZE_T == SIZEOF_INT
1752
    if (count > UINT_MAX) {
1753
      count = UINT_MAX;
1754
    }
1755
#  elif SIZEOF_SIZE_T == SIZEOF_LONG
1756
    if (count > ULONG_MAX) {
1757
      count = ULONG_MAX;
1758
    }
1759
#  elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
1760
    if (count > ULLONG_MAX) {
1761
      count = ULLONG_MAX;
1762
    }
1763
#  endif
1764

1765
    if (sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, count,
1766
        NULL, &len, 0) == -1) {
1767

1768
# elif defined(HAVE_MACOSX_SENDFILE)
1769
    off_t orig_len = count;
1770
    int res;
1771

1772
    /* Since Mac OSX uses the fourth argument as a value-return parameter,
1773
     * success or failure, we need to put the result into len after the
1774
     * call.
1775
     */
1776

1777
    res = sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, &orig_len,
1778
      NULL, 0);
1779
    len = orig_len;
1780

1781
    if (res < 0) {
1782
# elif defined(HAVE_AIX_SENDFILE)
1783

1784
    memset(&parms, 0, sizeof(parms));
1785

1786
    parms.file_descriptor = retr_fd;
1787
    parms.file_offset = (uint64_t) *offset;
1788
    parms.file_bytes = (int64_t) count;
1789

1790
    rc = send_file(&(PR_NETIO_FD(session.d->outstrm)), &(parms), (uint_t)0);
1791
    len = (int) parms.bytes_sent;
1792

1793
    if (rc < -1 || rc == 1) {
1794
# else
1795
    if (FALSE) {
1796
# endif /* HAVE_AIX_SENDFILE */
1797

1798
      /* IMO, BSD's semantics are warped.  Apparently, since we have our
1799
       * alarms tagged SA_INTERRUPT (allowing system calls to be
1800
       * interrupted - primarily for select), BSD will interrupt a
1801
       * sendfile operation as well, so we have to catch and handle this
1802
       * case specially.  It should also be noted that the sendfile(2) man
1803
       * page doesn't state any of this.
1804
       *
1805
       * HP/UX has the same semantics, however, EINTR is well documented
1806
       * as a side effect in the sendfile(2) man page.  HP/UX, however,
1807
       * is implemented horribly wrong.  If a signal would result in
1808
       * -1 being returned and EINTR being set, what ACTUALLY happens is
1809
       * that errno is cleared and the number of bytes written is returned.
1810
       *
1811
       * For obvious reasons, HP/UX sendfile is not supported yet.
1812
       */
1813
      if (errno == EINTR) {
1✔
1814
        if (XFER_ABORTED) {
×
1815
          session.xfer.total_bytes += len;
×
1816
          session.total_bytes += len;
×
1817
          session.total_bytes_out += len;
×
1818
          session.total_raw_out += len;
×
1819

1820
          return -1;
×
1821
        }
1822

1823
        pr_signals_handle();
×
1824

1825
        /* If we got everything in this transaction, we're done. */
1826
        if (len >= count) {
×
1827
          break;
1828
        }
1829

1830
        count -= len;
×
1831
        *offset += len;
×
1832

1833
        if (timeout_stalled) {
×
1834
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
×
1835
        }
1836

1837
        if (timeout_idle) {
×
1838
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
×
1839
        }
1840

1841
        session.xfer.total_bytes += len;
×
1842
        session.total_bytes += len;
×
1843
        session.total_bytes_out += len;
×
1844
        session.total_raw_out += len;
×
1845
        total += len;
×
1846

1847
        continue;
×
1848
      }
1849

1850
      error = errno;
1✔
1851
      (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
1✔
1852
      errno = error;
1✔
1853

1854
      return -1;
1✔
1855
    }
1856

1857
    break;
1858
  }
1859

1860
  if (flags & O_NONBLOCK) {
1✔
1861
    (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
×
1862
  }
1863

1864
  if (timeout_stalled) {
1✔
1865
    pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1✔
1866
  }
1867

1868
  if (timeout_idle) {
1✔
1869
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1✔
1870
  }
1871

1872
  session.xfer.total_bytes += len;
1✔
1873
  session.total_bytes += len;
1✔
1874
  session.total_bytes_out += len;
1✔
1875
  session.total_raw_out += len;
1✔
1876
  total += len;
1✔
1877

1878
  return total;
1✔
1879
}
1880
#else
1881
pr_sendfile_t pr_data_sendfile(int retr_fd, off_t *offset, off_t count) {
1882
  errno = ENOSYS;
1883
  return -1;
1884
}
1885
#endif /* HAVE_SENDFILE */
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