From c92fb3da1ce6f7b003c165bd3352d8c804e978c0 Mon Sep 17 00:00:00 2001 From: Pierre LALET <pierre.lalet@cea.fr> Date: Sat, 21 Jan 2017 14:34:40 +0100 Subject: [PATCH] Handle FlagValue fields changes with .raw_packet_cache --- scapy/fields.py | 9 +++++++++ scapy/packet.py | 2 +- test/regression.uts | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/scapy/fields.py b/scapy/fields.py index cecd8761..d4e5f4ca 100644 --- a/scapy/fields.py +++ b/scapy/fields.py @@ -26,6 +26,7 @@ class Field(object): __slots__ = ["name", "fmt", "default", "sz", "owners"] __metaclass__ = Field_metaclass islist = 0 + ismutable = False holds_packets = 0 def __init__(self, name, default, fmt="H"): self.name = name @@ -1008,6 +1009,8 @@ class FlagValue(object): self.value &= ~(2 ** self.names.index(attr)) else: return super(FlagValue, self).__setattr__(attr, value) + def copy(self): + return self.__class__(self.value, self.names) class FlagsField(BitField): @@ -1031,6 +1034,7 @@ class FlagsField(BitField): :param size: number of bits in the field :param names: (list or dict) label for each flag, Least Significant Bit tag's name is written first """ + ismutable = True __slots__ = ["multi", "names"] def __init__(self, name, default, size, names): self.multi = isinstance(names, list) @@ -1041,6 +1045,11 @@ class FlagsField(BitField): return type(x)(None if v is None else FlagValue(v, self.names) for v in x) return None if x is None else FlagValue(x, self.names) + def m2i(self, pkt, x): + if isinstance(x, (list, tuple)): + return type(x)(None if v is None else FlagValue(v, self.names) + for v in x) + return None if x is None else FlagValue(x, self.names) def i2repr(self, pkt, x): if isinstance(x, (list, tuple)): return repr(type(x)( diff --git a/scapy/packet.py b/scapy/packet.py index e2935ddb..9a6d73ec 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -589,7 +589,7 @@ Creates an EPS file describing a packet. If filename is not provided a temporary s, fval = f.getfield(self, s) # We need to track fields with mutable values to discard # .raw_packet_cache when needed. - if f.islist or f.holds_packets: + if f.islist or f.holds_packets or f.ismutable: self.raw_packet_cache_fields[f.name] = f.do_copy(fval) self.fields[f.name] = fval assert(raw.endswith(s)) diff --git a/test/regression.uts b/test/regression.uts index 393df949..b87cfb8a 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -7532,3 +7532,27 @@ assert not any(getattr(pkt.flags, f) for f in 'FSRECN') pkt.flags = 50 assert all(getattr(pkt.flags, f) for f in 'SAU') assert not any(getattr(pkt.flags, f) for f in 'FRPECN') + += Flag values mutation with .raw_packet_cache +~ IP TCP + +pkt = IP(str(IP(flags="MF")/TCP(flags="SA"))) +assert pkt.raw_packet_cache is not None +assert pkt[TCP].raw_packet_cache is not None +assert pkt.flags.MF +assert not pkt.flags.DF +assert not pkt.flags.evil +assert pkt[TCP].flags.S +assert pkt[TCP].flags.A +assert not any(getattr(pkt[TCP].flags, f) for f in 'FRPUECN') +pkt.flags.MF = 0 +pkt.flags.DF = 1 +pkt[TCP].flags.U = True +pkt[TCP].flags.S = False +pkt = IP(str(pkt)) +assert not pkt.flags.MF +assert pkt.flags.DF +assert not pkt.flags.evil +assert pkt[TCP].flags.A +assert pkt[TCP].flags.U +assert not any(getattr(pkt[TCP].flags, f) for f in 'FSRPECN') -- GitLab