Coverage Report

Created: 2026-08-14 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/freeradius-devel/server/request.h
Line
Count
Source
1
#pragma once
2
/*
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16
 */
17
18
/**
19
 * $Id: 7635a8baea0a8c90623321be0ae96449a63b8569 $
20
 *
21
 * @file lib/server/request.h
22
 * @brief The main request structure, and allocation functions.
23
 *
24
 * @copyright 1999-2018 The FreeRADIUS server project
25
 */
26
RCSIDH(request_h, "$Id: 7635a8baea0a8c90623321be0ae96449a63b8569 $")
27
28
/*
29
 *  Forward declarations to avoid dependency loops
30
 */
31
#ifdef __cplusplus
32
extern "C" {
33
#endif
34
35
typedef struct fr_async_s fr_async_t;
36
typedef struct request_s request_t;
37
38
typedef struct fr_client_s fr_client_t;
39
40
#ifdef __cplusplus
41
}
42
#endif
43
44
#include <freeradius-devel/server/log.h>
45
#include <freeradius-devel/server/rcode.h>
46
#include <freeradius-devel/server/signal.h>
47
#include <freeradius-devel/util/event.h>
48
#include <freeradius-devel/util/heap.h>
49
#include <freeradius-devel/util/packet.h>
50
#include <freeradius-devel/util/dlist.h>
51
52
#ifdef __cplusplus
53
extern "C" {
54
#endif
55
56
#ifndef NDEBUG
57
0
#  define REQUEST_MAGIC (0xdeadbeef)
58
#endif
59
60
/*
61
 *  Stack +
62
 *  4 pair lists and root +
63
 *  2 packets +
64
 *  some extra for VPs
65
 *
66
 *  Stack frames are allocated within the stack pool.
67
 */
68
0
#define REQUEST_POOL_NUM_OBJECTS ( \
69
0
          1 + \
70
0
          5 + \
71
0
          2 + \
72
0
          10 \
73
0
         )
74
75
/*
76
 *  Stack memory +
77
 *  4 pair lists and root +
78
 *  2 packets +
79
 *  some extra for VPs
80
 */
81
0
#define REQUEST_POOL_SIZE ( \
82
0
          UNLANG_STACK_POOL_SIZE + \
83
0
          (sizeof(fr_pair_t) * 5) + \
84
0
          (sizeof(fr_packet_t) * 2) + \
85
0
          (sizeof(fr_pair_t) * 10) \
86
0
        )
87
88
typedef enum {
89
  REQUEST_ACTIVE = 1,   //!< Request is active (running or runnable)
90
  REQUEST_STOP_PROCESSING,  //!< Request has been signalled to stop
91
  REQUEST_DONE,     //!< Request has completed
92
} request_master_state_t;
93
94
typedef enum request_state_t {
95
  REQUEST_INIT = 0,
96
  REQUEST_RECV,
97
  REQUEST_PROCESS,
98
  REQUEST_SEND,
99
  REQUEST_OTHER_1,
100
  REQUEST_OTHER_2,
101
  REQUEST_OTHER_3,
102
  REQUEST_OTHER_4,
103
} request_state_t;
104
105
extern HIDDEN fr_dict_attr_t const *request_attr_root;
106
extern fr_dict_attr_t const *request_attr_request;
107
extern fr_dict_attr_t const *request_attr_reply;
108
extern fr_dict_attr_t const *request_attr_control;
109
extern fr_dict_attr_t const *request_attr_state;
110
extern fr_dict_attr_t const *request_attr_local;
111
112
/** Convenience macro for accessing the request list
113
 *
114
 * This should be used in the form `&request->request_pairs`
115
 * to get a pointer to the head of the request list.
116
 */
117
0
#define request_pairs   pair_list.request->children
118
119
/** Talloc ctx for allocating request pairs under
120
 */
121
0
#define request_ctx   pair_list.request
122
123
/** Convenience macro for accessing the reply list
124
 *
125
 * This should be used in the form `&request->reply_pairs`
126
 * to get a pointer to the head of the request list.
127
 */
128
0
#define reply_pairs   pair_list.reply->children
129
130
/** Talloc ctx for allocating reply pairs under
131
 */
132
0
#define reply_ctx   pair_list.reply
133
134
/** Convenience macro for accessing the control list
135
 *
136
 * This should be used in the form `&request->control_pairs`
137
 * to get a pointer to the head of the request list.
138
 */
139
0
#define control_pairs   pair_list.control->children
140
141
/** Talloc ctx for allocating control pairs under
142
 */
143
0
#define control_ctx   pair_list.control
144
145
/** Convenience macro for accessing the state list
146
 *
147
 * This should be used in the form `&request->session_state_pairs`
148
 * to get a pointer to the head of the request list.
149
 */
150
0
#define session_state_pairs pair_list.state->children
151
152
/** Talloc ctx for allocating reply pairs under
153
 */
154
0
#define session_state_ctx pair_list.state
155
156
/** Convenience macro for accessing the state list
157
 *
158
 * This should be used in the form `&request->local_pairs`
159
 * to get a pointer to the head of the local list.
160
 */
161
0
#define local_pairs pair_list.local->children
162
163
/** Talloc ctx for allocating local variables
164
 */
165
0
#define local_ctx pair_list.local
166
167
/** Pair lists accessible from the request
168
 *
169
 */
170
typedef struct {
171
  fr_pair_t   *request; //!< Pair containing the request list.
172
  fr_pair_t   *reply;   //!< Pair containing the reply list.
173
  fr_pair_t   *control; //!< Pair containing the control list.
174
  fr_pair_t   *state;   //!< Pair containing the state list.
175
  fr_pair_t   *local;   //!< Pair containing local variables
176
} request_pair_lists_t;
177
178
typedef enum {
179
  REQUEST_TYPE_EXTERNAL = 0,    //!< A request received on the wire.
180
  REQUEST_TYPE_INTERNAL,      //!< A request generated internally.
181
  REQUEST_TYPE_DETACHED       //!< A request that was generated internally, but is now detached
182
            ///< (not associated with a parent request.)
183
} request_type_t;
184
185
#define request_is_external(_x) ((_x)->type == REQUEST_TYPE_EXTERNAL)
186
#define request_is_internal(_x) ((_x)->type == REQUEST_TYPE_INTERNAL)
187
0
#define request_is_detached(_x) ((_x)->type == REQUEST_TYPE_DETACHED)
188
0
#define request_is_detachable(_x) ((_x)->flags.detachable)
189
#define request_is_dynamic_client(_x) ((_x)->flags.dynamic_client)
190
#define request_set_dynamic_client(_x) ((_x)->flags.dynamic_client = true)
191
192
struct request_s {
193
#ifndef NDEBUG
194
  uint32_t    magic;    //!< Magic number used to detect memory corruption,
195
            //!< or request structs that have not been properly initialised.
196
197
  uint64_t    ins_count;  //!< count of instructions we've ran
198
  uint64_t    ins_max;  //!< max instruction to bail out at
199
200
#endif
201
  void      *stack;   //!< unlang interpreter stack.
202
203
  request_type_t    type;   //!< What type of request this is.
204
205
  request_t   *parent;  //!< Request that generated this request.
206
207
  uint64_t    number;   //!< Monotonically increasing request number. Reset on server restart.
208
  uint64_t    child_number;   //!< Monotonically increasing number for children of this request
209
  char const    *name;    //!< for debug printing, as (%d) is no longer sufficient
210
211
  uint64_t    seq_start;  //!< State sequence ID.  Stable identifier for a sequence of requests
212
            //!< and responses.
213
  fr_dict_t const   *proto_dict;    //!< Dictionary of the protocol that this request belongs to.
214
  fr_dict_t const   *local_dict;  //!< dictionary for local variables
215
216
  fr_pair_t   *pair_root; //!< Root attribute which contains the
217
            ///< other list attributes as children.
218
219
  /** Pair lists associated with the request
220
   *
221
   * @warning DO NOT allocate pairs directly beneath the root
222
   *      or in the ctx of the request.
223
   *      They MUST be allocated beneath their appropriate
224
   *      list attribute.
225
   */
226
  request_pair_lists_t  pair_list;  //!< Structure containing all pair lists.
227
228
  fr_dlist_head_t   data;   //!< Request data.
229
230
  /** Capabilities flags for this request
231
   *
232
   */
233
  struct {
234
    unsigned int      detachable : 1;   //!< This request may be detached from its parent..
235
    unsigned int    dynamic_client : 1; //!< this is a dynamic client request
236
  } flags;
237
238
  /** Logging information
239
   *
240
   */
241
  struct {
242
    log_dst_t   *dst;   //!< First in a list of log destinations.
243
244
    fr_log_lvl_t    lvl;    //!< Log messages with lvl >= to this should be logged.
245
246
    rindent_t   indent;   //!< Indentation for log messages.
247
  } log;
248
249
  char const    *component;   //!< Section the request is in.
250
  char const    *module;  //!< Module the request is currently being processed by.
251
252
  fr_packet_t   *packet;  //!< Incoming request.
253
  fr_packet_t   *reply;   //!< Outgoing response.
254
255
  fr_client_t   *client;  //!< The client that originally sent us the request.
256
257
  request_master_state_t  master_state; //!< Set by the master thread to signal the child that's currently
258
            //!< working with the request, to do something.
259
  bool      counted;  //!< Set if the request has been counted in the stats.
260
261
  rlm_rcode_t   rcode;    //!< Last rcode returned by a module
262
263
  fr_rb_node_t    dedup_node; //!< entry in the deduplication tree.
264
265
  fr_timer_t    *timeout; //!< Timer event for this request.  This tracks when we need to
266
            ///< forcefully terminate a request.
267
268
  uint32_t    options;  //!< mainly for proxying EAP-MSCHAPv2.
269
270
  fr_async_t    *async;   //!< for new async listeners
271
272
  char const    *alloc_file;  //!< File the request was allocated in.
273
274
  int     alloc_line; //!< Line the request was allocated on.
275
276
  fr_dlist_t    listen_entry; //!< request's entry in the list for this listener / socket
277
278
  uint32_t    priority; //!< higher == higher priority
279
  uint32_t    sequence; //!< higher == higher priority, too
280
281
  fr_heap_index_t   runnable; //!< entry in the heap of runnable packets
282
283
};        /* request_t typedef */
284
285
/** Optional arguments for initialising requests
286
 *
287
 */
288
typedef struct {
289
  fr_dict_t const   *namespace; //!< The namespace this request implements.
290
291
  request_t   *parent;  //!< If set, the request is a child request used to run
292
            ///< policy sections and additional virtual servers.
293
294
  request_pair_lists_t  pair_list;  //!< Alternative pair list heads.
295
            ///< These allow a request to expose nested attributes as
296
            ///< request or reply lists from the parent.
297
298
  bool      detachable; //!< Request should be detachable, i.e. able to run even
299
            ///< if its parent exits.
300
} request_init_args_t;
301
302
#ifdef WITH_VERIFY_PTR
303
0
#  define REQUEST_VERIFY(_x) request_verify(__FILE__, __LINE__, _x)
304
#else
305
/*
306
 *  Even if were building without WITH_VERIFY_PTR
307
 *  the pointer must not be NULL when these various macros are used
308
 *  so we can add some sneaky asserts.
309
 */
310
#  define REQUEST_VERIFY(_x) fr_assert(_x)
311
#endif
312
313
0
#define RAD_REQUEST_LVL_NONE  (0)    //!< No debug messages should be printed.
314
#define RAD_REQUEST_LVL_DEBUG (1)
315
#define RAD_REQUEST_LVL_DEBUG2  (2)
316
#define RAD_REQUEST_LVL_DEBUG3  (3)
317
#define RAD_REQUEST_LVL_DEBUG4  (4)
318
319
#define RAD_REQUEST_OPTION_CTX  (1 << 1)
320
#define RAD_REQUEST_OPTION_DETAIL (1 << 2)
321
322
#define   request_init(_ctx, _type, _args) \
323
    _request_init(__FILE__, __LINE__, _ctx, _type, _args)
324
325
int   _request_init(char const *file, int line,
326
            request_t *request, request_type_t type,
327
            request_init_args_t const *args);
328
329
int   request_slab_deinit(request_t *request);
330
331
/** Allocate a new external request outside of the request pool
332
 *
333
 * @param[in] _ctx  Talloc ctx to allocate the request in.
334
 * @param[in] _args Optional arguments that control how the request is initialised.
335
 */
336
#define   request_local_alloc_external(_ctx, _args) \
337
    _request_local_alloc(__FILE__, __LINE__, (_ctx), REQUEST_TYPE_EXTERNAL, (_args))
338
339
/** Allocate a new internal request outside of the request pool
340
 *
341
 * @param[in] _ctx  Talloc ctx to allocate the request in.
342
 * @param[in] _args Optional arguments that control how the request is initialised.
343
 */
344
#define   request_local_alloc_internal(_ctx, _args) \
345
0
    _request_local_alloc(__FILE__, __LINE__, (_ctx), REQUEST_TYPE_INTERNAL, (_args))
346
347
request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx,
348
              request_type_t type, request_init_args_t const *args);
349
350
fr_pair_t *request_state_replace(request_t *request, fr_pair_t *state) CC_HINT(nonnull(1));
351
352
int   request_detach(request_t *child);
353
354
int   request_global_init(void);
355
void    request_global_free(void);
356
357
void    request_log_prepend(request_t *request, fr_log_t *log, fr_log_lvl_t lvl);
358
359
#ifdef WITH_VERIFY_PTR
360
void    request_verify(char const *file, int line, request_t const *request); /* only for special debug builds */
361
#endif
362
363
static inline bool request_attr_is_list(fr_dict_attr_t const *da)
364
5.36k
{
365
5.36k
  return (da == request_attr_request) ||
366
4.61k
    (da == request_attr_reply) ||
367
4.61k
    (da == request_attr_control) ||
368
4.61k
    (da == request_attr_state) ||
369
4.61k
    (da == request_attr_local);
370
5.36k
}
Unexecuted instantiation: fuzzer_cf.c:request_attr_is_list
Unexecuted instantiation: fuzzer_xlat.c:request_attr_is_list
Unexecuted instantiation: fuzzer_tmpl.c:request_attr_is_list
Unexecuted instantiation: dl.c:request_attr_is_list
Unexecuted instantiation: base.c:request_attr_is_list
Unexecuted instantiation: cache.c:request_attr_is_list
Unexecuted instantiation: cert.c:request_attr_is_list
Unexecuted instantiation: conf.c:request_attr_is_list
Unexecuted instantiation: ctx.c:request_attr_is_list
Unexecuted instantiation: engine.c:request_attr_is_list
Unexecuted instantiation: log.c:request_attr_is_list
Unexecuted instantiation: pairs.c:request_attr_is_list
Unexecuted instantiation: session.c:request_attr_is_list
Unexecuted instantiation: strerror.c:request_attr_is_list
Unexecuted instantiation: utils.c:request_attr_is_list
Unexecuted instantiation: verify.c:request_attr_is_list
Unexecuted instantiation: version.c:request_attr_is_list
Unexecuted instantiation: virtual_server.c:request_attr_is_list
Unexecuted instantiation: auth.c:request_attr_is_list
Unexecuted instantiation: cf_file.c:request_attr_is_list
Unexecuted instantiation: cf_parse.c:request_attr_is_list
Unexecuted instantiation: cf_util.c:request_attr_is_list
Unexecuted instantiation: client.c:request_attr_is_list
Unexecuted instantiation: command.c:request_attr_is_list
Unexecuted instantiation: connection.c:request_attr_is_list
Unexecuted instantiation: dependency.c:request_attr_is_list
Unexecuted instantiation: dl_module.c:request_attr_is_list
Unexecuted instantiation: exec.c:request_attr_is_list
Unexecuted instantiation: exec_legacy.c:request_attr_is_list
Unexecuted instantiation: exfile.c:request_attr_is_list
Unexecuted instantiation: global_lib.c:request_attr_is_list
Unexecuted instantiation: main_config.c:request_attr_is_list
Unexecuted instantiation: main_loop.c:request_attr_is_list
Unexecuted instantiation: map.c:request_attr_is_list
Unexecuted instantiation: map_proc.c:request_attr_is_list
Unexecuted instantiation: module.c:request_attr_is_list
Unexecuted instantiation: module_method.c:request_attr_is_list
Unexecuted instantiation: module_rlm.c:request_attr_is_list
Unexecuted instantiation: paircmp.c:request_attr_is_list
Unexecuted instantiation: pairmove.c:request_attr_is_list
Unexecuted instantiation: password.c:request_attr_is_list
Unexecuted instantiation: pool.c:request_attr_is_list
Unexecuted instantiation: regex.c:request_attr_is_list
Unexecuted instantiation: request.c:request_attr_is_list
Unexecuted instantiation: request_data.c:request_attr_is_list
Unexecuted instantiation: snmp.c:request_attr_is_list
Unexecuted instantiation: state.c:request_attr_is_list
Unexecuted instantiation: stats.c:request_attr_is_list
Unexecuted instantiation: tmpl_dcursor.c:request_attr_is_list
Unexecuted instantiation: tmpl_eval.c:request_attr_is_list
tmpl_tokenize.c:request_attr_is_list
Line
Count
Source
364
5.34k
{
365
5.34k
  return (da == request_attr_request) ||
366
4.59k
    (da == request_attr_reply) ||
367
4.59k
    (da == request_attr_control) ||
368
4.59k
    (da == request_attr_state) ||
369
4.59k
    (da == request_attr_local);
370
5.34k
}
Unexecuted instantiation: trigger.c:request_attr_is_list
Unexecuted instantiation: trunk.c:request_attr_is_list
Unexecuted instantiation: users_file.c:request_attr_is_list
Unexecuted instantiation: util.c:request_attr_is_list
Unexecuted instantiation: virtual_servers.c:request_attr_is_list
Unexecuted instantiation: call.c:request_attr_is_list
Unexecuted instantiation: call_env.c:request_attr_is_list
Unexecuted instantiation: caller.c:request_attr_is_list
Unexecuted instantiation: catch.c:request_attr_is_list
Unexecuted instantiation: child_request.c:request_attr_is_list
Unexecuted instantiation: compile.c:request_attr_is_list
Unexecuted instantiation: condition.c:request_attr_is_list
Unexecuted instantiation: detach.c:request_attr_is_list
Unexecuted instantiation: edit.c:request_attr_is_list
Unexecuted instantiation: finally.c:request_attr_is_list
Unexecuted instantiation: foreach.c:request_attr_is_list
Unexecuted instantiation: function.c:request_attr_is_list
Unexecuted instantiation: group.c:request_attr_is_list
Unexecuted instantiation: interpret.c:request_attr_is_list
Unexecuted instantiation: interpret_synchronous.c:request_attr_is_list
Unexecuted instantiation: io.c:request_attr_is_list
Unexecuted instantiation: limit.c:request_attr_is_list
Unexecuted instantiation: load_balance.c:request_attr_is_list
Unexecuted instantiation: map_builtin.c:request_attr_is_list
Unexecuted instantiation: parallel.c:request_attr_is_list
Unexecuted instantiation: return.c:request_attr_is_list
Unexecuted instantiation: subrequest.c:request_attr_is_list
Unexecuted instantiation: switch.c:request_attr_is_list
Unexecuted instantiation: timeout.c:request_attr_is_list
Unexecuted instantiation: tmpl.c:request_attr_is_list
Unexecuted instantiation: try.c:request_attr_is_list
Unexecuted instantiation: transaction.c:request_attr_is_list
Unexecuted instantiation: xlat.c:request_attr_is_list
Unexecuted instantiation: xlat_alloc.c:request_attr_is_list
Unexecuted instantiation: xlat_builtin.c:request_attr_is_list
Unexecuted instantiation: xlat_eval.c:request_attr_is_list
xlat_expr.c:request_attr_is_list
Line
Count
Source
364
26
{
365
26
  return (da == request_attr_request) ||
366
26
    (da == request_attr_reply) ||
367
26
    (da == request_attr_control) ||
368
26
    (da == request_attr_state) ||
369
26
    (da == request_attr_local);
370
26
}
Unexecuted instantiation: xlat_func.c:request_attr_is_list
Unexecuted instantiation: xlat_inst.c:request_attr_is_list
Unexecuted instantiation: xlat_pair.c:request_attr_is_list
Unexecuted instantiation: xlat_purify.c:request_attr_is_list
Unexecuted instantiation: xlat_redundant.c:request_attr_is_list
Unexecuted instantiation: xlat_tokenize.c:request_attr_is_list
Unexecuted instantiation: json.c:request_attr_is_list
Unexecuted instantiation: jpath.c:request_attr_is_list
Unexecuted instantiation: app_io.c:request_attr_is_list
Unexecuted instantiation: channel.c:request_attr_is_list
Unexecuted instantiation: coord.c:request_attr_is_list
Unexecuted instantiation: coord_pair.c:request_attr_is_list
Unexecuted instantiation: master.c:request_attr_is_list
Unexecuted instantiation: network.c:request_attr_is_list
Unexecuted instantiation: schedule.c:request_attr_is_list
Unexecuted instantiation: thread.c:request_attr_is_list
Unexecuted instantiation: worker.c:request_attr_is_list
371
372
#ifdef __cplusplus
373
}
374
#endif