The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
call.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: 549a66db2f71425a612a8fe75a7a39ec8562be45 $
19 *
20 * @file unlang/call.c
21 * @brief Unlang "call" keyword evaluation. Used for calling virtual servers.
22 *
23 * @copyright 2006-2019 The FreeRADIUS server project
24 */
25RCSID("$Id: 549a66db2f71425a612a8fe75a7a39ec8562be45 $")
26
27#include <freeradius-devel/server/state.h>
28#include <freeradius-devel/server/pair.h>
29
30#include "call_priv.h"
31
34{
37 fr_pair_t *packet_type_vp = NULL;
38
39 switch (pair_update_reply(&packet_type_vp, gext->attr_packet_type)) {
40 case 0:
41 packet_type_vp->vp_uint32 = request->reply->code;
42 break;
43
44 case 1:
45 break; /* Don't change */
46 }
47
49}
50
53{
55
56 /*
57 * Push the contents of the call { } section onto the stack.
58 * This gets executed after the server returns.
59 */
60 return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING);
61}
62
63
66{
68 unlang_call_t *gext;
69 fr_dict_enum_value_t const *type_enum;
70 fr_pair_t *packet_type_vp = NULL;
71
72 /*
73 * Do not check for children here.
74 *
75 * Call shouldn't require children to execute as there
76 * can still be side effects from executing the virtual
77 * server.
78 */
80 gext = unlang_group_to_call(g);
81
82 /*
83 * Work out the current request type.
84 */
85 type_enum = fr_dict_enum_by_value(gext->attr_packet_type, fr_box_uint32(request->packet->code));
86 if (!type_enum) {
87 packet_type_vp = fr_pair_find_by_da(&request->request_pairs, NULL, gext->attr_packet_type);
88 if (!packet_type_vp) {
89 bad_packet_type:
90 REDEBUG("No such value '%u' of attribute 'Packet-Type' for server %s",
91 request->packet->code, cf_section_name2(gext->server_cs));
92 error:
93 *p_result = RLM_MODULE_FAIL;
95 }
96 type_enum = fr_dict_enum_by_value(packet_type_vp->da, &packet_type_vp->data);
97 if (!type_enum) goto bad_packet_type;
98
99 /*
100 * Sync up packet->code
101 */
102 request->packet->code = packet_type_vp->vp_uint32;
103 }
104
105 /*
106 * Sync up packet codes and attributes
107 *
108 * Fixme - packet->code needs to die...
109 */
110 if (!packet_type_vp) switch (pair_update_request(&packet_type_vp, gext->attr_packet_type)) {
111 case 0:
112 packet_type_vp->vp_uint32 = request->packet->code;
113 break;
114
115 case 1:
116 request->packet->code = packet_type_vp->vp_uint32;
117 break;
118
119 default:
120 goto error;
121 }
122
123 /*
124 * Need to add reply.Packet-Type if it
125 * wasn't set by the virtual server...
126 *
127 * AGAIN packet->code NEEDS TO DIE.
128 * DIE DIE DIE DIE DIE DIE DIE DIE DIE
129 * DIE DIE DIE DIE DIE DIE DIE DIE DIE
130 * DIE DIE DIE.
131 */
132 if (!g->children) {
134 } else {
136 }
137
138 if (virtual_server_push(request, gext->server_cs, UNLANG_SUB_FRAME) < 0) goto error;
139
141}
142
143/** Push a call frame onto the stack
144 *
145 * This should be used instead of virtual_server_push in the majority of the code
146 */
147unlang_action_t unlang_call_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
148{
149 unlang_stack_t *stack = request->stack;
150 unlang_call_t *c;
151 char const *name;
152 fr_dict_t const *dict;
154
155 /*
156 * Temporary hack until packet->code is removed
157 */
158 dict = virtual_server_dict_by_cs(server_cs);
159 if (!dict) {
160 REDEBUG("Virtual server \"%s\" not compiled", cf_section_name2(server_cs));
161 return UNLANG_ACTION_FAIL;
162 }
163
164 attr_packet_type = fr_dict_attr_by_name(NULL, fr_dict_root(dict), "Packet-Type");
165 if (!attr_packet_type) {
166 REDEBUG("No Packet-Type attribute available");
167 return UNLANG_ACTION_FAIL;
168 }
169
170 /*
171 * We need to have a unlang_module_t to push on the
172 * stack. The only sane way to do it is to attach it to
173 * the frame state.
174 */
175 name = cf_section_name2(server_cs);
176 MEM(c = talloc(stack, unlang_call_t)); /* Free at the same time as the state */
177 *c = (unlang_call_t){
178 .group = {
179 .self = {
181 .name = name,
182 .debug_name = name,
183 .ci = CF_TO_ITEM(server_cs),
184 .actions = {
185 .actions = {
186 [RLM_MODULE_REJECT] = 0,
187 [RLM_MODULE_FAIL] = MOD_ACTION_RETURN, /* Exit out of nested levels */
188 [RLM_MODULE_OK] = 0,
189 [RLM_MODULE_HANDLED] = 0,
190 [RLM_MODULE_INVALID] = 0,
193 [RLM_MODULE_NOOP] = 0,
195 },
196 .retry = RETRY_INIT,
197 },
198 },
199
200 .cs = server_cs,
201 },
202 .server_cs = server_cs,
203 .attr_packet_type = attr_packet_type
204 };
205
206 /*
207 * Push a new call frame onto the stack
208 */
210 RLM_MODULE_NOT_SET, UNLANG_NEXT_STOP, top_frame) < 0) {
211 talloc_free(c);
212 return UNLANG_ACTION_FAIL;
213 }
214
216}
217
218/** Return the last virtual server that was called
219 *
220 * @param[in] request To return virtual server for.
221 * @return
222 * - A virtual server CONF_SECTION on success.
223 * - NULL on failure.
224 */
226{
227 unlang_stack_t *stack = request->stack;
228 unsigned int depth;
229
230 /*
231 * Work back from the deepest frame
232 * looking for modules.
233 */
234 for (depth = stack_depth_current(request); depth > 0; depth--) {
235 unlang_stack_frame_t *frame = &stack->frame[depth];
236
237 /*
238 * Look at the module frames,
239 * trying to find one that represents
240 * a process state machine.
241 */
242 if (frame->instruction->type != UNLANG_TYPE_CALL) continue;
243
245 }
246 return NULL;
247}
248
250{
252 &(unlang_op_t){
253 .name = "call",
254 .interpret = unlang_call_frame_init,
255 .rcode_set = true,
256 .debug_braces = true,
257 });
258}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:39
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
#define RCSID(id)
Definition build.h:483
#define UNUSED
Definition build.h:315
static unlang_action_t unlang_call_resume(UNUSED rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Definition call.c:32
static unlang_action_t unlang_call_children(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Definition call.c:51
void unlang_call_init(void)
Definition call.c:249
unlang_action_t unlang_call_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Push a call frame onto the stack.
Definition call.c:147
CONF_SECTION * unlang_call_current(request_t *request)
Return the last virtual server that was called.
Definition call.c:225
static unlang_action_t unlang_call_frame_init(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
Definition call.c:64
static unlang_t * unlang_call_to_generic(unlang_call_t *call)
Cast a call keyword extension to a unlang_t structure.
Definition call_priv.h:64
CONF_SECTION * server_cs
Config section of the virtual server being executed.
Definition call_priv.h:39
fr_dict_attr_t const * attr_packet_type
Attribute used to specify packet type and sections run in the server_cs.
Definition call_priv.h:41
unlang_group_t group
Generic field common to all group type unlang_t nodes.
Definition call_priv.h:37
static unlang_call_t * unlang_group_to_call(unlang_group_t *g)
Cast a group structure to the call keyword extension.
Definition call_priv.h:48
Entry point into a proto_ module.
Definition call_priv.h:36
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1185
#define CF_TO_ITEM(_cf)
Auto cast from the input type to CONF_ITEM (which is the base type)
Definition cf_util.h:65
#define MEM(x)
Definition debug.h:36
static fr_dict_attr_t const * attr_packet_type
Definition dhcpclient.c:89
fr_dict_enum_value_t * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
Definition dict_util.c:3349
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
Definition dict_util.c:3263
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2400
Value of an enumerated attribute.
Definition dict.h:227
int unlang_interpret_push(request_t *request, unlang_t const *instruction, rlm_rcode_t default_rcode, bool do_next_sibling, bool top_frame)
Push a new frame onto the stack.
Definition interpret.c:161
unlang_action_t unlang_interpret_push_children(rlm_rcode_t *p_result, request_t *request, rlm_rcode_t default_rcode, bool do_next_sibling)
Push the children of the current frame onto a new frame onto the stack.
Definition interpret.c:243
#define UNLANG_SUB_FRAME
Definition interpret.h:36
void unlang_register(int type, unlang_op_t *op)
Register an operation with the interpreter.
Definition base.c:63
talloc_free(reap)
static char * stack[MAX_STACK]
Definition radmin.c:158
static uint8_t depth(fr_minmax_heap_index_t i)
Definition minmax_heap.c:83
@ MOD_ACTION_RETURN
Definition mod_action.h:40
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:693
#define pair_update_request(_attr, _da)
#define REDEBUG(fmt,...)
Definition radclient.h:52
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_NOT_SET
Error resolving rcode (should not be returned by modules).
Definition rcode.h:51
@ 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
static char const * name
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition pair.h:129
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define UNLANG_NEXT_SIBLING
Definition unlang_priv.h:93
#define UNLANG_NEXT_STOP
Definition unlang_priv.h:92
static unlang_group_t * unlang_generic_to_group(unlang_t const *p)
static int stack_depth_current(request_t *request)
@ UNLANG_TYPE_CALL
call another virtual server
Definition unlang_priv.h:66
static void frame_repeat(unlang_stack_frame_t *frame, unlang_process_t process)
Mark the current stack frame up for repeat, and set a new process function.
unlang_t const * instruction
The unlang node we're evaluating.
rlm_rcode_t result
The result from executing the instruction.
unlang_type_t type
The specialisation of this node.
unlang_t * children
Children beneath this group.
Generic representation of a grouping.
An unlang operation.
Our interpreter stack, as distinct from the C stack.
An unlang stack associated with a request.
#define RETRY_INIT
Definition retry.h:39
#define fr_box_uint32(_val)
Definition value.h:312
unlang_action_t virtual_server_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Set the request processing function.
fr_dict_t const * virtual_server_dict_by_cs(CONF_SECTION const *server_cs)
Return the namespace for the virtual server specified by a config section.