1
/* SCTP kernel reference Implementation
2
* (C) Copyright IBM Corp. 2001, 2003
3
* Copyright (c) 1999-2000 Cisco, Inc.
4
* Copyright (c) 1999-2001 Motorola, Inc.
5
* Copyright (c) 2001 Intel Corp.
6
* Copyright (c) 2001 Nokia, Inc.
7
* Copyright (c) 2001 La Monte H.P. Yarroll
9
* This is the Functional Test for testing SET_DEFAULT_SEND_PARAM sockopt and
10
* use of the SCTP_SNDRCV ancillary data.
12
* Just test payload protocol id and stream. This is mostly just a simple
15
* Send/receive two messages. Each with different stream & ppid.
17
* Ardelle Fan <ardelle.fan@intel.com>
19
* We use functions which approximate the user level API defined in
20
* draft-ietf-tsvwg-sctpsocket-07.txt.
22
#include <linux/types.h>
23
#include <linux/list.h> /* For struct list_head */
24
#include <linux/socket.h>
26
#include <linux/time.h> /* For struct timeval */
28
#include <linux/wait.h> /* For wait_queue_head_t */
29
#include <linux/skbuff.h>
30
#include <linux/errno.h>
31
#include <net/sctp/sctp.h>
32
#include <net/sctp/sm.h>
37
main(int argc, char *argv[])
39
int pf_class, af_family;
40
struct sctp_endpoint *ep1;
41
struct sctp_endpoint *ep2;
44
int error, bytes_sent;
45
union sctp_addr loop1;
46
union sctp_addr loop2;
47
struct sctp_association *asoc1;
48
struct sctp_association *asoc2;
51
struct msghdr inmessage;
52
char cmsghdr[CMSG_SPACE_SNDRCV] = {0};
53
char buf[CMSG_SPACE_INITMSG] = {0};
54
struct cmsghdr *outcmsg;
55
struct sctp_initmsg *initmsg;
56
struct sctp_sndrcvinfo info;
57
struct sctp_assoc_change *sac;
58
sctp_assoc_t associd1;
59
sctp_assoc_t associd2;
65
uint8_t *message = "hello, world!\n";
66
uint8_t *telephone = "Watson, come here! I need you!\n";
68
/* Do all that random stuff needed to make a sensible
73
/* Set some basic values which depend on the address family. */
77
loop1.v4.sin_family = AF_INET;
78
loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
79
loop1.v4.sin_port = htons(SCTP_TESTPORT_1);
80
loop2.v4.sin_family = AF_INET;
81
loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
82
loop2.v4.sin_port = htons(SCTP_TESTPORT_2);
85
/* Create the two endpoints which will talk to each other. */
86
sk1 = sctp_socket(pf_class, SOCK_SEQPACKET);
87
sk2 = sctp_socket(pf_class, SOCK_SEQPACKET);
89
/* Bind these sockets to the test ports. */
90
error = test_bind(sk1, (struct sockaddr *)&loop1, sizeof(loop1));
91
if (error != 0) { DUMP_CORE; }
93
error = test_bind(sk2, (struct sockaddr *)&loop2, sizeof(loop2));
94
if (error != 0) { DUMP_CORE; }
96
/* Mark sk2 as being able to accept new associations. */
97
if (0 != sctp_seqpacket_listen(sk2, 1)) {
101
/* Make sure that duplicate binding fails. */
102
error = test_bind(sk1, (struct sockaddr *)&loop1, sizeof(loop1));
103
if (error != -EINVAL) { DUMP_CORE; }
106
/* Build up a msghdr structure we can use for all sending. */
107
outmsg.msg_name = &loop2;
108
outmsg.msg_namelen = sizeof(loop2);
109
outmsg.msg_iov = &out_iov;
110
outmsg.msg_iovlen = 1;
111
outmsg.msg_flags = 0;
113
outmsg.msg_control = buf;
114
outmsg.msg_controllen = CMSG_SPACE_INITMSG;
115
outcmsg = CMSG_FIRSTHDR(&outmsg);
116
outcmsg->cmsg_level = IPPROTO_SCTP;
117
outcmsg->cmsg_type = SCTP_INIT;
118
outcmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_initmsg));
120
initmsg = (struct sctp_initmsg *)CMSG_DATA(outcmsg);
121
initmsg->sinit_num_ostreams = 20;
122
initmsg->sinit_max_instreams = 5;
123
initmsg->sinit_max_attempts = 0;
124
initmsg->sinit_max_init_timeo = 0;
126
/* Send the first message. This will create the association. */
127
outmsg.msg_iov->iov_base = message;
128
outmsg.msg_iov->iov_len = strlen(message) + 1;
129
bytes_sent = sctp_sendmsg(NULL, sk1, &outmsg, strlen(message)+1);
130
if (bytes_sent != strlen(message) + 1) { DUMP_CORE; }
132
/* Walk through the startup sequence. */
134
/* We should have an INIT sitting on the Internet. */
135
if (!test_for_chunk(SCTP_CID_INIT, TEST_NETWORK0)) {
139
/* Next we expect an INIT ACK. */
140
if (test_step(SCTP_CID_INIT_ACK, TEST_NETWORK0) <= 0) {
143
/* We expect a COOKIE ECHO. */
144
if (test_step(SCTP_CID_COOKIE_ECHO, TEST_NETWORK0) <= 0) {
148
#ifndef NO_COOKIE_ECHO_BUNDLE
149
/* We expect DATA bundled with that COOKIE ECHO. */
150
if (!test_for_chunk(SCTP_CID_DATA, TEST_NETWORK0)) {
153
#endif /* !NO_COOKIE_ECHO_BUNDLE */
155
/* We expect a COOKIE ACK. */
156
if (test_step(SCTP_CID_COOKIE_ACK, TEST_NETWORK0) <= 0) {
160
#ifdef NO_COOKIE_ECHO_BUNDLE
161
if (test_step(SCTP_CID_DATA, TEST_NETWORK0) <= 0) {
165
if (test_step(SCTP_CID_SACK, TEST_NETWORK0) <= 0) {
169
/* We should see a SACK next.
170
* We ARE truly clever and bundle the SACK with the COOKIE ACK.
172
if (!test_for_chunk(SCTP_CID_SACK, TEST_NETWORK0)) {
175
#endif /* NO_COOKIE_ECHO_BUNDLE */
177
/* Process the COOKIE ACK and the SACK. */
178
error = test_run_network();
179
if (0 != error) { DUMP_CORE; }
181
/* We have two established associations. Let's extract some
185
ep1 = sctp_sk(sk1)->ep;
186
asoc1= test_ep_first_asoc(ep1);
187
ep2 = sctp_sk(sk2)->ep;
188
asoc2 = test_ep_first_asoc(ep2);
190
if (!sctp_outq_is_empty(&asoc1->outqueue)) {
194
memset(&inmessage, 0x00, sizeof(inmessage));
196
/* NOW initialize inmessage with enough space for DATA... */
197
big_buffer = kmalloc(REALLY_BIG, GFP_KERNEL);
198
iov.iov_base = big_buffer;
199
iov.iov_len = REALLY_BIG;
200
inmessage.msg_iov = &iov;
201
inmessage.msg_iovlen = 1;
202
/* or a control message. */
203
inmessage.msg_control = &cmsghdr;
204
inmessage.msg_controllen = CMSG_SPACE_SNDRCV;
206
/* Get the communication up message from sk2. */
207
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
208
/* noblock */ 1, /* flags */ 0,
211
printk("recvmsg: Something went wrong, error: %d\n",
215
test_frame_check_notification(&inmessage,
217
sizeof(struct sctp_assoc_change),
221
sac = (struct sctp_assoc_change *)big_buffer;
222
associd2 = sac->sac_assoc_id;
223
printk("sk2 associd = %x\n", (unsigned int)associd2);
224
if (associd2 != (sctp_assoc_t)asoc2) {
229
/* Restore the altered values for the next call... */
230
iov.iov_base = big_buffer;
231
iov.iov_len = REALLY_BIG;
232
inmessage.msg_control = &cmsghdr;
233
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
236
/* Get the communication up message from sk1. */
237
error = sctp_recvmsg(NULL, sk1, &inmessage, REALLY_BIG,
238
/* noblock */ 1, /* flags */ 0,
241
printk("recvmsg: Something went wrong, error: %d\n",
245
test_frame_check_notification(&inmessage,
247
sizeof(struct sctp_assoc_change),
251
sac = (struct sctp_assoc_change *)big_buffer;
252
associd1 = sac->sac_assoc_id;
253
printk("sk1 associd = %x\n", (unsigned int)associd1);
254
if (associd1 != (sctp_assoc_t)asoc1) {
258
/* Restore the altered values for the next call... */
259
iov.iov_len = REALLY_BIG;
260
inmessage.msg_control = &cmsghdr;
261
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
264
/* Get the first message which was sent. */
265
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
266
/* noblock */ 1, /* flags */ 0,
268
if (error < 0) { DUMP_CORE; }
271
test_frame_check_message(&inmessage,
273
sizeof(struct sctp_cmsghdr),
277
sizeof(struct sctp_sndrcvinfo),
282
/* Fixup msg_control, as testframe leaves it in a goofy state. */
283
test_frame_fixup_msg_control(&inmessage,
284
sizeof(struct sctp_cmsghdr));
286
/* SET_DEFAULT_SEND_PARAM */
287
memset(&info, 0x00, sizeof(struct sctp_sndrcvinfo));
288
ppid = (uint32_t)rand();
289
info.sinfo_ppid = ppid;
291
info.sinfo_stream = stream;
292
info.sinfo_assoc_id = associd1;
293
error = sctp_setsockopt(sk1, IPPROTO_SCTP,
294
SCTP_DEFAULT_SEND_PARAM, (char *)&info,
295
sizeof(struct sctp_sndrcvinfo));
296
if (error != 0) { DUMP_CORE; }
298
/* Send a second message */
300
outmsg.msg_control = NULL;
301
outmsg.msg_controllen = 0;
302
outmsg.msg_iov->iov_base = telephone;
303
outmsg.msg_iov->iov_len = strlen(telephone) + 1;
305
bytes_sent = sctp_sendmsg(NULL, sk1, &outmsg, strlen(telephone)+1);
306
if (bytes_sent != strlen(telephone) + 1) { DUMP_CORE; }
308
error = test_run_network();
309
if (error != 0) { DUMP_CORE; }
311
/* Get that message. */
312
/* Restore the altered values for the next call. */
313
iov.iov_base = big_buffer;
314
iov.iov_len = REALLY_BIG;
315
inmessage.msg_iov = &iov;
316
inmessage.msg_iovlen = 1;
317
inmessage.msg_control = cmsghdr;
318
inmessage.msg_controllen = CMSG_SPACE_SNDRCV;
320
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
321
/* noblock */ 1, /* flags */ 0,
323
if (error < 0) { DUMP_CORE; }
324
test_frame_check_message(&inmessage,
330
sizeof(struct sctp_sndrcvinfo),
331
strlen(telephone) + 1,
335
/* Fixup msg_control, as testframe leaves it in a goofy state. */
336
test_frame_fixup_msg_control(&inmessage,
337
sizeof(struct sctp_cmsghdr));
339
/* Make sure that the stream and ppid were preserved. */
340
if (!test_check_sndrcvinfo(&inmessage, 0, stream, ppid)) {
341
printf("stream: %d, ppid: %d\n",stream, ppid);
345
/* Shut down the link. */
346
sctp_close(sk1, /* timeout */ 0);
348
error = test_run_network();
349
if (error != 0) { DUMP_CORE; }
352
sctp_close(sk2, /* timeout */ 0);
356
printk("\n\n%s passed\n\n\n", argv[0]);
359
/* Indicate successful completion. */