-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.go
159 lines (132 loc) · 3.94 KB
/
common.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
package rdv
import (
"context"
"errors"
"net"
"net/netip"
)
const (
maxAddrs = 10
protocolName = "rdv/1"
// Token for this rdv conn, chosen by a client. Request and response.
hToken = "Rdv-Token"
// Comma-separated list of self-reported ip:port addrs. Request only.
hSelfAddrs = "Rdv-Self-Addrs"
// A comma-separate list of observed and self-reported ip:port addrs of the peer. Response only.
hPeerAddrs = "Rdv-Peer-Addrs"
// Observed public ipv4:port addr of the requesting client, from the server's point of view.
// Response only.
hObservedAddr = "Rdv-Observed-Addr"
)
var (
ErrHijackFailed = errors.New("failed hijacking http conn")
ErrBadHandshake = errors.New("bad http handshake")
ErrProtocol = errors.New("rdv protocol error")
ErrUpgrade = errors.New("rdv http upgrade error")
ErrNotChosen = errors.New("no rdv conn chosen")
ErrServerClosed = errors.New("rdv server closed")
ErrPrivilegedPort = errors.New("bad addr: expected port >=1024")
ErrInvalidAddr = errors.New("bad addr: invalid addr")
ErrDontUse = errors.New("bad addr: not helpful for connectivity")
)
// TODO: Ipv4-mapped v6-addrs
func DefaultSelfAddrs(ctx context.Context, socket *Socket) []netip.AddrPort {
netAddrs, _ := net.InterfaceAddrs()
var addrs []netip.AddrPort
for _, netAddr := range netAddrs {
if len(addrs) > maxAddrs-1 { // save one addr for observed addr
break
}
prefixAddr := netip.MustParsePrefix(netAddr.String())
addr := netip.AddrPortFrom(prefixAddr.Addr(), socket.Port)
addrs = append(addrs, addr)
}
return addrs
}
// An IP address space is derived from an IP address. These are used for connectivity in rdv, and
// thus don't include multicast etc. order to differentiate between meaningful addrs.
type AddrSpace uint32
const (
// Denotes invalid spaces.
SpaceInvalid AddrSpace = 0
// Public IPv4 addrs, extremely common and useful for remote connectivity when available.
SpacePublic4 AddrSpace = 1 << iota
// Public IPv6 addrs, very common and very useful for both local and remote connectivity.
SpacePublic6
// Private IPv4 addrs are very common and useful for local connectivity.
SpacePrivate4
// ULA ipv6 addrs are not common (although link-local are).
SpacePrivate6
// Link-local ipv4 addrs are not common in most setups.
SpaceLink4
// Link-local ipv6 addrs are not recommended with rdv due to zones.
SpaceLink6
// Loopback addresses are mostly useful for testing.
SpaceLoopback
)
const (
// No spaces won't match any spaces
NoSpaces AddrSpace = 1 << 31
// Public IPs only
PublicSpaces AddrSpace = SpacePublic4 | SpacePublic6
// Sensible defaults for most users, includes private and public spaces
DefaultSpaces AddrSpace = SpacePublic4 | SpacePublic6 | SpacePrivate4 | SpacePrivate6
// All IP spaces
AllSpaces AddrSpace = ^NoSpaces
)
func (s AddrSpace) Includes(space AddrSpace) bool {
return space&s != 0
}
func (s AddrSpace) String() string {
switch s {
case SpacePublic4:
return "public4"
case SpacePublic6:
return "public6"
case SpacePrivate4:
return "private4"
case SpacePrivate6:
return "private6"
case SpaceLink4:
return "link4"
case SpaceLink6:
return "link6"
case SpaceLoopback:
return "loopback"
}
return "invalid"
}
// Get AddrPort and AddrSpace from a TCP net.Addr
func FromNetAddr(na net.Addr) (addr netip.AddrPort, space AddrSpace) {
addr, _ = netip.ParseAddrPort(na.String())
space = GetAddrSpace(addr.Addr())
return
}
func GetAddrSpace(ip netip.Addr) AddrSpace {
// TODO: Check what to do about ipv4-mapped ipv6 addresses
if !ip.IsValid() || ip.IsUnspecified() || ip.IsMulticast() {
return SpaceInvalid
}
if ip.IsLoopback() {
return SpaceLoopback
}
if ip.IsLinkLocalUnicast() {
if ip.Is4() {
return SpaceLink4
}
return SpaceLink6
}
if ip.IsPrivate() {
if ip.Is4() {
return SpacePrivate4
}
return SpacePrivate6
}
if ip.IsGlobalUnicast() {
if ip.Is4() {
return SpacePublic4
}
return SpacePublic6
}
return SpaceInvalid
}