From c58e3184e2940106d5bd880bfbe8a2efeeadd4c1 Mon Sep 17 00:00:00 2001
From: Phil <phil@secdev.org>
Date: Sun, 8 Mar 2009 10:56:22 +0100
Subject: [PATCH] Ability to reference a packet's fields in another packet's
 fields description

class Test(Packet):
    fields_desc = [ IntField("test1",0),
                    SNAP,
                    IntField("test2",1) ]


>>> ls(SNAP)
OUI        : X3BytesField         = (0)
code       : XShortEnumField      = (0)
>>> ls(Test)
test1      : IntField             = (0)
OUI        : X3BytesField         = (0)
code       : XShortEnumField      = (0)
test2      : IntField             = (1)
---
 scapy/base_classes.py | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/scapy/base_classes.py b/scapy/base_classes.py
index 1a77642e..221ada6b 100644
--- a/scapy/base_classes.py
+++ b/scapy/base_classes.py
@@ -122,8 +122,35 @@ class OID(Gen):
 
 class Packet_metaclass(type):
     def __new__(cls, name, bases, dct):
+        if "fields_desc" in dct: # perform resolution of references to other packets
+            current_fld = dct["fields_desc"]
+            resolved_fld = []
+            for f in current_fld:
+                if isinstance(f, Packet_metaclass): # reference to another fields_desc
+                    for f2 in f.fields_desc:
+                        resolved_fld.append(f2)
+                else:
+                    resolved_fld.append(f)
+        else: # look for a field_desc in parent classes
+            resolved_fld = None
+            for b in bases:
+                if hasattr(b,"fields_desc"):
+                    resolved_fld = b.fields_desc
+                    break
+
+        if resolved_fld: # perform default value replacements
+            final_fld = []
+            for f in resolved_fld:
+                if f.name in dct:
+                    f = f.copy()
+                    f.default = dct[f.name]
+                    del(dct[f.name])
+                final_fld.append(f)
+
+            dct["fields_desc"] = final_fld
+
         newcls = super(Packet_metaclass, cls).__new__(cls, name, bases, dct)
-        for f in newcls.fields_desc:
+        for f in newcls.fields_desc:                
             f.register_owner(newcls)
         config.conf.layers.register(newcls)
         return newcls
-- 
GitLab