forked from msgboxio/ike
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnet.go
91 lines (83 loc) · 1.86 KB
/
net.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
package ike
import (
"bytes"
"net"
"github.com/pkg/errors"
)
func FirstLastAddressToIPNet(start, end net.IP) *net.IPNet {
l := len(start)
if l != len(end) {
return nil
}
// shortcut
if bytes.Equal(start, end) {
return &net.IPNet{IP: start, Mask: net.CIDRMask(l*8, l*8)}
}
mask := make([]byte, l)
// This will only work if there are no holes in addresses given
for idx, _ := range start {
mask[idx] = ^(end[idx] - start[idx])
}
return &net.IPNet{IP: start, Mask: mask}
}
// copy of a useful function from ip.go
func networkNumberAndMask(n *net.IPNet) (ip net.IP, m net.IPMask) {
if ip = n.IP.To4(); ip == nil {
ip = n.IP
if len(ip) != net.IPv6len {
return nil, nil
}
}
m = n.Mask
switch len(m) {
case net.IPv4len:
if len(ip) != net.IPv4len {
return nil, nil
}
case net.IPv6len:
if len(ip) == net.IPv4len {
m = m[12:]
}
default:
return nil, nil
}
return
}
// IPNetToFirstLastAddress returns the first & last address derived from the IPNet notation
func IPNetToFirstLastAddress(n *net.IPNet) (first, last net.IP, err error) {
ip, m := networkNumberAndMask(n)
if ip == nil {
err = errors.New("cannot extract bounds from address: " + n.String())
return
}
last = make([]byte, len(ip))
first = make([]byte, len(ip))
for idx, val := range ip {
first[idx] = val & m[idx]
last[idx] = (val & m[idx]) | ^m[idx]
}
return
}
func AddrToIp(addr net.Addr) net.IP {
switch ip := addr.(type) {
case *net.TCPAddr:
return check4(ip.IP)
case *net.UDPAddr:
return check4(ip.IP)
}
return nil
}
func check4(ip net.IP) net.IP {
if ip4 := ip.To4(); ip4 != nil {
return ip4
}
return ip
}
func AddrToIpPort(addr net.Addr) (net.IP, int) {
if udp, ok := addr.(*net.UDPAddr); ok {
return check4(udp.IP), udp.Port
} else if tcp, ok := addr.(*net.TCPAddr); ok {
return check4(tcp.IP), tcp.Port
}
panic("enexpected addr " + addr.String())
}