END_TEST START_TEST (inet_connect_ipv6_test) { #ifdef PR_USE_IPV6 int res; conn_t *conn; const pr_netaddr_t *addr; unsigned char use_ipv6; use_ipv6 = pr_netaddr_use_ipv6(); pr_netaddr_enable_ipv6(); pr_inet_set_default_family(p, AF_INET6); conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); addr = pr_netaddr_get_addr(p, "::1", NULL); fail_unless(addr != NULL, "Failed to resolve '::1': %s", strerror(errno)); mark_point(); res = proxy_inet_connect(p, conn, addr, 80); fail_unless(res < 0, "Connected to 127.0.0.1#80 unexpectedly"); fail_unless(errno == ECONNREFUSED || errno == ENETUNREACH, "Expected ECONNREFUSED (%d) or ENETUNREACH (%d), got %s (%d)", ECONNREFUSED, ENETUNREACH, strerror(errno), errno); proxy_inet_close(p, conn); /* Try connecting to Google's DNS server. */ conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); addr = pr_netaddr_get_addr(p, "2001:4860:4860::8888", NULL); fail_unless(addr != NULL, "Failed to resolve '2001:4860:4860::8888': %s", strerror(errno)); mark_point(); res = proxy_inet_connect(p, conn, addr, 53); if (res < 0) { /* This could be expected, e.g. if there's no route. */ fail_unless(errno == EHOSTUNREACH || errno == ENETUNREACH, "Expected EHOSTUNREACH (%d) or ENETUNREACH (%d), got %s (%d)", EHOSTUNREACH, ENETUNREACH, strerror(errno), errno); } mark_point(); proxy_inet_close(p, conn); pr_inet_set_default_family(p, AF_INET); if (use_ipv6 == FALSE) { pr_netaddr_disable_ipv6(); } #endif /* PR_USE_IPV6 */ }
END_TEST START_TEST (inet_set_proto_opts_ipv6_test) { #ifdef PR_USE_IPV6 int fd, sockfd = -1, port = INPORT_ANY, res; conn_t *conn; unsigned char use_ipv6; use_ipv6 = pr_netaddr_use_ipv6(); pr_netaddr_enable_ipv6(); pr_inet_set_default_family(p, AF_INET6); conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); mark_point(); res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1); fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno)); mark_point(); fd = conn->rfd; conn->rfd = 8; res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1); fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno)); conn->rfd = fd; mark_point(); fd = conn->wfd; conn->wfd = 9; res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1); fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno)); conn->wfd = fd; mark_point(); fd = conn->listen_fd; conn->listen_fd = 10; res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1); fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno)); conn->listen_fd = fd; pr_inet_close(p, conn); pr_inet_set_default_family(p, AF_INET); if (use_ipv6 == FALSE) { pr_netaddr_disable_ipv6(); } #endif /* PR_USE_IPV6 */ }
static void tear_down(void) { if (getenv("TEST_VERBOSE") != NULL) { pr_trace_set_levels("inet", 0, 0); } pr_inet_set_default_family(p, 0); pr_inet_clear(); if (p) { destroy_pool(p); p = permanent_pool = NULL; } }
static void set_up(void) { if (p == NULL) { p = permanent_pool = make_sub_pool(NULL); } init_netaddr(); init_netio(); init_inet(); if (getenv("TEST_VERBOSE") != NULL) { pr_trace_set_levels("inet", 1, 20); } pr_inet_set_default_family(p, AF_INET); }
END_TEST START_TEST (inet_connect_nowait_test) { int sockfd = -1, port = INPORT_ANY, res; conn_t *conn; const pr_netaddr_t *addr; res = pr_inet_connect_nowait(NULL, NULL, NULL, port); 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_connect_nowait(p, conn, NULL, 80); fail_unless(res < 0, "Failed to handle null address"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL); fail_unless(addr != NULL, "Failed to resolve '127.0.0.1': %s", strerror(errno)); res = pr_inet_connect_nowait(p, conn, addr, 80); fail_unless(res != -1, "Connected to 127.0.0.1#80 unexpectedly"); /* Try connecting to Google's DNS server. */ addr = pr_netaddr_get_addr(p, "8.8.8.8", NULL); fail_unless(addr != NULL, "Failed to resolve '8.8.8.8': %s", strerror(errno)); res = pr_inet_connect_nowait(p, conn, addr, 53); if (res < 0 && errno != ECONNREFUSED) { fail_unless(res != -1, "Failed to connect to 8.8.8.8#53: %s", strerror(errno)); } pr_inet_close(p, conn); /* Restore the default family to AF_INET, for other tests. */ pr_inet_set_default_family(p, AF_INET); }
static void tear_down(void) { if (getenv("TEST_VERBOSE") != NULL) { pr_trace_set_levels("netio", 0, 0); pr_trace_set_levels("inet", 0, 0); pr_trace_set_levels("proxy.ftp.conn", 0, 0); } pr_inet_set_default_family(p, 0); pr_inet_clear(); if (p) { destroy_pool(p); p = permanent_pool = session.pool = NULL; main_server = NULL; session.c = NULL; session.notes = NULL; } }
static void set_up(void) { if (p == NULL) { p = permanent_pool = session.pool = make_sub_pool(NULL); session.c = NULL; session.notes = NULL; } init_netaddr(); init_netio(); init_inet(); create_main_server(); if (getenv("TEST_VERBOSE") != NULL) { pr_trace_set_levels("netio", 1, 20); pr_trace_set_levels("inet", 1, 20); pr_trace_set_levels("proxy.ftp.conn", 1, 20); } pr_inet_set_default_family(p, AF_INET); }
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; }
END_TEST START_TEST (inet_connect_ipv6_test) { #ifdef PR_USE_IPV6 int sockfd = -1, port = INPORT_ANY, res; conn_t *conn; const pr_netaddr_t *addr; unsigned char use_ipv6; use_ipv6 = pr_netaddr_use_ipv6(); pr_netaddr_enable_ipv6(); pr_inet_set_default_family(p, AF_INET6); conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); addr = pr_netaddr_get_addr(p, "::1", NULL); fail_unless(addr != NULL, "Failed to resolve '::1': %s", strerror(errno)); res = pr_inet_connect(p, conn, addr, 80); fail_unless(res < 0, "Connected to ::1#80 unexpectedly"); fail_unless(errno == ECONNREFUSED || errno == ENETUNREACH, "Expected ECONNREFUSED (%d) or ENETUNREACH (%d), got %s (%d)", ECONNREFUSED, ENETUNREACH, strerror(errno), errno); /* Try connecting to Google's DNS server. */ addr = pr_netaddr_get_addr(p, "2001:4860:4860::8888", NULL); fail_unless(addr != NULL, "Failed to resolve '2001:4860:4860::8888': %s", strerror(errno)); res = pr_inet_connect(p, conn, addr, 53); if (res < 0) { /* Note: We get EINVAL here because the socket already tried (and failed) * to connect to a different address. Interestingly, trying to connect(2) * using that same fd to a different address yields EINVAL. */ fail_unless(errno == EINVAL || errno == ENETUNREACH, "Expected EINVAL (%d) or ENETUNREACH (%d), got %s (%d)", EINVAL, ENETUNREACH, strerror(errno), errno); } pr_inet_close(p, conn); conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); res = pr_inet_connect(p, conn, addr, 53); if (res < 0) { /* This could be expected, e.g. if there's no route. */ fail_unless(errno == EHOSTUNREACH || errno == ENETUNREACH, "Expected EHOSTUNREACH (%d) or ENETUNREACH (%d), got %s (%d)", EHOSTUNREACH, ENETUNREACH, strerror(errno), errno); } res = pr_inet_connect(p, conn, addr, 53); fail_unless(res < 0, "Failed to connect to 2001:4860:4860::8888#53: %s", strerror(errno)); fail_unless(errno == EISCONN || errno == EHOSTUNREACH || errno == ENETUNREACH, "Expected EISCONN (%d) or EHOSTUNREACH (%d) or ENETUNREACH (%d), " "got %s (%d)", EISCONN, EHOSTUNREACH, ENETUNREACH, strerror(errno), errno); pr_inet_close(p, conn); pr_inet_set_default_family(p, AF_INET); if (use_ipv6 == FALSE) { pr_netaddr_disable_ipv6(); } #endif /* PR_USE_IPV6 */ }