comparison localtcpfwd.c @ 4:fe6bca95afa7

Makefile.in contains updated files required
author Matt Johnston <matt@ucc.asn.au>
date Tue, 01 Jun 2004 02:46:09 +0000
parents
children 425ed5c20157
comparison
equal deleted inserted replaced
-1:000000000000 4:fe6bca95afa7
1 #include "includes.h"
2 #include "session.h"
3 #include "dbutil.h"
4 #include "localtcpfwd.h"
5
6 #ifndef DISABLE_LOCALTCPFWD
7 static int newtcp(const char * host, int port);
8
9 /* Called upon creating a new direct tcp channel (ie we connect out to an
10 * address */
11 int newtcpdirect(struct Channel * channel) {
12
13 unsigned char* desthost = NULL;
14 unsigned int destport;
15 unsigned char* orighost = NULL;
16 unsigned int origport;
17 int sock;
18 int len;
19 int ret = DROPBEAR_FAILURE;
20
21 if (ses.opts->nolocaltcp) {
22 TRACE(("leave newtcpdirect: local tcp forwarding disabled"));
23 goto out;
24 }
25
26 desthost = buf_getstring(ses.payload, &len);
27 if (len > MAX_HOST_LEN) {
28 TRACE(("leave newtcpdirect: desthost too long"));
29 goto out;
30 }
31
32 destport = buf_getint(ses.payload);
33
34 orighost = buf_getstring(ses.payload, &len);
35 if (len > MAX_HOST_LEN) {
36 TRACE(("leave newtcpdirect: orighost too long"));
37 goto out;
38 }
39
40 origport = buf_getint(ses.payload);
41
42 /* best be sure */
43 if (origport > 65535 || destport > 65535) {
44 TRACE(("leave newtcpdirect: port > 65535"));
45 goto out;
46 }
47
48 sock = newtcp(desthost, destport);
49 if (sock < 0) {
50 TRACE(("leave newtcpdirect: sock failed"));
51 goto out;
52 }
53
54 ses.maxfd = MAX(ses.maxfd, sock);
55
56 /* Note that infd is actually the "outgoing" direction on the
57 * tcp connection, vice versa for outfd.
58 * We don't set outfd, that will get set after the connection's
59 * progress succeeds */
60 channel->infd = sock;
61 channel->initconn = 1;
62
63 ret = DROPBEAR_SUCCESS;
64
65 out:
66 m_free(desthost);
67 m_free(orighost);
68 TRACE(("leave newtcpdirect: ret %d", ret));
69 return ret;
70 }
71
72 /* Initiate a new TCP connection - this is non-blocking, so the socket
73 * returned will need to be checked for success when it is first written.
74 * Similarities with OpenSSH's connect_to() are not coincidental.
75 * Returns -1 on failure */
76 static int newtcp(const char * host, int port) {
77
78 int sock = -1;
79 char portstring[6];
80 struct addrinfo *res = NULL, *ai;
81 int val;
82
83 struct addrinfo hints;
84
85 TRACE(("enter newtcp"));
86
87 memset(&hints, 0, sizeof(hints));
88 /* TCP, either ip4 or ip6 */
89 hints.ai_socktype = SOCK_STREAM;
90 hints.ai_family = PF_UNSPEC;
91
92 snprintf(portstring, sizeof(portstring), "%d", port);
93 if (getaddrinfo(host, portstring, &hints, &res) != 0) {
94 if (res) {
95 freeaddrinfo(res);
96 }
97 TRACE(("leave newtcp: failed getaddrinfo"));
98 return -1;
99 }
100
101 /* Use the first socket that works */
102 for (ai = res; ai != NULL; ai = ai->ai_next) {
103
104 if (ai->ai_family != PF_INET && ai->ai_family != PF_INET6) {
105 continue;
106 }
107
108 sock = socket(ai->ai_family, SOCK_STREAM, 0);
109 if (sock < 0) {
110 TRACE(("TCP socket() failed"));
111 continue;
112 }
113
114 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
115 close(sock);
116 TRACE(("TCP non-blocking failed"));
117 continue;
118 }
119
120 /* non-blocking, so it might return without success (EINPROGRESS) */
121 if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
122 if (errno == EINPROGRESS) {
123 TRACE(("connect in progress"));
124 } else {
125 close(sock);
126 TRACE(("TCP connect failed"));
127 continue;
128 }
129 }
130 break;
131 }
132
133 freeaddrinfo(res);
134
135 if (ai == NULL) {
136 return -1;
137 }
138
139 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val));
140 return sock;
141 }
142 #endif /* DISABLE_LOCALTCPFWD */