1b5188056SFlorian Westphal // SPDX-License-Identifier: GPL-2.0
2b5188056SFlorian Westphal
3b5188056SFlorian Westphal #define _GNU_SOURCE
4b5188056SFlorian Westphal
5b5188056SFlorian Westphal #include <assert.h>
6b5188056SFlorian Westphal #include <errno.h>
7b5188056SFlorian Westphal #include <fcntl.h>
8b5188056SFlorian Westphal #include <limits.h>
9b5188056SFlorian Westphal #include <string.h>
10b5188056SFlorian Westphal #include <stdarg.h>
11b5188056SFlorian Westphal #include <stdbool.h>
12b5188056SFlorian Westphal #include <stdint.h>
13b5188056SFlorian Westphal #include <inttypes.h>
14b5188056SFlorian Westphal #include <stdio.h>
15b5188056SFlorian Westphal #include <stdlib.h>
16b5188056SFlorian Westphal #include <strings.h>
17b5188056SFlorian Westphal #include <unistd.h>
18b5188056SFlorian Westphal #include <time.h>
19b5188056SFlorian Westphal
20b5188056SFlorian Westphal #include <sys/ioctl.h>
21*00a4f8fdSWillem de Bruijn #include <sys/random.h>
22b5188056SFlorian Westphal #include <sys/socket.h>
23b5188056SFlorian Westphal #include <sys/types.h>
24b5188056SFlorian Westphal #include <sys/wait.h>
25b5188056SFlorian Westphal
26b5188056SFlorian Westphal #include <netdb.h>
27b5188056SFlorian Westphal #include <netinet/in.h>
28b5188056SFlorian Westphal
29b5188056SFlorian Westphal #include <linux/tcp.h>
30b5188056SFlorian Westphal #include <linux/sockios.h>
31b5188056SFlorian Westphal
32b5188056SFlorian Westphal #ifndef IPPROTO_MPTCP
33b5188056SFlorian Westphal #define IPPROTO_MPTCP 262
34b5188056SFlorian Westphal #endif
35b5188056SFlorian Westphal #ifndef SOL_MPTCP
36b5188056SFlorian Westphal #define SOL_MPTCP 284
37b5188056SFlorian Westphal #endif
38b5188056SFlorian Westphal
39b5188056SFlorian Westphal static int pf = AF_INET;
40b5188056SFlorian Westphal static int proto_tx = IPPROTO_MPTCP;
41b5188056SFlorian Westphal static int proto_rx = IPPROTO_MPTCP;
42b5188056SFlorian Westphal
die_perror(const char * msg)43b5188056SFlorian Westphal static void die_perror(const char *msg)
44b5188056SFlorian Westphal {
45b5188056SFlorian Westphal perror(msg);
46b5188056SFlorian Westphal exit(1);
47b5188056SFlorian Westphal }
48b5188056SFlorian Westphal
die_usage(int r)49b5188056SFlorian Westphal static void die_usage(int r)
50b5188056SFlorian Westphal {
51b5188056SFlorian Westphal fprintf(stderr, "Usage: mptcp_inq [-6] [ -t tcp|mptcp ] [ -r tcp|mptcp]\n");
52b5188056SFlorian Westphal exit(r);
53b5188056SFlorian Westphal }
54b5188056SFlorian Westphal
xerror(const char * fmt,...)55b5188056SFlorian Westphal static void xerror(const char *fmt, ...)
56b5188056SFlorian Westphal {
57b5188056SFlorian Westphal va_list ap;
58b5188056SFlorian Westphal
59b5188056SFlorian Westphal va_start(ap, fmt);
60b5188056SFlorian Westphal vfprintf(stderr, fmt, ap);
61b5188056SFlorian Westphal va_end(ap);
62b5188056SFlorian Westphal fputc('\n', stderr);
63b5188056SFlorian Westphal exit(1);
64b5188056SFlorian Westphal }
65b5188056SFlorian Westphal
getxinfo_strerr(int err)66b5188056SFlorian Westphal static const char *getxinfo_strerr(int err)
67b5188056SFlorian Westphal {
68b5188056SFlorian Westphal if (err == EAI_SYSTEM)
69b5188056SFlorian Westphal return strerror(errno);
70b5188056SFlorian Westphal
71b5188056SFlorian Westphal return gai_strerror(err);
72b5188056SFlorian Westphal }
73b5188056SFlorian Westphal
xgetaddrinfo(const char * node,const char * service,const struct addrinfo * hints,struct addrinfo ** res)74b5188056SFlorian Westphal static void xgetaddrinfo(const char *node, const char *service,
75b5188056SFlorian Westphal const struct addrinfo *hints,
76b5188056SFlorian Westphal struct addrinfo **res)
77b5188056SFlorian Westphal {
78b5188056SFlorian Westphal int err = getaddrinfo(node, service, hints, res);
79b5188056SFlorian Westphal
80b5188056SFlorian Westphal if (err) {
81b5188056SFlorian Westphal const char *errstr = getxinfo_strerr(err);
82b5188056SFlorian Westphal
83b5188056SFlorian Westphal fprintf(stderr, "Fatal: getaddrinfo(%s:%s): %s\n",
84b5188056SFlorian Westphal node ? node : "", service ? service : "", errstr);
85b5188056SFlorian Westphal exit(1);
86b5188056SFlorian Westphal }
87b5188056SFlorian Westphal }
88b5188056SFlorian Westphal
sock_listen_mptcp(const char * const listenaddr,const char * const port)89b5188056SFlorian Westphal static int sock_listen_mptcp(const char * const listenaddr,
90b5188056SFlorian Westphal const char * const port)
91b5188056SFlorian Westphal {
92fd37c2ecSMat Martineau int sock = -1;
93b5188056SFlorian Westphal struct addrinfo hints = {
94b5188056SFlorian Westphal .ai_protocol = IPPROTO_TCP,
95b5188056SFlorian Westphal .ai_socktype = SOCK_STREAM,
96b5188056SFlorian Westphal .ai_flags = AI_PASSIVE | AI_NUMERICHOST
97b5188056SFlorian Westphal };
98b5188056SFlorian Westphal
99b5188056SFlorian Westphal hints.ai_family = pf;
100b5188056SFlorian Westphal
101b5188056SFlorian Westphal struct addrinfo *a, *addr;
102b5188056SFlorian Westphal int one = 1;
103b5188056SFlorian Westphal
104b5188056SFlorian Westphal xgetaddrinfo(listenaddr, port, &hints, &addr);
105b5188056SFlorian Westphal hints.ai_family = pf;
106b5188056SFlorian Westphal
107b5188056SFlorian Westphal for (a = addr; a; a = a->ai_next) {
108b5188056SFlorian Westphal sock = socket(a->ai_family, a->ai_socktype, proto_rx);
109b5188056SFlorian Westphal if (sock < 0)
110b5188056SFlorian Westphal continue;
111b5188056SFlorian Westphal
112b5188056SFlorian Westphal if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
113b5188056SFlorian Westphal sizeof(one)))
114b5188056SFlorian Westphal perror("setsockopt");
115b5188056SFlorian Westphal
116b5188056SFlorian Westphal if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
117b5188056SFlorian Westphal break; /* success */
118b5188056SFlorian Westphal
119b5188056SFlorian Westphal perror("bind");
120b5188056SFlorian Westphal close(sock);
121b5188056SFlorian Westphal sock = -1;
122b5188056SFlorian Westphal }
123b5188056SFlorian Westphal
124b5188056SFlorian Westphal freeaddrinfo(addr);
125b5188056SFlorian Westphal
126b5188056SFlorian Westphal if (sock < 0)
127b5188056SFlorian Westphal xerror("could not create listen socket");
128b5188056SFlorian Westphal
129b5188056SFlorian Westphal if (listen(sock, 20))
130b5188056SFlorian Westphal die_perror("listen");
131b5188056SFlorian Westphal
132b5188056SFlorian Westphal return sock;
133b5188056SFlorian Westphal }
134b5188056SFlorian Westphal
sock_connect_mptcp(const char * const remoteaddr,const char * const port,int proto)135b5188056SFlorian Westphal static int sock_connect_mptcp(const char * const remoteaddr,
136b5188056SFlorian Westphal const char * const port, int proto)
137b5188056SFlorian Westphal {
138b5188056SFlorian Westphal struct addrinfo hints = {
139b5188056SFlorian Westphal .ai_protocol = IPPROTO_TCP,
140b5188056SFlorian Westphal .ai_socktype = SOCK_STREAM,
141b5188056SFlorian Westphal };
142b5188056SFlorian Westphal struct addrinfo *a, *addr;
143b5188056SFlorian Westphal int sock = -1;
144b5188056SFlorian Westphal
145b5188056SFlorian Westphal hints.ai_family = pf;
146b5188056SFlorian Westphal
147b5188056SFlorian Westphal xgetaddrinfo(remoteaddr, port, &hints, &addr);
148b5188056SFlorian Westphal for (a = addr; a; a = a->ai_next) {
149b5188056SFlorian Westphal sock = socket(a->ai_family, a->ai_socktype, proto);
150b5188056SFlorian Westphal if (sock < 0)
151b5188056SFlorian Westphal continue;
152b5188056SFlorian Westphal
153b5188056SFlorian Westphal if (connect(sock, a->ai_addr, a->ai_addrlen) == 0)
154b5188056SFlorian Westphal break; /* success */
155b5188056SFlorian Westphal
156b5188056SFlorian Westphal die_perror("connect");
157b5188056SFlorian Westphal }
158b5188056SFlorian Westphal
159b5188056SFlorian Westphal if (sock < 0)
160b5188056SFlorian Westphal xerror("could not create connect socket");
161b5188056SFlorian Westphal
162b5188056SFlorian Westphal freeaddrinfo(addr);
163b5188056SFlorian Westphal return sock;
164b5188056SFlorian Westphal }
165b5188056SFlorian Westphal
protostr_to_num(const char * s)166b5188056SFlorian Westphal static int protostr_to_num(const char *s)
167b5188056SFlorian Westphal {
168b5188056SFlorian Westphal if (strcasecmp(s, "tcp") == 0)
169b5188056SFlorian Westphal return IPPROTO_TCP;
170b5188056SFlorian Westphal if (strcasecmp(s, "mptcp") == 0)
171b5188056SFlorian Westphal return IPPROTO_MPTCP;
172b5188056SFlorian Westphal
173b5188056SFlorian Westphal die_usage(1);
174b5188056SFlorian Westphal return 0;
175b5188056SFlorian Westphal }
176b5188056SFlorian Westphal
parse_opts(int argc,char ** argv)177b5188056SFlorian Westphal static void parse_opts(int argc, char **argv)
178b5188056SFlorian Westphal {
179b5188056SFlorian Westphal int c;
180b5188056SFlorian Westphal
181b5188056SFlorian Westphal while ((c = getopt(argc, argv, "h6t:r:")) != -1) {
182b5188056SFlorian Westphal switch (c) {
183b5188056SFlorian Westphal case 'h':
184b5188056SFlorian Westphal die_usage(0);
185b5188056SFlorian Westphal break;
186b5188056SFlorian Westphal case '6':
187b5188056SFlorian Westphal pf = AF_INET6;
188b5188056SFlorian Westphal break;
189b5188056SFlorian Westphal case 't':
190b5188056SFlorian Westphal proto_tx = protostr_to_num(optarg);
191b5188056SFlorian Westphal break;
192b5188056SFlorian Westphal case 'r':
193b5188056SFlorian Westphal proto_rx = protostr_to_num(optarg);
194b5188056SFlorian Westphal break;
195b5188056SFlorian Westphal default:
196b5188056SFlorian Westphal die_usage(1);
197b5188056SFlorian Westphal break;
198b5188056SFlorian Westphal }
199b5188056SFlorian Westphal }
200b5188056SFlorian Westphal }
201b5188056SFlorian Westphal
202b5188056SFlorian Westphal /* wait up to timeout milliseconds */
wait_for_ack(int fd,int timeout,size_t total)203b5188056SFlorian Westphal static void wait_for_ack(int fd, int timeout, size_t total)
204b5188056SFlorian Westphal {
205b5188056SFlorian Westphal int i;
206b5188056SFlorian Westphal
207b5188056SFlorian Westphal for (i = 0; i < timeout; i++) {
208b5188056SFlorian Westphal int nsd, ret, queued = -1;
209b5188056SFlorian Westphal struct timespec req;
210b5188056SFlorian Westphal
211b5188056SFlorian Westphal ret = ioctl(fd, TIOCOUTQ, &queued);
212b5188056SFlorian Westphal if (ret < 0)
213b5188056SFlorian Westphal die_perror("TIOCOUTQ");
214b5188056SFlorian Westphal
215b5188056SFlorian Westphal ret = ioctl(fd, SIOCOUTQNSD, &nsd);
216b5188056SFlorian Westphal if (ret < 0)
217b5188056SFlorian Westphal die_perror("SIOCOUTQNSD");
218b5188056SFlorian Westphal
219b5188056SFlorian Westphal if ((size_t)queued > total)
220b5188056SFlorian Westphal xerror("TIOCOUTQ %u, but only %zu expected\n", queued, total);
221b5188056SFlorian Westphal assert(nsd <= queued);
222b5188056SFlorian Westphal
223b5188056SFlorian Westphal if (queued == 0)
224b5188056SFlorian Westphal return;
225b5188056SFlorian Westphal
226b5188056SFlorian Westphal /* wait for peer to ack rx of all data */
227b5188056SFlorian Westphal req.tv_sec = 0;
228b5188056SFlorian Westphal req.tv_nsec = 1 * 1000 * 1000ul; /* 1ms */
229b5188056SFlorian Westphal nanosleep(&req, NULL);
230b5188056SFlorian Westphal }
231b5188056SFlorian Westphal
232b5188056SFlorian Westphal xerror("still tx data queued after %u ms\n", timeout);
233b5188056SFlorian Westphal }
234b5188056SFlorian Westphal
connect_one_server(int fd,int unixfd)235b5188056SFlorian Westphal static void connect_one_server(int fd, int unixfd)
236b5188056SFlorian Westphal {
237b5188056SFlorian Westphal size_t len, i, total, sent;
238b5188056SFlorian Westphal char buf[4096], buf2[4096];
239b5188056SFlorian Westphal ssize_t ret;
240b5188056SFlorian Westphal
241b5188056SFlorian Westphal len = rand() % (sizeof(buf) - 1);
242b5188056SFlorian Westphal
243b5188056SFlorian Westphal if (len < 128)
244b5188056SFlorian Westphal len = 128;
245b5188056SFlorian Westphal
246b5188056SFlorian Westphal for (i = 0; i < len ; i++) {
247b5188056SFlorian Westphal buf[i] = rand() % 26;
248b5188056SFlorian Westphal buf[i] += 'A';
249b5188056SFlorian Westphal }
250b5188056SFlorian Westphal
251b5188056SFlorian Westphal buf[i] = '\n';
252b5188056SFlorian Westphal
253b5188056SFlorian Westphal /* un-block server */
254b5188056SFlorian Westphal ret = read(unixfd, buf2, 4);
255b5188056SFlorian Westphal assert(ret == 4);
256b5188056SFlorian Westphal
257b5188056SFlorian Westphal assert(strncmp(buf2, "xmit", 4) == 0);
258b5188056SFlorian Westphal
259b5188056SFlorian Westphal ret = write(unixfd, &len, sizeof(len));
260b5188056SFlorian Westphal assert(ret == (ssize_t)sizeof(len));
261b5188056SFlorian Westphal
262b5188056SFlorian Westphal ret = write(fd, buf, len);
263b5188056SFlorian Westphal if (ret < 0)
264b5188056SFlorian Westphal die_perror("write");
265b5188056SFlorian Westphal
266b5188056SFlorian Westphal if (ret != (ssize_t)len)
267b5188056SFlorian Westphal xerror("short write");
268b5188056SFlorian Westphal
269b5188056SFlorian Westphal ret = read(unixfd, buf2, 4);
270b5188056SFlorian Westphal assert(strncmp(buf2, "huge", 4) == 0);
271b5188056SFlorian Westphal
272b5188056SFlorian Westphal total = rand() % (16 * 1024 * 1024);
273b5188056SFlorian Westphal total += (1 * 1024 * 1024);
274b5188056SFlorian Westphal sent = total;
275b5188056SFlorian Westphal
276b5188056SFlorian Westphal ret = write(unixfd, &total, sizeof(total));
277b5188056SFlorian Westphal assert(ret == (ssize_t)sizeof(total));
278b5188056SFlorian Westphal
279b5188056SFlorian Westphal wait_for_ack(fd, 5000, len);
280b5188056SFlorian Westphal
281b5188056SFlorian Westphal while (total > 0) {
282b5188056SFlorian Westphal if (total > sizeof(buf))
283b5188056SFlorian Westphal len = sizeof(buf);
284b5188056SFlorian Westphal else
285b5188056SFlorian Westphal len = total;
286b5188056SFlorian Westphal
287b5188056SFlorian Westphal ret = write(fd, buf, len);
288b5188056SFlorian Westphal if (ret < 0)
289b5188056SFlorian Westphal die_perror("write");
290b5188056SFlorian Westphal total -= ret;
291b5188056SFlorian Westphal
292b5188056SFlorian Westphal /* we don't have to care about buf content, only
293b5188056SFlorian Westphal * number of total bytes sent
294b5188056SFlorian Westphal */
295b5188056SFlorian Westphal }
296b5188056SFlorian Westphal
297b5188056SFlorian Westphal ret = read(unixfd, buf2, 4);
298b5188056SFlorian Westphal assert(ret == 4);
299b5188056SFlorian Westphal assert(strncmp(buf2, "shut", 4) == 0);
300b5188056SFlorian Westphal
301b5188056SFlorian Westphal wait_for_ack(fd, 5000, sent);
302b5188056SFlorian Westphal
303b5188056SFlorian Westphal ret = write(fd, buf, 1);
304b5188056SFlorian Westphal assert(ret == 1);
305b5188056SFlorian Westphal close(fd);
306b5188056SFlorian Westphal ret = write(unixfd, "closed", 6);
307b5188056SFlorian Westphal assert(ret == 6);
308b5188056SFlorian Westphal
309b5188056SFlorian Westphal close(unixfd);
310b5188056SFlorian Westphal }
311b5188056SFlorian Westphal
get_tcp_inq(struct msghdr * msgh,unsigned int * inqv)312b5188056SFlorian Westphal static void get_tcp_inq(struct msghdr *msgh, unsigned int *inqv)
313b5188056SFlorian Westphal {
314b5188056SFlorian Westphal struct cmsghdr *cmsg;
315b5188056SFlorian Westphal
316b5188056SFlorian Westphal for (cmsg = CMSG_FIRSTHDR(msgh); cmsg ; cmsg = CMSG_NXTHDR(msgh, cmsg)) {
317b5188056SFlorian Westphal if (cmsg->cmsg_level == IPPROTO_TCP && cmsg->cmsg_type == TCP_CM_INQ) {
318b5188056SFlorian Westphal memcpy(inqv, CMSG_DATA(cmsg), sizeof(*inqv));
319b5188056SFlorian Westphal return;
320b5188056SFlorian Westphal }
321b5188056SFlorian Westphal }
322b5188056SFlorian Westphal
323b5188056SFlorian Westphal xerror("could not find TCP_CM_INQ cmsg type");
324b5188056SFlorian Westphal }
325b5188056SFlorian Westphal
process_one_client(int fd,int unixfd)326b5188056SFlorian Westphal static void process_one_client(int fd, int unixfd)
327b5188056SFlorian Westphal {
328b5188056SFlorian Westphal unsigned int tcp_inq;
329b5188056SFlorian Westphal size_t expect_len;
330b5188056SFlorian Westphal char msg_buf[4096];
331b5188056SFlorian Westphal char buf[4096];
332b5188056SFlorian Westphal char tmp[16];
333b5188056SFlorian Westphal struct iovec iov = {
334b5188056SFlorian Westphal .iov_base = buf,
335b5188056SFlorian Westphal .iov_len = 1,
336b5188056SFlorian Westphal };
337b5188056SFlorian Westphal struct msghdr msg = {
338b5188056SFlorian Westphal .msg_iov = &iov,
339b5188056SFlorian Westphal .msg_iovlen = 1,
340b5188056SFlorian Westphal .msg_control = msg_buf,
341b5188056SFlorian Westphal .msg_controllen = sizeof(msg_buf),
342b5188056SFlorian Westphal };
343b5188056SFlorian Westphal ssize_t ret, tot;
344b5188056SFlorian Westphal
345b5188056SFlorian Westphal ret = write(unixfd, "xmit", 4);
346b5188056SFlorian Westphal assert(ret == 4);
347b5188056SFlorian Westphal
348b5188056SFlorian Westphal ret = read(unixfd, &expect_len, sizeof(expect_len));
349b5188056SFlorian Westphal assert(ret == (ssize_t)sizeof(expect_len));
350b5188056SFlorian Westphal
351b5188056SFlorian Westphal if (expect_len > sizeof(buf))
352b5188056SFlorian Westphal xerror("expect len %zu exceeds buffer size", expect_len);
353b5188056SFlorian Westphal
354b5188056SFlorian Westphal for (;;) {
355b5188056SFlorian Westphal struct timespec req;
356b5188056SFlorian Westphal unsigned int queued;
357b5188056SFlorian Westphal
358b5188056SFlorian Westphal ret = ioctl(fd, FIONREAD, &queued);
359b5188056SFlorian Westphal if (ret < 0)
360b5188056SFlorian Westphal die_perror("FIONREAD");
361b5188056SFlorian Westphal if (queued > expect_len)
362b5188056SFlorian Westphal xerror("FIONREAD returned %u, but only %zu expected\n",
363b5188056SFlorian Westphal queued, expect_len);
364b5188056SFlorian Westphal if (queued == expect_len)
365b5188056SFlorian Westphal break;
366b5188056SFlorian Westphal
367b5188056SFlorian Westphal req.tv_sec = 0;
368b5188056SFlorian Westphal req.tv_nsec = 1000 * 1000ul;
369b5188056SFlorian Westphal nanosleep(&req, NULL);
370b5188056SFlorian Westphal }
371b5188056SFlorian Westphal
372b5188056SFlorian Westphal /* read one byte, expect cmsg to return expected - 1 */
373b5188056SFlorian Westphal ret = recvmsg(fd, &msg, 0);
374b5188056SFlorian Westphal if (ret < 0)
375b5188056SFlorian Westphal die_perror("recvmsg");
376b5188056SFlorian Westphal
377b5188056SFlorian Westphal if (msg.msg_controllen == 0)
378b5188056SFlorian Westphal xerror("msg_controllen is 0");
379b5188056SFlorian Westphal
380b5188056SFlorian Westphal get_tcp_inq(&msg, &tcp_inq);
381b5188056SFlorian Westphal
382b5188056SFlorian Westphal assert((size_t)tcp_inq == (expect_len - 1));
383b5188056SFlorian Westphal
384b5188056SFlorian Westphal iov.iov_len = sizeof(buf);
385b5188056SFlorian Westphal ret = recvmsg(fd, &msg, 0);
386b5188056SFlorian Westphal if (ret < 0)
387b5188056SFlorian Westphal die_perror("recvmsg");
388b5188056SFlorian Westphal
389b5188056SFlorian Westphal /* should have gotten exact remainder of all pending data */
390b5188056SFlorian Westphal assert(ret == (ssize_t)tcp_inq);
391b5188056SFlorian Westphal
392b5188056SFlorian Westphal /* should be 0, all drained */
393b5188056SFlorian Westphal get_tcp_inq(&msg, &tcp_inq);
394b5188056SFlorian Westphal assert(tcp_inq == 0);
395b5188056SFlorian Westphal
396b5188056SFlorian Westphal /* request a large swath of data. */
397b5188056SFlorian Westphal ret = write(unixfd, "huge", 4);
398b5188056SFlorian Westphal assert(ret == 4);
399b5188056SFlorian Westphal
400b5188056SFlorian Westphal ret = read(unixfd, &expect_len, sizeof(expect_len));
401b5188056SFlorian Westphal assert(ret == (ssize_t)sizeof(expect_len));
402b5188056SFlorian Westphal
403b5188056SFlorian Westphal /* peer should send us a few mb of data */
404b5188056SFlorian Westphal if (expect_len <= sizeof(buf))
405b5188056SFlorian Westphal xerror("expect len %zu too small\n", expect_len);
406b5188056SFlorian Westphal
407b5188056SFlorian Westphal tot = 0;
408b5188056SFlorian Westphal do {
409b5188056SFlorian Westphal iov.iov_len = sizeof(buf);
410b5188056SFlorian Westphal ret = recvmsg(fd, &msg, 0);
411b5188056SFlorian Westphal if (ret < 0)
412b5188056SFlorian Westphal die_perror("recvmsg");
413b5188056SFlorian Westphal
414b5188056SFlorian Westphal tot += ret;
415b5188056SFlorian Westphal
416b5188056SFlorian Westphal get_tcp_inq(&msg, &tcp_inq);
417b5188056SFlorian Westphal
418b5188056SFlorian Westphal if (tcp_inq > expect_len - tot)
419b5188056SFlorian Westphal xerror("inq %d, remaining %d total_len %d\n",
420b5188056SFlorian Westphal tcp_inq, expect_len - tot, (int)expect_len);
421b5188056SFlorian Westphal
422b5188056SFlorian Westphal assert(tcp_inq <= expect_len - tot);
423b5188056SFlorian Westphal } while ((size_t)tot < expect_len);
424b5188056SFlorian Westphal
425b5188056SFlorian Westphal ret = write(unixfd, "shut", 4);
426b5188056SFlorian Westphal assert(ret == 4);
427b5188056SFlorian Westphal
428b5188056SFlorian Westphal /* wait for hangup. Should have received one more byte of data. */
429b5188056SFlorian Westphal ret = read(unixfd, tmp, sizeof(tmp));
430b5188056SFlorian Westphal assert(ret == 6);
431b5188056SFlorian Westphal assert(strncmp(tmp, "closed", 6) == 0);
432b5188056SFlorian Westphal
433b5188056SFlorian Westphal sleep(1);
434b5188056SFlorian Westphal
435b5188056SFlorian Westphal iov.iov_len = 1;
436b5188056SFlorian Westphal ret = recvmsg(fd, &msg, 0);
437b5188056SFlorian Westphal if (ret < 0)
438b5188056SFlorian Westphal die_perror("recvmsg");
439b5188056SFlorian Westphal assert(ret == 1);
440b5188056SFlorian Westphal
441b5188056SFlorian Westphal get_tcp_inq(&msg, &tcp_inq);
442b5188056SFlorian Westphal
443b5188056SFlorian Westphal /* tcp_inq should be 1 due to received fin. */
444b5188056SFlorian Westphal assert(tcp_inq == 1);
445b5188056SFlorian Westphal
446b5188056SFlorian Westphal iov.iov_len = 1;
447b5188056SFlorian Westphal ret = recvmsg(fd, &msg, 0);
448b5188056SFlorian Westphal if (ret < 0)
449b5188056SFlorian Westphal die_perror("recvmsg");
450b5188056SFlorian Westphal
451b5188056SFlorian Westphal /* expect EOF */
452b5188056SFlorian Westphal assert(ret == 0);
453b5188056SFlorian Westphal get_tcp_inq(&msg, &tcp_inq);
454b5188056SFlorian Westphal assert(tcp_inq == 1);
455b5188056SFlorian Westphal
456b5188056SFlorian Westphal close(fd);
457b5188056SFlorian Westphal }
458b5188056SFlorian Westphal
xaccept(int s)459b5188056SFlorian Westphal static int xaccept(int s)
460b5188056SFlorian Westphal {
461b5188056SFlorian Westphal int fd = accept(s, NULL, 0);
462b5188056SFlorian Westphal
463b5188056SFlorian Westphal if (fd < 0)
464b5188056SFlorian Westphal die_perror("accept");
465b5188056SFlorian Westphal
466b5188056SFlorian Westphal return fd;
467b5188056SFlorian Westphal }
468b5188056SFlorian Westphal
server(int unixfd)469b5188056SFlorian Westphal static int server(int unixfd)
470b5188056SFlorian Westphal {
471b5188056SFlorian Westphal int fd = -1, r, on = 1;
472b5188056SFlorian Westphal
473b5188056SFlorian Westphal switch (pf) {
474b5188056SFlorian Westphal case AF_INET:
475b5188056SFlorian Westphal fd = sock_listen_mptcp("127.0.0.1", "15432");
476b5188056SFlorian Westphal break;
477b5188056SFlorian Westphal case AF_INET6:
478b5188056SFlorian Westphal fd = sock_listen_mptcp("::1", "15432");
479b5188056SFlorian Westphal break;
480b5188056SFlorian Westphal default:
481b5188056SFlorian Westphal xerror("Unknown pf %d\n", pf);
482b5188056SFlorian Westphal break;
483b5188056SFlorian Westphal }
484b5188056SFlorian Westphal
485b5188056SFlorian Westphal r = write(unixfd, "conn", 4);
486b5188056SFlorian Westphal assert(r == 4);
487b5188056SFlorian Westphal
488b5188056SFlorian Westphal alarm(15);
489b5188056SFlorian Westphal r = xaccept(fd);
490b5188056SFlorian Westphal
491b5188056SFlorian Westphal if (-1 == setsockopt(r, IPPROTO_TCP, TCP_INQ, &on, sizeof(on)))
492b5188056SFlorian Westphal die_perror("setsockopt");
493b5188056SFlorian Westphal
494b5188056SFlorian Westphal process_one_client(r, unixfd);
495b5188056SFlorian Westphal
496b5188056SFlorian Westphal return 0;
497b5188056SFlorian Westphal }
498b5188056SFlorian Westphal
client(int unixfd)499b5188056SFlorian Westphal static int client(int unixfd)
500b5188056SFlorian Westphal {
501b5188056SFlorian Westphal int fd = -1;
502b5188056SFlorian Westphal
503b5188056SFlorian Westphal alarm(15);
504b5188056SFlorian Westphal
505b5188056SFlorian Westphal switch (pf) {
506b5188056SFlorian Westphal case AF_INET:
507b5188056SFlorian Westphal fd = sock_connect_mptcp("127.0.0.1", "15432", proto_tx);
508b5188056SFlorian Westphal break;
509b5188056SFlorian Westphal case AF_INET6:
510b5188056SFlorian Westphal fd = sock_connect_mptcp("::1", "15432", proto_tx);
511b5188056SFlorian Westphal break;
512b5188056SFlorian Westphal default:
513b5188056SFlorian Westphal xerror("Unknown pf %d\n", pf);
514b5188056SFlorian Westphal }
515b5188056SFlorian Westphal
516b5188056SFlorian Westphal connect_one_server(fd, unixfd);
517b5188056SFlorian Westphal
518b5188056SFlorian Westphal return 0;
519b5188056SFlorian Westphal }
520b5188056SFlorian Westphal
init_rng(void)521b5188056SFlorian Westphal static void init_rng(void)
522b5188056SFlorian Westphal {
523b5188056SFlorian Westphal unsigned int foo;
524b5188056SFlorian Westphal
525*00a4f8fdSWillem de Bruijn if (getrandom(&foo, sizeof(foo), 0) == -1) {
526*00a4f8fdSWillem de Bruijn perror("getrandom");
527*00a4f8fdSWillem de Bruijn exit(1);
528b5188056SFlorian Westphal }
529b5188056SFlorian Westphal
530b5188056SFlorian Westphal srand(foo);
531b5188056SFlorian Westphal }
532b5188056SFlorian Westphal
xfork(void)533b5188056SFlorian Westphal static pid_t xfork(void)
534b5188056SFlorian Westphal {
535b5188056SFlorian Westphal pid_t p = fork();
536b5188056SFlorian Westphal
537b5188056SFlorian Westphal if (p < 0)
538b5188056SFlorian Westphal die_perror("fork");
539b5188056SFlorian Westphal else if (p == 0)
540b5188056SFlorian Westphal init_rng();
541b5188056SFlorian Westphal
542b5188056SFlorian Westphal return p;
543b5188056SFlorian Westphal }
544b5188056SFlorian Westphal
rcheck(int wstatus,const char * what)545b5188056SFlorian Westphal static int rcheck(int wstatus, const char *what)
546b5188056SFlorian Westphal {
547b5188056SFlorian Westphal if (WIFEXITED(wstatus)) {
548b5188056SFlorian Westphal if (WEXITSTATUS(wstatus) == 0)
549b5188056SFlorian Westphal return 0;
550b5188056SFlorian Westphal fprintf(stderr, "%s exited, status=%d\n", what, WEXITSTATUS(wstatus));
551b5188056SFlorian Westphal return WEXITSTATUS(wstatus);
552b5188056SFlorian Westphal } else if (WIFSIGNALED(wstatus)) {
553b5188056SFlorian Westphal xerror("%s killed by signal %d\n", what, WTERMSIG(wstatus));
554b5188056SFlorian Westphal } else if (WIFSTOPPED(wstatus)) {
555b5188056SFlorian Westphal xerror("%s stopped by signal %d\n", what, WSTOPSIG(wstatus));
556b5188056SFlorian Westphal }
557b5188056SFlorian Westphal
558b5188056SFlorian Westphal return 111;
559b5188056SFlorian Westphal }
560b5188056SFlorian Westphal
main(int argc,char * argv[])561b5188056SFlorian Westphal int main(int argc, char *argv[])
562b5188056SFlorian Westphal {
563b5188056SFlorian Westphal int e1, e2, wstatus;
564b5188056SFlorian Westphal pid_t s, c, ret;
565b5188056SFlorian Westphal int unixfds[2];
566b5188056SFlorian Westphal
567b5188056SFlorian Westphal parse_opts(argc, argv);
568b5188056SFlorian Westphal
569b5188056SFlorian Westphal e1 = socketpair(AF_UNIX, SOCK_DGRAM, 0, unixfds);
570b5188056SFlorian Westphal if (e1 < 0)
571b5188056SFlorian Westphal die_perror("pipe");
572b5188056SFlorian Westphal
573b5188056SFlorian Westphal s = xfork();
574b5188056SFlorian Westphal if (s == 0)
575b5188056SFlorian Westphal return server(unixfds[1]);
576b5188056SFlorian Westphal
577b5188056SFlorian Westphal close(unixfds[1]);
578b5188056SFlorian Westphal
579b5188056SFlorian Westphal /* wait until server bound a socket */
580b5188056SFlorian Westphal e1 = read(unixfds[0], &e1, 4);
581b5188056SFlorian Westphal assert(e1 == 4);
582b5188056SFlorian Westphal
583b5188056SFlorian Westphal c = xfork();
584b5188056SFlorian Westphal if (c == 0)
585b5188056SFlorian Westphal return client(unixfds[0]);
586b5188056SFlorian Westphal
587b5188056SFlorian Westphal close(unixfds[0]);
588b5188056SFlorian Westphal
589b5188056SFlorian Westphal ret = waitpid(s, &wstatus, 0);
590b5188056SFlorian Westphal if (ret == -1)
591b5188056SFlorian Westphal die_perror("waitpid");
592b5188056SFlorian Westphal e1 = rcheck(wstatus, "server");
593b5188056SFlorian Westphal ret = waitpid(c, &wstatus, 0);
594b5188056SFlorian Westphal if (ret == -1)
595b5188056SFlorian Westphal die_perror("waitpid");
596b5188056SFlorian Westphal e2 = rcheck(wstatus, "client");
597b5188056SFlorian Westphal
598b5188056SFlorian Westphal return e1 ? e1 : e2;
599b5188056SFlorian Westphal }
600