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

📄 sctp_darn.c

📁 SCTP 协议实现源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}} /* rcvbuf_func() */static struct sockaddr *get_bindx_addr(char *in, int *count){	struct sockaddr *tmp_addrs = NULL;	char *p = in;	/* Set the buffer for address parsing.  */	while ('\n' != *p) {		p++;	}	*p = '\0';	*count = 0;	tmp_addrs = append_addr(in, tmp_addrs, 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, in);		fprintf(stderr, "\n");		exit(2);	}	return tmp_addrs;} /* get_bindx_addr() */static intbindx_func(char *argv0, int sk, struct sockaddr *addrs, int count, int flag, int portnum){	int error;	int i;	struct sockaddr *sa_addr;	void *aptr;	if (0 == portnum) {		fprintf(stderr, "%s: A non-0 local port number is ", argv0);		fprintf(stderr, "required for bindx to work!\n");		return -1 ;	}	/* Set the port in every address.  */	aptr = addrs;	for (i = 0; i < count; i++) {		sa_addr = (struct sockaddr *)aptr;		switch(sa_addr->sa_family) {		case AF_INET:			((struct sockaddr_in *)sa_addr)->sin_port =				htons(portnum);			aptr += sizeof(struct sockaddr_in);			break;		case AF_INET6:			((struct sockaddr_in6 *)sa_addr)->sin6_port =				htons(portnum);			aptr += sizeof(struct sockaddr_in6);			break;		default:			fprintf(stderr, "Invalid address family\n");			return -1;		}	}	error = sctp_bindx(sk, addrs, count, flag);	if (error != 0) {		if (flag == SCTP_BINDX_ADD_ADDR) {			fprintf(stderr, "%s: error adding addrs: %s.\n",				argv0, strerror(errno));			return -1;		} else {			fprintf(stderr, "%s: error removing addrs: %s.\n",				argv0, strerror(errno));			return -1;		}	}	return 0;} /* bindx_func() */static intconnectx_func(char *argv0, int sk, struct sockaddr *addrs, int count){	int error;	int i;	struct sockaddr *sa_addr;	void *aptr;	if (0 == remote_port) {		fprintf(stderr, "%s: A non-0 remote port number is ", argv0);		fprintf(stderr, "required for connectx to work!\n");		return -1 ;	}	/* Set the port in every address.  */	aptr = addrs;	for (i = 0; i < count; i++) {		sa_addr = (struct sockaddr *)aptr;		switch(sa_addr->sa_family) {		case AF_INET:			((struct sockaddr_in *)sa_addr)->sin_port =				htons(remote_port);			aptr += sizeof(struct sockaddr_in);			break;		case AF_INET6:			((struct sockaddr_in6 *)sa_addr)->sin6_port =				htons(remote_port);			aptr += sizeof(struct sockaddr_in6);			break;		default:			fprintf(stderr, "Invalid address family\n");			return -1;		}	}	error = sctp_connectx(sk, addrs, count);	if (error != 0) {		if (errno == ECONNREFUSED)			return -2;		fprintf(stderr, "%s: error connecting to addrs: %s.\n",			argv0, strerror(errno));		return -1;	}	return 0;} /* connectx_func() */static voidprimary_func(char *argv0, int sk, char *cp, int set){	struct sctp_prim prim;	struct sockaddr_in *in_addr;	struct sockaddr_in6 *in6_addr;	struct sockaddr *saddr;	socklen_t prim_len;	int ret;	char *p = cp;	char addr_buf[INET6_ADDRSTRLEN];	const char *ap = NULL;	prim_len = sizeof(struct sctp_prim);	if (!set) {		prim.ssp_assoc_id = associd;		ret = getsockopt(sk, IPPROTO_SCTP, SCTP_PRIMARY_ADDR,				   &prim, &prim_len); 		if (ret < 0)			goto err;			saddr = (struct sockaddr *)&prim.ssp_addr;			if (AF_INET == saddr->sa_family) {			in_addr = (struct sockaddr_in *)&prim.ssp_addr;			ap = inet_ntop(AF_INET, &in_addr->sin_addr, addr_buf,				       INET6_ADDRSTRLEN);		} else if (AF_INET6 == saddr->sa_family) {			in6_addr = (struct sockaddr_in6 *)&prim.ssp_addr;			ap = inet_ntop(AF_INET6, &in6_addr->sin6_addr, addr_buf,				       INET6_ADDRSTRLEN);		}		if (!ap)			goto err;		printf("%s\n", ap);		return;	}	/* Set the buffer for address parsing.  */	while ('\n' != *p)		p++;	*p = '\0';	prim.ssp_assoc_id = associd;		if (strchr(cp, '.')) {		in_addr = (struct sockaddr_in *)&prim.ssp_addr;		in_addr->sin_port = htons(remote_port);		in_addr->sin_family = AF_INET;		ret = inet_pton (AF_INET, cp, &in_addr->sin_addr);		if (ret <= 0)			goto err;			} else if (strchr(cp, ':')) {		in6_addr = (struct sockaddr_in6 *)&prim.ssp_addr;		in6_addr->sin6_port = htons(remote_port);		in6_addr->sin6_family = AF_INET6;		ret = inet_pton(AF_INET6, cp, &in6_addr->sin6_addr);		if (ret <= 0)			goto err;			} else		goto err;	ret = setsockopt(sk, IPPROTO_SCTP, SCTP_PRIMARY_ADDR,			    &prim, sizeof(struct sctp_prim)); 	if (ret < 0)		goto err;	return;err:	if (!errno)		errno = EINVAL;	fprintf(stderr, "%s: error %s primary: %s.\n", argv0,	        (set)?"setting":"getting", strerror(errno));}static voidpeer_primary_func(char *argv0, int sk, char *cp, int set){	struct sctp_setpeerprim setpeerprim;	struct sockaddr_in *in_addr;	struct sockaddr_in6 *in6_addr;	int peer_prim_len, ret;	char *p = cp;	if (!set) {		goto err;	}	peer_prim_len = sizeof(struct sctp_setpeerprim);	/* Set the buffer for address parsing.  */	while ('\n' != *p)		p++;	*p = '\0';	setpeerprim.sspp_assoc_id = associd;		if (strchr(cp, '.')) {		in_addr = (struct sockaddr_in *)&setpeerprim.sspp_addr;		in_addr->sin_port = htons(local_port);		in_addr->sin_family = AF_INET;		ret = inet_pton (AF_INET, cp, &in_addr->sin_addr);		if (ret <= 0)			goto err;			} else if (strchr(cp, ':')) {		in6_addr = (struct sockaddr_in6 *)&setpeerprim.sspp_addr;		in6_addr->sin6_port = htons(local_port);		in6_addr->sin6_family = AF_INET6;		ret = inet_pton(AF_INET6, cp, &in6_addr->sin6_addr);		if (ret <= 0)			goto err;			} else		goto err;	ret = setsockopt(sk, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR,			    &setpeerprim, sizeof(struct sctp_setpeerprim)); 	if (ret < 0)		goto err;	return;err:	if (!errno)		errno = EINVAL;	fprintf(stderr, "%s: error %s peer_primary: %s.\n", argv0,	        (set)?"setting":"getting", strerror(errno));}static intnodelay_func(char *argv0, int sk, int val, int set){	socklen_t optlen;	int error;	if (set) {		error = setsockopt(sk, SOL_SCTP, SCTP_NODELAY,			(char *)&val, sizeof(val));	} else {		optlen = sizeof(val);		error = getsockopt(sk, SOL_SCTP, SCTP_NODELAY,			(char *)&val, &optlen);	}	if (error != 0) {		fprintf(stderr, "%s: Error setting/getting nodelay: %s.\n",			argv0, strerror(errno));		exit(1);	}	if (!set) {		printf("nodelay is %d.\n", val);	}	return error;}static intmaxseg_func(char *argv0, int sk, int val, int set){	socklen_t optlen;	int error;	if (set) {		error = setsockopt(sk, SOL_SCTP, SCTP_MAXSEG,			(char *)&val, sizeof(val));	} else {		optlen = sizeof(val);		error = getsockopt(sk, SOL_SCTP, SCTP_MAXSEG,			(char *)&val, &optlen);	}	if (error != 0) {		fprintf(stderr, "%s: Error setting/getting maxseg: %s.\n",			argv0, strerror(errno));		exit(1);	}	if (!set) {		printf("maxseg is %d.\n", val);	}	return error;}static intshutdown_func(char *argv0, int *skp, int shutdown_type){	struct msghdr outmessage;	char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];	struct cmsghdr *cmsg;        int error=0, bytes_sent;	struct sctp_sndrcvinfo *sinfo;	struct hostent *hst;	char *sd_type;	int sk = *skp;	if (shutdown_type == SHUTDOWN_ABORT)		sd_type = "ABORT";	else		sd_type = "SHUTDOWN";	/* Verify that the association is present. */	error = test_sk_for_assoc(sk, associd);	if (error != 0) {		printf("The association isn't present yet! Cannot %s!\n", sd_type);		return -1;	}	if (socket_type == SOCK_SEQPACKET) {		/* Set up the destination.  */		if (remote_host) {			hst = gethostbyname(remote_host);			if (hst == NULL) {				hst = gethostbyname2(remote_host, AF_INET6);			}			if (hst == NULL || hst->h_length < 1) {				fprintf(stderr, "%s: bad hostname: %s\n",					argv0, remote_host);				exit(1);			}			ra_family = hst->h_addrtype;			switch (ra_family) {			case AF_INET:				ra_len = sizeof(remote_addr.v4);				ra_raw = &remote_addr.v4.sin_addr;				remote_addr.v4.sin_port = htons(remote_port);				remote_addr.v4.sin_family = AF_INET;				break;			case AF_INET6:				ra_len = sizeof(remote_addr.v6);				ra_raw = &remote_addr.v6.sin6_addr;				remote_addr.v6.sin6_port = htons(remote_port);				remote_addr.v6.sin6_family = AF_INET6;				break;			default:				fprintf(stderr, "Invalid address type.\n");				exit(1);				break;			}			memcpy(ra_raw, hst->h_addr_list[0], hst->h_length);		}		/* Initialize the message struct we use to pass messages to		 * the remote socket.		 */		outmessage.msg_name = &remote_addr;		outmessage.msg_namelen = ra_len;		outmessage.msg_iov = NULL;		outmessage.msg_iovlen = 0;		outmessage.msg_control = outcmsg;		outmessage.msg_controllen = sizeof(outcmsg);		outmessage.msg_flags = 0;		cmsg = CMSG_FIRSTHDR(&outmessage);		cmsg->cmsg_level = IPPROTO_SCTP;		cmsg->cmsg_type = SCTP_SNDRCV;		cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));		outmessage.msg_controllen = cmsg->cmsg_len;		sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);		memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));		if (shutdown_type == SHUTDOWN_ABORT)			sinfo->sinfo_flags |= SCTP_ABORT;		else			sinfo->sinfo_flags |= SCTP_EOF;		sinfo->sinfo_assoc_id = associd;			bytes_sent = sendmsg(sk, &outmessage, 0);		if (bytes_sent != 0) {			printf("Failure:  %s.\n", strerror(errno));			return -1;		}		/* Receive the COMM_LOST or SHUTDOWN_COMP event. */		test_recv_assoc_change(sk);	} else {		if (shutdown_type == SHUTDOWN_ABORT) {			struct  linger {				int  l_onoff; 				int  l_linger;			} data = {1, 0};			error = setsockopt(sk, SOL_SOCKET, SO_LINGER,					   (char *)&data, sizeof(data));			if (error != 0) {				printf("setsockopt failed %s\n", strerror(errno));				exit(1);			}		}		error = close(sk);		if (error != 0) {			printf("close failed %s\n", strerror(errno));			exit(1);		}		*skp = sk = build_endpoint(argv0, local_port);	}	/* Verify that the association is no longer present.  */	error = test_sk_for_assoc(sk, associd);	if (error != 0) {		printf("Successfully %s the original association\n", sd_type);		associd = 0;		new_connection = 1;	} else {		printf("%s failed\n", sd_type);		exit(1);	}	return 0;}static inttest_sk_for_assoc(int sk, sctp_assoc_t assoc_id){	int error = 0;	struct sctp_status status;	socklen_t status_len;	memset(&status, 0, sizeof(status));	if (assoc_id)		status.sstat_assoc_id = assoc_id;	status_len = sizeof(struct sctp_status);	error = getsockopt(sk, SOL_SCTP, SCTP_STATUS,               		(char *)&status, &status_len);	return error;}/* Receive a notification and return the corresponding associd if the event is * SCTP_COMM_UP. Return 0 for any other event. */static sctp_assoc_ttest_recv_assoc_change(int sk){	struct msghdr inmessage;	struct iovec iov;	char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))];	int error;	/* Initialize inmessage with enough space for DATA... */	memset(&inmessage, 0, sizeof(inmessage));	if ((iov.iov_base = malloc(REALLY_BIG)) == NULL) {		printf("%s: Can't allocate memory.\n", __FUNCTION__);		exit(1);	}	iov.iov_len = REALLY_BIG;	inmessage.msg_iov = &iov;	inmessage.msg_iovlen = 1;	/* or a control message.  */	inmessage.msg_control = incmsg;	inmessage.msg_controllen = sizeof(incmsg);	error = recvmsg(sk, &inmessage, MSG_WAITALL);	if (error < 0) {		printf("%s: recvmsg: %s\n", __FUNCTION__, strerror(errno));		exit(1);	}	return test_verify_assoc_change(&inmessage);}/* Verify a notification and return the corresponding associd if the event is * SCTP_COMM_UP. Return 0 for any other event. */static sctp_assoc_ttest_verify_assoc_change(struct msghdr *msg){	union sctp_notification *sn;	if (!(msg->msg_flags & MSG_NOTIFICATION)) {		fprintf(stderr, "%s: Received data when notification is expected\n",		       __FUNCTION__);		exit(1);	}	sn = (union sctp_notification *)msg->msg_iov->iov_base;	if (SCTP_ASSOC_CHANGE != sn->sn_header.sn_type) {		fprintf(stderr, "%s: Received unexpected notification: %d",			__FUNCTION__, sn->sn_header.sn_type);		exit(1);	}	switch(sn->sn_assoc_change.sac_state)	{	case SCTP_COMM_UP:		printf("Recieved SCTP_COMM_UP\n");		break;	case SCTP_COMM_LOST:		printf("Recieved SCTP_COMM_LOST\n");		break;	case SCTP_RESTART:		printf("Recieved SCTP_RESTART\n");		break;	case SCTP_SHUTDOWN_COMP:		printf("Recieved SCTP_SHUTDOWN_COMP\n");		break;	case SCTP_CANT_STR_ASSOC:		printf("Recieved SCTP_CANT_STR_ASSOC\n");		break;	}	if (SCTP_COMM_UP == sn->sn_assoc_change.sac_state)		return sn->sn_assoc_change.sac_assoc_id;	else		return 0;}void print_addr_buf(void * laddrs, int n_laddrs){	void *addr_buf = laddrs;	int i;	for (i = 0; i < n_laddrs; i++) {		addr_buf += print_sockaddr((struct sockaddr *)addr_buf);		printf("\n");	}}int print_sockaddr(struct sockaddr *sa_addr){	struct sockaddr_in *in_addr;	struct sockaddr_in6 *in6_addr;	if (AF_INET == sa_addr->sa_family) {		in_addr = (struct sockaddr_in *)sa_addr;		printf("%d.%d.%d.%d:%d",		       NIPQUAD(in_addr->sin_addr),		       ntohs(in_addr->sin_port));		return sizeof(struct sockaddr_in);	} else {		in6_addr = (struct sockaddr_in6 *)sa_addr;		printf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%d",		       NIP6(in6_addr->sin6_addr),		       ntohs(in6_addr->sin6_port));		return sizeof(struct sockaddr_in6);	}}

⌨️ 快捷键说明

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