1 /* 2 * Copyright(c) 2016 Fujitsu Ltd. 3 * Author: Xiao Yang <yangx.jy (at) cn.fujitsu.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License 14 * alone with this program. 15 */ 16 17 /* 18 * Test Name: recvmsg03 19 * 20 * This test needs that rds socket is supported by system. 21 * If the size of address for receiving data is set larger than 22 * actaul size, recvmsg() will set msg_namelen incorrectly. 23 * 24 * Description: 25 * This is a regression test and has been fixed by kernel commit: 26 * 06b6a1cf6e776426766298d055bb3991957d90a7 (rds: set correct msg_namelen) 27 */ 28 29 #include <errno.h> 30 #include <string.h> 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 34 #include "tst_test.h" 35 36 #ifndef AF_RDS 37 # define AF_RDS 21 38 #endif 39 40 static void setup(void) 41 { 42 int res; 43 44 res = socket(AF_RDS, SOCK_SEQPACKET, 0); 45 if (res == -1) { 46 if (errno == EAFNOSUPPORT) 47 tst_brk(TCONF, "rds was not supported"); 48 else 49 tst_brk(TBROK | TERRNO, "socket() failed with rds"); 50 } 51 52 SAFE_CLOSE(res); 53 } 54 55 static void client(void) 56 { 57 int sock_fd1; 58 char send_buf[128] = "hello world"; 59 struct sockaddr_in server_addr; 60 struct sockaddr_in to_addr; 61 struct msghdr msg; 62 struct iovec iov; 63 64 sock_fd1 = SAFE_SOCKET(AF_RDS, SOCK_SEQPACKET, 0); 65 66 memset(&server_addr, 0, sizeof(server_addr)); 67 server_addr.sin_family = AF_INET; 68 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 69 server_addr.sin_port = htons(4001); 70 71 SAFE_BIND(sock_fd1, (struct sockaddr *) &server_addr, sizeof(server_addr)); 72 73 memset(&to_addr, 0, sizeof(to_addr)); 74 75 to_addr.sin_family = AF_INET; 76 to_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 77 to_addr.sin_port = htons(4000); 78 msg.msg_name = &to_addr; 79 msg.msg_namelen = sizeof(to_addr); 80 msg.msg_iov = &iov; 81 msg.msg_iovlen = 1; 82 msg.msg_iov->iov_base = send_buf; 83 msg.msg_iov->iov_len = strlen(send_buf) + 1; 84 msg.msg_control = 0; 85 msg.msg_controllen = 0; 86 msg.msg_flags = 0; 87 88 if (sendmsg(sock_fd1, &msg, 0) == -1) { 89 tst_brk(TBROK | TERRNO, 90 "sendmsg() failed to send data to server"); 91 } 92 93 TST_CHECKPOINT_WAIT(1); 94 95 SAFE_CLOSE(sock_fd1); 96 } 97 98 static void server(void) 99 { 100 int sock_fd2; 101 static char recv_buf[128]; 102 struct sockaddr_in server_addr; 103 struct sockaddr_in from_addr; 104 struct msghdr msg; 105 struct iovec iov; 106 107 sock_fd2 = SAFE_SOCKET(AF_RDS, SOCK_SEQPACKET, 0); 108 109 memset(&server_addr, 0, sizeof(server_addr)); 110 server_addr.sin_family = AF_INET; 111 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 112 server_addr.sin_port = htons(4000); 113 114 SAFE_BIND(sock_fd2, (struct sockaddr *) &server_addr, sizeof(server_addr)); 115 116 msg.msg_name = &from_addr; 117 msg.msg_namelen = sizeof(from_addr) + 16; 118 msg.msg_iov = &iov; 119 msg.msg_iovlen = 1; 120 msg.msg_iov->iov_base = recv_buf; 121 msg.msg_iov->iov_len = 128; 122 msg.msg_control = 0; 123 msg.msg_controllen = 0; 124 msg.msg_flags = 0; 125 126 TST_CHECKPOINT_WAKE(0); 127 128 TEST(recvmsg(sock_fd2, &msg, 0)); 129 if (TEST_RETURN == -1) { 130 tst_brk(TBROK | TTERRNO, 131 "recvmsg() failed to recvice data from client"); 132 } 133 134 if (msg.msg_namelen != sizeof(from_addr)) { 135 tst_res(TFAIL, "msg_namelen was set to %u incorrectly, " 136 "expected %lu", msg.msg_namelen, sizeof(from_addr)); 137 } else { 138 tst_res(TPASS, "msg_namelen was set to %u correctly", 139 msg.msg_namelen); 140 } 141 142 TST_CHECKPOINT_WAKE(1); 143 144 SAFE_CLOSE(sock_fd2); 145 } 146 147 static void verify_recvmsg(void) 148 { 149 pid_t pid; 150 151 pid = SAFE_FORK(); 152 if (pid == 0) { 153 TST_CHECKPOINT_WAIT(0); 154 client(); 155 } else { 156 server(); 157 tst_reap_children(); 158 } 159 } 160 161 static struct tst_test test = { 162 .forks_child = 1, 163 .needs_checkpoints = 1, 164 .setup = setup, 165 .test_all = verify_recvmsg 166 }; 167