wrap_udp.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:22k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /* Copyright (c) 1995,1996,1997 NEC Corporation. All rights reserved. */
- /* */
- /* The redistribution, use and modification in source or binary forms of */
- /* this software is subject to the conditions set forth in the copyright */
- /* document ("Copyright") included with this distribution. */
- /*
- * $Id: wrap_udp.c,v 1.61.2.1.2.8 1998/11/11 23:28:39 wlu Exp $
- */
- #include "socks5p.h"
- #include "buffer.h"
- #include "addr.h"
- #include "protocol.h"
- #include "wrap.h"
- #include "libproto.h"
- #include "hostname.h"
- #include "cache.h"
- #include "log.h"
- #include "msg.h"
- #define CODEABLE(x) ((x) && (x)->cinfo.auth.encode)
- #define AINFO(x) ((x)->cinfo.auth)
- #define SETVERS(x, y) ((x)[0] = (y))
- #define SETRESV(x, y) memset(x, 0, 2)
- #define SETFRAG(x, y) ((x)[2] = (y))
- /* implements the SOCKS_SEND protocol, sending a message to the server, and */
- /* perhaps sometime down the road receiving an advisory deny-send message. */
- /* adds the header (toport, toaddr, fragment info(if any)) to the message */
- /* message and sends it to the proxy */
- /* */
- /* C==>P <resv(2)><frag(1)><atype(1)><host(4/v)><port(2)><data> */
- /* */
- /* returns the number of bytes sent on success; -1 on failure */
- static IORETTYPE lsProtoSend(S5IOHandle fd, lsProxyInfo *pri, const IOPTRTYPE msg, IOLENTYPE len, int flags, const ss *dest, int dstlen) {
- char hostname[S5_HOSTNAME_SIZE], header[UDP_MAX_PAYLOAD];
- int headerlen, rval, nlen;
- S5NetAddr name;
- S5Packet buf[2];
- memset(&name, 0, sizeof(S5NetAddr));
- if (!lsGetCachedHostname((S5NetAddr *)dest, hostname, sizeof(hostname))) {
- name.sa.sa_family = AF_S5NAME;
- name.sn.sn_port = lsAddr2Port((S5NetAddr *)dest);
- strcpy(name.sn.sn_name, hostname);
- } else {
- lsAddrCopy(&name, (S5NetAddr *)dest, dstlen);
- }
- SETVERS(header, 0);
- SETRESV(header, 0); /* unused - reserved */
- SETFRAG(header, 0); /* unused - fragment */
- lsSetProtoAddr(SOCKS5_VERSION, header, &name);
- if ((nlen = len + (headerlen = HDRSIZE(header))) > UDP_MAX_PAYLOAD) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS sendto: Message too big for encapsulation...");
- SETSOCKETERROR(EMSGSIZE);
- return -1;
- }
- memcpy(header + headerlen, (char *)msg, len);
- if (CODEABLE(pri)) {
- buf[0].data = header;
- buf[0].len = nlen;
- buf[1].data = NULL;
- buf[1].len = 0;
- if (AINFO(pri).encode(&buf[0], &buf[1], S5_ENCODE, AINFO(pri).context) < nlen) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS sendto: Encode failed...");
- SETSOCKETERROR(EFAULT);
- return -1;
- }
- /* If the buffer was too big, bail. Otherwise, copy it... */
- if ((nlen = buf[1].len) > UDP_MAX_PAYLOAD) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS sendto: Encoded Message too big for encapsulation...");
- SETSOCKETERROR(EMSGSIZE);
- return -1;
- }
- memcpy(header, buf[1].data, buf[1].len);
- free(buf[1].data);
- nlen = buf[1].len;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS sendto: Sent %d byte msg to proxy %s:%d...", nlen, ADDRANDPORT(&pri->prxyin));
- rval = REAL(sendto)(fd, header, nlen, flags, (ss *)&pri->prxyin, sizeof(ssi));
- return (rval == nlen)?len:-1;
- }
- /* extracts the header info from msg and fills in the appropriate fields... */
- /* returns 0 on success and -1 on failure... */
- static int lsUdpExtractHeader(char *msg, int n, int *headerlen, ss *from, int fromlen) {
- S5NetAddr netaddr;
- /* Here we make sure that we really go a valid message... */
- if (n < (*headerlen = HDRSIZE(msg))) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS recvfrom: invalid message");
- return -1;
- }
- /* Extract the address from the header, and mark how long the header was */
- if (lsGetProtoAddr(SOCKS5_VERSION, msg, &netaddr) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS recvfrom: invalid message");
- return -1;
- }
- /* If the result came back as a name, we sent it as a name, so we can */
- /* just call gethostbyname on the name to find out what address we faked */
- /* it as... */
- switch (netaddr.sa.sa_family) {
- case AF_S5NAME:
- lsGetCachedAddress(netaddr.sn.sn_name, (S5NetAddr *)from);
- lsAddrSetPort((S5NetAddr *)from, netaddr.sn.sn_port);
- break;
- default:
- lsAddrCopy((S5NetAddr *)from, &netaddr, fromlen);
- break;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKS recvfrom: %s:%d", ADDRANDPORT((S5NetAddr *)from));
- return 0;
- }
- /* wrapper around the connect system call. */
- int lsUdpConnect(S5IOHandle sd, CONST ss *name, int namelen) {
- lsSocksInfo *pcon = lsConnectionFind(sd);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpConnect: fd %d", sd);
- /* if they were just trying to delete the current connection, do it. */
- if (name == NULL) {
- if (pcon) lsConnectionDel(sd);
- return 0;
- }
- /* If we think this isn't a udp socket, check to see if it's still ok. */
- /* If it is, return EISCONN as errno, otherwise delete it -- invalid. */
- if (pcon) {
- if (pcon->cmd != SOCKS_UDP) {
- if (S5IOCheck(pcon->fd) >= 0) {
- SETSOCKETERROR(EISCONN);
- return -1;
- }
- lsConnectionDel(sd);
- pcon = NULL;
- }
- /* If we're already talking to the right person, we're done... */
- if (pcon && ADDRCOMP((ssi *)name, &pcon->peer.sin)) return 0;
- }
- /* Make a connection since one didn't exit... or qthe address was wrong */
- if ((pcon = lsLibProtoExchg(sd, (S5NetAddr *)name, SOCKS_UDP)) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpConnect: Protocol exchange failed");
- return -1;
- }
- pcon->status = CON_ESTABLISHED;
- if (!pcon->cur || pcon->cur->how == DIRECT) return REAL(connect)(sd, (ss *)name, namelen);
- return 0;
- }
- static int proxy_bind(S5IOHandle sd, const S5NetAddr *dst) {
- lsSocksInfo *pcon;
- lsProxyInfo *pri;
- S5NetAddr na;
- int rval = 0;
- /* First establish the UDP session. Then exchange UDP_BIND sub-command */
- /* If the server doesn't support UDP sub-command, do the DISCARDHACK... */
- lsAddrCopy(&na, dst, lsAddrSize(dst));
- if ((pcon = lsLibProtoExchg(sd, &na, SOCKS_UDP)) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "proxy_bind: Protocol exchange failed");
- return -1;
- }
- if ((pri = pcon->cur) != NULL && pri->how != DIRECT) {
- if (pri->reserved & S5UDP_USECTRL) {
- if (pcon->myport != (u_short)0) lsAddrSetPort(&na, pcon->myport);
- rval = lsLibExchgUdpCmd(pcon, &na, S5UDP_BIND);
- } else { /* DISCARDHACK */
- char msg = ' ';
- lsAddrSetPort(&na, 9);
- rval = lsProtoSend(pcon->fd, pri, &msg, 1, 0, &na.sa, lsAddrSize(&na));
- }
- }
- if (rval < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "proxy_bind: UDP bind failed");
- return -1;
- }
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "proxy_bind: Done");
- return 0;
- }
- int lsUdpBind(S5IOHandle sd, CONST ss *name, int namelen) {
- lsSocksInfo *pcon;
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpBind: fd %d", sd);
- /* keep a record of binded socket for future use */
- pcon = lsLibProtoExchg(sd, NULL, SOCKS_UDP);
- /* More checking is needed, such as connected UDP socket, etc... */
- if (!lsLastCon || !lsLastCon->pri || lsLastCon->pri->how != SOCKS5_VERSION) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpBind: No prior connection found, binding locally");
- return REAL(bind)(sd, (ss *)name, namelen);
- }
- if (((ssi *)name)->sin_port != (u_short)0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpBind: bind local to %d", (int)((ssi *)name)->sin_port);
- if (REAL(bind)(sd, (ss *)name, namelen) < 0) return -1;
- }
- if (proxy_bind(sd, &lsLastCon->peer) < 0) {
- if (pcon && pcon->pri) lsProxyCacheDel(pcon, pcon->pri);
- return -1;
- }
- pcon->status = CON_BOUND;
- return 0;
- }
- /* wrapper around the send system call. */
- IORETTYPE lsUdpSend(S5IOHandle sd, const IOPTRTYPE msg, IOLENTYPE len, int flags) {
- lsSocksInfo *pcon = lsConnectionFind(sd);
- S5NetAddr junk;
- /* If we can't find a valid connection, for whatever reason, return a */
- /* direct send... */
- if (!pcon || (pcon->status != CON_ESTABLISHED && pcon->status != CON_ESTABLISHEDSEND)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpSend: No valid connection found, returning direct send");
- return REAL(send)(sd, msg, len, flags);
- }
- junk = pcon->peer;
- /* PROXY, see if the control connection is still there; if not reconnect */
- if ((pcon = lsLibProtoExchg(sd, &junk, SOCKS_UDP)) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpSend: Protocol exchange failed");
- return -1;
- }
- pcon->status = CON_ESTABLISHEDSEND;
- if (!pcon->cur || pcon->cur->how == DIRECT) return REAL(send)(sd, msg, len, flags);
- return lsProtoSend(sd, pcon->cur, msg, len, flags, &pcon->peer.sa, lsAddrSize(&pcon->peer));
- }
- /* wrapper around the sendto system call. */
- IORETTYPE lsUdpSendto(S5IOHandle s, const IOPTRTYPE msg, IOLENTYPE len, int flags, ss *to, int tolen) {
- lsSocksInfo *pcon = lsConnectionFind(s);
- u_char bs = CON_NOTESTABLISHED;
- S5NetAddr bp;
- int rval;
- /* Apparently some OSs allow a NULL address to mean send. */
- /* Unfortunately, this may get us caught in a loop, where lsUdpSendto */
- /* calls lsUdpSend which calls sendto which calls lsUdpSendto... So we */
- /* have all this DontLoop code to protect against that... */
- if (to == NULL) return lsUdpSend(s, msg, len, flags);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKSsendto %s:%d...", ADDRANDPORT((S5NetAddr *)to));
- /* only ok to sendto() the person we're connected to... */
- if (pcon && (pcon->status == CON_ESTABLISHED || pcon->status == CON_ESTABLISHEDSEND)) {
- if (!ADDRCOMP((ssi *)to, &pcon->peer.sin)) {
- memset(&bp, 0 , sizeof(S5NetAddr));
- lsAddrCopy(&bp, &pcon->peer, lsAddrSize(&pcon->peer));
- bs = pcon->status;
- } else return lsUdpSend(s, msg, len, flags);
- }
- /* No udp association for this socket, so send directly */
- if ((pcon = lsLibProtoExchg(s, (S5NetAddr *)to, SOCKS_UDP)) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpSendto: Protocol exchange failed");
- return -1;
- }
- /* Don't send a message using the wrong protocol... */
- if (!pcon->cur || pcon->cur->how != SOCKS5_VERSION) {
- rval = REAL(sendto)(s, msg, len, flags, to, tolen);
- } else {
- rval = lsProtoSend(s, pcon->cur, msg, len, flags, to, tolen);
- }
- if (bs != CON_NOTESTABLISHED) {
- pcon->status = bs;
- lsAddrCopy(&pcon->peer, &bp, lsAddrSize(&bp));
- } else if (pcon) pcon->status = CON_SENDTO;
- return rval;
- }
- /* wrapper around the recvfrom system call. */
- IORETTYPE lsUdpRecvfrom(S5IOHandle s, IOPTRTYPE msg, IOLENTYPE len, int flags, ss *from, int *fromlen, int isRecv) {
- lsSocksInfo *pcon = lsConnectionFind(s);
- char recvbuf[UDP_MAX_PAYLOAD+1], *obuf = NULL;
- int olen = 0, oset, fl = sizeof(ssi);
- lsProxyInfo *pri;
- ssi tmp;
- S5Packet buf[2];
- if (!isRecv) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKSrecvfrom...");
- } else {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKSrecv...");
- }
- if (!from) {
- from = (ss *)&tmp;
- fromlen = &fl;
- }
- if (!pcon || pcon->cmd != SOCKS_UDP) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "No valid connection found, returning direct recvfrom");
- if (isRecv) return REAL(recv)(s, msg, len, flags);
- return REAL(recvfrom)(s, msg, len, flags, from, fromlen);
- }
- /* Do we need to check whether the socket has sent a message or binded */
- /* remotely? We might need to do a remote bind here if neither is true.. */
- /* */
- /* If it is locally binded and remote tcp connection is available, do a */
- /* remote bind. */
- if (pcon->status == CON_NOTESTABLISHED) {
- if (lsLastCon != NULL) proxy_bind(s, &lsLastCon->peer);
- pcon->status = CON_RECV;
- }
- obuf = recvbuf;
- oset = 0;
- /* get a new message */
- if ((olen = REAL(recvfrom)(s, recvbuf, UDP_MAX_PAYLOAD, flags, from, fromlen)) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "recvfrom failed: %m");
- return -1;
- }
- /* verify the contents as being from the right person */
- if (!(pri = lsProxyCacheFind(pcon, (S5NetAddr *)from, SOCKS5_VERSION, 1)) || pri->how != SOCKS5_VERSION) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Direct recvfrom (%x;%d)", pri, pri?pri->how:0);
- goto done;
- }
- /* verify if the server is alive. If not, discard the packet and */
- /* and delete the proxy cache.... */
- if (S5IOCheck(pri->cinfo.fd) < 0) {
- lsProxyCacheDel(pcon, pri);
- return -1;
- }
- if (!ADDRCOMP(&pri->prxyin.sin, (ssi *)from)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Recv from wrong host");
- return -1;
- }
- if (CODEABLE(pri)) {
- buf[0].data = recvbuf;
- buf[0].len = olen;
- buf[0].off = olen;
- buf[1].data = NULL;
- buf[1].len = 0;
- buf[1].off = 0;
- if (AINFO(pri).encode(&buf[0], &buf[1], S5_DECODE, AINFO(pri).context) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Decoding failed");
- return -1;
- }
- obuf = buf[1].data;
- olen = buf[1].len;
- }
- if (lsUdpExtractHeader(obuf, olen, &oset, from, *fromlen) != 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Header extraction failed");
- if (obuf && obuf != recvbuf) free(obuf);
- return -1;
- }
- done:
- if (*fromlen > sizeof(ssi)) *fromlen = sizeof(ssi);
- memcpy((char *)msg, obuf + oset, olen = MIN((int)len, olen - oset));
- if (obuf && obuf != recvbuf) free(obuf);
- return olen;
- }
- /* wrapper around the getpeername system call. */
- /* returns 0 on success; -1 on failure */
- int lsUdpGetpeername(S5IOHandle sd, ss *name, int *namelen) {
- lsSocksInfo *pcon = lsConnectionFind(sd);
- if (!pcon || pcon->cmd != SOCKS_UDP || (pcon->status != CON_ESTABLISHED && pcon->status != CON_ESTABLISHEDSEND))
- return REAL(getpeername)(sd, name, namelen);
- if (name) {
- *namelen = MIN(*namelen, lsAddrSize(&pcon->peer));
- lsAddrCopy((S5NetAddr *)name, &pcon->peer, *namelen);
- }
- return 0;
- }
- /* wrapper around the getpeername system call. */
- /* returns 0 on success; -1 on failure */
- int lsUdpGetsockname(S5IOHandle sd, ss *name, int *namelen) {
- int rval;
- S5NetAddr junk;
- lsProxyInfo *pri;
- lsSocksInfo *pcon = lsConnectionFind(sd);
- rval = REAL(getsockname)(sd, name, namelen);
- if (!pcon || pcon->cmd != SOCKS_UDP || !lsAddrIsNull(&pcon->peer) || rval < 0) return rval;
- junk = pcon->peer;
- pcon = lsLibProtoExchg(sd, &junk, SOCKS_UDP);
- if (!pcon || !(pri = pcon->cur) || !(pri->reserved & S5UDP_USECTRL)) return rval;
- if (lsAddr2Port(&pri->prxyout) == (u_short)0 && lsLibExchgUdpCmd(pcon, &junk, S5UDP_GETSOCKNAME) < 0) return -1;
- ((ssi *)name)->sin_addr.s_addr = INADDR_ANY;
- lsAddrSetPort((S5NetAddr *)name, lsAddr2Port(&pri->prxyout));
- if (*namelen > sizeof(ssi)) *namelen = sizeof(ssi);
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "lsUdpGetSockname: %s:%d", ADDRANDPORT((S5NetAddr *)name));
- return 0;
- }
- #ifdef HAVE_SENDMSG
- IORETTYPE
- lsUdpSendmsg(S5IOHandle s, ms *msg, int flags)
- {
- ss *to;
- int tolen, i, len=0;
- char *buf;
- S5NetAddr dst;
- lsSocksInfo *pcon = lsConnectionFind(s);
- memset(&dst, 0 , sizeof(S5NetAddr));
- to = (struct sockaddr *) msg->msg_name;
- tolen = sizeof((struct sockaddr *) msg->msg_name);
- for(i=0; i<msg->msg_iovlen; i++)
- len += msg->msg_iov[i].iov_len;
- buf = (char *) malloc(len);
- for(i=0; i<msg->msg_iovlen; i++) {
- memcpy(buf, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
- buf = buf + msg->msg_iov[i].iov_len;
- }
- buf = buf - len;
- if(!to)
- return lsUdpSend(s, buf, len, flags);
- else
- lsAddrCopy(&dst, (S5NetAddr *)to, lsAddrSize((S5NetAddr *)to));
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0,"SOCKSsendmsg %s:%d..",
- ADDRANDPORT(&dst));
- /* only ok to sendmsg() the person we're connected to. */
- if(pcon&&(pcon->status == CON_ESTABLISHED ||
- pcon->status == CON_ESTABLISHEDSEND)) {
- if(!ADDRCOMP((ssi *)to, &pcon->peer.sin)) {
- SETSOCKETERROR(EISCONN);
- return -1;
- }
- else
- return lsUdpSend(s, buf, len, flags);
- }
- /* No udp association for this socket, so send directly */
- if((pcon = lsLibProtoExchg(s, &dst, SOCKS_UDP)) == NULL) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0,
- "lsUdpSendmsg: Protocol exchange failed");
- SETSOCKETERROR(EBADF);
- return -1;
- }
- pcon->status = CON_SENDTO;
- /* Don't send a message using the wrong protocol... */
- if(!pcon->cur || pcon->cur->how != SOCKS5_VERSION)
- return REAL(sendmsg)(s, msg, flags);
- /* Send the message directly... */
- return lsProtoSend(s, pcon->cur, (u_char *)buf, len, flags, to, tolen);
- }
- IORETTYPE
- lsUdpRecvmsg(S5IOHandle s, ms *msg, int flags)
- {
- u_char recvbuf[UDP_MAX_PAYLOAD+1], *obuf = NULL;
- int olen = 0, oset, fl = sizeof(ssi);
- lsProxyInfo *pri;
- ss *from;
- int fromlen;
- int len=0;
- int i;
- ssi tmp;
- lsSocksInfo *pcon = lsConnectionFind(s);
- S5Packet buf[2];
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "SOCKSrecvmsg...");
- from = (struct sockaddr *) msg->msg_name;
- fromlen = sizeof((struct sockaddr *) msg->msg_name);
- for(i=0; i<msg->msg_iovlen; i++)
- len += msg->msg_iov[i].iov_len;
- if(!from) {
- from = (ss *)&tmp;
- fromlen = fl;
- }
- if(!pcon || pcon->cmd != SOCKS_UDP) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0,
- "No valid connection found, returning direct recvmsg");
- return REAL(recvmsg)(s, msg, flags);
- }
- /* Do we need to check whether the socket has sent a message or bound */
- /* remotely? We might need to do a remote bind here if neither is true.. */
- /* */
- /* If it is locally bound and remote tcp connection is available, do a */
- /* remote bind. */
- if(pcon->status == CON_NOTESTABLISHED) {
- if(lsLastCon != NULL && proxy_bind(s, &lsLastCon->peer) < 0)
- return -1;
- pcon->status = CON_RECV;
- }
- for(oset = 0, obuf = recvbuf;; oset = 0, obuf = recvbuf) {
- if(olen != 0 && (flags & MSG_PEEK)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0,"Purging old message");
- REAL(recvmsg)(s, msg, flags&~MSG_PEEK);
- }
- /* get a new message */
- if((olen = REAL(recvmsg)(s, msg, flags )) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10),0,"recvmsg failed: %m");
- return -1;
- }
- /* verify the contents as being from the right person */
- if((pri = (lsProxyCacheFind(pcon, (S5NetAddr *)from,SOCKS5_VERSION, 1))) == NULL ||
- pri->how != SOCKS5_VERSION) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Direct recvmsg (%x;%d)", pri, pri?pri->how:0);
- goto done;
- }
- /* verify if the server is alive. If not, discard the packet and */
- /* and delete the proxy cache.... */
- if(S5IOCheck(pri->cinfo.fd) < 0) {
- lsProxyCacheDel(pcon, pri);
- continue;
- }
- if(!ADDRCOMP(&pri->prxyin.sin, (ssi *)from)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0,"Recvmsg from wrong host");
- continue;
- }
- if(CODEABLE(pri)) {
- buf[0].data = recvbuf;
- buf[0].len = olen;
- buf[0].off = olen;
- buf[1].data = NULL;
- buf[1].len = 0;
- buf[1].off = 0;
- if(AINFO(pri).encode(&buf[0],&buf[1],S5_DECODE,AINFO(pri).context) < 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Decoding failed");
- continue;
- }
- obuf = buf[1].data;
- olen = buf[1].len;
- }
- if(lsUdpExtractHeader(obuf, olen, &oset, from, fromlen) != 0) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0,"Header extraction failed");
- if(obuf != recvbuf)
- free(obuf);
- continue;
- }
- if((pcon->status == CON_ESTABLISHED || pcon->status == CON_ESTABLISHEDSEND)) {
- if (!ADDRCOMP(&pcon->peer.sin, (ssi *)from)) {
- S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0,"Recvmsg from wrong host");
- if(obuf != recvbuf)
- free(obuf);
- continue;
- } /* if (!ADDRCOMP(&pcon->peer.sin, (ssi *)from)) */
- } /* if(isRecv && (pcon->status == CON_ESTABLISHED....*/
- done:
- if(fromlen > sizeof(ssi))
- fromlen = sizeof(ssi);
- memcpy((u_char *)msg, obuf + oset, olen = MIN((int)len, olen - oset));
- if(obuf != recvbuf)
- free(obuf);
- return olen;
- } /* for(oset = 0, obuf = recvbuf;; ...) */
- }
- #endif /* HAVE_SENDMSG */