Mercurial > dropbear
comparison tcp-accept.c @ 389:5ff8218bcee9
propagate from branch 'au.asn.ucc.matt.ltm.dropbear' (head 2af95f00ebd5bb7a28b3817db1218442c935388e)
to branch 'au.asn.ucc.matt.dropbear' (head ecd779509ef23a8cdf64888904fc9b31d78aa933)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 11 Jan 2007 03:14:55 +0000 |
parents | a124aff0cbf1 |
children | c216212001fc |
comparison
equal
deleted
inserted
replaced
388:fb54020f78e1 | 389:5ff8218bcee9 |
---|---|
1 /* | |
2 * Dropbear SSH | |
3 * | |
4 * Copyright (c) 2002,2003 Matt Johnston | |
5 * All rights reserved. | |
6 * | |
7 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 * of this software and associated documentation files (the "Software"), to deal | |
9 * in the Software without restriction, including without limitation the rights | |
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 * copies of the Software, and to permit persons to whom the Software is | |
12 * furnished to do so, subject to the following conditions: | |
13 * | |
14 * The above copyright notice and this permission notice shall be included in | |
15 * all copies or substantial portions of the Software. | |
16 * | |
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
23 * SOFTWARE. */ | |
24 | |
25 #include "includes.h" | |
26 #include "ssh.h" | |
27 #include "tcpfwd.h" | |
28 #include "dbutil.h" | |
29 #include "session.h" | |
30 #include "buffer.h" | |
31 #include "packet.h" | |
32 #include "listener.h" | |
33 #include "runopts.h" | |
34 | |
35 #ifdef DROPBEAR_TCP_ACCEPT | |
36 | |
37 static void cleanup_tcp(struct Listener *listener) { | |
38 | |
39 struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata); | |
40 | |
41 m_free(tcpinfo->sendaddr); | |
42 m_free(tcpinfo->listenaddr); | |
43 m_free(tcpinfo); | |
44 } | |
45 | |
46 static void tcp_acceptor(struct Listener *listener, int sock) { | |
47 | |
48 int fd; | |
49 struct sockaddr_storage addr; | |
50 socklen_t len; | |
51 char ipstring[NI_MAXHOST], portstring[NI_MAXSERV]; | |
52 struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata); | |
53 | |
54 len = sizeof(addr); | |
55 | |
56 fd = accept(sock, (struct sockaddr*)&addr, &len); | |
57 if (fd < 0) { | |
58 return; | |
59 } | |
60 | |
61 if (getnameinfo((struct sockaddr*)&addr, len, ipstring, sizeof(ipstring), | |
62 portstring, sizeof(portstring), | |
63 NI_NUMERICHOST | NI_NUMERICSERV) != 0) { | |
64 return; | |
65 } | |
66 | |
67 if (send_msg_channel_open_init(fd, tcpinfo->chantype) == DROPBEAR_SUCCESS) { | |
68 unsigned char* addr = NULL; | |
69 unsigned int port = 0; | |
70 | |
71 if (tcpinfo->tcp_type == direct) { | |
72 /* "direct-tcpip" */ | |
73 /* host to connect, port to connect */ | |
74 addr = tcpinfo->sendaddr; | |
75 port = tcpinfo->sendport; | |
76 } else { | |
77 dropbear_assert(tcpinfo->tcp_type == forwarded); | |
78 /* "forwarded-tcpip" */ | |
79 /* address that was connected, port that was connected */ | |
80 addr = tcpinfo->listenaddr; | |
81 port = tcpinfo->listenport; | |
82 } | |
83 | |
84 buf_putstring(ses.writepayload, addr, strlen(addr)); | |
85 buf_putint(ses.writepayload, port); | |
86 | |
87 /* originator ip */ | |
88 buf_putstring(ses.writepayload, ipstring, strlen(ipstring)); | |
89 /* originator port */ | |
90 buf_putint(ses.writepayload, atol(portstring)); | |
91 | |
92 encrypt_packet(); | |
93 | |
94 } else { | |
95 /* XXX debug? */ | |
96 close(fd); | |
97 } | |
98 } | |
99 | |
100 int listen_tcpfwd(struct TCPListener* tcpinfo) { | |
101 | |
102 char portstring[NI_MAXSERV]; | |
103 int socks[DROPBEAR_MAX_SOCKS]; | |
104 struct Listener *listener = NULL; | |
105 int nsocks; | |
106 char* errstring = NULL; | |
107 // listen_spec = NULL indicates localhost | |
108 const char* listen_spec = NULL; | |
109 | |
110 TRACE(("enter listen_tcpfwd")) | |
111 | |
112 /* first we try to bind, so don't need to do so much cleanup on failure */ | |
113 snprintf(portstring, sizeof(portstring), "%d", tcpinfo->listenport); | |
114 | |
115 /* a listenaddr of "" will indicate all interfaces */ | |
116 if (opts.listen_fwd_all | |
117 && (strcmp(tcpinfo->listenaddr, "localhost") != 0) ) { | |
118 listen_spec = tcpinfo->listenaddr; | |
119 } | |
120 | |
121 nsocks = dropbear_listen(listen_spec, portstring, socks, | |
122 DROPBEAR_MAX_SOCKS, &errstring, &ses.maxfd); | |
123 if (nsocks < 0) { | |
124 dropbear_log(LOG_INFO, "TCP forward failed: %s", errstring); | |
125 m_free(errstring); | |
126 TRACE(("leave listen_tcpfwd: dropbear_listen failed")) | |
127 return DROPBEAR_FAILURE; | |
128 } | |
129 m_free(errstring); | |
130 | |
131 /* new_listener will close the socks if it fails */ | |
132 listener = new_listener(socks, nsocks, CHANNEL_ID_TCPFORWARDED, tcpinfo, | |
133 tcp_acceptor, cleanup_tcp); | |
134 | |
135 if (listener == NULL) { | |
136 TRACE(("leave listen_tcpfwd: listener failed")) | |
137 return DROPBEAR_FAILURE; | |
138 } | |
139 | |
140 TRACE(("leave listen_tcpfwd: success")) | |
141 return DROPBEAR_SUCCESS; | |
142 } | |
143 | |
144 #endif /* DROPBEAR_TCP_ACCEPT */ |