udp.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:24k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /* Copyright (c) 1995,1996,1997 NEC Corporation.  All rights reserved.       */
  2. /*                                                                           */
  3. /* The redistribution, use and modification in source or binary forms of     */
  4. /* this software is subject to the conditions set forth in the copyright     */
  5. /* document ("Copyright") included with this distribution.                   */
  6. /*
  7.  * $Id: udp.c,v 1.80.2.1.2.7 1998/11/04 00:03:41 steve Exp $
  8.  */
  9. /* This file has all the main functions for handling udp connections.  In    */
  10. /* particular it only one external function which is the main udp function,  */
  11. /* HandleUdpConnection().                                                    */
  12. #include "socks5p.h"
  13. #include "threads.h"
  14. #include "daemon.h"
  15. #include "protocol.h"
  16. #include "validate.h"
  17. #include "udputil.h"
  18. #include "msgids.h"
  19. #include "info.h"
  20. #include "msg.h"
  21. #include "s2s.h"
  22. #include "udp.h"
  23. #include "log.h"
  24. #ifndef UDPTIMEOUT
  25. #define UDPTIMEOUT 15*60
  26. #endif
  27. #define CODEABLE(x)          ((x) && (x)->auth.encode)
  28. #define CODEBUFF(a, b, c, d) ((a)->auth.encode(b, c, d, (a)->auth.context))
  29.     
  30. #define NEXTADDR(x) (((x)->nextVersion)?&((x)->sckAddr)  :&((x)->dstAddr))
  31. #define NEXTNAME(x) (((x)->nextVersion)? ((x)->sckName): ((x)->dstName))
  32. /* Close all the file descriptor, clean up the caches, log the exit error,   */
  33. /* and quit...                                                               */
  34. static void UdpCleanup(S5LinkInfo *pri, UdpInfo *u) {
  35.     S5IOHandle i;
  36.     void *tmp;
  37.     if (!u) return;
  38.     for (; u->scache ; u->scache = (struct scache *)tmp) {
  39. S5BufCleanContext(&u->scache->cinfo);
  40. RemoveIdentEntry(u->scache->idtentry);
  41. tmp = (void *)u->scache->next;
  42. free(u->scache);
  43.     }
  44.     S5BufCleanContext(&u->iio);
  45.     for (i = 0; i < u->maxfd; i++) {
  46. if (FD_ISSET(i, &u->myfds)) CLOSESOCKET(i);
  47.     }
  48.     if (u->relay != S5InvalidIOHandle) CLOSESOCKET(u->relay);
  49.     for (; u->acache ; u->acache = (struct acache *)tmp) {
  50. tmp = (void *)u->acache->next;
  51. free(u->acache);
  52.     }
  53.     for (; u->rcache ; u->rcache = (struct aroute *)tmp) {
  54. tmp = (void *)u->rcache->next;
  55. free(u->rcache);
  56.     }
  57.     for (; u->hcache; u->hcache = (struct hinfo *)tmp) {
  58. tmp = (void *)u->hcache->next;
  59. free(u->hcache);
  60.     }
  61.     tmp = (void *)u->sdring->next;
  62.     u->sdring->next = NULL;
  63.     u->sdring = (UdpSdRing *)tmp;
  64.     for (; u->sdring; u->sdring = (UdpSdRing *)tmp) {
  65.         tmp = (void *)u->sdring->next;
  66.         free(u->sdring);
  67.     }
  68.     
  69.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_UDP_END, "UDP Proxy Termination: (%s:%d) for user %s; %d bytes out %d bytes in",
  70.     pri->srcName, ntohs(lsAddr2Port(&pri->srcAddr)), pri->srcUser, pri->outbc, pri->inbc);
  71.     free(u);
  72.     u = NULL;
  73. }
  74. /* Process udp use_client_port sub-command.                                  */
  75. static void UdpUseClientPort(S5LinkInfo *pri, UdpInfo *u, u_char *err) {
  76.     /* do we need this ????            */
  77.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Doing USECLIENTPORT command");
  78.     if (!lsAddrAddrComp(&pri->dstAddr, &pri->srcAddr) ||
  79.     pri->dstAddr.sin.sin_addr.s_addr == INADDR_ANY ||
  80.     pri->dstAddr.sin.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
  81.      pri->clientPort = lsAddr2Port(&pri->dstAddr);
  82.      *err = SOCKS5_NOERR;
  83.     }
  84. }
  85. /* Process udp bind sub-command.                                             */
  86. static void UdpBind(S5LinkInfo *pri, UdpInfo *u, u_char *err) {
  87.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Doing BIND command");
  88.     if (ResolveNames(pri) < 0) return;
  89.     if (!lsAddrIsNull(&pri->dstAddr)) {
  90. *err = SOCKS5_BADADDR;
  91. return;
  92.     }
  93.     if (CheckIfCached(u, pri, 1) == 0) {
  94.     if (u->curs != NULL) {
  95.     if (S5IOCheck(u->curs->cinfo.fd) < 0) return; /* should it re-establish???    */
  96.     if (u->curs->reserved != S5UDP_USECTRL) {
  97. lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
  98.      *err = SOCKS5_NOERR;
  99.   return;
  100.     } else {
  101.      if (u->cura->bounded) lsAddrCopy(&pri->intAddr, &u->cura->baddr, sizeof(S5NetAddr));
  102.      else if (S5SExchgUdpCmd(u->curs->cinfo.fd, &u->curs->cinfo, pri, SOCKS5_VERSION, S5UDP_BIND, err) < 0) return;
  103.     }
  104. } else lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
  105.     } else {
  106.      if (CheckIfAllowed(u, pri) < 0) {
  107.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Command: Bind failed: permission denied");
  108.     *err = SOCKS5_AUTHORIZE;
  109.     return;
  110.         }
  111.         if (pri->nextVersion == SOCKS5_VERSION && FindProxyEntry(u, pri, &pri->sckAddr, 1) < 0) {
  112.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Command: Couldn't connect to proxy: %s:%d", ADDRANDPORT(&pri->sckAddr));
  113.     return;
  114.         } else if (pri->nextVersion == SOCKS5_VERSION) {
  115.     if (!(pri->nextReserved & S5UDP_USECTRL)) {
  116. /*
  117.                 S5NetAddr na;
  118.              char msg = '';
  119.           lsAddrCopy(&na, &pri->dstAddr, lsAddrSize(&pri->dstAddr));
  120.              lsAddrSetPort(&na, 9);
  121.              if (lsUdpProtoSend(pcon->fd, pri, &msg, 1, 0, &na.sa, lsAddrSize(&na)) < 0) return;
  122.    lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
  123. *err = SOCKS5_NOERR;
  124. */
  125.   return;
  126.          } else if (S5SExchgUdpCmd(u->curs->cinfo.fd, &u->curs->cinfo, pri, SOCKS5_VERSION, S5UDP_BIND, err) < 0) return;
  127.         } else if (pri->nextVersion != SOCKS5_VERSION) {
  128.     if (FindOutSocket(u, pri, &pri->dstAddr, pri->dstName) == S5InvalidIOHandle) {
  129.                 S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Command: Couldn't make out socket to destination: %s:%d", ADDRANDPORT(&pri->dstAddr));
  130.                 return;
  131.          }
  132.         }
  133.     }
  134.     u->cura->bounded = 1;
  135.     lsAddrCopy(&u->cura->baddr, &pri->intAddr, sizeof(S5NetAddr));
  136.     *err = SOCKS5_NOERR;
  137. }
  138. /* Process udp getsockname sub-command.                                      */
  139. static void UdpGetsockname(S5LinkInfo *pri, UdpInfo *u, u_char *err) {
  140.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Doing GETSOCKNAME command");
  141.     if (ResolveNames(pri) < 0) return;
  142.     if (!lsAddrIsNull(&pri->dstAddr)) {
  143. *err = SOCKS5_BADADDR;
  144. return;
  145.     }
  146.     if (CheckIfCached(u, pri, 1) < 0) return;
  147.     if (u->curs != NULL) {
  148. if (u->curs->reserved != S5UDP_USECTRL) return;
  149. if (S5IOCheck(u->curs->cinfo.fd) < 0) return;
  150.      if (u->cura->bounded) lsAddrCopy(&pri->intAddr, &u->cura->baddr, sizeof(S5NetAddr));
  151.      else if (S5SExchgUdpCmd(u->curs->cinfo.fd, &u->curs->cinfo, pri, SOCKS5_VERSION, S5UDP_GETSOCKNAME, err) < 0) return;
  152.     } else lsAddrCopy(&pri->intAddr, &u->curr->raddr, sizeof(S5NetAddr));
  153.     u->cura->bounded = 1;
  154.     lsAddrCopy(&u->cura->baddr, &pri->intAddr, sizeof(S5NetAddr));
  155.     *err = SOCKS5_NOERR;
  156. }
  157. /* Process udp sub-commands received on the tcp control channel.             */
  158. /* Current implementation supports three sub-commands. People should be      */
  159. /* able to add new sub-commands                                              */
  160. static int HandleCommand(S5LinkInfo *pri, UdpInfo *u) {
  161.     u_char cmd = 0, res = 0, s5err = SOCKS5_BADCMND;
  162.     memset((char *)&pri->intAddr, 0, sizeof(S5NetAddr));
  163.     pri->intAddr.sa.sa_family = AF_INET;
  164.     if (lsReadRequest(u->iio.fd, &u->iio, &pri->dstAddr, &pri->peerVersion, &cmd, &res) < 0) {
  165.      S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Read request command failed");
  166.         return -1;
  167.     }
  168.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Read command (%d) request (%s:%d)", (int)cmd, ADDRANDPORT(&pri->dstAddr));
  169.     switch (cmd) {
  170. case S5UDP_USECLIENTPORT:
  171.     UdpUseClientPort(pri, u, &s5err);
  172.     break;
  173. case S5UDP_BIND:
  174.     UdpBind(pri, u, &s5err);
  175.     break;
  176. case S5UDP_GETSOCKNAME:
  177.     UdpGetsockname(pri, u, &s5err);
  178.     break;
  179. default:
  180.          S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Command: Unknown command");
  181.     break;
  182.     }
  183.     return lsSendResponse(u->iio.fd, &u->iio, &pri->intAddr, pri->peerVersion, s5err, 0, NULL);
  184. }
  185. /* Proxy a request for the client.  This basically involves checking to see  */
  186. /* that the information is correct, then checking to see if it is allowed to */
  187. /* send to the destination (in FindOutDestination) as well as finding the    */
  188. /* intermediate destination...If the destination turns out to be directly    */
  189. /* reachable, then we may reassemble a fragment and send that instead.       */
  190. /*                                                                           */
  191. /* Arguments: sin -- the address of the person who sent the message to us    */
  192. static int RecvFromClient(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, S5NetAddr *sender) {
  193.     S5Packet buf[2];
  194.     /* Make sure the client really sent this message.  If not, assume it is  */
  195.     /* a forgery.                                                            */
  196.     if (lsAddrComp(&pri->srcAddr, sender)) {
  197.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Client Receive: Received message from non-client (%s:%d) on client socket", ADDRANDPORT(sender));
  198.         return -1;
  199.     }
  200.     /* Decode the message and copy the decode message into u->obuf.          */
  201.     if (CODEABLE(&u->iio)) {
  202. buf[0].data = u->obuf; buf[0].len = u->obuflen; buf[0].off = u->obuflen;
  203. buf[1].data = NULL;    buf[1].len = 0; buf[1].off = 0;
  204. if (CODEBUFF(&u->iio, &buf[0], &buf[1], S5_DECODE) < 0 || buf[1].len > UDP_MAX_PAYLOAD) {
  205.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Client Receive: Error decoding message");
  206.     return -1;
  207. } else {
  208.     memcpy(u->obuf, buf[1].data, buf[1].len);
  209.     u->obuflen = buf[1].len;
  210.     free(buf[1].data);
  211. }
  212.     }
  213.     /* A real message would have to have a length greater than the header    */
  214.     /* size.  Drop the message if it does not.                               */
  215.     if (u->obuflen <= MINHDRSIZE) {
  216. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Client Receive: Received invalid message from client: too short");
  217. return -1;
  218.     }
  219.     /* Extract the destination address and it's name.                        */
  220.     if (lsGetProtoAddr(SOCKS5_VERSION, u->obuf, &pri->dstAddr) < 0) {
  221. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Client Receive: Received invalid message from client: invalid address");
  222. return -1;
  223.     } 
  224.     if (ResolveNames(pri) < 0) {
  225. return -1;
  226.     }
  227.     /* Make sure we've either talked to this destination before, or we are   */
  228.     /* allowed to talk to it...                                              */
  229.     if (CheckIfCached(u, pri, 1) < 0 && CheckIfAllowed(u, pri) < 0) {
  230. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Client Receive: send failed: permission denied");
  231. return -1;
  232.     }
  233.     packet->data = u->obuf    + HDRSIZE(u->obuf);
  234.     packet->off  = u->obuflen - HDRSIZE(u->obuf);
  235.     packet->len  = UDP_MAX_PAYLOAD;
  236.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Client Receive: Received valid message of length %d", u->obuflen-HDRSIZE(u->obuf));
  237.     return u->obuflen - HDRSIZE(u->obuf);
  238. }
  239. /* Proxy a request back from a server. This basically involves checking to   */
  240. /* see if this is from a server we've talked to (FindCachedSocks) in which   */
  241. /* case we forward it on... If not, it was from the application server.      */
  242. /* To handle this case, we first check that this server is allowed (cache?)  */
  243. /* then, if it is, package it up (possibly fragmenting it) and ship it back  */
  244. /* to the client.                                                            */
  245. /*                                                                           */
  246. /* Arguments: sin -- the address of the person who sent the message to us    */
  247. static int RecvFromServer(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, S5NetAddr *sender) {
  248.     S5Packet buf[2];
  249.     
  250.     /* If we don't find a proxy entry, zero out the appropriate structures   */
  251.     /* so that when we look at them later, we don't do something wrong.  If  */
  252.     /* we did find one, go ahead and look up its name for logging...         */
  253.     pri->dstAddr = *sender;
  254.     if (FindProxyEntry(u, pri, &pri->dstAddr, 0) < 0) {
  255. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: Received message from dead server");
  256. return -1;
  257.     }
  258.     /* If we have a decode function for the server, go ahead and decode the  */
  259.     /* message and move it into the appropriate place                        */
  260.     if (CODEABLE(u->oiop)) {
  261. buf[0].data = u->obuf; buf[0].len = u->obuflen; buf[0].off = u->obuflen;
  262. buf[1].data = NULL;    buf[1].len = 0; buf[1].off = 0;
  263. if (CODEBUFF(u->oiop, &buf[0], &buf[1], S5_DECODE) < 0 || buf[1].len > UDP_MAX_PAYLOAD) {
  264.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: Error decoding message from server");
  265.     return -1;
  266. } else {
  267.     memcpy(u->obuf, buf[1].data, buf[1].len);
  268.     u->obuflen = buf[1].len;
  269.     free(buf[1].data);
  270. }
  271.     }
  272.     /* If FindProxyEntry told us this was from another socks server, strip   */
  273.     /* off the header that it put on the message...                          */
  274.     if (pri->nextVersion == SOCKS5_VERSION) {
  275. if (lsGetProtoAddr(SOCKS5_VERSION, u->obuf, &pri->dstAddr) < 0) {
  276.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: Received invalid message from server: invalid address");
  277.     return -1;
  278. u->obuflen -= HDRSIZE(u->obuf);
  279. u->obuf    += HDRSIZE(u->obuf);
  280.     }
  281.     GetName(pri->dstName, &pri->dstAddr);
  282.     /* Make sure we've talked to the sender before.  If not, we will ignore  */
  283.     /* this reply, assuming that this is a forgery.                          */
  284.     if (CheckIfCached(u, pri, 1) < 0 && CheckIfAllowed(u, pri) < 0) {
  285. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Server Receive: recv failed: permission denied");
  286.         return -1;
  287.     }
  288.     packet->data = u->obuf;
  289.     packet->len  = UDP_MAX_PAYLOAD;
  290.     packet->off  = u->obuflen;
  291.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(12), 0, "UDP Server Receive: Received valid message of length %d", u->obuflen);
  292.     return u->obuflen;
  293. }
  294. int UdpRecvPkt(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, int *dir) {
  295.     S5IOHandle maxfd;
  296.     fd_set fds;
  297.     UdpSdRing *sr;
  298.     int rval;
  299.     
  300.     for (;;) {
  301. struct timeval inact = { UDPTIMEOUT, 0 };
  302. if (*dir & S5_DIRECTION_IN) {
  303.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(15), 0, "UDP Receive: Selecting on outer sockets...");
  304.     maxfd = u->maxfd;
  305.     fds = u->myfds;
  306. } else {
  307.     maxfd = 0;
  308.     FD_ZERO(&fds);
  309. }
  310. if (*dir & S5_DIRECTION_OUT) {
  311.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(15), 0, "UDP Receive: Selecting on inner socket...");
  312.     FD_SET(u->relay, &fds);
  313.     maxfd = MAX(maxfd, u->relay);
  314. }
  315. FD_SET(u->iio.fd, &fds);    
  316. maxfd = MAX(maxfd, u->iio.fd);
  317. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(12), 0, "UDP Receive: Selecting...");
  318. switch (select(maxfd+1, &fds, NULL, NULL, &inact)) {
  319.     case 0:
  320. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Receive: Inactivity timeout expired");
  321. rval = -1;
  322. goto end;
  323.     case -1:
  324. if (ISSOCKETERROR(EINTR)) continue;
  325. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Receive: select failed: %m");
  326. rval = -1;
  327. goto end;
  328. }
  329. if (FD_ISSET(u->iio.fd, &fds)) {
  330.             if (S5IOCheck(u->iio.fd) < 0) rval = 0;
  331.     else if ((pri->peerReserved & S5UDP_USECTRL) && !HandleCommand(pri, u)) continue;
  332.     else {
  333.         S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Receive: client closed connection");
  334.         rval = -1;
  335.     }
  336.     goto end;
  337. }
  338.     
  339.         if (u->sdring) u->sdring = u->sdring->next;
  340.         for (sr = u->sdring;sr;sr = (u->sdring==sr->next)?NULL:sr->next) {
  341.             int fromlen = sizeof(S5NetAddr);
  342.             S5NetAddr sender;
  343.     
  344.     if (!FD_ISSET(sr->sd, &fds)) continue;
  345.     u->obuf    = u->mbuf         + MAXHDRSIZE;
  346.     u->obuflen = sizeof(u->mbuf) - MAXHDRSIZE;
  347.     
  348.     while ((u->obuflen = recvfrom(sr->sd, u->obuf, u->obuflen, 0, (ss *)&sender, &fromlen)) < 0 && ISSOCKETERROR(EINTR));
  349.     if (u->obuflen < 0) {
  350. S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Receive: real recvfrom failed: %m");
  351. rval = -1;
  352. goto end;
  353.     }
  354.     
  355.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Receive: received a message from %s:%d", ADDRANDPORT(&sender));
  356.     if (sr->sd == u->relay) {
  357. if ((rval = RecvFromClient(packet, pri, u, &sender)) <= 0) continue; 
  358. *dir = S5_DIRECTION_OUT;
  359.     } else {
  360.      if ((rval = RecvFromServer(packet, pri, u, &sender)) <= 0) continue;
  361.      *dir = S5_DIRECTION_IN;
  362.     }
  363.     goto end;
  364. }
  365.     }
  366.   end:
  367.     if (rval <= 0) {
  368. packet->data = NULL;
  369. packet->off  = 0;
  370. packet->len  = 0;
  371.     }
  372.     
  373.     return rval;
  374. }
  375.     
  376. int UdpSendPkt(S5Packet *packet, S5LinkInfo *pri, UdpInfo *u, int *dir) {
  377.     S5Packet buf[2];
  378.     S5NetAddr *dst;
  379.     S5IOInfo *info;
  380.     S5IOHandle fd;
  381.     int alen;
  382.     if (packet->data < u->mbuf + MAXHDRSIZE ||
  383. packet->data > u->mbuf + MAXHDRSIZE + UDP_MAX_PAYLOAD ) {
  384. char *tmp;
  385. if ((tmp = (char *)malloc(packet->off)) == NULL) {
  386.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP send: Malloc failed.");
  387.     u->obuflen = -1;
  388.     goto end;
  389. }
  390. memcpy(tmp, packet->data, packet->off);
  391. u->obuf    = u->mbuf      + MAXHDRSIZE;
  392. u->obuflen = packet->off;
  393. memcpy(u->obuf, tmp, u->obuflen);
  394. free(tmp);
  395.     } else {
  396. u->obuf    = packet->data;
  397. u->obuflen = packet->off;
  398.     }
  399.     
  400.     if (*dir == S5_DIRECTION_IN) {
  401. dst  = &pri->srcAddr;
  402. fd   = u->relay;
  403. info = &u->iio;
  404.     } else {
  405. /* If we'll be using a proxy and we haven't talked to it yet,        */
  406. /* initialize the connection and add it it list of know proxies...   */
  407. if (pri->nextVersion == SOCKS5_VERSION && FindProxyEntry(u, pri, &pri->sckAddr, 1) < 0) {
  408.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP send: Couldn't connect to %s:%d", ADDRANDPORT(&pri->sckAddr));
  409.     u->obuflen = -1;
  410.     goto end;
  411. }
  412. /* Find out how we should go out, update the byte count, and dump    */
  413. /* the packet if need be.                                            */
  414. fd   = FindOutSocket(u, pri, NEXTADDR(pri), NEXTNAME(pri));
  415. dst  = NEXTADDR(pri);
  416. info = u->oiop;
  417.     }
  418.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Sending to %s:%d", ADDRANDPORT(dst));
  419.     if (*dir == S5_DIRECTION_IN || pri->nextVersion == SOCKS5_VERSION) {
  420. if ((alen = lsGetProtoAddrLenFromAddr(SOCKS5_VERSION, &pri->dstAddr)) < 0) {
  421.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Send: Error filling in address in packet header");
  422.     u->obuflen = -1;
  423.     goto end;
  424. }
  425. u->obuf -= alen;
  426. memset(u->obuf, 0, 3);
  427. lsSetProtoAddr(SOCKS5_VERSION, u->obuf, &pri->dstAddr);
  428. u->obuflen += HDRSIZE(u->obuf);
  429.     }
  430.     
  431.     /* Encode the packet if necessary... This includes changing obuf to      */
  432.     /* point to the buffer that the encoding creates.  We'll free that       */
  433.     /* buffer later if need be.                                              */
  434.     if (CODEABLE(info)) {
  435. buf[0].data = u->obuf;
  436. buf[0].len  = u->obuflen;
  437. buf[0].off  = 0;
  438. buf[1].data = NULL;
  439. buf[1].len = 0;
  440. buf[1].off = 0;
  441. if (CODEBUFF(info, &buf[0], &buf[1], S5_ENCODE) < 0) {
  442.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Send: Error encoding message for client");
  443.     u->obuflen = -1;
  444.     goto end;
  445. } else {
  446.     u->obuf    = buf[1].data;
  447.     u->obuflen = buf[1].len;
  448. }
  449.     }
  450.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Sending a message of length %d", u->obuflen);
  451.     /* Send the message and log the fact that we have.                       */
  452.     if (sendto(fd, u->obuf, u->obuflen, 0, &dst->sa, sizeof(ssi)) < 0) {
  453. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "UDP Send: Sendto failed: %m");
  454.     } else if (*dir == S5_DIRECTION_OUT) {
  455. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Client Sent Message to %s:%d", ADDRANDPORT(dst));
  456.     } else {
  457. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Send: Client Recveived Message from %s:%d", ADDRANDPORT(&pri->dstAddr));
  458.     }
  459.     /* Free any space we had to allocate because of the encoding             */
  460.     if (CODEABLE(info)) {
  461. if (buf[1].data) free(buf[1].data);
  462.     }
  463.   end:
  464.     packet->data = NULL;
  465.     packet->off  = 0;
  466.     packet->len  = 0;
  467.     return u->obuflen;
  468. }
  469. int UdpSetup(S5IOInfo *ioinfo, S5LinkInfo *pri, S5CommandInfo *cmdinfo) {
  470.     int len = sizeof(S5NetAddr), rval = EXIT_ERR;
  471.     S5NetAddr route;
  472.     u_char s5err = SOCKS5_FAIL;
  473.     UdpInfo *u = NULL;
  474.     
  475.     /* The destination is really the port we'll be receiving request from    */
  476.     /* it is allowed to be 0, but we take that to mean we'll be recv'ing it  */
  477.     /* from the same place the tcp connection came from, different port      */
  478.     if (lsAddrAddrComp(&pri->dstAddr, &pri->srcAddr) != 0) {
  479. if (pri->dstAddr.sin.sin_addr.s_addr != INADDR_ANY && pri->dstAddr.sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
  480.     s5err = SOCKS5_BADADDR;
  481.     goto cleanup;
  482. }
  483.     }
  484.     /* Allocate space for the udp specific options we'll be using...         */
  485.     if (!(cmdinfo->option = (void *)(u = (UdpInfo *)calloc(1, sizeof(UdpInfo))))) {
  486. S5LogUpdate(S5LogDefaultHandle, S5_LOG_WARNING, 0, "UDP Setup: Malloc() failed");
  487. goto cleanup;
  488.     }
  489.     u->sdring = NULL;
  490.     u->iio  = *ioinfo;
  491.     memset(&u->myfds, 0, sizeof(fd_set));
  492.     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);
  493.     /* if the destination port is 0, we will assume the same port as tcp's    */
  494.     if (lsAddr2Port(&pri->dstAddr) != (u_short)0) lsAddrSetPort(&pri->srcAddr, lsAddr2Port(&pri->dstAddr));
  495.     /* We set the destination address same as the source for Authorize        */
  496.     /* function to distinguish the UDP request and UDP messages ...           */
  497.     lsAddrCopy(&pri->dstAddr, &pri->srcAddr, lsAddrSize(&pri->srcAddr));
  498.     if (Authorize(pri, 0) != AUTH_OK) {
  499. S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: Setup failed: permission denied");
  500. s5err = SOCKS5_AUTHORIZE;
  501. rval  = EXIT_AUTH;
  502. goto cleanup;
  503.     }
  504.     lsAddrCopy(&route, &pri->bndAddr, lsAddrSize(&pri->bndAddr));
  505.     lsAddrSetPort(&route, (u_short)0);
  506.     if ((u->relay = MakeOutSocket(u, &route, (u_short)0)) == S5InvalidIOHandle) {
  507. S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: Couldn't make main udp socket: %m");
  508. goto cleanup;
  509.     }
  510.     if (getsockname(u->relay, (ss *)&route.sa, &len) < 0) {
  511. S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: Getsockname failed on main udp socket: %m");
  512. goto cleanup;
  513.     }
  514.     lsAddrSetPort(&pri->bndAddr, lsAddr2Port(&route));
  515.     if (lsSendResponse(u->iio.fd, &u->iio, &pri->bndAddr, pri->peerVersion, SOCKS5_RESULT, (pri->peerReserved & S5UDP_USECTRL)?S5UDP_USECTRL:0, NULL) < 0) {
  516. S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP Setup: couldn't send response");
  517. rval = EXIT_NETERR;
  518. goto cleanup;
  519.     }
  520.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_UDP_ESTAB, "UDP Proxy Established: (%s:%d) for user %s",
  521.     pri->srcName, ntohs(lsAddr2Port(&pri->srcAddr)), pri->srcUser);
  522.     cmdinfo->recvpkt  = (int (*)(S5Packet *, S5LinkInfo *, void *, int *))UdpRecvPkt;
  523.     cmdinfo->sendpkt  = (int (*)(S5Packet *, S5LinkInfo *, void *, int *))UdpSendPkt;
  524.     cmdinfo->clean    = (int (*)(S5LinkInfo *, void *))UdpCleanup;
  525.     return EXIT_OK;
  526.   cleanup:
  527.     if (rval != EXIT_NETERR) lsSendResponse(ioinfo->fd, ioinfo, &pri->bndAddr, pri->peerVersion, s5err, 0, NULL);
  528.     if (u != NULL) UdpCleanup(pri, u);
  529.     else {
  530.      S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_UDP_END, "UDP Proxy Termination: (%s:%d) for user %s; %d bytes out %d bytes in",
  531.              pri->srcName, ntohs(lsAddr2Port(&pri->srcAddr)), pri->srcUser, pri->outbc, pri->inbc);
  532.      S5BufCleanContext(ioinfo);
  533.     }
  534.     /* Prevent any further problems from being seg faults.                   */
  535.     cmdinfo->option = NULL;
  536.     if (rval == EXIT_OK) rval = EXIT_ERR;
  537.     return rval;
  538. }