1 /* SCTP kernel Implementation 2 * (C) Copyright IBM Corp. 2004 3 * Copyright (c) 1999-2001 Motorola, Inc. 4 * 5 * The SCTP implementation is free software; 6 * you can redistribute it and/or modify it under the terms of 7 * the GNU General Public License as published by 8 * the Free Software Foundation; either version 2, or (at your option) 9 * any later version. 10 * 11 * The SCTP implementation is distributed in the hope that it 12 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 13 * ************************ 14 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 * See the GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU CC; see the file COPYING. If not, write to 19 * the Free Software Foundation, 59 Temple Place - Suite 330, 20 * Boston, MA 02111-1307, USA. 21 * 22 * Please send any bug reports or fixes you make to the 23 * email address(es): 24 * lksctp developers <lksctp-developers (at) lists.sourceforge.net> 25 * 26 * Or submit a bug report through the following website: 27 * http://www.sf.net/projects/lksctp 28 * 29 * Any bugs reported given to us we will try to fix... any fixes shared will 30 * be incorporated into the next SCTP release. 31 * 32 * Written or modified by: 33 * Sridhar Samudrala <sri (at) us.ibm.com> 34 */ 35 36 /* This is a kernel test to verify getsockname() and getpeername() interfaces 37 * for single-homed one-to-one style sockets. 38 */ 39 40 #include <stdio.h> 41 #include <unistd.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <fcntl.h> 45 #include <sys/types.h> 46 #include <sys/socket.h> 47 #include <sys/uio.h> 48 #include <netinet/in.h> 49 #include <errno.h> 50 #include <netinet/sctp.h> 51 #include <sctputil.h> 52 53 char *TCID = __FILE__; 54 int TST_TOTAL = 13; 55 int TST_CNT = 0; 56 57 #define MAX_CLIENTS 10 58 59 int 60 main(int argc, char *argv[]) 61 { 62 int clt_sk, svr_sk, accept_sk; 63 sockaddr_storage_t svr_loop, accept_loop; 64 sockaddr_storage_t svr_local_addr, svr_peer_addr; 65 sockaddr_storage_t clt_local_addr, clt_peer_addr; 66 socklen_t len; 67 int error; 68 int pf_class; 69 int fd, err_no = 0; 70 char filename[21]; 71 72 /* Rather than fflush() throughout the code, set stdout to 73 * be unbuffered. 74 */ 75 setvbuf(stdout, NULL, _IONBF, 0); 76 77 /* Initialize the server and client addresses. */ 78 #if TEST_V6 79 pf_class = PF_INET6; 80 svr_loop.v6.sin6_family = AF_INET6; 81 svr_loop.v6.sin6_addr = (struct in6_addr)SCTP_IN6ADDR_ANY_INIT; 82 svr_loop.v6.sin6_port = htons(SCTP_TESTPORT_1); 83 #else 84 pf_class = PF_INET; 85 svr_loop.v4.sin_family = AF_INET; 86 svr_loop.v4.sin_addr.s_addr = INADDR_ANY; 87 svr_loop.v4.sin_port = htons(SCTP_TESTPORT_1); 88 #endif 89 90 /* Create and bind the listening server socket. */ 91 svr_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); 92 test_bind(svr_sk, &svr_loop.sa, sizeof(svr_loop)); 93 94 bzero(&svr_local_addr, sizeof(svr_local_addr)); 95 len = sizeof(svr_local_addr); 96 /* Verify that getsockname() on an unconnected socket works fine. */ 97 error = getsockname(svr_sk, (struct sockaddr *)&svr_local_addr, &len); 98 if (0 != error) 99 tst_brkm(TBROK, tst_exit, "getsockname: %s", strerror(errno)); 100 101 tst_resm(TPASS, "getsockname on an unconnected socket"); 102 103 bzero(&svr_peer_addr, sizeof(svr_peer_addr)); 104 len = sizeof(svr_peer_addr); 105 /* Verify that getpeername() on an unconnected socket fails. */ 106 error = getpeername(svr_sk, (struct sockaddr *)&svr_peer_addr, &len); 107 if ((-1 != error) || (ENOTCONN != errno)) 108 tst_brkm(TBROK, tst_exit, "getpeername on an unconnected " 109 "socket error:%d, errno:%d", error, errno); 110 111 tst_resm(TPASS, "getpeername on an unconnected socket"); 112 113 /* Mark svr_sk as being able to accept new associations. */ 114 test_listen(svr_sk, 5); 115 116 /* Create the client socket. */ 117 clt_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); 118 119 /* Do a blocking connect from clt_sk to svr_sk */ 120 #if TEST_V6 121 svr_loop.v6.sin6_addr = in6addr_loopback; 122 #else 123 svr_loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 124 #endif 125 test_connect(clt_sk, &svr_loop.sa, sizeof(svr_loop)); 126 127 bzero(&clt_local_addr, sizeof(clt_local_addr)); 128 len = sizeof(clt_local_addr); 129 /* Get the client's local address. */ 130 error = getsockname(clt_sk, (struct sockaddr *)&clt_local_addr, &len); 131 if (0 != error) 132 tst_brkm(TBROK, tst_exit, "getsockname on a connected client " 133 "socket: %s", strerror(errno)); 134 135 tst_resm(TPASS, "getsockname on a connected client socket"); 136 137 bzero(&clt_peer_addr, sizeof(clt_peer_addr)); 138 len = sizeof(clt_peer_addr); 139 /* Get the client's peer address. */ 140 error = getpeername(clt_sk, (struct sockaddr *)&clt_peer_addr, &len); 141 if (0 != error) 142 tst_brkm(TBROK, tst_exit, "getpeername on a connected client " 143 "socket: %s", strerror(errno)); 144 145 tst_resm(TPASS, "getpeername on a connected client socket"); 146 147 /* Extract the association on the listening socket as a new socket. */ 148 len = sizeof(accept_loop); 149 accept_sk = test_accept(svr_sk, &accept_loop.sa, &len); 150 151 bzero(&svr_local_addr, sizeof(svr_local_addr)); 152 len = sizeof(svr_local_addr); 153 /* Get the server's local address. */ 154 error = getsockname(accept_sk, (struct sockaddr *)&svr_local_addr, 155 &len); 156 if (0 != error) 157 tst_brkm(TBROK, tst_exit, "getsockname on a connected server " 158 "socket: %s", strerror(errno)); 159 160 tst_resm(TPASS, "getsockname on a connected server socket"); 161 162 bzero(&svr_peer_addr, sizeof(svr_peer_addr)); 163 len = sizeof(svr_peer_addr); 164 /* Get the server's peer address. */ 165 error = getpeername(accept_sk, (struct sockaddr *)&svr_peer_addr, 166 &len); 167 if (0 != error) 168 tst_brkm(TBROK, tst_exit, "getpeername on a connected server " 169 "socket: %s", strerror(errno)); 170 171 tst_resm(TPASS, "getpeername on a connected server socket"); 172 173 if (svr_local_addr.v4.sin_port != clt_peer_addr.v4.sin_port) 174 tst_brkm(TBROK, tst_exit, "Server's local port(%d) doesn't " 175 "match Client's peer port(%d)\n", 176 svr_local_addr.v4.sin_port, clt_peer_addr.v4.sin_port); 177 178 if (svr_peer_addr.v4.sin_port != clt_local_addr.v4.sin_port) 179 tst_brkm(TBROK, tst_exit, "Server's peer port(%d) doesn't " 180 "match Client's local port(%d)\n", 181 svr_peer_addr.v4.sin_port, clt_local_addr.v4.sin_port); 182 #if TEST_V6 183 if (memcmp(&svr_local_addr, &clt_peer_addr, len) != 0) 184 tst_brkm(TBROK, tst_exit, "Server's local address and client's " 185 "peer addresses do not match\n"); 186 187 if (memcmp(&svr_peer_addr, &clt_local_addr, len) != 0) 188 tst_brkm(TBROK, tst_exit, "Server's peer address and client's " 189 "local addresses do not match\n"); 190 #else 191 if (svr_local_addr.v4.sin_addr.s_addr != 192 clt_peer_addr.v4.sin_addr.s_addr) 193 tst_brkm(TBROK, tst_exit, "Server's local address and client's " 194 "peer addresses do not match\n"); 195 if (svr_peer_addr.v4.sin_addr.s_addr != 196 clt_local_addr.v4.sin_addr.s_addr) 197 tst_brkm(TBROK, tst_exit, "Server's peer address and client's " 198 "local addresses do not match\n"); 199 #endif 200 tst_resm(TPASS, "getsockname/getpeername server/client match"); 201 202 bzero(&clt_local_addr, sizeof(clt_local_addr)); 203 len = sizeof(clt_local_addr); 204 /*getsockname(): Bad socket descriptor, EBADF expected error*/ 205 error = getsockname(-1, (struct sockaddr *)&clt_local_addr, &len); 206 if (error != -1 || errno != EBADF) 207 tst_brkm(TBROK, tst_exit, "getsockname on a bad socket " 208 "descriptor. error:%d errno:%d", error, errno); 209 210 tst_resm(TPASS, "getsockname on a bad socket descriptor - EBADF"); 211 212 /*getsockname(): Invalid socket, ENOTSOCK expected error*/ 213 strcpy(filename, "/tmp/sctptest.XXXXXX"); 214 fd = mkstemp(filename); 215 if (fd == -1) 216 tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s", 217 filename, strerror(errno)); 218 error = getsockname(fd, (struct sockaddr *)&clt_local_addr, &len); 219 if (error == -1) 220 err_no = errno; 221 close(fd); 222 unlink(filename); 223 if (error != -1 || err_no != ENOTSOCK) 224 tst_brkm(TBROK, tst_exit, "getsockname on an invalid socket " 225 "error:%d errno:%d", error, err_no); 226 227 tst_resm(TPASS, "getsockname on an invalid socket - ENOTSOCK"); 228 229 /*getsockname(): Invalid structure, EFAULT expected error*/ 230 error = getsockname(clt_sk, (struct sockaddr *)-1, &len); 231 if (error != -1 || errno != EFAULT) 232 tst_brkm(TBROK, tst_exit, "getsockname with invalid buffer " 233 "error:%d errno:%d", error, errno); 234 235 tst_resm(TPASS, "getsockname with invalid buffer - EFAULT"); 236 237 bzero(&clt_peer_addr, sizeof(clt_peer_addr)); 238 len = sizeof(clt_peer_addr); 239 /*getpeername(): Bad socket descriptor, EBADF expected error*/ 240 error = getpeername(-1, (struct sockaddr *)&clt_local_addr, &len); 241 if (error != -1 || errno != EBADF) 242 tst_brkm(TBROK, tst_exit, "getpeername on a bad socket " 243 "descriptor. error:%d errno:%d", error, errno); 244 245 tst_resm(TPASS, "getpeername on a bad socket descriptor - EBADF"); 246 247 /*getpeername(): Invalid socket, ENOTSOCK expected error*/ 248 strcpy(filename, "/tmp/sctptest.XXXXXX"); 249 fd = mkstemp(filename); 250 if (fd == -1) 251 tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s", 252 filename, strerror(errno)); 253 error = getpeername(fd, (struct sockaddr *)&clt_local_addr, &len); 254 if (error == -1) 255 err_no = errno; 256 close(fd); 257 unlink(filename); 258 if (error != -1 || err_no != ENOTSOCK) 259 tst_brkm(TBROK, tst_exit, "getpeername on an invalid socket " 260 "error:%d errno:%d", error, err_no); 261 262 tst_resm(TPASS, "getpeername on an invalid socket - ENOTSOCK"); 263 264 /*getpeername(): Invalid structure, EFAULT expected error*/ 265 error = getpeername(clt_sk, (struct sockaddr *)-1, &len); 266 if (error != -1 || errno != EFAULT) 267 tst_brkm(TBROK, tst_exit, "getpeername with invalid buffer " 268 "error:%d errno:%d", error, errno); 269 270 tst_resm(TPASS, "getpeername with invalid buffer - EFAULT"); 271 272 close(clt_sk); 273 close(svr_sk); 274 close(accept_sk); 275 276 /* Indicate successful completion. */ 277 return 0; 278 } 279