1 package nl
2
3 import (
4 "errors"
5 "fmt"
6 "net"
7 )
8
9 type IPv6SrHdr struct {
10 nextHdr uint8
11 hdrLen uint8
12 routingType uint8
13 segmentsLeft uint8
14 firstSegment uint8
15 flags uint8
16 reserved uint16
17
18 Segments []net.IP
19 }
20
21 func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool {
22 if len(s1.Segments) != len(s2.Segments) {
23 return false
24 }
25 for i := range s1.Segments {
26 if !s1.Segments[i].Equal(s2.Segments[i]) {
27 return false
28 }
29 }
30 return s1.nextHdr == s2.nextHdr &&
31 s1.hdrLen == s2.hdrLen &&
32 s1.routingType == s2.routingType &&
33 s1.segmentsLeft == s2.segmentsLeft &&
34 s1.firstSegment == s2.firstSegment &&
35 s1.flags == s2.flags
36
37 }
38
39
40 const (
41 SEG6_IPTUN_MODE_INLINE = iota
42 SEG6_IPTUN_MODE_ENCAP
43 )
44
45
46
47 const (
48 SEG6_IPTUNNEL_UNSPEC = iota
49 SEG6_IPTUNNEL_SRH
50 __SEG6_IPTUNNEL_MAX
51 )
52 const (
53 SEG6_IPTUNNEL_MAX = __SEG6_IPTUNNEL_MAX - 1
54 )
55
56 func EncodeSEG6Encap(mode int, segments []net.IP) ([]byte, error) {
57 nsegs := len(segments)
58 if nsegs == 0 {
59 return nil, errors.New("EncodeSEG6Encap: No Segment in srh")
60 }
61 b := make([]byte, 12, 12+len(segments)*16)
62 native := NativeEndian()
63 native.PutUint32(b, uint32(mode))
64 b[4] = 0
65 b[5] = uint8(16 * nsegs >> 3)
66 b[6] = IPV6_SRCRT_TYPE_4
67 b[7] = uint8(nsegs - 1)
68 b[8] = uint8(nsegs - 1)
69 b[9] = 0
70
71 native.PutUint16(b[10:], 0)
72 for _, netIP := range segments {
73 b = append(b, netIP...)
74 }
75 return b, nil
76 }
77
78 func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) {
79 native := NativeEndian()
80 mode := int(native.Uint32(buf))
81 srh := IPv6SrHdr{
82 nextHdr: buf[4],
83 hdrLen: buf[5],
84 routingType: buf[6],
85 segmentsLeft: buf[7],
86 firstSegment: buf[8],
87 flags: buf[9],
88 reserved: native.Uint16(buf[10:12]),
89 }
90 buf = buf[12:]
91 if len(buf)%16 != 0 {
92 err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)", len(buf))
93 return mode, nil, err
94 }
95 for len(buf) > 0 {
96 srh.Segments = append(srh.Segments, net.IP(buf[:16]))
97 buf = buf[16:]
98 }
99 return mode, srh.Segments, nil
100 }
101
102 func DecodeSEG6Srh(buf []byte) ([]net.IP, error) {
103 native := NativeEndian()
104 srh := IPv6SrHdr{
105 nextHdr: buf[0],
106 hdrLen: buf[1],
107 routingType: buf[2],
108 segmentsLeft: buf[3],
109 firstSegment: buf[4],
110 flags: buf[5],
111 reserved: native.Uint16(buf[6:8]),
112 }
113 buf = buf[8:]
114 if len(buf)%16 != 0 {
115 err := fmt.Errorf("DecodeSEG6Srh: error parsing Segment List (buf len: %d)", len(buf))
116 return nil, err
117 }
118 for len(buf) > 0 {
119 srh.Segments = append(srh.Segments, net.IP(buf[:16]))
120 buf = buf[16:]
121 }
122 return srh.Segments, nil
123 }
124 func EncodeSEG6Srh(segments []net.IP) ([]byte, error) {
125 nsegs := len(segments)
126 if nsegs == 0 {
127 return nil, errors.New("EncodeSEG6Srh: No Segments")
128 }
129 b := make([]byte, 8, 8+len(segments)*16)
130 native := NativeEndian()
131 b[0] = 0
132 b[1] = uint8(16 * nsegs >> 3)
133 b[2] = IPV6_SRCRT_TYPE_4
134 b[3] = uint8(nsegs - 1)
135 b[4] = uint8(nsegs - 1)
136 b[5] = 0
137
138 native.PutUint16(b[6:], 0)
139 for _, netIP := range segments {
140 b = append(b, netIP...)
141 }
142 return b, nil
143 }
144
145
146 func SEG6EncapModeString(mode int) string {
147 switch mode {
148 case SEG6_IPTUN_MODE_INLINE:
149 return "inline"
150 case SEG6_IPTUN_MODE_ENCAP:
151 return "encap"
152 }
153 return "unknown"
154 }
155
View as plain text