OLD | NEW |
(Empty) | |
| 1 // Copyright 2011 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 package ssh |
| 6 |
| 7 import ( |
| 8 "errors" |
| 9 "fmt" |
| 10 "io" |
| 11 "net" |
| 12 "time" |
| 13 ) |
| 14 |
| 15 // Dial initiates a connection to the addr from the remote host. |
| 16 // addr is resolved using net.ResolveTCPAddr before connection.· |
| 17 // This could allow an observer to observe the DNS name of the· |
| 18 // remote host. Consider using ssh.DialTCP to avoid this. |
| 19 func (c *ClientConn) Dial(n, addr string) (net.Conn, error) { |
| 20 raddr, err := net.ResolveTCPAddr(n, addr) |
| 21 if err != nil { |
| 22 return nil, err |
| 23 } |
| 24 return c.DialTCP(n, nil, raddr) |
| 25 } |
| 26 |
| 27 // DialTCP connects to the remote address raddr on the network net, |
| 28 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used |
| 29 // as the local address for the connection. |
| 30 func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, err
or) { |
| 31 if laddr == nil { |
| 32 laddr = &net.TCPAddr{ |
| 33 IP: net.IPv4zero, |
| 34 Port: 0, |
| 35 } |
| 36 } |
| 37 ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), radd
r.Port) |
| 38 if err != nil { |
| 39 return nil, err |
| 40 } |
| 41 return &tcpchanconn{ |
| 42 tcpchan: ch, |
| 43 laddr: laddr, |
| 44 raddr: raddr, |
| 45 }, nil |
| 46 } |
| 47 |
| 48 // RFC 4254 7.2 |
| 49 type channelOpenDirectMsg struct { |
| 50 ChanType string |
| 51 PeersId uint32 |
| 52 PeersWindow uint32 |
| 53 MaxPacketSize uint32 |
| 54 raddr string |
| 55 rport uint32 |
| 56 laddr string |
| 57 lport uint32 |
| 58 } |
| 59 |
| 60 // dial opens a direct-tcpip connection to the remote server. laddr and raddr ar
e passed as |
| 61 // strings and are expected to be resolveable at the remote end. |
| 62 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tc
pchan, error) { |
| 63 ch := c.newChan(c.transport) |
| 64 if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{ |
| 65 ChanType: "direct-tcpip", |
| 66 PeersId: ch.id, |
| 67 PeersWindow: 1 << 14, |
| 68 MaxPacketSize: 1 << 15, // RFC 4253 6.1 |
| 69 raddr: raddr, |
| 70 rport: uint32(rport), |
| 71 laddr: laddr, |
| 72 lport: uint32(lport), |
| 73 })); err != nil { |
| 74 c.chanlist.remove(ch.id) |
| 75 return nil, err |
| 76 } |
| 77 if err := ch.waitForChannelOpenResponse(); err != nil { |
| 78 c.chanlist.remove(ch.id) |
| 79 return nil, fmt.Errorf("ssh: unable to open direct tcpip connect
ion: %v", err) |
| 80 } |
| 81 return &tcpchan{ |
| 82 clientChan: ch, |
| 83 Reader: ch.stdout, |
| 84 Writer: ch.stdin, |
| 85 }, nil |
| 86 } |
| 87 |
| 88 type tcpchan struct { |
| 89 *clientChan // the backing channel |
| 90 io.Reader |
| 91 io.Writer |
| 92 } |
| 93 |
| 94 // tcpchanconn fulfills the net.Conn interface without· |
| 95 // the tcpchan having to hold laddr or raddr directly. |
| 96 type tcpchanconn struct { |
| 97 *tcpchan |
| 98 laddr, raddr net.Addr |
| 99 } |
| 100 |
| 101 // LocalAddr returns the local network address. |
| 102 func (t *tcpchanconn) LocalAddr() net.Addr { |
| 103 return t.laddr |
| 104 } |
| 105 |
| 106 // RemoteAddr returns the remote network address. |
| 107 func (t *tcpchanconn) RemoteAddr() net.Addr { |
| 108 return t.raddr |
| 109 } |
| 110 |
| 111 // SetDeadline sets the read and write deadlines associated |
| 112 // with the connection. |
| 113 func (t *tcpchanconn) SetDeadline(deadline time.Time) error { |
| 114 if err := t.SetReadDeadline(deadline); err != nil { |
| 115 return err |
| 116 } |
| 117 return t.SetWriteDeadline(deadline) |
| 118 } |
| 119 |
| 120 // SetReadDeadline sets the read deadline. |
| 121 // A zero value for t means Read will not time out. |
| 122 // After the deadline, the error from Read will implement net.Error |
| 123 // with Timeout() == true. |
| 124 func (t *tcpchanconn) SetReadDeadline(deadline time.Time) error { |
| 125 return errors.New("ssh: tcpchan: deadline not supported") |
| 126 } |
| 127 |
| 128 // SetWriteDeadline exists to satisfy the net.Conn interface |
| 129 // but is not implemented by this type. It always returns an error. |
| 130 func (t *tcpchanconn) SetWriteDeadline(deadline time.Time) error { |
| 131 return errors.New("ssh: tcpchan: deadline not supported") |
| 132 } |
OLD | NEW |