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