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

📄 sockd_request.c

📁 sock protocol ,it is useful!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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: sockd_request.c,v 1.110 1999/12/22 09:29:27 karls Exp $";/* * Since it only handles one client at a time there is no possibility * for the mother to send a new client before we have got rid of the * old one and thus no need for locking even on broken systems. * (#ifdef HAVE_SENDMSG_DEADLOCK) * XXX I have started to work on fixing this, so this process too * can support multiple clients, perhaps for a later release I will * have time to complete it.  Will also fix the terrible fact * that we just sit around and wait if the command is bind, wasting * the whole process on practically nothing. */__BEGIN_DECLSstatic voiddorequest __P((int mother, const struct sockd_request_t *request));/* * When a complete request has been read, this function can be * called.  It will perform the request "request->req" and send the * result to "mother". */static voidflushio __P((int mother, int clientcontrol, const struct response_t *response,				 struct sockd_io_t *io));/* * "flushes" a complete io object and free's any state/resources held by it. * "mother" is connection to mother for sending the io. * "clientcontrol" is the client connection. * "response" is the response to be sent the client. * "io" is the io object sent mother. */static voidproctitleupdate __P((const struct sockaddr *from));/* * Updates the title of this process. */static struct sockd_io_t *io_add __P((struct sockd_io_t *iolist, const struct sockd_io_t *newio));/* * Adds _a copy_ of the object "newio" to the list "iolist". * Returns a pointer to the (new) iolist. */static struct sockd_io_t *io_remove __P((struct sockd_io_t *iolist, struct sockd_io_t *rmio));/* * Removes the object "rmio" from the list "iolist". * Returns a pointer to the (new) iolist. */static struct sockd_io_t *io_find __P((struct sockd_io_t *iolist, const struct sockaddr *addr));/* * Scans "iolist" for a object that contains "addr" as a local address. * If "addr" is NULL, returns "iolist". * Returns: *		On success: pointer to the matching io object. *		On failure: NULL. */__END_DECLSvoidrun_request(mother)	struct sockd_mother_t *mother;{	const char *function = "run_request()";	struct sockd_request_t req;#if DIAGNOSTIC	const int freec = freedescriptors(config.option.debug ? "start" : NULL);#endif /* DIAGNOSTIC */	proctitleupdate(NULL);	/* CONSTCOND */	while (1) {		/*		 * Get request from mother, perform it, get next request.		 */		const char command = SOCKD_FREESLOT;		proctitleupdate(NULL);		if (recv_req(mother->s, &req) == -1)			sockdexit(-EXIT_FAILURE);		/* LINTED pointer casts may be troublesome */		proctitleupdate((struct sockaddr *)&req.from);		dorequest(mother->s, &req);		if (writen(mother->ack, &command, sizeof(command)) != sizeof(command))			serr(EXIT_FAILURE, "%s: sending ack to mother failed", function);#if DIAGNOSTIC		SASSERTX(freec == freedescriptors(config.option.debug ? "end" : NULL));#endif /* DIAGNOSTIC */	}}intrecv_req(s, req)	int s;	struct sockd_request_t *req;{	const char *function = "recv_req()";	int fdexpect, fdreceived, r;	struct iovec iovec[1];	struct msghdr msg;	CMSG_AALLOC(sizeof(int));	iovec[0].iov_base		= req;	iovec[0].iov_len		= sizeof(*req);	msg.msg_iov				= iovec;	msg.msg_iovlen			= ELEMENTS(iovec);	msg.msg_name			= NULL;	msg.msg_namelen		= 0;	CMSG_SETHDR_RECV(sizeof(cmsgmem));	if ((r = recvmsgn(s, &msg, 0, sizeof(*req))) != sizeof(*req)) {		switch (r) {			case -1:				swarn("%s: recvmsg() from mother", function);				break;			case 0:				slog(LOG_DEBUG, "%s: recvmsg(): mother closed connection",				function);				break;			default:				swarnx("%s: recvmsg(): unexpected %d/%d bytes from mother",				function, r, sizeof(*req));		}		return -1;	}	fdexpect = 1;#if !HAVE_DEFECT_RECVMSG	SASSERT(CMSG_GETLEN(msg) == sizeof(int) * fdexpect);#endif	fdreceived = 0;	CMSG_GETOBJECT(req->s, sizeof(req->s) * fdreceived++);	/* pointer fixup */	req->req.auth = &req->state.auth;	return 0;}static voiddorequest(mother, request)	int mother;	const struct sockd_request_t *request;{	const char *function = "dorequest()";	static const struct sockd_io_t ioinit;	struct sockaddr_in bound;	struct sockd_io_t io;	struct response_t response;	char a[MAXSOCKSHOSTSTRING], b[MAXSOCKSHOSTSTRING];	int p, permit, out;	slog(LOG_DEBUG, "received request: %s",	socks_packet2string(&request->req, SOCKS_REQUEST));	bzero(&response, sizeof(response));	response.host	= request->req.host;	response.auth	= request->req.auth;	io							= ioinit;	io.acceptrule			= request->rule;	io.state					= request->state;	io.state.extension	= config.extension;	/*	 * examine client request.	 */	/* supported version? */	switch (request->req.version) {		case SOCKS_V4:			response.version = SOCKS_V4REPLY_VERSION;			/* recognized command for this version? */			switch (request->req.command) {				case SOCKS_BIND:				case SOCKS_CONNECT:					io.state.protocol = SOCKS_TCP;					break;				default:					/* LINTED pointer casts may be troublesome */					slog(LOG_INFO, "%s: unrecognized v%d command: %d",					sockaddr2string((const struct sockaddr *)&request->from,					a, sizeof(a)), request->req.version, request->req.command);					send_failure(request->s, &response, SOCKS_FAILURE);					close(request->s);					return;			}			/* supported address format for this version? */			switch (request->req.host.atype) {				case SOCKS_ADDR_IPV4:					break;				default:					/* LINTED pointer casts may be troublesome */					slog(LOG_INFO, "%s: unrecognized v%d address type: %d",					sockaddr2string((const struct sockaddr *)&request->from,					a, sizeof(a)), request->req.version, request->req.host.atype);					send_failure(request->s, &response, SOCKS_ADDR_UNSUPP);					close(request->s);					return;			}			break; /* SOCKS_V4 */		case SOCKS_V5:			response.version = request->req.version;			/* recognized command for this version? */			switch (request->req.command) {				case SOCKS_BIND:				case SOCKS_CONNECT:					io.state.protocol = SOCKS_TCP;					break;				case SOCKS_UDPASSOCIATE:					io.state.protocol = SOCKS_UDP;					break;				default:					/* LINTED pointer casts may be troublesome */					slog(LOG_INFO, "%s: unrecognized v%d command: %d",					sockaddr2string((const struct sockaddr *)&request->from,					a, sizeof(a)), request->req.version, request->req.command);					send_failure(request->s, &response, SOCKS_CMD_UNSUPP);					close(request->s);					return;			}			/* supported address format for this version? */			switch (request->req.host.atype) {				case SOCKS_ADDR_IPV4:				case SOCKS_ADDR_DOMAIN:					break;				default:					/* LINTED pointer casts may be troublesome */					slog(LOG_INFO, "%s: unrecognized v%d address type: %d",					sockaddr2string((const struct sockaddr *)&request->from,					a, sizeof(a)), request->req.version, request->req.host.atype);					send_failure(request->s, &response, SOCKS_ADDR_UNSUPP);					close(request->s);					return;			}			break; /* SOCKS_V5 */		default:			SERRX(request->req.version);	}	/*	 * packet looks ok, fill in remaining bits needed to check rules.	 */	switch (request->req.command) {		case SOCKS_BIND:			/* LINTED pointer casts may be troublesome */			sockaddr2sockshost((const struct sockaddr *)&request->from, &io.src);			io.dst = request->req.host;			if (io.dst.atype					!= SOCKS_ADDR_IPV4			||  io.dst.addr.ipv4.s_addr	!= htonl(0)			||  io.dst.port					== htons(0))				io.state.extension.bind = 0;	/* not requesting bind extension. */			break;		case SOCKS_CONNECT:			/* LINTED pointer casts may be troublesome */			sockaddr2sockshost((const struct sockaddr *)&request->from, &io.src);			io.dst = request->req.host;			break;		case SOCKS_UDPASSOCIATE:			/*			 * for UDP_ASSOCIATE we are getting clients udp address,			 * not destination in request.			 * Destination address will be checked in the i/o loop for			 * each destination, for now just set it to INADDR_ANY.			 */			io.src						= request->req.host;			io.dst.atype				= SOCKS_ADDR_IPV4;			io.dst.addr.ipv4.s_addr	= htonl(INADDR_ANY);			io.dst.port					= htons(0);			break;		default:			SERRX(request->req.command);	}	/* socket to use for outgoing connection. */	switch (io.state.protocol) {		case SOCKS_TCP:			if ((out = socket(AF_INET, SOCK_STREAM, 0)) == -1)				swarn("%s: socket(SOCK_STREAM)", function);			break;		case SOCKS_UDP:			if ((out = socket(AF_INET, SOCK_DGRAM, 0)) == -1)				swarn("%s: socket(SOCK_DGRAM)", function);			break;		default:			SERRX(io.state.protocol);	}	if (out == -1) {		send_failure(request->s, &response, SOCKS_FAILURE);		close(request->s);		return;	}	setsockoptions(out);	/* find out what address to bind on clients behalf. */	bound	= *config.externalv;	switch (request->req.command) {		case SOCKS_BIND:			/* find out what port to bind;  v4/v5 semantics?  bind extension? */			switch (request->req.version) {				case SOCKS_V4:					if (io.state.extension.bind)						bound.sin_port	= io.dst.port;					else						/* best we can try for is to use same port as source. */						bound.sin_port	= request->from.sin_port;					break;				case SOCKS_V5:					bound.sin_port = io.dst.port;					break;				default:					SERRX(request->req.version);			}			break;		case SOCKS_CONNECT:			bound.sin_port	= request->from.sin_port;			break;		case SOCKS_UDPASSOCIATE:			bound.sin_port	= request->req.host.port;			break;		default:			SERRX(request->req.command);	}	/*	 * bind socket.	 */	if (config.compat.reuseaddr) {

⌨️ 快捷键说明

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