⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sctp_test.c

📁 SCTP 协议实现源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* SCTP kernel Implementation * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999 Cisco * Copyright (c) 1999, 2000, 2001 Motorola * Copyright (c) 2001-2002 Nokia * Copyright (c) 2001 La Monte H.P. Yarroll * * This is a userspace test application for the SCTP kernel  * implementation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied *                 ^^^^^^^^^^^^^^^^^^^^^^^^ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING.  If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any bug reports or fixes you make to the * email address(es): *    lksctp developers <lksctp-developers@lists.sourceforge.net> * * Or submit a bug report through the following website: *    http://www.sf.net/projects/lksctp * * Written or modified by: *   Hui Huang         <hui.huang@nokia.com> *   Sridhar Samudrala <samudrala@us.ibm.com> *   Jon Grimm         <jgrimm@us.ibm.com> *   Daisy Chang       <daisyc@us.ibm.com> *   Ryan Layer	       <rmlayer@us.ibm.com> */#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/uio.h>#include <netinet/in.h>#include <sys/errno.h>#include <errno.h>#include <netinet/sctp.h>#include <string.h>#include <arpa/inet.h>#include <sys/wait.h>#include <sys/param.h>#include <fcntl.h>#include <netdb.h>#include <net/if.h>#include <sys/resource.h>#define REALLY_BIG 65536#define SERVER 		0#define CLIENT 		1#define MIXED 		2#define NOT_DEFINED	666#define REPEAT 		10#define BIG_REPEAT	1000000#define MAX_BIND_RETRYS 10#define BODYSIZE	10#define MSG_CNT		10	/* If this is changed the msg_sizes array				   needs to be modified accordingly.  */#define DEFAULT_MAX_WINDOW 32768#define DEFAULT_MIN_WINDOW 1500#define DEBUG_NONE	0#define DEBUG_MIN	1#define DEBUG_MAX	2#define STREAM_PATTERN_SEQUENTIAL 0#define STREAM_PATTERN_RANDOM     1#define ORDER_PATTERN_UNORDERED   0#define ORDER_PATTERN_ORDERED     1#define ORDER_PATTERN_ALTERNATE   2#define ORDER_PATTERN_RANDOM      3#define ASSOC_PATTERN_SEQUENTIAL 0#define ASSOC_PATTERN_RANDOM     1#define NCASES 6#define MAX_POLL_SKS 256#define DEBUG_PRINT(level, print_this...)	\{						\	if (debug_level >= level) { 		\		fprintf(stdout, print_this); 	\		fflush(stdout); 		\	}					\} /* DEBUG_PRINT *//* Convenience structure to determine space needed for cmsg. */typedef union {        struct sctp_initmsg init;        struct sctp_sndrcvinfo sndrcvinfo;} _sctp_cmsg_data_t;#ifdef __FreeBSD__typedef union {        int                    raw;        struct sctp_initmsg     init;        struct sctp_sndrcvinfo  sndrcv;} sctp_cmsg_data_t;#endif#define CMSG_SPACE_INITMSG (CMSG_SPACE(sizeof(struct sctp_initmsg)))#define CMSG_SPACE_SNDRCV (CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)))typedef struct {	int rem_port;        int order_state;        int stream_state;	int msg_cnt;	int msg_sent;	int cycle;} _assoc_state;typedef struct {        int sk;        int assoc_i;	_assoc_state *assoc_state;} _poll_sks;char *local_host = NULL;int local_port = 0;char *remote_host = NULL;int remote_port = 0;/* struct sockaddr_in s_rem, s_loc; */struct sockaddr_storage s_rem, s_loc;int r_len, l_len;int test_case = 0;int size_arg = 0;int xflag = 0;int debug_level = DEBUG_MAX;int do_exit = 1;int stream_pattern = STREAM_PATTERN_SEQUENTIAL;int stream_state = 0;int order_pattern = ORDER_PATTERN_UNORDERED;int order_state = 0;int max_stream = 0;int seed = 0;int max_msgsize = DEFAULT_MAX_WINDOW;int assoc_pattern = ASSOC_PATTERN_SEQUENTIAL;int repeat_count = 0;int listeners = 0;int tosend = 0;_poll_sks poll_sks[MAX_POLL_SKS];int repeat = REPEAT;int msg_cnt = MSG_CNT;int drain = 0;unsigned char msg[] = "012345678901234567890123456789012345678901234567890";static int msg_sizes[NCASES][MSG_CNT] =	{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},	 {1452, 2904, 4356, 1452, 2904, 4356, 1452, 2904, 4356, 1452},	 {1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453},	 {1, 1453, 32768, 1, 1453, 32768, 1, 1453, 32768, 1},	 {1, 1000, 2000, 3000, 5000, 10000, 15000, 20000, 25000, 32768},	 {32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768},	};static const char *sac_state_tbl[] = {	"COMMUNICATION_UP",	"COMMUNICATION_LOST",	"RESTART",	"SHUTDOWN_COMPLETE",	"CANT_START_ASSOCICATION"};void usage(char *argv0){	fprintf(stderr, "\nusage:\n");	fprintf(stderr, "  server:\n");	fprintf(stderr, "  %8s -H local-addr -P local-port -l [-d level] [-x]\n"			"\t      [-L num-ports] [-S num-ports]\n"			"\t      [-a assoc-pattern]\n"			"\t      [-i interface]\n",		argv0);	fprintf(stderr, "\n");	fprintf(stderr, "  client:\n");	fprintf(stderr, "  %8s -H local-addr -P local-port -h remote-addr\n"		"\t      -p remote-port -s [-c case ] [-d level]\n"		"\t      [-x repeat] [-o order-pattern] ream-pattern]\n"		"\t      [-M max-stream] [-r rand-seed]\n"		"\t      [-m max-msgsize]\n"		"\t      [-L num-ports] [-S num-ports]\n"		"\t      [-a assoc-pattern]\n"		"\t      [-i interface]\n",		argv0);	fprintf(stderr, "\n");	fprintf(stderr, "\t-a assoc_pattern in the mixed mode\n");	fprintf(stderr, "\t   0 = sequential ascending(default)\n");	fprintf(stderr, "\t   1 = random\n");	fprintf(stderr, "\t-d debug\n");	fprintf(stderr, "\t   0 = none\n");	fprintf(stderr, "\t   1 = min(default)\n");	fprintf(stderr, "\t   2 = max\n");	fprintf(stderr, "\t-c testcase\n");	fprintf(stderr, "\t   0 = 1 byte packets.\n");	fprintf(stderr, "\t   1 = 1452 byte packets.\n");	fprintf(stderr, "\t       (fragmentation point for an i/f with ");	fprintf(stderr, "1500 as mtu.)\n");	fprintf(stderr, "\t   2 = 1453 byte packets.\n");	fprintf(stderr, "\t       (min. size at which fragmentation occurs\n");	fprintf(stderr, "\t        for an i/f with 1500 as mtu.)\n");	fprintf(stderr, "\t   3 = Sequence of 1, 1453, 32768 byte packets.\n");	fprintf(stderr, "\t   4 = Sequence of following size packets.\n");	fprintf(stderr, "\t       (1, 1000, 2000, 3000, 5000, 10000,");	fprintf(stderr, "15000, 20000, 25000, 32768)\n");	fprintf(stderr, "\t   5 = 32768 byte packets.\n");	fprintf(stderr, "\t       (default max receive window size.)\n");	fprintf(stderr, "\t   6 = random size packets.\n");	fprintf(stderr, "\t   -ve value = Packets of specifed size.\n");	fprintf(stderr, "\t-m msgsize(1500-65515, default value 32768)\n");	fprintf(stderr, "\t-x number of repeats\n");	fprintf(stderr, "\t-o order-pattern\n");	fprintf(stderr, "\t   0 = all unordered(default) \n");	fprintf(stderr, "\t   1 = all ordered \n");	fprintf(stderr, "\t   2 = alternating \n");        fprintf(stderr, "\t   3 = random\n");	fprintf(stderr, "\t-t stream-pattern\n");	fprintf(stderr, "\t   0 = sequential ascending(default)\n");	fprintf(stderr, "\t   1 = random\n");	fprintf(stderr, "\t-M max-stream (default value 0)\n");	fprintf(stderr, "\t-r seed (default 0, use time())\n");	fprintf(stderr, "\t-L num-ports (default value 0). Run the mixed mode\n");	fprintf(stderr, "\t-S num-ports (default value 0). Run the mixed mode\n");	fprintf(stderr, "\t-D drain. If in client mode do a read following send.\n");	fprintf(stderr, "\n");	fflush(stderr);} /* usage() */void *build_msg(int len){	int i = len - 1;	int n;	char *msg_buf, *p;	msg_buf = malloc(len);	if (NULL == msg_buf) {		fprintf(stderr, "\n\t\t*** malloc not enough memory!!! ***\n");		exit(1);	}	p = msg_buf;	do {		n = ((i > 50)?50:i);		memcpy(p, msg, ((i > 50)?50:i));		p += n;		i -= n;	} while (i > 0);	msg_buf[len-1] = '\0';	return(msg_buf);} /* build_msg() */static intprint_cmsg(int type, sctp_cmsg_data_t *data){        switch(type) {        case SCTP_INIT:		DEBUG_PRINT(DEBUG_MAX, "\tINIT\n");		if (DEBUG_MAX == debug_level) {			printf("\t\tsinit_num_ostreams=%d ",			       data->init.sinit_num_ostreams);                	printf("sinit_max_instreams=%d ",			       data->init.sinit_max_instreams);	                printf("sinit_max_attempts=%d ",			       data->init.sinit_max_attempts);        	        printf("sinit_max_init_timeo=%d\n",			       data->init.sinit_max_init_timeo);		}		break;        case SCTP_SNDRCV:		DEBUG_PRINT(DEBUG_MAX, "\t  SNDRCV");		if (DEBUG_MAX == debug_level) {        	        printf("(stream=%u ", 	data->sndrcv.sinfo_stream);                	printf("ssn=%u ", 	data->sndrcv.sinfo_ssn);			printf("tsn=%u ", 	data->sndrcv.sinfo_tsn);	                printf("flags=0x%x ",	data->sndrcv.sinfo_flags);        	        printf("ppid=%u\n",	data->sndrcv.sinfo_ppid);			printf("cumtsn=%u\n",   data->sndrcv.sinfo_cumtsn);                }		break;         default:		DEBUG_PRINT(DEBUG_MIN, "\tUnknown type: %d\n", type);                break;        }	fflush(stdout);        return 0;} /* print_cmsg() *//* This function prints the message. */static intprint_message(const int sk, struct msghdr *msg, size_t msg_len) {	struct cmsghdr *scmsg;	sctp_cmsg_data_t *data;        int i;        if (!(MSG_NOTIFICATION & msg->msg_flags)) {                int index = 0;		DEBUG_PRINT(DEBUG_MIN, "Data %d bytes.", msg_len);		DEBUG_PRINT(DEBUG_MAX, " First %d bytes: ",				    (msg_len < BODYSIZE)?msg_len:BODYSIZE);                /* Make sure that everything is printable and that we                 * are NUL terminated...                 */		while ( msg_len > 0 ) {			char *text, tmptext[BODYSIZE];			int len;			memset(tmptext, 0x0, BODYSIZE);			text = msg->msg_iov[index].iov_base;			len = msg->msg_iov[index].iov_len;			if (msg_len == 1 && text[0] == 0) {				DEBUG_PRINT(DEBUG_MIN, "<empty> text[0]=%d",					    text[0]);				break;			}			if ( len > msg_len ) {				/* text[(len = msg_len) - 1] = '\0'; */				text[(len = msg_len)] = '\0';			}			if ( (msg_len -= len) > 0 ) { index++; }			for (i = 0; i < len - 1; ++i) {				if (!isprint(text[i])) text[i] = '.';			} 			strncpy(tmptext, text, BODYSIZE); 			tmptext[BODYSIZE-1] = '\0';			DEBUG_PRINT(DEBUG_MAX, "%s", tmptext);                }                DEBUG_PRINT(DEBUG_MIN, "\n");                fflush(stdout);        }  else { /* if(we have notification) */		struct sctp_assoc_change *sac;		struct sctp_send_failed *ssf;		struct sctp_paddr_change *spc;		struct sctp_remote_error *sre;		union sctp_notification *snp;		char addrbuf[INET6_ADDRSTRLEN];		const char *ap;		struct sockaddr_in *sin;		struct sockaddr_in6 *sin6;		int index = 0;		snp = (union sctp_notification *)msg->msg_iov[index].iov_base;		DEBUG_PRINT(DEBUG_MIN, "Notification:");        			switch (snp->sn_header.sn_type) {			case SCTP_ASSOC_CHANGE:				sac = &snp->sn_assoc_change;				DEBUG_PRINT(DEBUG_MIN,					    " SCTP_ASSOC_CHANGE(%s)\n",					    sac_state_tbl[sac->sac_state]);				DEBUG_PRINT(DEBUG_MAX,					    "\t\t(assoc_change: state=%hu, "					    "error=%hu, instr=%hu "					    "outstr=%hu)\n",					    sac->sac_state, sac->sac_error,					    sac->sac_inbound_streams,					    sac->sac_outbound_streams);				break;			case SCTP_PEER_ADDR_CHANGE:				spc = &snp->sn_paddr_change;				DEBUG_PRINT(DEBUG_MIN,					    " SCTP_PEER_ADDR_CHANGE\n");				if (spc->spc_aaddr.ss_family == AF_INET) {					sin = (struct sockaddr_in *)					       &spc->spc_aaddr;					ap = inet_ntop(AF_INET, &sin->sin_addr,						       addrbuf,						       INET6_ADDRSTRLEN);				} else {					sin6 = (struct sockaddr_in6 *)						&spc->spc_aaddr;					ap = inet_ntop(AF_INET6,						       &sin6->sin6_addr,						       addrbuf,						       INET6_ADDRSTRLEN);				}				DEBUG_PRINT(DEBUG_MAX,					    "\t\t(peer_addr_change: %s "					    "state=%d, error=%d)\n",					    ap, spc->spc_state,					    spc->spc_error);				break;			case SCTP_SEND_FAILED:				ssf = &snp->sn_send_failed;				DEBUG_PRINT(DEBUG_MIN,					    " SCTP_SEND_FAILED\n");				DEBUG_PRINT(DEBUG_MAX,					    "\t\t(sendfailed: len=%hu "					    "err=%d)\n",					    ssf->ssf_length, ssf->ssf_error);				break;			case SCTP_REMOTE_ERROR:				sre = &snp->sn_remote_error;				DEBUG_PRINT(DEBUG_MIN,					    " SCTP_REMOTE_ERROR\n");				DEBUG_PRINT(DEBUG_MAX,					    "\t\t(remote_error: err=%hu)\n",					     ntohs(sre->sre_error));				break;			case SCTP_SHUTDOWN_EVENT:				DEBUG_PRINT(DEBUG_MIN,					    " SCTP_SHUTDOWN_EVENT\n");				break;			default:				DEBUG_PRINT(DEBUG_MIN,					    " Unknown type: %hu\n",					    snp->sn_header.sn_type);				break;		}		fflush(stdout);		return 1;        } /* notification received */        for (scmsg = CMSG_FIRSTHDR(msg);             scmsg != NULL;             scmsg = CMSG_NXTHDR(msg, scmsg)) {             			data = (sctp_cmsg_data_t *)CMSG_DATA(scmsg);		if (debug_level) print_cmsg(scmsg->cmsg_type, data);	}	fflush(stdout);        return 0;} /* print_message() */int socket_r(void){	struct sctp_event_subscribe subscribe;	int sk, error;	DEBUG_PRINT(DEBUG_MIN, "\tsocket(SOCK_SEQPACKET, IPPROTO_SCTP)");	if ((sk = socket(s_loc.ss_family, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0 ) {		if (do_exit) {			fprintf(stderr, "\n\n\t\t*** socket: failed to create"				" socket:  %s ***\n",        	       	        strerror(errno));			exit(1);		} else {			return -1;		}	}	DEBUG_PRINT(DEBUG_MIN, "  ->  sk=%d\n", sk);	memset(&subscribe, 0, sizeof(subscribe));	subscribe.sctp_data_io_event = 1;	subscribe.sctp_association_event = 1;	error = setsockopt(sk, SOL_SCTP, SCTP_EVENTS, (char *)&subscribe,			   sizeof(subscribe));	if (error) {		fprintf(stderr, "SCTP_EVENTS: error: %d\n", error);		exit(1);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -