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	"encoding/binary"
9
10	"golang.org/x/net/internal/iana"
11	"golang.org/x/net/ipv4"
12)
13
14// A ParamProb represents an ICMP parameter problem message body.
15type ParamProb struct {
16	Pointer    uintptr     // offset within the data where the error was detected
17	Data       []byte      // data, known as original datagram field
18	Extensions []Extension // extensions
19}
20
21// Len implements the Len method of MessageBody interface.
22func (p *ParamProb) Len(proto int) int {
23	if p == nil {
24		return 0
25	}
26	l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
27	return l
28}
29
30// Marshal implements the Marshal method of MessageBody interface.
31func (p *ParamProb) Marshal(proto int) ([]byte, error) {
32	switch proto {
33	case iana.ProtocolICMP:
34		if !validExtensions(ipv4.ICMPTypeParameterProblem, p.Extensions) {
35			return nil, errInvalidExtension
36		}
37		b, err := marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
38		if err != nil {
39			return nil, err
40		}
41		b[0] = byte(p.Pointer)
42		return b, nil
43	case iana.ProtocolIPv6ICMP:
44		b := make([]byte, p.Len(proto))
45		binary.BigEndian.PutUint32(b[:4], uint32(p.Pointer))
46		copy(b[4:], p.Data)
47		return b, nil
48	default:
49		return nil, errInvalidProtocol
50	}
51}
52
53// parseParamProb parses b as an ICMP parameter problem message body.
54func parseParamProb(proto int, typ Type, b []byte) (MessageBody, error) {
55	if len(b) < 4 {
56		return nil, errMessageTooShort
57	}
58	p := &ParamProb{}
59	if proto == iana.ProtocolIPv6ICMP {
60		p.Pointer = uintptr(binary.BigEndian.Uint32(b[:4]))
61		p.Data = make([]byte, len(b)-4)
62		copy(p.Data, b[4:])
63		return p, nil
64	}
65	p.Pointer = uintptr(b[0])
66	var err error
67	p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
68	if err != nil {
69		return nil, err
70	}
71	return p, nil
72}
73