paramprob.go 1.9 KB

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