|
|
ac7d03 |
From 8d88b50c3f79e054a039d123fdaf6aa3a5339135 Mon Sep 17 00:00:00 2001
|
|
|
ac7d03 |
From: Martin Basti <mbasti@redhat.com>
|
|
|
ac7d03 |
Date: Wed, 14 Jun 2017 14:47:23 +0200
|
|
|
ac7d03 |
Subject: [PATCH] refactor CheckedIPAddress class
|
|
|
ac7d03 |
|
|
|
ac7d03 |
Make methods without side effects (setting mask)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
https://pagure.io/freeipa/issue/4317
|
|
|
ac7d03 |
|
|
|
ac7d03 |
Reviewed-By: David Kupka <dkupka@redhat.com>
|
|
|
ac7d03 |
---
|
|
|
ac7d03 |
ipapython/ipautil.py | 29 ++++++++++++++++++++++-------
|
|
|
ac7d03 |
1 file changed, 22 insertions(+), 7 deletions(-)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
|
|
|
ac7d03 |
index 647ee833ae33f246de6d6b13703fac6e20eef7bc..2c020e3ecbf4d8b969511a6dd9b36ee955ba1f15 100644
|
|
|
ac7d03 |
--- a/ipapython/ipautil.py
|
|
|
ac7d03 |
+++ b/ipapython/ipautil.py
|
|
|
ac7d03 |
@@ -62,6 +62,12 @@ PROTOCOL_NAMES = {
|
|
|
ac7d03 |
socket.SOCK_DGRAM: 'udp'
|
|
|
ac7d03 |
}
|
|
|
ac7d03 |
|
|
|
ac7d03 |
+InterfaceDetails = collections.namedtuple(
|
|
|
ac7d03 |
+ 'InterfaceDetails', [
|
|
|
ac7d03 |
+ 'name', # interface name
|
|
|
ac7d03 |
+ 'ifnet' # network details of interface
|
|
|
ac7d03 |
+ ])
|
|
|
ac7d03 |
+
|
|
|
ac7d03 |
|
|
|
ac7d03 |
class UnsafeIPAddress(netaddr.IPAddress):
|
|
|
ac7d03 |
"""Any valid IP address with or without netmask."""
|
|
|
ac7d03 |
@@ -161,9 +167,12 @@ class CheckedIPAddress(UnsafeIPAddress):
|
|
|
ac7d03 |
raise ValueError("cannot use multicast IP address {}".format(addr))
|
|
|
ac7d03 |
|
|
|
ac7d03 |
if match_local:
|
|
|
ac7d03 |
- if not self.get_matching_interface():
|
|
|
ac7d03 |
+ intf_details = self.get_matching_interface()
|
|
|
ac7d03 |
+ if not intf_details:
|
|
|
ac7d03 |
raise ValueError('no network interface matches the IP address '
|
|
|
ac7d03 |
'and netmask {}'.format(addr))
|
|
|
ac7d03 |
+ else:
|
|
|
ac7d03 |
+ self.set_ip_net(intf_details.ifnet)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
if self._net is None:
|
|
|
ac7d03 |
if self.version == 4:
|
|
|
ac7d03 |
@@ -193,7 +202,8 @@ class CheckedIPAddress(UnsafeIPAddress):
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def get_matching_interface(self):
|
|
|
ac7d03 |
"""Find matching local interface for address
|
|
|
ac7d03 |
- :return: Interface name or None if no interface has this address
|
|
|
ac7d03 |
+ :return: InterfaceDetails named tuple or None if no interface has
|
|
|
ac7d03 |
+ this address
|
|
|
ac7d03 |
"""
|
|
|
ac7d03 |
if self.version == 4:
|
|
|
ac7d03 |
family = netifaces.AF_INET
|
|
|
ac7d03 |
@@ -204,7 +214,6 @@ class CheckedIPAddress(UnsafeIPAddress):
|
|
|
ac7d03 |
"Unsupported address family ({})".format(self.version)
|
|
|
ac7d03 |
)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- iface = None
|
|
|
ac7d03 |
for interface in netifaces.interfaces():
|
|
|
ac7d03 |
for ifdata in netifaces.ifaddresses(interface).get(family, []):
|
|
|
ac7d03 |
|
|
|
ac7d03 |
@@ -218,11 +227,17 @@ class CheckedIPAddress(UnsafeIPAddress):
|
|
|
ac7d03 |
))
|
|
|
ac7d03 |
|
|
|
ac7d03 |
if ifnet.ip == self:
|
|
|
ac7d03 |
- iface = interface
|
|
|
ac7d03 |
- self._net = ifnet
|
|
|
ac7d03 |
- break
|
|
|
ac7d03 |
+ return InterfaceDetails(interface, ifnet)
|
|
|
ac7d03 |
|
|
|
ac7d03 |
- return iface
|
|
|
ac7d03 |
+ def set_ip_net(self, ifnet):
|
|
|
ac7d03 |
+ """Set IP Network details for this address. IPNetwork is valid only
|
|
|
ac7d03 |
+ locally, so this should be set only for local IP addresses
|
|
|
ac7d03 |
+
|
|
|
ac7d03 |
+ :param ifnet: netaddr.IPNetwork object with information about IP
|
|
|
ac7d03 |
+ network where particula address belongs locally
|
|
|
ac7d03 |
+ """
|
|
|
ac7d03 |
+ assert isinstance(ifnet, netaddr.IPNetwork)
|
|
|
ac7d03 |
+ self._net = ifnet
|
|
|
ac7d03 |
|
|
|
ac7d03 |
|
|
|
ac7d03 |
def valid_ip(addr):
|
|
|
ac7d03 |
--
|
|
|
ac7d03 |
2.9.4
|
|
|
ac7d03 |
|