The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_ftp.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: c2cc907ccdd203f13be0bc9e9122dc0345974839 $
19 * @file rlm_ftp.c
20 * @brief Fetch objects from FTP endpoints
21 *
22 * @copyright 2025 NetworkRADIUS SARL (legal@networkradius.com)
23 */
24RCSID("$Id: c2cc907ccdd203f13be0bc9e9122dc0345974839 $")
25
26#include <freeradius-devel/curl/base.h>
27#include <freeradius-devel/curl/xlat.h>
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/cf_parse.h>
30
31#include <freeradius-devel/server/global_lib.h>
32#include <freeradius-devel/server/tmpl.h>
33#include <freeradius-devel/server/log.h>
34#include <freeradius-devel/util/atexit.h>
35#include <freeradius-devel/util/debug.h>
36#include <freeradius-devel/util/uri.h>
37#include <freeradius-devel/unlang/call_env.h>
38#include <freeradius-devel/unlang/xlat_func.h>
39
40#define FTP_BODY_ALLOC_CHUNK 1024
41
42typedef struct {
43 fr_curl_conn_config_t conn_config; //!< Configuration of slab allocated connection handles.
44 size_t max_resp_size; //!< Maximum size of incoming data.
45 bool binary; //!< Do we expect binary data - and so output octets.
46} rlm_ftp_t;
47
50
51typedef struct {
52 rlm_ftp_t const *inst; //!< Instance of rlm_ftp.
53 ftp_slab_list_t *slab; //!< Slab list for connection handles.
54 fr_curl_handle_t *mhandle; //!< Thread specific multi handle. Serves as the dispatch
55 //!< and coralling structure for FTP requests.
57
58typedef struct {
59 fr_curl_io_request_t *handle; //!< curl easy handle servicing our request.
61
62/*
63 * States for the response
64 */
70
71/*
72 * Curl inbound data context (passed to CURLOPT_WRITEFUNCTION as CURLOPT_WRITEDATA)
73 */
74typedef struct {
75 rlm_ftp_t const *instance; //!< This instance of rlm_ftp.
76
77 request_t *request; //!< Current request.
78 write_state_t state; //!< Decoder state.
79
80 char *buffer; //!< Raw incoming FTP data.
81 size_t alloc; //!< Space allocated for buffer.
82 size_t used; //!< Space used in buffer.
84
85/*
86 * Curl context data
87 */
88typedef struct {
89 rlm_ftp_response_t response; //!< Response context data.
91
92static int ftp_uri_part_escape(fr_value_box_t *vb, void *uctx);
93
94static fr_uri_part_t const ftp_uri_parts[] = {
95 { .name = "scheme", .safe_for = CURL_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L(":")), .part_adv = { [':'] = 1 }, .extra_skip = 2 },
96 { .name = "host", .safe_for = CURL_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L(":"), L("/")), .part_adv = { [':'] = 1, ['/'] = 2 }, .func = ftp_uri_part_escape },
97 { .name = "port", .safe_for = CURL_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L("/")), .part_adv = { ['/'] = 1 } },
98 { .name = "method", .safe_for = CURL_URI_SAFE_FOR, .func = ftp_uri_part_escape },
100};
101
102static const conf_parser_t module_config[] = {
103 { FR_CONF_OFFSET_TYPE_FLAGS("max_resp_size", FR_TYPE_SIZE, 0, rlm_ftp_t, max_resp_size), .dflt = "16k" },
104 { FR_CONF_OFFSET("binary", rlm_ftp_t, binary), .dflt = "no" },
105
106 { FR_CONF_OFFSET_SUBSECTION("connection", 0, rlm_ftp_t, conn_config, fr_curl_conn_config) },
107
109};
110
111extern global_lib_autoinst_t const * const rlm_ftp_lib[];
116
117/** URL escape a single box forming part of a URL
118 *
119 * @param[in] vb to escape
120 * @param[in] uctx UNUSED context containing CURL handle
121 * @return
122 * - 0 on success
123 * - -1 on failure
124 */
125static int ftp_uri_part_escape(fr_value_box_t *vb, UNUSED void *uctx)
126{
127 char *escaped, *str;
128
129 escaped = curl_easy_escape(fr_curl_tmp_handle(), vb->vb_strvalue, vb->vb_length);
130 if (!escaped) return -1;
131
132 /*
133 * Returned string the same length - nothing changed
134 */
135 if (strlen(escaped) == vb->vb_length) {
136 curl_free(escaped);
137 return 0;
138 }
139
140 str = talloc_typed_strdup(vb, escaped);
141 fr_value_box_strdup_shallow_replace(vb, str, strlen(str));
142
143 curl_free(escaped);
144
145 return 0;
146}
147
148static xlat_action_t ftp_get_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx,
149 UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
150{
151 rlm_ftp_t const *inst = talloc_get_type_abort(xctx->mctx->mi->data, rlm_ftp_t);
152 rlm_ftp_xlat_rctx_t *rctx = talloc_get_type_abort(xctx->rctx, rlm_ftp_xlat_rctx_t);
153 fr_curl_io_request_t *handle = talloc_get_type_abort(rctx->handle, fr_curl_io_request_t);
154 rlm_ftp_curl_context_t *curl_ctx = talloc_get_type_abort(handle->uctx, rlm_ftp_curl_context_t);
156
157 switch (curl_ctx->response.state) {
158 case WRITE_STATE_INIT:
160 xa = XLAT_ACTION_FAIL;
161 goto finish;
162
164 break;
165 }
166
167 if (curl_ctx->response.used > 0) {
168 fr_value_box_t *vb;
169
170 MEM(vb = fr_value_box_alloc_null(ctx));
171 if (inst->binary) {
172 fr_value_box_memdup(vb, vb, NULL, (uint8_t *)curl_ctx->response.buffer, curl_ctx->response.used, true);
173 } else {
174 fr_value_box_bstrndup(vb, vb, NULL, curl_ctx->response.buffer, curl_ctx->response.used, true);
175 }
177 }
178
179finish:
180 ftp_slab_release(handle);
181 talloc_free(rctx);
182
183 return xa;
184}
185
186static void ftp_io_xlat_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
187{
188 rlm_ftp_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, rlm_ftp_thread_t);
189 rlm_ftp_xlat_rctx_t *our_rctx = talloc_get_type_abort(xctx->rctx, rlm_ftp_xlat_rctx_t);
190 fr_curl_io_request_t *randle = talloc_get_type_abort(our_rctx->handle, fr_curl_io_request_t);
191 CURLMcode ret;
192
193 RDEBUG2("Forcefully cancelling pending FTP request");
194
195 ret = curl_multi_remove_handle(t->mhandle->mandle, randle->candle); /* Gracefully terminate the request */
196 if (ret != CURLM_OK) {
197 RERROR("Failed removing curl handle from multi-handle: %s (%i)", curl_multi_strerror(ret), ret);
198 /* Not much we can do */
199 }
200 t->mhandle->transfers--;
201
202 ftp_slab_release(randle);
203}
204
205
206static size_t ftp_response_body(void *in, size_t size, size_t nmemb, void *userdata)
207{
208 rlm_ftp_response_t *ctx = userdata;
209 request_t *request = ctx->request; /* Used by RDEBUG */
210
211 char const *start = in, *p = start, *end = p + (size * nmemb);
212 char *out_p;
213 size_t needed;
214
215 if (start == end) return 0; /* Nothing to process */
216
217 if ((ctx->instance->max_resp_size > 0) && ((ctx->used + (end - p)) > ctx->instance->max_resp_size)) {
218 REDEBUG("Incoming data (%zu bytes) exceeds max_body_in (%zu bytes). "
219 "Forcing body to type 'invalid'", ctx->used + (end - p), ctx->instance->max_resp_size);
221 TALLOC_FREE(ctx->buffer);
222 goto end;
223 }
224
225 needed = ROUND_UP(ctx->used + (end - p), FTP_BODY_ALLOC_CHUNK);
226 if (needed > ctx->alloc) {
227 MEM(ctx->buffer = talloc_bstr_realloc(NULL, ctx->buffer, needed));
228 ctx->alloc = needed;
229 }
230
231 out_p = ctx->buffer + ctx->used;
232 memcpy(out_p, p, (end - p));
233 out_p += (end - p);
234 *out_p = '\0';
235 ctx->used += (end - p);
237
238end:
239 return (end - start);
240}
241
242
244 { .required = true, .safe_for = CURL_URI_SAFE_FOR, .type = FR_TYPE_STRING, .will_escape = true }, /* URL */
246};
247
248/** Simple xlat to read data from an FTP URI
249 *
250 * Example:
251@verbatim
252%ftp.get('ftp://example.com/file.txt')
253@endverbatim
254 *
255 * @ingroup xlat_functions
256 */
258 xlat_ctx_t const *xctx, request_t *request,
259 fr_value_box_list_t *in)
260{
261 rlm_ftp_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, rlm_ftp_thread_t);
262 fr_curl_io_request_t *randle = NULL;
263 int ret;
264 fr_value_box_t *uri_vb;
265 rlm_ftp_curl_context_t *curl_ctx;
267
268 XLAT_ARGS(in, &uri_vb);
269
270 MEM(rctx = talloc(request, rlm_ftp_xlat_rctx_t));
271
272 /*
273 * Handle URI component escaping
274 */
275 if (fr_uri_escape_list(&uri_vb->vb_group, ftp_uri_parts, NULL) < 0) {
276 RPEDEBUG("Failed escaping URI");
277 error:
278 return XLAT_ACTION_FAIL;
279 }
280
282 uri_vb, &uri_vb->vb_group, FR_TYPE_STRING,
284 SIZE_MAX) < 0) {
285 REDEBUG("Concatenating URI");
286 goto error;
287 }
288
289 /*
290 * We get a connection from the pool here as the CURL object
291 * is needed to use curl_easy_escape() for escaping
292 */
293 randle = rctx->handle = ftp_slab_reserve(t->slab);
294 if (!randle) return XLAT_ACTION_FAIL;
295
296 randle->request = request; /* Populate the request pointer for escape callbacks */
297 curl_ctx = talloc_get_type_abort(randle->uctx, rlm_ftp_curl_context_t);
298
299 RDEBUG2("Sending FTP GET to \"%pV\"", uri_vb);
300
301 /*
302 * Configure various CURL options, and initialise the read/write
303 * context data.
304 */
305 FR_CURL_REQUEST_SET_OPTION(CURLOPT_URL, uri_vb->vb_strvalue);
306#if CURL_AT_LEAST_VERSION(7,85,0)
307 FR_CURL_REQUEST_SET_OPTION(CURLOPT_PROTOCOLS_STR, "ftp");
308#else
309 FR_CURL_REQUEST_SET_OPTION(CURLOPT_PROTOCOLS, CURLPROTO_FTP);
310#endif
311 FR_CURL_REQUEST_SET_OPTION(CURLOPT_WRITEFUNCTION, ftp_response_body);
312 FR_CURL_REQUEST_SET_OPTION(CURLOPT_WRITEDATA, &curl_ctx->response);
313
314 /*
315 * Send the CURL request
316 */
317 ret = fr_curl_io_request_enqueue(t->mhandle, request, randle);
318 if (ret < 0) {
319 ftp_slab_release(randle);
320 goto error;
321 }
322
324}
325
326/** Cleans up after a FTP request.
327 *
328 * Resets all options associated with a CURL handle, and frees any headers
329 * associated with it.
330 *
331 * Calls ftp_read_ctx_free and ftp_response_free to free any memory used by
332 * context data.
333 *
334 * @param[in] randle to cleanup.
335 * @param[in] uctx unused.
336 */
337static int _ftp_request_cleanup(fr_curl_io_request_t *randle, UNUSED void *uctx)
338{
339 rlm_ftp_curl_context_t *ctx = talloc_get_type_abort(randle->uctx, rlm_ftp_curl_context_t);
340 CURL *candle = randle->candle;
341
342 /*
343 * Clear any previously configured options
344 */
345 curl_easy_reset(candle);
346
347#ifndef NDEBUG
348 {
349 CURLcode ret;
350 /*
351 * With curl 7.61 when a request in cancelled we get a result
352 * with a NULL (invalid) pointer to private data. This lets
353 * us know that the request was returned to the slab.
354 */
355 ret = curl_easy_setopt(candle, CURLOPT_PRIVATE, (void *)0xdeadc341);
356 if (unlikely(ret != CURLE_OK)) {
357 ERROR("Failed to set private data on curl easy handle %p: %s",
358 candle, curl_easy_strerror(ret));
359 }
360 }
361#endif
362
363 /*
364 * Free response data
365 */
366 TALLOC_FREE(ctx->response.buffer);
367 ctx->response.alloc = 0;
368 ctx->response.used = 0;
369
370 randle->request = NULL;
371 return 0;
372}
373
375{
376 curl_easy_cleanup(randle->candle);
377 return 0;
378}
379
380static int ftp_conn_alloc(fr_curl_io_request_t *randle, void *uctx)
381{
382 rlm_ftp_t const *inst = talloc_get_type_abort(uctx, rlm_ftp_t);
383 rlm_ftp_curl_context_t *curl_ctx = NULL;
384
385 randle->candle = curl_easy_init();
386 if (unlikely(!randle->candle)) {
387 fr_strerror_printf("Unable to initialise CURL handle");
388 return -1;
389 }
390
391 MEM(curl_ctx = talloc_zero(randle, rlm_ftp_curl_context_t));
392 curl_ctx->response.instance = inst;
393
394 randle->uctx = curl_ctx;
395 talloc_set_destructor(randle, _mod_conn_free);
396
397 ftp_slab_element_set_destructor(randle, _ftp_request_cleanup, NULL);
398
399 return 0;
400}
401
402/** Create a thread specific multihandle
403 *
404 * Easy handles representing requests are added to the curl multihandle
405 * with the multihandle used for mux/demux.
406 *
407 * @param[in] mctx Thread instantiation data.
408 * @return
409 * - 0 on success.
410 * - -1 on failure.
411 */
413{
414 rlm_ftp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_ftp_t);
415 rlm_ftp_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_ftp_thread_t);
416 fr_curl_handle_t *mhandle;
417
418 t->inst = inst;
419
420 if (!(t->slab = ftp_slab_list_alloc(t, mctx->el, &inst->conn_config.reuse,
421 ftp_conn_alloc, NULL, inst, false, false))) {
422 ERROR("Connection handle pool instantiation failed");
423 return -1;
424 }
425
426 mhandle = fr_curl_io_init(t, mctx->el, false);
427 if (!mhandle) return -1;
428
429 t->mhandle = mhandle;
430
431 return 0;
432}
433
434/** Cleanup all outstanding requests associated with this thread
435 *
436 * Destroys all curl easy handles, and then the multihandle associated
437 * with this thread.
438 *
439 * @param[in] mctx data to destroy.
440 * @return 0
441 */
443{
444 rlm_ftp_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_ftp_thread_t);
445
446 talloc_free(t->mhandle); /* Ensure this is shutdown before the pool */
447 talloc_free(t->slab);
448
449 return 0;
450}
451
452static int mod_bootstrap(module_inst_ctx_t const *mctx)
453{
454 xlat_t *xlat;
455 rlm_ftp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_ftp_t);
456
457 if (unlikely(!(xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "get", ftp_get_xlat,
458 inst->binary ? FR_TYPE_OCTETS : FR_TYPE_STRING)))) return -1;
460
461 return 0;
462}
463
464static int mod_instantiate(module_inst_ctx_t const *mctx)
465{
466 rlm_ftp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_ftp_t);
467
468 inst->conn_config.reuse.num_children = 1;
469 inst->conn_config.reuse.child_pool_size = sizeof(rlm_ftp_curl_context_t);
470
471 return 0;
472}
473
474/*
475 * The module name should be the only globally exported symbol.
476 * That is, everything else should be 'static'.
477 *
478 * If the module needs to temporarily modify it's instantiation
479 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
480 * The server will then take care of ensuring that the module
481 * is single-threaded.
482 */
483extern module_rlm_t rlm_ftp;
485 .common = {
486 .magic = MODULE_MAGIC_INIT,
487 .name = "ftp",
488 .inst_size = sizeof(rlm_ftp_t),
489 .thread_inst_size = sizeof(rlm_ftp_thread_t),
490 .config = module_config,
491 .bootstrap = mod_bootstrap,
492 .instantiate = mod_instantiate,
493 .thread_instantiate = mod_thread_instantiate,
494 .thread_detach = mod_thread_detach
495 },
496 .method_group = {
497 .bindings = (module_method_binding_t[]){
499 }
500 }
501};
#define RCSID(id)
Definition build.h:485
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:658
#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
Definition cf_parse.h:284
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition cf_parse.h:313
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:241
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:595
fr_curl_handle_t * fr_curl_io_init(TALLOC_CTX *ctx, fr_event_list_t *el, bool multiplex)
#define FR_CURL_REQUEST_SET_OPTION(_x, _y)
Definition base.h:67
uint64_t transfers
How many transfers are current in progress.
Definition base.h:94
CURLM * mandle
The multi handle.
Definition base.h:95
request_t * request
Current request.
Definition base.h:104
void * uctx
Private data for the module using the API.
Definition base.h:105
int fr_curl_io_request_enqueue(fr_curl_handle_t *mhandle, request_t *request, fr_curl_io_request_t *creq)
Sends a request using libcurl.
Definition io.c:480
CURL * candle
Request specific handle.
Definition base.h:102
Uctx data for timer and I/O functions.
Definition base.h:91
Structure representing an individual request being passed to curl for processing.
Definition base.h:101
#define CURL_URI_SAFE_FOR
safe for value suitable for all users of the curl library
Definition xlat.h:36
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
Definition dcursor.h:437
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
static fr_slen_t in
Definition dict.h:841
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
#define GLOBAL_LIB_TERMINATOR
Definition global_lib.h:51
Structure to define how to initialise libraries with global configuration.
Definition global_lib.h:38
static xlat_action_t ftp_get_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Simple xlat to read data from an FTP URI.
Definition rlm_ftp.c:257
global_lib_autoinst_t fr_curl_autoinst
Definition base.c:387
CURL * fr_curl_tmp_handle(void)
Return a thread local curl easy handle.
Definition base.c:267
conf_parser_t fr_curl_conn_config[]
Definition base.c:97
#define RERROR(fmt,...)
Definition log.h:298
#define RPEDEBUG(fmt,...)
Definition log.h:376
talloc_free(reap)
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
Definition math.h:148
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_OCTETS
Raw octets.
unsigned char uint8_t
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * thread
Thread specific instance data.
Definition module_ctx.h:43
fr_event_list_t * el
Event list to register any IO handlers and timers against.
Definition module_ctx.h:68
void * thread
Thread instance data.
Definition module_ctx.h:67
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:64
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
Temporary structure to hold arguments for thread_instantiation calls.
Definition module_ctx.h:63
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Definition module_rlm.c:243
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
static int ftp_uri_part_escape(fr_value_box_t *vb, void *uctx)
static int _ftp_request_cleanup(fr_curl_io_request_t *randle, UNUSED void *uctx)
Cleans up after a FTP request.
Definition rlm_ftp.c:337
size_t used
Space used in buffer.
Definition rlm_ftp.c:82
static fr_uri_part_t const ftp_uri_parts[]
Definition rlm_ftp.c:94
fr_curl_handle_t * mhandle
Thread specific multi handle.
Definition rlm_ftp.c:54
static size_t ftp_response_body(void *in, size_t size, size_t nmemb, void *userdata)
Definition rlm_ftp.c:206
static void ftp_io_xlat_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
Definition rlm_ftp.c:186
bool binary
Do we expect binary data - and so output octets.
Definition rlm_ftp.c:45
request_t * request
Current request.
Definition rlm_ftp.c:77
fr_curl_io_request_t * handle
curl easy handle servicing our request.
Definition rlm_ftp.c:59
static int ftp_conn_alloc(fr_curl_io_request_t *randle, void *uctx)
Definition rlm_ftp.c:380
write_state_t state
Decoder state.
Definition rlm_ftp.c:78
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_ftp.c:452
size_t max_resp_size
Maximum size of incoming data.
Definition rlm_ftp.c:44
size_t alloc
Space allocated for buffer.
Definition rlm_ftp.c:81
static xlat_arg_parser_t const ftp_get_xlat_args[]
Definition rlm_ftp.c:243
global_lib_autoinst_t const *const rlm_ftp_lib[]
Definition rlm_ftp.c:112
char * buffer
Raw incoming FTP data.
Definition rlm_ftp.c:80
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Create a thread specific multihandle.
Definition rlm_ftp.c:412
fr_curl_conn_config_t conn_config
Configuration of slab allocated connection handles.
Definition rlm_ftp.c:43
rlm_ftp_t const * instance
This instance of rlm_ftp.
Definition rlm_ftp.c:75
rlm_ftp_t const * inst
Instance of rlm_ftp.
Definition rlm_ftp.c:52
write_state_t
Definition rlm_ftp.c:65
@ WRITE_STATE_INIT
Definition rlm_ftp.c:66
@ WRITE_STATE_DISCARD
Definition rlm_ftp.c:68
@ WRITE_STATE_POPULATED
Definition rlm_ftp.c:67
module_rlm_t rlm_ftp
Definition rlm_ftp.c:484
static const conf_parser_t module_config[]
Definition rlm_ftp.c:102
rlm_ftp_response_t response
Response context data.
Definition rlm_ftp.c:89
static int _mod_conn_free(fr_curl_io_request_t *randle)
Definition rlm_ftp.c:374
#define FTP_BODY_ALLOC_CHUNK
Definition rlm_ftp.c:40
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Cleanup all outstanding requests associated with this thread.
Definition rlm_ftp.c:442
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_ftp.c:464
ftp_slab_list_t * slab
Slab list for connection handles.
Definition rlm_ftp.c:53
static xlat_action_t ftp_get_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
Definition rlm_ftp.c:148
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition sbuff.h:192
size_t inst_size
Size of the module's instance data.
Definition module.h:212
void * data
Module's instance data.
Definition module.h:291
void * boot
Data allocated during the boostrap phase.
Definition module.h:294
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:152
Named methods exported by a module.
Definition module.h:174
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
#define FR_SLAB_FUNCS(_name, _type)
Define type specific wrapper functions for slabs and slab elements.
Definition slab.h:120
#define FR_SLAB_TYPES(_name, _type)
Define type specific wrapper structs for slabs and slab elements.
Definition slab.h:72
eap_aka_sim_process_conf_t * inst
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition talloc.c:650
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:467
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition xlat.c:560
uint8_t required
Argument must be present, and non-empty.
Definition xlat.h:146
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
Definition xlat.h:383
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumend by an xlat function.
Definition xlat.h:145
int fr_uri_escape_list(fr_value_box_list_t *uri, fr_uri_part_t const *uri_parts, void *uctx)
Parse a list of value boxes representing a URI.
Definition uri.c:140
#define XLAT_URI_PART_TERMINATOR
Definition uri.h:66
char const * name
Name of this part of the URI.
Definition uri.h:47
Definition for a single part of a URI.
Definition uri.h:46
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
Definition value.c:4283
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition value.c:4379
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
Definition value.c:4620
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
Definition value.c:5949
@ FR_VALUE_BOX_LIST_FREE
Definition value.h:237
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:651
static size_t char ** out
Definition value.h:1020
void * rctx
Resume context.
Definition xlat_ctx.h:54
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition xlat_ctx.h:52
An xlat calling ctx.
Definition xlat_ctx.h:49
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:363