コード例 #1
0
ファイル: inet.c プロジェクト: netdna/proftpd
/* Copy a connection structure, also creates a sub pool for the new
 * connection.
 */
conn_t *pr_inet_copy_conn(pool *p, conn_t *c) {
  conn_t *res = NULL;
  pool *sub_pool = NULL;

  if (p == NULL ||
      c == NULL) {
    errno = EINVAL;
    return NULL;
  }

  sub_pool = make_sub_pool(p);
  pr_pool_tag(sub_pool, "inet_copy_conn pool");

  res = (conn_t *) pcalloc(sub_pool, sizeof(conn_t));

  memcpy(res, c, sizeof(conn_t));
  res->pool = sub_pool;
  res->instrm = res->outstrm = NULL;

  if (c->local_addr) {
    res->local_addr = pr_netaddr_alloc(res->pool);

    if (pr_netaddr_set_family(res->local_addr,
        pr_netaddr_get_family(c->local_addr)) < 0) {
      destroy_pool(res->pool);
      return NULL;
    }

    pr_netaddr_set_sockaddr(res->local_addr,
      pr_netaddr_get_sockaddr(c->local_addr));
  }

  if (c->remote_addr) {
    res->remote_addr = pr_netaddr_alloc(res->pool);

    if (pr_netaddr_set_family(res->remote_addr,
        pr_netaddr_get_family(c->remote_addr)) < 0) {
      destroy_pool(res->pool);
      return NULL;
    }

    pr_netaddr_set_sockaddr(res->remote_addr,
      pr_netaddr_get_sockaddr(c->remote_addr));
  }

  if (c->remote_name) {
    res->remote_name = pstrdup(res->pool, c->remote_name);
  }

  register_cleanup(res->pool, (void *) res, conn_cleanup_cb, conn_cleanup_cb);
  return res;
}
コード例 #2
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
static int init_standalone_bindings(void) {
  int res = 0;
  server_rec *serv = NULL;
  unsigned char *default_server = NULL, is_default = FALSE;

  /* If a port is set to zero, the address/port is not bound to a socket
   * at all.
   */
  if (main_server->ServerPort) {

    /* If SocketBindTight is off, then pr_inet_create_conn() will
     * create and bind to a wildcard socket.  However, should it be an
     * IPv4 or an IPv6 wildcard socket?
     */
    if (!SocketBindTight) {
#ifdef PR_USE_IPV6
      if (pr_netaddr_use_ipv6()) {
        pr_inet_set_default_family(NULL, AF_INET6);

      } else {
        int default_family;

        default_family = pr_netaddr_get_family(main_server->addr);
        pr_inet_set_default_family(NULL, default_family);
      }
#else
      pr_inet_set_default_family(NULL,
        pr_netaddr_get_family(main_server->addr));
#endif /* PR_USE_IPV6 */
    }

    main_server->listen = pr_ipbind_get_listening_conn(main_server,
      (SocketBindTight ? main_server->addr : NULL), main_server->ServerPort);
    if (main_server->listen == NULL) {
      return -1;
    }

  } else {
    main_server->listen = NULL;
  }

  default_server = get_param_ptr(main_server->conf, "DefaultServer", FALSE);
  if (default_server != NULL &&
      *default_server == TRUE) {
    is_default = TRUE;
  }

  if (main_server->ServerPort ||
      is_default) {
    PR_CREATE_IPBIND(main_server, main_server->addr, main_server->ServerPort);
    PR_OPEN_IPBIND(main_server->addr, main_server->ServerPort,
      main_server->listen, is_default, TRUE, TRUE);
    PR_ADD_IPBINDS(main_server);
  }

  for (serv = main_server->next; serv; serv = serv->next) {
    config_rec *c;
    int is_namebind = FALSE;

    /* See if this server is a namebind, to be part of an existing ipbind. */
    c = find_config(serv->conf, CONF_PARAM, "ServerAlias", FALSE);
    while (c != NULL) {
      pr_signals_handle();

      res = pr_namebind_create(serv, c->argv[0], serv->addr, serv->ServerPort);
      if (res == 0) {
        is_namebind = TRUE;

        res = pr_namebind_open(c->argv[0], serv->addr, serv->ServerPort);
        if (res < 0) {
          pr_log_pri(PR_LOG_NOTICE,
            "%s:%d: notice: unable to open namebind '%s': %s", __FILE__,
            __LINE__, (char *) c->argv[0], strerror(errno));
        }

      } else {
        pr_log_pri(PR_LOG_NOTICE,
          "unable to create namebind for '%s' to %s#%u: %s",
          (char *) c->argv[0], pr_netaddr_get_ipstr(serv->addr),
          serv->ServerPort, strerror(errno));
      }

      c = find_config_next(c, c->next, CONF_PARAM, "ServerAlias", FALSE);
    }

    if (is_namebind == TRUE) {
      continue;
    }

    if (serv->ServerPort != main_server->ServerPort ||
        SocketBindTight ||
        !main_server->listen) {
      is_default = FALSE;

      default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
      if (default_server != NULL &&
          *default_server == TRUE) {
        is_default = TRUE;
      }

      if (serv->ServerPort) {
        if (!SocketBindTight) {
#ifdef PR_USE_IPV6
          if (pr_netaddr_use_ipv6()) {
            pr_inet_set_default_family(NULL, AF_INET6);

          } else {
            pr_inet_set_default_family(NULL, pr_netaddr_get_family(serv->addr));
          }
#else
          pr_inet_set_default_family(NULL, pr_netaddr_get_family(serv->addr));
#endif /* PR_USE_IPV6 */
        }

        serv->listen = pr_ipbind_get_listening_conn(serv,
          (SocketBindTight ? serv->addr : NULL), serv->ServerPort);
        if (serv->listen == NULL) {
          return -1;
        }

        PR_CREATE_IPBIND(serv, serv->addr, serv->ServerPort);
        PR_OPEN_IPBIND(serv->addr, serv->ServerPort, serv->listen, is_default,
          FALSE, TRUE);
        PR_ADD_IPBINDS(serv);

      } else if (is_default) {
        serv->listen = NULL;

        PR_CREATE_IPBIND(serv, serv->addr, serv->ServerPort);
        PR_OPEN_IPBIND(serv->addr, serv->ServerPort, serv->listen, is_default,
          FALSE, TRUE);
        PR_ADD_IPBINDS(serv);

      } else {
        serv->listen = NULL;
      }

    } else {
      /* Because this server is sharing the connection with the main server,
       * we need a cleanup handler to remove the server's reference when the
       * original connection's pool is destroyed.
       */

      is_default = FALSE;
      default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
      if (default_server != NULL &&
          *default_server == TRUE) {
        is_default = TRUE;
      }

      serv->listen = main_server->listen;
      register_cleanup(serv->listen->pool, &serv->listen, server_cleanup_cb,
        server_cleanup_cb);

      PR_CREATE_IPBIND(serv, serv->addr, serv->ServerPort);
      PR_OPEN_IPBIND(serv->addr, serv->ServerPort, NULL, is_default, FALSE,
        TRUE);
      PR_ADD_IPBINDS(serv);
    }
  }

  /* Any "unclaimed" listening conns can be removed and closed. */
  if (listening_conn_list) {
    struct listener_rec *lr, *lrn;

    for (lr = (struct listener_rec *) listening_conn_list->xas_list; lr; lr = lrn) {
      lrn = lr->next;

      if (!lr->claimed) {
        xaset_remove(listening_conn_list, (xasetmember_t *) lr);
        destroy_pool(lr->pool);
      }
    }
  }

  return 0;
}
コード例 #3
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
static int init_inetd_bindings(void) {
  int res = 0;
  server_rec *serv = NULL;
  unsigned char *default_server = NULL, is_default = FALSE;

  /* We explicitly do NOT use the get_listening_conn() function here, since
   * inetd-run daemons will not a) handle restarts, and thus b) will not have
   * already-open connections to choose from.
   */

  main_server->listen = pr_inet_create_conn(main_server->pool, STDIN_FILENO,
    NULL, INPORT_ANY, FALSE);
  if (main_server->listen == NULL) {
    return -1;
  }

  /* Note: Since we are being called via inetd/xinetd, any socket options
   * which may be attempted by listeners for this event may not work.
   */
  pr_inet_generate_socket_event("core.ctrl-listen", main_server,
    main_server->addr, main_server->listen->listen_fd);

  /* Fill in all the important connection information. */
  if (pr_inet_get_conn_info(main_server->listen, STDIN_FILENO) == -1) {
    int xerrno = errno;

    pr_log_pri(PR_LOG_WARNING, "fatal: unable to get connection info: %s",
      strerror(xerrno));

    if (xerrno == ENOTSOCK) {
      pr_log_pri(PR_LOG_ERR, "(Running from command line? "
        "Use `ServerType standalone' in config file!)");
    }

    exit(1);
  }

  default_server = get_param_ptr(main_server->conf, "DefaultServer", FALSE);
  if (default_server != NULL &&
      *default_server == TRUE) {
    is_default = TRUE;
  }

  PR_CREATE_IPBIND(main_server, main_server->addr, main_server->ServerPort);
  PR_OPEN_IPBIND(main_server->addr, main_server->ServerPort,
    main_server->listen, is_default, TRUE, TRUE);
  PR_ADD_IPBINDS(main_server);

  /* Now attach the faked connection to all virtual servers. */
  for (serv = main_server->next; serv; serv = serv->next) {

    /* Because this server is sharing the connection with the
     * main server, we need a cleanup handler to remove
     * the server's reference when the original connection's
     * pool is destroyed.
     */

    serv->listen = main_server->listen;
    register_cleanup(serv->listen->pool, &serv->listen, server_cleanup_cb,
      server_cleanup_cb);

    is_default = FALSE;
    default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
    if (default_server != NULL &&
        *default_server == TRUE) {
      is_default = TRUE;
    }

    PR_CREATE_IPBIND(serv, serv->addr, serv->ServerPort);
    PR_OPEN_IPBIND(serv->addr, serv->ServerPort, serv->listen, is_default,
      FALSE, TRUE);
    PR_ADD_IPBINDS(serv);
  }

  return 0;
}