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
|
package wgcfg
import (
"fmt"
"math"
"net"
)
// IP is an IPv4 or an IPv6 address.
//
// Internally the address is always represented in its IPv6 form.
// IPv4 addresses use the IPv4-in-IPv6 syntax.
type IP struct {
Addr [16]byte
}
func (ip IP) String() string { return net.IP(ip.Addr[:]).String() }
// IP converts ip into a standard library net.IP.
func (ip IP) IP() net.IP { return net.IP(ip.Addr[:]) }
// Is6 reports whether ip is an IPv6 address.
func (ip IP) Is6() bool { return !ip.Is4() }
// Is4 reports whether ip is an IPv4 address.
func (ip IP) Is4() bool {
return ip.Addr[0] == 0 && ip.Addr[1] == 0 &&
ip.Addr[2] == 0 && ip.Addr[3] == 0 &&
ip.Addr[4] == 0 && ip.Addr[5] == 0 &&
ip.Addr[6] == 0 && ip.Addr[7] == 0 &&
ip.Addr[8] == 0 && ip.Addr[9] == 0 &&
ip.Addr[10] == 0xff && ip.Addr[11] == 0xff
}
// To4 returns either a 4 byte slice for an IPv4 address, or nil if
// it's not IPv4.
func (ip IP) To4() []byte {
if ip.Is4() {
return ip.Addr[12:16]
} else {
return nil
}
}
// Equal reports whether ip == x.
func (ip IP) Equal(x IP) bool {
return ip == x
}
func (ip IP) MarshalText() ([]byte, error) {
return []byte(ip.String()), nil
}
func (ip *IP) UnmarshalText(text []byte) error {
parsedIP, ok := ParseIP(string(text))
if !ok {
return fmt.Errorf("wgcfg.IP: UnmarshalText: bad IP address %q", text)
}
*ip = parsedIP
return nil
}
func IPv4(b0, b1, b2, b3 byte) (ip IP) {
ip.Addr[10], ip.Addr[11] = 0xff, 0xff // IPv4-in-IPv6 prefix
ip.Addr[12] = b0
ip.Addr[13] = b1
ip.Addr[14] = b2
ip.Addr[15] = b3
return ip
}
// ParseIP parses the string representation of an address into an IP.
//
// It accepts IPv4 notation such as "1.2.3.4" and IPv6 notation like ""::0".
// The ok result reports whether s was a valid IP and ip is valid.
func ParseIP(s string) (ip IP, ok bool) {
netIP := net.ParseIP(s)
if netIP == nil {
return IP{}, false
}
copy(ip.Addr[:], netIP.To16())
return ip, true
}
// CIDR is a compact IP address and subnet mask.
type CIDR struct {
IP IP
Mask uint8 // 0-32 for IsIPv4, 4-128 for IsIPv6
}
// ParseCIDR parses CIDR notation into a CIDR type.
// Typical CIDR strings look like "192.168.1.0/24".
func ParseCIDR(s string) (CIDR, error) {
netIP, netAddr, err := net.ParseCIDR(s)
if err != nil {
return CIDR{}, err
}
var cidr CIDR
copy(cidr.IP.Addr[:], netIP.To16())
ones, _ := netAddr.Mask.Size()
cidr.Mask = uint8(ones)
return cidr, nil
}
func (r CIDR) String() string { return r.IPNet().String() }
func (r CIDR) IPNet() *net.IPNet {
bits := 128
if r.IP.Is4() {
bits = 32
}
return &net.IPNet{IP: r.IP.IP(), Mask: net.CIDRMask(int(r.Mask), bits)}
}
func (r CIDR) Contains(ip IP) bool {
c := int8(r.Mask)
i := 0
if r.IP.Is4() {
i = 12
if ip.Is6() {
return false
}
}
for ; i < 16 && c > 0; i++ {
var x uint8
if c < 8 {
x = 8 - uint8(c)
}
m := uint8(math.MaxUint8) >> x << x
a := r.IP.Addr[i] & m
b := ip.Addr[i] & m
if a != b {
return false
}
c -= 8
}
return true
}
func (r CIDR) MarshalText() ([]byte, error) {
return []byte(r.String()), nil
}
func (r *CIDR) UnmarshalText(text []byte) error {
cidr, err := ParseCIDR(string(text))
if err != nil {
return fmt.Errorf("wgcfg.CIDR: UnmarshalText: %v", err)
}
*r = cidr
return nil
}
|