diff --git a/scapy/layers/ntp.py b/scapy/layers/ntp.py index 6560e397c..fe9ace1a1 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 -## 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 +# 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 @@ class TimeStampField(FixedPointField): 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 a6a8fe816..849fb80cc 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -4998,3 +4998,1052 @@ assert(hasattr(eap, 'desired_auth_type')) 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")) +