HedongGao opened a new pull request, #17658:
URL: https://github.com/apache/nuttx/pull/17658

   ## Summary
   
   According to RFC 792 page 4, do the icmp checksum when recieve icmp packet 
if CONFIG_NET_ICMP_CHECKSUMS is set.
   
   ## Impact
   
   Before processing the message, the icmp stack first checks the validity of 
the checksum. And discard the icmp message that failed verification.
   
   ## Testing
   
   Turn on the compilation option of NET-ICPCHECK SUMS and enable the icmp 
checksum function.
   Set up a SIM environment and construct an ICMP request message with checksum 
error on the host side, and compare the performance before and after 
modification.
   Before the problem was fixed, the correctness of the physical checksum could 
result in an ICMP reply message, but after the fix, no checksum error message 
would be replied. The contracting code is as follows:
   
   `import socket
   import struct
   import binascii
   
   # -------------------------- Configuration Parameters 
--------------------------
   # Source/Destination MAC (convert string to bytes, colon-separated)
   SRC_MAC = "fa:b1:d9:6d:a0:d3"
   DST_MAC = "42:e1:c4:3f:48:dd"
   # Source/Destination IP
   SRC_IP = "10.0.1.1"
   DST_IP = "10.0.1.2"
   # Network interface name (modify according to actual environment, e.g., 
eth0, ens33)
   INTERFACE = "eth0"
   
   # -------------------------- Utility Functions --------------------------
   def mac_to_bytes(mac_str):
       """Convert MAC address string to bytes (e.g., fa:b1:d9:6d:a0:d3 -> 
b'\xfa\xb1\xd9\x6d\xa0\xd3')"""
       return binascii.unhexlify(mac_str.replace(":", ""))
   
   def ip_to_bytes(ip_str):
       """Convert IP address string to bytes (e.g., 10.0.1.1 -> 
b'\n\x00\x01\x01')"""
       return socket.inet_aton(ip_str)
   
   def calculate_checksum(data):
       """Calculate standard checksum (RFC 1071)"""
       sum_val = 0
       # Sum by 16-bit chunks
       for i in range(0, len(data), 2):
           if i + 1 < len(data):
               chunk = (data[i] << 8) + data[i+1]
           else:
               chunk = data[i] << 8  # Pad 0 for odd length
           sum_val += chunk
           sum_val = (sum_val & 0xffff) + (sum_val >> 16)  # Handle carry
       checksum = ~sum_val & 0xffff  # Invert and keep 16 bits
       return checksum
   
   # -------------------------- Packet Construction --------------------------
   # 1. Ethernet Frame Header (14 bytes)
   # Format: Destination MAC(6) + Source MAC(6) + Type(2, 0x0800 for IP)
   eth_header = struct.pack(
       "!6s6sH",
       mac_to_bytes(DST_MAC),
       mac_to_bytes(SRC_MAC),
       0x0800  # ETH_P_IP
   )
   
   # 2. IP Header (20 bytes, no options)
   ip_version = 4  # IPV4
   ip_ihl = 5      # Internet Header Length (5*4=20 bytes)
   ip_tos = 0      # Type of Service
   ip_total_len = 20 + 8  # IP header(20) + ICMP(8)
   ip_id = 12345   # Identification
   ip_flags = 0    # Flags
   ip_frag_off = 0 # Fragment Offset
   ip_ttl = 64     # Time to Live
   ip_proto = 1    # Protocol (1=ICMP)
   ip_checksum = 0 # Fill 0 first, calculate later
   ip_src = ip_to_bytes(SRC_IP)
   ip_dst = ip_to_bytes(DST_IP)
   
   # Assemble IP header (fill 0 for checksum first)
   ip_header = struct.pack(
       "!BBHHHBBH4s4s",
       (ip_version << 4) + ip_ihl,  # Version + IHL
       ip_tos,
       ip_total_len,
       ip_id,
       (ip_flags << 13) + ip_frag_off,  # Flags + Fragment Offset
       ip_ttl,
       ip_proto,
       ip_checksum,
       ip_src,
       ip_dst
   )
   
   # Calculate IP header checksum and reassemble
   ip_checksum = calculate_checksum(ip_header)
   ip_header = struct.pack(
       "!BBHHHBBH4s4s",
       (ip_version << 4) + ip_ihl,
       ip_tos,
       ip_total_len,
       ip_id,
       (ip_flags << 13) + ip_frag_off,
       ip_ttl,
       ip_proto,
       ip_checksum,
       ip_src,
       ip_dst
   )
   
   # 3. ICMP Request Packet (8 bytes, echo request)
   icmp_type = 8    # Type (8=echo request)
   icmp_code = 0    # Code (0)
   icmp_checksum = 0# Fill 0 first
   icmp_id = 5678   # Identifier
   icmp_seq = 1     # Sequence Number
   
   # Assemble ICMP header (fill 0 for checksum first)
   icmp_header = struct.pack(
       "!BBHHH",
       icmp_type,
       icmp_code,
       icmp_checksum,
       icmp_id,
       icmp_seq
   )
   
   # 【Key】Intentionally construct wrong ICMP checksum (correct checksum + 1 to 
break validity)
   correct_icmp_checksum = calculate_checksum(icmp_header)
   wrong_icmp_checksum = (correct_icmp_checksum + 1) & 0xffff  # Ensure 16 bits
   
   # Reassemble ICMP header (fill wrong checksum)
   icmp_header = struct.pack(
       "!BBHHH",
       icmp_type,
       icmp_code,
       wrong_icmp_checksum,
       icmp_id,
       icmp_seq
   )
   
   # 4. Complete packet: Ethernet header + IP header + ICMP header
   packet = eth_header + ip_header + icmp_header
   
   # -------------------------- Send Packet --------------------------
   def send_raw_packet():
       try:
           # Create raw socket (SOCK_RAW + ETH_P_ALL)
           # ETH_P_ALL=0x0003: Receive all Ethernet frames, manually construct 
link layer header when sending
           sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, 
socket.htons(0x0003))
           sock.bind((INTERFACE, 0))  # Bind to specified network interface
   
           # Send packet
           sock.send(packet)
           print("Raw ICMP packet sent successfully!")
           print(f"Key Information:")
           print(f"  Source MAC: {SRC_MAC} | Destination MAC: {DST_MAC}")
           print(f"  Source IP: {SRC_IP} | Destination IP: {DST_IP}")
           print(f"  Correct ICMP Checksum: 0x{correct_icmp_checksum:04x}")
           print(f"  Wrong ICMP Checksum: 0x{wrong_icmp_checksum:04x} (sent)")
   
       except PermissionError:
           print("Error: Need root privileges to run (sudo python3 xxx.py)")
       except Exception as e:
           print(f"Failed to send: {e}")
       finally:
           if 'sock' in locals():
               sock.close()
   
   if __name__ == "__main__":
       send_raw_packet()`
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to