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

📄 udp.c

📁 sock protocol ,it is useful!
💻 C
字号:
/* * Copyright (c) 1997, 1998, 1999 *      Inferno Nettverk A/S, Norway.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. The above copyright notice, this list of conditions and the following *    disclaimer must appear in all copies of the software, derivative works *    or modified versions, and any portions thereof, aswell as in all *    supporting documentation. * 2. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by *      Inferno Nettverk A/S, Norway. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Inferno Nettverk A/S requests users of this software to return to * *  Software Distribution Coordinator  or  sdc@inet.no *  Inferno Nettverk A/S *  Oslo Research Park *  Gaustadal閑n 21 *  N-0349 Oslo *  Norway * * any improvements or extensions that they make and grant Inferno Nettverk A/S * the rights to redistribute these changes. * */#include "common.h"static const char rcsid[] ="$Id: udp.c,v 1.110 1999/12/22 09:29:24 karls Exp $";/* ARGSUSED */ssize_tRsendto(s, msg, len, flags, to, tolen)	int s;	const void *msg;	size_t len;	int flags;	const struct sockaddr *to;	socklen_t tolen;{	struct socksfd_t *socksfd;	struct sockshost_t host;	char *nmsg;	size_t nlen;	ssize_t n;	if (to != NULL && to->sa_family != AF_INET)		return sendto(s, msg, len, flags, to, tolen);	if (udpsetup(s, to, SOCKS_SEND) != 0)		return errno == 0 ? sendto(s, msg, len, flags, to, tolen) : -1;	socksfd = socks_getaddr((unsigned int)s);	SASSERTX(socksfd != NULL);	if (to == NULL)		if (socksfd->state.udpconnect)			to = &socksfd->connected;		else			/* best we can do. */			return sendto(s, msg, len, flags, NULL, 0);	/* prefix a udp header to the msg */	nlen = len;	/* LINTED warning: cast discards 'const' from pointer target type */	if ((nmsg = udpheader_add(fakesockaddr2sockshost(to, &host), (char *)msg,	&nlen, 0)) == NULL) {		errno = ENOBUFS;		return -1;	}	n = sendto(s, nmsg, nlen, flags, 	socksfd->state.udpconnect ? NULL : &socksfd->reply, 	socksfd->state.udpconnect ? 0		: sizeof(socksfd->reply));	n -= nlen - len;	free(nmsg);	return MAX(-1, n);}ssize_tRrecvfrom(s, buf, len, flags, from, fromlen)	int s;	void *buf;	size_t len;	int flags;	struct sockaddr *from;	socklen_t *fromlen;{	const char *function = "Rrecvfrom()";	struct socksfd_t *socksfd;	struct udpheader_t header;	char *newbuf;	struct sockaddr newfrom;	socklen_t newfromlen;	size_t newlen;	ssize_t n;	if (!socks_addrisok((unsigned int)s)) {		socks_rmaddr((unsigned int)s);		return recvfrom(s, buf, len, flags, from, fromlen);	}	if (udpsetup(s, from, SOCKS_RECV) != 0)		return errno == 0 ? recvfrom(s, buf, len, flags, from, fromlen) : -1;	socksfd = socks_getaddr((unsigned int)s);	SASSERTX(socksfd != NULL);	if (!socksfd->state.protocol.udp)		/* assume tcp connection, nothing to do there. */		return recvfrom(s, buf, len, flags, from, fromlen);	/* if packet is from socksserver it will be prefixed with a header. */	newlen = len + sizeof(header);	if ((newbuf = (char *)malloc(sizeof(*newbuf) * newlen)) == NULL) {		errno = ENOBUFS;		return -1;	}	newfromlen = sizeof(newfrom);	if ((n = recvfrom(s, newbuf, newlen, flags, &newfrom, &newfromlen)) == -1) {		free(newbuf);		return n;	}	SASSERTX(newfromlen > 0);	if (sockaddrareeq(&newfrom, &socksfd->reply)) {		/*		 * packet is from socksserver.		*/		if (string2udpheader(newbuf, (size_t)n, &header) == NULL) {			char badfrom[MAXSOCKADDRSTRING];			swarnx("%s: unrecognized socks udppacket from %s",			function, sockaddr2string(&newfrom, badfrom, sizeof(badfrom)));			errno = EAGAIN;			return -1;	/* don't know if callee wants to retry. */		}		/* if connected udpsocket, only forward from "connected" source. */		if (socksfd->state.udpconnect) {			struct sockshost_t host;			if (!sockshostareeq(&header.host,			fakesockaddr2sockshost(&socksfd->connected, &host))) {				char a[MAXSOCKSHOSTSTRING];				char b[MAXSOCKSHOSTSTRING];				/*				 * We have a problem here ...  If we failed to resolve				 * address we gave to the socksserver and instead gave a				 * hostname to it, sockshostareeq() will fail unless the server				 * sends the address it is forwarding from as the sockshost too.				 *				 * It is better to place safe than sorry though, so				 * we have to drop the packet in that case, even if it				 * is from the correct source since we can not verify it.				 */				free(newbuf);				slog(LOG_DEBUG, "%s: expected udpreply from %s, got it from %s",				function,				sockshost2string(fakesockaddr2sockshost(&socksfd->connected,				&host), a, sizeof(a)),				sockshost2string(&header.host, b, sizeof(b)));				/*				 * Not sure what to do now, return error or retry?				 * Going with returning error for now.				 */#if 0				if ((p = fcntl(s, F_GETFL, 0)) == -1)					return -1;				if (p & NONBLOCKING) {#endif					errno = EAGAIN;					return -1;#if 0				}				/* else; assume the best thing is to retry. */				return Rrecvfrom(s, buf, len, flags, from, fromlen);#endif			}		}		/* replace "newfrom" with the address socksserver says packet is from. */		fakesockshost2sockaddr(&header.host, &newfrom);		/* callee doesn't get socksheader. */		n -= PACKETSIZE_UDP(&header);		SASSERTX(n >= 0);		memcpy(buf, &newbuf[PACKETSIZE_UDP(&header)], MIN(len, (size_t)n));	}	else /* ordinary udppacket, not from socksserver. */		memcpy(buf, newbuf, MIN(len, (size_t)n));	free(newbuf);	if (from != NULL) {		*fromlen = MIN(*fromlen, newfromlen);		memcpy(from, &newfrom, (size_t)*fromlen);	}	return MIN(len, (size_t)n);}intudpsetup(s, to, type)	int s;	const struct sockaddr *to;	int type;{	struct socks_t packet;	struct socksfd_t socksfd;	struct sockaddr_in newto;	struct sockshost_t src, dst;	socklen_t len;	int p;	if (!socks_addrisok((unsigned int)s))		socks_rmaddr((unsigned int)s);	if (socks_getaddr((unsigned int)s) != NULL)		return 0; /* all set up. */	/*	 * if this socket has not previously been used we need to	 * make a new connection to the socksserver for it.	 */	errno = 0;	switch (type) {		case SOCKS_RECV:			/*			 * problematic, trying to receive on socket not sent on.			 */			bzero(&newto, sizeof(newto));			newto.sin_family			= AF_INET;			newto.sin_addr.s_addr	= htonl(INADDR_ANY);			newto.sin_port				= htons(0);			/* LINTED pointer casts may be troublesome */			to = (struct sockaddr *)&newto;			break;		case SOCKS_SEND:			if (to == NULL)				return -1; /* no address and unknown socket, no idea. */			break;		default:			SERRX(type);	}	/*	 * we need to send the socksserver our address.	 * First check if the socket already has a name, if so	 * use that, otherwise assign the name ourselves.	 */	bzero(&socksfd, sizeof(socksfd));	len = sizeof(socksfd.local);	if (getsockname(s, &socksfd.local, &len) != 0)		return -1;	sockaddr2sockshost(&socksfd.local, &src);	fakesockaddr2sockshost(to, &dst);	bzero(&packet, sizeof(packet));	packet.version				= SOCKS_V5;	packet.req.version		= packet.version;	packet.req.command		= SOCKS_UDPASSOCIATE;	packet.req.flag			|= SOCKS_USECLIENTPORT;/*	packet.req.flag			|= SOCKS_INTERFACEREQUEST; */	packet.req.host			= src;	if ((socksfd.control = socket(AF_INET, SOCK_STREAM, 0)) == -1)		return -1;	if ((socksfd.route	= socks_connectroute(socksfd.control, &packet, &src, &dst)) == NULL) {		close(socksfd.control);		return -1;	}	/* LINTED  pointer casts may be troublesome */	if ((((struct sockaddr_in *)(&socksfd.local))->sin_addr.s_addr	== htonl(INADDR_ANY))	/* LINTED  pointer casts may be troublesome */	|| ((struct sockaddr_in *)(&socksfd.local))->sin_port == htons(0)) {		/*		 * local name not fixed, set it, port may be bound, we need to bind		 * ip too however.		 */		/* LINTED  pointer casts may be troublesome */		const in_port_t port = ((struct sockaddr_in *)(&socksfd.local))->sin_port;		if (port != htons(0)) {			/*			 * port is bound.  We will try to unbind and then rebind same port			 * but now also bind ip address.  XXX Dangerous stuff.			 */			if ((p = socketoptdup(s)) == -1) {				close(socksfd.control);				return -1;			}			if (dup2(p, s) == -1) {				close(socksfd.control);				close(p);				return -1;			}			close(p);		}		/*		 * don't have much of an idea on what ip address to use so might as		 * well use same as tcp connection to socksserver uses.		 */		len = sizeof(socksfd.local);		if (getsockname(socksfd.control, &socksfd.local, &len) != 0) {			close(socksfd.control);			return -1;		}		/* LINTED  pointer casts may be troublesome */		((struct sockaddr_in *)&socksfd.local)->sin_port = port;		if (bind(s, &socksfd.local, sizeof(socksfd.local)) != 0) {			close(socksfd.control);			return -1;		}		if (getsockname(s, &socksfd.local, &len) != 0) {			close(socksfd.control);			return -1;		}		sockaddr2sockshost(&socksfd.local, &packet.req.host);	}/*	packet.req.host.addr.ipv4.s_addr = htonl(INADDR_ANY); *//*	packet.req.host.port = htons(0); */	if (socks_negotiate(s, socksfd.control, &packet, socksfd.route) != 0)		return -1;	socksfd.state.auth				= packet.auth;	socksfd.state.version			= packet.version;	socksfd.state.command			= SOCKS_UDPASSOCIATE;	socksfd.state.protocol.udp		= 1;	sockshost2sockaddr(&packet.res.host, &socksfd.reply);	len = sizeof(socksfd.server);	if (getpeername(socksfd.control, &socksfd.server, &len) != 0) {		close(socksfd.control);		return -1;	}#if 0	/*	 * if the remote server supports interface requests, try to get	 * the address it's using on our behalf.	 */	if (packet.res.flag & SOCKS_INTERFACEREQUEST) {		struct interfacerequest_t ifreq;		ifreq.rsv				= 0;		ifreq.sub				= SOCKS_INTERFACEDATA;		ifreq.flag				= 0;		ifreq.host.atype		= SOCKS_ADDR_IPV4;		ifreq.host.addr.ipv4	= ((const struct sockaddr_in *)to)->sin_addr;		ifreq.host.port		= ((const struct sockaddr_in *)to)->sin_port;		if (send_interfacerequest(socksfd.control, &ifreq,		socksfd.state.version) == 0) {		}	}#endif	if (socks_addaddr((unsigned int)s, &socksfd) == NULL) {		close(socksfd.control);		errno = ENOBUFS;		return -1;	}	return 0;}

⌨️ 快捷键说明

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