The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
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: 8e29d1ad5820e138073fda4e0387d567fb3509c9 $
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
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
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
67
68#define PROCESS_PACKET_TYPE fr_bfd_packet_code_t
69#define PROCESS_CODE_MAX FR_BFD_CODE_MAX
70#define PROCESS_PACKET_CODE_VALID FR_BFD_PACKET_CODE_VALID
71#define PROCESS_INST process_bfd_t
72
73#define PROCESS_SEND_RECV (1)
74
75#include <freeradius-devel/server/process.h>
76
77/*
78 * Debug the packet if requested.
79 */
80static void bfd_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *list, bool received)
81{
82#ifdef WITH_IFINDEX_NAME_RESOLUTION
83 char if_name[IFNAMSIZ];
84#endif
85
86 if (!packet) return;
87 if (!RDEBUG_ENABLED) return;
88
89 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 "
90#ifdef WITH_IFINDEX_NAME_RESOLUTION
91 "%s%s%s"
92#endif
93 "",
94 received ? "Received" : "Sending",
96 packet->id,
97 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
98 fr_box_ipaddr(packet->socket.inet.src_ipaddr),
99 packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
100 packet->socket.inet.src_port,
101 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
102 fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
103 packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
104 packet->socket.inet.dst_port
105#ifdef WITH_IFINDEX_NAME_RESOLUTION
106 , packet->socket.inet.ifindex ? "via " : "",
107 packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
108 packet->socket.inet.ifindex ? " " : ""
109#endif
110 );
111
112 if (received || request->parent) {
113 log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
114 } else {
115 log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
116 }
117}
118
120{
121 rlm_rcode_t rcode = RESULT_RCODE;
122 fr_pair_t *vp;
123 uint32_t state = 0;
124
126
128
129 if (rcode == RLM_MODULE_FAIL) {
130 state = FR_BFD_ADMIN_DOWN;
131 } else {
132 /*
133 * Check for a state / reply code.
134 */
135 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_packet_type);
136 if (vp) {
137 if (!PROCESS_PACKET_CODE_VALID(vp->vp_uint32)) {
138 REDEBUG("Invalid BFD packet type %u", vp->vp_uint32);
140 }
141 state = vp->vp_uint32;
142 } else {
143 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_bfd_packet);
144 if (vp) vp = fr_pair_find_by_da_nested(&vp->vp_group, NULL, attr_bfd_state);
145 if (vp) {
146 if (!PROCESS_PACKET_CODE_VALID(vp->vp_uint8)) {
147 REDEBUG("Invalid BFD state %u", vp->vp_uint8);
149 }
150 state = vp->vp_uint8;
151 }
152 }
153 }
154
155 request->reply->code = state;
156
157 request->reply->timestamp = fr_time();
158
160}
161
162
163/*
164 * recv FOO
165 */
166static fr_process_state_t const process_state_packet[] = {
167 [ FR_BFD_ADMIN_DOWN ] = {
168 .default_reply = FR_BFD_DOWN,
169 .default_rcode = RLM_MODULE_NOOP,
170 .recv = recv_generic,
171 .resume = resume_recv_bfd,
172 .section_offset = offsetof(process_bfd_sections_t, recv_admin_down),
173 },
174
175 [ FR_BFD_DOWN ] = {
176 .default_reply = FR_BFD_DOWN,
177 .default_rcode = RLM_MODULE_NOOP,
178 .recv = recv_generic,
179 .resume = resume_recv_bfd,
180 .section_offset = offsetof(process_bfd_sections_t, recv_down),
181 },
182
183 [ FR_BFD_INIT ] = {
184 .default_reply = FR_BFD_UP,
185 .default_rcode = RLM_MODULE_NOOP,
186 .recv = recv_generic,
187 .resume = resume_recv_bfd,
188 .section_offset = offsetof(process_bfd_sections_t, recv_init),
189 },
190
191 [ FR_BFD_UP ] = {
192 .default_reply = FR_BFD_UP,
193 .default_rcode = RLM_MODULE_NOOP,
194 .recv = recv_generic,
195 .resume = resume_recv_bfd,
196 .section_offset = offsetof(process_bfd_sections_t, recv_up),
197 },
198};
199
200/*
201 * send FOO
202 */
203static fr_process_state_t const process_state_reply[] = {
204 [ FR_BFD_ADMIN_DOWN ] = {
205 .default_rcode = RLM_MODULE_NOOP,
206 .send = send_generic,
207 .resume = resume_send_generic,
208 .section_offset = offsetof(process_bfd_sections_t, send_admin_down),
209 },
210
211 [ FR_BFD_DOWN ] = {
212 .default_rcode = RLM_MODULE_NOOP,
213 .send = send_generic,
214 .resume = resume_send_generic,
215 .section_offset = offsetof(process_bfd_sections_t, send_down),
216 },
217
218 [ FR_BFD_INIT ] = {
219 .default_rcode = RLM_MODULE_NOOP,
220 .send = send_generic,
221 .resume = resume_send_generic,
222 .section_offset = offsetof(process_bfd_sections_t, send_init),
223 },
224
225 [ FR_BFD_UP ] = {
226 .default_rcode = RLM_MODULE_NOOP,
227 .send = send_generic,
228 .resume = resume_send_generic,
229 .section_offset = offsetof(process_bfd_sections_t, send_up),
230 },
231};
232
233static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
234{
235 fr_process_state_t const *state;
236 bfd_wrapper_t const *wrapper;
237
239
241 fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
242
243 request->component = "bfd";
244 request->module = NULL;
245
246 fr_assert(request->proto_dict == dict_bfd);
247
248 wrapper = (bfd_wrapper_t const *) request->packet->data;
249
250 /*
251 * If there's no packet, we must be calling the "send" routine
252 */
253 if (wrapper->type == BFD_WRAPPER_SEND_PACKET) {
254
255 UPDATE_STATE(reply);
256
257 bfd_packet_debug(request, request->reply, &request->reply_pairs, false);
258 return state->send(p_result, mctx, request);
259 }
260
262
263 UPDATE_STATE(packet);
264
265 if (!state->recv) {
266 REDEBUG("Invalid packet type (%u)", request->packet->code);
268 }
269
270 bfd_packet_debug(request, request->packet, &request->request_pairs, true);
271
272 return state->recv(p_result, mctx, request);
273}
274
275/*
276 * We send and receive the same packet types.
277 */
278#define SEND_RECV(_x, _y) \
279 { \
280 .section = SECTION_NAME("recv", _x), \
281 .actions = &mod_actions_postauth, \
282 .offset = PROCESS_CONF_OFFSET(recv_ ## _y), \
283 }, \
284 { \
285 .section = SECTION_NAME("send", _x), \
286 .actions = &mod_actions_postauth, \
287 .offset = PROCESS_CONF_OFFSET(send_ ## _y), \
288 }
289
291 SEND_RECV("Admin-Down", admin_down),
292 SEND_RECV("Down", down),
293 SEND_RECV("Init", init),
294 SEND_RECV("Up", up),
295
297};
298
299
302 .common = {
303 .magic = MODULE_MAGIC_INIT,
304 .name = "bfd",
306 MODULE_RCTX(process_rctx_t)
307 },
308 .process = mod_process,
309 .compile_list = compile_list,
310 .dict = &dict_bfd,
311 .packet_type = &attr_packet_type
312};
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
#define UNUSED
Definition build.h:336
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:292
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:305
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:311
Specifies an attribute which must be present for the module to function.
Definition dict.h:291
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:304
#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:91
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:855
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:831
#define fr_time()
Definition event.c:60
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition log.h:67
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:56
@ 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:784
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:707
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
#define PROCESS_PACKET_CODE_VALID
Definition base.c:65
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:65
fr_process_module_t process_bfd
Definition base.c:301
static void bfd_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *list, bool received)
Definition base.c:80
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:203
fr_dict_attr_autoload_t process_bfd_dict_attr[]
Definition base.c:42
RESUME_FLAG(recv_bfd, UNUSED,)
Definition base.c:119
static fr_dict_t const * dict_bfd
Definition base.c:29
#define SEND_RECV(_x, _y)
Definition base.c:278
static fr_process_state_t const process_state_packet[]
Definition base.c:166
#define PROCESS_TRACE
Trace each state function as it's entered.
Definition process.h:55
module_t common
Common fields for all loadable modules.
Common public symbol definition for all process modules.
char const * fr_bfd_packet_names[FR_BFD_CODE_MAX]
Definition base.c:64
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED()
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:54
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
Definition rcode.h:57
void * data
Module's instance data.
Definition module.h:293
#define MODULE_RCTX(_ctype)
Definition module.h:259
#define MODULE_INST(_ctype)
Definition module.h:257
init
Enter the EAP-IDENTITY state.
fr_pair_t * vp
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:117
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:75
#define fr_box_ipaddr(_val)
Definition value.h:317
#define COMPILE_TERMINATOR
Processing sections which are allowed in this virtual server.