update packaging
[platform/core/system/edge-orchestration.git] / vendor / github.com / miekg / dns / vendor / golang.org / x / net / icmp / interface.go
1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package icmp
6
7 import (
8         "encoding/binary"
9         "net"
10         "strings"
11
12         "golang.org/x/net/internal/iana"
13 )
14
15 const (
16         classInterfaceInfo = 2
17 )
18
19 const (
20         attrMTU = 1 << iota
21         attrName
22         attrIPAddr
23         attrIfIndex
24 )
25
26 // An InterfaceInfo represents interface and next-hop identification.
27 type InterfaceInfo struct {
28         Class     int // extension object class number
29         Type      int // extension object sub-type
30         Interface *net.Interface
31         Addr      *net.IPAddr
32 }
33
34 func (ifi *InterfaceInfo) nameLen() int {
35         if len(ifi.Interface.Name) > 63 {
36                 return 64
37         }
38         l := 1 + len(ifi.Interface.Name)
39         return (l + 3) &^ 3
40 }
41
42 func (ifi *InterfaceInfo) attrsAndLen(proto int) (attrs, l int) {
43         l = 4
44         if ifi.Interface != nil && ifi.Interface.Index > 0 {
45                 attrs |= attrIfIndex
46                 l += 4
47                 if len(ifi.Interface.Name) > 0 {
48                         attrs |= attrName
49                         l += ifi.nameLen()
50                 }
51                 if ifi.Interface.MTU > 0 {
52                         attrs |= attrMTU
53                         l += 4
54                 }
55         }
56         if ifi.Addr != nil {
57                 switch proto {
58                 case iana.ProtocolICMP:
59                         if ifi.Addr.IP.To4() != nil {
60                                 attrs |= attrIPAddr
61                                 l += 4 + net.IPv4len
62                         }
63                 case iana.ProtocolIPv6ICMP:
64                         if ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
65                                 attrs |= attrIPAddr
66                                 l += 4 + net.IPv6len
67                         }
68                 }
69         }
70         return
71 }
72
73 // Len implements the Len method of Extension interface.
74 func (ifi *InterfaceInfo) Len(proto int) int {
75         _, l := ifi.attrsAndLen(proto)
76         return l
77 }
78
79 // Marshal implements the Marshal method of Extension interface.
80 func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error) {
81         attrs, l := ifi.attrsAndLen(proto)
82         b := make([]byte, l)
83         if err := ifi.marshal(proto, b, attrs, l); err != nil {
84                 return nil, err
85         }
86         return b, nil
87 }
88
89 func (ifi *InterfaceInfo) marshal(proto int, b []byte, attrs, l int) error {
90         binary.BigEndian.PutUint16(b[:2], uint16(l))
91         b[2], b[3] = classInterfaceInfo, byte(ifi.Type)
92         for b = b[4:]; len(b) > 0 && attrs != 0; {
93                 switch {
94                 case attrs&attrIfIndex != 0:
95                         b = ifi.marshalIfIndex(proto, b)
96                         attrs &^= attrIfIndex
97                 case attrs&attrIPAddr != 0:
98                         b = ifi.marshalIPAddr(proto, b)
99                         attrs &^= attrIPAddr
100                 case attrs&attrName != 0:
101                         b = ifi.marshalName(proto, b)
102                         attrs &^= attrName
103                 case attrs&attrMTU != 0:
104                         b = ifi.marshalMTU(proto, b)
105                         attrs &^= attrMTU
106                 }
107         }
108         return nil
109 }
110
111 func (ifi *InterfaceInfo) marshalIfIndex(proto int, b []byte) []byte {
112         binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.Index))
113         return b[4:]
114 }
115
116 func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
117         if len(b) < 4 {
118                 return nil, errMessageTooShort
119         }
120         ifi.Interface.Index = int(binary.BigEndian.Uint32(b[:4]))
121         return b[4:], nil
122 }
123
124 func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
125         switch proto {
126         case iana.ProtocolICMP:
127                 binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv4))
128                 copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
129                 b = b[4+net.IPv4len:]
130         case iana.ProtocolIPv6ICMP:
131                 binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv6))
132                 copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
133                 b = b[4+net.IPv6len:]
134         }
135         return b
136 }
137
138 func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
139         if len(b) < 4 {
140                 return nil, errMessageTooShort
141         }
142         afi := int(binary.BigEndian.Uint16(b[:2]))
143         b = b[4:]
144         switch afi {
145         case iana.AddrFamilyIPv4:
146                 if len(b) < net.IPv4len {
147                         return nil, errMessageTooShort
148                 }
149                 ifi.Addr.IP = make(net.IP, net.IPv4len)
150                 copy(ifi.Addr.IP, b[:net.IPv4len])
151                 b = b[net.IPv4len:]
152         case iana.AddrFamilyIPv6:
153                 if len(b) < net.IPv6len {
154                         return nil, errMessageTooShort
155                 }
156                 ifi.Addr.IP = make(net.IP, net.IPv6len)
157                 copy(ifi.Addr.IP, b[:net.IPv6len])
158                 b = b[net.IPv6len:]
159         }
160         return b, nil
161 }
162
163 func (ifi *InterfaceInfo) marshalName(proto int, b []byte) []byte {
164         l := byte(ifi.nameLen())
165         b[0] = l
166         copy(b[1:], []byte(ifi.Interface.Name))
167         return b[l:]
168 }
169
170 func (ifi *InterfaceInfo) parseName(b []byte) ([]byte, error) {
171         if 4 > len(b) || len(b) < int(b[0]) {
172                 return nil, errMessageTooShort
173         }
174         l := int(b[0])
175         if l%4 != 0 || 4 > l || l > 64 {
176                 return nil, errInvalidExtension
177         }
178         var name [63]byte
179         copy(name[:], b[1:l])
180         ifi.Interface.Name = strings.Trim(string(name[:]), "\000")
181         return b[l:], nil
182 }
183
184 func (ifi *InterfaceInfo) marshalMTU(proto int, b []byte) []byte {
185         binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.MTU))
186         return b[4:]
187 }
188
189 func (ifi *InterfaceInfo) parseMTU(b []byte) ([]byte, error) {
190         if len(b) < 4 {
191                 return nil, errMessageTooShort
192         }
193         ifi.Interface.MTU = int(binary.BigEndian.Uint32(b[:4]))
194         return b[4:], nil
195 }
196
197 func parseInterfaceInfo(b []byte) (Extension, error) {
198         ifi := &InterfaceInfo{
199                 Class: int(b[2]),
200                 Type:  int(b[3]),
201         }
202         if ifi.Type&(attrIfIndex|attrName|attrMTU) != 0 {
203                 ifi.Interface = &net.Interface{}
204         }
205         if ifi.Type&attrIPAddr != 0 {
206                 ifi.Addr = &net.IPAddr{}
207         }
208         attrs := ifi.Type & (attrIfIndex | attrIPAddr | attrName | attrMTU)
209         for b = b[4:]; len(b) > 0 && attrs != 0; {
210                 var err error
211                 switch {
212                 case attrs&attrIfIndex != 0:
213                         b, err = ifi.parseIfIndex(b)
214                         attrs &^= attrIfIndex
215                 case attrs&attrIPAddr != 0:
216                         b, err = ifi.parseIPAddr(b)
217                         attrs &^= attrIPAddr
218                 case attrs&attrName != 0:
219                         b, err = ifi.parseName(b)
220                         attrs &^= attrName
221                 case attrs&attrMTU != 0:
222                         b, err = ifi.parseMTU(b)
223                         attrs &^= attrMTU
224                 }
225                 if err != nil {
226                         return nil, err
227                 }
228         }
229         if ifi.Interface != nil && ifi.Interface.Name != "" && ifi.Addr != nil && ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
230                 ifi.Addr.Zone = ifi.Interface.Name
231         }
232         return ifi, nil
233 }
234
235 const (
236         classInterfaceIdent    = 3
237         typeInterfaceByName    = 1
238         typeInterfaceByIndex   = 2
239         typeInterfaceByAddress = 3
240 )
241
242 // An InterfaceIdent represents interface identification.
243 type InterfaceIdent struct {
244         Class int    // extension object class number
245         Type  int    // extension object sub-type
246         Name  string // interface name
247         Index int    // interface index
248         AFI   int    // address family identifier; see address family numbers in IANA registry
249         Addr  []byte // address
250 }
251
252 // Len implements the Len method of Extension interface.
253 func (ifi *InterfaceIdent) Len(_ int) int {
254         switch ifi.Type {
255         case typeInterfaceByName:
256                 l := len(ifi.Name)
257                 if l > 255 {
258                         l = 255
259                 }
260                 return 4 + (l+3)&^3
261         case typeInterfaceByIndex:
262                 return 4 + 8
263         case typeInterfaceByAddress:
264                 return 4 + 4 + (len(ifi.Addr)+3)&^3
265         default:
266                 return 4
267         }
268 }
269
270 // Marshal implements the Marshal method of Extension interface.
271 func (ifi *InterfaceIdent) Marshal(proto int) ([]byte, error) {
272         b := make([]byte, ifi.Len(proto))
273         if err := ifi.marshal(proto, b); err != nil {
274                 return nil, err
275         }
276         return b, nil
277 }
278
279 func (ifi *InterfaceIdent) marshal(proto int, b []byte) error {
280         l := ifi.Len(proto)
281         binary.BigEndian.PutUint16(b[:2], uint16(l))
282         b[2], b[3] = classInterfaceIdent, byte(ifi.Type)
283         switch ifi.Type {
284         case typeInterfaceByName:
285                 copy(b[4:], ifi.Name)
286         case typeInterfaceByIndex:
287                 binary.BigEndian.PutUint64(b[4:4+8], uint64(ifi.Index))
288         case typeInterfaceByAddress:
289                 binary.BigEndian.PutUint16(b[4:4+2], uint16(ifi.AFI))
290                 b[4+2] = byte(len(ifi.Addr))
291                 copy(b[4+4:], ifi.Addr)
292         }
293         return nil
294 }
295
296 func parseInterfaceIdent(b []byte) (Extension, error) {
297         ifi := &InterfaceIdent{
298                 Class: int(b[2]),
299                 Type:  int(b[3]),
300         }
301         switch ifi.Type {
302         case typeInterfaceByName:
303                 ifi.Name = strings.Trim(string(b[4:]), string(0))
304         case typeInterfaceByIndex:
305                 if len(b[4:]) < 8 {
306                         return nil, errInvalidExtension
307                 }
308                 ifi.Index = int(binary.BigEndian.Uint64(b[4 : 4+8]))
309         case typeInterfaceByAddress:
310                 if len(b[4:]) < 4 {
311                         return nil, errInvalidExtension
312                 }
313                 ifi.AFI = int(binary.BigEndian.Uint16(b[4 : 4+2]))
314                 l := int(b[4+2])
315                 if len(b[4+4:]) < l {
316                         return nil, errInvalidExtension
317                 }
318                 ifi.Addr = make([]byte, l)
319                 copy(ifi.Addr, b[4+4:])
320         }
321         return ifi, nil
322 }