xref: /freebsd/contrib/capsicum-test/socket.cc (revision 955a3f9ad586f38395e66127f9f2f4afbf3d5a94)
18ac5aef8SEnji Cooper // Tests for socket functionality.
28ac5aef8SEnji Cooper #include <sys/types.h>
38ac5aef8SEnji Cooper #include <sys/socket.h>
48ac5aef8SEnji Cooper #include <sys/un.h>
58ac5aef8SEnji Cooper #include <netinet/in.h>
68ac5aef8SEnji Cooper #include <arpa/inet.h>
78ac5aef8SEnji Cooper #include <unistd.h>
88ac5aef8SEnji Cooper 
98ac5aef8SEnji Cooper #include <string>
108ac5aef8SEnji Cooper 
118ac5aef8SEnji Cooper #include "capsicum.h"
128ac5aef8SEnji Cooper #include "syscalls.h"
138ac5aef8SEnji Cooper #include "capsicum-test.h"
148ac5aef8SEnji Cooper 
TEST(Socket,UnixDomain)158ac5aef8SEnji Cooper TEST(Socket, UnixDomain) {
168ac5aef8SEnji Cooper   const char* socketName = TmpFile("capsicum-test.socket");
178ac5aef8SEnji Cooper   unlink(socketName);
188ac5aef8SEnji Cooper   cap_rights_t r_rw;
198ac5aef8SEnji Cooper   cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
208ac5aef8SEnji Cooper   cap_rights_t r_all;
218ac5aef8SEnji Cooper   cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
228ac5aef8SEnji Cooper 
23*955a3f9aSAlex Richardson   int pipefds[2];
24*955a3f9aSAlex Richardson   EXPECT_EQ(0, pipe(pipefds));
258ac5aef8SEnji Cooper   pid_t child = fork();
268ac5aef8SEnji Cooper   if (child == 0) {
278ac5aef8SEnji Cooper     // Child process: wait for server setup
28*955a3f9aSAlex Richardson     close(pipefds[0]);
29*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_CHILD_SHOULD_RUN);
308ac5aef8SEnji Cooper 
318ac5aef8SEnji Cooper     // Create sockets
328ac5aef8SEnji Cooper     int sock = socket(AF_UNIX, SOCK_STREAM, 0);
338ac5aef8SEnji Cooper     EXPECT_OK(sock);
348ac5aef8SEnji Cooper     if (sock < 0) return;
358ac5aef8SEnji Cooper 
368ac5aef8SEnji Cooper     int cap_sock_rw = dup(sock);
378ac5aef8SEnji Cooper     EXPECT_OK(cap_sock_rw);
388ac5aef8SEnji Cooper     EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
398ac5aef8SEnji Cooper     int cap_sock_all = dup(sock);
408ac5aef8SEnji Cooper     EXPECT_OK(cap_sock_all);
418ac5aef8SEnji Cooper     EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
428ac5aef8SEnji Cooper     EXPECT_OK(close(sock));
438ac5aef8SEnji Cooper 
448ac5aef8SEnji Cooper     // Connect socket
458ac5aef8SEnji Cooper     struct sockaddr_un un;
468ac5aef8SEnji Cooper     memset(&un, 0, sizeof(un));
478ac5aef8SEnji Cooper     un.sun_family = AF_UNIX;
488ac5aef8SEnji Cooper     strcpy(un.sun_path, socketName);
498ac5aef8SEnji Cooper     socklen_t len = sizeof(un);
508ac5aef8SEnji Cooper     EXPECT_NOTCAPABLE(connect_(cap_sock_rw, (struct sockaddr *)&un, len));
518ac5aef8SEnji Cooper     EXPECT_OK(connect_(cap_sock_all, (struct sockaddr *)&un, len));
528ac5aef8SEnji Cooper 
538ac5aef8SEnji Cooper     exit(HasFailure());
548ac5aef8SEnji Cooper   }
558ac5aef8SEnji Cooper 
568ac5aef8SEnji Cooper   int sock = socket(AF_UNIX, SOCK_STREAM, 0);
578ac5aef8SEnji Cooper   EXPECT_OK(sock);
588ac5aef8SEnji Cooper   if (sock < 0) return;
598ac5aef8SEnji Cooper 
608ac5aef8SEnji Cooper   int cap_sock_rw = dup(sock);
618ac5aef8SEnji Cooper   EXPECT_OK(cap_sock_rw);
628ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
638ac5aef8SEnji Cooper   int cap_sock_all = dup(sock);
648ac5aef8SEnji Cooper   EXPECT_OK(cap_sock_all);
658ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
668ac5aef8SEnji Cooper   EXPECT_OK(close(sock));
678ac5aef8SEnji Cooper 
688ac5aef8SEnji Cooper   struct sockaddr_un un;
698ac5aef8SEnji Cooper   memset(&un, 0, sizeof(un));
708ac5aef8SEnji Cooper   un.sun_family = AF_UNIX;
718ac5aef8SEnji Cooper   strcpy(un.sun_path, socketName);
728ac5aef8SEnji Cooper   socklen_t len =  (sizeof(un) - sizeof(un.sun_path) + strlen(un.sun_path));
738ac5aef8SEnji Cooper 
748ac5aef8SEnji Cooper   // Can only bind the fully-capable socket.
758ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(bind_(cap_sock_rw, (struct sockaddr *)&un, len));
768ac5aef8SEnji Cooper   EXPECT_OK(bind_(cap_sock_all, (struct sockaddr *)&un, len));
778ac5aef8SEnji Cooper 
788ac5aef8SEnji Cooper   // Can only listen on the fully-capable socket.
798ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(listen(cap_sock_rw, 3));
808ac5aef8SEnji Cooper   EXPECT_OK(listen(cap_sock_all, 3));
818ac5aef8SEnji Cooper 
828ac5aef8SEnji Cooper   // Can only do socket operations on the fully-capable socket.
838ac5aef8SEnji Cooper   len = sizeof(un);
848ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&un, &len));
858ac5aef8SEnji Cooper   int value = 0;
868ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, SOL_SOCKET, SO_DEBUG, &value, sizeof(value)));
878ac5aef8SEnji Cooper   len = sizeof(value);
888ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, SOL_SOCKET, SO_DEBUG, &value, &len));
898ac5aef8SEnji Cooper 
908ac5aef8SEnji Cooper   len = sizeof(un);
918ac5aef8SEnji Cooper   memset(&un, 0, sizeof(un));
928ac5aef8SEnji Cooper   EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&un, &len));
938ac5aef8SEnji Cooper   EXPECT_EQ(AF_UNIX, un.sun_family);
948ac5aef8SEnji Cooper   EXPECT_EQ(std::string(socketName), std::string(un.sun_path));
958ac5aef8SEnji Cooper   value = 0;
968ac5aef8SEnji Cooper   EXPECT_OK(setsockopt(cap_sock_all, SOL_SOCKET, SO_DEBUG, &value, sizeof(value)));
978ac5aef8SEnji Cooper   len = sizeof(value);
988ac5aef8SEnji Cooper   EXPECT_OK(getsockopt(cap_sock_all, SOL_SOCKET, SO_DEBUG, &value, &len));
998ac5aef8SEnji Cooper 
100*955a3f9aSAlex Richardson   // Tell the child process that we are ready and accept the incoming connection.
101*955a3f9aSAlex Richardson   EXPECT_OK(close(pipefds[1]));
102*955a3f9aSAlex Richardson   SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_CHILD_SHOULD_RUN);
1038ac5aef8SEnji Cooper   len = sizeof(un);
1048ac5aef8SEnji Cooper   memset(&un, 0, sizeof(un));
1058ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(accept(cap_sock_rw, (struct sockaddr *)&un, &len));
1068ac5aef8SEnji Cooper   int conn_fd = accept(cap_sock_all, (struct sockaddr *)&un, &len);
1078ac5aef8SEnji Cooper   EXPECT_OK(conn_fd);
1088ac5aef8SEnji Cooper 
1098ac5aef8SEnji Cooper #ifdef CAP_FROM_ACCEPT
1108ac5aef8SEnji Cooper   // New connection should also be a capability.
1118ac5aef8SEnji Cooper   cap_rights_t rights;
1128ac5aef8SEnji Cooper   cap_rights_init(&rights, 0);
1138ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_get(conn_fd, &rights));
1148ac5aef8SEnji Cooper   EXPECT_RIGHTS_IN(&rights, &r_all);
1158ac5aef8SEnji Cooper #endif
1168ac5aef8SEnji Cooper 
1178ac5aef8SEnji Cooper   // Wait for the child.
1188ac5aef8SEnji Cooper   int status;
1198ac5aef8SEnji Cooper   EXPECT_EQ(child, waitpid(child, &status, 0));
1208ac5aef8SEnji Cooper   int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1218ac5aef8SEnji Cooper   EXPECT_EQ(0, rc);
1228ac5aef8SEnji Cooper 
1238ac5aef8SEnji Cooper   close(conn_fd);
1248ac5aef8SEnji Cooper   close(cap_sock_rw);
1258ac5aef8SEnji Cooper   close(cap_sock_all);
1268ac5aef8SEnji Cooper   unlink(socketName);
1278ac5aef8SEnji Cooper }
1288ac5aef8SEnji Cooper 
TEST(Socket,TCP)1298ac5aef8SEnji Cooper TEST(Socket, TCP) {
1308ac5aef8SEnji Cooper   int sock = socket(AF_INET, SOCK_STREAM, 0);
1318ac5aef8SEnji Cooper   EXPECT_OK(sock);
1328ac5aef8SEnji Cooper   if (sock < 0) return;
1338ac5aef8SEnji Cooper 
1348ac5aef8SEnji Cooper   cap_rights_t r_rw;
1358ac5aef8SEnji Cooper   cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
1368ac5aef8SEnji Cooper   cap_rights_t r_all;
1378ac5aef8SEnji Cooper   cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
1388ac5aef8SEnji Cooper 
1398ac5aef8SEnji Cooper   int cap_sock_rw = dup(sock);
1408ac5aef8SEnji Cooper   EXPECT_OK(cap_sock_rw);
1418ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
1428ac5aef8SEnji Cooper   int cap_sock_all = dup(sock);
1438ac5aef8SEnji Cooper   EXPECT_OK(cap_sock_all);
1448ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
1458ac5aef8SEnji Cooper   close(sock);
1468ac5aef8SEnji Cooper 
1478ac5aef8SEnji Cooper   struct sockaddr_in addr;
1488ac5aef8SEnji Cooper   memset(&addr, 0, sizeof(addr));
1498ac5aef8SEnji Cooper   addr.sin_family = AF_INET;
1508ac5aef8SEnji Cooper   addr.sin_port = htons(0);
1518ac5aef8SEnji Cooper   addr.sin_addr.s_addr = htonl(INADDR_ANY);
1528ac5aef8SEnji Cooper   socklen_t len = sizeof(addr);
1538ac5aef8SEnji Cooper 
1548ac5aef8SEnji Cooper   // Can only bind the fully-capable socket.
1558ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(bind_(cap_sock_rw, (struct sockaddr *)&addr, len));
1568ac5aef8SEnji Cooper   EXPECT_OK(bind_(cap_sock_all, (struct sockaddr *)&addr, len));
1578ac5aef8SEnji Cooper 
1588ac5aef8SEnji Cooper   getsockname(cap_sock_all, (struct sockaddr *)&addr, &len);
1598ac5aef8SEnji Cooper   int port = ntohs(addr.sin_port);
1608ac5aef8SEnji Cooper 
161*955a3f9aSAlex Richardson   int pipefds[2];
162*955a3f9aSAlex Richardson   EXPECT_EQ(0, pipe(pipefds));
1638ac5aef8SEnji Cooper   // Now we know the port involved, fork off a child.
1648ac5aef8SEnji Cooper   pid_t child = fork();
1658ac5aef8SEnji Cooper   if (child == 0) {
1668ac5aef8SEnji Cooper     // Child process: wait for server setup
167*955a3f9aSAlex Richardson     close(pipefds[0]);
168*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_CHILD_SHOULD_RUN);
1698ac5aef8SEnji Cooper 
1708ac5aef8SEnji Cooper     // Create sockets
1718ac5aef8SEnji Cooper     int sock = socket(AF_INET, SOCK_STREAM, 0);
1728ac5aef8SEnji Cooper     EXPECT_OK(sock);
1738ac5aef8SEnji Cooper     if (sock < 0) return;
1748ac5aef8SEnji Cooper     int cap_sock_rw = dup(sock);
1758ac5aef8SEnji Cooper     EXPECT_OK(cap_sock_rw);
1768ac5aef8SEnji Cooper     EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
1778ac5aef8SEnji Cooper     int cap_sock_all = dup(sock);
1788ac5aef8SEnji Cooper     EXPECT_OK(cap_sock_all);
1798ac5aef8SEnji Cooper     EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
1808ac5aef8SEnji Cooper     close(sock);
1818ac5aef8SEnji Cooper 
1828ac5aef8SEnji Cooper     // Connect socket
1838ac5aef8SEnji Cooper     struct sockaddr_in addr;
1848ac5aef8SEnji Cooper     memset(&addr, 0, sizeof(addr));
1858ac5aef8SEnji Cooper     addr.sin_family = AF_INET;
1868ac5aef8SEnji Cooper     addr.sin_port = htons(port);  // Pick unused port
1878ac5aef8SEnji Cooper     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
1888ac5aef8SEnji Cooper     socklen_t len = sizeof(addr);
1898ac5aef8SEnji Cooper     EXPECT_NOTCAPABLE(connect_(cap_sock_rw, (struct sockaddr *)&addr, len));
1908ac5aef8SEnji Cooper     EXPECT_OK(connect_(cap_sock_all, (struct sockaddr *)&addr, len));
1918ac5aef8SEnji Cooper 
1928ac5aef8SEnji Cooper     exit(HasFailure());
1938ac5aef8SEnji Cooper   }
1948ac5aef8SEnji Cooper 
1958ac5aef8SEnji Cooper   // Can only listen on the fully-capable socket.
1968ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(listen(cap_sock_rw, 3));
1978ac5aef8SEnji Cooper   EXPECT_OK(listen(cap_sock_all, 3));
1988ac5aef8SEnji Cooper 
1998ac5aef8SEnji Cooper   // Can only do socket operations on the fully-capable socket.
2008ac5aef8SEnji Cooper   len = sizeof(addr);
2018ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len));
2028ac5aef8SEnji Cooper   int value = 1;
2038ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
2048ac5aef8SEnji Cooper   len = sizeof(value);
2058ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, &len));
2068ac5aef8SEnji Cooper 
2078ac5aef8SEnji Cooper   len = sizeof(addr);
2088ac5aef8SEnji Cooper   memset(&addr, 0, sizeof(addr));
2098ac5aef8SEnji Cooper   EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len));
2108ac5aef8SEnji Cooper   EXPECT_EQ(AF_INET, addr.sin_family);
2118ac5aef8SEnji Cooper   EXPECT_EQ(htons(port), addr.sin_port);
2128ac5aef8SEnji Cooper   value = 0;
2138ac5aef8SEnji Cooper   EXPECT_OK(setsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
2148ac5aef8SEnji Cooper   len = sizeof(value);
2158ac5aef8SEnji Cooper   EXPECT_OK(getsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, &len));
2168ac5aef8SEnji Cooper 
217*955a3f9aSAlex Richardson   // Tell the child process that we are ready and accept the incoming connection.
218*955a3f9aSAlex Richardson   EXPECT_OK(close(pipefds[1]));
219*955a3f9aSAlex Richardson   SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_CHILD_SHOULD_RUN);
2208ac5aef8SEnji Cooper   len = sizeof(addr);
2218ac5aef8SEnji Cooper   memset(&addr, 0, sizeof(addr));
2228ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(accept(cap_sock_rw, (struct sockaddr *)&addr, &len));
2238ac5aef8SEnji Cooper   int conn_fd = accept(cap_sock_all, (struct sockaddr *)&addr, &len);
2248ac5aef8SEnji Cooper   EXPECT_OK(conn_fd);
2258ac5aef8SEnji Cooper 
2268ac5aef8SEnji Cooper #ifdef CAP_FROM_ACCEPT
2278ac5aef8SEnji Cooper   // New connection should also be a capability.
2288ac5aef8SEnji Cooper   cap_rights_t rights;
2298ac5aef8SEnji Cooper   cap_rights_init(&rights, 0);
2308ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_get(conn_fd, &rights));
2318ac5aef8SEnji Cooper   EXPECT_RIGHTS_IN(&rights, &r_all);
2328ac5aef8SEnji Cooper #endif
2338ac5aef8SEnji Cooper 
2348ac5aef8SEnji Cooper   // Wait for the child.
2358ac5aef8SEnji Cooper   int status;
2368ac5aef8SEnji Cooper   EXPECT_EQ(child, waitpid(child, &status, 0));
2378ac5aef8SEnji Cooper   int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
2388ac5aef8SEnji Cooper   EXPECT_EQ(0, rc);
2398ac5aef8SEnji Cooper 
2408ac5aef8SEnji Cooper   close(conn_fd);
2418ac5aef8SEnji Cooper   close(cap_sock_rw);
2428ac5aef8SEnji Cooper   close(cap_sock_all);
2438ac5aef8SEnji Cooper }
2448ac5aef8SEnji Cooper 
TEST(Socket,UDP)2458ac5aef8SEnji Cooper TEST(Socket, UDP) {
2468ac5aef8SEnji Cooper   int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2478ac5aef8SEnji Cooper   EXPECT_OK(sock);
2488ac5aef8SEnji Cooper   if (sock < 0) return;
2498ac5aef8SEnji Cooper 
2508ac5aef8SEnji Cooper   cap_rights_t r_rw;
2518ac5aef8SEnji Cooper   cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
2528ac5aef8SEnji Cooper   cap_rights_t r_all;
2538ac5aef8SEnji Cooper   cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
2548ac5aef8SEnji Cooper   cap_rights_t r_connect;
2558ac5aef8SEnji Cooper   cap_rights_init(&r_connect, CAP_READ, CAP_WRITE, CAP_CONNECT);
2568ac5aef8SEnji Cooper 
2578ac5aef8SEnji Cooper   int cap_sock_rw = dup(sock);
2588ac5aef8SEnji Cooper   EXPECT_OK(cap_sock_rw);
2598ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
2608ac5aef8SEnji Cooper   int cap_sock_all = dup(sock);
2618ac5aef8SEnji Cooper   EXPECT_OK(cap_sock_all);
2628ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
2638ac5aef8SEnji Cooper   close(sock);
2648ac5aef8SEnji Cooper 
2658ac5aef8SEnji Cooper   struct sockaddr_in addr;
2668ac5aef8SEnji Cooper   memset(&addr, 0, sizeof(addr));
2678ac5aef8SEnji Cooper   addr.sin_family = AF_INET;
2688ac5aef8SEnji Cooper   addr.sin_port = htons(0);
2698ac5aef8SEnji Cooper   addr.sin_addr.s_addr = htonl(INADDR_ANY);
2708ac5aef8SEnji Cooper   socklen_t len = sizeof(addr);
2718ac5aef8SEnji Cooper 
2728ac5aef8SEnji Cooper   // Can only bind the fully-capable socket.
2738ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(bind_(cap_sock_rw, (struct sockaddr *)&addr, len));
2748ac5aef8SEnji Cooper   EXPECT_OK(bind_(cap_sock_all, (struct sockaddr *)&addr, len));
2758ac5aef8SEnji Cooper   getsockname(cap_sock_all, (struct sockaddr *)&addr, &len);
2768ac5aef8SEnji Cooper   int port = ntohs(addr.sin_port);
2778ac5aef8SEnji Cooper 
2788ac5aef8SEnji Cooper   // Can only do socket operations on the fully-capable socket.
2798ac5aef8SEnji Cooper   len = sizeof(addr);
2808ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len));
2818ac5aef8SEnji Cooper   int value = 1;
2828ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
2838ac5aef8SEnji Cooper   len = sizeof(value);
2848ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, &len));
2858ac5aef8SEnji Cooper 
2868ac5aef8SEnji Cooper   len = sizeof(addr);
2878ac5aef8SEnji Cooper   memset(&addr, 0, sizeof(addr));
2888ac5aef8SEnji Cooper   EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len));
2898ac5aef8SEnji Cooper   EXPECT_EQ(AF_INET, addr.sin_family);
2908ac5aef8SEnji Cooper   EXPECT_EQ(htons(port), addr.sin_port);
2918ac5aef8SEnji Cooper   value = 1;
2928ac5aef8SEnji Cooper   EXPECT_OK(setsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
2938ac5aef8SEnji Cooper   len = sizeof(value);
2948ac5aef8SEnji Cooper   EXPECT_OK(getsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, &len));
2958ac5aef8SEnji Cooper 
2968ac5aef8SEnji Cooper   pid_t child = fork();
2978ac5aef8SEnji Cooper   if (child == 0) {
2988ac5aef8SEnji Cooper     int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2998ac5aef8SEnji Cooper     EXPECT_OK(sock);
3008ac5aef8SEnji Cooper     int cap_sock_rw = dup(sock);
3018ac5aef8SEnji Cooper     EXPECT_OK(cap_sock_rw);
3028ac5aef8SEnji Cooper     EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
3038ac5aef8SEnji Cooper     int cap_sock_connect = dup(sock);
3048ac5aef8SEnji Cooper     EXPECT_OK(cap_sock_connect);
3058ac5aef8SEnji Cooper     EXPECT_OK(cap_rights_limit(cap_sock_connect, &r_connect));
3068ac5aef8SEnji Cooper     close(sock);
3078ac5aef8SEnji Cooper 
3088ac5aef8SEnji Cooper     // Can only sendmsg(2) to an address over a socket with CAP_CONNECT.
3098ac5aef8SEnji Cooper     unsigned char buffer[256];
3108ac5aef8SEnji Cooper     struct iovec iov;
3118ac5aef8SEnji Cooper     memset(&iov, 0, sizeof(iov));
3128ac5aef8SEnji Cooper     iov.iov_base = buffer;
3138ac5aef8SEnji Cooper     iov.iov_len = sizeof(buffer);
3148ac5aef8SEnji Cooper 
3158ac5aef8SEnji Cooper     struct msghdr mh;
3168ac5aef8SEnji Cooper     memset(&mh, 0, sizeof(mh));
3178ac5aef8SEnji Cooper     mh.msg_iov = &iov;
3188ac5aef8SEnji Cooper     mh.msg_iovlen = 1;
3198ac5aef8SEnji Cooper 
3208ac5aef8SEnji Cooper     struct sockaddr_in addr;
3218ac5aef8SEnji Cooper     memset(&addr, 0, sizeof(addr));
3228ac5aef8SEnji Cooper     addr.sin_family = AF_INET;
3238ac5aef8SEnji Cooper     addr.sin_port = htons(port);
3248ac5aef8SEnji Cooper     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3258ac5aef8SEnji Cooper     mh.msg_name = &addr;
3268ac5aef8SEnji Cooper     mh.msg_namelen = sizeof(addr);
3278ac5aef8SEnji Cooper 
3288ac5aef8SEnji Cooper     EXPECT_NOTCAPABLE(sendmsg(cap_sock_rw, &mh, 0));
3298ac5aef8SEnji Cooper     EXPECT_OK(sendmsg(cap_sock_connect, &mh, 0));
3308ac5aef8SEnji Cooper 
3318ac5aef8SEnji Cooper #ifdef HAVE_SEND_RECV_MMSG
3328ac5aef8SEnji Cooper     struct mmsghdr mv;
3338ac5aef8SEnji Cooper     memset(&mv, 0, sizeof(mv));
3348ac5aef8SEnji Cooper     memcpy(&mv.msg_hdr, &mh, sizeof(struct msghdr));
3358ac5aef8SEnji Cooper     EXPECT_NOTCAPABLE(sendmmsg(cap_sock_rw, &mv, 1, 0));
3368ac5aef8SEnji Cooper     EXPECT_OK(sendmmsg(cap_sock_connect, &mv, 1, 0));
3378ac5aef8SEnji Cooper #endif
3388ac5aef8SEnji Cooper     close(cap_sock_rw);
3398ac5aef8SEnji Cooper     close(cap_sock_connect);
3408ac5aef8SEnji Cooper     exit(HasFailure());
3418ac5aef8SEnji Cooper   }
3428ac5aef8SEnji Cooper   // Wait for the child.
3438ac5aef8SEnji Cooper   int status;
3448ac5aef8SEnji Cooper   EXPECT_EQ(child, waitpid(child, &status, 0));
3458ac5aef8SEnji Cooper   int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
3468ac5aef8SEnji Cooper   EXPECT_EQ(0, rc);
3478ac5aef8SEnji Cooper 
3488ac5aef8SEnji Cooper   close(cap_sock_rw);
3498ac5aef8SEnji Cooper   close(cap_sock_all);
3508ac5aef8SEnji Cooper }
351