Exemple #1
0
END_TEST

START_TEST (inet_set_socket_opts_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;
  struct tcp_keepalive keepalive;

  res = pr_inet_set_socket_opts(NULL, NULL, 1, 2, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_set_socket_opts(p, conn, 1, 2, NULL);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  res = pr_inet_set_socket_opts(p, conn, INT_MAX, INT_MAX, NULL);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  keepalive.keepalive_enabled = 1;
  keepalive.keepalive_idle = 1;
  keepalive.keepalive_count = 2;
  keepalive.keepalive_intvl = 3;
  res = pr_inet_set_socket_opts(p, conn, 1, 2, &keepalive);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  pr_inet_close(p, conn);
}
Exemple #2
0
END_TEST

START_TEST (inet_set_socket_opts_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  res = pr_inet_set_socket_opts(NULL, NULL, 1, 2, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_set_socket_opts(p, conn, 1, 2, NULL);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  pr_inet_close(p, conn);
}
Exemple #3
0
static int data_active_open(char *reason, off_t size) {
  conn_t *c;
  int rev;
  pr_netaddr_t *bind_addr;

  if (!reason && session.xfer.filename)
    reason = session.xfer.filename;

  if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(session.c->remote_addr)) {
    bind_addr = session.c->local_addr;

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

  session.d = pr_inet_create_conn(session.pool, -1, bind_addr,
    session.c->local_port-1, TRUE);

  /* Set the "stalled" timer, if any, to prevent the connection
   * open from taking too long
   */
  if (timeout_stalled) {
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
      "TimeoutStalled");
  }

  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);

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

  if (session.xfer.direction == PR_NETIO_IO_RD) {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
    
  } else {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
  }

  /* Make sure that the necessary socket options are set on the socket prior
   * to the call to connect(2).
   */
  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
    IPTOS_THROUGHPUT, 1);
  pr_inet_generate_socket_event("core.data-connect", main_server,
    session.d->local_addr, session.d->listen_fd);

  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
      session.data_port) == -1) {
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
      strerror(session.d->xerrno));
    destroy_pool(session.d->pool);
    session.d = NULL;
    return -1;
  }

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

  pr_netaddr_set_reverse_dns(rev);

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

    if (session.xfer.xfer_type != STOR_UNIQUE) {
      if (size)
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
          "(%" PR_LU " bytes)"), MODE_STRING, reason, (pr_off_t) size);
      else
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
          MODE_STRING, reason);

    } else {

      /* Format of 150 responses for STOU is explicitly dictated by
       * RFC 1123:
       *
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
       *
       *    The STOU command stores into a uniquely named file.  When it
       *    receives an STOU command, a Server-FTP MUST return the
       *    actual file name in the "125 Transfer Starting" or the "150
       *    Opening Data Connection" message that precedes the transfer
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
       *    exact format of these messages is hereby defined to be as
       *    follows:
       *
       *        125 FILE: pppp
       *        150 FILE: pppp
       *
       *    where pppp represents the unique pathname of the file that
       *    will be written.
       */
      pr_response_send(R_150, "FILE: %s", reason);
    }

    pr_inet_close(session.pool, session.d);
    pr_inet_set_nonblock(session.pool, session.d);
    session.d = c;
    return 0;
  }

  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
    strerror(session.d->xerrno));
  destroy_pool(session.d->pool);
  session.d = NULL;
  return -1;
}
Exemple #4
0
static int data_pasv_open(char *reason, off_t size) {
  conn_t *c;
  int rev;

  if (!reason && session.xfer.filename)
    reason = session.xfer.filename;

  /* Set the "stalled" timer, if any, to prevent the connection
   * open from taking too long
   */
  if (timeout_stalled) {
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
      "TimeoutStalled");
  }

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

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

  if (session.xfer.direction == PR_NETIO_IO_RD) {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);

  } else {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
  }

  c = pr_inet_accept(session.pool, session.d, session.c, -1, -1, TRUE);
  pr_netaddr_set_reverse_dns(rev);

  if (c && c->mode != CM_ERROR) {
    pr_inet_close(session.pool, session.d);
    pr_inet_set_nonblock(session.pool, c);
    session.d = c;

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

    if (session.xfer.xfer_type != STOR_UNIQUE) {
      if (size) {
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
          "(%" PR_LU " bytes)"), MODE_STRING, reason, (pr_off_t) size);

      } else {
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
          MODE_STRING, reason);
      }

    } else {

      /* Format of 150 responses for STOU is explicitly dictated by
       * RFC 1123:
       *
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
       *
       *    The STOU command stores into a uniquely named file.  When it
       *    receives an STOU command, a Server-FTP MUST return the
       *    actual file name in the "125 Transfer Starting" or the "150
       *    Opening Data Connection" message that precedes the transfer
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
       *    exact format of these messages is hereby defined to be as
       *    follows:
       *
       *        125 FILE: pppp
       *        150 FILE: pppp
       *
       *    where pppp represents the unique pathname of the file that
       *    will be written.
       */
      pr_response_send(R_150, "FILE: %s", reason);
    }

    return 0;
  }

  /* Check for error conditions. */
  if (c && c->mode == CM_ERROR)
    pr_log_pri(PR_LOG_ERR, "Error: unable to accept an incoming data "
      "connection (%s)", strerror(c->xerrno));

  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
    strerror(session.d->xerrno));
  destroy_pool(session.d->pool);
  session.d = NULL;
  return -1;
}
Exemple #5
0
static int data_active_open(char *reason, off_t size) {
  conn_t *c;
  int bind_port, rev;
  pr_netaddr_t *bind_addr;
  unsigned char *root_revoke = NULL;

  if (!reason && session.xfer.filename)
    reason = session.xfer.filename;

  if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(session.c->remote_addr)) {
    bind_addr = session.c->local_addr;

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

  /* Default source port to which to bind for the active transfer, as
   * per RFC959.
   */
  bind_port = session.c->local_port-1;

  /* A RootRevoke value of 0 indicates 'false', 1 indicates 'true', and
   * 2 indicates 'NonCompliantActiveTransfer'.  We change the source port for
   * a RootRevoke value of 2.
   */
  root_revoke = get_param_ptr(TOPLEVEL_CONF, "RootRevoke", FALSE);
  if (root_revoke != NULL &&
      *root_revoke == 2) {
    bind_port = INPORT_ANY;
  }

  session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);

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

    pr_netaddr_set_family(&session.data_addr, pr_netaddr_get_family(session.c->remote_addr));
    pr_netaddr_set_sockaddr(&session.data_addr, pr_netaddr_get_sockaddr(session.c->remote_addr));
  }

  /* Set the "stalled" timer, if any, to prevent the connection
   * open from taking too long
   */
  if (timeout_stalled) {
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
      "TimeoutStalled");
  }

  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);

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

  if (session.xfer.direction == PR_NETIO_IO_RD) {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
      main_server->tcp_keepalive);
    
  } else {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
      main_server->tcp_keepalive);
  }

  /* Make sure that the necessary socket options are set on the socket prior
   * to the call to connect(2).
   */
  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
    IPTOS_THROUGHPUT, 1);
  pr_inet_generate_socket_event("core.data-connect", main_server,
    session.d->local_addr, session.d->listen_fd);

  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
      session.data_port) == -1) {
    pr_log_debug(DEBUG6,
      "Error connecting to %s#%u for active data transfer: %s",
      pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
      strerror(session.d->xerrno));
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
      strerror(session.d->xerrno));
    errno = session.d->xerrno;

    destroy_pool(session.d->pool);
    session.d = NULL;
    return -1;
  }

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

  pr_netaddr_set_reverse_dns(rev);

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

    if (session.xfer.xfer_type != STOR_UNIQUE) {
      if (size) {
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
          "(%" PR_LU " bytes)"), MODE_STRING, reason, (pr_off_t) size);

      } else {
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
          MODE_STRING, reason);
      }

    } else {

      /* Format of 150 responses for STOU is explicitly dictated by
       * RFC 1123:
       *
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
       *
       *    The STOU command stores into a uniquely named file.  When it
       *    receives an STOU command, a Server-FTP MUST return the
       *    actual file name in the "125 Transfer Starting" or the "150
       *    Opening Data Connection" message that precedes the transfer
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
       *    exact format of these messages is hereby defined to be as
       *    follows:
       *
       *        125 FILE: pppp
       *        150 FILE: pppp
       *
       *    where pppp represents the unique pathname of the file that
       *    will be written.
       */
      pr_response_send(R_150, "FILE: %s", reason);
    }

    pr_inet_close(session.pool, session.d);
    pr_inet_set_nonblock(session.pool, session.d);
    session.d = c;
    return 0;
  }

  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
    strerror(session.d->xerrno));
  errno = session.d->xerrno;

  destroy_pool(session.d->pool);
  session.d = NULL;
  return -1;
}