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.
12 "golang.org/x/net/internal/iana"
16 classInterfaceInfo = 2
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
34 func (ifi *InterfaceInfo) nameLen() int {
35 if len(ifi.Interface.Name) > 63 {
38 l := 1 + len(ifi.Interface.Name)
42 func (ifi *InterfaceInfo) attrsAndLen(proto int) (attrs, l int) {
44 if ifi.Interface != nil && ifi.Interface.Index > 0 {
47 if len(ifi.Interface.Name) > 0 {
51 if ifi.Interface.MTU > 0 {
58 case iana.ProtocolICMP:
59 if ifi.Addr.IP.To4() != nil {
63 case iana.ProtocolIPv6ICMP:
64 if ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
73 // Len implements the Len method of Extension interface.
74 func (ifi *InterfaceInfo) Len(proto int) int {
75 _, l := ifi.attrsAndLen(proto)
79 // Marshal implements the Marshal method of Extension interface.
80 func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error) {
81 attrs, l := ifi.attrsAndLen(proto)
83 if err := ifi.marshal(proto, b, attrs, l); err != nil {
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; {
94 case attrs&attrIfIndex != 0:
95 b = ifi.marshalIfIndex(proto, b)
97 case attrs&attrIPAddr != 0:
98 b = ifi.marshalIPAddr(proto, b)
100 case attrs&attrName != 0:
101 b = ifi.marshalName(proto, b)
103 case attrs&attrMTU != 0:
104 b = ifi.marshalMTU(proto, b)
111 func (ifi *InterfaceInfo) marshalIfIndex(proto int, b []byte) []byte {
112 binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.Index))
116 func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
118 return nil, errMessageTooShort
120 ifi.Interface.Index = int(binary.BigEndian.Uint32(b[:4]))
124 func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
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:]
138 func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
140 return nil, errMessageTooShort
142 afi := int(binary.BigEndian.Uint16(b[:2]))
145 case iana.AddrFamilyIPv4:
146 if len(b) < net.IPv4len {
147 return nil, errMessageTooShort
149 ifi.Addr.IP = make(net.IP, net.IPv4len)
150 copy(ifi.Addr.IP, b[:net.IPv4len])
152 case iana.AddrFamilyIPv6:
153 if len(b) < net.IPv6len {
154 return nil, errMessageTooShort
156 ifi.Addr.IP = make(net.IP, net.IPv6len)
157 copy(ifi.Addr.IP, b[:net.IPv6len])
163 func (ifi *InterfaceInfo) marshalName(proto int, b []byte) []byte {
164 l := byte(ifi.nameLen())
166 copy(b[1:], []byte(ifi.Interface.Name))
170 func (ifi *InterfaceInfo) parseName(b []byte) ([]byte, error) {
171 if 4 > len(b) || len(b) < int(b[0]) {
172 return nil, errMessageTooShort
175 if l%4 != 0 || 4 > l || l > 64 {
176 return nil, errInvalidExtension
179 copy(name[:], b[1:l])
180 ifi.Interface.Name = strings.Trim(string(name[:]), "\000")
184 func (ifi *InterfaceInfo) marshalMTU(proto int, b []byte) []byte {
185 binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.MTU))
189 func (ifi *InterfaceInfo) parseMTU(b []byte) ([]byte, error) {
191 return nil, errMessageTooShort
193 ifi.Interface.MTU = int(binary.BigEndian.Uint32(b[:4]))
197 func parseInterfaceInfo(b []byte) (Extension, error) {
198 ifi := &InterfaceInfo{
202 if ifi.Type&(attrIfIndex|attrName|attrMTU) != 0 {
203 ifi.Interface = &net.Interface{}
205 if ifi.Type&attrIPAddr != 0 {
206 ifi.Addr = &net.IPAddr{}
208 attrs := ifi.Type & (attrIfIndex | attrIPAddr | attrName | attrMTU)
209 for b = b[4:]; len(b) > 0 && attrs != 0; {
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)
218 case attrs&attrName != 0:
219 b, err = ifi.parseName(b)
221 case attrs&attrMTU != 0:
222 b, err = ifi.parseMTU(b)
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
236 classInterfaceIdent = 3
237 typeInterfaceByName = 1
238 typeInterfaceByIndex = 2
239 typeInterfaceByAddress = 3
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
252 // Len implements the Len method of Extension interface.
253 func (ifi *InterfaceIdent) Len(_ int) int {
255 case typeInterfaceByName:
261 case typeInterfaceByIndex:
263 case typeInterfaceByAddress:
264 return 4 + 4 + (len(ifi.Addr)+3)&^3
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 {
279 func (ifi *InterfaceIdent) marshal(proto int, b []byte) error {
281 binary.BigEndian.PutUint16(b[:2], uint16(l))
282 b[2], b[3] = classInterfaceIdent, byte(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)
296 func parseInterfaceIdent(b []byte) (Extension, error) {
297 ifi := &InterfaceIdent{
302 case typeInterfaceByName:
303 ifi.Name = strings.Trim(string(b[4:]), string(0))
304 case typeInterfaceByIndex:
306 return nil, errInvalidExtension
308 ifi.Index = int(binary.BigEndian.Uint64(b[4 : 4+8]))
309 case typeInterfaceByAddress:
311 return nil, errInvalidExtension
313 ifi.AFI = int(binary.BigEndian.Uint16(b[4 : 4+2]))
315 if len(b[4+4:]) < l {
316 return nil, errInvalidExtension
318 ifi.Addr = make([]byte, l)
319 copy(ifi.Addr, b[4+4:])