1
// Copyright 2013 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.
8
"code.google.com/p/go.net/ipv6"
12
// icmpMessage represents an ICMP message.
13
type icmpMessage struct {
14
Type ipv6.ICMPType // type
16
Checksum int // checksum
17
Body icmpMessageBody // body
20
// icmpMessageBody represents an ICMP message body.
21
type icmpMessageBody interface {
23
Marshal() ([]byte, error)
26
// Marshal returns the binary enconding of the ICMP echo request or
28
func (m *icmpMessage) Marshal() ([]byte, error) {
29
b := []byte{byte(m.Type), byte(m.Code), 0, 0}
30
if m.Body != nil && m.Body.Len() != 0 {
31
mb, err := m.Body.Marshal()
38
case ipv6.ICMPTypeEchoRequest, ipv6.ICMPTypeEchoReply:
41
csumcv := len(b) - 1 // checksum coverage
43
for i := 0; i < csumcv; i += 2 {
44
s += uint32(b[i+1])<<8 | uint32(b[i])
47
s += uint32(b[csumcv])
51
// Place checksum back in header; using ^= avoids the
52
// assumption the checksum bytes are zero.
53
b[2] ^= byte(^s & 0xff)
58
// parseICMPMessage parses b as an ICMP message.
59
func parseICMPMessage(b []byte) (*icmpMessage, error) {
62
return nil, errors.New("message too short")
64
m := &icmpMessage{Type: ipv6.ICMPType(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
68
case ipv6.ICMPTypeEchoRequest, ipv6.ICMPTypeEchoReply:
69
m.Body, err = parseICMPEcho(b[4:])
78
// imcpEcho represenets an ICMP echo request or reply message body.
79
type icmpEcho struct {
81
Seq int // sequence number
85
func (p *icmpEcho) Len() int {
89
return 4 + len(p.Data)
92
// Marshal returns the binary enconding of the ICMP echo request or
93
// reply message body p.
94
func (p *icmpEcho) Marshal() ([]byte, error) {
95
b := make([]byte, 4+len(p.Data))
96
b[0], b[1] = byte(p.ID>>8), byte(p.ID&0xff)
97
b[2], b[3] = byte(p.Seq>>8), byte(p.Seq&0xff)
102
// parseICMPEcho parses b as an ICMP echo request or reply message
104
func parseICMPEcho(b []byte) (*icmpEcho, error) {
106
p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
108
p.Data = make([]byte, bodylen-4)