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

📄 sctp_darn.c

📁 SCTP 协议实现源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* SCTP kernel Implementation * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999 Cisco * Copyright (c) 1999, 2000, 2001 Motorola * Copyright (c) 2001 Nokia * Copyright (c) 2001 La Monte H.P. Yarroll * * 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 to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. * * Written or modified by: *    La Monte H.P. Yarroll <piggy@acm.org> *    Karl Knutson <karl@athena.chicago.il.us> *    Hui Huang <hui.huang@nokia.com> *    Daisy Chang <daisyc@us.ibm.com> *    Sridhar Samudrala <sri@us.ibm.com> *//* This is a userspace test application for the SCTP kernel  * implementation state machine.  It is vaguely inspired by Stevens' * program "sock". * * It has the limited ability to send messages and to listen for messages * sent via SCTP. */#include <stdio.h>#include <fcntl.h>#include <stdlib.h>//#define _GNU_SOURCE#include <getopt.h>#include <netdb.h>#include <ctype.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/uio.h>#include <netinet/in.h>#include <sys/errno.h>#include <sys/param.h>#include <sys/poll.h>#include <arpa/inet.h>#include <errno.h>#include <net/if.h>#include <netinet/sctp.h>#include <unistd.h>#include <string.h>#include <signal.h>#include "sctp_darn.h"char *TCID = __FILE__;int TST_TOTAL = 1;int TST_CNT = 0;#define GEN_DATA_FIRST	0x21#define GEN_DATA_LAST	0x7e/* Display an IPv4 address in readable format.  */#define NIPQUAD(addr) \        ((unsigned char *)&addr)[0], \        ((unsigned char *)&addr)[1], \        ((unsigned char *)&addr)[2], \        ((unsigned char *)&addr)[3]/* Display an IPv6 address in readable format.  */#define NIP6(addr) \        ntohs((addr).s6_addr16[0]), \        ntohs((addr).s6_addr16[1]), \        ntohs((addr).s6_addr16[2]), \        ntohs((addr).s6_addr16[3]), \        ntohs((addr).s6_addr16[4]), \        ntohs((addr).s6_addr16[5]), \        ntohs((addr).s6_addr16[6]), \        ntohs((addr).s6_addr16[7])/* These are the global options.  */char *local_host = NULL;int local_port = 0;char *remote_host = NULL;int remote_port = 0;command_t command = COMMAND_NONE;struct sockaddr *bindx_add_addrs = NULL;int bindx_add_count = 0;struct sockaddr *bindx_rem_addrs = NULL;int bindx_rem_count = 0;struct sockaddr *connectx_addrs = NULL;int connectx_count = 0;int interactive_mode = 0;int poll_skn = 0;int nonblocking = 0;int opt_space = 0;char gen_data = GEN_DATA_FIRST;char *inter_outbuf = NULL;int inter_outlen = 0;int inter_sk = 0;int poll_snd_size = 0;int use_poll = 0;int socket_type = SOCK_SEQPACKET;sctp_assoc_t associd = 0;int echo = 0;char *interface = "eth0";int if_index = 0;sockaddr_storage_t remote_addr;sa_family_t ra_family;	/* What family is remote_addr? */int ra_len = 0;		/* How long is remote_addr? */void *ra_raw;		/* This is the addr part of remote_addr. */int new_connection = 1;enum inter_cmd_num {	INTER_SND = 0,	INTER_RCV,	INTER_SNDBUF,	INTER_RCVBUF,	INTER_BINDX_ADD,	INTER_BINDX_REM,	INTER_SET_PRIM,	INTER_SET_PEER_PRIM,	INTER_SHUTDOWN,	INTER_ABORT,	INTER_NODELAY,	INTER_MAXSEG};enum shutdown_type {	SHUTDOWN_ABORT = 0,	SHUTDOWN_SHUTDOWN};struct inter_entry {	char *cmd;	int cmd_num;};struct inter_entry inter_commands[] = {	{"snd", INTER_SND},	{"rcv",	INTER_RCV},	{"sndbuf", INTER_SNDBUF},	{"rcvbuf", INTER_RCVBUF},	{"bindx-add", INTER_BINDX_ADD},	{"bindx-rem", INTER_BINDX_REM},	{"primary", INTER_SET_PRIM},	{"peer_primary", INTER_SET_PEER_PRIM},	{"shutdown", INTER_SHUTDOWN},	{"abort", INTER_ABORT},	{"nodelay", INTER_NODELAY},	{"maxseg", INTER_MAXSEG},	{NULL, -1},};#define POLL_SK_MAX 	256	/* The max number of sockets to select/poll. */int poll_sks[POLL_SK_MAX];		/* The array for using select(). */struct pollfd poll_fds[POLL_SK_MAX];	/* The array for using poll().  */#define POLL_SND_SIZE	16384	/* Default message size in the poll mode. */struct sockaddr *append_addr(const char *parm, struct sockaddr *addrs,			     int *ret_count) ;int build_endpoint(char *argv0, int portnum);static int parse_inter_commands(char *, char *, int);static void snd_func(char *);static void sndbuf_func(char *, int, int, int);static void rcvbuf_func(char *, int, int, int);static struct sockaddr *get_bindx_addr(char *, int *);static int bindx_func(char *, int, struct sockaddr *, int, int, int);static int connectx_func(char *, int, struct sockaddr *, int);static void  primary_func(char *, int, char *, int);static void  peer_primary_func(char *, int, char *, int);static int nodelay_func(char *, int, int val, int set);static int maxseg_func(char *, int, int val, int set);static int shutdown_func(char *argv0, int *skp, int shutdown_type);static int test_sk_for_assoc(int sk, sctp_assoc_t assoc_id);static char * gen_message(int);static sctp_assoc_t test_recv_assoc_change(int);static sctp_assoc_t test_verify_assoc_change(struct msghdr *);void print_addr_buf(void * laddrs, int n_laddrs);int print_sockaddr(struct sockaddr *sa_addr);intmain(int argc, char *argv[]) {	int sk = -1;	int error = 0;	int i;	signal(SIGPIPE, SIG_IGN);	parse_arguments(argc, argv);	switch(command) {	case COMMAND_NONE:		fprintf(stderr, "%s: Please specify a command.\n",			argv[0]);		exit(1);		break;	case COMMAND_LISTEN:		sk = build_endpoint(argv[0], local_port);		error = command_listen(argv[0], sk);		break;	case COMMAND_SEND:		sk = build_endpoint(argv[0], local_port);		error = command_send(argv[0], &sk);		break;	case COMMAND_POLL:		if (use_poll) {			for (i = 0; i < poll_skn; i++) {				poll_fds[i].fd = build_endpoint(argv[0],					local_port + i);			}		} else {			for (i = 0; i < poll_skn; i++) {				poll_sks[i] = build_endpoint(argv[0],					local_port + i);			}		}		error = command_poll(argv[0]);		break;	default:		fprintf(stderr, "%s: illegal command %d\n",			argv[0], command);		exit(1);	}	/* Shut down the link.  */	if (COMMAND_POLL != command) {		close(sk);	} else {		/* Shutdown all links.  */		if (use_poll) {			for (i = 0; i < poll_skn; i++) {				close(poll_fds[i].fd);			}		} else {			for (i = 0; i < poll_skn; i++) {				close(poll_sks[i]);			}		}	}	exit(error);}/******************************************************************** * 2nd Level Abstractions ********************************************************************/voidparse_arguments(int argc, char *argv[]) {	int option_index = 0;	int c;	struct sockaddr *tmp_addrs = NULL;	static struct option long_options[] = {		{"local",	1, 0, 1},		{"local-port",	1, 0, 2},		{"remote",	1, 0, 3},		{"remote-port",	1, 0, 4},		{"listen",	0, 0, 10},		{"send",	0, 0, 11},		{"bindx-add",	1, 0, 15},		{"bindx-rem",	1, 0, 16},		{"use-poll",	0, 0, 20},		{"echo",        0, 0, 'e'},		{"interface",   optional_argument, 0, 5,},		{"connectx",    1, 0, 17},		{0,		0, 0, 0}	};	/* Parse the arguments.  */	while (1) {		c = getopt_long (argc, argv, "B:H:IP:b:h:i:p:lm:nstz:ec:",				 long_options, &option_index);		if (c == -1)			break;		switch (c) {		case 0:			printf("option %s", long_options[option_index].name);			if (optarg) {				printf(" with arg %s", optarg);			}			printf("\n");			break;		case 1:		/* local host */		case 'H':			local_host = optarg;			break;		case 2:		/* local port */		case 'P':			local_port = atoi(optarg);			break;		case 3:		/* remote host */		case 'h':			remote_host = optarg;			break;		case 4:		/* remote port */		case 'p':			remote_port = atoi(optarg);			break;		case 5:  /* interface for sin6_scope_id */			if (optarg)				interface = optarg;			if_index = if_nametoindex(interface);			if (!if_index) {				printf("Interface %s unknown\n", interface);				exit(1);			}			break;			/* COMMANDS */		case 10:	/* listen */		case 'l':			if (command) {				fprintf(stderr,					"%s: pick ONE of listen or send\n",					argv[0]);				exit(1);			} else {				command = COMMAND_LISTEN;			}			break;		case 11:	/* send */		case 's':			if (command) {				fprintf(stderr,					"%s: pick ONE of listen or send\n",					argv[0]);				exit(1);			} else {				command = COMMAND_SEND;			}			break;		case 15:		/* bindx_add */		case 'B':			tmp_addrs =				append_addr(optarg, bindx_add_addrs,					    &bindx_add_count);			if (NULL == tmp_addrs) {				/* We have no memory, so keep fprintf()				 * from trying to allocate more.				 */				fprintf(stderr, "No memory to add ");				fprintf(stderr, optarg);				fprintf(stderr, "\n");				exit(2);			}			bindx_add_addrs = tmp_addrs;			break;		case 16:		/* bindx_rem */		case 'b':			tmp_addrs =				append_addr(optarg, bindx_rem_addrs,					    &bindx_rem_count);			if (NULL == tmp_addrs) {				/* We have no memory, so keep fprintf()				 * from trying to allocate more.				 */				fprintf(stderr, "No memory to add ");				fprintf(stderr, optarg);				fprintf(stderr, "\n");				exit(2);			}			bindx_rem_addrs = tmp_addrs;			break;		case 17:		/* connectx */		case 'c':			tmp_addrs =				append_addr(optarg, connectx_addrs,					    &connectx_count);			if (NULL == tmp_addrs) {				/* We have no memory, so keep fprintf()				 * from trying to allocate more.				 */				fprintf(stderr, "No memory to add ");				fprintf(stderr, optarg);				fprintf(stderr, "\n");				exit(2);			}			connectx_addrs = tmp_addrs;			break;		case 20:		/* use-poll */			use_poll = 1;			break;		case 'I':			interactive_mode = 1;			break;		case 'i':			command = COMMAND_POLL;			poll_skn = atoi(optarg);			if (poll_skn <= 0 || poll_skn > POLL_SK_MAX) {				fprintf(stderr, "Too many sockets for ");				fprintf(stderr, "for polling\n");				exit(2);			}			break;		case 'm':			opt_space = atoi(optarg);			break;		case 'n':			nonblocking = 1;			break;		case 't':			socket_type = SOCK_STREAM;			break;		case 'z':			poll_snd_size = atoi(optarg);			if (poll_snd_size <= 0) {				fprintf(stderr, "Bad message size.\n");				exit(2);			}			break;		case 'e':			echo = 1;			break;		case '?':			usage(argv[0]);			exit(1);		default:			printf ("%s: unrecognized option 0%c\n",				argv[0], c);			usage(argv[0]);			exit(1);		}	}	if (optind < argc)	{		fprintf(stderr, "%s: non-option arguments are illegal: ",			argv[0]);		while (optind < argc)			fprintf(stderr, "%s ", argv[optind++]);		fprintf (stderr, "\n");		usage(argv[0]);		exit(1);	}	if (NULL == local_host) {		fprintf(stderr, "%s: You MUST provide a local host.\n",			argv[0]);		usage(argv[0]);		exit(1);	}	if (command == COMMAND_SEND && NULL == remote_host	    && connectx_count == 0) {		fprintf(stderr, "%s: You MUST provide a remote host for sending.\n",			argv[0]);		usage(argv[0]);		exit(1);	}	if (remote_host != NULL && connectx_count != 0) {		fprintf(stderr, "%s: You can not provide both -h and -c options.\n",			argv[0]);		usage(argv[0]);		exit(1);	}} /* parse_arguments() *//* Set up the local endpoint.  */intbuild_endpoint(char *argv0, int portnum){	int retval;	struct hostent *hst;	sockaddr_storage_t local_addr;	sa_family_t la_family;	/* What family is local_addr? */	int la_len;		/* How long is local_addr? */	void *la_raw;		/* This is the addr part of local_addr. */	int error;	struct sctp_event_subscribe subscribe;	/* Get the transport address for the local host name.  */	hst = gethostbyname(local_host);	if (hst == NULL) {		hst = gethostbyname2(local_host, AF_INET6);	}	if (hst == NULL || hst->h_length < 1) {		fprintf(stderr, "%s: bad hostname: %s\n", argv0, local_host);		exit(1);	}	la_family = hst->h_addrtype;	switch (la_family) {	case AF_INET:		la_len = sizeof(local_addr.v4);		la_raw = &local_addr.v4.sin_addr;		local_addr.v4.sin_port = htons(portnum);		local_addr.v4.sin_family = AF_INET;		break;	case AF_INET6:		la_len = sizeof(local_addr.v6);		la_raw = &local_addr.v6.sin6_addr;		local_addr.v6.sin6_port = htons(portnum);		local_addr.v6.sin6_family = AF_INET6;		local_addr.v6.sin6_scope_id = if_index;		break;	default:		fprintf(stderr, "Invalid address type.\n");		exit(1);		break;	}	memcpy(la_raw, hst->h_addr_list[0], hst->h_length);	/* Create the local endpoint.  */	retval = socket(la_family, socket_type, IPPROTO_SCTP);	if (retval < 0) {		fprintf(stderr, "%s: failed to create socket:  %s.\n",			argv0, strerror(errno));		exit(1);	}	if (SOCK_SEQPACKET == socket_type) {		memset(&subscribe, 0, sizeof(subscribe));		subscribe.sctp_data_io_event = 1;		subscribe.sctp_association_event = 1;		error = setsockopt(retval, SOL_SCTP, SCTP_EVENTS,				   (char *)&subscribe, sizeof(subscribe));		if (error) {			fprintf(stderr, "SCTP_EVENTS: error: %d\n", error);			exit(1);		}	}	/* Bind this socket to the test port.  */	error = bind(retval, &local_addr.sa, la_len);	if (error != 0) {		fprintf(stderr, "%s: can not bind to %s:%d: %s.\n",			argv0, local_host, portnum,			strerror(errno));		exit(1);	}	/* Do we need to do bindx() to add any additional addresses? */	if (bindx_add_addrs) {		if (0 != bindx_func(argv0, retval, bindx_add_addrs,			bindx_add_count, SCTP_BINDX_ADD_ADDR, portnum)) {			fprintf(stderr, "bindx_func (add) failed.\n");			exit(1);		}	} /* if (bindx_add_addrs) */	/* Do we need to do bindx() to remove any bound addresses? */	if (bindx_rem_addrs) {		if (0 != bindx_func(argv0, retval, bindx_rem_addrs,			bindx_rem_count, SCTP_BINDX_REM_ADDR, portnum)) {			fprintf(stderr, "bindx_func (remove) failed.\n");			exit(1);		}

⌨️ 快捷键说明

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