Mercurial > dropbear
annotate cli-tcpfwd.c @ 64:efb5e0b335cf
TCP forwarding works.
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 12 Aug 2004 13:48:42 +0000 |
parents | dcc43965928f |
children | 38c3146aa23d |
rev | line source |
---|---|
62 | 1 #include "includes.h" |
2 #include "options.h" | |
64 | 3 #include "dbutil.h" |
4 #include "tcpfwd.h" | |
62 | 5 #include "channel.h" |
64 | 6 #include "runopts.h" |
7 #include "session.h" | |
8 #include "ssh.h" | |
62 | 9 |
64 | 10 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, |
11 unsigned int remoteport); | |
12 static int newtcpforwarded(struct Channel * channel); | |
13 | |
14 const struct ChanType cli_chan_tcpremote = { | |
15 1, /* sepfds */ | |
16 "forwarded-tcpip", | |
17 newtcpforwarded, | |
18 NULL, | |
19 NULL, | |
20 NULL | |
21 }; | |
62 | 22 static const struct ChanType cli_chan_tcplocal = { |
23 1, /* sepfds */ | |
24 "direct-tcpip", | |
25 NULL, | |
26 NULL, | |
64 | 27 NULL, |
62 | 28 NULL |
29 }; | |
30 | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
31 void setup_localtcp() { |
62 | 32 |
64 | 33 int ret; |
34 | |
35 if (cli_opts.localfwds == NULL) { | |
36 TRACE(("cli_opts.localfwds == NULL")); | |
37 } | |
38 | |
39 while (cli_opts.localfwds != NULL) { | |
40 ret = cli_localtcp(cli_opts.localfwds->listenport, | |
41 cli_opts.localfwds->connectaddr, | |
42 cli_opts.localfwds->connectport); | |
43 if (ret == DROPBEAR_FAILURE) { | |
44 dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", | |
45 cli_opts.localfwds->listenport, | |
46 cli_opts.localfwds->connectaddr, | |
47 cli_opts.localfwds->connectport); | |
48 } | |
49 | |
50 cli_opts.localfwds = cli_opts.localfwds->next; | |
51 } | |
62 | 52 |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
53 } |
62 | 54 |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
55 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, |
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
56 unsigned int remoteport) { |
62 | 57 |
58 struct TCPListener* tcpinfo = NULL; | |
64 | 59 int ret; |
60 | |
61 TRACE(("enter cli_localtcp: %d %s %d", listenport, remoteaddr, | |
62 remoteport)); | |
62 | 63 |
64 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*)); | |
63
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
65 tcpinfo->sendaddr = remoteaddr; |
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
66 tcpinfo->sendport = remoteport; |
dcc43965928f
- A nice cleaner structure for tcp (acceptor) forwarding.
Matt Johnston <matt@ucc.asn.au>
parents:
62
diff
changeset
|
67 tcpinfo->listenport = listenport; |
62 | 68 tcpinfo->chantype = &cli_chan_tcplocal; |
69 | |
70 ret = listen_tcpfwd(tcpinfo); | |
71 | |
72 if (ret == DROPBEAR_FAILURE) { | |
73 m_free(tcpinfo); | |
74 } | |
64 | 75 TRACE(("leave cli_localtcp: %d", ret)); |
62 | 76 return ret; |
77 } | |
64 | 78 |
79 static void send_msg_global_request_remotetcp(int port) { | |
80 | |
81 TRACE(("enter send_msg_global_request_remotetcp")); | |
82 | |
83 CHECKCLEARTOWRITE(); | |
84 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); | |
85 buf_putstring(ses.writepayload, "tcpip-forward", 13); | |
86 buf_putbyte(ses.writepayload, 0); | |
87 buf_putstring(ses.writepayload, "0.0.0.0", 7); /* TODO: IPv6? */ | |
88 buf_putint(ses.writepayload, port); | |
89 | |
90 encrypt_packet(); | |
91 | |
92 TRACE(("leave send_msg_global_request_remotetcp")); | |
93 } | |
94 | |
95 void setup_remotetcp() { | |
96 | |
97 struct TCPFwdList * iter = NULL; | |
98 | |
99 if (cli_opts.remotefwds == NULL) { | |
100 TRACE(("cli_opts.remotefwds == NULL")); | |
101 } | |
102 | |
103 iter = cli_opts.remotefwds; | |
104 | |
105 while (iter != NULL) { | |
106 send_msg_global_request_remotetcp(iter->listenport); | |
107 iter = iter->next; | |
108 } | |
109 } | |
110 | |
111 static int newtcpforwarded(struct Channel * channel) { | |
112 | |
113 unsigned int origport; | |
114 struct TCPFwdList * iter = NULL; | |
115 char portstring[NI_MAXSERV]; | |
116 int sock; | |
117 int ret = DROPBEAR_FAILURE; | |
118 | |
119 /* We don't care what address they connected to */ | |
120 buf_eatstring(ses.payload); | |
121 | |
122 origport = buf_getint(ses.payload); | |
123 | |
124 /* Find which port corresponds */ | |
125 iter = cli_opts.remotefwds; | |
126 | |
127 while (iter != NULL) { | |
128 if (origport == iter->listenport) { | |
129 break; | |
130 } | |
131 iter = iter->next; | |
132 } | |
133 | |
134 if (iter == NULL) { | |
135 /* We didn't request forwarding on that port */ | |
136 dropbear_log(LOG_INFO, "Server send unrequested port, from port %d", | |
137 origport); | |
138 goto out; | |
139 } | |
140 | |
141 snprintf(portstring, sizeof(portstring), "%d", iter->connectport); | |
142 sock = connect_remote(iter->connectaddr, portstring, 1, NULL); | |
143 if (sock < 0) { | |
144 TRACE(("leave newtcpdirect: sock failed")); | |
145 goto out; | |
146 } | |
147 | |
148 ses.maxfd = MAX(ses.maxfd, sock); | |
149 | |
150 /* Note that infd is actually the "outgoing" direction on the | |
151 * tcp connection, vice versa for outfd. | |
152 * We don't set outfd, that will get set after the connection's | |
153 * progress succeeds */ | |
154 channel->infd = sock; | |
155 channel->initconn = 1; | |
156 | |
157 ret = DROPBEAR_SUCCESS; | |
158 | |
159 out: | |
160 TRACE(("leave newtcpdirect: ret %d", ret)); | |
161 return ret; | |
162 } |