aboutsummaryrefslogtreecommitdiff
path: root/openssl/trunk/crypto/x509v3/v3_addr.c
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2006-07-22 23:17:49 +0000
committerRob Austein <sra@hactrn.net>2006-07-22 23:17:49 +0000
commit218a838e9c5187cfd3698ecec35a3f6a6c547d25 (patch)
treeebb59febc74bd77b7c129e159a9b16be427aa754 /openssl/trunk/crypto/x509v3/v3_addr.c
parent620fb77d27bd4296b7268e083c050b6b25f2fb89 (diff)
Add range_should_be_prefix() after concluding that previous code was
too clever (and didn't work). svn path=/openssl/trunk/crypto/x509v3/v3_addr.c; revision=48
Diffstat (limited to 'openssl/trunk/crypto/x509v3/v3_addr.c')
-rw-r--r--openssl/trunk/crypto/x509v3/v3_addr.c72
1 files changed, 63 insertions, 9 deletions
diff --git a/openssl/trunk/crypto/x509v3/v3_addr.c b/openssl/trunk/crypto/x509v3/v3_addr.c
index ac1004ec..28055399 100644
--- a/openssl/trunk/crypto/x509v3/v3_addr.c
+++ b/openssl/trunk/crypto/x509v3/v3_addr.c
@@ -92,6 +92,11 @@ static void addr_expand(unsigned char *addr,
}
/*
+ * Extract the prefix length from a bitstring.
+ */
+#define addr_prefixlen(bs) ((bs)->length * 8 - ((bs)->flags & 7))
+
+/*
* Compare two addresses.
* At the moment this is coded for simplicity, not for speed.
*
@@ -169,9 +174,7 @@ static int i2r_IPAddressOrRange(BIO *out,
case IPAddressOrRange_addressPrefix:
if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix))
return 0;
- BIO_printf(out, "/%d\n",
- ((aor->u.addressPrefix->length * 8) -
- (aor->u.addressPrefix->flags & 7)));
+ BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix));
continue;
case IPAddressOrRange_addressRange:
if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min))
@@ -268,8 +271,7 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a,
switch (a->type) {
case IPAddressOrRange_addressPrefix:
addr_a = a->u.addressPrefix;
- prefixlen_a = ((a->u.addressPrefix->length * 8) -
- (a->u.addressPrefix->flags & 7));
+ prefixlen_a = addr_prefixlen(a->u.addressPrefix);
break;
case IPAddressOrRange_addressRange:
addr_a = a->u.addressRange->min;
@@ -280,8 +282,7 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a,
switch (b->type) {
case IPAddressOrRange_addressPrefix:
addr_b = b->u.addressPrefix;
- prefixlen_b = ((b->u.addressPrefix->length * 8) -
- (b->u.addressPrefix->flags & 7));
+ prefixlen_b = addr_prefixlen(b->u.addressPrefix);
break;
case IPAddressOrRange_addressRange:
addr_b = b->u.addressRange->min;
@@ -312,6 +313,48 @@ static int v6IPAddressOrRange_cmp(const IPAddressOrRange * const *a,
}
/*
+ * Calculate whether a range should be collapsed to a prefix.
+ * prefixlen is set on return to indicate the prefix length we found
+ */
+static int range_should_be_prefix(const IPAddressRange *r,
+ const int length,
+ unsigned *prefixlen)
+{
+ unsigned char mask, min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN];
+ int p, i, j;
+ addr_expand(min, r->min, length, 0x00);
+ addr_expand(max, r->max, length, 0xFF);
+ i = 0;
+ while (i < length && min[i] == max[i])
+ i++;
+ j = length - 1;
+ while (j >= 0 && min[j] == 0x00 && max[j] == 0xFF)
+ j--;
+ if (i < j)
+ return 0;
+ if (i > j) {
+ *prefixlen = i * 8;
+ return 1;
+ }
+ mask = min[i] ^ max[i];
+ switch (mask) {
+ case 0x01: p = 7; break;
+ case 0x03: p = 6; break;
+ case 0x07: p = 5; break;
+ case 0x0F: p = 4; break;
+ case 0x1F: p = 3; break;
+ case 0x3F: p = 2; break;
+ case 0x7F: p = 1; break;
+ default: return 0;
+ }
+ if (min[i] & mask != 0 || max[i] & mask != mask)
+ return 0;
+ *prefixlen = i * 8 + p;
+ return 1;
+}
+
+
+/*
* Whack an IPAddressOrRanges into canonical form.
*/
static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
@@ -450,6 +493,12 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
/*
* Convert ranges to prefixes where possible.
*/
+#error broken
+ /*
+ * This needs to be rewritten to use range_should_be_prefix(), or
+ * needs to be combined with that code in a new function, or
+ * something. As it stands, this code does not work.
+ */
for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) {
IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i);
if (a->type == IPAddressOrRange_addressRange &&
@@ -457,8 +506,13 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
0x00, 0x00, length, 0) == 0) {
IPAddressRange *r = a->u.addressRange;
a->type = IPAddressOrRange_addressPrefix;
- a->u.addressPrefix = r->min;
- ASN1_BIT_STRING_free(r->max);
+ if (addr_prefixlen(r->min) > addr_prefixlen(r->max)) {
+ a->u.addressPrefix = r->min;
+ ASN1_BIT_STRING_free(r->max);
+ } else {
+ a->u.addressPrefix = r->max;
+ ASN1_BIT_STRING_free(r->min);
+ }
IPAddressRange_free(r);
}
}