62
|
1 #include "includes.h" |
|
2 #include "ssh.h" |
|
3 #include "tcp-accept.h" |
|
4 #include "dbutil.h" |
|
5 #include "session.h" |
|
6 #include "buffer.h" |
|
7 #include "packet.h" |
|
8 #include "listener.h" |
|
9 #include "runopts.h" |
|
10 |
|
11 #ifndef DISABLE_TCP_ACCEPT |
|
12 |
|
13 static void accept_tcp(struct Listener *listener, int sock) { |
|
14 |
|
15 int fd; |
|
16 struct sockaddr_storage addr; |
|
17 int len; |
|
18 char ipstring[NI_MAXHOST], portstring[NI_MAXSERV]; |
|
19 struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata); |
|
20 |
|
21 len = sizeof(addr); |
|
22 |
|
23 fd = accept(sock, (struct sockaddr*)&addr, &len); |
|
24 if (fd < 0) { |
|
25 return; |
|
26 } |
|
27 |
|
28 if (getnameinfo((struct sockaddr*)&addr, len, ipstring, sizeof(ipstring), |
|
29 portstring, sizeof(portstring), |
|
30 NI_NUMERICHOST | NI_NUMERICSERV) != 0) { |
|
31 return; |
|
32 } |
|
33 |
|
34 if (send_msg_channel_open_init(fd, tcpinfo->chantype) == DROPBEAR_SUCCESS) { |
|
35 |
|
36 buf_putstring(ses.writepayload, tcpinfo->addr, strlen(tcpinfo->addr)); |
|
37 buf_putint(ses.writepayload, tcpinfo->port); |
|
38 buf_putstring(ses.writepayload, ipstring, strlen(ipstring)); |
|
39 buf_putint(ses.writepayload, atol(portstring)); |
|
40 encrypt_packet(); |
|
41 |
|
42 } else { |
|
43 /* XXX debug? */ |
|
44 close(fd); |
|
45 } |
|
46 } |
|
47 |
|
48 static void cleanup_tcp(struct Listener *listener) { |
|
49 |
|
50 struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata); |
|
51 |
|
52 m_free(tcpinfo->addr); |
|
53 m_free(tcpinfo); |
|
54 } |
|
55 |
|
56 |
|
57 int listen_tcpfwd(struct TCPListener* tcpinfo) { |
|
58 |
|
59 char portstring[6]; /* "65535\0" */ |
|
60 int socks[DROPBEAR_MAX_SOCKS]; |
|
61 struct Listener *listener = NULL; |
|
62 int nsocks; |
|
63 |
|
64 TRACE(("enter listen_tcpfwd")); |
|
65 |
|
66 /* first we try to bind, so don't need to do so much cleanup on failure */ |
|
67 snprintf(portstring, sizeof(portstring), "%d", tcpinfo->port); |
|
68 nsocks = dropbear_listen(tcpinfo->addr, portstring, socks, |
|
69 DROPBEAR_MAX_SOCKS, NULL, &ses.maxfd); |
|
70 if (nsocks < 0) { |
|
71 TRACE(("leave listen_tcpfwd: dropbear_listen failed")); |
|
72 return DROPBEAR_FAILURE; |
|
73 } |
|
74 |
|
75 listener = new_listener(socks, nsocks, CHANNEL_ID_TCPFORWARDED, tcpinfo, |
|
76 accept_tcp, cleanup_tcp); |
|
77 |
|
78 if (listener == NULL) { |
|
79 m_free(tcpinfo); |
|
80 TRACE(("leave listen_tcpfwd: listener failed")); |
|
81 return DROPBEAR_FAILURE; |
|
82 } |
|
83 |
|
84 TRACE(("leave listen_tcpfwd: success")); |
|
85 return DROPBEAR_SUCCESS; |
|
86 } |
|
87 |
|
88 #endif /* DISABLE_REMOTETCPFWD */ |