1 /* 2 * This test is based on source contained in the man pages for sendmmsg and 3 * recvmmsg in release 4.15 of the Linux man-pages project. 4 */ 5 6 #define _GNU_SOURCE 7 #include <netinet/ip.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 14 #include "tst_test.h" 15 #include "tst_safe_macros.h" 16 #include "tst_safe_pthread.h" 17 18 #define BUFSIZE 16 19 #define VLEN 2 20 21 static void *sender_thread(LTP_ATTRIBUTE_UNUSED void *arg) 22 { 23 struct sockaddr_in addr; 24 struct mmsghdr msg[2]; 25 struct iovec msg1[2], msg2; 26 int send_sockfd; 27 int retval; 28 29 send_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0); 30 31 addr.sin_family = AF_INET; 32 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 33 addr.sin_port = htons(1234); 34 SAFE_CONNECT(send_sockfd, (struct sockaddr *) &addr, sizeof(addr)); 35 36 memset(msg1, 0, sizeof(msg1)); 37 msg1[0].iov_base = "one"; 38 msg1[0].iov_len = 3; 39 msg1[1].iov_base = "two"; 40 msg1[1].iov_len = 3; 41 42 memset(&msg2, 0, sizeof(msg2)); 43 msg2.iov_base = "three"; 44 msg2.iov_len = 5; 45 46 memset(msg, 0, sizeof(msg)); 47 msg[0].msg_hdr.msg_iov = msg1; 48 msg[0].msg_hdr.msg_iovlen = 2; 49 50 msg[1].msg_hdr.msg_iov = &msg2; 51 msg[1].msg_hdr.msg_iovlen = 1; 52 53 retval = sendmmsg(send_sockfd, msg, 2, 0); 54 if (retval < 0) 55 tst_brk(TFAIL|TTERRNO, "sendmmsg failed"); 56 57 return NULL; 58 } 59 60 61 static void *receiver_thread(LTP_ATTRIBUTE_UNUSED void *arg) 62 { 63 int receive_sockfd; 64 struct sockaddr_in addr; 65 struct mmsghdr msgs[VLEN]; 66 struct iovec iovecs[VLEN]; 67 char bufs[VLEN][BUFSIZE+1]; 68 struct timespec timeout; 69 int i, retval; 70 71 receive_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0); 72 addr.sin_family = AF_INET; 73 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 74 addr.sin_port = htons(1234); 75 SAFE_BIND(receive_sockfd, (struct sockaddr *)&addr, sizeof(addr)); 76 77 memset(msgs, 0, sizeof(msgs)); 78 for (i = 0; i < VLEN; i++) { 79 iovecs[i].iov_base = bufs[i]; 80 iovecs[i].iov_len = BUFSIZE; 81 msgs[i].msg_hdr.msg_iov = &iovecs[i]; 82 msgs[i].msg_hdr.msg_iovlen = 1; 83 } 84 85 timeout.tv_sec = 1; 86 timeout.tv_nsec = 0; 87 88 retval = recvmmsg(receive_sockfd, msgs, VLEN, 0, &timeout); 89 if (retval == -1) 90 tst_brk(TFAIL | TTERRNO, "recvmmsg failed"); 91 if (retval != 2) 92 tst_brk(TFAIL, "Received unexpected number of messages (%d)", 93 retval); 94 95 bufs[0][msgs[0].msg_len] = 0; 96 if (strcmp(bufs[0], "onetwo")) 97 tst_res(TFAIL, "Error in first received message."); 98 else 99 tst_res(TPASS, "First message received successfully."); 100 101 bufs[1][msgs[1].msg_len] = 0; 102 if (strcmp(bufs[1], "three")) 103 tst_res(TFAIL, "Error in second received message."); 104 else 105 tst_res(TPASS, "Second message received successfully."); 106 107 return NULL; 108 } 109 110 static void run(void) 111 { 112 pthread_t sender; 113 pthread_t receiver; 114 115 SAFE_PTHREAD_CREATE(&sender, NULL, sender_thread, NULL); 116 SAFE_PTHREAD_CREATE(&receiver, NULL, receiver_thread, NULL); 117 SAFE_PTHREAD_JOIN(sender, NULL); 118 SAFE_PTHREAD_JOIN(receiver, NULL); 119 } 120 121 static struct tst_test test = { 122 .test_all = run, 123 }; 124