/
address.go
232 lines (205 loc) · 7.1 KB
/
address.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
package node
import (
"encoding"
"errors"
"fmt"
"net"
"strings"
"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
)
var (
// ErrInvalidAddress is the error returned when a transport address is
// invalid.
ErrInvalidAddress = errors.New("node: invalid transport address")
// ErrConsensusAddressNoID is the error returned when a consensus address
// doesn't have the ID@ part.
ErrConsensusAddressNoID = errors.New("node: consensus address doesn't have ID@ part")
// ErrTLSAddressNoPubKey is the error returned when a TLS address doesn't have the PubKey@ part.
ErrTLSAddressNoPubKey = errors.New("node: TLS address missing PubKey@ part")
unroutableNetworks []net.IPNet
_ encoding.TextMarshaler = (*Address)(nil)
_ encoding.TextUnmarshaler = (*Address)(nil)
_ encoding.TextMarshaler = (*ConsensusAddress)(nil)
_ encoding.TextUnmarshaler = (*ConsensusAddress)(nil)
)
// Address represents a TCP address for the purpose of node descriptors.
type Address struct {
net.TCPAddr
}
// Equal compares vs another address for equality.
func (a *Address) Equal(other *Address) bool {
if !a.IP.Equal(other.IP) {
return false
}
if a.Port != other.Port {
return false
}
if a.Zone != other.Zone {
return false
}
return true
}
// MarshalText implements the encoding.TextMarshaler interface.
func (a *Address) MarshalText() ([]byte, error) {
return []byte(a.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (a *Address) UnmarshalText(text []byte) error {
tcpAddr, err := net.ResolveTCPAddr("", string(text))
if err != nil {
return err
}
a.TCPAddr = *tcpAddr
return nil
}
// FromIP populates the address from a net.IP and port.
func (a *Address) FromIP(ip net.IP, port uint16) error {
if ipv4 := ip.To4(); ipv4 != nil {
a.IP = ipv4
} else if ipv6 := ip.To16(); ipv6 != nil {
a.IP = ipv6
} else {
return ErrInvalidAddress
}
a.Port = int(port)
a.Zone = ""
return nil
}
// IsRoutable returns true iff the address is likely to be globally routable.
func (a *Address) IsRoutable() bool {
for _, v := range unroutableNetworks {
if v.Contains(a.IP) {
return false
}
}
return true
}
// String returns the string representation of an address.
func (a Address) String() string {
return a.TCPAddr.String()
}
// ConsensusAddress represents a Tendermint consensus address that includes an
// ID and a TCP address.
// NOTE: The consensus address ID could be different from the consensus ID
// to allow using a sentry node's ID and address instead of the validator's.
type ConsensusAddress struct {
// ID is public key identifying the node.
ID signature.PublicKey `json:"id"`
// Address is the address at which the node can be reached.
Address Address `json:"address"`
}
// MarshalText implements the encoding.TextMarshaler interface.
func (ca *ConsensusAddress) MarshalText() ([]byte, error) {
idStr := ca.ID.String()
addrStr, err := ca.Address.MarshalText()
if err != nil {
return nil, fmt.Errorf("node: error marshalling consensus address' TCP address: %w", err)
}
return []byte(fmt.Sprintf("%s@%s", idStr, addrStr)), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (ca *ConsensusAddress) UnmarshalText(text []byte) error {
spl := strings.Split(string(text), "@")
if len(spl) != 2 {
return ErrConsensusAddressNoID
}
if err := ca.ID.UnmarshalText([]byte(spl[0])); err != nil {
return fmt.Errorf("node: unable to parse consensus address' ID: %w", err)
}
if err := ca.Address.UnmarshalText([]byte(spl[1])); err != nil {
return fmt.Errorf("node: unable to parse consensus address' TCP address: %w", err)
}
return nil
}
// String returns a string representation of a consensus address.
func (ca *ConsensusAddress) String() string {
return fmt.Sprintf("%s@%s", ca.ID, ca.Address)
}
// TLSAddress represents an Oasis committee address that includes a TLS public key and a TCP
// address.
//
// NOTE: The address TLS public key can be different from the actual node TLS public key to allow
// using a sentry node's addresses.
type TLSAddress struct {
// PubKey is the public key used for establishing TLS connections.
PubKey signature.PublicKey `json:"pub_key"`
// Address is the address at which the node can be reached.
Address Address `json:"address"`
}
// Equal compares vs another TLSAddress for equality.
func (ta *TLSAddress) Equal(other *TLSAddress) bool {
if !ta.PubKey.Equal(other.PubKey) {
return false
}
if !ta.Address.Equal(&other.Address) {
return false
}
return true
}
// MarshalText implements the encoding.TextMarshaler interface.
func (ta *TLSAddress) MarshalText() ([]byte, error) {
pubKeyStr, err := ta.PubKey.MarshalText()
if err != nil {
return nil, fmt.Errorf("node: error marshalling TLS address' public key: %w", err)
}
addrStr, err := ta.Address.MarshalText()
if err != nil {
return nil, fmt.Errorf("node: error marshalling TLS address' TCP address: %w", err)
}
return []byte(fmt.Sprintf("%s@%s", pubKeyStr, addrStr)), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (ta *TLSAddress) UnmarshalText(text []byte) error {
spl := strings.Split(string(text), "@")
if len(spl) != 2 {
return ErrTLSAddressNoPubKey
}
if err := ta.PubKey.UnmarshalText([]byte(spl[0])); err != nil {
return fmt.Errorf("node: unable to parse TLS address' public key: %w", err)
}
if err := ta.Address.UnmarshalText([]byte(spl[1])); err != nil {
return fmt.Errorf("node: unable to parse TLS address' TCP address: %w", err)
}
return nil
}
// String returns a string representation of a TLS address.
func (ta *TLSAddress) String() string {
return ta.Address.String()
}
func init() {
// List taken from RFC 6890. This is different from what tendermint
// does (more restrictive).
for _, v := range []string{
"0.0.0.0/8", // RFC 1122
"10.0.0.0/8", // RFC 1918: Private-Use
"100.64.0.0/10", // RFC 6598: Shared Address Space
"127.0.0.0/8", // RFC 1122: Loopback
"169.254.0.0/16", // RFC 3927: Link Local
"172.16.0.0/12", // RFC 1918: Private-Use
"192.0.0.0/24", // RFC 6890
"192.0.0.0/29", // RFC 6333: DS-Lite
"192.0.2.0/24", // RFC 5737: Documentation (TEST-NET-1)
"192.168.0.0/16", // RFC 1918: Private-Use
"192.18.0.0/15", // RFC 2544: Benchmarking
"198.51.100.0/24", // RFC 5737: TEST-NET-2
"203.0.113.0/24", // RFC 5737: TEST-NET-3
"240.0.0.0/4", // RFC 1112: Reserved
"255.255.255.255/32", // RFC 919: Limited Broadcast
"::1/128", // RFC 4291: Loopback Address
"::/128", // RFC 4291: Unspecified Address
"100::/64", // RFC 6666: Discard-Only Address Block
"2001::/32", // RFC 4380: TEREDO
"2001:2::/48", // RFC 5180: Benchmarking
"2001:db8::/32", // RFC 3849: Documentation
"2001:10::/28", // RFC 4843: ORCHID
"2002::/16", // RFC 3056: 6to4
"fc00::/7", // RFC 4193: Unique-Local
"fe80::/10", // RFC 4291: Linked-Scoped Unicast
} {
_, ipNet, err := net.ParseCIDR(v)
if err != nil {
panic("node: failed to parse reserved net: " + err.Error())
}
unroutableNetworks = append(unroutableNetworks, *ipNet)
}
}