Raccept.c
上传用户:zm130024
上传日期:2007-01-04
资源大小:432k
文件大小:8k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1997, 1998, 1999
  3.  *      Inferno Nettverk A/S, Norway.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. The above copyright notice, this list of conditions and the following
  9.  *    disclaimer must appear in all copies of the software, derivative works
  10.  *    or modified versions, and any portions thereof, aswell as in all
  11.  *    supporting documentation.
  12.  * 2. All advertising materials mentioning features or use of this software
  13.  *    must display the following acknowledgement:
  14.  *      This product includes software developed by
  15.  *      Inferno Nettverk A/S, Norway.
  16.  * 3. The name of the author may not be used to endorse or promote products
  17.  *    derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  *
  30.  * Inferno Nettverk A/S requests users of this software to return to
  31.  *
  32.  *  Software Distribution Coordinator  or  sdc@inet.no
  33.  *  Inferno Nettverk A/S
  34.  *  Oslo Research Park
  35.  *  Gaustadal閑n 21
  36.  *  N-0349 Oslo
  37.  *  Norway
  38.  *
  39.  * any improvements or extensions that they make and grant Inferno Nettverk A/S
  40.  * the rights to redistribute these changes.
  41.  *
  42.  */
  43. #include "common.h"
  44. static const char rcsid[] =
  45. "$Id: Raccept.c,v 1.67 1999/09/02 10:41:11 michaels Exp $";
  46. int
  47. Raccept(s, addr, addrlen)
  48. int s;
  49. struct sockaddr *addr;
  50. socklen_t *addrlen;
  51. {
  52. const char *function = "Raccept()";
  53. char addrstring[MAXSOCKADDRSTRING];
  54. struct sockaddr accepted;
  55. struct socks_t packet;
  56. struct socksfd_t *socksfd;
  57. fd_set rset;
  58. int fdbits, p, iotype, remote;
  59. /* can't call Raccept() on unknown descriptors. */
  60. if (!socks_addrisok((unsigned int)s)) {
  61. socks_rmaddr((unsigned int)s);
  62. return accept(s, addr, addrlen);
  63. }
  64. socksfd = socks_getaddr((unsigned int)s);
  65. SASSERTX(socksfd != NULL);
  66. bzero(&packet, sizeof(packet));
  67. packet.version = (unsigned char)socksfd->state.version;
  68. if ((iotype = fcntl(s, F_GETFL, 0)) == -1)
  69. return -1;
  70. #if SOCKS_TRYHARDER
  71. /*
  72.  * Perhaps overkill, but try to be as compatible as possible.
  73.  * BSD supports multiple process' calling accept(2) on
  74.  * the same descriptor, try to support that functionality by locking
  75.  * the socksfd object ourself in this function, so another process
  76.  * calling Raccept() on this object will fail.
  77.  */
  78. if (iotype & NONBLOCKING)
  79. p = socks_lock(socksfd->state.lock, F_WRLCK, 0);
  80. else
  81. p = socks_lock(socksfd->state.lock, F_WRLCK, -1);
  82. if (p != 0)
  83. return -1;
  84. #endif /* SOCKS_TRYHARDER */
  85. FD_ZERO(&rset);
  86. fdbits = -1;
  87. /* check socket we listen on because we support ordinary connects. */
  88. FD_SET(s, &rset);
  89. fdbits = MAX(fdbits, s);
  90. switch (packet.version) {
  91. case SOCKS_V4:
  92. case SOCKS_V5:
  93. /* connection to server, for forwarded connections or errors. */
  94. FD_SET(socksfd->control, &rset);
  95. fdbits = MAX(fdbits, socksfd->control);
  96. break;
  97. case MSPROXY_V2:
  98. break; /* controlconnection checked asynchronously. */
  99. default:
  100. SERRX(packet.version);
  101. }
  102. SASSERTX(fdbits >= 0);
  103. ++fdbits;
  104. if (iotype & NONBLOCKING) {
  105. struct timeval timeout;
  106. timeout.tv_sec = 0;
  107. timeout.tv_usec = 0;
  108. if ((p = selectn(fdbits, &rset, NULL, NULL, &timeout)) == 0) {
  109. errno = EWOULDBLOCK;
  110. p = -1;
  111. }
  112. }
  113. else
  114. p = selectn(fdbits, &rset, NULL, NULL, NULL);
  115. if (p == -1) {
  116. #if SOCKS_TRYHARDER
  117. socks_unlock(socksfd->state.lock);
  118. #endif /* SOCKS_TRYHARDER */
  119. return -1;
  120. }
  121. SASSERTX(p > 0);
  122. if (FD_ISSET(s, &rset)) { /* pending connection on datasocket. */
  123. socklen_t len;
  124. len = sizeof(accepted);
  125. if ((remote = accept(s, &accepted, &len)) == -1) {
  126. #if SOCKS_TRYHARDER
  127. socks_unlock(socksfd->state.lock);
  128. #endif /* SOCKS_TRYHARDER */
  129. return -1;
  130. }
  131. slog(LOG_DEBUG, "%s: accepted: %s",
  132. function, sockaddr2string(&accepted, addrstring, sizeof(addrstring)));
  133. if (socksfd->state.acceptpending) {
  134. /*
  135.  * connection forwarded by server or a ordinary connect?
  136.  */
  137. /* LINTED pointer casts may be troublesome */
  138. if (((struct sockaddr_in *)&accepted)->sin_addr.s_addr
  139. ==  ((struct sockaddr_in *)&socksfd->reply)->sin_addr.s_addr) {
  140. /* matches servers ip address, could be forwarded. */
  141. int forwarded;
  142. switch (socksfd->state.version) {
  143. case SOCKS_V4:
  144. case SOCKS_V5:
  145. packet.req.version = (char)socksfd->state.version;
  146. packet.req.command = SOCKS_BIND;
  147. packet.req.flag = 0;
  148. sockaddr2sockshost(&accepted, &packet.req.host);
  149. packet.req.auth = &socksfd->state.auth;
  150. if (socks_sendrequest(socksfd->control, &packet.req) != 0)
  151. return -1;
  152. if (socks_recvresponse(socksfd->control, &packet.res,
  153. packet.req.version) != 0) {
  154. #if SOCKS_TRYHARDER
  155. socks_unlock(socksfd->state.lock);
  156. #endif
  157. return -1;
  158. }
  159. if (packet.res.host.atype != SOCKS_ADDR_IPV4) {
  160. swarnx("%s: unexpected atype in bindquery response: %d",
  161. function, packet.res.host.atype);
  162. #if SOCKS_TRYHARDER
  163. socks_unlock(socksfd->state.lock);
  164. #endif
  165. return -1;
  166. }
  167. if (packet.res.host.addr.ipv4.s_addr == htonl(0))
  168. forwarded = 0;
  169. else
  170. forwarded = 1;
  171. break;
  172. case MSPROXY_V2:
  173. if (sockaddrareeq(&socksfd->reply, &accepted)) {
  174. /* socksfd->accepted filled in by sigio(). */
  175. accepted = socksfd->accepted;
  176. sockaddr2sockshost(&socksfd->accepted, &packet.res.host);
  177. /* seems to support only one forward. */
  178. socksfd->state.acceptpending = 0;
  179. forwarded = 1;
  180. }
  181. else
  182. forwarded = 0;
  183. break;
  184. default:
  185. SERRX(socksfd->state.version);
  186. }
  187. if (forwarded) {
  188. /* a separate socket with it's own remote address. */
  189. socksfd = socks_addaddr((unsigned int)remote, socksfd);
  190. fakesockshost2sockaddr(&packet.res.host, &accepted);
  191. socksfd->accepted = accepted;
  192. /* has a different local address if INADDR_ANY was bound. */
  193. /* LINTED pointer casts may be troublesome */
  194. if (((struct sockaddr_in *)&socksfd->local)->sin_addr.s_addr
  195. == htonl(INADDR_ANY)) {
  196. len = sizeof(socksfd->local);
  197. if (getsockname(remote, &socksfd->local, &len) != 0)
  198. swarn("%s: getsockname(remote)", function);
  199. }
  200. }
  201. /* else; ordinary connect. */
  202. }
  203. }
  204. /* else; not bind extension, must be a ordinary connect. */
  205. }
  206. else { /* pending connection on controlchannel, server wants to forward. */
  207. SASSERTX(FD_ISSET(socksfd->control, &rset));
  208. switch (packet.version) {
  209. case SOCKS_V4:
  210. case SOCKS_V5:
  211. if (socks_recvresponse(socksfd->control, &packet.res,
  212. packet.version) != 0) {
  213. #if SOCKS_TRYHARDER
  214. socks_unlock(socksfd->state.lock);
  215. #endif
  216. return -1;
  217. }
  218. fakesockshost2sockaddr(&packet.res.host, &accepted);
  219. socksfd->accepted = accepted;
  220. remote = socksfd->control;
  221. break;
  222. case MSPROXY_V2:
  223. SERRX(0); /* should not be checked, so not checked either. */
  224. break;
  225. default:
  226. SERRX(packet.version);
  227. }
  228. }
  229. #if SOCKS_TRYHARDER
  230. socks_unlock(socksfd->state.lock);
  231. #endif
  232. if (addr != NULL) {
  233. *addrlen = MIN(*addrlen, sizeof(accepted));
  234. memcpy(addr, &accepted, (size_t)*addrlen);
  235. }
  236. return remote;
  237. }