Rebase.
[official-gcc.git] / libgo / go / net / mockicmp_test.go
blobe742365ea0325b35f16513621931f09326b3a1c8
1 // Copyright 2009 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.
5 package net
7 import "errors"
9 const (
10 icmpv4EchoRequest = 8
11 icmpv4EchoReply = 0
12 icmpv6EchoRequest = 128
13 icmpv6EchoReply = 129
16 // icmpMessage represents an ICMP message.
17 type icmpMessage struct {
18 Type int // type
19 Code int // code
20 Checksum int // checksum
21 Body icmpMessageBody // body
24 // icmpMessageBody represents an ICMP message body.
25 type icmpMessageBody interface {
26 Len() int
27 Marshal() ([]byte, error)
30 // Marshal returns the binary enconding of the ICMP echo request or
31 // reply message m.
32 func (m *icmpMessage) Marshal() ([]byte, error) {
33 b := []byte{byte(m.Type), byte(m.Code), 0, 0}
34 if m.Body != nil && m.Body.Len() != 0 {
35 mb, err := m.Body.Marshal()
36 if err != nil {
37 return nil, err
39 b = append(b, mb...)
41 switch m.Type {
42 case icmpv6EchoRequest, icmpv6EchoReply:
43 return b, nil
45 csumcv := len(b) - 1 // checksum coverage
46 s := uint32(0)
47 for i := 0; i < csumcv; i += 2 {
48 s += uint32(b[i+1])<<8 | uint32(b[i])
50 if csumcv&1 == 0 {
51 s += uint32(b[csumcv])
53 s = s>>16 + s&0xffff
54 s = s + s>>16
55 // Place checksum back in header; using ^= avoids the
56 // assumption the checksum bytes are zero.
57 b[2] ^= byte(^s)
58 b[3] ^= byte(^s >> 8)
59 return b, nil
62 // parseICMPMessage parses b as an ICMP message.
63 func parseICMPMessage(b []byte) (*icmpMessage, error) {
64 msglen := len(b)
65 if msglen < 4 {
66 return nil, errors.New("message too short")
68 m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
69 if msglen > 4 {
70 var err error
71 switch m.Type {
72 case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
73 m.Body, err = parseICMPEcho(b[4:])
74 if err != nil {
75 return nil, err
79 return m, nil
82 // imcpEcho represenets an ICMP echo request or reply message body.
83 type icmpEcho struct {
84 ID int // identifier
85 Seq int // sequence number
86 Data []byte // data
89 func (p *icmpEcho) Len() int {
90 if p == nil {
91 return 0
93 return 4 + len(p.Data)
96 // Marshal returns the binary enconding of the ICMP echo request or
97 // reply message body p.
98 func (p *icmpEcho) Marshal() ([]byte, error) {
99 b := make([]byte, 4+len(p.Data))
100 b[0], b[1] = byte(p.ID>>8), byte(p.ID)
101 b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
102 copy(b[4:], p.Data)
103 return b, nil
106 // parseICMPEcho parses b as an ICMP echo request or reply message
107 // body.
108 func parseICMPEcho(b []byte) (*icmpEcho, error) {
109 bodylen := len(b)
110 p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
111 if bodylen > 4 {
112 p.Data = make([]byte, bodylen-4)
113 copy(p.Data, b[4:])
115 return p, nil