#define is_truncated(_ret, _max) ((_ret) >= (_max))
#define truncate_len(_ret, _max) (((_ret) >= (_max)) ? ((_max) - 1) : _ret)
+size_t vp_data_prints_value(char *out, size_t outlen,
+ DICT_ATTR const *da, value_data_t const *data, size_t data_len, int8_t quote);
size_t vp_prints_value(char *out, size_t outlen, VALUE_PAIR const *vp, int8_t quote);
size_t vp_prints_value_json(char *out, size_t outlen, VALUE_PAIR const *vp);
size_t vp_prints(char *out, size_t outlen, VALUE_PAIR const *vp);
bool pairvalidate(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list);
bool pairvalidate_relaxed(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list);
VALUE_PAIR *paircopyvp(TALLOC_CTX *ctx, VALUE_PAIR const *vp);
-VALUE_PAIR *paircopyvpdata(TALLOC_CTX *ctx, DICT_ATTR const *da, VALUE_PAIR const *vp);
VALUE_PAIR *paircopy(TALLOC_CTX *ctx, VALUE_PAIR *from);
VALUE_PAIR *paircopy2(TALLOC_CTX *ctx, VALUE_PAIR *from, unsigned int attr, unsigned int vendor, int8_t tag);
VALUE_PAIR *pairsteal(TALLOC_CTX *ctx, VALUE_PAIR *from);
void pairstrsteal(VALUE_PAIR *vp, char const *src);
void pairstrcpy(VALUE_PAIR *vp, char const * src);
void pairstrncpy(VALUE_PAIR *vp, char const * src, size_t len);
+int pairdatacpy(VALUE_PAIR *vp, DICT_ATTR const *da, value_data_t const *data, size_t len);
void pairsprintf(VALUE_PAIR *vp, char const * fmt, ...) CC_HINT(format (printf, 2, 3));
void pairmove(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from);
void pairfilter(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from,
#ifdef WITH_ASCEND_BINARY
/* filters.c */
int ascend_parse_filter(VALUE_PAIR *vp, char const *value, size_t len);
-void print_abinary(char *out, size_t outlen, VALUE_PAIR const *vp, int8_t quote);
+void print_abinary(char *out, size_t outlen, uint8_t const *data, size_t len, int8_t quote);
#endif /*WITH_ASCEND_BINARY*/
/* random numbers in isaac.c */
* Note we don't bother checking 'len' after the snprintf's.
* This function should ONLY be called with a large (~1k) buffer.
*/
-void print_abinary(char *out, size_t outlen, VALUE_PAIR const *vp, int8_t quote)
+void print_abinary(char *out, size_t outlen, uint8_t const *data, size_t len, int8_t quote)
{
size_t i;
char *p;
- ascend_filter_t *filter;
+ ascend_filter_t const *filter;
static char const *action[] = {"drop", "forward"};
static char const *direction[] = {"out", "in"};
/*
* Just for paranoia: wrong size filters get printed as octets
*/
- if (vp->length != sizeof(*filter)) {
- uint8_t *f = (uint8_t *) &vp->vp_filter;
-
+ if (len != sizeof(*filter)) {
strcpy(p, "0x");
p += 2;
outlen -= 2;
- for (i = 0; i < vp->length; i++) {
- snprintf(p, outlen, "%02x", f[i]);
+ for (i = 0; i < len; i++) {
+ snprintf(p, outlen, "%02x", data[i]);
p += 2;
outlen -= 2;
}
outlen -= 3; /* account for leading & trailing quotes */
}
- filter = (ascend_filter_t *) &(vp->vp_filter);
+ filter = (ascend_filter_t const *) data;
i = snprintf(p, outlen, "%s %s %s", fr_int2str(filterType, filter->type, "??"),
direction[filter->direction & 0x01], action[filter->forward & 0x01]);
if (filter->u.ip.srcip) {
i = snprintf(p, outlen, " srcip %d.%d.%d.%d/%d",
- ((uint8_t *) &filter->u.ip.srcip)[0],
- ((uint8_t *) &filter->u.ip.srcip)[1],
- ((uint8_t *) &filter->u.ip.srcip)[2],
- ((uint8_t *) &filter->u.ip.srcip)[3],
+ ((uint8_t const *) &filter->u.ip.srcip)[0],
+ ((uint8_t const *) &filter->u.ip.srcip)[1],
+ ((uint8_t const *) &filter->u.ip.srcip)[2],
+ ((uint8_t const *) &filter->u.ip.srcip)[3],
filter->u.ip.srcmask);
p += i;
outlen -= i;
if (filter->u.ip.dstip) {
i = snprintf(p, outlen, " dstip %d.%d.%d.%d/%d",
- ((uint8_t *) &filter->u.ip.dstip)[0],
- ((uint8_t *) &filter->u.ip.dstip)[1],
- ((uint8_t *) &filter->u.ip.dstip)[2],
- ((uint8_t *) &filter->u.ip.dstip)[3],
+ ((uint8_t const *) &filter->u.ip.dstip)[0],
+ ((uint8_t const *) &filter->u.ip.dstip)[1],
+ ((uint8_t const *) &filter->u.ip.dstip)[2],
+ ((uint8_t const *) &filter->u.ip.dstip)[3],
filter->u.ip.dstmask);
p += i;
outlen -= i;
return outlen;
}
-
/** Print the value of an attribute to a string
*
- * @param[out] out Where to write the string.
- * @param[in] outlen Size of outlen (must be at least 3 bytes).
- * @param[in] vp to print.
- * @param[in] quote Char to add before and after printed value, if 0 no char will be added, if < 0 raw string will be
- * added.
- * @return the length of data written to out, or a value >= outlen on truncation.
*/
-size_t vp_prints_value(char *out, size_t outlen, VALUE_PAIR const *vp, int8_t quote)
+size_t vp_data_prints_value(char *out, size_t outlen,
+ DICT_ATTR const *da, value_data_t const *data, size_t data_len, int8_t quote)
{
DICT_VALUE *v;
char buf[1024]; /* Interim buffer to use with poorly behaved printing functions */
size_t len = 0, freespace = outlen;
- if (!vp) return 0;
-
- VERIFY_VP(vp);
-
- if (outlen == 0) return vp->length;
+ if (!data) return 0;
+ if (outlen == 0) return data_len;
*out = '\0';
- switch (vp->da->type) {
+ switch (da->type) {
case PW_TYPE_STRING:
/* need to copy the escaped value, but quoted */
if (quote > 0) {
if (freespace < 3) {
- return vp->length + 2;
+ return data_len + 2;
}
*out++ = (char) quote;
freespace--;
- len = fr_print_string(vp->vp_strvalue, vp->length, out, freespace);
+ len = fr_print_string(data->strvalue, data_len, out, freespace);
/* always terminate the quoted string with another quote */
if (len >= (freespace - 1)) {
out[outlen - 2] = (char) quote;
/* xlat.c - need to copy raw value verbatim */
else if (quote < 0) {
- if (outlen > vp->length) {
- memcpy(out, vp->vp_strvalue, vp->length + 1);
- return vp->length;
+ if (outlen > data_len) {
+ memcpy(out, data->strvalue, data_len + 1);
+ return data_len;
}
- memcpy(out, vp->vp_strvalue, outlen);
+ memcpy(out, data->strvalue, outlen);
out[outlen - 1] = '\0';
- return vp->length; /* not a typo */
+ return data_len; /* not a typo */
}
- return fr_print_string(vp->vp_strvalue, vp->length, out, outlen);
+ return fr_print_string(data->strvalue, data_len, out, outlen);
case PW_TYPE_INTEGER:
- if (vp->da->flags.has_tag) {
- /* Attribute value has a tag, need to ignore it */
- if ((v = dict_valbyattr(vp->da->attr, vp->da->vendor, (vp->vp_integer & 0xffffff))) != NULL) {
- a = v->name;
- len = strlen(a);
- } else {
- /* should never be truncated */
- len = snprintf(buf, sizeof(buf), "%u", (vp->vp_integer & 0xffffff));
- a = buf;
- }
- } else {
case PW_TYPE_BYTE:
case PW_TYPE_SHORT:
- /* Normal, non-tagged attribute */
- if ((v = dict_valbyattr(vp->da->attr, vp->da->vendor, vp->vp_integer)) != NULL) {
- a = v->name;
- len = strlen(a);
- } else {
- /* should never be truncated */
- len = snprintf(buf, sizeof(buf), "%u", vp->vp_integer);
- a = buf;
- }
+ /* Normal, non-tagged attribute */
+ if ((v = dict_valbyattr(da->attr, da->vendor, data->integer)) != NULL) {
+ a = v->name;
+ len = strlen(a);
+ } else {
+ /* should never be truncated */
+ len = snprintf(buf, sizeof(buf), "%u", data->integer);
+ a = buf;
}
break;
case PW_TYPE_INTEGER64:
- return snprintf(out, outlen, "%" PRIu64, vp->vp_integer64);
+ return snprintf(out, outlen, "%" PRIu64, data->integer64);
case PW_TYPE_DATE:
- t = vp->vp_date;
+ t = data->date;
if (quote > 0) {
len = strftime(buf, sizeof(buf) - 1, "%%%b %e %Y %H:%M:%S %Z%%", localtime_r(&t, &s_tm));
buf[0] = (char) quote;
break;
case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
- len = snprintf(buf, sizeof(buf), "%d", vp->vp_signed);
+ len = snprintf(buf, sizeof(buf), "%d", data->sinteger);
a = buf;
break;
case PW_TYPE_IPV4_ADDR:
- a = inet_ntop(AF_INET, &(vp->vp_ipaddr), buf, sizeof(buf));
+ a = inet_ntop(AF_INET, &(data->ipaddr), buf, sizeof(buf));
len = strlen(buf);
break;
case PW_TYPE_ABINARY:
#ifdef WITH_ASCEND_BINARY
-
- print_abinary(buf, sizeof(buf), vp, quote);
+ print_abinary(buf, sizeof(buf), (uint8_t const *) data->filter, len, quote);
a = buf;
len = strlen(buf);
break;
size_t max;
/* Return the number of bytes we would have written */
- len = (vp->length * 2) + 2;
+ len = (data_len * 2) + 2;
if (freespace <= 1) {
return len;
}
/* Get maximum number of bytes we can encode given freespace */
max = ((freespace % 2) ? freespace - 1 : freespace - 2) / 2;
- fr_bin2hex(out, vp->vp_octets, (vp->length > max) ? max : vp->length);
-
- return len;
+ fr_bin2hex(out, data->octets, (data_len > max) ? max : data_len);
}
- break;
+ return len;
case PW_TYPE_IFID:
- a = ifid_ntoa(buf, sizeof(buf), vp->vp_ifid);
+ a = ifid_ntoa(buf, sizeof(buf), data->ifid);
len = strlen(buf);
break;
case PW_TYPE_IPV6_ADDR:
- a = inet_ntop(AF_INET6, &vp->vp_ipv6addr, buf, sizeof(buf));
+ a = inet_ntop(AF_INET6, &data->ipv6addr, buf, sizeof(buf));
len = strlen(buf);
break;
/*
* Alignment issues.
*/
- memcpy(&addr, &(vp->vp_ipv6prefix[2]), sizeof(addr));
+ memcpy(&addr, &(data->ipv6prefix[2]), sizeof(addr));
a = inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
if (a) {
len = strlen(buf);
p += len;
- len += snprintf(p, sizeof(buf) - len, "/%u", (unsigned int) vp->vp_ipv6prefix[1]);
+ len += snprintf(p, sizeof(buf) - len, "/%u", (unsigned int) data->ipv6prefix[1]);
}
}
break;
/*
* Alignment issues.
*/
- memcpy(&addr, &(vp->vp_ipv4prefix[2]), sizeof(addr));
+ memcpy(&addr, &(data->ipv4prefix[2]), sizeof(addr));
a = inet_ntop(AF_INET, &addr, buf, sizeof(buf));
if (a) {
len = strlen(buf);
p += len;
- len += snprintf(p, sizeof(buf) - len, "/%u", (unsigned int) (vp->vp_ipv4prefix[1] & 0x3f));
+ len += snprintf(p, sizeof(buf) - len, "/%u", (unsigned int) (data->ipv4prefix[1] & 0x3f));
}
}
break;
case PW_TYPE_ETHERNET:
return snprintf(out, outlen, "%02x:%02x:%02x:%02x:%02x:%02x",
- vp->vp_ether[0], vp->vp_ether[1],
- vp->vp_ether[2], vp->vp_ether[3],
- vp->vp_ether[4], vp->vp_ether[5]);
+ data->ether[0], data->ether[1],
+ data->ether[2], data->ether[3],
+ data->ether[4], data->ether[5]);
default:
a = "UNKNOWN-TYPE";
return len; /* Return the number of bytes we would of written (for truncation detection) */
}
+/** Print the value of an attribute to a string
+ *
+ * @param[out] out Where to write the string.
+ * @param[in] outlen Size of outlen (must be at least 3 bytes).
+ * @param[in] vp to print.
+ * @param[in] quote Char to add before and after printed value, if 0 no char will be added, if < 0 raw string will be
+ * added.
+ * @return the length of data written to out, or a value >= outlen on truncation.
+ */
+size_t vp_prints_value(char *out, size_t outlen, VALUE_PAIR const *vp, int8_t quote)
+{
+ return vp_data_prints_value(out, outlen, vp->da, &vp->data, vp->length, quote);
+}
+
char *vp_aprint_type(TALLOC_CTX *ctx, PW_TYPE type)
{
switch (type) {
#ifdef WITH_ASCEND_BINARY
p = talloc_array(ctx, char, 128);
if (!p) return NULL;
- print_abinary(p, 128, vp, 0);
+ print_abinary(p, 128, (uint8_t *) *vp->vp_filter, vp->length, 0);
break;
#else
/* FALL THROUGH */
return n;
}
-/** Copy data from one VP to another
- *
- * Allocate a new pair using da, and copy over the value from the specified
- * vp.
- *
- * @todo Should be able to do type conversions.
- *
- * @param[in] ctx for talloc
- * @param[in] da of new attribute to alloc.
- * @param[in] vp to copy data from.
- * @return the new valuepair.
- */
-VALUE_PAIR *paircopyvpdata(TALLOC_CTX *ctx, DICT_ATTR const *da, VALUE_PAIR const *vp)
-{
- VALUE_PAIR *n;
-
- if (!vp) return NULL;
-
- VERIFY_VP(vp);
-
- /*
- * The types have to be identical, OR the "from" VP has
- * to be octets.
- */
- if (da->type != vp->da->type) {
- int length;
- uint8_t *p;
- VALUE_PAIR const **pvp;
-
- if (vp->da->type == PW_TYPE_OCTETS) {
- /*
- * Decode the octets buffer using the RADIUS decoder.
- */
- if (data2vp(ctx, NULL, NULL, NULL, da, vp->vp_octets, vp->length, vp->length, &n) < 0) {
- return NULL;
- }
-
- n->type = VT_DATA;
- return n;
- }
-
- /*
- * Else the destination type is octets
- */
- switch (vp->da->type) {
- default:
- return NULL; /* can't do it */
-
- case PW_TYPE_INTEGER:
- case PW_TYPE_IPV4_ADDR:
- case PW_TYPE_DATE:
- case PW_TYPE_IFID:
- case PW_TYPE_IPV6_ADDR:
- case PW_TYPE_IPV6_PREFIX:
- case PW_TYPE_BYTE:
- case PW_TYPE_SHORT:
- case PW_TYPE_ETHERNET:
- case PW_TYPE_SIGNED:
- case PW_TYPE_INTEGER64:
- case PW_TYPE_IPV4_PREFIX:
- break;
- }
-
- n = pairalloc(ctx, da);
- if (!n) return NULL;
-
- p = talloc_array(n, uint8_t, dict_attr_sizes[vp->da->type][1] + 2);
-
- pvp = &vp;
- length = rad_vp2attr(NULL, NULL, NULL, pvp, p, dict_attr_sizes[vp->da->type][1]);
- if (length < 0) {
- pairfree(&n);
- return NULL;
- }
-
- pairmemcpy(n, p + 2, length - 2);
- talloc_free(p);
- return n;
- }
-
- n = pairalloc(ctx, da);
- if (!n) return NULL;
-
- memcpy(n, vp, sizeof(*n));
- n->da = da;
-
- if (n->type == VT_XLAT) {
- n->value.xlat = talloc_typed_strdup(n, n->value.xlat);
- }
-
- if (n->data.ptr) switch (n->da->type) {
- case PW_TYPE_TLV:
- case PW_TYPE_OCTETS:
- n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
- talloc_set_type(n->vp_octets, uint8_t);
- break;
-
- case PW_TYPE_STRING:
- n->vp_strvalue = talloc_memdup(n, vp->vp_strvalue, n->length + 1); /* NULL byte */
- talloc_set_type(n->vp_strvalue, char);
- break;
-
- default:
- break;
- }
-
- n->next = NULL;
-
- return n;
-}
-
-
/** Copy a pairlist.
*
* Copy all pairs from 'from' regardless of tag, attribute or vendor.
pairtypeset(vp);
}
+/** Copy data from one VP to another
+ *
+ * Allocate a new pair using da, and copy over the value from the specified vp.
+ *
+ * @todo Should be able to do type conversions.
+ *
+ * @param[in,out] vp to update.
+ * @param[in] da Type of data represented by data.
+ * @param[in] data to copy.
+ * @param[in] len of data to copy.
+ */
+int pairdatacpy(VALUE_PAIR *vp, DICT_ATTR const *da, value_data_t const *data, size_t len)
+{
+ void *old;
+ VERIFY_VP(vp);
+
+ /*
+ * The da->types have to be identical, OR the "from" da->type has
+ * to be octets.
+ */
+ if (vp->da->type != da->type) {
+ /*
+ * Decode the octets buffer using the RADIUS decoder.
+ */
+ if (da->type == PW_TYPE_OCTETS) {
+ if (data2vp(vp, NULL, NULL, NULL, vp->da, data->octets, len, len, &vp) < 0) return -1;
+ vp->type = VT_DATA;
+ return 0;
+ }
+
+ /*
+ * Else if the destination da->type is octets
+ */
+ if (vp->da->type == PW_TYPE_OCTETS) {
+ int ret;
+ uint8_t *buff;
+ VALUE_PAIR const *pvp = vp;
+
+ buff = talloc_array(vp, uint8_t, dict_attr_sizes[da->type][1] + 2);
+
+ ret = rad_vp2rfc(NULL, NULL, NULL, &pvp, buff, dict_attr_sizes[da->type][1]);
+ if (ret < 0) return -1;
+
+ pairmemcpy(vp, buff + 2, ret - 2);
+ talloc_free(buff);
+
+ return 0;
+ }
+
+ /*
+ * Fixme...
+ */
+ fr_strerror_printf("Data conversion not supported");
+ return -1;
+ }
+
+ /*
+ * Clear existing value if there is one
+ */
+ memcpy(&old, &vp->data.ptr, sizeof(old));
+ talloc_free(old);
+
+ switch (vp->da->type) {
+ case PW_TYPE_TLV:
+ case PW_TYPE_OCTETS:
+ pairmemcpy(vp, data->octets, len);
+ break;
+
+ case PW_TYPE_STRING:
+ pairstrncpy(vp, data->strvalue, len);
+ break;
+
+ default:
+ memcpy(&vp->data, data, sizeof(vp->data));
+ break;
+ }
+ vp->length = len;
+
+ return 0;
+}
+
/** Print data into an "string" data type.
*
* @param[in,out] vp to update
if (vpt->type == VPT_TYPE_DATA) {
rad_assert(vp->da->type == vpt->vpt_da->type);
- memcpy(&vp->data, vpt->vpt_value, sizeof(vp->data));
- vp->length = vpt->vpt_length;
+ pairdatacpy(vp, vpt->vpt_da, vpt->vpt_value, vpt->vpt_length);
return vp;
}
return NULL;
}
- if ((pairparsevalue(vp, str, 0) < 0)) {
+ if (pairparsevalue(vp, str, 0) < 0) {
talloc_free(str);
pairfree(&vp);
return NULL;
case VPT_TYPE_DATA:
if (vpt->vpt_value) {
- VALUE_PAIR *vp;
- TALLOC_CTX *ctx;
-
- memcpy(&ctx, &vpt, sizeof(ctx)); /* hack */
-
- MEM(vp = pairalloc(ctx, vpt->vpt_da));
- memcpy(&vp->data, vpt->vpt_value, sizeof(vp->data));
- vp->length = vpt->vpt_length;
-
- q = vp_aprint_value(vp, vp);
-
- if ((vpt->vpt_da->type != PW_TYPE_STRING) &&
- (vpt->vpt_da->type != PW_TYPE_DATE)) {
- strlcpy(buffer, q, bufsize);
- } else {
- /*
- * FIXME: properly escape the string...
- */
- snprintf(buffer, bufsize, "\"%s\"", q);
- }
-
- talloc_free(q);
- pairfree(&vp);
- return strlen(buffer);
-
+ return vp_data_prints_value(buffer, bufsize, vpt->vpt_da,
+ vpt->vpt_value, vpt->vpt_length, '"');
} else {
*buffer = '\0';
return 0;
return q - buffer;
}
-
/** Print a map to a string
*
* @param[out] buffer for the output string
case VPT_TYPE_XLAT_STRUCT:
case VPT_TYPE_LITERAL:
case VPT_TYPE_DATA:
+ case VPT_TYPE_ATTR:
vp = pairalloc(request, da);
if (!vp) return -1;
vp->op = map->op;
}
/*
- * Copy the data over verbatim, assuming it's
- * actually data.
+ * Copy the data over verbatim
*/
- vp = paircopyvpdata(request, da, found);
- if (!vp) {
- return -1;
- }
+ if (pairdatacpy(vp, found->da, &found->data, found->length) < 0) return -1;
vp->op = map->op;
break;
rad_assert(map->src && map->src->vpt_da);
rad_assert(map->dst && map->dst->vpt_da);
rad_assert(map->src->vpt_da->type == map->dst->vpt_da->type);
- memcpy(&vp->data, map->src->vpt_value, sizeof(vp->data));
- vp->length = map->src->vpt_length;
+
+ if (pairdatacpy(vp, map->src->vpt_da, map->src->vpt_value, map->src->vpt_length) < 0) goto error;
+ vp->op = map->op;
break;
/*