-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathip.go
289 lines (242 loc) · 6.51 KB
/
ip.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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
package ipx
import (
"encoding/binary"
"errors"
"fmt"
"math/big"
"math/rand"
"net"
)
// Error definitions
var (
ErrInvalidIP = errors.New("invalid ip address")
)
// IP address lengths (bytes).
const (
IPv4len = 4
IPv6len = 16
)
// Well-known IPv4 addresses
var (
IPv4bcast = IPv4(255, 255, 255, 255) // limited broadcast
IPv4allsys = IPv4(224, 0, 0, 1) // all systems
IPv4allrouter = IPv4(224, 0, 0, 2) // all routers
IPv4zero = IPv4(0, 0, 0, 0) // all zeros
)
// Well-known IPv4 addresses' decimal represntation
var (
IPv4bcastInt = IPv4bcast.ToInt()
)
// Well-known IPv6 addresses
var (
IPv6zero = IP{net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
IPv6unspecified = IP{net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
IPv6loopback = IP{net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}
IPv6interfacelocalallnodes = IP{net.IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}}
IPv6linklocalallnodes = IP{net.IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}}
IPv6linklocalallrouters = IP{net.IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}}
)
// IP is a single IP address, a slice of bytes.
// Functions in this package accept
// either 4-byte (IPv4) or 16-byte (IPv6) slices as input.
type IP struct {
net.IP
}
// IsV4 returns true if ip address is v4
func (i IP) IsV4() bool {
i = i.To4()
return i.IP != nil
}
// IsV6 returns true if ip address is v6
func (i IP) IsV6() bool {
// check if ip is v4
if i.IsV4() {
return false
}
i = i.To16()
return i.IP != nil
}
// Before checks if i is before x
func (i IP) Before(x IP) bool {
return i.ToInt() < x.ToInt()
}
// ToInt returns the int reprenstation of IP
// If i is an IPv6 address, it returns zero
func (i IP) ToInt() uint32 {
i = i.To4()
if i.IP == nil {
return uint32(0)
}
return binary.BigEndian.Uint32(i.IP)
}
// ToBigInt returns the bigint reprenstation of IP
func (i IP) ToBigInt() *big.Int {
num := big.NewInt(0)
// bigint for ipv4
ip := i.To4()
if ip.IP == nil {
ip = i.To16()
}
num.SetBytes(ip.IP)
return num
}
// ToBinary returns the binary reprenstation of IP
func (i IP) ToBinary() string {
// ipv4
ip := i.To4()
if ip.IP != nil {
return fmt.Sprintf("%08b%08b%08b%08b", ip.IP[0], ip.IP[1], ip.IP[2], ip.IP[3])
}
// ipv6
// TODO: implement toBinary for ipv6
return ""
}
// ToHex returns the hex reprenstation of IP
func (i IP) ToHex() string {
// ipv4
ip := i.To4()
if ip.IP != nil {
return fmt.Sprintf("%02X%02X%02X%02X", ip.IP[0], ip.IP[1], ip.IP[2], ip.IP[3])
}
// ipv6
// TODO: implement toHex for ipv6
return ""
}
// IsPrivate returns whether i is in a private network
func (i IP) IsPrivate() bool {
for _, net := range privateNetworks {
if net.Contains(i) {
return true
}
}
return false
}
// GetNext returns the next IP
func (i IP) GetNext() IP {
// TODO: implement GetNext for IPv6
return i.GetNextN(uint32(1))
}
// GetNextN returns the n'th next IP
func (i IP) GetNextN(n uint32) IP {
// TODO: implement GetNextN for IPv6
val := i.ToInt()
val += n
i = FromInt(val)
return i
}
// GetAllNextN returns all IP's until n'th next IP
func (i IP) GetAllNextN(n uint32) []IP {
var ipList []IP
for j := 0; uint32(j) < n; j++ {
ipList = append(ipList, i.GetNextN(uint32(j+1)))
}
return ipList
}
// GetPrevious returns the previous IP
func (i IP) GetPrevious() IP {
// TODO: implement GetPrevious for IPv6
return i.GetPreviousN(uint32(1))
}
// GetPreviousN returns the n'th next IP
func (i IP) GetPreviousN(n uint32) IP {
// TODO: implement GetPreviousN for IPv6
val := i.ToInt()
if n > val {
n = n - val - 1
val = IPv4bcastInt
}
val -= n
i = FromInt(val)
return i
}
// GetAllPreviousN returns all IP's until n'th previous IP
func (i IP) GetAllPreviousN(n uint32) []IP {
var ipList []IP
for n > 0 {
ipList = append(ipList, i.GetPreviousN(uint32(n)))
n--
}
return ipList
}
// Equal reports whether ip and x are the same IP address.
// An IPv4 address and that same address in IPv6 form are
// considered to be equal.
func (i IP) Equal(x IP) bool {
return i.IP.Equal(x.IP)
}
// Mask returns the result of masking the IP address ip with mask.
func (i IP) Mask(mask IPMask) IP {
return IP{i.IP.Mask(mask.IPMask)}
}
// To4 converts the IPv4 address ip to a 4-byte representation.
// If ip is not an IPv4 address, To4 returns nil.
func (i IP) To4() IP {
return IP{i.IP.To4()}
}
// To16 converts the IP address ip to a 16-byte representation.
// If ip is not an IP address (it is the wrong length), To16 returns nil.
func (i IP) To16() IP {
return IP{i.IP.To16()}
}
// DefaultMask returns the default IP mask for the IP address ip.
// Only IPv4 addresses have default masks; DefaultMask returns
// nil if ip is not a valid IPv4 address.
func (i IP) DefaultMask() IPMask {
return IPMask{i.IP.DefaultMask()}
}
// IPv4 returns the IP address (in 16-byte form) of the IPv4 address a.b.c.d.
func IPv4(a, b, c, d byte) IP {
ip := net.IPv4(a, b, c, d)
return IP{ip}
}
// LookupIP looks up host using the local resolver.
// It returns a slice of that host's IPv4 and IPv6 addresses.
func LookupIP(host string) ([]IP, error) {
// array for returning ip's type of ipx.IP
var ipList []IP
netIPList, err := net.LookupIP(host)
for _, netIP := range netIPList {
ipList = append(ipList, IP{netIP})
}
return ipList, err
}
// MustParseIP parses s as an IP address, returning the result.
// The string s can be in IPv4 dotted decimal ("192.0.2.1"),
// IPv6 ("2001:db8::68"), or IPv4-mapped IPv6 ("::ffff:192.0.2.1") form.
// If s is not a valid textual representation of an IP address,
// MustParseIP throws a panic
func MustParseIP(s string) IP {
ip := net.ParseIP(s)
if ip == nil {
panic(ErrInvalidIP)
}
return IP{ip}
}
// ParseIP parses s as an IP address as exactly as MustParseIP.
// Differently, ParseIP returns ErrInvalidIP if s is not valid
// textual reprenstation of an IP address
func ParseIP(s string) (IP, error) {
ip := net.ParseIP(s)
if ip == nil {
return IP{}, ErrInvalidIP
}
return IP{ip}, nil
}
// FromInt parses i as an IP address
// Receieved from https://gist.github.com/ammario/649d4c0da650162efd404af23e25b86b
func FromInt(i uint32) IP {
ip := make(net.IP, 4)
binary.BigEndian.PutUint32(ip, i)
return IP{ip}
}
// RandomIPv4 returns a random IPv4 address
func RandomIPv4() IP {
return FromInt(uint32(rand.Intn(int(IPv4bcastInt))))
}
// ipEmptyString returns an empty string when ip is unset.
func ipEmptyString(ip net.IP) string {
if len(ip) == 0 {
return ""
}
return ip.String()
}