NTP module update

diff --git a/scapy/layers/ntp.py b/scapy/layers/ntp.py
index 6560e39..fe9ace1 100644
--- a/scapy/layers/ntp.py
+++ b/scapy/layers/ntp.py
@@ -1,33 +1,97 @@
-## This file is part of Scapy
-## See http://www.secdev.org/projects/scapy for more informations
-## Copyright (C) Philippe Biondi <phil@secdev.org>
-## This program is published under a GPLv2 license
+# This file is part of Scapy
+# See http://www.secdev.org/projects/scapy for more informations
+# Copyright (C) Philippe Biondi <phil@secdev.org>
+# This program is published under a GPLv2 license
 
 """
 NTP (Network Time Protocol).
+References : RFC 5905, RC 1305, ntpd source code
 """
 
+import struct
 import time
 import datetime
-from scapy.packet import *
-from scapy.fields import *
-from scapy.layers.inet import UDP
 
+from scapy.packet import Packet, bind_layers, Raw
+from scapy.fields import (BitField, BitEnumField, ByteField, ByteEnumField, \
+XByteField, SignedByteField, FlagsField, ShortField, LEShortField, IntField,\
+LEIntField, FixedPointField, IPField, StrField, StrFixedLenField,\
+StrFixedLenEnumField, PacketField, PacketLenField, PacketListField,\
+FieldListField, ConditionalField, PadField)
+from scapy.layers.inet6 import IP6Field
+from scapy.layers.inet import UDP
+from scapy.utils import lhex
+from scapy.config import conf
+
+
+
+#############################################################################
+##### Constants
+#############################################################################
+
+_NTP_AUTH_MD5_MIN_SIZE = 68
+_NTP_EXT_MIN_SIZE = 16
+_NTP_HDR_WITH_EXT_MIN_SIZE = _NTP_AUTH_MD5_MIN_SIZE + _NTP_EXT_MIN_SIZE
+_NTP_AUTH_MD5_TAIL_SIZE = 20
+_NTP_AUTH_MD5_DGST_SIZE = 16
+_NTP_PRIVATE_PACKET_MIN_SIZE = 8
+
+# ntpd "Private" messages are the shortest
+_NTP_PACKET_MIN_SIZE = _NTP_PRIVATE_PACKET_MIN_SIZE
+
+_NTP_PRIVATE_REQ_PKT_TAIL_LEN = 28
 
 # seconds between 01-01-1900 and 01-01-1970
 _NTP_BASETIME = 2208988800
 
+# include/ntp.h
+_NTP_SHIFT = 8
+_NTP_HASH_SIZE = 128
+
+
+#############################################################################
+##### Fields and utilities
+#############################################################################
+
+class XLEShortField(LEShortField):
+    """
+    XLEShortField which value is encoded in little endian.
+    """
+
+    def i2repr(self, pkt, x):
+        return lhex(self.i2h(pkt, x))
+
+
+class XStrFixedLenField(StrFixedLenField):
+    """
+    StrFixedLenField which value is printed as hexadecimal.
+    """
+
+    def i2repr(self, pkt, x):
+        output = ""
+        length = len(x)
+        len_from_val = self.length_from(pkt)
+        max_idx = length if length < len_from_val else len_from_val
+        for i in range(0, max_idx):
+            output += x[i].encode("hex")
+        return output
+
+
 class TimeStampField(FixedPointField):
+    """
+    This field handles the timestamp fields in the NTP header.
+    """
+
     def __init__(self, name, default):
         FixedPointField.__init__(self, name, default, 64, 32)
 
     def i2repr(self, pkt, val):
         if val is None:
             return "--"
-        val = self.i2h(pkt,val)
+        val = self.i2h(pkt, val)
         if val < _NTP_BASETIME:
             return val
-        return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(val-_NTP_BASETIME))
+        return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(val - _NTP_BASETIME))
 
     def any2i(self, pkt, val):
         if isinstance(val, basestring):
@@ -35,46 +99,1795 @@
         elif isinstance(val, datetime.datetime):
             val = int(val.strftime("%s")) + _NTP_BASETIME
         return FixedPointField.any2i(self, pkt, val)
-    
+
     def i2m(self, pkt, val):
         if val is None:
-            val = FixedPointField.any2i(self, pkt, time.time()+_NTP_BASETIME)
+            val = FixedPointField.any2i(self, pkt, time.time() + _NTP_BASETIME)
         return FixedPointField.i2m(self, pkt, val)
-        
+
+
+def get_cls(name, fallback_cls="Raw"):
+    """
+    Returns class named "name" if it exists, fallback_cls otherwise.
+    """
+
+    return globals().get(name, fallback_cls)
+
+
+#############################################################################
+##### NTP
+#############################################################################
+
+# RFC 5905 / Section 7.3
+_leap_indicator = {
+    0: "no warning",
+    1: "last minute of the day has 61 seconds",
+    2: "last minute of the day has 59 seconds",
+    3: "unknown (clock unsynchronized)"
+}
+
+
+# RFC 5905 / Section 7.3
+_ntp_modes = {
+    0: "reserved",
+    1: "symmetric active",
+    2: "symmetric passive",
+    3: "client",
+    4: "server",
+    5: "broadcast",
+    6: "NTP control message",
+    7: "reserved for private use"
+}
+
+
+# RFC 5905 / Section 7.3
+_reference_identifiers = {
+    "GOES": "Geosynchronous Orbit Environment Satellite",
+    "GPS ": "Global Position System",
+    "GAL ": "Galileo Positioning System",
+    "PPS ": "Generic pulse-per-second",
+    "IRIG": "Inter-Range Instrumentation Group",
+    "WWVB": "LF Radio WWVB Ft. Collins, CO 60 kHz",
+    "DCF ": "LF Radio DCF77 Mainflingen, DE 77.5 kHz",
+    "HBG ": "LF Radio HBG Prangins, HB 75 kHz",
+    "MSF ": "LF Radio MSF Anthorn, UK 60 kHz",
+    "JJY ": "LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz",
+    "LORC": "MF Radio LORAN C station, 100 kHz",
+    "TDF ": "MF Radio Allouis, FR 162 kHz",
+    "CHU ": "HF Radio CHU Ottawa, Ontario",
+    "WWV ": "HF Radio WWV Ft. Collins, CO",
+    "WWVH": "HF Radio WWVH Kauai, HI",
+    "NIST": "NIST telephone modem",
+    "ACTS": "NIST telephone modem",
+    "USNO": "USNO telephone modem",
+    "PTB ": "European telephone modem",
+}
+
+
+# RFC 5905 / Section 7.4
+_kiss_codes = {
+    "ACST": "The association belongs to a unicast server.",
+    "AUTH": "Server authentication failed.",
+    "AUTO": "Autokey sequence failed.",
+    "BCST": "The association belongs to a broadcast server.",
+    "CRYP": "Cryptographic authentication or identification failed.",
+    "DENY": "Access denied by remote server.",
+    "DROP": "Lost peer in symmetric mode.",
+    "RSTR": "Access denied due to local policy.",
+    "INIT": "The association has not yet synchronized for the first time.",
+    "MCST": "The association belongs to a dynamically discovered server.",
+    "NKEY": "No key found.",
+    "RATE": "Rate exceeded.",
+    "RMOT": "Alteration of association from a remote host running ntpdc."
+}
+
+
+# Used by _ntp_dispatcher to instantiate the appropriate class
+_ntp_cls_by_mode = {
+    0: "NTPHeader",
+    1: "NTPHeader",
+    2: "NTPHeader",
+    3: "NTPHeader",
+    4: "NTPHeader",
+    5: "NTPHeader",
+    6: "NTPControl",
+    7: "NTPPrivate"
+}
+
+
+def _ntp_dispatcher(payload):
+    """
+    Returns the right class for a given NTP packet.
+    """
+
+    cls = conf.raw_layer
+
+    # By default, calling NTP() will build a NTP packet as defined in RFC 5905
+    # (see the code of NTPHeader). Use NTPHeader for extension fields and MAC.
+    if payload is None:
+        cls = get_cls("NTPHeader", "Raw")
+
+    else:
+        length = len(payload)
+        if length >= _NTP_PACKET_MIN_SIZE:
+            first_byte = struct.unpack("!B", payload[0])[0]
+
+            # Extract NTP mode
+            mode_mask = 0x07
+            mode = first_byte & mode_mask
+
+            cls = get_cls(_ntp_cls_by_mode.get(mode, "Raw"), conf.raw_layer)
+
+    return cls
 
 
 class NTP(Packet):
-    # RFC 1769
-    name = "NTP"
-    fields_desc = [ 
-         BitEnumField('leap', 0, 2,
-                      { 0: 'nowarning',
-                        1: 'longminute',
-                        2: 'shortminute',
-                        3: 'notsync'}),
-         BitField('version', 3, 3),
-         BitEnumField('mode', 3, 3,
-                      { 0: 'reserved',
-                        1: 'sym_active',
-                        2: 'sym_passive',
-                        3: 'client',
-                        4: 'server',
-                        5: 'broadcast',
-                        6: 'control',
-                        7: 'private'}),
-         BitField('stratum', 2, 8),
-         BitField('poll', 0xa, 8),          ### XXX : it's a signed int
-         BitField('precision', 0, 8),       ### XXX : it's a signed int
-         FixedPointField('delay', 0, size=32, frac_bits=16),
-         FixedPointField('dispersion', 0, size=32, frac_bits=16),
-         IPField('id', "127.0.0.1"),
-         TimeStampField('ref', 0),
-         TimeStampField('orig', None),  # None means current time
-         TimeStampField('recv', 0),
-         TimeStampField('sent', None) 
-         ]
+    """
+    Base class that allows easier instantiation of a NTP packet from binary
+    data.
+    """
+
+    @classmethod
+    def dispatch_hook(cls, _pkt=None, *args, **kargs):
+        """
+        Returns the right class for the given data.
+        """
+
+        return _ntp_dispatcher(_pkt)
+
+    def pre_dissect(self, s):
+        """
+        Check that the payload is long enough to build a NTP packet.
+        """
+        length = len(s)
+        if length < _NTP_PACKET_MIN_SIZE:
+            err = " ({}".format(length) + " is < _NTP_PACKET_MIN_SIZE "
+            err += "({})).".format(_NTP_PACKET_MIN_SIZE)
+            raise _NTPInvalidDataException(err)
+        return s
+
+    # NTPHeader, NTPControl and NTPPrivate are NTP packets.
+    # This might help, for example when reading a pcap file.
+    def haslayer(self, cls):
+        ntp_classes = [
+            get_cls("NTPHeader"),
+            get_cls("NTPControl"),
+            get_cls("NTPPrivate")
+        ]
+        ret = 0
+        if cls == NTP:
+            # If cls is NTP (the parent class), check that the object is an
+            # instance of a NTP packet
+            for ntp_class in ntp_classes:
+                if isinstance(self, ntp_class):
+                    ret = 1
+                    break
+        elif cls in ntp_classes and isinstance(self, cls):
+            ret = 1
+        return ret
+
+    def getlayer(self, cls, nb=1, _track=None):
+        ntp_classes = [
+            get_cls("NTPHeader"),
+            get_cls("NTPControl"),
+            get_cls("NTPPrivate")
+        ]
+        layer = None
+        if cls == NTP:
+            for ntp_class in ntp_classes:
+                if isinstance(self, ntp_class):
+                    layer = self
+                    break
+        else:
+            layer = Packet.getlayer(self, cls, nb, _track)
+        return layer
+
     def mysummary(self):
         return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%")
 
 
-bind_layers( UDP,           NTP,           dport=123, sport=123)
+class _NTPAuthenticatorPaddingField(StrField):
+    """
+    StrField handling the padding that may be found before the
+    "authenticator" field.
+    """
+
+    def getfield(self, pkt, s):
+        ret = None
+        remain = s
+        length = len(s)
+
+        if length > _NTP_AUTH_MD5_TAIL_SIZE:
+            start = length - _NTP_AUTH_MD5_TAIL_SIZE
+            ret = s[:start]
+            remain = s[start:]
+        return remain, ret
+
+
+class NTPAuthenticator(Packet):
+    """
+    Packet handling the "authenticator" part of a NTP packet, as
+    defined in RFC 5905.
+    """
+
+    name = "Authenticator"
+    fields_desc = [
+        _NTPAuthenticatorPaddingField("padding", ""),
+        IntField("key_id", 0),
+        XStrFixedLenField("dgst", "", length_from=lambda x: 16)
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class NTPExtension(Packet):
+    """
+    Packet handling a NTPv4 extension.
+    """
+
+    #________________________________________________________________________
+    #
+    # RFC 7822
+    #________________________________________________________________________
+    #
+    # 7.5.  NTP Extension Field Format
+    #
+    #    In NTPv3, one or more extension fields can be inserted after the
+    #    header and before the MAC, if a MAC is present.
+    #
+    #    Other than defining the field format, this document makes no use
+    #    of the field contents.  An extension field contains a request or
+    #    response message in the format shown in Figure 14.
+    #
+    #     0                   1                   2                   3
+    #     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #    |          Field Type           |            Length             |
+    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #    .                                                               .
+    #    .                            Value                              .
+    #    .                                                               .
+    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #    |                       Padding (as needed)                     |
+    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #
+    #                    Figure 14: Extension Field Format
+    #
+    #
+    #    All extension fields are zero-padded to a word (four octets)
+    #    boundary.
+    #________________________________________________________________________
+    #
+
+    name = "extension"
+    fields_desc = [
+        ShortField("type", 0),
+        ShortField("len", 0),
+        PadField(PacketField("value", "", Packet), align=4, padwith="\x00")
+    ]
+
+
+class NTPExtPacketListField(PacketListField):
+
+    """
+    PacketListField handling NTPv4 extensions (NTPExtension list).
+    """
+
+    def m2i(self, pkt, m):
+        ret = None
+        if len(m) >= 16:
+            ret = NTPExtension(m)
+        else:
+            ret = Raw(m)
+        return ret
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+        length = len(s)
+        if length > _NTP_AUTH_MD5_TAIL_SIZE:
+            end = length - _NTP_AUTH_MD5_TAIL_SIZE
+            extensions = s[:end]
+            remain = s[end:]
+
+            extensions_len = len(extensions)
+            while extensions_len >= 16:
+                ext_len = struct.unpack("!H", extensions[2:4])[0]
+                current = extensions[:ext_len]
+                extensions = extensions[ext_len:]
+                current_packet = self.m2i(pkt, current)
+                lst.append(current_packet)
+                extensions_len = len(extensions)
+
+            if extensions_len > 0:
+                lst.append(self.m2i(pkt, extensions))
+
+        return remain, lst
+
+
+class NTPExtensions(Packet):
+    """
+    Packet handling the NTPv4 extensions and the "MAC part" of the packet.
+    """
+
+    #________________________________________________________________________
+    #
+    # RFC 5905 / RFC 7822
+    #________________________________________________________________________
+    #
+    # 7.5. NTP Extension Field Format
+    #
+    # In NTPv4, one or more extension fields can be inserted after the
+    # header and before the MAC, if a MAC is present.
+    #________________________________________________________________________
+    #
+
+    name = "NTPv4 extensions"
+    fields_desc = [
+        NTPExtPacketListField("extensions", [], Packet),
+        PacketField("mac", NTPAuthenticator(), NTPAuthenticator)
+    ]
+
+
+class NTPHeader(NTP):
+
+    """
+    Packet handling the RFC 5905 NTP packet.
+    """
+
+    #________________________________________________________________________
+    #
+    # RFC 5905
+    #________________________________________________________________________
+    #
+    #   0                   1                   2                   3
+    #   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |LI | VN  |Mode |    Stratum     |     Poll      |  Precision   |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                         Root Delay                            |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                         Root Dispersion                       |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                          Reference ID                         |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                                                               |
+    #  +                     Reference Timestamp (64)                  +
+    #  |                                                               |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                                                               |
+    #  +                      Origin Timestamp (64)                    +
+    #  |                                                               |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                                                               |
+    #  +                      Receive Timestamp (64)                   +
+    #  |                                                               |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                                                               |
+    #  +                      Transmit Timestamp (64)                  +
+    #  |                                                               |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                                                               |
+    #  .                                                               .
+    #  .                    Extension Field 1 (variable)               .
+    #  .                                                               .
+    #  |                                                               |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                                                               |
+    #  .                                                               .
+    #  .                    Extension Field 2 (variable)               .
+    #  .                                                               .
+    #  |                                                               |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                          Key Identifier                       |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #  |                                                               |
+    #  |                            dgst (128)                         |
+    #  |                                                               |
+    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #
+    #                  Figure 8: Packet Header Format
+    #________________________________________________________________________
+    #
+
+    name = "NTPHeader"
+    fields_desc = [
+        BitEnumField("leap", 0, 2, _leap_indicator),
+        BitField("version", 4, 3),
+        BitEnumField("mode", 3, 3, _ntp_modes),
+        BitField("stratum", 2, 8),
+        BitField("poll", 0xa, 8),
+        BitField("precision", 0, 8),
+        FixedPointField("delay", 0, size=32, frac_bits=16),
+        FixedPointField("dispersion", 0, size=32, frac_bits=16),
+        ConditionalField(IPField("id", "127.0.0.1"), lambda p: p.stratum > 1),
+        ConditionalField(
+            StrFixedLenEnumField(
+                "ref_id",
+                "",
+                length=4,
+                enum=_reference_identifiers
+            ),
+            lambda p: p.stratum < 2
+        ),
+        TimeStampField("ref", 0),
+        TimeStampField("orig", None),
+        TimeStampField("recv", 0),
+        TimeStampField("sent", None),
+    ]
+
+    def guess_payload_class(self, payload):
+        """
+        Handles NTPv4 extensions and MAC part (when authentication is used.)
+        """
+        plen = len(payload)
+
+        if plen > _NTP_AUTH_MD5_TAIL_SIZE:
+            return NTPExtensions
+        elif plen == _NTP_AUTH_MD5_TAIL_SIZE:
+            return NTPAuthenticator
+
+        return Packet.guess_payload_class(self, payload)
+
+
+class _NTPInvalidDataException(Exception):
+    """
+    Raised when it is not possible to instantiate a NTP packet with the
+    given data.
+    """
+
+    def __init__(self, details):
+        Exception.__init__(
+            self,
+            "Data does not seem to be a valid NTP message" + details
+        )
+
+
+##############################################################################
+##### Private (mode 7)
+##############################################################################
+
+# Operation codes
+_op_codes = {
+    0: "CTL_OP_UNSPEC",
+    1: "CTL_OP_READSTAT",
+    2: "CTL_OP_READVAR",
+    3: "CTL_OP_WRITEVAR",
+    4: "CTL_OP_READCLOCK",
+    5: "CTL_OP_WRITECLOCK",
+    6: "CTL_OP_SETTRAP",
+    7: "CTL_OP_ASYNCMSG",
+    8: "CTL_OP_CONFIGURE",
+    9: "CTL_OP_SAVECONFIG",
+    10: "CTL_OP_READ_MRU",
+    11: "CTL_OP_READ_ORDLIST_A",
+    12: "CTL_OP_REQ_NONCE",
+    31: "CTL_OP_UNSETTRAP"
+}
+
+
+# System status words
+_system_statuses = {
+    0: "no warning",
+    1: "last minute was 61 seconds",
+    2: "last minute was 59 seconds",
+    3: "alarm condition (clock not synchronized)"
+}
+
+
+_clock_sources = {
+    0: "unspecified or unknown",
+    1: " Calibrated atomic clock",
+    2: "VLF (band 4) or LF (band 5) radio",
+    3: "HF (band 7) radio",
+    4: "UHF (band 9) satellite",
+    5: "local net",
+    6: "UDP/NTP",
+    7: "UDP/TIME",
+    8: "eyeball-and-wristwatch",
+    9: "telephone modem"
+}
+
+
+_system_event_codes = {
+    0: "unspecified",
+    1: "system restart",
+    2: "system or hardware fault",
+    3: "system new status word (leap bits or synchronization change)",
+    4: "system new synchronization source or stratum (sys.peer or sys.stratum change)",
+    5: "system clock reset (offset correction exceeds CLOCK.MAX)",
+    6: "system invalid time or date",
+    7: "system clock exception",
+}
+
+
+# Peer status words
+_peer_statuses = {
+    0: "configured",
+    1: "authentication enabled",
+    2: "authentication okay",
+    3: "reachability okay",
+    4: "reserved"
+}
+
+
+_peer_selection = {
+    0: "rejected",
+    1: "passed sanity checks",
+    2: "passed correctness checks",
+    3: "passed candidate checks",
+    4: "passed outlyer checks",
+    5: "current synchronization source; max distance exceeded",
+    6: "current synchronization source; max distance okay",
+    7: "reserved"
+}
+
+
+_peer_event_codes = {
+    0: "unspecified",
+    1: "peer IP error",
+    2: "peer authentication failure",
+    3: "peer unreachable",
+    4: "peer reachable",
+    5: "peer clock exception",
+}
+
+
+# Clock status words
+_clock_statuses = {
+    0: "clock operating within nominals",
+    1: "reply timeout",
+    2: "bad reply format",
+    3: "hardware or software fault",
+    4: "propagation failure",
+    5: "bad date format or value",
+    6: "bad time format or value"
+}
+
+
+# Error status words
+_error_statuses = {
+    0: "unspecified",
+    1: "authentication failure",
+    2: "invalid message length or format",
+    3: "invalid opcode",
+    4: "unknown association identifier",
+    5: "unknown variable name",
+    6: "invalid variable value",
+    7: "administratively prohibited"
+}
+
+
+class NTPStatusPacket(Packet):
+    """
+    Packet handling a non specific status word.
+    """
+
+    name = "status"
+    fields_desc = [ShortField("status", 0)]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class NTPSystemStatusPacket(Packet):
+
+    """
+    Packet handling the system status fields.
+    """
+
+    name = "system status"
+    fields_desc = [
+        BitEnumField("leap_indicator", 0, 2, _system_statuses),
+        BitEnumField("clock_source", 0, 6, _clock_sources),
+        BitField("system_event_counter", 0, 4),
+        BitEnumField("system_event_code", 0, 4, _system_event_codes),
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class NTPPeerStatusPacket(Packet):
+    """
+    Packet handling the peer status fields.
+    """
+
+    name = "peer status"
+    fields_desc = [
+        BitField("configured", 0, 1),
+        BitField("auth_enabled", 0, 1),
+        BitField("authentic", 0, 1),
+        BitField("reachability", 0, 1),
+        BitField("reserved", 0, 1),
+        BitEnumField("peer_sel", 0, 3, _peer_selection),
+        BitField("peer_event_counter", 0, 4),
+        BitEnumField("peer_event_code", 0, 4, _peer_event_codes),
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class NTPClockStatusPacket(Packet):
+    """
+    Packet handling the clock status fields.
+    """
+
+    name = "clock status"
+    fields_desc = [
+        BitEnumField("clock_status", 0, 8, _clock_statuses),
+        BitField("code", 0, 8)
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class NTPErrorStatusPacket(Packet):
+    """
+    Packet handling the error status fields.
+    """
+
+    name = "error status"
+    fields_desc = [
+        BitEnumField("error_code", 0, 8, _error_statuses),
+        BitField("reserved", 0, 8)
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class NTPControlStatusField(PacketField):
+    """
+    This field provides better readability for the "status" field.
+    """
+
+    #________________________________________________________________________
+    #
+    # RFC 1305
+    #________________________________________________________________________
+    #
+    # Appendix B.3. Commands // ntpd source code: ntp_control.h
+    #________________________________________________________________________
+    #
+
+    def m2i(self, pkt, m):
+        ret = None
+        association_id = struct.unpack("!H", m[2:4])[0]
+
+        if pkt.error == 1:
+            ret = NTPErrorStatusPacket(m)
+
+        # op_code == CTL_OP_READSTAT
+        elif pkt.op_code == 1:
+            if association_id != 0:
+                ret = NTPPeerStatusPacket(m)
+            else:
+                ret = NTPSystemStatusPacket(m)
+
+        # op_code == CTL_OP_READVAR
+        elif pkt.op_code == 2:
+            if association_id != 0:
+                ret = NTPPeerStatusPacket(m)
+            else:
+                ret = NTPSystemStatusPacket(m)
+
+        # op_code == CTL_OP_WRITEVAR
+        elif pkt.op_code == 3:
+            ret = NTPStatusPacket(m)
+
+        # op_code == CTL_OP_READCLOCK or op_code == CTL_OP_WRITECLOCK
+        elif pkt.op_code == 4 or pkt.op_code == 5:
+            ret = NTPClockStatusPacket(m)
+
+        else:
+            ret = NTPStatusPacket(m)
+
+        return ret
+
+
+class NTPPeerStatusDataPacket(Packet):
+    """
+    Packet handling the data field when op_code is CTL_OP_READSTAT
+    and the association_id field is null.
+    """
+
+    name = "data / peer status"
+    fields_desc = [
+        ShortField("association_id", 0),
+        PacketField("peer_status", NTPPeerStatusPacket(), NTPPeerStatusPacket),
+    ]
+
+
+class NTPControlDataPacketLenField(PacketLenField):
+
+    """
+    PacketField handling the "data" field of NTP control messages.
+    """
+
+    def m2i(self, pkt, m):
+        ret = None
+
+        # op_code == CTL_OP_READSTAT
+        if pkt.op_code == 1:
+            if pkt.association_id == 0:
+                # Data contains association ID and peer status
+                ret = NTPPeerStatusDataPacket(m)
+            else:
+                ret = Raw(m)
+        else:
+            ret = Raw(m)
+
+        return ret
+
+    def getfield(self, pkt, s):
+        length = self.length_from(pkt)
+        i = None
+        if length > 0:
+            # RFC 1305
+            # The maximum number of data octets is 468.
+            #
+            # include/ntp_control.h
+            # u_char data[480 + MAX_MAC_LEN]; /* data + auth */
+            #
+            # Set the minimum length to 480 - 468
+            length = max(12, length)
+            if length % 4:
+                length += (4 - length % 4)
+        try:
+            i = self.m2i(pkt, s[:length])
+        except Exception:
+            if conf.debug_dissector:
+                raise
+            i = conf.raw_layer(load=s[:length])
+        return s[length:], i
+
+
+class NTPControl(NTP):
+    """
+    Packet handling NTP mode 6 / "Control" messages.
+    """
+
+    #________________________________________________________________________
+    #
+    # RFC 1305
+    #________________________________________________________________________
+    #
+    # Appendix B.3. Commands // ntpd source code: ntp_control.h
+    #________________________________________________________________________
+    #
+
+    name = "Control message"
+    fields_desc = [
+        BitField("zeros", 0, 2),
+        BitField("version", 2, 3),
+        BitField("mode", 6, 3),
+        BitField("response", 0, 1),
+        BitField("error", 0, 1),
+        BitField("more", 0, 1),
+        BitEnumField("op_code", 0, 5, _op_codes),
+        ShortField("sequence", 0),
+        ConditionalField(NTPControlStatusField(
+            "status_word", "", Packet), lambda p: p.response == 1),
+        ConditionalField(ShortField("status", 0), lambda p: p.response == 0),
+        ShortField("association_id", 0),
+        ShortField("offset", 0),
+        ShortField("count", None),
+        NTPControlDataPacketLenField(
+            "data", "", Packet, length_from=lambda p: p.count),
+        PacketField("authenticator", "", NTPAuthenticator),
+    ]
+
+    def post_build(self, p, pay):
+        if self.count is None:
+            length = 0
+            if self.data:
+                length = len(self.data)
+            p = p[:11] + struct.pack("!H", length) + p[13:]
+        return p + pay
+
+
+##############################################################################
+##### Private (mode 7)
+##############################################################################
+
+_information_error_codes = {
+    0: "INFO_OKAY",
+    1: "INFO_ERR_IMPL",
+    2: "INFO_ERR_REQ",
+    3: "INFO_ERR_FMT",
+    4: "INFO_ERR_NODATA",
+    7: "INFO_ERR_AUTH"
+}
+
+
+_implementations = {
+    0: "IMPL_UNIV",
+    2: "IMPL_XNTPD_OLD",
+    3: "XNTPD"
+}
+
+
+_request_codes = {
+    0: "REQ_PEER_LIST",
+    1: "REQ_PEER_LIST_SUM",
+    2: "REQ_PEER_INFO",
+    3: "REQ_PEER_STATS",
+    4: "REQ_SYS_INFO",
+    5: "REQ_SYS_STATS",
+    6: "REQ_IO_STATS",
+    7: "REQ_MEM_STATS",
+    8: "REQ_LOOP_INFO",
+    9: "REQ_TIMER_STATS",
+    10: "REQ_CONFIG",
+    11: "REQ_UNCONFIG",
+    12: "REQ_SET_SYS_FLAG",
+    13: "REQ_CLR_SYS_FLAG",
+    14: "REQ_MONITOR",
+    15: "REQ_NOMONITOR",
+    16: "REQ_GET_RESTRICT",
+    17: "REQ_RESADDFLAGS",
+    18: "REQ_RESSUBFLAGS",
+    19: "REQ_UNRESTRICT",
+    20: "REQ_MON_GETLIST",
+    21: "REQ_RESET_STATS",
+    22: "REQ_RESET_PEER",
+    23: "REQ_REREAD_KEYS",
+    24: "REQ_DO_DIRTY_HACK",
+    25: "REQ_DONT_DIRTY_HACK",
+    26: "REQ_TRUSTKEY",
+    27: "REQ_UNTRUSTKEY",
+    28: "REQ_AUTHINFO",
+    29: "REQ_TRAPS",
+    30: "REQ_ADD_TRAP",
+    31: "REQ_CLR_TRAP",
+    32: "REQ_REQUEST_KEY",
+    33: "REQ_CONTROL_KEY",
+    34: "REQ_GET_CTLSTATS",
+    35: "REQ_GET_LEAPINFO",
+    36: "REQ_GET_CLOCKINFO",
+    37: "REQ_SET_CLKFUDGE",
+    38: "REQ_GET_KERNEL",
+    39: "REQ_GET_CLKBUGINFO",
+    41: "REQ_SET_PRECISION",
+    42: "REQ_MON_GETLIST_1",
+    43: "REQ_HOSTNAME_ASSOCID",
+    44: "REQ_IF_STATS",
+    45: "REQ_IF_RELOAD"
+}
+
+
+# Flags in the peer information returns
+_peer_flags = [
+    "INFO_FLAG_CONFIG",
+    "INFO_FLAG_SYSPEER",
+    "INFO_FLAG_BURST",
+    "INFO_FLAG_REFCLOCK",
+    "INFO_FLAG_PREFER",
+    "INFO_FLAG_AUTHENABLE",
+    "INFO_FLAG_SEL_CANDIDATE",
+    "INFO_FLAG_SHORTLIST",
+    "INFO_FLAG_IBURST"
+]
+
+
+# Flags in the system information returns
+_sys_info_flags = [
+    "INFO_FLAG_BCLIENT",
+    "INFO_FLAG_AUTHENTICATE",
+    "INFO_FLAG_NTP",
+    "INFO_FLAG_KERNEL",
+    "INFO_FLAG_CAL",
+    "INFO_FLAG_PPS_SYNC",
+    "INFO_FLAG_MONITOR",
+    "INFO_FLAG_FILEGEN",
+]
+
+
+class NTPInfoPeerList(Packet):
+
+    """
+    Used to return raw lists of peers.
+    """
+    name = "info_peer_list"
+    fields_desc = [
+        IPField("addr", "0.0.0.0"),
+        ShortField("port", 0),
+        ByteEnumField("hmode", 0, _ntp_modes),
+        FlagsField("flags", 0, 8, _peer_flags),
+        IntField("v6_flag", 0),
+        IntField("unused1", 0),
+        IP6Field("addr6", "::")
+    ]
+
+
+class NTPInfoPeerSummary(Packet):
+    """
+    Sort of the info that ntpdc returns by default.
+    """
+    name = "info_peer_summary"
+    fields_desc = [
+        IPField("dstaddr", "0.0.0.0"),
+        IPField("srcaddr", "0.0.0.0"),
+        ShortField("srcport", 0),
+        ByteField("stratum", 0),
+        ByteField("hpoll", 0),
+        ByteField("ppoll", 0),
+        ByteField("reach", 0),
+        FlagsField("flags", 0, 8, _peer_flags),
+        ByteField("hmode", _ntp_modes),
+        FixedPointField("delay", 0, size=32, frac_bits=16),
+        TimeStampField("offset", 0),
+        FixedPointField("dispersion", 0, size=32, frac_bits=16),
+        IntField("v6_flag", 0),
+        IntField("unused1", 0),
+        IP6Field("dstaddr6", "::"),
+        IP6Field("srcaddr6", "::")
+    ]
+
+
+class NTPInfoPeer(Packet):
+    """
+    Peer information structure.
+    """
+
+    name = "info_peer"
+    fields_desc = [
+        IPField("dstaddr", "0.0.0.0"),
+        IPField("srcaddr", "0.0.0.0"),
+        ShortField("srcport", 0),
+        FlagsField("flags", 0, 8, _peer_flags),
+        ByteField("leap", 0),
+        ByteEnumField("hmode", 0, _ntp_modes),
+        ByteField("pmode", 0),
+        ByteField("stratum", 0),
+        ByteField("ppoll", 0),
+        ByteField("hpoll", 0),
+        SignedByteField("precision", 0),
+        ByteField("version", 0),
+        ByteField("unused8", 0),
+        ByteField("reach", 0),
+        ByteField("unreach", 0),
+        XByteField("flash", 0),
+        ByteField("ttl", 0),
+        XLEShortField("flash2", 0),
+        ShortField("associd", 0),
+        LEIntField("keyid", 0),
+        IntField("pkeyid", 0),
+        IPField("refid", 0),
+        IntField("timer", 0),
+        FixedPointField("rootdelay", 0, size=32, frac_bits=16),
+        FixedPointField("rootdispersion", 0, size=32, frac_bits=16),
+        TimeStampField("reftime", 0),
+        TimeStampField("org", 0),
+        TimeStampField("rec", 0),
+        TimeStampField("xmt", 0),
+        FieldListField(
+            "filtdelay",
+            [0.0 for i in range(0, _NTP_SHIFT)],
+            FixedPointField("", 0, size=32, frac_bits=16),
+            count_from=lambda p: _NTP_SHIFT
+        ),
+        FieldListField(
+            "filtoffset",
+            [0.0 for i in range(0, _NTP_SHIFT)],
+            TimeStampField("", 0),
+            count_from=lambda p: _NTP_SHIFT
+        ),
+        FieldListField(
+            "order",
+            [0 for i in range(0, _NTP_SHIFT)],
+            ByteField("", 0),
+            count_from=lambda p: _NTP_SHIFT
+        ),
+        FixedPointField("delay", 0, size=32, frac_bits=16),
+        FixedPointField("dispersion", 0, size=32, frac_bits=16),
+        TimeStampField("offset", 0),
+        FixedPointField("selectdisp", 0, size=32, frac_bits=16),
+        IntField("unused1", 0),
+        IntField("unused2", 0),
+        IntField("unused3", 0),
+        IntField("unused4", 0),
+        IntField("unused5", 0),
+        IntField("unused6", 0),
+        IntField("unused7", 0),
+        FixedPointField("estbdelay", 0, size=32, frac_bits=16),
+        IntField("v6_flag", 0),
+        IntField("unused9", 0),
+        IP6Field("dstaddr6", "::"),
+        IP6Field("srcaddr6", "::"),
+    ]
+
+
+class NTPInfoPeerStats(Packet):
+    """
+    Peer statistics structure.
+    """
+
+    name = "info_peer_stats"
+    fields_desc = [
+        IPField("dstaddr", "0.0.0.0"),
+        IPField("srcaddr", "0.0.0.0"),
+        ShortField("srcport", 0),
+        FlagsField("flags", 0, 16, _peer_flags),
+        IntField("timereset", 0),
+        IntField("timereceived", 0),
+        IntField("timetosend", 0),
+        IntField("timereachable", 0),
+        IntField("sent", 0),
+        IntField("unused1", 0),
+        IntField("processed", 0),
+        IntField("unused2", 0),
+        IntField("badauth", 0),
+        IntField("bogusorg", 0),
+        IntField("oldpkt", 0),
+        IntField("unused3", 0),
+        IntField("unused4", 0),
+        IntField("seldisp", 0),
+        IntField("selbroken", 0),
+        IntField("unused5", 0),
+        ByteField("candidate", 0),
+        ByteField("unused6", 0),
+        ByteField("unused7", 0),
+        ByteField("unused8", 0),
+        IntField("v6_flag", 0),
+        IntField("unused9", 0),
+        IP6Field("dstaddr6", "::"),
+        IP6Field("srcaddr6", "::"),
+    ]
+
+
+class NTPInfoLoop(Packet):
+    """
+    Loop filter variables.
+    """
+
+    name = "info_loop"
+    fields_desc = [
+        TimeStampField("last_offset", 0),
+        TimeStampField("drift_comp", 0),
+        IntField("compliance", 0),
+        IntField("watchdog_timer", 0)
+    ]
+
+
+class NTPInfoSys(Packet):
+    """
+    System info. Mostly the sys.* variables, plus a few unique to
+    the implementation.
+    """
+
+    name = "info_sys"
+    fields_desc = [
+        IPField("peer", "0.0.0.0"),
+        ByteField("peer_mode", 0),
+        ByteField("leap", 0),
+        ByteField("stratum", 0),
+        ByteField("precision", 0),
+        FixedPointField("rootdelay", 0, size=32, frac_bits=16),
+        FixedPointField("rootdispersion", 0, size=32, frac_bits=16),
+        IPField("refid", 0),
+        TimeStampField("reftime", 0),
+        IntField("poll", 0),
+        FlagsField("flags", 0, 8, _sys_info_flags),
+        ByteField("unused1", 0),
+        ByteField("unused2", 0),
+        ByteField("unused3", 0),
+        FixedPointField("bdelay", 0, size=32, frac_bits=16),
+        FixedPointField("frequency", 0, size=32, frac_bits=16),
+        TimeStampField("authdelay", 0),
+        FixedPointField("stability", 0, size=32, frac_bits=16),
+        IntField("v6_flag", 0),
+        IntField("unused4", 0),
+        IP6Field("peer6", "::")
+    ]
+
+
+class NTPInfoSysStats(Packet):
+    """
+    System stats. These are collected in the protocol module.
+    """
+
+    name = "info_sys_stats"
+    fields_desc = [
+        IntField("timeup", 0),
+        IntField("timereset", 0),
+        IntField("denied", 0),
+        IntField("oldversionpkt", 0),
+        IntField("newversionpkt", 0),
+        IntField("unknownversion", 0),
+        IntField("badlength", 0),
+        IntField("processed", 0),
+        IntField("badauth", 0),
+        IntField("received", 0),
+        IntField("limitrejected", 0)
+    ]
+
+
+class NTPInfoMemStats(Packet):
+    """
+    Peer memory statistics.
+    """
+
+    name = "info_mem_stats"
+    fields_desc = [
+        IntField("timereset", 0),
+        ShortField("totalpeermem", 0),
+        ShortField("freepeermem", 0),
+        IntField("findpeer_calls", 0),
+        IntField("allocations", 0),
+        IntField("demobilizations", 0),
+        FieldListField(
+            "hashcount",
+            [0.0 for i in range(0, _NTP_HASH_SIZE)],
+            ByteField("", 0),
+            count_from=lambda p: _NTP_HASH_SIZE
+        )
+    ]
+
+
+class NTPInfoIOStats(Packet):
+    """
+    I/O statistics.
+    """
+
+    name = "info_io_stats"
+    fields_desc = [
+        IntField("timereset", 0),
+        ShortField("totalrecvbufs", 0),
+        ShortField("freerecvbufs", 0),
+        ShortField("fullrecvbufs", 0),
+        ShortField("lowwater", 0),
+        IntField("dropped", 0),
+        IntField("ignored", 0),
+        IntField("received", 0),
+        IntField("sent", 0),
+        IntField("notsent", 0),
+        IntField("interrupts", 0),
+        IntField("int_received", 0)
+    ]
+
+
+class NTPInfoTimerStats(Packet):
+    """
+    Timer stats.
+    """
+
+    name = "info_timer_stats"
+    fields_desc = [
+        IntField("timereset", 0),
+        IntField("alarms", 0),
+        IntField("overflows", 0),
+        IntField("xmtcalls", 0),
+    ]
+
+
+_conf_peer_flags = [
+    "CONF_FLAG_AUTHENABLE",
+    "CONF_FLAG_PREFER",
+    "CONF_FLAG_BURST",
+    "CONF_FLAG_IBURST",
+    "CONF_FLAG_NOSELECT",
+    "CONF_FLAG_SKEY"
+]
+
+
+class NTPConfPeer(Packet):
+    """
+    Structure for passing peer configuration information.
+    """
+
+    name = "conf_peer"
+    fields_desc = [
+        IPField("peeraddr", "0.0.0.0"),
+        ByteField("hmode", 0),
+        ByteField("version", 0),
+        ByteField("minpoll", 0),
+        ByteField("maxpoll", 0),
+        FlagsField("flags", 0, 8, _conf_peer_flags),
+        ByteField("ttl", 0),
+        ShortField("unused1", 0),
+        IntField("keyid", 0),
+        StrFixedLenField("keystr", "", length=128),
+        IntField("v6_flag", 0),
+        IntField("unused2", 0),
+        IP6Field("peeraddr6", "::")
+    ]
+
+
+class NTPConfUnpeer(Packet):
+    """
+    Structure for passing peer deletion information.
+    """
+
+    name = "conf_unpeer"
+    fields_desc = [
+        IPField("peeraddr", "0.0.0.0"),
+        IntField("v6_flag", 0),
+        IP6Field("peeraddr6", "::")
+    ]
+
+
+_restrict_flags = [
+    "RES_IGNORE",
+    "RES_DONTSERVE",
+    "RES_DONTTRUST",
+    "RES_VERSION",
+    "RES_NOPEER",
+    "RES_LIMITED",
+    "RES_NOQUERY",
+    "RES_NOMODIFY",
+    "RES_NOTRAP",
+    "RES_LPTRAP",
+    "RES_KOD",
+    "RES_MSSNTP",
+    "RES_FLAKE",
+    "RES_NOMRULIST",
+]
+
+
+class NTPConfRestrict(Packet):
+    """
+    Structure used for specifying restrict entries.
+    """
+
+    name = "conf_restrict"
+    fields_desc = [
+        IPField("addr", "0.0.0.0"),
+        IPField("mask", "0.0.0.0"),
+        FlagsField("flags", 0, 16, _restrict_flags),
+        ShortField("m_flags", 0),
+        IntField("v6_flag", 0),
+        IP6Field("addr6", "::"),
+        IP6Field("mask6", "::")
+    ]
+
+
+class NTPInfoKernel(Packet):
+    """
+    Structure used for returning kernel pll/PPS information
+    """
+
+    name = "info_kernel"
+    fields_desc = [
+        IntField("offset", 0),
+        IntField("freq", 0),
+        IntField("maxerror", 0),
+        IntField("esterror", 0),
+        ShortField("status", 0),
+        ShortField("shift", 0),
+        IntField("constant", 0),
+        IntField("precision", 0),
+        IntField("tolerance", 0),
+        IntField("ppsfreq", 0),
+        IntField("jitter", 0),
+        IntField("stabil", 0),
+        IntField("jitcnt", 0),
+        IntField("calcnt", 0),
+        IntField("errcnt", 0),
+        IntField("stbcnt", 0),
+    ]
+
+
+class NTPInfoIfStatsIPv4(Packet):
+    """
+    Interface statistics.
+    """
+
+    name = "info_if_stats"
+    fields_desc = [
+        PadField(IPField("unaddr", "0.0.0.0"), 16, padwith="\x00"),
+        PadField(IPField("unbcast", "0.0.0.0"), 16, padwith="\x00"),
+        PadField(IPField("unmask", "0.0.0.0"), 16, padwith="\x00"),
+        IntField("v6_flag", 0),
+        StrFixedLenField("ifname", "", length=32),
+        IntField("flags", 0),
+        IntField("last_ttl", 0),
+        IntField("num_mcast", 0),
+        IntField("received", 0),
+        IntField("sent", 0),
+        IntField("notsent", 0),
+        IntField("uptime", 0),
+        IntField("scopeid", 0),
+        IntField("ifindex", 0),
+        IntField("ifnum", 0),
+        IntField("peercnt", 0),
+        ShortField("family", 0),
+        ByteField("ignore_packets", 0),
+        ByteField("action", 0),
+        IntField("_filler0", 0)
+    ]
+
+
+class NTPInfoIfStatsIPv6(Packet):
+    """
+    Interface statistics.
+    """
+
+    name = "info_if_stats"
+    fields_desc = [
+        IP6Field("unaddr", "::"),
+        IP6Field("unbcast", "::"),
+        IP6Field("unmask", "::"),
+        IntField("v6_flag", 0),
+        StrFixedLenField("ifname", "", length=32),
+        IntField("flags", 0),
+        IntField("last_ttl", 0),
+        IntField("num_mcast", 0),
+        IntField("received", 0),
+        IntField("sent", 0),
+        IntField("notsent", 0),
+        IntField("uptime", 0),
+        IntField("scopeid", 0),
+        IntField("ifindex", 0),
+        IntField("ifnum", 0),
+        IntField("peercnt", 0),
+        ShortField("family", 0),
+        ByteField("ignore_packets", 0),
+        ByteField("action", 0),
+        IntField("_filler0", 0)
+    ]
+
+
+class NTPInfoMonitor1(Packet):
+    """
+    Structure used for returning monitor data.
+    """
+
+    name = "InfoMonitor1"
+    fields_desc = [
+        IntField("lasttime", 0),
+        IntField("firsttime", 0),
+        IntField("lastdrop", 0),
+        IntField("count", 0),
+        IPField("addr", "0.0.0.0"),
+        IPField("daddr", "0.0.0.0"),
+        IntField("flags", 0),
+        ShortField("port", 0),
+        ByteField("mode", 0),
+        ByteField("version", 0),
+        IntField("v6_flag", 0),
+        IntField("unused1", 0),
+        IP6Field("addr6", "::"),
+        IP6Field("daddr6", "::")
+    ]
+
+
+class NTPInfoAuth(Packet):
+    """
+    Structure used to return information concerning the authentication module.
+    """
+
+    name = "info_auth"
+    fields_desc = [
+        IntField("timereset", 0),
+        IntField("numkeys", 0),
+        IntField("numfreekeys", 0),
+        IntField("keylookups", 0),
+        IntField("keynotfound", 0),
+        IntField("encryptions", 0),
+        IntField("decryptions", 0),
+        IntField("expired", 0),
+        IntField("keyuncached", 0),
+    ]
+
+
+class NTPConfTrap(Packet):
+    """
+    Structure used to pass add/clear trap information to the client
+    """
+
+    name = "conf_trap"
+    fields_desc = [
+        IPField("local_address", "0.0.0.0"),
+        IPField("trap_address", "0.0.0.0"),
+        ShortField("trap_port", 0),
+        ShortField("unused", 0),
+        IntField("v6_flag", 0),
+        IP6Field("local_address6", "::"),
+        IP6Field("trap_address6", "::"),
+    ]
+
+
+class NTPInfoControl(Packet):
+    """
+    Structure used to return statistics from the control module.
+    """
+
+    name = "info_control"
+    fields_desc = [
+        IntField("ctltimereset", 0),
+        IntField("numctlreq", 0),
+        IntField("numctlbadpkts", 0),
+        IntField("numctlresponses", 0),
+        IntField("numctlfrags", 0),
+        IntField("numctlerrors", 0),
+        IntField("numctltooshort", 0),
+        IntField("numctlinputresp", 0),
+        IntField("numctlinputfrag", 0),
+        IntField("numctlinputerr", 0),
+        IntField("numctlbadoffset", 0),
+        IntField("numctlbadversion", 0),
+        IntField("numctldatatooshort", 0),
+        IntField("numctlbadop", 0),
+        IntField("numasyncmsgs", 0),
+    ]
+
+
+# ntp_request.h
+_ntpd_private_errors = {
+    0: "no error",
+    1: "incompatible implementation number",
+    2: "unimplemented request code",
+    3: "format error (wrong data items, data size, packet size etc.)",
+    4: "no data available (e.g. request for details on unknown peer)",
+    5: "I don\"t know",
+    6: "I don\"t know",
+    7: "authentication failure (i.e. permission denied)",
+}
+
+
+# dict mapping request codes to the right response data class
+_private_data_objects = {
+    0: NTPInfoPeerList,  # "REQ_PEER_LIST",
+    1: NTPInfoPeerSummary,  # "REQ_PEER_LIST_SUM",
+    2: NTPInfoPeer,  # "REQ_PEER_INFO",
+    3: NTPInfoPeerStats,  # "REQ_PEER_STATS",
+    4: NTPInfoSys,  # "REQ_SYS_INFO",
+    5: NTPInfoSysStats,  # "REQ_SYS_STATS",
+    6: NTPInfoIOStats,  # "REQ_IO_STATS",
+    7: NTPInfoMemStats,  # "REQ_MEM_STATS",
+    8: NTPInfoLoop,  # "REQ_LOOP_INFO",
+    9: NTPInfoTimerStats,  # "REQ_TIMER_STATS",
+    10: NTPConfPeer,  # "REQ_CONFIG",
+    11: NTPConfUnpeer,  # "REQ_UNCONFIG",
+    28: NTPInfoAuth,  # "REQ_AUTHINFO",
+    30: NTPConfTrap,  # "REQ_ADD_TRAP",
+    34: NTPInfoControl,  # "REQ_GET_CTLSTATS",
+    38: NTPInfoKernel,  # "REQ_GET_KERNEL",
+    42: NTPInfoMonitor1,  # "REQ_MON_GETLIST_1",
+}
+
+
+class NTPPrivateRespPacketListField(PacketListField):
+    """
+    PacketListField handling the response data.
+    """
+
+    def m2i(self, pkt, s):
+        ret = None
+
+        # info_if_stats
+        if pkt.request_code == 44 or pkt.request_code == 45:
+            is_v6 = struct.unpack("!I", s[48:52])[0]
+            ret = NTPInfoIfStatsIPv6(s) if is_v6 else NTPInfoIfStatsIPv4(s)
+        else:
+            ret = _private_data_objects.get(pkt.request_code, Raw)(s)
+
+        return ret
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+        length = pkt.data_item_size
+        if length > 0:
+            item_counter = 0
+            # Response payloads can be placed in several packets
+            while len(remain) >= pkt.data_item_size and item_counter < pkt.nb_items:
+                current = remain[:length]
+                remain = remain[length:]
+                current_packet = self.m2i(pkt, current)
+                lst.append(current_packet)
+                item_counter += 1
+
+        return remain, lst
+
+
+class NTPPrivateReqPacket(Packet):
+    """
+    Packet handling request data.
+    """
+
+    name = "request data"
+    fields_desc = [StrField("req_data", "")]
+
+
+_request_codes = {
+    0: "REQ_PEER_LIST",
+    1: "REQ_PEER_LIST_SUM",
+    2: "REQ_PEER_INFO",
+    3: "REQ_PEER_STATS",
+    4: "REQ_SYS_INFO",
+    5: "REQ_SYS_STATS",
+    6: "REQ_IO_STATS",
+    7: "REQ_MEM_STATS",
+    8: "REQ_LOOP_INFO",
+    9: "REQ_TIMER_STATS",
+    10: "REQ_CONFIG",
+    11: "REQ_UNCONFIG",
+    12: "REQ_SET_SYS_FLAG",
+    13: "REQ_CLR_SYS_FLAG",
+    14: "REQ_MONITOR",
+    15: "REQ_NOMONITOR",
+    16: "REQ_GET_RESTRICT",
+    17: "REQ_RESADDFLAGS",
+    18: "REQ_RESSUBFLAGS",
+    19: "REQ_UNRESTRICT",
+    20: "REQ_MON_GETLIST",
+    21: "REQ_RESET_STATS",
+    22: "REQ_RESET_PEER",
+    23: "REQ_REREAD_KEYS",
+    24: "REQ_DO_DIRTY_HACK",
+    25: "REQ_DONT_DIRTY_HACK",
+    26: "REQ_TRUSTKEY",
+    27: "REQ_UNTRUSTKEY",
+    28: "REQ_AUTHINFO",
+    29: "REQ_TRAPS",
+    30: "REQ_ADD_TRAP",
+    31: "REQ_CLR_TRAP",
+    32: "REQ_REQUEST_KEY",
+    33: "REQ_CONTROL_KEY",
+    34: "REQ_GET_CTLSTATS",
+    35: "REQ_GET_LEAPINFO",
+    36: "REQ_GET_CLOCKINFO",
+    37: "REQ_SET_CLKFUDGE",
+    38: "REQ_GET_KERNEL",
+    39: "REQ_GET_CLKBUGINFO",
+    41: "REQ_SET_PRECISION",
+    42: "REQ_MON_GETLIST_1",
+    43: "REQ_HOSTNAME_ASSOCID",
+    44: "REQ_IF_STATS",
+    45: "REQ_IF_RELOAD"
+}
+
+
+class NTPPrivateReqPacketListField(PacketListField):
+    """
+    Handles specific request packets.
+    """
+
+    # See ntpdc/ntpdc.c and ntpdc/ntpdc_ops.c
+
+    def m2i(self, pkt, s):
+        ret = None
+
+        if pkt.request_code == 2 or pkt.request_code == 3:
+            # REQ_PEER_INFO (see ntpdc/ntpdc_ops.c: showpeer())
+            # REQ_PEER_STATS (for request only)
+            ret = NTPInfoPeerList(s)
+
+        elif pkt.request_code == 10:
+            # REQ_CONFIG
+            ret = NTPConfPeer(s)
+
+        elif pkt.request_code == 11:
+            # REQ_CONFIG
+            ret = NTPConfUnpeer(s)
+
+        elif pkt.request_code == 17:
+            # REQ_RESADDFLAGS
+            ret = NTPConfRestrict(s)
+
+        elif pkt.request_code == 18:
+            # REQ_RESSUBFLAGS
+            ret = NTPConfRestrict(s)
+
+        elif pkt.request_code == 22:
+            # REQ_RESET_PEER
+            ret = NTPConfUnpeer(s)
+
+        elif pkt.request_code == 30 or pkt.request_code == 31:
+            # REQ_ADD_TRAP
+            ret = NTPConfTrap(s)
+
+        else:
+            ret = NTPPrivateReqPacket(s)
+
+        return ret
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+        length = pkt.data_item_size
+        if length > 0:
+            item_counter = 0
+            while len(remain) >= pkt.data_item_size * pkt.nb_items and item_counter < pkt.nb_items:
+                current = remain[:length]
+                remain = remain[length:]
+                current_packet = self.m2i(pkt, current)
+                lst.append(current_packet)
+                item_counter += 1
+
+        # If "auth" bit is set, don"t forget the padding bytes
+        if pkt.auth:
+            padding_end = len(remain) - _NTP_PRIVATE_REQ_PKT_TAIL_LEN
+            current_packet = Raw(remain[:padding_end])
+            lst.append(current_packet)
+            remain = remain[padding_end:]
+
+        return remain, lst
+
+
+class NTPPrivatePktTail(Packet):
+    """
+    include/ntp_request.h
+    The req_pkt_tail structure is used by ntpd to adjust for different
+    packet sizes that may arrive.
+    """
+
+    name = "req_pkt_tail"
+    fields_desc = [
+        TimeStampField("tstamp", 0),
+        IntField("key_id", 0),
+        XStrFixedLenField(
+            "dgst", "", length_from=lambda x: _NTP_AUTH_MD5_DGST_SIZE)
+    ]
+
+
+class NTPPrivate(NTP):
+    """
+    Packet handling the private (mode 7) messages.
+    """
+
+    #________________________________________________________________________
+    #
+    # ntpd source code: ntp_request.h
+    #________________________________________________________________________
+    #
+    # A mode 7 packet is used exchanging data between an NTP server
+    # and a client for purposes other than time synchronization, e.g.
+    # monitoring, statistics gathering and configuration.  A mode 7
+    # packet has the following format:
+    #
+    #    0			  1		      2			  3
+    #    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #   |R|M| VN  | Mode|A|  Sequence   | Implementation|   Req Code    |
+    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #   |  Err  | Number of data items  |  MBZ  |   Size of data item   |
+    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #   |								|
+    #   |            Data (Minimum 0 octets, maximum 500 octets)        |
+    #   |                                                               |
+    #                            [...]                                  |
+    #   |			                                        |
+    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #   |               Encryption Keyid (when A bit set)               |
+    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #   |                                                               |
+    #   |          Message Authentication Code (when A bit set)         |
+    #   |                                                               |
+    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    #
+    # where the fields are (note that the client sends requests, the server
+    # responses):
+    #
+    # Response Bit:  This packet is a response (if clear, packet is a request).
+    #
+    # More Bit:	Set for all packets but the last in a response which
+    #      	requires more than one packet.
+    #
+    # Version Number: 2 for current version
+    #
+    # Mode:	Always 7
+    #
+    # Authenticated bit: If set, this packet is authenticated.
+    #
+    # Sequence number: For a multipacket response, contains the sequence
+    #      	number of this packet.  0 is the first in the sequence,
+    #      	127 (or less) is the last.  The More Bit must be set in
+    #      	all packets but the last.
+    #
+    # Implementation number: The number of the implementation this request code
+    #      	is defined by.  An implementation number of zero is used
+    #      	for requst codes/data formats which all implementations
+    #      	agree on.  Implementation number 255 is reserved (for
+    #      	extensions, in case we run out).
+    #
+    # Request code: An implementation-specific code which specifies the
+    #      	operation to be (which has been) performed and/or the
+    #      	format and semantics of the data included in the packet.
+    #
+    # Err:	Must be 0 for a request.  For a response, holds an error
+    #      	code relating to the request.  If nonzero, the operation
+    #      	requested wasn"t performed.
+    #
+    #      	0 - no error
+    #      	1 - incompatible implementation number
+    #      	2 - unimplemented request code
+    #      	3 - format error (wrong data items, data size, packet size etc.)
+    #      	4 - no data available (e.g. request for details on unknown peer)
+    #      	5-6 I don"t know
+    #      	7 - authentication failure (i.e. permission denied)
+    #
+    # Number of data items: number of data items in packet.  0 to 500
+    #
+    # MBZ:	A reserved data field, must be zero in requests and responses.
+    #
+    # Size of data item: size of each data item in packet.  0 to 500
+    #
+    # Data:	Variable sized area containing request/response data.  For
+    #      	requests and responses the size in octets must be greater
+    #      	than or equal to the product of the number of data items
+    #      	and the size of a data item.  For requests the data area
+    #      	must be exactly 40 octets in length.  For responses the
+    #      	data area may be any length between 0 and 500 octets
+    #      	inclusive.
+    #
+    # Message Authentication Code: Same as NTP spec, in definition and function.
+    #      	May optionally be included in requests which require
+    #      	authentication, is never included in responses.
+    #
+    # The version number, mode and keyid have the same function and are
+    # in the same location as a standard NTP packet.  The request packet
+    # is the same size as a standard NTP packet to ease receive buffer
+    # management, and to allow the same encryption procedure to be used
+    # both on mode 7 and standard NTP packets.  The mac is included when
+    # it is required that a request be authenticated, the keyid should be
+    # zero in requests in which the mac is not included.
+    #
+    # The data format depends on the implementation number/request code pair
+    # and whether the packet is a request or a response.  The only requirement
+    # is that data items start in the octet immediately following the size
+    # word and that data items be concatenated without padding between (i.e.
+    # if the data area is larger than data_items*size, all padding is at
+    # the end).  Padding is ignored, other than for encryption purposes.
+    # Implementations using encryption might want to include a time stamp
+    # or other data in the request packet padding.  The key used for requests
+    # is implementation defined, but key 15 is suggested as a default.
+    #________________________________________________________________________
+    #
+
+    name = "Private (mode 7)"
+    fields_desc = [
+        BitField("response", 0, 1),
+        BitField("more", 0, 1),
+        BitField("version", 2, 3),
+        BitField("mode", 0, 3),
+        BitField("auth", 0, 1),
+        BitField("seq", 0, 7),
+        ByteEnumField("implementation", 0, _implementations),
+        ByteEnumField("request_code", 0, _request_codes),
+        BitEnumField("err", 0, 4, _ntpd_private_errors),
+        BitField("nb_items", 0, 12),
+        BitField("mbz", 0, 4),
+        BitField("data_item_size", 0, 12),
+        ConditionalField(
+            NTPPrivateReqPacketListField(
+                "req_data",
+                [],
+                Packet,
+                length_from=lambda p: p.data_item_size,
+                count_from=lambda p: p.nb_items
+            ),
+            lambda p: p.response == 0
+        ),
+        # Responses
+        ConditionalField(
+            NTPPrivateRespPacketListField(
+                "data",
+                [],
+                Packet,
+                length_from=lambda p: p.data_item_size,
+                count_from=lambda p: p.nb_items
+            ),
+            lambda p: p.response == 1
+        ),
+        # Responses are not supposed to be authenticated
+        ConditionalField(PacketField("authenticator", "", NTPPrivatePktTail),
+                         lambda p: p.response == 0 and p.auth == 1),
+    ]
+
+
+##############################################################################
+##### Layer bindings
+##############################################################################
+
+bind_layers(UDP, NTP, {"sport": 123})
+bind_layers(UDP, NTP, {"dport": 123})
+bind_layers(UDP, NTP, {"sport": 123, "dport": 123})
+
+
diff --git a/test/regression.uts b/test/regression.uts
index a6a8fe8..849fb80 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -4998,3 +4998,1052 @@
 assert(eap.desired_auth_type == 43)
 
 
+################################### ntp.py ###################################
+#################################### NTP #####################################
++ NTP module tests
+
+= NTP - Layers (1)
+p = NTPHeader()
+assert(NTPHeader in p)
+assert(not NTPControl in p)
+assert(not NTPPrivate in p)
+assert(NTP in p)
+p = NTPControl()
+assert(not NTPHeader in p)
+assert(NTPControl in p)
+assert(not NTPPrivate in p)
+assert(NTP in p)
+p = NTPPrivate()
+assert(not NTPHeader in p)
+assert(not NTPControl in p)
+assert(NTPPrivate in p)
+assert(NTP in p)
+
+
+= NTP - Layers (2)
+p = NTPHeader()
+assert(type(p[NTP]) == NTPHeader)
+p = NTPControl()
+assert(type(p[NTP]) == NTPControl)
+p = NTPPrivate()
+assert(type(p[NTP]) == NTPPrivate)
+
+
+################################# NTPHeader ##################################
++ NTPHeader tests
+
+= NTPHeader - Basic checks
+len(str(NTP())) == 48
+
+
+= NTPHeader - Dissection
+s = "!\x0b\x06\xea\x00\x00\x00\x00\x00\x00\xf2\xc1\x7f\x7f\x01\x00\xdb9\xe8\xa21\x02\xe6\xbc\xdb9\xe8\x81\x02U8\xef\xdb9\xe8\x80\xdcl+\x06\xdb9\xe8\xa91\xcbI\xbf\x00\x00\x00\x01\xady\xf3\xa1\xe5\xfc\xd02\xd2j\x1e'\xc3\xc1\xb6\x0e"
+p = NTP(s)
+assert(isinstance(p, NTPHeader))
+assert(p[NTPAuthenticator].key_id == 1)
+assert(p[NTPAuthenticator].dgst.encode("hex") == 'ad79f3a1e5fcd032d26a1e27c3c1b60e')
+
+
+= NTPHeader - KoD
+s = '\xe4\x00\x06\xe8\x00\x00\x00\x00\x00\x00\x02\xcaINIT\x00\x00\x00\x00\x00\x00\x00\x00\xdb@\xe3\x9eH\xa3pj\xdb@\xe3\x9eH\xf0\xc3\\\xdb@\xe3\x9eH\xfaL\xac\x00\x00\x00\x01B\x86)\xc1Q4\x8bW8\xe7Q\xda\xd0Z\xbc\xb8'
+p = NTP(s)
+assert(isinstance(p, NTPHeader))
+assert(p.leap == 3)
+assert(p.version == 4)
+assert(p.mode == 4)
+assert(p.stratum == 0)
+assert(p.ref_id == 'INIT')
+
+
+############################ NTP Control (mode 6) ############################
++ NTP Control (mode 6) tests
+
+= NTP Control (mode 6) - CTL_OP_READSTAT (1) - request
+s = '\x16\x01\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 1)
+assert(p.sequence == 12)
+assert(p.status == 0)
+assert(p.association_id == 0)
+assert(p.offset == 0)
+assert(p.count == 0)
+assert(p.data == '')
+
+
+= NTP Control (mode 6) - CTL_OP_READSTAT (2) - response
+s = '\x16\x81\x00\x0c\x06d\x00\x00\x00\x00\x00\x04\xe5\xfc\xf6$'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 1)
+assert(p.sequence == 12)
+assert(isinstance(p.status_word, NTPSystemStatusPacket))
+assert(p.status_word.leap_indicator == 0)
+assert(p.status_word.clock_source == 6)
+assert(p.status_word.system_event_counter == 6)
+assert(p.status_word.system_event_code == 4)
+assert(p.association_id == 0)
+assert(p.offset == 0)
+assert(p.count == 4)
+assert(isinstance(p.data, NTPPeerStatusDataPacket))
+assert(p.data.association_id == 58876)
+assert(isinstance(p.data.peer_status, NTPPeerStatusPacket))
+assert(p.data.peer_status.configured == 1)
+assert(p.data.peer_status.auth_enabled == 1)
+assert(p.data.peer_status.authentic == 1)
+assert(p.data.peer_status.reachability == 1)
+assert(p.data.peer_status.reserved == 0)
+assert(p.data.peer_status.peer_sel == 6)
+assert(p.data.peer_status.peer_event_counter == 2)
+assert(p.data.peer_status.peer_event_code == 4)
+
+
+= NTP Control (mode 6) - CTL_OP_READVAR (1) - request
+s = '\x16\x02\x00\x12\x00\x00\xfc\x8f\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.op_code == 2)
+assert(p.sequence == 18)
+assert(p.status == 0)
+assert(p.association_id == 64655)
+assert(p.data == '')
+
+
+= NTP Control (mode 6) - CTL_OP_READVAR (2) - reponse (1st packet)
+s = '\xd6\xa2\x00\x12\xc0\x11\xfc\x8f\x00\x00\x01\xd4srcadr=192.168.122.1, srcport=123, dstadr=192.168.122.100, dstport=123,\r\nleap=3, stratum=16, precision=-24, rootdelay=0.000, rootdisp=0.000,\r\nrefid=INIT, reftime=0x00000000.00000000, rec=0x00000000.00000000,\r\nreach=0x0, unreach=5, hmode=1, pmode=0, hpoll=6, ppoll=10, headway=62,\r\nflash=0x1200, keyid=1, offset=0.000, delay=0.000, dispersion=15937.500,\r\njitter=0.000, xleave=0.240,\r\nfiltdelay= 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00,\r\nfiltoffset= 0.00 0.00 0.00 0.00 '
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 0)
+assert(p.more == 1)
+assert(p.op_code == 2)
+assert(p.sequence == 18)
+assert(isinstance(p.status_word, NTPPeerStatusPacket))
+assert(p.status_word.configured == 1)
+assert(p.status_word.auth_enabled == 1)
+assert(p.status_word.authentic == 0)
+assert(p.status_word.reachability == 0)
+assert(p.status_word.peer_sel == 0)
+assert(p.status_word.peer_event_counter == 1)
+assert(p.status_word.peer_event_code == 1)
+assert(p.association_id == 64655)
+assert(p.offset == 0)
+assert(p.count == 468)
+assert(p.data.load == 'srcadr=192.168.122.1, srcport=123, dstadr=192.168.122.100, dstport=123,\r\nleap=3, stratum=16, precision=-24, rootdelay=0.000, rootdisp=0.000,\r\nrefid=INIT, reftime=0x00000000.00000000, rec=0x00000000.00000000,\r\nreach=0x0, unreach=5, hmode=1, pmode=0, hpoll=6, ppoll=10, headway=62,\r\nflash=0x1200, keyid=1, offset=0.000, delay=0.000, dispersion=15937.500,\r\njitter=0.000, xleave=0.240,\r\nfiltdelay= 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00,\r\nfiltoffset= 0.00 0.00 0.00 0.00 ')
+ 
+
+= NTP Control (mode 6) - CTL_OP_READVAR (3) - reponse (2nd packet)
+s = '\xd6\x82\x00\x12\xc0\x11\xfc\x8f\x01\xd4\x00i0.00 0.00 0.00 0.00,\r\nfiltdisp= 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00\r\n\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 2)
+assert(p.sequence == 18)
+assert(isinstance(p.status_word, NTPPeerStatusPacket))
+assert(p.association_id == 64655)
+assert(p.offset == 468)
+assert(p.count == 105)
+assert(p.data.load == '0.00 0.00 0.00 0.00,\r\nfiltdisp= 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00\r\n\x00\x00\x00')
+
+
+= NTP Control (mode 6) - CTL_OP_READVAR (4) - request
+s = '\x16\x02\x00\x13\x00\x00s\xb5\x00\x00\x00\x0btest1,test2\x00\x00\x00\x00\x01=\xc2;\xc7\xed\xb9US9\xd6\x89\x08\xc8\xaf\xa6\x12'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 2)
+assert(len(p.data.load) == 12)
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '3dc23bc7edb9555339d68908c8afa612')
+
+
+= NTP Control (mode 6) - CTL_OP_READVAR (5) - response
+s = '\xd6\xc2\x00\x13\x05\x00s\xb5\x00\x00\x00\x00\x00\x00\x00\x01\x97(\x02I\xdb\xa0s8\xedr(`\xdbJX\n'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 1)
+assert(p.more == 0)
+assert(p.op_code == 2)
+assert(len(p.data.load) == 0)
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '97280249dba07338ed722860db4a580a')
+
+
+= NTP Control (mode 6) - CTL_OP_WRITEVAR (1) - request
+s = '\x16\x03\x00\x11\x00\x00\x00\x00\x00\x00\x00\x0btest1,test2\x00\x00\x00\x00\x01\xaf\xf1\x0c\xb4\xc9\x94m\xfcM\x90\tJ\xa1p\x94J'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 3)
+assert(len(p.data.load) == 12)
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == 'aff10cb4c9946dfc4d90094aa170944a')
+
+
+= NTP Control (mode 6) - CTL_OP_WRITEVAR (2) - response
+s = '\xd6\xc3\x00\x11\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80z\x80\xfb\xaf\xc4pg\x98S\xa8\xe5xe\x81\x1c'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 1)
+assert(p.more == 0)
+assert(p.op_code == 3)
+assert(hasattr(p, 'status_word'))
+assert(isinstance(p.status_word, NTPErrorStatusPacket))
+assert(p.status_word.error_code == 5)
+assert(len(p.data.load) == 0)
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '807a80fbafc470679853a8e57865811c')
+
+
+= NTP Control (mode 6) - CTL_OP_CONFIGURE (1) - request
+s = '\x16\x08\x00\x16\x00\x00\x00\x00\x00\x00\x00\x0ccontrolkey 1\x00\x00\x00\x01\xea\xa7\xac\xa8\x1bj\x9c\xdbX\xe1S\r6\xfb\xef\xa4'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 8)
+assert(p.count == 12)
+assert(p.data.load == 'controlkey 1')
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == 'eaa7aca81b6a9cdb58e1530d36fbefa4')
+
+
+= NTP Control (mode 6) - CTL_OP_CONFIGURE (2) - response
+s = '\xd6\x88\x00\x16\x00\x00\x00\x00\x00\x00\x00\x12Config Succeeded\r\n\x00\x00\x00\x00\x00\x01\xbf\xa6\xd8_\xf9m\x1e2l)<\xac\xee\xc2\xa59'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 8)
+assert(p.count == 18)
+assert(p.data.load == 'Config Succeeded\r\n\x00\x00')
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == 'bfa6d85ff96d1e326c293caceec2a539')
+
+
+= NTP Control (mode 6) - CTL_OP_SAVECONFIG (1) - request
+s = '\x16\t\x00\x1d\x00\x00\x00\x00\x00\x00\x00\x0fntp.test.2.conf\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc9\xfb\x8a\xbe<`_\xfa6\xd2\x18\xc3\xb7d\x89#'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 9)
+assert(p.count == 15)
+assert(p.data.load == 'ntp.test.2.conf\x00')
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == 'c9fb8abe3c605ffa36d218c3b7648923')
+
+
+= NTP Control (mode 6) - CTL_OP_SAVECONFIG (2) - response
+s = "\xd6\x89\x00\x1d\x00\x00\x00\x00\x00\x00\x00*Configuration saved to 'ntp.test.2.conf'\r\n\x00\x00\x00\x00\x00\x012\xc2\xbaY\xc53\xfe(\xf5P\xe5\xa0\x86\x02\x95\xd9"
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 9)
+assert(p.count == 42)
+assert(p.data.load == "Configuration saved to 'ntp.test.2.conf'\r\n\x00\x00")
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '32c2ba59c533fe28f550e5a0860295d9')
+
+
+= NTP Control (mode 6) - CTL_OP_REQ_NONCE (1) - request
+s = '\x16\x0c\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 12)
+assert(p.data == '')
+assert(p.authenticator == '')
+
+
+= NTP Control (mode 6) - CTL_OP_REQ_NONCE (2) - response
+s = '\xd6\x8c\x00\x07\x00\x00\x00\x00\x00\x00\x00 nonce=db4186a2e1d9022472e24bc9\r\n'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 0)
+assert(p.more == 0)
+assert(p.op_code == 12)
+assert(p.data.load == 'nonce=db4186a2e1d9022472e24bc9\r\n')
+assert(p.authenticator == '')
+
+
+= NTP Control (mode 6) - CTL_OP_READ_MRU (1) - request
+s = '\x16\n\x00\x08\x00\x00\x00\x00\x00\x00\x00(nonce=db4186a2e1d9022472e24bc9, frags=32'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 0)
+assert(p.error == 0)
+assert(p.op_code == 10)
+assert(p.count == 40)
+assert(p.data.load == 'nonce=db4186a2e1d9022472e24bc9, frags=32')
+assert(p.authenticator == '')
+
+= NTP Control (mode 6) - CTL_OP_READ_MRU (2) - response
+s = '\xd6\x8a\x00\x08\x00\x00\x00\x00\x00\x00\x00\xe9nonce=db4186a2e2073198b93c6419, addr.0=192.168.122.100:123,\r\nfirst.0=0xdb418673.323e1a89, last.0=0xdb418673.323e1a89, ct.0=1,\r\nmv.0=36, rs.0=0x0, WWQ.0=18446744073709509383, now=0xdb4186a2.e20ff8f4,\r\nlast.newest=0xdb418673.323e1a89\r\n\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPControl))
+assert(p.version == 2)
+assert(p.mode == 6)
+assert(p.response == 1)
+assert(p.error == 0)
+assert(p.op_code == 10)
+assert(p.count == 233)
+assert(p.data.load == 'nonce=db4186a2e2073198b93c6419, addr.0=192.168.122.100:123,\r\nfirst.0=0xdb418673.323e1a89, last.0=0xdb418673.323e1a89, ct.0=1,\r\nmv.0=36, rs.0=0x0, WWQ.0=18446744073709509383, now=0xdb4186a2.e20ff8f4,\r\nlast.newest=0xdb418673.323e1a89\r\n\x00\x00\x00')
+assert(p.authenticator == '')
+
+
+############################ NTP Private (mode 7) ############################
++ NTP Private (mode 7) tests
+
+= NTP Private (mode 7) - error - Dissection
+s = '\x97\x00\x03\x1d@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 29)
+assert(p.err == 4)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_PEER_LIST (1) - request
+s = '\x17\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 0)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_PEER_LIST (2) - response
+s = '\x97\x00\x03\x00\x00\x01\x00 \x7f\x7f\x01\x00\x00{\x03\x83\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 0)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 32)
+assert(type(p.data[0]) == NTPInfoPeerList)
+assert(p.data[0].addr) == "127.127.1.0"
+assert(p.data[0].port) == 123
+
+
+= NTP Private (mode 7) - REQ_PEER_INFO (1) - request
+s = '\x17\x00\x03\x02\x00\x01\x00 \xc0\xa8zf\x00{\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 2)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 32)
+assert(isinstance(p.req_data[0], NTPInfoPeerList))
+assert(p.req_data[0].addr == "192.168.122.102")
+assert(p.req_data[0].port == 123)
+
+
+= NTP Private (mode 7) - REQ_PEER_INFO (2) - response
+s = '\x97\x00\x03\x02\x00\x01\x01\x18\xc0\xa8zf\xc0\xa8ze\x00{\x01\x03\x01\x00\x10\x06\n\xea\x04\x00\x00\xaf"\x00"\x16\x04\xb3\x01\x00\x00\x00\x00\x00\x00\x00INIT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x82\x9d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb<\x8d\xc5\xde\x7fB\x89\xdb<\x8d\xc5\xde\x7fB\x89\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 2)
+assert(isinstance(p.data[0], NTPInfoPeer))
+assert(p.data[0].dstaddr == "192.168.122.102")
+assert(p.data[0].srcaddr == "192.168.122.101")
+assert(p.data[0].srcport == 123)
+assert(p.data[0].associd == 1203)
+assert(p.data[0].keyid == 1)
+
+
+= NTP Private (mode 7) - REQ_PEER_LIST_SUM (1) - request
+s = '\x17\x00\x03\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 1)
+
+
+= NTP Private (mode 7) - REQ_PEER_LIST_SUM (2) - response (1st packet)
+s = '\xd7\x00\x03\x01\x00\x06\x00H\n\x00\x02\x0f\xc0\x00\x02\x01\x00{\x10\x06\n\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x02\x0f\xc0\x00\x02\x02\x00{\x10\x06\n\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x01\x02\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x02\x0f\xc0\xa8d\x01\x00{\x10\x07\n\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01eth0\xc0\xa8zg\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x02\x0f\xc0\xa8d\x02\x00{\x10\x07\n\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x00\x02\xc0\xa8zh\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\n\x00\x02\x0f\xc0\xa8d\r\x00{\x10\x07\n\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8zk\x00{\x01\x01\xc0\xa8ze\xc0\xa8zf\x00{\x0b\x06\x07\xf4\x83\x01\x00\x00\x07\x89\x00\x00\x00\x007\xb1\x00h\x00\x00o?\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8zm\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 1)
+assert(isinstance(x, NTPInfoPeerSummary) for x in p.data)
+assert(p.data[0].srcaddr == "192.0.2.1")
+
+
+= NTP Private (mode 7) - REQ_PEER_LIST_SUM (3) - response (2nd packet)
+s = '\xd7\x01\x03\x01\x00\x06\x00H\xc0\xa8ze\xc0\xa8zg\x00{\x10\x08\n\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01eth1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8ze\xc0\xa8zg\x00{\x10\x08\n\x00\x11\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x01\x02\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8ze\xc0\xa8zh\x00{\x10\x08\n\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01eth0\xc0\xa8zg\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8ze\xc0\xa8zi\x00{\x10\x07\n\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x00\x02\xc0\xa8zh\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\xa8ze\xc0\xa8zj\x00{\x10\x07\n\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8zk\x00{\x01\x01\xc0\xa8ze\xc0\xa8zk\x00{\x10\x07\n\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8zm\x00{\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 1)
+assert(isinstance(x, NTPInfoPeerSummary) for x in p.data)
+assert(p.data[0].srcaddr == "192.168.122.103")
+
+
+= NTP Private (mode 7) - REQ_PEER_LIST_SUM (3) - response (3rd packet)
+s = '\x97\x02\x03\x01\x00\x02\x00H\xc0\xa8ze\xc0\xa8zl\x00{\x10\x07\n\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01eth1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8ze\xc0\xa8zm\x00{\x10\x07\n\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfd\xff\x00\x00\x00\x00\x00\x00\x01\x02\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 1)
+assert(isinstance(x, NTPInfoPeerSummary) for x in p.data)
+assert(p.data[0].srcaddr == "192.168.122.108")
+
+
+= NTP Private (mode 7) - REQ_PEER_STATS (1) - request
+s = '\x17\x00\x03\x03\x00\x01\x00 \xc0\xa8ze\x00{\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 3)
+assert(isinstance(p.req_data[0], NTPInfoPeerList))
+
+
+= NTP Private (mode 7) - REQ_PEER_STATS (2) - response
+s = '\x97\x00\x03\x03\x00\x01\x00x\xc0\xa8zf\xc0\xa8ze\x00{\x00\x01\x01\x00\x10\x06\x00\x00\x00)\x00\x00\x00\x1e\x00\x02\xda|\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x00\x0b\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x07\x00\x00\x00\x00\xde\x7fB\x89\x00<\x8d\xc5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 3)
+assert(isinstance(x, NTPInfoPeerStats) for x in p.data)
+
+
+= NTP Private (mode 7) - REQ_SYS_INFO (1) - request
+s = '\x17\x00\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 4)
+
+
+= NTP Private (mode 7) - REQ_SYS_INFO (2) - response
+s = '\x97\x00\x03\x04\x00\x01\x00P\x7f\x7f\x01\x00\x03\x00\x0b\xf0\x00\x00\x00\x00\x00\x00\x03\x06\x7f\x7f\x01\x00\xdb<\xca\xf3\xa1\x92\xe1\xf7\x06\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x07\x00\x00\x00\x00\xde\x7fB\x89\x00<\x8d\xc5'
+p = NTP(s)
+
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 4)
+assert(isinstance(p.data[0], NTPInfoSys))
+assert(p.data[0].peer == "127.127.1.0")
+assert(p.data[0].peer_mode == 3)
+assert(p.data[0].leap == 0)
+assert(p.data[0].stratum == 11)
+assert(p.data[0].precision == 240)
+assert(p.data[0].refid == "127.127.1.0")
+
+
+= NTP Private (mode 7) - REQ_SYS_STATS (1) - request
+s = '\x17\x00\x03\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 5)
+
+
+= NTP Private (mode 7) - REQ_SYS_STATS (2) - response
+s = '\x97\x00\x03\x05\x00\x01\x00,\x00\x02\xe2;\x00\x02\xe2;\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b%\x00\x00\x00\x00\x00\x00\x0b=\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 5)
+assert(isinstance(p.data[0], NTPInfoSysStats))
+assert(p.data[0].timeup == 188987)
+assert(p.data[0].received == 2877)
+
+
+= NTP Private (mode 7) - REQ_IO_STATS (1) - request
+s = '\x17\x00\x03\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 6)
+
+
+= NTP Private (mode 7) - REQ_IO_STATS (2) - response
+s = '\x97\x00\x03\x06\x00\x01\x00(\x00\x00\x03\x04\x00\n\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\xd9\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00J'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 6)
+assert(p.data[0].timereset == 772)
+assert(p.data[0].sent == 217)
+
+
+= NTP Private (mode 7) - REQ_MEM_STATS (1) - request
+s = '\x17\x00\x03\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 7)
+
+
+= NTP Private (mode 7) - REQ_MEM_STATS (2) - response
+s = '\x97\x00\x03\x07\x00\x01\x00\x94\x00\x00\n\xee\x00\x0f\x00\r\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 7)
+assert(p.data[0].timereset == 2798)
+assert(p.data[0].totalpeermem == 15)
+assert(p.data[0].freepeermem == 13)
+assert(p.data[0].findpeer_calls == 60)
+assert(p.data[0].hashcount[25] == 1 and p.data[0].hashcount[89] == 1)
+
+
+= NTP Private (mode 7) - REQ_LOOP_INFO (1) - request
+s = '\x17\x00\x03\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 8)
+
+
+= NTP Private (mode 7) - REQ_LOOP_INFO (2) - response
+s = '\x97\x00\x03\x08\x00\x01\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 8)
+assert(p.data[0].last_offset == 0.0)
+assert(p.data[0].watchdog_timer == 4)
+
+
+
+= NTP Private (mode 7) - REQ_TIMER_STATS (1) - request
+s = '\x17\x00\x03\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 9)
+
+
+= NTP Private (mode 7) - REQ_TIMER_STATS (2) - response
+s = '\x97\x00\x03\t\x00\x01\x00\x10\x00\x00\x01h\x00\x00\x01h\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 9)
+assert(p.data[0].timereset == 360)
+assert(p.data[0].alarms == 360)
+
+
+= NTP Private (mode 7) - REQ_CONFIG (1) - request
+s = '\x17\x80\x03\n\x00\x01\x00\xa8\xc0\xa8zm\x01\x03\x06\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xec\x93\xb1\xa8\xa0a\x00\x00\x00\x01Z\xba\xfe\x01\x1cr\x05d\xa1\x14\xb1)\xe9vD\x8d'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 10)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 168)
+assert(hasattr(p, 'req_data'))
+assert(isinstance(p.req_data[0], NTPConfPeer))
+assert(p.req_data[0].peeraddr == "192.168.122.109")
+assert(p.req_data[0].hmode == 1)
+assert(p.req_data[0].version == 3)
+assert(p.req_data[0].minpoll == 6)
+assert(p.req_data[0].maxpoll == 10)
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '5abafe011c720564a114b129e976448d')
+
+
+= NTP Private (mode 7) - REQ_CONFIG (2) - response
+s = '\x97\x00\x03\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 10)
+assert(p.err == 0)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_UNCONFIG (1) - request
+s = '\x17\x80\x03\x0b\x00\x01\x00\x18\xc0\xa8zk\x00\x00\x00\x00X\x88P\xb1\xff\x7f\x00\x008\x88P\xb1\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xf0\x1bq\xc8\xe5\xa6\x00\x00\x00\x01\x1dM;\xfeZ~]Z\xe3Ea\x92\x9aE\xd8%'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 11)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 24)
+assert(hasattr(p, 'req_data'))
+assert(isinstance(p.req_data[0], NTPConfUnpeer))
+assert(p.req_data[0].peeraddr == "192.168.122.107")
+assert(p.req_data[0].v6_flag == 0)
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '1d4d3bfe5a7e5d5ae34561929a45d825')
+
+
+= NTP Private (mode 7) - REQ_UNCONFIG (2) - response
+s = '\x97\x00\x03\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 11)
+assert(p.err == 0)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_RESADDFLAGS (1) - request
+s = '\x17\x80\x03\x11\x00\x01\x000\xc0\xa8zi\xff\xff\xff\xff\x04\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xf0V\xa9"\xe6_\x00\x00\x00\x01>=\xb70Tp\xee\xae\xe1\xad4b\xef\xe3\x80\xc8'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 17)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 48)
+assert(hasattr(p, 'req_data'))
+assert(isinstance(p.req_data[0], NTPConfRestrict))
+assert(p.req_data[0].addr == "192.168.122.105")
+assert(p.req_data[0].mask == "255.255.255.255")
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '3e3db7305470eeaee1ad3462efe380c8')
+
+
+= NTP Private (mode 7) - REQ_RESSUBFLAGS (1) - request
+s = '\x17\x80\x03\x12\x00\x01\x000\xc0\xa8zi\xff\xff\xff\xff\x00\x10\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xf0F\xe0C\xa9@\x00\x00\x00\x01>e\r\xdf\xdb\x1e1h\xd0\xca)L\x07k\x90\n'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 18)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 48)
+assert(hasattr(p, 'req_data'))
+assert(isinstance(p.req_data[0], NTPConfRestrict))
+assert(p.req_data[0].addr == "192.168.122.105")
+assert(p.req_data[0].mask == "255.255.255.255")
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '3e650ddfdb1e3168d0ca294c076b900a')
+
+
+= NTP Private (mode 7) - REQ_RESET_PEER (1) - request
+s = "\x17\x80\x03\x16\x00\x01\x00\x18\xc0\xa8zf\x00\x00\x00\x00X\x88P\xb1\xff\x7f\x00\x008\x88P\xb1\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xef!\x99\x88\xa3\xf1\x00\x00\x00\x01\xb1\xff\xe8\xefB=\xa9\x96\xdc\xe3\x13'\xb3\xfc\xc2\xf5"
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 22)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 24)
+assert(hasattr(p, 'req_data'))
+assert(isinstance(p.req_data[0], NTPConfUnpeer))
+assert(p.req_data[0].peeraddr == "192.168.122.102")
+assert(p.req_data[0].v6_flag == 0)
+
+
+= NTP Private (mode 7) - REQ_AUTHINFO (1) - response
+s = '\x97\x00\x03\x1c\x00\x01\x00$\x00\x00\x01\xdd\x00\x00\x00\x02\x00\x00\x00\n\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00/\x00\x00\x00\x00\x00\x00\x00\x01'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 28)
+assert(p.err == 0)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 36)
+assert(hasattr(p, 'data'))
+assert(isinstance(p.data[0], NTPInfoAuth))
+assert(p.data[0].timereset == 477)
+assert(p.data[0].numkeys == 2)
+assert(p.data[0].numfreekeys == 10)
+assert(p.data[0].keylookups == 96)
+assert(p.data[0].keynotfound == 0)
+assert(p.data[0].encryptions == 9)
+assert(p.data[0].decryptions == 47)
+assert(p.data[0].expired == 0)
+assert(p.data[0].keyuncached == 1)
+
+
+= NTP Private (mode 7) - REQ_ADD_TRAP (1) - request
+s = '\x17\x80\x03\x1e\x00\x01\x000\x00\x00\x00\x00\xc0\x00\x02\x03H\x0f\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xedB\xdd\xda\x7f\x97\x00\x00\x00\x01b$\xb8IM.\xa61\xd0\x85I\x8f\xa7\'\x89\x92'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 1)
+assert(p.request_code == 30)
+assert(p.err == 0)
+assert(p.nb_items == 1)
+assert(hasattr(p, 'req_data'))
+assert(isinstance(p.req_data[0], NTPConfTrap))
+assert(p.req_data[0].trap_address == '192.0.2.3')
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '6224b8494d2ea631d085498fa7278992')
+
+
+= NTP Private (mode 7) - REQ_ADD_TRAP (2) - response
+s = '\x97\x00\x03\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 30)
+assert(p.err == 0)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_CLR_TRAP (1) - request
+s = '\x17\x80\x03\x1f\x00\x01\x000\x00\x00\x00\x00\xc0\x00\x02\x03H\x0f\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xedb\xb3\x18\x1c\x00\x00\x00\x00\x01\xa5_V\x9e\xb8qD\x92\x1b\x1c>Z\xad]*\x89'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 1)
+assert(p.request_code == 31)
+assert(p.err == 0)
+assert(p.nb_items == 1)
+assert(hasattr(p, 'req_data'))
+assert(isinstance(p.req_data[0], NTPConfTrap))
+assert(p.req_data[0].trap_address == '192.0.2.3')
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == 'a55f569eb87144921b1c3e5aad5d2a89')
+
+
+= NTP Private (mode 7) - REQ_CLR_TRAP (2) - response
+s = '\x97\x00\x03\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 31)
+assert(p.err == 0)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_GET_CTLSTATS - response
+s = '\x97\x00\x03"\x00\x01\x00<\x00\x00\x00\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 34)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 60)
+assert(type(p.data[0]) == NTPInfoControl)
+assert(p.data[0].ctltimereset == 237)
+
+
+= NTP Private (mode 7) - REQ_GET_KERNEL (1) - request
+s = '\x17\x00\x03&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 38)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_GET_KERNEL (2) - response
+s = '\x97\x00\x03&\x00\x01\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf4$\x00\x00\xf4$\x00 A\x00\x00\x00\x00\x00\x03\x00\x00\x00\x01\x01\xf4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 38)
+assert(p.nb_items == 1)
+assert(p.data_item_size == 60)
+assert(isinstance(p.data[0], NTPInfoKernel))
+assert(p.data[0].maxerror == 16000000)
+assert(p.data[0].esterror == 16000000)
+assert(p.data[0].status == 8257)
+assert(p.data[0].constant == 3)
+assert(p.data[0].precision == 1)
+assert(p.data[0].tolerance == 32768000)
+
+
+
+= NTP Private (mode 7) - REQ_MON_GETLIST_1 (1) - request
+s = '\x17\x00\x03*\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 42)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+
+
+= NTP Private (mode 7) - REQ_MON_GETLIST_1 (2) - response
+s = '\xd7\x00\x03*\x00\x06\x00H\x00\x00\x00;\x00\x00\x00;\x00\x00\x01\xd0\x00\x00\x00\x01\x94mw\xe9\xc0\xa8zg\x00\x00\x00\x01\x00{\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00;\x00\x00\x01\xd0\x00\x00\x00\x01\x13\xb6\xa9J\xc0\xa8zg\x00\x00\x00\x01\x00{\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00;\x00\x00\x01\xd0\x00\x00\x00\x01\xbb]\x81\xea\xc0\xa8zg\x00\x00\x00\x01\x00{\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00;\x00\x00\x01\xd0\x00\x00\x00\x01\xfc\xbf\xd5a\xc0\xa8zg\x00\x00\x00\x01\x00{\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00;\x00\x00\x01\xd0\x00\x00\x00\x01\xbe\x10x\xa8\xc0\xa8zg\x00\x00\x00\x01\x00{\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00;\x00\x00\x01\xd0\x00\x00\x00\x01\xde[ng\xc0\xa8zg\x00\x00\x00\x01\x00{\x03\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.request_code == 42)
+assert(p.nb_items == 6)
+assert(p.data_item_size == 72)
+
+
+= NTP Private (mode 7) - REQ_IF_STATS (1) - request
+s = '\x17\x80\x03,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xeb\xdd\x8cH\xefe\x00\x00\x00\x01\x8b\xfb\x90u\xa8ad\xe8\x87\xca\xbf\x96\xd2\x9d\xddI'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 1)
+assert(p.request_code == 44)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == '8bfb9075a86164e887cabf96d29ddd49')
+
+
+= NTP Private (mode 7) - REQ_IF_STATS (2) - response
+s = "\xd7\x00\x03,\x00\x03\x00\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x01lo\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\n\x00'\xff\xfe\xe3\x81r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01eth0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\n\x00'\xff\xfe\xa0\x1d\xd0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01eth1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x00\x00\n\x00\x01\x00\x00\x00\x00"
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 44)
+assert(p.err == 0)
+assert(p.nb_items == 3)
+assert(p.data_item_size == 136)
+assert(isinstance(p.data[0], NTPInfoIfStatsIPv6))
+assert(p.data[0].unaddr == "::1")
+assert(p.data[0].unmask == "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
+assert(p.data[0].ifname.startswith("lo"))
+
+
+= NTP Private (mode 7) - REQ_IF_STATS (3) - response
+s = '\xd7\x01\x03,\x00\x03\x00\x88\xc0\xa8ze\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8z\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00eth1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x02\x00\x01\x00\x00\x00\x00\n\x00\x02\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x02\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00eth0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00lo\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 44)
+assert(p.err == 0)
+assert(p.nb_items == 3)
+assert(p.data_item_size == 136)
+assert(isinstance(p.data[0], NTPInfoIfStatsIPv4))
+assert(p.data[0].unaddr == "192.168.122.101")
+assert(p.data[0].unmask == "255.255.255.0")
+assert(p.data[0].ifname.startswith("eth1"))
+
+
+= NTP Private (mode 7) - REQ_IF_RELOAD (1) - request
+s = '\x17\x80\x03-\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb9\xed\xa3\xdc\x7f\xc6\x11\x00\x00\x00\x01\xfb>\x96*\xe7O\xf7\x8feh\xd4\x07L\xc0\x08\xcb'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 0)
+assert(p.more == 0)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 1)
+assert(p.request_code == 45)
+assert(p.nb_items == 0)
+assert(p.data_item_size == 0)
+assert(hasattr(p, 'authenticator'))
+assert(p.authenticator.key_id == 1)
+assert(p.authenticator.dgst.encode("hex") == 'fb3e962ae74ff78f6568d4074cc008cb')
+
+
+= NTP Private (mode 7) - REQ_IF_RELOAD (2) - response
+s = '\xd7\x00\x03-\x00\x03\x00\x88\x7f\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00lo\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\n\x00\x02\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x02\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00eth0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x01\xf4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x05\x00\x02\x00\x01\x00\x00\x00\x00\xc0\xa8ze\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8z\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00eth1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00}\x00\x00\x00\x00\x00\x00\x01\xf4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\t\x00\x02\x00\x01\x00\x00\x00\x00'
+p = NTP(s)
+assert(isinstance(p, NTPPrivate))
+assert(p.response == 1)
+assert(p.more == 1)
+assert(p.version == 2)
+assert(p.mode == 7)
+assert(p.auth == 0)
+assert(p.request_code == 45)
+assert(p.err == 0)
+assert(p.nb_items == 3)
+assert(p.data_item_size == 136)
+assert(isinstance(p.data[0], NTPInfoIfStatsIPv4))
+assert(p.data[0].unaddr == "127.0.0.1")
+assert(p.data[0].unmask == "255.0.0.0")
+assert(p.data[0].ifname.startswith("lo"))
+