The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
base.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: 55db89cc494d1ee0b3de0f628947dcd2e23021f2 $
19 * @file lib/eap/base.c
20 * @brief Code common to clients and to servers.
21 *
22 * @copyright 2000-2003,2006 The FreeRADIUS server project
23 * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
24 * @copyright 2003 Alan DeKok (aland@freeradius.org)
25 * @copyright 2003 Michael Richardson (mcr@sandelman.ottawa.on.ca)
26 */
27
28/*
29 * EAP PACKET FORMAT
30 * --- ------ ------
31 * 0 1 2 3
32 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
33 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 * | Code | Identifier | Length |
35 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * | Data ...
37 * +-+-+-+-+
38 *
39 *
40 * EAP Request and Response Packet Format
41 * --- ------- --- -------- ------ ------
42 * 0 1 2 3
43 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | Code | Identifier | Length |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * | Type | Type-Data ...
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
49 *
50 *
51 * EAP Success and Failure Packet Format
52 * --- ------- --- ------- ------ ------
53 * 0 1 2 3
54 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
55 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 * | Code | Identifier | Length |
57 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 *
59 */
60
61RCSID("$Id: 55db89cc494d1ee0b3de0f628947dcd2e23021f2 $")
62
63#define LOG_PREFIX "eap"
64
65#include <freeradius-devel/eap/base.h>
66#include <freeradius-devel/radius/defs.h>
67#include <freeradius-devel/server/state.h>
68#include <freeradius-devel/server/virtual_servers.h>
69#include <freeradius-devel/server/pair.h>
70#include <freeradius-devel/server/auth.h>
71#include <freeradius-devel/unlang/call.h>
72#include <freeradius-devel/unlang/interpret.h>
73#include <freeradius-devel/unlang/function.h>
74#include "types.h"
75#include "attrs.h"
76
80
83 { .out = &dict_freeradius, .proto = "freeradius" },
84 { .out = &dict_radius, .proto = "radius" },
85 { .out = &dict_tls, .proto = "tls" },
86 { NULL }
87};
88
107
110 { .out = &attr_chbind_response_code, .name = "Chbind-Response-Code", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
111 { .out = &attr_eap_identity, .name = "EAP-Identity", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
112 { .out = &attr_eap_session_id, .name = "EAP-Session-Id", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
113 { .out = &attr_eap_type, .name = "EAP-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
114 { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
115 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
116 { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
117 { .out = &attr_eap_channel_binding_message, .name = "Vendor-Specific.UKERNA.EAP-Channel-Binding-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
118 { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
119 { .out = &attr_eap_msk, .name = "EAP-MSK", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
120 { .out = &attr_eap_emsk, .name = "EAP-EMSK", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
121 { .out = &attr_framed_mtu, .name = "Framed-MTU", .type = FR_TYPE_UINT32, .dict = &dict_radius },
122 { .out = &attr_freeradius_proxied_to, .name = "Vendor-Specific.FreeRADIUS.Proxied-To", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
123 { .out = &attr_ms_mppe_send_key, .name = "Vendor-Specific.Microsoft.MPPE-Send-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
124 { .out = &attr_ms_mppe_recv_key, .name = "Vendor-Specific.Microsoft.MPPE-Recv-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
125 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
126 { .out = &attr_tls_min_version, .name = "Min-Version", .type = FR_TYPE_FLOAT32, .dict = &dict_tls },
127 { .out = &attr_tls_max_version, .name = "Max-Version", .type = FR_TYPE_FLOAT32, .dict = &dict_tls },
128
129 { NULL }
130};
131
132void eap_packet_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *list, eap_packet_raw_t const *eap)
133{
134 int total, size;
135 uint8_t const *ptr;
136 fr_pair_t *vp;
137
138 total = eap->length[0] * 256 + eap->length[1];
139
140 if (total == 0) {
141 DEBUG("Asked to encode empty EAP-Message!");
142 return;
143 }
144
145 ptr = (uint8_t const *) eap;
146
147 do {
148 size = total;
149 if (size > 253) size = 253;
150
152 fr_pair_value_memdup(vp, ptr, size, false);
153
154 fr_pair_append(list, vp);
155
156 ptr += size;
157 total -= size;
158 } while (total > 0);
159}
160
161/** Basic EAP packet verifications & validations
162 *
163 * @param[in] ctx talloc ctx for the eap packet.
164 * @param[in] eap_packet_p to validate.
165 * @return
166 * - true the packet is valid.
167 * - false the packet is invalid.
168 */
169static bool eap_is_valid(TALLOC_CTX *ctx, eap_packet_raw_t **eap_packet_p)
170{
171 uint16_t len;
172 size_t packet_len;
173 eap_packet_raw_t *eap_packet = *eap_packet_p;
174
175 /*
176 * These length checks are also done by eap_packet_from_vp(),
177 * but that's OK. The static analysis tools aren't smart
178 * enough to figure that out.
179 */
180 packet_len = talloc_array_length((uint8_t *) eap_packet);
181 if (packet_len <= EAP_HEADER_LEN) {
182 fr_strerror_printf("Invalid EAP data length %zu <= 4", packet_len);
183 return false;
184 }
185
186 memcpy(&len, eap_packet->length, sizeof(uint16_t));
187 len = ntohs(len);
188
189 if ((len <= EAP_HEADER_LEN) || (len > packet_len)) {
190 fr_strerror_printf("Invalid EAP length field. Expected value in range %d-%zu, was %u bytes",
191 EAP_HEADER_LEN, packet_len, len);
192 return false;
193 }
194
195 /*
196 * High level EAP packet checks
197 */
198 switch (eap_packet->code) {
201 break;
202
203 default:
204 fr_strerror_printf("Invalid EAP code %d: Ignoring the packet", eap_packet->code);
205 return false;
206 }
207
208 if ((eap_packet->data[0] == 0) ||
209 (eap_packet->data[0] >= FR_EAP_METHOD_MAX)) {
210 /*
211 * Handle expanded types by smashing them to
212 * normal types.
213 */
214 if (eap_packet->data[0] == FR_EAP_EXPANDED_TYPE) {
215 uint8_t *p, *q;
216
217 if (len <= (EAP_HEADER_LEN + 1 + 3 + 4)) {
218 fr_strerror_const("Expanded EAP type is too short: ignoring the packet");
219 return false;
220 }
221
222 if ((eap_packet->data[1] != 0) ||
223 (eap_packet->data[2] != 0) ||
224 (eap_packet->data[3] != 0)) {
225 fr_strerror_const("Expanded EAP type has unknown Vendor-ID: ignoring the packet");
226 return false;
227 }
228
229 if ((eap_packet->data[4] != 0) ||
230 (eap_packet->data[5] != 0) ||
231 (eap_packet->data[6] != 0)) {
232 fr_strerror_const("Expanded EAP type has unknown Vendor-Type: ignoring the packet");
233 return false;
234 }
235
236 if ((eap_packet->data[7] == 0) ||
237 (eap_packet->data[7] >= FR_EAP_METHOD_MAX)) {
238 fr_strerror_printf("Unsupported Expanded EAP type %s (%u): ignoring the packet",
239 eap_type2name(eap_packet->data[7]), eap_packet->data[7]);
240 return false;
241 }
242
243 if (eap_packet->data[7] == FR_EAP_METHOD_NAK) {
244 fr_strerror_const("Unsupported Expanded EAP-NAK: ignoring the packet");
245 return false;
246 }
247
248 /*
249 * Re-write the EAP packet to NOT have the expanded type.
250 */
251 q = (uint8_t *) eap_packet;
252 memmove(q + EAP_HEADER_LEN, q + EAP_HEADER_LEN + 7, len - 7 - EAP_HEADER_LEN);
253
254 p = talloc_realloc(ctx, eap_packet, uint8_t, len - 7);
255 if (!p) {
256 fr_strerror_printf("Unsupported EAP type %s (%u): ignoring the packet",
257 eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
258 return false;
259 }
260
261 len -= 7;
262 p[2] = (len >> 8) & 0xff;
263 p[3] = len & 0xff;
264
265 *eap_packet_p = (eap_packet_raw_t *)p;
266
267 return true;
268 }
269
270 fr_strerror_printf("Unsupported EAP type %s (%u): ignoring the packet",
271 eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
272 return false;
273 }
274
275 /* we don't expect notification, but we send it */
276 if (eap_packet->data[0] == FR_EAP_METHOD_NOTIFICATION) {
277 fr_strerror_const("Got NOTIFICATION, Ignoring the packet");
278 return false;
279 }
280
281 return true;
282}
283
284/*
285 * Handles multiple EAP-Message attrs
286 * ie concatenates all to get the complete EAP packet.
287 *
288 * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message,
289 * refer fragmentation in rfc2869.
290 */
292{
293 fr_pair_t *vp;
294 eap_packet_raw_t *eap_packet;
295 unsigned char *ptr;
296 uint16_t len;
297 int total_len;
298 fr_dcursor_t cursor;
299
300 /*
301 * Get only EAP-Message attribute list
302 */
304 if (!vp) {
305 fr_strerror_const("EAP-Message not found");
306 return NULL;
307 }
308
309 /*
310 * Sanity check the length before doing anything.
311 */
312 if (vp->vp_length < 4) {
313 fr_strerror_const("EAP packet is too short");
314 return NULL;
315 }
316
317 /*
318 * Get the Actual length from the EAP packet
319 * First EAP-Message contains the EAP packet header
320 */
321 memcpy(&len, vp->vp_strvalue + 2, sizeof(len));
322 len = ntohs(len);
323
324 /*
325 * Take out even more weird things.
326 */
327 if (len < 4) {
328 fr_strerror_const("EAP packet has invalid length (less than 4 bytes)");
329 return NULL;
330 }
331
332 /*
333 * Sanity check the length, BEFORE allocating memory.
334 */
335 total_len = 0;
336 for (vp = fr_dcursor_head(&cursor);
337 vp;
338 vp = fr_dcursor_next(&cursor)) {
339 total_len += vp->vp_length;
340
341 if (total_len > len) {
342 fr_strerror_printf("Malformed EAP packet. Length in packet header %i, "
343 "does not match actual length %i", len, total_len);
344 return NULL;
345 }
346 }
347
348 /*
349 * If the length is SMALLER, die, too.
350 */
351 if (total_len < len) {
352 fr_strerror_printf("Malformed EAP packet. Length in packet header does not "
353 "match actual length");
354 return NULL;
355 }
356
357 /*
358 * Now that we know the lengths are OK, allocate memory.
359 */
360 eap_packet = (eap_packet_raw_t *) talloc_zero_array(ctx, uint8_t, len);
361 if (!eap_packet) return NULL;
362
363 /*
364 * Copy the data from EAP-Message's over to our EAP packet.
365 */
366 ptr = (unsigned char *)eap_packet;
367
368 /* RADIUS ensures order of attrs, so just concatenate all */
369 for (vp = fr_dcursor_head(&cursor);
370 vp;
371 vp = fr_dcursor_next(&cursor)) {
372 memcpy(ptr, vp->vp_strvalue, vp->vp_length);
373 ptr += vp->vp_length;
374 }
375
376 if (!eap_is_valid(ctx, &eap_packet)) {
377 talloc_free(eap_packet);
378 return NULL;
379 }
380
381 return eap_packet;
382}
383
384/*
385 * Add raw hex data to the reply.
386 */
387void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
388{
389 fr_pair_t *vp;
390
391 MEM(pair_update_reply(&vp, da) >= 0);
392 fr_pair_value_memdup(vp, value, len, false);
393
394 RINDENT();
395 RDEBUG2("&reply.%pP", vp);
396 REXDENT();
397}
398
399/** Handle the result of running a subrequest through a virtual server
400 *
401 * Storing the value of the State attribute in readiness for the next round.
402 */
404 request_t *request, void *uctx)
405{
406 eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
407
408 /*
409 * Grab the child's session state for re-use in the next round
410 */
412
414}
415
416/** Run a subrequest through a virtual server
417 *
418 * If eap_session_t has a child_state, inject that as an attribute in the request.
419 *
420 * @param[in] request the current (real) request.
421 * @param[in] eap_session representing the outer eap method.
422 * @param[in] server_cs The virtual server to send the request to.
423 * @return
424 * - UNLANG_ACTION_PUSHED_CHILD on success
425 * - UNLANG_ACTION_FAIL on error
426 */
428{
429 fr_pair_t *vp;
430
431 fr_assert(request->parent);
432
433 RDEBUG2("Running request through virtual server \"%s\"", cf_section_name(server_cs));
434
435 /*
436 * Re-present the previously stored child's session state if there is one
437 */
439
440 if (fr_pair_prepend_by_da(request->request_ctx, &vp, &request->request_pairs,
443
444 if (unlang_function_push(request, NULL, eap_virtual_server_resume, NULL, 0,
445 UNLANG_SUB_FRAME, eap_session) < 0) return UNLANG_ACTION_FAIL;
446
447 if (unlang_call_push(request, server_cs, UNLANG_SUB_FRAME) < 0) return UNLANG_ACTION_FAIL;
448
450}
451
452/** Initialise the lib eap base library
453 *
454 */
456{
458 PERROR("%s", __FUNCTION__);
459 return -1;
460 }
461
462 /*
463 * But main_config.c does read the dictionaries before
464 * loading modules, so these have to exist.
465 */
467 PERROR("%s", __FUNCTION__);
469 return -1;
470 }
471
472 return 0;
473}
474
475/** De-init the lib eap base library
476 *
477 */
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
#define RCSID(id)
Definition build.h:483
#define UNUSED
Definition build.h:315
unlang_action_t unlang_call_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Push a call frame onto the stack.
Definition call.c:147
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
Definition cf_util.c:1197
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static void * fr_dcursor_head(fr_dcursor_t *cursor)
Rewind cursor to the start of the list.
Definition dcursor.h:234
#define MEM(x)
Definition debug.h:36
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition defs.h:33
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
#define fr_dict_autofree(_to_free)
Definition dict.h:853
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
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition dict_util.c:4090
#define fr_dict_autoload(_to_load)
Definition dict.h:850
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
Test enumeration values.
Definition dict_test.h:92
char const * eap_type2name(eap_type_t method)
Return an EAP-name for a particular type.
Definition types.c:54
@ FR_EAP_CODE_RESPONSE
Definition types.h:38
@ FR_EAP_CODE_REQUEST
Definition types.h:37
#define FR_EAP_EXPANDED_TYPE
Definition types.h:105
uint8_t data[1]
Definition types.h:125
uint8_t code
Definition types.h:122
#define EAP_HEADER_LEN
Definition types.h:34
uint8_t length[2]
Definition types.h:124
@ FR_EAP_METHOD_NAK
Definition types.h:48
@ FR_EAP_METHOD_NOTIFICATION
Definition types.h:47
@ FR_EAP_METHOD_MAX
Definition types.h:102
Structure to represent packet format of eap on wire
Definition types.h:121
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:111
#define UNLANG_SUB_FRAME
Definition interpret.h:36
static fr_dict_t const * dict_freeradius
Definition base.c:37
fr_dict_attr_autoload_t eap_base_dict_attr[]
Definition base.c:109
fr_dict_attr_t const * attr_packet_type
Definition base.c:93
void eap_packet_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *list, eap_packet_raw_t const *eap)
Definition base.c:132
fr_dict_attr_t const * attr_eap_session_id
Definition base.c:90
fr_dict_attr_t const * attr_state
Definition base.c:103
fr_dict_attr_t const * attr_eap_identity
Definition base.c:91
fr_dict_attr_t const * attr_freeradius_proxied_to
Definition base.c:100
fr_dict_attr_t const * attr_chbind_response_code
Definition base.c:89
fr_dict_attr_t const * attr_eap_message
Definition base.c:96
fr_dict_attr_t const * attr_eap_type
Definition base.c:92
fr_dict_attr_t const * attr_eap_msk
Definition base.c:97
fr_dict_attr_t const * attr_eap_channel_binding_message
Definition base.c:95
fr_dict_t const * dict_tls
Definition base.c:79
fr_dict_attr_t const * attr_tls_min_version
Definition base.c:105
fr_dict_t const * dict_radius
Definition base.c:78
int eap_base_init(void)
Initialise the lib eap base library.
Definition base.c:455
void eap_base_free(void)
De-init the lib eap base library.
Definition base.c:478
eap_packet_raw_t * eap_packet_from_vp(TALLOC_CTX *ctx, fr_pair_list_t *vps)
Definition base.c:291
fr_dict_attr_t const * attr_eap_emsk
Definition base.c:98
fr_dict_attr_t const * attr_ms_mppe_send_key
Definition base.c:101
fr_dict_attr_t const * attr_tls_max_version
Definition base.c:106
static unlang_action_t eap_virtual_server_resume(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Handle the result of running a subrequest through a virtual server.
Definition base.c:403
fr_dict_attr_t const * attr_user_name
Definition base.c:104
static bool eap_is_valid(TALLOC_CTX *ctx, eap_packet_raw_t **eap_packet_p)
Basic EAP packet verifications & validations.
Definition base.c:169
fr_dict_attr_t const * attr_framed_mtu
Definition base.c:99
fr_dict_attr_t const * attr_ms_mppe_recv_key
Definition base.c:102
unlang_action_t eap_virtual_server(request_t *request, eap_session_t *eap_session, CONF_SECTION *server_cs)
Run a subrequest through a virtual server.
Definition base.c:427
fr_dict_autoload_t eap_base_dict[]
Definition base.c:82
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
Definition base.c:387
fr_dict_attr_t const * attr_message_authenticator
Definition base.c:94
char * identity
NAI (User-Name) from EAP-Identity.
Definition session.h:55
#define REQUEST_DATA_EAP_SESSION
Definition session.h:32
Tracks the progress of a single session of any EAP method.
Definition session.h:40
#define PERROR(_fmt,...)
Definition log.h:228
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:443
#define RINDENT()
Indent R* messages by one level.
Definition log.h:430
talloc_free(reap)
unsigned short uint16_t
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
unsigned char uint8_t
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
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
int fr_pair_prepend_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and prepend)
Definition pair.c:1493
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:38
#define RDEBUG2(fmt,...)
Definition radclient.h:54
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition pair.h:129
void fr_state_restore_to_child(request_t *child, void const *unique_ptr, int unique_int)
Restore subrequest data from a parent request.
Definition state.c:858
void fr_state_store_in_parent(request_t *child, void const *unique_ptr, int unique_int)
Store subrequest's session-state list and persistable request data in its parent.
Definition state.c:812
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
Definition pair.h:628
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
Types of values contained within an fr_value_box_t.