]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Fixup support for polymorphic attributes (maybe)
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 30 Oct 2014 14:35:54 +0000 (10:35 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 30 Oct 2014 14:37:36 +0000 (10:37 -0400)
src/include/libradius.h
src/lib/pair.c
src/lib/value.c
src/main/tmpl.c

index 89b3f8bf6bf7f83a7296c8a1031c73aea59ebbee..20bd1857043d9421f2d4af14338dad302cc88da4 100644 (file)
@@ -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);
 
 /*
index dedd918deb8da3c33fcb18953793ffd0b39f339a..9ea075a829bf2a3c98898dce42e27379d8d284e1 100644 (file)
@@ -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, "<INVALID>"), da->name);
+                       return -1;
+               }
+               vp->da = da;
+       }
+
        vp->length = ret;
        vp->type = VT_DATA;
 
index f16aba0f7d2d2b960c7bc0c67f7a60d9c70122fe..1bcbf6d6d5707fdb783e36d52ed2f83f3450939c 100644 (file)
@@ -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;
        }
 
index 9e0591e7c74d3e9bb8b2c4e83ddb74ac21cc64dd..452a8f3e672f427657e1f3f39ac2d64f1e79bf19 100644 (file)
@@ -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);