Mercurial > dropbear
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 */ |