-
Notifications
You must be signed in to change notification settings - Fork 14
/
nat64.go
58 lines (47 loc) · 1.4 KB
/
nat64.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
// Copyright (c) 2022 RethinkDNS and its authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package x64
import (
"net"
"github.com/celzero/firestack/intra/log"
)
type nat64 struct {
}
func newNat64() *nat64 {
return &nat64{}
}
// IsNat64 Implements NAT64.
func (n *nat64) IsNat64(prefix64 *net.IPNet, ip6 net.IP) bool {
return prefix64.Contains(ip6)
}
// xAddr translates ip6 to IPv4 discarding prefix64.
// If prefix64 or ip6 is not valid, it returns zerovalueaddr.
// If ip6 is unspecified, it returns unspecified IPv4.
func (n *nat64) xAddr(prefix64 *net.IPNet, ip6 net.IP) net.IP {
return ip6to4(prefix64, ip6)
}
// ip6to4 converts ip6 to IPv4 discarding prefix64.
func ip6to4(prefix64 *net.IPNet, ip6 net.IP) net.IP {
if ip6.IsUnspecified() {
return net.IPv4zero
}
ip4 := make(net.IP, net.IPv4len)
bitmask, _ := prefix64.Mask.Size() // prefix64 expected to be never nil
startByte := bitmask / 8
if startByte+net.IPv4len > len(ip6) {
log.W("natpt: too long; cannot convert ip64(%v) / prefix64(%v) to ip4", ip6, prefix64)
return nil
}
for i := 0; i < net.IPv4len; i++ {
i6 := startByte + i
// skip byte 8, datatracker.ietf.org/doc/html/rfc6052#section-2.2
if i6 == 8 {
startByte++
}
ip4[i] = ip6[startByte+i]
}
return ip4
}