The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: fd2117bb6f0e1b583bcfb8001e454a82ef1cd4af $
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  */
43 typedef struct {
44  uint64_t nothing; // so that "solicit" isn't at offset 0
45 
54 
57 
61 
63 
68 
69 typedef 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  */
102 typedef struct {
107 
108 /** Records fields from the original relay-request so we have a known good copy
109  */
110 typedef struct {
116 
117 static fr_dict_t const *dict_dhcpv6;
119 
122  { .out = &dict_dhcpv6, .proto = "dhcpv6" },
123  { .out = &dict_freeradius, .proto = "freeradius" },
124  { NULL }
125 };
126 
137 
139 
142  { .out = &attr_client_id, .name = "Client-ID", .type = FR_TYPE_STRUCT, .dict = &dict_dhcpv6 },
143  { .out = &attr_hop_count, .name = "Hop-Count", .type = FR_TYPE_UINT8, .dict = &dict_dhcpv6 },
144  { .out = &attr_interface_id, .name = "Interface-ID", .type = FR_TYPE_OCTETS, .dict = &dict_dhcpv6 },
145  { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_dhcpv6 },
146  { .out = &attr_relay_link_address, .name = "Relay-Link-Address", .type = FR_TYPE_IPV6_ADDR, .dict = &dict_dhcpv6 },
147  { .out = &attr_relay_peer_address, .name = "Relay-Peer-Address", .type = FR_TYPE_IPV6_ADDR, .dict = &dict_dhcpv6 },
148  { .out = &attr_server_id, .name = "Server-ID", .type = FR_TYPE_STRUCT, .dict = &dict_dhcpv6 },
149  { .out = &attr_status_code_value, .name = "Status-Code.Value", .type = FR_TYPE_UINT16, .dict = &dict_dhcpv6 },
150  { .out = &attr_status_code_message, .name = "Status-Code.Message", .type = FR_TYPE_STRING, .dict = &dict_dhcpv6 },
151  { .out = &attr_transaction_id, .name = "Transaction-Id", .type = FR_TYPE_OCTETS, .dict = &dict_dhcpv6 },
152 
153  { .out = &attr_module_failure_message, .name = "Module-Failure-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
154  { NULL }
155 };
156 
161 
164  { .out = &enum_status_code_success, .name = "success", .attr = &attr_status_code_value },
165  { .out = &enum_status_code_unspec_fail, .name = "UnspecFail", .attr = &attr_status_code_value },
166  { .out = &enum_status_code_not_on_link, .name = "NotOnLink", .attr = &attr_status_code_value },
167  { .out = &enum_status_code_no_binding, .name = "NoBinding", .attr = &attr_status_code_value },
168  { NULL }
169 };
170 
171 #define FR_DHCPV6_PROCESS_CODE_VALID(_x) (FR_DHCPV6_PACKET_CODE_VALID(_x) || (_x == FR_DHCPV6_DO_NOT_RESPOND))
172 
173 #define PROCESS_PACKET_TYPE fr_dhcpv6_packet_code_t
174 #define PROCESS_CODE_MAX FR_DHCPV6_CODE_MAX
175 #define PROCESS_CODE_DO_NOT_RESPOND FR_DHCPV6_DO_NOT_RESPOND
176 #define PROCESS_PACKET_CODE_VALID FR_DHCPV6_PROCESS_CODE_VALID
177 #define PROCESS_INST process_dhcpv6_t
178 #define PROCESS_CODE_DYNAMIC_CLIENT FR_DHCPV6_REPLY
179 
180 /*
181  * DHCPv6 is nonstandard in that we reply
182  * to the majority of requests, but include a
183  * status code to indicate failures.
184  */
185 #define PROCESS_STATE_EXTRA_FIELDS fr_value_box_t const **status_codes[RLM_MODULE_NUMCODES];
186 #include <freeradius-devel/server/process.h>
187 
189  { FR_CONF_OFFSET("status_code_on_success", process_dhcpv6_t, status_code_on_success), .dflt = "no" },
190  { FR_CONF_OFFSET("send_failure_message", process_dhcpv6_t, send_failure_message), .dflt = "no" },
191  { FR_CONF_OFFSET("move_failure_message_to_parent", process_dhcpv6_t, move_failure_message_to_parent), .dflt = "yes" },
193 };
194 
196  {
197  .section = SECTION_NAME("recv", "Solicit"),
198  .actions = &mod_actions_postauth,
199  .offset = PROCESS_CONF_OFFSET(recv_solicit)
200  },
201  {
202  .section = SECTION_NAME("recv", "Request"),
203  .actions = &mod_actions_postauth,
204  .offset = PROCESS_CONF_OFFSET(recv_request)
205  },
206  {
207  .section = SECTION_NAME("recv", "Confirm"),
208  .actions = &mod_actions_postauth,
209  .offset = PROCESS_CONF_OFFSET(recv_confirm)
210  },
211  {
212  .section = SECTION_NAME("recv", "Renew"),
213  .actions = &mod_actions_postauth,
214  .offset = PROCESS_CONF_OFFSET(recv_renew)
215  },
216  {
217  .section = SECTION_NAME("recv", "Rebind"),
218  .actions = &mod_actions_postauth,
219  .offset = PROCESS_CONF_OFFSET(recv_rebind)
220  },
221  {
222  .section = SECTION_NAME("recv", "Release"),
223  .actions = &mod_actions_postauth,
224  .offset = PROCESS_CONF_OFFSET(recv_release)
225  },
226  {
227  .section = SECTION_NAME("recv", "Decline"),
228  .actions = &mod_actions_postauth,
229  .offset = PROCESS_CONF_OFFSET(recv_decline)
230  },
231  {
232  .section = SECTION_NAME("recv", "Reconfigure"),
233  .actions = &mod_actions_postauth,
234  .offset = PROCESS_CONF_OFFSET(recv_reconfigure)
235  },
236  {
237  .section = SECTION_NAME("recv", "Information-Request"),
238  .actions = &mod_actions_postauth,
239  .offset = PROCESS_CONF_OFFSET(recv_information_request)
240  },
241  {
242  .section = SECTION_NAME("recv", "Relay-Forward"),
243  .actions = &mod_actions_postauth,
244  .offset = PROCESS_CONF_OFFSET(recv_relay_forward)
245  },
246 
247  {
248  .section = SECTION_NAME("send", "Advertise"),
249  .actions = &mod_actions_postauth,
250  .offset = PROCESS_CONF_OFFSET(send_advertise)
251  },
252  {
253  .section = SECTION_NAME("send", "Reply"),
254  .actions = &mod_actions_postauth,
255  .offset = PROCESS_CONF_OFFSET(send_reply)
256  },
257  {
258  .section = SECTION_NAME("send", "Relay-Reply"),
259  .actions = &mod_actions_postauth,
260  .offset = PROCESS_CONF_OFFSET(send_relay_reply)
261  },
262  {
263  .section = SECTION_NAME("send", "Do-Not-Respond"),
264  .actions = &mod_actions_postauth,
265  .offset = PROCESS_CONF_OFFSET(do_not_respond)
266  },
267 
268  DYNAMIC_CLIENT_SECTIONS,
269 
271 };
272 
273 /*
274  * Debug the packet if requested.
275  */
276 static void dhcpv6_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
277 {
278 #ifdef WITH_IFINDEX_NAME_RESOLUTION
279  char if_name[IFNAMSIZ];
280 #endif
281  char const *module;
282 
283  if (!packet) return;
284  if (!RDEBUG_ENABLED) return;
285 
286  /*
287  * Looks better without module prefix
288  */
289  module = request->module;
290  request->module = NULL;
291 
292  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 "
293 #ifdef WITH_IFINDEX_NAME_RESOLUTION
294  "%s%s%s"
295 #endif
296  "",
297  received ? "Received" : "Sending",
298  fr_dhcpv6_packet_names[packet->code],
299  packet->id,
300  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
301  fr_box_ipaddr(packet->socket.inet.src_ipaddr),
302  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
303  packet->socket.inet.src_port,
304  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
305  fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
306  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
307  packet->socket.inet.dst_port
308 #ifdef WITH_IFINDEX_NAME_RESOLUTION
309  , packet->socket.inet.ifindex ? "via " : "",
310  packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
311  packet->socket.inet.ifindex ? " " : ""
312 #endif
313  );
314 
315  if (received || request->parent) {
316  log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
317  } else {
318  log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
319  }
320 
321  request->module = module;
322 }
323 
324 /** Keep a copy of header fields to prevent them being tampered with
325  *
326  */
327 static inline CC_HINT(always_inline)
329 {
330  fr_pair_t *transaction_id;
332 
333  transaction_id = fr_pair_find_by_da(&request->request_pairs, NULL, attr_transaction_id);
334  if (!transaction_id) {
335  REDEBUG("Missing Transaction-ID");
336  return NULL;
337  }
338 
339  if (transaction_id->vp_length != DHCPV6_TRANSACTION_ID_LEN) {
340  REDEBUG("Invalid Transaction-ID, expected len %u, got len %zu",
341  DHCPV6_TRANSACTION_ID_LEN, transaction_id->vp_length);
342  return NULL;
343  }
344 
346  rctx->transaction_id = fr_pair_copy(rctx, transaction_id);
347 
350 
351  /*
352  * These should just become straight copies
353  * when the structure pairs are nested.
354  */
355  switch (fr_pair_list_copy_by_ancestor(rctx, &rctx->client_id,
356  &request->request_pairs, attr_client_id)) {
357  case -1:
358  REDEBUG("Error copying Client-ID");
359  error:
360  talloc_free(rctx);
361  return NULL;
362 
363  case 0:
364  REDEBUG("Missing Client-ID");
365  goto error;
366 
367  default:
368  break;
369  }
370 
371  switch (fr_pair_list_copy_by_ancestor(rctx, &rctx->server_id,
372  &request->request_pairs, attr_server_id)) {
373  case -1:
374  REDEBUG("Error copying Server-ID");
375  goto error;
376 
377  case 0:
378  if (expect_server_id) {
379  REDEBUG("Missing Server-ID");
380  goto error;
381  }
382  break;
383 
384  default:
385  if (!expect_server_id) {
386  REDEBUG("Server-ID should not be present");
387  goto error;
388  }
389  break;
390  }
391 
392  return rctx;
393 }
394 
395 /** Validate a solicit/rebind/confirm message
396  *
397  * Servers MUST discard any solicit/rebind/confirm messages that
398  * do not include a Client Identifier option or that do include a
399  * Server Identifier option.
400  */
401 RECV(for_any_server)
402 {
403  CONF_SECTION *cs;
404  fr_process_state_t const *state;
405  process_dhcpv6_t const *inst = mctx->mi->data;
406  process_dhcpv6_client_fields_t *rctx = NULL;
407 
409 
410  rctx = dhcpv6_client_fields_store(request, false);
411  if (!rctx) RETURN_MODULE_INVALID;
412 
413  UPDATE_STATE_CS(packet);
414 
415  return unlang_module_yield_to_section(p_result, request,
416  cs, state->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  */
436 RECV(for_this_server)
437 {
438  CONF_SECTION *cs;
439  fr_process_state_t const *state;
440  process_dhcpv6_t const *inst = mctx->mi->data;
442 
444 
445  rctx = dhcpv6_client_fields_store(request, true);
446  if (!rctx) RETURN_MODULE_INVALID;
447 
448  UPDATE_STATE_CS(packet);
449 
450  return unlang_module_yield_to_section(p_result, request,
451  cs, state->rcode, state->resume,
452  NULL, 0, rctx);
453 }
454 
455 /** Copy a reply pair back into the response
456  *
457  */
458 static inline CC_HINT(always_inline)
459 int restore_field(request_t *request, fr_pair_t **to_restore)
460 {
461  fr_pair_t *vp;
462  int ret = 0;
463 
464  PAIR_VERIFY(*to_restore);
465 
466  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, (*to_restore)->da);
467  if (vp) {
468  if (fr_pair_cmp(vp, *to_restore) != 0) {
469  RWDEBUG("&reply.%pP does not match &request.%pP", vp, *to_restore);
470  free:
471  talloc_free(*to_restore);
472  *to_restore = NULL;
473  return ret;
474  }
475  } else if (fr_pair_steal_append(request->reply_ctx, &request->reply_pairs, *to_restore) < 0) {
476  RPERROR("Failed adding %s", (*to_restore)->da->name);
477  ret = -1;
478  goto free;
479  }
480  *to_restore = NULL;
481 
482  return 0;
483 }
484 
485 static inline CC_HINT(always_inline)
486 int restore_field_list(request_t *request, fr_pair_list_t *to_restore)
487 {
488  fr_pair_t *vp;
489 
490  while ((vp = fr_pair_list_head(to_restore))) {
491  fr_pair_remove(to_restore, vp);
492  if (restore_field(request, &vp) < 0) return -1;
493  }
494 
495  return 0;
496 }
497 
498 /** Add a status code if one doesn't already exist
499  *
500  */
501 static inline CC_HINT(always_inline)
502 void status_code_add(process_dhcpv6_t const *inst, request_t *request, fr_value_box_t const **code)
503 {
504  fr_pair_t *vp, *failure_message = NULL;
505  fr_value_box_t const *vb;
506  bool moved_failure_message = false;
507 
508  if (!code || !*code) return;
509 
510  vb = *code;
511 
512  /*
513  * If it's a success save some bytes
514  * in the packet and don't bother
515  * adding the success code unless
516  * explicitly requested to.
517  */
518  if ((vb->vb_uint16 == 0) && !inst->status_code_on_success) return;
519 
520  /*
521  * Don't override the user status
522  * code.
523  */
525 
526  /*
527  * Move the module failure messages upwards
528  * if requested to by the user.
529  */
530  if (inst->move_failure_message_to_parent && request->parent && (request->parent->dict == request->dict)) {
531  fr_pair_t const *prev = NULL;
532 
533  while ((failure_message = fr_pair_find_by_da(&request->request_pairs,
534  prev, attr_module_failure_message))) {
535  MEM(vp = fr_pair_copy(request->parent->request_ctx, failure_message));
536  fr_pair_append(&request->parent->request_pairs, vp);
537 
538  prev = fr_pair_remove(&request->request_pairs, failure_message);
539  talloc_free(failure_message);
540  }
541 
542  moved_failure_message = true;
543  }
544 
545  /*
546  * Concat all the module failure messages
547  * and place them in the status code
548  * message.
549  */
550  if (inst->send_failure_message && !moved_failure_message &&
551  (failure_message = fr_pair_find_by_da(&request->request_pairs, NULL, attr_module_failure_message)) &&
554  fr_sbuff_t sbuff;
555 
556  do {
557  /*
558  * Create an aggregation buffer up to
559  * the maximum length of a status
560  * message.
561  */
562  fr_sbuff_init_talloc(vp, &sbuff, &tctx, 1024, UINT16_MAX - 2);
563 
564  /*
565  * Best effort... it's probably OK
566  * if we truncate really long messages.
567  */
568  if (unlikely(fr_sbuff_in_bstrncpy(&sbuff, failure_message->vp_strvalue,
569  failure_message->vp_length) < 0)) break;
570  } while ((failure_message = fr_pair_find_by_da(&request->request_pairs, failure_message,
572  (fr_sbuff_in_strcpy_literal(&sbuff, ". ") == 2));
573  fr_sbuff_trim_talloc(&sbuff, SIZE_MAX); /* Fix size */
575  }
576 }
577 
578 /** Restore our copy of the header fields into the reply list
579  *
580  */
581 RESUME(send_to_client)
582 {
583  process_dhcpv6_t *inst = talloc_get_type_abort(mctx->mi->data, process_dhcpv6_t);
584  process_dhcpv6_client_fields_t *fields = talloc_get_type_abort(mctx->rctx, process_dhcpv6_client_fields_t);
585  fr_process_state_t const *state;
586 
587 
588  UPDATE_STATE(reply);
589 
590  /*
591  * Don't bother adding VPs if we're not going
592  * be responding to the client.
593  */
594  if (state->packet_type[*p_result] == FR_DHCPV6_DO_NOT_RESPOND) return CALL_RESUME(send_generic);
595 
596  /*
597  * Add a status code if we have one
598  */
599  status_code_add(inst, request, state->status_codes[*p_result]);
600 
601  /*
602  * If we have a status code entry then we'll
603  * be returning something to the client and
604  * need to fill in all these fields
605  */
606  if (unlikely(restore_field(request, &fields->transaction_id) < 0)) {
607  fail:
608  *p_result = RLM_MODULE_FAIL;
609  return CALL_RESUME(send_generic);
610  }
611  if (unlikely(restore_field_list(request, &fields->client_id) < 0)) goto fail;
612  if (unlikely(restore_field_list(request, &fields->server_id) < 0)) goto fail;
613 
614  dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
615 
616  return CALL_RESUME(send_generic);
617 }
618 
619 /** Record the original hop-count, link-address, peer-address etc...
620  *
621  */
622 static inline CC_HINT(always_inline)
624 {
625  fr_pair_t *hop_count, *link_address, *peer_address, *interface_id;
627 
628  hop_count = fr_pair_find_by_da(&request->request_pairs, NULL, attr_hop_count);
629  if (!hop_count) {
630  REDEBUG("Missing Hop-Count");
631  return NULL;
632  }
633 
634  link_address = fr_pair_find_by_da(&request->request_pairs, NULL, attr_relay_link_address);
635  if (!link_address) {
636  REDEBUG("Missing Link-Address");
637  return NULL;
638  }
639 
640  peer_address = fr_pair_find_by_da(&request->request_pairs, NULL, attr_relay_peer_address);
641  if (!peer_address) {
642  REDEBUG("Missing Peer-Address");
643  return NULL;
644  }
645 
646  interface_id = fr_pair_find_by_da(&request->request_pairs, NULL, attr_interface_id);
647 
648  /*
649  * Remember the relay fields
650  */
651  MEM(rctx = talloc_zero(unlang_interpret_frame_talloc_ctx(request), process_dhcpv6_relay_fields_t)); /* Safer to zero the whole thing */
652  MEM(rctx->hop_count = fr_pair_copy(rctx, hop_count));
653  MEM(rctx->link_address = fr_pair_copy(rctx, link_address));
654  MEM(rctx->peer_address = fr_pair_copy(rctx, peer_address));
655  if (interface_id) MEM(rctx->interface_id = fr_pair_copy(rctx, interface_id)); /* Optional */
656 
657  return rctx;
658 }
659 
660 /** Ensure we have the necessary pairs from the relay
661  *
662  */
663 RECV(from_relay)
664 {
665  CONF_SECTION *cs;
666  fr_process_state_t const *state;
667  process_dhcpv6_t const *inst = mctx->mi->data;
668  process_dhcpv6_relay_fields_t *rctx = NULL;
669 
670  rctx = dhcpv6_relay_fields_store(request);
671  if (!rctx) RETURN_MODULE_INVALID;
672 
673  UPDATE_STATE_CS(packet);
674 
675  return unlang_module_yield_to_section(p_result, request,
676  cs, state->rcode, state->resume,
677  NULL, 0, rctx);
678 }
679 
680 /** Restore our copy of the header fields into the reply list
681  *
682  */
683 RESUME(send_to_relay)
684 {
685  process_dhcpv6_t *inst = talloc_get_type_abort(mctx->mi->data, process_dhcpv6_t);
686  process_dhcpv6_relay_fields_t *fields = talloc_get_type_abort(mctx->rctx, process_dhcpv6_relay_fields_t);
687  fr_process_state_t const *state;
688 
689  UPDATE_STATE(reply);
690 
691  /*
692  * Add a status code if we have one
693  */
694  status_code_add(inst, request, state->status_codes[*p_result]);
695 
696  /*
697  * Restore relay fields
698  */
699  if (unlikely(restore_field(request, &fields->hop_count) < 0)) {
700  fail:
701  *p_result = RLM_MODULE_FAIL;
702  return CALL_RESUME(send_generic);
703  }
704  if (unlikely(restore_field(request, &fields->link_address) < 0)) goto fail;
705  if (unlikely(restore_field(request, &fields->peer_address) < 0)) goto fail;
706  if (fields->interface_id && unlikely(restore_field(request, &fields->interface_id) < 0)) goto fail;
707 
708  dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
709 
710  return CALL_RESUME(send_generic);
711 }
712 
713 /** Main dispatch function
714  *
715  */
716 static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
717 {
718  fr_process_state_t const *state;
719 
721 
723  fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
724 
725  request->component = "dhcpv6";
726  request->module = NULL;
727  fr_assert(request->dict == dict_dhcpv6);
728 
729  UPDATE_STATE(packet);
730 
731  if (!state->recv) {
732  REDEBUG("Invalid packet type (%u)", request->packet->code);
734  }
735 
736  dhcpv6_packet_debug(request, request->packet, &request->request_pairs, true);
737 
738  if (unlikely(request_is_dynamic_client(request))) {
739  return new_client(p_result, mctx, request);
740  }
741 
742  return state->recv(p_result, mctx, request);
743 }
744 
745 static int mod_instantiate(module_inst_ctx_t const *mctx)
746 {
747  process_dhcpv6_t *inst = talloc_get_type_abort(mctx->mi->data, process_dhcpv6_t);
748 
749  inst->server_cs = cf_item_to_section(cf_parent(mctx->mi->conf));
750 
751  return 0;
752 }
753 
754 static fr_process_state_t const process_state[] = {
755  /*
756  * A client sends a Solicit message to locate
757  * servers.
758  */
759  [ FR_DHCPV6_SOLICIT ] = {
760  .recv = recv_for_any_server,
761  .resume = resume_recv_generic,
762  .packet_type = {
766  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
767 
773  },
774  .status_codes = {
775  /* RLM_MODULE_NOOP - No response */
778  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
779 
780  /* RLM_MODULE_FAIL - No response */
781  /* RLM_MODULE_INVALID - No response */
782  /* RLM_MODULE_REJECT - No response */
783  /* RLM_MODULE_DISALLOW - No response */
784  /* RLM_MODULE_NOTFOUND - No response */
785  },
786  .rcode = RLM_MODULE_NOOP,
787  .section_offset = offsetof(process_dhcpv6_sections_t, recv_solicit),
788  },
789 
790  /*
791  * A client sends a Request message to request
792  * configuration parameters, including IP
793  * addresses, from a specific server.
794  */
795  [ FR_DHCPV6_REQUEST ] = {
796  .recv = recv_for_this_server,
797  .resume = resume_recv_generic,
798  .packet_type = {
802  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
803 
809  },
810  .status_codes = {
814  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
815 
821  },
822  .rcode = RLM_MODULE_NOOP,
823  .section_offset = offsetof(process_dhcpv6_sections_t, recv_request),
824  },
825 
826  /*
827  * A client sends a Confirm message to any
828  * available server to determine whether the
829  * addresses it was assigned are still appropriate
830  * to the link to which the client is connected.
831  */
832  [ FR_DHCPV6_CONFIRM ] = {
833  .recv = recv_for_any_server,
834  .resume = resume_recv_generic,
835  .packet_type = {
839  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
840 
846  },
847 
848  /*
849  * When the server receives a Confirm message, the server determines
850  * whether the addresses in the Confirm message are appropriate for the
851  * link to which the client is attached. If all of the addresses in the
852  * Confirm message pass this test, the server returns a status of
853  * Success. If any of the addresses do not pass this test, the server
854  * returns a status of NotOnLink. If the server is unable to perform
855  * this test (for example, the server does not have information about
856  * prefixes on the link to which the client is connected), or there were
857  * no addresses in any of the IAs sent by the client, the server MUST
858  * NOT send a reply to the client.
859  */
860  .status_codes = {
861  /* RLM_MODULE_NOOP - No response */
864  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
865 
866  /* RLM_MODULE_FAIL - No response */
867  /* RLM_MODULE_INVALID - No response */
869  /* RLM_MODULE_DISALLOW - No response */
870  /* RLM_MODULE_NOTFOUND - No response */
871  },
872  .rcode = RLM_MODULE_NOOP,
873  .section_offset = offsetof(process_dhcpv6_sections_t, recv_confirm),
874  },
875 
876  /*
877  * A client sends a Renew message to the server
878  * that originally provided the client's addresses
879  * and configuration parameters to extend the
880  * lifetimes on the addresses assigned to the
881  * client and to update other configuration
882  * parameters.
883  */
884  [ FR_DHCPV6_RENEW ] = {
885  .recv = recv_for_this_server,
886  .resume = resume_recv_generic,
887  .packet_type = {
891  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
892 
898  },
899 
900  /*
901  * If the server cannot find a client entry for the IA the server
902  * returns the IA containing no addresses with a Status Code option set
903  * to NoBinding in the Reply message.
904  */
905  .status_codes = {
909  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
910 
912  /* RLM_MODULE_INVALID - No response */
916  },
917  .rcode = RLM_MODULE_NOOP,
918  .section_offset = offsetof(process_dhcpv6_sections_t, recv_renew),
919  },
920 
921  /*
922  * A client sends a Rebind message to any
923  * available server to extend the lifetimes on the
924  * addresses assigned to the client and to update
925  * other configuration parameters; this message is
926  * sent after a client receives no response to a
927  * Renew message.
928  */
929  [ FR_DHCPV6_REBIND ] = {
930  .recv = recv_for_any_server,
931  .resume = resume_recv_generic,
932  .packet_type = {
936  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
937 
943  },
944  .status_codes = {
948  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
949 
951  /* RLM_MODULE_INVALID - No response */
955  },
956  .rcode = RLM_MODULE_NOOP,
957  .section_offset = offsetof(process_dhcpv6_sections_t, recv_rebind),
958  },
959  /*
960  * A client sends an Information-request
961  * message to a server to request configuration
962  * parameters without the assignment of any IP
963  * addresses to the client.
964  */
966  .recv = recv_for_any_server,
967  .resume = resume_recv_generic,
968  .packet_type = {
972  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
973 
979  },
980  .status_codes = {
984  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
985 
987  /* RLM_MODULE_INVALID - No response */
991  },
992  .rcode = RLM_MODULE_NOOP,
993  .section_offset = offsetof(process_dhcpv6_sections_t, recv_information_request),
994  },
995  /*
996  * A client sends a Release message to the server
997  * that assigned addresses to the client to
998  * indicate that the client will no longer use one
999  * or more of the assigned addresses.
1000  */
1001  [ FR_DHCPV6_RELEASE ] = {
1002  .recv = recv_for_this_server,
1003  .resume = resume_recv_generic,
1004  .packet_type = {
1008  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1009 
1015  },
1016  .status_codes = {
1020  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1021 
1023  /* RLM_MODULE_INVALID - No response */
1027  },
1028  .rcode = RLM_MODULE_NOOP,
1029 
1030  .section_offset = offsetof(process_dhcpv6_sections_t, recv_release),
1031  },
1032  /*
1033  *
1034  * A client sends a Decline message to a server to
1035  * indicate that the client has determined that
1036  * one or more addresses assigned by the server
1037  * are already in use on the link to which the
1038  * client is connected.
1039  */
1040  [ FR_DHCPV6_DECLINE ] = {
1041  .recv = recv_for_this_server, /* Need to check for attributes */
1042  .resume = resume_recv_generic,
1043  .packet_type = {
1047  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1048 
1054  },
1055  .status_codes = {
1059  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1060 
1062  /* RLM_MODULE_INVALID - No response */
1066  },
1067  .rcode = RLM_MODULE_NOOP,
1068  .section_offset = offsetof(process_dhcpv6_sections_t, recv_decline),
1069  },
1070  /*
1071  * A relay agent sends a Relay-forward message
1072  * to relay messages to servers, either directly
1073  * or through another relay agent. The received
1074  * message, either a client message or a
1075  * Relay-forward message from another relay
1076  * agent, is encapsulated in an option in the
1077  * Relay-forward message.
1078  */
1079  [ FR_DHCPV6_RELAY_FORWARD ] = {
1080  .recv = recv_from_relay,
1081  .resume = resume_recv_generic,
1082  .packet_type = {
1086  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1087 
1093  },
1094  .status_codes = {
1098  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1099 
1101  /* RLM_MODULE_INVALID - No response */
1105  },
1106  .rcode = RLM_MODULE_NOOP,
1107  .section_offset = offsetof(process_dhcpv6_sections_t, recv_relay_forward),
1108  },
1109  /*
1110  * A server sends an Advertise message to indicate
1111  * that it is available for DHCP service, in
1112  * response to a Solicit message received from a
1113  * client.
1114  */
1115  [ FR_DHCPV6_ADVERTISE ] = {
1116  .send = send_generic,
1117  .resume = resume_send_to_client,
1118  .packet_type = {
1124  },
1125  .status_codes = {
1129  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1130 
1131  /* RLM_MODULE_FAIL - No response */
1132  /* RLM_MODULE_INVALID - No response */
1133  /* RLM_MODULE_REJECT - No response */
1134  /* RLM_MODULE_DISALLOW - No response */
1135  /* RLM_MODULE_NOTFOUND - No response */
1136  },
1137  .rcode = RLM_MODULE_NOOP,
1138  .section_offset = offsetof(process_dhcpv6_sections_t, send_advertise),
1139  },
1140  /*
1141  * A server sends a Reply message containing
1142  * assigned addresses and configuration parameters
1143  * in response to a Solicit, Request, Renew,
1144  * Rebind message received from a client. A
1145  * server sends a Reply message containing
1146  * configuration parameters in response to an
1147  * Information-request message. A server sends a
1148  * Reply message in response to a Confirm message
1149  * confirming or denying that the addresses
1150  * assigned to the client are appropriate to the
1151  * link to which the client is connected. A
1152  * server sends a Reply message to acknowledge
1153  * receipt of a Release or Decline message.
1154  */
1155  [ FR_DHCPV6_REPLY ] = {
1156  .send = send_generic,
1157  .resume = resume_send_to_client,
1158  .packet_type = {
1159 
1165  },
1166  .status_codes = {
1170  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1171 
1173  /* RLM_MODULE_INVALID - No response */
1177  },
1178  .rcode = RLM_MODULE_NOOP,
1179  .section_offset = offsetof(process_dhcpv6_sections_t, send_reply),
1180  },
1181  /*
1182  * A server sends a Relay-reply message to a relay
1183  * agent containing a message that the relay
1184  * agent delivers to a client. The Relay-reply
1185  * message may be relayed by other relay agents
1186  * for delivery to the destination relay agent.
1187  * The server encapsulates the client message as
1188  * an option in the Relay-reply message, which the
1189  * relay agent extracts and relays to the client.
1190  */
1191  [ FR_DHCPV6_RELAY_REPLY ] = {
1192  .send = send_generic,
1193  .resume = resume_send_to_relay,
1194  .packet_type = {
1200  },
1201  .status_codes = {
1205  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1206 
1208  /* RLM_MODULE_INVALID - No response */
1212  },
1213  .rcode = RLM_MODULE_NOOP,
1214  .section_offset = offsetof(process_dhcpv6_sections_t, send_relay_reply),
1215  },
1216 
1217  [ FR_DHCPV6_DO_NOT_RESPOND ] = {
1218  .send = send_generic,
1219  .resume = resume_send_generic,
1220  .packet_type = {
1225 
1231  },
1232  .rcode = RLM_MODULE_NOOP,
1233  .section_offset = offsetof(process_dhcpv6_sections_t, do_not_respond),
1234  }
1235 };
1236 
1239  .common = {
1240  .magic = MODULE_MAGIC_INIT,
1241  .name = "dhcpv6",
1242  .config = dhcpv6_process_config,
1243  .inst_size = sizeof(process_dhcpv6_t),
1244 
1246  },
1247  .process = mod_process,
1248  .compile_list = compile_list,
1249  .dict = &dict_dhcpv6
1250 };
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:379
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:627
#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:268
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:564
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:684
#define cf_parent(_cf)
Definition: cf_util.h:101
@ 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:256
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:267
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:280
Specifies an attribute which must be present for the module to function.
Definition: dict.h:266
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:279
Specifies a value which must be present for the module to function.
Definition: dict.h:255
#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:1403
fr_dict_attr_t const * attr_packet_type
Definition: base.c:91
fr_dict_t const * dict_freeradius
Definition: base.c:77
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:854
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:612
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:830
#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.
Definition: merged_model.c:83
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_UINT8
8 Bit unsigned integer.
Definition: merged_model.c:97
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
Definition: merged_model.c:119
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unlang_mod_actions_t const mod_actions_postauth
Definition: mod_action.c:88
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:693
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:1969
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:2835
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
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:2455
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:546
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:489
RESUME(check_yiaddr)
Definition: base.c:133
CONF_SECTION * send_advertise
Definition: base.c:58
CONF_SECTION * recv_information_request
Definition: base.c:55
fr_pair_list_t client_id
Definition: base.c:104
static fr_dict_attr_t const * attr_hop_count
Definition: base.c:129
CONF_SECTION * send_reply
Definition: base.c:59
static fr_dict_attr_t const * attr_status_code_message
Definition: base.c:136
CONF_SECTION * recv_solicit
Definition: base.c:46
static fr_dict_attr_t const * attr_module_failure_message
Definition: base.c:138
static fr_dict_attr_t const * attr_status_code_value
Definition: base.c:135
static fr_dict_attr_t const * attr_relay_link_address
Definition: base.c:132
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Main dispatch function.
Definition: base.c:716
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:486
fr_pair_t * interface_id
Definition: base.c:114
fr_dict_autoload_t process_dhcpv6_dict[]
Definition: base.c:121
fr_dict_enum_autoload_t process_dhcpv6_dict_enum[]
Definition: base.c:163
static fr_value_box_t const * enum_status_code_success
Definition: base.c:157
fr_pair_t * transaction_id
Definition: base.c:103
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:502
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:459
CONF_SECTION * do_not_respond
Definition: base.c:62
static fr_value_box_t const * enum_status_code_no_binding
Definition: base.c:160
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
fr_pair_t * link_address
Definition: base.c:112
static fr_dict_attr_t const * attr_interface_id
Definition: base.c:130
static fr_dict_attr_t const * attr_server_id
Definition: base.c:128
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:158
CONF_SECTION * recv_rebind
Definition: base.c:50
static const virtual_server_compile_t compile_list[]
Definition: base.c:195
static conf_parser_t dhcpv6_process_config[]
Definition: base.c:188
CONF_SECTION * recv_release
Definition: base.c:51
static fr_process_state_t const process_state[]
Definition: base.c:754
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:276
CONF_SECTION * new_client
Definition: base.c:64
fr_dict_attr_autoload_t process_dhcpv6_dict_attr[]
Definition: base.c:141
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:623
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:117
fr_pair_list_t server_id
Definition: base.c:105
static fr_dict_attr_t const * attr_transaction_id
Definition: base.c:134
static process_dhcpv6_client_fields_t * dhcpv6_client_fields_store(request_t *request, bool expect_server_id)
Keep a copy of header fields to prevent them being tampered with.
Definition: base.c:328
static fr_dict_attr_t const * attr_client_id
Definition: base.c:127
static fr_value_box_t const * enum_status_code_not_on_link
Definition: base.c:159
CONF_SECTION * recv_confirm
Definition: base.c:48
#define PROCESS_PACKET_CODE_VALID
Definition: base.c:176
fr_pair_t * peer_address
Definition: base.c:113
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: base.c:745
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:133
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
Definition: base.c:401
fr_process_module_t process_dhcpv6
Definition: base.c:1238
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:110
#define PROCESS_TRACE
Trace each state function as it's entered.
Definition: process.h:65
module_t common
Common fields for all loadable modules.
Definition: process.h:55
Common public symbol definition for all process modules.
Definition: process.h:54
char const * fr_dhcpv6_packet_names[FR_DHCPV6_CODE_MAX]
Definition: base.c:71
#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)
Definition: radius1_test.c:190
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition: rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition: rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition: rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition: rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition: rcode.h:49
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition: rcode.h:44
#define request_is_dynamic_client(_x)
Definition: request.h:162
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1302
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:407
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:1458
#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:114
#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:329
void * data
Module's instance data.
Definition: module.h:271
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition: pair.h:129
unlang_action_t unlang_module_yield_to_section(rlm_rcode_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:248
RETURN_MODULE_FAIL
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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
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
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition: pair_inline.c:43
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:94
#define PAIR_VERIFY(_x)
Definition: pair.h:191
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:3740
#define fr_box_ipaddr(_val)
Definition: value.h:294
#define COMPILE_TERMINATOR
section_name_t const * section
Identifier for the section.
Processing sections which are allowed in this virtual server.