+ for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+ CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
+ unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN];
+ unsigned afi, *safi = NULL, safi_;
+ const char *addr_chars;
+ int prefixlen, i1, i2, delim, length;
+
+ if (!name_cmp(val->name, "IPv4")) {
+ afi = IANA_AFI_IPV4;
+ } else if (!name_cmp(val->name, "IPv6")) {
+ afi = IANA_AFI_IPV6;
+ } else if (!name_cmp(val->name, "IPv4-SAFI")) {
+ afi = IANA_AFI_IPV4;
+ safi = &safi_;
+ } else if (!name_cmp(val->name, "IPv6-SAFI")) {
+ afi = IANA_AFI_IPV6;
+ safi = &safi_;
+ } else {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
+ X509V3_R_EXTENSION_NAME_ERROR);
+ X509V3_conf_err(val);
+ goto err;
+ }
+
+ switch (afi) {
+ case IANA_AFI_IPV4:
+ addr_chars = v4addr_chars;
+ break;
+ case IANA_AFI_IPV6:
+ addr_chars = v6addr_chars;
+ break;
+ }
+
+ length = length_from_afi(afi);
+
+ /*
+ * Handle SAFI, if any, and BUF_strdup() so we can null-terminate
+ * the other input values.
+ */
+ if (safi != NULL) {
+ *safi = strtoul(val->value, &t, 0);
+ t += strspn(t, " \t");
+ if (*safi > 0xFF || *t++ != ':') {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_SAFI);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ t += strspn(t, " \t");
+ s = BUF_strdup(t);
+ } else {
+ s = BUF_strdup(val->value);
+ }
+ if (s == NULL) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /*
+ * Check for inheritance. Not worth additional complexity to
+ * optimize this (seldom-used) case.
+ */
+ if (!strcmp(s, "inherit")) {
+ if (!v3_addr_add_inherit(addr, afi, safi)) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
+ X509V3_R_INVALID_INHERITANCE);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ OPENSSL_free(s);
+ s = NULL;
+ continue;
+ }
+
+ i1 = strspn(s, addr_chars);
+ i2 = i1 + strspn(s + i1, " \t");
+ delim = s[i2++];
+ s[i1] = '\0';
+
+ if (a2i_ipadd(min, s) != length) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_IPADDRESS);
+ X509V3_conf_err(val);
+ goto err;
+ }
+
+ switch (delim) {
+ case '/':
+ prefixlen = (int)strtoul(s + i2, &t, 10);
+ if (t == s + i2 || *t != '\0') {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
+ X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ if (!v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ break;
+ case '-':
+ i1 = i2 + strspn(s + i2, " \t");
+ i2 = i1 + strspn(s + i1, addr_chars);
+ if (i1 == i2 || s[i2] != '\0') {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
+ X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ if (a2i_ipadd(max, s + i1) != length) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
+ X509V3_R_INVALID_IPADDRESS);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ if (memcmp(min, max, length_from_afi(afi)) > 0) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
+ X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_err(val);
+ goto err;
+ }
+ if (!v3_addr_add_range(addr, afi, safi, min, max)) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ break;
+ case '\0':
+ if (!v3_addr_add_prefix(addr, afi, safi, min, length * 8)) {
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ break;
+ default:
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS,
+ X509V3_R_EXTENSION_VALUE_ERROR);
+ X509V3_conf_err(val);
+ goto err;
+ }
+
+ OPENSSL_free(s);
+ s = NULL;