void init_bindings(void) { int res = 0; #ifdef PR_USE_IPV6 int sock; /* Check to see whether we can actually create an IPv6 socket. */ sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { pr_netaddr_disable_ipv6(); } else { (void) close(sock); } #endif /* PR_USE_IPV6 */ if (ServerType == SERVER_INETD) { res = init_inetd_bindings(); } else if (ServerType == SERVER_STANDALONE) { res = init_standalone_bindings(); } if (res < 0) { pr_log_pri(PR_LOG_ERR, "%s", "Unable to start proftpd; check logs for more details"); exit(1); } }
END_TEST START_TEST (netaddr_set_sockaddr_test) { pr_netaddr_t *addr; int res; struct sockaddr sa; const char *name; #ifdef PR_USE_IPV6 int family; #endif /* PR_USE_IPV6 */ res = pr_netaddr_set_sockaddr(NULL, NULL); fail_unless(res < 0, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); name = "127.0.0.1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); res = pr_netaddr_set_sockaddr(addr, NULL); fail_unless(res < 0, "Failed to handle null sockaddr"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); memset(&sa, 0, sizeof(sa)); res = pr_netaddr_set_sockaddr(addr, &sa); fail_unless(res == 0, "Failed to set sockaddr: %s", strerror(errno)); #ifdef PR_USE_IPV6 name = "::1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); res = pr_netaddr_set_sockaddr(addr, &sa); fail_unless(res == 0, "Failed to set sockaddr: %s", strerror(errno)); pr_netaddr_disable_ipv6(); res = pr_netaddr_set_sockaddr(addr, &sa); fail_unless(res < 0, "Set sockaddr unexpectedly"); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); pr_netaddr_enable_ipv6(); family = addr->na_family; addr->na_family = 777; res = pr_netaddr_set_sockaddr(addr, &sa); addr->na_family = family; fail_unless(res < 0, "Set sockaddr unexpectedly"); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); #endif /* PR_USE_IPV6 */ }
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 (netaddr_get_inaddr_test) { pr_netaddr_t *addr; int family; void *inaddr; const char *name; inaddr = pr_netaddr_get_inaddr(NULL); fail_unless(inaddr == NULL, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); family = AF_INET; name = "127.0.0.1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); inaddr = pr_netaddr_get_inaddr(addr); fail_unless(inaddr != NULL, "Failed to get inaddr: %s", strerror(errno)); #ifdef PR_USE_IPV6 family = AF_INET6; name = "::1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); inaddr = pr_netaddr_get_inaddr(addr); fail_unless(inaddr != NULL, "Failed to get inaddr: %s", strerror(errno)); pr_netaddr_disable_ipv6(); inaddr = pr_netaddr_get_inaddr(addr); fail_unless(inaddr == NULL, "Got inaddr unexpectedly"); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); pr_netaddr_enable_ipv6(); family = addr->na_family; addr->na_family = 777; inaddr = pr_netaddr_get_inaddr(addr); addr->na_family = family; fail_unless(inaddr == NULL, "Got inaddr unexpectedly"); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); #endif /* PR_USE_IPV6 */ }
END_TEST START_TEST (netaddr_get_sockaddr_len_test) { pr_netaddr_t *addr; size_t res; const char *name; #ifdef PR_USE_IPV6 int family; #endif /* PR_USE_IPV6 */ res = pr_netaddr_get_sockaddr_len(NULL); fail_unless(res == (size_t) -1, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); name = "127.0.0.1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); res = pr_netaddr_get_sockaddr_len(addr); fail_unless(res > 0, "Failed to get sockaddr len: %s", strerror(errno)); #ifdef PR_USE_IPV6 name = "::1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); res = pr_netaddr_get_sockaddr_len(addr); fail_unless(res > 0, "Failed to get sockaddr len: %s", strerror(errno)); pr_netaddr_disable_ipv6(); res = pr_netaddr_get_sockaddr_len(addr); fail_unless(res == (size_t) -1, "Got sockaddr len unexpectedly"); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); pr_netaddr_enable_ipv6(); family = addr->na_family; addr->na_family = 777; res = pr_netaddr_get_sockaddr_len(addr); addr->na_family = family; fail_unless(res == (size_t) -1, "Got sockaddr len unexpectedly"); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); #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 */ }
END_TEST START_TEST (netaddr_get_sockaddr_test) { pr_netaddr_t *addr; struct sockaddr *sockaddr; const char *name; #ifdef PR_USE_IPV6 int family; #endif /* PR_USE_IPV6 */ sockaddr = pr_netaddr_get_sockaddr(NULL); fail_unless(sockaddr == NULL, "Failed to handle null argument"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); name = "127.0.0.1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); sockaddr = pr_netaddr_get_sockaddr(addr); fail_unless(sockaddr != NULL, "Failed to get sock addr: %s", strerror(errno)); #ifdef PR_USE_IPV6 name = "::1"; addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); sockaddr = pr_netaddr_get_sockaddr(addr); fail_unless(sockaddr != NULL, "Failed to get sock addr: %s", strerror(errno)); pr_netaddr_disable_ipv6(); sockaddr = pr_netaddr_get_sockaddr(addr); fail_unless(sockaddr == NULL, "Got sock addr for IPv6 addr", strerror(errno)); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); pr_netaddr_enable_ipv6(); family = addr->na_family; addr->na_family = 777; sockaddr = pr_netaddr_get_sockaddr(addr); fail_unless(sockaddr == NULL, "Got sock addr for IPv6 addr", strerror(errno)); fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM, strerror(errno), errno); addr->na_family = family; #endif /* PR_USE_IPV6 */ }
static void tear_down(void) { if (getenv("TEST_VERBOSE") != NULL) { pr_trace_set_levels("proxy.ftp.msg", 0, 0); } if (use_ipv6 == FALSE) { pr_netaddr_disable_ipv6(); } if (p) { destroy_pool(p); p = permanent_pool = session.pool = NULL; session.c = NULL; session.notes = NULL; } }
END_TEST START_TEST (netaddr_disable_ipv6_test) { unsigned char use_ipv6; use_ipv6 = pr_netaddr_use_ipv6(); #ifdef PR_USE_IPV6 fail_unless(use_ipv6 == TRUE, "Expected %d, got %d", TRUE, use_ipv6); #else fail_unless(use_ipv6 == FALSE, "Expected %d, got %d", FALSE, use_ipv6); #endif pr_netaddr_disable_ipv6(); use_ipv6 = pr_netaddr_use_ipv6(); fail_unless(use_ipv6 == FALSE, "Expected %d, got %d", FALSE, use_ipv6); }
END_TEST START_TEST (parse_addr_test) { const pr_netaddr_t *res; const char *msg, *expected, *ip_str; res = proxy_ftp_msg_parse_addr(NULL, NULL, 0); fail_unless(res == NULL, "Failed to handle null pool"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); res = proxy_ftp_msg_parse_addr(p, NULL, 0); fail_unless(res == NULL, "Failed to handle null msg"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); msg = "foo"; res = proxy_ftp_msg_parse_addr(p, msg, 0); fail_unless(res == NULL, "Failed to handle invalid format"); fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM, strerror(errno), errno); msg = "(a,b,c,d,e,f)"; res = proxy_ftp_msg_parse_addr(p, msg, 0); fail_unless(res == NULL, "Failed to handle invalid format"); fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM, strerror(errno), errno); msg = "(1000,2000,3000,4000,5000,6000)"; res = proxy_ftp_msg_parse_addr(p, msg, 0); fail_unless(res == NULL, "Failed to handle invalid format"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); msg = "(1,2,3,4,5000,6000)"; res = proxy_ftp_msg_parse_addr(p, msg, 0); fail_unless(res == NULL, "Failed to handle invalid format"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); msg = "(0,0,0,0,1,2)"; res = proxy_ftp_msg_parse_addr(p, msg, 0); fail_unless(res == NULL, "Failed to handle invalid format"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); msg = "(1,2,3,4,0,0)"; res = proxy_ftp_msg_parse_addr(p, msg, 0); fail_unless(res == NULL, "Failed to handle invalid format"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); msg = "(127,0,0,1,8,73)"; res = proxy_ftp_msg_parse_addr(p, msg, 0); fail_unless(res != NULL, "Failed to parse message '%s': %s", msg, strerror(errno)); ip_str = pr_netaddr_get_ipstr(res); expected = "127.0.0.1"; fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'", expected, ip_str); fail_unless(ntohs(pr_netaddr_get_port(res)) == 2121, "Expected 2121, got %u", ntohs(pr_netaddr_get_port(res))); #ifdef PR_USE_IPV6 msg = "(127,0,0,1,8,73)"; res = proxy_ftp_msg_parse_addr(p, msg, AF_INET); fail_unless(res != NULL, "Failed to parse message '%s': %s", msg, strerror(errno)); ip_str = pr_netaddr_get_ipstr(res); expected = "127.0.0.1"; fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'", expected, ip_str); msg = "(127,0,0,1,8,73)"; res = proxy_ftp_msg_parse_addr(p, msg, AF_INET6); fail_unless(res != NULL, "Failed to parse message '%s': %s", msg, strerror(errno)); ip_str = pr_netaddr_get_ipstr(res); expected = "::ffff:127.0.0.1"; fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'", expected, ip_str); pr_netaddr_disable_ipv6(); res = proxy_ftp_msg_parse_addr(p, msg, AF_INET6); fail_unless(res != NULL, "Failed to parse message '%s': %s", msg, strerror(errno)); ip_str = pr_netaddr_get_ipstr(res); expected = "127.0.0.1"; fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'", expected, ip_str); pr_netaddr_enable_ipv6(); #endif /* PR_USE_IPV6 */ }
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 */ }