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

代理服务器

开发平台:

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: udputil.c,v 1.46.2.1.2.5 1998/10/09 14:19:53 steve Exp $
  8.  */
  9. /* This file has a bunch of utility (caching, socket finding, etc...) funcs  */
  10. /* for use in udp.c...Most of them are pretty simple and obvious.            */
  11. #include "socks5p.h"
  12. #include "threads.h"
  13. #include "daemon.h"
  14. #include "protocol.h"
  15. #include "udputil.h"
  16. #include "validate.h"
  17. #include "info.h"
  18. #include "log.h"
  19. #include "msg.h"
  20. #include "s2s.h"
  21. /* Find out which socket we're going to be using to get to host dest...      */
  22. /* Allocate a new entry if we make a new socket to go there...               */
  23. static S5IOHandle MakeOutUdpSocket(UdpInfo *u, S5NetAddr *addr, u_short port) {
  24.     static u_short udpport = 0;
  25.     u_short sudpport, tmpport = ntohs(lsAddr2Port(addr));
  26.     S5IOHandle sd;
  27.     S5NetAddr tmpaddr;
  28.     if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == S5InvalidIOHandle) {
  29. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP socket failed for address %s:%d: %m", ADDRANDPORT(addr));
  30. return S5InvalidIOHandle;
  31.     }
  32.     if (ludpport > 0 && udpport == 0) udpport = ludpport;
  33.     lsAddrCopy(&tmpaddr, addr, lsAddrSize(addr));
  34.     if (tmpport < ludpport || tmpport > hudpport) {
  35.         if (port == (u_short)0) {
  36.     lsAddrSetPort(&tmpaddr, htons(udpport));
  37.     udpport++;
  38. } else {
  39.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP client port(%d) is out of range (%d:%d)", (int)tmpport, (int)ludpport, (int)hudpport);
  40.     CLOSESOCKET(sd);
  41.     return S5InvalidIOHandle;
  42.         }
  43.     }
  44.     if (bind(sd, &tmpaddr.sa, lsAddrSize(&tmpaddr)) == 0) return sd;
  45.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP bind failed for address %s:%d: %m", ADDRANDPORT(&tmpaddr));
  46.     if (port == (u_short)0) {
  47. if (ludpport == 0) {
  48.             lsAddrSetPort(&tmpaddr, 0);
  49.     if (bind(sd, &tmpaddr.sa, lsAddrSize(&tmpaddr)) == 0) return sd;
  50. } else {
  51.     sudpport = udpport;
  52.     while (udpport < hudpport) {
  53.                 lsAddrSetPort(&tmpaddr, htons(udpport));
  54. udpport++;
  55. if (udpport == hudpport) udpport = ludpport;
  56.         if (bind(sd, &tmpaddr.sa, lsAddrSize(&tmpaddr)) == 0) return sd;
  57. if (udpport == sudpport) break;
  58.     }
  59. }
  60.     }
  61.     CLOSESOCKET(sd);
  62.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP no port is available");
  63.     return S5InvalidIOHandle;
  64. }
  65. S5IOHandle MakeOutSocket(UdpInfo *u, S5NetAddr *addr, u_short port) {
  66.     S5IOHandle sd;
  67.     int udpmaxbufsize = 64 * 1024;
  68.     int len = sizeof(int);
  69.     UdpSdRing *sr;
  70.     if ((sd = MakeOutUdpSocket(u, addr, port))!=S5InvalidIOHandle) {
  71.         if ((sr = (UdpSdRing *)calloc(1, sizeof(UdpSdRing))) == NULL) {
  72.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP: calloc failed");
  73.             CLOSESOCKET(sd);
  74.             return S5InvalidIOHandle;
  75.         }
  76.         sr->sd = sd;
  77.         if (!u->sdring) {
  78.             u->sdring = sr;
  79.             u->sdring->next = u->sdring;
  80.         }
  81.         else {
  82.             sr->next = u->sdring->next;
  83.             u->sdring->next = sr;
  84.         }
  85.         setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (const void*)&udpmaxbufsize, len);
  86.     }
  87.     return sd;
  88. }
  89. /* Find the out socket needed to get to the next hop (either sckAddr or      */
  90. /* dstsin).  If we haven't made a socket for getting there yet, make one and */
  91. /* add it to the route cache.                                                */
  92. S5IOHandle FindOutSocket(UdpInfo *u, S5LinkInfo *pri, const S5NetAddr *nextAddr, const char *nextName) {
  93.     int len = sizeof(S5NetAddr);
  94.     UdpRouteCache *ar;
  95.     S5NetAddr route;
  96.     /* XXX IPV6 stuff not finished here                                      */
  97.     GetRoute(nextAddr, nextName, "udp", &route);
  98.     lsAddrSetPort(&route, lsAddr2Port(&pri->srcAddr));
  99.     for (ar = u->rcache; ar; ar = ar->next) {
  100.         if (!lsAddrIsNull(&ar->raddr) && lsAddr2Port(&ar->raddr) == lsAddr2Port(&pri->srcAddr)) break;
  101. if (!lsAddrAddrComp(&ar->raddr, &route)) break;
  102.     }
  103.     if (!ar) {
  104. if ((ar = (UdpRouteCache *)calloc(1, sizeof(UdpRouteCache))) == NULL) {
  105.             S5LogUpdate(S5LogDefaultHandle, S5_LOG_ERROR, 0, "UDP: Creating route cache failed");
  106.     return S5InvalidIOHandle;
  107. }
  108. if ((ar->sd = MakeOutSocket(u, &route, pri->clientPort)) == S5InvalidIOHandle) {
  109.     free(ar);
  110.     return S5InvalidIOHandle;
  111. }
  112. ar->raddr = route;
  113.      if (getsockname(ar->sd, (ss *)&route.sa, &len) < 0) {
  114.     CLOSESOCKET(ar->sd);
  115.     free(ar);
  116.     return S5InvalidIOHandle;
  117. }
  118.         lsAddrSetPort(&ar->raddr, lsAddr2Port(&route));
  119. ar->next  = u->rcache;
  120. u->rcache = ar;
  121.         u->maxfd = (u->maxfd > ar->sd)?u->maxfd:ar->sd;
  122.         FD_SET(ar->sd, &u->myfds);
  123.     }
  124.     u->curr = ar;
  125.     pri->intAddr = ar->raddr;
  126.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Out interface: %s:%d", ADDRANDPORT(&ar->raddr));
  127.     return ar->sd;
  128. }
  129. /* find out if i've talked to this socks server, if not, set up a a cache    */
  130. /* entry for them too...  This does something like...send message to next    */
  131. /* socks5 server; receive a message back, mark that port as the port to talk */
  132. /* to that server.  Then do the client side of authentication with that      */
  133. /* server...                                                                 */
  134. static int AddProxyEntry(UdpInfo *u, S5LinkInfo *pri) {
  135.     UdpSocksCache *sc;
  136.     S5IOHandle outfd;
  137.     S5NetAddr tmp;
  138.     if (!(sc = (UdpSocksCache *)calloc(1, sizeof(UdpSocksCache)))) {
  139. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP malloc failed when adding a new proxy");
  140. return -1;
  141.     }
  142.     sc->next   = u->scache;
  143.     sc->tcpsin = pri->sckAddr;
  144.     strcpy(sc->name, pri->sckName);
  145.     InitIdentEntry(sc->idtentry);
  146.     S5BufSetupContext(&sc->cinfo);
  147.     u->scache  = sc;
  148.     if ((sc->cinfo.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  149. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP socket failed when contacting proxy: %m");
  150. goto error;
  151.     }
  152.     if ((outfd = FindOutSocket(u, pri, &pri->sckAddr, pri->sckName)) == S5InvalidIOHandle) {
  153. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP couldn't find an output udp socket to use with proxy");
  154. goto error;
  155.     }
  156.     lsAddrCopy(&tmp, &pri->intAddr, lsAddrSize(&pri->intAddr));
  157.     if (S5SExchangeProtocol(&u->iio, &sc->cinfo, pri, sc->idtentry, &tmp, &sc->udpsin) < 0) {
  158. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP Socks5 Protocol exchange failed");
  159. goto error;
  160.     }
  161.     sc->reserved = pri->nextReserved;
  162.     u->curs = sc;
  163.     return 0;
  164.   error:
  165.     u->scache = sc->next;
  166.     S5BufCleanContext(&sc->cinfo);
  167.     free(sc);
  168.     
  169.     return -1;
  170. }
  171. /* Find out if this person is a socks server we've talked to or not.         */
  172. /* If we're recv'ing, we're just checking, so we return our result if it is  */
  173. /* still alive...If we're sending, we need to initialize it if it does not   */
  174. /* exist in our cache, so we do exactly that...                              */
  175. int FindProxyEntry(UdpInfo *u, S5LinkInfo *pri, S5NetAddr *sckAddr, int tcp) {
  176.     int found = 0;
  177.     UdpSocksCache *sc, *prev = NULL;
  178.     for (sc = u->scache; sc; sc = sc->next) { 
  179. if (ADDRCOMP((tcp?&sc->tcpsin.sin:&sc->udpsin.sin), &sckAddr->sin)) break;
  180. prev = sc;
  181.     }
  182.     if (sc) {
  183. found = 1;
  184. if (S5IOCheck(sc->cinfo.fd) >= 0) {
  185.     if (!tcp) strcpy(pri->sckName, sc->name);
  186.     u->oiop          = &sc->cinfo;
  187.     pri->sckAddr     = sc->udpsin;
  188.     pri->nextVersion = SOCKS5_VERSION;
  189.     u->curs = sc;
  190.     
  191.     return 0;
  192. } else {
  193.     if (prev != NULL) prev->next = sc->next;
  194.     else u->scache = sc->next;
  195.     S5BufCleanContext(&sc->cinfo);
  196.     free(sc);
  197. }
  198.     }
  199.     if (!tcp) {
  200. if (found) return -1;
  201. memset(&pri->sckAddr, 0, sizeof(S5NetAddr));
  202. pri->nextVersion = 0;
  203. u->oiop          = NULL;
  204.     } else {
  205. if (AddProxyEntry(u, pri) < 0) return -1;
  206. pri->nextVersion = SOCKS5_VERSION;
  207. pri->sckAddr     = u->scache->udpsin;
  208. u->oiop          = &u->scache->cinfo;
  209.     }
  210.     return 0;
  211. }
  212. int CheckIfCached(UdpInfo *u, S5LinkInfo *pri, int checkport) {
  213.     UdpAuthCache *ac;
  214.     UdpRouteCache *ar;
  215.     UdpSocksCache *sc;
  216.     S5NetAddr route;
  217.     u_short port;
  218.     u->curs = NULL;
  219.     u->cura = NULL;
  220.     u->curr = NULL;
  221.     for (ac = u->acache; ac; ac = ac->next) {
  222. if (lsAddrAddrComp(&ac->addr, &pri->dstAddr)) continue;
  223. if (checkport) {
  224.     port = lsAddr2Port(&ac->addr);
  225.     if (port != (u_short)0 && port != lsAddr2Port(&pri->dstAddr)) continue;
  226. }
  227. u->cura = ac;
  228. if (pri->nextVersion) {
  229.          for (sc = u->scache; sc; sc = sc->next) {
  230.         if (!lsAddrComp((checkport)?&sc->tcpsin:&sc->udpsin, &pri->sckAddr)) break;
  231.          }
  232.     if ((u->curs = sc) == NULL) {
  233. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "CheckCache: The dst (%s:%d) come from wrong server", ADDRANDPORT(&pri->dstAddr));
  234. return -1;
  235.     } else {
  236.           GetRoute(&sc->udpsin, sc->name, "udp", &route);
  237.           for (ar = u->rcache; ar; ar = ar->next) {
  238.                     if (!lsAddrIsNull(&ar->raddr) && lsAddr2Port(&ar->raddr) == lsAddr2Port(&pri->srcAddr)) break;
  239.             if (!lsAddrAddrComp(&ar->raddr, &route)) break;
  240.           }
  241.      if ((u->curr = ar) == NULL) {
  242.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "CheckCache: The dst (%s:%d) come from wrong route", ADDRANDPORT(&sc->udpsin));
  243.     return -1;
  244.      } else return 0;
  245.     }
  246. } else {
  247.          GetRoute(&pri->dstAddr, pri->dstName, "udp", &route);
  248.          for (ar = u->rcache; ar; ar = ar->next) {
  249.                 if (!lsAddrIsNull(&ar->raddr) && lsAddr2Port(&ar->raddr) == lsAddr2Port(&pri->srcAddr)) break;
  250.         if (!lsAddrAddrComp(&ar->raddr, &route)) break;
  251.          }
  252.     if ((u->curr = ar) == NULL) {
  253. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "CheckCache: The dst (%s:%d) come from wrong route", ADDRANDPORT(&pri->dstAddr));
  254. return -1;
  255.     } else return 0;
  256. }
  257.     }
  258.     S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "CheckCache: The dst (%s:%d) is not cached", ADDRANDPORT(&pri->dstAddr));
  259.     return -1;
  260. }
  261. /* Is the current set of global variables allowed to proxy or not...?  If it */
  262. /* is, set the global variables we use (next_version, out) with the cached   */
  263. /* info...                                                                   */
  264. int CheckIfAllowed(UdpInfo *u, S5LinkInfo *pri) {
  265.     UdpAuthCache *ac;
  266.     /* haven't sent from the client to this host yet I guess we had better     */
  267.     /* make sure we're allowed to...then find out where we're sending it,      */
  268.     /* and resolve the names/reset the version if we need to.                  */
  269.     if (Authorize(pri, 0) != AUTH_OK) {
  270. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP authorization failed");
  271. return -1;
  272.     }
  273.     /* since we were allowed to talk, we should cache this entry...            */
  274.     if (!(ac = (UdpAuthCache *)calloc(1, sizeof(UdpAuthCache)))) {
  275. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "UDP calloc failed when allocating auth cache entry");
  276. return -1;
  277.     } 
  278.     lsAddrCopy(&ac->addr, &pri->dstAddr, sizeof(S5NetAddr));
  279.     ac->next  = u->acache;
  280.     u->acache = ac;
  281.     u->cura = ac;
  282.     return 0;
  283. }
  284. int WasResolved(UdpInfo *u, S5NetAddr *dst, char *name) {
  285. #ifdef SENDBACK_NAMES
  286.     UdpHostCache *h;
  287.     char *res;
  288.     if (dst->sa.sa_family != AF_INET) {
  289. return 0;
  290.     }
  291.     /* Find out if we looked up a name and found this address...             */
  292.     for (h = u->hcache; h; h=h->next) {
  293. if (h->addr.s_addr == dst->sin_addr.s_addr) break;
  294.     }
  295.     if (h && strcmp(h->name, name)) {
  296. strncpy(name, h->name, MIN(strlen(h->name)+1, S5_HOSTNAME_LEN));
  297. if (strlen(h->h_name)+1 > S5_HOSTNAME_SIZE) name[S5_HOSTNAME_SIZE-1] = '';
  298.     }
  299.     return h?1:0;
  300. #else
  301.     return 0;
  302. #endif
  303. }
  304. void MarkResolved(UdpInfo *u, S5NetAddr *dst, char *name) {
  305. #ifdef SENDBACK_NAMES
  306.     UdpHostCache *h;
  307.     /* If this host wasn't resolve (we're giving the name to the next        */
  308.     /* server), don't cache it, we won't be using it...                      */
  309.     if (dst->sa.sa_family != AF_INET) {
  310. return;
  311.     }
  312.     /* Find out if there was an entry already...                             */
  313.     for (h = u->hcache; h; h=h->next) {
  314. if (strcmp(h->name, name)) break;
  315.     }
  316.     if (h) {
  317. return;
  318.     }
  319.     if (!(h = (UdpHostCache *)malloc(sizeof(UdpHostCache)))) {
  320. S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Malloc failed when allocating resolved host entry");
  321. return;
  322.     }
  323.     strcpy(h->name, name);
  324.     h->addr = dst->sin.sin_addr;
  325.     h->next = u->hcache;
  326.     u->hcache = h;
  327. #endif
  328. }