The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_chap.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: 770156e5666917114753a2976460ecd582b8837c $
19 * @file rlm_chap.c
20 * @brief Process chap authentication requests.
21 *
22 * @copyright 2001,2006 The FreeRADIUS server project
23 */
24RCSID("$Id: 770156e5666917114753a2976460ecd582b8837c $")
25
26#define LOG_PREFIX mctx->mi->name
27
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/password.h>
30#include <freeradius-devel/server/module_rlm.h>
31#include <freeradius-devel/server/cf_parse.h>
32#include <freeradius-devel/util/chap.h>
33#include <freeradius-devel/unlang/xlat_func.h>
34#include <freeradius-devel/unlang/call_env.h>
35
40
41static const conf_parser_t module_config[] = {
42 { FR_CONF_OFFSET_TYPE_FLAGS("min_challenge_len", FR_TYPE_SIZE, 0, rlm_chap_t, min_challenge_len), .dflt = "16" },
44};
45
49
51 FR_CALL_ENV_METHOD_OUT(chap_xlat_call_env_t),
53 { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS,
56 chap_challenge), .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
58 }
59};
60
66
68 FR_CALL_ENV_METHOD_OUT(chap_autz_call_env_t),
70 { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS,
72 chap_autz_call_env_t, chap_password),
73 .pair.dflt = "&Chap-Password", .pair.dflt_quote = T_BARE_WORD },
74 { FR_CALL_ENV_PARSE_OFFSET("chap_challenge", FR_TYPE_OCTETS,
76 chap_autz_call_env_t, chap_challenge, chap_challenge_tmpl),
77 .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
79 }
80};
81
87
89 FR_CALL_ENV_METHOD_OUT(chap_auth_call_env_t),
94 .pair.dflt = "&User-Name", .pair.dflt_quote = T_BARE_WORD },
95 { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS,
97 chap_auth_call_env_t, chap_password),
98 .pair.dflt = "&Chap-Password", .pair.dflt_quote = T_BARE_WORD },
99 { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS,
101 chap_auth_call_env_t, chap_challenge),
102 .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
104 }
105};
106
108
111 { .out = &dict_freeradius, .proto = "freeradius" },
112 { NULL }
113};
114
117
120 { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
121 { .out = &attr_cleartext_password, .name = "Password.Cleartext", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
122
123 { NULL }
124};
125
127 { .required = true, .single = true, .type = FR_TYPE_STRING },
129};
130
131/** Produce a CHAP-Password hash value
132 *
133 * Example:
134@verbatim
135%chap.password(<password>) == 0x<id><md5_hash>
136@endverbatim
137 *
138 * @ingroup xlat_functions
139 */
141 xlat_ctx_t const *xctx,
142 request_t *request, fr_value_box_list_t *in)
143{
145 uint8_t chap_password[1 + FR_CHAP_CHALLENGE_LENGTH];
146 fr_value_box_t *vb;
147 uint8_t const *challenge;
148 size_t challenge_len;
149 fr_value_box_t *in_head = fr_value_box_list_head(in);
150 chap_xlat_call_env_t *env_data = talloc_get_type_abort(xctx->env_data, chap_xlat_call_env_t);
151
152 /*
153 * Use Chap-Challenge pair if present,
154 * Request Authenticator otherwise.
155 */
156 if ((env_data->chap_challenge.type == FR_TYPE_OCTETS) &&
157 (env_data->chap_challenge.vb_length >= inst->min_challenge_len)) {
158 challenge = env_data->chap_challenge.vb_octets;
159 challenge_len = env_data->chap_challenge.vb_length;
160 } else {
161 if (env_data->chap_challenge.type == FR_TYPE_OCTETS)
162 RWDEBUG("&request.CHAP-Challenge shorter than minimum length (%ld)", inst->min_challenge_len);
163 challenge = request->packet->vector;
164 challenge_len = RADIUS_AUTH_VECTOR_LENGTH;
165 }
166 fr_chap_encode(chap_password, (uint8_t)(fr_rand() & 0xff), challenge, challenge_len,
167 in_head->vb_strvalue, in_head->vb_length);
168
169 MEM(vb = fr_value_box_alloc_null(ctx));
170 fr_value_box_memdup(vb, vb, NULL, chap_password, sizeof(chap_password), false);
172
173 return XLAT_ACTION_DONE;
174}
175
176static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
177{
178 fr_pair_t *vp;
180 chap_autz_call_env_t *env_data = talloc_get_type_abort(mctx->env_data, chap_autz_call_env_t);
181
182 if (fr_pair_find_by_da(&request->control_pairs, NULL, attr_auth_type) != NULL) {
183 RDEBUG3("Auth-Type is already set. Not setting 'Auth-Type := %s'", mctx->mi->name);
185 }
186
187 /*
188 * This case means the warnings below won't be printed
189 * unless there's a CHAP-Password in the request.
190 */
191 if (env_data->chap_password.type != FR_TYPE_OCTETS) {
193 }
194
195 /*
196 * Create the CHAP-Challenge if it wasn't already in the packet.
197 *
198 * This is so that the rest of the code does not need to
199 * understand CHAP.
200 */
201 if (env_data->chap_challenge.type != FR_TYPE_OCTETS) {
202 RDEBUG2("Creating %s from request authenticator", env_data->chap_challenge_tmpl->name);
203
204 MEM(vp = fr_pair_afrom_da(request->request_ctx, tmpl_attr_tail_da(env_data->chap_challenge_tmpl)));
205 fr_pair_value_memdup(vp, request->packet->vector, sizeof(request->packet->vector), true);
206 fr_pair_append(&request->request_pairs, vp);
207 }
208
209 if (!inst->auth_type) {
210 WARN("No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup CHAP authentication",
211 mctx->mi->name, mctx->mi->name);
213 }
214
215 if (!module_rlm_section_type_set(request, attr_auth_type, inst->auth_type)) {
217 }
218
220}
221
222/*
223 * Find the named user in this modules database. Create the set
224 * of attribute-value pairs to check and reply with for this user
225 * from the database. The authentication code only needs to check
226 * the password, the rest is done here.
227 */
228static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
229{
231 fr_pair_t *known_good;
232 uint8_t pass_str[1 + FR_CHAP_CHALLENGE_LENGTH];
233 chap_auth_call_env_t *env_data = talloc_get_type_abort(mctx->env_data, chap_auth_call_env_t);
234
235 int ret;
236
237 fr_dict_attr_t const *allowed_passwords[] = { attr_cleartext_password };
238 bool ephemeral;
239
240 uint8_t const *challenge;
241 size_t challenge_len;
242
243 if (env_data->username.type != FR_TYPE_STRING) {
244 REDEBUG("&User-Name attribute is required for authentication");
246 }
247
248 if (env_data->chap_password.type != FR_TYPE_OCTETS) {
249 REDEBUG("You set '&control.Auth-Type = CHAP' for a request that "
250 "does not contain a CHAP-Password attribute!");
252 }
253
254 if (env_data->chap_password.vb_length == 0) {
255 REDEBUG("&request.CHAP-Password is empty");
257 }
258
259 if (env_data->chap_password.vb_length != FR_CHAP_CHALLENGE_LENGTH + 1) {
260 REDEBUG("&request.CHAP-Password has invalid length");
262 }
263
264 /*
265 * Retrieve the normalised version of
266 * the known_good password, without
267 * mangling the current password attributes
268 * in the request.
269 */
270 known_good = password_find(&ephemeral, request, request,
271 allowed_passwords, NUM_ELEMENTS(allowed_passwords),
272 false);
273 if (!known_good) {
274 REDEBUG("No \"known good\" password found for user");
276 }
277
278 /*
279 * Output is id + password hash
280 */
281
282 /*
283 * Use Chap-Challenge pair if present,
284 * Request Authenticator otherwise.
285 */
286 if ((env_data->chap_challenge.type == FR_TYPE_OCTETS) &&
287 (env_data->chap_challenge.vb_length >= inst->min_challenge_len)) {
288 challenge = env_data->chap_challenge.vb_octets;
289 challenge_len = env_data->chap_challenge.vb_length;
290 } else {
291 if (env_data->chap_challenge.type == FR_TYPE_OCTETS)
292 RWDEBUG("&request.CHAP-Challenge shorter than minimum length (%ld)", inst->min_challenge_len);
293 challenge = request->packet->vector;
294 challenge_len = RADIUS_AUTH_VECTOR_LENGTH;
295 }
296 fr_chap_encode(pass_str, env_data->chap_password.vb_octets[0], challenge, challenge_len,
297 known_good->vp_strvalue, known_good->vp_length);
298
299 /*
300 * The password_find function already emits
301 * a log message about the password attribute contents
302 * so we don't need to duplicate it here.
303 */
304 if (RDEBUG_ENABLED3) {
305 uint8_t const *p;
306 size_t length;
307
308 if (env_data->chap_challenge.type == FR_TYPE_OCTETS) {
309 RDEBUG2("Using challenge from &request.CHAP-Challenge");
310 p = env_data->chap_challenge.vb_octets;
311 length = env_data->chap_challenge.vb_length;
312 } else {
313 RDEBUG2("Using challenge from authenticator field");
314 p = request->packet->vector;
315 length = sizeof(request->packet->vector);
316 }
317
318 RINDENT();
319 RDEBUG3("CHAP challenge : %pH", fr_box_octets(p, length));
320 RDEBUG3("Client sent : %pH", fr_box_octets(env_data->chap_password.vb_octets + 1,
322 RDEBUG3("We calculated : %pH", fr_box_octets(pass_str + 1, FR_CHAP_CHALLENGE_LENGTH));
323 REXDENT();
324 }
325
326 /*
327 * Skip the id field at the beginning of the
328 * password and chap response.
329 */
330 ret = fr_digest_cmp(pass_str + 1, env_data->chap_password.vb_octets + 1, FR_CHAP_CHALLENGE_LENGTH);
331 if (ephemeral) TALLOC_FREE(known_good);
332 if (ret != 0) {
333 REDEBUG("Password comparison failed: password is incorrect");
334
336 }
337
338 RDEBUG2("CHAP user \"%pV\" authenticated successfully", &env_data->username);
339
341}
342
343/*
344 * Create instance for our module. Allocate space for
345 * instance structure and read configuration parameters
346 */
347static int mod_instantiate(module_inst_ctx_t const *mctx)
348{
349 rlm_chap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_chap_t);
350
351 inst->auth_type = fr_dict_enum_by_name(attr_auth_type, mctx->mi->name, -1);
352 if (!inst->auth_type) {
353 WARN("Failed to find 'authenticate %s {...}' section. CHAP authentication will likely not work",
354 mctx->mi->name);
355 }
356
357 return 0;
358}
359
360static int mod_bootstrap(module_inst_ctx_t const *mctx)
361{
362 xlat_t *xlat;
363
364 if (unlikely((xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "password", xlat_func_chap_password,
365 FR_TYPE_OCTETS)) == NULL)) return -1;
368
369 return 0;
370}
371
372/*
373 * The module name should be the only globally exported symbol.
374 * That is, everything else should be 'static'.
375 *
376 * If the module needs to temporarily modify it's instantiation
377 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
378 * The server will then take care of ensuring that the module
379 * is single-threaded.
380 */
383 .common = {
384 .magic = MODULE_MAGIC_INIT,
385 .name = "chap",
386 .inst_size = sizeof(rlm_chap_t),
387 .bootstrap = mod_bootstrap,
390 },
391 .method_group = {
392 .bindings = (module_method_binding_t[]){
393 { .section = SECTION_NAME("authenticate", CF_IDENT_ANY), .method = mod_authenticate, .method_env = &chap_auth_method_env },
394 { .section = SECTION_NAME("recv", "Access-Request"), .method = mod_authorize, .method_env = &chap_autz_method_env },
396 }
397 }
398};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define RCSID(id)
Definition build.h:483
#define unlikely(_x)
Definition build.h:381
#define NUM_ELEMENTS(_t)
Definition build.h:337
#define CALL_ENV_TERMINATOR
Definition call_env.h:231
#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...
Definition call_env.h:360
call_env_parser_t const * env
Parsing rules for call method env.
Definition call_env.h:242
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
Definition call_env.h:76
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl must contain an attribute reference.
Definition call_env.h:86
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
Definition call_env.h:75
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
Definition call_env.h:80
#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.
Definition call_env.h:335
Per method call config.
Definition call_env.h:175
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#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:579
#define CF_IDENT_ANY
Definition cf_util.h:78
void fr_chap_encode(uint8_t out[static 1+FR_CHAP_CHALLENGE_LENGTH], uint8_t id, uint8_t const *challenge, size_t challenge_len, char const *password, size_t password_len)
Encode a CHAP password.
Definition chap.c:34
#define FR_CHAP_CHALLENGE_LENGTH
Definition chap.h:33
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define MEM(x)
Definition debug.h:36
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3395
static fr_slen_t in
Definition dict.h:824
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
Value of an enumerated attribute.
Definition dict.h:227
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
static xlat_action_t xlat_func_chap_password(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Produce a CHAP-Password hash value.
Definition rlm_chap.c:140
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:443
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition log.h:335
#define RDEBUG3(fmt,...)
Definition log.h:343
#define RINDENT()
Indent R* messages by one level.
Definition log.h:430
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_OCTETS
Raw octets.
unsigned char uint8_t
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
Definition misc.c:472
void * env_data
Per call environment data.
Definition module_ctx.h:44
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
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:257
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
Definition module_rlm.c:427
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
#define RADIUS_AUTH_VECTOR_LENGTH
Definition net.h:89
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2981
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.
Definition pair.c:693
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1345
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.
Definition pair.c:283
fr_pair_t * password_find(bool *ephemeral, TALLOC_CTX *ctx, request_t *request, fr_dict_attr_t const *allowed_attrs[], size_t allowed_attrs_len, bool normify)
Find a "known good" password in the control list of a request.
Definition password.c:954
static const conf_parser_t config[]
Definition base.c:183
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define WARN(fmt,...)
Definition radclient.h:47
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:105
#define RETURN_MODULE_REJECT
Definition rcode.h:55
#define RETURN_MODULE_NOOP
Definition rcode.h:62
#define RETURN_MODULE_INVALID
Definition rcode.h:59
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
fr_dict_attr_autoload_t rlm_chap_dict_attr[]
Definition rlm_chap.c:119
static const call_env_method_t chap_autz_method_env
Definition rlm_chap.c:67
fr_value_box_t chap_password
Definition rlm_chap.c:84
fr_dict_enum_value_t * auth_type
Definition rlm_chap.c:37
static fr_dict_t const * dict_freeradius
Definition rlm_chap.c:107
fr_value_box_t chap_challenge
Definition rlm_chap.c:85
size_t min_challenge_len
Definition rlm_chap.c:38
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition rlm_chap.c:228
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_chap.c:360
fr_value_box_t chap_password
Definition rlm_chap.c:62
fr_dict_autoload_t rlm_chap_dict[]
Definition rlm_chap.c:110
static const call_env_method_t chap_auth_method_env
Definition rlm_chap.c:88
static fr_dict_attr_t const * attr_auth_type
Definition rlm_chap.c:115
static xlat_arg_parser_t const xlat_func_chap_password_args[]
Definition rlm_chap.c:126
static fr_dict_attr_t const * attr_cleartext_password
Definition rlm_chap.c:116
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition rlm_chap.c:176
module_rlm_t rlm_chap
Definition rlm_chap.c:382
fr_value_box_t chap_challenge
Definition rlm_chap.c:47
static const call_env_method_t chap_xlat_method_env
Definition rlm_chap.c:50
tmpl_t * chap_challenge_tmpl
Definition rlm_chap.c:64
static const conf_parser_t module_config[]
Definition rlm_chap.c:41
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_chap.c:347
fr_value_box_t username
Definition rlm_chap.c:83
fr_value_box_t chap_challenge
Definition rlm_chap.c:63
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
username
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
char const * name
Instance name e.g. user_database.
Definition module.h:335
size_t inst_size
Size of the module's instance data.
Definition module.h:203
void * data
Module's instance data.
Definition module.h:271
void * boot
Data allocated during the boostrap phase.
Definition module.h:274
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:151
Named methods exported by a module.
Definition module.h:173
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:812
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define talloc_get_type_abort_const
Definition talloc.h:282
@ T_BARE_WORD
Definition token.h:120
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:168
xlat_action_t
Definition xlat.h:37
@ 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:147
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:4468
int nonnull(2, 5))
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:632
static size_t char ** out
Definition value.h:997
#define fr_box_octets(_val, _len)
Definition value.h:288
void * env_data
Expanded call env data.
Definition xlat_ctx.h:53
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:365
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.
Definition xlat_func.c:392