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

📄 sctp_darn.c

📁 SCTP 协议实现源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	} /* if (bindx_rem_addrs) */	/* Do we want to run in the non-blocking mode? */	if (nonblocking) {		error = fcntl(retval, F_SETFL, O_NONBLOCK);		if (error != 0) {			fprintf(stderr, "%s: error fcntl: %s.\n",				argv0, strerror(errno));			exit(1);		}	}	if (opt_space) {		sndbuf_func(argv0, retval, opt_space, 1);		rcvbuf_func(argv0, retval, opt_space, 1);	}	return retval;} /* build_endpoint() *//* Convenience structure to determine space needed for cmsg. */typedef union {	struct sctp_initmsg init;	struct sctp_sndrcvinfo sndrcvinfo;} _sctp_cmsg_data_t;/* Listen on the socket, printing out anything that arrives.  */intcommand_listen(char *argv0, int sk){	char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))];	struct iovec iov;	struct msghdr inmessage;	sockaddr_storage_t msgname;	char message[REALLY_BIG];	int done = 0;	int error;	int c;	int recvsk = 0; 	/* Mark sk as being able to accept new associations */	error = listen(sk, 5);	if (error != 0) {		printf("\n\n\t\tlisten Failure:  %s.\n\n\n",		       strerror(errno));		exit(1);	}	if (nonblocking) {		if (!interactive_mode) {			printf("Use -I for interactive mode with");		       printf("	-n nonblocking\n");		       exit(1);		 }	}	/* Initialize the global value for interactive mode functions.  */	if (interactive_mode) {		inter_sk = sk;	}	/* 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", argv0);		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);	inmessage.msg_name = &msgname;	inmessage.msg_namelen = sizeof(msgname);	printf("%s listening...\n", argv0);	/* Get the messages sent */	done = 0;	while (!done) {		if (interactive_mode) {			/* Read from the user.  */			if (remote_host) {				printf("%s:%d-%s:%d Interactive mode> ",					local_host, local_port, remote_host,					remote_port);			} else {				printf("%s:%d-", local_host, local_port);				if (associd) {					print_sockaddr(&remote_addr.sa);				} else {					printf("?:%d", remote_port);				}				printf(" Interactive mode> ");			}			fflush(stdout);			if (NULL == fgets(message, REALLY_BIG, stdin)) {				done = 1;				continue;			}			if (0 <= (c = parse_inter_commands(argv0, message,				0))) {				if (INTER_RCV != c) {					continue;				}			} else {				continue;			}		}		if (socket_type == SOCK_STREAM) {			socklen_t len = 0;			if (!recvsk) {				if ((recvsk = accept(sk, NULL, &len)) < 0) {					fprintf(stderr, "%s: error: %s.\n",						argv0, strerror(errno));					exit(1);				}			}		} else {			recvsk = sk;		}		error = recvmsg(recvsk, &inmessage, MSG_WAITALL);		if (error < 0) {			if (nonblocking && (EAGAIN == errno)) {				error = 0;				continue;			}			if (socket_type == SOCK_STREAM) {				if (ENOTCONN != errno)					break;				printf("No association is present now!!\n");				close(recvsk);				recvsk = 0;				continue;			}			break;		}		test_print_message(sk, &inmessage, error);		/* Update the associd when a notification is received on a		 * UDP-style socket.		 */		if (inmessage.msg_flags & MSG_NOTIFICATION)			associd = test_verify_assoc_change(&inmessage);		if (echo) {			if( !(MSG_NOTIFICATION & inmessage.msg_flags)) {				sendto(sk, inmessage.msg_iov->iov_base,				       error, 0, (struct sockaddr *)&msgname,				       sizeof(msgname));			}		}		inmessage.msg_control = incmsg;		inmessage.msg_controllen = sizeof(incmsg);		inmessage.msg_name = &msgname;		inmessage.msg_namelen = sizeof(msgname);		iov.iov_len = REALLY_BIG;		/* Verify that the association is no longer present.  */		if (0 != test_sk_for_assoc(recvsk, associd)) {			printf("No association is present now!!\n");			if (socket_type == SOCK_STREAM) {				close(recvsk);				recvsk = 0;			}		}	}	if (error < 0) {		fprintf(stderr, "%s: error: %s.\n",			argv0, strerror(errno));		exit(1);	}	return error;} /* command_listen() *//* Read lines from stdin and send them to the socket.  */intcommand_send(char *argv0, int *skp){	struct msghdr outmsg;	struct iovec iov;	int done = 0;	char message[REALLY_BIG];	struct hostent *hst;	int c;	struct sockaddr *addrs;	int msglen;	int error = 0;	int sk = *skp;	/* Set up the destination.  */	if (remote_host != NULL) {		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;			remote_addr.v6.sin6_scope_id = if_index;			break;		default:			fprintf(stderr, "Invalid address type.\n");			exit(1);			break;		}		memcpy(ra_raw, hst->h_addr_list[0], hst->h_length);	}	/* Initialize the global value for interactive mode functions.  */	if (interactive_mode) {		inter_sk = sk;	}	printf("%s ready to send...\n", argv0);	while (!done) {		/* Read from the user.  */		if (remote_host) {			if (interactive_mode) {				printf("%s:%d-%s:%d Interactive mode> ",					local_host, local_port, remote_host,					remote_port);			} else {				printf("%s:%d-%s:%d> ",				       local_host, local_port,				       remote_host, remote_port);			}		} else {			printf("%s:%d-", local_host, local_port);			if (associd) {				print_sockaddr(&remote_addr.sa);			} else {				printf("XXXXXX:%d", remote_port);			}			if (interactive_mode) {				printf(" Interactive mode> ");			} else {				printf("> ");			}		}		fflush(stdout);		if (NULL == fgets(message, REALLY_BIG, stdin)) {			done = 1;			continue;		}		if (interactive_mode) {			/* This is the send only agent.  */			if (0 <= (c = parse_inter_commands(argv0, message,				1))) {				if (INTER_SND == c) {					iov.iov_base = inter_outbuf;					msglen = inter_outlen;					iov.iov_len = msglen;				} else {					continue;				}			} else {				continue;			}		} else {			/* Send to our neighbor.  */			msglen = strlen(message) + 1;			iov.iov_len = msglen;		}		/* For a UDP-style socket, verify if an existing association		 * has gone. If so, receive the pending SCTP_ASSOC_CHANGE		 * notification.		 */		if ((SOCK_SEQPACKET == socket_type) && associd &&		    (0 != test_sk_for_assoc(sk, associd))) {			associd = test_recv_assoc_change(sk);			printf("Old association gone, Starting a new one!\n");			new_connection = 1;		}		if (new_connection && connectx_count != 0) {			/* Do a sctp_connectx() to establish a connection. */			error = connectx_func(argv0, sk, connectx_addrs,					      connectx_count);			if (0 != error) {				if (error == -2) {					printf("Connection refused\n");					if (SOCK_SEQPACKET == socket_type) {						associd = test_recv_assoc_change(sk);					}					continue;				}				fprintf(stderr, "connectx failed.\n");				exit(1);			}			if (SOCK_SEQPACKET == socket_type) {				associd = test_recv_assoc_change(sk);			} else {				associd = 1;			}			int rc = sctp_getpaddrs(sk, associd, &addrs);			if (0 >= rc) {				if (rc == 0) {					fprintf(stderr, "sctp_getpaddrs failed, no peers.\n");				} else {					fprintf(stderr, "sctp_getpaddrs failed %s(%d).\n", strerror(errno), errno);				}				exit(1);			}			printf("New connection, peer addresses\n");			print_addr_buf(addrs, rc);			ra_family = addrs[0].sa_family;			switch (ra_family) {			case AF_INET:				ra_len = sizeof(remote_addr.v4);				break;			case AF_INET6:				ra_len = sizeof(remote_addr.v6);				break;			default:				fprintf(stderr, "Invalid address type.\n");				exit(1);			}			memcpy(&remote_addr, &addrs[0], ra_len);			sctp_freepaddrs(addrs);			new_connection = 0;		}		do {			if (SOCK_SEQPACKET == socket_type ||			    (connectx_count == 0 && new_connection)) {				/* Initialize the message struct we use to pass				 * messages to the remote socket.				 */				if (!interactive_mode) {					iov.iov_base = message;					iov.iov_len = msglen;				}				outmsg.msg_iov = &iov;				outmsg.msg_iovlen = 1;				outmsg.msg_control = NULL;				outmsg.msg_controllen = 0;				outmsg.msg_name = &remote_addr;				outmsg.msg_namelen = ra_len;				error = sendmsg(sk, &outmsg, 0);			} else {				error = send(sk, message, msglen, 0);				if (error == -1 && errno == EPIPE) {					error = close(sk);					if (error != 0) {						fprintf(stderr, "close failed %s\n", strerror(errno));						exit(1);					}					*skp = sk = build_endpoint(argv0, local_port);					break;				}			}			if (error != msglen) {				fprintf(stderr, "%s: error: %s.\n",					argv0, strerror(errno));				if (nonblocking && EAGAIN == errno) {					if (interactive_mode) {						break;					}					continue;				}				exit(1);			} else {				break;			}		} while (error != msglen);		/* If this is the first message sent over a UDP-style socket,		 * get the associd from the SCTP_ASSOC_CHANGE notification.		 */		if ((SOCK_SEQPACKET == socket_type) && (0 == associd))			associd = test_recv_assoc_change(sk);		/* Verify there is no association.  */		if (0 != test_sk_for_assoc(sk, associd)) {			printf("No association is present now!!\n");			new_connection = 1;		} else {			if (new_connection) {				int rc = sctp_getpaddrs(sk, associd, &addrs);				if (0 >= rc) {					if (rc == 0) {						fprintf(stderr, "sctp_getpaddrs failed, no peers.\n");					} else {						fprintf(stderr, "sctp_getpaddrs failed %s(%d).\n", strerror(errno), errno);					}					exit(1);				}				printf("New connection, peer addresses\n");				print_addr_buf(addrs, rc);				sctp_freepaddrs(addrs);				new_connection = 0;			}		}		/* Clean up.  */		if (interactive_mode) {			free(inter_outbuf);			inter_outbuf = NULL;		}	} /* while(!done) */	return error;} /* command_send() *//* Listen on the array of sockets, printing out anything that arrives.  */intcommand_poll(char *argv0){	char incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))];	struct iovec iov;	struct msghdr inmessage;	int done = 0;	int error = 0;	int max_fd, i, ret;	int size;	fd_set *ibitsp = NULL;	fd_set *obitsp = NULL;	fd_set *xbitsp = NULL;	struct msghdr outmsg;	struct hostent *hst;	int msglen;	int temp_fd, temp_set;	/* If a remote host is specified, initialize the destination. */	if (remote_host) {		/* Set up the destination.  */		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;			remote_addr.v6.sin6_scope_id = if_index;			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.	 	 */		outmsg.msg_iov = &iov;		outmsg.msg_iovlen = 1;		outmsg.msg_control = NULL;		outmsg.msg_controllen = 0;		outmsg.msg_name = &remote_addr;		outmsg.msg_namelen = ra_len;	}	max_fd = -1;	/* Set all of the sockets to be ready for listening. */	if (use_poll) {		for (i = 0; i < poll_skn; i++) {			error = listen(poll_fds[i].fd, 1);			if (error != 0) {				printf("%s: Listen failed on socket number ",					argv0);				printf("%d: %s.\n", i, strerror(errno));				exit(1);			}		}		printf("%s listening...\n", argv0);	} else {		for (i = 0; i < poll_skn; i++) {			error = listen(poll_sks[i], 1);			if (error != 0) {				printf("%s: Listen failed on socket number ",					argv0);				printf("%d: %s.\n", i, strerror(errno));				exit(1);			}			if (poll_sks[i] > max_fd) {				max_fd = poll_sks[i];			}		}		printf("%s listening...\n", argv0);		size = howmany(max_fd + 1, NFDBITS) * sizeof(fd_mask);		if ((ibitsp = (fd_set *)malloc(size)) == NULL) {			printf("%s: Can't allocate memory.\n", argv0);			exit(1);		}		if ((obitsp = (fd_set *)malloc(size)) == NULL) {			printf("%s: Can't allocate memory.\n", argv0);			exit(1);		}		if ((xbitsp = (fd_set *)malloc(size)) == NULL) {			printf("%s: Can't allocate memory.\n", argv0);			exit(1);		}		memset(ibitsp, 0, size);		memset(obitsp, 0, size);		memset(xbitsp, 0, size);	}	/* 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", argv0);		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);	done = 0;	/* Set the default send message size.  */	if (!poll_snd_size) {

⌨️ 快捷键说明

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