41 RCSID(
"$Id: d164d1f3bf09da743e90979d6d6a7a9c464aeda2 $")
43 #include <freeradius-devel/server/base.h>
44 #include <freeradius-devel/server/module_rlm.h>
45 #include <freeradius-devel/server/modpriv.h>
47 #include <freeradius-devel/util/debug.h>
48 #include <freeradius-devel/util/base16.h>
49 #include <freeradius-devel/util/token.h>
51 #include <freeradius-devel/redis/base.h>
52 #include <freeradius-devel/redis/cluster.h>
54 #include <freeradius-devel/unlang/call_env.h>
199 .pair.dflt =
"&reply.IP-Pool.Range", .pair.dflt_quote =
T_BARE_WORD },
217 .pair.dflt =
"&reply.IP-Pool.Range", .pair.dflt_quote =
T_BARE_WORD },
265 "local address_key" EOL
266 "local owner_key" EOL
278 "exists = redis.call('GET', owner_key);" EOL
280 " local expires = tonumber(redis.call('ZSCORE', pool_key, exists))" EOL
283 " if expires_in > 0 or static then" EOL
284 " ip = redis.call('HMGET', '{' .. KEYS[1] .. '}:"IPPOOL_ADDRESS_KEY":' .. exists, 'device', 'range', 'counter', 'gateway')" EOL
285 " if ip and (ip[1] == ARGV[3]) then" EOL
286 " if expires_in < tonumber(ARGV[2]) then" EOL
288 " expires_in = tonumber(ARGV[2])" EOL
289 " if not static then" EOL
290 " redis.call('EXPIRE', owner_key, ARGV[2])" EOL
297 " if ARGV[4] ~= ip[4] then" EOL
308 "ip = redis.call('ZREVRANGE', pool_key, -1, -1, 'WITHSCORES')" EOL
309 "if not ip or not ip[1] then" EOL
312 "if ip[2] >= ARGV[1] then" EOL
315 "redis.call('ZADD', pool_key, 'XX', ARGV[1] + ARGV[2], ip[1])" EOL
321 "redis.call('HMSET', address_key, 'device', ARGV[3], 'gateway', ARGV[4])" EOL
322 "redis.call('SET', owner_key, ip[1])" EOL
323 "redis.call('EXPIRE', owner_key, ARGV[2])" EOL
327 " redis.call('HGET', address_key, 'range'), " EOL
328 " tonumber(ARGV[2]), " EOL
329 " redis.call('HINCRBY', address_key, 'counter', 1)" EOL
353 "local address_key" EOL
354 "local owner_key" EOL
361 "found = redis.call('HMGET', address_key, 'range', 'device', 'gateway', 'counter' )" EOL
365 "if not found[2] then" EOL
368 "if found[2] ~= ARGV[4] then" EOL
376 "local expires = tonumber(redis.call('ZSCORE', pool_key, ARGV[3]))" EOL
387 "if not static and (redis.call('EXPIRE', owner_key, ARGV[2]) == 0) then" EOL
388 " redis.call('SET', owner_key, ARGV[3])" EOL
389 " redis.call('EXPIRE', owner_key, ARGV[2])" EOL
395 "if ARGV[5] ~= found[3] then" EOL
396 " redis.call('HSET', address_key, 'gateway', ARGV[5])" EOL
421 "local address_key" EOL
422 "local owner_key" EOL
429 "found = redis.call('HGET', address_key, 'device')" EOL
430 "if not found then" EOL
433 "if found and found ~= ARGV[3] then" EOL
441 "found = tonumber(redis.call('ZSCORE', pool_key, ARGV[2]))" EOL
448 "if not static then" EOL
450 " redis.call('DEL', owner_key)" EOL
454 " redis.call('HINCRBY', address_key, 'counter', 1) - 1" EOL
469 if (!wait_num)
return 0;
471 if (reply->type != REDIS_REPLY_INTEGER) {
472 REDEBUG(
"WAIT result is wrong type, expected integer got %s",
476 if (reply->integer < wait_num) {
477 REDEBUG(
"Too few slaves acknowledged allocation, needed %i, got %lli",
478 wait_num, reply->integer);
492 char *device_str = NULL, *gateway_str = NULL;
494 if (gateway_id && gateway_id->vb_length > 0) gateway_str =
fr_asprint(request, gateway_id->vb_strvalue,
495 gateway_id->vb_length,
'"');
496 if (owner && owner->vb_length > 0) device_str =
fr_asprint(request, owner->vb_strvalue, owner->vb_length,
'"');
500 RDEBUGX(lvl,
"Allocating lease from pool \"%pV\"%s%s%s%s%s%s, expires in %us",
502 device_str ?
", to \"" :
"", device_str ? device_str :
"",
503 device_str ?
"\"" :
"",
504 gateway_str ?
", on \"" :
"", gateway_str ? gateway_str :
"",
505 gateway_str ?
"\"" :
"",
510 RDEBUGX(lvl,
"Updating %pV in pool \"%pV\"%s%s%s%s%s%s, expires in %us",
512 device_str ?
", device \"" :
"", device_str ? device_str :
"",
513 device_str ?
"\"" :
"",
514 gateway_str ?
", gateway \"" :
"", gateway_str ? gateway_str :
"",
515 gateway_str ?
"\"" :
"",
520 RDEBUGX(lvl,
"Releasing %pV%s%s%s to pool \"%pV\"",
522 device_str ?
" leased by \"" :
"", device_str ? device_str :
"",
523 device_str ?
"\"" :
"",
560 uint8_t const *key,
size_t key_len,
562 char const digest[],
char const *script,
563 char const *cmd, ...)
566 redisReply *replies[5];
567 size_t reply_cnt = 0, i;
571 unsigned int pipelined = 0;
578 memset(replies, 0,
sizeof(replies));
588 RDEBUG3(
"Calling script 0x%s", digest);
590 redisvAppendCommand(conn->
handle, cmd, copy);
612 RDEBUG3(
"Loading script 0x%s", digest);
613 redisAppendCommand(conn->
handle,
"MULTI");
614 redisAppendCommand(conn->
handle,
"SCRIPT LOAD %s", script);
616 redisvAppendCommand(conn->
handle, cmd, copy);
618 redisAppendCommand(conn->
handle,
"EXEC");
633 if (replies[3]->
type != REDIS_REPLY_ARRAY) {
634 RERROR(
"Bad response to EXEC, expected array got %s",
641 if (replies[3]->elements != 2) {
642 RERROR(
"Bad response to EXEC, expected 2 result elements, got %zu",
643 replies[3]->elements);
646 if (replies[3]->element[0]->
type != REDIS_REPLY_STRING) {
647 RERROR(
"Bad response to SCRIPT LOAD, expected string got %s",
651 if (strcmp(replies[3]->element[0]->str, digest) != 0) {
652 RWDEBUG(
"Incorrect SHA1 from SCRIPT LOAD, expected %s, got %s",
653 digest, replies[3]->element[0]->str);
679 *
out = replies[3]->element[1];
680 replies[3]->element[1] = NULL;
700 redisReply *reply = NULL;
714 "EVALSHA %s 1 %b %u %u %b %b",
717 (
unsigned int)now.tv_sec, lease_time,
726 if (reply->type != REDIS_REPLY_ARRAY) {
727 REDEBUG(
"Expected result to be array got \"%s\"",
733 if (reply->elements == 0) {
734 REDEBUG(
"Got empty result array");
742 if (reply->element[0]->type != REDIS_REPLY_INTEGER) {
743 REDEBUG(
"Server returned unexpected type \"%s\" for rcode element (result[0])",
748 ret = reply->element[0]->integer;
749 if (ret < 0)
goto finish;
754 if (reply->elements > 1) {
763 switch (reply->element[1]->type) {
770 case REDIS_REPLY_INTEGER:
778 RPEDEBUG(
"Failed converting integer to IPv4 address");
789 case REDIS_REPLY_STRING:
791 NULL, reply->element[1]->str, reply->element[1]->len,
false);
800 REDEBUG(
"Server returned unexpected type \"%s\" for IP element (result[1])",
810 if (reply->elements > 2) {
811 switch (reply->element[2]->type) {
815 case REDIS_REPLY_STRING:
826 NULL, reply->element[2]->str, reply->element[2]->len,
true);
834 case REDIS_REPLY_NIL:
838 REDEBUG(
"Server returned unexpected type \"%s\" for range element (result[2])",
857 if (reply->element[3]->type != REDIS_REPLY_INTEGER) {
858 REDEBUG(
"Server returned unexpected type \"%s\" for expiry element (result[3])",
886 redisReply *reply = NULL;
893 if ((ip->
af == AF_INET) &&
inst->ipv4_integer) {
898 "EVALSHA %s 1 %b %u %u %u %b %b",
901 (
unsigned int)now.tv_sec, expires,
902 htonl(ip->
addr.v4.s_addr),
903 (
uint8_t const *)owner->vb_strvalue, owner->vb_length,
904 (
uint8_t const *)gateway_id->vb_strvalue, gateway_id->vb_length);
913 "EVALSHA %s 1 %b %u %u %s %b %b",
916 (
unsigned int)now.tv_sec, expires,
918 (
uint8_t const *)owner->vb_strvalue, owner->vb_length,
919 (
uint8_t const *)gateway_id->vb_strvalue, gateway_id->vb_length);
926 if (reply->type != REDIS_REPLY_ARRAY) {
927 REDEBUG(
"Expected result to be array got \"%s\"",
933 if (reply->elements == 0) {
934 REDEBUG(
"Got empty result array");
942 if (reply->element[0]->type != REDIS_REPLY_INTEGER) {
943 REDEBUG(
"Server returned unexpected type \"%s\" for rcode element (result[0])",
948 ret = reply->element[0]->integer;
949 if (ret < 0)
goto finish;
954 if (reply->elements > 1) {
955 switch (reply->element[1]->type) {
959 case REDIS_REPLY_STRING:
966 reply->element[1]->str, reply->element[1]->len,
true);
974 case REDIS_REPLY_NIL:
978 REDEBUG(
"Server returned unexpected type \"%s\" for range element (result[1])",
1021 redisReply *reply = NULL;
1028 if ((ip->
af == AF_INET) &&
inst->ipv4_integer) {
1030 (
uint8_t const *)key_prefix->vb_strvalue, key_prefix->vb_length,
1031 inst->wait_num,
inst->wait_timeout,
1033 "EVALSHA %s 1 %b %u %u %b",
1035 (
uint8_t const *)key_prefix->vb_strvalue, key_prefix->vb_length,
1036 (
unsigned int)now.tv_sec,
1037 htonl(ip->
addr.v4.s_addr),
1038 (
uint8_t const *)owner->vb_strvalue, owner->vb_length);
1044 (
uint8_t const *)key_prefix->vb_strvalue, key_prefix->vb_length,
1045 inst->wait_num,
inst->wait_timeout,
1047 "EVALSHA %s 1 %b %u %s %b",
1049 (
uint8_t const *)key_prefix->vb_strvalue, key_prefix->vb_length,
1050 (
unsigned int)now.tv_sec,
1052 (
uint8_t const *)owner->vb_strvalue, owner->vb_length);
1059 if (reply->type != REDIS_REPLY_ARRAY) {
1060 REDEBUG(
"Expected result to be array got \"%s\"",
1066 if (reply->elements == 0) {
1067 REDEBUG(
"Got empty result array");
1075 if (reply->element[0]->type != REDIS_REPLY_INTEGER) {
1076 REDEBUG(
"Server returned unexpected type \"%s\" for rcode element (result[0])",
1081 ret = reply->element[0]->integer;
1082 if (ret < 0)
goto finish;
1090 #define CHECK_POOL_NAME \
1091 if (env->pool_name.vb_length > IPPOOL_MAX_KEY_PREFIX_SIZE) { \
1092 REDEBUG("Pool name too long. Expected %u bytes, got %ld bytes", \
1093 IPPOOL_MAX_KEY_PREFIX_SIZE, env->pool_name.vb_length); \
1094 RETURN_MODULE_FAIL; \
1096 if (env->pool_name.vb_length == 0) { \
1097 RDEBUG2("Empty pool name. Doing nothing"); \
1098 RETURN_MODULE_NOOP; \
1119 RDEBUG2(
"IP address lease allocated");
1123 RWDEBUG(
"Pool contains no free addresses");
1150 if (
inst->copy_on_update) {
1174 REDEBUG(
"Requested IP address \"%pV\" is not a member of the specified pool",
1179 REDEBUG(
"Requested IP address' \"%pV\" lease already expired at time of renewal",
1184 REDEBUG(
"Requested IP address' \"%pV\" lease allocated to another device",
1213 REDEBUG(
"Requested IP address \"%pV\" is not a member of the specified pool",
1218 REDEBUG(
"Requested IP address' \"%pV\" lease allocated to another device",
1230 RDEBUG2(
"Bulk release not yet implemented");
1236 static bool done_hash =
false;
1244 if (!
inst->cluster)
return -1;
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define fr_base16_encode(_out, _in)
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl must contain an attribute reference.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field)
Specify a call_env_parser_t which writes out runtime results to the specified field.
#define FR_CALL_ENV_PARSE_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _parse_field)
Specify a call_env_parser_t which writes out the result of the parsing phase to the field specified.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
#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_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
fr_redis_rcode_t fr_redis_cluster_state_next(fr_redis_cluster_state_t *state, fr_redis_conn_t **conn, fr_redis_cluster_t *cluster, request_t *request, fr_redis_rcode_t status, redisReply **reply)
Get the next connection to attempt a command against.
fr_redis_rcode_t fr_redis_cluster_state_init(fr_redis_cluster_state_t *state, fr_redis_conn_t **conn, fr_redis_cluster_t *cluster, request_t *request, uint8_t const *key, size_t key_len, bool read_only)
Resolve a key to a pool, and reserve a connection in that pool.
fr_redis_cluster_t * fr_redis_cluster_alloc(TALLOC_CTX *ctx, CONF_SECTION *module, fr_redis_conf_t *conf, bool triggers_enabled, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Allocate and initialise a new cluster structure.
bool fr_redis_cluster_min_version(fr_redis_cluster_t *cluster, char const *min_version)
Check if members of the cluster are above a certain version.
Redis connection sequence state.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
#define FR_IPADDR_PREFIX_STRLEN
Like FR_IPADDR_STRLEN but with space for a prefix.
union fr_ipaddr_t::@130 addr
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define RDEBUGX(_l, fmt,...)
#define RPEDEBUG(fmt,...)
int map_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, UNUSED void *uctx)
Convert a map to a fr_pair_t.
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
void * env_data
Per call environment data.
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.
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
static const conf_parser_t config[]
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_INVALID
#define RETURN_MODULE_UPDATED
rlm_rcode_t
Return codes indicating the result of the module call.
#define RETURN_MODULE_NOTFOUND
static void fr_redis_pipeline_free(redisReply *reply[], size_t num)
redisContext * handle
Hiredis context used when issuing commands.
#define REDIS_COMMON_CONFIG
void fr_redis_reply_print(fr_log_lvl_t lvl, redisReply *reply, request_t *request, int idx)
Print the response data in a useful treelike form.
static void fr_redis_reply_free(redisReply **reply)
Wrap freeReplyObject so we consistently check for NULL pointers.
void fr_redis_version_print(void)
Print the version of libhiredis the server was built against.
fr_table_num_sorted_t const redis_reply_types[]
fr_redis_rcode_t fr_redis_pipeline_result(unsigned int *pipelined, fr_redis_rcode_t *rcode, redisReply *out[], size_t out_len, fr_redis_conn_t *conn)
Simplifies handling of pipelined commands with Redis cluster.
fr_redis_rcode_t
Codes are ordered inversely by priority.
@ REDIS_RCODE_SUCCESS
Operation was successful.
@ REDIS_RCODE_TRY_AGAIN
Try the operation again.
@ REDIS_RCODE_NO_SCRIPT
Script doesn't exist.
@ REDIS_RCODE_ERROR
Unrecoverable library/server error.
Configuration parameters for a redis connection.
Connection handle, holding a redis context.
#define IPPOOL_STATIC_BIT
#define _IPPOOL_RCODE_NOT_FOUND
#define _IPPOOL_RCODE_POOL_EMPTY
@ IPPOOL_RCODE_DEVICE_MISMATCH
@ IPPOOL_RCODE_POOL_EMPTY
#define _IPPOOL_RCODE_DEVICE_MISMATCH
#define _IPPOOL_RCODE_SUCCESS
#define IPPOOL_SPRINT_IP(_buff, _ip, _prefix)
If the prefix is as wide as the AF data size then print it without CIDR notation.
#define IPPOOL_ADDRESS_KEY
static void ippool_action_print(request_t *request, ippool_action_t action, fr_log_lvl_t lvl, fr_value_box_t const *key_prefix, fr_value_box_t const *ip, fr_value_box_t const *owner, fr_value_box_t const *gateway_id, uint32_t expires)
tmpl_t * expiry_attr
Time at which the lease will expire.
fr_redis_cluster_t * cluster
Redis cluster.
static unlang_action_t mod_release(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_load(void)
static char lua_update_cmd[]
Lua script for updating leases.
fr_value_box_t pool_name
Name of the pool we're allocating IP addresses from.
static char lua_release_digest[(SHA1_DIGEST_LENGTH *2)+1]
static char lua_alloc_digest[(SHA1_DIGEST_LENGTH *2)+1]
char const * name
Instance name.
fr_value_box_t gateway_id
Gateway identifier, usually NAS-Identifier or Option 82 gateway.
tmpl_t * range_attr
Attribute to write the range ID to.
module_rlm_t rlm_redis_ippool
fr_value_box_t offer_time
How long we should reserve a lease for during the pre-allocation stage (typically responding to DHCP ...
static ippool_rcode_t redis_ippool_release(rlm_redis_ippool_t const *inst, request_t *request, fr_value_box_t const *key_prefix, fr_ipaddr_t *ip, fr_value_box_t const *owner)
Release an existing IP address in a pool.
fr_value_box_t gateway_id
Gateway identifier, usually NAS-Identifier or Option 82 gateway.
static const call_env_method_t redis_ippool_update_method_env
fr_value_box_t owner
Unique lease owner identifier.
static ippool_rcode_t redis_ippool_update(rlm_redis_ippool_t const *inst, request_t *request, redis_ippool_update_call_env_t *env, fr_ipaddr_t *ip, fr_value_box_t const *owner, fr_value_box_t const *gateway_id, uint32_t expires)
Update an existing IP address in a pool.
fr_value_box_t pool_name
Name of the pool we're allocating IP addresses from.
static unlang_action_t mod_alloc(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_value_box_t pool_name
Name of the pool we're allocating IP addresses from.
fr_value_box_t lease_time
How long an IP address should be allocated for.
fr_value_box_t gateway_id
Gateway identifier, usually NAS-Identifier or Option 82 gateway.
static conf_parser_t redis_config[]
fr_value_box_t requested_address
Attribute to read the IP for renewal from.
fr_value_box_t requested_address
Attribute to read the IP for renewal from.
static char lua_release_cmd[]
Lua script for releasing leases.
fr_redis_conf_t conf
Connection parameters for the Redis server.
static fr_redis_rcode_t ippool_script(redisReply **out, request_t *request, fr_redis_cluster_t *cluster, uint8_t const *key, size_t key_len, uint32_t wait_num, fr_time_delta_t wait_timeout, char const digest[], char const *script, char const *cmd,...)
Execute a script against Redis cluster.
uint32_t wait_num
How many slaves we want to acknowledge allocations or updates.
static const call_env_method_t redis_ippool_release_method_env
fr_time_delta_t wait_timeout
How long we wait for slaves to acknowledge writing.
bool copy_on_update
Copy the address provided by ip_address to the allocated_address_attr if updates are successful.
tmpl_t * expiry_attr
Time at which the lease will expire.
static char lua_alloc_cmd[]
Lua script for allocating new leases.
tmpl_t * range_attr
Attribute to write the range ID to.
static unlang_action_t mod_bulk_release(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
tmpl_t * allocated_address_attr
Attribute to populate with allocated IP.
static ippool_rcode_t redis_ippool_allocate(rlm_redis_ippool_t const *inst, request_t *request, redis_ippool_alloc_call_env_t *env, uint32_t lease_time)
Allocate a new IP address from a pool.
bool ipv4_integer
Whether IPv4 addresses should be cast to integers, for renew operations.
fr_value_box_t owner
Unique lease owner identifier.
tmpl_t * allocated_address_attr
Attribute to populate with allocated IP.
fr_value_box_t gateway_id
Gateway identifier, usually NAS-Identifier or Option 82 gateway.
fr_value_box_t lease_time
How long an IP address should be allocated for.
static unlang_action_t mod_update(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_value_box_t pool_name
Name of the pool we're allocating IP addresses from.
static const call_env_method_t redis_ippool_bulk_release_method_env
static char lua_update_digest[(SHA1_DIGEST_LENGTH *2)+1]
fr_value_box_t owner
Unique lease owner identifier.
static int ippool_wait_check(request_t *request, uint32_t wait_num, redisReply *reply)
Check the requisite number of slaves replicated the lease info.
static conf_parser_t module_config[]
fr_value_box_t requested_address
Attribute to read the IP for renewal from.
static const call_env_method_t redis_ippool_alloc_method_env
Call environment used when calling redis_ippool allocate method.
Call environment used when calling redis_ippool bulk release method.
Call environment used when calling redis_ippool release method.
Call environment used when calling redis_ippool update method.
rlm_redis module instance
static int instantiate(module_inst_ctx_t const *mctx)
#define FR_SBUFF_OUT(_start, _len_or_end)
#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.
#define tmpl_value(_tmpl)
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
@ TMPL_TYPE_DATA
Value in native boxed format.
tmpl_t * tmpl_init_shallow(tmpl_t *vpt, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len, tmpl_rules_t const *t_rules))
Initialise a tmpl without copying the input name string.
void fr_sha1_init(fr_sha1_ctx *context)
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
#define SHA1_DIGEST_LENGTH
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
#define fr_time()
Allow us to arbitrarily manipulate time.
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
#define talloc_get_type_abort_const
#define fr_time_to_timeval(_when)
Convert server epoch time to unix epoch time.
static int64_t fr_time_delta_to_msec(fr_time_delta_t delta)
A time delta, a difference in time measured in nanoseconds.
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
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.
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
#define fr_value_box(_box, _var, _tainted)
Automagically fill in a box, determining the value type from the type of the C variable.
static size_t char ** out