The rlm_dhcpv4 provides the below xlat's functions to handle the DHCPV4 packets.
-### %{dhcpv4_decode:...}
+### %(dhcpv4_decode:...)
Decode DHCP option declared in dictionary.rfc2131.
update request {
&Tmp-Octets-0 := 0x520d0103abcdef0206010203040506
}
-if ("%{dhcpv4_decode:%{Tmp-Octets-0}}" != 2) {
+if ("%(dhcpv4_decode:%{Tmp-Octets-0})" != 2) {
update reply {
&Reply-Message := "Problems decoding the DHPCv4 fields."
}
"The value of Relay-Agent-Information.Circuit-ID=0xabcdef, Relay-Agent-Information.Remote-ID=0x010203040506"
```
-### %{dhcpv4_encode:...}
+### %(dhcpv4_encode:...)
Encode DHCP option declared in dictionary.rfc2131.
&Relay-Agent-Information.Remote-ID := 0x010203040506
}
update request {
- &Tmp-Octets-0 := "%{dhcpv4_encode:&request[*]}"
+ &Tmp-Octets-0 := "%(dhcpv4_encode:&request[*])"
}
if (&Tmp-Octets-0 != 0x520d0103abcdef0206010203040506) {
update reply {
#
# The rlm_dhcpv4 provides the below xlat's functions to handle the DHCPV4 packets.
#
-# ### %{dhcpv4_decode:...}
+# ### %(dhcpv4_decode:...)
#
# Decode DHCP option declared in dictionary.rfc2131.
#
# update request {
# &Tmp-Octets-0 := 0x520d0103abcdef0206010203040506
# }
-# if ("%{dhcpv4_decode:%{Tmp-Octets-0}}" != 2) {
+# if ("%(dhcpv4_decode:%{Tmp-Octets-0})" != 2) {
# update reply {
# &Reply-Message := "Problems decoding the DHPCv4 fields."
# }
# "The value of Relay-Agent-Information.Circuit-ID=0xabcdef, Relay-Agent-Information.Remote-ID=0x010203040506"
# ```
#
-# ### %{dhcpv4_encode:...}
+# ### %(dhcpv4_encode:...)
#
# Encode DHCP option declared in dictionary.rfc2131.
#
# &Relay-Agent-Information.Remote-ID := 0x010203040506
# }
# update request {
-# &Tmp-Octets-0 := "%{dhcpv4_encode:&request[*]}"
+# &Tmp-Octets-0 := "%(dhcpv4_encode:&request[*])"
# }
# if (&Tmp-Octets-0 != 0x520d0103abcdef0206010203040506) {
# update reply {
int xlat_fmt_get_vp(fr_pair_t **out, request_t *request, char const *name);
-int xlat_fmt_to_cursor(TALLOC_CTX *ctx, fr_dcursor_t **out,
- bool *tainted, request_t *requst, char const *fmt);
-
ssize_t xlat_eval(char *out, size_t outlen, request_t *request, char const *fmt, xlat_escape_legacy_t escape,
void const *escape_ctx)
CC_HINT(nonnull (1 ,3 ,4));
/** Return a VP from the specified request.
*
- * @note DEPRECATED, TO NOT USE. @see xlat_fmt_to_cursor instead.
+ * @note DEPRECATED, TO NOT USE.
*
* @param out where to write the pointer to the resolved VP. Will be NULL if the attribute couldn't
* be resolved.
}
-/** Convenience function to convert a string attribute reference to a cursor
- *
- * This is intended to be used by xlat functions which need to iterate over
- * an attribute reference provided as a format string or as a boxed value.
- *
- * We can't add attribute reference support to the xlat parser
- * as the inputs and outputs of xlat functions are all boxed values and
- * couldn't represent a fr_pair_t.
- *
- * @param[in] ctx To allocate new cursor in.
- * @param[out] out Where to write heap allocated cursor. Must be freed
- * once it's done with. The heap based cursor is to
- * simplify memory management, as all tmpls are heap
- * allocated, and we need to bind the lifetime of the
- * tmpl and tmpl cursor together.
- * @param[in] tainted May be NULL. Set to true if one or more of the pairs
- * in the cursor's scope have the tainted flag high.
- * @param[in] request The current request.
- * @param[in] fmt string. Leading whitespace will be ignored.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-int xlat_fmt_to_cursor(TALLOC_CTX *ctx, fr_dcursor_t **out,
- bool *tainted, request_t *request, char const *fmt)
-{
- tmpl_t *vpt;
- fr_pair_t *vp;
- fr_dcursor_t *cursor;
- tmpl_cursor_ctx_t cc;
-
- fr_skip_whitespace(fmt); /* Not binary safe, but attr refs should only contain printable chars */
-
- if (tmpl_afrom_attr_str(NULL, NULL, &vpt, fmt,
- &(tmpl_rules_t){
- .dict_def = request->dict,
- .prefix = TMPL_ATTR_REF_PREFIX_AUTO
- }) <= 0) {
- RPEDEBUG("Failed parsing attribute reference");
- return -1;
- }
-
- MEM(cursor = talloc(ctx, fr_dcursor_t));
- talloc_steal(cursor, vpt);
- vp = tmpl_cursor_init(NULL, NULL, &cc, cursor, request, vpt);
- tmpl_cursor_clear(&cc);
- *out = cursor;
-
- if (!tainted) return 0;
-
- *tainted = false; /* Needed for the rest of the code */
-
- if (!vp) return 0;
-
- do {
- if (vp->vp_tainted) {
- *tainted = true;
- break;
- }
- } while ((vp = fr_dcursor_next(cursor)));
-
- fr_dcursor_head(cursor); /* Reset */
-
- return 0;
-}
-
-
/*
* Compare two xlat_t structs, based ONLY on the module name.
*/
int nothing;
} rlm_dhcpv4_t;
+static xlat_arg_parser_t const dhcpv4_decode_xlat_args[] = {
+ { .single = true, .variadic = true, .type = FR_TYPE_VOID },
+ XLAT_ARG_PARSER_TERMINATOR
+};
+
/** Decode DHCP option data
*
* Creates DHCP attributes based on the given binary option data
*
* Example:
@verbatim
-%{dhcpv4_decode:%{Tmp-Octets-0}}
+%(dhcpv4_decode:%{Tmp-Octets-0})
@endverbatim
*
* @ingroup xlat_functions
request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
fr_value_box_list_t *in)
{
- fr_dcursor_t in_cursor;
- fr_value_box_t *vb, *vb_decoded;
- fr_pair_t *vp;
+ fr_value_box_t *vb = NULL, *vb_decoded;
+ fr_pair_t *vp = NULL;
fr_pair_list_t head;
int decoded = 0;
fr_pair_list_init(&head);
- for (vb = fr_dcursor_talloc_init(&in_cursor, in, fr_value_box_t);
- vb;
- vb = fr_dcursor_next(&in_cursor)) {
+ while ((vb = fr_dlist_next(in, vb))) {
uint8_t const *p, *end;
ssize_t len;
fr_pair_list_t vps;
fr_tmp_pair_list_move(&head, &vps);
}
- for (vp = fr_pair_list_head(&head);
- vp;
- vp = fr_pair_list_next(&head, vp)) {
+ while ((vp = fr_pair_list_next(&head, vp))) {
RDEBUG2("dhcp_option: &%pP", vp);
decoded++;
}
return XLAT_ACTION_DONE;
}
+static xlat_arg_parser_t const dhcpv4_encode_xlat_args[] = {
+ { .required = true, .single = true, .type = FR_TYPE_STRING },
+ XLAT_ARG_PARSER_TERMINATOR
+};
+
/** Encode DHCP option data
*
* Returns octet string created from the provided DHCP attributes
*
* Example:
@verbatim
-%{dhcpv4_encode:&request[*]}
+%(dhcpv4_encode:&request[*])
@endverbatim
*
* @ingroup xlat_functions
request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
fr_value_box_list_t *in)
{
+ tmpl_t *vpt;
+ fr_pair_t *vp;
fr_dcursor_t *cursor;
+ tmpl_cursor_ctx_t cc;
bool tainted = false;
fr_value_box_t *encoded;
ssize_t len = 0;
fr_value_box_t *in_head = fr_dlist_head(in);
- if (!in_head) return XLAT_ACTION_DONE;
-
- if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
- RPEDEBUG("Failed concatenating input string for attribute reference");
+ if (tmpl_afrom_attr_str(NULL, NULL, &vpt, in_head->vb_strvalue,
+ &(tmpl_rules_t){
+ .dict_def = request->dict,
+ .prefix = TMPL_ATTR_REF_PREFIX_AUTO
+ }) <= 0) {
+ RPEDEBUG("Failed parsing attribute reference");
return XLAT_ACTION_FAIL;
}
- if (xlat_fmt_to_cursor(NULL, &cursor, &tainted, request, in_head->vb_strvalue) < 0) return XLAT_ACTION_FAIL;
+ MEM(cursor = talloc(ctx, fr_dcursor_t));
+ talloc_steal(cursor, vpt);
+ vp = tmpl_cursor_init(NULL, NULL, &cc, cursor, request, vpt);
- if (!fr_dcursor_head(cursor)) return XLAT_ACTION_DONE; /* Nothing to encode */
+ if (!vp) return XLAT_ACTION_DONE; /* Nothing to encode */
while (fr_dcursor_filter_current(cursor, fr_dhcpv4_is_encodable, NULL)) {
+ vp = fr_dcursor_current(cursor);
+ if (vp->vp_tainted) tainted = true;
len = fr_dhcpv4_encode_option(&FR_DBUFF_TMP(p, end), cursor,
&(fr_dhcpv4_ctx_t){ .root = fr_dict_root(dict_dhcpv4) });
if (len < 0) {
RPEDEBUG("DHCP option encoding failed");
talloc_free(cursor);
+ tmpl_cursor_clear(&cc);
return XLAT_ACTION_FAIL;
}
p += len;
}
talloc_free(cursor);
+ tmpl_cursor_clear(&cc);
/*
* Pass the options string back
static int dhcp_load(void)
{
+ xlat_t *xlat;
+
if (fr_dhcpv4_global_init() < 0) {
PERROR("Failed initialising protocol library");
return -1;
}
- xlat_register(NULL, "dhcpv4_decode", dhcpv4_decode_xlat, false);
- xlat_register(NULL, "dhcpv4_encode", dhcpv4_encode_xlat, false);
+ xlat = xlat_register(NULL, "dhcpv4_decode", dhcpv4_decode_xlat, false);
+ xlat_func_args(xlat, dhcpv4_decode_xlat_args);
+ xlat = xlat_register(NULL, "dhcpv4_encode", dhcpv4_encode_xlat, false);
+ xlat_func_args(xlat, dhcpv4_encode_xlat_args);
return 0;
}
}
+ dhcpv4 {
+
+ }
+
}
policy {
--- /dev/null
+#
+# PRE: update
+#
+
+update control {
+ &Tmp-Octets-0 := 0x520d0103abcdef0206010203040506
+}
+
+if ("%(dhcpv4_decode:%{control.Tmp-Octets-0})" != 2) {
+ test_fail
+}
+
+debug_request
+
+if ( &Relay-Agent-Information.Circuit-Id != 0xabcdef ) {
+ test_fail
+}
+
+if ( &Relay-Agent-Information.Remote-Id != 0x010203040506 ) {
+ test_fail
+}
+
+update control {
+ &Tmp-Octets-1 := "%(dhcpv4_encode:&request[*])"
+}
+
+if ( &control.Tmp-Octets-1 != 0x520d0103abcdef0206010203040506 ) {
+ test_fail
+}
+
+debug_control
+success