xref: /aosp_15_r20/external/ltp/utils/sctp/func_tests/test_1_to_1_sockopt.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 /* SCTP kernel Implementation
2  * Copyright (c) 2003 Hewlett-Packard Development Company, L.P
3  * (C) Copyright IBM Corp. 2004
4  *
5  * This file has test cases to test negative scenarios for getsockopt ()
6  * setsockopt () call for 1-1 style sockets
7  *
8  * setsockopt () Tests:
9  * -------------------
10  * TEST1: setsockopt: Bad socket descriptor
11  * TEST2: setsockopt: Invalid socket
12  * TEST3: setsockopt: Invalid level
13  * TEST4: setsockopt: Invalid option buffer
14  * TEST5: setsockopt: Invalid option name
15  * TEST6: getsockopt: Bad socket descriptor
16  * TEST7: getsockopt: Invalid socket
17  * TEST8: getsockopt: Invalid option buffer
18  * TEST9: getsockopt: Invalid option name
19  *
20  * TEST10: getsockopt: SCTP_INITMSG
21  * TEST11: setsockopt: SCTP_INITMSG
22  * TEST12: setsockopt: SO_LINGER
23  * TEST13: getsockopt: SO_LINGER
24  * TEST14: getsockopt: SO_RCVBUF
25  * TEST15: getsockopt: SCTP_STATUS
26  * TEST16: setsockopt: SO_RCVBUF
27  * TEST17: setsockopt: SO_SNDBUF
28  * TEST18: getsockopt: SO_SNDBUF
29  * TEST19: getsockopt: SCTP_PRIMARY_ADDR
30  * TEST20: setsockopt: SCTP_PRIMARY_ADDR
31  * TEST21: getsockopt: SCTP_ASSOCINFO
32  * TEST22: setsockopt: SCTP_ASSOCINFO
33  *
34  * The SCTP implementation is free software;
35  * you can redistribute it and/or modify it under the terms of
36  * the GNU General Public License as published by
37  * the Free Software Foundation; either version 2, or (at your option)
38  * any later version.
39  *
40  * The SCTP implementation is distributed in the hope that it
41  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
42  *                 ************************
43  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
44  * See the GNU General Public License for more details.
45  *
46  * You should have received a copy of the GNU General Public License
47  * along with GNU CC; see the file COPYING.  If not, write to
48  * the Free Software Foundation, 59 Temple Place - Suite 330,
49  * Boston, MA 02111-1307, USA.
50  *
51  * Please send any bug reports or fixes you make to the
52  * email address(es):
53  *    lksctp developers <[email protected]>
54  *
55  * Or submit a bug report through the following website:
56  *    http://www.sf.net/projects/lksctp
57  *
58  * Any bugs reported given to us we will try to fix... any fixes shared will
59  * be incorporated into the next SCTP release.
60  *
61  */
62 
63 #include <stdio.h>
64 #include <unistd.h>
65 #include <fcntl.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <sys/types.h>
69 #include <sys/socket.h>
70 #include <netinet/in.h>
71 #include <errno.h>
72 #include <netinet/sctp.h>
73 #include <sys/uio.h>
74 #include <sctputil.h>
75 #include "tst_kernel.h"
76 
77 char *TCID = __FILE__;
78 int TST_TOTAL = 22;
79 int TST_CNT = 0;
80 
81 int
main(void)82 main(void)
83 {
84 	int error;
85 	socklen_t len;
86 	int sk, sk1, sk2, acpt_sk, pf_class;
87 	struct sctp_rtoinfo grtinfo;
88 	struct sockaddr_in lstn_addr, conn_addr;
89 	struct sctp_initmsg ginmsg; /*get the value for SCTP_INITMSG*/
90 	struct sctp_initmsg sinmsg; /*set the value for SCTP_INITMSG*/
91 	struct linger slinger; /*SO_LINGER structure*/
92 	struct linger glinger; /*SO_LINGER structure*/
93 	struct sockaddr_in addr;
94 	struct sockaddr_in *gaddr;
95 	struct sctp_status gstatus; /*SCTP_STATUS option*/
96 	int rcvbuf_val_get, rcvbuf_val_set; /*get and set var for SO_RCVBUF*/
97 	int sndbuf_val_get, sndbuf_val_set;/*get and set var for SO_SNDBUF*/
98 	struct sctp_prim gprimaddr;/*SCTP_PRIMARY_ADDR get*/
99 	struct sctp_prim sprimaddr;/*SCTP_PRIMARY_ADDR set*/
100 	struct sctp_assocparams sassocparams;  /* SCTP_ASSOCPARAMS set */
101 	struct sctp_assocparams gassocparams;  /* SCTP_ASSOCPARAMS get */
102 	int fd, err_no = 0;
103 	char filename[21];
104 
105 	if (tst_check_driver("sctp"))
106 		tst_brkm(TCONF, tst_exit, "sctp driver not available");
107 
108 	/* Rather than fflush() throughout the code, set stdout to
109          * be unbuffered.
110          */
111         setvbuf(stdout, NULL, _IONBF, 0);
112         setvbuf(stderr, NULL, _IONBF, 0);
113 
114 	pf_class = PF_INET;
115 
116 	sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
117 
118 	/*setsockopt() TEST1: Bad socket descriptor EBADF, Expected error*/
119         error = setsockopt(-1, IPPROTO_SCTP, 0, 0, 0);
120 	if (error != -1 || errno != EBADF)
121 		tst_brkm(TBROK, tst_exit, "setsockopt with a bad socket "
122 			 "descriptor error:%d, errno:%d", error, errno);
123 
124 	tst_resm(TPASS, "setsockopt() with a bad socket descriptor - EBADF");
125 
126 	/*setsockopt() TEST2: Invalid socket ENOTSOCK, Expected error*/
127 	strcpy(filename, "/tmp/sctptest.XXXXXX");
128 	fd = mkstemp(filename);
129 	if (fd == -1)
130 		tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s",
131 				filename, strerror(errno));
132 	error = setsockopt(fd, IPPROTO_SCTP, 0, 0, 0);
133 	if (error == -1)
134 		err_no = errno;
135 	close(fd);
136 	unlink(filename);
137 	if (error != -1 || err_no != ENOTSOCK)
138 		tst_brkm(TBROK, tst_exit, "setsockopt with an invalid socket "
139 			 "error:%d, errno:%d", error, err_no);
140 
141 	tst_resm(TPASS, "setsockopt() with an invalid socket - ENOTSOCK");
142 
143 	/*setsockopt() TEST3: Invalid level ENOPROTOOPT, Expected error*/
144         error = setsockopt(sk, -1, SCTP_RTOINFO, 0, 0);
145 	if (error != -1 || errno != ENOPROTOOPT)
146 		tst_brkm(TBROK, tst_exit, "setsockopt with invalid level "
147 			 "error:%d, errno:%d", error, errno);
148 
149 	tst_resm(TPASS, "setsockopt() with an invalid level - ENOPROTOOPT");
150 
151 	/*setsockopt() TEST4: Invalid option buffer EFAULT, Expected error*/
152         error = setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO,
153 		(const struct sctp_rtoinfo *)-1, sizeof(struct sctp_rtoinfo));
154 	if (error != -1 || errno != EFAULT)
155 		tst_brkm(TBROK, tst_exit, "setsockopt with invalid option "
156 			 "buffer error:%d, errno:%d", error, errno);
157 
158 	tst_resm(TPASS, "setsockopt() with invalid option buffer - EFAULT");
159 
160 	/*setsockopt() TEST5: Invalid option Name EOPNOTSUPP, Expected error*/
161         error = setsockopt(sk, IPPROTO_SCTP, SCTP_AUTOCLOSE, 0, 0);
162 	if (error != -1 || errno != EOPNOTSUPP)
163 		tst_brkm(TBROK, tst_exit, "setsockopt with invalid option "
164 			 "name error:%d, errno:%d", error, errno);
165 
166 	tst_resm(TPASS, "setsockopt() with invalid option name - EOPNOTSUPP");
167 
168 	/*getsockopt() TEST6: Bad socket descriptor EBADF, Expected error*/
169         error = getsockopt(-1, IPPROTO_SCTP, 0, 0, 0);
170 	if (error != -1 || errno != EBADF)
171 		tst_brkm(TBROK, tst_exit, "getsockopt with a bad socket "
172 			 "descriptor error:%d, errno:%d", error, errno);
173 
174 	tst_resm(TPASS, "getsockopt() with a bad socket descriptor - EBADF");
175 
176 	/*getsockopt() TEST7: Invalid socket ENOTSOCK, Expected error*/
177 	strcpy(filename, "/tmp/sctptest.XXXXXX");
178 	fd = mkstemp(filename);
179 	if (fd == -1)
180 		tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s",
181 				filename, strerror(errno));
182 	error = getsockopt(fd, IPPROTO_SCTP, 0, 0, 0);
183 	if (error == -1)
184 		err_no = errno;
185 	close(fd);
186 	unlink(filename);
187 	if (error != -1 || err_no != ENOTSOCK)
188 		tst_brkm(TBROK, tst_exit, "getsockopt with an invalid socket "
189 			 "error:%d, errno:%d", error, err_no);
190 
191 	tst_resm(TPASS, "getsockopt() with an invalid socket - ENOTSOCK");
192 #if 0
193 	/*getsockopt() TEST3: Invalid level ENOPROTOOPT, Expected error*/
194 	/*I have commented this test case because it is returning EOPNOTSUPP.
195 	When I checked the code there also it is returning EOPNOTSUPP. As this
196 	is not specific to TCP style, I do not want to do the code change*/
197 
198         error = getsockopt(sk, -1, SCTP_RTOINFO, 0, 0);
199 	if (error != -1 || errno != ENOPROTOOPT)
200 		tst_brkm(TBROK, tst_exit, "getsockopt with invalid level "
201 			 "error:%d, errno:%d", error, errno);
202 
203 	tst_resm(TPASS, "getsockopt() with an invalid level - ENOPROTOOPT");
204 #endif
205 	len = sizeof(struct sctp_rtoinfo);
206 
207 	/*getsockopt() TEST8: Invalid option buffer EFAULT, Expected error*/
208         error = getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO,
209 			   (struct sctp_rtoinfo *)-1, &len);
210 	if (error != -1 || errno != EFAULT)
211 		tst_brkm(TBROK, tst_exit, "getsockopt with invalid option "
212 			 "buffer error:%d, errno:%d", error, errno);
213 
214 	tst_resm(TPASS, "getsockopt() with invalid option buffer - EFAULT");
215 
216 	/*getsockopt() TEST9: Invalid option Name EOPNOTSUPP, Expected error*/
217         error = getsockopt(sk, IPPROTO_SCTP, SCTP_AUTOCLOSE, &grtinfo, &len);
218 	if (error != -1 || errno != EOPNOTSUPP)
219 		tst_brkm(TBROK, tst_exit, "getsockopt with invalid option "
220 			 "name error:%d, errno:%d", error, errno);
221 
222 	tst_resm(TPASS, "getsockopt() with invalid option name - EOPNOTSUPP");
223 
224 	close(sk);
225 
226 	sk1 = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
227 	sk2 = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
228 
229 	lstn_addr.sin_family = AF_INET;
230         lstn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK;
231         lstn_addr.sin_port = htons(SCTP_TESTPORT_1);
232 
233 	conn_addr.sin_family = AF_INET;
234         conn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK;
235         conn_addr.sin_port = htons(SCTP_TESTPORT_1);
236 
237         len = sizeof(struct sctp_initmsg);
238 
239 	/* TEST10: Test cases for getsockopt SCTP_INITMSG */
240 	test_getsockopt(sk1, SCTP_INITMSG, &ginmsg, &len);
241 
242 	tst_resm(TPASS, "getsockopt() SCTP_INITMSG - SUCCESS");
243 
244 	sinmsg.sinit_num_ostreams = 5;
245         sinmsg.sinit_max_instreams = 5;
246         sinmsg.sinit_max_attempts = 3;
247         sinmsg.sinit_max_init_timeo = 30;
248 	/* TEST11: Test case for setsockopt SCTP_INITMSG */
249 	test_setsockopt(sk1, SCTP_INITMSG, &sinmsg, sizeof(sinmsg));
250 
251 	test_getsockopt(sk1, SCTP_INITMSG, &ginmsg, &len);
252 
253 	if (sinmsg.sinit_num_ostreams != ginmsg.sinit_num_ostreams &&
254 	    sinmsg.sinit_max_instreams != ginmsg.sinit_max_instreams &&
255 	    sinmsg.sinit_max_attempts != ginmsg.sinit_max_attempts &&
256 	    sinmsg.sinit_max_init_timeo != ginmsg.sinit_max_init_timeo)
257 		tst_brkm(TBROK, tst_exit, "setsockopt/getsockopt SCTP_INITMSG "
258 			 "compare failed");
259 
260 	tst_resm(TPASS, "setsockopt() SCTP_INITMSG - SUCCESS");
261 
262 	/*Now get the values on different endpoint*/
263 	test_getsockopt(sk2, SCTP_INITMSG, &ginmsg, &len);
264 
265 	/*Comparison should not succeed here*/
266 	if (sinmsg.sinit_num_ostreams == ginmsg.sinit_num_ostreams &&
267 	    sinmsg.sinit_max_instreams == ginmsg.sinit_max_instreams &&
268 	    sinmsg.sinit_max_attempts == ginmsg.sinit_max_attempts &&
269 	    sinmsg.sinit_max_init_timeo == ginmsg.sinit_max_init_timeo)
270 		tst_brkm(TBROK, tst_exit, "setsockopt/getsockopt SCTP_INITMSG "
271 			 "unexpected compare success");
272 
273 	/* SO_LINGER Test with l_onff = 0 and l_linger = 0 */
274 	slinger.l_onoff = 0;
275 	slinger.l_linger = 0;
276 	test_bind(sk1, (struct sockaddr *) &lstn_addr, sizeof(lstn_addr));
277 	test_listen(sk1, 10 );
278 	len = sizeof(struct sockaddr_in);
279 	test_connect(sk2, (struct sockaddr *) &conn_addr, len);
280 
281 	acpt_sk = test_accept(sk1, (struct sockaddr *)&addr, &len);
282 
283         len = sizeof(struct linger);
284 	/* TEST12: Test case for setsockopt SO_LINGER */
285 	error = setsockopt(sk2, SOL_SOCKET, SO_LINGER, &slinger, len);
286 	if (error < 0)
287 		tst_brkm(TBROK, tst_exit, "setsockopt SO_LINGER "
288                          "error:%d, errno:%d", error, errno);
289 
290 	tst_resm(TPASS, "setsockopt() SO_LINGER - SUCCESS");
291 
292 	/* TEST13: Test case for getsockopt SO_LINGER */
293 	error = getsockopt(sk2, SOL_SOCKET, SO_LINGER, &glinger, &len);
294 	if (error < 0)
295 		tst_brkm(TBROK, tst_exit, "getsockopt SO_LINGER "
296                          "error:%d, errno:%d", error, errno);
297 
298 	tst_resm(TPASS, "getsockopt() SO_LINGER - SUCCESS");
299 
300 	if (slinger.l_onoff != glinger.l_onoff ||
301 	    slinger.l_linger != glinger.l_linger)
302 		tst_brkm(TBROK, tst_exit, "setsockopt/getsockopt SO_LINGER "
303 			 "compare failed");
304 
305 	/*First gets the default SO_RCVBUF value and comapres with the
306 	value obtained from SCTP_STATUS*/
307 	len = sizeof(int);
308 	/* TEST14: Test case for getsockopt SO_RCVBUF */
309 	error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &rcvbuf_val_get, &len);
310 	if (error < 0)
311 		tst_brkm(TBROK, tst_exit, "getsockopt SO_RCVBUF "
312                          "error:%d, errno:%d", error, errno);
313 
314 	tst_resm(TPASS, "getsockopt() SO_RCVBUF - SUCCESS");
315 
316 	len = sizeof(struct sctp_status);
317 	/* TEST15: Test case for getsockopt SCTP_STATUS */
318 	error = getsockopt(sk2, IPPROTO_SCTP, SCTP_STATUS, &gstatus, &len);
319 	if (error < 0)
320 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_STATUS "
321                          "error:%d, errno:%d", error, errno);
322 
323 	tst_resm(TPASS, "getsockopt() SCTP_STATUS - SUCCESS");
324 
325 	/* Reducing the SO_RCVBUF value using setsockopt() */
326 	/* Upstream has changed the MIN_RCVBUF (2048 + sizeof(struct sk_buff)) */
327 	len = sizeof(int);
328 	rcvbuf_val_set = 2048;
329 	/* TEST16: Test case for setsockopt SO_RCVBUF */
330 	error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &rcvbuf_val_set, len);
331 	if (error < 0)
332 		tst_brkm(TBROK, tst_exit, "setsockopt SO_RCVBUF "
333                          "error:%d, errno:%d", error, errno);
334 
335 	tst_resm(TPASS, "setsockopt() SO_RCVBUF - SUCCESS");
336 
337 	error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &rcvbuf_val_get, &len);
338 	if (error < 0)
339 		tst_brkm(TBROK, tst_exit, "getsockopt SO_RCVBUF "
340                          "error:%d, errno:%d", error, errno);
341 
342 	if ((2 * rcvbuf_val_set) != rcvbuf_val_get)
343 		tst_brkm(TBROK, tst_exit, "Comparison failed:Set value and "
344 			 "got value differs Set Value=%d Get Value=%d",
345 			 (2*rcvbuf_val_set), rcvbuf_val_get);
346 
347 	sndbuf_val_set = 5000;
348 	/* TEST17: Test case for setsockopt SO_SNDBUF */
349 	error = setsockopt(sk2, SOL_SOCKET, SO_SNDBUF, &sndbuf_val_set, len);
350 	if (error < 0)
351 		tst_brkm(TBROK, tst_exit, "setsockopt SO_SNDBUF "
352                          "error:%d, errno:%d", error, errno);
353 
354 	tst_resm(TPASS, "setsockopt() SO_SNDBUF - SUCCESS");
355 
356 	/* TEST18: Test case for getsockopt SO_SNDBUF */
357 	error = getsockopt(sk2, SOL_SOCKET, SO_SNDBUF, &sndbuf_val_get, &len);
358 	if (error < 0)
359 		tst_brkm(TBROK, tst_exit, "getsockopt SO_SNDBUF "
360                          "error:%d, errno:%d", error, errno);
361 
362 	tst_resm(TPASS, "getsockopt() SO_SNDBUF - SUCCESS");
363 
364 	if ((2 * sndbuf_val_set) != sndbuf_val_get)
365 		tst_brkm(TBROK, tst_exit, "Comparison failed:Set value and "
366 			 "got value differs Set Value=%d Get Value=%d\n",
367 			 (2*sndbuf_val_set), sndbuf_val_get);
368 
369 
370 	/* Getting the primary address using SCTP_PRIMARY_ADDR */
371         len = sizeof(struct sctp_prim);
372 	/* TEST19: Test case for getsockopt SCTP_PRIMARY_ADDR */
373 	error = getsockopt(sk2,IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &gprimaddr,
374 			   &len);
375 	if (error < 0)
376 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_PRIMARY_ADDR "
377                          "error:%d, errno:%d", error, errno);
378 
379 	tst_resm(TPASS, "getsockopt() SCTP_PRIMARY_ADDR - SUCCESS");
380 
381 	gaddr = (struct sockaddr_in *) &gprimaddr.ssp_addr;
382 	if(htons(gaddr->sin_port) != lstn_addr.sin_port &&
383 	   gaddr->sin_family != lstn_addr.sin_family &&
384 	   gaddr->sin_addr.s_addr != lstn_addr.sin_addr.s_addr)
385 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_PRIMARY_ADDR value "
386 			 "mismatch");
387 
388 	memcpy(&sprimaddr, &gprimaddr, sizeof(struct sctp_prim));
389 
390 	/* TEST20: Test case for setsockopt SCTP_PRIMARY_ADDR */
391 	error = setsockopt(sk2,IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &sprimaddr,
392 			   len);
393 	if (error < 0)
394 		tst_brkm(TBROK, tst_exit, "setsockopt SCTP_PRIMARY_ADDR "
395                          "error:%d, errno:%d", error, errno);
396 
397 	tst_resm(TPASS, "setsockopt() SCTP_PRIMARY_ADDR - SUCCESS");
398 
399 	/* TEST21: Test case for getsockopt SCTP_PRIMARY_ADDR */
400 	/* Getting the association info using SCTP_ASSOCINFO */
401         len = sizeof(struct sctp_assocparams);
402 	error = getsockopt(sk2, IPPROTO_SCTP, SCTP_ASSOCINFO, &gassocparams,
403 			   &len);
404 	if (error < 0)
405 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_ASSOCINFO "
406                          "error:%d, errno:%d", error, errno);
407 
408 	tst_resm(TPASS, "getsockopt() SCTP_ASSOCINFO - SUCCESS");
409 
410 	/* TEST21: Test case for setsockopt SCTP_ASSOCINFO */
411 	memcpy(&sassocparams, &gassocparams, sizeof(struct sctp_assocparams));
412 	sassocparams.sasoc_asocmaxrxt += 5;
413 	sassocparams.sasoc_cookie_life += 10;
414 
415 	error = setsockopt(sk2, IPPROTO_SCTP, SCTP_ASSOCINFO, &sassocparams,
416 			   len);
417 	if (error < 0)
418 		tst_brkm(TBROK, tst_exit, "setsockopt SCTP_ASSOCINFO "
419                          "error:%d, errno:%d", error, errno);
420 
421 	error = getsockopt(sk2, IPPROTO_SCTP, SCTP_ASSOCINFO, &gassocparams,
422 			   &len);
423 	if (error < 0)
424 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_ASSOCINFO "
425                          "error:%d, errno:%d", error, errno);
426 
427 	if (sassocparams.sasoc_asocmaxrxt != gassocparams.sasoc_asocmaxrxt ||
428 	    sassocparams.sasoc_cookie_life != gassocparams.sasoc_cookie_life)
429 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_ASSOCINFO value "
430 			 "mismatch");
431 	tst_resm(TPASS, "setsockopt() SCTP_ASSOCINFO - SUCCESS");
432 
433 	close(sk2);
434 	close(sk1);
435 	close(acpt_sk);
436 
437 	return 0;
438 }
439