|
@@ -7,8 +7,22 @@ package ipv6_test
|
|
|
import (
|
|
import (
|
|
|
"code.google.com/p/go.net/ipv6"
|
|
"code.google.com/p/go.net/ipv6"
|
|
|
"errors"
|
|
"errors"
|
|
|
|
|
+ "net"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+const (
|
|
|
|
|
+ ipv6PseudoHeaderLen = 2*net.IPv6len + 8
|
|
|
|
|
+ ianaProtocolIPv6ICMP = 58
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+func ipv6PseudoHeader(src, dst net.IP, nextHeader int) []byte {
|
|
|
|
|
+ b := make([]byte, ipv6PseudoHeaderLen)
|
|
|
|
|
+ copy(b[:net.IPv6len], src)
|
|
|
|
|
+ copy(b[net.IPv6len:], dst)
|
|
|
|
|
+ b[len(b)-1] = byte(nextHeader)
|
|
|
|
|
+ return b
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// icmpMessage represents an ICMP message.
|
|
// icmpMessage represents an ICMP message.
|
|
|
type icmpMessage struct {
|
|
type icmpMessage struct {
|
|
|
Type ipv6.ICMPType // type
|
|
Type ipv6.ICMPType // type
|
|
@@ -25,8 +39,11 @@ type icmpMessageBody interface {
|
|
|
|
|
|
|
|
// Marshal returns the binary enconding of the ICMP echo request or
|
|
// Marshal returns the binary enconding of the ICMP echo request or
|
|
|
// reply message m.
|
|
// reply message m.
|
|
|
-func (m *icmpMessage) Marshal() ([]byte, error) {
|
|
|
|
|
|
|
+func (m *icmpMessage) Marshal(psh []byte) ([]byte, error) {
|
|
|
b := []byte{byte(m.Type), byte(m.Code), 0, 0}
|
|
b := []byte{byte(m.Type), byte(m.Code), 0, 0}
|
|
|
|
|
+ if psh != nil {
|
|
|
|
|
+ b = append(psh, b...)
|
|
|
|
|
+ }
|
|
|
if m.Body != nil && m.Body.Len() != 0 {
|
|
if m.Body != nil && m.Body.Len() != 0 {
|
|
|
mb, err := m.Body.Marshal()
|
|
mb, err := m.Body.Marshal()
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -34,10 +51,11 @@ func (m *icmpMessage) Marshal() ([]byte, error) {
|
|
|
}
|
|
}
|
|
|
b = append(b, mb...)
|
|
b = append(b, mb...)
|
|
|
}
|
|
}
|
|
|
- switch m.Type {
|
|
|
|
|
- case ipv6.ICMPTypeEchoRequest, ipv6.ICMPTypeEchoReply:
|
|
|
|
|
|
|
+ if psh == nil {
|
|
|
return b, nil
|
|
return b, nil
|
|
|
}
|
|
}
|
|
|
|
|
+ off, l := 2*net.IPv6len, len(b)-len(psh)
|
|
|
|
|
+ b[off], b[off+1], b[off+2], b[off+3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
|
|
csumcv := len(b) - 1 // checksum coverage
|
|
csumcv := len(b) - 1 // checksum coverage
|
|
|
s := uint32(0)
|
|
s := uint32(0)
|
|
|
for i := 0; i < csumcv; i += 2 {
|
|
for i := 0; i < csumcv; i += 2 {
|
|
@@ -50,9 +68,9 @@ func (m *icmpMessage) Marshal() ([]byte, error) {
|
|
|
s = s + s>>16
|
|
s = s + s>>16
|
|
|
// Place checksum back in header; using ^= avoids the
|
|
// Place checksum back in header; using ^= avoids the
|
|
|
// assumption the checksum bytes are zero.
|
|
// assumption the checksum bytes are zero.
|
|
|
- b[2] ^= byte(^s)
|
|
|
|
|
- b[3] ^= byte(^s >> 8)
|
|
|
|
|
- return b, nil
|
|
|
|
|
|
|
+ b[len(psh)+2] ^= byte(^s)
|
|
|
|
|
+ b[len(psh)+3] ^= byte(^s >> 8)
|
|
|
|
|
+ return b[len(psh):], nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// parseICMPMessage parses b as an ICMP message.
|
|
// parseICMPMessage parses b as an ICMP message.
|