1// Copyright 2014 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
5package icmp
6
7import (
8	"golang.org/x/net/internal/iana"
9	"golang.org/x/net/ipv4"
10	"golang.org/x/net/ipv6"
11)
12
13// A DstUnreach represents an ICMP destination unreachable message
14// body.
15type DstUnreach struct {
16	Data       []byte      // data, known as original datagram field
17	Extensions []Extension // extensions
18}
19
20// Len implements the Len method of MessageBody interface.
21func (p *DstUnreach) Len(proto int) int {
22	if p == nil {
23		return 0
24	}
25	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
26	return l
27}
28
29// Marshal implements the Marshal method of MessageBody interface.
30func (p *DstUnreach) Marshal(proto int) ([]byte, error) {
31	var typ Type
32	switch proto {
33	case iana.ProtocolICMP:
34		typ = ipv4.ICMPTypeDestinationUnreachable
35	case iana.ProtocolIPv6ICMP:
36		typ = ipv6.ICMPTypeDestinationUnreachable
37	default:
38		return nil, errInvalidProtocol
39	}
40	if !validExtensions(typ, p.Extensions) {
41		return nil, errInvalidExtension
42	}
43	return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
44}
45
46// parseDstUnreach parses b as an ICMP destination unreachable message
47// body.
48func parseDstUnreach(proto int, typ Type, b []byte) (MessageBody, error) {
49	if len(b) < 4 {
50		return nil, errMessageTooShort
51	}
52	p := &DstUnreach{}
53	var err error
54	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
55	if err != nil {
56		return nil, err
57	}
58	return p, nil
59}
60