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: 1a8ea82268b28ea89f76085c75859994f7ff3af5 $
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  .name = "recv",
198  .name2 = "Solicit",
199  .component = MOD_POST_AUTH,
200  .offset = PROCESS_CONF_OFFSET(recv_solicit)
201  },
202  {
203  .name = "recv",
204  .name2 = "Request",
205  .component = MOD_POST_AUTH,
206  .offset = PROCESS_CONF_OFFSET(recv_request)
207  },
208  {
209  .name = "recv",
210  .name2 = "Confirm",
211  .component = MOD_POST_AUTH,
212  .offset = PROCESS_CONF_OFFSET(recv_confirm)
213  },
214  {
215  .name = "recv",
216  .name2 = "Renew",
217  .component = MOD_POST_AUTH,
218  .offset = PROCESS_CONF_OFFSET(recv_renew)
219  },
220  {
221  .name = "recv",
222  .name2 = "Rebind",
223  .component = MOD_POST_AUTH,
224  .offset = PROCESS_CONF_OFFSET(recv_rebind)
225  },
226  {
227  .name = "recv",
228  .name2 = "Release",
229  .component = MOD_POST_AUTH,
230  .offset = PROCESS_CONF_OFFSET(recv_release)
231  },
232  {
233  .name = "recv",
234  .name2 = "Decline",
235  .component = MOD_POST_AUTH,
236  .offset = PROCESS_CONF_OFFSET(recv_decline)
237  },
238  {
239  .name = "recv",
240  .name2 = "Reconfigure",
241  .component = MOD_POST_AUTH,
242  .offset = PROCESS_CONF_OFFSET(recv_reconfigure)
243  },
244  {
245  .name = "recv",
246  .name2 = "Information-Request",
247  .component = MOD_POST_AUTH,
248  .offset = PROCESS_CONF_OFFSET(recv_information_request)
249  },
250  {
251  .name = "recv",
252  .name2 = "Relay-Forward",
253  .component = MOD_POST_AUTH,
254  .offset = PROCESS_CONF_OFFSET(recv_relay_forward)
255  },
256 
257  {
258  .name = "send",
259  .name2 = "Advertise",
260  .component = MOD_POST_AUTH,
261  .offset = PROCESS_CONF_OFFSET(send_advertise)
262  },
263  {
264  .name = "send",
265  .name2 = "Reply",
266  .component = MOD_POST_AUTH,
267  .offset = PROCESS_CONF_OFFSET(send_reply)
268  },
269  {
270  .name = "send",
271  .name2 = "Relay-Reply",
272  .component = MOD_POST_AUTH,
273  .offset = PROCESS_CONF_OFFSET(send_relay_reply)
274  },
275  {
276  .name = "send",
277  .name2 = "Do-Not-Respond",
278  .component = MOD_POST_AUTH,
279  .offset = PROCESS_CONF_OFFSET(do_not_respond)
280  },
281 
282  DYNAMIC_CLIENT_SECTIONS,
283 
285 };
286 
287 /*
288  * Debug the packet if requested.
289  */
290 static void dhcpv6_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
291 {
292 #ifdef WITH_IFINDEX_NAME_RESOLUTION
293  char if_name[IFNAMSIZ];
294 #endif
295  char const *module;
296 
297  if (!packet) return;
298  if (!RDEBUG_ENABLED) return;
299 
300  /*
301  * Looks better without module prefix
302  */
303  module = request->module;
304  request->module = NULL;
305 
306  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 "
307 #ifdef WITH_IFINDEX_NAME_RESOLUTION
308  "%s%s%s"
309 #endif
310  "",
311  received ? "Received" : "Sending",
312  fr_dhcpv6_packet_names[packet->code],
313  packet->id,
314  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
315  fr_box_ipaddr(packet->socket.inet.src_ipaddr),
316  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
317  packet->socket.inet.src_port,
318  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
319  fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
320  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
321  packet->socket.inet.dst_port
322 #ifdef WITH_IFINDEX_NAME_RESOLUTION
323  , packet->socket.inet.ifindex ? "via " : "",
324  packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
325  packet->socket.inet.ifindex ? " " : ""
326 #endif
327  );
328 
329  if (received || request->parent) {
330  log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
331  } else {
332  log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
333  }
334 
335  request->module = module;
336 }
337 
338 /** Keep a copy of header fields to prevent them being tampered with
339  *
340  */
341 static inline CC_HINT(always_inline)
343 {
344  fr_pair_t *transaction_id;
346 
347  transaction_id = fr_pair_find_by_da(&request->request_pairs, NULL, attr_transaction_id);
348  if (!transaction_id) {
349  REDEBUG("Missing Transaction-ID");
350  return NULL;
351  }
352 
353  if (transaction_id->vp_length != DHCPV6_TRANSACTION_ID_LEN) {
354  REDEBUG("Invalid Transaction-ID, expected len %u, got len %zu",
355  DHCPV6_TRANSACTION_ID_LEN, transaction_id->vp_length);
356  return NULL;
357  }
358 
360  rctx->transaction_id = fr_pair_copy(rctx, transaction_id);
361 
364 
365  /*
366  * These should just become straight copies
367  * when the structure pairs are nested.
368  */
369  switch (fr_pair_list_copy_by_ancestor(rctx, &rctx->client_id,
370  &request->request_pairs, attr_client_id)) {
371  case -1:
372  REDEBUG("Error copying Client-ID");
373  error:
374  talloc_free(rctx);
375  return NULL;
376 
377  case 0:
378  REDEBUG("Missing Client-ID");
379  goto error;
380 
381  default:
382  break;
383  }
384 
385  switch (fr_pair_list_copy_by_ancestor(rctx, &rctx->server_id,
386  &request->request_pairs, attr_server_id)) {
387  case -1:
388  REDEBUG("Error copying Server-ID");
389  goto error;
390 
391  case 0:
392  if (expect_server_id) {
393  REDEBUG("Missing Server-ID");
394  goto error;
395  }
396  break;
397 
398  default:
399  if (!expect_server_id) {
400  REDEBUG("Server-ID should not be present");
401  goto error;
402  }
403  break;
404  }
405 
406  return rctx;
407 }
408 
409 /** Validate a solicit/rebind/confirm message
410  *
411  * Servers MUST discard any solicit/rebind/confirm messages that
412  * do not include a Client Identifier option or that do include a
413  * Server Identifier option.
414  */
415 RECV(for_any_server)
416 {
417  CONF_SECTION *cs;
418  fr_process_state_t const *state;
419  process_dhcpv6_t const *inst = mctx->inst->data;
420  process_dhcpv6_client_fields_t *rctx = NULL;
421 
423 
424  rctx = dhcpv6_client_fields_store(request, false);
425  if (!rctx) RETURN_MODULE_INVALID;
426 
427  UPDATE_STATE_CS(packet);
428 
429  return unlang_module_yield_to_section(p_result, request,
430  cs, state->rcode, state->resume,
431  NULL, 0, rctx);
432 }
433 
434 /** Validate a request/renew/decline/release
435  *
436  * Servers MUST discard any received Request message that meet any of
437  * the following conditions:
438  *
439  * - the message does not include a Server Identifier option.
440  *
441  * - the contents of the Server Identifier option do not match the
442  * server's DUID.
443  *
444  * - the message does not include a Client Identifier option.
445  *
446  * Servers MUST discard any received Confirm messages that do not
447  * include a Client Identifier option or that do include a Server
448  * Identifier option.
449  */
450 RECV(for_this_server)
451 {
452  CONF_SECTION *cs;
453  fr_process_state_t const *state;
454  process_dhcpv6_t const *inst = mctx->inst->data;
456 
458 
459  rctx = dhcpv6_client_fields_store(request, true);
460  if (!rctx) RETURN_MODULE_INVALID;
461 
462  UPDATE_STATE_CS(packet);
463 
464  return unlang_module_yield_to_section(p_result, request,
465  cs, state->rcode, state->resume,
466  NULL, 0, rctx);
467 }
468 
469 /** Copy a reply pair back into the response
470  *
471  */
472 static inline CC_HINT(always_inline)
473 int restore_field(request_t *request, fr_pair_t **to_restore)
474 {
475  fr_pair_t *vp;
476  int ret = 0;
477 
478  PAIR_VERIFY(*to_restore);
479 
480  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, (*to_restore)->da);
481  if (vp) {
482  if (fr_pair_cmp(vp, *to_restore) != 0) {
483  RWDEBUG("&reply.%pP does not match &request.%pP", vp, *to_restore);
484  free:
485  talloc_free(*to_restore);
486  *to_restore = NULL;
487  return ret;
488  }
489  } else if (fr_pair_steal_append(request->reply_ctx, &request->reply_pairs, *to_restore) < 0) {
490  RPERROR("Failed adding %s", (*to_restore)->da->name);
491  ret = -1;
492  goto free;
493  }
494  *to_restore = NULL;
495 
496  return 0;
497 }
498 
499 static inline CC_HINT(always_inline)
500 int restore_field_list(request_t *request, fr_pair_list_t *to_restore)
501 {
502  fr_pair_t *vp;
503 
504  while ((vp = fr_pair_list_head(to_restore))) {
505  fr_pair_remove(to_restore, vp);
506  if (restore_field(request, &vp) < 0) return -1;
507  }
508 
509  return 0;
510 }
511 
512 /** Add a status code if one doesn't already exist
513  *
514  */
515 static inline CC_HINT(always_inline)
516 void status_code_add(process_dhcpv6_t const *inst, request_t *request, fr_value_box_t const **code)
517 {
518  fr_pair_t *vp, *failure_message = NULL;
519  fr_value_box_t const *vb;
520  bool moved_failure_message = false;
521 
522  if (!code || !*code) return;
523 
524  vb = *code;
525 
526  /*
527  * If it's a success save some bytes
528  * in the packet and don't bother
529  * adding the success code unless
530  * explicitly requested to.
531  */
532  if ((vb->vb_uint16 == 0) && !inst->status_code_on_success) return;
533 
534  /*
535  * Don't override the user status
536  * code.
537  */
539 
540  /*
541  * Move the module failure messages upwards
542  * if requested to by the user.
543  */
544  if (inst->move_failure_message_to_parent && request->parent && (request->parent->dict == request->dict)) {
545  fr_pair_t const *prev = NULL;
546 
547  while ((failure_message = fr_pair_find_by_da(&request->request_pairs,
548  prev, attr_module_failure_message))) {
549  MEM(vp = fr_pair_copy(request->parent->request_ctx, failure_message));
550  fr_pair_append(&request->parent->request_pairs, vp);
551 
552  prev = fr_pair_remove(&request->request_pairs, failure_message);
553  talloc_free(failure_message);
554  }
555 
556  moved_failure_message = true;
557  }
558 
559  /*
560  * Concat all the module failure messages
561  * and place them in the status code
562  * message.
563  */
564  if (inst->send_failure_message && !moved_failure_message &&
565  (failure_message = fr_pair_find_by_da(&request->request_pairs, NULL, attr_module_failure_message)) &&
568  fr_sbuff_t sbuff;
569 
570  do {
571  /*
572  * Create an aggregation buffer up to
573  * the maximum length of a status
574  * message.
575  */
576  fr_sbuff_init_talloc(vp, &sbuff, &tctx, 1024, UINT16_MAX - 2);
577 
578  /*
579  * Best effort... it's probably OK
580  * if we truncate really long messages.
581  */
582  if (unlikely(fr_sbuff_in_bstrncpy(&sbuff, failure_message->vp_strvalue,
583  failure_message->vp_length) < 0)) break;
584  } while ((failure_message = fr_pair_find_by_da(&request->request_pairs, failure_message,
586  (fr_sbuff_in_strcpy_literal(&sbuff, ". ") == 2));
587  fr_sbuff_trim_talloc(&sbuff, SIZE_MAX); /* Fix size */
589  }
590 }
591 
592 /** Restore our copy of the header fields into the reply list
593  *
594  */
595 RESUME(send_to_client)
596 {
597  process_dhcpv6_t *inst = talloc_get_type_abort(mctx->inst->data, process_dhcpv6_t);
598  process_dhcpv6_client_fields_t *fields = talloc_get_type_abort(mctx->rctx, process_dhcpv6_client_fields_t);
599  fr_process_state_t const *state;
600 
601 
602  UPDATE_STATE(reply);
603 
604  /*
605  * Don't bother adding VPs if we're not going
606  * be responding to the client.
607  */
608  if (state->packet_type[*p_result] == FR_DHCPV6_DO_NOT_RESPOND) return CALL_RESUME(send_generic);
609 
610  /*
611  * Add a status code if we have one
612  */
613  status_code_add(inst, request, state->status_codes[*p_result]);
614 
615  /*
616  * If we have a status code entry then we'll
617  * be returning something to the client and
618  * need to fill in all these fields
619  */
620  if (unlikely(restore_field(request, &fields->transaction_id) < 0)) {
621  fail:
622  *p_result = RLM_MODULE_FAIL;
623  return CALL_RESUME(send_generic);
624  }
625  if (unlikely(restore_field_list(request, &fields->client_id) < 0)) goto fail;
626  if (unlikely(restore_field_list(request, &fields->server_id) < 0)) goto fail;
627 
628  dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
629 
630  return CALL_RESUME(send_generic);
631 }
632 
633 /** Record the original hop-count, link-address, peer-address etc...
634  *
635  */
636 static inline CC_HINT(always_inline)
638 {
639  fr_pair_t *hop_count, *link_address, *peer_address, *interface_id;
641 
642  hop_count = fr_pair_find_by_da(&request->request_pairs, NULL, attr_hop_count);
643  if (!hop_count) {
644  REDEBUG("Missing Hop-Count");
645  return NULL;
646  }
647 
648  link_address = fr_pair_find_by_da(&request->request_pairs, NULL, attr_relay_link_address);
649  if (!link_address) {
650  REDEBUG("Missing Link-Address");
651  return NULL;
652  }
653 
654  peer_address = fr_pair_find_by_da(&request->request_pairs, NULL, attr_relay_peer_address);
655  if (!peer_address) {
656  REDEBUG("Missing Peer-Address");
657  return NULL;
658  }
659 
660  interface_id = fr_pair_find_by_da(&request->request_pairs, NULL, attr_interface_id);
661 
662  /*
663  * Remember the relay fields
664  */
665  MEM(rctx = talloc_zero(unlang_interpret_frame_talloc_ctx(request), process_dhcpv6_relay_fields_t)); /* Safer to zero the whole thing */
666  MEM(rctx->hop_count = fr_pair_copy(rctx, hop_count));
667  MEM(rctx->link_address = fr_pair_copy(rctx, link_address));
668  MEM(rctx->peer_address = fr_pair_copy(rctx, peer_address));
669  if (interface_id) MEM(rctx->interface_id = fr_pair_copy(rctx, interface_id)); /* Optional */
670 
671  return rctx;
672 }
673 
674 /** Ensure we have the necessary pairs from the relay
675  *
676  */
677 RECV(from_relay)
678 {
679  CONF_SECTION *cs;
680  fr_process_state_t const *state;
681  process_dhcpv6_t const *inst = mctx->inst->data;
682  process_dhcpv6_relay_fields_t *rctx = NULL;
683 
684  rctx = dhcpv6_relay_fields_store(request);
685  if (!rctx) RETURN_MODULE_INVALID;
686 
687  UPDATE_STATE_CS(packet);
688 
689  return unlang_module_yield_to_section(p_result, request,
690  cs, state->rcode, state->resume,
691  NULL, 0, rctx);
692 }
693 
694 /** Restore our copy of the header fields into the reply list
695  *
696  */
697 RESUME(send_to_relay)
698 {
699  process_dhcpv6_t *inst = talloc_get_type_abort(mctx->inst->data, process_dhcpv6_t);
700  process_dhcpv6_relay_fields_t *fields = talloc_get_type_abort(mctx->rctx, process_dhcpv6_relay_fields_t);
701  fr_process_state_t const *state;
702 
703  UPDATE_STATE(reply);
704 
705  /*
706  * Add a status code if we have one
707  */
708  status_code_add(inst, request, state->status_codes[*p_result]);
709 
710  /*
711  * Restore relay fields
712  */
713  if (unlikely(restore_field(request, &fields->hop_count) < 0)) {
714  fail:
715  *p_result = RLM_MODULE_FAIL;
716  return CALL_RESUME(send_generic);
717  }
718  if (unlikely(restore_field(request, &fields->link_address) < 0)) goto fail;
719  if (unlikely(restore_field(request, &fields->peer_address) < 0)) goto fail;
720  if (fields->interface_id && unlikely(restore_field(request, &fields->interface_id) < 0)) goto fail;
721 
722  dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
723 
724  return CALL_RESUME(send_generic);
725 }
726 
727 /** Main dispatch function
728  *
729  */
730 static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
731 {
732  fr_process_state_t const *state;
733 
735 
737  fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
738 
739  request->component = "dhcpv6";
740  request->module = NULL;
741  fr_assert(request->dict == dict_dhcpv6);
742 
743  UPDATE_STATE(packet);
744 
745  if (!state->recv) {
746  REDEBUG("Invalid packet type (%u)", request->packet->code);
748  }
749 
750  dhcpv6_packet_debug(request, request->packet, &request->request_pairs, true);
751 
752  if (unlikely(request_is_dynamic_client(request))) {
753  return new_client(p_result, mctx, request);
754  }
755 
756  return state->recv(p_result, mctx, request);
757 }
758 
759 static int mod_bootstrap(module_inst_ctx_t const *mctx)
760 {
761  process_dhcpv6_t *inst = talloc_get_type_abort(mctx->inst->data, process_dhcpv6_t);
762 
763  inst->server_cs = cf_item_to_section(cf_parent(mctx->inst->conf));
764 
765  return 0;
766 }
767 
768 static fr_process_state_t const process_state[] = {
769  /*
770  * A client sends a Solicit message to locate
771  * servers.
772  */
773  [ FR_DHCPV6_SOLICIT ] = {
774  .recv = recv_for_any_server,
775  .resume = resume_recv_generic,
776  .packet_type = {
780  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
781 
787  },
788  .status_codes = {
789  /* RLM_MODULE_NOOP - No response */
792  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
793 
794  /* RLM_MODULE_FAIL - No response */
795  /* RLM_MODULE_INVALID - No response */
796  /* RLM_MODULE_REJECT - No response */
797  /* RLM_MODULE_DISALLOW - No response */
798  /* RLM_MODULE_NOTFOUND - No response */
799  },
800  .rcode = RLM_MODULE_NOOP,
801  .section_offset = offsetof(process_dhcpv6_sections_t, recv_solicit),
802  },
803 
804  /*
805  * A client sends a Request message to request
806  * configuration parameters, including IP
807  * addresses, from a specific server.
808  */
809  [ FR_DHCPV6_REQUEST ] = {
810  .recv = recv_for_this_server,
811  .resume = resume_recv_generic,
812  .packet_type = {
816  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
817 
823  },
824  .status_codes = {
828  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
829 
835  },
836  .rcode = RLM_MODULE_NOOP,
837  .section_offset = offsetof(process_dhcpv6_sections_t, recv_request),
838  },
839 
840  /*
841  * A client sends a Confirm message to any
842  * available server to determine whether the
843  * addresses it was assigned are still appropriate
844  * to the link to which the client is connected.
845  */
846  [ FR_DHCPV6_CONFIRM ] = {
847  .recv = recv_for_any_server,
848  .resume = resume_recv_generic,
849  .packet_type = {
853  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
854 
860  },
861 
862  /*
863  * When the server receives a Confirm message, the server determines
864  * whether the addresses in the Confirm message are appropriate for the
865  * link to which the client is attached. If all of the addresses in the
866  * Confirm message pass this test, the server returns a status of
867  * Success. If any of the addresses do not pass this test, the server
868  * returns a status of NotOnLink. If the server is unable to perform
869  * this test (for example, the server does not have information about
870  * prefixes on the link to which the client is connected), or there were
871  * no addresses in any of the IAs sent by the client, the server MUST
872  * NOT send a reply to the client.
873  */
874  .status_codes = {
875  /* RLM_MODULE_NOOP - No response */
878  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
879 
880  /* RLM_MODULE_FAIL - No response */
881  /* RLM_MODULE_INVALID - No response */
883  /* RLM_MODULE_DISALLOW - No response */
884  /* RLM_MODULE_NOTFOUND - No response */
885  },
886  .rcode = RLM_MODULE_NOOP,
887  .section_offset = offsetof(process_dhcpv6_sections_t, recv_confirm),
888  },
889 
890  /*
891  * A client sends a Renew message to the server
892  * that originally provided the client's addresses
893  * and configuration parameters to extend the
894  * lifetimes on the addresses assigned to the
895  * client and to update other configuration
896  * parameters.
897  */
898  [ FR_DHCPV6_RENEW ] = {
899  .recv = recv_for_this_server,
900  .resume = resume_recv_generic,
901  .packet_type = {
905  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
906 
912  },
913 
914  /*
915  * If the server cannot find a client entry for the IA the server
916  * returns the IA containing no addresses with a Status Code option set
917  * to NoBinding in the Reply message.
918  */
919  .status_codes = {
923  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
924 
926  /* RLM_MODULE_INVALID - No response */
930  },
931  .rcode = RLM_MODULE_NOOP,
932  .section_offset = offsetof(process_dhcpv6_sections_t, recv_renew),
933  },
934 
935  /*
936  * A client sends a Rebind message to any
937  * available server to extend the lifetimes on the
938  * addresses assigned to the client and to update
939  * other configuration parameters; this message is
940  * sent after a client receives no response to a
941  * Renew message.
942  */
943  [ FR_DHCPV6_REBIND ] = {
944  .recv = recv_for_any_server,
945  .resume = resume_recv_generic,
946  .packet_type = {
950  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
951 
957  },
958  .status_codes = {
962  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
963 
965  /* RLM_MODULE_INVALID - No response */
969  },
970  .rcode = RLM_MODULE_NOOP,
971  .section_offset = offsetof(process_dhcpv6_sections_t, recv_rebind),
972  },
973  /*
974  * A client sends an Information-request
975  * message to a server to request configuration
976  * parameters without the assignment of any IP
977  * addresses to the client.
978  */
980  .recv = recv_for_any_server,
981  .resume = resume_recv_generic,
982  .packet_type = {
986  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
987 
993  },
994  .status_codes = {
998  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
999 
1001  /* RLM_MODULE_INVALID - No response */
1005  },
1006  .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 
1029  },
1030  .status_codes = {
1034  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1035 
1037  /* RLM_MODULE_INVALID - No response */
1041  },
1042  .rcode = RLM_MODULE_NOOP,
1043 
1044  .section_offset = offsetof(process_dhcpv6_sections_t, recv_release),
1045  },
1046  /*
1047  *
1048  * A client sends a Decline message to a server to
1049  * indicate that the client has determined that
1050  * one or more addresses assigned by the server
1051  * are already in use on the link to which the
1052  * client is connected.
1053  */
1054  [ FR_DHCPV6_DECLINE ] = {
1055  .recv = recv_for_this_server, /* Need to check for attributes */
1056  .resume = resume_recv_generic,
1057  .packet_type = {
1061  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1062 
1068  },
1069  .status_codes = {
1073  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1074 
1076  /* RLM_MODULE_INVALID - No response */
1080  },
1081  .rcode = RLM_MODULE_NOOP,
1082  .section_offset = offsetof(process_dhcpv6_sections_t, recv_decline),
1083  },
1084  /*
1085  * A relay agent sends a Relay-forward message
1086  * to relay messages to servers, either directly
1087  * or through another relay agent. The received
1088  * message, either a client message or a
1089  * Relay-forward message from another relay
1090  * agent, is encapsulated in an option in the
1091  * Relay-forward message.
1092  */
1093  [ FR_DHCPV6_RELAY_FORWARD ] = {
1094  .recv = recv_from_relay,
1095  .resume = resume_recv_generic,
1096  .packet_type = {
1100  /* RLM_MODULE_HANDLED - Requires the user to set packet-type */
1101 
1107  },
1108  .status_codes = {
1112  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1113 
1115  /* RLM_MODULE_INVALID - No response */
1119  },
1120  .rcode = RLM_MODULE_NOOP,
1121  .section_offset = offsetof(process_dhcpv6_sections_t, recv_relay_forward),
1122  },
1123  /*
1124  * A server sends an Advertise message to indicate
1125  * that it is available for DHCP service, in
1126  * response to a Solicit message received from a
1127  * client.
1128  */
1129  [ FR_DHCPV6_ADVERTISE ] = {
1130  .send = send_generic,
1131  .resume = resume_send_to_client,
1132  .packet_type = {
1138  },
1139  .status_codes = {
1143  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1144 
1145  /* RLM_MODULE_FAIL - No response */
1146  /* RLM_MODULE_INVALID - No response */
1147  /* RLM_MODULE_REJECT - No response */
1148  /* RLM_MODULE_DISALLOW - No response */
1149  /* RLM_MODULE_NOTFOUND - No response */
1150  },
1151  .rcode = RLM_MODULE_NOOP,
1152  .section_offset = offsetof(process_dhcpv6_sections_t, send_advertise),
1153  },
1154  /*
1155  * A server sends a Reply message containing
1156  * assigned addresses and configuration parameters
1157  * in response to a Solicit, Request, Renew,
1158  * Rebind message received from a client. A
1159  * server sends a Reply message containing
1160  * configuration parameters in response to an
1161  * Information-request message. A server sends a
1162  * Reply message in response to a Confirm message
1163  * confirming or denying that the addresses
1164  * assigned to the client are appropriate to the
1165  * link to which the client is connected. A
1166  * server sends a Reply message to acknowledge
1167  * receipt of a Release or Decline message.
1168  */
1169  [ FR_DHCPV6_REPLY ] = {
1170  .send = send_generic,
1171  .resume = resume_send_to_client,
1172  .packet_type = {
1173 
1179  },
1180  .status_codes = {
1184  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1185 
1187  /* RLM_MODULE_INVALID - No response */
1191  },
1192  .rcode = RLM_MODULE_NOOP,
1193  .section_offset = offsetof(process_dhcpv6_sections_t, send_reply),
1194  },
1195  /*
1196  * A server sends a Relay-reply message to a relay
1197  * agent containing a message that the relay
1198  * agent delivers to a client. The Relay-reply
1199  * message may be relayed by other relay agents
1200  * for delivery to the destination relay agent.
1201  * The server encapsulates the client message as
1202  * an option in the Relay-reply message, which the
1203  * relay agent extracts and relays to the client.
1204  */
1205  [ FR_DHCPV6_RELAY_REPLY ] = {
1206  .send = send_generic,
1207  .resume = resume_send_to_relay,
1208  .packet_type = {
1214  },
1215  .status_codes = {
1219  /* RLM_MODULE_HANDLED - Requires the user to set status-code */
1220 
1222  /* RLM_MODULE_INVALID - No response */
1226  },
1227  .rcode = RLM_MODULE_NOOP,
1228  .section_offset = offsetof(process_dhcpv6_sections_t, send_relay_reply),
1229  },
1230 
1231  [ FR_DHCPV6_DO_NOT_RESPOND ] = {
1232  .send = send_generic,
1233  .resume = resume_send_generic,
1234  .packet_type = {
1239 
1245  },
1246  .rcode = RLM_MODULE_NOOP,
1247  .section_offset = offsetof(process_dhcpv6_sections_t, do_not_respond),
1248  }
1249 };
1250 
1253  .common = {
1254  .magic = MODULE_MAGIC_INIT,
1255  .name = "dhcpv6",
1256  .config = dhcpv6_process_config,
1257  .inst_size = sizeof(process_dhcpv6_t),
1258 
1259  .bootstrap = mod_bootstrap
1260  },
1261  .process = mod_process,
1262  .compile_list = compile_list,
1263  .dict = &dict_dhcpv6
1264 };
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:378
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#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:563
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:649
#define cf_parent(_cf)
Definition: cf_util.h:98
@ MOD_POST_AUTH
7 methods index for postauth section.
Definition: components.h:37
@ 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:239
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
Specifies a value which must be present for the module to function.
Definition: dict.h:238
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
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:1384
fr_dict_t const * dict_freeradius
Definition: base.c:73
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:845
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:603
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:821
#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
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
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:51
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:688
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:1966
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:2832
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:1340
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:2452
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:541
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:484
RESUME(check_yiaddr)
Definition: base.c:132
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_packet_type
Definition: base.c:131
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:730
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:500
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:516
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:473
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 int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition: base.c:759
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:768
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:290
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:637
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:342
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
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:415
fr_process_module_t process_dhcpv6
Definition: base.c:1252
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
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:399
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:1445
#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 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:516
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:270
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:190
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:3689
#define fr_box_ipaddr(_val)
Definition: value.h:287
#define COMPILE_TERMINATOR
char const * name
Name of the processing section, such as "recv" or "send".
Processing sections which are allowed in this virtual server.