From c82fa7f57360d0c337bee5e10941eab0a46c0c0d Mon Sep 17 00:00:00 2001
From: Thomas AUREL <thms.aurel@gmail.com>
Date: Wed, 29 Mar 2017 14:25:11 +0200
Subject: [PATCH] add internal doc & reform binding layers
---
doc/scapy/build_dissect.rst | 9 ++-
scapy/packet.py | 112 ++++++++++++++++++++++++++++++++----
2 files changed, 110 insertions(+), 11 deletions(-)
diff --git a/doc/scapy/build_dissect.rst b/doc/scapy/build_dissect.rst
index 6f9926d8..5f0ef6aa 100644
--- a/doc/scapy/build_dissect.rst
+++ b/doc/scapy/build_dissect.rst
@@ -387,7 +387,14 @@ Binding layers
One of the cool features with Scapy when dissecting layers is that is
try to guess for us what the next layer is. The official way to link 2
-layers is using ``bind_layers()``:
+layers is using ``bind_layers()`` function.
+
+Available inside the ``packet`` module, this function can be used as following::
+
+ bind_layers(ProtoA, ProtoB, FieldToBind=Value)
+
+Each time a packet ``ProtoA()/ProtoB()`` will be created, the ``FieldToBind`` of
+``ProtoA`` will be equal to ``Value``.
For instance, if you have a class ``HTTP``, you may expect that all the
packets coming from or going to port 80 will be decoded as such. This
diff --git a/scapy/packet.py b/scapy/packet.py
index eb8e265e..2ac07d15 100644
--- a/scapy/packet.py
+++ b/scapy/packet.py
@@ -131,9 +131,15 @@ class Packet(BasePacket):
self.post_transforms = [post_transform]
def init_fields(self):
+ """
+ Initialize each fields of the fields_desc dict
+ """
self.do_init_fields(self.fields_desc)
def do_init_fields(self, flist):
+ """
+ Initialize each fields of the fields_desc dict
+ """
for f in flist:
self.default_fields[f.name] = copy.deepcopy(f.default)
self.fieldtype[f.name] = f
@@ -340,6 +346,11 @@ class Packet(BasePacket):
return {fname: self.copy_field_value(fname, fval)
for fname, fval in fields.iteritems()}
def self_build(self, field_pos_list=None):
+ """
+ Create the default layer regarding fields_desc dict
+
+ :param field_pos_list:
+ """
if self.raw_packet_cache is not None:
for fname, fval in self.raw_packet_cache_fields.iteritems():
if self.getfieldval(fname) != fval:
@@ -361,9 +372,19 @@ class Packet(BasePacket):
return p
def do_build_payload(self):
+ """
+ Create the default version of the payload layer
+
+ :return: a string of payload layer
+ """
return self.payload.do_build()
def do_build(self):
+ """
+ Create the default version of the layer
+
+ :return: a string of the packet with the payload
+ """
if not self.explicit:
self = self.__iter__().next()
pkt = self.self_build()
@@ -379,13 +400,24 @@ class Packet(BasePacket):
return self.payload.build_padding()
def build(self):
+ """
+ Create the current layer
+
+ :return: string of the packet with the payload
+ """
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."""
+ """
+ DEV: called right after the current layer is build.
+
+ :param str pkt: the current packet (build by self_buil function)
+ :param str pay: the packet payload (build by do_build_payload function)
+ :return: a string of the packet with the payload
+ """
return pkt+pay
def build_done(self, p):
@@ -425,8 +457,14 @@ class Packet(BasePacket):
def psdump(self, filename=None, **kargs):
- """psdump(filename=None, layer_shift=0, rebuild=1)
-Creates an EPS file describing a packet. If filename is not provided a temporary file is created and gs is called."""
+ """
+ psdump(filename=None, layer_shift=0, rebuild=1)
+
+ Creates an EPS file describing a packet. If filename is not provided a
+ temporary file is created and gs is called.
+
+ :param filename: the file's filename
+ """
canvas = self.canvas_dump(**kargs)
if filename is None:
fname = get_temp_file(autoext=".eps")
@@ -436,8 +474,14 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
canvas.writeEPSfile(filename)
def pdfdump(self, filename=None, **kargs):
- """pdfdump(filename=None, layer_shift=0, rebuild=1)
- Creates a PDF file describing a packet. If filename is not provided a temporary file is created and xpdf is called."""
+ """
+ pdfdump(filename=None, layer_shift=0, rebuild=1)
+
+ Creates a PDF file describing a packet. If filename is not provided a
+ temporary file is created and xpdf is called.
+
+ :param filename: the file's filename
+ """
canvas = self.canvas_dump(**kargs)
if filename is None:
fname = get_temp_file(autoext=".pdf")
@@ -597,7 +641,12 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
def extract_padding(self, s):
- """DEV: to be overloaded to extract current layer's padding. Return a couple of strings (actual layer, padding)"""
+ """
+ DEV: to be overloaded to extract current layer's padding.
+
+ :param str s: the current layer
+ :return: a couple of strings (actual layer, padding)
+ """
return s,None
def post_dissect(self, s):
@@ -626,6 +675,11 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
return s
def do_dissect_payload(self, s):
+ """
+ Perform the dissection of the layer's payload
+
+ :param str s: the raw layer
+ """
if s:
cls = self.guess_payload_class(s)
try:
@@ -657,7 +711,13 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
def guess_payload_class(self, payload):
- """DEV: Guesses the next payload class from layer bonds. Can be overloaded to use a different mechanism."""
+ """
+ DEV: Guesses the next payload class from layer bonds.
+ Can be overloaded to use a different mechanism.
+
+ :param str payload: the layer's payload
+ :return: the payload class
+ """
for t in self.aliastypes:
for fval, cls in t.payload_guess:
ok = 1
@@ -670,7 +730,13 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
return self.default_payload_class(payload)
def default_payload_class(self, payload):
- """DEV: Returns the default payload class if nothing has been found by the guess_payload_class() method."""
+ """
+ DEV: Returns the default payload class if nothing has been found by the
+ guess_payload_class() method.
+
+ :param str payload: the layer's payload
+ :return: the default payload class define inside the configuration file
+ """
return conf.raw_layer
def hide_defaults(self):
@@ -873,6 +939,13 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
"""
Internal method that shows or dumps a hierarchical view of a packet.
Called by show.
+
+ :param dump: determine if it prints or returns the string value
+ :param int indent: the size of indentation for each layer
+ :param str lvl: additional information about the layer lvl
+ :param str label_lvl: additional information about the layer fields
+ :param first_call: determine if the current function is the first
+ :return: return a hierarchical view if dump, else print it
"""
if dump:
@@ -919,11 +992,30 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
return s
def show(self, dump=False, indent=3, lvl="", label_lvl=""):
- """Prints or returns (when "dump" is true) a hierarchical view of the packet. "indent" gives the size of indentation for each layer."""
+ """
+ Prints or returns (when "dump" is true) a hierarchical view of the
+ packet.
+
+ :param dump: determine if it prints or returns the string value
+ :param int indent: the size of indentation for each layer
+ :param str lvl: additional information about the layer lvl
+ :param str label_lvl: additional information about the layer fields
+ :return: return a hierarchical view if dump, else print it
+ """
return self._show_or_dump(dump, indent, lvl, label_lvl)
def show2(self, dump=False, indent=3, lvl="", label_lvl=""):
- """Prints or returns (when "dump" is true) a hierarchical view of an assembled version of the packet, so that automatic fields are calculated (checksums, etc.)"""
+ """
+ Prints or returns (when "dump" is true) a hierarchical view of an
+ assembled version of the packet, so that automatic fields are
+ calculated (checksums, etc.)
+
+ :param dump: determine if it prints or returns the string value
+ :param int indent: the size of indentation for each layer
+ :param str lvl: additional information about the layer lvl
+ :param str label_lvl: additional information about the layer fields
+ :return: return a hierarchical view if dump, else print it
+ """
return self.__class__(str(self)).show(dump, indent, lvl, label_lvl)
def sprintf(self, fmt, relax=1):
--
GitLab