no tests. will do soon.
RETURN_OK(0);
}
-static size_t parse_typed_value(command_result_t *result, fr_value_box_t *box, char const **out, char const *in, size_t inlen)
+static size_t parse_typed_value(command_result_t *result, command_file_ctx_t *cc, fr_value_box_t *box, char const **out, char const *in, size_t inlen)
{
fr_type_t type;
size_t match_len;
ssize_t slen;
char const *p;
fr_sbuff_t sbuff;
+ fr_dict_attr_t const *enumv = NULL;
/*
* Parse data types
if (*p == '"'){
p++;
sbuff = FR_SBUFF_IN(p, strlen(p));
- slen = fr_value_box_from_substr(box, box, FR_TYPE_STRING, NULL,
+ slen = fr_value_box_from_substr(box, box, FR_TYPE_STRING, enumv,
&sbuff,
&value_parse_rules_double_quoted);
if (slen < 0) {
} else {
sbuff = FR_SBUFF_IN(p, strlen(p));
- slen = fr_value_box_from_substr(box, box, type, NULL,
+ /*
+ * We have no other way to pass the dict to the value-box parse function.
+ */
+ if (type == FR_TYPE_ATTR) {
+ fr_dict_t const *dict = dictionary_current(cc);
+
+ if (!dict) {
+ fr_strerror_const("proto-dictionary must be defined");
+ RETURN_PARSE_ERROR(0);
+ }
+
+ enumv = fr_dict_root(dict);
+ }
+
+ fprintf(stderr, "PARSE TYPE %s %p\n", fr_type_to_str(type), enumv);
+
+ slen = fr_value_box_from_substr(box, box, type, enumv,
&sbuff,
&value_parse_rules_bareword_unquoted);
if (slen < 0) {
p = in;
end = in + inlen;
- match_len = parse_typed_value(result, a, &value, p, end - p);
+ match_len = parse_typed_value(result, cc, a, &value, p, end - p);
if (match_len == 0) return 0; /* errors have already been updated */
p += match_len;
}
fr_skip_whitespace(p);
- match_len = parse_typed_value(result, b, &value, p, end - p);
+ match_len = parse_typed_value(result, cc, b, &value, p, end - p);
if (match_len == 0) return 0;
p += match_len;
a = talloc_zero(group, fr_value_box_t);
- match_len = parse_typed_value(result, a, &value, p, end - p);
+ match_len = parse_typed_value(result, cc, a, &value, p, end - p);
if (match_len == 0) return 0; /* errors have already been updated */
fr_value_box_list_insert_tail(&group->vb_group, a);
p = in;
end = in + inlen;
- match_len = parse_typed_value(result, a, &value, p, end - p);
+ match_len = parse_typed_value(result, cc, a, &value, p, end - p);
if (match_len == 0) return 0; /* errors have already been updated */
p += match_len;
ssize_t slen;
fr_type_t type;
- match_len = parse_typed_value(result, box, &value, in, strlen(in));
+ match_len = parse_typed_value(result, cc, box, &value, in, strlen(in));
if (match_len == 0) {
talloc_free(box);
return 0; /* errors have already been updated */
* box as last time.
*/
box2 = talloc_zero(NULL, fr_value_box_t);
- if (fr_value_box_from_str(box2, box2, type, NULL,
+ if (fr_value_box_from_str(box2, box2, type, box->enumv,
data, slen,
&fr_value_unescape_double) < 0) {
talloc_free(box2);
fr_strerror_const("Structural boxes not yet supported");
return -1;
+ case FR_TYPE_ATTR:
case FR_TYPE_INTERNAL:
fr_strerror_printf("Box type %s cannot be converted to string", fr_type_to_str(vb->type));
return -1;
case FR_TYPE_IPV4_PREFIX:
case FR_TYPE_IPV6_ADDR:
case FR_TYPE_IPV6_PREFIX:
+ case FR_TYPE_ATTR:
/*
* Printing prefixes etc. does NOT result in the escape function being called! So
* instead, we cast the results to a string, and then escape the string.
case FR_TYPE_FLOAT64:
return FR_HTRIE_RB;
+ case FR_TYPE_ATTR:
case FR_TYPE_NON_LEAF:
break;
}
#define vp_float32 data.vb_float32
#define vp_float64 data.vb_float64
+#define vp_attr data.vb_attr
+
#define vp_date data.vb_date
#define vp_time_delta data.vb_time_delta
{ L("vendor"), FR_TYPE_VENDOR },
{ L("group"), FR_TYPE_GROUP },
+ { L("attribute"), FR_TYPE_ATTR },
+
/*
* Alternative names
*/
[FR_TYPE_TIME_DELTA] = "fr_time_delta_t",
[FR_TYPE_SIZE] = "size_t",
[FR_TYPE_VALUE_BOX] = "fr_value_box_t",
+ [FR_TYPE_ATTR] = "fr_dict_attr_t *",
[FR_TYPE_VOID] = "void *",
[FR_TYPE_VALUE_BOX_CURSOR] = "fr_dcursor_t *",
[FR_TYPE_TIME_DELTA] = sizeof(fr_time_delta_t),
[FR_TYPE_SIZE] = sizeof(size_t),
[FR_TYPE_VALUE_BOX] = sizeof(fr_value_box_t),
+ [FR_TYPE_ATTR] = sizeof(fr_dict_attr_t *),
[FR_TYPE_VOID] = sizeof(void *),
[FR_TYPE_VALUE_BOX_CURSOR] = sizeof(void *),
FR_TYPE_GROUP, //!< A grouping of other attributes
FR_TYPE_VALUE_BOX, //!< A boxed value.
+ FR_TYPE_ATTR, //!< A contains an attribute reference
FR_TYPE_VOID, //!< User data. Should be a talloced chunk
///< assigned to the ptr value of the union.
#define FR_TYPE_LEAF_DEF(_beg, _mid, _end) \
_beg(FR_TYPE_ETHERNET) \
_mid(FR_TYPE_IFID) \
+ _mid(FR_TYPE_ATTR) \
FR_TYPE_IP_DEF(_mid, _mid, _mid) \
FR_TYPE_VARIABLE_SIZE_DEF(_mid, _mid, _mid) \
FR_TYPE_NUMERIC_DEF(_mid, _mid, _end)
case FR_TYPE_NULL: /* NULLs are not comparable */
return -2;
+ case FR_TYPE_ATTR:
+ return CMP(a->vb_attr, b->vb_attr);
+
/*
* These should be handled at some point
*/
}
break;
+ case FR_TYPE_ATTR:
+ {
+ fr_value_box_t tmp, base;
+
+ /*
+ * For now, we only encode at depth 1. The protocol-specific encoders need to do
+ * something special for attributes at other depths.
+ */
+ if (value->vb_attr->depth != 1) {
+ fr_strerror_printf("Unsupported depth '%u' for attribute %s",
+ value->vb_attr->depth, value->vb_attr->name);
+ return 0;
+ }
+
+ switch (value->vb_attr->flags.length) {
+ case 1:
+ fr_value_box_init(&base, FR_TYPE_UINT8, NULL, false);
+ base.vb_uint8 = value->vb_attr->attr;
+ break;
+
+ case 2:
+ fr_value_box_init(&base, FR_TYPE_UINT16, NULL, false);
+ base.vb_uint16 = value->vb_attr->attr;
+ break;
+
+ case 4:
+ fr_value_box_init(&base, FR_TYPE_UINT32, NULL, false);
+ base.vb_uint32 = value->vb_attr->attr;
+ break;
+
+ default:
+ fr_strerror_printf("Unsupported length '%d' for attribute %s",
+ value->vb_attr->flags.length, value->vb_attr->name);
+ return 0;
+ }
+
+ fr_value_box_hton(&tmp, &base);
+
+ FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(&tmp, tmp.type), min);
+ }
+ break;
+
/*
* Dates and deltas are stored internally as
* 64-bit nanoseconds. We have to convert to the
FR_DBUFF_OUT_RETURN(&dst->vb_float64, &work_dbuff);
break;
+ case FR_TYPE_ATTR:
+ fr_strerror_const("Unsupported ntoh from FR_TYPE_ATTR");
+ return 0;
+
/*
* Dates and deltas are stored internally as
* 64-bit nanoseconds. We have to convert from
}
break; /* use generic string/octets stuff below */
+ case FR_TYPE_ATTR:
+ if (src->vb_attr->depth != 1) {
+ fr_strerror_printf("Unsupported depth '%d' for attribute %s",
+ src->vb_attr->depth, src->vb_attr->name);
+ return 0;
+
+ }
+
+ /*
+ * Convert it to an integer of the correct lenght. Then, cast it in place.
+ */
+ switch (src->vb_attr->flags.length) {
+ case 1:
+ fr_value_box_init(dst, FR_TYPE_UINT8, NULL, false);
+ dst->vb_uint8 = src->vb_attr->attr;
+ break;
+
+ case 2:
+ fr_value_box_init(dst, FR_TYPE_UINT16, NULL, false);
+ dst->vb_uint16 = src->vb_attr->attr;
+ break;
+
+ case 4:
+ fr_value_box_init(dst, FR_TYPE_UINT32, NULL, false);
+ dst->vb_uint32 = src->vb_attr->attr;
+ break;
+
+ default:
+ fr_strerror_printf("Unsupported length '%d' for attribute %s",
+ src->vb_attr->flags.length, src->vb_attr->name);
+ return 0;
+ }
+
+ return fr_value_box_cast_in_place(ctx, dst, dst_type, dst_enumv);
+
/*
* Invalid types for casting (were caught earlier)
*/
fr_strerror_const("Unexpected value for data type NULL");
return -1;
+ case FR_TYPE_ATTR:
+ if (!dst_enumv) {
+ fr_strerror_const("No dictionary passed for data type 'attr'");
+ return -1;
+ }
+
+ if (!dst_enumv->flags.is_root) {
+ fr_strerror_const("Can only start from dictioanry root for data type 'attr'");
+ return -1;
+ }
+
+ if (!fr_sbuff_next_if_char(&our_in, '@')) {
+ fr_strerror_const("Expected '@...' for attribute reference");
+ return -1;
+ }
+
+ fr_value_box_init(dst, dst_type, dst_enumv, false);
+
+ slen = fr_dict_attr_by_name_substr(NULL, &dst->vb_attr, dst_enumv, &our_in, rules->terminals);
+ if (slen <= 0) {
+ fr_strerror_printf("Failed to find the named attribute in %s", dst_enumv->name);
+ return -2;
+ }
+ fr_assert(dst->vb_attr != NULL);
+
+ FR_SBUFF_SET_RETURN(in, &our_in);
+
/*
* Dealt with below
*/
FR_SBUFF_IN_CHAR_RETURN(&our_out, '}');
break;
+ case FR_TYPE_ATTR:
+ if (data->vb_attr->depth != 1) {
+ fr_strerror_printf("Unsupported depth '%u' for attribute %s",
+ data->vb_attr->depth, data->vb_attr->name);
+ return 0;
+ }
+
+ FR_SBUFF_IN_CHAR_RETURN(&our_out, '@');
+ FR_SBUFF_IN_ESCAPE_RETURN(&our_out, data->vb_attr->name,
+ strlen(data->vb_attr->name), e_rules);
+ break;
+
case FR_TYPE_NULL:
FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "NULL");
break;
};
struct {
- void * _CONST cursor; //!< cursors
- char const * _CONST name; //!< name of the current cursor
+ void * _CONST cursor; //!< cursors
+ char const * _CONST name; //!< name of the current cursor
+ fr_dict_attr_t const * _CONST da; //!< dictionary reference
};
/*
#define vb_octets datum.octets
#define vb_void datum.ptr
#define vb_group datum.children
+#define vb_attr datum.da
#define vb_ip datum.ip
lua_pushinteger(L, (lua_Integer)vp->vp_size);
break;
+ case FR_TYPE_ATTR:
case FR_TYPE_NON_LEAF:
REDEBUG("Cannot convert %s to Lua type", fr_type_to_str(vp->vp_type));
return -1;
return value;
}
- default:
- fr_assert(0);
+ case FR_TYPE_ATTR:
+ case FR_TYPE_NON_LEAF:
+ REDEBUG("Cannot convert %s to ruby type", fr_type_to_str(vp->vp_type));
break;
}
+
return mrb_nil_value();
}
PERLINT(32)
PERLINT(64)
+
+ case FR_TYPE_SIZE:
+ *value = sv_2mortal(newSVuv(vp->vp_size));
+ break;
+
case FR_TYPE_BOOL:
*value = sv_2mortal(newSVuv(vp->vp_bool));
break;
break;
/* Only leaf nodes should be able to call this */
- default:
- fr_assert(0);
+ case FR_TYPE_ATTR:
+ case FR_TYPE_NON_LEAF:
+ croak("Cannot convert %s to Perl type", fr_type_to_str(vp->vp_type));
return -1;
}
case FR_TYPE_COMBO_IP_ADDR:
case FR_TYPE_COMBO_IP_PREFIX:
case FR_TYPE_ETHERNET:
+ case FR_TYPE_ATTR:
{
ssize_t slen;
char buffer[1024];
case FR_TYPE_COMBO_IP_ADDR:
case FR_TYPE_COMBO_IP_PREFIX:
case FR_TYPE_ETHERNET:
+ case FR_TYPE_ATTR:
{
char const *val;
ssize_t len;