-
-
Notifications
You must be signed in to change notification settings - Fork 19
/
cmd_ips.go
187 lines (149 loc) · 4.27 KB
/
cmd_ips.go
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package main
import (
"flag"
"fmt"
"net"
"strings"
)
// Structure for our options and state.
type ipsCommand struct {
// show only IPv4 addresses?
ipv4 bool
// show only IPv6 addresses?
ipv6 bool
// show local addresses?
local bool
// show global/remote addresses?
remote bool
// Cached store of network/netmask to IP-range - IPv4
ip4Ranges map[string]*net.IPNet
// Cached store of network/netmask to IP-range - IPv6
ip6Ranges map[string]*net.IPNet
}
// Arguments adds per-command args to the object.
func (i *ipsCommand) Arguments(f *flag.FlagSet) {
f.BoolVar(&i.ipv4, "4", true, "Should we show IPv4 addresses?")
f.BoolVar(&i.ipv6, "6", true, "Should we show IPv6 addresses?")
f.BoolVar(&i.local, "local", true, "Should we show local addresses?")
f.BoolVar(&i.remote, "remote", true, "Should we show global addresses?")
}
// Info returns the name of this subcommand.
func (i *ipsCommand) Info() (string, string) {
return "ips", `Show IP address information.
Details:
This command allows you to see local/global IP addresses assigned to
the current host.
By default all IP addresses will be shown, but you can disable protocols
and types of addresses you do not wish to see.
Examples:
$ sysbox ips -4=false
::1
fe80::feaa:14ff:fe32:688
fe80::78e5:95b6:1659:b407
$ sysbox ips -local=false -4=false
2a01:4f9:c010:27d8::1
`
}
// isLocal is a helper to test if an address is "local" or "remote".
func (i *ipsCommand) isLocal(address *net.IPNet) bool {
localIP4 := []string{
"10.0.0.0/8", // RFC1918
"100.64.0.0/10", // RFC 6598
"127.0.0.0/8", // IPv4 loopback
"169.254.0.0/16", // RFC3927 link-local
"172.16.0.0/12", // RFC1918
"192.0.0.0/24", // RFC 5736
"192.0.2.0/24", // RFC 5737
"192.168.0.0/16", // RFC1918
"192.18.0.0/15", // RFC 2544
"192.88.99.0/24", // RFC 3068
"198.51.100.0/24", //
"203.0.113.0/24", //
"224.0.0.0/4", // RFC 3171
"255.255.255.255/32", // RFC 919 Section 7
}
localIP6 := []string{
"::/128", // RFC 4291: Unspecified Address
"100::/64", // RFC 6666: Discard Address Block
"2001:2::/48", // RFC 5180: Benchmarking
"2001::/23", // RFC 2928: IETF Protocol Assignments
"2001::/32", // RFC 4380: TEREDO
"2001:db8::/32", // RFC 3849: Documentation
"::1/128", // RFC 4291: Loopback Address
"fc00::/7", // RFC 4193: Unique-Local
"fe80::/10", // RFC 4291: Section 2.5.6 Link-Scoped Unicast
"ff00::/8", // RFC 4291: Section 2.7
}
// Create our maps
if i.ip4Ranges == nil {
i.ip4Ranges = make(map[string]*net.IPNet)
i.ip6Ranges = make(map[string]*net.IPNet)
// Join our ranges.
tmp := localIP4
tmp = append(tmp, localIP6...)
// For each network-range.
for _, entry := range tmp {
// Parse
_, block, _ := net.ParseCIDR(entry)
// Record in the protocol-specific range
if strings.Contains(entry, ":") {
i.ip6Ranges[entry] = block
} else {
i.ip4Ranges[entry] = block
}
}
}
// The map we're testing from
testMap := i.ip4Ranges
// Are we testing an IPv6 address?
if strings.Contains(address.String(), ":") {
testMap = i.ip6Ranges
}
// Loop over the appropriate map and test for inclusion
for _, block := range testMap {
if block.Contains(address.IP) {
return true
}
}
// Not found.
return false
}
// Execute is invoked if the user specifies `ips` as the subcommand.
func (i *ipsCommand) Execute(args []string) int {
// Get addresses
addrs, err := net.InterfaceAddrs()
if err != nil {
fmt.Printf("Error finding IPs:%s\n", err.Error())
return 1
}
// For each one
for _, address := range addrs {
// cast ..
ipnet, ok := address.(*net.IPNet)
if !ok {
fmt.Printf("Failed to convert %v to IP\n", address)
return 1
}
// If we're not showing locals, then skip if this is.
if !i.local && i.isLocal(ipnet) {
continue
}
// If we're not showing globals, then skip if this is
if !i.remote && !i.isLocal(ipnet) {
continue
}
res := ipnet.IP.String()
// If we're not showing IPv4 and the address is that
// then skip it
if !i.ipv4 && !strings.Contains(res, ":") {
continue
}
// If we're not showing IPv6 and the address is that then
// skip it
if !i.ipv6 && strings.Contains(res, ":") {
continue
}
fmt.Println(res)
}
return 0
}