25 RCSID(
"$Id: d1cedaf327f1b6bae8effb50c4e4bfd602c62e2c $")
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/server/module_rlm.h>
29 #include <freeradius-devel/dhcpv4/dhcpv4.h>
30 #include <freeradius-devel/util/debug.h>
32 #include <freeradius-devel/server/map_proc.h>
65 #define NO_SEMICOLON (0)
66 #define YES_SEMICOLON (1)
67 #define MAYBE_SEMICOLON (2)
104 #define IDEBUG if (state->debug) DEBUG
216 if (state->
eof)
return 0;
229 if (feof(state->
fp)) {
247 if (!*p || (*p ==
'#'))
goto redo;
271 if (!state->
eof && !*state->
ptr) {
277 if (ret < 0)
return -1;
298 char *p = state->
ptr + 1;
315 if ((
size_t) (q - state->
string) >=
sizeof(state->
string)) {
354 if (ret < 0)
return ret;
371 while (isspace((
uint8_t) *state->
ptr) || (*state->
ptr ==
';') || (*state->
ptr ==
',')) state->
ptr++;
373 if (!*state->
ptr)
goto redo;
385 if (state->
token[0] ==
'"') {
394 for (p = state->
token; *p !=
'\0'; p++) {
424 if ((*p ==
'{') || (*p ==
'}') || (*p ==
'=')) {
425 if (p == state->
token) p++;
442 if (state->
token == state->
ptr)
goto redo;
475 if (*state->
token !=
'{') {
490 if (*state->
token !=
'}') {
504 if (*state->
token ==
'}') {
505 if (!allow_rcbrace) {
519 if (*state->
token ==
'{') {
545 if (!*cmd)
return -1;
559 if (ret <= 0)
return -1;
569 (
int) (
next - cmd), cmd);
601 if (strcmp(q,
"SECTION") == 0) {
602 if (q[7] !=
'\0')
return -1;
605 if (ret <= 0)
return ret;
608 if (ret < 0)
return ret;
624 while (*q && !isspace((
uint8_t) *q) && (*q !=
',')) {
625 if ((p - type_name) >= (
int)
sizeof(type_name))
return -1;
626 *(p++) = tolower((
uint8_t) *(q++));
659 (
int) (
next - cmd), cmd);
672 if (ret <= 0)
return ret;
686 (strcmp(state->
token,
"ignore") == 0)) {
698 if (ret < 0)
return ret;
717 if (!*
next)
return 1;
731 char *p, pathname[8192];
732 char const *
name = info->
argv[0]->vb_strvalue;
739 p = pathname + (p - state->
filename) + 1;
740 strlcpy(p,
name,
sizeof(pathname) - (p - pathname));
750 if (ret < 0)
return ret;
770 return fr_hash(self->ether,
sizeof(self->ether));
792 return fr_hash(self->client->vb_octets, self->client->vb_length);
813 fr_strerror_const(
"please implement 'option space name [ [ code width number ] [ length width number ] [ hash size number ] ]'");
832 #define TYPE_CHECK(name, type) if ((state->token_len == (sizeof(name) - 1)) && (memcmp(state->token, name, sizeof(name) - 1) == 0)) return type
862 p = strchr(
name,
'.');
888 if (ret < 0)
goto error;
894 if (ret <= 0)
goto error_ret;
901 memset(&flags, 0,
sizeof(flags));
915 if (ret <= 0)
goto error_ret;
918 if ((state->
token_len == 5) && (memcmp(state->
token,
"array", 5) == 0)) {
922 if (ret <= 0)
goto error_ret;
924 if (! ((state->
token_len == 2) && (memcmp(state->
token,
"of", 2) == 0))) {
934 if (ret <= 0)
goto error_ret;
962 ((da->attr != box.vb_uint32) || (da->type !=
type))) {
975 if (da && (da->type !=
type)) {
976 fr_strerror_printf(
"cannot add different type for a pre-existing code %d", box.vb_uint32);
988 if (ret < 0)
return ret;
1033 if (!da->flags.array)
return 2;
1040 if (ret <= 0)
return ret;
1045 if (ret < 0)
return ret;
1082 if (ret < 0)
return ret;
1086 if (argc == 2)
break;
1100 if (strcmp(argv[0],
"space") == 0) {
1123 memcpy(
name,
"DHCP-", 5);
1138 if (strcmp(argv[1],
"code") != 0) {
1152 int start, end, half;
1155 char const *q = NULL;
1159 end = num_tokens - 1;
1171 while (start <= end) {
1172 half = (start + end) / 2;
1179 ret = state->
token[0] - tokens[half].
name[0];
1180 if (ret != 0)
goto recurse;
1182 ret = state->
token[1] - tokens[half].
name[1];
1183 if (ret != 0)
goto recurse;
1185 ret = state->
token[2] - tokens[half].
name[2];
1186 if (ret != 0)
goto recurse;
1203 if (!c || isspace((
uint8_t) c)) {
1252 ERROR(
"Command '%.*s' is not supported.",
1264 WARN(
"Command '%.*s' is not yet implemented.",
1269 WARN(
"Ignoring command '%.*s'. It is not relevant.",
1281 if (tokens[half].max_argc) {
1289 info->
cmd = &tokens[half];
1300 if (ret <= 0)
return ret;
1330 if (tokens[half].parse) {
1331 ret = tokens[half].
parse(state, info);
1352 if (ret == 2)
return 1;
1388 for (child = info->
child; child != NULL; child = child->
next) {
1401 info->
argv[0]->vb_strvalue);
1409 memcpy(my_ether->
ether, &(ether->
argv[0]->vb_ether),
sizeof(my_ether->
ether));
1410 my_ether->
host = info;
1417 fr_strerror_printf(
"'host %s' and 'host %s' contain duplicate 'hardware ethernet' fields",
1418 info->
argv[0]->vb_strvalue, old_ether->
host->
argv[0]->vb_strvalue);
1430 my_uid->
host = info;
1434 fr_strerror_printf(
"'host %s' and 'host %s' contain duplicate 'option client-identifier' fields",
1435 info->
argv[0]->vb_strvalue, old_uid->
host->
argv[0]->vb_strvalue);
1447 info->
argv[0]->vb_strvalue);
1456 info->
argv[0]->vb_strvalue);
1467 if (!info->
parent)
return 2;
1477 if (!
parent->hosts_by_ether) {
1479 if (!
parent->hosts_by_ether) {
1486 info->
argv[0]->vb_strvalue);
1494 if (!
parent->hosts_by_uid) {
1496 if (!
parent->hosts_by_uid) {
1504 info->
argv[0]->vb_strvalue);
1521 #define vb_ipv4addr vb_ip.addr.v4.s_addr
1535 if (!(netmask & (~netmask >> 1))) {
1543 if ((info->
argv[0]->vb_ipv4addr & netmask) != info->
argv[0]->vb_ipv4addr) {
1551 netmask = netmask - ((netmask >> 1) & 0x55555555);
1552 netmask = (netmask & 0x33333333) + ((netmask >> 2) & 0x33333333);
1553 netmask = (netmask + (netmask >> 4)) & 0x0F0F0F0F;
1554 netmask = netmask + (netmask >> 8);
1555 netmask = netmask + (netmask >> 16);
1556 bits = netmask & 0x0000003F;
1573 if (!
parent->subnets)
return -1;
1625 host = client->
host;
1632 if (!
vp)
return NULL;
1634 memcpy(&my_ether.
ether,
vp->vp_ether,
sizeof(my_ether.
ether));
1637 if (!ether)
return NULL;
1659 if (!info->
parent)
return -1;
1664 if (ret < 0)
return ret;
1672 #define member_size(type, member) sizeof(((type *)0)->member)
1753 if (yiaddr)
return 0;
1756 if (!host)
return 0;
1761 for (info = host->
child; info != NULL; info = info->
next) {
1762 if (!info->
cmd)
return -1;
1767 if (info->
child)
continue;
1774 if (ret < 0)
return ret;
1804 if (
head->hosts_by_ether) {
1808 if (!host)
goto subnet;
1814 if (child_ret < 0)
return child_ret;
1815 if (child_ret == 1) ret = 1;
1823 if (
head->subnets && yiaddr) {
1825 if (!info)
goto recurse;
1828 if (child_ret < 0)
return child_ret;
1829 if (child_ret == 1) ret = 1;
1833 for (info =
head->child; info != NULL; info = info->
next) {
1834 if (!info->
cmd)
return -1;
1839 if (child_ret < 0)
return child_ret;
1840 if (child_ret == 0)
continue;
1877 if (reply)
continue;
1887 if (!copy)
return -1;
1908 #define isc_not_done ISC_NOOP, NULL, NULL
1909 #define isc_ignore ISC_IGNORE, NULL, NULL
1910 #define isc_invalid ISC_INVALID, NULL, NULL
1918 {
"adaptive-lease-time-threshold INTEGER",
isc_not_done, 1},
1924 {
"bind-local-address6 BOOL",
isc_ignore, 1},
1935 {
"ddns-other-guard-is-dynamic BOOL",
isc_not_done, 1},
1944 {
"dhcpv6-lease-file-name STRING",
isc_ignore, 1},
1945 {
"dhcpv6-pid-file-name STRING",
isc_ignore, 1},
1952 {
"dynamic-bootp-lease-cutoff UINT32",
isc_not_done, 1},
1953 {
"dynamic-bootp-lease-length UINT32",
isc_not_done, 1},
1959 {
"group SECTION",
ISC_GROUP, NULL, NULL, 1},
1973 {
"ldap-dhcp-server-cn STRING",
isc_ignore, 1},
1974 {
"ldap-gssapi-keytab STRING",
isc_ignore, 1},
1975 {
"ldap-gssapi-principal STRING",
isc_ignore, 1},
1985 {
"ldap-TLS-Certificate STRING",
isc_ignore, 1},
1987 {
"ldap-tls-crlcheck STRING,",
isc_ignore, 1},
1989 {
"ldap-tls-randfile STRING",
isc_ignore, 1},
1990 {
"ldap-tls-reqcert STRING,",
isc_ignore, 1},
1997 {
"limited-broadcast-address IPADDR",
isc_not_done, 1},
2002 {
"log-threshold-high UINT8",
isc_ignore, 1},
2014 {
"option STRING STRING,",
ISC_OPTION, NULL, NULL, 16},
2035 {
"use-lease-addr-for-default-route BOOL",
isc_not_done, 1},
2078 if (ret < 0)
return ret;
2079 if (ret == 0)
break;
2084 if (*state->
token ==
'}')
break;
2087 if (ret < 0)
return ret;
2088 if (ret == 0)
break;
2117 fp = fopen(filename,
"r");
2123 memset(&state, 0,
sizeof(state));
2153 if (ret == 0)
break;
2160 if (ret < 0)
goto fail;
2161 if (ret == 0)
break;
2170 if (!*last)
return 0;
2187 if (!
inst->hosts_by_ether)
return -1;
2190 if (!
inst->hosts_by_uid)
return -1;
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
static int const char char buffer[256]
#define MEMCMP_RETURN(_a, _b, _field, _len_field)
Return if the contents of the specified field is not identical between the specified structures.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_log_warn(_cf, _fmt,...)
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
unsigned int array
Pack multiples into 1 attr.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
int fr_dict_attr_add(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, unsigned int attr, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
Specifies an attribute which must be present for the module to function.
Values of the encryption flags.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
uint32_t fr_hash(void const *data, size_t size)
void * fr_hash_table_find(fr_hash_table_t *ht, void const *data)
bool fr_hash_table_insert(fr_hash_table_t *ht, void const *data)
#define fr_hash_table_alloc(_ctx, _hash_node, _cmp_node, _free_node)
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
#define fr_skip_not_whitespace(_p)
Skip everything that's not whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
module_t common
Common fields presented by all modules.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
static const conf_parser_t config[]
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_UPDATED
rlm_rcode_t
Return codes indicating the result of the module call.
static rlm_isc_dhcp_info_t * get_host(request_t *request, fr_hash_table_t *hosts_by_ether, fr_hash_table_t *hosts_by_uid)
char * ptr
pointer into read buffer
static int parse_option(rlm_isc_dhcp_info_t *parent, rlm_isc_dhcp_tokenizer_t *state, fr_dict_attr_t const *da, char *value)
#define TYPE_CHECK(name, type)
Parse one type string.
int(* rlm_isc_dhcp_parse_t)(rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
bool allow_eof
do we allow EOF? (i.e. braces == 0)
fr_dict_attr_autoload_t rlm_isc_dhcp_dict_attr[]
static int match_keyword(rlm_isc_dhcp_info_t *parent, rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_cmd_t const *tokens, int num_tokens)
static int parse_include(rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
static int8_t host_ether_cmp(void const *one, void const *two)
static int refill(rlm_isc_dhcp_tokenizer_t *state)
Refills the read buffer with one line from the file.
fr_hash_table_t * hosts_by_ether
by MAC address
static int parse_options(rlm_isc_dhcp_info_t *parent, rlm_isc_dhcp_tokenizer_t *state)
Parse "option" command.
size_t token_len
length of the token
int(* rlm_isc_dhcp_apply_t)(rlm_isc_dhcp_t const *inst, request_t *request, rlm_isc_dhcp_info_t *info)
rlm_isc_dhcp_t * inst
module instance
int braces
how many levels deep we are in a { ... }
static int parse_subnet(rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
subnet IPADDR netmask MASK { ...
rlm_isc_dhcp_info_t * host
static int parse_server_identifier(UNUSED rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
server-identifier IPADDR
rlm_isc_dhcp_info_t * head
char * token
current token that we parsed
rlm_isc_dhcp_parse_t parse
static fr_dict_attr_t const * attr_server_identifier
static int parse_host(rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
host NAME { ...
fr_dict_autoload_t rlm_isc_dhcp_dict[]
static int parse_section(rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
Parse a section { ...
fr_hash_table_t * hosts_by_uid
by client identifier
fr_hash_table_t * hosts_by_uid
by client identifier
static int parse_server_name(UNUSED rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
server-name STRING
static int parse_next_server(UNUSED rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
next-server IPADDR
static fr_dict_attr_t const * attr_boot_filename
static uint32_t host_uid_hash(void const *data)
static int parse_option_definition(rlm_isc_dhcp_info_t *parent, rlm_isc_dhcp_tokenizer_t *state, char *name)
option new-name code new-code = definition ;
rlm_isc_dhcp_info_t ** last
pointer to last child
module_rlm_t rlm_isc_dhcp
static int skip_spaces(rlm_isc_dhcp_tokenizer_t *state, char *p)
char string[256]
double quoted strings go here, so we don't mangle the input buffer
static fr_dict_t const * dict_dhcpv4
bool saw_semicolon
whether we saw a semicolon
static fr_dict_attr_t const * attr_client_hardware_address
static int apply_fixed_ip(rlm_isc_dhcp_t const *inst, request_t *request)
Apply fixed IPs.
static fr_dict_attr_t const * attr_your_ip_address
static int parse_filename(UNUSED rlm_isc_dhcp_tokenizer_t *state, rlm_isc_dhcp_info_t *info)
filename STRING
static const rlm_isc_dhcp_cmd_t commands[]
Table of commands that we allow.
static fr_dict_attr_t const * attr_server_name
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
char * line
where the current line started
fr_pair_list_t options
DHCP options.
bool debug
internal developer debugging
static int read_file(rlm_isc_dhcp_t *inst, rlm_isc_dhcp_info_t *parent, char const *filename)
Open a file and read it into a parent.
rlm_isc_dhcp_info_t * next
void * data
per-thing parsed data.
static fr_dict_attr_t const * attr_client_identifier
static fr_type_t isc2fr_type(rlm_isc_dhcp_tokenizer_t *state)
size_t bufsize
size of read buffer
static int apply(rlm_isc_dhcp_t const *inst, request_t *request, rlm_isc_dhcp_info_t *head)
Apply all rules except fixed IP.
rlm_isc_dhcp_cmd_t const * cmd
static fr_dict_attr_t const * attr_server_ip_address
static int8_t host_uid_cmp(void const *one, void const *two)
static char const * spaces
rlm_isc_dhcp_apply_t apply
static const conf_parser_t module_config[]
fr_hash_table_t * hosts_by_ether
by MAC address
rlm_isc_dhcp_info_t * parent
static int add_option_by_da(rlm_isc_dhcp_info_t *info, fr_dict_attr_t const *da)
static int read_string(rlm_isc_dhcp_tokenizer_t *state)
static uint32_t host_ether_hash(void const *data)
static int mod_instantiate(module_inst_ctx_t const *mctx)
static int read_token(rlm_isc_dhcp_tokenizer_t *state, fr_token_t hint, int semicolon, bool allow_rcbrace)
Reads one token into state->token.
static int parse_option_space(UNUSED rlm_isc_dhcp_info_t *parent, UNUSED rlm_isc_dhcp_tokenizer_t *state, UNUSED char *name)
option space name [ [ code width number ] [ length width number ] [ hash size number ] ] ;
rlm_isc_dhcp_info_t * child
@ ISC_NOOP
we don't do anything with it
@ ISC_IGNORE
we deliberately ignore it
@ ISC_INVALID
we recognize it, but don't implement it
#define member_size(type, member)
static int match_subword(rlm_isc_dhcp_tokenizer_t *state, char const *cmd, rlm_isc_dhcp_info_t *info)
Recursively match subwords inside of a command string.
rlm_isc_dhcp_info_t * host
static unlang_action_t mod_post_auth(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Describes the commands that we accept, including it's syntax (i.e.
Holds information about the thing we parsed.
Holds the state of the current tokenizer.
static int instantiate(module_inst_ctx_t const *mctx)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
size_t strlcpy(char *dst, char const *src, size_t siz)
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define talloc_get_type_abort_const
fr_trie_t * fr_trie_alloc(TALLOC_CTX *ctx, fr_trie_key_t get_key, fr_free_t free_data)
Allocate a trie.
int fr_trie_insert_by_key(fr_trie_t *ft, void const *key, size_t keylen, void const *data)
Insert a key and user ctx into a trie.
void * fr_trie_lookup_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Lookup a key in a trie and return user ctx, if any.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
#define fr_type_is_null(_x)
static fr_type_t fr_type_from_str(char const *type)
Return the constant value representing a type.
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.