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

📄 sctp_darn.c

📁 SCTP 协议实现源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		poll_snd_size = POLL_SND_SIZE;	}	while (!done) {		if (use_poll) {			for (i = 0; i < poll_skn; i++) {				poll_fds[i].events = POLLIN;			}			if (remote_host) {				/* Poll output on the first socket.  */				poll_fds[0].events |= POLLOUT;			}			if ((ret = poll(poll_fds, poll_skn, -1))) {				if (ret == -1) {					break;				}			}		} else {			for (i = 0; i < poll_skn; i++) {				FD_SET(poll_sks[i], ibitsp);				FD_SET(poll_sks[i], xbitsp);			}			if (remote_host) {				/* Only select output on the first socket.  */				FD_SET(poll_sks[0], obitsp);			}			if ((ret = select(max_fd + 1, ibitsp, obitsp, xbitsp,				(struct timeval *)0)) < 0) {				if (ret == -1) {					break;				}			}		}		if (remote_host) {			if (use_poll) {				temp_set = poll_fds[0].revents & POLLOUT;				temp_fd = poll_fds[0].fd;			} else {				temp_set = FD_ISSET(poll_sks[0], obitsp);				temp_fd = poll_sks[0];			}			if (temp_set) {				inter_outbuf = gen_message(poll_snd_size);				if (!inter_outbuf) {					fprintf(stderr,					"Cannot allocate out message.\n");					exit(1);				}				iov.iov_base = inter_outbuf;				msglen = poll_snd_size;				iov.iov_len = msglen;				error = sendmsg(temp_fd, &outmsg, 0);				fprintf(stderr,					"sent a message, msglen = %d\n",					msglen);				if (error != msglen) {					fprintf(stderr, "%s: error: %s.\n",						argv0, strerror(errno));					if ((!nonblocking) ||					    (EAGAIN != errno)) {						exit(1);					}				}				/* Clean up.  */				free(inter_outbuf);				inter_outbuf = NULL;			}		} /* while(!done) */		for (i = 0; !done && (i < poll_skn); i++) {			if (use_poll) {				temp_set = poll_fds[i].revents & POLLIN;				temp_fd = poll_fds[i].fd;			} else {				temp_set = FD_ISSET(poll_sks[i], ibitsp);				temp_fd = poll_sks[i];			}			if (temp_set) {				error = recvmsg(temp_fd, &inmessage,					MSG_WAITALL);				if (error < 0) {					if ((EAGAIN == errno)) {						error = 0;						continue;					}					else {						fprintf(stderr,							"%s: error: %s.\n",							argv0,							strerror(errno));						exit(1);					}				}				test_print_message(temp_fd, &inmessage, error);				inmessage.msg_control = incmsg;				inmessage.msg_controllen = sizeof(incmsg);				iov.iov_len = REALLY_BIG;			}			/* 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);			/* Verify there is no association. */			if (0 != test_sk_for_assoc(poll_sks[i], associd)) {				printf("No association is present in sk "				       "No.%d now!!\n",i);			}		}	}	if (!use_poll) {		free(ibitsp);		free(obitsp);		free(xbitsp);	}	return error;} /* command_poll() *//******************************************************************** * 3rd Level Abstractions ********************************************************************/#define FPS(arg) fprintf(stderr, arg)voidusage(char *argv0){	/*	 * The bindx options, --bindx-add and --bindx-rem, are added to	 *	 * 1. provide first testcases for the new bindx system call	 *	 * 2. continue to grow sctp_darn with more functions and	 * features so it will be equivalent to the "sock" tool for	 * TCP as for SCTP.	 *	 * FIXME -	 *	 * It is not very effective to use these two options in the	 * current command line mode of sctp_darn. For example, the	 * --bindx-rem option can only be used in conjunction with the	 * --bindx-add simply to test the function in the kernel	 * path. Ideally, bindx needs to be tested by a tool which	 * provides an interactive mode for users to change parameters	 * and configuration dynamically with existing endpoints and	 * associations.	 */	fprintf(stderr, "Usage: %s -H <localhost> -P <localport> "		"[-h <remotehost>] [-p <remoteport>] -l|s\n"		" -H, --local\t\tspecify one of the local addresses,\n"		" -P, --local-port\tspecify the port number for local addresses,\n"		" -h, --remote\t\tspecify the peer address,\n"		" -p, --remote-port\tspecify the port number for the peer address,\n"		" -l, --listen\t\tprint messages received from the peer,\n"		" -s, --send\t\tsend messages to the peer,\n"		" -B, --bindx-add"		"\tadd the specified address(es) as additional bind\n"		"\t\t\taddresses to the local socket. Multiple addresses can\n"		"\t\t\tbe specified by using this argument multiple times.\n"		"\t\t\tFor example, '-B 10.0.0.1 -B 20.0.0.2'.\n"		" -b, --bindx-rem"		"\tremove the specified address(es) from the bind\n"		"\t\t\taddresses of the local socket. Multiple addresses can\n"		"\t\t\tbe specified by using this argument multiple times.\n"		"\t\t\tFor example, '-b 10.0.0.1 -b 20.0.0.2'.\n"		" -c, --connectx"		"\t\tuse the specified address(es) for connection to the\n"		"\t\t\tpeer socket. Multiple addresses can be specified by\n"		"\t\t\tusing this argument multiple times.\n"		"\t\t\tFor example, '-c 10.0.0.1 -c 20.0.0.2'.\n"		"\t\t\tThis option is incompatible with the -h option.\n"		" -I\t\t\tuse the interactive mode.\n"		" -i\t\t\tsetup the specified number of endpoints by using the\n"		"\t\t\tspecified local host (-H) and local port (-P). The port\n"        	"\t\t\tnumber will be incremented by one for each additional\n"        	"\t\t\tendpoint.  All of these endpoints will be listening.\n"		"\t\t\tIf a remote host (-h) and a remote port are also\n"		"\t\t\tspecified, the first endpoint will start sending fixed\n"		"\t\t\tsized messages to the remote host.\n"		" -m\t\t\tspecify the sockopt sndbuf/rcvbuf size.\n"		" -n\t\t\tset the socket(s) to be in the non-blocking mode.\n"		"\t\t\tcollect messages from stdin and deliver them to the\n"		"\t\t\tpeer,\n"		"--use-poll\t\tuse system call poll() for polling among the\n"		"\t\t\tnumber of endpoints specified by the -i option. Without\n"		"\t\t\tthis option, select() would be used as default.\n"		" -t\t\t\tuse SOCK_STREAM tcp-style sockets.\n"		" -z\t\t\tspecify the message size to be sent.  The default\n"		"\t\t\tmessage size generated would be 16K.\n"		" --interface=\"ifname\"\tselect interface for sin6_scope_id.\n",		argv0);}/* This function checks messages to see if they are of type 'event' * and if they are well-formed. */intuser_test_check_message(struct msghdr *msg,                        int controllen,                        sctp_cmsg_t event){	if (msg->msg_controllen != controllen) {		fprintf(stderr,			"Got control structure of length %d, not %d\n",			msg->msg_controllen, controllen);		exit(1);	}	if (controllen > 0 && event != CMSG_FIRSTHDR(msg)->cmsg_type) {		fprintf(stderr, "Wrong kind of event: %d, not %d\n",			CMSG_FIRSTHDR(msg)->cmsg_type, event);		exit(1);	}	return 1;} /* user_test_check_message() *//* Add another address represented as the string 'parm' to the list * addrs.  The argument count is the number of addrs on input and is * adjusted for output. */struct sockaddr *append_addr(const char *parm, struct sockaddr *addrs, int *ret_count){	struct sockaddr *new_addrs = NULL;	void *aptr;	struct sockaddr *sa_addr;	struct sockaddr_in *b4ap;	struct sockaddr_in6 *b6ap;	struct hostent *hst4 = NULL;	struct hostent *hst6 = NULL;	int i4 = 0;	int i6 = 0;	int j;	int orig_count = *ret_count;	int count = orig_count;	/* Get the entries for this host.  */	hst4 = gethostbyname(parm);	hst6 = gethostbyname2(parm, AF_INET6);	if ((NULL == hst4 || hst4->h_length < 1)	    && (NULL == hst6 || hst6->h_length < 1)) {		fprintf(stderr, "bad hostname: %s\n", parm);		goto finally;	}	/* Figure out the number of addresses.  */	if (NULL != hst4) {		for (i4 = 0; NULL != hst4->h_addr_list[i4]; ++i4) {			count++;		}	}	if (NULL != hst6) {		for (i6 = 0; NULL != hst6->h_addr_list[i6]; ++i6) {			count++;		}	}	/* Expand memory for the new addresses.  Assume all the addresses 	 * are v6 addresses.	 */	new_addrs = (struct sockaddr *)		realloc(addrs, sizeof(struct sockaddr_in6) * count);	if (NULL == new_addrs) {		count = *ret_count;		goto finally;	}	/* Skip the existing addresses. */	aptr = new_addrs; 	for (j = 0; j < orig_count; j++) {		sa_addr = (struct sockaddr *)aptr;		switch(sa_addr->sa_family) {		case AF_INET:			aptr += sizeof(struct sockaddr_in);			break;		case AF_INET6:			aptr += sizeof(struct sockaddr_in6);			break;		default:			count = orig_count;			goto finally;		}	}							/* Put the new addresses away.  */	if (NULL != hst4) {		for (j = 0; j < i4; ++j) {			b4ap = (struct sockaddr_in *)aptr;			bzero(b4ap, sizeof(*b4ap));			b4ap->sin_family = AF_INET;			b4ap->sin_port = htons(local_port);			bcopy(hst4->h_addr_list[j], &b4ap->sin_addr,			      hst4->h_length);			aptr += sizeof(struct sockaddr_in);		} /* for (loop through the new v4 addresses) */	}	if (NULL != hst6) {		for (j = 0; j < i6; ++j) {			b6ap = (struct sockaddr_in6 *)aptr;			bzero(b6ap, sizeof(*b6ap));			b6ap->sin6_family = AF_INET6;			b6ap->sin6_port =  htons(local_port);			b6ap->sin6_scope_id = if_index;			bcopy(hst6->h_addr_list[j], &b6ap->sin6_addr,			      hst6->h_length);			aptr += sizeof(struct sockaddr_in6);		} /* for (loop through the new v6 addresses) */	} finally:	*ret_count = count;	return new_addrs;} /* append_addr() */static intparse_inter_commands(char *argv0, char *input, int snd_only){	int i;	char *p;	int len;	int set = 0;	int val;	struct sockaddr *tmp_addrs = NULL;	p = input;	if (*p == '?' || *p == '\n') {		printf("Interactive commands:\n");		printf("snd=<int>        - Do a sendmsg with the specified");		printf(" length.\n");		printf("rcv=<int>        - Do a recvmsg.");		printf("The length is ignored for now.\n");		printf("bindx-add=<addr> - Add a local address");		printf(" with bindx. \n");		printf("bindx-rem=<addr> - Remove a local address");		printf(" with bindx. \n");		printf("rcvbuf=<int>     - Get/Set receive buffer size\n");		printf("sndbuf=<int>     - Get/Set send buffer size.\n");		printf("primary=<addr>   - Get/Set association's primary\n");		printf("peer_primary=addr- Set association's peer_primary\n");		printf("maxseg=<int>     - Get/Set Maximum fragment size.\n");		printf("nodelay=<0|1>    - Get/Set NODELAY option.\n");		printf("shutdown         - Shutdown the association.\n");		printf("abort            - Abort the association.\n");		printf("?                - Help. Display this message.\n");		return -1;	}	for (i = 0; i < REALLY_BIG; i++) {		if (('=' == *p) ||		    ('?' == *p) ||		    ('\n' == *p)) {			if ('=' == *p) {				set = 1;			}			*p++ = '\0';			break;		}		p++;	}	if (i >= REALLY_BIG) {		printf("Invalid input.\n");		return -1;	}	i = 0;	while (NULL != inter_commands[i].cmd) {		if (!strcmp(input, inter_commands[i].cmd)) {			switch (i) {			case INTER_SND:				if (snd_only) {					if (*p < '0' || *p > '9') {						goto err_input;					}					snd_func(p);				} else {					goto err_input;				}				break;			case INTER_RCV:				if (snd_only) {					goto err_input;				}				break;			case INTER_SNDBUF:				if (set) {					if (*p < '0' || *p > '9') {						goto err_input;					}				}				len = (set) ? atoi(p) : 0;				sndbuf_func(argv0, inter_sk, len, set);				break;			case INTER_RCVBUF:				if (set) {					if (*p < '0' || *p > '9') {						goto err_input;					}				}				len = (set) ? atoi(p) : 0;				rcvbuf_func(argv0, inter_sk, len, set);				break;			case INTER_BINDX_ADD:				tmp_addrs = get_bindx_addr(p, &len);				bindx_func(argv0, inter_sk, tmp_addrs, len,					SCTP_BINDX_ADD_ADDR, local_port);				free(tmp_addrs);				break;			case INTER_BINDX_REM:				tmp_addrs = get_bindx_addr(p, &len);				bindx_func(argv0, inter_sk, tmp_addrs, len,					SCTP_BINDX_REM_ADDR, local_port);				free(tmp_addrs);				break;			case INTER_SET_PRIM:				primary_func(argv0, inter_sk, p, set);				break;			case INTER_SET_PEER_PRIM:				peer_primary_func(argv0, inter_sk, p, set);				break;			case INTER_SHUTDOWN:				shutdown_func(argv0, &inter_sk, SHUTDOWN_SHUTDOWN);				break;			case INTER_ABORT:				shutdown_func(argv0, &inter_sk, SHUTDOWN_ABORT);				break;			case INTER_NODELAY:				if (set) {					if (*p < '0' || *p > '9') {						goto err_input;					}				}				val = (set) ? atoi(p) : 0;				nodelay_func(argv0, inter_sk, val, set);				break;			case INTER_MAXSEG:				if (set) {					if (*p < '0' || *p > '9') {						goto err_input;					}				}				val = (set) ? atoi(p) : 0;				maxseg_func(argv0, inter_sk, val, set);				break;			default:				goto err_input;				break;			}			return i;		}		i++;	}err_input:	printf("Invalid input.\n");	return -1;} /* parse_inter_commands() */static char *gen_message(int len){	char *buf;	char *p;	int i;	buf = malloc(len);	if (NULL != buf) {		for (i = 0, p = buf; i < len; i++, p++) {			if (gen_data > GEN_DATA_LAST) {				gen_data = GEN_DATA_FIRST;			}			*p = gen_data++;		}	}	return(buf);} /* gen_message() */static voidsnd_func(char *input){	int len;	len = atoi(input);	if (!(inter_outbuf = gen_message(len))) {		fprintf(stderr, "Cannot allocate out message.\n");		exit(1);	}	inter_outlen = len;} /* snd_func() */static voidsndbuf_func(char *argv0, int sk, int len, int set){	int error;	socklen_t optlen;	if (set) {		error = setsockopt(sk, SOL_SOCKET, SO_SNDBUF,			(char *)&len, sizeof(len));	} else {		optlen = sizeof(len);		error = getsockopt(sk, SOL_SOCKET, SO_SNDBUF,			(char *)&len, &optlen);	}	if (error != 0) {		fprintf(stderr, "%s: Error setting/getting sndbuf: %s.\n",			argv0, strerror(errno));		exit(1);	}	if (!set) {		printf("sndbuf is %d.\n", len);	}} /* sndbuf_func() */static voidrcvbuf_func(char *argv0, int sk, int len, int set){	int error;	socklen_t optlen;	if (set) {		error = setsockopt(sk, SOL_SOCKET, SO_RCVBUF,			(char *)&len, sizeof(len));	} else {		optlen = sizeof(len);		error = getsockopt(sk, SOL_SOCKET, SO_RCVBUF,			(char *)&len, &optlen);	}	if (error != 0) {		fprintf(stderr, "%s: Error setting/getting rcvbuf: %s.\n",			argv0, strerror(errno));		exit(1);	}	if (!set) {		printf("rcvbuf is %d.\n", len);

⌨️ 快捷键说明

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