Skip to content

Commit

Permalink
Add tags and array references to value_pair_tmpl_t
Browse files Browse the repository at this point in the history
radius_parse_attr() parses them
radius_tmpl2str() prints them
condition.txt tests them
radius_vpt_get_vp() uses tag now, but not array ref

No other code has been updated. e.g. evaluate, etc.
  • Loading branch information
alandekok committed Apr 14, 2014
1 parent 0c7488f commit 17bdd5b
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 7 deletions.
2 changes: 2 additions & 0 deletions src/include/map.h
Expand Up @@ -126,6 +126,8 @@ typedef struct value_pair_tmpl_t {
pair_lists_t list; //!< List to search or insert in.

DICT_ATTR const *da; //!< Resolved dictionary attribute.
unsigned int num; //!< for array references
int8_t tag; //!< for tag references
value_data_t const *vpd; //!< actual data
size_t length; //!< of the vpd data
xlat_exp_t *xlat; //!< pre-parsed xlat_exp_t
Expand Down
87 changes: 83 additions & 4 deletions src/main/map.c
Expand Up @@ -65,9 +65,11 @@ void radius_tmplfree(value_pair_tmpl_t **tmpl)
*/
int radius_parse_attr(value_pair_tmpl_t *vpt, char const *name, request_refs_t request_def, pair_lists_t list_def)
{
DICT_ATTR const *da;
char const *p;
size_t len;
unsigned long num;
char *q;
DICT_ATTR const *da;

memset(vpt, 0, sizeof(*vpt));
vpt->name = name;
Expand All @@ -93,7 +95,7 @@ int radius_parse_attr(value_pair_tmpl_t *vpt, char const *name, request_refs_t r
return 0;
}

da = dict_attrbyname(p);
da = dict_attrbytagged_name(p);
if (!da) {
da = dict_attrunknownbyname(p, false);
if (!da) {
Expand All @@ -102,8 +104,60 @@ int radius_parse_attr(value_pair_tmpl_t *vpt, char const *name, request_refs_t r
}
}
vpt->da = da;

vpt->type = VPT_TYPE_ATTR;
vpt->tag = TAG_ANY;

while (*p) {
if (*p == ':') break;
if (*p == '[') break;
p++;
}

if (*p == ':') {
if (!da->flags.has_tag) {
fr_strerror_printf("Attribute '%s' cannot have a tag",
da->name);
return -1;
}

num = strtoul(p + 1, &q, 10);
if (num > 0x1f) {
fr_strerror_printf("Invalid tag value '%u'",
(unsigned int) num);
return -1;
}

if (num == 0) {
vpt->tag = TAG_ANY;
} else {
vpt->tag = num;
}
p = q;
}

if (!*p) return 0;

if (*p != '[') {
fr_strerror_printf("Unexpected text after tag in '%s'",
name);
return -1;
}

num = strtoul(p + 1, &q, 10);
if (num > 1000) {
fr_strerror_printf("Invalid array reference '%u'",
(unsigned int) num);
return -1;
}

if ((*q != ']') || (q[1] != '\0')) {
fr_strerror_printf("Unexpected text after array in '%s'",
name);
return -1;
}

vpt->num = num;

return 0;
}

Expand Down Expand Up @@ -553,6 +607,7 @@ int radius_attrmap(CONF_SECTION *cs, value_pair_map_t **head,
*/
size_t radius_tmpl2str(char *buffer, size_t bufsize, value_pair_tmpl_t const *vpt)
{
size_t len;
char c;
char const *p;
char *q = buffer;
Expand Down Expand Up @@ -609,7 +664,31 @@ size_t radius_tmpl2str(char *buffer, size_t bufsize, value_pair_tmpl_t const *vp
fr_int2str(pair_lists, vpt->list, ""),
vpt->da->name);
}
return strlen(buffer);

len = strlen(buffer);

if ((vpt->tag == TAG_ANY) && !vpt->num) {
return len;
}

q = buffer + len;
bufsize -= len;

if (vpt->tag != TAG_ANY) {
snprintf(q, bufsize, ":%d", vpt->tag);
len = strlen(q);
q += len;
bufsize -= len;
}

if (vpt->num) {
snprintf(q, bufsize, "[%u]", vpt->num);
len = strlen(q);
q += len;
bufsize -= len;
}

return (q - buffer);

case VPT_TYPE_DATA:
{
Expand Down
2 changes: 1 addition & 1 deletion src/main/valuepair.c
Expand Up @@ -1583,7 +1583,7 @@ VALUE_PAIR *radius_vpt_get_vp(REQUEST *request, value_pair_tmpl_t const *vpt)
* May not may not be found, but it *is* a known name.
*/
case VPT_TYPE_ATTR:
return pairfind(*vps, vpt->da->attr, vpt->da->vendor, TAG_ANY);
return pairfind(*vps, vpt->da->attr, vpt->da->vendor, vpt->tag);

case VPT_TYPE_LIST:
return *vps;
Expand Down
22 changes: 20 additions & 2 deletions src/tests/unit/condition.txt
Expand Up @@ -450,8 +450,26 @@ data <ipaddr>&Filter-Id == &Framed-IP-Address
condition <ipaddr>&Class == &Framed-IP-Address
data <ipaddr>&Class == &Framed-IP-Address

#
# Tags of zero get parsed and the tag gets ignored
#
condition &Tunnel-Password:0 == "Hello"
data ERROR offset 0 Unknown attribute
data &Tunnel-Password == "Hello"

condition &Tunnel-Password:1 == "Hello"
data &Tunnel-Password:1 == "Hello"

#
# zero offset into arrays get parsed and ignored
#
condition &User-Name[0] == "bob"
data ERROR offset 0 Unknown attribute
data &User-Name == "bob"

condition &User-Name[1] == "bob"
data &User-Name[1] == "bob"

condition &Tunnel-Password:1[0] == "Hello"
data &Tunnel-Password:1 == "Hello"

condition &Tunnel-Password:1[3] == "Hello"
data &Tunnel-Password:1[3] == "Hello"

0 comments on commit 17bdd5b

Please sign in to comment.