1f08c3bdfSopenharmony_ci/* SCTP kernel Implementation 2f08c3bdfSopenharmony_ci * (C) Copyright IBM Corp. 2003 3f08c3bdfSopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This file is part of the SCTP kernel Implementation 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * The SCTP implementation is free software; 8f08c3bdfSopenharmony_ci * you can redistribute it and/or modify it under the terms of 9f08c3bdfSopenharmony_ci * the GNU General Public License as published by 10f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2, or (at your option) 11f08c3bdfSopenharmony_ci * any later version. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * The SCTP implementation is distributed in the hope that it 14f08c3bdfSopenharmony_ci * will be useful, but WITHOUT ANY WARRANTY; without even the implied 15f08c3bdfSopenharmony_ci * ************************ 16f08c3bdfSopenharmony_ci * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17f08c3bdfSopenharmony_ci * See the GNU General Public License for more details. 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 20f08c3bdfSopenharmony_ci * along with GNU CC; see the file COPYING. If not, write to 21f08c3bdfSopenharmony_ci * the Free Software Foundation, 59 Temple Place - Suite 330, 22f08c3bdfSopenharmony_ci * Boston, MA 02111-1307, USA. 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * Please send any bug reports or fixes you make to the 25f08c3bdfSopenharmony_ci * email address(es): 26f08c3bdfSopenharmony_ci * lksctp developers <lksctp-developers@lists.sourceforge.net> 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * Or submit a bug report through the following website: 29f08c3bdfSopenharmony_ci * http://www.sf.net/projects/lksctp 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * Any bugs reported to us we will try to fix... any fixes shared will 32f08c3bdfSopenharmony_ci * be incorporated into the next SCTP release. 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci * Written or modified by: 35f08c3bdfSopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 36f08c3bdfSopenharmony_ci */ 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci/* This is a kernel test to verify the TCP-style socket interfaces. */ 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci#include <stdio.h> 41f08c3bdfSopenharmony_ci#include <unistd.h> 42f08c3bdfSopenharmony_ci#include <stdlib.h> 43f08c3bdfSopenharmony_ci#include <string.h> 44f08c3bdfSopenharmony_ci#include <fcntl.h> 45f08c3bdfSopenharmony_ci#include <sys/types.h> 46f08c3bdfSopenharmony_ci#include <sys/socket.h> 47f08c3bdfSopenharmony_ci#include <sys/uio.h> 48f08c3bdfSopenharmony_ci#include <sys/poll.h> 49f08c3bdfSopenharmony_ci#include <netinet/in.h> 50f08c3bdfSopenharmony_ci#include <errno.h> 51f08c3bdfSopenharmony_ci#include <netinet/sctp.h> 52f08c3bdfSopenharmony_ci#include <sctputil.h> 53f08c3bdfSopenharmony_ci#include "tst_kernel.h" 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_cichar *TCID = __FILE__; 56f08c3bdfSopenharmony_ciint TST_TOTAL = 22; 57f08c3bdfSopenharmony_ciint TST_CNT = 0; 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci#define MAX_CLIENTS 10 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ciint 62f08c3bdfSopenharmony_cimain(void) 63f08c3bdfSopenharmony_ci{ 64f08c3bdfSopenharmony_ci int clt_sk[MAX_CLIENTS], accept_sk[MAX_CLIENTS]; 65f08c3bdfSopenharmony_ci int listen_sk, clt2_sk, accept2_sk; 66f08c3bdfSopenharmony_ci sockaddr_storage_t clt_loop[MAX_CLIENTS]; 67f08c3bdfSopenharmony_ci sockaddr_storage_t svr_loop, accept_loop, clt2_loop; 68f08c3bdfSopenharmony_ci socklen_t addrlen; 69f08c3bdfSopenharmony_ci int error, i; 70f08c3bdfSopenharmony_ci char *message = "hello, world!\n"; 71f08c3bdfSopenharmony_ci char msgbuf[100]; 72f08c3bdfSopenharmony_ci int pf_class; 73f08c3bdfSopenharmony_ci struct pollfd poll_fd; 74f08c3bdfSopenharmony_ci fd_set set; 75f08c3bdfSopenharmony_ci struct msghdr outmessage; 76f08c3bdfSopenharmony_ci char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; 77f08c3bdfSopenharmony_ci struct iovec out_iov; 78f08c3bdfSopenharmony_ci struct cmsghdr *cmsg; 79f08c3bdfSopenharmony_ci struct sctp_sndrcvinfo *sinfo; 80f08c3bdfSopenharmony_ci struct msghdr inmessage; 81f08c3bdfSopenharmony_ci char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))]; 82f08c3bdfSopenharmony_ci char *big_buffer; 83f08c3bdfSopenharmony_ci struct iovec iov; 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci if (tst_check_driver("sctp")) 86f08c3bdfSopenharmony_ci tst_brkm(TCONF, tst_exit, "sctp driver not available"); 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci /* Rather than fflush() throughout the code, set stdout to 89f08c3bdfSopenharmony_ci * be unbuffered. 90f08c3bdfSopenharmony_ci */ 91f08c3bdfSopenharmony_ci setvbuf(stdout, NULL, _IONBF, 0); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci /* Initialize the server and client addresses. */ 94f08c3bdfSopenharmony_ci#if TEST_V6 95f08c3bdfSopenharmony_ci pf_class = PF_INET6; 96f08c3bdfSopenharmony_ci svr_loop.v6.sin6_family = AF_INET6; 97f08c3bdfSopenharmony_ci svr_loop.v6.sin6_addr = in6addr_loopback; 98f08c3bdfSopenharmony_ci svr_loop.v6.sin6_port = htons(SCTP_TESTPORT_1); 99f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 100f08c3bdfSopenharmony_ci clt_loop[i].v6.sin6_family = AF_INET6; 101f08c3bdfSopenharmony_ci clt_loop[i].v6.sin6_addr = in6addr_loopback; 102f08c3bdfSopenharmony_ci clt_loop[i].v6.sin6_port = htons(SCTP_TESTPORT_2 + i); 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci clt2_loop.v6.sin6_family = AF_INET6; 105f08c3bdfSopenharmony_ci clt2_loop.v6.sin6_addr = in6addr_loopback; 106f08c3bdfSopenharmony_ci clt2_loop.v6.sin6_port = htons(SCTP_TESTPORT_2 + i); 107f08c3bdfSopenharmony_ci#else 108f08c3bdfSopenharmony_ci pf_class = PF_INET; 109f08c3bdfSopenharmony_ci svr_loop.v4.sin_family = AF_INET; 110f08c3bdfSopenharmony_ci svr_loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 111f08c3bdfSopenharmony_ci svr_loop.v4.sin_port = htons(SCTP_TESTPORT_1); 112f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 113f08c3bdfSopenharmony_ci clt_loop[i].v4.sin_family = AF_INET; 114f08c3bdfSopenharmony_ci clt_loop[i].v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 115f08c3bdfSopenharmony_ci clt_loop[i].v4.sin_port = htons(SCTP_TESTPORT_2 + i); 116f08c3bdfSopenharmony_ci } 117f08c3bdfSopenharmony_ci clt2_loop.v4.sin_family = AF_INET; 118f08c3bdfSopenharmony_ci clt2_loop.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK; 119f08c3bdfSopenharmony_ci clt2_loop.v4.sin_port = htons(SCTP_TESTPORT_2 + i); 120f08c3bdfSopenharmony_ci#endif 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci /* Create and bind the listening server socket. */ 123f08c3bdfSopenharmony_ci listen_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); 124f08c3bdfSopenharmony_ci test_bind(listen_sk, &svr_loop.sa, sizeof(svr_loop)); 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci /* Mark listen_sk as being able to accept new associations. */ 127f08c3bdfSopenharmony_ci test_listen(listen_sk, MAX_CLIENTS-1); 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci /* Create and bind the client sockets. */ 130f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 131f08c3bdfSopenharmony_ci clt_sk[i] = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); 132f08c3bdfSopenharmony_ci test_bind(clt_sk[i], &clt_loop[i].sa, sizeof(clt_loop[i])); 133f08c3bdfSopenharmony_ci } 134f08c3bdfSopenharmony_ci clt2_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); 135f08c3bdfSopenharmony_ci test_bind(clt2_sk, &clt2_loop.sa, sizeof(clt2_loop)); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci addrlen = sizeof(accept_loop); 138f08c3bdfSopenharmony_ci /* Try to do accept on a non-listening socket. It should fail. */ 139f08c3bdfSopenharmony_ci error = accept(clt_sk[0], &accept_loop.sa, &addrlen); 140f08c3bdfSopenharmony_ci if ((-1 != error) && (EINVAL != errno)) 141f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "accept on non-listening socket " 142f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci tst_resm(TPASS, "accept on non-listening socket"); 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci /* Try to do a connect from a listening socket. It should fail. */ 147f08c3bdfSopenharmony_ci error = connect(listen_sk, (struct sockaddr *)&clt_loop[0], 148f08c3bdfSopenharmony_ci sizeof(clt_loop[0])); 149f08c3bdfSopenharmony_ci if ((-1 != error) && (EISCONN != errno)) 150f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "connect to non-listening socket " 151f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci tst_resm(TPASS, "connect to non-listening socket"); 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci /* Do a blocking connect from clt_sk's to listen_sk */ 156f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) 157f08c3bdfSopenharmony_ci test_connect(clt_sk[i], &svr_loop.sa, sizeof(svr_loop)); 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci tst_resm(TPASS, "connect to listening socket"); 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci /* Verify that no more connect's can be done after the acceptq 162f08c3bdfSopenharmony_ci * backlog has reached the max value. 163f08c3bdfSopenharmony_ci */ 164f08c3bdfSopenharmony_ci error = connect(clt2_sk, &svr_loop.sa, sizeof(svr_loop)); 165f08c3bdfSopenharmony_ci if ((-1 != error) && (ECONNREFUSED != errno)) 166f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "connect after max backlog " 167f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ci tst_resm(TPASS, "connect after max backlog"); 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci /* Extract the associations on the listening socket as new sockets. */ 172f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 173f08c3bdfSopenharmony_ci poll_fd.fd = listen_sk; 174f08c3bdfSopenharmony_ci poll_fd.events = POLLIN; 175f08c3bdfSopenharmony_ci poll_fd.revents = 0; 176f08c3bdfSopenharmony_ci error = poll(&poll_fd, 1, -1); 177f08c3bdfSopenharmony_ci if ((1 != error) && (1 != poll_fd.revents)) 178f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "Unexpected return value " 179f08c3bdfSopenharmony_ci "with poll, error:%d errno:%d, revents:%d", 180f08c3bdfSopenharmony_ci error, errno, poll_fd.revents); 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_ci addrlen = sizeof(accept_loop); 183f08c3bdfSopenharmony_ci accept_sk[i] = test_accept(listen_sk, &accept_loop.sa, 184f08c3bdfSopenharmony_ci &addrlen); 185f08c3bdfSopenharmony_ci } 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci tst_resm(TPASS, "accept from listening socket"); 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_ci /* Try to do a connect on an established socket. It should fail. */ 190f08c3bdfSopenharmony_ci error = connect(accept_sk[0], &clt_loop[0].sa, sizeof(clt_loop[0])); 191f08c3bdfSopenharmony_ci if ((-1 != error) || (EISCONN != errno)) 192f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "connect on an established socket " 193f08c3bdfSopenharmony_ci "error:%d errno:%d", error, errno); 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_ci tst_resm(TPASS, "connect on an established socket"); 196f08c3bdfSopenharmony_ci 197f08c3bdfSopenharmony_ci /* Try to do accept on an established socket. It should fail. */ 198f08c3bdfSopenharmony_ci error = accept(accept_sk[0], &accept_loop.sa, &addrlen); 199f08c3bdfSopenharmony_ci if ((-1 != error) && (EINVAL != errno)) 200f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "accept on an established socket " 201f08c3bdfSopenharmony_ci "error:%d errno:%d", error, errno); 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci error = accept(clt_sk[0], &accept_loop.sa, &addrlen); 204f08c3bdfSopenharmony_ci if ((-1 != error) && (EINVAL != errno)) 205f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "accept on an established socket " 206f08c3bdfSopenharmony_ci "failure: error:%d errno:%d", error, errno); 207f08c3bdfSopenharmony_ci 208f08c3bdfSopenharmony_ci tst_resm(TPASS, "accept on an established socket"); 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci /* Send and receive a message from the client sockets to the accepted 211f08c3bdfSopenharmony_ci * sockets. 212f08c3bdfSopenharmony_ci */ 213f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 214f08c3bdfSopenharmony_ci test_send(clt_sk[i], message, strlen(message), 0); 215f08c3bdfSopenharmony_ci test_recv(accept_sk[i], msgbuf, 100, 0); 216f08c3bdfSopenharmony_ci } 217f08c3bdfSopenharmony_ci 218f08c3bdfSopenharmony_ci tst_resm(TPASS, "client sockets -> accepted sockets"); 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci /* Send and receive a message from the accepted sockets to the client 221f08c3bdfSopenharmony_ci * sockets. 222f08c3bdfSopenharmony_ci */ 223f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) { 224f08c3bdfSopenharmony_ci test_send(accept_sk[i], message, strlen(message), 0); 225f08c3bdfSopenharmony_ci test_recv(clt_sk[i], msgbuf, 100, 0); 226f08c3bdfSopenharmony_ci } 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci tst_resm(TPASS, "accepted sockets -> client sockets"); 229f08c3bdfSopenharmony_ci 230f08c3bdfSopenharmony_ci /* Sending a message on a listening socket should fail. */ 231f08c3bdfSopenharmony_ci error = send(listen_sk, message, strlen(message), MSG_NOSIGNAL); 232f08c3bdfSopenharmony_ci if ((-1 != error) || (EPIPE != errno)) 233f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "send on a listening socket " 234f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci tst_resm(TPASS, "send on a listening socket"); 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_ci /* Trying to receive a message on a listening socket should fail. */ 239f08c3bdfSopenharmony_ci error = recv(listen_sk, msgbuf, 100, 0); 240f08c3bdfSopenharmony_ci if ((-1 != error) || (ENOTCONN != errno)) 241f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "recv on a listening socket " 242f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 243f08c3bdfSopenharmony_ci 244f08c3bdfSopenharmony_ci tst_resm(TPASS, "recv on a listening socket"); 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci /* TESTCASES for shutdown() */ 247f08c3bdfSopenharmony_ci errno = 0; 248f08c3bdfSopenharmony_ci test_send(accept_sk[0], message, strlen(message), 0); 249f08c3bdfSopenharmony_ci 250f08c3bdfSopenharmony_ci /* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ 251f08c3bdfSopenharmony_ci test_enable_assoc_change(clt_sk[0]); 252f08c3bdfSopenharmony_ci 253f08c3bdfSopenharmony_ci /* Do a SHUT_WR on clt_sk[0] to disable any new sends. */ 254f08c3bdfSopenharmony_ci test_shutdown(clt_sk[0], SHUT_WR); 255f08c3bdfSopenharmony_ci 256f08c3bdfSopenharmony_ci /* Reading on a socket that has received SHUTDOWN should return 0 257f08c3bdfSopenharmony_ci * indicating EOF. 258f08c3bdfSopenharmony_ci */ 259f08c3bdfSopenharmony_ci error = recv(accept_sk[0], msgbuf, 100, 0); 260f08c3bdfSopenharmony_ci if ((0 != error) || (0 != errno)) 261f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "recv on a SHUTDOWN received socket " 262f08c3bdfSopenharmony_ci "error:%d errno:%d", error, errno); 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci tst_resm(TPASS, "recv on a SHUTDOWN received socket"); 265f08c3bdfSopenharmony_ci 266f08c3bdfSopenharmony_ci /* Read the pending message on clt_sk[0] that was received before 267f08c3bdfSopenharmony_ci * SHUTDOWN call. 268f08c3bdfSopenharmony_ci */ 269f08c3bdfSopenharmony_ci test_recv(clt_sk[0], msgbuf, 100, 0); 270f08c3bdfSopenharmony_ci 271f08c3bdfSopenharmony_ci /* Initialize inmessage for all receives. */ 272f08c3bdfSopenharmony_ci big_buffer = test_malloc(REALLY_BIG); 273f08c3bdfSopenharmony_ci memset(&inmessage, 0, sizeof(inmessage)); 274f08c3bdfSopenharmony_ci iov.iov_base = big_buffer; 275f08c3bdfSopenharmony_ci iov.iov_len = REALLY_BIG; 276f08c3bdfSopenharmony_ci inmessage.msg_iov = &iov; 277f08c3bdfSopenharmony_ci inmessage.msg_iovlen = 1; 278f08c3bdfSopenharmony_ci inmessage.msg_control = incmsg; 279f08c3bdfSopenharmony_ci inmessage.msg_controllen = sizeof(incmsg); 280f08c3bdfSopenharmony_ci 281f08c3bdfSopenharmony_ci /* Receive the SHUTDOWN_COMP notification as they are enabled. */ 282f08c3bdfSopenharmony_ci error = test_recvmsg(clt_sk[0], &inmessage, MSG_WAITALL); 283f08c3bdfSopenharmony_ci test_check_msg_notification(&inmessage, error, 284f08c3bdfSopenharmony_ci sizeof(struct sctp_assoc_change), 285f08c3bdfSopenharmony_ci SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP); 286f08c3bdfSopenharmony_ci 287f08c3bdfSopenharmony_ci tst_resm(TPASS, "recv SHUTDOWN_COMP notification on a SHUT_WR socket"); 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_ci /* No more messages and the association is SHUTDOWN, should fail. */ 290f08c3bdfSopenharmony_ci error = recv(clt_sk[0], msgbuf, 100, 0); 291f08c3bdfSopenharmony_ci if ((-1 != error) || (ENOTCONN != errno)) 292f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "recv on a SHUTDOWN sent socket " 293f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 294f08c3bdfSopenharmony_ci 295f08c3bdfSopenharmony_ci tst_resm(TPASS, "recv on a SHUTDOWN sent socket"); 296f08c3bdfSopenharmony_ci 297f08c3bdfSopenharmony_ci errno = 0; 298f08c3bdfSopenharmony_ci 299f08c3bdfSopenharmony_ci /* Do a SHUT_RD on clt_sk[1] to disable any new receives. */ 300f08c3bdfSopenharmony_ci test_shutdown(clt_sk[1], SHUT_RD); 301f08c3bdfSopenharmony_ci 302f08c3bdfSopenharmony_ci error = recv(clt_sk[1], msgbuf, 100, 0); 303f08c3bdfSopenharmony_ci if ((0 != error) || (0 != errno)) 304f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "recv on a SHUT_RD socket " 305f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 306f08c3bdfSopenharmony_ci 307f08c3bdfSopenharmony_ci /* Sending a message on SHUT_RD socket. */ 308f08c3bdfSopenharmony_ci test_send(clt_sk[1], message, strlen(message), 0); 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci /* Receive the message sent on SHUT_RD socket. */ 311f08c3bdfSopenharmony_ci test_recv(accept_sk[1], msgbuf, 100, 0); 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ci /* Send a message to the SHUT_RD socket. */ 314f08c3bdfSopenharmony_ci test_send(accept_sk[1], message, strlen(message), 0); 315f08c3bdfSopenharmony_ci 316f08c3bdfSopenharmony_ci /* We should not receive the message as the socket is SHUT_RD */ 317f08c3bdfSopenharmony_ci error = recv(clt_sk[1], msgbuf, 100, 0); 318f08c3bdfSopenharmony_ci if ((0 != error) || (0 != errno)) 319f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "recv on a SHUT_RD socket " 320f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 321f08c3bdfSopenharmony_ci 322f08c3bdfSopenharmony_ci tst_resm(TPASS, "recv on a SHUT_RD socket"); 323f08c3bdfSopenharmony_ci 324f08c3bdfSopenharmony_ci /* Do a SHUT_RDWR on clt_sk[2] to disable any new sends/receives. */ 325f08c3bdfSopenharmony_ci test_shutdown(clt_sk[2], SHUT_RDWR); 326f08c3bdfSopenharmony_ci 327f08c3bdfSopenharmony_ci error = recv(accept_sk[2], msgbuf, 100, 0); 328f08c3bdfSopenharmony_ci if ((0 != error) || (0 != errno)) 329f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "recv on a SHUT_RDWR socket " 330f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 331f08c3bdfSopenharmony_ci 332f08c3bdfSopenharmony_ci error = recv(clt_sk[2], msgbuf, 100, 0); 333f08c3bdfSopenharmony_ci if ((0 != error) || (0 != errno)) 334f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "recv on a SHUT_RDWR socket " 335f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ci tst_resm(TPASS, "recv on a SHUT_RDWR socket"); 338f08c3bdfSopenharmony_ci 339f08c3bdfSopenharmony_ci error = 0; 340f08c3bdfSopenharmony_ci 341f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) 342f08c3bdfSopenharmony_ci close(clt_sk[i]); 343f08c3bdfSopenharmony_ci for (i = 0; i < MAX_CLIENTS; i++) 344f08c3bdfSopenharmony_ci close(accept_sk[i]); 345f08c3bdfSopenharmony_ci 346f08c3bdfSopenharmony_ci /* Test case to verify accept of a CLOSED association. */ 347f08c3bdfSopenharmony_ci /* Do a connect, send and a close to ESTABLISH and CLOSE an 348f08c3bdfSopenharmony_ci * association on the listening socket. 349f08c3bdfSopenharmony_ci */ 350f08c3bdfSopenharmony_ci test_connect(clt2_sk, &svr_loop.sa, sizeof(svr_loop)); 351f08c3bdfSopenharmony_ci 352f08c3bdfSopenharmony_ci test_send(clt2_sk, message, strlen(message), 0); 353f08c3bdfSopenharmony_ci 354f08c3bdfSopenharmony_ci close(clt2_sk); 355f08c3bdfSopenharmony_ci 356f08c3bdfSopenharmony_ci FD_ZERO(&set); 357f08c3bdfSopenharmony_ci FD_SET(listen_sk, &set); 358f08c3bdfSopenharmony_ci 359f08c3bdfSopenharmony_ci error = select(listen_sk + 1, &set, NULL, NULL, NULL); 360f08c3bdfSopenharmony_ci if (1 != error) 361f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "select error:%d, " 362f08c3bdfSopenharmony_ci "errno: %d", error, errno); 363f08c3bdfSopenharmony_ci 364f08c3bdfSopenharmony_ci /* Now accept the CLOSED association waiting on the listening 365f08c3bdfSopenharmony_ci * socket. 366f08c3bdfSopenharmony_ci */ 367f08c3bdfSopenharmony_ci accept2_sk = test_accept(listen_sk, &accept_loop.sa, &addrlen); 368f08c3bdfSopenharmony_ci 369f08c3bdfSopenharmony_ci /* Receive the message sent before doing a close. */ 370f08c3bdfSopenharmony_ci test_recv(accept2_sk, msgbuf, 100, 0); 371f08c3bdfSopenharmony_ci 372f08c3bdfSopenharmony_ci /* Receive EOF indication as there are no more messages and the 373f08c3bdfSopenharmony_ci * socket is SHUTDOWN. 374f08c3bdfSopenharmony_ci */ 375f08c3bdfSopenharmony_ci error = recv(accept2_sk, msgbuf, 100, 0); 376f08c3bdfSopenharmony_ci if ((0 != error) || (0 != errno)) 377f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "Unexpected error return on " 378f08c3bdfSopenharmony_ci "recv(error:%d, errno:%d)", error, errno); 379f08c3bdfSopenharmony_ci 380f08c3bdfSopenharmony_ci tst_resm(TPASS, "accept of a CLOSED association"); 381f08c3bdfSopenharmony_ci 382f08c3bdfSopenharmony_ci /* Trying to send a message over the CLOSED association should 383f08c3bdfSopenharmony_ci * generate EPIPE. 384f08c3bdfSopenharmony_ci */ 385f08c3bdfSopenharmony_ci error = send(accept2_sk, message, strlen(message), MSG_NOSIGNAL); 386f08c3bdfSopenharmony_ci if ((-1 != error) || (EPIPE != errno)) 387f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "send to a CLOSED association " 388f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 389f08c3bdfSopenharmony_ci 390f08c3bdfSopenharmony_ci tst_resm(TPASS, "send to a CLOSED association"); 391f08c3bdfSopenharmony_ci 392f08c3bdfSopenharmony_ci error = 0; 393f08c3bdfSopenharmony_ci close(accept2_sk); 394f08c3bdfSopenharmony_ci 395f08c3bdfSopenharmony_ci /* Verify that auto-connect can be done on a TCP-style socket using 396f08c3bdfSopenharmony_ci * sendto/sendmsg. 397f08c3bdfSopenharmony_ci */ 398f08c3bdfSopenharmony_ci clt2_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP); 399f08c3bdfSopenharmony_ci test_bind(clt2_sk, &clt2_loop.sa, sizeof(clt2_loop)); 400f08c3bdfSopenharmony_ci 401f08c3bdfSopenharmony_ci /* Do a sendto() without a connect() */ 402f08c3bdfSopenharmony_ci test_sendto(clt2_sk, message, strlen(message), 0, &svr_loop.sa, 403f08c3bdfSopenharmony_ci sizeof(svr_loop)); 404f08c3bdfSopenharmony_ci 405f08c3bdfSopenharmony_ci accept2_sk = test_accept(listen_sk, &accept_loop.sa, &addrlen); 406f08c3bdfSopenharmony_ci 407f08c3bdfSopenharmony_ci test_recv(accept2_sk, msgbuf, 100, 0); 408f08c3bdfSopenharmony_ci 409f08c3bdfSopenharmony_ci tst_resm(TPASS, "auto-connect using sendto"); 410f08c3bdfSopenharmony_ci 411f08c3bdfSopenharmony_ci outmessage.msg_name = &svr_loop; 412f08c3bdfSopenharmony_ci outmessage.msg_namelen = sizeof(svr_loop); 413f08c3bdfSopenharmony_ci outmessage.msg_iov = NULL; 414f08c3bdfSopenharmony_ci outmessage.msg_iovlen = 0; 415f08c3bdfSopenharmony_ci outmessage.msg_control = outcmsg; 416f08c3bdfSopenharmony_ci outmessage.msg_controllen = sizeof(outcmsg); 417f08c3bdfSopenharmony_ci outmessage.msg_flags = 0; 418f08c3bdfSopenharmony_ci 419f08c3bdfSopenharmony_ci cmsg = CMSG_FIRSTHDR(&outmessage); 420f08c3bdfSopenharmony_ci cmsg->cmsg_level = IPPROTO_SCTP; 421f08c3bdfSopenharmony_ci cmsg->cmsg_type = SCTP_SNDRCV; 422f08c3bdfSopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); 423f08c3bdfSopenharmony_ci outmessage.msg_controllen = cmsg->cmsg_len; 424f08c3bdfSopenharmony_ci sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 425f08c3bdfSopenharmony_ci memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo)); 426f08c3bdfSopenharmony_ci 427f08c3bdfSopenharmony_ci /* Verify that SCTP_EOF cannot be used to shutdown an association 428f08c3bdfSopenharmony_ci * on a TCP-style socket. 429f08c3bdfSopenharmony_ci */ 430f08c3bdfSopenharmony_ci sinfo->sinfo_flags |= SCTP_EOF; 431f08c3bdfSopenharmony_ci error = sendmsg(clt2_sk, &outmessage, 0); 432f08c3bdfSopenharmony_ci if ((-1 != error) || (EINVAL != errno)) 433f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "sendmsg with SCTP_EOF flag " 434f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 435f08c3bdfSopenharmony_ci 436f08c3bdfSopenharmony_ci tst_resm(TPASS, "sendmsg with SCTP_EOF flag"); 437f08c3bdfSopenharmony_ci 438f08c3bdfSopenharmony_ci /* Verify that SCTP_ABORT cannot be used to abort an association 439f08c3bdfSopenharmony_ci * on a TCP-style socket. 440f08c3bdfSopenharmony_ci */ 441f08c3bdfSopenharmony_ci sinfo->sinfo_flags |= SCTP_ABORT; 442f08c3bdfSopenharmony_ci error = sendmsg(clt2_sk, &outmessage, 0); 443f08c3bdfSopenharmony_ci if ((-1 != error) || (EINVAL != errno)) 444f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "sendmsg with SCTP_ABORT flag " 445f08c3bdfSopenharmony_ci "error:%d, errno:%d", error, errno); 446f08c3bdfSopenharmony_ci 447f08c3bdfSopenharmony_ci tst_resm(TPASS, "sendmsg with SCTP_ABORT flag"); 448f08c3bdfSopenharmony_ci 449f08c3bdfSopenharmony_ci /* Verify that a normal message can be sent using sendmsg. */ 450f08c3bdfSopenharmony_ci outmessage.msg_iov = &out_iov; 451f08c3bdfSopenharmony_ci outmessage.msg_iovlen = 1; 452f08c3bdfSopenharmony_ci out_iov.iov_base = message; 453f08c3bdfSopenharmony_ci out_iov.iov_len = strlen(message) + 1; 454f08c3bdfSopenharmony_ci sinfo->sinfo_flags = 0; 455f08c3bdfSopenharmony_ci test_sendmsg(clt2_sk, &outmessage, 0, strlen(message)+1); 456f08c3bdfSopenharmony_ci 457f08c3bdfSopenharmony_ci test_recv(accept2_sk, msgbuf, 100, 0); 458f08c3bdfSopenharmony_ci 459f08c3bdfSopenharmony_ci tst_resm(TPASS, "sendmsg with no flags"); 460f08c3bdfSopenharmony_ci 461f08c3bdfSopenharmony_ci close(clt2_sk); 462f08c3bdfSopenharmony_ci close(accept2_sk); 463f08c3bdfSopenharmony_ci close(listen_sk); 464f08c3bdfSopenharmony_ci 465f08c3bdfSopenharmony_ci /* Indicate successful completion. */ 466f08c3bdfSopenharmony_ci return 0; 467f08c3bdfSopenharmony_ci} 468