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

📄 sctputil.c

📁 SCTP 协议实现源代码
💻 C
字号:
/* SCTP kernel Implementation * (C) Copyright IBM Corp. 2001, 2003 * Copyright (C) 1999 Cisco * Copyright (C) 1999-2000 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> *    Narasimha Budihal <narsi@refcode.org> *    Karl Knutson <karl@athena.chicago.il.us> *    Jon Grimm <jgrimm@us.ibm.com> *    Daisy Chang <daisyc@us.ibm.com> *    Sridhar Samudrala <sri@us.ibm.com> */#include <stdio.h>#include <errno.h> #include <ctype.h>#include <string.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 <malloc.h>#include <netinet/sctp.h>#include <sctputil.h>/* This function prints the cmsg data. */voidtest_print_cmsg(sctp_cmsg_t type, sctp_cmsg_data_t *data){	switch(type) {	case SCTP_INIT:		printf("INIT\n");		printf("   sinit_num_ostreams %d\n",		       data->init.sinit_num_ostreams);		printf("   sinit_max_instreams %d\n",		       data->init.sinit_max_instreams);		printf("   sinit_max_attempts %d\n",		       data->init.sinit_max_attempts);		printf("   sinit_max_init_timeo %d\n",		       data->init.sinit_max_init_timeo);				break;	case SCTP_SNDRCV:		printf("SNDRCV\n");		printf("   sinfo_stream %u\n",	data->sndrcv.sinfo_stream);		printf("   sinfo_ssn %u\n",	data->sndrcv.sinfo_ssn);		printf("   sinfo_flags 0x%x\n",	data->sndrcv.sinfo_flags);		printf("   sinfo_ppid %u\n",	data->sndrcv.sinfo_ppid);		printf("   sinfo_context %x\n",	data->sndrcv.sinfo_context);		printf("   sinfo_tsn     %u\n",    data->sndrcv.sinfo_tsn);		printf("   sinfo_cumtsn  %u\n",    data->sndrcv.sinfo_cumtsn);		printf("   sinfo_assoc_id  %u\n", data->sndrcv.sinfo_assoc_id);				break;			default:		printf("UNKNOWN CMSG: %d\n", type);		break;	}}/* This function prints the message. */voidtest_print_message(int sk, struct msghdr *msg, size_t msg_len) {	sctp_cmsg_data_t *data;	struct cmsghdr *cmsg;	int i;	int done = 0;	char save;	union sctp_notification *sn;	for (cmsg = CMSG_FIRSTHDR(msg);	     cmsg != NULL;	     cmsg = CMSG_NXTHDR(msg, cmsg)) {		     data = (sctp_cmsg_data_t *)CMSG_DATA(cmsg);		     test_print_cmsg(cmsg->cmsg_type, data);	}	if (!(MSG_NOTIFICATION & msg->msg_flags)) {		int index = 0;		/* Make sure that everything is printable and that we		 * are NUL terminated...		 */		printf("DATA(%d):  ", msg_len);		while ( msg_len > 0 ) {			char *text;			int len;			text = msg->msg_iov[index].iov_base;			len = msg->msg_iov[index].iov_len;                        save = text[msg_len-1];			if ( len > msg_len ) {                                text[(len = msg_len) - 1] = '\0';                        }			if ( (msg_len -= len) > 0 ) { index++; }			for (i = 0; i < len - 1; ++i) {                                if (!isprint(text[i])) text[i] = '.';                        }					printf("%s", text);			text[msg_len-1] = save;			if ( (done = !strcmp(text, "exit")) ) { break; }		}	} else {		printf("NOTIFICATION: ");		sn = (union sctp_notification *)msg->msg_iov[0].iov_base;		switch (sn->sn_header.sn_type) {		case SCTP_ASSOC_CHANGE:			switch (sn->sn_assoc_change.sac_state) {			case SCTP_COMM_UP:				printf("ASSOC_CHANGE - COMM_UP");				break;			case SCTP_COMM_LOST:				printf("ASSOC_CHANGE - COMM_LOST");				break;			case SCTP_RESTART:				printf("ASSOC_CHANGE - RESTART");				break;			case SCTP_SHUTDOWN_COMP:				printf("ASSOC_CHANGE - SHUTDOWN_COMP");				break;			case SCTP_CANT_STR_ASSOC:				printf("ASSOC_CHANGE - CANT_STR_ASSOC");				break;			default:				printf("ASSOC_CHANGE - UNEXPECTED(%d)",				       sn->sn_assoc_change.sac_state);				break;			}			break;		default:			printf("%d", sn->sn_header.sn_type);			break;		}	}	printf("\n");}/* Check if a buf/msg_flags matches a notification, its type, and possibly an * additional field in the corresponding notification structure. */void test_check_buf_notification(void *buf, int datalen, int msg_flags,			    int expected_datalen, uint16_t expected_sn_type,			    uint32_t expected_additional){	union sctp_notification *sn;		if (!(msg_flags & MSG_NOTIFICATION))		tst_brkm(TBROK, tst_exit, "Got a datamsg, expecting "			 "notification");		if (expected_datalen <= 0)		return;	if (datalen != expected_datalen)		tst_brkm(TBROK, tst_exit, "Got a notification of unexpected "			 "length:%d, expected length:%d", datalen,			 expected_datalen);			sn = (union sctp_notification *)buf;	if (sn->sn_header.sn_type != expected_sn_type)		tst_brkm(TBROK, tst_exit, "Unexpected notification:%d"			 "expected:%d", sn->sn_header.sn_type,			  expected_sn_type);		switch(sn->sn_header.sn_type){	case SCTP_ASSOC_CHANGE:		if (sn->sn_assoc_change.sac_state != expected_additional)			tst_brkm(TBROK, tst_exit, "Unexpected sac_state:%d "				 "expected:%d", sn->sn_assoc_change.sac_state,				  expected_additional);		break;	default:		break;	}}/* Check if a message matches a notification, its type, and possibly an * additional field in the corresponding notification structure. */void test_check_msg_notification(struct msghdr *msg, int datalen,			    int expected_datalen, uint16_t expected_sn_type,			    uint32_t expected_additional){	test_check_buf_notification(msg->msg_iov[0].iov_base, datalen,				    msg->msg_flags, expected_datalen,				    expected_sn_type, expected_additional);}/* Check if a buf/msg_flags/sinfo corresponds to data, its length, msg_flags, * stream and ppid. */voidtest_check_buf_data(void *buf, int datalen, int msg_flags,		    struct sctp_sndrcvinfo *sinfo, int expected_datalen,		    int expected_msg_flags, uint16_t expected_stream,		    uint32_t expected_ppid){	if (msg_flags & MSG_NOTIFICATION)		tst_brkm(TBROK, tst_exit, "Got a notification, expecting a"			 "datamsg");	if (expected_datalen <= 0)		return;	if (datalen != expected_datalen)		tst_brkm(TBROK, tst_exit, "Got a datamsg of unexpected "			 "length:%d, expected length:%d", datalen,			 expected_datalen);	if ((msg_flags & ~0x80000000) != expected_msg_flags)		tst_brkm(TBROK, tst_exit, "Unexpected msg_flags:0x%x "			 "expecting:0x%x", msg_flags, expected_msg_flags);	if ((0 == expected_stream) && (0 == expected_ppid))		return; 	if (!sinfo)		tst_brkm(TBROK, tst_exit, "Null sinfo, but expected "			 "stream:%d expected ppid:%d", expected_stream,			 expected_ppid);	if (sinfo->sinfo_stream != expected_stream)		tst_brkm(TBROK, tst_exit, "stream mismatch: expected:%x "			 "got:%x", expected_stream, sinfo->sinfo_stream);	if (sinfo->sinfo_ppid != expected_ppid)		tst_brkm(TBROK, tst_exit, "ppid mismatch: expected:%x "			 "got:%x\n", expected_ppid, sinfo->sinfo_ppid);}/* Check if a message corresponds to data, its length, msg_flags, stream and * ppid. */voidtest_check_msg_data(struct msghdr *msg, int datalen, int expected_datalen,		    int expected_msg_flags, uint16_t expected_stream,		    uint32_t expected_ppid){	struct cmsghdr *cmsg = NULL;	struct sctp_sndrcvinfo *sinfo = NULL;	/* Receive auxiliary data in msgh. */	for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;				 cmsg = CMSG_NXTHDR(msg, cmsg)){		if (IPPROTO_SCTP == cmsg->cmsg_level &&		    SCTP_SNDRCV == cmsg->cmsg_type)			break;	} /* for( all cmsgs) */	if ((!cmsg) ||	    (cmsg->cmsg_len < CMSG_LEN(sizeof(struct sctp_sndrcvinfo))))		sinfo = NULL;	else		sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);	test_check_buf_data(msg->msg_iov[0].iov_base, datalen, msg->msg_flags,			    sinfo, expected_datalen, expected_msg_flags,			    expected_stream, expected_ppid);}/* Allocate a buffer of requested len and fill in with data. */void *test_build_msg(int len){	int i = len - 1;	int n;	unsigned char msg[] = 		"012345678901234567890123456789012345678901234567890";	char *msg_buf, *p;	msg_buf = (char *)malloc(len);	if (!msg_buf)		tst_brkm(TBROK, tst_exit, "malloc failed");	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);}/* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */void test_enable_assoc_change(int fd){	struct sctp_event_subscribe subscribe;	memset(&subscribe, 0, sizeof(subscribe));	subscribe.sctp_data_io_event = 1;	subscribe.sctp_association_event = 1;	test_setsockopt(fd, SCTP_EVENTS, (char *)&subscribe,		        sizeof(subscribe));}static int cmp_addr(sockaddr_storage_t *addr1, sockaddr_storage_t *addr2){	if (addr1->sa.sa_family != addr2->sa.sa_family)		return 0;	switch (addr1->sa.sa_family) {	case AF_INET6:		if (addr1->v6.sin6_port != addr2->v6.sin6_port)			return -1;		return memcmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr,			      sizeof(addr1->v6.sin6_addr));	case AF_INET:		if (addr1->v4.sin_port != addr2->v4.sin_port)			return 0;		return memcmp(&addr1->v4.sin_addr, &addr2->v4.sin_addr,			      sizeof(addr1->v4.sin_addr));	default:		tst_brkm(TBROK, tst_exit, "invalid address type %d",			 addr1->sa.sa_family);		return -1;	}}/* Test peer addresses for association. */int test_peer_addr(int sk, sctp_assoc_t asoc, sockaddr_storage_t *peers, int count){	struct sockaddr *addrs;	int error, i, j;	struct sockaddr *sa_addr;	socklen_t addrs_size = 0;	void *addrbuf;	char *found = (char *) malloc(count);	memset(found, 0, count);	error = sctp_getpaddrs(sk, asoc, &addrs);	if (-1 == error) {		tst_brkm(TBROK, tst_exit, "sctp_getpaddrs: %s", strerror(errno));		return error;	}	if (error != count) {		sctp_freepaddrs(addrs);		tst_brkm(TBROK, tst_exit, "peer count %d mismatch, expected %d",			 error, count);	}	addrbuf = addrs;	for (i = 0; i < count; i++) {		sa_addr = (struct sockaddr *)addrbuf;		switch (sa_addr->sa_family) {		case AF_INET:			addrs_size += sizeof(struct sockaddr_in);			addrbuf += sizeof(struct sockaddr_in);			break;		case AF_INET6:			addrs_size += sizeof(struct sockaddr_in6);			addrbuf += sizeof(struct sockaddr_in6);			break;		default:			errno = EINVAL;			sctp_freepaddrs(addrs);			tst_brkm(TBROK, tst_exit, "sctp_getpaddrs: %s", strerror(errno));			return -1;		}		for (j = 0; j < count; j++) {			if (cmp_addr((sockaddr_storage_t *)sa_addr,				     &peers[j]) == 0) {				found[j] = 1;			}		}	}	for (j = 0; j < count; j++) {		if (found[j] == 0) {			tst_brkm(TBROK, tst_exit, "peer address %d not found", j);		}	}	sctp_freepaddrs(addrs);	return 0;}

⌨️ 快捷键说明

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