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
 .B =
 .RI [ remote-addr ]
 .IB network / mask
+\&...
 .PP
 This means that the peer
 .I tag
 .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.  
 .IB network / mask \fR.  
-Here,
+Here, a
 .I network
 is an IP address in dotted-quad form, and
 .I mask
 .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
 
   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
   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
   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):
   """
 
   def __init__(me, file):
@@ -239,18 +239,23 @@ class Config (object):
                                   (spec[i], e))
               i += 1
 
                                   (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.
 
             ## 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
 
     ## 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)
 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)',
     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.
 
 ###--------------------------------------------------------------------------
 ### Responding to a network up/down event.
@@ -363,14 +368,14 @@ def kickpeers():
       statemap = {}
       want = None
       matchp = False
       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:
         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 \
         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))
           if T._debug: print '#     %s: SELECTED' % info
           statemap[t] = 'up'
           select.append('%s=%s' % (g, t))