[Git][NTPsec/ntpsec][master] 3 commits: ntpq: Add noflake and doflake for packet loss simulation.

James Browning gitlab at mg.gitlab.com
Sun Sep 27 01:08:18 UTC 2020



James Browning pushed to branch master at NTPsec / ntpsec


Commits:
78a96b1e by James Browning at 2020-09-27T00:58:52+00:00
ntpq: Add noflake and doflake for packet loss simulation.




- - - - -
c6147f6b by James Browning at 2020-09-27T00:58:52+00:00
mode 6: Allow returning multiple specific MRU entries ...

if limit == 1 and multiple addresses provided.
mode 6: Solve packet storm when mrulist limit=1
- - - - -
4cb4e4c3 by James Browning at 2020-09-27T00:58:52+00:00
pylib: add first 16 addr & last arguments to mrulist


- - - - -


4 changed files:

- docs/includes/ntpq-body.adoc
- ntpclients/ntpq.py
- ntpd/ntp_control.c
- pylib/packet.py


Changes:

=====================================
docs/includes/ntpq-body.adoc
=====================================
@@ -150,6 +150,12 @@ as following.
 +debug more | less | off+::
   Turns internal query program debugging on and off.
 
++noflake+::
++doflake 'probability'::
+  Disables or enables the dropping of control packets by ntpq for testing.
+  Probabilities 0 and 1 should be certainly accepted and discarded
+  respectively. No default, but 0.1 should be a one in ten loss rate.
+
 +logfile <stderr> | filename+::
   Displays or sets the file for debug logging. <stderr> will send logs
   to standard error.
@@ -301,7 +307,8 @@ ind assid status conf reach auth condition last_event cnt
   server so loaded that none of its MRU entries age out before they
   are shipped. With this option, each segment is reported as it arrives.
 
-[[mrulist]]+mrulist+ [+limited+ | +kod+ | +mincount=+'count' | +mindrop=+'drop' | +minscore=+'score' | +maxlstint=+'seconds' | +minlstint=+'seconds' | +laddr=+'localaddr' | +sort=+'sortorder' | +resany=+'hexmask' | +resall=+'hexmask']::
+[[mrulist]]+mrulist+ [+limited+ | +kod+ | +mincount=+'count' | +mindrop=+'drop' | +minscore=+'score' | +maxlstint=+'seconds' | +minlstint=+'seconds' | +laddr=+'localaddr' | +sort=+'sortorder' | +resany=+'hexmask' | +resall=+'hexmask' | +limit=+'limit' |
++addr.'num'=+'address']::
   Obtain and print traffic counts collected and maintained by the
   monitor facility. This is useful for tracking who _uses_ or
   _abuses_ your server.
@@ -310,6 +317,19 @@ With the exception of +sort=+'sortorder', the options
 filter the list returned by +ntpd+. The +limited+ and +kod+ options
 return only entries representing client addresses from which the last
 packet received triggered either discarding or a KoD response.
+the +addr.'num'=+ option adds specific addresses to retrieve when
++limit=+'1'. Values of 0 to 15 are supported for 'num'. Also, used
+internallly with +last.'num'=+'hextime' to select starting point
+for retrieving continued response.
+the +frags=+'frags' option limits the number of datagrams
+(fragments) in response.  Used by newer ntpq versions instead
+of limit= when retrieving multiple entries.
+The +limit=+ option limits the MRU entries returned. limit=1
+is a special case:  Instead of fetching beginning with the
+supplied starting point's newer neighbor, fetch the supplied
+entries. This enables fetching a multiple entries by IP
+addresses.  When limit is not one and frags= is provided,
+the fragment limit controls.
 The +mincount=+'count' option filters entries that have received less
 than 'count' packets.
 The +mindrop=+'drop' option filters entries that have dropped less


=====================================
ntpclients/ntpq.py
=====================================
@@ -1215,6 +1215,42 @@ usage: config_from_file <configuration filename>
         for entry in entries:
             self.say(self.formatter.summary(entry) + "\n")
 
+    def do_noflake(self):
+        """Disables the dropping of control packets by ntpq for testing."""
+        self.session.flakey = False
+
+    def help_noflake(self):
+        """Print help for noflake."""
+        self.say("""\
+function: Disables the dropping of received packets by ntpq for testing.
+usage: noflake
+""")
+
+    def do_doflake(self, line):
+        """Drop some received packets for testing.
+
+        Probabilities 0 and 1 should be certainly accepted
+        and discarded respectively. No default, but 0.1
+        should be a one in ten loss rate.
+        """
+        try:
+            _ = float(line)
+            if not 0 < _ < 1:
+                raise ValueError
+            self.session.flakey = _
+        except ValueError:
+            self.say('Flakiness must be a (positive) float less than 1.')
+
+    def help_doflake(self):
+        """Print help for doflake."""
+        self.say("""\
+function: Enables the dropping of control packets by
+ntpq for testing. Probabilities 0 and 1 should be
+certainly accepted and discarded respectively. No
+default, but 0.1 should be a one in ten loss rate.
+usage: doflake <probability>
+""")
+
     def do_mrulist(self, line):
         """display the list of most recently seen source addresses,
            tags mincount=... resall=0x... resany=0x..."""


=====================================
ntpd/ntp_control.c
=====================================
@@ -3637,10 +3637,25 @@ static void read_mru_list(
 	} else if (0 != limit && 0 == frags)
 		frags = MRU_FRAGS_LIMIT;
 
+	mon = NULL;
+	if (limit == 1) {
+		for (i = 0; i < COUNTOF(last); i++) {
+			mon = mon_get_slot(&addr[i]);
+			if (mon != NULL) {
+				send_mru_entry(mon, i);
+			}
+		}
+		generate_nonce(rbufp, buf, sizeof(buf));
+		ctl_putunqstr("nonce", buf, strlen(buf));
+		get_systime(&now);
+		ctl_putts("now", &now);
+		ctl_flushpkt(0);
+		return;
+	}
+
 	/*
 	 * Find the starting point if one was provided.
 	 */
-	mon = NULL;
 	for (i = 0; i < (size_t)priors; i++) {
 		mon = mon_get_slot(&addr[i]);
 		if (mon != NULL) {


=====================================
pylib/packet.py
=====================================
@@ -207,6 +207,7 @@ from __future__ import print_function, division
 import getpass
 import hmac
 import os
+import random
 import select
 import socket
 import string
@@ -740,6 +741,7 @@ class ControlSession:
         self.logfp = sys.stdout
         self.nonce_xmit = 0
         self.slots = 0
+        self.flakey = None
 
     def warndbg(self, text, threshold):
         ntp.util.dolog(self.logfp, text, self.debug, threshold)
@@ -1019,6 +1021,10 @@ class ControlSession:
                 # usually, errno 111: connection refused
                 raise ControlException(SERR_SOCKET)
 
+            if self.flakey and self.flakey >= random.random():
+                warndbg('Flaky: I deliberately dropped a packet.', 1)
+                rawdata = None
+
             warndbg("Received %d octets" % len(rawdata), 3)
             rpkt = ControlPacket(self)
             try:
@@ -1597,6 +1603,11 @@ def parse_mru_variables(variables):
                  "maxlstint", "minlstint", "laddr", "recent",
                  "sort", "frags", "limit"):
             continue
+        elif k.startswith('addr.') or k.startswith('last.'):
+            kn = k.split('.')
+            if len(kn) != 2 or kn[1] not in map(str, list(range(16))):
+                raise ControlException(SERR_BADPARAM % k)
+            continue
         else:
             raise ControlException(SERR_BADPARAM % k)
     if 'frags' in variables:



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/366569b1ea50015b8556799c4d0cccbbfce666b7...4cb4e4c37f4e8a5de0eb4562f5d81831112f3e1b

-- 
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/366569b1ea50015b8556799c4d0cccbbfce666b7...4cb4e4c37f4e8a5de0eb4562f5d81831112f3e1b
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/20200927/f982c854/attachment-0001.htm>


More information about the vc mailing list