Beispiel #1
0
int pr_ipbind_add_binds(server_rec *serv) {
  int res = 0;
  config_rec *c = NULL;
  conn_t *listen_conn = NULL;
  const pr_netaddr_t *addr = NULL;

  if (serv == NULL) {
    errno = EINVAL;
    return -1;
  }

  c = find_config(serv->conf, CONF_PARAM, "_bind_", FALSE);
  while (c != NULL) {
    listen_conn = NULL;

    pr_signals_handle();

    addr = pr_netaddr_get_addr(serv->pool, c->argv[0], NULL);
    if (addr == NULL) {
      pr_log_pri(PR_LOG_WARNING,
       "notice: unable to determine IP address of '%s'", (char *) c->argv[0]);
      c = find_config_next(c, c->next, CONF_PARAM, "_bind_", FALSE);
      continue;
    }

    /* If the SocketBindTight directive is in effect, create a separate
     * listen socket for this address, and add it to the binding list.
     */
    if (SocketBindTight &&
        serv->ServerPort) {
      listen_conn = pr_ipbind_get_listening_conn(serv, addr, serv->ServerPort);
      if (listen_conn == NULL) {
        return -1;
      }

      PR_CREATE_IPBIND(serv, addr, serv->ServerPort);
      PR_OPEN_IPBIND(addr, serv->ServerPort, listen_conn, FALSE, FALSE, TRUE);

    } else {

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

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

  return 0;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}