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

📄 sctp_xconnect.c

📁 SCTP 协议实现源代码
💻 C
字号:
/* SCTP kernel Implementation * (C) Copyright IBM Corp. 2003 * * The SCTP implementation 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. * * The SCTP implementation 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 * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. * * Written or modified by: *    Ryan Layer		<rmlayer@us.ibm.com> */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/uio.h>#include <netinet/in.h>#include <errno.h>#include <netinet/sctp.h>#include <sctputil.h>#include <netdb.h>#include <getopt.h>char *TCID = __FILE__;int TST_TOTAL = 1;int TST_CNT = 0;#define MAXHOSTNAME 64#define MAXCLIENTNUM 10000#define TRUE 1#define SERVER 1#define CLIENT 0#define NOT_DEFINED -1int mode = NOT_DEFINED;int	assoc_num,	remote_port,	local_port;int active = 0;char *local_host = NULL;char *remote_host = NULL;sockaddr_storage_t client_loop,		server_loop;struct hostent *hst;void usage(char *argv0);void parse_arguments(int argc, char*argv[]);void data_received(struct msghdr *inmessage, int len, int stream,                        int server_socket);int event_received(struct msghdr *inmessage, int assoc_num);void process_ready_sockets(int client_socket[], int assoc_num, fd_set *rfds);void server_mode(void);void client_mode(void);/* Print the syntax/usage */void usage(char *argv0){	printf("usage: %s -H localhost -P localport -l|c [-h remotehost]\n"	       "\t\t[-p remoteport] [-a] [-n <cnt>]\n" 	       " -H\t\tspecify a local address.\n"	       " -P\t\tspecify the local port number to be used\n"	       " -l\t\trun in server mode.\n"	       " -c\t\trun in client mode.\n"	       " -h\t\tspecify the peer address.\n"	       " -p\t\tspecify the port number for the peer address.\n"	       " -a\t\tactively generate traffic with the server.\n"	       " -n\t\tspecify the number of associations to create.\n",	       argv0);}/* Parse command line options */void parse_arguments(int argc, char*argv[]) {	int c;	while ((c = getopt(argc, argv, ":H:P:ach:ln:p:")) >= 0) {		switch (c) {			case 'H':				local_host = optarg;				break;			case 'P':				local_port = atoi(optarg);				break;			case 'c':			    if (mode == NOT_DEFINED)					mode = CLIENT;				else {					usage(argv[0]);					exit(0);				}				break;			case 'a':				active = 1;				break;			case 'h':				remote_host = optarg;				break;			case 'l':			    if (mode == NOT_DEFINED)					mode = SERVER;				else {					usage(argv[0]);					exit(0);				}				break;			case 'n':				assoc_num = atoi(optarg);				break;			case 'p':				remote_port = atoi(optarg);				break;			default:				usage(argv[0]);				exit(0);		}	} /* while() */	if (mode == CLIENT) {		if (assoc_num) {			if (assoc_num > MAXCLIENTNUM) {				printf("The number of associations indicated "					"is greater than the");				printf("max number of associations "					"allowed(%d).", MAXCLIENTNUM);				usage(argv[0]);				exit(0);			}		} else			assoc_num = 1;		if (remote_host && remote_port) {			hst = gethostbyname(remote_host);			memcpy(&server_loop.v4.sin_addr, hst->h_addr_list[0],				   sizeof(server_loop.v4.sin_addr));			server_loop.v4.sin_family = AF_INET;server_loop.v4.sin_port = htons(remote_port);		} else {			printf("Remote host and remote port must be defined "				"in client mode\n");			usage(argv[0]);			exit(0);		}		if (local_host) {			hst = gethostbyname(local_host);			memcpy(&client_loop.v4.sin_addr, hst->h_addr_list[0],				   sizeof(client_loop.v4.sin_addr));		} else			client_loop.v4.sin_addr.s_addr = INADDR_ANY;		if (local_port)			client_loop.v4.sin_port = htons(local_port);		else			client_loop.v4.sin_port = 0;		client_loop.v4.sin_family = AF_INET;	} else if (mode == SERVER) {		if (active) {			printf("This option if for client use only");			usage(argv[0]);			exit(0);		}		if (remote_host || remote_port) {			printf("Remote values not needed in server mode.\n");			usage(argv[0]);			exit(0);		}		if (local_host) {			hst = gethostbyname(local_host);			memcpy(&server_loop.v4.sin_addr, hst->h_addr_list[0],				   sizeof(server_loop.v4.sin_addr));		} else			server_loop.v4.sin_addr.s_addr = INADDR_ANY;		if (local_port)			server_loop.v4.sin_port = htons(local_port);		else {			printf("Specify a local port in server mode.\n");			usage(argv[0]);			exit(0);		}		server_loop.v4.sin_family = AF_INET;	} else {		printf("Must assisgn a client or server mode.\n");		usage(argv[0]);		exit(0);	}} /* parse_arguments() *//* Handle data recieved */void data_received(struct msghdr *inmessage, int len, int stream, int socket) {	int ppid, error;	char *ping = "PING";	if (mode == SERVER) {		ppid = rand();		error = sctp_sendmsg(socket,				inmessage->msg_iov->iov_base,				len,				(struct sockaddr *)inmessage->msg_name,				inmessage->msg_namelen,				ppid,				0,				stream,				0, 0);		if (error < 0) {			printf("Send Failure: %s.\n", strerror(errno));			DUMP_CORE;		}	} else {		ppid = rand();		printf("Data Received by socket #: %d.\n", socket);		printf("\tMessage = %s\n",			(char *)inmessage->msg_iov->iov_base);		if (active) {			sctp_sendmsg(socket,				ping,				strlen(ping) + 1,				(struct sockaddr *)&server_loop,				sizeof (server_loop),				ppid,				0,				stream,				0, 0);		}	}}/* This will print what type of SCTP_ASSOC_CHANGE state that was recieved */void print_sctp_sac_state(struct msghdr *msg) {	char *data;	union sctp_notification *sn;	if (msg->msg_flags & MSG_NOTIFICATION) {		data = (char *)msg->msg_iov[0].iov_base;		sn = (union sctp_notification *)data;		switch (sn->sn_assoc_change.sac_state) {				case SCTP_COMM_UP:						printf("SCTP_COMM_UP\n");						break;				case SCTP_COMM_LOST:						printf("SCTP_COMM_LOST\n");						break;				case SCTP_RESTART:						printf("SCTP_RESTART");						break;				case SCTP_SHUTDOWN_COMP:						printf("SCTP_SHUTDOWN_COMP\n");						break;				case SCTP_CANT_STR_ASSOC:						printf("SCTP_CANT_STR_ASSOC\n");						break;				default:						break;		}	}} /* void print_sctp_sac_state() *//* Tests what type of MSG_NOTIFICATION has been received.* For now this fucntion only works with SCTP_ASSOC_CHANGE * types, but can be easily expanded.** Will return...* -1 if the msg_flags is not MSG_NOTIFICATION*  0 if the MSG_NOTIFICATION type differs from the type*       passed into the additional variable*  1 if the MSG_NOTIFICATION type matches the type*       passed into the additional variable*/int test_check_notification_type(struct msghdr *msg,	uint16_t sn_type,	uint32_t additional) {	char *data;	union sctp_notification *sn;	if (!(msg->msg_flags & MSG_NOTIFICATION)) {		return -1;	} else {		/* Fixup for testframe. */		data = (char *)msg->msg_iov[0].iov_base;		sn = (union sctp_notification *)data;		if (sn->sn_header.sn_type != sn_type)			return 0;		else if (sn->sn_header.sn_type == SCTP_ASSOC_CHANGE)			if (sn->sn_assoc_change.sac_state == additional)				return 1;		return 0;	}}/* Determine the type of event and make correct adjustments to the* association count*/int event_received(struct msghdr *inmessage, int assoc_num) {	int error;	printf("Event Received\n");	print_sctp_sac_state(inmessage);	if (mode == SERVER) {		/* Test type of Event */		error = test_check_notification_type(inmessage,						SCTP_ASSOC_CHANGE,						SCTP_COMM_UP);		if (error > 0) {			assoc_num++;			printf("Assosiation Established: count = %d.\n",				assoc_num);		} else {			error = test_check_notification_type(inmessage,							SCTP_ASSOC_CHANGE,							SCTP_SHUTDOWN_COMP);			if (error > 0) {				assoc_num--;				printf("Assosiation Shutdown: count = %d.\n",					assoc_num);			}		}	}	return assoc_num;}void server_mode() {	sockaddr_storage_t msgname;	int server_socket,		error,		stream;	int assoc_num =0;	struct msghdr inmessage;	struct iovec iov;	char *big_buffer;	char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))];	if ((big_buffer = malloc(REALLY_BIG)) == NULL) {		printf("malloc failure: %s\n", strerror(errno));		DUMP_CORE;	}	printf("Running in Server Mode...\n");	memset(&inmessage, 0, sizeof(inmessage));	iov.iov_base = big_buffer;	iov.iov_len = REALLY_BIG;	inmessage.msg_iov = &iov;	inmessage.msg_iovlen =1;	inmessage.msg_control = incmsg;	inmessage.msg_controllen = sizeof(incmsg);	inmessage.msg_name = &msgname;	inmessage.msg_namelen = sizeof (msgname);	stream = 1;	server_socket = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);	if (server_socket < 0) {		printf("Socket Failure:  %s.\n", strerror(errno));		DUMP_CORE;	}	error = bind(server_socket, &server_loop.sa, sizeof(server_loop));	if (error != 0 ) {		printf("Bind Failure: %s.\n", strerror(errno));		DUMP_CORE;	}	error = listen(server_socket, 1);	if (error != 0) {		printf("Listen Failure: %s.\n", strerror(errno));		DUMP_CORE;	}	while (TRUE) {		error = recvmsg(server_socket, &inmessage, MSG_WAITALL);		if (error < 0) {			printf("Receive Failure: %s\n",			strerror(errno));		} else {		if (inmessage.msg_flags & MSG_NOTIFICATION)			assoc_num = event_received(&inmessage, assoc_num);		else			data_received(&inmessage, error, stream, server_socket);		}	}}void client_mode() {	int i, error, stream, max_socket = 0;	uint32_t ppid = 0;	int client_socket[assoc_num];	char *message = "Awake";	fd_set rfds;	struct timeval tv;        stream = 1;	printf("Running in Client Mode...\n");        /* Create the sockets */	for (i = 0; i < assoc_num; i++) {		client_socket[i] = socket(PF_INET, SOCK_SEQPACKET,					IPPROTO_SCTP);		if (client_socket[i] < 0 ){			printf("Socket Failure: %s.\n", strerror(errno));			DUMP_CORE;		}		if (local_port) {			error = bind(client_socket[i], &client_loop.sa,				sizeof(client_loop));			if (error < 0) {				printf("Bind Failure: %s\n", strerror(errno));				DUMP_CORE;			}		}		printf("Create Socket #: %d\n", client_socket[i]);		/* Connect to server and send initial message */		error = connect(client_socket[i], &server_loop.sa,						    sizeof(server_loop));		if (error < 0){			printf("Connect Failure: %s.\n", strerror(errno));			DUMP_CORE;		}		max_socket = client_socket[i];                ppid++;		/* Send initial message */		error = sctp_sendmsg(client_socket[i],				message,				strlen(message) + 1,				(struct sockaddr *)&server_loop,				sizeof(server_loop),				ppid,				0,				stream,				0, 0);		if (error < 0 ) {			printf("Send Failure: %s.\n", strerror(errno));			DUMP_CORE;		}	}	while (TRUE){		/* Clear the set for select() */		FD_ZERO(&rfds);		/* Set time out values for select() */		tv.tv_sec = 5;		tv.tv_usec = 0;		/* Add the sockets select() will examine */		for (i = 0; i < assoc_num; i++) {			FD_SET(client_socket[i], &rfds);		}		/* Wait until there is data to be read from one of the		 * sockets, or until the timer expires		 */		error = select(max_socket + 1, &rfds, NULL, NULL, &tv);		if (error < 0) {			printf("Select Failure: %s.\n", strerror(errno));			DUMP_CORE;		} else if (error) {			/* Loop through the array of sockets to find the ones			 *that have information to be read			 */			process_ready_sockets(client_socket, assoc_num, &rfds);		}	}}void process_ready_sockets(int client_socket[], int assoc_num, fd_set *rfds) {        int i, stream, error;	struct msghdr inmessage;	struct iovec iov;	char *big_buffer;	char incmsg[CMSG_SPACE(sizeof (sctp_cmsg_data_t))];	sockaddr_storage_t msgname;	if ((big_buffer = malloc(REALLY_BIG)) == NULL) {		printf("malloc failure: %s\n", strerror(errno));		DUMP_CORE;	}        /* Setup inmessage to be able to receive in incomming message */	memset(&inmessage, 0, sizeof (inmessage));	iov.iov_base = big_buffer;	iov.iov_len = REALLY_BIG;	inmessage.msg_iov = &iov;	inmessage.msg_iovlen =1;	inmessage.msg_control = incmsg;	inmessage.msg_controllen = sizeof (incmsg);	inmessage.msg_name = &msgname;	inmessage.msg_namelen = sizeof (msgname);	stream = 1;	for( i = 0; i < assoc_num; i++) {		if (FD_ISSET(client_socket[i], rfds)) {				error = recvmsg(client_socket[i], &inmessage,						MSG_WAITALL);				if (error < 0)						printf("Receive Failure: %s\n",							strerror(errno));				else {		/* Test to find the type of message that was read(event/data) */					if (inmessage.msg_flags &						MSG_NOTIFICATION)						 event_received(&inmessage,								0);					else						data_received(&inmessage, error,							stream,							client_socket[i]);			}		}	}}int main(int argc, char *argv[]) {	parse_arguments(argc, argv);	if (mode == SERVER) {		server_mode();	} else if (mode == CLIENT){		client_mode();	}	exit(1);}

⌨️ 快捷键说明

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