@@ -239,3 +239,106 @@ func Test_CreateRejectPacketIPv6_ExtensionHeaders(t *testing.T) {
239239 tcpOut := rejectPacket [ipv6 .HeaderLen :]
240240 assert .Equal (t , byte (0b00000100 ), tcpOut [13 ]) // RST only
241241}
242+
243+ func TestCreateICMPEchoResponse_IPv4 (t * testing.T ) {
244+ // Build a simple IPv4 ICMP Echo Request
245+ packet := make ([]byte , 28 )
246+ packet [0 ] = 0x45 // version 4, IHL 5
247+ binary .BigEndian .PutUint16 (packet [2 :], uint16 (28 )) // total length
248+ packet [8 ] = 64 // TTL
249+ packet [9 ] = 1 // protocol ICMP
250+ copy (packet [12 :16 ], net .IPv4 (10 , 0 , 0 , 1 ).To4 ()) // src
251+ copy (packet [16 :20 ], net .IPv4 (10 , 0 , 0 , 2 ).To4 ()) // dst
252+ packet [20 ] = 8 // ICMP Echo Request
253+
254+ out := make ([]byte , len (packet ))
255+ result := CreateICMPEchoResponse (packet , out )
256+ assert .NotNil (t , result )
257+ assert .Equal (t , byte (0x45 ), result [0 ])
258+ // src/dst swapped
259+ assert .Equal (t , net .IPv4 (10 , 0 , 0 , 2 ).To4 (), net .IP (result [12 :16 ]))
260+ assert .Equal (t , net .IPv4 (10 , 0 , 0 , 1 ).To4 (), net .IP (result [16 :20 ]))
261+ // ICMP Echo Reply
262+ assert .Equal (t , byte (0 ), result [20 ])
263+ }
264+
265+ func TestCreateICMPEchoResponse_IPv6 (t * testing.T ) {
266+ src := net .ParseIP ("fd00::1" ).To16 ()
267+ dst := net .ParseIP ("fd00::2" ).To16 ()
268+
269+ // Build an IPv6 ICMPv6 Echo Request packet
270+ // IPv6 header (40 bytes) + ICMPv6 (8 bytes)
271+ packet := make ([]byte , 48 )
272+ packet [0 ] = 0x60 // version 6
273+ payloadLen := uint16 (8 ) // ICMPv6 header only
274+ binary .BigEndian .PutUint16 (packet [4 :], payloadLen )
275+ packet [6 ] = 58 // Next Header: ICMPv6
276+ packet [7 ] = 64 // Hop Limit
277+ copy (packet [8 :24 ], src ) // src address
278+ copy (packet [24 :40 ], dst ) // dst address
279+
280+ // ICMPv6 Echo Request
281+ icmp := packet [40 :]
282+ icmp [0 ] = 128 // type: Echo Request
283+ icmp [1 ] = 0 // code
284+ binary .BigEndian .PutUint16 (icmp [4 :], 1 ) // identifier
285+ binary .BigEndian .PutUint16 (icmp [6 :], 1 ) // sequence number
286+
287+ // Compute correct checksum for the request
288+ csum := ipv6PseudoheaderChecksum (src , dst , 58 , uint32 (payloadLen ))
289+ binary .BigEndian .PutUint16 (icmp [2 :], tcpipChecksum (icmp , csum ))
290+
291+ out := make ([]byte , len (packet ))
292+ result := CreateICMPEchoResponse (packet , out )
293+ assert .NotNil (t , result )
294+
295+ // Version should still be 6
296+ assert .Equal (t , byte (6 ), result [0 ]>> 4 )
297+ // src/dst swapped
298+ assert .Equal (t , dst , net .IP (result [8 :24 ]))
299+ assert .Equal (t , src , net .IP (result [24 :40 ]))
300+ // ICMPv6 Echo Reply type
301+ assert .Equal (t , byte (129 ), result [40 ])
302+
303+ // Verify checksum is valid (tcpipChecksum returns 0 when data+checksum is correct)
304+ respIcmp := result [40 :]
305+ verifyCsum := ipv6PseudoheaderChecksum (result [8 :24 ], result [24 :40 ], 58 , uint32 (payloadLen ))
306+ assert .Equal (t , uint16 (0 ), tcpipChecksum (respIcmp , verifyCsum ))
307+ }
308+
309+ func TestCreateICMPEchoResponse_IPv6_NotEchoRequest (t * testing.T ) {
310+ src := net .ParseIP ("fd00::1" ).To16 ()
311+ dst := net .ParseIP ("fd00::2" ).To16 ()
312+
313+ packet := make ([]byte , 48 )
314+ packet [0 ] = 0x60
315+ binary .BigEndian .PutUint16 (packet [4 :], 8 )
316+ packet [6 ] = 58
317+ packet [7 ] = 64
318+ copy (packet [8 :24 ], src )
319+ copy (packet [24 :40 ], dst )
320+
321+ // ICMPv6 type 1 (Destination Unreachable) - not Echo Request
322+ packet [40 ] = 1
323+
324+ out := make ([]byte , len (packet ))
325+ result := CreateICMPEchoResponse (packet , out )
326+ assert .Nil (t , result )
327+ }
328+
329+ func TestCreateICMPEchoResponse_IPv6_NotICMPv6 (t * testing.T ) {
330+ src := net .ParseIP ("fd00::1" ).To16 ()
331+ dst := net .ParseIP ("fd00::2" ).To16 ()
332+
333+ packet := make ([]byte , 48 )
334+ packet [0 ] = 0x60
335+ binary .BigEndian .PutUint16 (packet [4 :], 8 )
336+ packet [6 ] = 6 // TCP, not ICMPv6
337+ packet [7 ] = 64
338+ copy (packet [8 :24 ], src )
339+ copy (packet [24 :40 ], dst )
340+
341+ out := make ([]byte , len (packet ))
342+ result := CreateICMPEchoResponse (packet , out )
343+ assert .Nil (t , result )
344+ }
0 commit comments