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

📄 sockd_io.c

📁 sock protocol ,it is useful!
💻 C
📖 第 1 页 / 共 3 页
字号:
	SASSERTX(io->allocated);	if (io->rule.log.disconnect) {		char logmsg[MAXHOSTNAMELEN * 2 + 1024];		char in[MAXSOCKADDRSTRING], out[MAXSOCKADDRSTRING];		/* LINTED pointer casts may be troublesome */		sockaddr2string((struct sockaddr *)&io->in.raddr, in, sizeof(in));		switch (io->state.command) {			case SOCKS_BIND:			case SOCKS_BINDREPLY:			case SOCKS_CONNECT:				/* LINTED pointer casts may be troublesome */				sockaddr2string((struct sockaddr *)&io->out.raddr, out,				sizeof(out));				break;			case SOCKS_UDPASSOCIATE:				snprintf(out, sizeof(out), "`world'");				break;			default:				SERRX(io->state.command);		}		snprintf(logmsg, sizeof(logmsg),		"%s: %lu -> %s -> %lu,  %lu -> %s -> %lu",		protocol2string(io->state.protocol),		(unsigned long)io->in.written, in, (unsigned long)io->in.read,		(unsigned long)io->out.written, out, (unsigned long)io->out.read);		errno = errno_s;		if (fd < 0)			switch (status) {				case IO_SRCBLOCK:					slog(LOG_INFO, "%s: delayed sourceblock", logmsg);					break;				case IO_ERROR:					swarn("%s: connection error", logmsg);					break;				case IO_CLOSE:					slog(LOG_INFO, "%s: connection closed", logmsg);					break;				case IO_TIMEOUT:					slog(LOG_INFO, "%s: connection i/o expired", logmsg);					break;				default:					slog(LOG_INFO, "%s: short read/write", logmsg);			}		else if (fd == io->in.s || fd == io->control.s) {			switch (status) {				case IO_SRCBLOCK:					slog(LOG_INFO, "%s: delayed sourceblock", logmsg);					break;				case IO_ERROR:					swarn("%s: client error", logmsg);					break;				case IO_CLOSE:					slog(LOG_INFO, "%s: client closed", logmsg);					break;				case IO_TIMEOUT:					slog(LOG_INFO, "%s: client i/o expired", logmsg);					break;				default:					slog(LOG_INFO, "%s: client short read/write", logmsg);			}		}		else if (fd == io->out.s) {			switch (status) {				case IO_SRCBLOCK:					slog(LOG_INFO, "%s: delayed sourceblock", logmsg);					break;				case IO_ERROR:					swarn("%s: remote error", logmsg);					break;				case IO_CLOSE:					slog(LOG_INFO, "%s: remote closed", logmsg);					break;				case IO_TIMEOUT:					slog(LOG_INFO, "%s: remote i/o expired", logmsg);					break;				default:					slog(LOG_INFO, "%s: remote short read/write", logmsg);			}		}		else			SERRX(fd);	}	/* this may end up logging same disconnect twice, but not our choice. */	if (io->acceptrule.log.disconnect) {		struct connectionstate_t state = io->state;		state.command = SOCKS_DISCONNECT;		iolog(&io->acceptrule, &state, OPERATION_DISCONNECT, &io->src, &io->dst,		NULL, 0);	}	close_iodescriptors(io);	io->allocated = 0;	if (mother != -1) {		const char b = SOCKD_FREESLOT;		/* ack io slot free. */		if (writen(mother, &b, sizeof(b)) != sizeof(b))			swarn("%s: writen(): mother", function);	}	proctitleupdate();}voidclose_iodescriptors(io)	const struct sockd_io_t *io;{	close(io->in.s);	close(io->out.s);	switch (io->state.command) {		case SOCKS_CONNECT:			break;		case SOCKS_BIND:		case SOCKS_BINDREPLY:			if (!io->state.extension.bind)				break;			/* else: */ /* FALLTHROUGH */		case SOCKS_UDPASSOCIATE:			close(io->control.s);			break;		default:			SERRX(io->state.command);	}}intrecv_io(s, io)	int s;	struct sockd_io_t *io;{	const char *function = "recv_io()";	int i, fdexpect, fdreceived;	size_t length = 0;	struct iovec iovec[1];	struct msghdr msg;	CMSG_AALLOC(sizeof(int) * FDPASS_MAX);	if (io == NULL) {	/* child semantics; find a io ourselves. */		for (i = 0; i < ioc; ++i)			if (!iov[i].allocated) {				io = &iov[i];				break;			}		if (io == NULL) {			/*			 * either mother died/closed connection, or there is another error.			 * Both cases should be rare so try to find out what the problem is.			 */			char buf;			if (recv(s, &buf, sizeof(buf), MSG_PEEK) > 0)				SERRX(allocated());			return -1;		}	}	iovec[0].iov_base		= io;	iovec[0].iov_len		= sizeof(*io);	length				  += iovec[0].iov_len;	msg.msg_iov				= iovec;	msg.msg_iovlen			= ELEMENTS(iovec);	msg.msg_name			= NULL;	msg.msg_namelen		= 0;	CMSG_SETHDR_RECV(sizeof(cmsgmem));	if (recvmsgn(s, &msg, 0, length) != (ssize_t)length) {		swarn("%s: recvmsgn()", function);		return -1;	}	/* figure out how many descriptors we are supposed to be passed. */	switch (io->state.command) {		case SOCKS_BIND:		case SOCKS_BINDREPLY:			if (io->state.extension.bind)				fdexpect = 3;	/* in, out, control. */			else				fdexpect = 2;	/* in and out. */			break;		case SOCKS_CONNECT:			fdexpect = 2;	/* in and out */			break;		case SOCKS_UDPASSOCIATE:			fdexpect = 3;	/* in, out, and control */			break;		default:			SERRX(io->state.command);	}	/* calculate expected datalen */#if !HAVE_DEFECT_RECVMSG	SASSERT(CMSG_GETLEN(msg) == sizeof(int) * fdexpect);#endif	/*	 * Get descriptors sent us.	 */	fdreceived = 0;	CMSG_GETOBJECT(io->in.s, sizeof(io->in.s) * fdreceived++);	CMSG_GETOBJECT(io->out.s, sizeof(io->out.s) * fdreceived++);	switch (io->state.command) {		case SOCKS_BIND:		case SOCKS_BINDREPLY:			if (io->state.extension.bind)				CMSG_GETOBJECT(io->control.s, sizeof(io->control.s) * fdreceived++);			else				io->control.s = -1;			break;		case SOCKS_CONNECT:			io->control.s = -1;			break;		case SOCKS_UDPASSOCIATE:			CMSG_GETOBJECT(io->control.s, sizeof(io->control.s) * fdreceived++);			break;		default:			SERRX(io->state.command);	}	time(&io->time);	io->allocated = 1;#if DEBUG	printfd(io, "received");#endif	return 0;}static voidio_clearset(io, set)	const struct sockd_io_t *io;	fd_set *set;{	FD_CLR(io->in.s, set);	FD_CLR(io->out.s, set);	switch (io->state.command) {		case SOCKS_CONNECT:			break;		case SOCKS_BIND:		case SOCKS_BINDREPLY:			if (!io->state.extension.bind)				break;			/* else: */ /* FALLTHROUGH */		case SOCKS_UDPASSOCIATE:			FD_CLR(io->control.s, set);			break;		default:			SERRX(io->state.command);	}}static intallocated(void){	int i, alloc;	for (i = 0, alloc = 0; i < ioc; ++i)		if (iov[i].allocated)			++alloc;	return alloc;}static voiddoio(mother, io, rset, wset, flags)	int mother;	struct sockd_io_t *io;	fd_set *rset, *wset;	int flags;{	const char *function = "doio()";	/* CONSTCOND */	char buf[MAX(SOCKD_BUFSIZETCP, SOCKD_BUFSIZEUDP)	+ sizeof(struct udpheader_t)];	ssize_t r, w;	SASSERTX(io->allocated);	SASSERTX((FD_ISSET(io->in.s, rset) && FD_ISSET(io->out.s, wset))	||			(FD_ISSET(io->in.s, wset) && FD_ISSET(io->out.s, rset))	||			(flags & MSG_OOB)	||			(io->control.s != -1 && FD_ISSET(io->control.s, rset)));	switch (io->state.protocol) {		case SOCKS_TCP: {			int bad;			/* from in to out... */			if (FD_ISSET(io->in.s, rset) && FD_ISSET(io->out.s, wset)) {				bad = -1;				r = io_rw(&io->in, &io->out, &bad, buf, flags);				if (bad != -1) {					delete_io(mother, io, bad, r);					return;				}				iolog(&io->rule, &io->state, OPERATION_IO, &io->src, &io->dst, buf,				(size_t)r);			}			/* ... and out to in. */			if (FD_ISSET(io->out.s, rset) && FD_ISSET(io->in.s, wset)) {				bad = -1;				r = io_rw(&io->out, &io->in, &bad, buf, flags);				if (bad != -1) {					delete_io(mother, io, bad, r);					return;				}				iolog(&io->rule, &io->state, OPERATION_IO, &io->dst, &io->src, buf,				(size_t)r);			}			break;		}		case SOCKS_UDP: {			struct udpheader_t header;			socklen_t fromlen;			int permit;			/*			 * UDP is sadly considerably more complex than TCP;			 * need to check rules on each packet, need to check if it			 * was received from expected src, etc.			 */			/* udp to relay from client to destination? */			if (FD_ISSET(io->in.s, rset) && FD_ISSET(io->out.s, wset)) {				const int lflags = flags & ~MSG_OOB;				struct sockaddr from;				fromlen = sizeof(from);				if ((r = recvfrom(io->in.s, buf, io->out.sndlowat, lflags, &from,				&fromlen)) == -1) {					delete_io(mother, io, io->in.s, r);					return;				}				UDPFROMLENCHECK(io->in.s, fromlen);				/*				 * If client hasn't sent us it's address yet we have to				 * assume the first packet is from is it.				 * Client can only blame itself if not.				 */				if (io->in.raddr.sin_addr.s_addr == htonl(INADDR_ANY)				||  io->in.raddr.sin_port			== htons(0)) {					if (io->in.raddr.sin_addr.s_addr == htonl(INADDR_ANY))					/* LINTED pointer casts may be troublesome */						io->in.raddr.sin_addr.s_addr						= ((struct sockaddr_in *)&from)->sin_addr.s_addr;					if (io->in.raddr.sin_port == htons(0))						/* LINTED pointer casts may be troublesome */						io->in.raddr.sin_port						= ((struct sockaddr_in *)&from)->sin_port;					/* LINTED pointer casts may be troublesome */					sockaddr2sockshost((struct sockaddr *)&io->in.raddr, &io->src);				}				/*				 * When we receive the first packet we also have a fixed source				 * so connect the socket, both for better performance and so				 * that getpeername() will work on it (libwrap/rulespermit()).				 */				if (io->in.read == 0) { /* could happen more than once, but ok. */					struct connectionstate_t rstate;					/* LINTED pointer casts may be troublesome */					if (!sockaddrareeq((struct sockaddr *)&io->in.raddr, &from)) {						char src[MAXSOCKADDRSTRING], dst[MAXSOCKADDRSTRING];						/* perhaps this should be LOG_DEBUG. */						slog(LOG_NOTICE,						"%s(0): %s: expected from %s, got it from %s",						VERDICT_BLOCKs, protocol2string(io->state.protocol),						/* LINTED pointer casts may be troublesome */

⌨️ 快捷键说明

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