Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions scapy/packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@
_T = TypeVar("_T", Dict[str, Any], Optional[Dict[str, Any]])


def _resolved_fields_desc(fields_desc):
# type: (Sequence[Union[AnyField, Type['Packet']]]) -> List[AnyField]
"""Return fields_desc entries after Packet_metaclass resolution."""
return cast(List[AnyField], list(fields_desc))


class Packet(
BasePacket,
_CanvasDumpExtended,
Expand All @@ -106,7 +112,7 @@ class Packet(
"process_information"
]
name = None
fields_desc = [] # type: ClassVar[List[AnyField]]
fields_desc = [] # type: ClassVar[List[Union[AnyField, Type[Packet]]]] # noqa: E501
deprecated_fields = {} # type: Dict[str, Tuple[str, str]]
overload_fields = {} # type: Dict[Type[Packet], Dict[str, Any]]
payload_guess = [] # type: List[Tuple[Dict[str, Any], Type[Packet]]]
Expand Down Expand Up @@ -190,7 +196,7 @@ def __init__(self,
# We use this strange initialization so that the fields
# are initialized in their declaration order.
# It is required to always support MultipleTypeField
for field in self.fields_desc:
for field in _resolved_fields_desc(self.fields_desc):
fname = field.name
try:
value = fields.pop(fname)
Expand Down Expand Up @@ -323,7 +329,7 @@ def init_fields(self, for_dissect_only=False):
"""

if self.class_dont_cache.get(self.__class__, False):
self.do_init_fields(self.fields_desc)
self.do_init_fields(_resolved_fields_desc(self.fields_desc))
else:
self.do_init_cached_fields(for_dissect_only=for_dissect_only)

Expand Down Expand Up @@ -354,7 +360,7 @@ def do_init_cached_fields(self, for_dissect_only=False):

# Build the fields information
if Packet.class_default_fields.get(cls_name, None) is None:
self.prepare_cached_fields(self.fields_desc)
self.prepare_cached_fields(_resolved_fields_desc(self.fields_desc))

# Use fields information from cache
default_fields = Packet.class_default_fields.get(cls_name, None)
Expand Down Expand Up @@ -398,7 +404,7 @@ def prepare_cached_fields(self, flist):
if isinstance(f, MultipleTypeField):
# Abort
self.class_dont_cache[cls_name] = True
self.do_init_fields(self.fields_desc)
self.do_init_fields(_resolved_fields_desc(self.fields_desc))
return

class_default_fields[f.name] = copy.deepcopy(f.default)
Expand Down Expand Up @@ -631,7 +637,7 @@ def __repr__(self):
# type: () -> str
s = ""
ct = conf.color_theme
for f in self.fields_desc:
for f in _resolved_fields_desc(self.fields_desc):
if isinstance(f, ConditionalField) and not f._evalcond(self):
continue
if f.name in self.fields:
Expand Down Expand Up @@ -770,7 +776,7 @@ def self_build(self):
if self.raw_packet_cache is not None:
return self.raw_packet_cache
p = b""
for f in self.fields_desc:
for f in _resolved_fields_desc(self.fields_desc):
val = self.getfieldval(f.name)
if isinstance(val, RawVal):
p += bytes(val)
Expand Down Expand Up @@ -851,7 +857,7 @@ def do_build_ps(self):
p = b""
pl = []
q = b""
for f in self.fields_desc:
for f in _resolved_fields_desc(self.fields_desc):
if isinstance(f, ConditionalField) and not f._evalcond(self):
continue
p = f.addfield(self, p, self.getfieldval(f.name))
Expand Down Expand Up @@ -1079,7 +1085,7 @@ def do_dissect(self, s):
# type: (bytes) -> bytes
_raw = s
self.raw_packet_cache_fields = {}
for f in self.fields_desc:
for f in _resolved_fields_desc(self.fields_desc):
s, fval = f.getfield(self, s)
# Skip unused ConditionalField
if isinstance(f, ConditionalField) and fval is None:
Expand Down Expand Up @@ -1291,8 +1297,8 @@ def __eq__(self, other):
# type: (Any) -> bool
if not isinstance(other, self.__class__):
return False
for f in self.fields_desc:
if f not in other.fields_desc:
for f in _resolved_fields_desc(self.fields_desc):
if f not in _resolved_fields_desc(other.fields_desc):
return False
if self.getfieldval(f.name) != other.getfieldval(f.name):
return False
Expand Down Expand Up @@ -1503,7 +1509,7 @@ def _show_or_dump(self,
ct.punct("###["),
ct.layer_name(self.name),
ct.punct("]###"))
fields = self.fields_desc.copy()
fields = _resolved_fields_desc(self.fields_desc).copy()
while fields:
f = fields.pop(0)
if isinstance(f, ConditionalField) and not f._evalcond(self):
Expand Down Expand Up @@ -1737,7 +1743,7 @@ def _do_summary(self):
ret = self.__class__.__name__ if self.show_summary else ""
if self.__class__ in conf.emph:
impf = []
for f in self.fields_desc:
for f in _resolved_fields_desc(self.fields_desc):
if f in conf.emph:
impf.append("%s=%s" % (f.name, f.i2repr(self, self.getfieldval(f.name)))) # noqa: E501
ret = "%s [%s]" % (ret, " ".join(impf))
Expand Down Expand Up @@ -1775,7 +1781,10 @@ def _command(self, json=False):
f = []
iterator: Iterator[Tuple[str, Any]]
if json:
iterator = ((x.name, self.getfieldval(x.name)) for x in self.fields_desc)
iterator = (
(x.name, self.getfieldval(x.name))
for x in _resolved_fields_desc(self.fields_desc)
)
else:
iterator = iter(self.fields.items())
for fn, fv in iterator:
Expand Down Expand Up @@ -2423,7 +2432,7 @@ def _pkt_ls(obj, # type: Union[Packet, Type[Packet]]
if not issubtype(obj, Packet) and not is_pkt:
raise ValueError
fields = []
for f in obj.fields_desc:
for f in _resolved_fields_desc(obj.fields_desc):
cur_fld = f
attrs = [] # type: List[str]
long_attrs = [] # type: List[str]
Expand Down Expand Up @@ -2581,7 +2590,7 @@ def rfc(cls, ret=False, legend=True):

# Generate packet groups
def _iterfields() -> Iterator[Tuple[str, int]]:
for f in cls.fields_desc:
for f in _resolved_fields_desc(cls.fields_desc):
# Fancy field name
fname = f.name.upper().replace("_", " ")
fsize = int(f.sz * 8)
Expand Down Expand Up @@ -2697,7 +2706,7 @@ def fuzz(p, # type: _P
while not isinstance(q, NoPayload):
new_default_fields = {}
multiple_type_fields = [] # type: List[str]
for f in q.fields_desc:
for f in _resolved_fields_desc(q.fields_desc):
if isinstance(f, PacketListField):
for r in getattr(q, f.name):
fuzz(r, _inplace=1)
Expand Down
Loading