Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ #include <darwintest.h> #include <poll.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> static int sockv6_open(void) { int s; s = socket(AF_INET6, SOCK_DGRAM, 0); T_QUIET; T_ASSERT_POSIX_SUCCESS(s, "socket(AF_INET6, SOCK_DGRAM, 0)"); return s; } static int sockv6_bind(int s, in_port_t port) { struct sockaddr_in6 sin6; bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; sin6.sin6_port = port; return bind(s, (const struct sockaddr *)&sin6, sizeof(sin6)); } static void sockv6_set_v6only(int s) { int on = 1; int ret; ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "setsockopt(%d, IPV6_ONLY)", s); } static bool alloc_and_bind_ports(in_port_t port_start, in_port_t port_end, int bind_attempts) { int bound_count = 0; bool success = true; for (in_port_t i = port_start; success && i <= port_end; i++) { int s6 = -1; int s6_other = -1; int ret; s6 = sockv6_open(); sockv6_set_v6only(s6); if (sockv6_bind(s6, i) != 0) { /* find the next available port */ goto loop_done; } s6_other = sockv6_open(); ret = sockv6_bind(s6_other, i); T_WITH_ERRNO; T_QUIET; T_ASSERT_TRUE(ret != 0, "socket %d bind %d", s6_other, i); /* * After bind fails, try binding to a different port. * For non-root user, this will panic without the fix for * <rdar://problem/35243417>. */ if (sockv6_bind(s6_other, i + 1) == 0) { bound_count++; if (bound_count >= bind_attempts) { break; } } loop_done: if (s6 >= 0) { close(s6); } if (s6_other >= 0) { close(s6_other); } } T_ASSERT_TRUE(bound_count == bind_attempts, "number of successful binds %d (out of %d)", bound_count, bind_attempts); return success; } T_DECL(socket_bind_35243417, "bind IPv6 only UDP socket, then bind IPv6 socket.", T_META_ASROOT(false), T_META_CHECK_LEAKS(false)) { alloc_and_bind_ports(1, 65534, 10); } T_DECL(socket_bind_35243417_root, "bind IPv6 only UDP socket, then bind IPv6 socket.", T_META_ASROOT(true)) { alloc_and_bind_ports(1, 65534, 10); } |