]> www.infradead.org Git - users/dhowells/kafs-utils.git/commitdiff
Use the Python ipaddress module to represent IP addresses
authorDavid Howells <dhowells@redhat.com>
Tue, 13 May 2014 13:27:58 +0000 (14:27 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 13 May 2014 16:36:35 +0000 (17:36 +0100)
Use the Python ipaddress module to represent IP addresses internally rather
than trying to do it myself.

Signed-off-by: David Howells <dhowells@redhat.com>
suite/exception.py
suite/lib/addrcache.py
suite/lib/cell.py
suite/lib/server.py
suite/lib/vlserver.py

index 7d90a8c8d127f2cd8f6d1ea7e268e64e37a49184..815e94c2eefb1ea866a14e71be100c6e6cb4a50d 100644 (file)
@@ -6,6 +6,10 @@ class AFSArgumentError(AFSException):
     """An argument parsing error was encountered"""
     pass
 
+class AFSNetAddressError(AFSException):
+    """A network address parsing error was encountered"""
+    pass
+
 class AFSHelpFlag(AFSException):
     """The -help flag was specified to a command."""
     pass
index 8829263236caabaa68e9513301ca321713f41303..05e32044c0f9acae3708c990b517e28276cfee49 100644 (file)
@@ -22,34 +22,32 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
 from afs import exception
-from socket import gethostbyname_ex, gethostbyaddr, gaierror, herror, inet_pton, inet_ntoa, AF_INET, AF_INET6
+from socket import gethostbyname_ex, gethostbyaddr, gaierror, herror
 import sys
+import ipaddress
 
 cache_n2a = dict()
 cache_a2n = dict()
 
-class NetAddressError(exception.AFSException):
-    """Error raised by L{address cache}."""
-
 def add(name, addr):
     global cache_n2a, cache_a2n
     name = name.lower().rstrip(".")
     if name not in cache_n2a:
         cache_n2a[name] = []
-    if addr not in cache_n2a[name]:
+    if str(addr) not in cache_n2a[name]:
         cache_n2a[name].append(addr)
-    cache_a2n[addr] = name
+    cache_a2n[str(addr)] = name
 
 def add_ghb(name, addr, result):
     hostname, aliaslist, ipaddrlist = result
-    if addr and addr not in ipaddrlist:
-        print("Inconsistent lookup of '", addr, "'", file=sys.stderr)
+    if addr and str(addr) not in ipaddrlist:
+        print("Inconsistent lookup of '", str(addr), "'", file=sys.stderr)
     for i in ipaddrlist:
         if name:
-            add(name, i)
-        add(hostname, i)
+            add(name, ipaddress.IPv4Address(i))
+        add(hostname, ipaddress.IPv4Address(i))
         for j in aliaslist:
-            add(j, i)
+            add(j, ipaddress.IPv4Address(i))
 
 ###############################################################################
 #
@@ -59,18 +57,12 @@ def add_ghb(name, addr, result):
 def name2addrs(name):
     global cache_n2a
 
-    # Try parsing as a numeric IPv4 address
     try:
-        addr = inet_pton(AF_INET, name)
-        return name
-    except OSError:
-        pass
-
-    # Try parsing as a numeric IPv6 address
-    try:
-        addr = inet_pton(AF_INET6, name)
-        raise NetAddressError("IPv6 is not currently supported")
-    except OSError:
+        addr = ipaddress.ip_address(name)
+        if addr.version == 6:
+            raise exception.AFSNetAddressError("IPv6 is not currently supported")
+        return str(addr)
+    except ValueError:
         pass
 
     name = name.lower().rstrip(".")
@@ -80,70 +72,45 @@ def name2addrs(name):
     try:
         result = gethostbyname_ex(name)
     except gaierror as e:
-        raise NetAddressError("Couldn't resolve '" + name + "'")
+        raise exception.AFSNetAddressError("Couldn't resolve '" + name + "'")
     add_ghb(name, None, result)
 
     return cache_n2a[name]
 
 ###############################################################################
 #
-# Convert a string address to an address in integer form
+# Convert a string address to an address
 #
 ###############################################################################
-def addr2addr_int(name):
-    # Try parsing as a numeric IPv4 address
-    try:
-        addr = inet_pton(AF_INET, name)
-        inaddr  = addr[0] << 24
-        inaddr |= addr[1] << 16
-        inaddr |= addr[2] <<  8
-        inaddr |= addr[3] <<  0
-        return inaddr
-    except OSError:
-        pass
-
-    # Try parsing as a numeric IPv6 address
+def addr2addr(name):
     try:
-        addr = inet_pton(AF_INET6, name)
-        raise NetAddressError("IPv6 is not currently supported")
-    except OSError:
-        pass
-    raise NetAddressError("Can't translate '" +  name + "' to integer")
+        addr = ipaddress.ip_address(name)
+        if addr.version == 6:
+            raise exception.AFSNetAddressError("IPv6 is not currently supported")
+        return addr
+    except ValueError:
+        raise exception.AFSNetAddressError("Can't translate '" +  name + "' to integer")
 
 ###############################################################################
 #
-# Convert a name or string address to an address in integer form
+# Convert a name or string address to an address
 #
 ###############################################################################
-def name2addr_int(name):
+def name2addr(name):
     global cache_n2a
 
     # Try parsing as a numeric IPv4 address
     try:
-        addr = inet_pton(AF_INET, name)
-        inaddr  = addr[0] << 24
-        inaddr |= addr[1] << 16
-        inaddr |= addr[2] <<  8
-        inaddr |= addr[3] <<  0
-        return inaddr
-    except OSError:
-        pass
-
-    # Try parsing as a numeric IPv6 address
-    try:
-        addr = inet_pton(AF_INET6, name)
-        raise NetAddressError("IPv6 is not currently supported")
-    except OSError:
+        addr = ipaddress.ip_address(name)
+        if addr.version == 6:
+            raise exception.AFSNetAddressError("IPv6 is not currently supported")
+        return addr
+    except ValueError:
         pass
 
     if name not in cache_n2a:
         return None
-    addr = inet_pton(AF_INET, cache_n2a[name][0])
-    inaddr  = addr[0] << 24
-    inaddr |= addr[1] << 16
-    inaddr |= addr[2] <<  8
-    inaddr |= addr[3] <<  0
-    return inaddr
+    return cache_n2a[name][0]
 
 ###############################################################################
 #
@@ -153,15 +120,21 @@ def name2addr_int(name):
 ###############################################################################
 def addrs2name(addrs):
     global cache_a2n
+    cooked_addrs = []
     for addr in addrs:
-        if addr in cache_a2n:
-            return cache_a2n[addr]
+        if str(type(addr)) != "<class 'IPv4Address'>":
+            addr = ipaddress.ip_address(addr)
+            cooked_addrs.append(addr)
+        else:
+            cooked_addrs.append(addr)
+        if str(addr) in cache_a2n:
+            return cache_a2n[str(addr)]
 
     for addr in addrs:
         try:
-            result = gethostbyaddr(addr)
+            result = gethostbyaddr(str(addr))
             add_ghb(None, addr, result)
-            return cache_a2n[addr]
+            return cache_a2n[str(addr)]
         except herror:
             pass
 
@@ -170,19 +143,6 @@ def addrs2name(addrs):
 def addr2name(addr):
     return addrs2name([ addr ])
 
-###############################################################################
-#
-# Convert an integer address to a string address.
-#
-###############################################################################
-def int2addr(i):
-    inaddr = bytearray(4)
-    inaddr[0] = (i >> 24) & 0xff
-    inaddr[1] = (i >> 16) & 0xff
-    inaddr[2] = (i >>  8) & 0xff
-    inaddr[3] = (i >>  0) & 0xff
-    return inet_ntoa(bytes(inaddr))
-
 ###############################################################################
 #
 # Resolve an integer or string address to a string address or a name,
@@ -190,11 +150,23 @@ def int2addr(i):
 #
 ###############################################################################
 def resolve(params, addr):
-    if str(type(addr)) == "<class 'int'>":
-        addr = int2addr(addr)
+    if str(type(addr)) != "<class 'IPv4Address'>" and str(type(addr)) != "<class 'IPv6Address'>":
+        addr = ipaddress.ip_address(addr)
     if "noresolve" in params:
-        return addr
+        return str(addr)
     name = addr2name(addr)
     if name == None:
-        return addr
+        return str(addr)
     return name
+
+###############################################################################
+#
+# Convert an integer or a string address to an address.
+#
+###############################################################################
+def addr2addr(addr):
+    if str(type(addr)) != "<class 'IPv4Address'>" and str(type(addr)) != "<class 'IPv6Address'>":
+        addr = ipaddress.ip_address(addr)
+    if addr.version == 6:
+        raise exception.AFSNetAddressError("IPv6 is not currently supported")
+    return addr
index fda13c1cd7b1e19c45ba0a45a47190a2f3ba3197..9fdfa1eef7187b9a9d0e63d93bc115de52d0efb8 100644 (file)
@@ -143,10 +143,10 @@ class cell:
 
         key, security = self.determine_security(params)
 
-        for vlserver in self.query_vl_addrs():
-            verbose("Trying ", vlserver, "\n")
+        for vladdr in self.query_vl_addrs():
+            verbose("Trying vlserver ", vladdr, "\n")
 
-            z_conn = kafs.rx_new_connection(vlserver, kafs.VL_PORT, kafs.VL_SERVICE,
+            z_conn = kafs.rx_new_connection(str(vladdr), kafs.VL_PORT, kafs.VL_SERVICE,
                                             key, security)
             try:
                 ret = kafs.VL_Probe(z_conn)
@@ -164,8 +164,8 @@ class cell:
     def open_volume_server(self, server, params=None):
         key, security = self.determine_security(params)
 
-        verbose("Trying ", server.addr(), "\n")
-        vol_conn = kafs.rx_new_connection(server.addr(),
+        verbose("Trying volserver ", server, "\n")
+        vol_conn = kafs.rx_new_connection(str(server.addr()),
                                           kafs.VOLSERVICE_PORT,
                                           kafs.VOLSERVICE_ID,
                                           key, security)
@@ -175,8 +175,8 @@ class cell:
     def open_bos_server(self, server, params=None):
         key, security = self.determine_security(params)
 
-        verbose("Trying ", server.addr(), "\n")
-        bos_conn = kafs.rx_new_connection(server.addr(),
+        verbose("Trying bosserver ", server, "\n")
+        bos_conn = kafs.rx_new_connection(str(server.addr()),
                                           kafs.BOSSERVICE_PORT,
                                           kafs.BOSSERVICE_ID,
                                           key, security)
index aed6a66dd29861062a36bfd53dce38a817b56d80..4b43deb5e2f3ce4f489845e7fc57bc37b88ce420 100644 (file)
@@ -24,32 +24,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 from afs import exception
 import afs.lib.addrcache as addrcache
 from afs.lib.output import *
-from socket import inet_pton, inet_ntoa, AF_INET, AF_INET6;
 
 class ServerError(exception.AFSException):
     """Error raised by L{volserver} objects."""
 
 class server:
     """Represents the name and addresses of a server on the network."""
-    def __init__(self, name):
+    def __init__(self, name, addr=None):
         self.__name = None
         self.__addrs4 = None
         self.__addrs6 = None
-        self.__inaddr = None
 
-        if str(type(name)) == "<class 'int'>":
-            self.__addrs4 = [ addrcache.int2addr(name) ]
-        else:
-            # Try parsing as a numeric IPv4 address
-            try:
-                self.__addrs4 = [ inet_pton(AF_INET, name) ]
-            except OSError:
-                # Try parsing as a numeric IPv6 address
-                try:
-                    self.__addrs6 = [ inet_pton(AF_INET6, name) ]
-                    raise NetAddressError("IPv6 is not currently supported")
-                except OSError:
-                    self.__name = name
+        try:
+            self.__addrs4 = [ addrcache.addr2addr(name) ]
+        except ValueError:
+            self.__name = name
+
+        if addr != None:
+            self.__addrs4 = [ addrcache.addr2addr(addr) ]
 
     def __repr__(self):
         if self.__name != None:
index 6e0b57b5e51995b085e4f0940190d31a4e021f40..d632a2f9aea14cb591aec17ab0609063bfc6e560 100644 (file)
@@ -27,9 +27,9 @@ from afs.lib.server import server
 
 class vlserver(server):
     """Represents an AFS Volume Location server.  We hold the server address here."""
-    def __init__(self, name):
+    def __init__(self, name, addr=None):
         verbose("New VolServer ", name, "\n")
-        server.__init__(self, name)
+        server.__init__(self, name, addr)
 
     def __repr__(self):
         return "<" + "AFSVL:" + server.__str_(self) + ">"