udp.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:24k
源码类别:
代理服务器
开发平台:
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: udp.c,v 1.80.2.1.2.7 1998/11/04 00:03:41 steve Exp $
- */
- /* This file has all the main functions for handling udp connections. In */
- /* particular it only one external function which is the main udp function, */
- /* HandleUdpConnection(). */
- #include "socks5p.h"
- #include "threads.h"
- #include "daemon.h"
- #include "protocol.h"
- #include "validate.h"
- #include "udputil.h"
- #include "msgids.h"
- #include "info.h"
- #include "msg.h"
- #include "s2s.h"
- #include "udp.h"
- #include "log.h"
- #ifndef UDPTIMEOUT
- #define UDPTIMEOUT 15*60
- #endif
- #define CODEABLE(x) ((x) && (x)->auth.encode)
- #define CODEBUFF(a, b, c, d) ((a)->auth.encode(b, c, d, (a)->auth.context))
- #define NEXTADDR(x) (((x)->nextVersion)?&((x)->sckAddr) :&((x)->dstAddr))
- #define NEXTNAME(x) (((x)->nextVersion)? ((x)->sckName): ((x)->dstName))
- /* Close all the file descriptor, clean up the caches, log the exit error, */
- /* and quit... */
- static void UdpCleanup(S5LinkInfo *pri, UdpInfo *u) {
- S5IOHandle i;
- void *tmp;
- if (!u) return;
- for (; u->scache ; u->scache = (struct scache *)tmp) {
- S5BufCleanContext(&u->scache->cinfo);
- RemoveIdentEntry(u->scache->idtentry);
- tmp = (void *)u->scache->next;
- free(u->scache);
- }
- S5BufCleanContext(&u->iio);
- for (i = 0; i < u->maxfd; i++) {
- if (FD_ISSET(i, &u->myfds)) CLOSESOCKET(i);
- }
- if (u->relay != S5InvalidIOHandle) CLOSESOCKET(u->relay);
- for (; u->acache ; u->acache = (struct acache *)tmp) {
- tmp = (void *)u->acache->next;
- free(u->acache);
- }
- for (; u->rcache ; u->rcache = (struct aroute *)tmp) {
- tmp = (void *)u->rcache->next;
- free(u->rcache);
- }
- for (; u->hcache; u->hcache = (struct hinfo *)tmp) {
- tmp = (void *)u->hcache->next;
- free(u->hcache);
- }
- tmp = (void *)u->sdring->next;
- u->sdring->next = NULL;
- u->sdring = (UdpSdRing *)tmp;
- for (; u->sdring; u->sdring = (UdpSdRing *)tmp) {
- tmp = (void *)u->sdring->next;
- free(u->sdring);
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_UDP_END, "UDP Proxy Termination: (%s:%d) for user %s; %d bytes out %d bytes in",
- pri->srcName, ntohs(lsAddr2Port(&pri->srcAddr)), pri->srcUser, pri->outbc, pri->inbc);
- free(u);
- u = NULL;
- }
- /* Process udp use_client_port sub-command. */
- static void UdpUseClientPort(S5LinkInfo *pri, UdpInfo *u, u_char *err) {
- /* do we need this ???? */
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Doing USECLIENTPORT command");
- if (!lsAddrAddrComp(&pri->dstAddr, &pri->srcAddr) ||
- pri->dstAddr.sin.sin_addr.s_addr == INADDR_ANY ||
- pri->dstAddr.sin.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
- pri->clientPort = lsAddr2Port(&pri->dstAddr);
- *err = SOCKS5_NOERR;
- }
- }
- /* Process udp bind sub-command. */
- static void UdpBind(S5LinkInfo *pri, UdpInfo *u, u_char *err) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Doing BIND command");
- if (ResolveNames(pri) < 0) return;
- if (!lsAddrIsNull(&pri->dstAddr)) {
- *err = SOCKS5_BADADDR;
- return;
- }
- if (CheckIfCached(u, pri, 1) == 0) {
- if (u->curs != NULL) {
- if (S5IOCheck(u->curs->cinfo.fd) < 0) return; /* should it re-establish??? */
- if (u->curs->reserved != S5UDP_USECTRL) {
- lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
- *err = SOCKS5_NOERR;
- return;
- } else {
- if (u->cura->bounded) lsAddrCopy(&pri->intAddr, &u->cura->baddr, sizeof(S5NetAddr));
- else if (S5SExchgUdpCmd(u->curs->cinfo.fd, &u->curs->cinfo, pri, SOCKS5_VERSION, S5UDP_BIND, err) < 0) return;
- }
- } else lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
- } else {
- if (CheckIfAllowed(u, pri) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Command: Bind failed: permission denied");
- *err = SOCKS5_AUTHORIZE;
- return;
- }
- if (pri->nextVersion == SOCKS5_VERSION && FindProxyEntry(u, pri, &pri->sckAddr, 1) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Command: Couldn't connect to proxy: %s:%d", ADDRANDPORT(&pri->sckAddr));
- return;
- } else if (pri->nextVersion == SOCKS5_VERSION) {
- if (!(pri->nextReserved & S5UDP_USECTRL)) {
- /*
- S5NetAddr na;
- char msg = ' ';
- lsAddrCopy(&na, &pri->dstAddr, lsAddrSize(&pri->dstAddr));
- lsAddrSetPort(&na, 9);
- if (lsUdpProtoSend(pcon->fd, pri, &msg, 1, 0, &na.sa, lsAddrSize(&na)) < 0) return;
- lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
- *err = SOCKS5_NOERR;
- */
- return;
- } else if (S5SExchgUdpCmd(u->curs->cinfo.fd, &u->curs->cinfo, pri, SOCKS5_VERSION, S5UDP_BIND, err) < 0) return;
- } else if (pri->nextVersion != SOCKS5_VERSION) {
- if (FindOutSocket(u, pri, &pri->dstAddr, pri->dstName) == S5InvalidIOHandle) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Command: Couldn't make out socket to destination: %s:%d", ADDRANDPORT(&pri->dstAddr));
- return;
- }
- }
- }
- u->cura->bounded = 1;
- lsAddrCopy(&u->cura->baddr, &pri->intAddr, sizeof(S5NetAddr));
- *err = SOCKS5_NOERR;
- }
- /* Process udp getsockname sub-command. */
- static void UdpGetsockname(S5LinkInfo *pri, UdpInfo *u, u_char *err) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Doing GETSOCKNAME command");
- if (ResolveNames(pri) < 0) return;
- if (!lsAddrIsNull(&pri->dstAddr)) {
- *err = SOCKS5_BADADDR;
- return;
- }
- if (CheckIfCached(u, pri, 1) < 0) return;
- if (u->curs != NULL) {
- if (u->curs->reserved != S5UDP_USECTRL) return;
- if (S5IOCheck(u->curs->cinfo.fd) < 0) return;
- if (u->cura->bounded) lsAddrCopy(&pri->intAddr, &u->cura->baddr, sizeof(S5NetAddr));
- else if (S5SExchgUdpCmd(u->curs->cinfo.fd, &u->curs->cinfo, pri, SOCKS5_VERSION, S5UDP_GETSOCKNAME, err) < 0) return;
- } else lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
- u->cura->bounded = 1;
- lsAddrCopy(&u->cura->baddr, &pri->intAddr, sizeof(S5NetAddr));
- *err = SOCKS5_NOERR;
- }
- /* Process udp sub-commands received on the tcp control channel. */
- /* Current implementation supports three sub-commands. People should be */
- /* able to add new sub-commands */
- static int HandleCommand(S5LinkInfo *pri, UdpInfo *u) {
- u_char cmd = 0, res = 0, s5err = SOCKS5_BADCMND;
- memset((char *)&pri->intAddr, 0, sizeof(S5NetAddr));
- pri->intAddr.sa.sa_family = AF_INET;
- if (lsReadRequest(u->iio.fd, &u->iio, &pri->dstAddr, &pri->peerVersion, &cmd, &res) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Read request command failed");
- return -1;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Read command (%d) request (%s:%d)", (int)cmd, ADDRANDPORT(&pri->dstAddr));
- switch (cmd) {
- case S5UDP_USECLIENTPORT:
- UdpUseClientPort(pri, u, &s5err);
- break;
- case S5UDP_BIND:
- UdpBind(pri, u, &s5err);
- break;
- case S5UDP_GETSOCKNAME:
- UdpGetsockname(pri, u, &s5err);
- break;
- default:
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Unknown command");
- break;
- }
- return lsSendResponse(u->iio.fd, &u->iio, &pri->intAddr, pri->peerVersion, s5err, 0, NULL);
- }
- /* Proxy a request for the client. This basically involves checking to see */
- /* that the information is correct, then checking to see if it is allowed to */
- /* send to the destination (in FindOutDestination) as well as finding the */
- /* intermediate destination...If the destination turns out to be directly */
- /* reachable, then we may reassemble a fragment and send that instead. */
- /* */
- /* Arguments: sin -- the address of the person who sent the message to us */
- static int RecvFromClient(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, S5NetAddr *sender) {
- S5Packet buf[2];
- /* Make sure the client really sent this message. If not, assume it is */
- /* a forgery. */
- if (lsAddrComp(&pri->srcAddr, sender)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Client Receive: Received message from non-client (%s:%d) on client socket", ADDRANDPORT(sender));
- return -1;
- }
- /* Decode the message and copy the decode message into u->obuf. */
- if (CODEABLE(&u->iio)) {
- buf[0].data = u->obuf; buf[0].len = u->obuflen; buf[0].off = u->obuflen;
- buf[1].data = NULL; buf[1].len = 0; buf[1].off = 0;
- if (CODEBUFF(&u->iio, &buf[0], &buf[1], S5_DECODE) < 0 || buf[1].len > UDP_MAX_PAYLOAD) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Client Receive: Error decoding message");
- return -1;
- } else {
- memcpy(u->obuf, buf[1].data, buf[1].len);
- u->obuflen = buf[1].len;
- free(buf[1].data);
- }
- }
- /* A real message would have to have a length greater than the header */
- /* size. Drop the message if it does not. */
- if (u->obuflen <= MINHDRSIZE) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Client Receive: Received invalid message from client: too short");
- return -1;
- }
- /* Extract the destination address and it's name. */
- if (lsGetProtoAddr(SOCKS5_VERSION, u->obuf, &pri->dstAddr) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Client Receive: Received invalid message from client: invalid address");
- return -1;
- }
- if (ResolveNames(pri) < 0) {
- return -1;
- }
- /* Make sure we've either talked to this destination before, or we are */
- /* allowed to talk to it... */
- if (CheckIfCached(u, pri, 1) < 0 && CheckIfAllowed(u, pri) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Client Receive: send failed: permission denied");
- return -1;
- }
- packet->data = u->obuf + HDRSIZE(u->obuf);
- packet->off = u->obuflen - HDRSIZE(u->obuf);
- packet->len = UDP_MAX_PAYLOAD;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Client Receive: Received valid message of length %d", u->obuflen-HDRSIZE(u->obuf));
- return u->obuflen - HDRSIZE(u->obuf);
- }
- /* Proxy a request back from a server. This basically involves checking to */
- /* see if this is from a server we've talked to (FindCachedSocks) in which */
- /* case we forward it on... If not, it was from the application server. */
- /* To handle this case, we first check that this server is allowed (cache?) */
- /* then, if it is, package it up (possibly fragmenting it) and ship it back */
- /* to the client. */
- /* */
- /* Arguments: sin -- the address of the person who sent the message to us */
- static int RecvFromServer(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, S5NetAddr *sender) {
- S5Packet buf[2];
- /* If we don't find a proxy entry, zero out the appropriate structures */
- /* so that when we look at them later, we don't do something wrong. If */
- /* we did find one, go ahead and look up its name for logging... */
- pri->dstAddr = *sender;
- if (FindProxyEntry(u, pri, &pri->dstAddr, 0) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: Received message from dead server");
- return -1;
- }
- /* If we have a decode function for the server, go ahead and decode the */
- /* message and move it into the appropriate place */
- if (CODEABLE(u->oiop)) {
- buf[0].data = u->obuf; buf[0].len = u->obuflen; buf[0].off = u->obuflen;
- buf[1].data = NULL; buf[1].len = 0; buf[1].off = 0;
- if (CODEBUFF(u->oiop, &buf[0], &buf[1], S5_DECODE) < 0 || buf[1].len > UDP_MAX_PAYLOAD) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: Error decoding message from server");
- return -1;
- } else {
- memcpy(u->obuf, buf[1].data, buf[1].len);
- u->obuflen = buf[1].len;
- free(buf[1].data);
- }
- }
- /* If FindProxyEntry told us this was from another socks server, strip */
- /* off the header that it put on the message... */
- if (pri->nextVersion == SOCKS5_VERSION) {
- if (lsGetProtoAddr(SOCKS5_VERSION, u->obuf, &pri->dstAddr) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: Received invalid message from server: invalid address");
- return -1;
- }
- u->obuflen -= HDRSIZE(u->obuf);
- u->obuf += HDRSIZE(u->obuf);
- }
- GetName(pri->dstName, &pri->dstAddr);
- /* Make sure we've talked to the sender before. If not, we will ignore */
- /* this reply, assuming that this is a forgery. */
- if (CheckIfCached(u, pri, 1) < 0 && CheckIfAllowed(u, pri) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: recv failed: permission denied");
- return -1;
- }
- packet->data = u->obuf;
- packet->len = UDP_MAX_PAYLOAD;
- packet->off = u->obuflen;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(12), 0, "UDP Server Receive: Received valid message of length %d", u->obuflen);
- return u->obuflen;
- }
- int UdpRecvPkt(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, int *dir) {
- S5IOHandle maxfd;
- fd_set fds;
- UdpSdRing *sr;
- int rval;
- for (;;) {
- struct timeval inact = { UDPTIMEOUT, 0 };
- if (*dir & S5_DIRECTION_IN) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(15), 0, "UDP Receive: Selecting on outer sockets...");
- maxfd = u->maxfd;
- fds = u->myfds;
- } else {
- maxfd = 0;
- FD_ZERO(&fds);
- }
- if (*dir & S5_DIRECTION_OUT) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(15), 0, "UDP Receive: Selecting on inner socket...");
- FD_SET(u->relay, &fds);
- maxfd = MAX(maxfd, u->relay);
- }
- FD_SET(u->iio.fd, &fds);
- maxfd = MAX(maxfd, u->iio.fd);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(12), 0, "UDP Receive: Selecting...");
- switch (select(maxfd+1, &fds, NULL, NULL, &inact)) {
- case 0:
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Receive: Inactivity timeout expired");
- rval = -1;
- goto end;
- case -1:
- if (ISSOCKETERROR(EINTR)) continue;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Receive: select failed: %m");
- rval = -1;
- goto end;
- }
- if (FD_ISSET(u->iio.fd, &fds)) {
- if (S5IOCheck(u->iio.fd) < 0) rval = 0;
- else if ((pri->peerReserved & S5UDP_USECTRL) && !HandleCommand(pri, u)) continue;
- else {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Receive: client closed connection");
- rval = -1;
- }
- goto end;
- }
- if (u->sdring) u->sdring = u->sdring->next;
- for (sr = u->sdring;sr;sr = (u->sdring==sr->next)?NULL:sr->next) {
- int fromlen = sizeof(S5NetAddr);
- S5NetAddr sender;
- if (!FD_ISSET(sr->sd, &fds)) continue;
- u->obuf = u->mbuf + MAXHDRSIZE;
- u->obuflen = sizeof(u->mbuf) - MAXHDRSIZE;
- while ((u->obuflen = recvfrom(sr->sd, u->obuf, u->obuflen, 0, (ss *)&sender, &fromlen)) < 0 && ISSOCKETERROR(EINTR));
- if (u->obuflen < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Receive: real recvfrom failed: %m");
- rval = -1;
- goto end;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Receive: received a message from %s:%d", ADDRANDPORT(&sender));
- if (sr->sd == u->relay) {
- if ((rval = RecvFromClient(packet, pri, u, &sender)) <= 0) continue;
- *dir = S5_DIRECTION_OUT;
- } else {
- if ((rval = RecvFromServer(packet, pri, u, &sender)) <= 0) continue;
- *dir = S5_DIRECTION_IN;
- }
- goto end;
- }
- }
- end:
- if (rval <= 0) {
- packet->data = NULL;
- packet->off = 0;
- packet->len = 0;
- }
- return rval;
- }
- int UdpSendPkt(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, int *dir) {
- S5Packet buf[2];
- S5NetAddr *dst;
- S5IOInfo *info;
- S5IOHandle fd;
- int alen;
- if (packet->data < u->mbuf + MAXHDRSIZE ||
- packet->data > u->mbuf + MAXHDRSIZE + UDP_MAX_PAYLOAD ) {
- char *tmp;
- if ((tmp = (char *)malloc(packet->off)) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP send: Malloc failed.");
- u->obuflen = -1;
- goto end;
- }
- memcpy(tmp, packet->data, packet->off);
- u->obuf = u->mbuf + MAXHDRSIZE;
- u->obuflen = packet->off;
- memcpy(u->obuf, tmp, u->obuflen);
- free(tmp);
- } else {
- u->obuf = packet->data;
- u->obuflen = packet->off;
- }
- if (*dir == S5_DIRECTION_IN) {
- dst = &pri->srcAddr;
- fd = u->relay;
- info = &u->iio;
- } else {
- /* If we'll be using a proxy and we haven't talked to it yet, */
- /* initialize the connection and add it it list of know proxies... */
- if (pri->nextVersion == SOCKS5_VERSION && FindProxyEntry(u, pri, &pri->sckAddr, 1) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP send: Couldn't connect to %s:%d", ADDRANDPORT(&pri->sckAddr));
- u->obuflen = -1;
- goto end;
- }
- /* Find out how we should go out, update the byte count, and dump */
- /* the packet if need be. */
- fd = FindOutSocket(u, pri, NEXTADDR(pri), NEXTNAME(pri));
- dst = NEXTADDR(pri);
- info = u->oiop;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Sending to %s:%d", ADDRANDPORT(dst));
- if (*dir == S5_DIRECTION_IN || pri->nextVersion == SOCKS5_VERSION) {
- if ((alen = lsGetProtoAddrLenFromAddr(SOCKS5_VERSION, &pri->dstAddr)) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Send: Error filling in address in packet header");
- u->obuflen = -1;
- goto end;
- }
- u->obuf -= alen;
- memset(u->obuf, 0, 3);
- lsSetProtoAddr(SOCKS5_VERSION, u->obuf, &pri->dstAddr);
- u->obuflen += HDRSIZE(u->obuf);
- }
- /* Encode the packet if necessary... This includes changing obuf to */
- /* point to the buffer that the encoding creates. We'll free that */
- /* buffer later if need be. */
- if (CODEABLE(info)) {
- buf[0].data = u->obuf;
- buf[0].len = u->obuflen;
- buf[0].off = 0;
- buf[1].data = NULL;
- buf[1].len = 0;
- buf[1].off = 0;
- if (CODEBUFF(info, &buf[0], &buf[1], S5_ENCODE) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Send: Error encoding message for client");
- u->obuflen = -1;
- goto end;
- } else {
- u->obuf = buf[1].data;
- u->obuflen = buf[1].len;
- }
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Sending a message of length %d", u->obuflen);
- /* Send the message and log the fact that we have. */
- if (sendto(fd, u->obuf, u->obuflen, 0, &dst->sa, sizeof(ssi)) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Send: Sendto failed: %m");
- } else if (*dir == S5_DIRECTION_OUT) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Client Sent Message to %s:%d", ADDRANDPORT(dst));
- } else {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Client Recveived Message from %s:%d", ADDRANDPORT(&pri->dstAddr));
- }
- /* Free any space we had to allocate because of the encoding */
- if (CODEABLE(info)) {
- if (buf[1].data) free(buf[1].data);
- }
- end:
- packet->data = NULL;
- packet->off = 0;
- packet->len = 0;
- return u->obuflen;
- }
- int UdpSetup(S5IOInfo *ioinfo, S5LinkInfo *pri, S5CommandInfo *cmdinfo) {
- int len = sizeof(S5NetAddr), rval = EXIT_ERR;
- S5NetAddr route;
- u_char s5err = SOCKS5_FAIL;
- UdpInfo *u = NULL;
- /* The destination is really the port we'll be receiving request from */
- /* it is allowed to be 0, but we take that to mean we'll be recv'ing it */
- /* from the same place the tcp connection came from, different port */
- if (lsAddrAddrComp(&pri->dstAddr, &pri->srcAddr) != 0) {
- if (pri->dstAddr.sin.sin_addr.s_addr != INADDR_ANY && pri->dstAddr.sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
- s5err = SOCKS5_BADADDR;
- goto cleanup;
- }
- }
- /* Allocate space for the udp specific options we'll be using... */
- if (!(cmdinfo->option = (void *)(u = (UdpInfo *)calloc(1, sizeof(UdpInfo))))) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Setup: Malloc() failed");
- goto cleanup;
- }
- u->sdring = NULL;
- u->iio = *ioinfo;
- memset(&u->myfds, 0, sizeof(fd_set));
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_UDP_START, "UDP Proxy Request: (%s:%d) for user %s", pri->srcName, ntohs(lsAddr2Port(&pri->srcAddr)), pri->srcUser);
- /* if the destination port is 0, we will assume the same port as tcp's */
- if (lsAddr2Port(&pri->dstAddr) != (u_short)0) lsAddrSetPort(&pri->srcAddr, lsAddr2Port(&pri->dstAddr));
- /* We set the destination address same as the source for Authorize */
- /* function to distinguish the UDP request and UDP messages ... */
- lsAddrCopy(&pri->dstAddr, &pri->srcAddr, lsAddrSize(&pri->srcAddr));
- if (Authorize(pri, 0) != AUTH_OK) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: Setup failed: permission denied");
- s5err = SOCKS5_AUTHORIZE;
- rval = EXIT_AUTH;
- goto cleanup;
- }
- lsAddrCopy(&route, &pri->bndAddr, lsAddrSize(&pri->bndAddr));
- lsAddrSetPort(&route, (u_short)0);
- if ((u->relay = MakeOutSocket(u, &route, (u_short)0)) == S5InvalidIOHandle) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: Couldn't make main udp socket: %m");
- goto cleanup;
- }
- if (getsockname(u->relay, (ss *)&route.sa, &len) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: Getsockname failed on main udp socket: %m");
- goto cleanup;
- }
- lsAddrSetPort(&pri->bndAddr, lsAddr2Port(&route));
- if (lsSendResponse(u->iio.fd, &u->iio, &pri->bndAddr, pri->peerVersion, SOCKS5_RESULT, (pri->peerReserved & S5UDP_USECTRL)?S5UDP_USECTRL:0, NULL) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: couldn't send response");
- rval = EXIT_NETERR;
- goto cleanup;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_UDP_ESTAB, "UDP Proxy Established: (%s:%d) for user %s",
- pri->srcName, ntohs(lsAddr2Port(&pri->srcAddr)), pri->srcUser);
- cmdinfo->recvpkt = (int (*)(S5Packet *, S5LinkInfo *, void *, int *))UdpRecvPkt;
- cmdinfo->sendpkt = (int (*)(S5Packet *, S5LinkInfo *, void *, int *))UdpSendPkt;
- cmdinfo->clean = (int (*)(S5LinkInfo *, void *))UdpCleanup;
- return EXIT_OK;
- cleanup:
- if (rval != EXIT_NETERR) lsSendResponse(ioinfo->fd, ioinfo, &pri->bndAddr, pri->peerVersion, s5err, 0, NULL);
- if (u != NULL) UdpCleanup(pri, u);
- else {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_UDP_END, "UDP Proxy Termination: (%s:%d) for user %s; %d bytes out %d bytes in",
- pri->srcName, ntohs(lsAddr2Port(&pri->srcAddr)), pri->srcUser, pri->outbc, pri->inbc);
- S5BufCleanContext(ioinfo);
- }
- /* Prevent any further problems from being seg faults. */
- cmdinfo->option = NULL;
- if (rval == EXIT_OK) rval = EXIT_ERR;
- return rval;
- }