svc/conntrack.in: Allow multiple networks in a peer pattern.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 29 Sep 2017 00:24:47 +0000 (01:24 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 28 Jun 2018 23:29:24 +0000 (00:29 +0100)
This is sensible now that we're not trying to compare them for
specificness.

svc/conntrack.8.in
svc/conntrack.in

index 004ffa8..940097a 100644 (file)
@@ -85,13 +85,14 @@ followed by peer definitions, each of which looks like this:
 .B =
 .RI [ remote-addr ]
 .IB network / mask
+\&...
 .PP
 This means that the peer
 .I tag
-should be selected if the host's current IP address is within the
-network indicated by
+should be selected if the host's current IP address is within one of the
+networks indicated by
 .IB network / mask \fR.  
-Here,
+Here, a
 .I network
 is an IP address in dotted-quad form, and
 .I mask
index 261cf64..a31b268 100644 (file)
@@ -137,11 +137,11 @@ class Config (object):
 
   The most interesting thing is probably the `groups' slot, which stores a
   list of pairs (NAME, PATTERNS); the NAME is a string, and the PATTERNS a
-  list of (TAG, PEER, NET) triples.  The implication is that there should be
+  list of (TAG, PEER, NETS) triples.  The implication is that there should be
   precisely one peer from the set, and that it should be named TAG, where
-  (TAG, PEER, NET) is the first triple such that the host's primary IP
+  (TAG, PEER, NETS) is the first triple such that the host's primary IP
   address (if PEER is None -- or the IP address it would use for
-  communicating with PEER) is within the NET.
+  communicating with PEER) is within one of the networks defined by NETS.
   """
 
   def __init__(me, file):
@@ -239,18 +239,23 @@ class Config (object):
                                   (spec[i], e))
               i += 1
 
-            ## Parse the local network.
-            if len(spec) != i + 1:
-              raise ConfigError(me._file, lno, 'no network defined')
-            try:
-              net = parse_net(spec[i])
-            except Exception, e:
-              raise ConfigError(me._file, lno,
-                                "invalid IP network `%s': %s" %
-                                (spec[i], e))
+            ## Parse the list of local networks.
+            nets = []
+            while i < len(spec):
+              try:
+                net = parse_net(spec[i])
+              except Exception, e:
+                raise ConfigError(me._file, lno,
+                                  "invalid IP network `%s': %s" %
+                                  (spec[i], e))
+              else:
+                nets.append(net)
+              i += 1
+            if not nets:
+              raise ConfigError(me._file, lno, 'no networks defined')
 
             ## Add this entry to the list.
-            grplist.append((name, peer, net))
+            grplist.append((name, peer, nets))
 
     ## Fill in the default test address if necessary.
     if testaddr is None: testaddr = TESTADDR
@@ -271,10 +276,10 @@ def cmd_showgroups():
 def cmd_showgroup(g):
   try: pats = CF.groups[g]
   except KeyError: raise T.TripeJobError('unknown-group', g)
-  for t, p, n in pats:
+  for t, p, nn in pats:
     T.svcinfo('peer', t,
               'target', p and str(p) or '(default)',
-              'net', str(n))
+              'net', ' '.join(map(str, nn)))
 
 ###--------------------------------------------------------------------------
 ### Responding to a network up/down event.
@@ -363,14 +368,14 @@ def kickpeers():
       statemap = {}
       want = None
       matchp = False
-      for t, p, n in pp:
+      for t, p, nn in pp:
         if p is None or not upness: ip = addr
         else: ip = localaddr(p)
         if T._debug:
-          info = 'peer=%s; target=%s; net=%s; local=%s' % (
-            t, p or '(default)', n, straddr(ip))
+          info = 'peer = %s; target = %s; nets = %s; local = %s' % (
+            t, p or '(default)', ', '.join(map(str, nn)), straddr(ip))
         if upness and not matchp and \
-              ip is not None and ip.withinp(n):
+           ip is not None and any(ip.withinp(n) for n in nn):
           if T._debug: print '#     %s: SELECTED' % info
           statemap[t] = 'up'
           select.append('%s=%s' % (g, t))