The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
base.c
Go to the documentation of this file.
1/*
2 * This program 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
5 * (at 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: 161720ab2848a3cb5958f9a737998e763ce78466 $
19 * @file src/process/dhcpv6/base.c
20 * @brief Base DHCPV6 processing.
21 *
22 * This code was originally written under contract for Network RADIUS
23 * but has been substantially modified from its original form outside
24 * of the project that required its creation.
25 *
26 * @copyright 2021 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
27 * @copyright 2020 Network RADIUS SAS (legal@networkradius.com)
28 */
29#define LOG_PREFIX "process_dhcpv6 - "
30
31#include <freeradius-devel/io/application.h>
32#include <freeradius-devel/server/protocol.h>
33#include <freeradius-devel/server/pair.h>
34#include <freeradius-devel/unlang/interpret.h>
35#include <freeradius-devel/util/dict.h>
36#include <freeradius-devel/util/debug.h>
37#include <freeradius-devel/dhcpv6/dhcpv6.h>
38#include <freeradius-devel/protocol/dhcpv6/freeradius.internal.h>
39
40/*
41 * DHCPV6 state machine configuration
42 */
68
69typedef struct {
70 CONF_SECTION *server_cs; //!< Our virtual server.
71 process_dhcpv6_sections_t sections; //!< Pointers to various config sections
72 ///< we need to execute.
73 bool status_code_on_success; //!< Controls whether we add a status-code
74 ///< option to outbound packets if the status
75 ///< code would be 0.
76 ///< This is allowed by RFC 3315, but seems
77 ///< to cause issues with some clients.
78
79 bool send_failure_message; //!< If true, all instances of
80 ///< Module-Failure-Message in the request
81 ///< are concatenated and returned in the
82 ///< status-message field of the status-code
83 ///< option if the status-code is anything
84 ///< other than success.
85 ///< This may leak information about the
86 ///< internal state of the server, so is
87 ///< disabled by default.
88
89 bool move_failure_message_to_parent; //!< If true, and a parent exists, and the
90 ///< parent is a DHCPv6 request, all module
91 ///< failure messages will get copied to the
92 ///< parent and then freed.
93 ///< When combined with send_failure_message
94 ///< this ensures only the outer relay message
95 ///< contains failure data. The outer relay
96 ///< typically being controlled by the admin
97 ///< and not the end user.
99
100/** Records fields from the original request so we have a known good copy
101 */
109
110/** Records fields from the original relay-request so we have a known good copy
111 */
118
119static fr_dict_t const *dict_dhcpv6;
121
124 { .out = &dict_dhcpv6, .proto = "dhcpv6" },
125 { .out = &dict_freeradius, .proto = "freeradius" },
127};
128
139
141
144 { .out = &attr_client_id, .name = "Client-ID", .type = FR_TYPE_STRUCT, .dict = &dict_dhcpv6 },
145 { .out = &attr_hop_count, .name = "Hop-Count", .type = FR_TYPE_UINT8, .dict = &dict_dhcpv6 },
146 { .out = &attr_interface_id, .name = "Interface-ID", .type = FR_TYPE_OCTETS, .dict = &dict_dhcpv6 },
147 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_dhcpv6 },
148 { .out = &attr_relay_link_address, .name = "Relay-Link-Address", .type = FR_TYPE_IPV6_ADDR, .dict = &dict_dhcpv6 },
149 { .out = &attr_relay_peer_address, .name = "Relay-Peer-Address", .type = FR_TYPE_IPV6_ADDR, .dict = &dict_dhcpv6 },
150 { .out = &attr_server_id, .name = "Server-ID", .type = FR_TYPE_STRUCT, .dict = &dict_dhcpv6 },
151 { .out = &attr_status_code_value, .name = "Status-Code.Value", .type = FR_TYPE_UINT16, .dict = &dict_dhcpv6 },
152 { .out = &attr_status_code_message, .name = "Status-Code.Message", .type = FR_TYPE_STRING, .dict = &dict_dhcpv6 },
153 { .out = &attr_transaction_id, .name = "Transaction-Id", .type = FR_TYPE_OCTETS, .dict = &dict_dhcpv6 },
154
155 { .out = &attr_module_failure_message, .name = "Module-Failure-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
157};
158
163
166 { .out = &enum_status_code_success, .name = "success", .attr = &attr_status_code_value },
167 { .out = &enum_status_code_unspec_fail, .name = "UnspecFail", .attr = &attr_status_code_value },
168 { .out = &enum_status_code_not_on_link, .name = "NotOnLink", .attr = &attr_status_code_value },
169 { .out = &enum_status_code_no_binding, .name = "NoBinding", .attr = &attr_status_code_value },
171};
172
173#define FR_DHCPV6_PROCESS_CODE_VALID(_x) (FR_DHCPV6_PACKET_CODE_VALID(_x) || (_x == FR_DHCPV6_DO_NOT_RESPOND))
174
175#define PROCESS_PACKET_TYPE fr_dhcpv6_packet_code_t
176#define PROCESS_CODE_MAX FR_DHCPV6_CODE_MAX
177#define PROCESS_CODE_DO_NOT_RESPOND FR_DHCPV6_DO_NOT_RESPOND
178#define PROCESS_PACKET_CODE_VALID FR_DHCPV6_PROCESS_CODE_VALID
179#define PROCESS_INST process_dhcpv6_t
180#define PROCESS_RCTX process_dhcpv6_rctx_t
181#define PROCESS_CODE_DYNAMIC_CLIENT FR_DHCPV6_REPLY
182
183/*
184 * DHCPv6 is nonstandard in that we reply
185 * to the majority of requests, but include a
186 * status code to indicate failures.
187 */
188#define PROCESS_STATE_EXTRA_FIELDS fr_value_box_t const **status_codes[RLM_MODULE_NUMCODES];
189#include <freeradius-devel/server/process.h>
190
192 { FR_CONF_OFFSET("status_code_on_success", process_dhcpv6_t, status_code_on_success), .dflt = "no" },
193 { FR_CONF_OFFSET("send_failure_message", process_dhcpv6_t, send_failure_message), .dflt = "no" },
194 { FR_CONF_OFFSET("move_failure_message_to_parent", process_dhcpv6_t, move_failure_message_to_parent), .dflt = "yes" },
196};
197
199 {
200 .section = SECTION_NAME("recv", "Solicit"),
201 .actions = &mod_actions_postauth,
202 .offset = PROCESS_CONF_OFFSET(recv_solicit)
203 },
204 {
205 .section = SECTION_NAME("recv", "Request"),
207 .offset = PROCESS_CONF_OFFSET(recv_request)
208 },
209 {
210 .section = SECTION_NAME("recv", "Confirm"),
212 .offset = PROCESS_CONF_OFFSET(recv_confirm)
213 },
214 {
215 .section = SECTION_NAME("recv", "Renew"),
217 .offset = PROCESS_CONF_OFFSET(recv_renew)
218 },
219 {
220 .section = SECTION_NAME("recv", "Rebind"),
222 .offset = PROCESS_CONF_OFFSET(recv_rebind)
223 },
224 {
225 .section = SECTION_NAME("recv", "Release"),
227 .offset = PROCESS_CONF_OFFSET(recv_release)
228 },
229 {
230 .section = SECTION_NAME("recv", "Decline"),
232 .offset = PROCESS_CONF_OFFSET(recv_decline)
233 },
234 {
235 .section = SECTION_NAME("recv", "Reconfigure"),
237 .offset = PROCESS_CONF_OFFSET(recv_reconfigure)
238 },
239 {
240 .section = SECTION_NAME("recv", "Information-Request"),
242 .offset = PROCESS_CONF_OFFSET(recv_information_request)
243 },
244 {
245 .section = SECTION_NAME("recv", "Relay-Forward"),
247 .offset = PROCESS_CONF_OFFSET(recv_relay_forward)
248 },
249
250 {
251 .section = SECTION_NAME("send", "Advertise"),
253 .offset = PROCESS_CONF_OFFSET(send_advertise)
254 },
255 {
256 .section = SECTION_NAME("send", "Reply"),
259 },
260 {
261 .section = SECTION_NAME("send", "Relay-Reply"),
263 .offset = PROCESS_CONF_OFFSET(send_relay_reply)
264 },
265 {
266 .section = SECTION_NAME("send", "Do-Not-Respond"),
268 .offset = PROCESS_CONF_OFFSET(do_not_respond)
269 },
270
271 DYNAMIC_CLIENT_SECTIONS,
272
274};
275
276/*
277 * Debug the packet if requested.
278 */
279static void dhcpv6_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
280{
281#ifdef WITH_IFINDEX_NAME_RESOLUTION
282 char if_name[IFNAMSIZ];
283#endif
284 char const *module;
285
286 if (!packet) return;
287 if (!RDEBUG_ENABLED) return;
288
289 /*
290 * Looks better without module prefix
291 */
292 module = request->module;
293 request->module = NULL;
294
295 log_request(L_DBG, L_DBG_LVL_1, request, __FILE__, __LINE__, "%s %s XID %08x from %s%pV%s:%i to %s%pV%s:%i "
296#ifdef WITH_IFINDEX_NAME_RESOLUTION
297 "%s%s%s"
298#endif
299 "",
300 received ? "Received" : "Sending",
302 packet->id,
303 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
304 fr_box_ipaddr(packet->socket.inet.src_ipaddr),
305 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
306 packet->socket.inet.src_port,
307 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
308 fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
309 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
310 packet->socket.inet.dst_port
311#ifdef WITH_IFINDEX_NAME_RESOLUTION
312 , packet->socket.inet.ifindex ? "via " : "",
313 packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
314 packet->socket.inet.ifindex ? " " : ""
315#endif
316 );
317
318 if (received || request->parent) {
319 log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
320 } else {
321 log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
322 }
323
324 request->module = module;
325}
326
327/** Keep a copy of header fields to prevent them being tampered with
328 *
329 */
330static inline CC_HINT(always_inline)
331int dhcpv6_client_fields_store(request_t *request, process_dhcpv6_rctx_t *rctx, bool expect_server_id)
332{
333 fr_pair_t *transaction_id;
334
335 transaction_id = fr_pair_find_by_da(&request->request_pairs, NULL, attr_transaction_id);
336 if (!transaction_id) {
337 REDEBUG("Missing Transaction-ID");
338 return -1;
339 }
340
341 if (transaction_id->vp_length != DHCPV6_TRANSACTION_ID_LEN) {
342 REDEBUG("Invalid Transaction-ID, expected len %u, got len %zu",
343 DHCPV6_TRANSACTION_ID_LEN, transaction_id->vp_length);
344 return -1;
345 }
346
347 rctx->transaction_id = fr_pair_copy(rctx, transaction_id);
348
349 fr_pair_list_init(&rctx->client_id);
350 fr_pair_list_init(&rctx->server_id);
351
352 /*
353 * These should just become straight copies
354 * when the structure pairs are nested.
355 */
356 switch (fr_pair_list_copy_by_ancestor(rctx, &rctx->client_id,
357 &request->request_pairs, attr_client_id)) {
358 case -1:
359 REDEBUG("Error copying Client-ID");
360 error:
361 talloc_free(rctx);
362 return -1;
363
364 case 0:
365 REDEBUG("Missing Client-ID");
366 goto error;
367
368 default:
369 break;
370 }
371
372 switch (fr_pair_list_copy_by_ancestor(rctx, &rctx->server_id,
373 &request->request_pairs, attr_server_id)) {
374 case -1:
375 REDEBUG("Error copying Server-ID");
376 goto error;
377
378 case 0:
379 if (expect_server_id) {
380 REDEBUG("Missing Server-ID");
381 goto error;
382 }
383 break;
384
385 default:
386 if (!expect_server_id) {
387 REDEBUG("Server-ID should not be present");
388 goto error;
389 }
390 break;
391 }
392
393 return 0;
394}
395
396/** Validate a solicit/rebind/confirm message
397 *
398 * Servers MUST discard any solicit/rebind/confirm messages that
399 * do not include a Client Identifier option or that do include a
400 * Server Identifier option.
401 */
402RECV(for_any_server)
403{
404 CONF_SECTION *cs;
405 fr_process_state_t const *state;
406 process_dhcpv6_t const *inst = mctx->mi->data;
407 process_dhcpv6_rctx_t *rctx = talloc_get_type_abort(mctx->rctx, process_dhcpv6_rctx_t);
408
410
411 if (dhcpv6_client_fields_store(request, rctx, false) < 0) RETURN_UNLANG_INVALID;
412
413 UPDATE_STATE_CS(packet);
414
415 return unlang_module_yield_to_section(RESULT_P, request,
416 cs, state->default_rcode, state->resume,
417 NULL, 0, rctx);
418}
419
420/** Validate a request/renew/decline/release
421 *
422 * Servers MUST discard any received Request message that meet any of
423 * the following conditions:
424 *
425 * - the message does not include a Server Identifier option.
426 *
427 * - the contents of the Server Identifier option do not match the
428 * server's DUID.
429 *
430 * - the message does not include a Client Identifier option.
431 *
432 * Servers MUST discard any received Confirm messages that do not
433 * include a Client Identifier option or that do include a Server
434 * Identifier option.
435 */
436RECV(for_this_server)
437{
438 CONF_SECTION *cs;
439 fr_process_state_t const *state;
440 process_dhcpv6_t const *inst = mctx->mi->data;
441 process_dhcpv6_rctx_t *rctx = talloc_get_type_abort(mctx->rctx, process_dhcpv6_rctx_t);
442
444
445 if (dhcpv6_client_fields_store(request, rctx, true) < 0) RETURN_UNLANG_INVALID;
446
447 UPDATE_STATE_CS(packet);
448
449 return unlang_module_yield_to_section(RESULT_P, request,
450 cs, state->default_rcode, state->resume,
451 NULL, 0, rctx);
452}
453
454/** Copy a reply pair back into the response
455 *
456 */
457static inline CC_HINT(always_inline)
458int restore_field(request_t *request, fr_pair_t **to_restore)
459{
460 fr_pair_t *vp;
461 int ret = 0;
462
463 PAIR_VERIFY(*to_restore);
464
465 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, (*to_restore)->da);
466 if (vp) {
467 if (fr_pair_cmp(vp, *to_restore) != 0) {
468 RWDEBUG("reply.%pP does not match request.%pP", vp, *to_restore);
469 free:
470 talloc_free(*to_restore);
471 *to_restore = NULL;
472 return ret;
473 }
474 } else if (fr_pair_steal_append(request->reply_ctx, &request->reply_pairs, *to_restore) < 0) {
475 RPERROR("Failed adding %s", (*to_restore)->da->name);
476 ret = -1;
477 goto free;
478 }
479 *to_restore = NULL;
480
481 return 0;
482}
483
484static inline CC_HINT(always_inline)
486{
487 fr_pair_t *vp;
488
489 while ((vp = fr_pair_list_head(to_restore))) {
490 fr_pair_remove(to_restore, vp);
491 if (restore_field(request, &vp) < 0) return -1;
492 }
493
494 return 0;
495}
496
497/** Add a status code if one doesn't already exist
498 *
499 */
500static inline CC_HINT(always_inline)
502{
503 fr_pair_t *vp, *failure_message = NULL;
504 fr_value_box_t const *vb;
505 bool moved_failure_message = false;
506
507 if (!code || !*code) return;
508
509 vb = *code;
510
511 /*
512 * If it's a success save some bytes
513 * in the packet and don't bother
514 * adding the success code unless
515 * explicitly requested to.
516 */
517 if ((vb->vb_uint16 == 0) && !inst->status_code_on_success) return;
518
519 /*
520 * Don't override the user status
521 * code.
522 */
524 if (unlikely(fr_value_box_copy(vp, &vp->data, vb) < 0)) {
525 RPERROR("Failed copying status code value");
527 return;
528 }
529 }
530
531 /*
532 * Move the module failure messages upwards
533 * if requested to by the user.
534 */
535 if (inst->move_failure_message_to_parent && request->parent && (request->parent->proto_dict == request->proto_dict)) {
536 fr_pair_t const *prev = NULL;
537
538 while ((failure_message = fr_pair_find_by_da(&request->request_pairs,
540 MEM(vp = fr_pair_copy(request->parent->request_ctx, failure_message));
541 fr_pair_append(&request->parent->request_pairs, vp);
542
543 prev = fr_pair_remove(&request->request_pairs, failure_message);
544 talloc_free(failure_message);
545 }
546
547 moved_failure_message = true;
548 }
549
550 /*
551 * Concat all the module failure messages
552 * and place them in the status code
553 * message.
554 */
555 if (inst->send_failure_message && !moved_failure_message &&
556 (failure_message = fr_pair_find_by_da(&request->request_pairs, NULL, attr_module_failure_message)) &&
559 fr_sbuff_t sbuff;
560
561 do {
562 /*
563 * Create an aggregation buffer up to
564 * the maximum length of a status
565 * message.
566 */
567 fr_sbuff_init_talloc(vp, &sbuff, &tctx, 1024, UINT16_MAX - 2);
568
569 /*
570 * Best effort... it's probably OK
571 * if we truncate really long messages.
572 */
573 if (unlikely(fr_sbuff_in_bstrncpy(&sbuff, failure_message->vp_strvalue,
574 failure_message->vp_length) < 0)) break;
575 } while ((failure_message = fr_pair_find_by_da(&request->request_pairs, failure_message,
577 (fr_sbuff_in_strcpy_literal(&sbuff, ". ") == 2));
578 fr_sbuff_trim_talloc(&sbuff, SIZE_MAX); /* Fix size */
580 }
581}
582
583/** Restore our copy of the header fields into the reply list
584 *
585 */
586RESUME(send_to_client)
587{
588 process_dhcpv6_t *inst = talloc_get_type_abort(mctx->mi->data, process_dhcpv6_t);
589 process_dhcpv6_rctx_t *fields = talloc_get_type_abort(mctx->rctx, process_dhcpv6_rctx_t);
590 fr_process_state_t const *state;
591
592
593 UPDATE_STATE(reply);
594
595 /*
596 * Don't bother adding VPs if we're not going
597 * be responding to the client.
598 */
599 if (state->packet_type[RESULT_RCODE] == FR_DHCPV6_DO_NOT_RESPOND) return CALL_RESUME(send_generic);
600
601 /*
602 * Add a status code if we have one
603 */
604 status_code_add(inst, request, state->status_codes[RESULT_RCODE]);
605
606 /*
607 * If we have a status code entry then we'll
608 * be returning something to the client and
609 * need to fill in all these fields
610 */
611 if (unlikely(restore_field(request, &fields->transaction_id) < 0)) {
612 fail:
613 p_result->rcode = RLM_MODULE_FAIL;
614 return CALL_RESUME(send_generic);
615 }
616 if (unlikely(restore_field_list(request, &fields->client_id) < 0)) goto fail;
617 if (unlikely(restore_field_list(request, &fields->server_id) < 0)) goto fail;
618
619 dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
620
621 return CALL_RESUME(send_generic);
622}
623
624/** Record the original hop-count, link-address, peer-address etc...
625 *
626 */
627static inline CC_HINT(always_inline)
629{
630 fr_pair_t *hop_count, *link_address, *peer_address, *interface_id;
632
633 hop_count = fr_pair_find_by_da(&request->request_pairs, NULL, attr_hop_count);
634 if (!hop_count) {
635 REDEBUG("Missing Hop-Count");
636 return NULL;
637 }
638
639 link_address = fr_pair_find_by_da(&request->request_pairs, NULL, attr_relay_link_address);
640 if (!link_address) {
641 REDEBUG("Missing Link-Address");
642 return NULL;
643 }
644
645 peer_address = fr_pair_find_by_da(&request->request_pairs, NULL, attr_relay_peer_address);
646 if (!peer_address) {
647 REDEBUG("Missing Peer-Address");
648 return NULL;
649 }
650
651 interface_id = fr_pair_find_by_da(&request->request_pairs, NULL, attr_interface_id);
652
653 /*
654 * Remember the relay fields
655 */
656 MEM(rctx = talloc_zero(unlang_interpret_frame_talloc_ctx(request), process_dhcpv6_relay_fields_t)); /* Safer to zero the whole thing */
657 MEM(rctx->hop_count = fr_pair_copy(rctx, hop_count));
658 MEM(rctx->link_address = fr_pair_copy(rctx, link_address));
659 MEM(rctx->peer_address = fr_pair_copy(rctx, peer_address));
660 if (interface_id) MEM(rctx->interface_id = fr_pair_copy(rctx, interface_id)); /* Optional */
661
662 return rctx;
663}
664
665/** Ensure we have the necessary pairs from the relay
666 *
667 */
668RECV(from_relay)
669{
670 CONF_SECTION *cs;
671 fr_process_state_t const *state;
672 process_dhcpv6_t const *inst = mctx->mi->data;
673 process_dhcpv6_relay_fields_t *relay_fields = NULL;
674 process_dhcpv6_rctx_t *rctx = talloc_get_type_abort(mctx->rctx, process_dhcpv6_rctx_t);
675
676 relay_fields = dhcpv6_relay_fields_store(request);
677 if (!relay_fields) RETURN_UNLANG_INVALID;
678 rctx->uctx = relay_fields;
679
680 UPDATE_STATE_CS(packet);
681
682 return unlang_module_yield_to_section(RESULT_P, request,
683 cs, state->default_rcode, state->resume,
684 NULL, 0, rctx);
685}
686
687/** Restore our copy of the header fields into the reply list
688 *
689 */
690RESUME(send_to_relay)
691{
692 process_dhcpv6_t *inst = talloc_get_type_abort(mctx->mi->data, process_dhcpv6_t);
693 process_dhcpv6_rctx_t *rctx = talloc_get_type_abort(mctx->rctx, process_dhcpv6_rctx_t);
694 process_dhcpv6_relay_fields_t *fields = talloc_get_type_abort(rctx->uctx, process_dhcpv6_relay_fields_t);
695 fr_process_state_t const *state;
696
697 UPDATE_STATE(reply);
698
699 /*
700 * Add a status code if we have one
701 */
702 status_code_add(inst, request, state->status_codes[RESULT_RCODE]);
703
704 /*
705 * Restore relay fields
706 */
707 if (unlikely(restore_field(request, &fields->hop_count) < 0)) {
708 fail:
709 p_result->rcode = RLM_MODULE_FAIL;
710 return CALL_RESUME(send_generic);
711 }
712 if (unlikely(restore_field(request, &fields->link_address) < 0)) goto fail;
713 if (unlikely(restore_field(request, &fields->peer_address) < 0)) goto fail;
714 if (fields->interface_id && unlikely(restore_field(request, &fields->interface_id) < 0)) goto fail;
715
716 dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
717
718 return CALL_RESUME(send_generic);
719}
720
721/** Main dispatch function
722 *
723 */
724static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
725{
726 fr_process_state_t const *state;
727
729
731 fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
732
733 request->component = "dhcpv6";
734 request->module = NULL;
735 fr_assert(request->proto_dict == dict_dhcpv6);
736
737 UPDATE_STATE(packet);
738
739 if (!state->recv) {
740 REDEBUG("Invalid packet type (%u)", request->packet->code);
742 }
743
744 dhcpv6_packet_debug(request, request->packet, &request->request_pairs, true);
745
746 if (unlikely(request_is_dynamic_client(request))) {
747 return new_client(p_result, mctx, request);
748 }
749
750 return state->recv(p_result, mctx, request);
751}
752
753static int mod_instantiate(module_inst_ctx_t const *mctx)
754{
755 process_dhcpv6_t *inst = talloc_get_type_abort(mctx->mi->data, process_dhcpv6_t);
756
757 inst->server_cs = cf_item_to_section(cf_parent(mctx->mi->conf));
758
759 return 0;
760}
761
762static fr_process_state_t const process_state[] = {
763 /*
764 * A client sends a Solicit message to locate
765 * servers.
766 */
767 [ FR_DHCPV6_SOLICIT ] = {
768 .recv = recv_for_any_server,
769 .resume = resume_recv_generic,
770 .packet_type = {
774 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
775
782 },
783 .status_codes = {
784 /* RLM_MODULE_NOOP - No response */
787 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
788
789 /* RLM_MODULE_FAIL - No response */
790 /* RLM_MODULE_INVALID - No response */
791 /* RLM_MODULE_REJECT - No response */
792 /* RLM_MODULE_DISALLOW - No response */
793 /* RLM_MODULE_NOTFOUND - No response */
794 },
795 .default_rcode = RLM_MODULE_NOOP,
796 .section_offset = offsetof(process_dhcpv6_sections_t, recv_solicit),
797 },
798
799 /*
800 * A client sends a Request message to request
801 * configuration parameters, including IP
802 * addresses, from a specific server.
803 */
804 [ FR_DHCPV6_REQUEST ] = {
805 .recv = recv_for_this_server,
806 .resume = resume_recv_generic,
807 .packet_type = {
811 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
812
819 },
820 .status_codes = {
824 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
825
831 },
832 .default_rcode = RLM_MODULE_NOOP,
833 .section_offset = offsetof(process_dhcpv6_sections_t, recv_request),
834 },
835
836 /*
837 * A client sends a Confirm message to any
838 * available server to determine whether the
839 * addresses it was assigned are still appropriate
840 * to the link to which the client is connected.
841 */
842 [ FR_DHCPV6_CONFIRM ] = {
843 .recv = recv_for_any_server,
844 .resume = resume_recv_generic,
845 .packet_type = {
849 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
850
857 },
858
859 /*
860 * When the server receives a Confirm message, the server determines
861 * whether the addresses in the Confirm message are appropriate for the
862 * link to which the client is attached. If all of the addresses in the
863 * Confirm message pass this test, the server returns a status of
864 * Success. If any of the addresses do not pass this test, the server
865 * returns a status of NotOnLink. If the server is unable to perform
866 * this test (for example, the server does not have information about
867 * prefixes on the link to which the client is connected), or there were
868 * no addresses in any of the IAs sent by the client, the server MUST
869 * NOT send a reply to the client.
870 */
871 .status_codes = {
872 /* RLM_MODULE_NOOP - No response */
875 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
876
877 /* RLM_MODULE_FAIL - No response */
878 /* RLM_MODULE_INVALID - No response */
880 /* RLM_MODULE_DISALLOW - No response */
881 /* RLM_MODULE_NOTFOUND - No response */
882 },
883 .default_rcode = RLM_MODULE_NOOP,
884 .section_offset = offsetof(process_dhcpv6_sections_t, recv_confirm),
885 },
886
887 /*
888 * A client sends a Renew message to the server
889 * that originally provided the client's addresses
890 * and configuration parameters to extend the
891 * lifetimes on the addresses assigned to the
892 * client and to update other configuration
893 * parameters.
894 */
895 [ FR_DHCPV6_RENEW ] = {
896 .recv = recv_for_this_server,
897 .resume = resume_recv_generic,
898 .packet_type = {
902 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
903
910 },
911
912 /*
913 * If the server cannot find a client entry for the IA the server
914 * returns the IA containing no addresses with a Status Code option set
915 * to NoBinding in the Reply message.
916 */
917 .status_codes = {
921 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
922
924 /* RLM_MODULE_INVALID - No response */
928 },
929 .default_rcode = RLM_MODULE_NOOP,
930 .section_offset = offsetof(process_dhcpv6_sections_t, recv_renew),
931 },
932
933 /*
934 * A client sends a Rebind message to any
935 * available server to extend the lifetimes on the
936 * addresses assigned to the client and to update
937 * other configuration parameters; this message is
938 * sent after a client receives no response to a
939 * Renew message.
940 */
941 [ FR_DHCPV6_REBIND ] = {
942 .recv = recv_for_any_server,
943 .resume = resume_recv_generic,
944 .packet_type = {
948 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
949
956 },
957 .status_codes = {
961 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
962
964 /* RLM_MODULE_INVALID - No response */
968 },
969 .default_rcode = RLM_MODULE_NOOP,
970 .section_offset = offsetof(process_dhcpv6_sections_t, recv_rebind),
971 },
972 /*
973 * A client sends an Information-request
974 * message to a server to request configuration
975 * parameters without the assignment of any IP
976 * addresses to the client.
977 */
979 .recv = recv_for_any_server,
980 .resume = resume_recv_generic,
981 .packet_type = {
985 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
986
993 },
994 .status_codes = {
998 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
999
1001 /* RLM_MODULE_INVALID - No response */
1005 },
1006 .default_rcode = RLM_MODULE_NOOP,
1007 .section_offset = offsetof(process_dhcpv6_sections_t, recv_information_request),
1008 },
1009 /*
1010 * A client sends a Release message to the server
1011 * that assigned addresses to the client to
1012 * indicate that the client will no longer use one
1013 * or more of the assigned addresses.
1014 */
1015 [ FR_DHCPV6_RELEASE ] = {
1016 .recv = recv_for_this_server,
1017 .resume = resume_recv_generic,
1018 .packet_type = {
1022 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1023
1030 },
1031 .status_codes = {
1035 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1036
1038 /* RLM_MODULE_INVALID - No response */
1042 },
1043 .default_rcode = RLM_MODULE_NOOP,
1044
1045 .section_offset = offsetof(process_dhcpv6_sections_t, recv_release),
1046 },
1047 /*
1048 *
1049 * A client sends a Decline message to a server to
1050 * indicate that the client has determined that
1051 * one or more addresses assigned by the server
1052 * are already in use on the link to which the
1053 * client is connected.
1054 */
1055 [ FR_DHCPV6_DECLINE ] = {
1056 .recv = recv_for_this_server, /* Need to check for attributes */
1057 .resume = resume_recv_generic,
1058 .packet_type = {
1062 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1063
1070 },
1071 .status_codes = {
1075 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1076
1078 /* RLM_MODULE_INVALID - No response */
1082 },
1083 .default_rcode = RLM_MODULE_NOOP,
1084 .result_rcode = RLM_MODULE_REJECT,
1085 .section_offset = offsetof(process_dhcpv6_sections_t, recv_decline),
1086 },
1087 /*
1088 * A relay agent sends a Relay-forward message
1089 * to relay messages to servers, either directly
1090 * or through another relay agent. The received
1091 * message, either a client message or a
1092 * Relay-forward message from another relay
1093 * agent, is encapsulated in an option in the
1094 * Relay-forward message.
1095 */
1097 .recv = recv_from_relay,
1098 .resume = resume_recv_generic,
1099 .packet_type = {
1103 /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1104
1111 },
1112 .status_codes = {
1116 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1117
1119 /* RLM_MODULE_INVALID - No response */
1123 },
1124 .default_rcode = RLM_MODULE_NOOP,
1125 .section_offset = offsetof(process_dhcpv6_sections_t, recv_relay_forward),
1126 },
1127 /*
1128 * A server sends an Advertise message to indicate
1129 * that it is available for DHCP service, in
1130 * response to a Solicit message received from a
1131 * client.
1132 */
1133 [ FR_DHCPV6_ADVERTISE ] = {
1134 .send = send_generic,
1135 .resume = resume_send_to_client,
1136 .packet_type = {
1143 },
1144 .status_codes = {
1148 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1149
1150 /* RLM_MODULE_FAIL - No response */
1151 /* RLM_MODULE_INVALID - No response */
1152 /* RLM_MODULE_REJECT - No response */
1153 /* RLM_MODULE_DISALLOW - No response */
1154 /* RLM_MODULE_NOTFOUND - No response */
1155 },
1156 .default_rcode = RLM_MODULE_NOOP,
1157 .result_rcode = RLM_MODULE_OK,
1158 .section_offset = offsetof(process_dhcpv6_sections_t, send_advertise),
1159 },
1160 /*
1161 * A server sends a Reply message containing
1162 * assigned addresses and configuration parameters
1163 * in response to a Solicit, Request, Renew,
1164 * Rebind message received from a client. A
1165 * server sends a Reply message containing
1166 * configuration parameters in response to an
1167 * Information-request message. A server sends a
1168 * Reply message in response to a Confirm message
1169 * confirming or denying that the addresses
1170 * assigned to the client are appropriate to the
1171 * link to which the client is connected. A
1172 * server sends a Reply message to acknowledge
1173 * receipt of a Release or Decline message.
1174 */
1175 [ FR_DHCPV6_REPLY ] = {
1176 .send = send_generic,
1177 .resume = resume_send_to_client,
1178 .packet_type = {
1179
1186 },
1187 .status_codes = {
1191 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1192
1194 /* RLM_MODULE_INVALID - No response */
1198 },
1199 .default_rcode = RLM_MODULE_NOOP,
1200 .result_rcode = RLM_MODULE_OK,
1201 .section_offset = offsetof(process_dhcpv6_sections_t, send_reply),
1202 },
1203 /*
1204 * A server sends a Relay-reply message to a relay
1205 * agent containing a message that the relay
1206 * agent delivers to a client. The Relay-reply
1207 * message may be relayed by other relay agents
1208 * for delivery to the destination relay agent.
1209 * The server encapsulates the client message as
1210 * an option in the Relay-reply message, which the
1211 * relay agent extracts and relays to the client.
1212 */
1213 [ FR_DHCPV6_RELAY_REPLY ] = {
1214 .send = send_generic,
1215 .resume = resume_send_to_relay,
1216 .packet_type = {
1223 },
1224 .status_codes = {
1228 /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1229
1231 /* RLM_MODULE_INVALID - No response */
1235 },
1236 .default_rcode = RLM_MODULE_NOOP,
1237 .result_rcode = RLM_MODULE_OK,
1238 .section_offset = offsetof(process_dhcpv6_sections_t, send_relay_reply),
1239 },
1240
1242 .send = send_generic,
1243 .resume = resume_send_generic,
1244 .packet_type = {
1249
1256 },
1257 .default_rcode = RLM_MODULE_NOOP,
1258 .result_rcode = RLM_MODULE_HANDLED,
1259 .section_offset = offsetof(process_dhcpv6_sections_t, do_not_respond),
1260 }
1261};
1262
1265 .common = {
1266 .magic = MODULE_MAGIC_INIT,
1267 .name = "dhcpv6",
1271
1272 .instantiate = mod_instantiate
1273 },
1274 .process = mod_process,
1275 .compile_list = compile_list,
1276 .dict = &dict_dhcpv6,
1277 .packet_type = &attr_packet_type
1278};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define unlikely(_x)
Definition build.h:383
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:660
#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:283
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:597
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
#define cf_parent(_cf)
Definition cf_util.h:101
#define MEM(x)
Definition debug.h:36
@ FR_DHCPV6_RELEASE
Definition dhcpv6.h:75
@ FR_DHCPV6_DECLINE
Definition dhcpv6.h:76
@ FR_DHCPV6_ADVERTISE
Definition dhcpv6.h:69
@ FR_DHCPV6_DO_NOT_RESPOND
Definition dhcpv6.h:104
@ FR_DHCPV6_REBIND
Definition dhcpv6.h:73
@ FR_DHCPV6_REPLY
Definition dhcpv6.h:74
@ FR_DHCPV6_CONFIRM
Definition dhcpv6.h:71
@ FR_DHCPV6_SOLICIT
Definition dhcpv6.h:68
@ FR_DHCPV6_RENEW
Definition dhcpv6.h:72
@ FR_DHCPV6_INFORMATION_REQUEST
Definition dhcpv6.h:78
@ FR_DHCPV6_REQUEST
Definition dhcpv6.h:70
@ FR_DHCPV6_RELAY_FORWARD
Definition dhcpv6.h:79
@ FR_DHCPV6_RELAY_REPLY
Definition dhcpv6.h:80
#define DHCPV6_TRANSACTION_ID_LEN
Definition dhcpv6.h:37
fr_value_box_t const ** out
Enumeration value.
Definition dict.h:282
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:293
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:306
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:312
Specifies an attribute which must be present for the module to function.
Definition dict.h:292
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:305
Specifies a value which must be present for the module to function.
Definition dict.h:281
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
free(array)
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition interpret.c:1658
static fr_dict_t const * dict_freeradius
Definition base.c:37
fr_dict_attr_t const * attr_packet_type
Definition base.c:93
static fr_dict_attr_t const * attr_module_failure_message
Definition log.c:206
void log_request_proto_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a list of protocol fr_pair_ts.
Definition log.c:868
void log_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt,...)
Marshal variadic log arguments into a va_list and pass to normal logging functions.
Definition log.c:610
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
Definition log.c:844
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RPERROR(fmt,...)
Definition log.h:302
talloc_free(reap)
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition log.h:70
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:59
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_OCTETS
Raw octets.
unlang_mod_actions_t const mod_actions_postauth
Definition mod_action.c:93
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Definition mod_action.h:64
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
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:703
int fr_pair_cmp(fr_pair_t const *a, fr_pair_t const *b)
Compare two pairs, using the operator from "a".
Definition pair.c:1972
int fr_pair_value_bstrndup_shallow(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Assign a string to a "string" type value pair.
Definition pair.c:2846
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:1348
int fr_pair_list_copy_by_ancestor(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_dict_attr_t const *parent_da)
Duplicate pairs in a list where the da is a descendant of parent_da.
Definition pair.c:2465
int fr_pair_steal_append(TALLOC_CTX *list_ctx, fr_pair_list_t *list, fr_pair_t *vp)
Change a vp's talloc ctx and insert it into a new list.
Definition pair.c:556
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition pair.c:497
static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition base.c:188
static const virtual_server_compile_t compile_list[]
Definition base.c:214
static fr_process_state_t const process_state[]
Definition base.c:69
#define PROCESS_PACKET_CODE_VALID
Definition base.c:65
CONF_SECTION * send_advertise
Definition base.c:58
CONF_SECTION * recv_information_request
Definition base.c:55
static fr_dict_attr_t const * attr_hop_count
Definition base.c:131
CONF_SECTION * send_reply
Definition base.c:59
static fr_dict_attr_t const * attr_status_code_message
Definition base.c:138
CONF_SECTION * recv_solicit
Definition base.c:46
static fr_dict_attr_t const * attr_status_code_value
Definition base.c:137
static fr_dict_attr_t const * attr_relay_link_address
Definition base.c:134
bool move_failure_message_to_parent
If true, and a parent exists, and the parent is a DHCPv6 request, all module failure messages will ge...
Definition base.c:89
CONF_SECTION * recv_request
Definition base.c:47
static int restore_field_list(request_t *request, fr_pair_list_t *to_restore)
Definition base.c:485
fr_dict_autoload_t process_dhcpv6_dict[]
Definition base.c:123
fr_dict_enum_autoload_t process_dhcpv6_dict_enum[]
Definition base.c:165
static fr_value_box_t const * enum_status_code_success
Definition base.c:159
fr_pair_list_t server_id
Definition base.c:105
static void status_code_add(process_dhcpv6_t const *inst, request_t *request, fr_value_box_t const **code)
Add a status code if one doesn't already exist.
Definition base.c:501
CONF_SECTION * server_cs
Our virtual server.
Definition base.c:70
static int restore_field(request_t *request, fr_pair_t **to_restore)
Copy a reply pair back into the response.
Definition base.c:458
CONF_SECTION * do_not_respond
Definition base.c:62
static fr_value_box_t const * enum_status_code_no_binding
Definition base.c:162
fr_pair_list_t client_id
Definition base.c:104
bool status_code_on_success
Controls whether we add a status-code option to outbound packets if the status code would be 0.
Definition base.c:73
CONF_SECTION * recv_decline
Definition base.c:52
static fr_dict_attr_t const * attr_interface_id
Definition base.c:132
static fr_dict_attr_t const * attr_server_id
Definition base.c:130
CONF_SECTION * recv_relay_forward
Definition base.c:56
CONF_SECTION * deny_client
Definition base.c:66
static fr_value_box_t const * enum_status_code_unspec_fail
Definition base.c:160
CONF_SECTION * recv_rebind
Definition base.c:50
static conf_parser_t dhcpv6_process_config[]
Definition base.c:191
CONF_SECTION * recv_release
Definition base.c:51
static int dhcpv6_client_fields_store(request_t *request, process_dhcpv6_rctx_t *rctx, bool expect_server_id)
Keep a copy of header fields to prevent them being tampered with.
Definition base.c:331
fr_pair_t * transaction_id
Definition base.c:103
CONF_SECTION * recv_renew
Definition base.c:49
static void dhcpv6_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
Definition base.c:279
CONF_SECTION * new_client
Definition base.c:64
fr_dict_attr_autoload_t process_dhcpv6_dict_attr[]
Definition base.c:143
unlang_result_t result
Definition base.c:106
CONF_SECTION * add_client
Definition base.c:65
bool send_failure_message
If true, all instances of Module-Failure-Message in the request are concatenated and returned in the ...
Definition base.c:79
CONF_SECTION * recv_reconfigure
Definition base.c:53
static fr_dict_t const * dict_dhcpv6
Definition base.c:119
static process_dhcpv6_relay_fields_t * dhcpv6_relay_fields_store(request_t *request)
Record the original hop-count, link-address, peer-address etc...
Definition base.c:628
static fr_dict_attr_t const * attr_transaction_id
Definition base.c:136
static fr_dict_attr_t const * attr_client_id
Definition base.c:129
static fr_value_box_t const * enum_status_code_not_on_link
Definition base.c:161
CONF_SECTION * recv_confirm
Definition base.c:48
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition base.c:753
process_dhcpv6_sections_t sections
Pointers to various config sections we need to execute.
Definition base.c:71
CONF_SECTION * send_relay_reply
Definition base.c:60
static fr_dict_attr_t const * attr_relay_peer_address
Definition base.c:135
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
Definition base.c:402
fr_process_module_t process_dhcpv6
Definition base.c:1264
Records fields from the original request so we have a known good copy.
Definition base.c:102
Records fields from the original relay-request so we have a known good copy.
Definition base.c:112
#define PROCESS_TRACE
Trace each state function as it's entered.
Definition process.h:55
#define PROCESS_CONF_OFFSET(_x)
Definition process.h:79
module_t common
Common fields for all loadable modules.
Common public symbol definition for all process modules.
char const * fr_dhcpv6_packet_names[FR_DHCPV6_CODE_MAX]
Definition base.c:72
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG_ENABLED()
Definition radclient.h:49
static void send_reply(int sockfd, fr_channel_data_t *reply)
#define RETURN_UNLANG_INVALID
Definition rcode.h:62
#define RETURN_UNLANG_FAIL
Definition rcode.h:59
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:47
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:45
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:44
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition rcode.h:48
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:43
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
Definition rcode.h:52
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:49
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:51
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:50
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:46
#define request_is_dynamic_client(_x)
Definition request.h:188
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
Definition sbuff.c:424
ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len)
Copy bytes into the sbuff up to the first \0.
Definition sbuff.c:1483
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_used(_sbuff_or_marker)
#define fr_sbuff_in_strcpy_literal(_sbuff, _str)
Talloc sbuff extension structure.
Definition sbuff.h:140
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:349
void * data
Module's instance data.
Definition module.h:291
#define MODULE_RCTX(_ctype)
Definition module.h:257
#define MODULE_INST(_ctype)
Definition module.h:255
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:206
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition pair.h:129
#define pair_delete_reply(_pair_or_da)
Delete a fr_pair_t in the reply list.
Definition pair.h:181
unlang_action_t unlang_module_yield_to_section(unlang_result_t *p_result, request_t *request, CONF_SECTION *subcs, rlm_rcode_t default_rcode, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Definition module.c:236
eap_aka_sim_process_conf_t * inst
#define RESUME(_x)
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:244
unsigned int code
Packet code (type).
Definition packet.h:61
fr_socket_t socket
This packet was received on.
Definition packet.h:57
int id
Packet ID (used to link requests/responses).
Definition packet.h:60
#define PAIR_VERIFY(_x)
Definition pair.h:202
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
Definition pair_inline.c:93
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:42
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:78
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:4174
#define fr_box_ipaddr(_val)
Definition value.h:316
section_name_t const * section
Identifier for the section.
#define COMPILE_TERMINATOR
Processing sections which are allowed in this virtual server.