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