1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
package main
import (
"context"
"fmt"
"io"
"net"
"os"
"time"
)
const (
port = 60321
timeout = time.Minute
usage = "Usage: hose <host>"
)
func main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "%s\n", usage)
os.Exit(1)
}
remote, err := parseHost(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "failed to resolve host '%s'\n", os.Args[1])
os.Exit(1)
} else if remote == nil {
fmt.Fprintf(os.Stderr, "%s is not a valid IP address or host name\n",
os.Args[1])
os.Exit(1)
}
ifss, err := net.Interfaces()
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
ifs := selectIfs(ifss)
if ifs == nil {
fmt.Fprintf(os.Stderr, "no suitable network interfaces\n")
os.Exit(1)
}
local, err := ip(ifs)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
} else if local == nil {
fmt.Fprintf(os.Stderr, "no suitable ip addresses\n")
os.Exit(1)
}
errs := make(chan error)
go listen(local, remote, errs)
go send(addr(remote, port), errs)
// Wait for goroutines.
nroutines := 2
for i := 0; i < nroutines; i++ {
if err := <-errs; err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
}
}
}
// listen listens on local for connections from remote and copies received data
// to stdout. Sends exactly one (possible nil) error to errs.
func listen(local, remote net.IP, errs chan error) {
l, err := net.Listen("tcp", addr(local, port))
if err != nil {
errs <- err
return
}
var c net.Conn
for {
c, err = l.Accept()
if err != nil {
errs <- err
return
}
host, _, err := net.SplitHostPort(c.RemoteAddr().String())
if err != nil {
errs <- err
return
}
if host := net.ParseIP(host); host != nil && host.Equal(remote) {
break
}
}
io.Copy(os.Stdout, c)
c.Close()
l.Close()
errs <- nil
}
// send sends data from stdin to addr. addr has the form "host:port" (see
// net.Dial). Sends exactly one (possible nil) error to errs.
func send(addr string, errs chan<- error) {
var d net.Dialer
ctx, cancel := context.WithTimeout(context.Background(), timeout)
c, err := d.DialContext(ctx, "tcp", addr)
if err != nil {
errs <- err
return
}
io.Copy(c, os.Stdin)
c.Close()
cancel()
errs <- nil
}
// addr joins an IP address and a port number into a full address. See net.Dial.
func addr(ip net.IP, port uint) string {
return net.JoinHostPort(fmt.Sprintf("%s", ip), fmt.Sprintf("%d", port))
}
// parseHost returns the IP address represented by s. s is either a literal IP
// address or a hostname. nil is returned if the hostname does not resolve to
// any addresses,
func parseHost(s string) (net.IP, error) {
if ip := net.ParseIP(s); ip != nil {
return ip, nil
}
addrs, err := net.LookupIP(s)
if err != nil {
return nil, err
}
if len(addrs) < 1 {
return nil, nil
}
return addrs[0], nil
}
// selectIfs returns a network interface from ifs that is up, running and not
// a loopback interface. Returns nil if no such interface exists.
func selectIfs(ifs []net.Interface) *net.Interface {
for _, i := range ifs {
if (i.Flags&net.FlagUp != 0) &&
(i.Flags&net.FlagRunning != 0) &&
(i.Flags&net.FlagLoopback == 0) {
return &i
}
}
return nil
}
// ip returns the first IP address bound to ifs or nil if none are bound.
func ip(ifs *net.Interface) (net.IP, error) {
addrs, err := ifs.Addrs()
if err != nil {
return nil, err
} else if len(addrs) < 1 {
return nil, nil
}
ip, _, err := net.ParseCIDR(addrs[0].String())
if err != nil {
return nil, err
}
return ip, nil
}
|