aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2012-10-13 02:05:48 +0000
committerRob Austein <sra@hactrn.net>2012-10-13 02:05:48 +0000
commit62ad1981e5cbac473dd271725d33ff162f4884de (patch)
tree4301c64502a9c9514b35262da75799fba2d1ec24
parent0410c74a1c6cfe7aae557f31195b662bf2792a0a (diff)
Consolidate all the IP-version-specific voodoo into a read-only data
structure. svn path=/branches/tk274/; revision=4777
-rw-r--r--rpkid/ext/POW.c201
1 files changed, 96 insertions, 105 deletions
diff --git a/rpkid/ext/POW.c b/rpkid/ext/POW.c
index 2838b851..c6c02c82 100644
--- a/rpkid/ext/POW.c
+++ b/rpkid/ext/POW.c
@@ -207,6 +207,29 @@ static const struct {
};
/*
+ * IP versions.
+ */
+
+typedef struct ipaddress_version {
+ unsigned version;
+ unsigned afi;
+ unsigned af;
+ unsigned length;
+} ipaddress_version;
+
+static const ipaddress_version ipaddress_version_4 = {
+ 4, IANA_AFI_IPV4, AF_INET, 4
+};
+
+static const ipaddress_version ipaddress_version_6 = {
+ 6, IANA_AFI_IPV6, AF_INET6, 16
+};
+
+static const ipaddress_version * const ipaddress_versions[] = {
+ &ipaddress_version_4, &ipaddress_version_6
+};
+
+/*
* Exception objects.
*/
@@ -240,9 +263,7 @@ static PyTypeObject
typedef struct {
PyObject_HEAD
unsigned char address[16];
- unsigned char version;
- unsigned char length;
- unsigned short af;
+ const struct ipaddress_version *type;
} ipaddress_object;
typedef struct {
@@ -941,6 +962,7 @@ ipaddress_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject *pylong = NULL;
int version = 0;
const char *s = NULL;
+ int v;
ENTERING(ipaddress_object_new);
@@ -950,12 +972,8 @@ ipaddress_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (POW_IPAddress_Check(init)) {
ipaddress_object *src = (ipaddress_object *) init;
-
memcpy(self->address, src->address, sizeof(self->address));
- self->version = src->version;
- self->length = src->length;
- self->af = src->af;
-
+ self->type = src->type;
return (PyObject *) self;
}
@@ -964,21 +982,23 @@ ipaddress_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
else if (version == 0)
version = strchr(s, ':') ? 6 : 4;
- switch (version) {
- case 4: self->length = 4; self->af = AF_INET; break;
- case 6: self->length = 16; self->af = AF_INET6; break;
- default: lose("Unknown IP version number");
- }
- self->version = version;
+ self->type = NULL;
+
+ for (v = 0; v < sizeof(ipaddress_versions)/sizeof(*ipaddress_versions); v++)
+ if (version == ipaddress_versions[v]->version)
+ self->type = ipaddress_versions[v];
+
+ if (self->type == NULL)
+ lose("Unknown IP version number");
if (s != NULL) {
- if (inet_pton(self->af, s, self->address) <= 0)
+ if (inet_pton(self->type->af, s, self->address) <= 0)
lose("Couldn't parse IP address");
return (PyObject *) self;
}
if ((pylong = PyNumber_Long(init)) != NULL) {
- if (_PyLong_AsByteArray((PyLongObject *) pylong, self->address, self->length, 0, 0) < 0)
+ if (_PyLong_AsByteArray((PyLongObject *) pylong, self->address, self->type->length, 0, 0) < 0)
goto error;
Py_XDECREF(pylong);
return (PyObject *) self;
@@ -999,7 +1019,7 @@ ipaddress_object_str(ipaddress_object *self)
ENTERING(ipaddress_object_str);
- if (!inet_ntop(self->af, self->address, addrstr, sizeof(addrstr)))
+ if (!inet_ntop(self->type->af, self->address, addrstr, sizeof(addrstr)))
lose("Couldn't convert IP address");
return PyString_FromString(addrstr);
@@ -1015,7 +1035,7 @@ ipaddress_object_repr(ipaddress_object *self)
ENTERING(ipaddress_object_repr);
- if (!inet_ntop(self->af, self->address, addrstr, sizeof(addrstr)))
+ if (!inet_ntop(self->type->af, self->address, addrstr, sizeof(addrstr)))
lose("Couldn't convert IP address");
return PyString_FromFormat("<%s object %s at %p>",
@@ -1067,7 +1087,7 @@ ipaddress_object_hash(ipaddress_object *self)
ENTERING(ipaddress_object_hash);
- for (i = 0; i < self->length; i++)
+ for (i = 0; i < self->type->length; i++)
h ^= self->address[i] << ((i & 3) << 3);
return (long) h == -1 ? 0 : (long) h;
@@ -1085,25 +1105,26 @@ ipaddress_object_from_bytes(PyTypeObject *type, PyObject *args)
ipaddress_object *result = NULL;
char *bytes = NULL;
size_t len;
+ int v;
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;
+ result->type = NULL;
- switch (len) {
- case 4: result->version = 4; result->af = AF_INET; break;
- case 16: result->version = 6; result->af = AF_INET6; break;
- }
+ for (v = 0; v < sizeof(ipaddress_versions)/sizeof(*ipaddress_versions); v++)
+ if (len == ipaddress_versions[v]->length)
+ result->type = ipaddress_versions[v];
+
+ if (result->type == NULL)
+ lose("Unknown IP version number");
+
+ memcpy(result->address, bytes, len);
error:
return (PyObject *) result;
@@ -1118,21 +1139,21 @@ static PyObject *
ipaddress_object_to_bytes(ipaddress_object *self)
{
ENTERING(ipaddress_object_from_bytes);
- return PyString_FromStringAndSize(self->address, self->length);
+ return PyString_FromStringAndSize(self->address, self->type->length);
}
static PyObject *
ipaddress_object_get_bits(ipaddress_object *self, void *closure)
{
ENTERING(ipaddress_object_get_bits);
- return PyInt_FromLong(self->length * 8);
+ return PyInt_FromLong(self->type->length * 8);
}
static PyObject *
ipaddress_object_get_version(ipaddress_object *self, void *closure)
{
ENTERING(ipaddress_object_get_version);
- return PyInt_FromLong(self->version);
+ return PyInt_FromLong(self->type->version);
}
static PyObject *
@@ -1154,7 +1175,7 @@ ipaddress_object_number_binary_helper(binaryfunc function, PyObject *arg1, PyObj
addr2 = (ipaddress_object *) arg2;
if ((addr1 == NULL && addr2 == NULL) ||
- (addr1 != NULL && addr2 != NULL && addr1->version != addr2->version) ||
+ (addr1 != NULL && addr2 != NULL && addr1->type != addr2->type) ||
(obj1 = PyNumber_Long(arg1)) == NULL ||
(obj2 = PyNumber_Long(arg2)) == NULL) {
result = (ipaddress_object *) Py_NotImplemented;
@@ -1172,11 +1193,9 @@ ipaddress_object_number_binary_helper(binaryfunc function, PyObject *arg1, PyObj
if ((result = (ipaddress_object *) addr->ob_type->tp_alloc(addr->ob_type, 0)) == NULL)
goto error;
- result->version = addr->version;
- result->length = addr->length;
- result->af = addr->af;
+ result->type = addr->type;
- if (_PyLong_AsByteArray((PyLongObject *) obj4, result->address, result->length, 0, 0) < 0) {
+ if (_PyLong_AsByteArray((PyLongObject *) obj4, result->address, result->type->length, 0, 0) < 0) {
Py_XDECREF(result);
result = NULL;
}
@@ -1200,7 +1219,7 @@ ipaddress_object_number_long(PyObject *arg)
if (!POW_IPAddress_Check(arg))
return Py_NotImplemented;
- return _PyLong_FromByteArray(addr->address, addr->length, 0, 0);
+ return _PyLong_FromByteArray(addr->address, addr->type->length, 0, 0);
}
static PyObject *
@@ -1266,7 +1285,7 @@ ipaddress_object_number_nonzero(ipaddress_object *self)
ENTERING(ipaddress_object_number_nonzero);
- for (i = 0; i < self->length; i++)
+ for (i = 0; i < self->type->length; i++)
if (self->address[i] != 0)
return 1;
return 0;
@@ -1283,11 +1302,9 @@ ipaddress_object_number_invert(ipaddress_object *self)
if ((result = (ipaddress_object *) self->ob_type->tp_alloc(self->ob_type, 0)) == NULL)
goto error;
- result->version = self->version;
- result->length = self->length;
- result->af = self->af;
+ result->type = self->type;
- for (i = 0; i < self->length; i++)
+ for (i = 0; i < self->type->length; i++)
result->address[i] = ~self->address[i];
error: /* Fall through */
@@ -2401,13 +2418,14 @@ x509_object_get_rfc3779(x509_object *self)
if ((addr = X509_get_ext_d2i(self->x509, NID_sbgp_ipAddrBlock, NULL, NULL)) != NULL) {
for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
+ const struct ipaddress_version *ip_type = NULL;
const unsigned int afi = v3_addr_get_afi(f);
PyObject **result_obj = NULL;
int addr_len = 0;
switch (afi) {
- case IANA_AFI_IPV4: result_obj = &ipv4_result; break;
- case IANA_AFI_IPV6: result_obj = &ipv6_result; break;
+ case IANA_AFI_IPV4: result_obj = &ipv4_result; ip_type = &ipaddress_version_4; break;
+ case IANA_AFI_IPV6: result_obj = &ipv6_result; ip_type = &ipaddress_version_6; break;
default: lose_type_error("Unknown AFI");
}
@@ -2435,8 +2453,7 @@ x509_object_get_rfc3779(x509_object *self)
goto error;
for (j = 0; j < sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges); j++) {
- IPAddressOrRange *aor = sk_IPAddressOrRange_value(f->ipAddressChoice->u.addressesOrRanges,
- j);
+ IPAddressOrRange *aor = sk_IPAddressOrRange_value(f->ipAddressChoice->u.addressesOrRanges, j);
ipaddress_object *addr_b = NULL;
ipaddress_object *addr_e = NULL;
@@ -2447,21 +2464,11 @@ x509_object_get_rfc3779(x509_object *self)
addr_b = (ipaddress_object *) range_b;
addr_e = (ipaddress_object *) range_e;
- if ((addr_len = v3_addr_get_range(aor, afi, addr_b->address, addr_e->address, sizeof(addr_b->address))) == 0)
+ if ((addr_len = v3_addr_get_range(aor, afi, addr_b->address, addr_e->address,
+ sizeof(addr_b->address))) == 0)
lose_type_error("Couldn't unpack IP addresses from BIT STRINGs");
- switch (afi) {
- case IANA_AFI_IPV4:
- addr_b->version = addr_e->version = 4;
- addr_b->length = addr_e->length = 4;
- addr_b->af = addr_e->af = AF_INET;
- break;
- case IANA_AFI_IPV6:
- addr_b->version = addr_e->version = 6;
- addr_b->length = addr_e->length = 16;
- addr_b->af = addr_e->af = AF_INET6;
- break;
- }
+ addr_b->type = addr_e->type = ip_type;
if ((range = Py_BuildValue("(NN)", range_b, range_e)) == NULL)
goto error;
@@ -2579,7 +2586,7 @@ x509_object_set_rfc3779(x509_object *self, PyObject *args, PyObject *kwds)
}
if (ipv4_arg != Py_None || ipv6_arg != Py_None) {
- int afi;
+ int v;
empty = 1;
@@ -2588,19 +2595,17 @@ x509_object_set_rfc3779(x509_object *self, PyObject *args, PyObject *kwds)
/*
* Cheap trick to let us inline all of this instead of being
- * forced to use a separate function. Should probably use a
- * separate function anyway, but am waiting until I have the ROA
- * code written to decide how best to refactor all of this.
+ * forced to use a separate function. Refactor, some day.
*/
- for (afi = 0; afi < IANA_AFI_IPV4 + IANA_AFI_IPV6; afi++) {
+ for (v = 0; v < sizeof(ipaddress_versions)/sizeof(*ipaddress_versions); v++) {
+ const struct ipaddress_version *ip_type = ipaddress_versions[v];
PyObject **argp;
- int len;
- switch (afi) {
- case IANA_AFI_IPV4: len = 4; argp = &ipv4_arg; break;
- case IANA_AFI_IPV6: len = 16; argp = &ipv6_arg; break;
- default: continue;
+ switch (ip_type->version) {
+ case 4: argp = &ipv4_arg; break;
+ case 6: argp = &ipv6_arg; break;
+ default: continue; /* Never happens */
}
if (PyString_Check(*argp)) {
@@ -2608,7 +2613,7 @@ x509_object_set_rfc3779(x509_object *self, PyObject *args, PyObject *kwds)
if (strcmp(PyString_AsString(*argp), "inherit"))
lose_type_error("Argument must be sequence of range pairs, or \"inherit\"");
- if (!v3_addr_add_inherit(addr, afi, NULL))
+ if (!v3_addr_add_inherit(addr, ip_type->afi, NULL))
lose_no_memory();
empty = 0;
@@ -2628,13 +2633,12 @@ x509_object_set_rfc3779(x509_object *self, PyObject *args, PyObject *kwds)
addr_b = (ipaddress_object *) range_b;
addr_e = (ipaddress_object *) range_e;
- if (addr_b->version != addr_e->version ||
- addr_b->length != len ||
- addr_e->length != len ||
- memcmp(addr_b->address, addr_e->address, addr_b->length) > 0)
+ if (addr_b->type != ip_type ||
+ addr_e->type != ip_type ||
+ memcmp(addr_b->address, addr_e->address, ip_type->length) > 0)
lose("IPAddrBlock must be sequence of address pairs, or \"inherit\"");
- if (!v3_addr_add_range(addr, afi, NULL, addr_b->address, addr_e->address))
+ if (!v3_addr_add_range(addr, ip_type->afi, NULL, addr_b->address, addr_e->address))
lose_openssl_error("Couldn't add range to IPAddrBlock");
Py_XDECREF(item);
@@ -6990,11 +6994,12 @@ roa_object_get_prefixes(roa_object *self)
for (i = 0; i < sk_ROAIPAddressFamily_num(self->roa->ipAddrBlocks); i++) {
ROAIPAddressFamily *fam = sk_ROAIPAddressFamily_value(self->roa->ipAddrBlocks, i);
const unsigned afi = (fam->addressFamily->data[0] << 8) | (fam->addressFamily->data[1]);
+ const ipaddress_version *ip_type = NULL;
PyObject **resultp = NULL;
switch (afi) {
- case IANA_AFI_IPV4: resultp = &ipv4_result; break;
- case IANA_AFI_IPV6: resultp = &ipv6_result; break;
+ case IANA_AFI_IPV4: resultp = &ipv4_result; ip_type = &ipaddress_version_4; break;
+ case IANA_AFI_IPV6: resultp = &ipv6_result; ip_type = &ipaddress_version_6; break;
default: lose_type_error("Unknown AFI");
}
@@ -7014,22 +7019,11 @@ roa_object_get_prefixes(roa_object *self)
if ((addr = (ipaddress_object *) POW_IPAddress_Type.tp_alloc(&POW_IPAddress_Type, 0)) == NULL)
goto error;
- switch (afi) {
- case IANA_AFI_IPV4:
- addr->version = 4;
- addr->length = 4;
- addr->af = AF_INET;
- break;
- case IANA_AFI_IPV6:
- addr->version = 6;
- addr->length = 16;
- addr->af = AF_INET6;
- break;
- }
+ addr->type = ip_type;
memset(addr->address, 0, sizeof(addr->address));
- if (a->IPAddress->length > addr->length)
+ if (a->IPAddress->length > addr->type->length)
lose("ROAIPAddress BIT STRING too long for AFI");
if (a->IPAddress->length > 0) {
@@ -7085,7 +7079,8 @@ roa_object_set_prefixes(roa_object *self, PyObject *args, PyObject *kwds)
PyObject *ipv6_arg = Py_None;
PyObject *iterator = NULL;
PyObject *item = NULL;
- int afi, ok = 0;
+ int ok = 0;
+ int v;
ENTERING(roa_object_set_prefixes);
@@ -7098,26 +7093,22 @@ roa_object_set_prefixes(roa_object *self, PyObject *args, PyObject *kwds)
if ((prefixes = sk_ROAIPAddressFamily_new_null()) == NULL)
lose_no_memory();
- /*
- * Cheap trick. Refactor once I figure out how this all works.
- */
-
- for (afi = 0; afi < IANA_AFI_IPV4 + IANA_AFI_IPV6; afi++) {
+ for (v = 0; v < sizeof(ipaddress_versions)/sizeof(*ipaddress_versions); v++) {
+ const struct ipaddress_version *ip_type = ipaddress_versions[v];
unsigned char afibuf[2];
PyObject **argp;
- int len;
- switch (afi) {
- case IANA_AFI_IPV4: len = 4; argp = &ipv4_arg; break;
- case IANA_AFI_IPV6: len = 16; argp = &ipv6_arg; break;
+ switch (ip_type->version) {
+ case 4: argp = &ipv4_arg; break;
+ case 6: argp = &ipv6_arg; break;
default: continue;
}
if (*argp == Py_None)
continue;
- afibuf[0] = (afi >> 8) & 0xFF;
- afibuf[1] = afi & 0xFF;
+ afibuf[0] = (ip_type->afi >> 8) & 0xFF;
+ afibuf[1] = (ip_type->afi ) & 0xFF;
if ((iterator = PyObject_GetIter(*argp)) == NULL)
goto error;
@@ -7138,13 +7129,13 @@ roa_object_set_prefixes(roa_object *self, PyObject *args, PyObject *kwds)
goto error;
}
- if (addr->length != len)
+ if (addr->type != ip_type)
lose_type_error("Bad ROA prefix");
- if (prefixlen > addr->length * 8)
+ if (prefixlen > addr->type->length * 8)
lose("Bad prefix length");
- if (maxprefixlen > addr->length * 8 || maxprefixlen < prefixlen)
+ if (maxprefixlen > addr->type->length * 8 || maxprefixlen < prefixlen)
lose("Bad maxLength value");
bytelen = (prefixlen + 7) / 8;