1 // Tests of SCTP functionality
2 // Requires: libsctp-dev package on Debian Linux, CONFIG_IP_SCTP in kernel config
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <netinet/sctp.h>
13 #include "capsicum-test.h"
15 static cap_rights_t r_ro;
16 static cap_rights_t r_wo;
17 static cap_rights_t r_rw;
18 static cap_rights_t r_all;
19 static cap_rights_t r_all_nopeel;
20 #define DO_PEELOFF 0x1A
23 static int SctpClient(int port, unsigned char byte) {
25 int sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
27 if (sock < 0) return sock;
28 int cap_sock_ro = dup(sock);
29 EXPECT_OK(cap_sock_ro);
30 EXPECT_OK(cap_rights_limit(cap_sock_ro, &r_rw));
31 int cap_sock_rw = dup(sock);
32 EXPECT_OK(cap_sock_rw);
33 EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
34 int cap_sock_all = dup(sock);
35 EXPECT_OK(cap_sock_all);
36 EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
39 // Send a message. Requires CAP_WRITE and CAP_CONNECT.
40 struct sockaddr_in serv_addr;
41 memset(&serv_addr, 0, sizeof(serv_addr));
42 serv_addr.sin_family = AF_INET;
43 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
44 serv_addr.sin_port = htons(port);
46 EXPECT_NOTCAPABLE(sctp_sendmsg(cap_sock_ro, &byte, 1,
47 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
49 EXPECT_NOTCAPABLE(sctp_sendmsg(cap_sock_rw, &byte, 1,
50 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
52 if (verbose) fprintf(stderr, " [%d]sctp_sendmsg(%02x)\n", getpid_(), byte);
53 EXPECT_OK(sctp_sendmsg(cap_sock_all, &byte, 1,
54 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
63 int sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
67 cap_rights_init(&r_ro, CAP_READ);
68 cap_rights_init(&r_wo, CAP_WRITE);
69 cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
70 cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
71 cap_rights_init(&r_all_nopeel, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
72 cap_rights_clear(&r_all_nopeel, CAP_PEELOFF);
74 int cap_sock_wo = dup(sock);
75 EXPECT_OK(cap_sock_wo);
76 EXPECT_OK(cap_rights_limit(cap_sock_wo, &r_wo));
77 int cap_sock_rw = dup(sock);
78 EXPECT_OK(cap_sock_rw);
79 EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
80 int cap_sock_all = dup(sock);
81 EXPECT_OK(cap_sock_all);
82 EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
83 int cap_sock_all_nopeel = dup(sock);
84 EXPECT_OK(cap_sock_all_nopeel);
85 EXPECT_OK(cap_rights_limit(cap_sock_all_nopeel, &r_all_nopeel));
88 struct sockaddr_in addr;
89 memset(&addr, 0, sizeof(addr));
90 addr.sin_family = AF_INET;
91 addr.sin_port = htons(0);
92 addr.sin_addr.s_addr = htonl(INADDR_ANY);
93 socklen_t len = sizeof(addr);
95 // Can only bind the fully-capable socket.
96 EXPECT_NOTCAPABLE(bind(cap_sock_rw, (struct sockaddr *)&addr, len));
97 EXPECT_OK(bind(cap_sock_all, (struct sockaddr *)&addr, len));
99 EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr *)&addr, &len));
100 int port = ntohs(addr.sin_port);
102 // Now we know the port involved, fork off children to run clients.
103 pid_t child1 = fork();
105 // Child process 1: wait for server setup
107 // Send a message that triggers peeloff
108 int client_sock = SctpClient(port, DO_PEELOFF);
114 pid_t child2 = fork();
116 // Child process 2: wait for server setup
118 // Send a message that triggers server exit
119 int client_sock = SctpClient(port, DO_TERM);
124 // Can only listen on the fully-capable socket.
125 EXPECT_NOTCAPABLE(listen(cap_sock_rw, 3));
126 EXPECT_OK(listen(cap_sock_all, 3));
128 // Can only do socket operations on the fully-capable socket.
130 EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len));
132 struct sctp_event_subscribe events;
133 memset(&events, 0, sizeof(events));
134 events.sctp_association_event = 1;
135 events.sctp_data_io_event = 1;
136 EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)));
137 len = sizeof(events);
138 EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, &len));
139 memset(&events, 0, sizeof(events));
140 events.sctp_association_event = 1;
141 events.sctp_data_io_event = 1;
142 EXPECT_OK(setsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)));
143 len = sizeof(events);
144 EXPECT_OK(getsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, &len));
147 memset(&addr, 0, sizeof(addr));
148 EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len));
149 EXPECT_EQ(AF_INET, addr.sin_family);
150 EXPECT_EQ(htons(port), addr.sin_port);
152 struct sockaddr_in client_addr;
153 socklen_t addr_len = sizeof(client_addr);
154 unsigned char buffer[1024];
155 struct sctp_sndrcvinfo sri;
156 memset(&sri, 0, sizeof(sri));
158 EXPECT_NOTCAPABLE(sctp_recvmsg(cap_sock_wo, buffer, sizeof(buffer),
159 (struct sockaddr*)&client_addr, &addr_len,
163 memset(&sri, 0, sizeof(sri));
164 int len = sctp_recvmsg(cap_sock_rw, buffer, sizeof(buffer),
165 (struct sockaddr*)&client_addr, &addr_len,
167 if (len < 0 && errno == EAGAIN) goto retry;
170 if (verbose) fprintf(stderr, "[%d]sctp_recvmsg(%02x..)", getpid_(), (unsigned)buffer[0]);
171 if (buffer[0] == DO_PEELOFF) {
172 if (verbose) fprintf(stderr, "..peeling off association %08lx\n", (long)sri.sinfo_assoc_id);
173 // Peel off the association. Needs CAP_PEELOFF.
174 int rc1 = sctp_peeloff(cap_sock_all_nopeel, sri.sinfo_assoc_id);
175 EXPECT_NOTCAPABLE(rc1);
176 int rc2 = sctp_peeloff(cap_sock_all, sri.sinfo_assoc_id);
178 int peeled = std::max(rc1, rc2);
180 #ifdef CAP_FROM_PEELOFF
181 // Peeled off FD should have same rights as original socket.
183 EXPECT_OK(cap_rights_get(peeled, &rights));
184 EXPECT_RIGHTS_EQ(&r_all, &rights);
188 } else if (buffer[0] == DO_TERM) {
189 if (verbose) fprintf(stderr, "..terminating server\n");
192 } else if (len < 0) {
197 // Wait for the children.
200 EXPECT_EQ(child1, waitpid(child1, &status, 0));
201 rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
203 EXPECT_EQ(child2, waitpid(child2, &status, 0));
204 rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
210 close(cap_sock_all_nopeel);