diff options
author | Rob Austein <sra@hactrn.net> | 2012-10-12 21:42:51 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2012-10-12 21:42:51 +0000 |
commit | f91067126a35c2df1d5fff8d0061262e568114c1 (patch) | |
tree | 7998f195ca3236701fead828549fed23dc180024 | |
parent | 0de5ca9137dfafdf85e2d268016b3e6b6908fd02 (diff) |
Replace rpki.ipaddrs with rpki.POW.IPAddress.
svn path=/branches/tk274/; revision=4773
-rw-r--r-- | rpkid/ext/POW.c | 97 | ||||
-rw-r--r-- | rpkid/rpki/gui/app/forms.py | 10 | ||||
-rw-r--r-- | rpkid/rpki/gui/cacheview/models.py | 1 | ||||
-rw-r--r-- | rpkid/rpki/gui/cacheview/views.py | 8 | ||||
-rw-r--r-- | rpkid/rpki/gui/models.py | 15 | ||||
-rw-r--r-- | rpkid/rpki/irdb/models.py | 7 | ||||
-rw-r--r-- | rpkid/rpki/resource_set.py | 108 |
7 files changed, 158 insertions, 88 deletions
diff --git a/rpkid/ext/POW.c b/rpkid/ext/POW.c index 5ff31812..0411014a 100644 --- a/rpkid/ext/POW.c +++ b/rpkid/ext/POW.c @@ -942,6 +942,8 @@ ipaddress_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) int version = 0; const char *s = NULL; + ENTERING(ipaddress_object_new); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &init, &version) || (self = (ipaddress_object *) type->tp_alloc(type, 0)) == NULL) goto error; @@ -995,6 +997,8 @@ ipaddress_object_str(ipaddress_object *self) { char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1]; + ENTERING(ipaddress_object_str); + if (!inet_ntop(self->af, self->address, addrstr, sizeof(addrstr))) lose("Couldn't convert IP address"); @@ -1009,6 +1013,8 @@ ipaddress_object_repr(ipaddress_object *self) { char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1]; + ENTERING(ipaddress_object_repr); + if (!inet_ntop(self->af, self->address, addrstr, sizeof(addrstr))) lose("Couldn't convert IP address"); @@ -1026,6 +1032,8 @@ ipaddress_object_compare(PyObject *arg1, PyObject *arg2) PyObject *obj2 = PyNumber_Long(arg2); int cmp = -1; + ENTERING(ipaddress_object_compare); + if (obj1 != NULL && obj2 != NULL) cmp = PyObject_Compare(obj1, obj2); @@ -1041,6 +1049,8 @@ ipaddress_object_richcompare(PyObject *arg1, PyObject *arg2, int op) PyObject *obj2 = PyNumber_Long(arg2); PyObject *result = NULL; + ENTERING(ipaddress_object_richcompare); + if (obj1 != NULL && obj2 != NULL) result = PyObject_RichCompare(obj1, obj2, op); @@ -1055,19 +1065,77 @@ ipaddress_object_hash(ipaddress_object *self) unsigned long h = 0; int i; + ENTERING(ipaddress_object_hash); + for (i = 0; i < self->length; i++) h ^= self->address[i] << ((i & 3) << 3); return (long) h == -1 ? 0 : (long) h; } +static char ipaddress_object_from_bytes__doc__[] = + "Construct an IPAddress object from a sequence of bytes.\n" + "\n" + "Argument must be a Python string of exactly 4 or 16 bytes.\n" + ; + +static PyObject * +ipaddress_object_from_bytes(PyTypeObject *type, PyObject *args) +{ + ipaddress_object *result = NULL; + char *bytes = NULL; + size_t len; + + ENTERING(ipaddress_object_from_bytes); + + if (!PyArg_ParseTuple(args, "s#", &bytes, &len)) + goto error; + + if (len != 4 && len != 16) + lose("Argument must be a string of exactly 4 or 16 bytes"); + + if ((result = (ipaddress_object *) type->tp_alloc(type, 0)) == NULL) + goto error; + + memcpy(result->address, bytes, len); + result->length = len; + + switch (len) { + case 4: result->version = 4; result->af = AF_INET; break; + case 16: result->version = 6; result->af = AF_INET6; break; + } + + error: + return (PyObject *) result; +} + +static char ipaddress_object_to_bytes__doc__[] = + "Returns a Python string of exactly 4 or 16 bytes representing\n" + "the binary value of this IPAddress.\n" + ; + +static PyObject * +ipaddress_object_to_bytes(ipaddress_object *self) +{ + ENTERING(ipaddress_object_from_bytes); + return PyString_FromStringAndSize(self->address, self->length); +} + static PyObject * ipaddress_object_get_bits(ipaddress_object *self, void *closure) { + ENTERING(ipaddress_object_get_bits); return PyInt_FromLong(self->length * 8); } static PyObject * +ipaddress_object_get_version(ipaddress_object *self, void *closure) +{ + ENTERING(ipaddress_object_get_version); + return PyInt_FromLong(self->version); +} + +static PyObject * ipaddress_object_number_binary_helper(binaryfunc function, PyObject *arg1, PyObject *arg2) { ipaddress_object *addr = NULL; @@ -1127,6 +1195,8 @@ ipaddress_object_number_long(PyObject *arg) { ipaddress_object *addr = (ipaddress_object *) arg; + ENTERING(ipaddress_object_number_long); + if (!POW_IPAddress_Check(arg)) return Py_NotImplemented; @@ -1136,48 +1206,56 @@ ipaddress_object_number_long(PyObject *arg) static PyObject * ipaddress_object_number_int(PyObject *arg) { + ENTERING(ipaddress_object_number_int); return ipaddress_object_number_long(arg); } static PyObject * ipaddress_object_number_add(PyObject *arg1, PyObject *arg2) { + ENTERING(ipaddress_object_number_add); return ipaddress_object_number_binary_helper(PyNumber_Add, arg1, arg2); } static PyObject * ipaddress_object_number_subtract(PyObject *arg1, PyObject *arg2) { + ENTERING(ipaddress_object_number_subtract); return ipaddress_object_number_binary_helper(PyNumber_Subtract, arg1, arg2); } static PyObject * ipaddress_object_number_lshift(PyObject *arg1, PyObject *arg2) { + ENTERING(ipaddress_object_number_lshift); return ipaddress_object_number_binary_helper(PyNumber_Lshift, arg1, arg2); } static PyObject * ipaddress_object_number_rshift(PyObject *arg1, PyObject *arg2) { + ENTERING(ipaddress_object_number_rshift); return ipaddress_object_number_binary_helper(PyNumber_Rshift, arg1, arg2); } static PyObject * ipaddress_object_number_and(PyObject *arg1, PyObject *arg2) { + ENTERING(ipaddress_object_number_and); return ipaddress_object_number_binary_helper(PyNumber_And, arg1, arg2); } static PyObject * ipaddress_object_number_xor(PyObject *arg1, PyObject *arg2) { + ENTERING(ipaddress_object_number_xor); return ipaddress_object_number_binary_helper(PyNumber_Xor, arg1, arg2); } static PyObject * ipaddress_object_number_or(PyObject *arg1, PyObject *arg2) { + ENTERING(ipaddress_object_number_or); return ipaddress_object_number_binary_helper(PyNumber_Or, arg1, arg2); } @@ -1186,6 +1264,8 @@ ipaddress_object_number_nonzero(ipaddress_object *self) { int i; + ENTERING(ipaddress_object_number_nonzero); + for (i = 0; i < self->length; i++) if (self->address[i] != 0) return 1; @@ -1198,6 +1278,8 @@ ipaddress_object_number_invert(ipaddress_object *self) ipaddress_object *result = NULL; int i; + ENTERING(ipaddress_object_number_invert); + if ((result = (ipaddress_object *) self->ob_type->tp_alloc(self->ob_type, 0)) == NULL) goto error; @@ -1212,8 +1294,15 @@ ipaddress_object_number_invert(ipaddress_object *self) return (PyObject *) result; } -static PyGetSetDef ipaddress_getsetters[] = { - {"bits", (getter) ipaddress_object_get_bits}, +static struct PyMethodDef ipaddress_object_methods[] = { + Define_Method(toBytes, ipaddress_object_to_bytes, METH_NOARGS), + Define_Class_Method(fromBytes, ipaddress_object_from_bytes, METH_VARARGS), + {NULL} +}; + +static PyGetSetDef ipaddress_object_getsetters[] = { + {"bits", (getter) ipaddress_object_get_bits}, + {"version", (getter) ipaddress_object_get_version}, {NULL} }; @@ -1288,9 +1377,9 @@ static PyTypeObject POW_IPAddress_Type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + ipaddress_object_methods, /* tp_methods */ 0, /* tp_members */ - ipaddress_getsetters, /* tp_getset */ + ipaddress_object_getsetters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ diff --git a/rpkid/rpki/gui/app/forms.py b/rpkid/rpki/gui/app/forms.py index 80439b00..2166343a 100644 --- a/rpkid/rpki/gui/app/forms.py +++ b/rpkid/rpki/gui/app/forms.py @@ -23,7 +23,7 @@ from rpki.resource_set import (resource_range_as, resource_range_ipv4, from rpki.gui.app import models from rpki.exceptions import BadIPResource from rpki.gui.app.glue import str_to_resource_range -import rpki.ipaddrs +from rpki.POW import IPAddress class AddConfForm(forms.Form): @@ -190,11 +190,7 @@ class ROARequest(forms.Form): """ prefix = self.cleaned_data.get('prefix') if '/' not in prefix: - p = rpki.ipaddrs.parse(prefix) - - # rpki.ipaddrs.parse doesn't return a v?addr object, so can't - # introspect p.bits - bits = 32 if ':' not in prefix else 64 + p = IPAddress(prefix) # determine the first nonzero bit starting from the lsb and # subtract from the address size to find the closest classful @@ -203,7 +199,7 @@ class ROARequest(forms.Form): while (p != 0) and (p & 1) == 0: prefixlen = prefixlen + 1 p = p >> 1 - mask = bits - (8 * (prefixlen / 8)) + mask = p.bits - (8 * (prefixlen / 8)) prefix = prefix + '/' + str(mask) return str_to_resource_range(prefix) diff --git a/rpkid/rpki/gui/cacheview/models.py b/rpkid/rpki/gui/cacheview/models.py index 4be45b5c..f58cca33 100644 --- a/rpkid/rpki/gui/cacheview/models.py +++ b/rpkid/rpki/gui/cacheview/models.py @@ -20,7 +20,6 @@ import time from django.db import models -import rpki.ipaddrs import rpki.resource_set import rpki.gui.models diff --git a/rpkid/rpki/gui/cacheview/views.py b/rpkid/rpki/gui/cacheview/views.py index b75763fa..ffb04136 100644 --- a/rpkid/rpki/gui/cacheview/views.py +++ b/rpkid/rpki/gui/cacheview/views.py @@ -20,7 +20,7 @@ from django.shortcuts import get_object_or_404, redirect from rpki.gui.cacheview import models, forms, misc from rpki.gui.app.views import render from rpki.resource_set import resource_range_as -from rpki.ipaddrs import v4addr, v6addr +from rpki.POW import IPAddress # Create your views here. @@ -133,11 +133,7 @@ def query_view(request): prefix_list = [] for roa in roas: for pfx in roa.prefixes.all(): - if pfx.family == 4: - addr = v4addr(pfx.prefix.encode()) - elif pfx.family == 6: - addr = v6addr(pfx.prefix.encode()) - + addr = IPAddress(pfx.prefix.encode()) prefix_list.append((pfx, roa, addr)) prefix_list.sort(cmp=cmp_prefix) diff --git a/rpkid/rpki/gui/models.py b/rpkid/rpki/gui/models.py index 749f335f..3f601f7c 100644 --- a/rpkid/rpki/gui/models.py +++ b/rpkid/rpki/gui/models.py @@ -23,7 +23,7 @@ import struct from django.db import models import rpki.resource_set -import rpki.ipaddrs +import rpki.POW class IPv6AddressField(models.Field): "Field large enough to hold a 128-bit unsigned integer." @@ -34,16 +34,15 @@ class IPv6AddressField(models.Field): return 'binary(16)' def to_python(self, value): - if isinstance(value, rpki.ipaddrs.v6addr): + if isinstance(value, rpki.POW.IPAddress): return value - x = struct.unpack('!QQ', value) - return rpki.ipaddrs.v6addr((x[0] << 64) | x[1]) + return rpki.POW.IPAddress.from_bytes(value) def get_db_prep_value(self, value, connection, prepared): - return struct.pack('!QQ', (long(value) >> 64) & 0xFFFFFFFFFFFFFFFFL, long(value) & 0xFFFFFFFFFFFFFFFFL) + return value.to_bytes() class IPv4AddressField(models.Field): - "Wrapper around rpki.ipaddrs.v4addr." + "Wrapper around rpki.POW.IPAddress." __metaclass__ = models.SubfieldBase @@ -51,9 +50,9 @@ class IPv4AddressField(models.Field): return 'int UNSIGNED' def to_python(self, value): - if isinstance(value, rpki.ipaddrs.v4addr): + if isinstance(value, rpki.POW.IPAddress): return value - return rpki.ipaddrs.v4addr(value) + return rpki.POW.IPAddress(value) def get_db_prep_value(self, value, connection, prepared): return long(value) diff --git a/rpkid/rpki/irdb/models.py b/rpkid/rpki/irdb/models.py index 7727e0fe..8a41647d 100644 --- a/rpkid/rpki/irdb/models.py +++ b/rpkid/rpki/irdb/models.py @@ -26,7 +26,6 @@ import django.db.models import rpki.x509 import rpki.sundial import rpki.resource_set -import rpki.ipaddrs import socket ## @var ip_version_choices @@ -565,11 +564,9 @@ class ROARequestPrefix(django.db.models.Model): def as_roa_prefix(self): if self.version == 'IPv4': - return rpki.resource_set.roa_prefix_ipv4(rpki.ipaddrs.v4addr(self.prefix), - self.prefixlen, self.max_prefixlen) + return rpki.resource_set.roa_prefix_ipv4(self.prefix, self.prefixlen, self.max_prefixlen) else: - return rpki.resource_set.roa_prefix_ipv6(rpki.ipaddrs.v6addr(self.prefix), - self.prefixlen, self.max_prefixlen) + return rpki.resource_set.roa_prefix_ipv6(self.prefix, self.prefixlen, self.max_prefixlen) def as_resource_range(self): return self.as_roa_prefix().to_resource_range() diff --git a/rpkid/rpki/resource_set.py b/rpkid/rpki/resource_set.py index c39d9059..cd6a405e 100644 --- a/rpkid/rpki/resource_set.py +++ b/rpkid/rpki/resource_set.py @@ -41,9 +41,9 @@ PERFORMANCE OF THIS SOFTWARE. import re import math -import rpki.ipaddrs import rpki.oids import rpki.exceptions +import rpki.POW ## @var inherit_token # Token used to indicate inheritance in read and print syntax. @@ -65,18 +65,12 @@ class resource_range(object): """ def __init__(self, min, max): - """ - Initialize and sanity check a resource_range. - """ assert min.__class__ is max.__class__, "Type mismatch, %r doesn't match %r" % (min.__class__, max.__class__) assert min <= max, "Mis-ordered range: %s before %s" % (min, max) self.min = min self.max = max def __cmp__(self, other): - """ - Compare two resource_range objects. - """ assert self.__class__ is other.__class__, "Type mismatch, comparing %r with %r" % (self.__class__, other.__class__) return cmp(self.min, other.min) or cmp(self.max, other.max) @@ -93,6 +87,11 @@ class resource_range_as(resource_range): datum_type = long + def __init__(self, min, max): + resource_range.__init__(self, + long(min) if isinstance(min, int) else min, + long(max) if isinstance(max, int) else max) + def __str__(self): """ Convert a resource_range_as to string format. @@ -133,6 +132,11 @@ class resource_range_ip(resource_range): directly. """ + ## @var datum_type + # Type of underlying data (min and max). + + datum_type = rpki.POW.IPAddress + def prefixlen(self): """ Determine whether a resource_range_ip can be expressed as a @@ -142,7 +146,7 @@ class resource_range_ip(resource_range): mask = self.min ^ self.max if self.min & mask != 0: raise rpki.exceptions.MustBePrefix - prefixlen = self.datum_type.bits + prefixlen = self.min.bits while mask & 1: prefixlen -= 1 mask >>= 1 @@ -150,9 +154,6 @@ class resource_range_ip(resource_range): raise rpki.exceptions.MustBePrefix return prefixlen - # Backwards compatability, will go away at some point - _prefixlen = prefixlen - def __str__(self): """ Convert a resource_range_ip to string format. @@ -169,10 +170,10 @@ class resource_range_ip(resource_range): """ r = re_address_range.match(x) if r: - return cls(cls.datum_type(r.group(1)), cls.datum_type(r.group(2))) + return cls(rpki.POW.IPAddress(r.group(1)), rpki.POW.IPAddress(r.group(2))) r = re_prefix.match(x) if r: - return cls.make_prefix(cls.datum_type(r.group(1)), int(r.group(2))) + return cls.make_prefix(rpki.POW.IPAddress(r.group(1)), int(r.group(2))) raise rpki.exceptions.BadIPResource, 'Bad IP resource "%s"' % (x) @classmethod @@ -180,11 +181,11 @@ class resource_range_ip(resource_range): """ Construct a resource range corresponding to a prefix. """ - assert isinstance(prefix, cls.datum_type) and isinstance(prefixlen, (int, long)) - assert prefixlen >= 0 and prefixlen <= cls.datum_type.bits, "Nonsensical prefix length: %s" % prefixlen - mask = (1 << (cls.datum_type.bits - prefixlen)) - 1 + assert isinstance(prefix, rpki.POW.IPAddress) and isinstance(prefixlen, (int, long)) + assert prefixlen >= 0 and prefixlen <= prefix.bits, "Nonsensical prefix length: %s" % prefixlen + mask = (1 << (prefix.bits - prefixlen)) - 1 assert (prefix & mask) == 0, "Resource not in canonical form: %s/%s" % (prefix, prefixlen) - return cls(cls.datum_type(prefix), cls.datum_type(prefix | mask)) + return cls(prefix, rpki.POW.IPAddress(prefix | mask)) def chop_into_prefixes(self, result): """ @@ -198,7 +199,7 @@ class resource_range_ip(resource_range): min = self.min max = self.max while max >= min: - bits = int(math.log(max - min + 1, 2)) + bits = int(math.log(long(max - min + 1), 2)) while True: mask = ~(~0 << bits) assert min + mask <= max @@ -206,8 +207,8 @@ class resource_range_ip(resource_range): break assert bits > 0 bits -= 1 - result.append(self.make_prefix(min, self.datum_type.bits - bits)) - min = self.datum_type(min + mask + 1) + result.append(self.make_prefix(min, min.bits - bits)) + min = min + mask + 1 @classmethod def from_strings(cls, a, b = None): @@ -216,54 +217,55 @@ class resource_range_ip(resource_range): """ if b is None: b = a - a = rpki.ipaddrs.parse(a) - b = rpki.ipaddrs.parse(b) - if a.__class__ is not b.__class__: + a = rpki.POW.IPAddress(a) + b = rpki.POW.IPAddress(b) + if a.version != b.version: raise TypeError if cls is resource_range_ip: - if isinstance(a, rpki.ipaddrs.v4addr): + if a.version == 4: return resource_range_ipv4(a, b) - if isinstance(a, rpki.ipaddrs.v6addr): + if a.version == 6: return resource_range_ipv6(a, b) - elif isinstance(a, cls.datum_type): + elif a.version == cls.version: return cls(a, b) - raise TypeError + else: + raise TypeError class resource_range_ipv4(resource_range_ip): """ Range of IPv4 addresses. """ - ## @var datum_type - # Type of underlying data (min and max). - - datum_type = rpki.ipaddrs.v4addr + version = 4 class resource_range_ipv6(resource_range_ip): """ Range of IPv6 addresses. """ - ## @var datum_type - # Type of underlying data (min and max). - - datum_type = rpki.ipaddrs.v6addr + version = 6 def _rsplit(rset, that): """ Utility function to split a resource range into two resource ranges. """ + this = rset.pop(0) - cell_type = type(this.min) - assert type(this) is type(that) and type(this.max) is cell_type and \ - type(that.min) is cell_type and type(that.max) is cell_type + + assert type(this) is type(that), "type(this) [%r] is not type(that) [%r]" % (type(this), type(that)) + + assert type(this.min) is type(that.min), "type(this.min) [%r] is not type(that.min) [%r]" % (type(this.min), type(that.min)) + assert type(this.min) is type(this.max), "type(this.min) [%r] is not type(this.max) [%r]" % (type(this.min), type(this.max)) + assert type(that.min) is type(that.max), "type(that.min) [%r] is not type(that.max) [%r]" % (type(that.min), type(that.max)) + if this.min < that.min: - rset.insert(0, type(this)(this.min, cell_type(that.min - 1))) + rset.insert(0, type(this)(this.min, type(that.min)(that.min - 1))) rset.insert(1, type(this)(that.min, this.max)) + else: assert this.max > that.max rset.insert(0, type(this)(this.min, that.max)) - rset.insert(1, type(this)(cell_type(that.max + 1), this.max)) + rset.insert(1, type(this)(type(that.max)(that.max + 1), this.max)) class resource_set(list): """ @@ -664,14 +666,9 @@ class resource_bag(object): temporary: in the long run, we should be using rpki.POW.IPAddress rather than long here. """ - asn = [resource_range_as(long(r[0]), long(r[1])) - for r in resources[0] or ()] - v4 = [resource_range_ipv4(rpki.ipaddrs.v4addr(long(r[0])), - rpki.ipaddrs.v4addr(long(r[1]))) - for r in resources[1] or ()] - v6 = [resource_range_ipv6(rpki.ipaddrs.v6addr(long(r[0])), - rpki.ipaddrs.v6addr(long(r[1]))) - for r in resources[2] or ()] + asn = [resource_range_as(r[0], r[1]) for r in resources[0] or ()] + v4 = [resource_range_ipv4(r[0], r[1]) for r in resources[1] or ()] + v6 = [resource_range_ipv6(r[0], r[1]) for r in resources[2] or ()] return cls(resource_set_as(asn) if asn else None, resource_set_ipv4(v4) if v4 else None, resource_set_ipv6(v6) if v6 else None) @@ -829,16 +826,13 @@ class roa_prefix(object): """ Return highest address covered by prefix. """ - t = self.range_type.datum_type - return t(self.prefix | ((1 << (t.bits - self.prefixlen)) - 1)) + return self.prefix | ((1 << (self.prefix.bits - self.prefixlen)) - 1) def to_POW_roa_tuple(self): """ Convert a resource_range_ip to rpki.POW.ROA.setPrefixes() format. """ - return (rpki.POW.IPAddress(self.prefix, self.range_type.datum_type.ipversion), - self.prefixlen, - None if self.prefixlen == self.max_prefixlen else self.max_prefixlen) + return self.prefix, self.prefixlen, self.max_prefixlen @classmethod def parse_str(cls, x): @@ -847,10 +841,10 @@ class roa_prefix(object): """ r = re_prefix_with_maxlen.match(x) if r: - return cls(cls.range_type.datum_type(r.group(1)), int(r.group(2)), int(r.group(3))) + return cls(rpki.POW.IPAddress(r.group(1)), int(r.group(2)), int(r.group(3))) r = re_prefix.match(x) if r: - return cls(cls.range_type.datum_type(r.group(1)), int(r.group(2))) + return cls(rpki.POW.IPAddress(r.group(1)), int(r.group(2))) raise rpki.exceptions.BadROAPrefix, 'Bad ROA prefix "%s"' % (x) class roa_prefix_ipv4(roa_prefix): @@ -935,7 +929,7 @@ class roa_prefix_set(list): """ sql.execute(query, args) - return cls([cls.prefix_type(cls.prefix_type.range_type.datum_type(x), int(y), int(z)) + return cls([cls.prefix_type(rpki.POW.IPAddress(x), int(y), int(z)) for (x, y, z) in sql.fetchall()]) @classmethod @@ -947,7 +941,7 @@ class roa_prefix_set(list): max_prefixlen) triples. """ - return cls([cls.prefix_type(cls.prefix_type.range_type.datum_type(x), int(y), int(z)) + return cls([cls.prefix_type(rpki.POW.IPAddress(x), int(y), int(z)) for (x, y, z) in iterable]) def to_POW_roa_tuple(self): |