[Git][NTPsec/ntpsec][master] There can be only one. Packet analyzer in Python, that is.
Eric S. Raymond
gitlab at mg.gitlab.com
Wed Nov 23 14:51:07 UTC 2016
Eric S. Raymond pushed to branch master at NTPsec / ntpsec
Commits:
d4762f1b by Eric S. Raymond at 2016-11-23T09:50:28-05:00
There can be only one. Packet analyzer in Python, that is.
- - - - -
2 changed files:
- ntpdig/pyntpdig
- pylib/packet.py
Changes:
=====================================
ntpdig/pyntpdig
=====================================
--- a/ntpdig/pyntpdig
+++ b/ntpdig/pyntpdig
@@ -40,8 +40,6 @@ from __future__ import print_function, division
import sys, socket, select, struct, time, getopt, datetime
-# This code can run with a large subset of its capabilities
-# even when the ntp library is not available.
try:
import ntp.packet
import ntp.util
@@ -49,51 +47,6 @@ except:
sys.stderr.write("ntpdig: can't find Python NTP library -- check PYTHONPATH.\n")
sys.exit(1)
-class SNTPPacket:
- @staticmethod
- def rescale(t):
- "Scale from NTP time to POSIX time"
- # Note: assumes we're in the same NTP era as the transmitter...
- UNIX_EPOCH = 2208988800
- return (t * 2**-32) - UNIX_EPOCH
- def __init__(self, data):
- self.hostname = None
- self.resolved = None
- self.received = time.time()
- self.data = data
- (self.livnm, self.stratum, self.poll, self.precision,
- self.root_delay, self.root_dispersion,
- self.reference_id, self.reference_timestamp,
- self.origin_timestamp, self.receive_timestamp,
- self.transmit_timestamp) = struct.unpack("!BBBBIIIQQQQ", data[:48])
- self.root_delay *= 2**-16
- self.root_dispersion *= 2**-16
- self.reference_timestamp = SNTPPacket.rescale(self.reference_timestamp)
- self.origin_timestamp = SNTPPacket.rescale(self.origin_timestamp)
- self.receive_timestamp = SNTPPacket.rescale(self.receive_timestamp)
- self.transmit_timestamp = SNTPPacket.rescale(self.transmit_timestamp)
- if len(data) > 192:
- self.extension_data = data[-12:192]
- self.auth_data = data[-12:]
- else:
- self.extension_data = None
- self.auth_data = None
- self.trusted = True
- def delta(self):
- return self.root_delay
- def epsilon(self):
- return self.root_dispersion
- def synchd(self):
- "Synchronization distance, estimates worst-case error in seconds"
- # This is "lambda" in NTP-speak, but that's a Python keyword
- return abs(self.delta() - self.epsilon())
- def adjust(self):
- "Adjustment implied by this packet."
- # FIXME: Clip low digits according to precision
- return self.received - self.transmit_timestamp
- def leap(self):
- return ("no-leap", "add-leap", "del-leap", "unsync")[((self.livnm) >> 6) & 0x3]
-
def queryhost(server, concurrent, timeout=5, port=123):
"Query IP addresses associated with a specified host."
try:
@@ -140,7 +93,7 @@ def queryhost(server, concurrent, timeout=5, port=123):
log("MAC verification on reply from %s failed" % sockaddr[0])
elif debug:
log("MAC verification on reply from %s succeeded" % sockaddr[0])
- pkt = SNTPPacket(d)
+ pkt = ntp.packet.SyncPacket(d)
pkt.hostname = server
pkt.resolved = sockaddr[0]
packets.append(pkt)
=====================================
pylib/packet.py
=====================================
--- a/pylib/packet.py
+++ b/pylib/packet.py
@@ -229,7 +229,7 @@ class Packet:
@staticmethod
def PKT_LI_VN_MODE(l, v, m): return ((((l) & 3) << 6) | Packet.VN_MODE((v), (m)))
- def __init__(self, session, version, mode):
+ def __init__(self, mode=MODE_CLIENT, version=NTP_VERSION, session=None):
self.session = session # Where to get session context
self.li_vn_mode = 0 # leap, version, mode (uint8_t)
# Subclasses have variable fields here
@@ -255,9 +255,12 @@ class Packet:
class SyncPacket(Packet):
"Mode 1-5 time-synchronization packet, including SNTP."
+ format = "!BBBBIIIQQQQ"
+ HEADER_LEN = 48
+ UNIX_EPOCH = 2208988800 # Midnight 1 Jan 1970 in secs since NTP epoch
- def __init__(self, session=None):
- Packet.__init__(self, session, session.pktversion, MODE_CONTROL)
+ def __init__(self, data= None):
+ Packet.__init__(self)
self.status = 0 # status word for association (uint16_t)
self.stratum = 0
self.poll = 0
@@ -270,25 +273,64 @@ class SyncPacket(Packet):
self.receive_timestamp = 0
self.transmit_timestamp = 0
self.extension = ''
- format = "!BBBBIIIQQQQ"
- HEADER_LEN = 48
- UNIX_EPOCH = 2208988800 # Midnight 1 Jan 1970 in secs since NTP epoch
+ self.data = data
+ if self.data is not None:
+ self.analyze(self.data)
+ self.posixize()
+ self.hostname = None
+ self.resolved = None
+ self.received = time.time()
+ if len(self.data) > 192:
+ self.extension_data = data[-12:192]
+ self.auth_data = data[-12:]
+ else:
+ self.extension_data = None
+ self.auth_data = None
+ self.trusted = True
def analyze(self, rawdata):
(self.li_vn_mode,
self.stratum,
self.poll,
self.precision,
- self.rootdelay,
- self.rootdispersion,
+ self.root_delay,
+ self.root_dispersion,
self.refid,
self.reference_timestamp,
self.origin_timestamp,
self.receive_timestamp,
self.transmit_timestamp) \
- = struct.unpack(ControlPacket.format, rawdata[:SyncPacket.HEADER_LEN])
+ = struct.unpack(SyncPacket.format, rawdata[:SyncPacket.HEADER_LEN])
self.data = rawdata[SyncPacket.HEADER_LEN:]
+ @staticmethod
+ def ntp_to_posix(t):
+ "Scale from NTP time to POSIX time"
+ # Note: assumes we're in the same NTP era as the transmitter...
+ return (t * 2**-32) - SyncPacket.UNIX_EPOCH
+
+ def posixize(self):
+ self.root_delay *= 2**-16
+ self.root_dispersion *= 2**-16
+ self.reference_timestamp = SyncPacket.ntp_to_posix(self.reference_timestamp)
+ self.origin_timestamp = SyncPacket.ntp_to_posix(self.origin_timestamp)
+ self.receive_timestamp = SyncPacket.ntp_to_posix(self.receive_timestamp)
+ self.transmit_timestamp = SyncPacket.ntp_to_posix(self.transmit_timestamp)
+
+ def delta(self):
+ return self.root_delay
+ def epsilon(self):
+ return self.root_dispersion
+ def synchd(self):
+ "Synchronization distance, estimates worst-case error in seconds"
+ # This is "lambda" in NTP-speak, but that's a Python keyword
+ return abs(self.delta() - self.epsilon())
+ def adjust(self):
+ "Adjustment implied by this packet."
+ # FIXME: Clip low digits according to precision
+ return self.received - self.transmit_timestamp
+ def leap(self):
+ return ("no-leap", "add-leap", "del-leap", "unsync")[((self.li_vn_mode) >> 6) & 0x3]
def flatten(self):
"Flatten the packet into an octet sequence."
body = struct.pack(ControlPacket.format,
@@ -305,15 +347,6 @@ class SyncPacket(Packet):
self.transmit_timestamp)
return body + self.extension
- def send(self):
- self.session.sendpkt(self.flatten())
-
- @staticmethod
- def ntp_to_posix(t):
- "Scale from NTP time to POSIX time"
- # Note: assumes we're in the same NTP era as the transmitter...
- return (t * 2**-32) - UNIX_EPOCH
-
def refid_octets(self):
"Analyze refid into octets."
return ((self.refid >> 24) & 0xff,
@@ -336,7 +369,9 @@ class ControlPacket(Packet):
"Mode 6 request/response."
def __init__(self, session, opcode=0, associd=0, qdata=''):
- Packet.__init__(self, session, session.pktversion, MODE_CONTROL)
+ Packet.__init__(self, mode=MODE_CONTROL,
+ version=session.pktversion,
+ session=session)
self.r_e_m_op = opcode # ntpq operation code
self.sequence = 1 # sequence number of request (uint16_t)
self.status = 0 # status word for association (uint16_t)
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/d4762f1ba4357ae81994b49e57057d94d0e9f983
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ntpsec.org/pipermail/vc/attachments/20161123/effcf4a5/attachment.html>
More information about the vc
mailing list