blob: cd7654b7afd52eabd4176c2b791695348ee83ec1 [file] [log] [blame]
Austin Schuh8d0a2852019-12-28 22:54:28 -08001/* SCTP kernel Implementation
2 * (C) Copyright IBM Corp. 2001, 2003
3 * Copyright (c) 1999 Cisco
4 * Copyright (c) 1999, 2000, 2001 Motorola
5 * Copyright (c) 2001-2002 Nokia
6 * Copyright (c) 2001 La Monte H.P. Yarroll
7 *
8 * This is a userspace test application for the SCTP kernel
9 * implementation.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it
17 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18 * ^^^^^^^^^^^^^^^^^^^^^^^^
19 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 * See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with GNU CC; see the file COPYING. If not, write to
24 * the Free Software Foundation, 59 Temple Place - Suite 330,
25 * Boston, MA 02111-1307, USA.
26 *
27 * Please send any bug reports or fixes you make to the
28 * email address(es):
29 * lksctp developers <lksctp-developers@lists.sourceforge.net>
30 *
31 * Or submit a bug report through the following website:
32 * http://www.sf.net/projects/lksctp
33 *
34 * Written or modified by:
35 * Hui Huang <hui.huang@nokia.com>
36 * Sridhar Samudrala <samudrala@us.ibm.com>
37 * Jon Grimm <jgrimm@us.ibm.com>
38 * Daisy Chang <daisyc@us.ibm.com>
39 * Ryan Layer <rmlayer@us.ibm.com>
40 */
41
42#include <ctype.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <unistd.h>
46#include <time.h>
47#include <sys/types.h>
48#include <sys/socket.h>
49#include <sys/uio.h>
50#include <netinet/in.h>
51#include <errno.h>
52#include <netinet/sctp.h>
53#include <string.h>
54#include <arpa/inet.h>
55#include <sys/wait.h>
56#include <sys/param.h>
57#include <fcntl.h>
58#include <netdb.h>
59#include <net/if.h>
60
61#include <sys/resource.h>
62
63
64#define REALLY_BIG 65536
65
66#define SERVER 0
67#define CLIENT 1
68#define MIXED 2
69#define NOT_DEFINED 666
70
71#define REPEAT 10
72#define BIG_REPEAT 1000000
73#define MAX_BIND_RETRYS 10
74#define BODYSIZE 10
75#define MSG_CNT 10 /* If this is changed the msg_sizes array
76 needs to be modified accordingly. */
77
78#define DEFAULT_MAX_WINDOW 32768
79#define DEFAULT_MIN_WINDOW 1500
80
81#define DEBUG_NONE 0
82#define DEBUG_MIN 1
83#define DEBUG_MAX 2
84
85#define STREAM_PATTERN_SEQUENTIAL 0
86#define STREAM_PATTERN_RANDOM 1
87
88#define ORDER_PATTERN_UNORDERED 0
89#define ORDER_PATTERN_ORDERED 1
90#define ORDER_PATTERN_ALTERNATE 2
91#define ORDER_PATTERN_RANDOM 3
92
93#define ASSOC_PATTERN_SEQUENTIAL 0
94#define ASSOC_PATTERN_RANDOM 1
95
96#define NCASES 6
97#define MAX_POLL_SKS 256
98
99#define DEBUG_PRINT(level, print_this...) \
100{ \
101 if (debug_level >= level) { \
102 fprintf(stdout, print_this); \
103 fflush(stdout); \
104 } \
105} /* DEBUG_PRINT */
106
107/* Convenience structure to determine space needed for cmsg. */
108typedef union {
109 struct sctp_initmsg init;
110 struct sctp_sndrcvinfo sndrcvinfo;
111} _sctp_cmsg_data_t;
112
113#ifdef __FreeBSD__
114typedef union {
115 int raw;
116 struct sctp_initmsg init;
117 struct sctp_sndrcvinfo sndrcv;
118} sctp_cmsg_data_t;
119#endif
120
121#define CMSG_SPACE_INITMSG (CMSG_SPACE(sizeof(struct sctp_initmsg)))
122#define CMSG_SPACE_SNDRCV (CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)))
123
124typedef struct {
125 int rem_port;
126 int order_state;
127 int stream_state;
128 int msg_cnt;
129 int msg_sent;
130 int cycle;
131} _assoc_state;
132
133typedef struct {
134 int sk;
135 int assoc_i;
136 _assoc_state *assoc_state;
137} _poll_sks;
138
139char *local_host = NULL;
140int local_port = 0;
141char *remote_host = NULL;
142int remote_port = 0;
143/* struct sockaddr_in s_rem, s_loc; */
144struct sockaddr_storage s_rem, s_loc;
145int r_len, l_len;
146int test_case = 0;
147int size_arg = 0;
148int xflag = 0;
149int debug_level = DEBUG_MAX;
150int do_exit = 1;
151int stream_pattern = STREAM_PATTERN_SEQUENTIAL;
152int stream_state = 0;
153int order_pattern = ORDER_PATTERN_UNORDERED;
154int order_state = 0;
155int max_stream = 0;
156int seed = 0;
157int max_msgsize = DEFAULT_MAX_WINDOW;
158int timetolive = 0;
159int assoc_pattern = ASSOC_PATTERN_SEQUENTIAL;
160int socket_type = SOCK_SEQPACKET;
161int repeat_count = 0;
162int listeners = 0;
163int tosend = 0;
164_poll_sks poll_sks[MAX_POLL_SKS];
165int repeat = REPEAT;
166int msg_cnt = MSG_CNT;
167int drain = 0;
168int role = NOT_DEFINED;
169struct sockaddr *bindx_add_addrs = NULL;
170int bindx_add_count = 0;
171struct sockaddr *connectx_addrs = NULL;
172int connectx_count = 0;
173int if_index = 0;
174
175unsigned char msg[] = "012345678901234567890123456789012345678901234567890";
176
177static int msg_sizes[NCASES][MSG_CNT] =
178 {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
179 {1452, 2904, 4356, 1452, 2904, 4356, 1452, 2904, 4356, 1452},
180 {1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453},
181 {1, 1453, 32768, 1, 1453, 32768, 1, 1453, 32768, 1},
182 {1, 1000, 2000, 3000, 5000, 10000, 15000, 20000, 25000, 32768},
183 {32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768},
184 };
185
186static const char *sac_state_tbl[] = {
187 "COMMUNICATION_UP",
188 "COMMUNICATION_LOST",
189 "RESTART",
190 "SHUTDOWN_COMPLETE",
191 "CANT_START_ASSOCICATION"
192};
193
194void usage(char *argv0)
195{
196 fprintf(stderr, "\nusage:\n");
197 fprintf(stderr, " server:\n");
198 fprintf(stderr, " %8s -H local-addr -P local-port -l [-d level] [-x]\n"
199 "\t [-L num-ports] [-S num-ports]\n"
200 "\t [-a assoc-pattern]\n"
201 "\t [-i interface]\n",
202 argv0);
203 fprintf(stderr, "\n");
204 fprintf(stderr, " client:\n");
205 fprintf(stderr, " %8s -H local-addr -P local-port -h remote-addr\n"
206 "\t -p remote-port -s [-c case ] [-d level]\n"
207 "\t [-x repeat] [-o order-pattern] [-t stream-pattern]\n"
208 "\t [-M max-stream] [-r rand-seed]\n"
209 "\t [-m max-msgsize]\n"
210 "\t [-L num-ports] [-S num-ports]\n"
211 "\t [-a assoc-pattern]\n"
212 "\t [-i interface]\n",
213 argv0);
214 fprintf(stderr, "\n");
215 fprintf(stderr, "\t-a assoc_pattern in the mixed mode\n");
216 fprintf(stderr, "\t 0 = sequential ascending(default)\n");
217 fprintf(stderr, "\t 1 = random\n");
218 fprintf(stderr, "\t-d debug\n");
219 fprintf(stderr, "\t 0 = none\n");
220 fprintf(stderr, "\t 1 = min(default)\n");
221 fprintf(stderr, "\t 2 = max\n");
222 fprintf(stderr, "\t-c testcase\n");
223 fprintf(stderr, "\t 0 = 1 byte packets.\n");
224 fprintf(stderr, "\t 1 = Sequence of multiples of 1452 byte packets.\n");
225 fprintf(stderr, "\t (1452 is fragmentation point for an i/f with ");
226 fprintf(stderr, "1500 as mtu.)\n");
227 fprintf(stderr, "\t 2 = 1453 byte packets.\n");
228 fprintf(stderr, "\t (min. size at which fragmentation occurs\n");
229 fprintf(stderr, "\t for an i/f with 1500 as mtu.)\n");
230 fprintf(stderr, "\t 3 = Sequence of 1, 1453, 32768 byte packets.\n");
231 fprintf(stderr, "\t 4 = Sequence of following size packets.\n");
232 fprintf(stderr, "\t (1, 1000, 2000, 3000, 5000, 10000,");
233 fprintf(stderr, "15000, 20000, 25000, 32768)\n");
234 fprintf(stderr, "\t 5 = 32768 byte packets.\n");
235 fprintf(stderr, "\t (default max receive window size.)\n");
236 fprintf(stderr, "\t 6 = random size packets.\n");
237 fprintf(stderr, "\t -ve value = Packets of specifed size.\n");
238 fprintf(stderr, "\t-m max msgsize for option -c 6 (1500-65515, default value 32768)\n");
239 fprintf(stderr, "\t-x number of repeats\n");
240 fprintf(stderr, "\t-o order-pattern\n");
241 fprintf(stderr, "\t 0 = all unordered(default) \n");
242 fprintf(stderr, "\t 1 = all ordered \n");
243 fprintf(stderr, "\t 2 = alternating \n");
244 fprintf(stderr, "\t 3 = random\n");
245 fprintf(stderr, "\t-t stream-pattern\n");
246 fprintf(stderr, "\t 0 = sequential ascending(default)\n");
247 fprintf(stderr, "\t 1 = random\n");
248 fprintf(stderr, "\t-M max-stream (default value 0)\n");
249 fprintf(stderr, "\t-r seed (default 0, use time())\n");
250 fprintf(stderr, "\t-L num-ports (default value 0). Run the mixed mode\n");
251 fprintf(stderr, "\t-S num-ports (default value 0). Run the mixed mode\n");
252 fprintf(stderr, "\t-D drain. If in client mode do a read following send.\n");
253 fprintf(stderr, "\t-T use SOCK_STREAM tcp-style sockets.\n");
254 fprintf(stderr, "\t-B add the specified address(es) as additional bind\n");
255 fprintf(stderr, "\t addresses of the local socket. Multiple addresses can\n");
256 fprintf(stderr, "\t be specified by using this argument multiple times.\n");
257 fprintf(stderr, "\t For example, '-B 10.0.0.1 -B 20.0.0.2'.\n");
258 fprintf(stderr, "\t In case of IPv6 linklocal address, interface name can be set in following way \n");
259 fprintf(stderr, "\t For example, '-B fe80::f8c3:b77f:698e:4506%%eth2'.\n");
260 fprintf(stderr, "\t-C use the specified address(es) for connection to the\n");
261 fprintf(stderr, "\t peer socket. Multiple addresses can be specified by\n");
262 fprintf(stderr, "\t using this argument multiple times.\n");
263 fprintf(stderr, "\t For example, '-C 10.0.0.1 -C 20.0.0.2'.\n");
264 fprintf(stderr, "\t This option is incompatible with the -h option.\n");
265 fprintf(stderr, "\t-O time to live (default value 0)\n");
266 fprintf(stderr, "\n");
267 fflush(stderr);
268
269} /* usage() */
270
271void *
272build_msg(int len)
273{
274 int i = len - 1;
275 int n;
276 char *msg_buf, *p;
277
278 msg_buf = malloc(len);
279 if (NULL == msg_buf) {
280 fprintf(stderr, "\n\t\t*** malloc not enough memory!!! ***\n");
281 exit(1);
282 }
283 p = msg_buf;
284
285 do {
286 n = ((i > 50)?50:i);
287 memcpy(p, msg, ((i > 50)?50:i));
288 p += n;
289 i -= n;
290 } while (i > 0);
291
292 msg_buf[len-1] = '\0';
293
294 return(msg_buf);
295
296} /* build_msg() */
297
298static int
299print_cmsg(int type, sctp_cmsg_data_t *data)
300{
301 switch(type) {
302 case SCTP_INIT:
303 DEBUG_PRINT(DEBUG_MAX, "\tINIT\n");
304 if (DEBUG_MAX == debug_level) {
305 printf("\t\tsinit_num_ostreams=%d ",
306 data->init.sinit_num_ostreams);
307 printf("sinit_max_instreams=%d ",
308 data->init.sinit_max_instreams);
309 printf("sinit_max_attempts=%d ",
310 data->init.sinit_max_attempts);
311 printf("sinit_max_init_timeo=%d\n",
312 data->init.sinit_max_init_timeo);
313 }
314 break;
315 case SCTP_SNDRCV:
316 DEBUG_PRINT(DEBUG_MAX, "\t SNDRCV");
317 if (DEBUG_MAX == debug_level) {
318 printf("(stream=%u ", data->sndrcv.sinfo_stream);
319 printf("ssn=%u ", data->sndrcv.sinfo_ssn);
320 printf("tsn=%u ", data->sndrcv.sinfo_tsn);
321 printf("flags=0x%x ", data->sndrcv.sinfo_flags);
322 printf("ppid=%u\n", data->sndrcv.sinfo_ppid);
323 printf("cumtsn=%u\n", data->sndrcv.sinfo_cumtsn);
324 }
325 break;
326 default:
327 DEBUG_PRINT(DEBUG_MIN, "\tUnknown type: %d\n", type);
328 break;
329 }
330 fflush(stdout);
331 return 0;
332
333} /* print_cmsg() */
334
335/* This function prints the message. */
336static int
337print_message(const int sk, struct msghdr *msg, size_t msg_len) {
338 struct cmsghdr *scmsg;
339 sctp_cmsg_data_t *data;
340 int i;
341
342 if (!(MSG_NOTIFICATION & msg->msg_flags)) {
343 int index = 0;
344
345 DEBUG_PRINT(DEBUG_MIN, "Data %zu bytes.", msg_len);
346 DEBUG_PRINT(DEBUG_MAX, " First %zu bytes: ",
347 (msg_len < BODYSIZE)?msg_len:BODYSIZE);
348 /* Make sure that everything is printable and that we
349 * are NUL terminated...
350 */
351 while ( msg_len > 0 ) {
352 char *text, tmptext[BODYSIZE];
353 int len;
354
355 memset(tmptext, 0x0, BODYSIZE);
356
357 text = msg->msg_iov[index].iov_base;
358 len = msg->msg_iov[index].iov_len;
359
360 if (msg_len == 1 && text[0] == 0) {
361 DEBUG_PRINT(DEBUG_MIN, "<empty> text[0]=%d",
362 text[0]);
363 break;
364 }
365
366 if ( len > msg_len ) {
367 /* text[(len = msg_len) - 1] = '\0'; */
368 text[(len = msg_len)] = '\0';
369 }
370
371 if ( (msg_len -= len) > 0 ) { index++; }
372
373 for (i = 0; i < len - 1; ++i) {
374 if (!isprint(text[i])) text[i] = '.';
375 }
376
377 strncpy(tmptext, text, BODYSIZE);
378 tmptext[BODYSIZE-1] = '\0';
379
380 DEBUG_PRINT(DEBUG_MAX, "%s", tmptext);
381 }
382
383 DEBUG_PRINT(DEBUG_MIN, "\n");
384 fflush(stdout);
385 } else { /* if(we have notification) */
386 struct sctp_assoc_change *sac;
387 struct sctp_send_failed *ssf;
388 struct sctp_paddr_change *spc;
389 struct sctp_remote_error *sre;
390 union sctp_notification *snp;
391 char addrbuf[INET6_ADDRSTRLEN];
392 const char *ap;
393 struct sockaddr_in *sin;
394 struct sockaddr_in6 *sin6;
395 int index = 0;
396
397 snp = (union sctp_notification *)msg->msg_iov[index].iov_base;
398
399 DEBUG_PRINT(DEBUG_MIN, "Notification:");
400
401 switch (snp->sn_header.sn_type) {
402 case SCTP_ASSOC_CHANGE:
403 sac = &snp->sn_assoc_change;
404 DEBUG_PRINT(DEBUG_MIN,
405 " SCTP_ASSOC_CHANGE(%s)\n",
406 sac_state_tbl[sac->sac_state]);
407 DEBUG_PRINT(DEBUG_MAX,
408 "\t\t(assoc_change: state=%hu, "
409 "error=%hu, instr=%hu "
410 "outstr=%hu)\n",
411 sac->sac_state, sac->sac_error,
412 sac->sac_inbound_streams,
413 sac->sac_outbound_streams);
414 break;
415 case SCTP_PEER_ADDR_CHANGE:
416 spc = &snp->sn_paddr_change;
417 DEBUG_PRINT(DEBUG_MIN,
418 " SCTP_PEER_ADDR_CHANGE\n");
419 if (spc->spc_aaddr.ss_family == AF_INET) {
420 sin = (struct sockaddr_in *)
421 &spc->spc_aaddr;
422 ap = inet_ntop(AF_INET, &sin->sin_addr,
423 addrbuf,
424 INET6_ADDRSTRLEN);
425 } else {
426 sin6 = (struct sockaddr_in6 *)
427 &spc->spc_aaddr;
428 ap = inet_ntop(AF_INET6,
429 &sin6->sin6_addr,
430 addrbuf,
431 INET6_ADDRSTRLEN);
432 }
433 DEBUG_PRINT(DEBUG_MAX,
434 "\t\t(peer_addr_change: %s "
435 "state=%d, error=%d)\n",
436 ap, spc->spc_state,
437 spc->spc_error);
438 break;
439 case SCTP_SEND_FAILED:
440 ssf = &snp->sn_send_failed;
441 DEBUG_PRINT(DEBUG_MIN,
442 " SCTP_SEND_FAILED\n");
443 DEBUG_PRINT(DEBUG_MAX,
444 "\t\t(sendfailed: len=%hu "
445 "err=%d)\n",
446 ssf->ssf_length, ssf->ssf_error);
447 break;
448 case SCTP_REMOTE_ERROR:
449 sre = &snp->sn_remote_error;
450 DEBUG_PRINT(DEBUG_MIN,
451 " SCTP_REMOTE_ERROR\n");
452 DEBUG_PRINT(DEBUG_MAX,
453 "\t\t(remote_error: err=%hu)\n",
454 ntohs(sre->sre_error));
455 break;
456 case SCTP_SHUTDOWN_EVENT:
457 DEBUG_PRINT(DEBUG_MIN,
458 " SCTP_SHUTDOWN_EVENT\n");
459 break;
460 default:
461 DEBUG_PRINT(DEBUG_MIN,
462 " Unknown type: %hu\n",
463 snp->sn_header.sn_type);
464 break;
465 }
466
467 fflush(stdout);
468 return 1;
469
470 } /* notification received */
471
472 for (scmsg = CMSG_FIRSTHDR(msg);
473 scmsg != NULL;
474 scmsg = CMSG_NXTHDR(msg, scmsg)) {
475
476 data = (sctp_cmsg_data_t *)CMSG_DATA(scmsg);
477 if (debug_level) print_cmsg(scmsg->cmsg_type, data);
478 }
479
480
481 fflush(stdout);
482 return 0;
483
484} /* print_message() */
485
486struct sockaddr *
487append_addr(const char *parm, struct sockaddr *addrs, int *ret_count)
488{
489 struct sockaddr *new_addrs = NULL;
490 void *aptr;
491 struct sockaddr *sa_addr;
492 struct sockaddr_in *b4ap;
493 struct sockaddr_in6 *b6ap;
494 struct hostent *hst4 = NULL;
495 struct hostent *hst6 = NULL;
496 int i4 = 0;
497 int i6 = 0;
498 int j;
499 int orig_count = *ret_count;
500 int count = orig_count;
501 char *ipaddr = strdup(parm);
502 char *ifname;
503 int ifindex = 0;
504
505 /* check the interface. */
506 ifname = strchr(ipaddr,'%');
507 if (ifname) {
508 *ifname=0;
509 ifname++;
510 ifindex = if_nametoindex(ifname);
511 if (!ifindex) {
512 fprintf(stderr, "bad interface name: %s\n", ifname);
513 goto finally;
514 }
515 }
516
517 /* Get the entries for this host. */
518 hst4 = gethostbyname(ipaddr);
519 hst6 = gethostbyname2(ipaddr, AF_INET6);
520
521 if ((NULL == hst4 || hst4->h_length < 1)
522 && (NULL == hst6 || hst6->h_length < 1)) {
523 fprintf(stderr, "bad hostname: %s\n", ipaddr);
524 goto finally;
525 }
526
527 /* Figure out the number of addresses. */
528 if (NULL != hst4) {
529 for (i4 = 0; NULL != hst4->h_addr_list[i4]; ++i4) {
530 count++;
531 }
532 }
533 if (NULL != hst6) {
534 for (i6 = 0; NULL != hst6->h_addr_list[i6]; ++i6) {
535 count++;
536 }
537 }
538
539 /* Expand memory for the new addresses. Assume all the addresses
540 * are v6 addresses.
541 */
542 new_addrs = (struct sockaddr *)
543 realloc(addrs, sizeof(struct sockaddr_in6) * count);
544
545 if (NULL == new_addrs) {
546 count = *ret_count;
547 goto finally;
548 }
549
550 /* Skip the existing addresses. */
551 aptr = new_addrs;
552 for (j = 0; j < orig_count; j++) {
553 sa_addr = (struct sockaddr *)aptr;
554 switch(sa_addr->sa_family) {
555 case AF_INET:
556 aptr += sizeof(struct sockaddr_in);
557 break;
558 case AF_INET6:
559 aptr += sizeof(struct sockaddr_in6);
560 break;
561 default:
562 count = orig_count;
563 goto finally;
564 }
565 }
566
567 /* Put the new addresses away. */
568 if (NULL != hst4) {
569 for (j = 0; j < i4; ++j) {
570 b4ap = (struct sockaddr_in *)aptr;
571 memset(b4ap, 0x00, sizeof(*b4ap));
572 b4ap->sin_family = AF_INET;
573 b4ap->sin_port = htons(local_port);
574 bcopy(hst4->h_addr_list[j], &b4ap->sin_addr,
575 hst4->h_length);
576
577 aptr += sizeof(struct sockaddr_in);
578 } /* for (loop through the new v4 addresses) */
579 }
580
581 if (NULL != hst6) {
582 for (j = 0; j < i6; ++j) {
583 b6ap = (struct sockaddr_in6 *)aptr;
584 memset(b6ap, 0x00, sizeof(*b6ap));
585 b6ap->sin6_family = AF_INET6;
586 b6ap->sin6_port = htons(local_port);
587 b6ap->sin6_scope_id = if_index;
588 bcopy(hst6->h_addr_list[j], &b6ap->sin6_addr,
589 hst6->h_length);
590 if (!ifindex) {
591 b6ap->sin6_scope_id = ifindex;
592 }
593
594 aptr += sizeof(struct sockaddr_in6);
595 } /* for (loop through the new v6 addresses) */
596 }
597
598 finally:
599 free(ipaddr);
600 *ret_count = count;
601
602 return new_addrs;
603
604} /* append_addr() */
605
606int socket_r(void)
607{
608 struct sctp_event_subscribe subscribe;
609 int sk, error;
610
611 DEBUG_PRINT(DEBUG_MIN, "\tsocket(%s, IPPROTO_SCTP)",
612 (socket_type == SOCK_SEQPACKET) ? "SOCK_SEQPACKET" : "SOCK_STREAM");
613
614 if ((sk = socket(s_loc.ss_family, socket_type, IPPROTO_SCTP)) < 0 ) {
615 if (do_exit) {
616 fprintf(stderr, "\n\n\t\t*** socket: failed to create"
617 " socket: %s ***\n",
618 strerror(errno));
619 exit(1);
620 } else {
621 return -1;
622 }
623 }
624 DEBUG_PRINT(DEBUG_MIN, " -> sk=%d\n", sk);
625
626 memset(&subscribe, 0, sizeof(subscribe));
627 subscribe.sctp_data_io_event = 1;
628 subscribe.sctp_association_event = 1;
629 error = setsockopt(sk, SOL_SCTP, SCTP_EVENTS, (char *)&subscribe,
630 sizeof(subscribe));
631 if (error) {
632 fprintf(stderr, "SCTP_EVENTS: error: %d\n", error);
633 exit(1);
634 }
635 if (max_stream > 0) {
636 struct sctp_initmsg initmsg;
637 memset(&initmsg, 0, sizeof(struct sctp_initmsg));
638 initmsg.sinit_num_ostreams = max_stream;
639 error = setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(struct sctp_initmsg));
640 if (error) {
641 fprintf(stderr, "SCTP_INITMSG: error: %d\n", error);
642 exit(1);
643 }
644 }
645 return sk;
646
647} /* socket_r() */
648
649int bind_r(int sk, struct sockaddr_storage *saddr)
650{
651 int error = 0, i = 0;
652 char *host_s, *serv_s;
653
654 if ((host_s = malloc(NI_MAXHOST)) == NULL) {
655 fprintf(stderr, "\n\t\t*** host_s malloc failed!!! ***\n");
656 exit(1);
657 }
658 if ((serv_s = malloc(NI_MAXSERV)) == NULL) {
659 fprintf(stderr, "\n\t\t*** serv_s malloc failed!!! ***\n");
660 exit(1);
661 }
662
663 do {
664 if (i > 0) sleep(1); /* sleep a while before new try... */
665
666 error = getnameinfo((struct sockaddr *)saddr, l_len, host_s,
667 NI_MAXHOST, serv_s, NI_MAXSERV,
668 NI_NUMERICHOST);
669
670 if (error)
671 printf("%s\n", gai_strerror(error));
672
673 DEBUG_PRINT(DEBUG_MIN,
674 "\tbind(sk=%d, [a:%s,p:%s]) -- attempt %d/%d\n",
675 sk, host_s, serv_s, i+1, MAX_BIND_RETRYS);
676
677 error = bind(sk, (struct sockaddr *)saddr, l_len);
678
679 if (error != 0) {
680 if( errno != EADDRINUSE ) {
681 if (do_exit) {
682 fprintf(stderr, "\n\n\t\t***bind: can "
683 "not bind to %s:%s: %s ****\n",
684 host_s, serv_s,
685 strerror(errno));
686 exit(1);
687 } else {
688 return -1;
689 }
690 }
691 }
692 i++;
693 if (i >= MAX_BIND_RETRYS) {
694 fprintf(stderr, "Maximum bind() attempts. "
695 "Die now...\n\n");
696 exit(1);
697 }
698 } while (error < 0 && i < MAX_BIND_RETRYS);
699
700 free(host_s);
701 free(serv_s);
702 return 0;
703
704} /* bind_r() */
705
706int
707bindx_r(int sk, struct sockaddr *addrs, int count, int flag)
708{
709 int error;
710 int i;
711 struct sockaddr *sa_addr;
712 void *aptr;
713
714 /* Set the port in every address. */
715 aptr = addrs;
716 for (i = 0; i < count; i++) {
717 sa_addr = (struct sockaddr *)aptr;
718
719 switch(sa_addr->sa_family) {
720 case AF_INET:
721 ((struct sockaddr_in *)sa_addr)->sin_port =
722 htons(local_port);
723 aptr += sizeof(struct sockaddr_in);
724 break;
725 case AF_INET6:
726 ((struct sockaddr_in6 *)sa_addr)->sin6_port =
727 htons(local_port);
728 aptr += sizeof(struct sockaddr_in6);
729 break;
730 default:
731 fprintf(stderr, "Invalid address family\n");
732 exit(1);
733 }
734 }
735
736 error = sctp_bindx(sk, addrs, count, flag);
737 if (error != 0) {
738 fprintf(stderr, "\n\n\t\t***bindx_r: error adding addrs:"
739 " %s. ***\n", strerror(errno));
740 exit(1);
741 }
742
743 return 0;
744
745} /* bindx_r() */
746
747int listen_r(int sk, int listen_count)
748{
749 int error = 0;
750
751 DEBUG_PRINT(DEBUG_MIN, "\tlisten(sk=%d,backlog=%d)\n",
752 sk, listen_count);
753
754 /* Mark sk as being able to accept new associations */
755 error = listen(sk, listen_count);
756 if (error != 0) {
757 if (do_exit) {
758 fprintf(stderr, "\n\n\t\t*** listen: %s ***\n\n\n",
759 strerror(errno));
760 exit(1);
761 }
762 else return -1;
763 }
764 return 0;
765
766} /* listen_r() */
767
768int accept_r(int sk){
769 socklen_t len = 0;
770 int subsk;
771
772 DEBUG_PRINT(DEBUG_MIN, "\taccept(sk=%d)\n", sk);
773
774 subsk = accept(sk, NULL, &len);
775 if (subsk < 0) {
776 fprintf(stderr, "\n\n\t\t*** accept: %s ***\n\n\n", strerror(errno));
777 exit(1);
778 }
779
780 return subsk;
781} /* accept_r() */
782
783int connect_r(int sk, const struct sockaddr *serv_addr, socklen_t addrlen)
784{
785 int error = 0;
786
787 DEBUG_PRINT(DEBUG_MIN, "\tconnect(sk=%d)\n", sk);
788
789 /* Mark sk as being able to accept new associations */
790 error = connect(sk, serv_addr, addrlen);
791 if (error != 0) {
792 if (do_exit) {
793 fprintf(stderr, "\n\n\t\t*** connect: %s ***\n\n\n",
794 strerror(errno));
795 exit(1);
796 }
797 else return -1;
798 }
799 return 0;
800
801} /* connect_r() */
802
803int connectx_r(int sk, struct sockaddr *addrs, int count)
804{
805 int error;
806 int i;
807 struct sockaddr *sa_addr;
808 void *aptr;
809
810 /* Set the port in every address. */
811 aptr = addrs;
812 for (i = 0; i < count; i++) {
813 sa_addr = (struct sockaddr *)aptr;
814
815 switch(sa_addr->sa_family) {
816 case AF_INET:
817 ((struct sockaddr_in *)sa_addr)->sin_port =
818 htons(remote_port);
819 aptr += sizeof(struct sockaddr_in);
820 break;
821 case AF_INET6:
822 ((struct sockaddr_in6 *)sa_addr)->sin6_port =
823 htons(remote_port);
824 aptr += sizeof(struct sockaddr_in6);
825 break;
826 default:
827 fprintf(stderr, "Invalid address family\n");
828 exit(1);
829 }
830 }
831
832 error = sctp_connectx(sk, addrs, count, NULL);
833 if (error != 0) {
834 fprintf(stderr, "\n\n\t\t*** connectx_r: error connecting"
835 " to addrs: %s ***\n", strerror(errno));
836 exit(1);
837 }
838
839 return 0;
840
841} /* connectx_r() */
842
843int receive_r(int sk, int once)
844{
845 int recvsk = sk, i = 0, error = 0;
846 char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))];
847 struct iovec iov;
848 struct msghdr inmessage;
849
850 /* Initialize inmessage with enough space for DATA... */
851 memset(&inmessage, 0, sizeof(inmessage));
852 if ((iov.iov_base = malloc(REALLY_BIG)) == NULL) {
853 fprintf(stderr, "\n\t\t*** malloc not enough memory!!! ***\n");
854 exit(1);
855 }
856 iov.iov_len = REALLY_BIG;
857 inmessage.msg_iov = &iov;
858 inmessage.msg_iovlen = 1;
859 /* or a control message. */
860 inmessage.msg_control = incmsg;
861 inmessage.msg_controllen = sizeof(incmsg);
862
863 /* Get the messages sent */
864 while (1) {
865
866 if (recvsk == sk && socket_type == SOCK_STREAM &&
867 role == SERVER)
868 recvsk = accept_r(sk);
869
870 DEBUG_PRINT(DEBUG_MIN, "\trecvmsg(sk=%d) ", sk);
871
872 error = recvmsg(recvsk, &inmessage, MSG_WAITALL);
873 if (error < 0 && errno != EAGAIN) {
874 if (errno == ENOTCONN && socket_type == SOCK_STREAM &&
875 role == SERVER) {
876 printf("No association is present now!!\n");
877 close(recvsk);
878 recvsk = sk;
879 continue;
880 }
881
882 fprintf(stderr, "\n\t\t*** recvmsg: %s ***\n\n",
883 strerror(errno));
884 fflush(stdout);
885 if (do_exit) exit(1);
886 else goto error_out;
887 }
888 else if (error == 0) {
889 if (socket_type == SOCK_STREAM && role == SERVER) {
890 printf("No association is present now!!\n");
891 close(recvsk);
892 recvsk = sk;
893 continue;
894 }
895 printf("\n\t\trecvmsg() returned 0 !!!!\n");
896 fflush(stdout);
897 }
898
899 if (print_message(recvsk, &inmessage, error) > 0)
900 continue; /* got a notification... */
901
902 inmessage.msg_control = incmsg;
903 inmessage.msg_controllen = sizeof(incmsg);
904 iov.iov_len = REALLY_BIG;
905 i++;
906 if (once)
907 break;
908 }
909
910 if (recvsk != sk)
911 close(recvsk);
912
913 free(iov.iov_base);
914 return 0;
915error_out:
916 close(sk);
917 free(iov.iov_base);
918 return -1;
919
920} /* receive_r () */
921
922int next_order(int state, int pattern)
923{
924 switch (pattern){
925 case ORDER_PATTERN_UNORDERED:
926 state = 0;
927 break;
928 case ORDER_PATTERN_ORDERED:
929 state = 1;
930 break;
931 case ORDER_PATTERN_ALTERNATE:
932 state = state ? 0 : 1;
933 break;
934 case ORDER_PATTERN_RANDOM:
935 state = rand() % 2;
936 break;
937 }
938
939 return state;
940}
941
942int next_stream(int state, int pattern)
943{
944 switch (pattern){
945 case STREAM_PATTERN_RANDOM:
946 state = rand() % (max_stream == 0 ? 1 : max_stream);
947 break;
948 case STREAM_PATTERN_SEQUENTIAL:
949 state = state + 1;
950 if (state >= max_stream)
951 state = 0;
952 break;
953 }
954
955 return state;
956}
957
958int next_msg_size(int msg_cnt)
959{
960 int msg_size;
961
962 if (size_arg) {
963 msg_size = size_arg;
964 } else if (test_case < NCASES) {
965 msg_size = msg_sizes[test_case][msg_cnt];
966 } else {
967 msg_size = (rand() % max_msgsize) + 1;
968 }
969
970 return msg_size;
971
972} /* next_msg_size() */
973
974int next_assoc(int i, int state, int pattern)
975{
976 int j;
977 int found = 0;
978 _assoc_state *as;
979
980
981 switch (pattern){
982 case ASSOC_PATTERN_RANDOM:
983 state = rand() % tosend;
984 break;
985 case ASSOC_PATTERN_SEQUENTIAL:
986 state = state + 1;
987 if (state >= tosend)
988 state = 0;
989 break;
990 }
991
992 as = poll_sks[i].assoc_state;
993 j = state;
994 do {
995 if (as[j].msg_sent < repeat_count) {
996 found = 1;
997 break;
998 }
999 if (++j >= tosend) {
1000 j = 0;
1001 }
1002 } while (j != state);
1003
1004 if (found) {
1005 return j;
1006 } else {
1007 return -1;
1008 }
1009
1010} /* next_assoc() */
1011
1012int send_r(int sk, int stream, int order, int send_size, int assoc_i)
1013{
1014 int error = 0;
1015 struct msghdr outmsg;
1016 struct iovec iov;
1017 char *message = NULL;
1018 int msglen = 0;
1019 char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
1020 struct cmsghdr *cmsg;
1021 struct sctp_sndrcvinfo *sinfo;
1022
1023 if (send_size > 0) {
1024 message = build_msg(send_size);
1025 msglen = strlen(message) + 1;
1026 iov.iov_base = message;
1027 iov.iov_len = msglen;
1028 }
1029 else {
1030 if (do_exit) {
1031 exit(1);
1032 } else {
1033 goto error_out;
1034 }
1035 }
1036
1037 outmsg.msg_name = &s_rem;
1038 outmsg.msg_namelen = sizeof(struct sockaddr_storage);
1039 outmsg.msg_iov = &iov;
1040 outmsg.msg_iovlen = 1;
1041 outmsg.msg_control = outcmsg;
1042 outmsg.msg_controllen = sizeof(outcmsg);
1043 outmsg.msg_flags = 0;
1044
1045 cmsg = CMSG_FIRSTHDR(&outmsg);
1046 cmsg->cmsg_level = IPPROTO_SCTP;
1047 cmsg->cmsg_type = SCTP_SNDRCV;
1048 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
1049
1050 outmsg.msg_controllen = cmsg->cmsg_len;
1051 sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
1052 memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
1053 sinfo->sinfo_ppid = rand();
1054 sinfo->sinfo_stream = stream;
1055 sinfo->sinfo_flags = 0;
1056 if (!order)
1057 sinfo->sinfo_flags = SCTP_UNORDERED;
1058 if (timetolive)
1059 sinfo->sinfo_timetolive = timetolive;
1060
1061 DEBUG_PRINT(DEBUG_MIN, "\tsendmsg(sk=%d, assoc=%d) %4d bytes.\n",
1062 sk, assoc_i, send_size);
1063 DEBUG_PRINT(DEBUG_MAX, "\t SNDRCV");
1064 if (DEBUG_MAX == debug_level) {
1065 printf("(stream=%u ", sinfo->sinfo_stream);
1066 printf("flags=0x%x ", sinfo->sinfo_flags);
1067 printf("ppid=%u\n", sinfo->sinfo_ppid);
1068 }
1069
1070 /* Send to our neighbor. */
1071 error = sendmsg(sk, &outmsg, MSG_WAITALL);
1072 if (error != msglen) {
1073 fprintf(stderr, "\n\t\t*** sendmsg: %s ***\n\n",
1074 strerror(errno));
1075 fflush(stdout);
1076
1077 if (do_exit) {
1078 exit(1);
1079 } else {
1080 if (!drain)
1081 goto error_out;
1082 }
1083 }
1084
1085 if (send_size > 0) free(message);
1086 return 0;
1087error_out:
1088 if (send_size > 0) free(message);
1089 return -1;
1090
1091} /* send_r() */
1092
1093int close_r(int sk)
1094{
1095 int error = 0;
1096
1097 DEBUG_PRINT(DEBUG_MIN, "\tclose(sk=%d)\n",sk);
1098
1099 error = close(sk);
1100 if (error != 0) {
1101 if (do_exit) {
1102 fprintf(stderr, "\n\n\t\t*** close: %s ***\n\n",
1103 strerror(errno));
1104 exit(1);
1105 } else {
1106 return -1;
1107 }
1108 }
1109 fflush(stdout);
1110 return 0;
1111
1112} /* close_r() */
1113
1114void
1115server(int sk)
1116{
1117 if (max_msgsize > DEFAULT_MAX_WINDOW) {
1118 if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, &max_msgsize,
1119 sizeof(max_msgsize)) < 0) {
1120 perror("setsockopt(SO_RCVBUF)");
1121 exit(1);
1122 }
1123 }
1124
1125 receive_r(sk, 0);
1126
1127} /* server() */
1128
1129void
1130client(int sk)
1131{
1132 int msg_size;
1133 int i;
1134
1135 for (i = 0; i < msg_cnt; i++) {
1136
1137 msg_size = next_msg_size(i);
1138 order_state = next_order(order_state, order_pattern);
1139 stream_state = next_stream(stream_state, stream_pattern);
1140
1141 if (send_r(sk, stream_state, order_state, msg_size, 0) < 0)
1142 break;
1143 /* The sender is echoing so do discard the echoed data. */
1144 if (drain) {
1145 receive_r(sk, 1);
1146 }
1147 }
1148} /* client() */
1149
1150void
1151mixed_mode_test(void)
1152{
1153 int error, i, j, max_fd, sks, size;
1154 int assoc_i, n_msg_size, n_order, n_stream;
1155 int done = 0;
1156 fd_set *ibitsp = NULL, *obitsp = NULL, *xbitsp = NULL;
1157 char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))];
1158 struct iovec iov;
1159 struct msghdr inmessage;
1160 _assoc_state *as;
1161
1162
1163 /* Set up the listeners. If listeners is 0, set up one socket for
1164 * transmitting only.
1165 */
1166 iov.iov_base = NULL;
1167 max_fd = -1;
1168 sks = (0 == listeners) ? 1 : listeners;
1169 memset(poll_sks, 0, sks * sizeof(_poll_sks));
1170
1171 for (i = 0; i < sks; i++) {
1172 poll_sks[i].sk = socket_r();
1173
1174 if (s_loc.ss_family == AF_INET6)
1175 ( (struct sockaddr_in6 *)&s_loc)->sin6_port =
1176 htons(local_port + i);
1177 else
1178 ( (struct sockaddr_in *)&s_loc)->sin_port =
1179 htons(local_port + i);
1180
1181 bind_r(poll_sks[i].sk, &s_loc);
1182 if (listeners) {
1183 listen_r(poll_sks[i].sk, 100);
1184 }
1185 if (max_msgsize > DEFAULT_MAX_WINDOW) {
1186 if (setsockopt(poll_sks[i].sk, SOL_SOCKET, SO_RCVBUF,
1187 &max_msgsize, sizeof(max_msgsize)) < 0) {
1188 perror("setsockopt(SO_RCVBUF)");
1189 exit(1);
1190 }
1191 }
1192
1193 if (tosend) {
1194 if ((poll_sks[i].assoc_state = (_assoc_state *)malloc(
1195 sizeof(_assoc_state) * tosend)) == NULL) {
1196 printf("Can't allocate memory.\n");
1197 goto clean_up;
1198 }
1199 memset(poll_sks[i].assoc_state, 0,
1200 sizeof(_assoc_state) * tosend);
1201 }
1202
1203 if (poll_sks[i].sk > max_fd) {
1204 max_fd = poll_sks[i].sk;
1205 }
1206 }
1207
1208 size = howmany(max_fd + 1, NFDBITS) * sizeof(fd_mask);
1209 if ((ibitsp = (fd_set *)malloc(size)) == NULL) {
1210 printf("Can't allocate memory.\n");
1211 goto clean_up;
1212 }
1213 if ((obitsp = (fd_set *)malloc(size)) == NULL) {
1214 printf("Can't allocate memory.\n");
1215 goto clean_up;
1216 }
1217 if ((xbitsp = (fd_set *)malloc(size)) == NULL) {
1218 printf("Can't allocate memory.\n");
1219 goto clean_up;
1220 }
1221
1222 memset(ibitsp, 0, size);
1223 memset(obitsp, 0, size);
1224 memset(xbitsp, 0, size);
1225
1226
1227 /* Initialize inmessage with enough space for DATA... */
1228 memset(&inmessage, 0, sizeof(inmessage));
1229 if ((iov.iov_base = malloc(REALLY_BIG)) == NULL) {
1230 fprintf(stderr, "\n\t\t*** malloc not enough memory!!! ***\n");
1231 goto clean_up;
1232 }
1233 iov.iov_len = REALLY_BIG;
1234 inmessage.msg_iov = &iov;
1235 inmessage.msg_iovlen = 1;
1236 /* or a control message. */
1237 inmessage.msg_control = incmsg;
1238 inmessage.msg_controllen = sizeof(incmsg);
1239
1240 /* Set up the remote port number per association for output. */
1241 for (i = 0; i < sks; i++) {
1242 as = poll_sks[i].assoc_state;
1243 for (j = 0; j < tosend; j++) {
1244 as[j].rem_port = remote_port + j;
1245 }
1246 }
1247
1248 while (!done) {
1249
1250 for (i = 0; i < sks; i++) {
1251 FD_SET(poll_sks[i].sk, ibitsp);
1252 FD_SET(poll_sks[i].sk, obitsp);
1253 FD_SET(poll_sks[i].sk, xbitsp);
1254 }
1255 if ((error = select(max_fd + 1, ibitsp, obitsp, xbitsp,
1256 (struct timeval *)0)) < 0) {
1257 fprintf(stderr, "\n\t\t*** select() failed ");
1258 fprintf(stderr, "with error: %s\n\n",
1259 strerror(errno));
1260 fflush(stdout);
1261 goto clean_up;
1262 }
1263
1264 for (i = 0; i < sks; i++) {
1265 /* Is there anything to read from the socket? */
1266 if (listeners && FD_ISSET(poll_sks[i].sk, ibitsp)) {
1267
1268 FD_CLR(poll_sks[i].sk, ibitsp);
1269 error = recvmsg(poll_sks[i].sk, &inmessage,
1270 MSG_WAITALL);
1271 if (error < 0) {
1272 fprintf(stderr,
1273 "\n\t\t*** recvmsg: %s ***\n\n",
1274 strerror(errno));
1275 fflush(stdout);
1276 goto clean_up;
1277 }
1278 else if (error == 0) {
1279 printf("\n\t\trecvmsg() returned ");
1280 printf("0 !!!!\n");
1281 fflush(stdout);
1282 }
1283
1284 print_message(poll_sks[i].sk, &inmessage,
1285 error);
1286
1287 inmessage.msg_control = incmsg;
1288 inmessage.msg_controllen = sizeof(incmsg);
1289 iov.iov_len = REALLY_BIG;
1290 }
1291
1292 /* Is this socket writeable? */
1293 if (tosend && FD_ISSET(poll_sks[i].sk, obitsp)) {
1294
1295 FD_CLR(poll_sks[i].sk, obitsp);
1296
1297 /* Pick an association. */
1298 assoc_i = next_assoc(i, poll_sks[i].assoc_i,
1299 assoc_pattern);
1300 if (assoc_i < 0) {
1301 /* No work to do on any associations.
1302 * We are probably done. */
1303 if (!listeners) {
1304 done = 1;
1305 }
1306 continue;
1307 }
1308 poll_sks[i].assoc_i = assoc_i;
1309
1310 as = poll_sks[i].assoc_state;
1311 n_msg_size = next_msg_size(as[assoc_i].msg_cnt);
1312 n_order = as[assoc_i].order_state =
1313 next_order(as[assoc_i].order_state,
1314 order_pattern);
1315 n_stream = as[assoc_i].stream_state =
1316 next_stream(as[assoc_i].stream_state,
1317 stream_pattern);
1318
1319 /* Set the destination port. */
1320 if (s_rem.ss_family == AF_INET6)
1321 ( (struct sockaddr_in6 *)&s_rem)->
1322 sin6_port =
1323 htons(as[assoc_i].rem_port);
1324 else
1325 ( (struct sockaddr_in *)&s_rem)->
1326 sin_port =
1327 htons(as[assoc_i].rem_port);
1328
1329 /* Send a message thru the association. */
1330 if (send_r(poll_sks[i].sk, n_stream, n_order,
1331 n_msg_size, assoc_i) < 0) {
1332 /* Don't increment counter if there
1333 * is a problem of sending.
1334 */
1335 continue;
1336 }
1337
1338 /* Increment counters. */
1339 if (++as[assoc_i].msg_cnt >= MSG_CNT) {
1340 as[assoc_i].msg_cnt = 0;
1341 }
1342 if (++as[assoc_i].msg_sent >=
1343 repeat_count) {
1344 fprintf(stderr, "Association #%d in ",
1345 assoc_i);
1346 fprintf(stderr, "sk=%d has ",
1347 poll_sks[i].sk);
1348 fprintf(stderr, "completed %d msg as ",
1349 as[assoc_i].msg_sent);
1350 fprintf(stderr, "cycle %d.\n",
1351 ++as[assoc_i].cycle);
1352
1353 /* In the mixed mode, -x not only
1354 * specify the longer repeat cycle,
1355 * but it also mean to run the test
1356 * forever.
1357 */
1358 if (xflag) {
1359 as[assoc_i].msg_sent = 0;
1360 }
1361
1362 }
1363
1364 }
1365 }
1366 }
1367
1368clean_up:
1369 for (i = 0; i < sks; i++) {
1370 close(poll_sks[i].sk);
1371 if (poll_sks[i].assoc_state) {
1372 free(poll_sks[i].assoc_state);
1373 }
1374 }
1375
1376 if (ibitsp) free(ibitsp);
1377 if (obitsp) free(obitsp);
1378 if (xbitsp) free(xbitsp);
1379
1380 if (iov.iov_base) free(iov.iov_base);
1381
1382} /* mixed_mode_test() */
1383
1384void start_test(int role)
1385{
1386 int sk;
1387 int i = 0;
1388
1389 DEBUG_PRINT(DEBUG_NONE, "\nStarting tests...\n");
1390
1391 repeat_count = repeat;
1392
1393
1394 if (MIXED == role) {
1395 repeat_count = repeat_count * msg_cnt; /* Repeat per assoc. */
1396 mixed_mode_test();
1397 return;
1398 }
1399
1400 sk = socket_r();
1401 if (sk < 0) {
1402 DEBUG_PRINT(DEBUG_NONE, "\nSocket create err %d\n", errno);
1403 return;
1404 }
1405
1406 if (bind_r(sk, &s_loc) == -1) {
1407 DEBUG_PRINT(DEBUG_NONE, "\nSocket bind err %d\n", errno);
1408 return;
1409 }
1410
1411 /* Do we need to do bindx() to add any additional addresses? */
1412 if (bindx_add_addrs)
1413 bindx_r(sk, bindx_add_addrs, bindx_add_count,
1414 SCTP_BINDX_ADD_ADDR);
1415
1416 if (role == SERVER) {
1417 listen_r(sk, 100);
1418 } else {
1419 if (socket_type == SOCK_STREAM && connectx_count == 0)
1420 connect_r(sk, (struct sockaddr *)&s_rem, r_len);
1421
1422 if (connectx_count != 0)
1423 connectx_r(sk, connectx_addrs, connectx_count);
1424 }
1425
1426 if (!debug_level) {
1427 printf(" ");
1428 }
1429
1430 for(i = 0; i < repeat_count; i++) {
1431
1432 if (role == SERVER) {
1433 DEBUG_PRINT(DEBUG_NONE,
1434 "Server: Receiving packets.\n");
1435 server(sk);
1436 } else {
1437 DEBUG_PRINT(DEBUG_NONE,
1438 "Client: Sending packets.(%d/%d)\n",
1439 i+1, repeat_count);
1440 client(sk);
1441 }
1442
1443 fflush(stdout);
1444 }
1445
1446 close_r(sk);
1447
1448} /* start_test() */
1449
1450int
1451main(int argc, char *argv[])
1452{
1453 int c;
1454 char *interface = NULL;
1455 struct sockaddr_in *t_addr;
1456 struct sockaddr_in6 *t_addr6;
1457 struct sockaddr *tmp_addrs = NULL;
1458
1459 /* Parse the arguments. */
1460 while ((c = getopt(argc, argv, ":H:L:P:S:a:h:p:c:d:lm:sx:X:o:t:M:r:w:Di:TB:C:O:")) >= 0 ) {
1461
1462 switch (c) {
1463 case 'H':
1464 local_host = optarg;
1465 break;
1466 case 'L':
1467 role = MIXED;
1468 listeners = atoi(optarg);
1469 if (listeners > MAX_POLL_SKS) {
1470 usage(argv[0]);
1471 exit(1);
1472 }
1473 break;
1474 case 'P':
1475 local_port = atoi(optarg);
1476 break;
1477 case 'S':
1478 role = MIXED;
1479 tosend = atoi(optarg);
1480 if (tosend > MAX_POLL_SKS) {
1481 usage(argv[0]);
1482 exit(1);
1483 }
1484 break;
1485 case 'a':
1486 assoc_pattern = atoi(optarg);
1487 if (assoc_pattern < ASSOC_PATTERN_SEQUENTIAL
1488 || assoc_pattern > ASSOC_PATTERN_RANDOM ) {
1489 usage(argv[0]);
1490 exit(1);
1491 }
1492 break;
1493 case 'h':
1494 remote_host = optarg;
1495 break;
1496 case 'D':
1497 drain = 1;
1498 do_exit = 0;
1499 break;
1500 case 'p':
1501 remote_port = atoi(optarg);
1502 break;
1503 case 's':
1504 if (role != NOT_DEFINED) {
1505 printf("%s: only -s or -l\n", argv[0]);
1506 usage(argv[0]);
1507 exit(1);
1508 }
1509 role = CLIENT;
1510 break;
1511 case 'l':
1512 if (role != NOT_DEFINED) {
1513 printf("%s: only -s or -l\n", argv[0]);
1514 usage(argv[0]);
1515 exit(1);
1516 }
1517 role = SERVER;
1518 break;
1519 case 'd':
1520 debug_level = atoi(optarg);
1521 if (debug_level < DEBUG_NONE
1522 || debug_level > DEBUG_MAX) {
1523 usage(argv[0]);
1524 exit(1);
1525 }
1526 break;
1527 case 'x':
1528 repeat = atoi(optarg);
1529 if (!repeat) {
1530 xflag = 1;
1531 repeat = BIG_REPEAT;
1532 }
1533 break;
1534 case 'X':
1535 msg_cnt = atoi(optarg);
1536 if ((msg_cnt <= 0) || (msg_cnt > MSG_CNT)) {
1537 usage(argv[0]);
1538 exit(1);
1539 }
1540 break;
1541 case 'c':
1542 test_case = atoi(optarg);
1543 if (test_case > NCASES) {
1544 usage(argv[0]);
1545 exit(1);
1546 }
1547 if (test_case < 0) {
1548 size_arg = -test_case;
1549 }
1550
1551 break;
1552 case 'o':
1553 order_pattern = atoi(optarg);
1554 if (order_pattern < ORDER_PATTERN_UNORDERED
1555 || order_pattern > ORDER_PATTERN_RANDOM ) {
1556 usage(argv[0]);
1557 exit(1);
1558 }
1559 break;
1560 case 'O':
1561 timetolive = atoi(optarg);
1562 if (timetolive < 0) {
1563 usage(argv[0]);
1564 exit(1);
1565 }
1566 break;
1567 case 't':
1568 stream_pattern = atoi(optarg);
1569 if (stream_pattern < STREAM_PATTERN_SEQUENTIAL
1570 || stream_pattern > STREAM_PATTERN_RANDOM ) {
1571 usage(argv[0]);
1572 exit(1);
1573 }
1574 break;
1575 case 'M':
1576 max_stream = atoi(optarg);
1577 if (max_stream < 0
1578 || max_stream >= (1<<16)) {
1579 usage(argv[0]);
1580 exit(1);
1581 }
1582 break;
1583 case 'r':
1584 seed = atoi(optarg);
1585 break;
1586 case 'm':
1587 max_msgsize = atoi(optarg);
1588#if 0
1589 if ((max_msgsize < DEFAULT_MIN_WINDOW) ||
1590 (max_msgsize > 65515)) {
1591 usage(argv[0]);
1592 exit(1);
1593 }
1594#endif
1595 break;
1596 case 'i':
1597 interface = optarg;
1598 if_index = if_nametoindex(interface);
1599 if (!if_index) {
1600 printf("Interface %s unknown\n", interface);
1601 exit(1);
1602 }
1603 break;
1604 case 'T':
1605 socket_type = SOCK_STREAM;
1606 break;
1607 case 'B':
1608 tmp_addrs = append_addr(optarg, bindx_add_addrs,
1609 &bindx_add_count);
1610 if (NULL == tmp_addrs) {
1611 fprintf(stderr, "No memory to add ");
1612 fprintf(stderr, "%s\n", optarg);
1613 exit(1);
1614 }
1615 bindx_add_addrs = tmp_addrs;
1616 break;
1617 case 'C':
1618 tmp_addrs = append_addr(optarg, connectx_addrs,
1619 &connectx_count);
1620 if (NULL == tmp_addrs) {
1621 fprintf(stderr, "No memory to add ");
1622 fprintf(stderr, "%s\n", optarg);
1623 exit(1);
1624 }
1625 connectx_addrs = tmp_addrs;
1626 break;
1627 case '?':
1628 default:
1629 usage(argv[0]);
1630 exit(0);
1631 }
1632 } /* while() */
1633
1634 if (NOT_DEFINED == role) {
1635 usage(argv[0]);
1636 exit(1);
1637 }
1638
1639
1640 if (SERVER == role && NULL == local_host && remote_host != NULL) {
1641 fprintf (stderr, "%s: Server needs local address, "
1642 "not remote address\n", argv[0]);
1643 usage(argv[0]);
1644 exit(1);
1645 }
1646 if (CLIENT == role && NULL == remote_host && connectx_count == 0) {
1647 fprintf (stderr, "%s: Client needs at least remote address "
1648 "& port\n", argv[0]);
1649 usage(argv[0]);
1650 exit(1);
1651 }
1652 if (MIXED == role) {
1653 if (listeners && NULL == local_host) {
1654 fprintf (stderr, "%s: Servers need local address\n",
1655 argv[0]);
1656 usage(argv[0]);
1657 exit(1);
1658 }
1659 if (tosend && NULL == remote_host) {
1660 fprintf (stderr, "%s: Clients need remote address ",
1661 argv[0]);
1662 fprintf (stderr, "& port\n");
1663 usage(argv[0]);
1664 exit(1);
1665 }
1666 }
1667
1668 if (optind < argc) {
1669 fprintf(stderr, "%s: non-option arguments are illegal: ",
1670 argv[0]);
1671 while (optind < argc)
1672 fprintf(stderr, "%s ", argv[optind++]);
1673 fprintf (stderr, "\n");
1674 usage(argv[0]);
1675 exit(1);
1676 }
1677
1678 if (remote_host != NULL && connectx_count != 0) {
1679 fprintf(stderr, "%s: You can not provide both -h and -C options.\n",
1680 argv[0]);
1681 usage(argv[0]);
1682 exit(1);
1683 }
1684
1685 if (remote_host != NULL && remote_port != 0) {
1686 struct addrinfo *res;
1687 int error;
1688 char *host_s, *serv_s;
1689
1690 if ((host_s = malloc(NI_MAXHOST)) == NULL) {
1691 fprintf(stderr, "\n*** host_s malloc failed!!! ***\n");
1692 exit(1);
1693 }
1694 if ((serv_s = malloc(NI_MAXSERV)) == NULL) {
1695 fprintf(stderr, "\n*** serv_s malloc failed!!! ***\n");
1696 exit(1);
1697 }
1698
1699 error = getaddrinfo(remote_host, 0, NULL, &res);
1700 if (error) {
1701 printf("%s.\n", gai_strerror(error));
1702 usage(argv[0]);
1703 exit(1);
1704 }
1705
1706 switch (res->ai_family) {
1707 case AF_INET:
1708 t_addr = (struct sockaddr_in *)&s_rem;
1709
1710 memcpy(t_addr, res->ai_addr,
1711 res->ai_addrlen);
1712 t_addr->sin_family = res->ai_family;
1713 t_addr->sin_port = htons(remote_port);
1714
1715 r_len = res->ai_addrlen;
1716
1717#ifdef __FreeBSD__
1718 t_addr->sin_len = r_len;
1719#endif
1720 break;
1721 case AF_INET6:
1722
1723 t_addr6 = (struct sockaddr_in6 *)&s_rem;
1724
1725 memcpy(t_addr6, res->ai_addr,
1726 res->ai_addrlen);
1727 t_addr6->sin6_family = res->ai_family;
1728 t_addr6->sin6_port = htons(remote_port);
1729 if (interface)
1730 t_addr6->sin6_scope_id =
1731 if_nametoindex(interface);
1732
1733 r_len = res->ai_addrlen;
1734
1735#ifdef __FreeBSD__
1736 t_addr6->sin6_len = r_len;
1737#endif
1738 break;
1739 }
1740
1741 getnameinfo((struct sockaddr *)&s_rem, r_len, host_s,
1742 NI_MAXHOST, serv_s, NI_MAXSERV, NI_NUMERICHOST);
1743
1744 DEBUG_PRINT(DEBUG_MAX, "remote:addr=%s, port=%s, family=%d\n",
1745 host_s, serv_s, res->ai_family);
1746
1747 freeaddrinfo(res);
1748 }
1749
1750 if (connectx_count != 0) {
1751 switch (connectx_addrs->sa_family) {
1752 case AF_INET:
1753 t_addr = (struct sockaddr_in *)&s_rem;
1754 r_len = sizeof(struct sockaddr_in);
1755 memcpy(t_addr, connectx_addrs, r_len);
1756 t_addr->sin_port = htons(remote_port);
1757 break;
1758 case AF_INET6:
1759 t_addr6 = (struct sockaddr_in6 *)&s_rem;
1760 r_len = sizeof(struct sockaddr_in6);
1761 memcpy(t_addr6, connectx_addrs, r_len);
1762 t_addr6->sin6_port = htons(remote_port);
1763 break;
1764 }
1765 }
1766
1767 if (local_host != NULL) {
1768 struct addrinfo *res;
1769 int error;
1770 char *host_s, *serv_s;
1771 struct sockaddr_in *t_addr;
1772 struct sockaddr_in6 *t_addr6;
1773
1774 if ((host_s = malloc(NI_MAXHOST)) == NULL) {
1775 fprintf(stderr, "\n*** host_s malloc failed!!! ***\n");
1776 exit(1);
1777 }
1778 if ((serv_s = malloc(NI_MAXSERV)) == NULL) {
1779 fprintf(stderr, "\n*** serv_s malloc failed!!! ***\n");
1780 exit(1);
1781 }
1782
1783 if (strcmp(local_host, "0") == 0)
1784 local_host = "0.0.0.0";
1785
1786 error = getaddrinfo(local_host, 0, NULL, &res);
1787 if (error) {
1788 printf("%s.\n", gai_strerror(error));
1789 usage(argv[0]);
1790 exit(1);
1791 }
1792
1793 switch (res->ai_family) {
1794 case AF_INET:
1795 t_addr = (struct sockaddr_in *)&s_loc;
1796 memcpy(t_addr, res->ai_addr,
1797 res->ai_addrlen);
1798 t_addr->sin_family = res->ai_family;
1799 t_addr->sin_port = htons(local_port);
1800
1801 l_len = res->ai_addrlen;
1802
1803#ifdef __FreeBSD__
1804 t_addr->sin_len = l_len;
1805#endif
1806 break;
1807 case AF_INET6:
1808 t_addr6 = (struct sockaddr_in6 *)&s_loc;
1809
1810 memcpy(t_addr6, res->ai_addr,
1811 res->ai_addrlen);
1812 t_addr6->sin6_family = res->ai_family;
1813 t_addr6->sin6_port = htons(local_port);
1814 if (interface)
1815 t_addr6->sin6_scope_id =
1816 if_nametoindex(interface);
1817
1818 l_len = res->ai_addrlen;
1819
1820#ifdef __FreeBSD__
1821 t_addr6->sin6_len = l_len;
1822#endif
1823 break;
1824 }
1825
1826 error = getnameinfo((struct sockaddr *)&s_loc, l_len, host_s,
1827 NI_MAXHOST, serv_s, NI_MAXSERV, NI_NUMERICHOST);
1828
1829 if (error)
1830 printf("%s..\n", gai_strerror(error));
1831
1832 DEBUG_PRINT(DEBUG_MAX, "local:addr=%s, port=%s, family=%d\n",
1833 host_s, serv_s, res->ai_family);
1834
1835 freeaddrinfo(res);
1836 }
1837
1838
1839 /* A half-hearted attempt to seed rand() */
1840 if (seed == 0 ) {
1841 seed = time(0);
1842 DEBUG_PRINT(DEBUG_NONE, "seed = %d\n", seed);
1843 }
1844
1845 srand(seed);
1846
1847 /* Let the testing begin. */
1848 start_test(role);
1849
1850 return 0;
1851
1852} /* main() */