forked from free5gc/pfcp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
NodeID.go
121 lines (105 loc) · 2.82 KB
/
NodeID.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
package pfcpType
import (
"errors"
"fmt"
"net"
"github.com/aalayanahmad/pfcp/logger"
)
const (
NodeIdTypeIpv4Address uint8 = iota
NodeIdTypeIpv6Address
NodeIdTypeFqdn
)
type NodeID struct {
NodeIdType uint8 // 0x00001111
IP net.IP
FQDN string
}
func (n *NodeID) MarshalBinary() ([]byte, error) {
var data []byte
data = append([]byte(""), n.NodeIdType)
var nodeIdValue []byte
// Octet 6 to o
switch n.NodeIdType {
case NodeIdTypeIpv4Address:
if len(n.IP) == 0 || n.FQDN != "" {
return []byte(""), errors.New("type of node ID is ipv4, should fill IP field and FQDN field should be empty")
}
if len(n.IP) != net.IPv4len {
return []byte(""), errors.New("length of node id data shall be 4 Octet if node id is an IPv4 address")
}
nodeIdValue = n.IP
case NodeIdTypeIpv6Address:
if len(n.IP) == 0 || n.FQDN != "" {
return []byte(""), errors.New("type of node ID is ipv6, should fill IP field and FQDN field should be empty")
}
if len(n.IP) != net.IPv6len {
return []byte(""), errors.New("length of node id data shall be 16 Octet if node id is an IPv6 address")
}
nodeIdValue = n.IP
case NodeIdTypeFqdn:
if n.FQDN == "" || n.IP != nil {
return []byte(""), errors.New("type of node ID is fqdn, should fill FQDN field and IP field should be empty")
}
if rfc1035RR, err := fqdnToRfc1035(n.FQDN, false); err != nil {
return nil, err
} else {
nodeIdValue = rfc1035RR
}
default:
return nil, errors.New("type of node id should be ipv4, ipv6 or fqdn")
}
data = append(data, nodeIdValue...)
return data, nil
}
func (n *NodeID) UnmarshalBinary(data []byte) error {
length := uint16(len(data))
var idx uint16 = 0
// Octet 5
if length < idx+1 {
return fmt.Errorf("Inadequate TLV length: %d", length)
}
n.NodeIdType = data[idx] & Mask4
idx = idx + 1
// Octet 6 to o
switch n.NodeIdType {
case NodeIdTypeIpv4Address:
if length < idx+net.IPv4len {
return fmt.Errorf("Inadequate TLV length: %d", length)
}
n.IP = data[idx : idx+net.IPv4len]
n.FQDN = ""
idx = idx + net.IPv4len
case NodeIdTypeIpv6Address:
if length < idx+net.IPv6len {
return fmt.Errorf("Inadequate TLV length: %d", length)
}
n.IP = data[idx : idx+net.IPv6len]
n.FQDN = ""
idx = idx + net.IPv6len
case NodeIdTypeFqdn:
rfc1035RR := data[idx:]
n.FQDN = rfc1035tofqdn(rfc1035RR)
n.IP = nil
idx = idx + uint16(len(rfc1035RR))
}
if length != idx {
return fmt.Errorf("Inadequate TLV length: %d", length)
}
return nil
}
func (n *NodeID) ResolveNodeIdToIp() net.IP {
switch n.NodeIdType {
case NodeIdTypeIpv4Address, NodeIdTypeIpv6Address:
return n.IP
case NodeIdTypeFqdn:
if ns, err := net.LookupHost(n.FQDN); err != nil {
logger.PFCPLog.Warnf("Host lookup failed: %+v", err)
return net.IPv4zero
} else {
return net.ParseIP(ns[0])
}
default:
return net.IPv4zero
}
}