svc/conntrack.in: Factor out network parsing.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 28 Sep 2017 18:26:51 +0000 (19:26 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 28 Jun 2018 23:29:23 +0000 (00:29 +0100)
The new function is a little stricter than the old one.  The address
given must actually be the base address of the network, rather than any
old address within it.

svc/conntrack.in

index ef042f7..2dc380b 100644 (file)
@@ -100,6 +100,18 @@ def toposort(cmp, things):
 def parse_address(addrstr):
   return unpack('>L', S.inet_aton(addrstr))[0]
 
+def parse_net(netstr):
+  try: sl = netstr.index('/')
+  except ValueError: raise ValueError('missing mask')
+  addr = parse_address(netstr[:sl])
+  if netstr[sl + 1:].isdigit():
+    n = int(netstr[sl + 1:], 10)
+    mask = (1 << 32) - (1 << 32 - n)
+  else:
+    mask = parse_address(netstr[sl + 1:])
+  if addr&~mask: raise ValueError('network contains bits set beyond mask')
+  return addr, mask
+
 def straddr(a): return a is None and '#<none>' or S.inet_ntoa(pack('>L', a))
 def strmask(m):
   for i in xrange(33):
@@ -181,14 +193,8 @@ class Config (object):
         ## Syntax of a net is ADDRESS/MASK, where ADDRESS is a dotted-quad,
         ## and MASK is either a dotted-quad or a single integer N indicating
         ## a mask with N leading ones followed by trailing zeroes.
-        slash = net.index('/')
-        addr = parse_address(net[:slash])
-        if net[slash + 1:].isdigit():
-          n = int(net[slash + 1:], 10)
-          mask = (1 << 32) - (1 << 32 - n)
-        else:
-          mask = parse_address(net[slash + 1:])
-        pats.append((tag, peer, addr & mask, mask))
+        addr, mask = parse_net(net)
+        pats.append((tag, peer, addr, mask))
 
       ## Annoyingly, RawConfigParser doesn't preserve the order of options.
       ## In order to make things vaguely sane, we topologically sort the