tcpip.go 3.6 KB

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