From 1e59ef63c8d647c1557ffebcdc775ccb5a8b70c0 Mon Sep 17 00:00:00 2001 From: Phil <phil@secdev.org> Date: Wed, 21 Apr 2010 18:21:44 +0200 Subject: [PATCH] Simplified the build mecanism Packet.build() is called only on the first layer. It will call Packet.do_build() which will recurse through all layers. For each layer, it will call Packet.self_build() which will do the job for each layer. Packet.do_build() will call Packet.post_build() and transform on them, and concatenate them. Then Packet.build() will call Packet.build_padding() and Packet.build_done(). Note that this undetermined case will have a different behavior: Raw("ABC")/Padding("abc")/Raw("DEF")/Padding("def") It was "ABCabcDEFdef" Now it is "ABCDEFabcdef" --- scapy/asn1packet.py | 2 +- scapy/packet.py | 56 ++++++++++++++++++++++++++------------------- test/regression.uts | 2 +- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/scapy/asn1packet.py b/scapy/asn1packet.py index dc900b0a..e49942ce 100644 --- a/scapy/asn1packet.py +++ b/scapy/asn1packet.py @@ -12,7 +12,7 @@ class ASN1_Packet(Packet): flist = self.ASN1_root.get_fields_list() self.do_init_fields(flist) self.fields_desc = flist - def do_build(self): + def self_build(self): return self.ASN1_root.build(self) def do_dissect(self, x): return self.ASN1_root.dissect(self, x) diff --git a/scapy/packet.py b/scapy/packet.py index 1f51f318..3410a925 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -281,37 +281,44 @@ class Packet(BasePacket): return True def __len__(self): return len(self.__str__()) - def do_build(self): + def self_build(self, field_pos_list=None): p="" for f in self.fields_desc: val = self.getfieldval(f.name) if isinstance(val, RawVal): - p += str(val) + sval = str(val) + p += sval + if field_pos_list is not None: + field_pos_list.append( (f.name, sval.encode("string_escape"), len(p), len(sval) ) ) else: p = f.addfield(self, p, val) return p - - def post_build(self, pkt, pay): - """DEV: called right after the current layer is build.""" - return pkt+pay - def build_payload(self): - return self.payload.build(internal=1) + def do_build_payload(self): + return self.payload.do_build() - def build(self,internal=0): + def do_build(self): if not self.explicit: self = self.__iter__().next() - pkt = self.do_build() + pkt = self.self_build() for t in self.post_transforms: pkt = t(pkt) - pay = self.build_payload() + pay = self.do_build_payload() p = self.post_build(pkt,pay) - if not internal: - pad = self.payload.getlayer(Padding) - if pad: - p += pad.build() - p = self.build_done(p) return p + + def build_padding(self): + return self.payload.build_padding() + + def build(self): + p = self.do_build() + p += self.build_padding() + p = self.build_done(p) + return p + + def post_build(self, pkt, pay): + """DEV: called right after the current layer is build.""" + return pkt+pay def build_done(self, p): return self.payload.build_done(p) @@ -1029,8 +1036,12 @@ class NoPayload(Packet): return "" def __nonzero__(self): return False - def build(self, internal=0): - return "" + def do_build(self): + return "" + def build(self): + return "" + def build_padding(self): + return "" def build_done(self, p): return p def build_ps(self, internal=0): @@ -1109,11 +1120,10 @@ class Raw(Packet): class Padding(Raw): name = "Padding" - def build(self, internal=0): - if internal: - return "" - else: - return Raw.build(self) + def self_build(self): + return "" + def build_padding(self): + return self.load+self.payload.build_padding() conf.raw_layer = Raw if conf.default_l2 is None: diff --git a/test/regression.uts b/test/regression.uts index f5b5f732..069c617d 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -125,7 +125,7 @@ assert( _ == "abcdef" ) str(Raw("ABC")/Padding("abc")/Padding("def")) assert( _ == "ABCabcdef" ) str(Raw("ABC")/Padding("abc")/Raw("DEF")/Padding("def")) -assert( _ == "ABCabcDEFdef" ) +assert( _ == "ABCDEFabcdef" ) = Padding and length computation IP(str(IP()/Padding("abc"))) -- GitLab