OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / icmp / extension.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 "encoding/binary"
8
9 // An Extension represents an ICMP extension.
10 type Extension interface {
11         // Len returns the length of ICMP extension.
12         // Proto must be either the ICMPv4 or ICMPv6 protocol number.
13         Len(proto int) int
14
15         // Marshal returns the binary encoding of ICMP extension.
16         // Proto must be either the ICMPv4 or ICMPv6 protocol number.
17         Marshal(proto int) ([]byte, error)
18 }
19
20 const extensionVersion = 2
21
22 func validExtensionHeader(b []byte) bool {
23         v := int(b[0]&0xf0) >> 4
24         s := binary.BigEndian.Uint16(b[2:4])
25         if s != 0 {
26                 s = checksum(b)
27         }
28         if v != extensionVersion || s != 0 {
29                 return false
30         }
31         return true
32 }
33
34 // parseExtensions parses b as a list of ICMP extensions.
35 // The length attribute l must be the length attribute field in
36 // received icmp messages.
37 //
38 // It will return a list of ICMP extensions and an adjusted length
39 // attribute that represents the length of the padded original
40 // datagram field. Otherwise, it returns an error.
41 func parseExtensions(b []byte, l int) ([]Extension, int, error) {
42         // Still a lot of non-RFC 4884 compliant implementations are
43         // out there. Set the length attribute l to 128 when it looks
44         // inappropriate for backwards compatibility.
45         //
46         // A minimal extension at least requires 8 octets; 4 octets
47         // for an extension header, and 4 octets for a single object
48         // header.
49         //
50         // See RFC 4884 for further information.
51         if 128 > l || l+8 > len(b) {
52                 l = 128
53         }
54         if l+8 > len(b) {
55                 return nil, -1, errNoExtension
56         }
57         if !validExtensionHeader(b[l:]) {
58                 if l == 128 {
59                         return nil, -1, errNoExtension
60                 }
61                 l = 128
62                 if !validExtensionHeader(b[l:]) {
63                         return nil, -1, errNoExtension
64                 }
65         }
66         var exts []Extension
67         for b = b[l+4:]; len(b) >= 4; {
68                 ol := int(binary.BigEndian.Uint16(b[:2]))
69                 if 4 > ol || ol > len(b) {
70                         break
71                 }
72                 switch b[2] {
73                 case classMPLSLabelStack:
74                         ext, err := parseMPLSLabelStack(b[:ol])
75                         if err != nil {
76                                 return nil, -1, err
77                         }
78                         exts = append(exts, ext)
79                 case classInterfaceInfo:
80                         ext, err := parseInterfaceInfo(b[:ol])
81                         if err != nil {
82                                 return nil, -1, err
83                         }
84                         exts = append(exts, ext)
85                 }
86                 b = b[ol:]
87         }
88         return exts, l, nil
89 }