1f08c3bdfSopenharmony_ci/* SCTP kernel Implementation 2f08c3bdfSopenharmony_ci * (C) Copyright IBM Corp. 2001, 2003 3f08c3bdfSopenharmony_ci * Copyright (C) 1999 Cisco 4f08c3bdfSopenharmony_ci * Copyright (C) 1999-2000 Motorola 5f08c3bdfSopenharmony_ci # Copyright (C) 2001 Nokia 6f08c3bdfSopenharmony_ci * Copyright (C) 2001 La Monte H.P. Yarroll 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * The SCTP implementation is free software; 9f08c3bdfSopenharmony_ci * you can redistribute it and/or modify it under the terms of 10f08c3bdfSopenharmony_ci * the GNU General Public License as published by 11f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2, or (at your option) 12f08c3bdfSopenharmony_ci * any later version. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * The SCTP implementation is distributed in the hope that it 15f08c3bdfSopenharmony_ci * will be useful, but WITHOUT ANY WARRANTY; without even the implied 16f08c3bdfSopenharmony_ci * ************************ 17f08c3bdfSopenharmony_ci * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 18f08c3bdfSopenharmony_ci * See the GNU General Public License for more details. 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 21f08c3bdfSopenharmony_ci * along with GNU CC; see the file COPYING. If not, write to 22f08c3bdfSopenharmony_ci * the Free Software Foundation, 59 Temple Place - Suite 330, 23f08c3bdfSopenharmony_ci * Boston, MA 02111-1307, USA. 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * Please send any bug reports or fixes you make to the 26f08c3bdfSopenharmony_ci * email address(es): 27f08c3bdfSopenharmony_ci * lksctp developers <lksctp-developers@lists.sourceforge.net> 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * Or submit a bug report through the following website: 30f08c3bdfSopenharmony_ci * http://www.sf.net/projects/lksctp 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * Any bugs reported to us we will try to fix... any fixes shared will 33f08c3bdfSopenharmony_ci * be incorporated into the next SCTP release. 34f08c3bdfSopenharmony_ci * 35f08c3bdfSopenharmony_ci * Written or modified by: 36f08c3bdfSopenharmony_ci * La Monte H.P. Yarroll <piggy@acm.org> 37f08c3bdfSopenharmony_ci * Narasimha Budihal <narsi@refcode.org> 38f08c3bdfSopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 39f08c3bdfSopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 40f08c3bdfSopenharmony_ci * Daisy Chang <daisyc@us.ibm.com> 41f08c3bdfSopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 42f08c3bdfSopenharmony_ci */ 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci#include <stdio.h> 45f08c3bdfSopenharmony_ci#include <errno.h> 46f08c3bdfSopenharmony_ci#include <ctype.h> 47f08c3bdfSopenharmony_ci#include <string.h> 48f08c3bdfSopenharmony_ci#include <sys/types.h> 49f08c3bdfSopenharmony_ci#include <sys/socket.h> 50f08c3bdfSopenharmony_ci#include <sys/uio.h> 51f08c3bdfSopenharmony_ci#include <netinet/in.h> 52f08c3bdfSopenharmony_ci#include <sys/errno.h> 53f08c3bdfSopenharmony_ci#include <errno.h> 54f08c3bdfSopenharmony_ci#include <malloc.h> 55f08c3bdfSopenharmony_ci#include "netinet/sctp.h" 56f08c3bdfSopenharmony_ci#include "sctputil.h" 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci/* This function prints the cmsg data. */ 59f08c3bdfSopenharmony_civoid 60f08c3bdfSopenharmony_citest_print_cmsg(sctp_cmsg_t type, sctp_cmsg_data_t *data) 61f08c3bdfSopenharmony_ci{ 62f08c3bdfSopenharmony_ci switch(type) { 63f08c3bdfSopenharmony_ci case SCTP_INIT: 64f08c3bdfSopenharmony_ci printf("INIT\n"); 65f08c3bdfSopenharmony_ci printf(" sinit_num_ostreams %d\n", 66f08c3bdfSopenharmony_ci data->init.sinit_num_ostreams); 67f08c3bdfSopenharmony_ci printf(" sinit_max_instreams %d\n", 68f08c3bdfSopenharmony_ci data->init.sinit_max_instreams); 69f08c3bdfSopenharmony_ci printf(" sinit_max_attempts %d\n", 70f08c3bdfSopenharmony_ci data->init.sinit_max_attempts); 71f08c3bdfSopenharmony_ci printf(" sinit_max_init_timeo %d\n", 72f08c3bdfSopenharmony_ci data->init.sinit_max_init_timeo); 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci break; 75f08c3bdfSopenharmony_ci case SCTP_SNDRCV: 76f08c3bdfSopenharmony_ci printf("SNDRCV\n"); 77f08c3bdfSopenharmony_ci printf(" sinfo_stream %u\n", data->sndrcv.sinfo_stream); 78f08c3bdfSopenharmony_ci printf(" sinfo_ssn %u\n", data->sndrcv.sinfo_ssn); 79f08c3bdfSopenharmony_ci printf(" sinfo_flags 0x%x\n", data->sndrcv.sinfo_flags); 80f08c3bdfSopenharmony_ci printf(" sinfo_ppid %u\n", data->sndrcv.sinfo_ppid); 81f08c3bdfSopenharmony_ci printf(" sinfo_context %x\n", data->sndrcv.sinfo_context); 82f08c3bdfSopenharmony_ci printf(" sinfo_tsn %u\n", data->sndrcv.sinfo_tsn); 83f08c3bdfSopenharmony_ci printf(" sinfo_cumtsn %u\n", data->sndrcv.sinfo_cumtsn); 84f08c3bdfSopenharmony_ci printf(" sinfo_assoc_id %u\n", data->sndrcv.sinfo_assoc_id); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci break; 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci default: 89f08c3bdfSopenharmony_ci printf("UNKNOWN CMSG: %d\n", type); 90f08c3bdfSopenharmony_ci break; 91f08c3bdfSopenharmony_ci } 92f08c3bdfSopenharmony_ci} 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci/* This function prints the message. */ 95f08c3bdfSopenharmony_civoid 96f08c3bdfSopenharmony_citest_print_message(int sk LTP_ATTRIBUTE_UNUSED, struct msghdr *msg, size_t msg_len) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci sctp_cmsg_data_t *data; 99f08c3bdfSopenharmony_ci struct cmsghdr *cmsg; 100f08c3bdfSopenharmony_ci unsigned int i; 101f08c3bdfSopenharmony_ci int done = 0; 102f08c3bdfSopenharmony_ci char save; 103f08c3bdfSopenharmony_ci union sctp_notification *sn; 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci for (cmsg = CMSG_FIRSTHDR(msg); 106f08c3bdfSopenharmony_ci cmsg != NULL; 107f08c3bdfSopenharmony_ci cmsg = CMSG_NXTHDR(msg, cmsg)) { 108f08c3bdfSopenharmony_ci data = (sctp_cmsg_data_t *)CMSG_DATA(cmsg); 109f08c3bdfSopenharmony_ci test_print_cmsg(cmsg->cmsg_type, data); 110f08c3bdfSopenharmony_ci } 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci if (!(MSG_NOTIFICATION & msg->msg_flags)) { 113f08c3bdfSopenharmony_ci int index = 0; 114f08c3bdfSopenharmony_ci /* Make sure that everything is printable and that we 115f08c3bdfSopenharmony_ci * are NUL terminated... 116f08c3bdfSopenharmony_ci */ 117f08c3bdfSopenharmony_ci printf("DATA(%ld): ", msg_len); 118f08c3bdfSopenharmony_ci while ( msg_len > 0 ) { 119f08c3bdfSopenharmony_ci char *text; 120f08c3bdfSopenharmony_ci unsigned int len; 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci text = msg->msg_iov[index].iov_base; 123f08c3bdfSopenharmony_ci len = msg->msg_iov[index].iov_len; 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci save = text[msg_len-1]; 126f08c3bdfSopenharmony_ci if ( len > msg_len ) { 127f08c3bdfSopenharmony_ci text[(len = msg_len) - 1] = '\0'; 128f08c3bdfSopenharmony_ci } 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci if ( (msg_len -= len) > 0 ) { index++; } 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci for (i = 0; i < len - 1; ++i) { 133f08c3bdfSopenharmony_ci if (!isprint(text[i])) text[i] = '.'; 134f08c3bdfSopenharmony_ci } 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci printf("%s", text); 137f08c3bdfSopenharmony_ci text[msg_len-1] = save; 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_ci if ( (done = !strcmp(text, "exit")) ) { break; } 140f08c3bdfSopenharmony_ci } 141f08c3bdfSopenharmony_ci } else { 142f08c3bdfSopenharmony_ci printf("NOTIFICATION: "); 143f08c3bdfSopenharmony_ci sn = (union sctp_notification *)msg->msg_iov[0].iov_base; 144f08c3bdfSopenharmony_ci switch (sn->sn_header.sn_type) { 145f08c3bdfSopenharmony_ci case SCTP_ASSOC_CHANGE: 146f08c3bdfSopenharmony_ci switch (sn->sn_assoc_change.sac_state) { 147f08c3bdfSopenharmony_ci case SCTP_COMM_UP: 148f08c3bdfSopenharmony_ci printf("ASSOC_CHANGE - COMM_UP"); 149f08c3bdfSopenharmony_ci break; 150f08c3bdfSopenharmony_ci case SCTP_COMM_LOST: 151f08c3bdfSopenharmony_ci printf("ASSOC_CHANGE - COMM_LOST"); 152f08c3bdfSopenharmony_ci break; 153f08c3bdfSopenharmony_ci case SCTP_RESTART: 154f08c3bdfSopenharmony_ci printf("ASSOC_CHANGE - RESTART"); 155f08c3bdfSopenharmony_ci break; 156f08c3bdfSopenharmony_ci case SCTP_SHUTDOWN_COMP: 157f08c3bdfSopenharmony_ci printf("ASSOC_CHANGE - SHUTDOWN_COMP"); 158f08c3bdfSopenharmony_ci break; 159f08c3bdfSopenharmony_ci case SCTP_CANT_STR_ASSOC: 160f08c3bdfSopenharmony_ci printf("ASSOC_CHANGE - CANT_STR_ASSOC"); 161f08c3bdfSopenharmony_ci break; 162f08c3bdfSopenharmony_ci default: 163f08c3bdfSopenharmony_ci printf("ASSOC_CHANGE - UNEXPECTED(%d)", 164f08c3bdfSopenharmony_ci sn->sn_assoc_change.sac_state); 165f08c3bdfSopenharmony_ci break; 166f08c3bdfSopenharmony_ci } 167f08c3bdfSopenharmony_ci break; 168f08c3bdfSopenharmony_ci default: 169f08c3bdfSopenharmony_ci printf("%d", sn->sn_header.sn_type); 170f08c3bdfSopenharmony_ci break; 171f08c3bdfSopenharmony_ci } 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci printf("\n"); 175f08c3bdfSopenharmony_ci} 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci/* Check if a buf/msg_flags matches a notification, its type, and possibly an 178f08c3bdfSopenharmony_ci * additional field in the corresponding notification structure. 179f08c3bdfSopenharmony_ci */ 180f08c3bdfSopenharmony_civoid 181f08c3bdfSopenharmony_citest_check_buf_notification(void *buf, int datalen, int msg_flags, 182f08c3bdfSopenharmony_ci int expected_datalen, uint16_t expected_sn_type, 183f08c3bdfSopenharmony_ci uint32_t expected_additional) 184f08c3bdfSopenharmony_ci{ 185f08c3bdfSopenharmony_ci union sctp_notification *sn; 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci if (!(msg_flags & MSG_NOTIFICATION)) 188f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 189f08c3bdfSopenharmony_ci "Got a datamsg, expecting notification"); 190f08c3bdfSopenharmony_ci 191f08c3bdfSopenharmony_ci if (expected_datalen <= 0) 192f08c3bdfSopenharmony_ci return; 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci if (datalen != expected_datalen) 195f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 196f08c3bdfSopenharmony_ci "Got a notification of unexpected length:%d, expected length:%d", 197f08c3bdfSopenharmony_ci datalen, expected_datalen); 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci sn = (union sctp_notification *)buf; 200f08c3bdfSopenharmony_ci if (sn->sn_header.sn_type != expected_sn_type) 201f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 202f08c3bdfSopenharmony_ci "Unexpected notification:%d expected:%d", 203f08c3bdfSopenharmony_ci sn->sn_header.sn_type, expected_sn_type); 204f08c3bdfSopenharmony_ci 205f08c3bdfSopenharmony_ci switch(sn->sn_header.sn_type){ 206f08c3bdfSopenharmony_ci case SCTP_ASSOC_CHANGE: 207f08c3bdfSopenharmony_ci if (sn->sn_assoc_change.sac_state != expected_additional) 208f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 209f08c3bdfSopenharmony_ci "Unexpected sac_state:%d expected:%d", 210f08c3bdfSopenharmony_ci sn->sn_assoc_change.sac_state, expected_additional); 211f08c3bdfSopenharmony_ci break; 212f08c3bdfSopenharmony_ci default: 213f08c3bdfSopenharmony_ci break; 214f08c3bdfSopenharmony_ci } 215f08c3bdfSopenharmony_ci} 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci/* Check if a message matches a notification, its type, and possibly an 218f08c3bdfSopenharmony_ci * additional field in the corresponding notification structure. 219f08c3bdfSopenharmony_ci */ 220f08c3bdfSopenharmony_civoid 221f08c3bdfSopenharmony_citest_check_msg_notification(struct msghdr *msg, int datalen, 222f08c3bdfSopenharmony_ci int expected_datalen, uint16_t expected_sn_type, 223f08c3bdfSopenharmony_ci uint32_t expected_additional) 224f08c3bdfSopenharmony_ci{ 225f08c3bdfSopenharmony_ci test_check_buf_notification(msg->msg_iov[0].iov_base, datalen, 226f08c3bdfSopenharmony_ci msg->msg_flags, expected_datalen, 227f08c3bdfSopenharmony_ci expected_sn_type, expected_additional); 228f08c3bdfSopenharmony_ci} 229f08c3bdfSopenharmony_ci 230f08c3bdfSopenharmony_ci/* Check if a buf/msg_flags/sinfo corresponds to data, its length, msg_flags, 231f08c3bdfSopenharmony_ci * stream and ppid. 232f08c3bdfSopenharmony_ci */ 233f08c3bdfSopenharmony_civoid 234f08c3bdfSopenharmony_citest_check_buf_data(void *buf LTP_ATTRIBUTE_UNUSED, int datalen, int msg_flags, 235f08c3bdfSopenharmony_ci struct sctp_sndrcvinfo *sinfo, int expected_datalen, 236f08c3bdfSopenharmony_ci int expected_msg_flags, uint16_t expected_stream, 237f08c3bdfSopenharmony_ci uint32_t expected_ppid) 238f08c3bdfSopenharmony_ci{ 239f08c3bdfSopenharmony_ci if (msg_flags & MSG_NOTIFICATION) 240f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 241f08c3bdfSopenharmony_ci "Got a notification, expecting a datamsg"); 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_ci if (expected_datalen <= 0) 244f08c3bdfSopenharmony_ci return; 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci if (datalen != expected_datalen) 247f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 248f08c3bdfSopenharmony_ci "Got a datamsg of unexpected length:%d, expected length:%d", 249f08c3bdfSopenharmony_ci datalen, expected_datalen); 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci if (((int)(msg_flags & ~0x80000000)) != expected_msg_flags) 252f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 253f08c3bdfSopenharmony_ci "Unexpected msg_flags:0x%x expecting:0x%x", 254f08c3bdfSopenharmony_ci msg_flags, expected_msg_flags); 255f08c3bdfSopenharmony_ci 256f08c3bdfSopenharmony_ci if ((0 == expected_stream) && (0 == expected_ppid)) 257f08c3bdfSopenharmony_ci return; 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_ci if (!sinfo) 260f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 261f08c3bdfSopenharmony_ci "Null sinfo, but expected stream:%d expected ppid:%d", 262f08c3bdfSopenharmony_ci expected_stream, expected_ppid); 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci if (sinfo->sinfo_stream != expected_stream) 265f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 266f08c3bdfSopenharmony_ci "stream mismatch: expected:%x got:%x", 267f08c3bdfSopenharmony_ci expected_stream, sinfo->sinfo_stream); 268f08c3bdfSopenharmony_ci if (sinfo->sinfo_ppid != expected_ppid) 269f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 270f08c3bdfSopenharmony_ci "ppid mismatch: expected:%x got:%x\n", 271f08c3bdfSopenharmony_ci expected_ppid, sinfo->sinfo_ppid); 272f08c3bdfSopenharmony_ci} 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci/* Check if a message corresponds to data, its length, msg_flags, stream and 275f08c3bdfSopenharmony_ci * ppid. 276f08c3bdfSopenharmony_ci */ 277f08c3bdfSopenharmony_civoid 278f08c3bdfSopenharmony_citest_check_msg_data(struct msghdr *msg, int datalen, int expected_datalen, 279f08c3bdfSopenharmony_ci int expected_msg_flags, uint16_t expected_stream, 280f08c3bdfSopenharmony_ci uint32_t expected_ppid) 281f08c3bdfSopenharmony_ci{ 282f08c3bdfSopenharmony_ci struct cmsghdr *cmsg = NULL; 283f08c3bdfSopenharmony_ci struct sctp_sndrcvinfo *sinfo = NULL; 284f08c3bdfSopenharmony_ci 285f08c3bdfSopenharmony_ci /* Receive auxiliary data in msgh. */ 286f08c3bdfSopenharmony_ci for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 287f08c3bdfSopenharmony_ci cmsg = CMSG_NXTHDR(msg, cmsg)){ 288f08c3bdfSopenharmony_ci if (IPPROTO_SCTP == cmsg->cmsg_level && 289f08c3bdfSopenharmony_ci SCTP_SNDRCV == cmsg->cmsg_type) 290f08c3bdfSopenharmony_ci break; 291f08c3bdfSopenharmony_ci } /* for( all cmsgs) */ 292f08c3bdfSopenharmony_ci 293f08c3bdfSopenharmony_ci if ((!cmsg) || 294f08c3bdfSopenharmony_ci (cmsg->cmsg_len < CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))) 295f08c3bdfSopenharmony_ci sinfo = NULL; 296f08c3bdfSopenharmony_ci else 297f08c3bdfSopenharmony_ci sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); 298f08c3bdfSopenharmony_ci 299f08c3bdfSopenharmony_ci test_check_buf_data(msg->msg_iov[0].iov_base, datalen, msg->msg_flags, 300f08c3bdfSopenharmony_ci sinfo, expected_datalen, expected_msg_flags, 301f08c3bdfSopenharmony_ci expected_stream, expected_ppid); 302f08c3bdfSopenharmony_ci 303f08c3bdfSopenharmony_ci} 304f08c3bdfSopenharmony_ci 305f08c3bdfSopenharmony_ci 306f08c3bdfSopenharmony_ci/* Allocate a buffer of requested len and fill in with data. */ 307f08c3bdfSopenharmony_civoid * 308f08c3bdfSopenharmony_citest_build_msg(int len) 309f08c3bdfSopenharmony_ci{ 310f08c3bdfSopenharmony_ci int i = len - 1; 311f08c3bdfSopenharmony_ci int n; 312f08c3bdfSopenharmony_ci unsigned char msg[] = 313f08c3bdfSopenharmony_ci "012345678901234567890123456789012345678901234567890"; 314f08c3bdfSopenharmony_ci char *msg_buf, *p; 315f08c3bdfSopenharmony_ci 316f08c3bdfSopenharmony_ci msg_buf = (char *)malloc(len); 317f08c3bdfSopenharmony_ci if (!msg_buf) 318f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, "malloc failed"); 319f08c3bdfSopenharmony_ci 320f08c3bdfSopenharmony_ci p = msg_buf; 321f08c3bdfSopenharmony_ci 322f08c3bdfSopenharmony_ci do { 323f08c3bdfSopenharmony_ci n = ((i > 50)?50:i); 324f08c3bdfSopenharmony_ci memcpy(p, msg, ((i > 50)?50:i)); 325f08c3bdfSopenharmony_ci p += n; 326f08c3bdfSopenharmony_ci i -= n; 327f08c3bdfSopenharmony_ci } while (i > 0); 328f08c3bdfSopenharmony_ci 329f08c3bdfSopenharmony_ci msg_buf[len-1] = '\0'; 330f08c3bdfSopenharmony_ci 331f08c3bdfSopenharmony_ci return(msg_buf); 332f08c3bdfSopenharmony_ci} 333f08c3bdfSopenharmony_ci 334f08c3bdfSopenharmony_ci/* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */ 335f08c3bdfSopenharmony_civoid test_enable_assoc_change(int fd) 336f08c3bdfSopenharmony_ci{ 337f08c3bdfSopenharmony_ci struct sctp_event_subscribe subscribe; 338f08c3bdfSopenharmony_ci 339f08c3bdfSopenharmony_ci memset(&subscribe, 0, sizeof(subscribe)); 340f08c3bdfSopenharmony_ci subscribe.sctp_data_io_event = 1; 341f08c3bdfSopenharmony_ci subscribe.sctp_association_event = 1; 342f08c3bdfSopenharmony_ci test_setsockopt(fd, SCTP_EVENTS, (char *)&subscribe, 343f08c3bdfSopenharmony_ci sizeof(subscribe)); 344f08c3bdfSopenharmony_ci} 345f08c3bdfSopenharmony_ci 346f08c3bdfSopenharmony_cistatic int cmp_addr(sockaddr_storage_t *addr1, sockaddr_storage_t *addr2) 347f08c3bdfSopenharmony_ci{ 348f08c3bdfSopenharmony_ci if (addr1->sa.sa_family != addr2->sa.sa_family) 349f08c3bdfSopenharmony_ci return 0; 350f08c3bdfSopenharmony_ci switch (addr1->sa.sa_family) { 351f08c3bdfSopenharmony_ci case AF_INET6: 352f08c3bdfSopenharmony_ci if (addr1->v6.sin6_port != addr2->v6.sin6_port) 353f08c3bdfSopenharmony_ci return -1; 354f08c3bdfSopenharmony_ci return memcmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr, 355f08c3bdfSopenharmony_ci sizeof(addr1->v6.sin6_addr)); 356f08c3bdfSopenharmony_ci case AF_INET: 357f08c3bdfSopenharmony_ci if (addr1->v4.sin_port != addr2->v4.sin_port) 358f08c3bdfSopenharmony_ci return 0; 359f08c3bdfSopenharmony_ci return memcmp(&addr1->v4.sin_addr, &addr2->v4.sin_addr, 360f08c3bdfSopenharmony_ci sizeof(addr1->v4.sin_addr)); 361f08c3bdfSopenharmony_ci default: 362f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 363f08c3bdfSopenharmony_ci "invalid address type %d", addr1->sa.sa_family); 364f08c3bdfSopenharmony_ci return -1; 365f08c3bdfSopenharmony_ci } 366f08c3bdfSopenharmony_ci} 367f08c3bdfSopenharmony_ci 368f08c3bdfSopenharmony_ci/* Test peer addresses for association. */ 369f08c3bdfSopenharmony_ciint test_peer_addr(int sk, sctp_assoc_t asoc, sockaddr_storage_t *peers, int count) 370f08c3bdfSopenharmony_ci{ 371f08c3bdfSopenharmony_ci struct sockaddr *addrs; 372f08c3bdfSopenharmony_ci int error, i, j; 373f08c3bdfSopenharmony_ci struct sockaddr *sa_addr; 374f08c3bdfSopenharmony_ci socklen_t addrs_size = 0; 375f08c3bdfSopenharmony_ci void *addrbuf; 376f08c3bdfSopenharmony_ci char found[count]; 377f08c3bdfSopenharmony_ci memset(found, 0, count); 378f08c3bdfSopenharmony_ci 379f08c3bdfSopenharmony_ci error = sctp_getpaddrs(sk, asoc, &addrs); 380f08c3bdfSopenharmony_ci if (-1 == error) { 381f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 382f08c3bdfSopenharmony_ci "sctp_getpaddrs: %s", strerror(errno)); 383f08c3bdfSopenharmony_ci return error; 384f08c3bdfSopenharmony_ci } 385f08c3bdfSopenharmony_ci if (error != count) { 386f08c3bdfSopenharmony_ci sctp_freepaddrs(addrs); 387f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 388f08c3bdfSopenharmony_ci "peer count %d mismatch, expected %d", 389f08c3bdfSopenharmony_ci error, count); 390f08c3bdfSopenharmony_ci } 391f08c3bdfSopenharmony_ci addrbuf = addrs; 392f08c3bdfSopenharmony_ci for (i = 0; i < count; i++) { 393f08c3bdfSopenharmony_ci sa_addr = (struct sockaddr *)addrbuf; 394f08c3bdfSopenharmony_ci switch (sa_addr->sa_family) { 395f08c3bdfSopenharmony_ci case AF_INET: 396f08c3bdfSopenharmony_ci addrs_size += sizeof(struct sockaddr_in); 397f08c3bdfSopenharmony_ci addrbuf += sizeof(struct sockaddr_in); 398f08c3bdfSopenharmony_ci break; 399f08c3bdfSopenharmony_ci case AF_INET6: 400f08c3bdfSopenharmony_ci addrs_size += sizeof(struct sockaddr_in6); 401f08c3bdfSopenharmony_ci addrbuf += sizeof(struct sockaddr_in6); 402f08c3bdfSopenharmony_ci break; 403f08c3bdfSopenharmony_ci default: 404f08c3bdfSopenharmony_ci errno = EINVAL; 405f08c3bdfSopenharmony_ci sctp_freepaddrs(addrs); 406f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 407f08c3bdfSopenharmony_ci "sctp_getpaddrs: %s", strerror(errno)); 408f08c3bdfSopenharmony_ci return -1; 409f08c3bdfSopenharmony_ci } 410f08c3bdfSopenharmony_ci for (j = 0; j < count; j++) { 411f08c3bdfSopenharmony_ci if (cmp_addr((sockaddr_storage_t *)sa_addr, 412f08c3bdfSopenharmony_ci &peers[j]) == 0) { 413f08c3bdfSopenharmony_ci found[j] = 1; 414f08c3bdfSopenharmony_ci } 415f08c3bdfSopenharmony_ci } 416f08c3bdfSopenharmony_ci } 417f08c3bdfSopenharmony_ci for (j = 0; j < count; j++) { 418f08c3bdfSopenharmony_ci if (found[j] == 0) { 419f08c3bdfSopenharmony_ci tst_brkm(TBROK, tst_exit, 420f08c3bdfSopenharmony_ci "peer address %d not found", j); 421f08c3bdfSopenharmony_ci } 422f08c3bdfSopenharmony_ci } 423f08c3bdfSopenharmony_ci sctp_freepaddrs(addrs); 424f08c3bdfSopenharmony_ci return 0; 425f08c3bdfSopenharmony_ci} 426