From: Arran Cudbard-Bell Date: Thu, 30 Oct 2014 14:35:54 +0000 (-0400) Subject: Fixup support for polymorphic attributes (maybe) X-Git-Tag: branch_3_1_x~4835 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b3d63dc4c40e7c61d6200a2daee291410ea66e7f;p=thirdparty%2Ffreeradius-server.git Fixup support for polymorphic attributes (maybe) --- diff --git a/src/include/libradius.h b/src/include/libradius.h index 89b3f8bf6bf..20bd1857043 100644 --- a/src/include/libradius.h +++ b/src/include/libradius.h @@ -660,7 +660,7 @@ int value_data_cmp_op(FR_TOKEN op, PW_TYPE b_type, size_t b_length, value_data_t const *b); ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *out, - PW_TYPE type, DICT_ATTR const *enumv, + PW_TYPE *type, DICT_ATTR const *enumv, char const *value, ssize_t inlen); /* diff --git a/src/lib/pair.c b/src/lib/pair.c index dedd918deb8..9ea075a829b 100644 --- a/src/lib/pair.c +++ b/src/lib/pair.c @@ -1104,14 +1104,32 @@ void pairfilter(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned in int pairparsevalue(VALUE_PAIR *vp, char const *value, size_t inlen) { ssize_t ret; - + PW_TYPE type; VERIFY_VP(vp); if (!value) return -1; - ret = value_data_from_str(vp, &vp->data, vp->da->type, vp->da, value, inlen); + type = vp->da->type; + + ret = value_data_from_str(vp, &vp->data, &type, vp->da, value, inlen); if (ret < 0) return -1; + /* + * If we parsed to a different type than the DA associated with + * the VALUE_PAIR we now need to fixup the DA. + */ + if (type != vp->da->type) { + DICT_ATTR const *da; + + da = dict_attrbytype(vp->da->attr, vp->da->vendor, type); + if (!da) { + fr_strerror_printf("Cannot find %s variant of attribute \"%s\"", + fr_int2str(dict_attr_types, type, ""), da->name); + return -1; + } + vp->da = da; + } + vp->length = ret; vp->type = VT_DATA; diff --git a/src/lib/value.c b/src/lib/value.c index f16aba0f7d2..1bcbf6d6d57 100644 --- a/src/lib/value.c +++ b/src/lib/value.c @@ -412,17 +412,17 @@ static char const hextab[] = "0123456789abcdef"; /** Convert string value to a value_data_t type * - * @param ctx to alloc strings in. - * @param out where to write parsed value. - * @param type of value data to create. - * @param enumv DICT_ATTR with string aliases for integer values. - * @param value String to convert. Binary safe for variable length values if len is provided. - * @param inlen may be < 0 in which case strlen(len) is used to determine length, else inlen + * @param[in] ctx to alloc strings in. + * @param[out] out where to write parsed value. + * @param[in,out] type of value data to create/type of value created. + * @param[in] enumv DICT_ATTR with string aliases for integer values. + * @param[in] value String to convert. Binary safe for variable length values if len is provided. + * @param[in] inlen may be < 0 in which case strlen(len) is used to determine length, else inlen * should be the length of the string or sub string to parse. * @return length of data written to out or -1 on parse error. */ ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *out, - PW_TYPE type, DICT_ATTR const *enumv, + PW_TYPE *type, DICT_ATTR const *enumv, char const *value, ssize_t inlen) { DICT_VALUE *dval; @@ -437,13 +437,13 @@ ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *out, /* * Set size for all fixed length attributes. */ - ret = dict_attr_sizes[type][1]; /* Max length */ + ret = dict_attr_sizes[*type][1]; /* Max length */ /* * It's a variable ret type so we just alloc a new buffer * of size len and copy. */ - switch (type) { + switch (*type) { case PW_TYPE_STRING: { size_t p_len; @@ -692,7 +692,7 @@ ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *out, value = buffer; } - switch(type) { + switch(*type) { case PW_TYPE_BYTE: { char *p; @@ -881,31 +881,20 @@ ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *out, */ case PW_TYPE_IP_ADDR: { - DICT_ATTR const *da; - if (inet_pton(AF_INET6, value, &out->ipv6addr) > 0) { - da = dict_attrbytype(enumv->attr, enumv->vendor, PW_TYPE_IPV6_ADDR); - if (!da) { - fr_strerror_printf("Cannot find ipv6addr for %s", enumv->name); - return -1; - } - ret = dict_attr_sizes[PW_TYPE_IP_ADDR][1]; /* ret of IPv6 address */ + *type = PW_TYPE_IPV6_ADDR; + ret = dict_attr_sizes[PW_TYPE_IP_ADDR][1]; /* size of IPv6 address */ } else { fr_ipaddr_t ipaddr; - da = dict_attrbytype(enumv->attr, enumv->vendor, PW_TYPE_IPV4_ADDR); - if (!da) { - fr_strerror_printf("Cannot find ipaddr for %s", enumv->name); - return -1; - } - if (ip_hton(&ipaddr, AF_INET, value, false) < 0) { fr_strerror_printf("Failed to find IPv4 address for %s", value); return -1; } + *type = PW_TYPE_IPV4_ADDR; out->ipaddr.s_addr = ipaddr.ipaddr.ip4addr.s_addr; - ret = dict_attr_sizes[PW_TYPE_IP_ADDR][0]; + ret = dict_attr_sizes[PW_TYPE_IP_ADDR][0]; /* size of IPv4 address */ } } break; @@ -919,7 +908,7 @@ ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *out, * Anything else. */ default: - fr_strerror_printf("unknown attribute type %d", type); + fr_strerror_printf("Unknown attribute type %d", *type); return -1; } diff --git a/src/main/tmpl.c b/src/main/tmpl.c index 9e0591e7c74..452a8f3e672 100644 --- a/src/main/tmpl.c +++ b/src/main/tmpl.c @@ -1228,6 +1228,7 @@ bool tmpl_cast_in_place(value_pair_tmpl_t *vpt, DICT_ATTR const *da) { value_data_t *data; ssize_t ret; + PW_TYPE type; VERIFY_TMPL(vpt); @@ -1235,8 +1236,13 @@ bool tmpl_cast_in_place(value_pair_tmpl_t *vpt, DICT_ATTR const *da) rad_assert(da != NULL); rad_assert(vpt->type == TMPL_TYPE_LITERAL); + vpt->tmpl_data_type = da->type; + data = talloc_zero(vpt, value_data_t); - ret = value_data_from_str(vpt, data, da->type, da, vpt->name, vpt->len); + /* + * Why do we pass a pointer to the tmpl type? Goddamn WiMAX. + */ + ret = value_data_from_str(vpt, data, &vpt->tmpl_data_type, da, vpt->name, vpt->len); if (ret < 0) { talloc_free(data); return false; @@ -1245,7 +1251,6 @@ bool tmpl_cast_in_place(value_pair_tmpl_t *vpt, DICT_ATTR const *da) vpt->type = TMPL_TYPE_DATA; vpt->tmpl_data_value = data; vpt->tmpl_data_length = (size_t) ret; - vpt->tmpl_data_type = da->type; VERIFY_TMPL(vpt);