1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00

nlmanager: ipnetwork: don't set prefixlen flag if prefix has default value

nlmanager: ipnetwork: fix 'IPv4Address' object has no attribute 'split' exception

nlpacket: use IP[v4|6]Address object when network mask is not provided or needed

nlpacket: AttributeIPAddress: fix decode handler for Routes

    During the python2 to 3 migration there was some refactoring
    Seems like some code specific to Route-decoding was removed
    This patch is fixing the issue by re-adding this code and
    tweaking it a little bit (to make it nice and clean :))

Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
This commit is contained in:
Julien Fortin
2020-04-14 18:19:10 +02:00
parent dc74cedae4
commit bc2cf49ade
2 changed files with 50 additions and 28 deletions

View File

@@ -27,16 +27,25 @@ class IPNetwork:
__INIT_WITH_PREFIXLEN = 0b01
def __init__(self, ip, prefixlen=None, scope=0):
ip_family_handler = {
0: ipaddress.ip_address,
4: ipaddress.IPv4Address,
6: ipaddress.IPv6Address
}
def __init__(self, ip, prefixlen=None, scope=0, family=0):
if isinstance(ip, IPNetwork):
prefixlen = ip.prefixlen
scope = ip.scope
family = ip.version
ip = ip.ip
self.__scope = scope
self.__flags = 0
if isinstance(ip, int):
self._ip = ipaddress.ip_address(ip)
ip = str(self._ip)
elif isinstance(ip, IPNetwork):
self._ip = ip._ip
self.__prefixlen = ip.prefixlen
self._ip = self.ip_family_handler[family](ip)
else:
if not prefixlen:
try:
@@ -53,11 +62,12 @@ class IPNetwork:
self.__prefixlen = int(prefixlen)
except ValueError:
if isinstance(prefixlen, str) and "." in prefixlen:
self.__prefixlen = ipaddress.ip_network("{}/{}".format(ip, prefixlen), strict=False).prefixlen
self.__prefixlen = ipaddress.ip_network("{}/{}".format(self.ip, prefixlen), strict=False).prefixlen
else:
raise
self.__flags |= self.__INIT_WITH_PREFIXLEN
if (self.ip.version == 4 and self.prefixlen != 32) or (self.ip.version == 6 and self.prefixlen != 128):
self.__flags |= self.__INIT_WITH_PREFIXLEN
def __hash__(self):
return int(self._ip) ^ self.__prefixlen ^ self.version
@@ -105,7 +115,7 @@ class IPNetwork:
class IPv4Network(IPNetwork):
def __init__(self, *args, **kwargs):
super(IPv4Network, self).__init__(*args, **kwargs)
super(IPv4Network, self).__init__(family=4, *args, **kwargs)
if self.version != 4:
self._ip = ipaddress.IPv4Address(self._ip)
@@ -113,7 +123,7 @@ class IPv4Network(IPNetwork):
class IPv6Network(IPNetwork):
def __init__(self, *args, **kwargs):
super(IPv6Network, self).__init__(*args, **kwargs)
super(IPv6Network, self).__init__(family=6, *args, **kwargs)
if self.version != 6:
self._ip = ipaddress.IPv6Address(self._ip)
@@ -151,3 +161,11 @@ class IPv4Address(IPv4Network):
def __repr__(self):
return str(self._ip)
class IPv6Address(IPv6Network):
def __init__(self, *args, **kwargs):
super(IPv6Address, self).__init__(*args, **kwargs)
self.ignore_prefixlen()
def __repr__(self):
return str(self._ip)

View File

@@ -1053,12 +1053,12 @@ class Attribute(object):
@staticmethod
def decode_ipv4_address_attribute(data, _=None):
return ipnetwork.IPNetwork(unpack(">L", data[4:8])[0])
return ipnetwork.IPv4Address(unpack(">L", data[4:8])[0])
@staticmethod
def decode_ipv6_address_attribute(data, _=None):
(data1, data2) = unpack(">QQ", data[4:20])
return ipnetwork.IPNetwork(data1 << 64 | data2)
return ipnetwork.IPv6Address(data1 << 64 | data2)
@staticmethod
def decode_bond_ad_info_attribute(data, info_data_end):
@@ -1391,11 +1391,11 @@ class AttributeIPAddress(Attribute):
prefixlen = parent_msg.dst_len
if self.family in (AF_INET, AF_BRIDGE):
self.value = ipnetwork.IPNetwork(unpack(self.PACK, self.data[4:])[0], prefixlen, scope)
self.value = ipnetwork.IPv4Network(unpack(self.PACK, self.data[4:])[0], prefixlen, scope)
elif self.family == AF_INET6:
(data1, data2) = unpack(self.PACK, self.data[4:])
self.value = ipnetwork.IPNetwork(data1 << 64 | data2, prefixlen, scope)
self.value = ipnetwork.IPv6Network(data1 << 64 | data2, prefixlen, scope)
else:
self.log.debug("AttributeIPAddress: decode: unsupported address family ({})".format(self.family))
@@ -1437,6 +1437,12 @@ class AttributeIPAddress(Attribute):
return line_number
class AttributeIPAddressNoMask(AttributeIPAddress):
def decode(self, *args, **kwargs):
super(AttributeIPAddressNoMask, self).decode(*args, **kwargs)
self.value = self.value.ip
class AttributeMACAddress(Attribute):
def __init__(self, atype, string, family, logger):
@@ -1453,7 +1459,7 @@ class AttributeMACAddress(Attribute):
try:
# GRE interface uses a 4-byte IP address for this attribute
if self.length == 8:
self.value = ipnetwork.IPNetwork(unpack('>L', self.data[4:])[0])
self.value = ipnetwork.IPv4Address(unpack('>L', self.data[4:])[0])
# MAC Address
elif self.length == 10:
@@ -1462,7 +1468,7 @@ class AttributeMACAddress(Attribute):
self.value = mac_int_to_str(self.raw)
# GREv6 interface uses a 16-byte IP address for this attribute
elif self.length == 20:
self.value = ipnetwork.IPNetwork(unpack('>L', self.data[16:])[0])
self.value = ipnetwork.IPv6Address(unpack('>L', self.data[16:])[0])
else:
self.log.info("Length of MACAddress attribute not supported: %d" % self.length)
@@ -1959,14 +1965,14 @@ struct rtnexthop {
if self.family == AF_INET:
if len(data) < self.IPV4_LEN:
break
nexthop = ipnetwork.IPNetwork(unpack('>L', data[:self.IPV4_LEN])[0])
nexthop = ipnetwork.IPv4Address(unpack('>L', data[:self.IPV4_LEN])[0])
self.value.append((nexthop, rtnh_ifindex, rtnh_flags, rtnh_hops))
elif self.family == AF_INET6:
if len(data) < self.IPV6_LEN:
break
(data1, data2) = unpack('>QQ', data[:self.IPV6_LEN])
nexthop = ipnetwork.IPNetwork(data1 << 64 | data2)
nexthop = ipnetwork.IPv6Address(data1 << 64 | data2)
self.value.append((nexthop, rtnh_ifindex, rtnh_flags, rtnh_hops))
data = data[(rtnh_len-self.RTNH_LEN-self.HEADER_LEN):]
@@ -2845,8 +2851,7 @@ class AttributeIFLA_LINKINFO(Attribute):
sub_attr_payload[sub_attr_length_index] = sub_attr_length
# add padding
for x in range(self.pad_bytes_needed(sub_attr_length)):
sub_attr_pack_layout.append('x')
sub_attr_pack_layout[-1] = "%s%s" % (sub_attr_pack_layout[-1], "x" * self.pad_bytes_needed(sub_attr_length))
# The [1:] is to remove the leading = so that when we do the ''.join() later
# we do not end up with an = in the middle of the pack layout string. There
@@ -3088,7 +3093,6 @@ class AttributeIFLA_PROTINFO(Attribute):
#
# Until we cross that bridge though we will keep things nice and simple and
# pack everything via a single pack() call.
for (sub_attr_type, sub_attr_value) in self.value.items():
sub_attr_pack_layout = ['=', 'HH']
sub_attr_payload = [0, sub_attr_type]
@@ -4502,10 +4506,10 @@ class AttributeMDBA_MDB(Attribute):
info = [ifindex,state,flags,vid]
proto = unpack('=H',sub_attr_data[28:30])[0]
if proto == htons(ETH_P_IP):
ip_addr = ipnetwork.IPNetwork(unpack('>L', sub_attr_data[12:16])[0])
ip_addr = ipnetwork.IPv4Address(unpack('>L', sub_attr_data[12:16])[0])
else:
(data1, data2) = unpack('>QQ',sub_attr_data[12:28])
ip_addr = ipnetwork.IPNetwork(data1 << 64 | data2)
ip_addr = ipnetwork.IPv6Address(data1 << 64 | data2)
info.append(ip_addr)
@@ -4540,10 +4544,10 @@ class AttributeMDBA_MDB(Attribute):
info = list(info)
proto = unpack('=H',sub_attr_data[28:30])[0]
if proto == 8:
ip_addr = ipnetwork.IPNetwork(unpack('>L', sub_attr_data[12:16])[0])
ip_addr = ipnetwork.IPv4Address(unpack('>L', sub_attr_data[12:16])[0])
else:
(data1, data2) = unpack('>QQ',sub_attr_data[12:28])
ip_addr = ipnetwork.IPNetwork(data1 << 64 | data2)
ip_addr = ipnetwork.IPv6Address(data1 << 64 | data2)
info.append(ip_addr)
self.value[MDB.MDBA_MDB_ENTRY][MDB.MDBA_MDB_ENTRY_INFO] = info
@@ -4677,7 +4681,7 @@ class AttributeMDBA_SET_ENTRY(Attribute):
elif proto == htons(ETH_P_IPV6):
self.PACK = '=IBBHQQHxx'
(ifindex, flags, state,vid, data1,data2, proto) = unpack(self.PACK, self.data[4:])
ip = ipnetwork.IPNetwork(data1 << 64 | data2)
ip = ipnetwork.IPv6Address(data1 << 64 | data2)
else:
raise Exception("%d Invalid Proto" % proto)
self.LEN = calcsize(self.PACK)
@@ -4951,7 +4955,7 @@ class Neighbor(NetlinkPacket):
attribute_to_class = {
NDA_UNSPEC : ('NDA_UNSPEC', AttributeGeneric),
NDA_DST : ('NDA_DST', AttributeIPAddress),
NDA_DST : ('NDA_DST', AttributeIPAddressNoMask),
NDA_LLADDR : ('NDA_LLADDR', AttributeMACAddress),
NDA_CACHEINFO : ('NDA_CACHEINFO', AttributeFourByteList),
NDA_PROBES : ('NDA_PROBES', AttributeFourByteValue),
@@ -5300,7 +5304,7 @@ class Route(NetlinkPacket):
dst = self.get_attribute_value(self.RTA_DST)
if dst:
return "%s/%d" % (dst, self.src_len)
return "%s" % dst
else:
if self.family == AF_INET:
return "0.0.0.0/0"