packet_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package packet
  2. import (
  3. "bytes"
  4. "net/netip"
  5. "testing"
  6. "github.com/google/gopacket"
  7. "github.com/google/gopacket/layers"
  8. "github.com/stretchr/testify/require"
  9. "golang.org/x/net/icmp"
  10. "golang.org/x/net/ipv4"
  11. "golang.org/x/net/ipv6"
  12. )
  13. func TestNewICMPTTLExceedPacket(t *testing.T) {
  14. ipv4Packet := IP{
  15. Src: netip.MustParseAddr("192.168.1.1"),
  16. Dst: netip.MustParseAddr("10.0.0.1"),
  17. Protocol: layers.IPProtocolICMPv4,
  18. TTL: 0,
  19. }
  20. icmpV4Packet := ICMP{
  21. IP: &ipv4Packet,
  22. Message: &icmp.Message{
  23. Type: ipv4.ICMPTypeEcho,
  24. Code: 0,
  25. Body: &icmp.Echo{
  26. ID: 25821,
  27. Seq: 58129,
  28. Data: []byte("test ttl=0"),
  29. },
  30. },
  31. }
  32. assertTTLExceedPacket(t, &icmpV4Packet)
  33. icmpV4Packet.Body = &icmp.Echo{
  34. ID: 3487,
  35. Seq: 19183,
  36. Data: make([]byte, ipv4MinMTU),
  37. }
  38. assertTTLExceedPacket(t, &icmpV4Packet)
  39. ipv6Packet := IP{
  40. Src: netip.MustParseAddr("fd51:2391:523:f4ee::1"),
  41. Dst: netip.MustParseAddr("fd51:2391:697:f4ee::2"),
  42. Protocol: layers.IPProtocolICMPv6,
  43. TTL: 0,
  44. }
  45. icmpV6Packet := ICMP{
  46. IP: &ipv6Packet,
  47. Message: &icmp.Message{
  48. Type: ipv6.ICMPTypeEchoRequest,
  49. Code: 0,
  50. Body: &icmp.Echo{
  51. ID: 25821,
  52. Seq: 58129,
  53. Data: []byte("test ttl=0"),
  54. },
  55. },
  56. }
  57. assertTTLExceedPacket(t, &icmpV6Packet)
  58. icmpV6Packet.Body = &icmp.Echo{
  59. ID: 1497,
  60. Seq: 39284,
  61. Data: make([]byte, ipv6MinMTU),
  62. }
  63. assertTTLExceedPacket(t, &icmpV6Packet)
  64. }
  65. func assertTTLExceedPacket(t *testing.T, pk *ICMP) {
  66. encoder := NewEncoder()
  67. rawPacket, err := encoder.Encode(pk)
  68. require.NoError(t, err)
  69. minMTU := ipv4MinMTU
  70. headerLen := ipv4MinHeaderLen
  71. routerIP := netip.MustParseAddr("172.16.0.3")
  72. if pk.Dst.Is6() {
  73. minMTU = ipv6MinMTU
  74. headerLen = ipv6HeaderLen
  75. routerIP = netip.MustParseAddr("fd51:2391:697:f4ee::3")
  76. }
  77. ttlExceedPacket := NewICMPTTLExceedPacket(pk.IP, rawPacket, routerIP)
  78. require.Equal(t, routerIP, ttlExceedPacket.Src)
  79. require.Equal(t, pk.Src, ttlExceedPacket.Dst)
  80. require.Equal(t, pk.Protocol, ttlExceedPacket.Protocol)
  81. require.Equal(t, DefaultTTL, ttlExceedPacket.TTL)
  82. timeExceed, ok := ttlExceedPacket.Body.(*icmp.TimeExceeded)
  83. require.True(t, ok)
  84. if len(rawPacket.Data) > minMTU {
  85. require.True(t, bytes.Equal(timeExceed.Data, rawPacket.Data[:minMTU-headerLen-icmpHeaderLen]))
  86. } else {
  87. require.True(t, bytes.Equal(timeExceed.Data, rawPacket.Data))
  88. }
  89. rawTTLExceedPacket, err := encoder.Encode(ttlExceedPacket)
  90. require.NoError(t, err)
  91. if len(rawPacket.Data) > minMTU {
  92. require.Len(t, rawTTLExceedPacket.Data, minMTU)
  93. } else {
  94. require.Len(t, rawTTLExceedPacket.Data, headerLen+icmpHeaderLen+len(rawPacket.Data))
  95. require.True(t, bytes.Equal(rawPacket.Data, rawTTLExceedPacket.Data[headerLen+icmpHeaderLen:]))
  96. }
  97. decoder := NewICMPDecoder()
  98. decodedPacket, err := decoder.Decode(rawTTLExceedPacket)
  99. require.NoError(t, err)
  100. assertICMPChecksum(t, decodedPacket)
  101. }
  102. func assertICMPChecksum(t *testing.T, icmpPacket *ICMP) {
  103. buf := gopacket.NewSerializeBuffer()
  104. if icmpPacket.Protocol == layers.IPProtocolICMPv4 {
  105. icmpv4 := layers.ICMPv4{
  106. TypeCode: layers.CreateICMPv4TypeCode(uint8(icmpPacket.Type.(ipv4.ICMPType)), uint8(icmpPacket.Code)),
  107. }
  108. switch body := icmpPacket.Body.(type) {
  109. case *icmp.Echo:
  110. icmpv4.Id = uint16(body.ID)
  111. icmpv4.Seq = uint16(body.Seq)
  112. payload := gopacket.Payload(body.Data)
  113. require.NoError(t, payload.SerializeTo(buf, serializeOpts))
  114. default:
  115. require.NoError(t, serializeICMPAsPayload(icmpPacket.Message, buf))
  116. }
  117. // SerializeTo sets the checksum in icmpv4
  118. require.NoError(t, icmpv4.SerializeTo(buf, serializeOpts))
  119. require.Equal(t, icmpv4.Checksum, uint16(icmpPacket.Checksum))
  120. } else {
  121. switch body := icmpPacket.Body.(type) {
  122. case *icmp.Echo:
  123. payload := gopacket.Payload(body.Data)
  124. require.NoError(t, payload.SerializeTo(buf, serializeOpts))
  125. echo := layers.ICMPv6Echo{
  126. Identifier: uint16(body.ID),
  127. SeqNumber: uint16(body.Seq),
  128. }
  129. require.NoError(t, echo.SerializeTo(buf, serializeOpts))
  130. default:
  131. require.NoError(t, serializeICMPAsPayload(icmpPacket.Message, buf))
  132. }
  133. icmpv6 := layers.ICMPv6{
  134. TypeCode: layers.CreateICMPv6TypeCode(uint8(icmpPacket.Type.(ipv6.ICMPType)), uint8(icmpPacket.Code)),
  135. }
  136. ipLayer := layers.IPv6{
  137. Version: 6,
  138. SrcIP: icmpPacket.Src.AsSlice(),
  139. DstIP: icmpPacket.Dst.AsSlice(),
  140. NextHeader: icmpPacket.Protocol,
  141. HopLimit: icmpPacket.TTL,
  142. }
  143. require.NoError(t, icmpv6.SetNetworkLayerForChecksum(&ipLayer))
  144. // SerializeTo sets the checksum in icmpv4
  145. require.NoError(t, icmpv6.SerializeTo(buf, serializeOpts))
  146. require.Equal(t, icmpv6.Checksum, uint16(icmpPacket.Checksum))
  147. }
  148. }
  149. func serializeICMPAsPayload(message *icmp.Message, buf gopacket.SerializeBuffer) error {
  150. serializedBody, err := message.Body.Marshal(message.Type.Protocol())
  151. if err != nil {
  152. return err
  153. }
  154. payload := gopacket.Payload(serializedBody)
  155. return payload.SerializeTo(buf, serializeOpts)
  156. }
  157. func TestChecksum(t *testing.T) {
  158. data := []byte{0x63, 0x2c, 0x49, 0xd6, 0x00, 0x0d, 0xc1, 0xda}
  159. pk := ICMP{
  160. IP: &IP{
  161. Src: netip.MustParseAddr("2606:4700:110:89c1:c63a:861:e08c:b049"),
  162. Dst: netip.MustParseAddr("fde8:b693:d420:109b::2"),
  163. Protocol: layers.IPProtocolICMPv6,
  164. TTL: 3,
  165. },
  166. Message: &icmp.Message{
  167. Type: ipv6.ICMPTypeEchoRequest,
  168. Code: 0,
  169. Body: &icmp.Echo{
  170. ID: 0x20a7,
  171. Seq: 8,
  172. Data: data,
  173. },
  174. },
  175. }
  176. encoder := NewEncoder()
  177. encoded, err := encoder.Encode(&pk)
  178. require.NoError(t, err)
  179. decoder := NewICMPDecoder()
  180. decoded, err := decoder.Decode(encoded)
  181. require.Equal(t, 0xff96, decoded.Checksum)
  182. }