Jelajahi Sumber

Merge "icmp: make Marshal of MessageBody, ParseMessage work correctly on parameter problem message"

Mikio Hara 11 tahun lalu
induk
melakukan
972f0c5fbe
7 mengubah file dengan 33 tambahan dan 19 penghapusan
  1. 2 2
      icmp/dstunreach.go
  2. 2 2
      icmp/echo.go
  3. 4 4
      icmp/message.go
  4. 4 3
      icmp/messagebody.go
  5. 2 2
      icmp/packettoobig.go
  6. 17 4
      icmp/paramprob.go
  7. 2 2
      icmp/timeexceeded.go

+ 2 - 2
icmp/dstunreach.go

@@ -19,7 +19,7 @@ func (p *DstUnreach) Len() int {
 }
 
 // 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 @@ func (p *DstUnreach) Marshal() ([]byte, error) {
 
 // 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

+ 2 - 2
icmp/echo.go

@@ -20,7 +20,7 @@ func (p *Echo) Len() int {
 }
 
 // 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 @@ func (p *Echo) Marshal() ([]byte, error) {
 }
 
 // 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

+ 4 - 4
icmp/message.go

@@ -63,7 +63,7 @@ func (m *Message) Marshal(psh []byte) ([]byte, error) {
 		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 @@ func (m *Message) Marshal(psh []byte) ([]byte, error) {
 	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 @@ func ParseMessage(proto int, b []byte) (*Message, error) {
 		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

+ 4 - 3
icmp/messagebody.go

@@ -10,7 +10,8 @@ type MessageBody interface {
 	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 @@ func (p *DefaultMessageBody) Len() int {
 }
 
 // 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

+ 2 - 2
icmp/packettoobig.go

@@ -19,7 +19,7 @@ func (p *PacketTooBig) Len() int {
 }
 
 // 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 @@ func (p *PacketTooBig) Marshal() ([]byte, error) {
 }
 
 // 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

+ 17 - 4
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 @@ func (p *ParamProb) Len() int {
 }
 
 // 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:])

+ 2 - 2
icmp/timeexceeded.go

@@ -18,14 +18,14 @@ func (p *TimeExceeded) Len() int {
 }
 
 // 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