File: DoNewBind.c

package info (click to toggle)
socks4-server 4.3.beta2-9
  • links: PTS
  • area: main
  • in suites: potato
  • size: 1,532 kB
  • ctags: 1,777
  • sloc: ansic: 19,309; makefile: 400; sh: 69
file content (149 lines) | stat: -rw-r--r-- 4,425 bytes parent folder | download | duplicates (9)
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;
}