• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <lksctp-developers@lists.sourceforge.net>
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 
76 char *TCID = __FILE__;
77 int TST_TOTAL = 22;
78 int TST_CNT = 0;
79 
80 int
main(void)81 main(void)
82 {
83 	int error;
84 	socklen_t len;
85 	int sk, sk1, sk2, acpt_sk, pf_class;
86 	struct sctp_rtoinfo grtinfo;
87 	struct sockaddr_in lstn_addr, conn_addr;
88 	struct sctp_initmsg ginmsg; /*get the value for SCTP_INITMSG*/
89 	struct sctp_initmsg sinmsg; /*set the value for SCTP_INITMSG*/
90 	struct linger slinger; /*SO_LINGER structure*/
91 	struct linger glinger; /*SO_LINGER structure*/
92 	struct sockaddr_in addr;
93 	struct sockaddr_in *gaddr;
94 	struct sctp_status gstatus; /*SCTP_STATUS option*/
95 	int rcvbuf_val_get, rcvbuf_val_set; /*get and set var for SO_RCVBUF*/
96 	int sndbuf_val_get, sndbuf_val_set;/*get and set var for SO_SNDBUF*/
97 	struct sctp_prim gprimaddr;/*SCTP_PRIMARY_ADDR get*/
98 	struct sctp_prim sprimaddr;/*SCTP_PRIMARY_ADDR set*/
99 	struct sctp_assocparams sassocparams;  /* SCTP_ASSOCPARAMS set */
100 	struct sctp_assocparams gassocparams;  /* SCTP_ASSOCPARAMS get */
101 	int fd, err_no = 0;
102 	char filename[21];
103 
104 	/* Rather than fflush() throughout the code, set stdout to
105          * be unbuffered.
106          */
107         setvbuf(stdout, NULL, _IONBF, 0);
108         setvbuf(stderr, NULL, _IONBF, 0);
109 
110 	pf_class = PF_INET;
111 
112 	sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
113 
114 	/*setsockopt() TEST1: Bad socket descriptor EBADF, Expected error*/
115         error = setsockopt(-1, IPPROTO_SCTP, 0, 0, 0);
116 	if (error != -1 || errno != EBADF)
117 		tst_brkm(TBROK, tst_exit, "setsockopt with a bad socket "
118 			 "descriptor error:%d, errno:%d", error, errno);
119 
120 	tst_resm(TPASS, "setsockopt() with a bad socket descriptor - EBADF");
121 
122 	/*setsockopt() TEST2: Invalid socket ENOTSOCK, Expected error*/
123 	strcpy(filename, "/tmp/sctptest.XXXXXX");
124 	fd = mkstemp(filename);
125 	if (fd == -1)
126 		tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s",
127 				filename, strerror(errno));
128 	error = setsockopt(fd, IPPROTO_SCTP, 0, 0, 0);
129 	if (error == -1)
130 		err_no = errno;
131 	close(fd);
132 	unlink(filename);
133 	if (error != -1 || err_no != ENOTSOCK)
134 		tst_brkm(TBROK, tst_exit, "setsockopt with an invalid socket "
135 			 "error:%d, errno:%d", error, err_no);
136 
137 	tst_resm(TPASS, "setsockopt() with an invalid socket - ENOTSOCK");
138 
139 	/*setsockopt() TEST3: Invalid level ENOPROTOOPT, Expected error*/
140         error = setsockopt(sk, -1, SCTP_RTOINFO, 0, 0);
141 	if (error != -1 || errno != ENOPROTOOPT)
142 		tst_brkm(TBROK, tst_exit, "setsockopt with invalid level "
143 			 "error:%d, errno:%d", error, errno);
144 
145 	tst_resm(TPASS, "setsockopt() with an invalid level - ENOPROTOOPT");
146 
147 	/*setsockopt() TEST4: Invalid option buffer EFAULT, Expected error*/
148         error = setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO,
149 		(const struct sctp_rtoinfo *)-1, sizeof(struct sctp_rtoinfo));
150 	if (error != -1 || errno != EFAULT)
151 		tst_brkm(TBROK, tst_exit, "setsockopt with invalid option "
152 			 "buffer error:%d, errno:%d", error, errno);
153 
154 	tst_resm(TPASS, "setsockopt() with invalid option buffer - EFAULT");
155 
156 	/*setsockopt() TEST5: Invalid option Name EOPNOTSUPP, Expected error*/
157         error = setsockopt(sk, IPPROTO_SCTP, SCTP_AUTOCLOSE, 0, 0);
158 	if (error != -1 || errno != EOPNOTSUPP)
159 		tst_brkm(TBROK, tst_exit, "setsockopt with invalid option "
160 			 "name error:%d, errno:%d", error, errno);
161 
162 	tst_resm(TPASS, "setsockopt() with invalid option name - EOPNOTSUPP");
163 
164 	/*getsockopt() TEST6: Bad socket descriptor EBADF, Expected error*/
165         error = getsockopt(-1, IPPROTO_SCTP, 0, 0, 0);
166 	if (error != -1 || errno != EBADF)
167 		tst_brkm(TBROK, tst_exit, "getsockopt with a bad socket "
168 			 "descriptor error:%d, errno:%d", error, errno);
169 
170 	tst_resm(TPASS, "getsockopt() with a bad socket descriptor - EBADF");
171 
172 	/*getsockopt() TEST7: Invalid socket ENOTSOCK, Expected error*/
173 	strcpy(filename, "/tmp/sctptest.XXXXXX");
174 	fd = mkstemp(filename);
175 	if (fd == -1)
176 		tst_brkm(TBROK, tst_exit, "Failed to mkstemp %s: %s",
177 				filename, strerror(errno));
178 	error = getsockopt(fd, IPPROTO_SCTP, 0, 0, 0);
179 	if (error == -1)
180 		err_no = errno;
181 	close(fd);
182 	unlink(filename);
183 	if (error != -1 || err_no != ENOTSOCK)
184 		tst_brkm(TBROK, tst_exit, "getsockopt with an invalid socket "
185 			 "error:%d, errno:%d", error, err_no);
186 
187 	tst_resm(TPASS, "getsockopt() with an invalid socket - ENOTSOCK");
188 #if 0
189 	/*getsockopt() TEST3: Invalid level ENOPROTOOPT, Expected error*/
190 	/*I have commented this test case because it is returning EOPNOTSUPP.
191 	When I checked the code there also it is returning EOPNOTSUPP. As this
192 	is not specific to TCP style, I do not want to do the code change*/
193 
194         error = getsockopt(sk, -1, SCTP_RTOINFO, 0, 0);
195 	if (error != -1 || errno != ENOPROTOOPT)
196 		tst_brkm(TBROK, tst_exit, "getsockopt with invalid level "
197 			 "error:%d, errno:%d", error, errno);
198 
199 	tst_resm(TPASS, "getsockopt() with an invalid level - ENOPROTOOPT");
200 #endif
201 	len = sizeof(struct sctp_rtoinfo);
202 
203 	/*getsockopt() TEST8: Invalid option buffer EFAULT, Expected error*/
204         error = getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO,
205 			   (struct sctp_rtoinfo *)-1, &len);
206 	if (error != -1 || errno != EFAULT)
207 		tst_brkm(TBROK, tst_exit, "getsockopt with invalid option "
208 			 "buffer error:%d, errno:%d", error, errno);
209 
210 	tst_resm(TPASS, "getsockopt() with invalid option buffer - EFAULT");
211 
212 	/*getsockopt() TEST9: Invalid option Name EOPNOTSUPP, Expected error*/
213         error = getsockopt(sk, IPPROTO_SCTP, SCTP_AUTOCLOSE, &grtinfo, &len);
214 	if (error != -1 || errno != EOPNOTSUPP)
215 		tst_brkm(TBROK, tst_exit, "getsockopt with invalid option "
216 			 "name error:%d, errno:%d", error, errno);
217 
218 	tst_resm(TPASS, "getsockopt() with invalid option name - EOPNOTSUPP");
219 
220 	close(sk);
221 
222 	sk1 = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
223 	sk2 = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);
224 
225 	lstn_addr.sin_family = AF_INET;
226         lstn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK;
227         lstn_addr.sin_port = htons(SCTP_TESTPORT_1);
228 
229 	conn_addr.sin_family = AF_INET;
230         conn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK;
231         conn_addr.sin_port = htons(SCTP_TESTPORT_1);
232 
233         len = sizeof(struct sctp_initmsg);
234 
235 	/* TEST10: Test cases for getsockopt SCTP_INITMSG */
236 	test_getsockopt(sk1, SCTP_INITMSG, &ginmsg, &len);
237 
238 	tst_resm(TPASS, "getsockopt() SCTP_INITMSG - SUCCESS");
239 
240 	sinmsg.sinit_num_ostreams = 5;
241         sinmsg.sinit_max_instreams = 5;
242         sinmsg.sinit_max_attempts = 3;
243         sinmsg.sinit_max_init_timeo = 30;
244 	/* TEST11: Test case for setsockopt SCTP_INITMSG */
245 	test_setsockopt(sk1, SCTP_INITMSG, &sinmsg, sizeof(sinmsg));
246 
247 	test_getsockopt(sk1, SCTP_INITMSG, &ginmsg, &len);
248 
249 	if (sinmsg.sinit_num_ostreams != ginmsg.sinit_num_ostreams &&
250 	    sinmsg.sinit_max_instreams != ginmsg.sinit_max_instreams &&
251 	    sinmsg.sinit_max_attempts != ginmsg.sinit_max_attempts &&
252 	    sinmsg.sinit_max_init_timeo != ginmsg.sinit_max_init_timeo)
253 		tst_brkm(TBROK, tst_exit, "setsockopt/getsockopt SCTP_INITMSG "
254 			 "compare failed");
255 
256 	tst_resm(TPASS, "setsockopt() SCTP_INITMSG - SUCCESS");
257 
258 	/*Now get the values on different endpoint*/
259 	test_getsockopt(sk2, SCTP_INITMSG, &ginmsg, &len);
260 
261 	/*Comparison should not succeed here*/
262 	if (sinmsg.sinit_num_ostreams == ginmsg.sinit_num_ostreams &&
263 	    sinmsg.sinit_max_instreams == ginmsg.sinit_max_instreams &&
264 	    sinmsg.sinit_max_attempts == ginmsg.sinit_max_attempts &&
265 	    sinmsg.sinit_max_init_timeo == ginmsg.sinit_max_init_timeo)
266 		tst_brkm(TBROK, tst_exit, "setsockopt/getsockopt SCTP_INITMSG "
267 			 "unexpected compare success");
268 
269 	/* SO_LINGER Test with l_onff = 0 and l_linger = 0 */
270 	slinger.l_onoff = 0;
271 	slinger.l_linger = 0;
272 	test_bind(sk1, (struct sockaddr *) &lstn_addr, sizeof(lstn_addr));
273 	test_listen(sk1, 10 );
274 	len = sizeof(struct sockaddr_in);
275 	test_connect(sk2, (struct sockaddr *) &conn_addr, len);
276 
277 	acpt_sk = test_accept(sk1, (struct sockaddr *)&addr, &len);
278 
279         len = sizeof(struct linger);
280 	/* TEST12: Test case for setsockopt SO_LINGER */
281 	error = setsockopt(sk2, SOL_SOCKET, SO_LINGER, &slinger, len);
282 	if (error < 0)
283 		tst_brkm(TBROK, tst_exit, "setsockopt SO_LINGER "
284                          "error:%d, errno:%d", error, errno);
285 
286 	tst_resm(TPASS, "setsockopt() SO_LINGER - SUCCESS");
287 
288 	/* TEST13: Test case for getsockopt SO_LINGER */
289 	error = getsockopt(sk2, SOL_SOCKET, SO_LINGER, &glinger, &len);
290 	if (error < 0)
291 		tst_brkm(TBROK, tst_exit, "getsockopt SO_LINGER "
292                          "error:%d, errno:%d", error, errno);
293 
294 	tst_resm(TPASS, "getsockopt() SO_LINGER - SUCCESS");
295 
296 	if (slinger.l_onoff != glinger.l_onoff ||
297 	    slinger.l_linger != glinger.l_linger)
298 		tst_brkm(TBROK, tst_exit, "setsockopt/getsockopt SO_LINGER "
299 			 "compare failed");
300 
301 	/*First gets the default SO_RCVBUF value and comapres with the
302 	value obtained from SCTP_STATUS*/
303 	len = sizeof(int);
304 	/* TEST14: Test case for getsockopt SO_RCVBUF */
305 	error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &rcvbuf_val_get, &len);
306 	if (error < 0)
307 		tst_brkm(TBROK, tst_exit, "getsockopt SO_RCVBUF "
308                          "error:%d, errno:%d", error, errno);
309 
310 	tst_resm(TPASS, "getsockopt() SO_RCVBUF - SUCCESS");
311 
312 	len = sizeof(struct sctp_status);
313 	/* TEST15: Test case for getsockopt SCTP_STATUS */
314 	error = getsockopt(sk2, IPPROTO_SCTP, SCTP_STATUS, &gstatus, &len);
315 	if (error < 0)
316 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_STATUS "
317                          "error:%d, errno:%d", error, errno);
318 
319 	tst_resm(TPASS, "getsockopt() SCTP_STATUS - SUCCESS");
320 
321 	/* Reducing the SO_RCVBUF value using setsockopt() */
322 	/* Upstream has changed the MIN_RCVBUF (2048 + sizeof(struct sk_buff)) */
323 	len = sizeof(int);
324 	rcvbuf_val_set = 2048;
325 	/* TEST16: Test case for setsockopt SO_RCVBUF */
326 	error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &rcvbuf_val_set, len);
327 	if (error < 0)
328 		tst_brkm(TBROK, tst_exit, "setsockopt SO_RCVBUF "
329                          "error:%d, errno:%d", error, errno);
330 
331 	tst_resm(TPASS, "setsockopt() SO_RCVBUF - SUCCESS");
332 
333 	error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &rcvbuf_val_get, &len);
334 	if (error < 0)
335 		tst_brkm(TBROK, tst_exit, "getsockopt SO_RCVBUF "
336                          "error:%d, errno:%d", error, errno);
337 
338 	if ((2 * rcvbuf_val_set) != rcvbuf_val_get)
339 		tst_brkm(TBROK, tst_exit, "Comparison failed:Set value and "
340 			 "got value differs Set Value=%d Get Value=%d",
341 			 (2*rcvbuf_val_set), rcvbuf_val_get);
342 
343 	sndbuf_val_set = 5000;
344 	/* TEST17: Test case for setsockopt SO_SNDBUF */
345 	error = setsockopt(sk2, SOL_SOCKET, SO_SNDBUF, &sndbuf_val_set, len);
346 	if (error < 0)
347 		tst_brkm(TBROK, tst_exit, "setsockopt SO_SNDBUF "
348                          "error:%d, errno:%d", error, errno);
349 
350 	tst_resm(TPASS, "setsockopt() SO_SNDBUF - SUCCESS");
351 
352 	/* TEST18: Test case for getsockopt SO_SNDBUF */
353 	error = getsockopt(sk2, SOL_SOCKET, SO_SNDBUF, &sndbuf_val_get, &len);
354 	if (error < 0)
355 		tst_brkm(TBROK, tst_exit, "getsockopt SO_SNDBUF "
356                          "error:%d, errno:%d", error, errno);
357 
358 	tst_resm(TPASS, "getsockopt() SO_SNDBUF - SUCCESS");
359 
360 	if ((2 * sndbuf_val_set) != sndbuf_val_get)
361 		tst_brkm(TBROK, tst_exit, "Comparison failed:Set value and "
362 			 "got value differs Set Value=%d Get Value=%d\n",
363 			 (2*sndbuf_val_set), sndbuf_val_get);
364 
365 
366 	/* Getting the primary address using SCTP_PRIMARY_ADDR */
367         len = sizeof(struct sctp_prim);
368 	/* TEST19: Test case for getsockopt SCTP_PRIMARY_ADDR */
369 	error = getsockopt(sk2,IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &gprimaddr,
370 			   &len);
371 	if (error < 0)
372 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_PRIMARY_ADDR "
373                          "error:%d, errno:%d", error, errno);
374 
375 	tst_resm(TPASS, "getsockopt() SCTP_PRIMARY_ADDR - SUCCESS");
376 
377 	gaddr = (struct sockaddr_in *) &gprimaddr.ssp_addr;
378 	if(htons(gaddr->sin_port) != lstn_addr.sin_port &&
379 	   gaddr->sin_family != lstn_addr.sin_family &&
380 	   gaddr->sin_addr.s_addr != lstn_addr.sin_addr.s_addr)
381 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_PRIMARY_ADDR value "
382 			 "mismatch");
383 
384 	memcpy(&sprimaddr, &gprimaddr, sizeof(struct sctp_prim));
385 
386 	/* TEST20: Test case for setsockopt SCTP_PRIMARY_ADDR */
387 	error = setsockopt(sk2,IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &sprimaddr,
388 			   len);
389 	if (error < 0)
390 		tst_brkm(TBROK, tst_exit, "setsockopt SCTP_PRIMARY_ADDR "
391                          "error:%d, errno:%d", error, errno);
392 
393 	tst_resm(TPASS, "setsockopt() SCTP_PRIMARY_ADDR - SUCCESS");
394 
395 	/* TEST21: Test case for getsockopt SCTP_PRIMARY_ADDR */
396 	/* Getting the association info using SCTP_ASSOCINFO */
397         len = sizeof(struct sctp_assocparams);
398 	error = getsockopt(sk2, IPPROTO_SCTP, SCTP_ASSOCINFO, &gassocparams,
399 			   &len);
400 	if (error < 0)
401 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_ASSOCINFO "
402                          "error:%d, errno:%d", error, errno);
403 
404 	tst_resm(TPASS, "getsockopt() SCTP_ASSOCINFO - SUCCESS");
405 
406 	/* TEST21: Test case for setsockopt SCTP_ASSOCINFO */
407 	memcpy(&sassocparams, &gassocparams, sizeof(struct sctp_assocparams));
408 	sassocparams.sasoc_asocmaxrxt += 5;
409 	sassocparams.sasoc_cookie_life += 10;
410 
411 	error = setsockopt(sk2, IPPROTO_SCTP, SCTP_ASSOCINFO, &sassocparams,
412 			   len);
413 	if (error < 0)
414 		tst_brkm(TBROK, tst_exit, "setsockopt SCTP_ASSOCINFO "
415                          "error:%d, errno:%d", error, errno);
416 
417 	error = getsockopt(sk2, IPPROTO_SCTP, SCTP_ASSOCINFO, &gassocparams,
418 			   &len);
419 	if (error < 0)
420 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_ASSOCINFO "
421                          "error:%d, errno:%d", error, errno);
422 
423 	if (sassocparams.sasoc_asocmaxrxt != gassocparams.sasoc_asocmaxrxt ||
424 	    sassocparams.sasoc_cookie_life != gassocparams.sasoc_cookie_life)
425 		tst_brkm(TBROK, tst_exit, "getsockopt SCTP_ASSOCINFO value "
426 			 "mismatch");
427 	tst_resm(TPASS, "setsockopt() SCTP_ASSOCINFO - SUCCESS");
428 
429 	close(sk2);
430 	close(sk1);
431 	close(acpt_sk);
432 
433 	return 0;
434 }
435