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: e4704d77bb518c7ef65ca2c4083a14960d3c1207 $
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
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 state = vp->vp_uint32;
138 } else {
139 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_bfd_packet);
140 if (vp) vp = fr_pair_find_by_da_nested(&vp->vp_group, NULL, attr_bfd_state);
141 if (vp) state = vp->vp_uint8;
142 }
143 }
144
146
147 request->reply->code = state;
148
149 request->reply->timestamp = fr_time();
150
152}
153
154
155/*
156 * recv FOO
157 */
158static fr_process_state_t const process_state_packet[] = {
159 [ FR_BFD_ADMIN_DOWN ] = {
160 .default_reply = FR_BFD_DOWN,
161 .default_rcode = RLM_MODULE_NOOP,
162 .recv = recv_generic,
163 .resume = resume_recv_bfd,
164 .section_offset = offsetof(process_bfd_sections_t, recv_admin_down),
165 },
166
167 [ FR_BFD_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_down),
173 },
174
175 [ FR_BFD_INIT ] = {
176 .default_reply = FR_BFD_UP,
177 .default_rcode = RLM_MODULE_NOOP,
178 .recv = recv_generic,
179 .resume = resume_recv_bfd,
180 .section_offset = offsetof(process_bfd_sections_t, recv_init),
181 },
182
183 [ FR_BFD_UP ] = {
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_up),
189 },
190};
191
192/*
193 * send FOO
194 */
195static fr_process_state_t const process_state_reply[] = {
196 [ FR_BFD_ADMIN_DOWN ] = {
197 .default_rcode = RLM_MODULE_NOOP,
198 .send = send_generic,
199 .resume = resume_send_generic,
200 .section_offset = offsetof(process_bfd_sections_t, send_admin_down),
201 },
202
203 [ FR_BFD_DOWN ] = {
204 .default_rcode = RLM_MODULE_NOOP,
205 .send = send_generic,
206 .resume = resume_send_generic,
207 .section_offset = offsetof(process_bfd_sections_t, send_down),
208 },
209
210 [ FR_BFD_INIT ] = {
211 .default_rcode = RLM_MODULE_NOOP,
212 .send = send_generic,
213 .resume = resume_send_generic,
214 .section_offset = offsetof(process_bfd_sections_t, send_init),
215 },
216
217 [ FR_BFD_UP ] = {
218 .default_rcode = RLM_MODULE_NOOP,
219 .send = send_generic,
220 .resume = resume_send_generic,
221 .section_offset = offsetof(process_bfd_sections_t, send_up),
222 },
223};
224
225static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
226{
227 fr_process_state_t const *state;
228 bfd_wrapper_t const *wrapper;
229
231
233 fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
234
235 request->component = "bfd";
236 request->module = NULL;
237
238 fr_assert(request->proto_dict == dict_bfd);
239
240 wrapper = (bfd_wrapper_t const *) request->packet->data;
241
242 /*
243 * If there's no packet, we must be calling the "send" routine
244 */
245 if (wrapper->type == BFD_WRAPPER_SEND_PACKET) {
247
248 UPDATE_STATE(reply);
249
250 bfd_packet_debug(request, request->reply, &request->reply_pairs, false);
251 return state->send(p_result, mctx, request);
252 }
253
255
256 UPDATE_STATE(packet);
257
258 if (!state->recv) {
259 REDEBUG("Invalid packet type (%u)", request->packet->code);
261 }
262
263 bfd_packet_debug(request, request->packet, &request->request_pairs, true);
264
265 return state->recv(p_result, mctx, request);
266}
267
268/*
269 * We send and receive the same packet types.
270 */
271#define SEND_RECV(_x, _y) \
272 { \
273 .section = SECTION_NAME("recv", _x), \
274 .actions = &mod_actions_postauth, \
275 .offset = PROCESS_CONF_OFFSET(recv_ ## _y), \
276 }, \
277 { \
278 .section = SECTION_NAME("send", _x), \
279 .actions = &mod_actions_postauth, \
280 .offset = PROCESS_CONF_OFFSET(send_ ## _y), \
281 }
282
284 SEND_RECV("Admin-Down", admin_down),
285 SEND_RECV("Down", down),
286 SEND_RECV("Init", init),
287 SEND_RECV("Up", up),
288
290};
291
292
295 .common = {
296 .magic = MODULE_MAGIC_INIT,
297 .name = "bfd",
299 MODULE_RCTX(process_rctx_t)
300 },
301 .process = mod_process,
302 .compile_list = compile_list,
303 .dict = &dict_bfd,
304 .packet_type = &attr_packet_type
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
#define UNUSED
Definition build.h:317
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:274
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:287
Specifies an attribute which must be present for the module to function.
Definition dict.h:273
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:286
#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:852
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:828
@ 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:774
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:697
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:294
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:195
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:271
static fr_process_state_t const process_state_packet[]
Definition base.c:158
#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: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_UNLANG_FAIL
Definition rcode.h:57
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:51
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
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:287
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:313
#define COMPILE_TERMINATOR
Processing sections which are allowed in this virtual server.