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