Imported Upstream version 1.0.10
[platform/upstream/lksctp-tools.git] / src / apps / sctp_test.c
1 /* 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 <sys/errno.h>
52 #include <errno.h>
53 #include <netinet/sctp.h>
54 #include <string.h>
55 #include <arpa/inet.h>
56 #include <sys/wait.h>
57 #include <sys/param.h>
58 #include <fcntl.h>
59 #include <netdb.h>
60 #include <net/if.h>
61
62 #include <sys/resource.h>
63
64
65 #define REALLY_BIG 65536
66
67 #define SERVER          0
68 #define CLIENT          1
69 #define MIXED           2
70 #define NOT_DEFINED     666
71
72 #define REPEAT          10
73 #define BIG_REPEAT      1000000
74 #define MAX_BIND_RETRYS 10
75 #define BODYSIZE        10
76 #define MSG_CNT         10      /* If this is changed the msg_sizes array
77                                    needs to be modified accordingly.  */
78
79 #define DEFAULT_MAX_WINDOW 32768
80 #define DEFAULT_MIN_WINDOW 1500
81
82 #define DEBUG_NONE      0
83 #define DEBUG_MIN       1
84 #define DEBUG_MAX       2
85
86 #define STREAM_PATTERN_SEQUENTIAL 0
87 #define STREAM_PATTERN_RANDOM     1
88
89 #define ORDER_PATTERN_UNORDERED   0
90 #define ORDER_PATTERN_ORDERED     1
91 #define ORDER_PATTERN_ALTERNATE   2
92 #define ORDER_PATTERN_RANDOM      3
93
94 #define ASSOC_PATTERN_SEQUENTIAL 0
95 #define ASSOC_PATTERN_RANDOM     1
96
97 #define NCASES 6
98 #define MAX_POLL_SKS 256
99
100 #define DEBUG_PRINT(level, print_this...)       \
101 {                                               \
102         if (debug_level >= level) {             \
103                 fprintf(stdout, print_this);    \
104                 fflush(stdout);                 \
105         }                                       \
106 } /* DEBUG_PRINT */
107
108 /* Convenience structure to determine space needed for cmsg. */
109 typedef union {
110         struct sctp_initmsg init;
111         struct sctp_sndrcvinfo sndrcvinfo;
112 } _sctp_cmsg_data_t;
113
114 #ifdef __FreeBSD__
115 typedef union {
116         int                    raw;
117         struct sctp_initmsg     init;
118         struct sctp_sndrcvinfo  sndrcv;
119 } sctp_cmsg_data_t;
120 #endif
121
122 #define CMSG_SPACE_INITMSG (CMSG_SPACE(sizeof(struct sctp_initmsg)))
123 #define CMSG_SPACE_SNDRCV (CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)))
124
125 typedef struct {
126         int rem_port;
127         int order_state;
128         int stream_state;
129         int msg_cnt;
130         int msg_sent;
131         int cycle;
132 } _assoc_state;
133
134 typedef struct {
135         int sk;
136         int assoc_i;
137         _assoc_state *assoc_state;
138 } _poll_sks;
139
140 char *local_host = NULL;
141 int local_port = 0;
142 char *remote_host = NULL;
143 int remote_port = 0;
144 /* struct sockaddr_in s_rem, s_loc; */
145 struct sockaddr_storage s_rem, s_loc;
146 int r_len, l_len;
147 int test_case = 0;
148 int size_arg = 0;
149 int xflag = 0;
150 int debug_level = DEBUG_MAX;
151 int do_exit = 1;
152 int stream_pattern = STREAM_PATTERN_SEQUENTIAL;
153 int stream_state = 0;
154 int order_pattern = ORDER_PATTERN_UNORDERED;
155 int order_state = 0;
156 int max_stream = 0;
157 int seed = 0;
158 int max_msgsize = DEFAULT_MAX_WINDOW;
159 int assoc_pattern = ASSOC_PATTERN_SEQUENTIAL;
160 int socket_type = SOCK_SEQPACKET;
161 int repeat_count = 0;
162 int listeners = 0;
163 int tosend = 0;
164 _poll_sks poll_sks[MAX_POLL_SKS];
165 int repeat = REPEAT;
166 int msg_cnt = MSG_CNT;
167 int drain = 0;
168 int role = NOT_DEFINED;
169
170 unsigned char msg[] = "012345678901234567890123456789012345678901234567890";
171
172 static int msg_sizes[NCASES][MSG_CNT] =
173         {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
174          {1452, 2904, 4356, 1452, 2904, 4356, 1452, 2904, 4356, 1452},
175          {1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453},
176          {1, 1453, 32768, 1, 1453, 32768, 1, 1453, 32768, 1},
177          {1, 1000, 2000, 3000, 5000, 10000, 15000, 20000, 25000, 32768},
178          {32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768},
179         };
180
181 static const char *sac_state_tbl[] = {
182         "COMMUNICATION_UP",
183         "COMMUNICATION_LOST",
184         "RESTART",
185         "SHUTDOWN_COMPLETE",
186         "CANT_START_ASSOCICATION"
187 };
188
189 void usage(char *argv0)
190 {
191         fprintf(stderr, "\nusage:\n");
192         fprintf(stderr, "  server:\n");
193         fprintf(stderr, "  %8s -H local-addr -P local-port -l [-d level] [-x]\n"
194                         "\t      [-L num-ports] [-S num-ports]\n"
195                         "\t      [-a assoc-pattern]\n"
196                         "\t      [-i interface]\n",
197                 argv0);
198         fprintf(stderr, "\n");
199         fprintf(stderr, "  client:\n");
200         fprintf(stderr, "  %8s -H local-addr -P local-port -h remote-addr\n"
201                 "\t      -p remote-port -s [-c case ] [-d level]\n"
202                 "\t      [-x repeat] [-o order-pattern] ream-pattern]\n"
203                 "\t      [-M max-stream] [-r rand-seed]\n"
204                 "\t      [-m max-msgsize]\n"
205                 "\t      [-L num-ports] [-S num-ports]\n"
206                 "\t      [-a assoc-pattern]\n"
207                 "\t      [-i interface]\n",
208                 argv0);
209         fprintf(stderr, "\n");
210         fprintf(stderr, "\t-a assoc_pattern in the mixed mode\n");
211         fprintf(stderr, "\t   0 = sequential ascending(default)\n");
212         fprintf(stderr, "\t   1 = random\n");
213         fprintf(stderr, "\t-d debug\n");
214         fprintf(stderr, "\t   0 = none\n");
215         fprintf(stderr, "\t   1 = min(default)\n");
216         fprintf(stderr, "\t   2 = max\n");
217         fprintf(stderr, "\t-c testcase\n");
218         fprintf(stderr, "\t   0 = 1 byte packets.\n");
219         fprintf(stderr, "\t   1 = 1452 byte packets.\n");
220         fprintf(stderr, "\t       (fragmentation point for an i/f with ");
221         fprintf(stderr, "1500 as mtu.)\n");
222         fprintf(stderr, "\t   2 = 1453 byte packets.\n");
223         fprintf(stderr, "\t       (min. size at which fragmentation occurs\n");
224         fprintf(stderr, "\t        for an i/f with 1500 as mtu.)\n");
225         fprintf(stderr, "\t   3 = Sequence of 1, 1453, 32768 byte packets.\n");
226         fprintf(stderr, "\t   4 = Sequence of following size packets.\n");
227         fprintf(stderr, "\t       (1, 1000, 2000, 3000, 5000, 10000,");
228         fprintf(stderr, "15000, 20000, 25000, 32768)\n");
229         fprintf(stderr, "\t   5 = 32768 byte packets.\n");
230         fprintf(stderr, "\t       (default max receive window size.)\n");
231         fprintf(stderr, "\t   6 = random size packets.\n");
232         fprintf(stderr, "\t   -ve value = Packets of specifed size.\n");
233         fprintf(stderr, "\t-m msgsize(1500-65515, default value 32768)\n");
234         fprintf(stderr, "\t-x number of repeats\n");
235         fprintf(stderr, "\t-o order-pattern\n");
236         fprintf(stderr, "\t   0 = all unordered(default) \n");
237         fprintf(stderr, "\t   1 = all ordered \n");
238         fprintf(stderr, "\t   2 = alternating \n");
239         fprintf(stderr, "\t   3 = random\n");
240         fprintf(stderr, "\t-t stream-pattern\n");
241         fprintf(stderr, "\t   0 = sequential ascending(default)\n");
242         fprintf(stderr, "\t   1 = random\n");
243         fprintf(stderr, "\t-M max-stream (default value 0)\n");
244         fprintf(stderr, "\t-r seed (default 0, use time())\n");
245         fprintf(stderr, "\t-L num-ports (default value 0). Run the mixed mode\n");
246         fprintf(stderr, "\t-S num-ports (default value 0). Run the mixed mode\n");
247         fprintf(stderr, "\t-D drain. If in client mode do a read following send.\n");
248         fprintf(stderr, "\t-T use SOCK_STREAM tcp-style sockets.\n");
249         fprintf(stderr, "\n");
250         fflush(stderr);
251
252 } /* usage() */
253
254 void *
255 build_msg(int len)
256 {
257         int i = len - 1;
258         int n;
259         char *msg_buf, *p;
260
261         msg_buf = malloc(len);
262         if (NULL == msg_buf) {
263                 fprintf(stderr, "\n\t\t*** malloc not enough memory!!! ***\n");
264                 exit(1);
265         }
266         p = msg_buf;
267
268         do {
269                 n = ((i > 50)?50:i);
270                 memcpy(p, msg, ((i > 50)?50:i));
271                 p += n;
272                 i -= n;
273         } while (i > 0);
274
275         msg_buf[len-1] = '\0';
276
277         return(msg_buf);
278
279 } /* build_msg() */
280
281 static int
282 print_cmsg(int type, sctp_cmsg_data_t *data)
283 {
284         switch(type) {
285         case SCTP_INIT:
286                 DEBUG_PRINT(DEBUG_MAX, "\tINIT\n");
287                 if (DEBUG_MAX == debug_level) {
288                         printf("\t\tsinit_num_ostreams=%d ",
289                                data->init.sinit_num_ostreams);
290                         printf("sinit_max_instreams=%d ",
291                                data->init.sinit_max_instreams);
292                         printf("sinit_max_attempts=%d ",
293                                data->init.sinit_max_attempts);
294                         printf("sinit_max_init_timeo=%d\n",
295                                data->init.sinit_max_init_timeo);
296                 }
297                 break;
298         case SCTP_SNDRCV:
299                 DEBUG_PRINT(DEBUG_MAX, "\t  SNDRCV");
300                 if (DEBUG_MAX == debug_level) {
301                         printf("(stream=%u ",   data->sndrcv.sinfo_stream);
302                         printf("ssn=%u ",       data->sndrcv.sinfo_ssn);
303                         printf("tsn=%u ",       data->sndrcv.sinfo_tsn);
304                         printf("flags=0x%x ",   data->sndrcv.sinfo_flags);
305                         printf("ppid=%u\n",     data->sndrcv.sinfo_ppid);
306                         printf("cumtsn=%u\n",   data->sndrcv.sinfo_cumtsn);
307                 }
308                 break;
309          default:
310                 DEBUG_PRINT(DEBUG_MIN, "\tUnknown type: %d\n", type);
311                 break;
312         }
313         fflush(stdout);
314         return 0;
315
316 } /* print_cmsg() */
317
318 /* This function prints the message. */
319 static int
320 print_message(const int sk, struct msghdr *msg, size_t msg_len) {
321         struct cmsghdr *scmsg;
322         sctp_cmsg_data_t *data;
323         int i;
324
325         if (!(MSG_NOTIFICATION & msg->msg_flags)) {
326                 int index = 0;
327
328                 DEBUG_PRINT(DEBUG_MIN, "Data %d bytes.", msg_len);
329
330                 DEBUG_PRINT(DEBUG_MAX, " First %d bytes: ",
331                                     (msg_len < BODYSIZE)?msg_len:BODYSIZE);
332                 /* Make sure that everything is printable and that we
333                  * are NUL terminated...
334                  */
335                 while ( msg_len > 0 ) {
336                         char *text, tmptext[BODYSIZE];
337                         int len;
338
339                         memset(tmptext, 0x0, BODYSIZE);
340
341                         text = msg->msg_iov[index].iov_base;
342                         len = msg->msg_iov[index].iov_len;
343
344                         if (msg_len == 1 && text[0] == 0) {
345                                 DEBUG_PRINT(DEBUG_MIN, "<empty> text[0]=%d",
346                                             text[0]);
347                                 break;
348                         }
349
350                         if ( len > msg_len ) {
351                                 /* text[(len = msg_len) - 1] = '\0'; */
352                                 text[(len = msg_len)] = '\0';
353                         }
354
355                         if ( (msg_len -= len) > 0 ) { index++; }
356
357                         for (i = 0; i < len - 1; ++i) {
358                                 if (!isprint(text[i])) text[i] = '.';
359                         }
360
361                         strncpy(tmptext, text, BODYSIZE);
362                         tmptext[BODYSIZE-1] = '\0';
363
364                         DEBUG_PRINT(DEBUG_MAX, "%s", tmptext);
365                 }
366
367                 DEBUG_PRINT(DEBUG_MIN, "\n");
368                 fflush(stdout);
369         }  else { /* if(we have notification) */
370                 struct sctp_assoc_change *sac;
371                 struct sctp_send_failed *ssf;
372                 struct sctp_paddr_change *spc;
373                 struct sctp_remote_error *sre;
374                 union sctp_notification *snp;
375                 char addrbuf[INET6_ADDRSTRLEN];
376                 const char *ap;
377                 struct sockaddr_in *sin;
378                 struct sockaddr_in6 *sin6;
379                 int index = 0;
380
381                 snp = (union sctp_notification *)msg->msg_iov[index].iov_base;
382
383                 DEBUG_PRINT(DEBUG_MIN, "Notification:");
384                 
385                 switch (snp->sn_header.sn_type) {
386                         case SCTP_ASSOC_CHANGE:
387                                 sac = &snp->sn_assoc_change;
388                                 DEBUG_PRINT(DEBUG_MIN,
389                                             " SCTP_ASSOC_CHANGE(%s)\n",
390                                             sac_state_tbl[sac->sac_state]);
391                                 DEBUG_PRINT(DEBUG_MAX,
392                                             "\t\t(assoc_change: state=%hu, "
393                                             "error=%hu, instr=%hu "
394                                             "outstr=%hu)\n",
395                                             sac->sac_state, sac->sac_error,
396                                             sac->sac_inbound_streams,
397                                             sac->sac_outbound_streams);
398                                 break;
399                         case SCTP_PEER_ADDR_CHANGE:
400                                 spc = &snp->sn_paddr_change;
401                                 DEBUG_PRINT(DEBUG_MIN,
402                                             " SCTP_PEER_ADDR_CHANGE\n");
403                                 if (spc->spc_aaddr.ss_family == AF_INET) {
404                                         sin = (struct sockaddr_in *)
405                                                &spc->spc_aaddr;
406                                         ap = inet_ntop(AF_INET, &sin->sin_addr,
407                                                        addrbuf,
408                                                        INET6_ADDRSTRLEN);
409                                 } else {
410                                         sin6 = (struct sockaddr_in6 *)
411                                                 &spc->spc_aaddr;
412                                         ap = inet_ntop(AF_INET6,
413                                                        &sin6->sin6_addr,
414                                                        addrbuf,
415                                                        INET6_ADDRSTRLEN);
416                                 }
417                                 DEBUG_PRINT(DEBUG_MAX,
418                                             "\t\t(peer_addr_change: %s "
419                                             "state=%d, error=%d)\n",
420                                             ap, spc->spc_state,
421                                             spc->spc_error);
422                                 break;
423                         case SCTP_SEND_FAILED:
424                                 ssf = &snp->sn_send_failed;
425                                 DEBUG_PRINT(DEBUG_MIN,
426                                             " SCTP_SEND_FAILED\n");
427                                 DEBUG_PRINT(DEBUG_MAX,
428                                             "\t\t(sendfailed: len=%hu "
429                                             "err=%d)\n",
430                                             ssf->ssf_length, ssf->ssf_error);
431                                 break;
432                         case SCTP_REMOTE_ERROR:
433                                 sre = &snp->sn_remote_error;
434                                 DEBUG_PRINT(DEBUG_MIN,
435                                             " SCTP_REMOTE_ERROR\n");
436                                 DEBUG_PRINT(DEBUG_MAX,
437                                             "\t\t(remote_error: err=%hu)\n",
438                                              ntohs(sre->sre_error));
439                                 break;
440                         case SCTP_SHUTDOWN_EVENT:
441                                 DEBUG_PRINT(DEBUG_MIN,
442                                             " SCTP_SHUTDOWN_EVENT\n");
443                                 break;
444                         default:
445                                 DEBUG_PRINT(DEBUG_MIN,
446                                             " Unknown type: %hu\n",
447                                             snp->sn_header.sn_type);
448                                 break;
449                 }
450
451                 fflush(stdout);
452                 return 1;
453
454         } /* notification received */
455
456         for (scmsg = CMSG_FIRSTHDR(msg);
457              scmsg != NULL;
458              scmsg = CMSG_NXTHDR(msg, scmsg)) {
459                 
460                 data = (sctp_cmsg_data_t *)CMSG_DATA(scmsg);
461                 if (debug_level) print_cmsg(scmsg->cmsg_type, data);
462         }
463
464
465         fflush(stdout);
466         return 0;
467
468 } /* print_message() */
469
470 int socket_r(void)
471 {
472         struct sctp_event_subscribe subscribe;
473         int sk, error;
474
475         DEBUG_PRINT(DEBUG_MIN, "\tsocket(%s, IPPROTO_SCTP)",
476                 (socket_type == SOCK_SEQPACKET) ? "SOCK_SEQPACKET" : "SOCK_STREAM");
477
478         if ((sk = socket(s_loc.ss_family, socket_type, IPPROTO_SCTP)) < 0 ) {
479                 if (do_exit) {
480                         fprintf(stderr, "\n\n\t\t*** socket: failed to create"
481                                 " socket:  %s ***\n",
482                                 strerror(errno));
483                         exit(1);
484                 } else {
485                         return -1;
486                 }
487         }
488         DEBUG_PRINT(DEBUG_MIN, "  ->  sk=%d\n", sk);
489
490         memset(&subscribe, 0, sizeof(subscribe));
491         subscribe.sctp_data_io_event = 1;
492         subscribe.sctp_association_event = 1;
493         error = setsockopt(sk, SOL_SCTP, SCTP_EVENTS, (char *)&subscribe,
494                            sizeof(subscribe));
495         if (error) {
496                 fprintf(stderr, "SCTP_EVENTS: error: %d\n", error);
497                 exit(1);
498         }
499
500         return sk;
501
502 } /* socket_r() */
503
504 int bind_r(int sk, struct sockaddr_storage *saddr)
505 {
506         int error = 0, i = 0;
507         char *host_s, *serv_s;
508
509         if ((host_s = malloc(NI_MAXHOST)) == NULL) {
510                 fprintf(stderr, "\n\t\t*** host_s malloc failed!!! ***\n");
511                 exit(1);
512         }
513         if ((serv_s = malloc(NI_MAXSERV)) == NULL) {
514                 fprintf(stderr, "\n\t\t*** serv_s malloc failed!!! ***\n");
515                 exit(1);
516         }
517
518         do {
519                 if (i > 0) sleep(1); /* sleep a while before new try... */
520
521                 error = getnameinfo((struct sockaddr *)saddr, l_len, host_s,
522                                     NI_MAXHOST, serv_s, NI_MAXSERV,
523                                     NI_NUMERICHOST);
524
525                 if (error)
526                         printf("%s\n", gai_strerror(error));
527
528                 DEBUG_PRINT(DEBUG_MIN,
529                             "\tbind(sk=%d, [a:%s,p:%s])  --  attempt %d/%d\n",
530                             sk, host_s, serv_s, i+1, MAX_BIND_RETRYS);
531
532                 error = bind(sk, (struct sockaddr *)saddr, l_len);
533
534                 if (error != 0) {
535                         if( errno != EADDRINUSE ) {
536                                 if (do_exit) {
537                                         fprintf(stderr, "\n\n\t\t***bind: can "
538                                                 "not bind to %s:%s: %s ****\n",
539                                                 host_s, serv_s,
540                                                 strerror(errno));
541                                         exit(1);
542                                 } else {
543                                         return -1;
544                                 }
545                         }
546                 }
547                 i++;
548                 if (i >= MAX_BIND_RETRYS) {
549                         fprintf(stderr, "Maximum bind() attempts. "
550                                 "Die now...\n\n");
551                         exit(1);
552                 }
553         } while (error < 0 && i < MAX_BIND_RETRYS);
554
555         return 0;
556
557 } /* bind_r() */
558
559 int listen_r(int sk, int listen_count)
560 {
561         int error = 0;
562         
563         DEBUG_PRINT(DEBUG_MIN, "\tlisten(sk=%d,backlog=%d)\n",
564                     sk, listen_count);
565
566         /* Mark sk as being able to accept new associations */
567         error = listen(sk, 1);
568         if (error != 0) {
569                 if (do_exit) {
570                         fprintf(stderr, "\n\n\t\t*** listen:  %s ***\n\n\n",
571                                 strerror(errno));
572                         exit(1);
573                 }
574                 else return -1;
575         }
576         return 0;
577
578 } /* listen_r() */
579
580 int accept_r(int sk){
581         socklen_t len = 0;
582         int subsk;
583
584         DEBUG_PRINT(DEBUG_MIN, "\taccept(sk=%d)\n", sk);
585
586         subsk = accept(sk, NULL, &len);
587         if (subsk < 0) {
588                 fprintf(stderr, "\n\n\t\t*** accept:  %s ***\n\n\n", strerror(errno));
589                 exit(1);
590         }
591
592         return subsk;
593 } /* accept_r() */
594
595 int connect_r(int sk, const struct sockaddr *serv_addr, socklen_t addrlen)
596 {
597         int error = 0;
598
599         DEBUG_PRINT(DEBUG_MIN, "\tconnect(sk=%d)\n", sk);
600
601         /* Mark sk as being able to accept new associations */
602         error = connect(sk, serv_addr, addrlen);
603         if (error != 0) {
604                 if (do_exit) {
605                         fprintf(stderr, "\n\n\t\t*** connect:  %s ***\n\n\n",
606                                 strerror(errno));
607                         exit(1);
608                 }
609                 else return -1;
610         }
611         return 0;
612
613 } /* connect_r() */
614
615 int receive_r(int sk, int once)
616 {
617         int recvsk = sk, i = 0, error = 0;
618         char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))];
619         struct iovec iov;
620         struct msghdr inmessage;
621
622         /* Initialize inmessage with enough space for DATA... */
623         memset(&inmessage, 0, sizeof(inmessage));
624         if ((iov.iov_base = malloc(REALLY_BIG)) == NULL) {
625                 fprintf(stderr, "\n\t\t*** malloc not enough memory!!! ***\n");
626                 exit(1);
627         }
628         iov.iov_len = REALLY_BIG;
629         inmessage.msg_iov = &iov;
630         inmessage.msg_iovlen = 1;
631         /* or a control message.  */
632         inmessage.msg_control = incmsg;
633         inmessage.msg_controllen = sizeof(incmsg);
634
635         /* Get the messages sent */
636         while (1) {
637
638                 if (recvsk == sk && socket_type == SOCK_STREAM &&
639                     role == SERVER)
640                         recvsk = accept_r(sk);
641
642                 DEBUG_PRINT(DEBUG_MIN, "\trecvmsg(sk=%d) ", sk);
643
644                 error = recvmsg(recvsk, &inmessage, MSG_WAITALL);
645                 if (error < 0 && error != EAGAIN) {
646                         if (errno == ENOTCONN && socket_type == SOCK_STREAM &&
647                             role == SERVER) {
648                                 printf("No association is present now!!\n");
649                                 close(recvsk);
650                                 recvsk = sk;
651                                 continue;
652                         }
653
654                         fprintf(stderr, "\n\t\t*** recvmsg: %s ***\n\n",
655                                         strerror(errno));
656                         fflush(stdout);
657                         if (do_exit) exit(1);
658                         else goto error_out;
659                 }
660                 else if (error == 0) {
661                         if (socket_type == SOCK_STREAM && role == SERVER) {
662                                 printf("No association is present now!!\n");
663                                 close(recvsk);
664                                 recvsk = sk;
665                                 continue;
666                         }
667                         printf("\n\t\trecvmsg() returned 0 !!!!\n");
668                         fflush(stdout);
669                 }
670
671                 if (print_message(recvsk, &inmessage, error) > 0)
672                         continue; /* got a notification... */
673
674                 inmessage.msg_control = incmsg;
675                 inmessage.msg_controllen = sizeof(incmsg);
676                 iov.iov_len = REALLY_BIG;
677                 i++;
678                 if (once)
679                         break;
680         }
681
682         if (recvsk != sk)
683                 close(recvsk);
684
685         free(iov.iov_base);
686         return 0;
687 error_out:
688         close(sk);
689         free(iov.iov_base);
690         return -1;
691
692 } /* receive_r () */
693
694 int next_order(int state, int pattern)
695 {
696         switch (pattern){
697         case ORDER_PATTERN_UNORDERED:
698                 state = 0;
699                 break;
700         case ORDER_PATTERN_ORDERED:
701                 state = 1;
702                 break;
703         case ORDER_PATTERN_ALTERNATE:
704                 state = state ? 0 : 1;
705                 break;
706         case ORDER_PATTERN_RANDOM:
707                 state = rand() % 2;
708                 break;
709         }
710
711         return state;
712 }
713
714 int next_stream(int state, int pattern)
715 {
716         switch (pattern){
717         case STREAM_PATTERN_RANDOM:
718                 state = rand() % (max_stream + 1);
719                 break;
720         case STREAM_PATTERN_SEQUENTIAL:
721                 state = state + 1;
722                 if (state > max_stream)
723                         state = 0;
724                 break;
725         }
726
727         return state;
728 }
729
730 int next_msg_size(int msg_cnt)
731 {
732         int msg_size;
733
734         if (size_arg) {
735                 msg_size = size_arg;
736         } else if (test_case < NCASES) {
737                 msg_size = msg_sizes[test_case][msg_cnt];
738         } else {
739                 msg_size = (rand() % max_msgsize) + 1;
740         }
741
742         return msg_size;
743
744 } /* next_msg_size() */
745
746 int next_assoc(int i, int state, int pattern)
747 {
748         int j;
749         int found = 0;
750         _assoc_state *as;
751
752
753         switch (pattern){
754         case ASSOC_PATTERN_RANDOM:
755                 state = rand() % tosend;
756                 break;
757         case ASSOC_PATTERN_SEQUENTIAL:
758                 state = state + 1;
759                 if (state >= tosend)
760                         state = 0;
761                 break;
762         }
763
764         as = poll_sks[i].assoc_state;
765         j = state;
766         do {
767                 if (as[j].msg_sent < repeat_count) {
768                         found = 1;
769                         break;
770                 }
771                 if (++j >= tosend) {
772                         j = 0;
773                 }
774         } while (j != state);
775
776         if (found) {
777                 return j;
778         } else {
779                 return -1;
780         }
781         
782 } /* next_assoc() */
783
784 int send_r(int sk, int stream, int order, int send_size, int assoc_i)
785 {
786         int error = 0;
787         struct msghdr outmsg;
788         struct iovec iov;
789         char *message = NULL;
790         int msglen = 0;
791         char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
792         struct cmsghdr *cmsg;
793         struct sctp_sndrcvinfo *sinfo;
794
795         if (send_size > 0) {
796                 message = build_msg(send_size);
797                 msglen = strlen(message) + 1;
798                 iov.iov_base = message;
799                 iov.iov_len = msglen;
800         }
801         else {
802                 if (do_exit) {
803                         exit(1);
804                 } else {
805                         goto error_out;
806                 }
807         }
808
809         outmsg.msg_name = &s_rem;
810         outmsg.msg_namelen = sizeof(struct sockaddr_storage);
811         outmsg.msg_iov = &iov;
812         outmsg.msg_iovlen = 1;
813         outmsg.msg_control = outcmsg;
814         outmsg.msg_controllen = sizeof(outcmsg);
815         outmsg.msg_flags = 0;
816
817         cmsg = CMSG_FIRSTHDR(&outmsg);
818         cmsg->cmsg_level = IPPROTO_SCTP;
819         cmsg->cmsg_type = SCTP_SNDRCV;
820         cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
821
822         outmsg.msg_controllen = cmsg->cmsg_len;
823         sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
824         memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
825         sinfo->sinfo_ppid = rand();
826         sinfo->sinfo_stream = stream;
827         sinfo->sinfo_flags = 0;
828         if (!order)
829                 sinfo->sinfo_flags = SCTP_UNORDERED;
830
831         DEBUG_PRINT(DEBUG_MIN, "\tsendmsg(sk=%d, assoc=%d) %4d bytes.\n",
832                     sk, assoc_i, send_size);
833         DEBUG_PRINT(DEBUG_MAX, "\t  SNDRCV");
834         if (DEBUG_MAX == debug_level) {
835                 printf("(stream=%u ",   sinfo->sinfo_stream);
836                 printf("flags=0x%x ",   sinfo->sinfo_flags);
837                 printf("ppid=%u\n",     sinfo->sinfo_ppid);
838         }
839
840         /* Send to our neighbor.  */
841         error = sendmsg(sk, &outmsg, MSG_WAITALL);
842         if (error != msglen) {
843                 fprintf(stderr, "\n\t\t*** sendmsg: %s ***\n\n",
844                         strerror(errno));
845                 fflush(stdout);
846         
847                 if (do_exit) {
848                         exit(1);
849                 } else {
850                         if (!drain)
851                                 goto error_out;
852                 }
853         }
854
855         if (send_size > 0) free(message);
856         return 0;
857 error_out:
858         if (send_size > 0) free(message);
859         return -1;
860
861 } /* send_r() */
862
863 int close_r(int sk)
864 {
865         int error = 0;
866         
867         DEBUG_PRINT(DEBUG_MIN, "\tclose(sk=%d)\n",sk);
868
869         error = close(sk);
870         if (error != 0) {
871                 if (do_exit) {
872                         fprintf(stderr, "\n\n\t\t*** close: %s ***\n\n",
873                                 strerror(errno));
874                         exit(1);
875                 } else {
876                         return -1;
877                 }
878         }
879         fflush(stdout);
880         return 0;
881
882 } /* close_r() */
883
884 void
885 server(int sk)
886 {
887         if (max_msgsize > DEFAULT_MAX_WINDOW) {
888                 if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, &max_msgsize,
889                                sizeof(max_msgsize)) < 0) {
890                         perror("setsockopt(SO_RCVBUF)");
891                         exit(1);
892                 }       
893         }
894
895         receive_r(sk, 0);
896
897 } /* server() */
898
899 void
900 client(int sk)
901 {
902         int msg_size;
903         int i;
904
905         for (i = 0; i < msg_cnt; i++) {
906
907                 msg_size = next_msg_size(i);
908                 order_state = next_order(order_state, order_pattern);
909                 stream_state = next_stream(stream_state, stream_pattern);
910
911                 if (send_r(sk, stream_state, order_state, msg_size, 0) < 0) {
912                         close(sk);
913                         break;
914                 }
915                 /* The sender is echoing so do discard the echoed data. */
916                 if (drain) {
917                         receive_r(sk, 1);
918                 }
919         }
920 } /* client() */
921
922 void
923 mixed_mode_test(void)
924 {
925         int error, i, j, max_fd, sks, size;
926         int assoc_i, n_msg_size, n_order, n_stream;
927         int done = 0;
928         fd_set *ibitsp = NULL, *obitsp = NULL, *xbitsp = NULL;
929         char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))];
930         struct iovec iov;
931         struct msghdr inmessage;
932         _assoc_state *as;
933
934         
935         /* Set up the listeners.  If listeners is 0, set up one socket for
936          * transmitting only.
937          */
938         iov.iov_base = NULL;
939         max_fd = -1;
940         sks = (0 == listeners) ? 1 : listeners;
941         memset(poll_sks, 0, sizeof(sks * sizeof(_poll_sks)));
942
943         for (i = 0; i < sks; i++) {
944                 poll_sks[i].sk = socket_r();
945
946                 if (s_loc.ss_family == AF_INET6)
947                         ( (struct sockaddr_in6 *)&s_loc)->sin6_port =
948                                 htons(local_port + i);
949                 else
950                         ( (struct sockaddr_in *)&s_loc)->sin_port =
951                                 htons(local_port + i);
952
953                 bind_r(poll_sks[i].sk, &s_loc);
954                 if (listeners) {
955                         listen_r(poll_sks[i].sk, 100);
956                 }
957                 if (max_msgsize > DEFAULT_MAX_WINDOW) {
958                         if (setsockopt(poll_sks[i].sk, SOL_SOCKET, SO_RCVBUF,
959                                 &max_msgsize, sizeof(max_msgsize)) < 0) {
960                                 perror("setsockopt(SO_RCVBUF)");
961                                 exit(1);
962                         }
963                 }       
964
965                 if (tosend) {
966                         if ((poll_sks[i].assoc_state = (_assoc_state *)malloc(
967                                 sizeof(_assoc_state) * tosend)) == NULL) {
968                                 printf("Can't allocate memory.\n");
969                                 goto clean_up;
970                         }
971                         memset(poll_sks[i].assoc_state, 0,
972                                 sizeof(_assoc_state) * tosend);
973                 }
974
975                 if (poll_sks[i].sk > max_fd) {
976                         max_fd = poll_sks[i].sk;
977                 }
978         }
979
980         size = howmany(max_fd + 1, NFDBITS) * sizeof(fd_mask);
981         if ((ibitsp = (fd_set *)malloc(size)) == NULL) {
982                 printf("Can't allocate memory.\n");
983                 goto clean_up;
984         }
985         if ((obitsp = (fd_set *)malloc(size)) == NULL) {
986                 printf("Can't allocate memory.\n");
987                 goto clean_up;
988         }
989         if ((xbitsp = (fd_set *)malloc(size)) == NULL) {
990                 printf("Can't allocate memory.\n");
991                 goto clean_up;
992         }
993
994         memset(ibitsp, 0, size);
995         memset(obitsp, 0, size);
996         memset(xbitsp, 0, size);
997
998
999         /* Initialize inmessage with enough space for DATA... */
1000         memset(&inmessage, 0, sizeof(inmessage));
1001         if ((iov.iov_base = malloc(REALLY_BIG)) == NULL) {
1002                 fprintf(stderr, "\n\t\t*** malloc not enough memory!!! ***\n");
1003                 goto clean_up;
1004         }
1005         iov.iov_len = REALLY_BIG;
1006         inmessage.msg_iov = &iov;
1007         inmessage.msg_iovlen = 1;
1008         /* or a control message.  */
1009         inmessage.msg_control = incmsg;
1010         inmessage.msg_controllen = sizeof(incmsg);
1011
1012         /* Set up the remote port number per association for output.  */
1013         for (i = 0; i < sks; i++) {
1014                 as = poll_sks[i].assoc_state;
1015                 for (j = 0; j < tosend; j++) {
1016                         as[j].rem_port = remote_port + j;
1017                 }
1018         }
1019
1020         while (!done) {
1021
1022                 for (i = 0; i < sks; i++) {
1023                         FD_SET(poll_sks[i].sk, ibitsp);
1024                         FD_SET(poll_sks[i].sk, obitsp);
1025                         FD_SET(poll_sks[i].sk, xbitsp);
1026                 }
1027                 if ((error = select(max_fd + 1, ibitsp, obitsp, xbitsp,
1028                         (struct timeval *)0)) < 0) {
1029                         fprintf(stderr, "\n\t\t*** select() failed ");
1030                         fprintf(stderr, "with error: %s\n\n",
1031                                 strerror(errno));
1032                         fflush(stdout);
1033                         goto clean_up;
1034                 }
1035                 
1036                 for (i = 0; i < sks; i++) {
1037                         /* Is there anything to read from the socket?  */
1038                         if (listeners && FD_ISSET(poll_sks[i].sk, ibitsp)) {
1039
1040                                 FD_CLR(poll_sks[i].sk, ibitsp);
1041                                 error = recvmsg(poll_sks[i].sk, &inmessage,
1042                                         MSG_WAITALL);
1043                                 if (error < 0) {
1044                                         fprintf(stderr,
1045                                                 "\n\t\t*** recvmsg: %s ***\n\n",
1046                                                 strerror(errno));
1047                                         fflush(stdout);
1048                                         goto clean_up;
1049                                 }
1050                                 else if (error == 0) {
1051                                         printf("\n\t\trecvmsg() returned ");
1052                                         printf("0 !!!!\n");
1053                                         fflush(stdout);
1054                                 }
1055
1056                                 print_message(poll_sks[i].sk, &inmessage,
1057                                         error);
1058
1059                                 inmessage.msg_control = incmsg;
1060                                 inmessage.msg_controllen = sizeof(incmsg);
1061                                 iov.iov_len = REALLY_BIG;
1062                         }
1063                         
1064                         /* Is this socket writeable?  */
1065                         if (tosend && FD_ISSET(poll_sks[i].sk, obitsp)) {
1066
1067                                 FD_CLR(poll_sks[i].sk, obitsp);
1068
1069                                 /* Pick an association.  */
1070                                 assoc_i = next_assoc(i, poll_sks[i].assoc_i,
1071                                                 assoc_pattern);
1072                                 if (assoc_i < 0) {
1073                                         /* No work to do on any associations.
1074                                          * We are probably done. */
1075                                         if (!listeners) {
1076                                                 done = 1;
1077                                         }
1078                                         continue;
1079                                 }
1080                                 poll_sks[i].assoc_i = assoc_i;
1081
1082                                 as = poll_sks[i].assoc_state;
1083                                 n_msg_size = next_msg_size(as[assoc_i].msg_cnt);
1084                                 n_order = as[assoc_i].order_state =
1085                                         next_order(as[assoc_i].order_state,
1086                                         order_pattern);
1087                                 n_stream = as[assoc_i].stream_state =
1088                                         next_stream(as[assoc_i].stream_state,
1089                                         stream_pattern);
1090
1091                                 /* Set the destination port.  */
1092                                 if (s_rem.ss_family == AF_INET6)
1093                                         ( (struct sockaddr_in6 *)&s_rem)->
1094                                                 sin6_port =
1095                                                 htons(as[assoc_i].rem_port);
1096                                 else
1097                                         ( (struct sockaddr_in *)&s_rem)->
1098                                                 sin_port =
1099                                                 htons(as[assoc_i].rem_port);
1100
1101                                 /* Send a message thru the association.  */
1102                                 if (send_r(poll_sks[i].sk, n_stream, n_order,
1103                                         n_msg_size, assoc_i) < 0) {
1104                                         /* Don't increment counter if there
1105                                          * is a problem of sending.
1106                                          */
1107                                         continue;
1108                                 }
1109
1110                                 /* Increment counters. */
1111                                 if (++as[assoc_i].msg_cnt >= MSG_CNT) {
1112                                         as[assoc_i].msg_cnt = 0;
1113                                 }
1114                                 if (++as[assoc_i].msg_sent >=
1115                                         repeat_count) {
1116                                         fprintf(stderr, "Association #%d in ",
1117                                                 assoc_i);
1118                                         fprintf(stderr, "sk=%d has ",
1119                                                 poll_sks[i].sk);
1120                                         fprintf(stderr, "completed %d msg as ",
1121                                                 as[assoc_i].msg_sent);
1122                                         fprintf(stderr, "cycle %d.\n",
1123                                                 ++as[assoc_i].cycle);
1124
1125                                         /* In the mixed mode, -x not only
1126                                          * specify the longer repeat cycle,
1127                                          * but it also mean to run the test
1128                                          * forever.
1129                                          */
1130                                         if (xflag) {
1131                                                 as[assoc_i].msg_sent = 0;
1132                                         }
1133
1134                                 }
1135
1136                         }
1137                 }
1138         }
1139
1140 clean_up:
1141         for (i = 0; i < sks; i++) {
1142                 close(poll_sks[i].sk);
1143                 if (poll_sks[i].assoc_state) {
1144                         free(poll_sks[i].assoc_state);
1145                 }
1146         }
1147
1148         if (ibitsp) free(ibitsp);
1149         if (obitsp) free(obitsp);
1150         if (xbitsp) free(xbitsp);
1151
1152         if (iov.iov_base) free(iov.iov_base);
1153
1154 } /* mixed_mode_test() */
1155
1156 void start_test(int role)
1157 {
1158         int sk;
1159         int i = 0;
1160         
1161         DEBUG_PRINT(DEBUG_NONE, "\nStarting tests...\n");
1162
1163         repeat_count = repeat;
1164
1165
1166         if (MIXED == role) {
1167                 repeat_count = repeat_count * msg_cnt;  /* Repeat per assoc. */
1168                 mixed_mode_test();
1169                 return;
1170         }
1171
1172         sk = socket_r();
1173         bind_r(sk, &s_loc);
1174
1175         if (role == SERVER) {
1176                 listen_r(sk, 100);
1177         } else if (socket_type == SOCK_STREAM) {
1178                 connect_r(sk, (struct sockaddr *)&s_rem, r_len);
1179         }
1180
1181         if (!debug_level) {
1182                 printf("     ");
1183         }
1184
1185         for(i = 0; i < repeat_count; i++) {
1186                 
1187                 if (role == SERVER) {
1188                         DEBUG_PRINT(DEBUG_NONE,
1189                                     "Server: Receiving packets.\n");
1190                         server(sk);
1191                 } else {
1192                         DEBUG_PRINT(DEBUG_NONE,
1193                                     "Client: Sending packets.(%d/%d)\n",
1194                                     i+1, repeat_count);
1195                         client(sk);
1196                 }
1197
1198                 fflush(stdout);
1199         }
1200
1201         close_r(sk);
1202
1203 } /* start_test() */
1204
1205 int
1206 main(int argc, char *argv[])
1207 {
1208         int c;
1209         char *interface = NULL;
1210         struct sockaddr_in *t_addr;
1211         struct sockaddr_in6 *t_addr6;
1212         
1213         /* Parse the arguments.  */
1214         while ((c = getopt(argc, argv, ":H:L:P:S:a:h:p:c:d:lm:sx:X:o:t:M:r:w:Di:T")) >= 0 ) {
1215
1216                 switch (c) {
1217                 case 'H':
1218                         local_host = optarg;
1219                         break;
1220                 case 'L':
1221                         role = MIXED;
1222                         listeners = atoi(optarg);
1223                         if (listeners > MAX_POLL_SKS) {
1224                                 usage(argv[0]);
1225                                 exit(1);
1226                         }
1227                         break;
1228                 case 'P':
1229                         local_port = atoi(optarg);
1230                         break;
1231                 case 'S':
1232                         role = MIXED;
1233                         tosend = atoi(optarg);
1234                         if (tosend > MAX_POLL_SKS) {
1235                                 usage(argv[0]);
1236                                 exit(1);
1237                         }
1238                         break;
1239                 case 'a':
1240                         assoc_pattern = atoi(optarg);
1241                         if (assoc_pattern <  ASSOC_PATTERN_SEQUENTIAL
1242                             || assoc_pattern > ASSOC_PATTERN_RANDOM ) {
1243                                 usage(argv[0]);
1244                                 exit(1);
1245                         }
1246                         break;
1247                 case 'h':
1248                         remote_host = optarg;
1249                         break;
1250                 case 'D':
1251                         drain = 1;
1252                         do_exit = 0;
1253                         break;
1254                 case 'p':
1255                         remote_port = atoi(optarg);
1256                         break;
1257                 case 's':
1258                         if (role != NOT_DEFINED) {
1259                                 printf("%s: only -s or -l\n", argv[0]);
1260                                 usage(argv[0]);
1261                                 exit(1);
1262                         }
1263                         role = CLIENT;
1264                         break;
1265                 case 'l':
1266                         if (role != NOT_DEFINED) {
1267                                 printf("%s: only -s or -l\n", argv[0]);
1268                                 usage(argv[0]);
1269                                 exit(1);
1270                         }
1271                         role = SERVER;
1272                         break;
1273                 case 'd':
1274                         debug_level = atoi(optarg);
1275                         if (debug_level < DEBUG_NONE
1276                             || debug_level > DEBUG_MAX) {
1277                                 usage(argv[0]);
1278                                 exit(1);
1279                         }
1280                         break;
1281                 case 'x':
1282                         repeat = atoi(optarg);
1283                         if (!repeat) {
1284                                 xflag = 1;
1285                                 repeat = BIG_REPEAT;
1286                         }
1287                         break;
1288                 case 'X':
1289                         msg_cnt = atoi(optarg);
1290                         if ((msg_cnt <= 0) || (msg_cnt > MSG_CNT)) {
1291                                 usage(argv[0]);
1292                                 exit(1);
1293                         }
1294                         break;
1295                 case 'c':
1296                         test_case = atoi(optarg);
1297                         if (test_case > NCASES) {
1298                                 usage(argv[0]);
1299                                 exit(1);
1300                         }
1301                         if (test_case < 0) {
1302                                 size_arg = -test_case;
1303                         }
1304                         
1305                         break;
1306                 case 'o':
1307                         order_pattern = atoi(optarg);
1308                         if (order_pattern <  ORDER_PATTERN_UNORDERED
1309                             || order_pattern  > ORDER_PATTERN_RANDOM ) {
1310                                 usage(argv[0]);
1311                                 exit(1);
1312                         }
1313                         break;
1314                 case 't':
1315                         stream_pattern = atoi(optarg);
1316                         if (stream_pattern <  STREAM_PATTERN_SEQUENTIAL
1317                             || stream_pattern > STREAM_PATTERN_RANDOM ) {
1318                                 usage(argv[0]);
1319                                 exit(1);
1320                         }
1321                         break;
1322                 case 'M':
1323                         max_stream = atoi(optarg);
1324                         if (max_stream <  0
1325                             || max_stream >= (1<<16)) {
1326                                 usage(argv[0]);
1327                                 exit(1);
1328                         }
1329                         break;
1330                 case 'r':
1331                         seed = atoi(optarg);
1332                         break;
1333                 case 'm':
1334                         max_msgsize = atoi(optarg);
1335 #if 0
1336                         if ((max_msgsize < DEFAULT_MIN_WINDOW) ||
1337                             (max_msgsize > 65515)) {
1338                                 usage(argv[0]);
1339                                 exit(1);
1340                         }
1341 #endif
1342                         break;
1343                 case 'i':
1344                         interface = optarg;
1345                         break;
1346                 case 'T':
1347                         socket_type = SOCK_STREAM;
1348                         break;
1349                 case '?':
1350                 default:
1351                         usage(argv[0]);
1352                         exit(0);
1353                 }
1354         } /* while() */
1355
1356         if (NOT_DEFINED == role) {
1357                 usage(argv[0]);
1358                 exit(1);
1359         }
1360
1361
1362         if (SERVER == role && NULL == local_host && remote_host != NULL) {
1363                 fprintf (stderr, "%s: Server needs local address, "
1364                          "not remote address\n", argv[0]);
1365                 usage(argv[0]);
1366                 exit(1);
1367         }
1368         if (CLIENT == role && NULL == remote_host) {
1369                 fprintf (stderr, "%s: Client needs at least remote address "
1370                          "& port\n", argv[0]);
1371                 usage(argv[0]);
1372                 exit(1);
1373         }
1374         if (MIXED == role) {
1375                 if (listeners && NULL == local_host) {
1376                         fprintf (stderr, "%s: Servers need local address\n",
1377                                 argv[0]);
1378                         usage(argv[0]);
1379                         exit(1);
1380                 }
1381                 if (tosend && NULL == remote_host) {
1382                         fprintf (stderr, "%s: Clients need remote address ",
1383                                 argv[0]);
1384                         fprintf (stderr, "& port\n");
1385                         usage(argv[0]);
1386                         exit(1);
1387                 }
1388         }
1389
1390         if (optind < argc) {
1391                 fprintf(stderr, "%s: non-option arguments are illegal: ",
1392                         argv[0]);
1393                 while (optind < argc)
1394                         fprintf(stderr, "%s ", argv[optind++]);
1395                 fprintf (stderr, "\n");
1396                 usage(argv[0]);
1397                 exit(1);
1398         }
1399
1400         if (remote_host != NULL && remote_port != 0) {
1401                 struct addrinfo *res;
1402                 int error;
1403                 char *host_s, *serv_s;
1404
1405                 if ((host_s = malloc(NI_MAXHOST)) == NULL) {
1406                         fprintf(stderr, "\n*** host_s malloc failed!!! ***\n");
1407                         exit(1);
1408                 }
1409                 if ((serv_s = malloc(NI_MAXSERV)) == NULL) {
1410                         fprintf(stderr, "\n*** serv_s malloc failed!!! ***\n");
1411                         exit(1);
1412                 }
1413
1414                 error = getaddrinfo(remote_host, 0, NULL, &res);
1415                 if (error) {
1416                         printf("%s.\n", gai_strerror(error));
1417                         usage(argv[0]);
1418                         exit(1);
1419                 }
1420
1421                 switch (res->ai_family) {
1422                         case AF_INET:
1423                                 t_addr = (struct sockaddr_in *)&s_rem;
1424
1425                                 t_addr->sin_family = AF_INET;
1426                                 t_addr->sin_port = htons(remote_port);
1427                                 inet_pton(AF_INET, remote_host,
1428                                               &t_addr->sin_addr);
1429
1430                                 r_len = sizeof (struct sockaddr_in);
1431 #ifdef __FreeBSD__
1432                                 t_addr->sin_len = r_len;
1433 #endif
1434                                 break;
1435                         case AF_INET6:
1436
1437                                 t_addr6 = (struct sockaddr_in6 *)&s_rem;
1438                                 
1439                                 if (interface)
1440                                         t_addr6->sin6_scope_id =
1441                                                 if_nametoindex(interface);
1442                                 t_addr6->sin6_family = AF_INET6;
1443                                 t_addr6->sin6_port = htons(remote_port);
1444                                 inet_pton(AF_INET6, remote_host,
1445                                               &t_addr6->sin6_addr);
1446
1447                                 r_len = sizeof (struct sockaddr_in6);
1448
1449 #ifdef __FreeBSD__
1450                                 t_addr6->sin6_len = r_len;
1451 #endif
1452                                 break;
1453                 }
1454
1455                 getnameinfo((struct sockaddr *)&s_rem, r_len, host_s,
1456                             NI_MAXHOST, serv_s, NI_MAXSERV, NI_NUMERICHOST);
1457                         
1458
1459                 DEBUG_PRINT(DEBUG_MAX, "remote:addr=%s, port=%s, family=%d\n",
1460                             host_s, serv_s, res->ai_family);
1461         }
1462
1463         if (local_host != NULL) {
1464                 struct addrinfo *res;
1465                 int error;
1466                 char *host_s, *serv_s;
1467                 struct sockaddr_in *t_addr;
1468                 struct sockaddr_in6 *t_addr6;
1469
1470                 if ((host_s = malloc(NI_MAXHOST)) == NULL) {
1471                         fprintf(stderr, "\n*** host_s malloc failed!!! ***\n");
1472                         exit(1);
1473                 }
1474                 if ((serv_s = malloc(NI_MAXSERV)) == NULL) {
1475                         fprintf(stderr, "\n*** serv_s malloc failed!!! ***\n");
1476                         exit(1);
1477                 }
1478
1479                 if (strcmp(local_host, "0") == 0)
1480                         local_host = "0.0.0.0";
1481
1482                 error = getaddrinfo(local_host, 0, NULL, &res);
1483                 if (error) {
1484                         printf("%s.\n", gai_strerror(error));
1485                         usage(argv[0]);
1486                         exit(1);
1487                 }
1488
1489                         
1490                 switch (res->ai_family) {
1491                         case AF_INET:
1492                                 t_addr = (struct sockaddr_in *)&s_loc;
1493                                 t_addr->sin_family = AF_INET;
1494                                 t_addr->sin_port = htons(local_port);
1495                                 inet_pton(AF_INET, local_host,
1496                                               &t_addr->sin_addr);
1497
1498                                 l_len = sizeof (struct sockaddr_in);
1499 #ifdef __FreeBSD__
1500                                 t_addr->sin_len = l_len;
1501 #endif
1502                                 break;
1503                         case AF_INET6:
1504                                 t_addr6 = (struct sockaddr_in6 *)&s_loc;
1505
1506                                 if (interface)
1507                                         t_addr6->sin6_scope_id =
1508                                                 if_nametoindex(interface);
1509                                 t_addr6->sin6_family = AF_INET6;
1510                                 t_addr6->sin6_port = htons(local_port);
1511
1512                                 inet_pton(AF_INET6, local_host,
1513                                               &t_addr6->sin6_addr);
1514
1515                                 l_len = sizeof (struct sockaddr_in6);
1516
1517 #ifdef __FreeBSD__
1518                                 t_addr6->sin6_len = l_len;
1519 #endif
1520                                 break;
1521                 }
1522
1523                 error = getnameinfo((struct sockaddr *)&s_loc, l_len, host_s,
1524                             NI_MAXHOST, serv_s, NI_MAXSERV, NI_NUMERICHOST);
1525
1526                 if (error)
1527                         printf("%s..\n", gai_strerror(error));
1528
1529                 DEBUG_PRINT(DEBUG_MAX, "local:addr=%s, port=%s, family=%d\n",
1530                             host_s, serv_s, res->ai_family);
1531         }
1532
1533
1534         /* A half-hearted attempt to seed rand() */
1535         if (seed == 0 ) {
1536                 seed = time(0);
1537                 DEBUG_PRINT(DEBUG_NONE, "seed = %d\n", seed);   
1538         }
1539         
1540         srand(seed);
1541
1542         /* Let the testing begin. */
1543         start_test(role);
1544
1545         return 0;
1546
1547 } /*  main() */