The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
sql.c
Go to the documentation of this file.
1/*
2 * sql.c rlm_sql - FreeRADIUS SQL Module
3 * Main code directly taken from ICRADIUS
4 *
5 * Version: $Id: 92777b2a5b1d4743f36d3e1b27ce64b89e68cb32 $
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 * @copyright 2001,2006 The FreeRADIUS server project
22 * @copyright 2000 Mike Machado (mike@innercite.com)
23 * @copyright 2000 Alan DeKok (aland@freeradius.org)
24 * @copyright 2001 Chad Miller (cmiller@surfsouth.com)
25 */
26
27RCSID("$Id: 92777b2a5b1d4743f36d3e1b27ce64b89e68cb32 $")
28
29#define LOG_PREFIX inst->name
30
31#include <freeradius-devel/server/base.h>
32#include <freeradius-devel/util/debug.h>
33
34#include <sys/file.h>
35#include <sys/stat.h>
36
37#include <ctype.h>
38
39#include "rlm_sql.h"
40
41/*
42 * Translate rlm_sql rcodes to humanly
43 * readable reason strings.
44 */
46 { L("need alt query"), RLM_SQL_ALT_QUERY },
47 { L("no connection"), RLM_SQL_RECONNECT },
48 { L("no more rows"), RLM_SQL_NO_MORE_ROWS },
49 { L("query invalid"), RLM_SQL_QUERY_INVALID },
50 { L("server error"), RLM_SQL_ERROR },
51 { L("success"), RLM_SQL_OK }
52};
54
56 { L("alternate"), RLM_SQL_ALT_QUERY },
57 { L("empty"), RLM_SQL_NO_MORE_ROWS },
58 { L("error"), RLM_SQL_ERROR },
59 { L("invalid"), RLM_SQL_QUERY_INVALID },
60 { L("ok"), RLM_SQL_OK },
61 { L("reconnect"), RLM_SQL_RECONNECT }
62};
64
65/** Call the driver's sql_fetch_row function
66 *
67 * Calls the driver's sql_fetch_row logging any errors. On success, will
68 * write row data to ``uctx->row``.
69 *
70 * The rcode within the query context is updated to
71 * - #RLM_SQL_OK on success.
72 * - other #sql_rcode_t constants on error.
73 *
74 * @param p_result Result of current module call.
75 * @param request Current request.
76 * @param uctx query context containing query to execute.
77 * @return an unlang_action_t.
78 */
80{
81 fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
82 rlm_sql_t const *inst = query_ctx->inst;
83
84 if (!query_ctx->tconn) {
85 ROPTIONAL(RERROR, ERROR, "Invalid connection");
86 query_ctx->rcode = RLM_SQL_ERROR;
88 }
89
90 /*
91 * We can't implement reconnect logic here, because the caller
92 * may require the original connection to free up queries or
93 * result sets associated with that connection.
94 */
95 (inst->driver->sql_fetch_row)(p_result, request, query_ctx);
96 switch (query_ctx->rcode) {
97 case RLM_SQL_OK:
98 fr_assert(query_ctx->row != NULL);
100
102 fr_assert(query_ctx->row == NULL);
104
105 default:
106 ROPTIONAL(RERROR, ERROR, "Error fetching row");
107 rlm_sql_print_error(inst, request, query_ctx, false);
109 }
110}
111
112/** Retrieve any errors from the SQL driver
113 *
114 * Retrieves errors from the driver from the last operation and writes them to
115 * to request/global log, in the ERROR, WARN, INFO and DEBUG categories.
116 *
117 * @param inst Instance of rlm_sql.
118 * @param request Current request, may be NULL.
119 * @param query_ctx Query context to retrieve errors for.
120 * @param force_debug Force all errors to be logged as debug messages.
121 */
122void rlm_sql_print_error(rlm_sql_t const *inst, request_t *request, fr_sql_query_t *query_ctx, bool force_debug)
123{
124 char const *driver = inst->driver_submodule->name;
125 sql_log_entry_t log[20];
126 size_t num, i;
127 TALLOC_CTX *log_ctx;
128
129 /*
130 * Every driver reads the errors off the connection handle, which the
131 * trunk frees when it closes the connection. A query that failed
132 * because its connection died is resumed after that has happened,
133 * so there is nothing left to ask the driver for.
134 */
135 if (!query_ctx->tconn || query_ctx->tconn->conn->is_closed) {
136 ROPTIONAL(RERROR, ERROR, "%s: Connection closed", driver);
137 return;
138 }
139
140 log_ctx = talloc_new(NULL);
141
142 num = (inst->driver->sql_error)(log_ctx, log, (NUM_ELEMENTS(log)), query_ctx);
143 if (num == 0) {
144 ROPTIONAL(RERROR, ERROR, "Unknown error");
145 talloc_free(log_ctx);
146 return;
147 }
148
149 for (i = 0; i < num; i++) {
150 if (force_debug) goto debug;
151
152 switch (log[i].type) {
153 case L_ERR:
154 ROPTIONAL(RERROR, ERROR, "%s: %s", driver, log[i].msg);
155 break;
156
157 case L_WARN:
158 ROPTIONAL(RWARN, WARN, "%s: %s", driver, log[i].msg);
159 break;
160
161 case L_INFO:
162 ROPTIONAL(RINFO, INFO, "%s: %s", driver, log[i].msg);
163 break;
164
165 case L_DBG:
166 default:
167 debug:
168 ROPTIONAL(RDEBUG2, DEBUG2, "%s: %s", driver, log[i].msg);
169 break;
170 }
171 }
172
173 talloc_free(log_ctx);
174}
175
176/** Automatically run the correct `finish` function when freeing an SQL query
177 *
178 * And mark any associated trunk request as complete.
179 */
181{
182 if (to_free->status > 0) {
183 if (to_free->type == SQL_QUERY_SELECT) {
184 (to_free->inst->driver->sql_finish_select_query)(to_free, &to_free->inst->config);
185 } else {
186 (to_free->inst->driver->sql_finish_query)(to_free, &to_free->inst->config);
187 }
188 }
189 if (to_free->treq) trunk_request_signal_complete(to_free->treq);
190 return 0;
191}
192
193/** Allocate an sql query structure
194 *
195 */
196fr_sql_query_t *fr_sql_query_alloc(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request,
197 trunk_t *trunk, char const *query_str, fr_sql_query_type_t type)
198{
199 fr_sql_query_t *query;
200 MEM(query = talloc(ctx, fr_sql_query_t));
201 *query = (fr_sql_query_t) {
202 .inst = inst,
203 .request = request,
204 .trunk = trunk,
205 .query_str = query_str,
206 .type = type
207 };
208 talloc_set_destructor(query, fr_sql_query_free);
209 return query;
210}
211
212/** Yield processing after submitting a trunk request.
213 */
215 UNUSED request_t *request, UNUSED void *uctx)
216{
217 return UNLANG_ACTION_YIELD;
218}
219
220/** Cancel an SQL query submitted on a trunk
221 */
222static void sql_trunk_query_cancel(request_t *request, UNUSED fr_signal_t action, void *uctx)
223{
224 fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
225 trunk_request_t *treq;
226
227 if (!query_ctx->treq) return;
228 treq = query_ctx->treq;
229
230 /*
231 * A reapable trunk request has already completed.
232 */
233 if (unlikely(treq->state == TRUNK_REQUEST_STATE_REAPABLE)) {
234 fr_sql_query_free(query_ctx);
235 query_ctx->treq = NULL;
236 query_ctx->status = 0;
237 query_ctx->tconn = NULL;
238 return;
239 }
240
241 RDEBUG2("Forcefully cancelling query %s", query_ctx->query_str);
242
243 /*
244 * The query_ctx needs to be parented by the treq so that it still exists
245 * when the cancel_mux callback is run.
246 */
247 if (query_ctx->inst->driver->trunk_io_funcs.request_cancel_mux) talloc_steal(treq, query_ctx);
248 query_ctx->treq = NULL;
249
251}
252
253/** Submit an SQL query using a trunk connection.
254 *
255 * @param p_result Result of current module call.
256 * @param request Current request.
257 * @param uctx query context containing query to execute.
258 * @return an unlang_action_t.
259 */
261{
262 fr_sql_query_t *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
263 trunk_enqueue_t status;
264
265 fr_assert(query_ctx->trunk);
266
267 /* There's no query to run, return an error */
268 if (query_ctx->query_str[0] == '\0') {
269 if (request) REDEBUG("Zero length query");
271 }
272
273 /*
274 * If the query already has a treq, and that is not in the "init" state
275 * then this is part of an ongoing transaction and needs requeueing
276 * to submit on the same connection.
277 */
278 if (query_ctx->treq && query_ctx->treq->state != TRUNK_REQUEST_STATE_INIT) {
279 status = trunk_request_requeue(query_ctx->treq);
280 } else {
281 status = trunk_request_enqueue(&query_ctx->treq, query_ctx->trunk, request, query_ctx, NULL);
282 }
283 switch (status) {
284 case TRUNK_ENQUEUE_OK:
286 /*
287 * Drivers such as SQLite which are synchronous run the query immediately
288 * on queueing. If the query fails then the trunk request will be failed
289 * in which case the query_ctx will no longer have a trunk request.
290 */
291 if (!query_ctx->treq) RETURN_UNLANG_FAIL;
292
293 /*
294 * Synchronous drivers will have processed the query and set the
295 * state of the trunk request to reapable - so in that case don't
296 * yield (in sql_trunk_query_start)
297 */
298 if (unlang_function_push_with_result(/* allow the caller of rlm_sql_trunk_query to get at the rcode */p_result,
299 request,
300 query_ctx->treq->state == TRUNK_REQUEST_STATE_REAPABLE ?
302 query_ctx->type == SQL_QUERY_SELECT ?
303 query_ctx->inst->driver->sql_select_query_resume :
304 query_ctx->inst->driver->sql_query_resume,
305 sql_trunk_query_cancel, ~FR_SIGNAL_CANCEL,
306 UNLANG_SUB_FRAME, query_ctx) < 0) RETURN_UNLANG_FAIL;
307 p_result->rcode = RLM_MODULE_OK;
309
310 default:
311 REDEBUG("Unable to enqueue SQL query");
312 query_ctx->status = SQL_QUERY_FAILED;
313 query_ctx->rcode = RLM_SQL_ERROR;
315 }
316}
317
318/** Process the results of an SQL query to produce a map list.
319 *
320 */
322{
323 fr_sql_map_ctx_t *map_ctx = talloc_get_type_abort(uctx, fr_sql_map_ctx_t);
324 tmpl_rules_t lhs_rules = (tmpl_rules_t) {
325 .attr = {
326 .dict_def = request->local_dict,
327 .list_def = map_ctx->list,
328 .list_presence = TMPL_ATTR_LIST_ALLOW
329 }
330 };
331 tmpl_rules_t rhs_rules = lhs_rules;
332 fr_sql_query_t *query_ctx = map_ctx->query_ctx;
333 rlm_sql_row_t row;
334 map_t *parent = NULL;
335 rlm_sql_t const *inst = map_ctx->inst;
336
338
339 if (query_ctx->rcode != RLM_SQL_OK) {
340 rlm_sql_print_error(inst, request, query_ctx, false);
342 }
343
344 while ((inst->fetch_row(p_result, request, query_ctx) == UNLANG_ACTION_CALCULATE_RESULT) &&
345 (query_ctx->rcode == RLM_SQL_OK)) {
346 map_t *map;
347
348 row = query_ctx->row;
349 if (!row[2] || !row[3] || !row[4]) {
350 RPERROR("SQL query returned NULL values");
352 }
353 if (map_afrom_fields(map_ctx->ctx, &map, &parent, request, row[2], row[4], row[3],
354 &lhs_rules, &rhs_rules,
355 !(inst->config.expand_rhs || map_ctx->expand_rhs)) < 0) {
356 RPEDEBUG("Data read from SQL cannot be parsed.");
357 REDEBUG(" %s", row[2]);
358 REDEBUG(" %s", row[4]);
359 REDEBUG(" %s", row[3]);
361 }
362 if (!map->parent) map_list_insert_tail(map_ctx->out, map);
363
364 map_ctx->rows++;
365 }
366 talloc_free(query_ctx);
367
369}
370
371/** Submit the query to get any user / group check or reply pairs
372 *
373 */
375{
376 rlm_sql_t const *inst = map_ctx->inst;
377
378 fr_assert(request);
379 fr_assert(map_ctx->query);
380
381 MEM(map_ctx->query_ctx = fr_sql_query_alloc(map_ctx->ctx, inst, request, trunk,
382 map_ctx->query->vb_strvalue, SQL_QUERY_SELECT));
383
385 request,
386 NULL,
388 NULL, 0,
390 map_ctx) < 0) return UNLANG_ACTION_FAIL;
391
392 return unlang_function_push_with_result(/* discard, sql_get_map_list_resume uses query_ctx->rcode */ NULL,
393 request,
394 inst->select,
395 NULL,
396 NULL, 0,
398 map_ctx->query_ctx);
399}
400
401/*
402 * Log the query to a file.
403 */
404void rlm_sql_query_log(rlm_sql_t const *inst, char const *filename, char const *query)
405{
406 int fd;
407 size_t len;
408 bool failed = false; /* Write the log message outside of the critical region */
409
410 fd = exfile_open(inst->ef, filename, 0640, 0, NULL);
411 if (fd < 0) {
412 ERROR("Couldn't open logfile '%s': %s", filename, fr_syserror(errno));
413
414 /* coverity[missing_unlock] */
415 return;
416 }
417
418 len = strlen(query);
419 if ((write(fd, query, len) < 0) || (write(fd, ";\n", 2) < 0)) failed = true;
420
421 if (failed) ERROR("Failed writing to logfile '%s': %s", filename, fr_syserror(errno));
422
423 exfile_close(inst->ef, fd);
424}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:39
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
Definition action.h:41
log_entry msg
Definition acutest.h:794
#define RCSID(id)
Definition build.h:560
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:228
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
#define NUM_ELEMENTS(_t)
Definition build.h:406
#define MEM(x)
Definition debug.h:38
#define ERROR(fmt,...)
Definition dhcpclient.c:40
int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, int flags, off_t *offset)
Open a new log file, or maybe an existing one.
Definition exfile.c:528
int exfile_close(exfile_t *ef, int fd)
Close the log file.
Definition exfile.c:595
#define unlang_function_push_with_result(_result_p, _request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack that produces a result.
Definition function.h:144
talloc_free(hp)
#define UNLANG_SUB_FRAME
Definition interpret.h:37
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
Definition interpret.h:140
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition log.h:545
#define RWARN(fmt,...)
Definition log.h:314
#define RERROR(fmt,...)
Definition log.h:315
#define RPERROR(fmt,...)
Definition log.h:319
#define RINFO(fmt,...)
Definition log.h:313
#define RPEDEBUG(fmt,...)
Definition log.h:393
int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, request_t *request, char const *lhs, char const *op_str, char const *rhs, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, bool bare_word_only)
Convert a fr_pair_t into a map.
Definition map.c:2459
@ L_WARN
Warning.
Definition log.h:54
@ L_ERR
Error message.
Definition log.h:53
@ L_INFO
Informational message.
Definition log.h:52
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:56
static TALLOC_CTX * map_ctx
Definition map_builtin.c:32
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
#define DEBUG2(fmt,...)
#define WARN(fmt,...)
#define INFO(fmt,...)
Definition radict.c:63
#define RETURN_UNLANG_INVALID
Definition rcode.h:66
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
#define RETURN_UNLANG_OK
Definition rcode.h:64
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:49
fr_dict_attr_t const * request_attr_request
Definition request.c:43
Prototypes and functions for the SQL module.
fr_sql_query_status_t status
Status of the query.
Definition rlm_sql.h:144
trunk_connection_t * tconn
Trunk connection this query is being run on.
Definition rlm_sql.h:140
fr_sql_query_type_t type
Type of query.
Definition rlm_sql.h:143
trunk_t * trunk
Trunk this query is being run on.
Definition rlm_sql.h:139
rlm_sql_t const * inst
Module instance for this query.
Definition rlm_sql.h:137
char const * query_str
Query string to run.
Definition rlm_sql.h:142
@ RLM_SQL_QUERY_INVALID
Query syntax error.
Definition rlm_sql.h:45
@ RLM_SQL_ALT_QUERY
Key constraint violation, use an alternative query.
Definition rlm_sql.h:49
@ RLM_SQL_RECONNECT
Stale connection, should reconnect.
Definition rlm_sql.h:48
@ RLM_SQL_ERROR
General connection/server error.
Definition rlm_sql.h:46
@ RLM_SQL_OK
Success.
Definition rlm_sql.h:47
@ RLM_SQL_NO_MORE_ROWS
No more rows available.
Definition rlm_sql.h:50
fr_sql_query_type_t
Definition rlm_sql.h:119
@ SQL_QUERY_SELECT
Definition rlm_sql.h:120
char ** rlm_sql_row_t
Definition rlm_sql.h:59
rlm_sql_row_t row
Row data from the last query.
Definition rlm_sql.h:146
sql_rcode_t rcode
Result code.
Definition rlm_sql.h:145
trunk_request_t * treq
Trunk request for this query.
Definition rlm_sql.h:141
@ SQL_QUERY_FAILED
Failed to submit.
Definition rlm_sql.h:127
Context used when fetching attribute value pairs as a map list.
Definition rlm_sql.h:152
Definition rlm_sql.h:61
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:339
@ TMPL_ATTR_LIST_ALLOW
Attribute refs are allowed to have a list.
Definition tmpl.h:262
struct tmpl_rules_s tmpl_rules_t
Definition tmpl.h:233
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
fr_sql_query_t * fr_sql_query_alloc(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request, trunk_t *trunk, char const *query_str, fr_sql_query_type_t type)
Allocate an sql query structure.
Definition sql.c:196
size_t sql_rcode_table_len
Definition sql.c:63
static int fr_sql_query_free(fr_sql_query_t *to_free)
Automatically run the correct finish function when freeing an SQL query.
Definition sql.c:180
static void sql_trunk_query_cancel(request_t *request, UNUSED fr_signal_t action, void *uctx)
Cancel an SQL query submitted on a trunk.
Definition sql.c:222
unlang_action_t sql_get_map_list(unlang_result_t *p_result, request_t *request, fr_sql_map_ctx_t *map_ctx, trunk_t *trunk)
Submit the query to get any user / group check or reply pairs.
Definition sql.c:374
unlang_action_t rlm_sql_fetch_row(unlang_result_t *p_result, request_t *request, void *uctx)
Call the driver's sql_fetch_row function.
Definition sql.c:79
void rlm_sql_query_log(rlm_sql_t const *inst, char const *filename, char const *query)
Definition sql.c:404
static unlang_action_t sql_get_map_list_resume(unlang_result_t *p_result, request_t *request, void *uctx)
Process the results of an SQL query to produce a map list.
Definition sql.c:321
fr_table_num_sorted_t const sql_rcode_table[]
Definition sql.c:55
static unlang_action_t sql_trunk_query_start(UNUSED unlang_result_t *p_result, UNUSED request_t *request, UNUSED void *uctx)
Yield processing after submitting a trunk request.
Definition sql.c:214
void rlm_sql_print_error(rlm_sql_t const *inst, request_t *request, fr_sql_query_t *query_ctx, bool force_debug)
Retrieve any errors from the SQL driver.
Definition sql.c:122
size_t sql_rcode_description_table_len
Definition sql.c:53
fr_table_num_sorted_t const sql_rcode_description_table[]
Definition sql.c:45
unlang_action_t rlm_sql_trunk_query(unlang_result_t *p_result, request_t *request, void *uctx)
Submit an SQL query using a trunk connection.
Definition sql.c:260
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
Value pair map.
Definition map.h:77
map_t * parent
Definition map.h:88
unlang_function_with_result_t sql_select_query_resume
Callback run after an SQL select trunk query is run.
Definition rlm_sql.h:206
trunk_io_funcs_t trunk_io_funcs
Trunk callback functions for this driver.
Definition rlm_sql.h:224
sql_rcode_t(* sql_finish_query)(fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
Definition rlm_sql.h:217
sql_rcode_t(* sql_finish_select_query)(fr_sql_query_t *query_ctx, rlm_sql_config_t const *config)
Definition rlm_sql.h:218
unlang_function_with_result_t sql_query_resume
Callback run after an SQL trunk query is run.
Definition rlm_sql.h:205
rlm_sql_config_t config
Definition rlm_sql.h:228
rlm_sql_driver_t const * driver
Driver's exported interface.
Definition rlm_sql.h:235
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
Definition tmpl.h:295
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
trunk_enqueue_t trunk_request_enqueue(trunk_request_t **treq_out, trunk_t *trunk, request_t *request, void *preq, void *rctx)
Enqueue a request that needs data written to the trunk.
Definition trunk.c:2657
trunk_enqueue_t trunk_request_requeue(trunk_request_t *treq)
Re-enqueue a request on the same connection.
Definition trunk.c:2746
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
Definition trunk.c:2216
void trunk_request_signal_complete(trunk_request_t *treq)
Signal that a trunk request is complete.
Definition trunk.c:2158
Wraps a normal request.
Definition trunk.c:99
Main trunk management handle.
Definition trunk.c:219
trunk_enqueue_t
Definition trunk.h:158
@ TRUNK_ENQUEUE_OK
Operation was successful.
Definition trunk.h:160
@ TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
Definition trunk.h:159
trunk_request_cancel_mux_t request_cancel_mux
!< Read one or more requests from a connection.
Definition trunk.h:760
@ TRUNK_REQUEST_STATE_REAPABLE
Request has been written, needs to persist, but we are not currently waiting for any response.
Definition trunk.h:183
@ TRUNK_REQUEST_STATE_INIT
Initial state.
Definition trunk.h:172
static fr_slen_t parent
Definition pair.h:858