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

代理服务器

开发平台:

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: udp.c,v 1.110 1999/12/22 09:29:24 karls Exp $";
  46. /* ARGSUSED */
  47. ssize_t
  48. Rsendto(s, msg, len, flags, to, tolen)
  49. int s;
  50. const void *msg;
  51. size_t len;
  52. int flags;
  53. const struct sockaddr *to;
  54. socklen_t tolen;
  55. {
  56. struct socksfd_t *socksfd;
  57. struct sockshost_t host;
  58. char *nmsg;
  59. size_t nlen;
  60. ssize_t n;
  61. if (to != NULL && to->sa_family != AF_INET)
  62. return sendto(s, msg, len, flags, to, tolen);
  63. if (udpsetup(s, to, SOCKS_SEND) != 0)
  64. return errno == 0 ? sendto(s, msg, len, flags, to, tolen) : -1;
  65. socksfd = socks_getaddr((unsigned int)s);
  66. SASSERTX(socksfd != NULL);
  67. if (to == NULL)
  68. if (socksfd->state.udpconnect)
  69. to = &socksfd->connected;
  70. else
  71. /* best we can do. */
  72. return sendto(s, msg, len, flags, NULL, 0);
  73. /* prefix a udp header to the msg */
  74. nlen = len;
  75. /* LINTED warning: cast discards 'const' from pointer target type */
  76. if ((nmsg = udpheader_add(fakesockaddr2sockshost(to, &host), (char *)msg,
  77. &nlen, 0)) == NULL) {
  78. errno = ENOBUFS;
  79. return -1;
  80. }
  81. n = sendto(s, nmsg, nlen, flags, 
  82. socksfd->state.udpconnect ? NULL : &socksfd->reply, 
  83. socksfd->state.udpconnect ? 0 : sizeof(socksfd->reply));
  84. n -= nlen - len;
  85. free(nmsg);
  86. return MAX(-1, n);
  87. }
  88. ssize_t
  89. Rrecvfrom(s, buf, len, flags, from, fromlen)
  90. int s;
  91. void *buf;
  92. size_t len;
  93. int flags;
  94. struct sockaddr *from;
  95. socklen_t *fromlen;
  96. {
  97. const char *function = "Rrecvfrom()";
  98. struct socksfd_t *socksfd;
  99. struct udpheader_t header;
  100. char *newbuf;
  101. struct sockaddr newfrom;
  102. socklen_t newfromlen;
  103. size_t newlen;
  104. ssize_t n;
  105. if (!socks_addrisok((unsigned int)s)) {
  106. socks_rmaddr((unsigned int)s);
  107. return recvfrom(s, buf, len, flags, from, fromlen);
  108. }
  109. if (udpsetup(s, from, SOCKS_RECV) != 0)
  110. return errno == 0 ? recvfrom(s, buf, len, flags, from, fromlen) : -1;
  111. socksfd = socks_getaddr((unsigned int)s);
  112. SASSERTX(socksfd != NULL);
  113. if (!socksfd->state.protocol.udp)
  114. /* assume tcp connection, nothing to do there. */
  115. return recvfrom(s, buf, len, flags, from, fromlen);
  116. /* if packet is from socksserver it will be prefixed with a header. */
  117. newlen = len + sizeof(header);
  118. if ((newbuf = (char *)malloc(sizeof(*newbuf) * newlen)) == NULL) {
  119. errno = ENOBUFS;
  120. return -1;
  121. }
  122. newfromlen = sizeof(newfrom);
  123. if ((n = recvfrom(s, newbuf, newlen, flags, &newfrom, &newfromlen)) == -1) {
  124. free(newbuf);
  125. return n;
  126. }
  127. SASSERTX(newfromlen > 0);
  128. if (sockaddrareeq(&newfrom, &socksfd->reply)) {
  129. /*
  130.  * packet is from socksserver.
  131. */
  132. if (string2udpheader(newbuf, (size_t)n, &header) == NULL) {
  133. char badfrom[MAXSOCKADDRSTRING];
  134. swarnx("%s: unrecognized socks udppacket from %s",
  135. function, sockaddr2string(&newfrom, badfrom, sizeof(badfrom)));
  136. errno = EAGAIN;
  137. return -1; /* don't know if callee wants to retry. */
  138. }
  139. /* if connected udpsocket, only forward from "connected" source. */
  140. if (socksfd->state.udpconnect) {
  141. struct sockshost_t host;
  142. if (!sockshostareeq(&header.host,
  143. fakesockaddr2sockshost(&socksfd->connected, &host))) {
  144. char a[MAXSOCKSHOSTSTRING];
  145. char b[MAXSOCKSHOSTSTRING];
  146. /*
  147.  * We have a problem here ...  If we failed to resolve
  148.  * address we gave to the socksserver and instead gave a
  149.  * hostname to it, sockshostareeq() will fail unless the server
  150.  * sends the address it is forwarding from as the sockshost too.
  151.  *
  152.  * It is better to place safe than sorry though, so
  153.  * we have to drop the packet in that case, even if it
  154.  * is from the correct source since we can not verify it.
  155.  */
  156. free(newbuf);
  157. slog(LOG_DEBUG, "%s: expected udpreply from %s, got it from %s",
  158. function,
  159. sockshost2string(fakesockaddr2sockshost(&socksfd->connected,
  160. &host), a, sizeof(a)),
  161. sockshost2string(&header.host, b, sizeof(b)));
  162. /*
  163.  * Not sure what to do now, return error or retry?
  164.  * Going with returning error for now.
  165.  */
  166. #if 0
  167. if ((p = fcntl(s, F_GETFL, 0)) == -1)
  168. return -1;
  169. if (p & NONBLOCKING) {
  170. #endif
  171. errno = EAGAIN;
  172. return -1;
  173. #if 0
  174. }
  175. /* else; assume the best thing is to retry. */
  176. return Rrecvfrom(s, buf, len, flags, from, fromlen);
  177. #endif
  178. }
  179. }
  180. /* replace "newfrom" with the address socksserver says packet is from. */
  181. fakesockshost2sockaddr(&header.host, &newfrom);
  182. /* callee doesn't get socksheader. */
  183. n -= PACKETSIZE_UDP(&header);
  184. SASSERTX(n >= 0);
  185. memcpy(buf, &newbuf[PACKETSIZE_UDP(&header)], MIN(len, (size_t)n));
  186. }
  187. else /* ordinary udppacket, not from socksserver. */
  188. memcpy(buf, newbuf, MIN(len, (size_t)n));
  189. free(newbuf);
  190. if (from != NULL) {
  191. *fromlen = MIN(*fromlen, newfromlen);
  192. memcpy(from, &newfrom, (size_t)*fromlen);
  193. }
  194. return MIN(len, (size_t)n);
  195. }
  196. int
  197. udpsetup(s, to, type)
  198. int s;
  199. const struct sockaddr *to;
  200. int type;
  201. {
  202. struct socks_t packet;
  203. struct socksfd_t socksfd;
  204. struct sockaddr_in newto;
  205. struct sockshost_t src, dst;
  206. socklen_t len;
  207. int p;
  208. if (!socks_addrisok((unsigned int)s))
  209. socks_rmaddr((unsigned int)s);
  210. if (socks_getaddr((unsigned int)s) != NULL)
  211. return 0; /* all set up. */
  212. /*
  213.  * if this socket has not previously been used we need to
  214.  * make a new connection to the socksserver for it.
  215.  */
  216. errno = 0;
  217. switch (type) {
  218. case SOCKS_RECV:
  219. /*
  220.  * problematic, trying to receive on socket not sent on.
  221.  */
  222. bzero(&newto, sizeof(newto));
  223. newto.sin_family = AF_INET;
  224. newto.sin_addr.s_addr = htonl(INADDR_ANY);
  225. newto.sin_port = htons(0);
  226. /* LINTED pointer casts may be troublesome */
  227. to = (struct sockaddr *)&newto;
  228. break;
  229. case SOCKS_SEND:
  230. if (to == NULL)
  231. return -1; /* no address and unknown socket, no idea. */
  232. break;
  233. default:
  234. SERRX(type);
  235. }
  236. /*
  237.  * we need to send the socksserver our address.
  238.  * First check if the socket already has a name, if so
  239.  * use that, otherwise assign the name ourselves.
  240.  */
  241. bzero(&socksfd, sizeof(socksfd));
  242. len = sizeof(socksfd.local);
  243. if (getsockname(s, &socksfd.local, &len) != 0)
  244. return -1;
  245. sockaddr2sockshost(&socksfd.local, &src);
  246. fakesockaddr2sockshost(to, &dst);
  247. bzero(&packet, sizeof(packet));
  248. packet.version = SOCKS_V5;
  249. packet.req.version = packet.version;
  250. packet.req.command = SOCKS_UDPASSOCIATE;
  251. packet.req.flag |= SOCKS_USECLIENTPORT;
  252. /* packet.req.flag |= SOCKS_INTERFACEREQUEST; */
  253. packet.req.host = src;
  254. if ((socksfd.control = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  255. return -1;
  256. if ((socksfd.route
  257. = socks_connectroute(socksfd.control, &packet, &src, &dst)) == NULL) {
  258. close(socksfd.control);
  259. return -1;
  260. }
  261. /* LINTED  pointer casts may be troublesome */
  262. if ((((struct sockaddr_in *)(&socksfd.local))->sin_addr.s_addr
  263. == htonl(INADDR_ANY))
  264. /* LINTED  pointer casts may be troublesome */
  265. || ((struct sockaddr_in *)(&socksfd.local))->sin_port == htons(0)) {
  266. /*
  267.  * local name not fixed, set it, port may be bound, we need to bind
  268.  * ip too however.
  269.  */
  270. /* LINTED  pointer casts may be troublesome */
  271. const in_port_t port = ((struct sockaddr_in *)(&socksfd.local))->sin_port;
  272. if (port != htons(0)) {
  273. /*
  274.  * port is bound.  We will try to unbind and then rebind same port
  275.  * but now also bind ip address.  XXX Dangerous stuff.
  276.  */
  277. if ((p = socketoptdup(s)) == -1) {
  278. close(socksfd.control);
  279. return -1;
  280. }
  281. if (dup2(p, s) == -1) {
  282. close(socksfd.control);
  283. close(p);
  284. return -1;
  285. }
  286. close(p);
  287. }
  288. /*
  289.  * don't have much of an idea on what ip address to use so might as
  290.  * well use same as tcp connection to socksserver uses.
  291.  */
  292. len = sizeof(socksfd.local);
  293. if (getsockname(socksfd.control, &socksfd.local, &len) != 0) {
  294. close(socksfd.control);
  295. return -1;
  296. }
  297. /* LINTED  pointer casts may be troublesome */
  298. ((struct sockaddr_in *)&socksfd.local)->sin_port = port;
  299. if (bind(s, &socksfd.local, sizeof(socksfd.local)) != 0) {
  300. close(socksfd.control);
  301. return -1;
  302. }
  303. if (getsockname(s, &socksfd.local, &len) != 0) {
  304. close(socksfd.control);
  305. return -1;
  306. }
  307. sockaddr2sockshost(&socksfd.local, &packet.req.host);
  308. }
  309. /* packet.req.host.addr.ipv4.s_addr = htonl(INADDR_ANY); */
  310. /* packet.req.host.port = htons(0); */
  311. if (socks_negotiate(s, socksfd.control, &packet, socksfd.route) != 0)
  312. return -1;
  313. socksfd.state.auth = packet.auth;
  314. socksfd.state.version = packet.version;
  315. socksfd.state.command = SOCKS_UDPASSOCIATE;
  316. socksfd.state.protocol.udp = 1;
  317. sockshost2sockaddr(&packet.res.host, &socksfd.reply);
  318. len = sizeof(socksfd.server);
  319. if (getpeername(socksfd.control, &socksfd.server, &len) != 0) {
  320. close(socksfd.control);
  321. return -1;
  322. }
  323. #if 0
  324. /*
  325.  * if the remote server supports interface requests, try to get
  326.  * the address it's using on our behalf.
  327.  */
  328. if (packet.res.flag & SOCKS_INTERFACEREQUEST) {
  329. struct interfacerequest_t ifreq;
  330. ifreq.rsv = 0;
  331. ifreq.sub = SOCKS_INTERFACEDATA;
  332. ifreq.flag = 0;
  333. ifreq.host.atype = SOCKS_ADDR_IPV4;
  334. ifreq.host.addr.ipv4 = ((const struct sockaddr_in *)to)->sin_addr;
  335. ifreq.host.port = ((const struct sockaddr_in *)to)->sin_port;
  336. if (send_interfacerequest(socksfd.control, &ifreq,
  337. socksfd.state.version) == 0) {
  338. }
  339. }
  340. #endif
  341. if (socks_addaddr((unsigned int)s, &socksfd) == NULL) {
  342. close(socksfd.control);
  343. errno = ENOBUFS;
  344. return -1;
  345. }
  346. return 0;
  347. }