[Git][NTPsec/ntpsec][master] 3 commits: Implement C ntpq's odd hostname-truncation rules in pyntpq.

Eric S. Raymond gitlab at mg.gitlab.com
Wed Oct 26 05:04:12 UTC 2016


Eric S. Raymond pushed to branch master at NTPsec / ntpsec


Commits:
44aae17d by Eric S. Raymond at 2016-10-26T01:01:23-04:00
Implement C ntpq's odd hostname-truncation rules in pyntpq.

- - - - -
ee50d579 by Eric S. Raymond at 2016-10-26T01:01:23-04:00
Method for shipping configuration in Python - untested.

- - - - -
7ec55328 by Eric S. Raymond at 2016-10-26T01:02:46-04:00
Incomplete implementation of cooked output.

- - - - -


2 changed files:

- ntpq/pyntpq
- pylib/packet.py


Changes:

=====================================
ntpq/pyntpq
=====================================
--- a/ntpq/pyntpq
+++ b/ntpq/pyntpq
@@ -128,58 +128,6 @@ NTP_LFP		= 0x7	# NTP timestamp
 NTP_MODE	= 0x8	# peer mode
 NTP_2BIT	= 0x9	# leap bits
 
-# Format values
-PADDING	= 0
-HA	= 1	# host address
-NA	= 2	# network address
-LP	= 3	# leap (print in binary)
-RF	= 4	# refid (sometimes string, sometimes not)
-AR	= 5	# array of times
-FX	= 6	# test flags
-TS	= 7	# l_fp timestamp in hex
-OC	= 8	# integer, print in octal
-EOV	= 255	# end of table
-
-# For the most part ntpq simply displays what ntpd provides in the
-# mostly plain-text mode 6 responses.  A few variable names are by
-# default "cooked" to provide more human-friendly output.  This is
-# a dictionary of cooked variables.
-cookedvars = {
-    "leap":		LP,
-    "reach":		OC,
-    "refid":		RF,
-    "reftime":		TS,
-    "clock":		TS,
-    "org":		TS,
-    "rec":		TS,
-    "xmt":		TS,
-    "flash":		FX,
-    "srcadr":		HA,
-    "peeradr":		HA,	# compat with others
-    "dstadr":		NA,
-    "filtdelay":	AR,
-    "filtoffset":	AR,
-    "filtdisp":		AR,
-    "filterror":	AR,	# compat with others
-}
-
-# flasher bits
-tstflagnames = (
-	"pkt_dup",		# BOGON1
-	"pkt_bogus",		# BOGON2
-	"pkt_unsync",		# BOGON3
-	"pkt_denied",		# BOGON4
-	"pkt_auth",		# BOGON5
-	"pkt_stratum",		# BOGON6
-	"pkt_header",		# BOGON7
-	"pkt_autokey",		# BOGON8
-	"pkt_crypto",		# BOGON9
-	"peer_stratum",		# BOGON10
-	"peer_dist",		# BOGON11
-	"peer_loop",		# BOGON12
-	"peer_unreach"		# BOGON13
-)
-
 class Ntpq(cmd.Cmd):
     "ntpq command interpreter"
 
@@ -226,6 +174,15 @@ usage: help [ command ]
     __peerheader  = "     remote           refid      " + __common + "jitter\n"
     __apeerheader = "     remote       refid   assid  " + __common + "jitter\n"
 
+    @staticmethod
+    def high_truncate(hostname, maxlen):
+        "Truncate on the left using leading _ to indicate 'more'."
+        # Used for local IPv6 addresses, best distinguashed by low bits
+        if len(hostname) <= maxlen:
+            return hostname
+        else:
+            return '-' + hostname[-maxlen+1:]
+
     def __dogetassoc(self):
         try:
             self.peers = self.session.readstat()
@@ -436,7 +393,7 @@ usage: help [ command ]
             c = " .+*"[CTL_PEER_STATVAL(self.session.rstatus) & 0x3]
         if len(self.chosts) > 1:
             maxhostlen = max([len(host) for (host, _af) in self.chosts])
-            self.say("%-*s " % (maxhostlen, self.session.hostname))
+            self.say(Ntpq.high_truncate(self.session.hostname, maxhostlen)+ " ")
         def is_ipv6(addr): return ":" in addr and "." not in addr
         if socket.AF_UNSPEC == af or af == (socket.AF_INET6 if is_ipv6(srcaddr) else socket.AF_INET):
             # Source host or clockname
@@ -507,7 +464,7 @@ usage: help [ command ]
         if len(self.chosts) > 1:
             maxhostlen = max([len(host) for (host, _af) in self.chosts])
             self.say("%-*.*s " % \
-                             (maxhostlen, maxhostlen, "server"))
+                             (maxhostlen, maxhostlen+1, "server"))
         self.say(header)
         self.say(("=" * (maxhostlen + 78)) + "\n")
         for peer in self.peers:
@@ -562,7 +519,7 @@ usage: help [ command ]
             return ()
         return (lo, hi)
 
-    def __printvars(self, variables, type, quiet):
+    def __printvars(self, variables, dtype, quiet):
         if self.rawmode:
             if not quiet:
                 self.say("status=0x%04x,\n" % self.session.rstatus)
@@ -570,10 +527,67 @@ usage: help [ command ]
             # high-half characters.  We won't do that unless somebody
             # files a bug, Mode 6 never seems to generate those in
             # variable fetches.
-            raw = session.response.replace(",\r\n",",\n")
-            self.say(raw)
+            text = session.response.replace(",\r\n",",\n")
         else:
-            pass
+            if not quiet:
+                self.say("status=%04x %s,\n" % \
+                         (self.session.rstatus,
+                          statustoa(dtype, self.session.rstatus)))
+
+            out_chars = 0
+            text = ""
+            print(variables)
+            for (name, value) in variables.items():
+                item = "%s=" % name
+                if name in ("reftime", "clock", "org", "rec", "xmt"):
+                    item += prettydate(value)
+                elif name in ("srcadr", "peeradr", "dstadr", "refid"):
+                    # C ntpq cooked these in obscure ways.  Since they
+                    # came up from the daemon as human-readable
+                    # strings this was probably a bad idea, but we'll
+                    # leave this case separated in case somebody thinks
+                    # re-cooking them is a good idea.
+                    item += value
+                elif name == "leap":
+                    item += ("00", "01", "10", "11")[value]
+                elif name == "reach":
+                    item += "%03lo" % value
+                elif name in("filtdelay", "filtoffset", "filtdisp", "filterror"):
+                    item += "\t".join(value.split())
+                elif name == "flash":
+                    item += "%02x" % value
+                    if value == 0:
+                        item += " ok"
+                    else:
+                        # flasher bits
+                        tstflagnames = (
+                            "pkt_dup",		# BOGON1
+                            "pkt_bogus",	# BOGON2
+                            "pkt_unsync",	# BOGON3
+                            "pkt_denied",	# BOGON4
+                            "pkt_auth",		# BOGON5
+                            "pkt_stratum",	# BOGON6
+                            "pkt_header",	# BOGON7
+                            "pkt_autokey",	# BOGON8
+                            "pkt_crypto",	# BOGON9
+                            "peer_stratum",	# BOGON10
+                            "peer_dist",	# BOGON11
+                            "peer_loop",	# BOGON12
+                            "peer_unreach"	# BOGON13
+                        )
+                        for (i, n) in enumerate(tstflagnames):
+                            if (1 << i) & value:
+                                item += tstflagnames + " "
+                        item = item[:-1]
+                else:
+                    item += repr(value)
+                item += ","
+                if len(text + item) > 78:
+                    text += "\n"
+                else:
+                    text += " "
+            text = text[:-2] + "\n"
+        self.say(text)
 
     def __dolist(self, varlist, associd, op, type):
         "List variables associated with a specified peer."
@@ -583,7 +597,6 @@ usage: help [ command ]
             quiet = False;
 	else:
             quiet = not (not varlist)	# nonempty?
-
         try:
             variables = self.session.readvar(associd, varlist, op)
         except Mode6Exception as e:
@@ -653,7 +666,7 @@ usage: timeout [ msec ]
             elif fmt == NTP_LFP:
                 self.say("%s  %s\n" % (legend, prettydate(value)))
             elif fmt in (NTP_2BIT, NTP_MODE):
-                self.say("%s  %s\n" % (legend, bin(value)[2:]))
+                self.say("%s %s\n" % (legend, ("00", "01", "10", "11")[value]))
             else:
                 self.warn("unexpected vc type %s for %s, value %s\n" % (fmt, name, value))
 


=====================================
pylib/packet.py
=====================================
--- a/pylib/packet.py
+++ b/pylib/packet.py
@@ -636,4 +636,10 @@ class Mode6Session:
                     # string-valued variables.
                     items.append((pair, ""))
         return collections.OrderedDict(items)
+
+    def config(self, configtext):
+        "Send configuration text to the daemon."
+        self.doquery(opcode=CTL_OP_CONFIGURE, qdata=configtext, auth=True)
+        return self.response
+
 # end



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/6d22f121a9bb635e209e27c13de1eca094b8549f...7ec553280d604ed4fa7564cdf10894239e549af9
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ntpsec.org/pipermail/vc/attachments/20161026/8e62c07a/attachment.html>


More information about the vc mailing list