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: 1e63dbf0a51538de406cfde701fbcc1d640356ca $
19 * @file src/process/bfd/base.c
20 * @brief BFD processing.
21 *
22 * @copyright 2023 Network RADIUS SAS (legal@networkradius.com)
23 */
24#include <freeradius-devel/server/protocol.h>
25#include <freeradius-devel/util/debug.h>
26#include <freeradius-devel/bfd/bfd.h>
27#include "bfd/session.h"
28
29static fr_dict_t const *dict_bfd;
30
33 { .out = &dict_bfd, .proto = "bfd" },
34 { NULL }
35};
36
40
43 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_bfd},
44
45 { .out = &attr_bfd_packet, .name = "Packet", .type = FR_TYPE_STRUCT, .dict = &dict_bfd},
46 { .out = &attr_bfd_state, .name = "Packet.state", .type = FR_TYPE_UINT8, .dict = &dict_bfd},
47
48 { NULL }
49};
50
51#define SECTION(_x) \
52 CONF_SECTION *recv_ ## _x; \
53 CONF_SECTION *send_ ## _x
54
55typedef struct {
56 uint64_t nothing; // so that the next field isn't at offset 0
57
58 SECTION(admin_down);
59 SECTION(down);
63
69
70#define PROCESS_PACKET_TYPE fr_bfd_packet_code_t
71#define PROCESS_CODE_MAX FR_BFD_CODE_MAX
72#define PROCESS_PACKET_CODE_VALID FR_BFD_PACKET_CODE_VALID
73#define PROCESS_INST process_bfd_t
74
75#define PROCESS_SEND_RECV (1)
76
77#include <freeradius-devel/server/process.h>
78
79/*
80 * Debug the packet if requested.
81 */
82static void bfd_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *list, bool received)
83{
84#ifdef WITH_IFINDEX_NAME_RESOLUTION
85 char if_name[IFNAMSIZ];
86#endif
87
88 if (!packet) return;
89 if (!RDEBUG_ENABLED) return;
90
91 log_request(L_DBG, L_DBG_LVL_1, request, __FILE__, __LINE__, "%s %s ID %d from %s%pV%s:%i to %s%pV%s:%i "
92#ifdef WITH_IFINDEX_NAME_RESOLUTION
93 "%s%s%s"
94#endif
95 "",
96 received ? "Received" : "Sending",
98 packet->id,
99 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
100 fr_box_ipaddr(packet->socket.inet.src_ipaddr),
101 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
102 packet->socket.inet.src_port,
103 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
104 fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
105 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
106 packet->socket.inet.dst_port
107#ifdef WITH_IFINDEX_NAME_RESOLUTION
108 , packet->socket.inet.ifindex ? "via " : "",
109 packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
110 packet->socket.inet.ifindex ? " " : ""
111#endif
112 );
113
114 if (received || request->parent) {
115 log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
116 } else {
117 log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
118 }
119}
120
122{
123 rlm_rcode_t rcode = *p_result;
124 fr_pair_t *vp;
125 uint32_t state = 0;
126
128
130
131 if (rcode == RLM_MODULE_FAIL) {
132 state = FR_BFD_ADMIN_DOWN;
133 } else {
134 /*
135 * Check for a state / reply code.
136 */
137 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_packet_type);
138 if (vp) {
139 state = vp->vp_uint32;
140 } else {
141 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_bfd_packet);
142 if (vp) vp = fr_pair_find_by_da_nested(&vp->vp_group, NULL, attr_bfd_state);
143 if (vp) state = vp->vp_uint8;
144 }
145 }
146
148
149 request->reply->code = state;
150
151 request->reply->timestamp = fr_time();
152
154}
155
156
157/*
158 * recv FOO
159 */
160static fr_process_state_t const process_state_packet[] = {
161 [ FR_BFD_ADMIN_DOWN ] = {
162 .default_reply = FR_BFD_DOWN,
163 .rcode = RLM_MODULE_NOOP,
164 .recv = recv_generic,
165 .resume = resume_recv_bfd,
166 .section_offset = offsetof(process_bfd_sections_t, recv_admin_down),
167 },
168
169 [ FR_BFD_DOWN ] = {
170 .default_reply = FR_BFD_DOWN,
171 .rcode = RLM_MODULE_NOOP,
172 .recv = recv_generic,
173 .resume = resume_recv_bfd,
174 .section_offset = offsetof(process_bfd_sections_t, recv_down),
175 },
176
177 [ FR_BFD_INIT ] = {
178 .default_reply = FR_BFD_UP,
179 .rcode = RLM_MODULE_NOOP,
180 .recv = recv_generic,
181 .resume = resume_recv_bfd,
182 .section_offset = offsetof(process_bfd_sections_t, recv_init),
183 },
184
185 [ FR_BFD_UP ] = {
186 .default_reply = FR_BFD_UP,
187 .rcode = RLM_MODULE_NOOP,
188 .recv = recv_generic,
189 .resume = resume_recv_bfd,
190 .section_offset = offsetof(process_bfd_sections_t, recv_up),
191 },
192};
193
194/*
195 * send FOO
196 */
197static fr_process_state_t const process_state_reply[] = {
198 [ FR_BFD_ADMIN_DOWN ] = {
199 .rcode = RLM_MODULE_NOOP,
200 .send = send_generic,
201 .resume = resume_send_generic,
202 .section_offset = offsetof(process_bfd_sections_t, send_admin_down),
203 },
204
205 [ FR_BFD_DOWN ] = {
206 .rcode = RLM_MODULE_NOOP,
207 .send = send_generic,
208 .resume = resume_send_generic,
209 .section_offset = offsetof(process_bfd_sections_t, send_down),
210 },
211
212 [ FR_BFD_INIT ] = {
213 .rcode = RLM_MODULE_NOOP,
214 .send = send_generic,
215 .resume = resume_send_generic,
216 .section_offset = offsetof(process_bfd_sections_t, send_init),
217 },
218
219 [ FR_BFD_UP ] = {
220 .rcode = RLM_MODULE_NOOP,
221 .send = send_generic,
222 .resume = resume_send_generic,
223 .section_offset = offsetof(process_bfd_sections_t, send_up),
224 },
225};
226
227static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
228{
229 fr_process_state_t const *state;
230 bfd_wrapper_t const *wrapper;
231
233
235 fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
236
237 request->component = "bfd";
238 request->module = NULL;
239
240 fr_assert(request->dict == dict_bfd);
241
242 wrapper = (bfd_wrapper_t const *) request->packet->data;
243
244 /*
245 * If there's no packet, we must be calling the "send" routine
246 */
247 if (wrapper->type == BFD_WRAPPER_SEND_PACKET) {
249
250 UPDATE_STATE(reply);
251
252 bfd_packet_debug(request, request->reply, &request->reply_pairs, false);
253 return state->send(p_result, mctx, request);
254 }
255
257
258 UPDATE_STATE(packet);
259
260 if (!state->recv) {
261 REDEBUG("Invalid packet type (%u)", request->packet->code);
263 }
264
265 bfd_packet_debug(request, request->packet, &request->request_pairs, true);
266
267 return state->recv(p_result, mctx, request);
268}
269
270/*
271 * We send and receive the same packet types.
272 */
273#define SEND_RECV(_x, _y) \
274 { \
275 .section = SECTION_NAME("recv", _x), \
276 .actions = &mod_actions_postauth, \
277 .offset = PROCESS_CONF_OFFSET(recv_ ## _y), \
278 }, \
279 { \
280 .section = SECTION_NAME("send", _x), \
281 .actions = &mod_actions_postauth, \
282 .offset = PROCESS_CONF_OFFSET(send_ ## _y), \
283 }
284
286 SEND_RECV("Admin-Down", admin_down),
287 SEND_RECV("Down", down),
288 SEND_RECV("Init", init),
289 SEND_RECV("Up", up),
290
292};
293
294
297 .common = {
298 .magic = MODULE_MAGIC_INIT,
299 .name = "bfd",
300 .inst_size = sizeof(process_bfd_t),
301 },
302 .process = mod_process,
303 .compile_list = compile_list,
304 .dict = &dict_bfd,
305};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
@ FR_BFD_INIT
Definition bfd.h:146
@ FR_BFD_ADMIN_DOWN
Definition bfd.h:144
@ FR_BFD_UP
Definition bfd.h:147
@ FR_BFD_DOWN
Definition bfd.h:145
static bool init
Definition fuzzer.c:41
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
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:854
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:612
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:830
@ 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
@ BFD_WRAPPER_SEND_PACKET
Definition session.h:127
@ BFD_WRAPPER_RECV_PACKET
Definition session.h:126
uint32_t type
Definition session.h:142
@ 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
unsigned int uint32_t
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_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition pair.c:770
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
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition base.c:179
static const virtual_server_compile_t compile_list[]
Definition base.c:205
#define PROCESS_PACKET_CODE_VALID
Definition base.c:64
fr_dict_autoload_t process_bfd_dict[]
Definition base.c:32
static fr_dict_attr_t const * attr_bfd_packet
Definition base.c:38
process_bfd_sections_t sections
Definition base.c:67
fr_process_module_t process_bfd
Definition base.c:296
bool unused
Definition base.c:65
static void bfd_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *list, bool received)
Definition base.c:82
static fr_dict_attr_t const * attr_bfd_state
Definition base.c:39
static fr_process_state_t const process_state_reply[]
Definition base.c:197
fr_dict_attr_autoload_t process_bfd_dict_attr[]
Definition base.c:42
static fr_dict_t const * dict_bfd
Definition base.c:29
#define SEND_RECV(_x, _y)
Definition base.c:273
static fr_process_state_t const process_state_packet[]
Definition base.c:160
RESUME_NO_MCTX(recv_bfd)
Definition base.c:121
#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_bfd_packet_names[FR_BFD_CODE_MAX]
Definition base.c:63
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG_ENABLED()
Definition radclient.h:49
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:42
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:48
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
Definition rcode.h:50
size_t inst_size
Size of the module's instance data.
Definition module.h:203
void * data
Module's instance data.
Definition module.h:271
fr_pair_t * vp
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
uint64_t nothing
Definition base.c:56
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define talloc_get_type_abort_const
Definition talloc.h:282
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
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:78
#define fr_box_ipaddr(_val)
Definition value.h:294
#define COMPILE_TERMINATOR
Processing sections which are allowed in this virtual server.