...
1
2
3
4
5 package icmp
6
7 import (
8 "encoding/binary"
9
10 "golang.org/x/net/ipv4"
11 "golang.org/x/net/ipv6"
12 )
13
14
15 type Extension interface {
16
17
18
19 Len(proto int) int
20
21
22
23
24 Marshal(proto int) ([]byte, error)
25 }
26
27 const extensionVersion = 2
28
29 func validExtensionHeader(b []byte) bool {
30 v := int(b[0]&0xf0) >> 4
31 s := binary.BigEndian.Uint16(b[2:4])
32 if s != 0 {
33 s = checksum(b)
34 }
35 if v != extensionVersion || s != 0 {
36 return false
37 }
38 return true
39 }
40
41
42
43
44
45
46
47
48 func parseExtensions(typ Type, b []byte, l int) ([]Extension, int, error) {
49
50
51
52
53
54
55
56
57
58 switch typ {
59 case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
60 if len(b) < 8 || !validExtensionHeader(b) {
61 return nil, -1, errNoExtension
62 }
63 l = 0
64 default:
65 if 128 > l || l+8 > len(b) {
66 l = 128
67 }
68 if l+8 > len(b) {
69 return nil, -1, errNoExtension
70 }
71 if !validExtensionHeader(b[l:]) {
72 if l == 128 {
73 return nil, -1, errNoExtension
74 }
75 l = 128
76 if !validExtensionHeader(b[l:]) {
77 return nil, -1, errNoExtension
78 }
79 }
80 }
81 var exts []Extension
82 for b = b[l+4:]; len(b) >= 4; {
83 ol := int(binary.BigEndian.Uint16(b[:2]))
84 if 4 > ol || ol > len(b) {
85 break
86 }
87 switch b[2] {
88 case classMPLSLabelStack:
89 ext, err := parseMPLSLabelStack(b[:ol])
90 if err != nil {
91 return nil, -1, err
92 }
93 exts = append(exts, ext)
94 case classInterfaceInfo:
95 ext, err := parseInterfaceInfo(b[:ol])
96 if err != nil {
97 return nil, -1, err
98 }
99 exts = append(exts, ext)
100 case classInterfaceIdent:
101 ext, err := parseInterfaceIdent(b[:ol])
102 if err != nil {
103 return nil, -1, err
104 }
105 exts = append(exts, ext)
106 default:
107 ext := &RawExtension{Data: make([]byte, ol)}
108 copy(ext.Data, b[:ol])
109 exts = append(exts, ext)
110 }
111 b = b[ol:]
112 }
113 return exts, l, nil
114 }
115
116 func validExtensions(typ Type, exts []Extension) bool {
117 switch typ {
118 case ipv4.ICMPTypeDestinationUnreachable, ipv4.ICMPTypeTimeExceeded, ipv4.ICMPTypeParameterProblem,
119 ipv6.ICMPTypeDestinationUnreachable, ipv6.ICMPTypeTimeExceeded:
120 for i := range exts {
121 switch exts[i].(type) {
122 case *MPLSLabelStack, *InterfaceInfo, *RawExtension:
123 default:
124 return false
125 }
126 }
127 return true
128 case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
129 var n int
130 for i := range exts {
131 switch exts[i].(type) {
132 case *InterfaceIdent:
133 n++
134 case *RawExtension:
135 default:
136 return false
137 }
138 }
139
140
141
142 if n == 1 && len(exts) > 1 {
143 return false
144 }
145 return true
146 default:
147 return false
148 }
149 }
150
151
152
153
154
155 type RawExtension struct {
156 Data []byte
157 }
158
159
160 func (p *RawExtension) Len(proto int) int {
161 if p == nil {
162 return 0
163 }
164 return len(p.Data)
165 }
166
167
168 func (p *RawExtension) Marshal(proto int) ([]byte, error) {
169 return p.Data, nil
170 }
171
View as plain text