/* 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; }
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; }
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; }