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: 9de8e062e14475bfb8be192198dd19626e7180da $
19  * @file src/process/dns/base.c
20  * @brief DNS processing.
21  *
22  * @copyright 2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  * @copyright 2020 Network RADIUS SAS (legal@networkradius.com)
24  */
25 #include "lib/server/components.h"
26 #include "lib/server/rcode.h"
27 #include <freeradius-devel/server/protocol.h>
28 #include <freeradius-devel/server/pair.h>
29 #include <freeradius-devel/util/debug.h>
30 #include <freeradius-devel/util/pair.h>
31 #include <freeradius-devel/unlang/interpret.h>
32 #include <freeradius-devel/dns/dns.h>
33 #include <freeradius-devel/protocol/dns/rfc1034.h>
34 
35 /** Update this if new rcodes are added
36  */
37 #define FR_DNS_RCODE_MAX FR_RCODE_VALUE_BAD_COOKIE
38 
39 static fr_dict_t const *dict_dns;
40 
43  { .out = &dict_dns, .proto = "dns" },
44  { NULL }
45 };
46 
49 static fr_dict_attr_t const *attr_id;
52 static fr_dict_attr_t const *attr_rcode;
54 
57  { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_dns},
58  { .out = &attr_header, .name = "Header", .type = FR_TYPE_STRUCT, .dict = &dict_dns},
59  { .out = &attr_opcode, .name = "Header.Opcode", .type = FR_TYPE_UINT8, .dict = &dict_dns},
60  { .out = &attr_id, .name = "Header.ID", .type = FR_TYPE_UINT16, .dict = &dict_dns},
61  { .out = &attr_response_bit, .name = "Header.Query", .type = FR_TYPE_BOOL, .dict = &dict_dns},
62  { .out = &attr_rcode, .name = "Header.Rcode", .type = FR_TYPE_UINT8, .dict = &dict_dns},
63  { .out = &attr_authoritative_bit, .name = "Header.Authoritative", .type = FR_TYPE_BOOL, .dict = &dict_dns},
64  { NULL }
65 };
66 
72 
75  { .out = &enum_rcode_no_error, .name = "No-Error", .attr = &attr_rcode }, /* ok/updated */
76  { .out = &enum_rcode_format_error, .name = "Format-Error", .attr = &attr_rcode }, /* invalid */
77  { .out = &enum_rcode_server_failure, .name = "Server-Failure", .attr = &attr_rcode }, /* fail */
78  { .out = &enum_rcode_name_error, .name = "Name-Error", .attr = &attr_rcode }, /* notfound */
79  { .out = &enum_rcode_refused, .name = "Refused", .attr = &attr_rcode }, /* reject */
80  { NULL }
81 };
82 
83 typedef struct {
84  uint64_t nothing; // so that the next field isn't at offset 0
85 
86  /** Request/response sections
87  *
88  */
99 
100  /** DNS rcode error sections (not the same as rlm_rcode_t values)
101  *
102  * These are called after the `recv { ... }` section runs if rcode is non-zero
103  */
105 
108 
109 typedef struct {
111 } process_dns_t;
112 
113 /** Records fields from the original request so we have a known good copy
114  */
115 typedef struct {
116  uint16_t id; //!< Identity of the request.
117  uint8_t opcode; //!< Opcode, what type of query this is.
119 
120 #define PROCESS_PACKET_TYPE fr_dns_packet_code_t
121 #define PROCESS_CODE_MAX FR_DNS_CODE_MAX
122 #define PROCESS_CODE_DO_NOT_RESPOND FR_DNS_DO_NOT_RESPOND
123 #define PROCESS_PACKET_CODE_VALID FR_DNS_PACKET_CODE_VALID
124 #define PROCESS_INST process_dns_t
125 
126 /** Map an rlm_rcode_t to a header.rcode value
127  */
128 #define PROCESS_STATE_EXTRA_FIELDS fr_value_box_t const **dns_rcode[RLM_MODULE_NUMCODES];
129 
130 #include <freeradius-devel/server/process.h>
131 
133  {
134  .name = "recv",
135  .name2 = "Query",
136  .component = MOD_AUTHORIZE,
137  .offset = PROCESS_CONF_OFFSET(query),
138  },
139  {
140  .name = "send",
141  .name2 = "Query-Response",
142  .component = MOD_POST_AUTH,
143  .offset = PROCESS_CONF_OFFSET(query_response),
144  },
145  {
146  .name = "recv",
147  .name2 = "Inverse-Query",
148  .component = MOD_AUTHORIZE,
149  .offset = PROCESS_CONF_OFFSET(inverse_query),
150  },
151  {
152  .name = "send",
153  .name2 = "Inverse-Query-Response",
154  .component = MOD_POST_AUTH,
155  .offset = PROCESS_CONF_OFFSET(inverse_query_response),
156  },
157  {
158  .name = "recv",
159  .name2 = "Status",
160  .component = MOD_AUTHORIZE,
161  .offset = PROCESS_CONF_OFFSET(status),
162  },
163  {
164  .name = "send",
165  .name2 = "Status-Response",
166  .component = MOD_POST_AUTH,
167  .offset = PROCESS_CONF_OFFSET(status_response),
168  },
169  {
170  .name = "recv",
171  .name2 = "Update",
172  .component = MOD_AUTHORIZE,
173  .offset = PROCESS_CONF_OFFSET(update),
174  },
175  {
176  .name = "send",
177  .name2 = "Update-Response",
178  .component = MOD_POST_AUTH,
179  .offset = PROCESS_CONF_OFFSET(update_response),
180  },
181  {
182  .name = "recv",
183  .name2 = "Stateful-Operation",
184  .component = MOD_AUTHORIZE,
185  .offset = PROCESS_CONF_OFFSET(stateful_operation),
186  },
187  {
188  .name = "send",
189  .name2 = "Stateful-Operation-Response",
190  .component = MOD_POST_AUTH,
191  .offset = PROCESS_CONF_OFFSET(stateful_operation_response),
192  },
193  {
194  .name = "send",
195  .name2 = "Do-Not-Respond",
196  .component = MOD_POST_AUTH,
197  .offset = PROCESS_CONF_OFFSET(do_not_respond),
198  },
199 
200 #define ERROR_SECTION(_name, _number) \
201  { \
202  .name = "error", \
203  .name2 = _name, \
204  .component = MOD_POST_AUTH, \
205  .offset = PROCESS_CONF_OFFSET(rcode[_number]), \
206  }
207 
208  /*
209  * Error sections that can execute after the recv { ... }
210  * section has run.
211  */
212  ERROR_SECTION("Format-Error", FR_RCODE_VALUE_FORMAT_ERROR),
213  ERROR_SECTION("Server-Failure", FR_RCODE_VALUE_SERVER_FAILURE),
214  ERROR_SECTION("Name-Error", FR_RCODE_VALUE_NAME_ERROR),
215  ERROR_SECTION("Not-Implemented", FR_RCODE_VALUE_NOT_IMPLEMENTED),
216  ERROR_SECTION("Refused", FR_RCODE_VALUE_REFUSED),
217  ERROR_SECTION("YX-Domain", FR_RCODE_VALUE_YX_DOMAIN),
218  ERROR_SECTION("YX-Resource-Record-Set", FR_RCODE_VALUE_YX_RESOURCE_RECORD_SET),
219  ERROR_SECTION("NX-Resource-Record-Set", FR_RCODE_VALUE_NX_RESOURCE_RECORD_SET),
220  ERROR_SECTION("Not-Auth", FR_RCODE_VALUE_NOT_AUTH),
221  ERROR_SECTION("Not-Zone", FR_RCODE_VALUE_NOT_ZONE),
222  ERROR_SECTION("DSO-Type-Not-Implemented", FR_RCODE_VALUE_DSO_TYPE_NOT_IMPLEMENTED),
223  ERROR_SECTION("Bad-Signature", FR_RCODE_VALUE_BAD_SIGNATURE),
224  ERROR_SECTION("Bad-Key", FR_RCODE_VALUE_BAD_KEY),
225  ERROR_SECTION("Bad-Time", FR_RCODE_VALUE_BAD_TIME),
226  ERROR_SECTION("Bad-Mode", FR_RCODE_VALUE_BAD_MODE),
227  ERROR_SECTION("Bad-Name", FR_RCODE_VALUE_BAD_NAME),
228  ERROR_SECTION("Bad-Algorithm", FR_RCODE_VALUE_BAD_ALGORITHM),
229  ERROR_SECTION("Bad-Truncation", FR_RCODE_VALUE_BAD_TRUNCATION),
230  ERROR_SECTION("Bad-Cookie", FR_RCODE_VALUE_BAD_COOKIE),
232 };
233 
234 /*
235  * Debug the packet if requested.
236  */
237 static void dns_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
238 {
239  if (!packet) return;
240  if (!RDEBUG_ENABLED) return;
241 
242  if ((packet->code & 0x0f) >= FR_DNS_CODE_MAX) return;
243 
244  log_request(L_DBG, L_DBG_LVL_1, request, __FILE__, __LINE__, "%s %s",
245  received ? "Received" : "Sending",
246  fr_dns_packet_names[packet->code & 0x0f]);
247 
248  if (received || request->parent) {
249  log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
250  } else {
251  log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
252  }
253 }
254 
255 /** Keep a copy of header fields to prevent them being tampered with
256  *
257  */
258 static inline CC_HINT(always_inline)
260 {
261  fr_pair_t *header;
262  fr_pair_t *id;
263  fr_pair_t *opcode;
264  process_dns_fields_t *rctx;
265 
266  /*
267  * We could use fr_find_by_da_nested, but it's more efficient
268  * to look up the header attribute once.
269  */
270  header = fr_pair_find_by_da(&request->request_pairs, NULL, attr_header);
271  if (!header) {
272  REDEBUG("Missing Header attribute");
273  return NULL;
274  }
275 
276  id = fr_pair_find_by_da(&header->vp_group, NULL, attr_id);
277  if (!id) {
278  REDEBUG("Missing ID attribute");
279  return NULL;
280  }
281 
282  opcode = fr_pair_find_by_da(&header->vp_group, NULL, attr_opcode);
283  if (!opcode) {
284  REDEBUG("Missing Opcode attribute");
285  return NULL;
286  }
287 
289  rctx->id = id->vp_uint16;
290  rctx->opcode = opcode->vp_uint8;
291 
292  return rctx;
293 }
294 
295 /** Copy values from the request header back into the response
296  *
297  * If a value already exists in the response, don't overwrite it so the user has absolute control
298  */
299 static inline CC_HINT(always_inline)
301 {
302  fr_pair_t *header;
303  fr_pair_t *id;
304  fr_pair_t *response;
305  fr_pair_t *authoritative;
306  fr_pair_t *opcode;
307  int ret;
308 
309  MEM(pair_update_reply(&header, attr_header) >= 0);
310 
311  /*
312  * ID should always match the request
313  * but we allow overrides for testing.
314  */
315  MEM((ret = fr_pair_update_by_da_parent(header, &id, attr_id)) != -1);
316  fr_assert_msg(ret >= 0, "Failed to update header attribute %s:", fr_strerror());
317  if (ret == 0) id->vp_uint16 = rctx->id;
318 
319  /*
320  * This marks the packet as a response.
321  * Save the user from having to do this manually.
322  */
323  MEM((ret = fr_pair_update_by_da_parent(header, &response, attr_response_bit)) != -1);
324  fr_assert_msg(ret >= 0, "Failed to update response_bit attribute %s:", fr_strerror());
325  if (ret == 0) response->vp_bool = true;
326 
327  /*
328  * Opcode should always match the request
329  * but we allow overrides for testing.
330  */
331  MEM((ret = fr_pair_update_by_da_parent(header, &opcode, attr_opcode)) != -1);
332  fr_assert_msg(ret >= 0, "Failed to update opcode attribute %s:", fr_strerror());
333  if (ret == 0) opcode->vp_uint8 = rctx->opcode;
334 
335  /*
336  * Default to setting the authoritative bit if
337  * it's not been set by something already.
338  */
339  MEM((ret = fr_pair_update_by_da_parent(header, &authoritative, attr_authoritative_bit)) != -1);
340  fr_assert_msg(ret >= 0, "Failed to update authoritative_bit attribute %s:", fr_strerror());
341  if (ret == 0) authoritative->vp_bool = true;
342 
343  return 0;
344 }
345 
346 /** Add/update the rcode attribute based on the last rlm_rcode value
347  *
348  */
349 static inline CC_HINT(always_inline)
350 void dns_rcode_add(fr_pair_t **rcode, request_t *request, fr_value_box_t const **code)
351 {
352  fr_value_box_t const *vb;
353  int ret;
354 
355  if (!code || !*code) return;
356 
357  vb = *code;
358 
359  /*
360  * Don't override the user status
361  * code.
362  */
363  MEM((ret = fr_pair_update_by_da_parent(request->reply_ctx, rcode, attr_rcode)) >= 0);
364  if (ret == 0) {
365  fr_value_box_copy(*rcode, &(*rcode)->data, vb);
366  (*rcode)->data.enumv = (*rcode)->da; /* Hack, boxes should have their enumv field populated */
367  }
368 }
369 
370 /** Store basic information from the request, and jump into the correct processing section
371  *
372  */
373 RECV(request)
374 {
375  process_dns_fields_t *rctx;
376 
378 
379  rctx = dns_fields_store(request);
380  if (!rctx) RETURN_MODULE_INVALID;
381 
382  return CALL_RECV_RCTX(generic, rctx);
383 }
384 
385 /** Sets the DNS rcode after we get a result from the recv section
386  *
387  * Calls error processing sections as appropriate
388  */
389 RESUME(recv_request)
390 {
391  process_dns_t const *inst = talloc_get_type_abort_const(mctx->inst->data, process_dns_t);
392  fr_process_state_t const *state;
393  fr_pair_t *rcode = NULL;
394 
396 
397  /*
398  * Pick the next state based on the response
399  */
400  UPDATE_STATE(reply);
401 
402  /*
403  * Don't bother adding VPs if we're not going
404  * be responding to the client.
405  */
406  if (state->packet_type[*p_result] == FR_DNS_DO_NOT_RESPOND) return CALL_RESUME(recv_generic);
407 
408  /*
409  * Add an rcode based on the result of the `recv { ... }` section
410  */
411  dns_rcode_add(&rcode, request, state->dns_rcode[*p_result]);
412 
413 #ifdef __clang_analyzer__
414  if (!rcode) return UNLANG_ACTION_FAIL;
415 #endif
416 
417  /*
418  * Call an appropriate error section if it's been set
419  * otherwise, just call the generic recv resume
420  * which'll call an appropriate send section.
421  */
422  if ((rcode->vp_uint8 < NUM_ELEMENTS(inst->sections.rcode)) &&
423  (inst->sections.rcode[rcode->vp_uint8])) {
424  return unlang_module_yield_to_section(p_result, request,
425  inst->sections.rcode[rcode->vp_uint8],
427  /*
428  * We ignore everything from the error section
429  * it's only there for logging.
430  *
431  * Jump straight to the send function.
432  */
433  state->send,
434  NULL, 0, mctx->rctx);
435  }
436 
437  /*
438  * Use that rcode to determine the processing section
439  */
440  return CALL_RESUME(recv_generic);
441 }
442 
443 /** Set defaults in the response and values copied from the request like opcode and id
444  *
445  */
446 RESUME(send_response)
447 {
448  fr_process_state_t const *state;
449  fr_pair_t *vp;
450 
451  UPDATE_STATE(reply);
452 
453  /*
454  * Don't bother adding VPs if we're not going
455  * be responding to the client.
456  */
457  if (state->packet_type[*p_result] == FR_DNS_DO_NOT_RESPOND) return CALL_RESUME(send_generic);
458 
459  /*
460  * Add fields from the request back in,
461  * deferring to user specified values.
462  */
463  dns_fields_restore(request, talloc_get_type_abort(mctx->rctx, process_dns_fields_t));
464 
465  /*
466  * Do this last, so we show everything
467  * we'll be sending back.
468  */
469  dns_packet_debug(request, request->reply, &request->reply_pairs, false);
470 
471  /*
472  * Hack. This is because this stupid framework uses
473  * packet_type values to represent request and response
474  * packet types, and DNS uses the same values for
475  * both request and response packet types.
476  */
478  request->reply->code = vp->vp_uint8 = state->default_reply;
479 
480  return CALL_RESUME(send_generic);
481 }
482 
483 /** Entry point into the state machine
484  */
485 static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
486 {
487  fr_process_state_t const *state;
488 
490 
492  fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
493 
494  request->component = "dns";
495  request->module = NULL;
496  fr_assert(request->dict == dict_dns);
497 
498  UPDATE_STATE(packet);
499 
500  if (!state->recv) {
501  REDEBUG("Invalid packet type (%u)", request->packet->code);
503  }
504 
505  dns_packet_debug(request, request->packet, &request->request_pairs, true);
506 
507  return state->recv(p_result, mctx, request);
508 }
509 
510 #define DNS_RCODE_COMMON \
511  .dns_rcode = { \
512  [RLM_MODULE_NOOP] = &enum_rcode_no_error, \
513  [RLM_MODULE_OK] = &enum_rcode_no_error, \
514  [RLM_MODULE_UPDATED] = &enum_rcode_no_error, \
515  [RLM_MODULE_HANDLED] = &enum_rcode_no_error, \
516  [RLM_MODULE_REJECT] = &enum_rcode_refused, \
517  [RLM_MODULE_FAIL] = &enum_rcode_server_failure, \
518  [RLM_MODULE_INVALID] = &enum_rcode_format_error, \
519  [RLM_MODULE_DISALLOW] = &enum_rcode_refused, \
520  [RLM_MODULE_NOTFOUND] = &enum_rcode_name_error \
521  }
522 
523 static fr_process_state_t const process_state[] = {
524  [ FR_DNS_QUERY ] = {
526  .default_reply = FR_DNS_QUERY_RESPONSE,
527  .rcode = RLM_MODULE_NOOP,
528  .recv = recv_request,
529  .resume = resume_recv_request,
530  .section_offset = PROCESS_CONF_OFFSET(query),
531  },
532  [ FR_DNS_INVERSE_QUERY ] = {
534  .default_reply = FR_DNS_INVERSE_QUERY_RESPONSE,
535  .rcode = RLM_MODULE_NOOP,
536  .recv = recv_request,
537  .resume = resume_recv_request,
538  .section_offset = PROCESS_CONF_OFFSET(inverse_query),
539  },
540  [ FR_DNS_STATUS ] = {
542  .default_reply = FR_DNS_STATUS_RESPONSE,
543  .rcode = RLM_MODULE_NOOP,
544  .recv = recv_request,
545  .resume = resume_recv_request,
546  .section_offset = PROCESS_CONF_OFFSET(status),
547  },
548  [ FR_DNS_UPDATE ] = {
550  .default_reply = FR_DNS_UPDATE_RESPONSE,
551  .rcode = RLM_MODULE_NOOP,
552  .recv = recv_request,
553  .resume = resume_recv_request,
554  .section_offset = PROCESS_CONF_OFFSET(update),
555  },
558  .default_reply = FR_DNS_STATEFUL_OPERATION_RESPONSE,
559  .rcode = RLM_MODULE_NOOP,
560  .recv = recv_request,
561  .resume = resume_recv_request,
562  .section_offset = PROCESS_CONF_OFFSET(stateful_operation),
563  },
564  [ FR_DNS_QUERY_RESPONSE ] = {
565  .default_reply = FR_DNS_QUERY,
566  .rcode = RLM_MODULE_NOOP,
567  .send = send_generic,
568  .resume = resume_send_response,
569  .section_offset = PROCESS_CONF_OFFSET(query_response),
570  },
571 
573  .default_reply = FR_DNS_QUERY,
574  .rcode = RLM_MODULE_NOOP,
575  .send = send_generic,
576  .resume = resume_send_response,
577  .section_offset = PROCESS_CONF_OFFSET(inverse_query_response),
578  },
579 
580  [ FR_DNS_STATUS_RESPONSE ] = {
581  .default_reply = FR_DNS_STATUS,
582  .rcode = RLM_MODULE_NOOP,
583  .send = send_generic,
584  .resume = resume_send_response,
585  .section_offset = PROCESS_CONF_OFFSET(status_response),
586  },
587 
588  [ FR_DNS_UPDATE_RESPONSE ] = {
589  .default_reply = FR_DNS_UPDATE,
590  .rcode = RLM_MODULE_NOOP,
591  .send = send_generic,
592  .resume = resume_send_response,
593  .section_offset = PROCESS_CONF_OFFSET(update_response),
594  },
595 
597  .default_reply = FR_DNS_STATEFUL_OPERATION,
598  .rcode = RLM_MODULE_NOOP,
599  .send = send_generic,
600  .resume = resume_send_response,
601  .section_offset = PROCESS_CONF_OFFSET(stateful_operation_response),
602  },
603 
604  [ FR_DNS_DO_NOT_RESPOND ] = {
605  .packet_type = {
609 
615  },
616  .rcode = RLM_MODULE_NOOP,
617  .send = send_generic,
618  .resume = resume_send_response,
619  .section_offset = PROCESS_CONF_OFFSET(do_not_respond),
620  },
621 };
622 
625  .common = {
626  .magic = MODULE_MAGIC_INIT,
627  .name = "dns",
628  .inst_size = sizeof(process_dns_t)
629  },
630  .process = mod_process,
631  .compile_list = compile_list,
632  .dict = &dict_dns,
633 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition: action.h:36
#define NUM_ELEMENTS(_t)
Definition: build.h:335
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
Module components.
@ MOD_POST_AUTH
7 methods index for postauth section.
Definition: components.h:37
@ MOD_AUTHORIZE
1 methods index for authorize section.
Definition: components.h:34
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition: debug.h:208
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
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
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
@ 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
unsigned short uint16_t
Definition: merged_model.c:31
@ 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_BOOL
A truth value.
Definition: merged_model.c:95
unsigned char uint8_t
Definition: merged_model.c:30
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
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_update_by_da_parent(fr_pair_t *parent, fr_pair_t **out, fr_dict_attr_t const *da)
Return the first fr_pair_t matching the fr_dict_attr_t or alloc a new fr_pair_t and its subtree (and ...
Definition: pair.c:1591
RESUME(check_yiaddr)
Definition: base.c:132
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
Definition: base.c:415
fr_dict_attr_autoload_t process_dns_dict_attr[]
Definition: base.c:56
CONF_SECTION * stateful_operation_response
Definition: base.c:98
fr_dict_autoload_t process_dns_dict[]
Definition: base.c:42
static void dns_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
Definition: base.c:237
static fr_dict_attr_t const * attr_packet_type
Definition: base.c:47
#define ERROR_SECTION(_name, _number)
uint64_t nothing
Definition: base.c:84
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Entry point into the state machine.
Definition: base.c:485
static fr_value_box_t const * enum_rcode_server_failure
Definition: base.c:69
static fr_dict_attr_t const * attr_authoritative_bit
Definition: base.c:53
CONF_SECTION * status
Definition: base.c:93
static void dns_rcode_add(fr_pair_t **rcode, request_t *request, fr_value_box_t const **code)
Add/update the rcode attribute based on the last rlm_rcode value.
Definition: base.c:350
static process_dns_fields_t * dns_fields_store(request_t *request)
Keep a copy of header fields to prevent them being tampered with.
Definition: base.c:259
CONF_SECTION * inverse_query_response
Definition: base.c:92
CONF_SECTION * query_response
Definition: base.c:90
CONF_SECTION * stateful_operation
Definition: base.c:97
static fr_dict_attr_t const * attr_opcode
Definition: base.c:51
static fr_value_box_t const * enum_rcode_refused
Definition: base.c:71
static fr_dict_attr_t const * attr_response_bit
Definition: base.c:50
static fr_value_box_t const * enum_rcode_no_error
Definition: base.c:67
CONF_SECTION * query
Request/response sections.
Definition: base.c:89
uint8_t opcode
Opcode, what type of query this is.
Definition: base.c:117
static fr_dict_attr_t const * attr_id
Definition: base.c:49
static const virtual_server_compile_t compile_list[]
Definition: base.c:132
CONF_SECTION * inverse_query
Definition: base.c:91
static fr_process_state_t const process_state[]
Definition: base.c:523
#define FR_DNS_RCODE_MAX
Update this if new rcodes are added.
Definition: base.c:37
fr_dict_enum_autoload_t process_dns_dict_enum[]
Definition: base.c:74
process_dns_sections_t sections
Definition: base.c:110
static fr_value_box_t const * enum_rcode_name_error
Definition: base.c:70
uint16_t id
Identity of the request.
Definition: base.c:116
#define DNS_RCODE_COMMON
Definition: base.c:510
static fr_dict_t const * dict_dns
Definition: base.c:39
CONF_SECTION * update_response
Definition: base.c:96
CONF_SECTION * update
Definition: base.c:95
static fr_value_box_t const * enum_rcode_format_error
Definition: base.c:68
static fr_dict_attr_t const * attr_header
Definition: base.c:48
CONF_SECTION * status_response
Definition: base.c:94
static int dns_fields_restore(request_t *request, process_dns_fields_t *rctx)
Copy values from the request header back into the response.
Definition: base.c:300
CONF_SECTION * do_not_respond
Definition: base.c:106
#define PROCESS_PACKET_CODE_VALID
Definition: base.c:123
fr_process_module_t process_dns
Definition: base.c:624
static fr_dict_attr_t const * attr_rcode
Definition: base.c:52
Records fields from the original request so we have a known good copy.
Definition: base.c:115
#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_dns_packet_names[FR_DNS_CODE_MAX]
Definition: base.c:68
@ FR_DNS_DO_NOT_RESPOND
Definition: dns.h:108
@ FR_DNS_STATEFUL_OPERATION_RESPONSE
Definition: dns.h:106
@ FR_DNS_UPDATE_RESPONSE
Definition: dns.h:105
@ FR_DNS_STATEFUL_OPERATION
Definition: dns.h:98
@ FR_DNS_QUERY
Definition: dns.h:93
@ FR_DNS_QUERY_RESPONSE
Definition: dns.h:101
@ FR_DNS_STATUS_RESPONSE
Definition: dns.h:103
@ FR_DNS_INVERSE_QUERY
Definition: dns.h:94
@ FR_DNS_STATUS
Definition: dns.h:95
@ FR_DNS_INVERSE_QUERY_RESPONSE
Definition: dns.h:102
@ FR_DNS_UPDATE
Definition: dns.h:97
@ FR_DNS_CODE_MAX
Definition: dns.h:99
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG_ENABLED()
Definition: radclient.h:49
Return codes returned by modules and virtual server sections.
#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
#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
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
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 COMPILE_TERMINATOR
char const * name
Name of the processing section, such as "recv" or "send".
Processing sections which are allowed in this virtual server.