diff --git a/scapy/base_classes.py b/scapy/base_classes.py index 3fa054866c9297fbf4687e3a853742d8b86e3fca..f805c18ba79ba30029cf5759d41ac9fe047a1dd7 100644 --- a/scapy/base_classes.py +++ b/scapy/base_classes.py @@ -16,6 +16,7 @@ import config import error class Gen(object): + __slots__ = [] def __iter__(self): return iter([]) @@ -175,10 +176,17 @@ class Packet_metaclass(type): dct["fields_desc"] = final_fld + if "__slots__" not in dct: + dct["__slots__"] = [] newcls = super(Packet_metaclass, cls).__new__(cls, name, bases, dct) + if hasattr(newcls, "aliastypes"): + newcls.aliastypes = [newcls] + newcls.aliastypes + else: + newcls.aliastypes = [newcls] + if hasattr(newcls,"register_variant"): newcls.register_variant() - for f in newcls.fields_desc: + for f in newcls.fields_desc: f.register_owner(newcls) config.conf.layers.register(newcls) return newcls @@ -220,7 +228,7 @@ class NewDefaultValues(Packet_metaclass): return super(NewDefaultValues, cls).__new__(cls, name, bases, dct) class BasePacket(Gen): - pass + __slots__ = [] ############################# @@ -229,6 +237,3 @@ class BasePacket(Gen): class BasePacketList: pass - - - diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py index 4b6694617881220430e61e3c630c36be16e77fc0..6cc4303db2f0b54811a5b65fd3b45855b22b3f7e 100644 --- a/scapy/layers/inet.py +++ b/scapy/layers/inet.py @@ -27,8 +27,9 @@ import scapy.as_resolvers ## IP Tools class ## #################### -class IPTools: - """Add more powers to a class that have a "src" attribute.""" +class IPTools(object): + """Add more powers to a class with an "src" attribute.""" + __slots__ = [] def whois(self): os.system("whois %s" % self.src) def ottl(self): diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index ba5674c454a3ccb0ab4b43a4feee756da4c3c241..94f1660896949125a96d8f56e6ec354889d1780a 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -945,7 +945,7 @@ def defragment6(pktlist): q = res[0] nh = q[IPv6ExtHdrFragment].nh q[IPv6ExtHdrFragment].underlayer.nh = nh - q[IPv6ExtHdrFragment].underlayer.payload = None + del q[IPv6ExtHdrFragment].underlayer.payload q /= conf.raw_layer(load=fragmentable) return IPv6(str(q)) @@ -991,12 +991,12 @@ def fragment6(pkt, fragSize): # Keep fragment header fragHeader = pkt[IPv6ExtHdrFragment] - fragHeader.payload = None # detach payload + del fragHeader.payload # detach payload # Unfragmentable Part unfragPartLen = len(s) - fragPartLen - 8 unfragPart = pkt - pkt[IPv6ExtHdrFragment].underlayer.payload = None # detach payload + del pkt[IPv6ExtHdrFragment].underlayer.payload # detach payload # Cut the fragmentable part to fit fragSize. Inner fragments have # a length that is an integer multiple of 8 octets. last Frag MTU diff --git a/scapy/packet.py b/scapy/packet.py index 04fb3346916f37efab4f016271117c2a99d484a9..4f44353bf343c0abd6ae60a7e66c4c759dbd8022 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -33,23 +33,20 @@ class RawVal: class Packet(BasePacket): + __slots__ = [ + "time", "sent_time", "name", "default_fields", + "overloaded_fields", "fields", "fieldtype", "packetfields", + "initialized", "original", "explicit", "raw_packet_cache", + "raw_packet_cache_fields", "_pkt", "post_transforms", + # then payload and underlayer + "payload", "underlayer", + ] __metaclass__ = Packet_metaclass - name=None - + name = None fields_desc = [] - - aliastypes = [] overload_fields = {} - - underlayer = None - - sent_time = None payload_guess = [] - initialized = 0 - show_indent=1 - explicit = 0 - raw_packet_cache = None - raw_packet_cache_fields = None + show_indent = 1 @classmethod def from_hexcap(cls): @@ -67,20 +64,20 @@ class Packet(BasePacket): def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields): self.time = time.time() - self.sent_time = 0 - if self.name is None: - self.name = self.__class__.__name__ - self.aliastypes = [ self.__class__ ] + self.aliastypes + self.sent_time = None self.default_fields = {} self.overloaded_fields = {} - self.fields={} - self.fieldtype={} - self.packetfields=[] - self.__dict__["payload"] = NoPayload() + self.fields = {} + self.fieldtype = {} + self.packetfields = [] + self.payload = NoPayload() self.init_fields() self.underlayer = _underlayer self.initialized = 1 self.original = _pkt + self.explicit = 0 + self.raw_packet_cache = None + self.raw_packet_cache_fields = None if _pkt: self.dissect(_pkt) if not _internal: @@ -124,19 +121,19 @@ class Packet(BasePacket): self.payload.add_payload(payload) else: if isinstance(payload, Packet): - self.__dict__["payload"] = payload + self.payload = payload payload.add_underlayer(self) for t in self.aliastypes: if payload.overload_fields.has_key(t): self.overloaded_fields = payload.overload_fields[t] break elif type(payload) is str: - self.__dict__["payload"] = conf.raw_layer(load=payload) + self.payload = conf.raw_layer(load=payload) else: raise TypeError("payload must be either 'Packet' or 'str', not [%s]" % repr(payload)) def remove_payload(self): self.payload.remove_underlayer(self) - self.__dict__["payload"] = NoPayload() + self.payload = NoPayload() self.overloaded_fields = {} def add_underlayer(self, underlayer): self.underlayer = underlayer @@ -148,7 +145,6 @@ class Packet(BasePacket): clone.fields = self.copy_fields_dict(self.fields) clone.default_fields = self.copy_fields_dict(self.default_fields) clone.overloaded_fields = self.overloaded_fields.copy() - clone.overload_fields = self.overload_fields.copy() clone.underlayer = self.underlayer clone.explicit = self.explicit clone.raw_packet_cache = self.raw_packet_cache @@ -156,7 +152,7 @@ class Packet(BasePacket): self.raw_packet_cache_fields ) clone.post_transforms = self.post_transforms[:] - clone.__dict__["payload"] = self.payload.copy() + clone.payload = self.payload.copy() clone.payload.add_underlayer(clone) return clone @@ -179,7 +175,7 @@ class Packet(BasePacket): return self.payload.getfield_and_val(attr) def __getattr__(self, attr): - if self.initialized: + if hasattr(self, "initialized"): fld,v = self.getfield_and_val(attr) if fld is not None: return fld.i2h(self, v) @@ -203,15 +199,23 @@ class Packet(BasePacket): else: self.payload.setfieldval(attr,val) + def attr_in_slots(self, attr): + """Return True iff `attr` belongs to the `__slots__` list of + this class or any parent class. + + """ + return any(attr in cls.__slots__ for cls in self.__class__.__mro__ + if hasattr(cls, "__slots__")) + def __setattr__(self, attr, val): - if self.initialized: + if hasattr(self, "initialized"): + if self.attr_in_slots(attr): + return object.__setattr__(self, attr, val) try: - self.setfieldval(attr,val) + return self.setfieldval(attr,val) except AttributeError: pass - else: - return - self.__dict__[attr] = val + return object.__setattr__(self, attr, val) def delfieldval(self, attr): if self.fields.has_key(attr): @@ -227,17 +231,16 @@ class Packet(BasePacket): self.payload.delfieldval(attr) def __delattr__(self, attr): - if self.initialized: + if hasattr(self, "initialized"): + if attr == "payload": + return self.remove_payload() + if self.attr_in_slots(attr): + return object.__delattr__(self, attr) try: - self.delfieldval(attr) + return self.delfieldval(attr) except AttributeError: pass - else: - return - if self.__dict__.has_key(attr): - del(self.__dict__[attr]) - else: - raise AttributeError(attr) + return object.__delattr__(self, attr) def __repr__(self): s = "" @@ -657,7 +660,6 @@ Creates an EPS file describing a packet. If filename is not provided a temporary pkt.default_fields = self.copy_fields_dict(self.default_fields) pkt.time = self.time pkt.underlayer = self.underlayer - pkt.overload_fields = self.overload_fields.copy() pkt.post_transforms = self.post_transforms pkt.raw_packet_cache = self.raw_packet_cache pkt.raw_packet_cache_fields = self.copy_fields_dict( @@ -1112,7 +1114,7 @@ class NoPayload(Packet): elif attr in self.__class__.__dict__: return self.__class__.__dict__[attr] else: - raise AttributeError, attr + raise AttributeError(attr) def hide_defaults(self): pass def __iter__(self):