msg_oob.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright Amazon.com Inc. or its affiliates. */
  3. #include <fcntl.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <netinet/in.h>
  7. #include <sys/epoll.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/signalfd.h>
  10. #include <sys/socket.h>
  11. #include "kselftest_harness.h"
  12. #define BUF_SZ 32
  13. FIXTURE(msg_oob)
  14. {
  15. int fd[4]; /* 0: AF_UNIX sender
  16. * 1: AF_UNIX receiver
  17. * 2: TCP sender
  18. * 3: TCP receiver
  19. */
  20. int signal_fd;
  21. int epoll_fd[2]; /* 0: AF_UNIX receiver
  22. * 1: TCP receiver
  23. */
  24. bool tcp_compliant;
  25. };
  26. FIXTURE_VARIANT(msg_oob)
  27. {
  28. bool peek;
  29. };
  30. FIXTURE_VARIANT_ADD(msg_oob, no_peek)
  31. {
  32. .peek = false,
  33. };
  34. FIXTURE_VARIANT_ADD(msg_oob, peek)
  35. {
  36. .peek = true
  37. };
  38. static void create_unix_socketpair(struct __test_metadata *_metadata,
  39. FIXTURE_DATA(msg_oob) *self)
  40. {
  41. int ret;
  42. ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, self->fd);
  43. ASSERT_EQ(ret, 0);
  44. }
  45. static void create_tcp_socketpair(struct __test_metadata *_metadata,
  46. FIXTURE_DATA(msg_oob) *self)
  47. {
  48. struct sockaddr_in addr;
  49. socklen_t addrlen;
  50. int listen_fd;
  51. int ret;
  52. listen_fd = socket(AF_INET, SOCK_STREAM, 0);
  53. ASSERT_GE(listen_fd, 0);
  54. ret = listen(listen_fd, -1);
  55. ASSERT_EQ(ret, 0);
  56. addrlen = sizeof(addr);
  57. ret = getsockname(listen_fd, (struct sockaddr *)&addr, &addrlen);
  58. ASSERT_EQ(ret, 0);
  59. self->fd[2] = socket(AF_INET, SOCK_STREAM, 0);
  60. ASSERT_GE(self->fd[2], 0);
  61. ret = connect(self->fd[2], (struct sockaddr *)&addr, addrlen);
  62. ASSERT_EQ(ret, 0);
  63. self->fd[3] = accept(listen_fd, (struct sockaddr *)&addr, &addrlen);
  64. ASSERT_GE(self->fd[3], 0);
  65. ret = fcntl(self->fd[3], F_SETFL, O_NONBLOCK);
  66. ASSERT_EQ(ret, 0);
  67. }
  68. static void setup_sigurg(struct __test_metadata *_metadata,
  69. FIXTURE_DATA(msg_oob) *self)
  70. {
  71. struct signalfd_siginfo siginfo;
  72. int pid = getpid();
  73. sigset_t mask;
  74. int i, ret;
  75. for (i = 0; i < 2; i++) {
  76. ret = ioctl(self->fd[i * 2 + 1], FIOSETOWN, &pid);
  77. ASSERT_EQ(ret, 0);
  78. }
  79. ret = sigemptyset(&mask);
  80. ASSERT_EQ(ret, 0);
  81. ret = sigaddset(&mask, SIGURG);
  82. ASSERT_EQ(ret, 0);
  83. ret = sigprocmask(SIG_BLOCK, &mask, NULL);
  84. ASSERT_EQ(ret, 0);
  85. self->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK);
  86. ASSERT_GE(self->signal_fd, 0);
  87. ret = read(self->signal_fd, &siginfo, sizeof(siginfo));
  88. ASSERT_EQ(ret, -1);
  89. }
  90. static void setup_epollpri(struct __test_metadata *_metadata,
  91. FIXTURE_DATA(msg_oob) *self)
  92. {
  93. struct epoll_event event = {
  94. .events = EPOLLPRI,
  95. };
  96. int i;
  97. for (i = 0; i < 2; i++) {
  98. int ret;
  99. self->epoll_fd[i] = epoll_create1(0);
  100. ASSERT_GE(self->epoll_fd[i], 0);
  101. ret = epoll_ctl(self->epoll_fd[i], EPOLL_CTL_ADD, self->fd[i * 2 + 1], &event);
  102. ASSERT_EQ(ret, 0);
  103. }
  104. }
  105. static void close_sockets(FIXTURE_DATA(msg_oob) *self)
  106. {
  107. int i;
  108. for (i = 0; i < 4; i++)
  109. close(self->fd[i]);
  110. }
  111. FIXTURE_SETUP(msg_oob)
  112. {
  113. create_unix_socketpair(_metadata, self);
  114. create_tcp_socketpair(_metadata, self);
  115. setup_sigurg(_metadata, self);
  116. setup_epollpri(_metadata, self);
  117. self->tcp_compliant = true;
  118. }
  119. FIXTURE_TEARDOWN(msg_oob)
  120. {
  121. close_sockets(self);
  122. }
  123. static void __epollpair(struct __test_metadata *_metadata,
  124. FIXTURE_DATA(msg_oob) *self,
  125. bool oob_remaining)
  126. {
  127. struct epoll_event event[2] = {};
  128. int i, ret[2];
  129. for (i = 0; i < 2; i++)
  130. ret[i] = epoll_wait(self->epoll_fd[i], &event[i], 1, 0);
  131. ASSERT_EQ(ret[0], oob_remaining);
  132. if (self->tcp_compliant)
  133. ASSERT_EQ(ret[0], ret[1]);
  134. if (oob_remaining) {
  135. ASSERT_EQ(event[0].events, EPOLLPRI);
  136. if (self->tcp_compliant)
  137. ASSERT_EQ(event[0].events, event[1].events);
  138. }
  139. }
  140. static void __sendpair(struct __test_metadata *_metadata,
  141. FIXTURE_DATA(msg_oob) *self,
  142. const void *buf, size_t len, int flags)
  143. {
  144. int i, ret[2];
  145. for (i = 0; i < 2; i++) {
  146. struct signalfd_siginfo siginfo = {};
  147. int bytes;
  148. ret[i] = send(self->fd[i * 2], buf, len, flags);
  149. bytes = read(self->signal_fd, &siginfo, sizeof(siginfo));
  150. if (flags & MSG_OOB) {
  151. ASSERT_EQ(bytes, sizeof(siginfo));
  152. ASSERT_EQ(siginfo.ssi_signo, SIGURG);
  153. bytes = read(self->signal_fd, &siginfo, sizeof(siginfo));
  154. }
  155. ASSERT_EQ(bytes, -1);
  156. }
  157. ASSERT_EQ(ret[0], len);
  158. ASSERT_EQ(ret[0], ret[1]);
  159. }
  160. static void __recvpair(struct __test_metadata *_metadata,
  161. FIXTURE_DATA(msg_oob) *self,
  162. const char *expected_buf, int expected_len,
  163. int buf_len, int flags, bool is_sender)
  164. {
  165. int i, ret[2], recv_errno[2], expected_errno = 0;
  166. char recv_buf[2][BUF_SZ] = {};
  167. bool printed = false;
  168. ASSERT_GE(BUF_SZ, buf_len);
  169. errno = 0;
  170. for (i = 0; i < 2; i++) {
  171. int index = is_sender ? i * 2 : i * 2 + 1;
  172. ret[i] = recv(self->fd[index], recv_buf[i], buf_len, flags);
  173. recv_errno[i] = errno;
  174. }
  175. if (expected_len < 0) {
  176. expected_errno = -expected_len;
  177. expected_len = -1;
  178. }
  179. if (ret[0] != expected_len || recv_errno[0] != expected_errno) {
  180. TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]);
  181. TH_LOG("Expected:%s", expected_errno ? strerror(expected_errno) : expected_buf);
  182. ASSERT_EQ(ret[0], expected_len);
  183. ASSERT_EQ(recv_errno[0], expected_errno);
  184. }
  185. if (ret[0] != ret[1] || recv_errno[0] != recv_errno[1]) {
  186. TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]);
  187. TH_LOG("TCP :%s", ret[1] < 0 ? strerror(recv_errno[1]) : recv_buf[1]);
  188. printed = true;
  189. if (self->tcp_compliant) {
  190. ASSERT_EQ(ret[0], ret[1]);
  191. ASSERT_EQ(recv_errno[0], recv_errno[1]);
  192. }
  193. }
  194. if (expected_len >= 0) {
  195. int cmp;
  196. cmp = strncmp(expected_buf, recv_buf[0], expected_len);
  197. if (cmp) {
  198. TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]);
  199. TH_LOG("Expected:%s", expected_errno ? strerror(expected_errno) : expected_buf);
  200. ASSERT_EQ(cmp, 0);
  201. }
  202. cmp = strncmp(recv_buf[0], recv_buf[1], expected_len);
  203. if (cmp) {
  204. if (!printed) {
  205. TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]);
  206. TH_LOG("TCP :%s", ret[1] < 0 ? strerror(recv_errno[1]) : recv_buf[1]);
  207. }
  208. if (self->tcp_compliant)
  209. ASSERT_EQ(cmp, 0);
  210. }
  211. }
  212. }
  213. static void __setinlinepair(struct __test_metadata *_metadata,
  214. FIXTURE_DATA(msg_oob) *self)
  215. {
  216. int i, oob_inline = 1;
  217. for (i = 0; i < 2; i++) {
  218. int ret;
  219. ret = setsockopt(self->fd[i * 2 + 1], SOL_SOCKET, SO_OOBINLINE,
  220. &oob_inline, sizeof(oob_inline));
  221. ASSERT_EQ(ret, 0);
  222. }
  223. }
  224. static void __siocatmarkpair(struct __test_metadata *_metadata,
  225. FIXTURE_DATA(msg_oob) *self,
  226. bool oob_head)
  227. {
  228. int answ[2] = {};
  229. int i;
  230. for (i = 0; i < 2; i++) {
  231. int ret;
  232. ret = ioctl(self->fd[i * 2 + 1], SIOCATMARK, &answ[i]);
  233. ASSERT_EQ(ret, 0);
  234. }
  235. ASSERT_EQ(answ[0], oob_head);
  236. if (self->tcp_compliant)
  237. ASSERT_EQ(answ[0], answ[1]);
  238. }
  239. static void __resetpair(struct __test_metadata *_metadata,
  240. FIXTURE_DATA(msg_oob) *self,
  241. const FIXTURE_VARIANT(msg_oob) *variant,
  242. bool reset)
  243. {
  244. int i;
  245. for (i = 0; i < 2; i++)
  246. close(self->fd[i * 2 + 1]);
  247. __recvpair(_metadata, self, "", reset ? -ECONNRESET : 0, 1,
  248. variant->peek ? MSG_PEEK : 0, true);
  249. }
  250. #define sendpair(buf, len, flags) \
  251. __sendpair(_metadata, self, buf, len, flags)
  252. #define recvpair(expected_buf, expected_len, buf_len, flags) \
  253. do { \
  254. if (variant->peek) \
  255. __recvpair(_metadata, self, \
  256. expected_buf, expected_len, \
  257. buf_len, (flags) | MSG_PEEK, false); \
  258. __recvpair(_metadata, self, \
  259. expected_buf, expected_len, \
  260. buf_len, flags, false); \
  261. } while (0)
  262. #define epollpair(oob_remaining) \
  263. __epollpair(_metadata, self, oob_remaining)
  264. #define siocatmarkpair(oob_head) \
  265. __siocatmarkpair(_metadata, self, oob_head)
  266. #define setinlinepair() \
  267. __setinlinepair(_metadata, self)
  268. #define resetpair(reset) \
  269. __resetpair(_metadata, self, variant, reset)
  270. #define tcp_incompliant \
  271. for (self->tcp_compliant = false; \
  272. self->tcp_compliant == false; \
  273. self->tcp_compliant = true)
  274. TEST_F(msg_oob, non_oob)
  275. {
  276. sendpair("x", 1, 0);
  277. epollpair(false);
  278. siocatmarkpair(false);
  279. recvpair("", -EINVAL, 1, MSG_OOB);
  280. epollpair(false);
  281. siocatmarkpair(false);
  282. resetpair(true);
  283. }
  284. TEST_F(msg_oob, non_oob_no_reset)
  285. {
  286. sendpair("x", 1, 0);
  287. epollpair(false);
  288. siocatmarkpair(false);
  289. recvpair("x", 1, 1, 0);
  290. epollpair(false);
  291. siocatmarkpair(false);
  292. resetpair(false);
  293. }
  294. TEST_F(msg_oob, oob)
  295. {
  296. sendpair("x", 1, MSG_OOB);
  297. epollpair(true);
  298. siocatmarkpair(true);
  299. recvpair("x", 1, 1, MSG_OOB);
  300. epollpair(false);
  301. siocatmarkpair(true);
  302. tcp_incompliant {
  303. resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */
  304. }
  305. }
  306. TEST_F(msg_oob, oob_reset)
  307. {
  308. sendpair("x", 1, MSG_OOB);
  309. epollpair(true);
  310. siocatmarkpair(true);
  311. resetpair(true);
  312. }
  313. TEST_F(msg_oob, oob_drop)
  314. {
  315. sendpair("x", 1, MSG_OOB);
  316. epollpair(true);
  317. siocatmarkpair(true);
  318. recvpair("", -EAGAIN, 1, 0); /* Drop OOB. */
  319. epollpair(false);
  320. siocatmarkpair(false);
  321. recvpair("", -EINVAL, 1, MSG_OOB);
  322. epollpair(false);
  323. siocatmarkpair(false);
  324. resetpair(false);
  325. }
  326. TEST_F(msg_oob, oob_ahead)
  327. {
  328. sendpair("hello", 5, MSG_OOB);
  329. epollpair(true);
  330. siocatmarkpair(false);
  331. recvpair("o", 1, 1, MSG_OOB);
  332. epollpair(false);
  333. siocatmarkpair(false);
  334. recvpair("hell", 4, 4, 0);
  335. epollpair(false);
  336. siocatmarkpair(true);
  337. tcp_incompliant {
  338. resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */
  339. }
  340. }
  341. TEST_F(msg_oob, oob_break)
  342. {
  343. sendpair("hello", 5, MSG_OOB);
  344. epollpair(true);
  345. siocatmarkpair(false);
  346. recvpair("hell", 4, 5, 0); /* Break at OOB even with enough buffer. */
  347. epollpair(true);
  348. siocatmarkpair(true);
  349. recvpair("o", 1, 1, MSG_OOB);
  350. epollpair(false);
  351. siocatmarkpair(true);
  352. recvpair("", -EAGAIN, 1, 0);
  353. siocatmarkpair(false);
  354. resetpair(false);
  355. }
  356. TEST_F(msg_oob, oob_ahead_break)
  357. {
  358. sendpair("hello", 5, MSG_OOB);
  359. epollpair(true);
  360. siocatmarkpair(false);
  361. sendpair("world", 5, 0);
  362. epollpair(true);
  363. siocatmarkpair(false);
  364. recvpair("o", 1, 1, MSG_OOB);
  365. epollpair(false);
  366. siocatmarkpair(false);
  367. recvpair("hell", 4, 9, 0); /* Break at OOB even after it's recv()ed. */
  368. epollpair(false);
  369. siocatmarkpair(true);
  370. recvpair("world", 5, 5, 0);
  371. epollpair(false);
  372. siocatmarkpair(false);
  373. resetpair(false);
  374. }
  375. TEST_F(msg_oob, oob_break_drop)
  376. {
  377. sendpair("hello", 5, MSG_OOB);
  378. epollpair(true);
  379. siocatmarkpair(false);
  380. sendpair("world", 5, 0);
  381. epollpair(true);
  382. siocatmarkpair(false);
  383. recvpair("hell", 4, 10, 0); /* Break at OOB even with enough buffer. */
  384. epollpair(true);
  385. siocatmarkpair(true);
  386. recvpair("world", 5, 10, 0); /* Drop OOB and recv() the next skb. */
  387. epollpair(false);
  388. siocatmarkpair(false);
  389. recvpair("", -EINVAL, 1, MSG_OOB);
  390. epollpair(false);
  391. siocatmarkpair(false);
  392. resetpair(false);
  393. }
  394. TEST_F(msg_oob, ex_oob_break)
  395. {
  396. sendpair("hello", 5, MSG_OOB);
  397. epollpair(true);
  398. siocatmarkpair(false);
  399. sendpair("wor", 3, MSG_OOB);
  400. epollpair(true);
  401. siocatmarkpair(false);
  402. sendpair("ld", 2, 0);
  403. epollpair(true);
  404. siocatmarkpair(false);
  405. recvpair("hellowo", 7, 10, 0); /* Break at OOB but not at ex-OOB. */
  406. epollpair(true);
  407. siocatmarkpair(true);
  408. recvpair("r", 1, 1, MSG_OOB);
  409. epollpair(false);
  410. siocatmarkpair(true);
  411. recvpair("ld", 2, 2, 0);
  412. epollpair(false);
  413. siocatmarkpair(false);
  414. resetpair(false);
  415. }
  416. TEST_F(msg_oob, ex_oob_drop)
  417. {
  418. sendpair("x", 1, MSG_OOB);
  419. epollpair(true);
  420. siocatmarkpair(true);
  421. sendpair("y", 1, MSG_OOB); /* TCP drops "x" at this moment. */
  422. epollpair(true);
  423. tcp_incompliant {
  424. siocatmarkpair(false);
  425. recvpair("x", 1, 1, 0); /* TCP drops "y" by passing through it. */
  426. epollpair(true);
  427. siocatmarkpair(true);
  428. recvpair("y", 1, 1, MSG_OOB); /* TCP returns -EINVAL. */
  429. epollpair(false);
  430. siocatmarkpair(true);
  431. }
  432. resetpair(false);
  433. }
  434. TEST_F(msg_oob, ex_oob_drop_2)
  435. {
  436. sendpair("x", 1, MSG_OOB);
  437. epollpair(true);
  438. siocatmarkpair(true);
  439. sendpair("y", 1, MSG_OOB); /* TCP drops "x" at this moment. */
  440. epollpair(true);
  441. tcp_incompliant {
  442. siocatmarkpair(false);
  443. }
  444. recvpair("y", 1, 1, MSG_OOB);
  445. epollpair(false);
  446. tcp_incompliant {
  447. siocatmarkpair(false);
  448. recvpair("x", 1, 1, 0); /* TCP returns -EAGAIN. */
  449. epollpair(false);
  450. siocatmarkpair(true);
  451. }
  452. resetpair(false);
  453. }
  454. TEST_F(msg_oob, ex_oob_oob)
  455. {
  456. sendpair("x", 1, MSG_OOB);
  457. epollpair(true);
  458. siocatmarkpair(true);
  459. recvpair("x", 1, 1, MSG_OOB);
  460. epollpair(false);
  461. siocatmarkpair(true);
  462. sendpair("y", 1, MSG_OOB);
  463. epollpair(true);
  464. siocatmarkpair(true);
  465. recvpair("", -EAGAIN, 1, 0);
  466. epollpair(false);
  467. siocatmarkpair(false);
  468. recvpair("", -EINVAL, 1, MSG_OOB);
  469. epollpair(false);
  470. siocatmarkpair(false);
  471. resetpair(false);
  472. }
  473. TEST_F(msg_oob, ex_oob_ex_oob)
  474. {
  475. sendpair("x", 1, MSG_OOB);
  476. epollpair(true);
  477. siocatmarkpair(true);
  478. recvpair("x", 1, 1, MSG_OOB);
  479. epollpair(false);
  480. siocatmarkpair(true);
  481. sendpair("y", 1, MSG_OOB);
  482. epollpair(true);
  483. siocatmarkpair(true);
  484. recvpair("y", 1, 1, MSG_OOB);
  485. epollpair(false);
  486. siocatmarkpair(true);
  487. tcp_incompliant {
  488. resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */
  489. }
  490. }
  491. TEST_F(msg_oob, ex_oob_ex_oob_oob)
  492. {
  493. sendpair("x", 1, MSG_OOB);
  494. epollpair(true);
  495. siocatmarkpair(true);
  496. recvpair("x", 1, 1, MSG_OOB);
  497. epollpair(false);
  498. siocatmarkpair(true);
  499. sendpair("y", 1, MSG_OOB);
  500. epollpair(true);
  501. siocatmarkpair(true);
  502. recvpair("y", 1, 1, MSG_OOB);
  503. epollpair(false);
  504. siocatmarkpair(true);
  505. sendpair("z", 1, MSG_OOB);
  506. epollpair(true);
  507. siocatmarkpair(true);
  508. }
  509. TEST_F(msg_oob, ex_oob_ahead_break)
  510. {
  511. sendpair("hello", 5, MSG_OOB);
  512. epollpair(true);
  513. siocatmarkpair(false);
  514. sendpair("wor", 3, MSG_OOB);
  515. epollpair(true);
  516. siocatmarkpair(false);
  517. recvpair("r", 1, 1, MSG_OOB);
  518. epollpair(false);
  519. siocatmarkpair(false);
  520. sendpair("ld", 2, MSG_OOB);
  521. epollpair(true);
  522. siocatmarkpair(false);
  523. tcp_incompliant {
  524. recvpair("hellowol", 8, 10, 0); /* TCP recv()s "helloworl", why "r" ?? */
  525. }
  526. epollpair(true);
  527. siocatmarkpair(true);
  528. recvpair("d", 1, 1, MSG_OOB);
  529. epollpair(false);
  530. siocatmarkpair(true);
  531. tcp_incompliant {
  532. resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */
  533. }
  534. }
  535. TEST_F(msg_oob, ex_oob_siocatmark)
  536. {
  537. sendpair("hello", 5, MSG_OOB);
  538. epollpair(true);
  539. siocatmarkpair(false);
  540. recvpair("o", 1, 1, MSG_OOB);
  541. epollpair(false);
  542. siocatmarkpair(false);
  543. sendpair("world", 5, MSG_OOB);
  544. epollpair(true);
  545. siocatmarkpair(false);
  546. recvpair("hell", 4, 4, 0); /* Intentionally stop at ex-OOB. */
  547. epollpair(true);
  548. siocatmarkpair(false);
  549. resetpair(true);
  550. }
  551. TEST_F(msg_oob, inline_oob)
  552. {
  553. setinlinepair();
  554. sendpair("x", 1, MSG_OOB);
  555. epollpair(true);
  556. siocatmarkpair(true);
  557. recvpair("", -EINVAL, 1, MSG_OOB);
  558. epollpair(true);
  559. siocatmarkpair(true);
  560. recvpair("x", 1, 1, 0);
  561. epollpair(false);
  562. siocatmarkpair(false);
  563. resetpair(false);
  564. }
  565. TEST_F(msg_oob, inline_oob_break)
  566. {
  567. setinlinepair();
  568. sendpair("hello", 5, MSG_OOB);
  569. epollpair(true);
  570. siocatmarkpair(false);
  571. recvpair("", -EINVAL, 1, MSG_OOB);
  572. epollpair(true);
  573. siocatmarkpair(false);
  574. recvpair("hell", 4, 5, 0); /* Break at OOB but not at ex-OOB. */
  575. epollpair(true);
  576. siocatmarkpair(true);
  577. recvpair("o", 1, 1, 0);
  578. epollpair(false);
  579. siocatmarkpair(false);
  580. resetpair(false);
  581. }
  582. TEST_F(msg_oob, inline_oob_ahead_break)
  583. {
  584. sendpair("hello", 5, MSG_OOB);
  585. epollpair(true);
  586. siocatmarkpair(false);
  587. sendpair("world", 5, 0);
  588. epollpair(true);
  589. siocatmarkpair(false);
  590. recvpair("o", 1, 1, MSG_OOB);
  591. epollpair(false);
  592. siocatmarkpair(false);
  593. setinlinepair();
  594. recvpair("hell", 4, 9, 0); /* Break at OOB even with enough buffer. */
  595. epollpair(false);
  596. siocatmarkpair(true);
  597. tcp_incompliant {
  598. recvpair("world", 5, 6, 0); /* TCP recv()s "oworld", ... "o" ??? */
  599. }
  600. epollpair(false);
  601. siocatmarkpair(false);
  602. resetpair(false);
  603. }
  604. TEST_F(msg_oob, inline_ex_oob_break)
  605. {
  606. sendpair("hello", 5, MSG_OOB);
  607. epollpair(true);
  608. siocatmarkpair(false);
  609. sendpair("wor", 3, MSG_OOB);
  610. epollpair(true);
  611. siocatmarkpair(false);
  612. sendpair("ld", 2, 0);
  613. epollpair(true);
  614. siocatmarkpair(false);
  615. setinlinepair();
  616. recvpair("hellowo", 7, 10, 0); /* Break at OOB but not at ex-OOB. */
  617. epollpair(true);
  618. siocatmarkpair(true);
  619. recvpair("rld", 3, 3, 0);
  620. epollpair(false);
  621. siocatmarkpair(false);
  622. resetpair(false);
  623. }
  624. TEST_F(msg_oob, inline_ex_oob_no_drop)
  625. {
  626. sendpair("x", 1, MSG_OOB);
  627. epollpair(true);
  628. siocatmarkpair(true);
  629. setinlinepair();
  630. sendpair("y", 1, MSG_OOB); /* TCP does NOT drops "x" at this moment. */
  631. epollpair(true);
  632. siocatmarkpair(false);
  633. recvpair("x", 1, 1, 0);
  634. epollpair(true);
  635. siocatmarkpair(true);
  636. recvpair("y", 1, 1, 0);
  637. epollpair(false);
  638. siocatmarkpair(false);
  639. resetpair(false);
  640. }
  641. TEST_F(msg_oob, inline_ex_oob_drop)
  642. {
  643. sendpair("x", 1, MSG_OOB);
  644. epollpair(true);
  645. siocatmarkpair(true);
  646. sendpair("y", 1, MSG_OOB); /* TCP drops "x" at this moment. */
  647. epollpair(true);
  648. setinlinepair();
  649. tcp_incompliant {
  650. siocatmarkpair(false);
  651. recvpair("x", 1, 1, 0); /* TCP recv()s "y". */
  652. epollpair(true);
  653. siocatmarkpair(true);
  654. recvpair("y", 1, 1, 0); /* TCP returns -EAGAIN. */
  655. epollpair(false);
  656. siocatmarkpair(false);
  657. }
  658. resetpair(false);
  659. }
  660. TEST_F(msg_oob, inline_ex_oob_siocatmark)
  661. {
  662. sendpair("hello", 5, MSG_OOB);
  663. epollpair(true);
  664. siocatmarkpair(false);
  665. recvpair("o", 1, 1, MSG_OOB);
  666. epollpair(false);
  667. siocatmarkpair(false);
  668. setinlinepair();
  669. sendpair("world", 5, MSG_OOB);
  670. epollpair(true);
  671. siocatmarkpair(false);
  672. recvpair("hell", 4, 4, 0); /* Intentionally stop at ex-OOB. */
  673. epollpair(true);
  674. siocatmarkpair(false);
  675. resetpair(true);
  676. }
  677. TEST_HARNESS_MAIN