1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/* DoNewBind */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <syslog.h>
#include "socks.h"
extern void sockd_fail();
extern u_int32 sockd_ckrt();
extern char *socks_porttoserv();
#if defined(SOCKSIFIED_SOCKD)
extern int SOCKSinit();
extern u_int32 socks_last_conn_host;
extern unsigned short socks_last_conn_port;
extern struct sockshost_s socks_srcsh, socks_dstsh;
#endif /* #if defined(SOCKSIFIED_SOCKD) */
/*
** Set up a socket to be connected to from the outside world.
** diffrence between this an the Version1 protocal is that
** the socket has to be bound from a specific host that
** is passed.
*/
#if defined(SOCKSIFIED_SOCKD)
int RDoNewBind(in, srcshp, dstshp, rtAddr, Nrt, myaddr, log_msg)
#else
int DoNewBind(in, srcshp, dstshp, rtAddr, Nrt, myaddr, log_msg)
#endif /* #if defined(SOCKSIFIED_SOCKD) */
int in;
struct sockshost_s *srcshp, *dstshp;
struct config *rtAddr;
int Nrt;
u_int32 myaddr;
char *log_msg;
/* returns descriptor of socket connection to destination */
{
int new, out, len = sizeof(struct sockaddr_in);
struct sockaddr_in sin;
Socks_t ndst;
int turnon = 1;
struct in_addr *pIP;
int i;
#define dst_name dstshp->dmname[0]
#define dst_serv dstshp->portname
bzero((char *)&sin, sizeof(sin));
#if defined(SO_OOBINLINE)
setsockopt(in, SOL_SOCKET, SO_OOBINLINE, &turnon, sizeof(turnon));
#endif
sin.sin_family = AF_INET;
ndst.version = SOCKS_REPLY_VERSION;
ndst.cmd = SOCKS_RESULT;
sin.sin_port = htons(0);
if ((out = socket(AF_INET, SOCK_STREAM, 0)) < 0)
sockd_fail("socket()", in, &ndst,log_msg);
#if defined(SOCKSIFIED_SOCKD)
sin.sin_addr.s_addr = htonl(INADDR_ANY);
SOCKSinit("rsockd");
socks_last_conn_host = dstshp->shipaddr[0].s_addr;
socks_last_conn_port = dstshp->port;
for (i= 0; i < MAXNAMESPERHOST; i++) {
socks_srcsh.dmname[i] = srcshp->dmname[i];
socks_dstsh.dmname[i] = dstshp->dmname[i];
}
for (i = 0; i < MAXIPPERHOST; i++) {
socks_srcsh.shipaddr[i].s_addr = srcshp->shipaddr[i].s_addr;
socks_dstsh.shipaddr[i].s_addr = dstshp->shipaddr[i].s_addr;
}
strcpy(socks_srcsh.user, srcshp->user);
strcpy(socks_srcsh.ruser, srcshp->ruser);
socks_dstsh.port = srcshp->port;
strcpy(socks_dstsh.portname, dstshp->portname);
if (Rbind(out, (struct sockaddr *)&sin, sizeof(sin)) < 0)
sockd_fail("bind()", in, &ndst,log_msg);
if (Rgetsockname(out, (struct sockaddr *)&sin, &len) < 0)
sockd_fail("getsockname()", in, &ndst,log_msg);
#else
#if defined(MULTIHOMED_SERVER)
sin.sin_addr.s_addr = sockd_ckrt(dstshp, rtAddr, Nrt);
#else
sin.sin_addr.s_addr = myaddr;
#endif /* #if defined(MULTIHOMED_SERVER) */
if (bind(out, (struct sockaddr *)&sin, sizeof(sin)) < 0)
sockd_fail("bind()", in, &ndst,log_msg);
if (getsockname(out, (struct sockaddr *)&sin, &len) < 0)
sockd_fail("getsockname()", in, &ndst,log_msg);
#endif /* #if defined(SOCKSIFIED_SOCKD) */
ndst.port = sin.sin_port;
ndst.host = sin.sin_addr.s_addr;
#if defined(SOCKSIFIED_SOCKD)
if (Rlisten(out, 1) < 0)
sockd_fail("listen()", in, &ndst,log_msg);
#else
if (listen(out, 1) < 0)
sockd_fail("listen()", in, &ndst,log_msg);
#endif /* #if defined(SOCKSIFIED_SOCKD) */
socks_SendDst(in, &ndst);
len = sizeof(struct sockaddr_in);
#if defined(SOCKSIFIED_SOCKD)
if ((new = Raccept(out, (struct sockaddr *)&sin, &len)) < 0)
sockd_fail("accept()", in, &ndst, log_msg);
#else
if ((new = accept(out, (struct sockaddr *)&sin, &len)) < 0)
sockd_fail("accept()", in, &ndst, log_msg);
#endif /* #if defined(SOCKSIFIED_SOCKD) */
#if defined(SO_OOBINLINE)
setsockopt(new, SOL_SOCKET, SO_OOBINLINE, &turnon, sizeof(turnon));
#endif
close(out);
(void)socks_porttoserv(sin.sin_port, dst_serv, sizeof(dst_serv));
#if !defined(SOCKSIFIED_SOCKD)
if (dstshp->shipaddr[0].s_addr != -1) {
for (pIP = dstshp->shipaddr; (*pIP).s_addr != 0; pIP++) {
if (sin.sin_addr.s_addr = (*pIP).s_addr)
break;
}
if ((*pIP).s_addr == 0) {
socks_IPtohost(&sin.sin_addr, dstshp);
socks_porttoserv(sin.sin_port, dst_serv, sizeof(dst_serv));
syslog(LOG_LOW, "failed -- %s. Error: connected to wrong host %s (%s)",
log_msg, dst_name, dst_serv);
ndst.cmd = SOCKS_FAIL;
socks_SendDst(in, &ndst);
exit(1);
}
}
#endif /* #if !defined(SOCKSIFIED_SOCKD) */
syslog(LOG_LOW, "connected -- %s (%s)", log_msg, dst_serv);
ndst.port = sin.sin_port;
ndst.host = sin.sin_addr.s_addr;
socks_SendDst(in, &ndst);
return new;
}
|