update packaging
[platform/core/system/edge-orchestration.git] / vendor / github.com / miekg / dns / vendor / golang.org / x / net / icmp / multipart.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 "golang.org/x/net/internal/iana"
8
9 // multipartMessageBodyDataLen takes b as an original datagram and
10 // exts as extensions, and returns a required length for message body
11 // and a required length for a padded original datagram in wire
12 // format.
13 func multipartMessageBodyDataLen(proto int, withOrigDgram bool, b []byte, exts []Extension) (bodyLen, dataLen int) {
14         for _, ext := range exts {
15                 bodyLen += ext.Len(proto)
16         }
17         if bodyLen > 0 {
18                 if withOrigDgram {
19                         dataLen = multipartMessageOrigDatagramLen(proto, b)
20                 }
21                 bodyLen += 4 // length of extension header
22         } else {
23                 dataLen = len(b)
24         }
25         bodyLen += dataLen
26         return bodyLen, dataLen
27 }
28
29 // multipartMessageOrigDatagramLen takes b as an original datagram,
30 // and returns a required length for a padded orignal datagram in wire
31 // format.
32 func multipartMessageOrigDatagramLen(proto int, b []byte) int {
33         roundup := func(b []byte, align int) int {
34                 // According to RFC 4884, the padded original datagram
35                 // field must contain at least 128 octets.
36                 if len(b) < 128 {
37                         return 128
38                 }
39                 r := len(b)
40                 return (r + align - 1) & ^(align - 1)
41         }
42         switch proto {
43         case iana.ProtocolICMP:
44                 return roundup(b, 4)
45         case iana.ProtocolIPv6ICMP:
46                 return roundup(b, 8)
47         default:
48                 return len(b)
49         }
50 }
51
52 // marshalMultipartMessageBody takes data as an original datagram and
53 // exts as extesnsions, and returns a binary encoding of message body.
54 // It can be used for non-multipart message bodies when exts is nil.
55 func marshalMultipartMessageBody(proto int, withOrigDgram bool, data []byte, exts []Extension) ([]byte, error) {
56         bodyLen, dataLen := multipartMessageBodyDataLen(proto, withOrigDgram, data, exts)
57         b := make([]byte, 4+bodyLen)
58         copy(b[4:], data)
59         off := dataLen + 4
60         if len(exts) > 0 {
61                 b[dataLen+4] = byte(extensionVersion << 4)
62                 off += 4 // length of object header
63                 for _, ext := range exts {
64                         switch ext := ext.(type) {
65                         case *MPLSLabelStack:
66                                 if err := ext.marshal(proto, b[off:]); err != nil {
67                                         return nil, err
68                                 }
69                                 off += ext.Len(proto)
70                         case *InterfaceInfo:
71                                 attrs, l := ext.attrsAndLen(proto)
72                                 if err := ext.marshal(proto, b[off:], attrs, l); err != nil {
73                                         return nil, err
74                                 }
75                                 off += ext.Len(proto)
76                         case *InterfaceIdent:
77                                 if err := ext.marshal(proto, b[off:]); err != nil {
78                                         return nil, err
79                                 }
80                                 off += ext.Len(proto)
81                         }
82                 }
83                 s := checksum(b[dataLen+4:])
84                 b[dataLen+4+2] ^= byte(s)
85                 b[dataLen+4+3] ^= byte(s >> 8)
86                 if withOrigDgram {
87                         switch proto {
88                         case iana.ProtocolICMP:
89                                 b[1] = byte(dataLen / 4)
90                         case iana.ProtocolIPv6ICMP:
91                                 b[0] = byte(dataLen / 8)
92                         }
93                 }
94         }
95         return b, nil
96 }
97
98 // parseMultipartMessageBody parses b as either a non-multipart
99 // message body or a multipart message body.
100 func parseMultipartMessageBody(proto int, typ Type, b []byte) ([]byte, []Extension, error) {
101         var l int
102         switch proto {
103         case iana.ProtocolICMP:
104                 l = 4 * int(b[1])
105         case iana.ProtocolIPv6ICMP:
106                 l = 8 * int(b[0])
107         }
108         if len(b) == 4 {
109                 return nil, nil, nil
110         }
111         exts, l, err := parseExtensions(typ, b[4:], l)
112         if err != nil {
113                 l = len(b) - 4
114         }
115         var data []byte
116         if l > 0 {
117                 data = make([]byte, l)
118                 copy(data, b[4:])
119         }
120         return data, exts, nil
121 }