12
12
var testExternal = flag.Bool("external", true, "allow use of external networks during long test")
17
icmpv6EchoRequest = 128
21
// icmpMessage represents an ICMP message.
22
type icmpMessage struct {
25
Checksum int // checksum
26
Body icmpMessageBody // body
29
// icmpMessageBody represents an ICMP message body.
30
type icmpMessageBody interface {
32
Marshal() ([]byte, error)
35
// Marshal returns the binary enconding of the ICMP echo request or
37
func (m *icmpMessage) Marshal() ([]byte, error) {
38
b := []byte{byte(m.Type), byte(m.Code), 0, 0}
39
if m.Body != nil && m.Body.Len() != 0 {
40
mb, err := m.Body.Marshal()
47
case icmpv6EchoRequest, icmpv6EchoReply:
50
csumcv := len(b) - 1 // checksum coverage
14
func newICMPEchoRequest(id, seqnum, msglen int, filler []byte) []byte {
15
b := newICMPInfoMessage(id, seqnum, msglen, filler)
17
// calculate ICMP checksum
52
for i := 0; i < csumcv; i += 2 {
20
for i := 0; i < cklen-1; i += 2 {
53
21
s += uint32(b[i+1])<<8 | uint32(b[i])
56
s += uint32(b[csumcv])
24
s += uint32(b[cklen-1])
60
// Place checksum back in header; using ^= avoids the
61
// assumption the checksum bytes are zero.
26
s = (s >> 16) + (s & 0xffff)
28
// place checksum back in header; using ^= avoids the
29
// assumption the checksum bytes are zero
62
30
b[2] ^= byte(^s & 0xff)
63
31
b[3] ^= byte(^s >> 8)
67
// parseICMPMessage parses b as an ICMP message.
68
func parseICMPMessage(b []byte) (*icmpMessage, error) {
71
return nil, errors.New("message too short")
73
m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
77
case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
78
m.Body, err = parseICMPEcho(b[4:])
87
// imcpEcho represenets an ICMP echo request or reply message body.
88
type icmpEcho struct {
90
Seq int // sequence number
94
func (p *icmpEcho) Len() int {
98
return 4 + len(p.Data)
101
// Marshal returns the binary enconding of the ICMP echo request or
102
// reply message body p.
103
func (p *icmpEcho) Marshal() ([]byte, error) {
104
b := make([]byte, 4+len(p.Data))
105
b[0], b[1] = byte(p.ID>>8), byte(p.ID&0xff)
106
b[2], b[3] = byte(p.Seq>>8), byte(p.Seq&0xff)
111
// parseICMPEcho parses b as an ICMP echo request or reply message
113
func parseICMPEcho(b []byte) (*icmpEcho, error) {
115
p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
117
p.Data = make([]byte, bodylen-4)
35
func newICMPInfoMessage(id, seqnum, msglen int, filler []byte) []byte {
36
b := make([]byte, msglen)
37
copy(b[8:], bytes.Repeat(filler, (msglen-8)/len(filler)+1))
42
b[4] = byte(id >> 8) // identifier
43
b[5] = byte(id & 0xff) // identifier
44
b[6] = byte(seqnum >> 8) // sequence number
45
b[7] = byte(seqnum & 0xff) // sequence number