The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
base.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 4d027f5176003dd24e073362174421ef54caba13 $
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 <freeradius-devel/server/protocol.h>
26#include <freeradius-devel/server/pair.h>
27#include <freeradius-devel/server/rcode.h>
28#include <freeradius-devel/util/debug.h>
29#include <freeradius-devel/util/pair.h>
30#include <freeradius-devel/unlang/interpret.h>
31#include <freeradius-devel/dns/dns.h>
32#include <freeradius-devel/protocol/dns/rfc1034.h>
33
34/** Update this if new rcodes are added
35 */
36#define FR_DNS_RCODE_MAX (FR_RCODE_VALUE_BAD_COOKIE + 1)
37
38static fr_dict_t const *dict_dns;
39
45
48static fr_dict_attr_t const *attr_id;
53
56 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_dns},
57 { .out = &attr_header, .name = "Header", .type = FR_TYPE_STRUCT, .dict = &dict_dns},
58 { .out = &attr_opcode, .name = "Header.Opcode", .type = FR_TYPE_UINT8, .dict = &dict_dns},
59 { .out = &attr_id, .name = "Header.ID", .type = FR_TYPE_UINT16, .dict = &dict_dns},
60 { .out = &attr_response_bit, .name = "Header.Query", .type = FR_TYPE_BOOL, .dict = &dict_dns},
61 { .out = &attr_rcode, .name = "Header.Rcode", .type = FR_TYPE_UINT8, .dict = &dict_dns},
62 { .out = &attr_authoritative_bit, .name = "Header.Authoritative", .type = FR_TYPE_BOOL, .dict = &dict_dns},
64};
65
71
74 { .out = &enum_rcode_no_error, .name = "No-Error", .attr = &attr_rcode }, /* ok/updated */
75 { .out = &enum_rcode_format_error, .name = "Format-Error", .attr = &attr_rcode }, /* invalid */
76 { .out = &enum_rcode_server_failure, .name = "Server-Failure", .attr = &attr_rcode }, /* fail */
77 { .out = &enum_rcode_name_error, .name = "Name-Error", .attr = &attr_rcode }, /* notfound */
78 { .out = &enum_rcode_refused, .name = "Refused", .attr = &attr_rcode }, /* reject */
80};
81
82typedef struct {
83 uint64_t nothing; // so that the next field isn't at offset 0
84
85 /** Request/response sections
86 *
87 */
98
99 /** DNS rcode error sections (not the same as rlm_rcode_t values)
100 *
101 * These are called after the `recv { ... }` section runs if rcode is non-zero
102 */
104
107
111
112/** Records fields from the original request so we have a known good copy
113 */
114typedef struct {
115 uint16_t id; //!< Identity of the request.
116 uint8_t opcode; //!< Opcode, what type of query this is.
118
119#define PROCESS_PACKET_TYPE fr_dns_packet_code_t
120#define PROCESS_CODE_MAX FR_DNS_CODE_MAX
121#define PROCESS_CODE_DO_NOT_RESPOND FR_DNS_DO_NOT_RESPOND
122#define PROCESS_PACKET_CODE_VALID FR_DNS_PACKET_CODE_VALID
123#define PROCESS_INST process_dns_t
124#define PROCESS_RCTX_EXTRA_FIELDS process_dns_fields_t fields;
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 .section = SECTION_NAME("recv", "Query"),
135 .actions = &mod_actions_authorize,
136 .offset = PROCESS_CONF_OFFSET(query),
137 },
138 {
139 .section = SECTION_NAME("send", "Query-Response"),
141 .offset = PROCESS_CONF_OFFSET(query_response),
142 },
143 {
144 .section = SECTION_NAME("recv", "Inverse-Query"),
146 .offset = PROCESS_CONF_OFFSET(inverse_query),
147 },
148 {
149 .section = SECTION_NAME("send", "Inverse-Query-Response"),
151 .offset = PROCESS_CONF_OFFSET(inverse_query_response),
152 },
153 {
154 .section = SECTION_NAME("recv", "Status"),
156 .offset = PROCESS_CONF_OFFSET(status),
157 },
158 {
159 .section = SECTION_NAME("send", "Status-Response"),
161 .offset = PROCESS_CONF_OFFSET(status_response),
162 },
163 {
164 .section = SECTION_NAME("recv", "Update"),
166 .offset = PROCESS_CONF_OFFSET(update),
167 },
168 {
169 .section = SECTION_NAME("send", "Update-Response"),
171 .offset = PROCESS_CONF_OFFSET(update_response),
172 },
173 {
174 .section = SECTION_NAME("recv", "Stateful-Operation"),
176 .offset = PROCESS_CONF_OFFSET(stateful_operation),
177 },
178 {
179 .section = SECTION_NAME("send", "Stateful-Operation-Response"),
181 .offset = PROCESS_CONF_OFFSET(stateful_operation_response),
182 },
183 {
184 .section = SECTION_NAME("send", "Do-Not-Respond"),
186 .offset = PROCESS_CONF_OFFSET(do_not_respond),
187 },
188
189#define ERROR_SECTION(_name, _number) \
190 { \
191 .section = SECTION_NAME("error", _name), \
192 .actions = &mod_actions_postauth, \
193 .offset = PROCESS_CONF_OFFSET(rcode[_number]), \
194 }
195
196 /*
197 * Error sections that can execute after the recv { ... }
198 * section has run.
199 */
200 ERROR_SECTION("Format-Error", FR_RCODE_VALUE_FORMAT_ERROR),
201 ERROR_SECTION("Server-Failure", FR_RCODE_VALUE_SERVER_FAILURE),
202 ERROR_SECTION("Name-Error", FR_RCODE_VALUE_NAME_ERROR),
203 ERROR_SECTION("Not-Implemented", FR_RCODE_VALUE_NOT_IMPLEMENTED),
204 ERROR_SECTION("Refused", FR_RCODE_VALUE_REFUSED),
205 ERROR_SECTION("YX-Domain", FR_RCODE_VALUE_YX_DOMAIN),
206 ERROR_SECTION("YX-Resource-Record-Set", FR_RCODE_VALUE_YX_RESOURCE_RECORD_SET),
207 ERROR_SECTION("NX-Resource-Record-Set", FR_RCODE_VALUE_NX_RESOURCE_RECORD_SET),
208 ERROR_SECTION("Not-Auth", FR_RCODE_VALUE_NOT_AUTH),
209 ERROR_SECTION("Not-Zone", FR_RCODE_VALUE_NOT_ZONE),
210 ERROR_SECTION("DSO-Type-Not-Implemented", FR_RCODE_VALUE_DSO_TYPE_NOT_IMPLEMENTED),
211 ERROR_SECTION("Bad-Signature", FR_RCODE_VALUE_BAD_SIGNATURE),
212 ERROR_SECTION("Bad-Key", FR_RCODE_VALUE_BAD_KEY),
213 ERROR_SECTION("Bad-Time", FR_RCODE_VALUE_BAD_TIME),
214 ERROR_SECTION("Bad-Mode", FR_RCODE_VALUE_BAD_MODE),
215 ERROR_SECTION("Bad-Name", FR_RCODE_VALUE_BAD_NAME),
216 ERROR_SECTION("Bad-Algorithm", FR_RCODE_VALUE_BAD_ALGORITHM),
217 ERROR_SECTION("Bad-Truncation", FR_RCODE_VALUE_BAD_TRUNCATION),
218 ERROR_SECTION("Bad-Cookie", FR_RCODE_VALUE_BAD_COOKIE),
220};
221
222/*
223 * Debug the packet if requested.
224 */
225static void dns_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
226{
227 if (!packet) return;
228 if (!RDEBUG_ENABLED) return;
229
230 if ((packet->code & 0x0f) >= FR_DNS_CODE_MAX) return;
231
232 if (!fr_dns_packet_names[packet->code & 0x0f]) return;
233
234 log_request(L_DBG, L_DBG_LVL_1, request, __FILE__, __LINE__, "%s %s",
235 received ? "Received" : "Sending",
236 fr_dns_packet_names[packet->code & 0x0f]);
237
238 if (received || request->parent) {
239 log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
240 } else {
241 log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
242 }
243}
244
245/** Keep a copy of header fields to prevent them being tampered with
246 *
247 */
248static inline CC_HINT(always_inline)
249process_rctx_t *dns_fields_store(request_t *request)
250{
251 fr_pair_t *header;
252 fr_pair_t *id;
253 fr_pair_t *opcode;
254 process_rctx_t *rctx;
255
256 /*
257 * We could use fr_find_by_da_nested, but it's more efficient
258 * to look up the header attribute once.
259 */
260 header = fr_pair_find_by_da(&request->request_pairs, NULL, attr_header);
261 if (!header) {
262 REDEBUG("Missing Header attribute");
263 return NULL;
264 }
265
266 id = fr_pair_find_by_da(&header->vp_group, NULL, attr_id);
267 if (!id) {
268 REDEBUG("Missing ID attribute");
269 return NULL;
270 }
271
272 opcode = fr_pair_find_by_da(&header->vp_group, NULL, attr_opcode);
273 if (!opcode) {
274 REDEBUG("Missing Opcode attribute");
275 return NULL;
276 }
277
278 MEM(rctx = talloc(unlang_interpret_frame_talloc_ctx(request), process_rctx_t));
279 rctx->fields.id = id->vp_uint16;
280 rctx->fields.opcode = opcode->vp_uint8;
281
282 return rctx;
283}
284
285/** Copy values from the request header back into the response
286 *
287 * If a value already exists in the response, don't overwrite it so the user has absolute control
288 */
289static inline CC_HINT(always_inline)
290int dns_fields_restore(request_t *request, process_rctx_t *rctx)
291{
292 fr_pair_t *header;
293 fr_pair_t *id;
294 fr_pair_t *response;
295 fr_pair_t *authoritative;
296 fr_pair_t *opcode;
297 int ret;
298
299 MEM(pair_update_reply(&header, attr_header) >= 0);
300
301 /*
302 * ID should always match the request
303 * but we allow overrides for testing.
304 */
305 MEM((ret = fr_pair_update_by_da_parent(header, &id, attr_id)) != -1);
306 fr_assert_msg(ret >= 0, "Failed to update header attribute %s:", fr_strerror());
307 if (ret == 0) id->vp_uint16 = rctx->fields.id;
308
309 /*
310 * This marks the packet as a response.
311 * Save the user from having to do this manually.
312 */
313 MEM((ret = fr_pair_update_by_da_parent(header, &response, attr_response_bit)) != -1);
314 fr_assert_msg(ret >= 0, "Failed to update response_bit attribute %s:", fr_strerror());
315 if (ret == 0) response->vp_bool = true;
316
317 /*
318 * Opcode should always match the request
319 * but we allow overrides for testing.
320 */
321 MEM((ret = fr_pair_update_by_da_parent(header, &opcode, attr_opcode)) != -1);
322 fr_assert_msg(ret >= 0, "Failed to update opcode attribute %s:", fr_strerror());
323 if (ret == 0) opcode->vp_uint8 = rctx->fields.opcode;
324
325 /*
326 * Default to setting the authoritative bit if
327 * it's not been set by something already.
328 */
329 MEM((ret = fr_pair_update_by_da_parent(header, &authoritative, attr_authoritative_bit)) != -1);
330 fr_assert_msg(ret >= 0, "Failed to update authoritative_bit attribute %s:", fr_strerror());
331 if (ret == 0) authoritative->vp_bool = true;
332
333 return 0;
334}
335
336/** Add/update the rcode attribute based on the last rlm_rcode value
337 *
338 */
339static inline CC_HINT(always_inline)
340void dns_rcode_add(fr_pair_t **rcode, request_t *request, fr_value_box_t const **code)
341{
342 fr_value_box_t const *vb;
343 int ret;
344
345 if (!code || !*code) return;
346
347 vb = *code;
348
349 /*
350 * Don't override the user status
351 * code.
352 */
353 MEM((ret = fr_pair_update_by_da_parent(request->reply_ctx, rcode, attr_rcode)) >= 0);
354 if (ret == 0) {
355 if (unlikely(fr_value_box_copy(*rcode, &(*rcode)->data, vb) < 0)) {
356 RPEDEBUG("Failed copying rcode value");
357 return;
358 }
359 (*rcode)->data.enumv = (*rcode)->da; /* Hack, boxes should have their enumv field populated */
360 }
361}
362
363/** Store basic information from the request, and jump into the correct processing section
364 *
365 */
366RECV(request)
367{
368 process_rctx_t *rctx;
369
371
372 rctx = dns_fields_store(request);
373 if (!rctx) RETURN_UNLANG_INVALID;
374
375 return CALL_RECV_RCTX(generic, rctx);
376}
377
378/** Sets the DNS rcode after we get a result from the recv section
379 *
380 * Calls error processing sections as appropriate
381 */
382RESUME(recv_request)
383{
385 fr_process_state_t const *state;
386 fr_pair_t *rcode = NULL;
387
389
390 /*
391 * Pick the next state based on the response
392 */
393 UPDATE_STATE(reply);
394
395 /*
396 * Don't bother adding VPs if we're not going
397 * be responding to the client.
398 */
399 if (state->packet_type[RESULT_RCODE] == FR_DNS_DO_NOT_RESPOND) return CALL_RESUME(recv_generic);
400
401 /*
402 * Add an rcode based on the result of the `recv { ... }` section
403 */
404 dns_rcode_add(&rcode, request, state->dns_rcode[RESULT_RCODE]);
405
406 /*
407 * Call an appropriate error section if it's been set
408 * otherwise, just call the generic recv resume
409 * which'll call an appropriate send section.
410 */
411 if (rcode && (rcode->vp_uint8 < NUM_ELEMENTS(inst->sections.rcode)) &&
412 (inst->sections.rcode[rcode->vp_uint8])) {
413 return unlang_module_yield_to_section(RESULT_P, request,
414 inst->sections.rcode[rcode->vp_uint8],
416 /*
417 * We ignore everything from the error section
418 * it's only there for logging.
419 *
420 * Jump straight to the send function.
421 */
422 state->send,
423 NULL, 0, mctx->rctx);
424 }
425
426 /*
427 * Use that rcode to determine the processing section
428 */
429 return CALL_RESUME(recv_generic);
430}
431
432/** Set defaults in the response and values copied from the request like opcode and id
433 *
434 */
435RESUME(send_response)
436{
437 fr_process_state_t const *state;
438 fr_pair_t *vp;
439
440 UPDATE_STATE(reply);
441
442 /*
443 * Don't bother adding VPs if we're not going
444 * be responding to the client.
445 */
446 if (state->packet_type[RESULT_RCODE] == FR_DNS_DO_NOT_RESPOND) return CALL_RESUME(send_generic);
447
448 /*
449 * Add fields from the request back in,
450 * deferring to user specified values.
451 */
452 dns_fields_restore(request, talloc_get_type_abort(mctx->rctx, process_rctx_t));
453
454 /*
455 * Do this last, so we show everything
456 * we'll be sending back.
457 */
458 dns_packet_debug(request, request->reply, &request->reply_pairs, false);
459
460 /*
461 * Hack. This is because this stupid framework uses
462 * packet_type values to represent request and response
463 * packet types, and DNS uses the same values for
464 * both request and response packet types.
465 */
467 MEM(vp);
468 request->reply->code = vp->vp_uint32 = state->default_reply;
469
470 return CALL_RESUME(send_generic);
471}
472
473/** Entry point into the state machine
474 */
475static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
476{
477 fr_process_state_t const *state;
478
480
482 fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
483
484 request->component = "dns";
485 request->module = NULL;
486 fr_assert(request->proto_dict == dict_dns);
487
488 UPDATE_STATE(packet);
489
490 if (!state->recv) {
491 REDEBUG("Invalid packet type (%u)", request->packet->code);
493 }
494
495 dns_packet_debug(request, request->packet, &request->request_pairs, true);
496
497 return state->recv(p_result, mctx, request);
498}
499
500#define DNS_RCODE_COMMON \
501 .dns_rcode = { \
502 [RLM_MODULE_NOOP] = &enum_rcode_no_error, \
503 [RLM_MODULE_OK] = &enum_rcode_no_error, \
504 [RLM_MODULE_UPDATED] = &enum_rcode_no_error, \
505 [RLM_MODULE_HANDLED] = &enum_rcode_no_error, \
506 [RLM_MODULE_REJECT] = &enum_rcode_refused, \
507 [RLM_MODULE_FAIL] = &enum_rcode_server_failure, \
508 [RLM_MODULE_INVALID] = &enum_rcode_format_error, \
509 [RLM_MODULE_DISALLOW] = &enum_rcode_refused, \
510 [RLM_MODULE_NOTFOUND] = &enum_rcode_name_error, \
511 [RLM_MODULE_TIMEOUT] = &enum_rcode_server_failure, \
512 }
513
514static fr_process_state_t const process_state[] = {
515 [ FR_DNS_QUERY ] = {
517 .default_reply = FR_DNS_QUERY_RESPONSE,
518 .default_rcode = RLM_MODULE_NOOP,
519 .recv = recv_request,
520 .resume = resume_recv_request,
521 .section_offset = PROCESS_CONF_OFFSET(query),
522 },
525 .default_reply = FR_DNS_INVERSE_QUERY_RESPONSE,
526 .default_rcode = RLM_MODULE_NOOP,
527 .recv = recv_request,
528 .resume = resume_recv_request,
529 .section_offset = PROCESS_CONF_OFFSET(inverse_query),
530 },
531 [ FR_DNS_STATUS ] = {
533 .default_reply = FR_DNS_STATUS_RESPONSE,
534 .default_rcode = RLM_MODULE_NOOP,
535 .recv = recv_request,
536 .resume = resume_recv_request,
537 .section_offset = PROCESS_CONF_OFFSET(status),
538 },
539 [ FR_DNS_UPDATE ] = {
541 .default_reply = FR_DNS_UPDATE_RESPONSE,
542 .default_rcode = RLM_MODULE_NOOP,
543 .recv = recv_request,
544 .resume = resume_recv_request,
545 .section_offset = PROCESS_CONF_OFFSET(update),
546 },
549 .default_reply = FR_DNS_STATEFUL_OPERATION_RESPONSE,
550 .default_rcode = RLM_MODULE_NOOP,
551 .recv = recv_request,
552 .resume = resume_recv_request,
553 .section_offset = PROCESS_CONF_OFFSET(stateful_operation),
554 },
556 .default_reply = FR_DNS_QUERY,
557 .default_rcode = RLM_MODULE_NOOP,
558 .result_rcode = RLM_MODULE_OK,
559 .send = send_generic,
560 .resume = resume_send_response,
561 .section_offset = PROCESS_CONF_OFFSET(query_response),
562 },
563
565 .default_reply = FR_DNS_QUERY,
566 .default_rcode = RLM_MODULE_NOOP,
567 .result_rcode = RLM_MODULE_OK,
568 .send = send_generic,
569 .resume = resume_send_response,
570 .section_offset = PROCESS_CONF_OFFSET(inverse_query_response),
571 },
572
574 .default_reply = FR_DNS_STATUS,
575 .default_rcode = RLM_MODULE_NOOP,
576 .result_rcode = RLM_MODULE_OK,
577 .send = send_generic,
578 .resume = resume_send_response,
579 .section_offset = PROCESS_CONF_OFFSET(status_response),
580 },
581
583 .default_reply = FR_DNS_UPDATE,
584 .default_rcode = RLM_MODULE_NOOP,
585 .result_rcode = RLM_MODULE_OK,
586 .send = send_generic,
587 .resume = resume_send_response,
588 .section_offset = PROCESS_CONF_OFFSET(update_response),
589 },
590
592 .default_reply = FR_DNS_STATEFUL_OPERATION,
593 .default_rcode = RLM_MODULE_NOOP,
594 .result_rcode = RLM_MODULE_OK,
595 .send = send_generic,
596 .resume = resume_send_response,
597 .section_offset = PROCESS_CONF_OFFSET(stateful_operation_response),
598 },
599
601 .packet_type = {
605
612 },
613 .default_rcode = RLM_MODULE_NOOP,
614 .result_rcode = RLM_MODULE_HANDLED,
615 .send = send_generic,
616 .resume = resume_send_response,
617 .section_offset = PROCESS_CONF_OFFSET(do_not_respond),
618 },
619};
620
623 .common = {
624 .magic = MODULE_MAGIC_INIT,
625 .name = "dns",
627 MODULE_RCTX(process_rctx_t)
628 },
629 .process = mod_process,
630 .compile_list = compile_list,
631 .dict = &dict_dns,
632 .packet_type = &attr_packet_type
633};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
#define unlikely(_x)
Definition build.h:383
#define NUM_ELEMENTS(_t)
Definition build.h:339
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
#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:202
#define MEM(x)
Definition debug.h:36
fr_value_box_t const ** out
Enumeration value.
Definition dict.h:283
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:294
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:307
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:313
Specifies an attribute which must be present for the module to function.
Definition dict.h:293
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:306
Specifies a value which must be present for the module to function.
Definition dict.h:282
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition interpret.c:1684
fr_dict_attr_t const * attr_packet_type
Definition base.c:93
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:844
void log_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt,...)
Marshal variadic log arguments into a va_list and pass to normal logging functions.
Definition log.c:610
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
Definition log.c:820
#define RPEDEBUG(fmt,...)
Definition log.h:388
@ 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
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_BOOL
A truth value.
unsigned char uint8_t
unlang_mod_actions_t const mod_actions_authorize
Definition mod_action.c:46
unlang_mod_actions_t const mod_actions_postauth
Definition mod_action.c:93
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Definition mod_action.h:69
module_instance_t const * mi
Instance of the module being instantiated.
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:709
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:1604
static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition base.c:188
static const virtual_server_compile_t compile_list[]
Definition base.c:214
static fr_process_state_t const process_state[]
Definition base.c:69
#define PROCESS_PACKET_CODE_VALID
Definition base.c:65
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
Definition base.c:400
fr_dict_attr_autoload_t process_dns_dict_attr[]
Definition base.c:55
CONF_SECTION * stateful_operation_response
Definition base.c:97
fr_dict_autoload_t process_dns_dict[]
Definition base.c:41
static void dns_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
Definition base.c:225
#define ERROR_SECTION(_name, _number)
uint64_t nothing
Definition base.c:83
static fr_value_box_t const * enum_rcode_server_failure
Definition base.c:68
static fr_dict_attr_t const * attr_authoritative_bit
Definition base.c:52
CONF_SECTION * status
Definition base.c:92
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:340
CONF_SECTION * inverse_query_response
Definition base.c:91
CONF_SECTION * query_response
Definition base.c:89
CONF_SECTION * stateful_operation
Definition base.c:96
static int dns_fields_restore(request_t *request, process_rctx_t *rctx)
Copy values from the request header back into the response.
Definition base.c:290
static fr_dict_attr_t const * attr_opcode
Definition base.c:50
static fr_value_box_t const * enum_rcode_refused
Definition base.c:70
static fr_dict_attr_t const * attr_response_bit
Definition base.c:49
static fr_value_box_t const * enum_rcode_no_error
Definition base.c:66
CONF_SECTION * query
Request/response sections.
Definition base.c:88
uint8_t opcode
Opcode, what type of query this is.
Definition base.c:116
static fr_dict_attr_t const * attr_id
Definition base.c:48
CONF_SECTION * inverse_query
Definition base.c:90
#define FR_DNS_RCODE_MAX
Update this if new rcodes are added.
Definition base.c:36
fr_dict_enum_autoload_t process_dns_dict_enum[]
Definition base.c:73
process_dns_sections_t sections
Definition base.c:109
static fr_value_box_t const * enum_rcode_name_error
Definition base.c:69
uint16_t id
Identity of the request.
Definition base.c:115
#define DNS_RCODE_COMMON
Definition base.c:500
static fr_dict_t const * dict_dns
Definition base.c:38
CONF_SECTION * update_response
Definition base.c:95
CONF_SECTION * update
Definition base.c:94
static process_rctx_t * dns_fields_store(request_t *request)
Keep a copy of header fields to prevent them being tampered with.
Definition base.c:249
static fr_value_box_t const * enum_rcode_format_error
Definition base.c:67
static fr_dict_attr_t const * attr_header
Definition base.c:47
CONF_SECTION * status_response
Definition base.c:93
CONF_SECTION * do_not_respond
Definition base.c:105
fr_process_module_t process_dns
Definition base.c:622
static fr_dict_attr_t const * attr_rcode
Definition base.c:51
Records fields from the original request so we have a known good copy.
Definition base.c:114
#define PROCESS_TRACE
Trace each state function as it's entered.
Definition process.h:55
#define PROCESS_CONF_OFFSET(_x)
Definition process.h:79
module_t common
Common fields for all loadable modules.
Common public symbol definition for all process modules.
char const * fr_dns_packet_names[FR_DNS_CODE_MAX]
Definition base.c:68
@ FR_DNS_DO_NOT_RESPOND
Definition dns.h:99
@ FR_DNS_STATEFUL_OPERATION_RESPONSE
Definition dns.h:97
@ FR_DNS_UPDATE_RESPONSE
Definition dns.h:96
@ FR_DNS_STATEFUL_OPERATION
Definition dns.h:89
@ FR_DNS_QUERY
Definition dns.h:84
@ FR_DNS_QUERY_RESPONSE
Definition dns.h:92
@ FR_DNS_STATUS_RESPONSE
Definition dns.h:94
@ FR_DNS_INVERSE_QUERY
Definition dns.h:85
@ FR_DNS_STATUS
Definition dns.h:86
@ FR_DNS_INVERSE_QUERY_RESPONSE
Definition dns.h:93
@ FR_DNS_UPDATE
Definition dns.h:88
@ FR_DNS_CODE_MAX
Definition dns.h:90
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED()
#define RETURN_UNLANG_INVALID
Definition rcode.h:66
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:51
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:49
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition rcode.h:52
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:47
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
Definition rcode.h:56
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:53
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:55
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:54
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:50
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
void * data
Module's instance data.
Definition module.h:291
#define MODULE_RCTX(_ctype)
Definition module.h:257
#define MODULE_INST(_ctype)
Definition module.h:255
#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(unlang_result_t *p_result, request_t *request, CONF_SECTION *subcs, rlm_rcode_t default_rcode, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Definition module.c:236
eap_aka_sim_process_conf_t * inst
#define RESUME(_x)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define talloc_get_type_abort_const
Definition talloc.h:113
unsigned int code
Packet code (type).
Definition packet.h:61
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
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:4409
section_name_t const * section
Identifier for the section.
#define COMPILE_TERMINATOR
Processing sections which are allowed in this virtual server.