tracer.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:11k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /* Copyright (c) 1995,1996,1997 NEC Corporation. All rights reserved. */
- /* */
- /* The redistribution, use and modification in source or binary forms of */
- /* this software is subject to the conditions set forth in the copyright */
- /* document ("Copyright") included with this distribution. */
- /*
- * $Id: tracer.c,v 1.40.4.3 1998/11/04 00:03:40 steve Exp $
- */
- #include "socks5p.h"
- #include "daemon.h"
- #include "protocol.h"
- #include "validate.h"
- #include "sident.h"
- #include "msgids.h"
- #include "flow.h"
- #include "info.h"
- #include "log.h"
- #include "msg.h"
- #include "s2s.h"
- struct ptinfo {
- S5IOInfo iio, oio, pio;
- int stopchild, childpid, exitval, msgsent;
- char tmpmsg[GENERICBUFSIZE], idtentry[IDTENTRY_SIZE];
- char *packetbuf;
- };
- typedef struct ptinfo PTInfo;
- #define CommandName(x) (((x)->peerCommand == SOCKS_PING)?"PING":"Traceroute")
- #ifndef REPLYTIMEOUT
- #define REPLYTIMEOUT 60
- #endif
- static int Popen(S5LinkInfo *pri, PTInfo *ptinfo) {
- S5IOHandle pds[2];
- #ifndef TROUTEPROG
- if (pri->peerCommand == SOCKS_TRACER) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "%s: No real program to exec", CommandName(pri));
- return -1;
- }
- #endif
- #ifndef PINGPROG
- if (pri->peerCommand != SOCKS_TRACER) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "%s: No real program to exec", CommandName(pri));
- return -1;
- }
- #endif
- if (pipe(pds) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "%s pipe failed: %m", CommandName(pri));
- return -1;
- }
- if ((ptinfo->childpid = fork()) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "%s fork failed: %m", CommandName(pri));
- close(pds[0]);
- close(pds[1]);
- return -1;
- }
- S5BufSetupContext(&ptinfo->pio);
- ptinfo->pio.fd = pds[0];
- if (ptinfo->childpid == 0) {
- close(pds[0]);
- if (dup2(pds[1], STDOUT_FILENO) < 0) _exit(-1);
- if (dup2(pds[1], STDERR_FILENO) < 0) _exit(-1);
- close(pds[1]);
- #ifdef TROUTEPROG
- if ((pri->peerCommand == SOCKS_TRACER)) {
- int verbose = pri->peerReserved & SOCKS5_FLAG_VERBOSE;
- int noname = pri->peerReserved & SOCKS5_FLAG_NONAME;
- if (pri->nextVersion) {
- if (noname) execlp(TROUTEPROG, "traceroute", "-n", (verbose?"-v":pri->sckName), verbose?pri->sckName:NULL, NULL);
- else execlp(TROUTEPROG, "traceroute", (verbose?"-v":pri->sckName), verbose?pri->sckName:NULL, NULL);
- } else {
- if (noname) execlp(TROUTEPROG, "traceroute", "-n", (verbose?"-v":pri->dstName), verbose?pri->dstName:NULL, NULL);
- else execlp(TROUTEPROG, "traceroute", (verbose?"-v":pri->dstName), verbose?pri->dstName:NULL, NULL);
- }
- }
- #endif
- #ifdef PINGPROG
- if (!(pri->peerCommand == SOCKS_TRACER)) {
- execlp(PINGPROG, "ping", pri->dstName, NULL);
- }
- #endif
- _exit(0);
- }
- ptinfo->stopchild = 1;
- close(pds[1]);
- return 0;
- }
- static int InitProxy(S5LinkInfo *pri, PTInfo *ptinfo) {
- S5NetAddr junk;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "%s Using proxy (version %d) %s:%d", CommandName(pri), (int)pri->nextVersion, ADDRANDPORT(&pri->sckAddr));
- if ((ptinfo->oio.fd = socket(AF_INET, SOCK_STREAM, 0)) == S5InvalidIOHandle) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "%s socket failed: %m", CommandName(pri));
- return -1;
- }
- if (S5SExchangeProtocol(&ptinfo->iio, &ptinfo->oio, pri, ptinfo->idtentry, &pri->dstAddr, &junk) == 0) {
- return 0;
- }
- CLOSESOCKET(ptinfo->oio.fd);
- ptinfo->oio.fd = S5InvalidIOHandle;
- return -1;
- }
- static void WaitChild(PTInfo *coption) {
- int wstatus;
- if (!coption->stopchild) return;
- #ifdef HAVE_WAITPID
- waitpid(coption->childpid, &wstatus, 0);
- #else
- wait4(coption->childpid, &wstatus, 0, NULL);
- #endif
- close(coption->pio.fd);
- coption->pio.fd = S5InvalidIOHandle;
- coption->stopchild = 0;
- coption->childpid = 0;
- }
- static int PTRecvPkt(S5Packet *packet, S5LinkInfo *pri, PTInfo *coption, int *dir) {
- int rv = EXIT_ERR, savedir;
- if (!coption) {
- return EXIT_ERR;
- } else if (coption->pio.fd != S5InvalidIOHandle && !coption->msgsent) {
- packet->data = (char *)malloc(GENERICBUFSIZE * sizeof(char));
- packet->len = GENERICBUFSIZE;
- packet->off = 0;
- if (packet->data) {
- strcpy(packet->data, coption->tmpmsg);
- packet->off = rv = strlen(coption->tmpmsg);
- *dir = S5_DIRECTION_IN;
- coption->msgsent = 1;
- } else return EXIT_ERR;
- } else {
- if (coption->pio.fd != S5InvalidIOHandle) {
- for (;;) {
- savedir = *dir;
- rv = S5TcpFlowRecv(&coption->iio, &coption->pio, packet, dir);
- if (rv == 0 && *dir == S5_DIRECTION_IN) {
- /* The pipe is closed (command done) as just the first part */
- /* of a 2 part process by closing the pipe and go to the */
- /* second part to get dome "real" data... */
- WaitChild(coption);
- *dir = savedir;
- if (pri->nextVersion) rv = S5TcpFlowRecv(&coption->iio, &coption->oio, packet, dir);
- } else if (rv > 0 && *dir == S5_DIRECTION_OUT) {
- /* If the client sends anything, it is a message to stop. */
- if (coption->stopchild) {
- kill(coption->childpid, SIGINT);
- coption->stopchild = 0;
- }
- *dir = savedir;
- packet->off = 0;
- continue;
- }
- break;
- }
- } else rv = S5TcpFlowRecv(&coption->iio, &coption->oio, packet, dir);
- }
- if (rv < 0) coption->exitval = EXIT_ERR;
- else coption->exitval = EXIT_OK;
- if (packet->data) coption->packetbuf = packet->data;
- return rv;
- }
- static int PTSendPkt(S5Packet *packet, S5LinkInfo *pri, PTInfo *coption, int *dir) {
- int rv;
- if (!coption) return -1;
- rv = S5TcpFlowSend(&coption->iio, &coption->oio, packet, dir);
- if (rv < 0) coption->exitval = EXIT_ERR;
- else coption->exitval = EXIT_OK;
- return rv;
- }
- static int PTClose(S5LinkInfo *linkinfo, PTInfo *coption) {
- if (!coption) return -1;
- if (coption->childpid > 0 && coption->stopchild) {
- kill(coption->childpid, SIGINT);
- WaitChild(coption);
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_PT_END, "%s Proxy Terminated: %s (%s to %s) for user %s: %d bytes out, %d bytes in",
- CommandName(linkinfo), (coption->exitval == EXIT_ERR)?"Abnormal":"Normal",
- linkinfo->srcName, linkinfo->dstName, linkinfo->srcUser,
- linkinfo->outbc, linkinfo->inbc);
- S5BufCleanContext(&coption->oio);
- S5BufCleanContext(&coption->iio);
- S5BufCleanContext(&coption->pio);
- if (coption->packetbuf) free(coption->packetbuf);
- RemoveIdentEntry(coption->idtentry);
- free(coption);
- return 0;
- }
- int PTSetup(S5IOInfo *ioinfo, S5LinkInfo *linkinfo, S5CommandInfo *cinfo) {
- int turnon = 1, rval = EXIT_ERR;
- PTInfo *ptinfo;
- if (ResolveNames(linkinfo) < 0) {
- goto cleanup;
- }
- if (!(cinfo->option = (void *)(ptinfo = (PTInfo *)malloc(sizeof(PTInfo))))) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "%s malloc failed", CommandName(linkinfo));
- goto cleanup;
- }
- ptinfo->exitval = EXIT_OK;
- ptinfo->msgsent = 0;
- ptinfo->stopchild = 0;
- ptinfo->childpid = 0;
- ptinfo->iio = *ioinfo;
- ptinfo->packetbuf = NULL;
- InitIdentEntry(ptinfo->idtentry);
- S5BufSetupContext(&ptinfo->oio);
- S5BufSetupContext(&ptinfo->pio);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_PT_START, "%s Proxy Request: (%s to %s) for user %s",
- CommandName(linkinfo), linkinfo->srcName, linkinfo->dstName, linkinfo->srcUser);
- if (Authorize(linkinfo, 0) != AUTH_OK) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, MSGID_SERVER_PT_AUTH, "%s Authorization failed", CommandName(linkinfo));
- rval = EXIT_AUTH;
- goto cleanup;
- }
- if (linkinfo->nextVersion && InitProxy(linkinfo, ptinfo) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "%s Init Proxy Failed", CommandName(linkinfo));
- goto cleanup;
- }
- if (linkinfo->peerCommand == SOCKS_TRACER) {
- sprintf(ptinfo->tmpmsg, "nTraceroute to %s...n", linkinfo->nextVersion?linkinfo->sckName:linkinfo->dstName);
- } else {
- ptinfo->msgsent = 1;
- }
- if (!linkinfo->nextVersion || linkinfo->peerCommand == SOCKS_TRACER) {
- if (Popen(linkinfo, ptinfo) < 0) {
- if (!linkinfo->nextVersion) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "%s Failed to open pipe for real command", CommandName(linkinfo));
- goto cleanup;
- }
- if (linkinfo->peerCommand == SOCKS_TRACER) {
- strcat(ptinfo->tmpmsg, "Traceroute not available on this hostn");
- }
- }
- }
- /* Set out of band data inline, since we won't be dealing with it.... */
- if (setsockopt(ptinfo->iio.fd, SOL_SOCKET, SO_OOBINLINE, (char *)&turnon, sizeof(int)) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "%s Setup: Failed to inline out-of-band data: %m", CommandName(linkinfo));
- rval = EXIT_NETERR;
- goto cleanup;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_PT_ESTAB, "%s Proxy Established: (%s to %s) for user %s",
- CommandName(linkinfo), linkinfo->srcName, linkinfo->dstName, linkinfo->srcUser);
- if (lsSendResponse(ptinfo->iio.fd, &ptinfo->iio, &linkinfo->dstAddr, linkinfo->peerVersion, 0, 0, NULL) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Client closed connection");
- rval = EXIT_NETERR;
- goto cleanup;
- }
- recv_sigio(ioinfo->fd);
- cinfo->recvpkt = (int (*)(S5Packet *, S5LinkInfo *, void *, int *))PTRecvPkt;
- cinfo->sendpkt = (int (*)(S5Packet *, S5LinkInfo *, void *, int *))PTSendPkt;
- cinfo->clean = (int (*)(S5LinkInfo *, void *))PTClose;
- return EXIT_OK;
- cleanup:
- if (rval != EXIT_NETERR) lsSendResponse(ioinfo->fd, ioinfo, &linkinfo->dstAddr, linkinfo->peerVersion, 1, 0, NULL);
- if (ptinfo != NULL) {
- ptinfo->exitval = EXIT_ERR;
- PTClose(linkinfo, ptinfo);
- } else {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_PT_END, "%s Proxy Terminated: %s (%s to %s) for user %s: %d bytes out, %d bytes in",
- CommandName(linkinfo), "Abnormal",
- linkinfo->srcName, linkinfo->dstName, linkinfo->srcUser,
- linkinfo->outbc, linkinfo->inbc);
- S5BufCleanContext(ioinfo);
- }
- cinfo->option = NULL;
- if (rval == EXIT_OK) rval = EXIT_ERR;
- return rval;
- }