1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci 3f08c3bdfSopenharmony_ci/*\ 4f08c3bdfSopenharmony_ci * Test recvmmsg() errors: 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * - EBADF Bad socket file descriptor 7f08c3bdfSopenharmony_ci * - EFAULT Bad message vector address 8f08c3bdfSopenharmony_ci * - EINVAL Bad seconds value for the timeout argument 9f08c3bdfSopenharmony_ci * - EINVAL Bad nanoseconds value for the timeout argument 10f08c3bdfSopenharmony_ci * - EFAULT Bad timeout address 11f08c3bdfSopenharmony_ci */ 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci#define _GNU_SOURCE 14f08c3bdfSopenharmony_ci#include "../sendmmsg/sendmmsg.h" 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_cistatic int send_sockfd; 17f08c3bdfSopenharmony_cistatic int receive_sockfd; 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#define VLEN 1 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_cistatic struct mmsghdr *msg; 22f08c3bdfSopenharmony_cistatic struct iovec *iov; 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic void *bad_addr; 25f08c3bdfSopenharmony_cistatic int bad_fd = -1; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_cistatic struct tst_ts ts; 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_cistruct test_case { 30f08c3bdfSopenharmony_ci const char *desc; 31f08c3bdfSopenharmony_ci int *fd; 32f08c3bdfSopenharmony_ci long tv_sec; 33f08c3bdfSopenharmony_ci long tv_nsec; 34f08c3bdfSopenharmony_ci int exp_errno; 35f08c3bdfSopenharmony_ci struct mmsghdr **msg_vec; 36f08c3bdfSopenharmony_ci int bad_ts_addr; 37f08c3bdfSopenharmony_ci}; 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic struct test_case tcase[] = { 40f08c3bdfSopenharmony_ci { 41f08c3bdfSopenharmony_ci .desc = "bad socket file descriptor", 42f08c3bdfSopenharmony_ci .fd = &bad_fd, 43f08c3bdfSopenharmony_ci .exp_errno = EBADF, 44f08c3bdfSopenharmony_ci .msg_vec = &msg, 45f08c3bdfSopenharmony_ci }, 46f08c3bdfSopenharmony_ci { 47f08c3bdfSopenharmony_ci .desc = "bad message vector address", 48f08c3bdfSopenharmony_ci .fd = &receive_sockfd, 49f08c3bdfSopenharmony_ci .exp_errno = EFAULT, 50f08c3bdfSopenharmony_ci .msg_vec = (void*)&bad_addr, 51f08c3bdfSopenharmony_ci }, 52f08c3bdfSopenharmony_ci { 53f08c3bdfSopenharmony_ci .desc = "negative seconds in timeout", 54f08c3bdfSopenharmony_ci .fd = &receive_sockfd, 55f08c3bdfSopenharmony_ci .tv_sec = -1, 56f08c3bdfSopenharmony_ci .tv_nsec = 0, 57f08c3bdfSopenharmony_ci .exp_errno = EINVAL, 58f08c3bdfSopenharmony_ci .msg_vec = &msg, 59f08c3bdfSopenharmony_ci }, 60f08c3bdfSopenharmony_ci { 61f08c3bdfSopenharmony_ci .desc = "overflow in nanoseconds in timeout", 62f08c3bdfSopenharmony_ci .fd = &receive_sockfd, 63f08c3bdfSopenharmony_ci .tv_sec = 1, 64f08c3bdfSopenharmony_ci .tv_nsec = 1000000001, 65f08c3bdfSopenharmony_ci .exp_errno = EINVAL, 66f08c3bdfSopenharmony_ci .msg_vec = &msg, 67f08c3bdfSopenharmony_ci }, 68f08c3bdfSopenharmony_ci { 69f08c3bdfSopenharmony_ci .desc = "bad timeout address", 70f08c3bdfSopenharmony_ci .fd = &receive_sockfd, 71f08c3bdfSopenharmony_ci .exp_errno = EFAULT, 72f08c3bdfSopenharmony_ci .msg_vec = &msg, 73f08c3bdfSopenharmony_ci .bad_ts_addr = 1, 74f08c3bdfSopenharmony_ci } 75f08c3bdfSopenharmony_ci}; 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_cistatic void do_test(unsigned int i) 78f08c3bdfSopenharmony_ci{ 79f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 80f08c3bdfSopenharmony_ci struct test_case *tc = &tcase[i]; 81f08c3bdfSopenharmony_ci void *timeout; 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci ts.type = tv->ts_type; 84f08c3bdfSopenharmony_ci tst_ts_set_sec(&ts, tc->tv_sec); 85f08c3bdfSopenharmony_ci tst_ts_set_nsec(&ts, tc->tv_nsec); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci if (tc->bad_ts_addr) 88f08c3bdfSopenharmony_ci timeout = bad_addr; 89f08c3bdfSopenharmony_ci else 90f08c3bdfSopenharmony_ci timeout = tst_ts_get(&ts); 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci TST_EXP_FAIL2(tv->recvmmsg(*tc->fd, *tc->msg_vec, VLEN, 0, timeout), 93f08c3bdfSopenharmony_ci tc->exp_errno, "recvmmsg() %s", tc->desc); 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_cistatic void setup(void) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci struct sockaddr_in addr; 99f08c3bdfSopenharmony_ci unsigned int port = TST_GET_UNUSED_PORT(AF_INET, SOCK_DGRAM); 100f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc); 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci send_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0); 105f08c3bdfSopenharmony_ci receive_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0); 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci addr.sin_family = AF_INET; 108f08c3bdfSopenharmony_ci addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 109f08c3bdfSopenharmony_ci addr.sin_port = port; 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci SAFE_BIND(receive_sockfd, (struct sockaddr *)&addr, sizeof(addr)); 112f08c3bdfSopenharmony_ci SAFE_CONNECT(send_sockfd, (struct sockaddr *)&addr, sizeof(addr)); 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci msg[0].msg_hdr.msg_iov = iov; 115f08c3bdfSopenharmony_ci msg[0].msg_hdr.msg_iovlen = 1; 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci TEST(tv->sendmmsg(send_sockfd, msg, 1, 0)); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci if (TST_RET != 1) { 120f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "sendmmsg() failed"); 121f08c3bdfSopenharmony_ci return; 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci bad_addr = tst_get_bad_addr(NULL); 125f08c3bdfSopenharmony_ci} 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_cistatic void cleanup(void) 128f08c3bdfSopenharmony_ci{ 129f08c3bdfSopenharmony_ci if (send_sockfd > 0) 130f08c3bdfSopenharmony_ci SAFE_CLOSE(send_sockfd); 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci if (receive_sockfd > 0) 133f08c3bdfSopenharmony_ci SAFE_CLOSE(receive_sockfd); 134f08c3bdfSopenharmony_ci} 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_cistatic struct tst_test test = { 137f08c3bdfSopenharmony_ci .test = do_test, 138f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcase), 139f08c3bdfSopenharmony_ci .setup = setup, 140f08c3bdfSopenharmony_ci .cleanup = cleanup, 141f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variants), 142f08c3bdfSopenharmony_ci .bufs = (struct tst_buffers []) { 143f08c3bdfSopenharmony_ci {&iov, .iov_sizes = (int[]){1, -1}}, 144f08c3bdfSopenharmony_ci {&msg, .size = VLEN * sizeof(*msg)}, 145f08c3bdfSopenharmony_ci {}, 146f08c3bdfSopenharmony_ci } 147f08c3bdfSopenharmony_ci}; 148