home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / socks / lib / Rconnect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-27  |  4.3 KB  |  249 lines

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <sys/errno.h>
  5. #include <stdio.h>
  6. #include <netdb.h>
  7. #include <arpa/nameser.h>
  8. #include <resolv.h>
  9. #include <pwd.h>
  10. #include "socks.h"
  11.  
  12. extern int             errno;
  13. extern char            *getenv();
  14. static struct sockaddr_in    cursin;
  15. static unsigned long        SocksHost;
  16.  
  17. static int SendDst(s, dst)
  18. int    s;
  19. Socks_t    *dst;
  20. {
  21.     Write8(s, dst->version);
  22.     Write8(s, dst->cmd);
  23.     Write32(s, dst->port);
  24.     Write32(s, dst->host);
  25. }
  26.  
  27. static int GetDst(s, dst)
  28. int    s;
  29. Socks_t    *dst;
  30. {
  31.     Read8(s, dst->version);
  32.     Read8(s, dst->cmd);
  33.     Read32(s, dst->port);
  34.     Read32(s, dst->host);
  35. }
  36.  
  37. Rconnect(sock, sin, size)
  38. int            sock;
  39. struct sockaddr_in    *sin;
  40. int            size;
  41. {
  42.     Socks_t            dst;
  43.     struct sockaddr_in    nsin;
  44.     struct passwd        *pw;
  45.  
  46.     if ((size != sizeof(struct sockaddr_in))||(sin->sin_family != AF_INET)){
  47.         errno = EAFNOSUPPORT;
  48.         return -1;
  49.     }
  50.  
  51.     nsin.sin_family = AF_INET;
  52.     nsin.sin_port = GetSockPort();
  53.     nsin.sin_addr.s_addr = SocksHost;
  54.  
  55.     if (connect(sock, &nsin, sizeof(struct sockaddr_in)) < 0) {
  56.         errno = ETIMEDOUT;
  57.         return -1;
  58.     }
  59.  
  60.     dst.version = SOCKS_VERSION;
  61.     dst.cmd = SOCKS_CONNECT;
  62.     dst.port = sin->sin_port;
  63.     dst.host = sin->sin_addr.s_addr;
  64.  
  65.     SendDst(sock, &dst);
  66.  
  67. #if SOCKS_VERSION > 2
  68.     if ((pw = getpwuid(getuid())) == NULL) {
  69.         char    c = '\0';
  70.         write(sock, &c, 1);
  71.     } else {
  72.         write(sock, pw->pw_name, strlen(pw->pw_name) + 1);
  73.     }
  74. #endif
  75.  
  76.     GetDst(sock, &dst);
  77.  
  78.     if (dst.cmd == SOCKS_FAIL) {
  79.         errno = ETIMEDOUT;
  80.         return -1;
  81.     }
  82.  
  83.     return 0;
  84. }
  85.  
  86. /*
  87. **  Set up a bind for a remote host, add fill 'cursin' in with the
  88. **   remote server information.
  89. */
  90. Rbind(sock, sin, size, remhost)
  91. int            sock;
  92. struct sockaddr_in    *sin;
  93. int            size;
  94. unsigned long        remhost;
  95. {
  96.     struct sockaddr_in    nsin;
  97.     Socks_t            dst;
  98.     struct passwd        *pw;
  99.  
  100.     nsin.sin_family = AF_INET;
  101.     nsin.sin_port = GetSockPort();
  102.     nsin.sin_addr.s_addr = SocksHost;
  103.  
  104.     if (connect(sock, &nsin, sizeof(struct sockaddr_in)) < 0)
  105.         return -1;
  106.  
  107.     dst.version = SOCKS_VERSION;
  108.     dst.cmd     = SOCKS_BIND;
  109.     dst.port    = 0;
  110.     dst.host    = remhost;
  111.  
  112.     SendDst(sock, &dst);
  113.  
  114. #if SOCKS_VERSION > 2
  115.     if ((pw = getpwuid(getuid())) == NULL) {
  116.         char    c = '\0';
  117.         write(sock, &c, 1);
  118.     } else {
  119.         write(sock, pw->pw_name, strlen(pw->pw_name) + 1);
  120.     }
  121. #endif
  122.  
  123.     GetDst(sock, &dst);
  124.  
  125.     cursin.sin_family = AF_INET;
  126.     cursin.sin_port = dst.port;
  127.     cursin.sin_addr.s_addr = SocksHost;
  128.  
  129.     return 0;
  130. }
  131.  
  132. /*
  133. **  Stub routine since the listen will have alread succeded on the
  134. **   server.
  135. */
  136. Rlisten(s, n)
  137. int    s, n;
  138. {
  139.     return 0;
  140. }
  141.  
  142. /*
  143. **  Well we know where we got a connection from.
  144. */
  145. Rgetsockname(sock, sin, size)
  146. int            sock;
  147. struct sockaddr_in    *sin;
  148. int            *size;
  149. {
  150.     *size = sizeof(struct sockaddr_in);
  151.     *sin = cursin;
  152.  
  153.     return 0;
  154. }
  155.  
  156. /*
  157. **  Do an accept, which is really a select for some data on
  158. **    the present socket.
  159. */
  160. Raccept(sock, sin, size)
  161. int            sock;
  162. struct sockaddr_in    *sin;
  163. int            *size;
  164. {
  165.     fd_set        fds;
  166.     Socks_t        dst;
  167.  
  168.     FD_ZERO(&fds);
  169.     FD_SET(sock, &fds);
  170.  
  171.     if (select(getdtablesize(), &fds, NULL, NULL, NULL) > 0)
  172.         if (FD_ISSET(sock, &fds)) {
  173.             GetDst(sock, &dst);
  174.             sin->sin_family = AF_INET;
  175.             sin->sin_port = dst.port;
  176.             sin->sin_addr.s_addr = dst.host;
  177.  
  178.             return dup(sock);
  179.         }
  180.     return -1;
  181. }
  182.  
  183. SOCKSinit()
  184. {
  185. #ifdef NEED_REMOTE_NAMESERVER
  186.     static char    defaultNS[] = SOCKS_DEFAULT_NS;
  187. #endif
  188.     static char    defaultHOST[] = SOCKS_DEFAULT_HOST;
  189.     char        *cp, *ns;
  190.     struct hostent    *hp;
  191.  
  192.     res_init();
  193.  
  194. #ifdef NEED_REMOTE_NAMESERVER
  195.     if (((cp = getenv("SOCKS_NS")) != NULL) ||
  196.         ((cp = getenv("SOCKS_HOST")) != NULL)) {
  197.         ns = cp;
  198.     } else {
  199.         ns = defaultNS;
  200.     }
  201.  
  202.     if ((hp = gethostbyname(ns)) == NULL) {
  203.         _res.nsaddr_list[0].sin_addr.s_addr = inet_addr(ns);
  204.     } else {
  205.         bcopy(hp->h_addr_list[0], 
  206.             &_res.nsaddr_list[0].sin_addr, hp->h_length);
  207.     }
  208.  
  209.     _res.nscount = 1;
  210. #endif
  211.  
  212.     if ((cp = getenv("SOCKS_HOST")) == NULL) {
  213.         ns = defaultHOST;
  214.     } else {
  215.         ns = cp;
  216.     }
  217.  
  218.     if ((hp = gethostbyname(ns)) == NULL) {
  219.         SocksHost = inet_addr(ns);
  220.     } else {
  221.         bcopy(hp->h_addr_list[0], &SocksHost, hp->h_length);
  222.     }
  223.  
  224.     /*
  225.     **  Make sure it is defined before we let things
  226.     **   get to far along.
  227.     */
  228.     (void) GetSockPort();
  229. }
  230.  
  231. int GetSockPort()
  232. {
  233.     struct servent    *sp;
  234.     static int    service = -1;
  235.  
  236.     if (service > 0)
  237.         return service;
  238.     
  239.     if ((sp = getservbyname("socks", "tcp")) != NULL)
  240.         return service = sp->s_port;
  241.  
  242. #ifdef SOCKS_DEF_PORT
  243.     return service = SOCKS_DEF_PORT;
  244. #else
  245.     fprintf(stderr,"Unknown service socks/tcp\n");
  246.     exit(1);
  247. #endif
  248. }
  249.