<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/testsuite/+/13222">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">lib/python/asterisk/pcap/py Replace construct_legacy.protocols<br><br>The "protocols" module provides parsing for PCAP packets<br>layers 2-4 (Ethernet, IPv4/IPv6, UDP/TCP).  The<br>Testsuite uses it to parse packets for the tests that<br>need that functionality.<br><br>It was originally part of the "construct" module but was removed<br>after v2.5.5.  Unfortunately, it was and is the only<br>standalone/low overhead packet parsing module available.<br><br>This python package is an extract from the construct package v2.5.5.<br>Since construct itself underwent major API changes since v2.5.5,<br>the protocols code needed significant work to make it compatible<br>with the current construct version (2.9 at the time of this writing).<br>Since no functional changes were made, only API compatibility<br>changes, the original construct (license)[LICENSE.md] still<br>applies and is included here.<br><br>* Ported construct.protocols to construct 2.9 and added it<br>  to lib/python.<br><br>* Updated pcap.py...<br>** Using /lib/python/PcapListener directly instead of through<br>   test_case to make it a bit less complicated and to facilitate<br>   standalone unit tests.<br>** Refactored for construct 2.9<br>** Removed references to construct.protcols<br>** Added a unit test.<br>   cd <testsuite_dir>/lib/python/asterisk<br>   PYTHONPATH=<testsuite_dir>/lib/python python2 pcap.py --help<br><br>* Updated tests that used construct_legacy to work with<br>  construct 2.9<br><br>Change-Id: Id38d01a2cd073b240fde909a38c95d69313bbbe7<br>---<br>M lib/python/asterisk/pcap.py<br>M lib/python/asterisk/test_case.py<br>A lib/python/protocols/LICENSE.md<br>A lib/python/protocols/README.md<br>A lib/python/protocols/__init__.py<br>A lib/python/protocols/application/__init__.py<br>A lib/python/protocols/ipstack.py<br>A lib/python/protocols/layer2/__init__.py<br>A lib/python/protocols/layer2/arp.py<br>A lib/python/protocols/layer2/ethernet.py<br>A lib/python/protocols/layer2/mtp2.py<br>A lib/python/protocols/layer3/__init__.py<br>A lib/python/protocols/layer3/ipv4.py<br>A lib/python/protocols/layer3/ipv6.py<br>A lib/python/protocols/layer4/__init__.py<br>A lib/python/protocols/layer4/tcp.py<br>A lib/python/protocols/layer4/udp.py<br>A lib/python/protocols/unconverted/application/dns.py<br>A lib/python/protocols/unconverted/layer3/dhcpv4.py<br>A lib/python/protocols/unconverted/layer3/dhcpv6.py<br>A lib/python/protocols/unconverted/layer3/icmpv4.py<br>A lib/python/protocols/unconverted/layer3/igmpv2.py<br>A lib/python/protocols/unconverted/layer3/mtp3.py<br>A lib/python/protocols/unconverted/layer4/isup.py<br>M tests/channels/SIP/pcap_demo/run-test<br>M tests/channels/SIP/pcap_demo/test-config.yaml<br>M tests/channels/pjsip/rtp/rtp_keepalive/base/rtp.py<br>M tests/hep/hep_capture_node.py<br>28 files changed, 1,354 insertions(+), 144 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/lib/python/asterisk/pcap.py b/lib/python/asterisk/pcap.py</span><br><span>index cb5fa5c..536a7ca 100644</span><br><span>--- a/lib/python/asterisk/pcap.py</span><br><span>+++ b/lib/python/asterisk/pcap.py</span><br><span>@@ -13,18 +13,16 @@</span><br><span> </span><br><span> import sys</span><br><span> import logging</span><br><span style="color: hsl(120, 100%, 40%);">+import signal</span><br><span style="color: hsl(120, 100%, 40%);">+import argparse</span><br><span> import binascii</span><br><span> </span><br><span> sys.path.append('lib/python')</span><br><span> </span><br><span> from twisted.internet.protocol import DatagramProtocol</span><br><span> from twisted.internet import reactor</span><br><span style="color: hsl(0, 100%, 40%);">-try:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct_legacy import *</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct_legacy.protocols.ipstack import ip_stack</span><br><span style="color: hsl(0, 100%, 40%);">-except ImportError:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct import *</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct.protocols.ipstack import ip_stack</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span> try:</span><br><span>     from yappcap import PcapOffline</span><br><span>     PCAP_AVAILABLE = True</span><br><span>@@ -33,6 +31,9 @@</span><br><span> </span><br><span> import rlmi</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.ipstack import ip_stack</span><br><span style="color: hsl(120, 100%, 40%);">+from pcap_listener import PcapListener as PacketCapturer</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span> </span><br><span>@@ -59,18 +60,13 @@</span><br><span>         filename = module_config.get('filename')</span><br><span>         snaplen = module_config.get('snaplen')</span><br><span>         buffer_size = module_config.get('buffer-size')</span><br><span style="color: hsl(0, 100%, 40%);">-        if (module_config.get('register-observer')):</span><br><span style="color: hsl(0, 100%, 40%);">-            test_object.register_pcap_observer(self.__pcap_callback)</span><br><span>         self.debug_packets = module_config.get('debug-packets', False)</span><br><span> </span><br><span>         # Let exceptions propagate - if we can't create the pcap, this should</span><br><span>         # throw the exception to the pluggable module creation routines</span><br><span style="color: hsl(0, 100%, 40%);">-        test_object.create_pcap_listener(</span><br><span style="color: hsl(0, 100%, 40%);">-            device=device,</span><br><span style="color: hsl(0, 100%, 40%);">-            bpf_filter=bpf_filter,</span><br><span style="color: hsl(0, 100%, 40%);">-            dumpfile=filename,</span><br><span style="color: hsl(0, 100%, 40%);">-            snaplen=snaplen,</span><br><span style="color: hsl(0, 100%, 40%);">-            buffer_size=buffer_size)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        PacketCapturer(device, bpf_filter, filename, self.__pcap_callback,</span><br><span style="color: hsl(120, 100%, 40%);">+            snaplen, buffer_size)</span><br><span> </span><br><span>     def __pcap_callback(self, packet):</span><br><span>         """Private callback that logs packets if the configuration supports it</span><br><span>@@ -108,7 +104,6 @@</span><br><span>         packet_type A text string describing what type of packet this is</span><br><span>         raw_packet  The bytes comprising the packet</span><br><span>         """</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>         self.packet_type = packet_type</span><br><span>         self.raw_packet = raw_packet</span><br><span>         if isinstance(self.raw_packet, str):</span><br><span>@@ -154,43 +149,45 @@</span><br><span>         self.__parse_raw_data(self.transport_layer.next)</span><br><span> </span><br><span>     def __parse_raw_data(self, binary_blob):</span><br><span style="color: hsl(0, 100%, 40%);">-        header_def = Struct('rtcp_header',</span><br><span style="color: hsl(0, 100%, 40%);">-                            BitStruct('header',</span><br><span style="color: hsl(0, 100%, 40%);">-                                      BitField('version', 2),</span><br><span style="color: hsl(120, 100%, 40%);">+        header_def = 'rtcp_header' / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+                            'header' / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+                                      'version' / BitsInteger(2),</span><br><span>                                       Padding(1),</span><br><span style="color: hsl(0, 100%, 40%);">-                                      BitField('reception_report_count', 5),</span><br><span style="color: hsl(120, 100%, 40%);">+                                      'reception_report_count' / BitsInteger(5),</span><br><span>                                       ),</span><br><span style="color: hsl(0, 100%, 40%);">-                            UBInt8('packet_type'),</span><br><span style="color: hsl(0, 100%, 40%);">-                            UBInt16('length'),</span><br><span style="color: hsl(0, 100%, 40%);">-                            UBInt32('ssrc'))</span><br><span style="color: hsl(120, 100%, 40%);">+                            'packet_type' / Bytewise(Int8ub),</span><br><span style="color: hsl(120, 100%, 40%);">+                            'length' / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+                            'ssrc' / Bytewise(Int32ub)</span><br><span style="color: hsl(120, 100%, 40%);">+                            )</span><br><span>         self.rtcp_header = header_def.parse(binary_blob)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         report_block_def = GreedyRange(</span><br><span style="color: hsl(0, 100%, 40%);">-            Struct(</span><br><span style="color: hsl(0, 100%, 40%);">-                'report_block',</span><br><span style="color: hsl(0, 100%, 40%);">-                UBInt32('ssrc'),</span><br><span style="color: hsl(0, 100%, 40%);">-                BitStruct(</span><br><span style="color: hsl(0, 100%, 40%);">-                    'lost_counts',</span><br><span style="color: hsl(0, 100%, 40%);">-                    BitField('fraction_lost', 8),</span><br><span style="color: hsl(0, 100%, 40%);">-                    BitField('packets_lost', 24)),</span><br><span style="color: hsl(0, 100%, 40%);">-                UBInt32('sequence_number_received'),</span><br><span style="color: hsl(0, 100%, 40%);">-                UBInt32('interarrival_jitter'),</span><br><span style="color: hsl(0, 100%, 40%);">-                UBInt32('last_sr'),</span><br><span style="color: hsl(0, 100%, 40%);">-                UBInt32('delay_last_sr')</span><br><span style="color: hsl(120, 100%, 40%);">+            'report_block' / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+                'ssrc' / Bytewise(Int32ub),</span><br><span style="color: hsl(120, 100%, 40%);">+                'lost_counts' / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+                    'fraction_lost' / BitsInteger(8),</span><br><span style="color: hsl(120, 100%, 40%);">+                    'packets_lost' / BitsInteger(24)</span><br><span style="color: hsl(120, 100%, 40%);">+                ),</span><br><span style="color: hsl(120, 100%, 40%);">+                'sequence_number_received' / Bytewise(Int32ub),</span><br><span style="color: hsl(120, 100%, 40%);">+                'interarrival_jitter' / Bytewise(Int32ub),</span><br><span style="color: hsl(120, 100%, 40%);">+                'last_sr' / Bytewise(Int32ub),</span><br><span style="color: hsl(120, 100%, 40%);">+                'delay_last_sr' / Bytewise(Int32ub)</span><br><span>             )</span><br><span>         )</span><br><span>         if self.rtcp_header.packet_type == 200:</span><br><span>             sender_def = Struct('sr',</span><br><span style="color: hsl(0, 100%, 40%);">-                                Struct('sender_info',</span><br><span style="color: hsl(0, 100%, 40%);">-                                       UBInt32('ntp_msw'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                       UBInt32('ntp_lsw'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                       UBInt32('rtp_timestamp'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                       UBInt32('sender_packet_count'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                       UBInt32('sender_octet_count')),</span><br><span style="color: hsl(120, 100%, 40%);">+                                'sender_info' / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+                                       'ntp_msw' / Int32ub,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       'ntp_lsw' / Int32ub,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       'rtp_timestamp' / Int32ub,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       'sender_packet_count' / Int32ub,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       'sender_octet_count' / Int32ub</span><br><span style="color: hsl(120, 100%, 40%);">+                                       ),</span><br><span>                                 report_block_def)</span><br><span> </span><br><span>             self.sender_report = sender_def.parse(binary_blob[8:])</span><br><span>         elif self.rtcp_header.packet_type == 201:</span><br><span style="color: hsl(0, 100%, 40%);">-            receiver_def = Struct('rr',</span><br><span style="color: hsl(120, 100%, 40%);">+            receiver_def = 'rr' / Struct(</span><br><span>                                   report_block_def)</span><br><span>             self.receiver_report = receiver_def.parse(binary_blob[8:])</span><br><span> </span><br><span>@@ -205,19 +202,16 @@</span><br><span>     """An RTP Packet</span><br><span>     """</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    rtp_header = Struct(</span><br><span style="color: hsl(0, 100%, 40%);">-        "rtp_header",</span><br><span style="color: hsl(0, 100%, 40%);">-        EmbeddedBitStruct(</span><br><span style="color: hsl(0, 100%, 40%);">-            BitField("version", 2),</span><br><span style="color: hsl(0, 100%, 40%);">-            Bit("padding"),</span><br><span style="color: hsl(0, 100%, 40%);">-            Bit("extension"),</span><br><span style="color: hsl(0, 100%, 40%);">-            Nibble("csrc_count"),</span><br><span style="color: hsl(0, 100%, 40%);">-            Bit("marker"),</span><br><span style="color: hsl(0, 100%, 40%);">-            BitField("payload_type", 7),</span><br><span style="color: hsl(0, 100%, 40%);">-        ),</span><br><span style="color: hsl(0, 100%, 40%);">-        UBInt16("sequence_number"),</span><br><span style="color: hsl(0, 100%, 40%);">-        UBInt32("timestamp"),</span><br><span style="color: hsl(0, 100%, 40%);">-        UBInt32("ssrc"),</span><br><span style="color: hsl(120, 100%, 40%);">+    rtp_header = "rtp_header" / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+        "version" / BitsInteger(2),</span><br><span style="color: hsl(120, 100%, 40%);">+        "padding" / Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+        "extension" / Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+        "csrc_count" / Nibble,</span><br><span style="color: hsl(120, 100%, 40%);">+        "marker" / Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+        "payload_type" / BitsInteger(7),</span><br><span style="color: hsl(120, 100%, 40%);">+        "sequence_number" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+        "timestamp"  / Bytewise(Int32ub),</span><br><span style="color: hsl(120, 100%, 40%);">+        "ssrc" / Bytewise(Int32ub),</span><br><span>         # 'csrc' can be added later when needed</span><br><span>     )</span><br><span> </span><br><span>@@ -748,6 +742,7 @@</span><br><span>         """</span><br><span>         (host, port) = addr</span><br><span>         packet = self.packet_factory.interpret_packet(packet)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         if packet is None:</span><br><span>             return</span><br><span> </span><br><span>@@ -760,10 +755,12 @@</span><br><span>         if host not in self.traces:</span><br><span>             self.traces[host] = []</span><br><span>         self.traces[host].append(packet)</span><br><span style="color: hsl(0, 100%, 40%);">-        if packet.packet_type not in self.callbacks:</span><br><span style="color: hsl(0, 100%, 40%);">-            return</span><br><span style="color: hsl(0, 100%, 40%);">-        for callback in self.callbacks[packet.packet_type]:</span><br><span style="color: hsl(0, 100%, 40%);">-            callback(packet)</span><br><span style="color: hsl(120, 100%, 40%);">+        if packet.packet_type in self.callbacks:</span><br><span style="color: hsl(120, 100%, 40%);">+            for callback in self.callbacks[packet.packet_type]:</span><br><span style="color: hsl(120, 100%, 40%);">+                callback(packet)</span><br><span style="color: hsl(120, 100%, 40%);">+        if "*" in self.callbacks:</span><br><span style="color: hsl(120, 100%, 40%);">+            for callback in self.callbacks["*"]:</span><br><span style="color: hsl(120, 100%, 40%);">+                callback(packet)</span><br><span> </span><br><span>     def add_callback(self, packet_type, callback):</span><br><span>         """Add a callback function for received packets of a particular type</span><br><span>@@ -872,11 +869,16 @@</span><br><span>         module_config The module configuration for this pluggable module</span><br><span>         test_object   The object we will attach to</span><br><span>         """</span><br><span style="color: hsl(0, 100%, 40%);">-        if not 'register-observer' in module_config:</span><br><span style="color: hsl(0, 100%, 40%);">-            raise Exception('VOIPListener needs register-observer to be set')</span><br><span style="color: hsl(0, 100%, 40%);">-        VOIPSniffer.__init__(self, module_config, test_object)</span><br><span style="color: hsl(0, 100%, 40%);">-        PcapListener.__init__(self, module_config, test_object)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        VOIPSniffer.__init__(self, module_config, test_object)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        packet_type = module_config.get("packet-type")</span><br><span style="color: hsl(120, 100%, 40%);">+        bpf = module_config.get("bpf-filter")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if packet_type:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.add_callback(packet_type, module_config.get("callback"))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        PcapListener.__init__(self, module_config, test_object)</span><br><span> </span><br><span>     def pcap_callback(self, packet):</span><br><span>         """Packet capture callback function</span><br><span>@@ -888,5 +890,49 @@</span><br><span>         Keyword Arguments:</span><br><span>         packet A received packet from the pcap listener</span><br><span>         """</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         self.process_packet(packet, (None, None))</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# This is a unit test for capture and parsing.</span><br><span style="color: hsl(120, 100%, 40%);">+# By default it listens on the loopback interface</span><br><span style="color: hsl(120, 100%, 40%);">+# UDP port 5060.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def callback(packet):</span><br><span style="color: hsl(120, 100%, 40%);">+        print(packet)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def signal_handler(sig, frame):</span><br><span style="color: hsl(120, 100%, 40%);">+        print('You pressed Ctrl+C!')</span><br><span style="color: hsl(120, 100%, 40%);">+        reactor.stop()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    signal.signal(signal.SIGINT, signal_handler)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    parser = argparse.ArgumentParser(description="pcap unit test")</span><br><span style="color: hsl(120, 100%, 40%);">+    parser.add_argument("-i", "--interface", metavar="i", action="store",</span><br><span style="color: hsl(120, 100%, 40%);">+                      type=str, dest="interface", default="lo",</span><br><span style="color: hsl(120, 100%, 40%);">+                      help="Interface to listen on")</span><br><span style="color: hsl(120, 100%, 40%);">+    parser.add_argument("-f", "--filter", metavar="f", action="store",</span><br><span style="color: hsl(120, 100%, 40%);">+                      type=str, dest="filter", default="udp port 5060",</span><br><span style="color: hsl(120, 100%, 40%);">+                      help="BPF Filter")</span><br><span style="color: hsl(120, 100%, 40%);">+    parser.add_argument("-o", "--output", metavar="o", action="store",</span><br><span style="color: hsl(120, 100%, 40%);">+                      type=str, dest="output", default="/tmp/pcap_unit_test.pcap",</span><br><span style="color: hsl(120, 100%, 40%);">+                      help="Output file")</span><br><span style="color: hsl(120, 100%, 40%);">+    options = parser.parse_args()</span><br><span style="color: hsl(120, 100%, 40%);">+    print('Listening on "%s", using filter "%s", capturing to "%s"'</span><br><span style="color: hsl(120, 100%, 40%);">+          % (options.interface, options.filter, options.output))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    module_config = {</span><br><span style="color: hsl(120, 100%, 40%);">+        "device": options.interface,</span><br><span style="color: hsl(120, 100%, 40%);">+        "bpf-filter": options.filter,</span><br><span style="color: hsl(120, 100%, 40%);">+        "filename": options.output,</span><br><span style="color: hsl(120, 100%, 40%);">+        "snaplen": 65535,</span><br><span style="color: hsl(120, 100%, 40%);">+        "buffer-size": 0,</span><br><span style="color: hsl(120, 100%, 40%);">+        "callback": callback,</span><br><span style="color: hsl(120, 100%, 40%);">+        "debug-packets": True,</span><br><span style="color: hsl(120, 100%, 40%);">+        "packet-type": "*"</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    pcap = VOIPListener(module_config, None)</span><br><span style="color: hsl(120, 100%, 40%);">+    reactor.run()</span><br><span>diff --git a/lib/python/asterisk/test_case.py b/lib/python/asterisk/test_case.py</span><br><span>index 7bf6d16..1c7edfa 100644</span><br><span>--- a/lib/python/asterisk/test_case.py</span><br><span>+++ b/lib/python/asterisk/test_case.py</span><br><span>@@ -138,7 +138,6 @@</span><br><span>         self._stop_callbacks = []</span><br><span>         self._ami_connect_callbacks = []</span><br><span>         self._ami_reconnect_callbacks = []</span><br><span style="color: hsl(0, 100%, 40%);">-        self._pcap_callbacks = []</span><br><span>         self._stop_deferred = None</span><br><span>         log_full = True</span><br><span>         log_messages = True</span><br><span>@@ -396,7 +395,7 @@</span><br><span>         # tests can create their own. Tests may only want to watch a specific</span><br><span>         # port, while a general logger will want to watch more general traffic</span><br><span>         # which can be filtered later.</span><br><span style="color: hsl(0, 100%, 40%);">-        return PcapListener(device, bpf_filter, dumpfile, self._pcap_callback,</span><br><span style="color: hsl(120, 100%, 40%);">+        return PcapListener(device, bpf_filter, dumpfile, self.pcap_callback,</span><br><span>                             snaplen, buffer_size)</span><br><span> </span><br><span>     def start_asterisk(self):</span><br><span>@@ -622,12 +621,6 @@</span><br><span>         """Virtual method used to receive captured packets."""</span><br><span>         pass</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    def _pcap_callback(self, packet):</span><br><span style="color: hsl(0, 100%, 40%);">-        """Packet capture callback"""</span><br><span style="color: hsl(0, 100%, 40%);">-        self.pcap_callback(packet)</span><br><span style="color: hsl(0, 100%, 40%);">-        for callback in self._pcap_callbacks:</span><br><span style="color: hsl(0, 100%, 40%);">-            callback(packet)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>     def handle_originate_failure(self, reason):</span><br><span>         """Fail the test on an Originate failure</span><br><span> </span><br><span>@@ -676,17 +669,6 @@</span><br><span> </span><br><span>         return self.passed</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    def register_pcap_observer(self, callback):</span><br><span style="color: hsl(0, 100%, 40%);">-        """Register an observer that will be called when a packet is received</span><br><span style="color: hsl(0, 100%, 40%);">-        from a created pcap listener</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        Keyword Arguments:</span><br><span style="color: hsl(0, 100%, 40%);">-        callback The callback to receive the packet. The callback function</span><br><span style="color: hsl(0, 100%, 40%);">-                 should take in a single parameter, which will be the packet</span><br><span style="color: hsl(0, 100%, 40%);">-                 received</span><br><span style="color: hsl(0, 100%, 40%);">-        """</span><br><span style="color: hsl(0, 100%, 40%);">-        self._pcap_callbacks.append(callback)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>     def register_start_observer(self, callback):</span><br><span>         """Register an observer that will be called when all Asterisk instances</span><br><span>         have started</span><br><span>diff --git a/lib/python/protocols/LICENSE.md b/lib/python/protocols/LICENSE.md</span><br><span>new file mode 100644</span><br><span>index 0000000..366ed6e</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/LICENSE.md</span><br><span>@@ -0,0 +1,24 @@</span><br><span style="color: hsl(120, 100%, 40%);">+```</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2006-2018</span><br><span style="color: hsl(120, 100%, 40%);">+    Arkadiusz Bulski (arek.bulski@gmail.com)</span><br><span style="color: hsl(120, 100%, 40%);">+    Tomer Filiba (tomerfiliba@gmail.com)</span><br><span style="color: hsl(120, 100%, 40%);">+    Corbin Simpson (MostAwesomeDude@gmail.com)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Permission is hereby granted, free of charge, to any person obtaining a copy</span><br><span style="color: hsl(120, 100%, 40%);">+of this software and associated documentation files (the "Software"), to deal</span><br><span style="color: hsl(120, 100%, 40%);">+in the Software without restriction, including without limitation the rights</span><br><span style="color: hsl(120, 100%, 40%);">+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</span><br><span style="color: hsl(120, 100%, 40%);">+copies of the Software, and to permit persons to whom the Software is</span><br><span style="color: hsl(120, 100%, 40%);">+furnished to do so, subject to the following conditions:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The above copyright notice and this permission notice shall be included in all</span><br><span style="color: hsl(120, 100%, 40%);">+copies or substantial portions of the Software.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</span><br><span style="color: hsl(120, 100%, 40%);">+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</span><br><span style="color: hsl(120, 100%, 40%);">+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE</span><br><span style="color: hsl(120, 100%, 40%);">+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</span><br><span style="color: hsl(120, 100%, 40%);">+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,</span><br><span style="color: hsl(120, 100%, 40%);">+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE</span><br><span style="color: hsl(120, 100%, 40%);">+SOFTWARE.</span><br><span style="color: hsl(120, 100%, 40%);">+```</span><br><span>\ No newline at end of file</span><br><span>diff --git a/lib/python/protocols/README.md b/lib/python/protocols/README.md</span><br><span>new file mode 100644</span><br><span>index 0000000..171a5e1</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/README.md</span><br><span>@@ -0,0 +1,47 @@</span><br><span style="color: hsl(120, 100%, 40%);">+## protocols</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The "protocols" module provides parsing for PCAP packets</span><br><span style="color: hsl(120, 100%, 40%);">+layers 2-4 (Ethernet, IPv4/IPv6, UDP/TCP).  The</span><br><span style="color: hsl(120, 100%, 40%);">+Testsuite uses it to parse packets for the tests that</span><br><span style="color: hsl(120, 100%, 40%);">+need that functionality.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+It was originally part of the</span><br><span style="color: hsl(120, 100%, 40%);">+[construct](https://github.com/construct/construct)</span><br><span style="color: hsl(120, 100%, 40%);">+module but was removed after v2.5.5.  Unfortunately,</span><br><span style="color: hsl(120, 100%, 40%);">+it was and is the only standalone/low overhead packet parsing</span><br><span style="color: hsl(120, 100%, 40%);">+module available.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This python package is an extract from the</span><br><span style="color: hsl(120, 100%, 40%);">+[construct](https://github.com/construct/construct)</span><br><span style="color: hsl(120, 100%, 40%);">+package v2.5.5.  Since construct itself underwent</span><br><span style="color: hsl(120, 100%, 40%);">+major API changes since v2.5.5, the protocols</span><br><span style="color: hsl(120, 100%, 40%);">+code needed significant work to make it compatible</span><br><span style="color: hsl(120, 100%, 40%);">+with the current construct version (2.9 at the</span><br><span style="color: hsl(120, 100%, 40%);">+time of this writing).  Since no functional changes</span><br><span style="color: hsl(120, 100%, 40%);">+were made, only API compatibility changes, the</span><br><span style="color: hsl(120, 100%, 40%);">+original construct (license)[LICENSE.md] still</span><br><span style="color: hsl(120, 100%, 40%);">+applies and is included here.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This module is compatible with both python2 and</span><br><span style="color: hsl(120, 100%, 40%);">+python3.  It also contains unit tests for every</span><br><span style="color: hsl(120, 100%, 40%);">+parser including the top-level ipstack wrapper.</span><br><span style="color: hsl(120, 100%, 40%);">+To run the unit tests, you must add</span><br><span style="color: hsl(120, 100%, 40%);">+`<testsuite_path>/lib/python` to the `PYTHONPATH`</span><br><span style="color: hsl(120, 100%, 40%);">+environment variable.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Example</span><br><span style="color: hsl(120, 100%, 40%);">+```</span><br><span style="color: hsl(120, 100%, 40%);">+# cd /usr/src/asterisk/testsuite/lib/python</span><br><span style="color: hsl(120, 100%, 40%);">+# PYTHONPATH=/usr/src/asterisk/testsuite/lib/python python3</span><br><span style="color: hsl(120, 100%, 40%);">+./ipstack.py</span><br><span style="color: hsl(120, 100%, 40%);">+```</span><br><span style="color: hsl(120, 100%, 40%);">+Or...</span><br><span style="color: hsl(120, 100%, 40%);">+```</span><br><span style="color: hsl(120, 100%, 40%);">+# cd /usr/src/asterisk/testsuite/lib/python</span><br><span style="color: hsl(120, 100%, 40%);">+# PYTHONPATH=../ python3 ./ipstack.py</span><br><span style="color: hsl(120, 100%, 40%);">+```</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+There is also an "unconverted" directory in this</span><br><span style="color: hsl(120, 100%, 40%);">+module which contains parsers we don't use and</span><br><span style="color: hsl(120, 100%, 40%);">+therefore haven't been updated wo work with</span><br><span style="color: hsl(120, 100%, 40%);">+the latest construct.</span><br><span>diff --git a/lib/python/protocols/__init__.py b/lib/python/protocols/__init__.py</span><br><span>new file mode 100644</span><br><span>index 0000000..0ec215e</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/__init__.py</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+protocols - a collection of network protocols</span><br><span style="color: hsl(120, 100%, 40%);">+unlike the formats package, protocols convey information between two sides</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span>diff --git a/lib/python/protocols/application/__init__.py b/lib/python/protocols/application/__init__.py</span><br><span>new file mode 100644</span><br><span>index 0000000..7ea61f7</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/application/__init__.py</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+application layer (various) protocols</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/ipstack.py b/lib/python/protocols/ipstack.py</span><br><span>new file mode 100644</span><br><span>index 0000000..cd63fce</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/ipstack.py</span><br><span>@@ -0,0 +1,146 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+TCP/IP Protocol Stack</span><br><span style="color: hsl(120, 100%, 40%);">+Note: before parsing the application layer over a TCP stream, you must</span><br><span style="color: hsl(120, 100%, 40%);">+first combine all the TCP frames into a stream. See utils.tcpip for</span><br><span style="color: hsl(120, 100%, 40%);">+some solutions</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+#import six</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import Struct, HexDump, Switch, Pass, Computed, Hex, Bytes, setGlobalPrintFullStrings</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.layer2.ethernet import ethernet_header</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.layer3.ipv4 import ipv4_header</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.layer3.ipv6 import ipv6_header</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.layer4.tcp import tcp_header</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.layer4.udp import udp_header</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+setGlobalPrintFullStrings(True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+layer4_tcp = "layer4_tcp" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "layer" / Computed(4),</span><br><span style="color: hsl(120, 100%, 40%);">+    "packet_type" / Computed("TCP"),</span><br><span style="color: hsl(120, 100%, 40%);">+    "header" / tcp_header,</span><br><span style="color: hsl(120, 100%, 40%);">+    "next" / Bytes(lambda ctx: ctx["_"]["header"].payload_length - ctx["header"].header_length)</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+layer4_udp = "layer4_udp" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "layer" / Computed(4),</span><br><span style="color: hsl(120, 100%, 40%);">+    "packet_type" / Computed("UDP"),</span><br><span style="color: hsl(120, 100%, 40%);">+    "header" / udp_header,</span><br><span style="color: hsl(120, 100%, 40%);">+    "next" / Bytes(lambda ctx: ctx["header"].payload_length)</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+layer3_payload = "next" / Switch(lambda ctx: ctx["header"].protocol,</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+        "TCP" : layer4_tcp,</span><br><span style="color: hsl(120, 100%, 40%);">+        "UDP" : layer4_udp,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    default = Pass</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+layer3_ipv4 = "layer3_ipv4" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "layer" / Computed(3),</span><br><span style="color: hsl(120, 100%, 40%);">+    "packet_type" / Computed("IPv4"),</span><br><span style="color: hsl(120, 100%, 40%);">+    "header" / ipv4_header,</span><br><span style="color: hsl(120, 100%, 40%);">+    layer3_payload,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+layer3_ipv6 = "layer3_ipv6" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "layer" / Computed(3),</span><br><span style="color: hsl(120, 100%, 40%);">+    "packet_type" / Computed("IPv6"),</span><br><span style="color: hsl(120, 100%, 40%);">+    "header" / ipv6_header,</span><br><span style="color: hsl(120, 100%, 40%);">+    layer3_payload,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+layer2_ethernet = "layer2_ethernet" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "layer" / Computed(2),</span><br><span style="color: hsl(120, 100%, 40%);">+    "packet_type" / Computed("ETHERNET"),</span><br><span style="color: hsl(120, 100%, 40%);">+    "header" / ethernet_header,</span><br><span style="color: hsl(120, 100%, 40%);">+    "next" / Switch(lambda ctx: ctx["header"].type,</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            "IPv4" : layer3_ipv4,</span><br><span style="color: hsl(120, 100%, 40%);">+            "IPv6" : layer3_ipv6,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+        default = Pass,</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ip_stack = "ip_stack" / layer2_ethernet</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap1 = unhexlify(</span><br><span style="color: hsl(120, 100%, 40%);">+    "0011508c283c001150886b570800450001e971474000800684e4c0a80202525eedda11"</span><br><span style="color: hsl(120, 100%, 40%);">+    "2a0050d98ec61d54fe977d501844705dcc0000474554202f20485454502f312e310d0a"</span><br><span style="color: hsl(120, 100%, 40%);">+    "486f73743a207777772e707974686f6e2e6f72670d0a557365722d4167656e743a204d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420"</span><br><span style="color: hsl(120, 100%, 40%);">+    "352e313b20656e2d55533b2072763a312e382e302e3129204765636b6f2f3230303630"</span><br><span style="color: hsl(120, 100%, 40%);">+    "3131312046697265666f782f312e352e302e310d0a4163636570743a20746578742f78"</span><br><span style="color: hsl(120, 100%, 40%);">+    "6d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "302e382c696d6167652f706e672c2a2f2a3b713d302e350d0a4163636570742d4c616e"</span><br><span style="color: hsl(120, 100%, 40%);">+    "67756167653a20656e2d75732c656e3b713d302e350d0a4163636570742d456e636f64"</span><br><span style="color: hsl(120, 100%, 40%);">+    "696e673a20677a69702c6465666c6174650d0a4163636570742d436861727365743a20"</span><br><span style="color: hsl(120, 100%, 40%);">+    "49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e370d0a4b6565"</span><br><span style="color: hsl(120, 100%, 40%);">+    "702d416c6976653a203330300d0a436f6e6e656374696f6e3a206b6565702d616c6976"</span><br><span style="color: hsl(120, 100%, 40%);">+    "650d0a507261676d613a206e6f2d63616368650d0a43616368652d436f6e74726f6c3a"</span><br><span style="color: hsl(120, 100%, 40%);">+    "206e6f2d63616368650d0a0d0a"</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    cap2 = unhexlify(</span><br><span style="color: hsl(120, 100%, 40%);">+    "0002e3426009001150f2c280080045900598fd22000036063291d149baeec0a8023c00"</span><br><span style="color: hsl(120, 100%, 40%);">+    "500cc33b8aa7dcc4e588065010ffffcecd0000485454502f312e3120323030204f4b0d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "0a446174653a204672692c2031352044656320323030362032313a32363a323520474d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "540d0a5033503a20706f6c6963797265663d22687474703a2f2f7033702e7961686f6f"</span><br><span style="color: hsl(120, 100%, 40%);">+    "2e636f6d2f7733632f7033702e786d6c222c2043503d2243414f2044535020434f5220"</span><br><span style="color: hsl(120, 100%, 40%);">+    "4355522041444d20444556205441492050534120505344204956416920495644692043"</span><br><span style="color: hsl(120, 100%, 40%);">+    "4f4e692054454c6f204f545069204f55522044454c692053414d69204f54526920554e"</span><br><span style="color: hsl(120, 100%, 40%);">+    "5269205055426920494e4420504859204f4e4c20554e49205055522046494e20434f4d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "204e415620494e542044454d20434e542053544120504f4c204845412050524520474f"</span><br><span style="color: hsl(120, 100%, 40%);">+    "56220d0a43616368652d436f6e74726f6c3a20707269766174650d0a566172793a2055"</span><br><span style="color: hsl(120, 100%, 40%);">+    "7365722d4167656e740d0a5365742d436f6f6b69653a20443d5f796c683d58336f444d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "54466b64476c6f5a7a567842463954417a49334d5459784e446b4563476c6b417a4578"</span><br><span style="color: hsl(120, 100%, 40%);">+    "4e6a59794d5463314e5463456447567a64414d7742485274634777446157356b5a5867"</span><br><span style="color: hsl(120, 100%, 40%);">+    "7462412d2d3b20706174683d2f3b20646f6d61696e3d2e7961686f6f2e636f6d0d0a43"</span><br><span style="color: hsl(120, 100%, 40%);">+    "6f6e6e656374696f6e3a20636c6f73650d0a5472616e736665722d456e636f64696e67"</span><br><span style="color: hsl(120, 100%, 40%);">+    "3a206368756e6b65640d0a436f6e74656e742d547970653a20746578742f68746d6c3b"</span><br><span style="color: hsl(120, 100%, 40%);">+    "20636861727365743d7574662d380d0a436f6e74656e742d456e636f64696e673a2067"</span><br><span style="color: hsl(120, 100%, 40%);">+    "7a69700d0a0d0a366263382020200d0a1f8b0800000000000003dcbd6977db38b200fa"</span><br><span style="color: hsl(120, 100%, 40%);">+    "f9fa9cf90f88326dd9b1169212b5d891739cd84ed2936d1277a7d3cbf1a1484a624c91"</span><br><span style="color: hsl(120, 100%, 40%);">+    "0c4979893bbfec7d7bbfec556121012eb29d65e6be7be7762c9240a1502854150a85c2"</span><br><span style="color: hsl(120, 100%, 40%);">+    "c37b87af9f9c7c7873449e9dbc7c41defcf2f8c5f327a4d1ee76dff79e74bb872787ec"</span><br><span style="color: hsl(120, 100%, 40%);">+    "43bfa3e9ddeed1ab06692cd234daed762f2e2e3a17bd4e18cfbb276fbb8b74e9f7bb49"</span><br><span style="color: hsl(120, 100%, 40%);">+    "1a7b76da7152a7b1bff110dfed3f5cb896030f4b37b508566dbb9f56def9a4f1240c52"</span><br><span style="color: hsl(120, 100%, 40%);">+    "3748db275791db20367b9a3452f732a5d0f688bdb0e2c44d27bf9c1cb7470830b1632f"</span><br><span style="color: hsl(120, 100%, 40%);">+    "4a490a3578c18fd6b9c5dec2f7732b2641783109dc0b7268a56e2bd527a931497b93b4"</span><br><span style="color: hsl(120, 100%, 40%);">+    "3f49cd493a98a4c3493a9aa4e349aa6bf01f7cd78d89d6b2ed49b3d9baf223f8b307b5"</span><br><span style="color: hsl(120, 100%, 40%);">+    "004a67eea627ded2dddadedb78d8656de428f856305f5973779223b0fff05ebbbde1db"</span><br><span style="color: hsl(120, 100%, 40%);">+    "67082a499289ae0f06863e1c8f4c0639eaccbdd9a3547abf798a1f0ec6c73fafd2e4f1"</span><br><span style="color: hsl(120, 100%, 40%);">+    "51ffd5f1c9e2f9e37ff74e74fbddd941b375eadb0942b3e3d5723a69f6060373a6cff4"</span><br><span style="color: hsl(120, 100%, 40%);">+    "9e6df586dac8b11c4d1f1afd81319b0df45e6fd4925a6cee6db4dbfb19e225bc1b12e5"</span><br><span style="color: hsl(120, 100%, 40%);">+    "6a098aed9309715c3b74dc5fde3e7f122ea3308061dac22f4018a4f8878367af5f4f2e"</span><br><span style="color: hsl(120, 100%, 40%);">+    "bcc001a2d187bfffbefeb2477f75026be9269165bb93d92ab0532f0cb68264fbda9b6d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "dd0b92bfff867f3abe1bccd3c5f675eca6ab3820c1caf7f7be20e05363029f93c8f7d2"</span><br><span style="color: hsl(120, 100%, 40%);">+    "ad46a7b1bd475ff62614f2de2c8cb7f08537d93a35fed0fe9a4c1af44363fb91beabed"</span><br><span style="color: hsl(120, 100%, 40%);">+    "790f4f0d0e7a6f67c7dbbe3eedfd01e5bcbffe9a64bf289e00307bb1f7852371dadb13"</span><br><span style="color: hsl(120, 100%, 40%);">+    "3df0c3798efba9d93a1db44e87dbd7d8b4cf50e95c780e304be745389fbbf11ef4cddf"</span><br><span style="color: hsl(120, 100%, 40%);">+    "dcf4b162d629fa94d7defbe2fa892b3ece2c78d8fb221a84517003476a73dc3ad535d6"</span><br><span style="color: hsl(120, 100%, 40%);">+    "e22c7fbd0db8cf3a511ca6211d3e28933fed9d8ea54f381f66c0c7f2cb0e4c3898ad2b"</span><br><span style="color: hsl(120, 100%, 40%);">+    "3b0de3c9e918bf25abc88d6ddf02d65581418f94174addc9ebe94717e67ce557207b6d"</span><br><span style="color: hsl(120, 100%, 40%);">+    "45f892773ae393adc62af57c18ecd27b46e5aa2feea5b58c7c173e6d94be1d3bd5afa3"</span><br><span style="color: hsl(120, 100%, 40%);">+    "fcf571d409ded9b1eb06ef3d275d00c36f25f4916c6ed2a911cef88b0e4c0ecfa7a5b6"</span><br><span style="color: hsl(120, 100%, 40%);">+    "27936600b3d28d9bdbe411"</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = ip_stack.parse(cap1)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    # Print just the payload</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj.next.next.next)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = ip_stack.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    assert built == cap1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    print ("-" * 80)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = ip_stack.parse(cap2)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj.next.next.header)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = ip_stack.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    assert built == cap2</span><br><span>diff --git a/lib/python/protocols/layer2/__init__.py b/lib/python/protocols/layer2/__init__.py</span><br><span>new file mode 100644</span><br><span>index 0000000..bdcdb4a</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer2/__init__.py</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+layer 2 (data link) protocols</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer2/arp.py b/lib/python/protocols/layer2/arp.py</span><br><span>new file mode 100644</span><br><span>index 0000000..a88acfa</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer2/arp.py</span><br><span>@@ -0,0 +1,103 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Ethernet (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.layer3.ipv4 import IpAddress</span><br><span style="color: hsl(120, 100%, 40%);">+from ethernet import MacAddress</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+def HwAddress(name):</span><br><span style="color: hsl(120, 100%, 40%);">+    return IfThenElse(name, lambda ctx: ctx.hardware_type == "ETHERNET",</span><br><span style="color: hsl(120, 100%, 40%);">+        MacAddressAdapter(Field("data", lambda ctx: ctx.hwaddr_length)),</span><br><span style="color: hsl(120, 100%, 40%);">+        Field("data", lambda ctx: ctx.hwaddr_length)</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def ProtoAddress(name):</span><br><span style="color: hsl(120, 100%, 40%);">+    return IfThenElse(name, lambda ctx: ctx.protocol_type == "IP",</span><br><span style="color: hsl(120, 100%, 40%);">+        IpAddressAdapter(Field("data", lambda ctx: ctx.protoaddr_length)),</span><br><span style="color: hsl(120, 100%, 40%);">+        Field("data", lambda ctx: ctx.protoaddr_length)</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def HardwareTypeEnum(code):</span><br><span style="color: hsl(120, 100%, 40%);">+    return Enum(code,</span><br><span style="color: hsl(120, 100%, 40%);">+        ETHERNET = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        EXPERIMENTAL_ETHERNET = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        ProNET_TOKEN_RING = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        CHAOS = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        IEEE802 = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        ARCNET = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+        HYPERCHANNEL = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        ULTRALINK = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+        FRAME_RELAY = 15,</span><br><span style="color: hsl(120, 100%, 40%);">+        FIBRE_CHANNEL = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+        IEEE1394 = 24,</span><br><span style="color: hsl(120, 100%, 40%);">+        HIPARP = 28,</span><br><span style="color: hsl(120, 100%, 40%);">+        ISO7816_3 = 29,</span><br><span style="color: hsl(120, 100%, 40%);">+        ARPSEC = 30,</span><br><span style="color: hsl(120, 100%, 40%);">+        IPSEC_TUNNEL = 31,</span><br><span style="color: hsl(120, 100%, 40%);">+        INFINIBAND = 32,</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def OpcodeEnum(code):</span><br><span style="color: hsl(120, 100%, 40%);">+    return Enum(code,</span><br><span style="color: hsl(120, 100%, 40%);">+        REQUEST = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        REPLY = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        REQUEST_REVERSE = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+        REPLY_REVERSE = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        DRARP_REQUEST = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        DRARP_REPLY = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        DRARP_ERROR = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+        InARP_REQUEST = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        InARP_REPLY = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+        ARP_NAK = 10</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+arp_header = "arp_header" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "hardware_type" / HardwareTypeEnum(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "protocol_type" / Enum(Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+        IP = 0x0800,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    "hwaddr_length" / Int8ub,</span><br><span style="color: hsl(120, 100%, 40%);">+    "protoaddr_length" / Int8ub,</span><br><span style="color: hsl(120, 100%, 40%);">+    "opcode" / OpcodeEnum(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "source_hwaddr" / MacAddress(),</span><br><span style="color: hsl(120, 100%, 40%);">+    "source_protoaddr" / IpAddress(),</span><br><span style="color: hsl(120, 100%, 40%);">+    "dest_hwaddr" / MacAddress(),</span><br><span style="color: hsl(120, 100%, 40%);">+    "dest_protoaddr" / IpAddress(),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+rarp_header = "rarp_header" / arp_header</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap1 = unhexlify(b"00010800060400010002e3426009c0a80204000000000000c0a80201")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = arp_header.parse(cap1)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = arp_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert built == cap1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    print ("-" * 80)</span><br><span style="color: hsl(120, 100%, 40%);">+    </span><br><span style="color: hsl(120, 100%, 40%);">+    cap2 = unhexlify(b"00010800060400020011508c283cc0a802010002e3426009c0a80204")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = arp_header.parse(cap2)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = arp_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert built == cap2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer2/ethernet.py b/lib/python/protocols/layer2/ethernet.py</span><br><span>new file mode 100644</span><br><span>index 0000000..15a52aa</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer2/ethernet.py</span><br><span>@@ -0,0 +1,40 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Ethernet (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import hexlify, unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class MacAddressAdapter(Adapter):</span><br><span style="color: hsl(120, 100%, 40%);">+    def _encode(self, obj, context, path):</span><br><span style="color: hsl(120, 100%, 40%);">+        return unhexlify(obj.replace("-", ""))</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode(self, obj, context, path):</span><br><span style="color: hsl(120, 100%, 40%);">+        return "-".join(hexlify(b) for b in obj)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def MacAddress():</span><br><span style="color: hsl(120, 100%, 40%);">+    return MacAddressAdapter(Bytes(6))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ethernet_header = "ethernet_header" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "destination" / MacAddress(),</span><br><span style="color: hsl(120, 100%, 40%);">+    "source" / MacAddress(),</span><br><span style="color: hsl(120, 100%, 40%);">+    "type" / Enum(Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+        IPv4=0x0800,</span><br><span style="color: hsl(120, 100%, 40%);">+        ARP=0x0806,</span><br><span style="color: hsl(120, 100%, 40%);">+        RARP=0x8035,</span><br><span style="color: hsl(120, 100%, 40%);">+        X25=0x0805,</span><br><span style="color: hsl(120, 100%, 40%);">+        IPX=0x8137,</span><br><span style="color: hsl(120, 100%, 40%);">+        IPv6=0x86DD</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap = unhexlify(b"0011508c283c0002e34260090800")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = ethernet_header.parse(cap)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = ethernet_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert built == cap</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer2/mtp2.py b/lib/python/protocols/layer2/mtp2.py</span><br><span>new file mode 100644</span><br><span>index 0000000..c73ade9</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer2/mtp2.py</span><br><span>@@ -0,0 +1,30 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Message Transport Part 2 (SS7 protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+(untested)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+mtp2_header = "mtp2_header" / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "flag1" / Octet,</span><br><span style="color: hsl(120, 100%, 40%);">+    "bsn" / BitsInteger(7),</span><br><span style="color: hsl(120, 100%, 40%);">+    "bib" / Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+    "fsn" / BitsInteger(7),</span><br><span style="color: hsl(120, 100%, 40%);">+    "sib" / Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+    "length" / Octet,</span><br><span style="color: hsl(120, 100%, 40%);">+    "service_info" / Octet,</span><br><span style="color: hsl(120, 100%, 40%);">+    "signalling_info" / Octet,</span><br><span style="color: hsl(120, 100%, 40%);">+    "crc" / BitsInteger(16),</span><br><span style="color: hsl(120, 100%, 40%);">+    "flag2" / Octet,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap = unhexlify(b"0bcc003500280689aa")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = mtp2_header.parse(cap)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = mtp2_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert cap == built</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer3/__init__.py b/lib/python/protocols/layer3/__init__.py</span><br><span>new file mode 100644</span><br><span>index 0000000..4477713</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer3/__init__.py</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+layer 3 (network) protocols</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer3/ipv4.py b/lib/python/protocols/layer3/ipv4.py</span><br><span>new file mode 100644</span><br><span>index 0000000..2ea0ad9</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer3/ipv4.py</span><br><span>@@ -0,0 +1,73 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Internet Protocol version 4 (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class IpAddressAdapter(Adapter):</span><br><span style="color: hsl(120, 100%, 40%);">+    def _encode(self, obj, context, path):</span><br><span style="color: hsl(120, 100%, 40%);">+        return "".join(chr(int(b)) for b in obj.split("."))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode(self, obj, context, path):</span><br><span style="color: hsl(120, 100%, 40%);">+        return ".".join(str(ord(b)) for b in obj)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def IpAddress():</span><br><span style="color: hsl(120, 100%, 40%);">+    return IpAddressAdapter(Bytes(4))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def ProtocolEnum(code):</span><br><span style="color: hsl(120, 100%, 40%);">+    return Enum(code,</span><br><span style="color: hsl(120, 100%, 40%);">+        ICMP = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        TCP = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        UDP = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ipv4_header = "ip_header" / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+   "version" / Nibble,</span><br><span style="color: hsl(120, 100%, 40%);">+   "header_length" / ExprAdapter(Nibble,</span><br><span style="color: hsl(120, 100%, 40%);">+        lambda obj, ctx: obj * 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        lambda obj, ctx: obj / 4</span><br><span style="color: hsl(120, 100%, 40%);">+        ),</span><br><span style="color: hsl(120, 100%, 40%);">+    "tos" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+        "precedence" / BitsInteger(3),</span><br><span style="color: hsl(120, 100%, 40%);">+        "minimize_delay" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "high_throuput" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "high_reliability" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "minimize_cost" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        Padding(1),</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    "total_length" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "payload_length" / Computed(lambda ctx: ctx.total_length - ctx.header_length),</span><br><span style="color: hsl(120, 100%, 40%);">+    "identification" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "flags" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+        Padding(1),</span><br><span style="color: hsl(120, 100%, 40%);">+        "dont_fragment" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "more_fragments" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    "frame_offset" / BitsInteger(13),</span><br><span style="color: hsl(120, 100%, 40%);">+    "ttl" / Bytewise(Int8ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "protocol" / Bytewise(ProtocolEnum(Int8ub)),</span><br><span style="color: hsl(120, 100%, 40%);">+    "checksum" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "source" / Bytewise(IpAddress()),</span><br><span style="color: hsl(120, 100%, 40%);">+    "destination" / Bytewise(IpAddress()),</span><br><span style="color: hsl(120, 100%, 40%);">+    "options" / Computed(lambda ctx: ctx.header_length - 20),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap = unhexlify(b"4600003ca0e3000080116185c0a80205d474a126")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = ipv4_header.parse(cap)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = ipv4_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert built == cap</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer3/ipv6.py b/lib/python/protocols/layer3/ipv6.py</span><br><span>new file mode 100644</span><br><span>index 0000000..cfc345b</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer3/ipv6.py</span><br><span>@@ -0,0 +1,39 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Internet Protocol version 6 (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.layer3.ipv4 import ProtocolEnum</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class Ipv6AddressAdapter(Adapter):</span><br><span style="color: hsl(120, 100%, 40%);">+    def _encode(self, obj, context, path):</span><br><span style="color: hsl(120, 100%, 40%);">+        return "".join(part.decode("hex") for part in obj.split(":"))</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode(self, obj, context, path):</span><br><span style="color: hsl(120, 100%, 40%);">+        return ":".join(b.encode("hex") for b in obj)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def Ipv6Address():</span><br><span style="color: hsl(120, 100%, 40%);">+    return Ipv6AddressAdapter(Bytes(16))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ipv6_header = "ip_header" / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "version" / OneOf(BitsInteger(4), [6]),</span><br><span style="color: hsl(120, 100%, 40%);">+    "traffic_class" / BitsInteger(8),</span><br><span style="color: hsl(120, 100%, 40%);">+    "flow_label" / BitsInteger(20),</span><br><span style="color: hsl(120, 100%, 40%);">+    "payload_length" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "protocol" / Bytewise(ProtocolEnum(Int8ub)),</span><br><span style="color: hsl(120, 100%, 40%);">+    "ttl" / Bytewise(Int8ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "source" / Bytewise(Ipv6Address()),</span><br><span style="color: hsl(120, 100%, 40%);">+    "destination" / Bytewise(Ipv6Address()),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap = unhexlify(b"6ff0000001020680" b"0123456789ABCDEF" b"FEDCBA9876543210" b"FEDCBA9876543210" b"0123456789ABCDEF")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = ipv6_header.parse(cap)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = ipv6_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert built == cap</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer4/__init__.py b/lib/python/protocols/layer4/__init__.py</span><br><span>new file mode 100644</span><br><span>index 0000000..38693c6</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer4/__init__.py</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+layer 4 (transporation) protocols</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer4/tcp.py b/lib/python/protocols/layer4/tcp.py</span><br><span>new file mode 100644</span><br><span>index 0000000..b2d3162</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer4/tcp.py</span><br><span>@@ -0,0 +1,63 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Transmission Control Protocol (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+setGlobalPrintFullStrings(True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+tcp_header = "tcp_header" / BitStruct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "source" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "destination" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "seq" / Bytewise(Int32ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "ack" / Bytewise(Int32ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "header_length" / ExprAdapter(Nibble,</span><br><span style="color: hsl(120, 100%, 40%);">+        encoder = lambda obj, ctx: obj / 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        decoder = lambda obj, ctx: obj * 4,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Padding(3),</span><br><span style="color: hsl(120, 100%, 40%);">+    "flags" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+        "ns" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "cwr" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "ece" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "urg" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "ack" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "psh" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "rst" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "syn" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+        "fin" / Flag,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    "window" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "checksum" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "urgent" / Bytewise(Int16ub),</span><br><span style="color: hsl(120, 100%, 40%);">+    "options" / Computed(lambda ctx: ctx.header_length - 20),</span><br><span style="color: hsl(120, 100%, 40%);">+#    "_payload" / Bytewise(GreedyBytes),</span><br><span style="color: hsl(120, 100%, 40%);">+#    "payload_length" / Computed(lambda ctx: len(ctx._payload)),</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap = unhexlify(b"0db5005062303fb21836e9e650184470c9bc000031323334")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = tcp_header.parse(cap)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = tcp_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert cap == built</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/layer4/udp.py b/lib/python/protocols/layer4/udp.py</span><br><span>new file mode 100644</span><br><span>index 0000000..6b4bcb1</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/layer4/udp.py</span><br><span>@@ -0,0 +1,29 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+User Datagram Protocol (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+udp_header = "udp_header" / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+    "header_length" / Computed(lambda ctx: 8),</span><br><span style="color: hsl(120, 100%, 40%);">+    "source" / Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+    "destination" / Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+    "payload_length" / ExprAdapter(Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+        encoder = lambda obj, ctx: obj + 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        decoder = lambda obj, ctx: obj - 8,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    "checksum" / Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap = unhexlify(b"0bcc003500280689")</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = udp_header.parse(cap)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    built = udp_header.build(obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print(repr(built))</span><br><span style="color: hsl(120, 100%, 40%);">+    assert cap == built</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/unconverted/application/dns.py b/lib/python/protocols/unconverted/application/dns.py</span><br><span>new file mode 100644</span><br><span>index 0000000..d157227</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/unconverted/application/dns.py</span><br><span>@@ -0,0 +1,143 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Domain Name System (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.protocols.layer3.ipv4 import IpAddressAdapter</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class DnsStringAdapter(Adapter):</span><br><span style="color: hsl(120, 100%, 40%);">+    def _encode(self, obj, context):</span><br><span style="color: hsl(120, 100%, 40%);">+        parts = obj.split(".")</span><br><span style="color: hsl(120, 100%, 40%);">+        parts.append("")</span><br><span style="color: hsl(120, 100%, 40%);">+        return parts</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode(self, obj, context):</span><br><span style="color: hsl(120, 100%, 40%);">+        return ".".join(obj[:-1])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dns_record_class = Enum(UBInt16("class"),</span><br><span style="color: hsl(120, 100%, 40%);">+    RESERVED = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    INTERNET = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+    CHAOS = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+    HESIOD = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+    NONE = 254,</span><br><span style="color: hsl(120, 100%, 40%);">+    ANY = 255,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dns_record_type = Enum(UBInt16("type"),</span><br><span style="color: hsl(120, 100%, 40%);">+    IPv4 = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+    AUTHORITIVE_NAME_SERVER = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+    CANONICAL_NAME = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+    NULL = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+    MAIL_EXCHANGE = 15,</span><br><span style="color: hsl(120, 100%, 40%);">+    TEXT = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+    X25 = 19,</span><br><span style="color: hsl(120, 100%, 40%);">+    ISDN = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+    IPv6 = 28,</span><br><span style="color: hsl(120, 100%, 40%);">+    UNSPECIFIED = 103,</span><br><span style="color: hsl(120, 100%, 40%);">+    ALL = 255,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+query_record = Struct("query_record",</span><br><span style="color: hsl(120, 100%, 40%);">+    DnsStringAdapter(</span><br><span style="color: hsl(120, 100%, 40%);">+        RepeatUntil(lambda obj, ctx: obj == "",</span><br><span style="color: hsl(120, 100%, 40%);">+            PascalString("name")</span><br><span style="color: hsl(120, 100%, 40%);">+        )</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    dns_record_type,</span><br><span style="color: hsl(120, 100%, 40%);">+    dns_record_class,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+rdata = Field("rdata", lambda ctx: ctx.rdata_length)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+resource_record = Struct("resource_record",</span><br><span style="color: hsl(120, 100%, 40%);">+    CString("name", terminators = b"\xc0\x00"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Padding(1),</span><br><span style="color: hsl(120, 100%, 40%);">+    dns_record_type,</span><br><span style="color: hsl(120, 100%, 40%);">+    dns_record_class,</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt32("ttl"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("rdata_length"),</span><br><span style="color: hsl(120, 100%, 40%);">+    IfThenElse("data", lambda ctx: ctx.type == "IPv4",</span><br><span style="color: hsl(120, 100%, 40%);">+        IpAddressAdapter(rdata),</span><br><span style="color: hsl(120, 100%, 40%);">+        rdata</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dns = Struct("dns",</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("id"),</span><br><span style="color: hsl(120, 100%, 40%);">+    BitStruct("flags",</span><br><span style="color: hsl(120, 100%, 40%);">+        Enum(Bit("type"),</span><br><span style="color: hsl(120, 100%, 40%);">+            QUERY = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            RESPONSE = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        ),</span><br><span style="color: hsl(120, 100%, 40%);">+        Enum(Nibble("opcode"),</span><br><span style="color: hsl(120, 100%, 40%);">+            STANDARD_QUERY = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            INVERSE_QUERY = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+            SERVER_STATUS_REQUEST = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+            NOTIFY = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+            UPDATE = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        ),</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag("authoritive_answer"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag("truncation"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag("recurssion_desired"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag("recursion_available"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Padding(1),</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag("authenticated_data"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag("checking_disabled"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Enum(Nibble("response_code"),</span><br><span style="color: hsl(120, 100%, 40%);">+            SUCCESS = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            FORMAT_ERROR = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+            SERVER_FAILURE = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+            NAME_DOES_NOT_EXIST = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+            NOT_IMPLEMENTED = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+            REFUSED = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+            NAME_SHOULD_NOT_EXIST = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+            RR_SHOULD_NOT_EXIST = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+            RR_SHOULD_EXIST = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+            NOT_AUTHORITIVE = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+            NOT_ZONE = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+        ),</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("question_count"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("answer_count"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("authority_count"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("additional_count"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Array(lambda ctx: ctx.question_count,</span><br><span style="color: hsl(120, 100%, 40%);">+        Rename("questions", query_record),</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Rename("answers",</span><br><span style="color: hsl(120, 100%, 40%);">+        Array(lambda ctx: ctx.answer_count, resource_record)</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Rename("authorities",</span><br><span style="color: hsl(120, 100%, 40%);">+        Array(lambda ctx: ctx.authority_count, resource_record)</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Array(lambda ctx: ctx.additional_count,</span><br><span style="color: hsl(120, 100%, 40%);">+        Rename("additionals", resource_record),</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap1 = unhexlify(b"2624010000010000000000000377777706676f6f676c6503636f6d0000010001")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    cap2 = unhexlify(six.b(</span><br><span style="color: hsl(120, 100%, 40%);">+    "2624818000010005000600060377777706676f6f676c6503636f6d0000010001c00c00"</span><br><span style="color: hsl(120, 100%, 40%);">+    "05000100089065000803777777016cc010c02c0001000100000004000440e9b768c02c"</span><br><span style="color: hsl(120, 100%, 40%);">+    "0001000100000004000440e9b793c02c0001000100000004000440e9b763c02c000100"</span><br><span style="color: hsl(120, 100%, 40%);">+    "0100000004000440e9b767c030000200010000a88600040163c030c030000200010000"</span><br><span style="color: hsl(120, 100%, 40%);">+    "a88600040164c030c030000200010000a88600040165c030c030000200010000a88600"</span><br><span style="color: hsl(120, 100%, 40%);">+    "040167c030c030000200010000a88600040161c030c030000200010000a88600040162"</span><br><span style="color: hsl(120, 100%, 40%);">+    "c030c0c00001000100011d0c0004d8ef3509c0d0000100010000ca7c000440e9b309c0"</span><br><span style="color: hsl(120, 100%, 40%);">+    "80000100010000c4c5000440e9a109c0900001000100004391000440e9b709c0a00001"</span><br><span style="color: hsl(120, 100%, 40%);">+    "00010000ca7c000442660b09c0b00001000100000266000440e9a709"</span><br><span style="color: hsl(120, 100%, 40%);">+    ))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = dns.parse(cap1)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (repr(dns.build(obj)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    print ("-" * 80)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    obj = dns.parse(cap2)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (obj)</span><br><span style="color: hsl(120, 100%, 40%);">+    print (repr(dns.build(obj)))</span><br><span>diff --git a/lib/python/protocols/unconverted/layer3/dhcpv4.py b/lib/python/protocols/unconverted/layer3/dhcpv4.py</span><br><span>new file mode 100644</span><br><span>index 0000000..d0e5a07</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/unconverted/layer3/dhcpv4.py</span><br><span>@@ -0,0 +1,195 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Dynamic Host Configuration Protocol for IPv4</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+http://www.networksorcery.com/enp/protocol/dhcp.htm</span><br><span style="color: hsl(120, 100%, 40%);">+http://www.networksorcery.com/enp/protocol/bootp/options.htm</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from ipv4 import IpAddress</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dhcp_option = Struct("dhcp_option",</span><br><span style="color: hsl(120, 100%, 40%);">+    Enum(Byte("code"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Pad = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+        Subnet_Mask = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        Time_Offset = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        Router = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+        Time_Server = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        Name_Server = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        Domain_Name_Server = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        Log_Server = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+        Quote_Server = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        LPR_Server = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+        Impress_Server = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+        Resource_Location_Server = 11,</span><br><span style="color: hsl(120, 100%, 40%);">+        Host_Name = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+        Boot_File_Size = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+        Merit_Dump_File = 14,</span><br><span style="color: hsl(120, 100%, 40%);">+        Domain_Name = 15,</span><br><span style="color: hsl(120, 100%, 40%);">+        Swap_Server = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+        Root_Path = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+        Extensions_Path = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+        IP_Forwarding_enabledisable = 19,</span><br><span style="color: hsl(120, 100%, 40%);">+        Nonlocal_Source_Routing_enabledisable = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+        Policy_Filter = 21,</span><br><span style="color: hsl(120, 100%, 40%);">+        Maximum_Datagram_Reassembly_Size = 22,</span><br><span style="color: hsl(120, 100%, 40%);">+        Default_IP_TTL = 23,</span><br><span style="color: hsl(120, 100%, 40%);">+        Path_MTU_Aging_Timeout = 24,</span><br><span style="color: hsl(120, 100%, 40%);">+        Path_MTU_Plateau_Table = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+        Interface_MTU = 26,</span><br><span style="color: hsl(120, 100%, 40%);">+        All_Subnets_are_Local = 27,</span><br><span style="color: hsl(120, 100%, 40%);">+        Broadcast_Address = 28,</span><br><span style="color: hsl(120, 100%, 40%);">+        Perform_Mask_Discovery = 29,</span><br><span style="color: hsl(120, 100%, 40%);">+        Mask_supplier = 30,</span><br><span style="color: hsl(120, 100%, 40%);">+        Perform_router_discovery = 31,</span><br><span style="color: hsl(120, 100%, 40%);">+        Router_solicitation_address = 32,</span><br><span style="color: hsl(120, 100%, 40%);">+        Static_routing_table = 33,</span><br><span style="color: hsl(120, 100%, 40%);">+        Trailer_encapsulation = 34,</span><br><span style="color: hsl(120, 100%, 40%);">+        ARP_cache_timeout = 35,</span><br><span style="color: hsl(120, 100%, 40%);">+        Ethernet_encapsulation = 36,</span><br><span style="color: hsl(120, 100%, 40%);">+        Default_TCP_TTL = 37,</span><br><span style="color: hsl(120, 100%, 40%);">+        TCP_keepalive_interval = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+        TCP_keepalive_garbage = 39,</span><br><span style="color: hsl(120, 100%, 40%);">+        Network_Information_Service_domain = 40,</span><br><span style="color: hsl(120, 100%, 40%);">+        Network_Information_Servers = 41,</span><br><span style="color: hsl(120, 100%, 40%);">+        NTP_servers = 42,</span><br><span style="color: hsl(120, 100%, 40%);">+        Vendor_specific_information = 43,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetBIOS_over_TCPIP_name_server = 44,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetBIOS_over_TCPIP_Datagram_Distribution_Server = 45,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetBIOS_over_TCPIP_Node_Type = 46,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetBIOS_over_TCPIP_Scope = 47,</span><br><span style="color: hsl(120, 100%, 40%);">+        X_Window_System_Font_Server = 48,</span><br><span style="color: hsl(120, 100%, 40%);">+        X_Window_System_Display_Manager = 49,</span><br><span style="color: hsl(120, 100%, 40%);">+        Requested_IP_Address = 50,</span><br><span style="color: hsl(120, 100%, 40%);">+        IP_address_lease_time = 51,</span><br><span style="color: hsl(120, 100%, 40%);">+        Option_overload = 52,</span><br><span style="color: hsl(120, 100%, 40%);">+        DHCP_message_type = 53,</span><br><span style="color: hsl(120, 100%, 40%);">+        Server_identifier = 54,</span><br><span style="color: hsl(120, 100%, 40%);">+        Parameter_request_list = 55,</span><br><span style="color: hsl(120, 100%, 40%);">+        Message = 56,</span><br><span style="color: hsl(120, 100%, 40%);">+        Maximum_DHCP_message_size = 57,</span><br><span style="color: hsl(120, 100%, 40%);">+        Renew_time_value = 58,</span><br><span style="color: hsl(120, 100%, 40%);">+        Rebinding_time_value = 59,</span><br><span style="color: hsl(120, 100%, 40%);">+        Class_identifier = 60,</span><br><span style="color: hsl(120, 100%, 40%);">+        Client_identifier = 61,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetWareIP_Domain_Name = 62,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetWareIP_information = 63,</span><br><span style="color: hsl(120, 100%, 40%);">+        Network_Information_Service_Domain = 64,</span><br><span style="color: hsl(120, 100%, 40%);">+        Network_Information_Service_Servers = 65,</span><br><span style="color: hsl(120, 100%, 40%);">+        TFTP_server_name = 66,</span><br><span style="color: hsl(120, 100%, 40%);">+        Bootfile_name = 67,</span><br><span style="color: hsl(120, 100%, 40%);">+        Mobile_IP_Home_Agent = 68,</span><br><span style="color: hsl(120, 100%, 40%);">+        Simple_Mail_Transport_Protocol_Server = 69,</span><br><span style="color: hsl(120, 100%, 40%);">+        Post_Office_Protocol_Server = 70,</span><br><span style="color: hsl(120, 100%, 40%);">+        Network_News_Transport_Protocol_Server = 71,</span><br><span style="color: hsl(120, 100%, 40%);">+        Default_World_Wide_Web_Server = 72,</span><br><span style="color: hsl(120, 100%, 40%);">+        Default_Finger_Server = 73,</span><br><span style="color: hsl(120, 100%, 40%);">+        Default_Internet_Relay_Chat_Server = 74,</span><br><span style="color: hsl(120, 100%, 40%);">+        StreetTalk_Server = 75,</span><br><span style="color: hsl(120, 100%, 40%);">+        StreetTalk_Directory_Assistance_Server = 76,</span><br><span style="color: hsl(120, 100%, 40%);">+        User_Class_Information = 77,</span><br><span style="color: hsl(120, 100%, 40%);">+        SLP_Directory_Agent = 78,</span><br><span style="color: hsl(120, 100%, 40%);">+        SLP_Service_Scope = 79,</span><br><span style="color: hsl(120, 100%, 40%);">+        Rapid_Commit = 80,</span><br><span style="color: hsl(120, 100%, 40%);">+        Fully_Qualified_Domain_Name = 81,</span><br><span style="color: hsl(120, 100%, 40%);">+        Relay_Agent_Information = 82,</span><br><span style="color: hsl(120, 100%, 40%);">+        Internet_Storage_Name_Service = 83,</span><br><span style="color: hsl(120, 100%, 40%);">+        NDS_servers = 85,</span><br><span style="color: hsl(120, 100%, 40%);">+        NDS_tree_name = 86,</span><br><span style="color: hsl(120, 100%, 40%);">+        NDS_context = 87,</span><br><span style="color: hsl(120, 100%, 40%);">+        BCMCS_Controller_Domain_Name_list = 88,</span><br><span style="color: hsl(120, 100%, 40%);">+        BCMCS_Controller_IPv4_address_list = 89,</span><br><span style="color: hsl(120, 100%, 40%);">+        Authentication = 90,</span><br><span style="color: hsl(120, 100%, 40%);">+        Client_last_transaction_time = 91,</span><br><span style="color: hsl(120, 100%, 40%);">+        Associated_ip = 92,</span><br><span style="color: hsl(120, 100%, 40%);">+        Client_System_Architecture_Type = 93,</span><br><span style="color: hsl(120, 100%, 40%);">+        Client_Network_Interface_Identifier = 94,</span><br><span style="color: hsl(120, 100%, 40%);">+        Lightweight_Directory_Access_Protocol = 95,</span><br><span style="color: hsl(120, 100%, 40%);">+        Client_Machine_Identifier = 97,</span><br><span style="color: hsl(120, 100%, 40%);">+        Open_Group_User_Authentication = 98,</span><br><span style="color: hsl(120, 100%, 40%);">+        Autonomous_System_Number = 109,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetInfo_Parent_Server_Address = 112,</span><br><span style="color: hsl(120, 100%, 40%);">+        NetInfo_Parent_Server_Tag = 113,</span><br><span style="color: hsl(120, 100%, 40%);">+        URL = 114,</span><br><span style="color: hsl(120, 100%, 40%);">+        Auto_Configure = 116,</span><br><span style="color: hsl(120, 100%, 40%);">+        Name_Service_Search = 117,</span><br><span style="color: hsl(120, 100%, 40%);">+        Subnet_Selection = 118,</span><br><span style="color: hsl(120, 100%, 40%);">+        DNS_domain_search_list = 119,</span><br><span style="color: hsl(120, 100%, 40%);">+        SIP_Servers_DHCP_Option = 120,</span><br><span style="color: hsl(120, 100%, 40%);">+        Classless_Static_Route_Option = 121,</span><br><span style="color: hsl(120, 100%, 40%);">+        CableLabs_Client_Configuration = 122,</span><br><span style="color: hsl(120, 100%, 40%);">+        GeoConf = 123,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Switch("value", lambda ctx: ctx.code,</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            # codes without any value</span><br><span style="color: hsl(120, 100%, 40%);">+            "Pad" : Pass,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+        # codes followed by length and value fields</span><br><span style="color: hsl(120, 100%, 40%);">+        default = Struct("value",</span><br><span style="color: hsl(120, 100%, 40%);">+            Byte("length"),</span><br><span style="color: hsl(120, 100%, 40%);">+            Field("data", lambda ctx: ctx.length),</span><br><span style="color: hsl(120, 100%, 40%);">+        )</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dhcp_header = Struct("dhcp_header",</span><br><span style="color: hsl(120, 100%, 40%);">+    Enum(Byte("opcode"),</span><br><span style="color: hsl(120, 100%, 40%);">+        BootRequest = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        BootReply = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Enum(Byte("hardware_type"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Ethernet = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        Experimental_Ethernet = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        ProNET_Token_Ring = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        Chaos = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        IEEE_802 = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        ARCNET = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+        Hyperchannel = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        Lanstar = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Byte("hardware_address_length"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Byte("hop_count"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt32("transaction_id"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("elapsed_time"),</span><br><span style="color: hsl(120, 100%, 40%);">+    BitStruct("flags",</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag("boardcast"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Padding(15),</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    IpAddress("client_addr"),</span><br><span style="color: hsl(120, 100%, 40%);">+    IpAddress("your_addr"),</span><br><span style="color: hsl(120, 100%, 40%);">+    IpAddress("server_addr"),</span><br><span style="color: hsl(120, 100%, 40%);">+    IpAddress("relay_addr"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Bytes("client_hardware_addr", 16),</span><br><span style="color: hsl(120, 100%, 40%);">+    Bytes("server_host_name", 64),</span><br><span style="color: hsl(120, 100%, 40%);">+    Bytes("boot_filename", 128),</span><br><span style="color: hsl(120, 100%, 40%);">+    # BOOTP/DHCP options</span><br><span style="color: hsl(120, 100%, 40%);">+    # "The first four bytes contain the (decimal) values 99, 130, 83 and 99"</span><br><span style="color: hsl(120, 100%, 40%);">+    Const(Bytes("magic", 4), b"\x63\x82\x53\x63"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Rename("options", OptionalGreedyRange(dhcp_option)),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    test = unhexlify(six.b(</span><br><span style="color: hsl(120, 100%, 40%);">+        "0101060167c05f5a00000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "0102030405060708090a0b0c"</span><br><span style="color: hsl(120, 100%, 40%);">+        "0d0e0f10"</span><br><span style="color: hsl(120, 100%, 40%);">+        "DEADBEEFBEEF"</span><br><span style="color: hsl(120, 100%, 40%);">+        "000000000000000000000000000000000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "000000000000000000000000000000000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "000000000000000000000000000000000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "000000000000000000000000000000000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "000000000000000000000000000000000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "000000000000000000000000000000000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "000000000000000000000000000000000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "00000000000000000000000000"</span><br><span style="color: hsl(120, 100%, 40%);">+        "63825363"</span><br><span style="color: hsl(120, 100%, 40%);">+        "3501083d0701DEADBEEFBEEF0c04417375733c084d53465420352e"</span><br><span style="color: hsl(120, 100%, 40%);">+        "30370d010f03062c2e2f1f2179f92bfc52210117566c616e333338"</span><br><span style="color: hsl(120, 100%, 40%);">+        "382b45746865726e6574312f302f32340206f8f0827348f9ff"</span><br><span style="color: hsl(120, 100%, 40%);">+    ))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    print (dhcp_header.parse(test))</span><br><span>diff --git a/lib/python/protocols/unconverted/layer3/dhcpv6.py b/lib/python/protocols/unconverted/layer3/dhcpv6.py</span><br><span>new file mode 100644</span><br><span>index 0000000..b9ff172</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/unconverted/layer3/dhcpv6.py</span><br><span>@@ -0,0 +1,111 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+the Dynamic Host Configuration Protocol (DHCP) for IPv6</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+http://www.networksorcery.com/enp/rfc/rfc3315.txt</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from ipv6 import Ipv6Address</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dhcp_option = Struct("dhcp_option",</span><br><span style="color: hsl(120, 100%, 40%);">+    Enum(UBInt16("code"),</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_CLIENTID = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_SERVERID = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_IA_NA = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_IA_TA = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_IAADDR = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_ORO = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_PREFERENCE = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_ELAPSED_TIME = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_RELAY_MSG = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_AUTH = 11,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_UNICAST = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_STATUS_CODE = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_RAPID_COMMIT = 14,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_USER_CLASS = 15,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_VENDOR_CLASS = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_VENDOR_OPTS = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_INTERFACE_ID = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_RECONF_MSG = 19,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_RECONF_ACCEPT = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+        SIP_SERVERS_DOMAIN_NAME_LIST = 21,</span><br><span style="color: hsl(120, 100%, 40%);">+        SIP_SERVERS_IPV6_ADDRESS_LIST = 22,</span><br><span style="color: hsl(120, 100%, 40%);">+        DNS_RECURSIVE_NAME_SERVER = 23,</span><br><span style="color: hsl(120, 100%, 40%);">+        DOMAIN_SEARCH_LIST = 24,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_IA_PD = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_IAPREFIX = 26,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_NIS_SERVERS = 27,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_NISP_SERVERS = 28,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_NIS_DOMAIN_NAME = 29,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_NISP_DOMAIN_NAME = 30,</span><br><span style="color: hsl(120, 100%, 40%);">+        SNTP_SERVER_LIST = 31,</span><br><span style="color: hsl(120, 100%, 40%);">+        INFORMATION_REFRESH_TIME = 32,</span><br><span style="color: hsl(120, 100%, 40%);">+        BCMCS_CONTROLLER_DOMAIN_NAME_LIST = 33,</span><br><span style="color: hsl(120, 100%, 40%);">+        BCMCS_CONTROLLER_IPV6_ADDRESS_LIST = 34,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_GEOCONF_CIVIC = 36,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_REMOTE_ID = 37,</span><br><span style="color: hsl(120, 100%, 40%);">+        RELAY_AGENT_SUBSCRIBER_ID = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+        OPTION_CLIENT_FQDN = 39,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("length"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Field("data", lambda ctx: ctx.length),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+client_message = Struct("client_message",</span><br><span style="color: hsl(120, 100%, 40%);">+    Bitwise(BitField("transaction_id", 24)),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+relay_message = Struct("relay_message",</span><br><span style="color: hsl(120, 100%, 40%);">+    Byte("hop_count"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Ipv6Address("linkaddr"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Ipv6Address("peeraddr"),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dhcp_message = Struct("dhcp_message",</span><br><span style="color: hsl(120, 100%, 40%);">+    Enum(Byte("msgtype"),</span><br><span style="color: hsl(120, 100%, 40%);">+        # these are client-server messages</span><br><span style="color: hsl(120, 100%, 40%);">+        SOLICIT = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        ADVERTISE = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+        REQUEST = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+        CONFIRM = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        RENEW = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        REBIND = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        REPLY = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+        RELEASE_ = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        DECLINE_ = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+        RECONFIGURE = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+        INFORMATION_REQUEST = 11,</span><br><span style="color: hsl(120, 100%, 40%);">+        # these two are relay messages</span><br><span style="color: hsl(120, 100%, 40%);">+        RELAY_FORW = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+        RELAY_REPL = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    # relay messages have a different structure from client-server messages</span><br><span style="color: hsl(120, 100%, 40%);">+    Switch("params", lambda ctx: ctx.msgtype,</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            "RELAY_FORW" : relay_message,</span><br><span style="color: hsl(120, 100%, 40%);">+            "RELAY_REPL" : relay_message,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+        default = client_message,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Rename("options", GreedyRange(dhcp_option)),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    test1 = b"\x03\x11\x22\x33\x00\x17\x00\x03ABC\x00\x05\x00\x05HELLO"</span><br><span style="color: hsl(120, 100%, 40%);">+    test2 = b"\x0c\x040123456789abcdef0123456789abcdef\x00\x09\x00\x0bhello world\x00\x01\x00\x00"</span><br><span style="color: hsl(120, 100%, 40%);">+    print (dhcp_message.parse(test1))</span><br><span style="color: hsl(120, 100%, 40%);">+    print (dhcp_message.parse(test2))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/unconverted/layer3/icmpv4.py b/lib/python/protocols/unconverted/layer3/icmpv4.py</span><br><span>new file mode 100644</span><br><span>index 0000000..7a554d1</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/unconverted/layer3/icmpv4.py</span><br><span>@@ -0,0 +1,87 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Internet Control Message Protocol for IPv4 (TCP/IP protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from ipv4 import IpAddress</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+echo_payload = Struct("echo_payload",</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("identifier"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("sequence"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Bytes("data", 32), # length is implementation dependent... </span><br><span style="color: hsl(120, 100%, 40%);">+                       # is anyone using more than 32 bytes?</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dest_unreachable_payload = Struct("dest_unreachable_payload",</span><br><span style="color: hsl(120, 100%, 40%);">+    Padding(2),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("next_hop_mtu"),</span><br><span style="color: hsl(120, 100%, 40%);">+    IpAddress("host"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Bytes("echo", 8),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+dest_unreachable_code = Enum(Byte("code"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Network_unreachable_error = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    Host_unreachable_error = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+    Protocol_unreachable_error = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+    Port_unreachable_error = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+    The_datagram_is_too_big = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+    Source_route_failed_error = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+    Destination_network_unknown_error = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+    Destination_host_unknown_error = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+    Source_host_isolated_error = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+    Desination_administratively_prohibited = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+    Host_administratively_prohibited2 = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+    Network_TOS_unreachable = 11,</span><br><span style="color: hsl(120, 100%, 40%);">+    Host_TOS_unreachable = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+icmp_header = Struct("icmp_header",</span><br><span style="color: hsl(120, 100%, 40%);">+    Enum(Byte("type"),</span><br><span style="color: hsl(120, 100%, 40%);">+        Echo_reply = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+        Destination_unreachable = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+        Source_quench = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+        Redirect = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+        Alternate_host_address = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+        Echo_request = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+        Router_advertisement = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+        Router_solicitation = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+        Time_exceeded = 11,</span><br><span style="color: hsl(120, 100%, 40%);">+        Parameter_problem = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+        Timestamp_request = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+        Timestamp_reply = 14,</span><br><span style="color: hsl(120, 100%, 40%);">+        Information_request = 15,</span><br><span style="color: hsl(120, 100%, 40%);">+        Information_reply = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+        Address_mask_request = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+        Address_mask_reply = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+        _default_ = Pass,</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    Switch("code", lambda ctx: ctx.type,</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            "Destination_unreachable" : dest_unreachable_code,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+        default = Byte("code"),</span><br><span style="color: hsl(120, 100%, 40%);">+    ),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("crc"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Switch("payload", lambda ctx: ctx.type,</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            "Echo_reply" : echo_payload,</span><br><span style="color: hsl(120, 100%, 40%);">+            "Echo_request" : echo_payload,</span><br><span style="color: hsl(120, 100%, 40%);">+            "Destination_unreachable" : dest_unreachable_payload,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span style="color: hsl(120, 100%, 40%);">+        default = Pass</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+    cap1 = unhexlify(six.b("0800305c02001b006162636465666768696a6b6c6d6e6f70717273747576776162"</span><br><span style="color: hsl(120, 100%, 40%);">+        "63646566676869"))</span><br><span style="color: hsl(120, 100%, 40%);">+    cap2 = unhexlify(six.b("0000385c02001b006162636465666768696a6b6c6d6e6f70717273747576776162"</span><br><span style="color: hsl(120, 100%, 40%);">+        "63646566676869"))</span><br><span style="color: hsl(120, 100%, 40%);">+    cap3 = unhexlify(b"0301000000001122aabbccdd0102030405060708")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    print (icmp_header.parse(cap1))</span><br><span style="color: hsl(120, 100%, 40%);">+    print (icmp_header.parse(cap2))</span><br><span style="color: hsl(120, 100%, 40%);">+    print (icmp_header.parse(cap3))</span><br><span>diff --git a/lib/python/protocols/unconverted/layer3/igmpv2.py b/lib/python/protocols/unconverted/layer3/igmpv2.py</span><br><span>new file mode 100644</span><br><span>index 0000000..99ab6db</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/unconverted/layer3/igmpv2.py</span><br><span>@@ -0,0 +1,29 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+What : Internet Group Management Protocol, Version 2</span><br><span style="color: hsl(120, 100%, 40%);">+ How : http://www.ietf.org/rfc/rfc2236.txt</span><br><span style="color: hsl(120, 100%, 40%);">+ Who : jesse @ housejunkie . ca</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from binascii import unhexlify</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import Byte, Enum,Struct, UBInt16</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.protocols.layer3.ipv4 import IpAddress</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+igmp_type = Enum(Byte("igmp_type"),</span><br><span style="color: hsl(120, 100%, 40%);">+    MEMBERSHIP_QUERY = 0x11,</span><br><span style="color: hsl(120, 100%, 40%);">+    MEMBERSHIP_REPORT_V1 = 0x12,</span><br><span style="color: hsl(120, 100%, 40%);">+    MEMBERSHIP_REPORT_V2 = 0x16,</span><br><span style="color: hsl(120, 100%, 40%);">+    LEAVE_GROUP = 0x17,</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+igmpv2_header = Struct("igmpv2_header",</span><br><span style="color: hsl(120, 100%, 40%);">+    igmp_type,</span><br><span style="color: hsl(120, 100%, 40%);">+    Byte("max_resp_time"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("checksum"),</span><br><span style="color: hsl(120, 100%, 40%);">+    IpAddress("group_address"),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == '__main__':</span><br><span style="color: hsl(120, 100%, 40%);">+    capture = unhexlify(b"1600FA01EFFFFFFD")</span><br><span style="color: hsl(120, 100%, 40%);">+    print (igmpv2_header.parse(capture))</span><br><span>diff --git a/lib/python/protocols/unconverted/layer3/mtp3.py b/lib/python/protocols/unconverted/layer3/mtp3.py</span><br><span>new file mode 100644</span><br><span>index 0000000..7f712f2</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/unconverted/layer3/mtp3.py</span><br><span>@@ -0,0 +1,12 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+Message Transport Part 3 (SS7 protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+(untested)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+mtp3_header = BitStruct("mtp3_header",</span><br><span style="color: hsl(120, 100%, 40%);">+    Nibble("service_indicator"),</span><br><span style="color: hsl(120, 100%, 40%);">+    Nibble("subservice"),</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/lib/python/protocols/unconverted/layer4/isup.py b/lib/python/protocols/unconverted/layer4/isup.py</span><br><span>new file mode 100644</span><br><span>index 0000000..8111b60</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/protocols/unconverted/layer4/isup.py</span><br><span>@@ -0,0 +1,15 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+ISDN User Part (SS7 protocol stack)</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+isup_header = Struct("isup_header",</span><br><span style="color: hsl(120, 100%, 40%);">+    Bytes("routing_label", 5),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt16("cic"),</span><br><span style="color: hsl(120, 100%, 40%);">+    UBInt8("message_type"),</span><br><span style="color: hsl(120, 100%, 40%);">+    # mandatory fixed parameters</span><br><span style="color: hsl(120, 100%, 40%);">+    # mandatory variable parameters</span><br><span style="color: hsl(120, 100%, 40%);">+    # optional parameters</span><br><span style="color: hsl(120, 100%, 40%);">+)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/tests/channels/SIP/pcap_demo/run-test b/tests/channels/SIP/pcap_demo/run-test</span><br><span>index 8400a85..ecb2bb0 100755</span><br><span>--- a/tests/channels/SIP/pcap_demo/run-test</span><br><span>+++ b/tests/channels/SIP/pcap_demo/run-test</span><br><span>@@ -9,10 +9,7 @@</span><br><span> from sip_message import SIPMessage, SIPMessageTest</span><br><span> </span><br><span> from twisted.internet import reactor</span><br><span style="color: hsl(0, 100%, 40%);">-try:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct_legacy.protocols.ipstack import ip_stack</span><br><span style="color: hsl(0, 100%, 40%);">-except ImportError:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct.protocols.ipstack import ip_stack</span><br><span style="color: hsl(120, 100%, 40%);">+from protocols.ipstack import ip_stack</span><br><span> </span><br><span> logger = logging.getLogger(__name__)</span><br><span> test1 = [</span><br><span>diff --git a/tests/channels/SIP/pcap_demo/test-config.yaml b/tests/channels/SIP/pcap_demo/test-config.yaml</span><br><span>index 6a5111a..ec151be 100644</span><br><span>--- a/tests/channels/SIP/pcap_demo/test-config.yaml</span><br><span>+++ b/tests/channels/SIP/pcap_demo/test-config.yaml</span><br><span>@@ -16,7 +16,6 @@</span><br><span> properties:</span><br><span>     dependencies:</span><br><span>         - python : 'twisted'</span><br><span style="color: hsl(0, 100%, 40%);">-        - python : 'construct'</span><br><span>         - 'pcap'</span><br><span>         - asterisk : 'chan_sip'</span><br><span>     tags:</span><br><span>diff --git a/tests/channels/pjsip/rtp/rtp_keepalive/base/rtp.py b/tests/channels/pjsip/rtp/rtp_keepalive/base/rtp.py</span><br><span>index 2e325f5..633971d 100644</span><br><span>--- a/tests/channels/pjsip/rtp/rtp_keepalive/base/rtp.py</span><br><span>+++ b/tests/channels/pjsip/rtp/rtp_keepalive/base/rtp.py</span><br><span>@@ -12,11 +12,7 @@</span><br><span> </span><br><span> from twisted.internet.protocol import DatagramProtocol</span><br><span> from twisted.internet import reactor</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-try:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct_legacy import *</span><br><span style="color: hsl(0, 100%, 40%);">-except ImportError:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.pcap import RTPPacket</span><br><span> </span><br><span> sys.path.append('lib/python')</span><br><span> </span><br><span>@@ -30,22 +26,9 @@</span><br><span>         self.test_object.register_stop_observer(self.asterisk_stopped)</span><br><span> </span><br><span>     def datagramReceived(self, data, (host, port)):</span><br><span style="color: hsl(0, 100%, 40%);">-        header = Struct('rtp_packet',</span><br><span style="color: hsl(0, 100%, 40%);">-                        BitStruct('header',</span><br><span style="color: hsl(0, 100%, 40%);">-                                  BitField('version', 2),</span><br><span style="color: hsl(0, 100%, 40%);">-                                  Bit('padding'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                  Bit('extension'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                  Nibble('csrc_count'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                  Bit('marker'),</span><br><span style="color: hsl(0, 100%, 40%);">-                                  BitField('payload', 7)</span><br><span style="color: hsl(0, 100%, 40%);">-                                  ),</span><br><span style="color: hsl(0, 100%, 40%);">-                        UBInt16('sequence_number'),</span><br><span style="color: hsl(0, 100%, 40%);">-                        UBInt32('timestamp'),</span><br><span style="color: hsl(0, 100%, 40%);">-                        UBInt32('ssrc')</span><br><span style="color: hsl(0, 100%, 40%);">-                        )</span><br><span style="color: hsl(0, 100%, 40%);">-        rtp_header = header.parse(data)</span><br><span style="color: hsl(120, 100%, 40%);">+        rtp_header = RTPPacket.rtp_header.parse(data)</span><br><span>         LOGGER.debug("Parsed RTP packet is {0}".format(rtp_header))</span><br><span style="color: hsl(0, 100%, 40%);">-        if rtp_header.header.payload == 13:</span><br><span style="color: hsl(120, 100%, 40%);">+        if rtp_header.payload_type == 13:</span><br><span>             current_time = time.time()</span><br><span>             # Don't compare intervals on the first received CNG</span><br><span>             if self.last_rx_time:</span><br><span>diff --git a/tests/hep/hep_capture_node.py b/tests/hep/hep_capture_node.py</span><br><span>index 0fb081e..010756a 100644</span><br><span>--- a/tests/hep/hep_capture_node.py</span><br><span>+++ b/tests/hep/hep_capture_node.py</span><br><span>@@ -20,10 +20,8 @@</span><br><span> from twisted.internet.protocol import DatagramProtocol</span><br><span> from twisted.internet import reactor</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-try:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct_legacy import *</span><br><span style="color: hsl(0, 100%, 40%);">-except ImportError:</span><br><span style="color: hsl(0, 100%, 40%);">-    from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct.core import *</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>@@ -107,40 +105,40 @@</span><br><span> </span><br><span>         self.module = module</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        self.hep_chunk = Struct('hep_chunk',</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt16('vendor_id'),</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt16('type_id'),</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt16('length'))</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_ctrl = Struct('hep_ctrl',</span><br><span style="color: hsl(0, 100%, 40%);">-            Array(4, UBInt8('id')),</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt16('length'))</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_ip_family = Struct('hep_ip_family',</span><br><span style="color: hsl(120, 100%, 40%);">+        self.hep_chunk = 'hep_chunk' / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+            'vendor_id' / Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+            'type_id' / Int16ub,</span><br><span style="color: hsl(120, 100%, 40%);">+            'length' / Int16ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_ctrl = 'hep_ctrl' / Struct(</span><br><span style="color: hsl(120, 100%, 40%);">+            'id' / Array(4, Int8ub),</span><br><span style="color: hsl(120, 100%, 40%);">+            'length' / Int16ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_ip_family = 'hep_ip_family' / Struct(</span><br><span>             self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt8('ip_family'));</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_ip_id = Struct('hep_ip_id',</span><br><span style="color: hsl(120, 100%, 40%);">+            'ip_family' / Int8ub);</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_ip_id = 'hep_ip_id' / Struct(</span><br><span>             self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt8('ip_id'))</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_port = Struct('hep_port',</span><br><span style="color: hsl(120, 100%, 40%);">+            'ip_id' / Int8ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_port = 'hep_port' / Struct(</span><br><span>             self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt16('port'))</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_timestamp_sec = Struct('hep_timestamp_sec',</span><br><span style="color: hsl(120, 100%, 40%);">+            'port' / Int16ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_timestamp_sec = 'hep_timestamp_sec' / Struct(</span><br><span>             self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt32('timestamp_sec'))</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_timestamp_usec = Struct('hep_timestamp_usec',</span><br><span style="color: hsl(120, 100%, 40%);">+            'timestamp_sec' / Int32ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_timestamp_usec = 'hep_timestamp_usec' / Struct(</span><br><span>             self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt32('timestamp_usec'))</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_protocol_type = Struct('hep_protocol_type',</span><br><span style="color: hsl(120, 100%, 40%);">+            'timestamp_usec' / Int32ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_protocol_type = 'hep_protocol_type' / Struct(</span><br><span>             self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt8('protocol_type'))</span><br><span style="color: hsl(0, 100%, 40%);">-        hep_capture_agent_id = Struct('hep_capture_agent_id',</span><br><span style="color: hsl(120, 100%, 40%);">+            'protocol_type' / Int8ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        hep_capture_agent_id = 'hep_capture_agent_id' / Struct(</span><br><span>             self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-            UBInt32('capture_agent_id'))</span><br><span style="color: hsl(0, 100%, 40%);">-        self.hep_generic_msg = Struct('hep_generic',</span><br><span style="color: hsl(120, 100%, 40%);">+            'capture_agent_id' / Int32ub)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.hep_generic_msg = 'hep_generic' / Struct(</span><br><span>             hep_ctrl,</span><br><span>             hep_ip_family,</span><br><span>             hep_ip_id,</span><br><span style="color: hsl(0, 100%, 40%);">-            Struct('src_port', hep_port),</span><br><span style="color: hsl(0, 100%, 40%);">-            Struct('dst_port', hep_port),</span><br><span style="color: hsl(120, 100%, 40%);">+            'src_port' / Struct(hep_port),</span><br><span style="color: hsl(120, 100%, 40%);">+            'dst_port' / Struct(hep_port),</span><br><span>             hep_timestamp_sec,</span><br><span>             hep_timestamp_usec,</span><br><span>             hep_protocol_type,</span><br><span>@@ -161,18 +159,18 @@</span><br><span>         dst_addr = None</span><br><span>         if parsed_hdr.hep_ip_family.ip_family == IP_FAMILY.v4:</span><br><span>             # IPv4</span><br><span style="color: hsl(0, 100%, 40%);">-            hep_ipv4_addr = Struct('hep_ipv4_addr',</span><br><span style="color: hsl(120, 100%, 40%);">+            hep_ipv4_addr = 'hep_ipv4_addr' / Struct(</span><br><span>                 self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-                String('ipv4_addr', 4))</span><br><span style="color: hsl(120, 100%, 40%);">+                'ipv4_addr' / PaddedString(4, "ascii"))</span><br><span>             src_addr = hep_ipv4_addr.parse(data[length:])</span><br><span>             length += hep_ipv4_addr.sizeof()</span><br><span>             dst_addr = hep_ipv4_addr.parse(data[length:])</span><br><span>             length += hep_ipv4_addr.sizeof()</span><br><span>         elif parsed_hdr.hep_ip_family.ip_family == IP_FAMILY.v6:</span><br><span>             # IPv6</span><br><span style="color: hsl(0, 100%, 40%);">-            hep_ipv6_addr = Struct('hep_ipv6_addr',</span><br><span style="color: hsl(120, 100%, 40%);">+            hep_ipv6_addr = 'hep_ipv6_addr' / Struct(</span><br><span>                 self.hep_chunk,</span><br><span style="color: hsl(0, 100%, 40%);">-                String('ipv6_addr', 16))</span><br><span style="color: hsl(120, 100%, 40%);">+                'ipv6_addr' / PaddedString(16, "ascii"))</span><br><span>             src_addr = hep_ipv6_addr.parse(data[length:])</span><br><span>             length += hep_ipv6_addr.sizeof()</span><br><span>             dst_addr = hep_ipv6_addr.parse(data[length:])</span><br><span>@@ -185,20 +183,20 @@</span><br><span>             hdr = self.hep_chunk.parse(data[length:])</span><br><span>             length += self.hep_chunk.sizeof()</span><br><span>             if hdr.type_id == HEP_VARIABLE_TYPES.auth_key:</span><br><span style="color: hsl(0, 100%, 40%);">-                hep_auth_key = String('hep_auth_key',</span><br><span style="color: hsl(0, 100%, 40%);">-                                      hdr.length - self.hep_chunk.sizeof())</span><br><span style="color: hsl(120, 100%, 40%);">+                hep_auth_key = 'hep_auth_key' / PaddedString(</span><br><span style="color: hsl(120, 100%, 40%);">+                                      hdr.length - self.hep_chunk.sizeof(), "ascii")</span><br><span>                 packet.auth_key = hep_auth_key.parse(data[length:])</span><br><span>                 length += hep_auth_key.sizeof() - self.hep_chunk.sizeof()</span><br><span>             elif hdr.type_id == HEP_VARIABLE_TYPES.payload:</span><br><span style="color: hsl(0, 100%, 40%);">-                hep_payload = String('hep_payload',</span><br><span style="color: hsl(0, 100%, 40%);">-                                     hdr.length - self.hep_chunk.sizeof())</span><br><span style="color: hsl(120, 100%, 40%);">+                hep_payload = 'hep_payload' / PaddedString(</span><br><span style="color: hsl(120, 100%, 40%);">+                                     hdr.length - self.hep_chunk.sizeof(), "ascii")</span><br><span>                 packet.payload = hep_payload.parse(data[length:])</span><br><span>                 length += hep_payload.sizeof() - self.hep_chunk.sizeof()</span><br><span> </span><br><span>                 LOGGER.debug('Packet payload: %s' % packet.payload)</span><br><span>             elif hdr.type_id == HEP_VARIABLE_TYPES.uuid:</span><br><span style="color: hsl(0, 100%, 40%);">-                hep_uuid = String('hep_uuid',</span><br><span style="color: hsl(0, 100%, 40%);">-                                  hdr.length - self.hep_chunk.sizeof())</span><br><span style="color: hsl(120, 100%, 40%);">+                hep_uuid = 'hep_uuid' / PaddedString(</span><br><span style="color: hsl(120, 100%, 40%);">+                                  hdr.length - self.hep_chunk.sizeof(), "ascii")</span><br><span>                 packet.uuid = hep_uuid.parse(data[length:])</span><br><span>                 length += hep_uuid.sizeof() - self.hep_chunk.sizeof()</span><br><span>         self.module.verify_packet(packet)</span><br><span>@@ -379,4 +377,3 @@</span><br><span>                 LOGGER.error('Failed to match packet %d: %s' %</span><br><span>                     (self.current_packet, str(packet.__dict__)))</span><br><span>                 self.test_object.set_passed(False)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/testsuite/+/13222">change 13222</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/testsuite/+/13222"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: testsuite </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-Change-Id: Id38d01a2cd073b240fde909a38c95d69313bbbe7 </div>
<div style="display:none"> Gerrit-Change-Number: 13222 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>