📄 v3_addr.c
字号:
*result = aor; return 1; err: IPAddressOrRange_free(aor); return 0;}/* * Construct a range. If it can be expressed as a prefix, * return a prefix instead. Doing this here simplifies * the rest of the code considerably. */static int make_addressRange(IPAddressOrRange **result, unsigned char *min, unsigned char *max, const int length){ IPAddressOrRange *aor; int i, prefixlen; if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0) return make_addressPrefix(result, min, prefixlen); if ((aor = IPAddressOrRange_new()) == NULL) return 0; aor->type = IPAddressOrRange_addressRange; OPENSSL_assert(aor->u.addressRange == NULL); if ((aor->u.addressRange = IPAddressRange_new()) == NULL) goto err; if (aor->u.addressRange->min == NULL && (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL) goto err; if (aor->u.addressRange->max == NULL && (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL) goto err; for (i = length; i > 0 && min[i - 1] == 0x00; --i) ; if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i)) goto err; aor->u.addressRange->min->flags &= ~7; aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT; if (i > 0) { unsigned char b = min[i - 1]; int j = 1; while ((b & (0xFFU >> j)) != 0) ++j; aor->u.addressRange->min->flags |= 8 - j; } for (i = length; i > 0 && max[i - 1] == 0xFF; --i) ; if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i)) goto err; aor->u.addressRange->max->flags &= ~7; aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT; if (i > 0) { unsigned char b = max[i - 1]; int j = 1; while ((b & (0xFFU >> j)) != (0xFFU >> j)) ++j; aor->u.addressRange->max->flags |= 8 - j; } *result = aor; return 1; err: IPAddressOrRange_free(aor); return 0;}/* * Construct a new address family or find an existing one. */static IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi){ IPAddressFamily *f; unsigned char key[3]; unsigned keylen; int i; key[0] = (afi >> 8) & 0xFF; key[1] = afi & 0xFF; if (safi != NULL) { key[2] = *safi & 0xFF; keylen = 3; } else { keylen = 2; } for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { f = sk_IPAddressFamily_value(addr, i); OPENSSL_assert(f->addressFamily->data != NULL); if (f->addressFamily->length == keylen && !memcmp(f->addressFamily->data, key, keylen)) return f; } if ((f = IPAddressFamily_new()) == NULL) goto err; if (f->ipAddressChoice == NULL && (f->ipAddressChoice = IPAddressChoice_new()) == NULL) goto err; if (f->addressFamily == NULL && (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL) goto err; if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen)) goto err; if (!sk_IPAddressFamily_push(addr, f)) goto err; return f; err: IPAddressFamily_free(f); return NULL;}/* * Add an inheritance element. */int v3_addr_add_inherit(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi){ IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); if (f == NULL || f->ipAddressChoice == NULL || (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && f->ipAddressChoice->u.addressesOrRanges != NULL)) return 0; if (f->ipAddressChoice->type == IPAddressChoice_inherit && f->ipAddressChoice->u.inherit != NULL) return 1; if (f->ipAddressChoice->u.inherit == NULL && (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) return 0; f->ipAddressChoice->type = IPAddressChoice_inherit; return 1;}/* * Construct an IPAddressOrRange sequence, or return an existing one. */static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi){ IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); IPAddressOrRanges *aors = NULL; if (f == NULL || f->ipAddressChoice == NULL || (f->ipAddressChoice->type == IPAddressChoice_inherit && f->ipAddressChoice->u.inherit != NULL)) return NULL; if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) aors = f->ipAddressChoice->u.addressesOrRanges; if (aors != NULL) return aors; if ((aors = sk_IPAddressOrRange_new_null()) == NULL) return NULL; switch (afi) { case IANA_AFI_IPV4: (void)sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); break; case IANA_AFI_IPV6: (void)sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); break; } f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; f->ipAddressChoice->u.addressesOrRanges = aors; return aors;}/* * Add a prefix. */int v3_addr_add_prefix(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi, unsigned char *a, const int prefixlen){ IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); IPAddressOrRange *aor; if (aors == NULL || !make_addressPrefix(&aor, a, prefixlen)) return 0; if (sk_IPAddressOrRange_push(aors, aor)) return 1; IPAddressOrRange_free(aor); return 0;}/* * Add a range. */int v3_addr_add_range(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi, unsigned char *min, unsigned char *max){ IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); IPAddressOrRange *aor; int length = length_from_afi(afi); if (aors == NULL) return 0; if (!make_addressRange(&aor, min, max, length)) return 0; if (sk_IPAddressOrRange_push(aors, aor)) return 1; IPAddressOrRange_free(aor); return 0;}/* * Extract min and max values from an IPAddressOrRange. */static void extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max, int length){ OPENSSL_assert(aor != NULL && min != NULL && max != NULL); switch (aor->type) { case IPAddressOrRange_addressPrefix: addr_expand(min, aor->u.addressPrefix, length, 0x00); addr_expand(max, aor->u.addressPrefix, length, 0xFF); return; case IPAddressOrRange_addressRange: addr_expand(min, aor->u.addressRange->min, length, 0x00); addr_expand(max, aor->u.addressRange->max, length, 0xFF); return; }}/* * Public wrapper for extract_min_max(). */int v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, unsigned char *min, unsigned char *max, const int length){ int afi_length = length_from_afi(afi); if (aor == NULL || min == NULL || max == NULL || afi_length == 0 || length < afi_length || (aor->type != IPAddressOrRange_addressPrefix && aor->type != IPAddressOrRange_addressRange)) return 0; extract_min_max(aor, min, max, afi_length); return afi_length;}/* * Sort comparision function for a sequence of IPAddressFamily. * * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about * the ordering: I can read it as meaning that IPv6 without a SAFI * comes before IPv4 with a SAFI, which seems pretty weird. The * examples in appendix B suggest that the author intended the * null-SAFI rule to apply only within a single AFI, which is what I * would have expected and is what the following code implements. */static int IPAddressFamily_cmp(const IPAddressFamily * const *a_, const IPAddressFamily * const *b_){ const ASN1_OCTET_STRING *a = (*a_)->addressFamily; const ASN1_OCTET_STRING *b = (*b_)->addressFamily; int len = ((a->length <= b->length) ? a->length : b->length); int cmp = memcmp(a->data, b->data, len); return cmp ? cmp : a->length - b->length;}/* * Check whether an IPAddrBLocks is in canonical form. */int v3_addr_is_canonical(IPAddrBlocks *addr){ unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; IPAddressOrRanges *aors; int i, j, k; /* * Empty extension is cannonical. */ if (addr == NULL) return 1; /* * Check whether the top-level list is in order. */ for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) { const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i); const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1); if (IPAddressFamily_cmp(&a, &b) >= 0) return 0; } /* * Top level's ok, now check each address family. */ for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); int length = length_from_afi(v3_addr_get_afi(f)); /* * Inheritance is canonical. Anything other than inheritance or * a SEQUENCE OF IPAddressOrRange is an ASN.1 error or something. */ if (f == NULL || f->ipAddressChoice == NULL) return 0; switch (f->ipAddressChoice->type) { case IPAddressChoice_inherit: continue; case IPAddressChoice_addressesOrRanges: break; default: return 0; } /* * It's an IPAddressOrRanges sequence, check it. */ aors = f->ipAddressChoice->u.addressesOrRanges; if (sk_IPAddressOrRange_num(aors) == 0) return 0; for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); extract_min_max(a, a_min, a_max, length); extract_min_max(b, b_min, b_max, length); /* * Punt misordered list, overlapping start, or inverted range. */ if (memcmp(a_min, b_min, length) >= 0 || memcmp(a_min, a_max, length) > 0 || memcmp(b_min, b_max, length) > 0) return 0; /* * Punt if adjacent or overlapping. Check for adjacency by * subtracting one from b_min first. */ for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) ; if (memcmp(a_max, b_min, length) >= 0) return 0; /* * Check for range that should be expressed as a prefix. */ if (a->type == IPAddressOrRange_addressRange && range_should_be_prefix(a_min, a_max, length) >= 0) return 0; } /* * Check final range to see if it should be a prefix. */ j = sk_IPAddressOrRange_num(aors) - 1; { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); if (a->type == IPAddressOrRange_addressRange) { extract_min_max(a, a_min, a_max, length); if (range_should_be_prefix(a_min, a_max, length) >= 0) return 0; } } } /* * If we made it through all that, we're happy. */ return 1;}/* * Whack an IPAddressOrRanges into canonical form. */static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi){ int i, j, length = length_from_afi(afi); /* * Sort the IPAddressOrRanges sequence. */ sk_IPAddressOrRange_sort(aors); /* * Clean up representation issues, punt on duplicates or overlaps. */ for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i); IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1); unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; extract_min_max(a, a_min, a_max, length); extract_min_max(b, b_min, b_max, length); /* * Punt overlaps. */ if (memcmp(a_max, b_min, length) >= 0) return 0; /* * Merge if a and b are adjacent. We check for * adjacency by subtracting one from b_min first. */ for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) ; if (memcmp(a_max, b_min, length) == 0) { IPAddressOrRange *merged; if (!make_addressRange(&merged, a_min, b_max, length)) return 0; sk_IPAddressOrRange_set(aors, i, merged);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -