From 69d2399789e0fe6be26c7a4bf145f2a200ee24fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20De=20Keersmaeker?=
 <francois.dekeersmaeker@uclouvain.be>
Date: Wed, 31 May 2023 16:59:31 +0200
Subject: [PATCH] Fix checksum and len fields update

---
 src/packet/BOOTP.py     |  2 +-
 src/packet/CoAP.py      |  2 +-
 src/packet/DNS.py       |  2 +-
 src/packet/IGMPv3mr.py  |  7 +------
 src/packet/Packet.py    | 34 ++++++++++++++++++++++------------
 src/packet/Transport.py |  2 +-
 6 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/src/packet/BOOTP.py b/src/packet/BOOTP.py
index 805562b..075697b 100644
--- a/src/packet/BOOTP.py
+++ b/src/packet/BOOTP.py
@@ -91,7 +91,7 @@ class BOOTP(Packet):
             self.set_dhcp_option(field, new_value)  # Set new value for field
 
         # Update checksums
-        self.update_checksums()
+        self.update_fields()
 
         # Return value: dictionary containing tweak information
         return self.get_dict_log(field, old_value, new_value)
diff --git a/src/packet/CoAP.py b/src/packet/CoAP.py
index 9d79806..1d1d9e0 100644
--- a/src/packet/CoAP.py
+++ b/src/packet/CoAP.py
@@ -101,7 +101,7 @@ class CoAP(Packet):
             self.layer.setfieldval("options", result["new_options"])
         
         # Update checksums
-        self.update_checksums()
+        self.update_fields()
 
         # Return value: dictionary containing tweak information
         return self.get_dict_log(field, old_value, new_value)
diff --git a/src/packet/DNS.py b/src/packet/DNS.py
index 7b2de66..6e9d750 100644
--- a/src/packet/DNS.py
+++ b/src/packet/DNS.py
@@ -110,7 +110,7 @@ class DNS(Packet):
                 question_record.setfieldval("qname", new_value_single)
         
         # Update checksums
-        self.update_checksums()
+        self.update_fields()
 
         # Return value: dictionary containing tweak information
         return self.get_dict_log(field, old_value, new_value)
diff --git a/src/packet/IGMPv3mr.py b/src/packet/IGMPv3mr.py
index 2015bf3..2f1cfc0 100644
--- a/src/packet/IGMPv3mr.py
+++ b/src/packet/IGMPv3mr.py
@@ -33,14 +33,9 @@ class IGMPv3mr(Packet):
             new_value += new_address
             group.setfieldval("maddr", new_address)
             i += 1
-        
-        logging.info(f"Packet {self.id}: randomized all IGMPv3 group addresses.")
 
         # Update checksums
-        del self.packet.getlayer("IGMPv3").chksum
-        del self.packet.getlayer("IP").len
-        del self.packet.getlayer("IP").chksum
-        self.packet = scapy.Ether(self.packet.build())
+        self.update_fields()
 
         # Return value: dictionary containing tweak information
         return self.get_dict_log("maddr", old_value, new_value)
diff --git a/src/packet/Packet.py b/src/packet/Packet.py
index 9c60a96..d739cff 100644
--- a/src/packet/Packet.py
+++ b/src/packet/Packet.py
@@ -194,19 +194,29 @@ class Packet:
         self.packet.time = timestamp
     
 
-    def update_checksums(self) -> None:
+    def update_fields(self) -> None:
         """
-        Update packet checksums, if needed.
+        Update checksum and length fields on all relevant layers,
+        and rebuild packet.
         """
-        if self.packet.haslayer("IP"):
-            ip_layer = self.packet.getlayer("IP")
-            ip_layer.delfieldval("len")
-            ip_layer.delfieldval("chksum")
-            transport_layer = self.packet.getlayer(2)
-            if hasattr(transport_layer, "len"):
-                transport_layer.delfieldval("len")
-            if hasattr(transport_layer, "chksum"):
-                transport_layer.delfieldval("chksum")
+        # Loop on all packet layers
+        i = 0
+        while True:
+            layer = self.packet.getlayer(i)
+            if layer is None:
+                break
+            
+            # Delete checksum field
+            if hasattr(layer, "chksum") and layer.getfieldval("chksum") is not None:
+                layer.delfieldval("chksum")
+
+            # Delete length field
+            if hasattr(layer, "len") and layer.getfieldval("len") is not None:
+                layer.delfieldval("len")
+            
+            i += 1
+
+        # Rebuild packet, to update deleted fields
         self.rebuild()
 
         
@@ -305,7 +315,7 @@ class Packet:
         self.layer.setfieldval(field, new_value)
 
         # Update checksums
-        self.update_checksums()
+        self.update_fields()
 
         # Return value: dictionary containing tweak information
         return self.get_dict_log(field, old_value, new_value)
diff --git a/src/packet/Transport.py b/src/packet/Transport.py
index 9109bac..433d82c 100644
--- a/src/packet/Transport.py
+++ b/src/packet/Transport.py
@@ -50,7 +50,7 @@ class Transport(Packet):
         self.layer.setfieldval(field, new_value)
 
         # Update checksums, if needed
-        self.update_checksums()
+        self.update_fields()
 
         # Return value: dictionary containing tweak information
         return self.get_dict_log(field, old_value, new_value)
-- 
GitLab