svc/conntrack.in: Split out a base class from `InetAddress'.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 29 Sep 2017 08:23:43 +0000 (09:23 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Thu, 28 Jun 2018 23:29:24 +0000 (00:29 +0100)
Now adding more families should be pretty easy.

svc/conntrack.in

index cc753d4..bfdd7b8 100644 (file)
@@ -42,6 +42,7 @@ for i in ['mainloop', 'mainloop.glib']:
 try: from gi.repository import GLib as G
 except ImportError: import gobject as G
 from struct import pack, unpack
+from cStringIO import StringIO
 
 SM = T.svcmgr
 ##__import__('rmcr').__debug = True
@@ -54,47 +55,89 @@ class struct (object):
   def __init__(me, **kw):
     me.__dict__.update(kw)
 
+def loadb(s):
+  n = 0
+  for ch in s: n = 256*n + ord(ch)
+  return n
+
+def storeb(n, wd = None):
+  if wd is None: wd = n.bit_length()
+  s = StringIO()
+  for i in xrange((wd - 1)&-8, -8, -8): s.write(chr((n >> i)&0xff))
+  return s.getvalue()
+
 ###--------------------------------------------------------------------------
 ### Address manipulation.
+###
+### I think this is the most demanding application, in terms of address
+### hacking, in the entire TrIPE suite.  At least we don't have to do it in
+### C.
 
-class InetAddress (object):
-  AF = S.AF_INET
-  AFNAME = 'IPv4'
+class BaseAddress (object):
   def __init__(me, addrstr, maskstr = None):
-    me.addr = me._addrstr_to_int(addrstr)
+    me._setaddr(addrstr)
     if maskstr is None:
       me.mask = -1
     elif maskstr.isdigit():
-      me.mask = (1 << 32) - (1 << 32 - int(maskstr))
+      me.mask = (1 << me.NBITS) - (1 << me.NBITS - int(maskstr))
     else:
-      me.mask = me._addrstr_to_int(maskstr)
+      me._setmask(maskstr)
     if me.addr&~me.mask:
       raise ValueError('network contains bits set beyond mask')
   def _addrstr_to_int(me, addrstr):
-    return unpack('>L', S.inet_aton(addrstr))[0]
+    try: return loadb(S.inet_pton(me.AF, addrstr))
+    except S.error: raise ValueError('bad address syntax')
   def _int_to_addrstr(me, n):
-    return S.inet_ntoa(pack('>L', n))
+    return S.inet_ntop(me.AF, storeb(me.addr, me.NBITS))
+  def _setmask(me, maskstr):
+    raise ValueError('only prefix masked supported')
+  def _maskstr(me):
+    raise ValueError('only prefix masked supported')
   def sockaddr(me, port = 0):
     if me.mask != -1: raise ValueError('not a simple address')
-    return me._int_to_addrstr(me.addr), port
+    return me._sockaddr(port)
   def __str__(me):
-    addrstr = me._int_to_addrstr(me.addr)
+    addrstr = me._addrstr()
     if me.mask == -1:
       return addrstr
     else:
-      inv = me.mask ^ ((1 << 32) - 1)
+      inv = me.mask ^ ((1 << me.NBITS) - 1)
       if (inv&(inv + 1)) == 0:
-        return '%s/%d' % (addrstr, 32 - inv.bit_length())
+        return '%s/%d' % (addrstr, me.NBITS - inv.bit_length())
       else:
-        return '%s/%s' % (addrstr, me._int_to_addrstr(me.mask))
+        return '%s/%s' % (addrstr, me._maskstr())
   def withinp(me, net):
+    if type(net) != type(me): return False
     if (me.mask&net.mask) != net.mask: return False
     if (me.addr ^ net.addr)&net.mask: return False
-    return True
+    return me._withinp(net)
   def eq(me, other):
+    if type(me) != type(other): return False
     if me.mask != other.mask: return False
     if me.addr != other.addr: return False
+    return me._eq(other)
+  def _withinp(me, net):
     return True
+  def _eq(me, other):
+    return True
+
+class InetAddress (BaseAddress):
+  AF = S.AF_INET
+  AFNAME = 'IPv4'
+  NBITS = 32
+  def _addrstr_to_int(me, addrstr):
+    try: return loadb(S.inet_aton(addrstr))
+    except S.error: raise ValueError('bad address syntax')
+  def _setaddr(me, addrstr):
+    me.addr = me._addrstr_to_int(addrstr)
+  def _setmask(me, maskstr):
+    me.mask = me._addrstr_to_int(maskstr)
+  def _addrstr(me):
+    return me._int_to_addrstr(me.addr)
+  def _maskstr(me):
+    return me._int_to_addrstr(me.mask)
+  def _sockaddr(me, port = 0):
+    return (me._addrstr(), port)
   @classmethod
   def from_sockaddr(cls, sa):
     addr, port = (lambda a, p: (a, p))(*sa)