| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- // Copyright 2011 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package ssh
- import (
- "errors"
- "fmt"
- "io"
- "net"
- "time"
- )
- // Dial initiates a connection to the addr from the remote host.
- // addr is resolved using net.ResolveTCPAddr before connection.
- // This could allow an observer to observe the DNS name of the
- // remote host. Consider using ssh.DialTCP to avoid this.
- func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
- raddr, err := net.ResolveTCPAddr(n, addr)
- if err != nil {
- return nil, err
- }
- return c.DialTCP(n, nil, raddr)
- }
- // DialTCP connects to the remote address raddr on the network net,
- // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
- // as the local address for the connection.
- func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
- if laddr == nil {
- laddr = &net.TCPAddr{
- IP: net.IPv4zero,
- Port: 0,
- }
- }
- ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
- if err != nil {
- return nil, err
- }
- return &tcpchanconn{
- tcpchan: ch,
- laddr: laddr,
- raddr: raddr,
- }, nil
- }
- // RFC 4254 7.2
- type channelOpenDirectMsg struct {
- ChanType string
- PeersId uint32
- PeersWindow uint32
- MaxPacketSize uint32
- raddr string
- rport uint32
- laddr string
- lport uint32
- }
- // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
- // strings and are expected to be resolveable at the remote end.
- func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) {
- ch := c.newChan(c.transport)
- if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
- ChanType: "direct-tcpip",
- PeersId: ch.id,
- PeersWindow: 1 << 14,
- MaxPacketSize: 1 << 15, // RFC 4253 6.1
- raddr: raddr,
- rport: uint32(rport),
- laddr: laddr,
- lport: uint32(lport),
- })); err != nil {
- c.chanlist.remove(ch.id)
- return nil, err
- }
- if err := ch.waitForChannelOpenResponse(); err != nil {
- c.chanlist.remove(ch.id)
- return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
- }
- return &tcpchan{
- clientChan: ch,
- Reader: ch.stdout,
- Writer: ch.stdin,
- }, nil
- }
- type tcpchan struct {
- *clientChan // the backing channel
- io.Reader
- io.Writer
- }
- // tcpchanconn fulfills the net.Conn interface without
- // the tcpchan having to hold laddr or raddr directly.
- type tcpchanconn struct {
- *tcpchan
- laddr, raddr net.Addr
- }
- // LocalAddr returns the local network address.
- func (t *tcpchanconn) LocalAddr() net.Addr {
- return t.laddr
- }
- // RemoteAddr returns the remote network address.
- func (t *tcpchanconn) RemoteAddr() net.Addr {
- return t.raddr
- }
- // SetDeadline sets the read and write deadlines associated
- // with the connection.
- func (t *tcpchanconn) SetDeadline(deadline time.Time) error {
- if err := t.SetReadDeadline(deadline); err != nil {
- return err
- }
- return t.SetWriteDeadline(deadline)
- }
- // SetReadDeadline sets the read deadline.
- // A zero value for t means Read will not time out.
- // After the deadline, the error from Read will implement net.Error
- // with Timeout() == true.
- func (t *tcpchanconn) SetReadDeadline(deadline time.Time) error {
- return errors.New("ssh: tcpchan: deadline not supported")
- }
- // SetWriteDeadline exists to satisfy the net.Conn interface
- // but is not implemented by this type. It always returns an error.
- func (t *tcpchanconn) SetWriteDeadline(deadline time.Time) error {
- return errors.New("ssh: tcpchan: deadline not supported")
- }
|