26 RCSID(
"$Id: b4e42b572f49276313b43c8d47b54a7d6cf4ccda $")
28 #define LOG_PREFIX inst->name
31 #include <freeradius-devel/util/debug.h>
32 #include <freeradius-devel/radius/radius.h>
33 #include <freeradius-devel/unlang/function.h>
145 #define RESERVE_CONNECTION(_handle, _sql, _request) if (!_sql->driver->uses_trunks) { \
146 handle = fr_pool_connection_get(_sql->pool, _request); \
148 REDEBUG("Failed reserving SQL connection"); \
149 RETURN_MODULE_FAIL; \
160 int rlen, retval = 0;
167 if (query_ctx->
rcode < 0) {
168 REDEBUG(
"Failed fetching query_result");
172 row = query_ctx->
row;
174 RDEBUG2(
"SQL query did not return any results");
179 REDEBUG(
"The first column of the result was NULL");
183 rlen = strlen(row[0]);
184 if (rlen >= outlen) {
185 REDEBUG(
"The first column of the result was too long (%d)", rlen);
224 if (strcmp(talloc_get_name(
inst->sql),
"rlm_sql_t") != 0) {
225 cf_log_err(
conf,
"Module \"%s\" is not an instance of the rlm_sql module",
242 #define REPEAT_MOD_ALLOC_RESUME if (unlang_function_repeat_set(request, mod_alloc_resume) < 0) RETURN_MODULE_FAIL
243 #define SUBMIT_QUERY(_query_str, _new_status, _type, _function) do { \
244 alloc_ctx->status = _new_status; \
245 REPEAT_MOD_ALLOC_RESUME; \
246 query_ctx->query_str = _query_str; \
247 query_ctx->type = _type; \
248 query_ctx->status = SQL_QUERY_PREPARED; \
249 alloc_ctx->query = query; \
250 return unlang_function_push(request, sql->_function, NULL, NULL, 0, UNLANG_SUB_FRAME, query_ctx); \
269 int allocation_len = 0;
286 switch (alloc_ctx->
status) {
308 goto expand_requested;
312 goto expand_requested;
315 TALLOC_FREE(alloc_ctx->
query);
319 if (allocation_len > 0)
goto make_pair;
339 TALLOC_FREE(alloc_ctx->
query);
343 if (allocation_len > 0)
goto make_pair;
358 TALLOC_FREE(alloc_ctx->
query);
363 if (allocation_len > 0)
goto make_pair;
386 RWDEBUG(
"IP address could not be allocated");
410 REDEBUG(
"Invalid IP address [%s] returned from database query.", allocation);
414 RDEBUG2(
"Allocated IP %s", allocation);
439 TALLOC_FREE(alloc_ctx->
query);
442 if (allocation_len) {
461 RWDEBUG(
"IP address could not be allocated as no pool exists with the name \"%pV\"",
471 TALLOC_FREE(alloc_ctx->
query);
535 .trunk = thread->
trunk,
548 fr_value_box_list_init(&alloc_ctx->
values);
717 &our_rules) < 0)
return -1;
718 *(
void **)
out = parsed_tmpl;
722 #define QUERY_ESCAPE .pair.escape = { \
723 .func = sqlippool_box_escape, \
724 .mode = TMPL_ESCAPE_PRE_CONCAT, \
725 .uctx = { .func = { .alloc = sql_escape_uctx_alloc }, .type = TMPL_ESCAPE_UCTX_ALLOC_FUNC }, \
726 }, .pair.func = call_env_parse
733 .pair.dflt =
"&control.IP-Pool.Name", .pair.dflt_quote =
T_BARE_WORD },
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
strcpy(log_entry->msg, buffer)
#define fr_atexit_thread_local(_name, _free, _uctx)
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_PARSE_OFFSET(_name, _cast_type, _flags, _struct, _field, _parse_field)
Specify a call_env_parser_t which writes out runtime results and the result of the parsing phase to t...
#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_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
module_instance_t const * mi
Module instance that the callenv is registered to.
#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_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
#define cf_log_err(_cf, _fmt,...)
fr_dcursor_eval_t void const * uctx
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
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.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
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_instance_t * module_rlm_static_by_name(module_instance_t const *parent, char const *asked_name)
module_t common
Common fields presented by all modules.
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
static const conf_parser_t config[]
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_RCODE(_rcode)
#define RLM_MODULE_USER_SECTION_REJECT
Rcodes that translate to a user configurable section failing overall.
#define RETURN_MODULE_UPDATED
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_UPDATED
OK (pairs modified).
#define RETURN_MODULE_NOTFOUND
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
void * request_data_reference(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request without removing it.
#define request_data_add(_request, _unique_ptr, _unique_int, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
static int instantiate(module_inst_ctx_t const *mctx)
Prototypes and functions for the SQL module.
trunk_t * trunk
Trunk connection for this thread.
fr_sql_query_status_t status
Status of the query.
rlm_sql_t const * inst
Module instance for this query.
char const * query_str
Query string to run.
request_t * request
Request this query relates to.
void * sql_escape_arg
Thread specific argument to be passed to escape function.
rlm_sql_row_t row
Row data from the last query.
sql_rcode_t rcode
Result code.
@ SQL_QUERY_PREPARED
Ready to submit.
static void * sql_escape_uctx_alloc(request_t *request, void const *uctx)
fr_value_box_t requested_address
IP address being requested by client.
#define REPEAT_MOD_ALLOC_RESUME
tmpl_t * pool_check
tmpl to expand as query for checking for existence of the pool.
static unlang_action_t mod_common_free_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Resume function called after mod_common "free" query has completed.
rlm_sql_handle_t * handle
SQL handle being used for queries.
static const call_env_method_t sqlippool_bulk_release_method_env
static int _sql_escape_uxtx_free(void *uctx)
fr_value_box_t allocated_address
Existing value for allocated IP.
fr_sql_query_t * query_ctx
Query context for allocation queries.
fr_value_box_t free
SQL query to clear other offered IPs. Only used in "update" method.
fr_value_box_list_t values
Where to put the expanded queries ready for execution.
static int call_env_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
Custom parser for sqlippool call env.
static const call_env_method_t sqlippool_release_method_env
rlm_rcode_t rcode
Result code to return after running "commit".
trunk_t * trunk
Trunk connection for queries.
static const call_env_method_t sqlippool_update_method_env
rlm_sql_t const * sql
SQL module instance.
#define RESERVE_CONNECTION(_handle, _sql, _request)
static int sqlippool_result_process(char *out, int outlen, fr_sql_query_t *query_ctx)
static unlang_action_t mod_alloc(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Initiate the allocation of an IP address from the pool.
request_t * request
Current request.
ippool_alloc_call_env_t * env
Call environment for the allocation.
ippool_common_call_env_t * env
Call environment for the update.
static const call_env_method_t sqlippool_alloc_method_env
fr_value_box_t * query
Current query being run.
request_t * request
Current request.
static unlang_action_t mod_common(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Common function used by module methods which perform an optional "free" then "update".
static const call_env_method_t sqlippool_mark_method_env
rlm_sql_handle_t * handle
SQL handle being used for queries.
static unlang_action_t mod_alloc_resume(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Resume function called after each IP allocation query is expanded.
static int sqlippool_box_escape(fr_value_box_t *vb, void *uctx)
Call SQL module box_escape_func to escape tainted values.
tmpl_t * pool_name_tmpl
Tmpl used to expand pool_name.
static unlang_action_t mod_common_update_resume(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
Resume function called after mod_common "update" query has completed.
fr_sql_query_t * query_ctx
Query context for allocation queries.
fr_value_box_t commit
SQL query to commit transaction.
tmpl_t * existing
tmpl to expand as query for finding the existing IP.
#define SUBMIT_QUERY(_query_str, _new_status, _type, _function)
tmpl_t * requested
tmpl to expand as query for finding the requested IP.
fr_value_box_t pool_name
Name of pool address will be allocated from.
static int sqlippool_common_ctx_free(ippool_common_ctx_t *to_free)
Return connection to pool when mod_common context is freed.
static int sqlippool_alloc_ctx_free(ippool_alloc_ctx_t *to_free)
Release SQL pool connections when alloc context is freed.
fr_value_box_t update
SQL query to update an IP record.
fr_value_box_t begin
SQL query to begin transaction.
tmpl_t * find
tmpl to expand as query for finding an unused IP.
tmpl_t * allocated_address_attr
Attribute to populate with allocated IP.
ippool_alloc_status_t status
Status of the allocation.
module_rlm_t rlm_sqlippool
ippool_alloc_status_t
Current step in IP allocation state machine.
@ IPPOOL_ALLOC_POOL_CHECK_RUN
Run the "pool_check" query.
@ IPPOOL_ALLOC_FIND_RUN
Run the "find" query.
@ IPPOOL_ALLOC_MAKE_PAIR
Make the pair.
@ IPPOOL_ALLOC_POOL_CHECK
Expanding the "pool_check" query.
@ IPPOOL_ALLOC_REQUESTED
Expanding the "requested" query.
@ IPPOOL_ALLOC_COMMIT_RUN
RUn the "commit" query.
@ IPPOOL_ALLOC_REQUESTED_RUN
Run the "requested" query.
@ IPPOOL_ALLOC_EXISTING_RUN
Run the "existing" query.
@ IPPOOL_ALLOC_UPDATE_RUN
Run the "update" query.
@ IPPOOL_ALLOC_FIND
Expanding the "find" query.
@ IPPOOL_ALLOC_EXISTING
Expanding the "existing" query.
@ IPPOOL_ALLOC_UPDATE
Expanding the "update" query.
@ IPPOOL_ALLOC_NO_ADDRESS
No address was found.
@ IPPOOL_ALLOC_BEGIN_RUN
Run the "begin" query.
static int mod_instantiate(module_inst_ctx_t const *mctx)
static conf_parser_t module_config[]
tmpl_t * update
tmpl to expand as query for updating the found IP.
rlm_sql_t const * sql
SQL module instance.
Call environment used by module alloc method.
Resume context for IP allocation.
Call environment used by all other module methods.
Resume context for IP update / release.
#define FR_SBUFF_IN(_start, _len_or_end)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
char const * name
Instance name e.g. user_database.
static module_thread_instance_t * module_thread(module_instance_t const *mi)
Retrieve module/thread specific instance for a module.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
void * data
Thread specific instance data.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
tmpl_escape_t escape
How escaping should be handled during evaluation.
fr_value_box_safe_for_t literals_safe_for
safe_for value assigned to literal values in xlats, execs, and data.
@ TMPL_TYPE_DATA
Value in native boxed format.
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
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.
Optional arguments passed to vp_tmpl functions.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
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.
int(* sql_affected_rows)(fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
sql_rcode_t(* sql_finish_query)(fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
sql_rcode_t(* sql_finish_select_query)(fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
unlang_function_t fetch_row
fr_value_box_escape_t box_escape_func
rlm_sql_driver_t const * driver
Driver's exported interface.
fr_sql_query_t *(* query_alloc)(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request, rlm_sql_handle_t *handle, trunk_t *trunk, char const *query_str, fr_sql_query_type_t type)
module_instance_t const * mi
Module instance data for thread lookups.
void * sql_escape_arg
Instance specific argument to be passed to escape function.
#define talloc_get_type_abort_const
int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args)
Push a tmpl onto the stack for evaluation.
fr_value_box_escape_t func
How to escape when returned from evaluation.
struct tmpl_escape_t::@74 uctx
fr_value_box_safe_for_t safe_for
Value to set on boxes which have been escaped by the fr_value_box_escape_t function.
Main trunk management handle.
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
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_MAX_STRING_LEN
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
static size_t char ** out