PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/tools/testing/selftests/net/mptcp/mptcp_connect.c

https://gitlab.com/pachecof/centos-stream-9
C | 1263 lines | 999 code | 242 blank | 22 comment | 232 complexity | 0554dba4f8e17f2d78157c98420cb9e7 MD5 | raw file
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <errno.h>
  4. #include <limits.h>
  5. #include <fcntl.h>
  6. #include <string.h>
  7. #include <stdarg.h>
  8. #include <stdbool.h>
  9. #include <stdint.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <strings.h>
  13. #include <signal.h>
  14. #include <unistd.h>
  15. #include <time.h>
  16. #include <sys/poll.h>
  17. #include <sys/sendfile.h>
  18. #include <sys/stat.h>
  19. #include <sys/socket.h>
  20. #include <sys/types.h>
  21. #include <sys/mman.h>
  22. #include <netdb.h>
  23. #include <netinet/in.h>
  24. #include <linux/tcp.h>
  25. #include <linux/time_types.h>
  26. extern int optind;
  27. #ifndef IPPROTO_MPTCP
  28. #define IPPROTO_MPTCP 262
  29. #endif
  30. #ifndef TCP_ULP
  31. #define TCP_ULP 31
  32. #endif
  33. static int poll_timeout = 10 * 1000;
  34. static bool listen_mode;
  35. static bool quit;
  36. enum cfg_mode {
  37. CFG_MODE_POLL,
  38. CFG_MODE_MMAP,
  39. CFG_MODE_SENDFILE,
  40. };
  41. enum cfg_peek {
  42. CFG_NONE_PEEK,
  43. CFG_WITH_PEEK,
  44. CFG_AFTER_PEEK,
  45. };
  46. static enum cfg_mode cfg_mode = CFG_MODE_POLL;
  47. static enum cfg_peek cfg_peek = CFG_NONE_PEEK;
  48. static const char *cfg_host;
  49. static const char *cfg_port = "12000";
  50. static int cfg_sock_proto = IPPROTO_MPTCP;
  51. static int pf = AF_INET;
  52. static int cfg_sndbuf;
  53. static int cfg_rcvbuf;
  54. static bool cfg_join;
  55. static bool cfg_remove;
  56. static unsigned int cfg_time;
  57. static unsigned int cfg_do_w;
  58. static int cfg_wait;
  59. static uint32_t cfg_mark;
  60. struct cfg_cmsg_types {
  61. unsigned int cmsg_enabled:1;
  62. unsigned int timestampns:1;
  63. unsigned int tcp_inq:1;
  64. };
  65. struct cfg_sockopt_types {
  66. unsigned int transparent:1;
  67. };
  68. struct tcp_inq_state {
  69. unsigned int last;
  70. bool expect_eof;
  71. };
  72. static struct tcp_inq_state tcp_inq;
  73. static struct cfg_cmsg_types cfg_cmsg_types;
  74. static struct cfg_sockopt_types cfg_sockopt_types;
  75. static void die_usage(void)
  76. {
  77. fprintf(stderr, "Usage: mptcp_connect [-6] [-u] [-s MPTCP|TCP] [-p port] [-m mode]"
  78. "[-l] [-w sec] [-t num] [-T num] connect_address\n");
  79. fprintf(stderr, "\t-6 use ipv6\n");
  80. fprintf(stderr, "\t-t num -- set poll timeout to num\n");
  81. fprintf(stderr, "\t-T num -- set expected runtime to num ms\n");
  82. fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n");
  83. fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n");
  84. fprintf(stderr, "\t-p num -- use port num\n");
  85. fprintf(stderr, "\t-s [MPTCP|TCP] -- use mptcp(default) or tcp sockets\n");
  86. fprintf(stderr, "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n");
  87. fprintf(stderr, "\t-M mark -- set socket packet mark\n");
  88. fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
  89. fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n");
  90. fprintf(stderr, "\t-o option -- test sockopt <option>\n");
  91. fprintf(stderr,
  92. "\t-P [saveWithPeek|saveAfterPeek] -- save data with/after MSG_PEEK form tcp socket\n");
  93. exit(1);
  94. }
  95. static void xerror(const char *fmt, ...)
  96. {
  97. va_list ap;
  98. va_start(ap, fmt);
  99. vfprintf(stderr, fmt, ap);
  100. va_end(ap);
  101. exit(1);
  102. }
  103. static void handle_signal(int nr)
  104. {
  105. quit = true;
  106. }
  107. static const char *getxinfo_strerr(int err)
  108. {
  109. if (err == EAI_SYSTEM)
  110. return strerror(errno);
  111. return gai_strerror(err);
  112. }
  113. static void xgetnameinfo(const struct sockaddr *addr, socklen_t addrlen,
  114. char *host, socklen_t hostlen,
  115. char *serv, socklen_t servlen)
  116. {
  117. int flags = NI_NUMERICHOST | NI_NUMERICSERV;
  118. int err = getnameinfo(addr, addrlen, host, hostlen, serv, servlen,
  119. flags);
  120. if (err) {
  121. const char *errstr = getxinfo_strerr(err);
  122. fprintf(stderr, "Fatal: getnameinfo: %s\n", errstr);
  123. exit(1);
  124. }
  125. }
  126. static void xgetaddrinfo(const char *node, const char *service,
  127. const struct addrinfo *hints,
  128. struct addrinfo **res)
  129. {
  130. int err = getaddrinfo(node, service, hints, res);
  131. if (err) {
  132. const char *errstr = getxinfo_strerr(err);
  133. fprintf(stderr, "Fatal: getaddrinfo(%s:%s): %s\n",
  134. node ? node : "", service ? service : "", errstr);
  135. exit(1);
  136. }
  137. }
  138. static void set_rcvbuf(int fd, unsigned int size)
  139. {
  140. int err;
  141. err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
  142. if (err) {
  143. perror("set SO_RCVBUF");
  144. exit(1);
  145. }
  146. }
  147. static void set_sndbuf(int fd, unsigned int size)
  148. {
  149. int err;
  150. err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
  151. if (err) {
  152. perror("set SO_SNDBUF");
  153. exit(1);
  154. }
  155. }
  156. static void set_mark(int fd, uint32_t mark)
  157. {
  158. int err;
  159. err = setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
  160. if (err) {
  161. perror("set SO_MARK");
  162. exit(1);
  163. }
  164. }
  165. static void set_transparent(int fd, int pf)
  166. {
  167. int one = 1;
  168. switch (pf) {
  169. case AF_INET:
  170. if (-1 == setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)))
  171. perror("IP_TRANSPARENT");
  172. break;
  173. case AF_INET6:
  174. if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)))
  175. perror("IPV6_TRANSPARENT");
  176. break;
  177. }
  178. }
  179. static int do_ulp_so(int sock, const char *name)
  180. {
  181. return setsockopt(sock, IPPROTO_TCP, TCP_ULP, name, strlen(name));
  182. }
  183. #define X(m) xerror("%s:%u: %s: failed for proto %d at line %u", __FILE__, __LINE__, (m), proto, line)
  184. static void sock_test_tcpulp(int sock, int proto, unsigned int line)
  185. {
  186. socklen_t buflen = 8;
  187. char buf[8] = "";
  188. int ret = getsockopt(sock, IPPROTO_TCP, TCP_ULP, buf, &buflen);
  189. if (ret != 0)
  190. X("getsockopt");
  191. if (buflen > 0) {
  192. if (strcmp(buf, "mptcp") != 0)
  193. xerror("unexpected ULP '%s' for proto %d at line %u", buf, proto, line);
  194. ret = do_ulp_so(sock, "tls");
  195. if (ret == 0)
  196. X("setsockopt");
  197. } else if (proto == IPPROTO_MPTCP) {
  198. ret = do_ulp_so(sock, "tls");
  199. if (ret != -1)
  200. X("setsockopt");
  201. }
  202. ret = do_ulp_so(sock, "mptcp");
  203. if (ret != -1)
  204. X("setsockopt");
  205. #undef X
  206. }
  207. #define SOCK_TEST_TCPULP(s, p) sock_test_tcpulp((s), (p), __LINE__)
  208. static int sock_listen_mptcp(const char * const listenaddr,
  209. const char * const port)
  210. {
  211. int sock;
  212. struct addrinfo hints = {
  213. .ai_protocol = IPPROTO_TCP,
  214. .ai_socktype = SOCK_STREAM,
  215. .ai_flags = AI_PASSIVE | AI_NUMERICHOST
  216. };
  217. hints.ai_family = pf;
  218. struct addrinfo *a, *addr;
  219. int one = 1;
  220. xgetaddrinfo(listenaddr, port, &hints, &addr);
  221. hints.ai_family = pf;
  222. for (a = addr; a; a = a->ai_next) {
  223. sock = socket(a->ai_family, a->ai_socktype, cfg_sock_proto);
  224. if (sock < 0)
  225. continue;
  226. SOCK_TEST_TCPULP(sock, cfg_sock_proto);
  227. if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
  228. sizeof(one)))
  229. perror("setsockopt");
  230. if (cfg_sockopt_types.transparent)
  231. set_transparent(sock, pf);
  232. if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
  233. break; /* success */
  234. perror("bind");
  235. close(sock);
  236. sock = -1;
  237. }
  238. freeaddrinfo(addr);
  239. if (sock < 0) {
  240. fprintf(stderr, "Could not create listen socket\n");
  241. return sock;
  242. }
  243. SOCK_TEST_TCPULP(sock, cfg_sock_proto);
  244. if (listen(sock, 20)) {
  245. perror("listen");
  246. close(sock);
  247. return -1;
  248. }
  249. SOCK_TEST_TCPULP(sock, cfg_sock_proto);
  250. return sock;
  251. }
  252. static int sock_connect_mptcp(const char * const remoteaddr,
  253. const char * const port, int proto)
  254. {
  255. struct addrinfo hints = {
  256. .ai_protocol = IPPROTO_TCP,
  257. .ai_socktype = SOCK_STREAM,
  258. };
  259. struct addrinfo *a, *addr;
  260. int sock = -1;
  261. hints.ai_family = pf;
  262. xgetaddrinfo(remoteaddr, port, &hints, &addr);
  263. for (a = addr; a; a = a->ai_next) {
  264. sock = socket(a->ai_family, a->ai_socktype, proto);
  265. if (sock < 0) {
  266. perror("socket");
  267. continue;
  268. }
  269. SOCK_TEST_TCPULP(sock, proto);
  270. if (cfg_mark)
  271. set_mark(sock, cfg_mark);
  272. if (connect(sock, a->ai_addr, a->ai_addrlen) == 0)
  273. break; /* success */
  274. perror("connect()");
  275. close(sock);
  276. sock = -1;
  277. }
  278. freeaddrinfo(addr);
  279. if (sock != -1)
  280. SOCK_TEST_TCPULP(sock, proto);
  281. return sock;
  282. }
  283. static size_t do_rnd_write(const int fd, char *buf, const size_t len)
  284. {
  285. static bool first = true;
  286. unsigned int do_w;
  287. ssize_t bw;
  288. do_w = rand() & 0xffff;
  289. if (do_w == 0 || do_w > len)
  290. do_w = len;
  291. if (cfg_join && first && do_w > 100)
  292. do_w = 100;
  293. if (cfg_remove && do_w > cfg_do_w)
  294. do_w = cfg_do_w;
  295. bw = write(fd, buf, do_w);
  296. if (bw < 0)
  297. perror("write");
  298. /* let the join handshake complete, before going on */
  299. if (cfg_join && first) {
  300. usleep(200000);
  301. first = false;
  302. }
  303. if (cfg_remove)
  304. usleep(200000);
  305. return bw;
  306. }
  307. static size_t do_write(const int fd, char *buf, const size_t len)
  308. {
  309. size_t offset = 0;
  310. while (offset < len) {
  311. size_t written;
  312. ssize_t bw;
  313. bw = write(fd, buf + offset, len - offset);
  314. if (bw < 0) {
  315. perror("write");
  316. return 0;
  317. }
  318. written = (size_t)bw;
  319. offset += written;
  320. }
  321. return offset;
  322. }
  323. static void process_cmsg(struct msghdr *msgh)
  324. {
  325. struct __kernel_timespec ts;
  326. bool inq_found = false;
  327. bool ts_found = false;
  328. unsigned int inq = 0;
  329. struct cmsghdr *cmsg;
  330. for (cmsg = CMSG_FIRSTHDR(msgh); cmsg ; cmsg = CMSG_NXTHDR(msgh, cmsg)) {
  331. if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPNS_NEW) {
  332. memcpy(&ts, CMSG_DATA(cmsg), sizeof(ts));
  333. ts_found = true;
  334. continue;
  335. }
  336. if (cmsg->cmsg_level == IPPROTO_TCP && cmsg->cmsg_type == TCP_CM_INQ) {
  337. memcpy(&inq, CMSG_DATA(cmsg), sizeof(inq));
  338. inq_found = true;
  339. continue;
  340. }
  341. }
  342. if (cfg_cmsg_types.timestampns) {
  343. if (!ts_found)
  344. xerror("TIMESTAMPNS not present\n");
  345. }
  346. if (cfg_cmsg_types.tcp_inq) {
  347. if (!inq_found)
  348. xerror("TCP_INQ not present\n");
  349. if (inq > 1024)
  350. xerror("tcp_inq %u is larger than one kbyte\n", inq);
  351. tcp_inq.last = inq;
  352. }
  353. }
  354. static ssize_t do_recvmsg_cmsg(const int fd, char *buf, const size_t len)
  355. {
  356. char msg_buf[8192];
  357. struct iovec iov = {
  358. .iov_base = buf,
  359. .iov_len = len,
  360. };
  361. struct msghdr msg = {
  362. .msg_iov = &iov,
  363. .msg_iovlen = 1,
  364. .msg_control = msg_buf,
  365. .msg_controllen = sizeof(msg_buf),
  366. };
  367. int flags = 0;
  368. unsigned int last_hint = tcp_inq.last;
  369. int ret = recvmsg(fd, &msg, flags);
  370. if (ret <= 0) {
  371. if (ret == 0 && tcp_inq.expect_eof)
  372. return ret;
  373. if (ret == 0 && cfg_cmsg_types.tcp_inq)
  374. if (last_hint != 1 && last_hint != 0)
  375. xerror("EOF but last tcp_inq hint was %u\n", last_hint);
  376. return ret;
  377. }
  378. if (tcp_inq.expect_eof)
  379. xerror("expected EOF, last_hint %u, now %u\n",
  380. last_hint, tcp_inq.last);
  381. if (msg.msg_controllen && !cfg_cmsg_types.cmsg_enabled)
  382. xerror("got %lu bytes of cmsg data, expected 0\n",
  383. (unsigned long)msg.msg_controllen);
  384. if (msg.msg_controllen == 0 && cfg_cmsg_types.cmsg_enabled)
  385. xerror("%s\n", "got no cmsg data");
  386. if (msg.msg_controllen)
  387. process_cmsg(&msg);
  388. if (cfg_cmsg_types.tcp_inq) {
  389. if ((size_t)ret < len && last_hint > (unsigned int)ret) {
  390. if (ret + 1 != (int)last_hint) {
  391. int next = read(fd, msg_buf, sizeof(msg_buf));
  392. xerror("read %u of %u, last_hint was %u tcp_inq hint now %u next_read returned %d/%m\n",
  393. ret, (unsigned int)len, last_hint, tcp_inq.last, next);
  394. } else {
  395. tcp_inq.expect_eof = true;
  396. }
  397. }
  398. }
  399. return ret;
  400. }
  401. static ssize_t do_rnd_read(const int fd, char *buf, const size_t len)
  402. {
  403. int ret = 0;
  404. char tmp[16384];
  405. size_t cap = rand();
  406. cap &= 0xffff;
  407. if (cap == 0)
  408. cap = 1;
  409. else if (cap > len)
  410. cap = len;
  411. if (cfg_peek == CFG_WITH_PEEK) {
  412. ret = recv(fd, buf, cap, MSG_PEEK);
  413. ret = (ret < 0) ? ret : read(fd, tmp, ret);
  414. } else if (cfg_peek == CFG_AFTER_PEEK) {
  415. ret = recv(fd, buf, cap, MSG_PEEK);
  416. ret = (ret < 0) ? ret : read(fd, buf, cap);
  417. } else if (cfg_cmsg_types.cmsg_enabled) {
  418. ret = do_recvmsg_cmsg(fd, buf, cap);
  419. } else {
  420. ret = read(fd, buf, cap);
  421. }
  422. return ret;
  423. }
  424. static void set_nonblock(int fd)
  425. {
  426. int flags = fcntl(fd, F_GETFL);
  427. if (flags == -1)
  428. return;
  429. fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  430. }
  431. static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after_out)
  432. {
  433. struct pollfd fds = {
  434. .fd = peerfd,
  435. .events = POLLIN | POLLOUT,
  436. };
  437. unsigned int woff = 0, wlen = 0;
  438. char wbuf[8192];
  439. set_nonblock(peerfd);
  440. for (;;) {
  441. char rbuf[8192];
  442. ssize_t len;
  443. if (fds.events == 0)
  444. break;
  445. switch (poll(&fds, 1, poll_timeout)) {
  446. case -1:
  447. if (errno == EINTR)
  448. continue;
  449. perror("poll");
  450. return 1;
  451. case 0:
  452. fprintf(stderr, "%s: poll timed out (events: "
  453. "POLLIN %u, POLLOUT %u)\n", __func__,
  454. fds.events & POLLIN, fds.events & POLLOUT);
  455. return 2;
  456. }
  457. if (fds.revents & POLLIN) {
  458. len = do_rnd_read(peerfd, rbuf, sizeof(rbuf));
  459. if (len == 0) {
  460. /* no more data to receive:
  461. * peer has closed its write side
  462. */
  463. fds.events &= ~POLLIN;
  464. if ((fds.events & POLLOUT) == 0) {
  465. *in_closed_after_out = true;
  466. /* and nothing more to send */
  467. break;
  468. }
  469. /* Else, still have data to transmit */
  470. } else if (len < 0) {
  471. perror("read");
  472. return 3;
  473. }
  474. do_write(outfd, rbuf, len);
  475. }
  476. if (fds.revents & POLLOUT) {
  477. if (wlen == 0) {
  478. woff = 0;
  479. wlen = read(infd, wbuf, sizeof(wbuf));
  480. }
  481. if (wlen > 0) {
  482. ssize_t bw;
  483. bw = do_rnd_write(peerfd, wbuf + woff, wlen);
  484. if (bw < 0)
  485. return 111;
  486. woff += bw;
  487. wlen -= bw;
  488. } else if (wlen == 0) {
  489. /* We have no more data to send. */
  490. fds.events &= ~POLLOUT;
  491. if ((fds.events & POLLIN) == 0)
  492. /* ... and peer also closed already */
  493. break;
  494. /* ... but we still receive.
  495. * Close our write side, ev. give some time
  496. * for address notification and/or checking
  497. * the current status
  498. */
  499. if (cfg_wait)
  500. usleep(cfg_wait);
  501. shutdown(peerfd, SHUT_WR);
  502. } else {
  503. if (errno == EINTR)
  504. continue;
  505. perror("read");
  506. return 4;
  507. }
  508. }
  509. if (fds.revents & (POLLERR | POLLNVAL)) {
  510. fprintf(stderr, "Unexpected revents: "
  511. "POLLERR/POLLNVAL(%x)\n", fds.revents);
  512. return 5;
  513. }
  514. }
  515. /* leave some time for late join/announce */
  516. if (cfg_remove)
  517. usleep(cfg_wait);
  518. close(peerfd);
  519. return 0;
  520. }
  521. static int do_recvfile(int infd, int outfd)
  522. {
  523. ssize_t r;
  524. do {
  525. char buf[16384];
  526. r = do_rnd_read(infd, buf, sizeof(buf));
  527. if (r > 0) {
  528. if (write(outfd, buf, r) != r)
  529. break;
  530. } else if (r < 0) {
  531. perror("read");
  532. }
  533. } while (r > 0);
  534. return (int)r;
  535. }
  536. static int do_mmap(int infd, int outfd, unsigned int size)
  537. {
  538. char *inbuf = mmap(NULL, size, PROT_READ, MAP_SHARED, infd, 0);
  539. ssize_t ret = 0, off = 0;
  540. size_t rem;
  541. if (inbuf == MAP_FAILED) {
  542. perror("mmap");
  543. return 1;
  544. }
  545. rem = size;
  546. while (rem > 0) {
  547. ret = write(outfd, inbuf + off, rem);
  548. if (ret < 0) {
  549. perror("write");
  550. break;
  551. }
  552. off += ret;
  553. rem -= ret;
  554. }
  555. munmap(inbuf, size);
  556. return rem;
  557. }
  558. static int get_infd_size(int fd)
  559. {
  560. struct stat sb;
  561. ssize_t count;
  562. int err;
  563. err = fstat(fd, &sb);
  564. if (err < 0) {
  565. perror("fstat");
  566. return -1;
  567. }
  568. if ((sb.st_mode & S_IFMT) != S_IFREG) {
  569. fprintf(stderr, "%s: stdin is not a regular file\n", __func__);
  570. return -2;
  571. }
  572. count = sb.st_size;
  573. if (count > INT_MAX) {
  574. fprintf(stderr, "File too large: %zu\n", count);
  575. return -3;
  576. }
  577. return (int)count;
  578. }
  579. static int do_sendfile(int infd, int outfd, unsigned int count)
  580. {
  581. while (count > 0) {
  582. ssize_t r;
  583. r = sendfile(outfd, infd, NULL, count);
  584. if (r < 0) {
  585. perror("sendfile");
  586. return 3;
  587. }
  588. count -= r;
  589. }
  590. return 0;
  591. }
  592. static int copyfd_io_mmap(int infd, int peerfd, int outfd,
  593. unsigned int size, bool *in_closed_after_out)
  594. {
  595. int err;
  596. if (listen_mode) {
  597. err = do_recvfile(peerfd, outfd);
  598. if (err)
  599. return err;
  600. err = do_mmap(infd, peerfd, size);
  601. } else {
  602. err = do_mmap(infd, peerfd, size);
  603. if (err)
  604. return err;
  605. shutdown(peerfd, SHUT_WR);
  606. err = do_recvfile(peerfd, outfd);
  607. *in_closed_after_out = true;
  608. }
  609. return err;
  610. }
  611. static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
  612. unsigned int size, bool *in_closed_after_out)
  613. {
  614. int err;
  615. if (listen_mode) {
  616. err = do_recvfile(peerfd, outfd);
  617. if (err)
  618. return err;
  619. err = do_sendfile(infd, peerfd, size);
  620. } else {
  621. err = do_sendfile(infd, peerfd, size);
  622. if (err)
  623. return err;
  624. err = do_recvfile(peerfd, outfd);
  625. *in_closed_after_out = true;
  626. }
  627. return err;
  628. }
  629. static int copyfd_io(int infd, int peerfd, int outfd)
  630. {
  631. bool in_closed_after_out = false;
  632. struct timespec start, end;
  633. int file_size;
  634. int ret;
  635. if (cfg_time && (clock_gettime(CLOCK_MONOTONIC, &start) < 0))
  636. xerror("can not fetch start time %d", errno);
  637. switch (cfg_mode) {
  638. case CFG_MODE_POLL:
  639. ret = copyfd_io_poll(infd, peerfd, outfd, &in_closed_after_out);
  640. break;
  641. case CFG_MODE_MMAP:
  642. file_size = get_infd_size(infd);
  643. if (file_size < 0)
  644. return file_size;
  645. ret = copyfd_io_mmap(infd, peerfd, outfd, file_size, &in_closed_after_out);
  646. break;
  647. case CFG_MODE_SENDFILE:
  648. file_size = get_infd_size(infd);
  649. if (file_size < 0)
  650. return file_size;
  651. ret = copyfd_io_sendfile(infd, peerfd, outfd, file_size, &in_closed_after_out);
  652. break;
  653. default:
  654. fprintf(stderr, "Invalid mode %d\n", cfg_mode);
  655. die_usage();
  656. return 1;
  657. }
  658. if (ret)
  659. return ret;
  660. if (cfg_time) {
  661. unsigned int delta_ms;
  662. if (clock_gettime(CLOCK_MONOTONIC, &end) < 0)
  663. xerror("can not fetch end time %d", errno);
  664. delta_ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000;
  665. if (delta_ms > cfg_time) {
  666. xerror("transfer slower than expected! runtime %d ms, expected %d ms",
  667. delta_ms, cfg_time);
  668. }
  669. /* show the runtime only if this end shutdown(wr) before receiving the EOF,
  670. * (that is, if this end got the longer runtime)
  671. */
  672. if (in_closed_after_out)
  673. fprintf(stderr, "%d", delta_ms);
  674. }
  675. return 0;
  676. }
  677. static void check_sockaddr(int pf, struct sockaddr_storage *ss,
  678. socklen_t salen)
  679. {
  680. struct sockaddr_in6 *sin6;
  681. struct sockaddr_in *sin;
  682. socklen_t wanted_size = 0;
  683. switch (pf) {
  684. case AF_INET:
  685. wanted_size = sizeof(*sin);
  686. sin = (void *)ss;
  687. if (!sin->sin_port)
  688. fprintf(stderr, "accept: something wrong: ip connection from port 0");
  689. break;
  690. case AF_INET6:
  691. wanted_size = sizeof(*sin6);
  692. sin6 = (void *)ss;
  693. if (!sin6->sin6_port)
  694. fprintf(stderr, "accept: something wrong: ipv6 connection from port 0");
  695. break;
  696. default:
  697. fprintf(stderr, "accept: Unknown pf %d, salen %u\n", pf, salen);
  698. return;
  699. }
  700. if (salen != wanted_size)
  701. fprintf(stderr, "accept: size mismatch, got %d expected %d\n",
  702. (int)salen, wanted_size);
  703. if (ss->ss_family != pf)
  704. fprintf(stderr, "accept: pf mismatch, expect %d, ss_family is %d\n",
  705. (int)ss->ss_family, pf);
  706. }
  707. static void check_getpeername(int fd, struct sockaddr_storage *ss, socklen_t salen)
  708. {
  709. struct sockaddr_storage peerss;
  710. socklen_t peersalen = sizeof(peerss);
  711. if (getpeername(fd, (struct sockaddr *)&peerss, &peersalen) < 0) {
  712. perror("getpeername");
  713. return;
  714. }
  715. if (peersalen != salen) {
  716. fprintf(stderr, "%s: %d vs %d\n", __func__, peersalen, salen);
  717. return;
  718. }
  719. if (memcmp(ss, &peerss, peersalen)) {
  720. char a[INET6_ADDRSTRLEN];
  721. char b[INET6_ADDRSTRLEN];
  722. char c[INET6_ADDRSTRLEN];
  723. char d[INET6_ADDRSTRLEN];
  724. xgetnameinfo((struct sockaddr *)ss, salen,
  725. a, sizeof(a), b, sizeof(b));
  726. xgetnameinfo((struct sockaddr *)&peerss, peersalen,
  727. c, sizeof(c), d, sizeof(d));
  728. fprintf(stderr, "%s: memcmp failure: accept %s vs peername %s, %s vs %s salen %d vs %d\n",
  729. __func__, a, c, b, d, peersalen, salen);
  730. }
  731. }
  732. static void check_getpeername_connect(int fd)
  733. {
  734. struct sockaddr_storage ss;
  735. socklen_t salen = sizeof(ss);
  736. char a[INET6_ADDRSTRLEN];
  737. char b[INET6_ADDRSTRLEN];
  738. if (getpeername(fd, (struct sockaddr *)&ss, &salen) < 0) {
  739. perror("getpeername");
  740. return;
  741. }
  742. xgetnameinfo((struct sockaddr *)&ss, salen,
  743. a, sizeof(a), b, sizeof(b));
  744. if (strcmp(cfg_host, a) || strcmp(cfg_port, b))
  745. fprintf(stderr, "%s: %s vs %s, %s vs %s\n", __func__,
  746. cfg_host, a, cfg_port, b);
  747. }
  748. static void maybe_close(int fd)
  749. {
  750. unsigned int r = rand();
  751. if (!(cfg_join || cfg_remove) && (r & 1))
  752. close(fd);
  753. }
  754. int main_loop_s(int listensock)
  755. {
  756. struct sockaddr_storage ss;
  757. struct pollfd polls;
  758. socklen_t salen;
  759. int remotesock;
  760. polls.fd = listensock;
  761. polls.events = POLLIN;
  762. switch (poll(&polls, 1, poll_timeout)) {
  763. case -1:
  764. perror("poll");
  765. return 1;
  766. case 0:
  767. fprintf(stderr, "%s: timed out\n", __func__);
  768. close(listensock);
  769. return 2;
  770. }
  771. salen = sizeof(ss);
  772. remotesock = accept(listensock, (struct sockaddr *)&ss, &salen);
  773. if (remotesock >= 0) {
  774. maybe_close(listensock);
  775. check_sockaddr(pf, &ss, salen);
  776. check_getpeername(remotesock, &ss, salen);
  777. SOCK_TEST_TCPULP(remotesock, 0);
  778. return copyfd_io(0, remotesock, 1);
  779. }
  780. perror("accept");
  781. return 1;
  782. }
  783. static void init_rng(void)
  784. {
  785. int fd = open("/dev/urandom", O_RDONLY);
  786. unsigned int foo;
  787. if (fd > 0) {
  788. int ret = read(fd, &foo, sizeof(foo));
  789. if (ret < 0)
  790. srand(fd + foo);
  791. close(fd);
  792. }
  793. srand(foo);
  794. }
  795. static void xsetsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
  796. {
  797. int err;
  798. err = setsockopt(fd, level, optname, optval, optlen);
  799. if (err) {
  800. perror("setsockopt");
  801. exit(1);
  802. }
  803. }
  804. static void apply_cmsg_types(int fd, const struct cfg_cmsg_types *cmsg)
  805. {
  806. static const unsigned int on = 1;
  807. if (cmsg->timestampns)
  808. xsetsockopt(fd, SOL_SOCKET, SO_TIMESTAMPNS_NEW, &on, sizeof(on));
  809. if (cmsg->tcp_inq)
  810. xsetsockopt(fd, IPPROTO_TCP, TCP_INQ, &on, sizeof(on));
  811. }
  812. static void parse_cmsg_types(const char *type)
  813. {
  814. char *next = strchr(type, ',');
  815. unsigned int len = 0;
  816. cfg_cmsg_types.cmsg_enabled = 1;
  817. if (next) {
  818. parse_cmsg_types(next + 1);
  819. len = next - type;
  820. } else {
  821. len = strlen(type);
  822. }
  823. if (strncmp(type, "TIMESTAMPNS", len) == 0) {
  824. cfg_cmsg_types.timestampns = 1;
  825. return;
  826. }
  827. if (strncmp(type, "TCPINQ", len) == 0) {
  828. cfg_cmsg_types.tcp_inq = 1;
  829. return;
  830. }
  831. fprintf(stderr, "Unrecognized cmsg option %s\n", type);
  832. exit(1);
  833. }
  834. static void parse_setsock_options(const char *name)
  835. {
  836. char *next = strchr(name, ',');
  837. unsigned int len = 0;
  838. if (next) {
  839. parse_setsock_options(next + 1);
  840. len = next - name;
  841. } else {
  842. len = strlen(name);
  843. }
  844. if (strncmp(name, "TRANSPARENT", len) == 0) {
  845. cfg_sockopt_types.transparent = 1;
  846. return;
  847. }
  848. fprintf(stderr, "Unrecognized setsockopt option %s\n", name);
  849. exit(1);
  850. }
  851. int main_loop(void)
  852. {
  853. int fd;
  854. /* listener is ready. */
  855. fd = sock_connect_mptcp(cfg_host, cfg_port, cfg_sock_proto);
  856. if (fd < 0)
  857. return 2;
  858. check_getpeername_connect(fd);
  859. SOCK_TEST_TCPULP(fd, cfg_sock_proto);
  860. if (cfg_rcvbuf)
  861. set_rcvbuf(fd, cfg_rcvbuf);
  862. if (cfg_sndbuf)
  863. set_sndbuf(fd, cfg_sndbuf);
  864. if (cfg_cmsg_types.cmsg_enabled)
  865. apply_cmsg_types(fd, &cfg_cmsg_types);
  866. return copyfd_io(0, fd, 1);
  867. }
  868. int parse_proto(const char *proto)
  869. {
  870. if (!strcasecmp(proto, "MPTCP"))
  871. return IPPROTO_MPTCP;
  872. if (!strcasecmp(proto, "TCP"))
  873. return IPPROTO_TCP;
  874. fprintf(stderr, "Unknown protocol: %s\n.", proto);
  875. die_usage();
  876. /* silence compiler warning */
  877. return 0;
  878. }
  879. int parse_mode(const char *mode)
  880. {
  881. if (!strcasecmp(mode, "poll"))
  882. return CFG_MODE_POLL;
  883. if (!strcasecmp(mode, "mmap"))
  884. return CFG_MODE_MMAP;
  885. if (!strcasecmp(mode, "sendfile"))
  886. return CFG_MODE_SENDFILE;
  887. fprintf(stderr, "Unknown test mode: %s\n", mode);
  888. fprintf(stderr, "Supported modes are:\n");
  889. fprintf(stderr, "\t\t\"poll\" - interleaved read/write using poll()\n");
  890. fprintf(stderr, "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n");
  891. fprintf(stderr, "\t\t\"sendfile\" - send entire input file (sendfile), then read response (-l will read input first)\n");
  892. die_usage();
  893. /* silence compiler warning */
  894. return 0;
  895. }
  896. int parse_peek(const char *mode)
  897. {
  898. if (!strcasecmp(mode, "saveWithPeek"))
  899. return CFG_WITH_PEEK;
  900. if (!strcasecmp(mode, "saveAfterPeek"))
  901. return CFG_AFTER_PEEK;
  902. fprintf(stderr, "Unknown: %s\n", mode);
  903. fprintf(stderr, "Supported MSG_PEEK mode are:\n");
  904. fprintf(stderr,
  905. "\t\t\"saveWithPeek\" - recv data with flags 'MSG_PEEK' and save the peek data into file\n");
  906. fprintf(stderr,
  907. "\t\t\"saveAfterPeek\" - read and save data into file after recv with flags 'MSG_PEEK'\n");
  908. die_usage();
  909. /* silence compiler warning */
  910. return 0;
  911. }
  912. static int parse_int(const char *size)
  913. {
  914. unsigned long s;
  915. errno = 0;
  916. s = strtoul(size, NULL, 0);
  917. if (errno) {
  918. fprintf(stderr, "Invalid sndbuf size %s (%s)\n",
  919. size, strerror(errno));
  920. die_usage();
  921. }
  922. if (s > INT_MAX) {
  923. fprintf(stderr, "Invalid sndbuf size %s (%s)\n",
  924. size, strerror(ERANGE));
  925. die_usage();
  926. }
  927. return (int)s;
  928. }
  929. static void parse_opts(int argc, char **argv)
  930. {
  931. int c;
  932. while ((c = getopt(argc, argv, "6jr:lp:s:ht:T:m:S:R:w:M:P:c:o:")) != -1) {
  933. switch (c) {
  934. case 'j':
  935. cfg_join = true;
  936. cfg_mode = CFG_MODE_POLL;
  937. break;
  938. case 'r':
  939. cfg_remove = true;
  940. cfg_mode = CFG_MODE_POLL;
  941. cfg_wait = 400000;
  942. cfg_do_w = atoi(optarg);
  943. if (cfg_do_w <= 0)
  944. cfg_do_w = 50;
  945. break;
  946. case 'l':
  947. listen_mode = true;
  948. break;
  949. case 'p':
  950. cfg_port = optarg;
  951. break;
  952. case 's':
  953. cfg_sock_proto = parse_proto(optarg);
  954. break;
  955. case 'h':
  956. die_usage();
  957. break;
  958. case '6':
  959. pf = AF_INET6;
  960. break;
  961. case 't':
  962. poll_timeout = atoi(optarg) * 1000;
  963. if (poll_timeout <= 0)
  964. poll_timeout = -1;
  965. break;
  966. case 'T':
  967. cfg_time = atoi(optarg);
  968. break;
  969. case 'm':
  970. cfg_mode = parse_mode(optarg);
  971. break;
  972. case 'S':
  973. cfg_sndbuf = parse_int(optarg);
  974. break;
  975. case 'R':
  976. cfg_rcvbuf = parse_int(optarg);
  977. break;
  978. case 'w':
  979. cfg_wait = atoi(optarg)*1000000;
  980. break;
  981. case 'M':
  982. cfg_mark = strtol(optarg, NULL, 0);
  983. break;
  984. case 'P':
  985. cfg_peek = parse_peek(optarg);
  986. break;
  987. case 'c':
  988. parse_cmsg_types(optarg);
  989. break;
  990. case 'o':
  991. parse_setsock_options(optarg);
  992. break;
  993. }
  994. }
  995. if (optind + 1 != argc)
  996. die_usage();
  997. cfg_host = argv[optind];
  998. if (strchr(cfg_host, ':'))
  999. pf = AF_INET6;
  1000. }
  1001. int main(int argc, char *argv[])
  1002. {
  1003. init_rng();
  1004. signal(SIGUSR1, handle_signal);
  1005. parse_opts(argc, argv);
  1006. if (listen_mode) {
  1007. int fd = sock_listen_mptcp(cfg_host, cfg_port);
  1008. if (fd < 0)
  1009. return 1;
  1010. if (cfg_rcvbuf)
  1011. set_rcvbuf(fd, cfg_rcvbuf);
  1012. if (cfg_sndbuf)
  1013. set_sndbuf(fd, cfg_sndbuf);
  1014. if (cfg_mark)
  1015. set_mark(fd, cfg_mark);
  1016. if (cfg_cmsg_types.cmsg_enabled)
  1017. apply_cmsg_types(fd, &cfg_cmsg_types);
  1018. return main_loop_s(fd);
  1019. }
  1020. return main_loop();
  1021. }