[Git][NTPsec/ntpsec][master] Changed MIB system to use seperate read/write callbacks

Ian Bruene gitlab at mg.gitlab.com
Thu Nov 9 19:22:57 UTC 2017


Ian Bruene pushed to branch master at NTPsec / ntpsec


Commits:
9a41ad75 by Ian Bruene at 2017-11-09T13:22:34-06:00
Changed MIB system to use seperate read/write callbacks

SNMP writes are a multi step process, combining the read and write
function will result in a very cluttered and error prone block of code.

- - - - -


3 changed files:

- ntpclients/ntpsnmpd
- pylib/agentx.py
- tests/pylib/test_agentx.py


Changes:

=====================================
ntpclients/ntpsnmpd
=====================================
--- a/ntpclients/ntpsnmpd
+++ b/ntpclients/ntpsnmpd
@@ -46,199 +46,201 @@ class DataSource:  # This may be broken up in future to be less NTP-specific
         # ntpEntNotifications
         self.oidTree = {
             0:
-            node(True, None,
+            node(None, None, True,
                  # ntpEntNotifModeChange
-                 {1: node(True, None, None),
+                 {1: node(None, None, True, None),
                   # ntpEntNotifStratumChange
-                  2: node(True, None, None),
+                  2: node(None, None, True, None),
                   # ntpEntNotifSyspeerChange
-                  3: node(True, None, None),
+                  3: node(None, None, True, None),
                   # ntpEntNotifAddAssociation
-                  4: node(True, None, None),
+                  4: node(None, None, True, None),
                   # ntpEntNotifRemoveAsociation
-                  5: node(True, None, None),
+                  5: node(None, None, True, None),
                   # ntpEntNotifConfigChanged
-                  6: node(True, None, None),
+                  6: node(None, None, True, None),
                   # ntpEntNotifLeapSecondAnnounced
-                  7: node(True, None, None),
+                  7: node(None, None, True, None),
                   # ntpEntNotifHeartbeat
-                  8: node(True, None, None)}),
+                  8: node(None, None, True, None)}),
             # ntpSnmpMIBObjects
             1:
-            node(True, None,
+            node(None, None, True,
                  # ntpEntInfo
                  {1:
-                  node(True, None,
+                  node(None, None, True,
                        # ntpNetSoftwareName utf8str
-                       {1: node(True,
-                                (lambda oid:
+                       {1: node((lambda oid:
                                  self.cb_systemInfo(oid, None, "name")),
-                                None),
+                                None, True, None),
                         # ntpEntSoftwareVersion utf8str
-                        2: node(True,
-                                (lambda oid:
+                        2: node((lambda oid:
                                  self.cb_systemInfo(oid, None, "version")),
-                                None),
+                                None, True, None),
                         # ntpEntSoftwareVendor utf8str
-                        3: node(True,
-                                (lambda oid:
+                        3: node((lambda oid:
                                  self.cb_systemInfo(oid, None, "vendor")),
-                                None),
+                                None, True, None),
                         # ntpEntSystemType utf8str
-                        4: node(True,
-                                (lambda oid:
+                        4: node((lambda oid:
                                  self.cb_systemInfo(oid, None, "system")),
-                                None),
+                                None, True, None),
                         # ntpEntTimeResolution uint32
-                        5: node(True, self.cb_timeResolution, None),
+                        5: node(self.cb_timeResolution, None, True, None),
                         # ntpEntTimePrecision int32
-                        6: node(True, self.cb_timePrecision, None),
+                        6: node(self.cb_timePrecision, None, True, None),
                         # ntpEntTimeDistance DisplayString
-                        7: node(True, self.cb_timeDistance, None)}),
+                        7: node(self.cb_timeDistance, None, True, None)}),
                   # ntpEntStatus
                   2:
-                  node(True, None,
+                  node(None, None, True,
                        # ntpEntStatusCurrentMode INTEGER {...}
-                       {1: node(True, self.cb_statusCurrentMode, None),
+                       {1: node(self.cb_statusCurrentMode, None, True, None),
                         # ntpEntStatusStratum NtpStratum
-                        2: node(True, self.cb_statusStratum, None),
+                        2: node(self.cb_statusStratum, None, True, None),
                         # ntpEntStatusActiveRefSourceId
                         #  uint32 (0..99999)
-                        3: node(True,self.cb_statusActiveRefSourceID,
-                                None),
+                        3: node(self.cb_statusActiveRefSourceID,
+                                None, True, None),
                         # ntpEntStatusActiveRefSourceName utf8str
-                        4: node(True, self.cb_statusActiveRefSourceName,
-                                None),
+                        4: node(self.cb_statusActiveRefSourceName,
+                                None, True, None),
                         # ntpEntStatusActiveOffset DisplayString
-                        5: node(True, self.cb_statusActiveOffset, None),
+                        5: node(self.cb_statusActiveOffset, None, True, None),
                         # ntpEntStatusNumberOfRefSources
                         #  unit32 (0..99)
-                        6: node(True, self.cb_statusNumRefSources, None),
+                        6: node(self.cb_statusNumRefSources, None, True, None),
                         # ntpEntStatusDispersion DisplayString
-                        7: node(True, self.cb_statusDispersion, None),
+                        7: node(self.cb_statusDispersion, None, True, None),
                         # ntpEntStatusEntityUptime TimeTicks
-                        8: node(True, self.cb_statusEntityUptime, None),
+                        8: node(self.cb_statusEntityUptime, None, True, None),
                         # ntpEntStatusDateTime NtpDateTime
-                        9: node(True, self.cb_statusDateTime, None),
+                        9: node(self.cb_statusDateTime, None, True, None),
                         # ntpEntStatusLeapSecond NtpDateTime
-                        10: node(True, self.cb_statusLeapSecond, None),
+                        10: node(self.cb_statusLeapSecond, None, True, None),
                         # ntpEntStatusLeapSecondDirection
                         #  int32 (-1..1)
-                        11: node(True, self.cb_statusLeapSecDirection, None),
+                        11: node(self.cb_statusLeapSecDirection,
+                                 None, True, None),
                         # ntpEntStatusInPkts Counter32
-                        12: node(True, self.cb_statusInPkts, None),
+                        12: node(self.cb_statusInPkts, None, True, None),
                         # ntpEntStatusOutPkts Counter32
-                        13: node(True, self.cb_statusOutPkts, None),
+                        13: node(self.cb_statusOutPkts, None, True, None),
                         # ntpEntStatusBadVersion Counter32
-                        14: node(True, self.cb_statusBadVersion, None),
+                        14: node(self.cb_statusBadVersion, None, True, None),
                         # ntpEntStatusProtocolError Counter32
-                        15: node(True, self.cb_statusProtocolError, None),
+                        15: node(self.cb_statusProtocolError,
+                                 None, True, None),
                         # ntpEntStatusNotifications Counter32
-                        16: node(True, self.cb_statusNotifications, None),
+                        16: node(self.cb_statusNotifications,
+                                 None, True, None),
                         # ntpEntStatPktModeTable
                         #  SEQUENCE of NtpEntStatPktModeEntry
                         17:
-                        node(True, None,
+                        node(None, None, True,
                              # ntpEntStatPktModeEntry SEQUENCE {...}
                              {1:
-                              node(True, None,
+                              node(None, None, True,
                                    # ntpEntStatPktMode INTEGER {...}
-                                   {1: node(True, None, None),
+                                   {1: node(None, None, True, None),
                                     # ntpEntStatPktSent Counter32
-                                    2: node(True, None, None),
+                                    2: node(None, None, True, None),
                                     # ntpEntStatPktRecived Counter32
-                                    3: node(True, None, None)})})}),
+                                    3: node(None, None, True, None)})})}),
                   # ntpAssociation
                   3:
-                  node(True, None,
+                  node(None, None, True,
                        # ntpAssociationTable
                        #  SEQUENCE of NtpAssociationEntry
                        {1:
-                        node(True, None,
+                        node(None, None, True,
                              # ntpAssociationEntry SEQUENCE {...}
                              {1:
-                              node(True, None,
+                              node(None, None, True,
                                    # ntpAssocId uint32 (1..99999)
-                                   {1: node(True, self.cb_assocID, None),
+                                   {1: node(self.cb_assocID, None, True, None),
                                     # ntpAssocName utf8str
-                                    2: node(True, self.cb_assocName, None),
+                                    2: node(self.cb_assocName,
+                                            None, True, None),
                                     # ntpAssocRefId DisplayString
-                                    3: node(True, self.cb_assocRefID, None),
+                                    3: node(self.cb_assocRefID,
+                                            None, True, None),
                                     # ntpAssocAddressType
                                     #  InetAddressType
-                                    4: node(True, self.cb_assocAddrType,
-                                            None),
+                                    4: node(self.cb_assocAddrType,
+                                            None, True, None),
                                     # ntpAssocAddress
                                     #  InetAddress SIZE (4|8|16|20)
-                                    5: node(True, self.cb_assocAddr, None),
+                                    5: node(self.cb_assocAddr,
+                                            None, True, None),
                                     # ntpAssocOffset DisplayString
-                                    6: node(True, self.cb_assocOffset,
-                                            None),
+                                    6: node(self.cb_assocOffset,
+                                            None, True, None),
                                     # ntpAssocStratum NtpStratum
-                                    7: node(True, self.cb_assocStratum,
-                                            None),
+                                    7: node(self.cb_assocStratum,
+                                            None, True, None),
                                     # ntpAssocStatusJitter
                                     #  DisplayString
-                                    8: node(True, self.cb_assocStatusJitter,
-                                            None),
+                                    8: node(self.cb_assocStatusJitter,
+                                            None, True, None),
                                     # ntpAssocStatusDelay
                                     #  DisplayString
-                                    9: node(True, self.cb_assocStatusDelay,
-                                            None),
+                                    9: node(self.cb_assocStatusDelay,
+                                            None, True, None),
                                     # ntpAssocStatusDispersion
                                     #  DisplayString
-                                    10: node(True, self.cb_assocStatusDisp,
-                                             None)})}),
+                                    10: node(self.cb_assocStatusDisp,
+                                             None, True, None)})}),
                         # ntpAssociationStatisticsTable
                         #  SEQUENCE of ntpAssociationStatisticsEntry
                         2:
-                        node(True, None,
+                        node(None, None, True,
                              # ntpAssociationStatisticsEntry
                              #  SEQUENCE {...}
                              {1:
-                              node(True, None,
+                              node(None, None, True,
                                    # ntpAssocStatInPkts Counter32
-                                   {1: node(True, self.cb_assocStatInPkts,
-                                            None),
+                                   {1: node(self.cb_assocStatInPkts,
+                                            None, True, None),
                                     # ntpAssocStatOutPkts Counter32
-                                    2: node(True, self.cb_assocStatOutPkts,
-                                            None),
+                                    2: node(self.cb_assocStatOutPkts,
+                                            None, True, None),
                                     # ntpAssocStatProtocolError
                                     #  Counter32
-                                    3: node(True, self.cb_assocStatProtoErr,
-                                            None)})})}),
+                                    3: node(self.cb_assocStatProtoErr,
+                                            None, True, None)})})}),
                   # ntpEntControl
                   4:
-                  node(True, None,
+                  node(None, None, True,
                        # ntpEntHeartbeatInterval unit32
-                       {1: node(True, self.cb_entHeartbeatInterval,
-                                None),
+                       {1: node(self.cb_entHeartbeatInterval,
+                                None, True, None),
                         # ntpEntNotifBits BITS {...}
-                        2: node(True, self.cb_entNotifBits, None)}),
+                        2: node(self.cb_entNotifBits, None, True, None)}),
                   # ntpEntNotifObjects
                   5:
-                  node(True, None,
+                  node(None, None, True,
                        # ntpEntNotifMessage utf8str
-                       {1: node(True, self.cb_entNotifMessage, None)})}),
+                       {1: node(self.cb_entNotifMessage, None, True, None)})}),
             # ntpEntConformance
             2:
-            node(True, None,
+            node(None, None, True,
                  # ntpEntCompliances
                 {1:
-                 node(True, None,
+                 node(None, None, True,
                       # ntpEntNTPCompliance
-                      {1: node(True, None, None),
+                      {1: node(None, None, True, None),
                        # ntpEntSNTPCompliance
-                       2: node(True, None, None)}),
+                       2: node(None, None, True, None)}),
                  # ntpEntGroups
                  2:
-                 node(True, None,
+                 node(None, None, True,
                       # ntpEntObjectsGroup1 OBJECTS {...}
-                      {1: node(True, None, None),
+                      {1: node(None, None, True, None),
                        # ntpEntObjectsGroup2 OBJECTS {...}
-                       2: node(True, None, None),
+                       2: node(None, None, True, None),
                        # ntpEntNotifGroup NOTIFICATIONS {...}
-                       3: node(True, None, None)})})}
+                       3: node(None, None, True, None)})})}
         self.session = ntp.packet.ControlSession()
         self.session.openhost(DEFHOST)  # only local for now
 
@@ -246,16 +248,16 @@ class DataSource:  # This may be broken up in future to be less NTP-specific
         gen = ax.walkMIBTree(self.oidTree, ntpRootOID)
         while True:
             try:
-                oid, callback = gen.next()
+                oid, reader, writer = gen.next()
                 if nextP is True:
                     oidhit = (oid > searchoid)
                 else:
                     oidhit = (oid.subids == searchoid.subids)
-                if oidhit and (callback is not None):
+                if oidhit and (reader is not None):
                     if returnGenerator is True:
-                        return oid, callback, gen
+                        return oid, reader, gen
                     else:
-                        return oid, callback
+                        return oid, reader
             except StopIteration:
                 if returnGenerator is True:
                     return None, None, None
@@ -278,19 +280,19 @@ class DataSource:  # This may be broken up in future to be less NTP-specific
         # Find the first OID
         while True:
             try:
-                oid, callback = gen.next()
-                if callback is None:
+                oid, reader, writer = gen.next()
+                if reader is None:
                     continue  # skip unimplemented OIDs
                 elif oid.subids == oidrange.start.subids:
                     # ok, found the start, do we need to skip it?
                     if oidrange.start.include is True:
-                        oids.append((oid, callback))
+                        oids.append((oid, reader))
                         break
                     else:
                         continue
                 elif oid > oidrange.start:
                     # If we are here it means we hit the start but skipped
-                    oids.append((oid, callback))
+                    oids.append((oid, reader))
                     break
             except StopIteration:
                 # Couldn't find *anything*
@@ -300,13 +302,13 @@ class DataSource:  # This may be broken up in future to be less NTP-specific
         # Start filling in the rest of the range
         while True:
             try:
-                oid, callback = gen.next()
-                if callback is None:
+                oid, reader = gen.next()
+                if reader is None:
                     continue  # skip unimplemented OIDs
                 elif (oidrange.end is not None) and (oid >= oidrange.end):
                     break  # past the end of a bounded range
                 else:
-                    oids.append((oid, callback))
+                    oids.append((oid, reader))
             except StopIteration:
                 break  # We have run off the end of the MIB
         return oids


=====================================
pylib/agentx.py
=====================================
--- a/pylib/agentx.py
+++ b/pylib/agentx.py
@@ -1306,8 +1306,8 @@ def decode_packet(data):
 
 def walkMIBTree(tree, rootpath=()):
     # Tree node formats:
-    # {"static": True, "callback": <func>, "subids": {.blah.}}
-    # {"static": False, "callback": <func>, "subids": <func>}
+    # {"reader": <func>, "writer": <func>, "static": True, "subids": {.blah.}}
+    # {"reader": <func>, "writer": <func>, "static": False, "subids": <func>}
     # The "subids" function in dynamic nodes must return an MIB tree
     nodeStack = []
     oidStack = []
@@ -1327,7 +1327,7 @@ def walkMIBTree(tree, rootpath=()):
                 return
         key = currentKeys[keyID]
         oid = OID(rootpath + tuple(oidStack) + (key,))
-        yield (oid, current[key]["callback"])
+        yield (oid, current[key]["reader"], current[key]["writer"])
         if current[key]["subids"] is not None:
             # Push current node, move down a level
             nodeStack.append((current, currentKeys, keyID, key))
@@ -1344,8 +1344,9 @@ def walkMIBTree(tree, rootpath=()):
         keyID += 1
 
 
-def mibnode(static, callback, subs):
-    return {"static": static, "callback": callback, "subids": subs}
+def mibnode(reader, writer, static, subs):
+    return {"writer": writer, "reader": reader,
+            "static": static, "subids": subs}
 
 
 # Value types


=====================================
tests/pylib/test_agentx.py
=====================================
--- a/tests/pylib/test_agentx.py
+++ b/tests/pylib/test_agentx.py
@@ -2507,115 +2507,99 @@ class TestNtpclientsNtpsnmpd(unittest.TestCase):
         # Test empty tree
         self.assertEqual(tuple(f({})), ())
         # Test flat, fully static tree
-        self.assertEqual(tuple(f({0: {"static": True, "callback": None,
-                                      "subids": None},
-                                  1: {"static": True, "callback": None,
-                                      "subids": None},
-                                  2: {"static": True, "callback": None,
-                                      "subids": None},
-                                  5: {"static": True, "callback": None,
-                                      "subids": None}})),
-                         ((x.OID((0,)), None),
-                          (x.OID((1,)), None),
-                          (x.OID((2,)), None),
-                          (x.OID((5,)), None)))
+        self.assertEqual(tuple(f({0: {"reader": None, "writer": None,
+                                      "static": True, "subids": None},
+                                  1: {"reader": None, "writer": None,
+                                      "static": True, "subids": None},
+                                  2: {"reader": None, "writer": None,
+                                      "static": True, "subids": None},
+                                  5: {"reader": None, "writer": None,
+                                      "static": True, "subids": None}})),
+                         ((x.OID((0,)), None, None),
+                          (x.OID((1,)), None, None),
+                          (x.OID((2,)), None, None),
+                          (x.OID((5,)), None, None)))
         # Test nested, fully static tree
-        self.assertEqual(tuple(f({0: {"static": True,
-                                      "callback": None,
-                                      "subids": None},
-                                  1: {"static": True,
-                                      "callback": None,
-                                      "subids":
-                                      {0: {"static": True,
-                                           "callback": None,
-                                           "subids": None},
-                                       1: {"static": True,
-                                           "callback": None,
-                                           "subids":
-                                           {42: {"static": True,
-                                                 "callback": None,
+        self.assertEqual(tuple(f({0: {"reader": None, "writer": None,
+                                      "static": True, "subids": None},
+                                  1: {"reader": None, "writer": None,
+                                      "static": True, "subids":
+                                      {0: {"reader": None, "writer": None,
+                                           "static": True, "subids": None},
+                                       1: {"reader": None, "writer": None,
+                                           "static": True, "subids":
+                                           {42: {"reader": None,
+                                                 "writer": None,
+                                                 "static": True,
                                                  "subids": None}}}}},
-                                  5: {"static": True,
-                                      "callback": None,
-                                      "subids": None}})),
-                         ((x.OID((0,)), None),
-                          (x.OID((1,)), None),
-                          (x.OID((1, 0)), None),
-                          (x.OID((1, 1)), None),
-                          (x.OID((1, 1, 42)), None),
-                          (x.OID((5,)), None)))
+                                  5: {"reader": None, "writer": None,
+                                      "static": True, "subids": None}})),
+                         ((x.OID((0,)), None, None),
+                          (x.OID((1,)), None, None),
+                          (x.OID((1, 0)), None, None),
+                          (x.OID((1, 1)), None, None),
+                          (x.OID((1, 1, 42)), None, None),
+                          (x.OID((5,)), None, None)))
         # Test nested, fully static tree, with rootpath
-        self.assertEqual(tuple(f({0: {"static": True,
-                                      "callback": None,
-                                      "subids": None},
-                                  1: {"static": True,
-                                      "callback": None,
-                                      "subids":
-                                      {0: {"static": True,
-                                           "callback": None,
-                                           "subids": None},
-                                       1: {"static": True,
-                                           "callback": None,
-                                           "subids":
-                                           {42: {"static": True,
-                                                 "callback": None,
+        self.assertEqual(tuple(f({0: {"reader": None, "writer": None,
+                                      "static": True, "subids": None},
+                                  1: {"reader": None, "writer": None,
+                                      "static": True, "subids":
+                                      {0: {"reader": None, "writer": None,
+                                           "static": True, "subids": None},
+                                       1: {"reader": None, "writer": None,
+                                           "static": True, "subids":
+                                           {42: {"reader": None,
+                                                 "writer": None,
+                                                 "static": True,
                                                  "subids": None}}}}},
-                                  5: {"static": True,
-                                      "callback": None,
-                                      "subids": None}}, (23,))),
-                         ((x.OID((23, 0)), None),
-                          (x.OID((23, 1)), None),
-                          (x.OID((23, 1, 0)), None),
-                          (x.OID((23, 1, 1)), None),
-                          (x.OID((23, 1, 1, 42)), None),
-                          (x.OID((23, 5)), None)))
+                                  5: {"reader": None, "writer": None,
+                                      "static": True, "subids": None}},
+                                 (23,))),
+                         ((x.OID((23, 0)), None, None),
+                          (x.OID((23, 1)), None, None),
+                          (x.OID((23, 1, 0)), None, None),
+                          (x.OID((23, 1, 1)), None, None),
+                          (x.OID((23, 1, 1, 42)), None, None),
+                          (x.OID((23, 5)), None, None)))
         # subid lambda for dynamic tree testing
-        submaker = (lambda : {0: {"static": True,
-                                  "callback": None,
-                                  "subids": None},
-                              1: {"static": True,
-                                      "callback": None,
-                                      "subids":
-                                      {0: {"static": True,
-                                           "callback": None,
-                                           "subids": None}}},
-                              2: {"static": True,
-                                  "callback": None,
-                                  "subids": None}})
+        submaker = (lambda : {0: {"reader": None, "writer": None,
+                                  "static": True, "subids": None},
+                              1: {"reader": None, "writer": None,
+                                  "static": True, "subids":
+                                  {0: {"reader": None, "writer": None,
+                                       "static": True, "subids": None}}},
+                              2: {"reader": None, "writer": None,
+                                  "static": True, "subids": None}})
         # Test tree with dynamic nodes
-        self.assertEqual(tuple(f({0: {"static": True,
-                                      "callback": None,
-                                      "subids": None},
-                                  1: {"static": False,
-                                      "callback": None,
-                                      "subids": submaker},
-                                  2: {"static": True,
-                                      "callback": None,
-                                      "subids": None}})),
-                         ((x.OID((0,)), None),
-                          (x.OID((1,)), None),
-                          (x.OID((1, 0)), None),
-                          (x.OID((1, 1)), None),
-                          (x.OID((1, 1, 0)), None),
-                          (x.OID((1, 2)), None),
-                          (x.OID((2,)), None)))
+        self.assertEqual(tuple(f({0: {"reader": None, "writer": None,
+                                      "static": True, "subids": None},
+                                  1: {"reader": None, "writer": None,
+                                      "static": False, "subids": submaker},
+                                  2: {"reader": None, "writer": None,
+                                      "static": True, "subids": None}})),
+                         ((x.OID((0,)), None, None),
+                          (x.OID((1,)), None, None),
+                          (x.OID((1, 0)), None, None),
+                          (x.OID((1, 1)), None, None),
+                          (x.OID((1, 1, 0)), None, None),
+                          (x.OID((1, 2)), None, None),
+                          (x.OID((2,)), None, None)))
         # Test tree with dynamic nodes and root path
-        self.assertEqual(tuple(f({0: {"static": True,
-                                      "callback": None,
-                                      "subids": None},
-                                  1: {"static": False,
-                                      "callback": None,
-                                      "subids": submaker},
-                                  2: {"static": True,
-                                      "callback": None,
-                                      "subids": None}}, (23,))),
-                         ((x.OID((23, 0)), None),
-                          (x.OID((23, 1)), None),
-                          (x.OID((23, 1, 0)), None),
-                          (x.OID((23, 1, 1)), None),
-                          (x.OID((23, 1, 1, 0)), None),
-                          (x.OID((23, 1, 2)), None),
-                          (x.OID((23, 2)), None)))
+        self.assertEqual(tuple(f({0: {"reader": None, "writer": None,
+                                      "static": True, "subids": None},
+                                  1: {"reader": None, "writer": None,
+                                      "static": False, "subids": submaker},
+                                  2: {"reader": None, "writer": None,
+                                      "static": True, "subids": None}},
+                                 (23,))),
+                         ((x.OID((23, 0)), None, None),
+                          (x.OID((23, 1)), None, None),
+                          (x.OID((23, 1, 0)), None, None),
+                          (x.OID((23, 1, 1)), None, None),
+                          (x.OID((23, 1, 1, 0)), None, None),
+                          (x.OID((23, 1, 2)), None, None),
+                          (x.OID((23, 2)), None, None)))
 
 
 if __name__ == "__main__":



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/9a41ad75c84161d020cd7628b479cce2e387fe63

---
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/commit/9a41ad75c84161d020cd7628b479cce2e387fe63
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20171109/94544118/attachment.html>


More information about the vc mailing list