PageRenderTime 58ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

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

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