Merge "icmp: make Marshal of MessageBody, ParseMessage work correctly on parameter problem message"
diff --git a/icmp/dstunreach.go b/icmp/dstunreach.go
index 8241017..3f843cd 100644
--- a/icmp/dstunreach.go
+++ b/icmp/dstunreach.go
@@ -19,7 +19,7 @@
}
// Marshal implements the Marshal method of MessageBody interface.
-func (p *DstUnreach) Marshal() ([]byte, error) {
+func (p *DstUnreach) Marshal(proto int) ([]byte, error) {
b := make([]byte, 4+len(p.Data))
copy(b[4:], p.Data)
return b, nil
@@ -27,7 +27,7 @@
// parseDstUnreach parses b as an ICMP destination unreachable message
// body.
-func parseDstUnreach(b []byte) (MessageBody, error) {
+func parseDstUnreach(proto int, b []byte) (MessageBody, error) {
bodyLen := len(b)
if bodyLen < 4 {
return nil, errMessageTooShort
diff --git a/icmp/echo.go b/icmp/echo.go
index dfac9cb..6b373fc 100644
--- a/icmp/echo.go
+++ b/icmp/echo.go
@@ -20,7 +20,7 @@
}
// Marshal implements the Marshal method of MessageBody interface.
-func (p *Echo) Marshal() ([]byte, error) {
+func (p *Echo) Marshal(proto int) ([]byte, error) {
b := make([]byte, 4+len(p.Data))
b[0], b[1] = byte(p.ID>>8), byte(p.ID)
b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
@@ -29,7 +29,7 @@
}
// parseEcho parses b as an ICMP echo request or reply message body.
-func parseEcho(b []byte) (MessageBody, error) {
+func parseEcho(proto int, b []byte) (MessageBody, error) {
bodyLen := len(b)
if bodyLen < 4 {
return nil, errMessageTooShort
diff --git a/icmp/message.go b/icmp/message.go
index 3d89108..13398a0 100644
--- a/icmp/message.go
+++ b/icmp/message.go
@@ -63,7 +63,7 @@
b = append(psh, b...)
}
if m.Body != nil && m.Body.Len() != 0 {
- mb, err := m.Body.Marshal()
+ mb, err := m.Body.Marshal(m.Type.Protocol())
if err != nil {
return nil, err
}
@@ -93,7 +93,7 @@
return b[len(psh):], nil
}
-var parseFns = map[Type]func([]byte) (MessageBody, error){
+var parseFns = map[Type]func(int, []byte) (MessageBody, error){
ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
ipv4.ICMPTypeTimeExceeded: parseTimeExceeded,
ipv4.ICMPTypeParameterProblem: parseParamProb,
@@ -127,9 +127,9 @@
return nil, syscall.EINVAL
}
if fn, ok := parseFns[m.Type]; !ok {
- m.Body, err = parseDefaultMessageBody(b[4:])
+ m.Body, err = parseDefaultMessageBody(proto, b[4:])
} else {
- m.Body, err = fn(b[4:])
+ m.Body, err = fn(proto, b[4:])
}
if err != nil {
return nil, err
diff --git a/icmp/messagebody.go b/icmp/messagebody.go
index f653ab6..30f2df8 100644
--- a/icmp/messagebody.go
+++ b/icmp/messagebody.go
@@ -10,7 +10,8 @@
Len() int
// Marshal returns the binary enconding of ICMP message body.
- Marshal() ([]byte, error)
+ // Proto must be either the ICMPv4 or ICMPv6 protocol number.
+ Marshal(proto int) ([]byte, error)
}
// A DefaultMessageBody represents the default message body.
@@ -27,12 +28,12 @@
}
// Marshal implements the Marshal method of MessageBody interface.
-func (p *DefaultMessageBody) Marshal() ([]byte, error) {
+func (p *DefaultMessageBody) Marshal(proto int) ([]byte, error) {
return p.Data, nil
}
// parseDefaultMessageBody parses b as an ICMP message body.
-func parseDefaultMessageBody(b []byte) (MessageBody, error) {
+func parseDefaultMessageBody(proto int, b []byte) (MessageBody, error) {
p := &DefaultMessageBody{Data: make([]byte, len(b))}
copy(p.Data, b)
return p, nil
diff --git a/icmp/packettoobig.go b/icmp/packettoobig.go
index fc10192..0628e38 100644
--- a/icmp/packettoobig.go
+++ b/icmp/packettoobig.go
@@ -19,7 +19,7 @@
}
// Marshal implements the Marshal method of MessageBody interface.
-func (p *PacketTooBig) Marshal() ([]byte, error) {
+func (p *PacketTooBig) Marshal(proto int) ([]byte, error) {
b := make([]byte, 4+len(p.Data))
b[0], b[1], b[2], b[3] = byte(p.MTU>>24), byte(p.MTU>>16), byte(p.MTU>>8), byte(p.MTU)
copy(b[4:], p.Data)
@@ -27,7 +27,7 @@
}
// parsePacketTooBig parses b as an ICMP packet too big message body.
-func parsePacketTooBig(b []byte) (MessageBody, error) {
+func parsePacketTooBig(proto int, b []byte) (MessageBody, error) {
bodyLen := len(b)
if bodyLen < 4 {
return nil, errMessageTooShort
diff --git a/icmp/paramprob.go b/icmp/paramprob.go
index be32ce0..ecf80ec 100644
--- a/icmp/paramprob.go
+++ b/icmp/paramprob.go
@@ -4,6 +4,8 @@
package icmp
+import "golang.org/x/net/internal/iana"
+
// A ParamProb represents an ICMP parameter problem message body.
type ParamProb struct {
Pointer uintptr // offset within the data where the error was detected
@@ -19,20 +21,31 @@
}
// Marshal implements the Marshal method of MessageBody interface.
-func (p *ParamProb) Marshal() ([]byte, error) {
+func (p *ParamProb) Marshal(proto int) ([]byte, error) {
b := make([]byte, 4+len(p.Data))
- b[0], b[1], b[2], b[3] = byte(p.Pointer>>24), byte(p.Pointer>>16), byte(p.Pointer>>8), byte(p.Pointer)
+ switch proto {
+ case iana.ProtocolICMP:
+ b[0] = byte(p.Pointer)
+ case iana.ProtocolIPv6ICMP:
+ b[0], b[1], b[2], b[3] = byte(p.Pointer>>24), byte(p.Pointer>>16), byte(p.Pointer>>8), byte(p.Pointer)
+ }
copy(b[4:], p.Data)
return b, nil
}
// parseParamProb parses b as an ICMP parameter problem message body.
-func parseParamProb(b []byte) (MessageBody, error) {
+func parseParamProb(proto int, b []byte) (MessageBody, error) {
bodyLen := len(b)
if bodyLen < 4 {
return nil, errMessageTooShort
}
- p := &ParamProb{Pointer: uintptr(b[0])<<24 | uintptr(b[1])<<16 | uintptr(b[2])<<8 | uintptr(b[3])}
+ p := &ParamProb{}
+ switch proto {
+ case iana.ProtocolICMP:
+ p.Pointer = uintptr(b[0])
+ case iana.ProtocolIPv6ICMP:
+ p.Pointer = uintptr(b[0])<<24 | uintptr(b[1])<<16 | uintptr(b[2])<<8 | uintptr(b[3])
+ }
if bodyLen > 4 {
p.Data = make([]byte, bodyLen-4)
copy(p.Data, b[4:])
diff --git a/icmp/timeexceeded.go b/icmp/timeexceeded.go
index 993a150..0f0bb91 100644
--- a/icmp/timeexceeded.go
+++ b/icmp/timeexceeded.go
@@ -18,14 +18,14 @@
}
// Marshal implements the Marshal method of MessageBody interface.
-func (p *TimeExceeded) Marshal() ([]byte, error) {
+func (p *TimeExceeded) Marshal(proto int) ([]byte, error) {
b := make([]byte, 4+len(p.Data))
copy(b[4:], p.Data)
return b, nil
}
// parseTimeExceeded parses b as an ICMP time exceeded message body.
-func parseTimeExceeded(b []byte) (MessageBody, error) {
+func parseTimeExceeded(proto int, b []byte) (MessageBody, error) {
bodyLen := len(b)
if bodyLen < 4 {
return nil, errMessageTooShort