The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
fd_config.c
Go to the documentation of this file.
1/*
2 * This program is 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 (at
5 * 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: 97b2dc1011490b8f42839aa914d8aacf0b61074d $
19 * @file lib/bio/fd_config.c
20 * @brief BIO abstractions for configuring file descriptors.
21 *
22 * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
23 */
24
25#include <freeradius-devel/server/cf_parse.h>
26#include <freeradius-devel/server/tmpl.h>
27#include <freeradius-devel/util/perm.h>
28
29#include <freeradius-devel/bio/fd_priv.h>
30
32 { L("read-only"), O_RDONLY },
33 { L("read-write"), O_RDWR },
34 { L("ro"), O_RDONLY },
35 { L("rw"), O_RDWR },
36};
38
39static int mode_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
40{
41 int mode;
42 char const *name = cf_pair_value(cf_item_to_pair(ci));
43
45 if (mode < 0) {
46 cf_log_err(ci, "Invalid mode name \"%s\"", name);
47 return -1;
48 }
49
50 *(int *) out = mode;
51
52 return 0;
53}
54
55/** Parse "transport" and then set the subconfig
56 *
57 */
58static int common_transport_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule, fr_table_ptr_sorted_t const *transport_table, size_t transport_table_len)
59{
60 int socket_type = SOCK_STREAM;
61 conf_parser_t const *rules;
62 char const *name = cf_pair_value(cf_item_to_pair(ci));
64 CONF_SECTION *cs, *subcs;
65
66 rules = fr_table_value_by_str(transport_table, name, NULL);
67 if (!rules) {
68 cf_log_err(ci, "Invalid transport name \"%s\"", name);
69 return -1;
70 }
71
73
74 /*
75 * Find the relevant subsection. Note that we don't do anything with it, as we push a parse
76 * rule in the parent which then points to the subsection.
77 */
78 subcs = cf_section_find(cs, name, NULL);
79 if (!subcs) {
80 cf_log_perr(ci, "Failed finding transport configuration section %s { ... }", name);
81 return -1;
82 }
83
84 /*
85 * Note that these offsets will get interpreted as being offsets from base of the subsection.
86 * i.e. the parent section and the subsection have to be parsed with the same base pointer.
87 */
88 if (cf_section_rules_push(cs, rules) < 0) {
89 cf_log_perr(ci, "Failed updating parse rules");
90 return -1;
91 }
92
93 if (strcmp(name, "udp") == 0) socket_type = SOCK_DGRAM;
94
95 /*
96 * Client sockets are always connected.
97 */
98 fd_config->socket_type = socket_type;
99 *(char const **) out = name;
100
101 return 0;
102}
103
106 { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, dst_ipaddr) },
107 { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, dst_ipaddr) },
108
109 { FR_CONF_OFFSET("port", fr_bio_fd_config_t, dst_port) },
110
111 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipaddr", FR_TYPE_COMBO_IP_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
112 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
113 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
114
115 { FR_CONF_OFFSET("src_port", fr_bio_fd_config_t, src_port) },
116 { FR_CONF_OFFSET("src_port_start", fr_bio_fd_config_t, src_port_start) },
117 { FR_CONF_OFFSET("src_port_end", fr_bio_fd_config_t, src_port_end) },
118
119 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
120
121#if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
122 { FR_CONF_OFFSET("exceed_mtu", fr_bio_fd_config_t, exceed_mtu), .dflt = "yes" },
123#endif
124
125 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
126 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
127
129};
130
132 { FR_CONF_POINTER("udp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_udp_sub_config },
133
135};
136
137
139 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipaddr", FR_TYPE_COMBO_IP_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
140 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
141 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
142
143 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
144
145 { FR_CONF_OFFSET("src_port_start", fr_bio_fd_config_t, src_port_start) },
146 { FR_CONF_OFFSET("src_port_end", fr_bio_fd_config_t, src_port_end) },
147
148#if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
149 { FR_CONF_OFFSET("exceed_mtu", fr_bio_fd_config_t, exceed_mtu), .dflt = "yes" },
150#endif
151
152 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
153 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
154
156};
157
163
164
167 { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, dst_ipaddr) },
168 { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, dst_ipaddr) },
169
170 { FR_CONF_OFFSET("port", fr_bio_fd_config_t, dst_port) },
171
172 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipaddr", FR_TYPE_COMBO_IP_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
173 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
174 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
175
176 { FR_CONF_OFFSET("src_port", fr_bio_fd_config_t, src_port) },
177 { FR_CONF_OFFSET("src_port_start", fr_bio_fd_config_t, src_port_start) },
178 { FR_CONF_OFFSET("src_port_end", fr_bio_fd_config_t, src_port_end) },
179
180 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
181
182 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
183 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
184
185 { FR_CONF_OFFSET("delay_tcp_writes", fr_bio_fd_config_t, tcp_delay) },
186
188};
189
191 { FR_CONF_POINTER("tcp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_tcp_sub_config },
192
194};
195
198
199 { FR_CONF_OFFSET("permissions", fr_bio_fd_config_t, perm), .dflt = "0600", .func = cf_parse_permissions },
200
201 { FR_CONF_OFFSET("mode", fr_bio_fd_config_t, flags), .dflt = "read-write", .func = mode_parse },
202
204};
205
207 { FR_CONF_POINTER("file", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_file_sub_config },
208
210};
211
217
219 { FR_CONF_POINTER("unix", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_unix_sub_config },
220
222};
223
225 { L("file"), client_file_config },
226 { L("tcp"), client_tcp_config },
227 { L("udp"), client_udp_config },
228 { L("unix"), client_unix_config },
229};
231
232/** Parse "transport" and then set the subconfig
233 *
234 */
235static int client_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
236{
238
239 /*
240 * Unconnected UDP sockets can only take src_ipaddr, but not port, and not dst_ipaddr.
241 */
243 char const *name = cf_pair_value(cf_item_to_pair(ci));
245
246 if (strcmp(name, "udp") != 0) {
247 cf_log_err(ci, "Invalid transport for unconnected UDP socket");
248 return -1;
249 }
250
252 cf_log_perr(ci, "Failed updating parse rules");
253 return -1;
254 }
255
256 fd_config->socket_type = SOCK_DGRAM;
257 *(char const **) out = name;
258
259 return 0;
260 }
261
263
264 return common_transport_parse(ctx, out, parent, ci, rule,
266}
267
268/*
269 * Client uses src_ipaddr for our address, and ipaddr for their address.
270 */
272 { FR_CONF_OFFSET("transport", fr_bio_fd_config_t, transport), .func = client_transport_parse },
273
274 { FR_CONF_OFFSET("async", fr_bio_fd_config_t, async), .dflt = "true" },
275
277};
278
279/*
280 * Server configuration
281 *
282 * "ipaddr" is src_ipaddr
283 * There's no "dst_ipaddr" or "src_ipaddr" in the config.
284 *
285 * Files have permissions which can be set.
286 */
287
290 { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
291 { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
292
293 { FR_CONF_OFFSET("port", fr_bio_fd_config_t, src_port) },
294
295 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
296
297 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
298 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
299
300#if (defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)) || defined(IP_DONTFRAG)
301 { FR_CONF_OFFSET("exceed_mtu", fr_bio_fd_config_t, exceed_mtu), .dflt = "yes" },
302#endif
303
305};
306
308 { FR_CONF_POINTER("udp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_udp_sub_config },
309
311};
312
315 { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
316 { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
317
318 { FR_CONF_OFFSET("port", fr_bio_fd_config_t, src_port) },
319
320 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
321
322 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
323 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
324
325 { FR_CONF_OFFSET("delay_tcp_writes", fr_bio_fd_config_t, tcp_delay) },
326
328};
329
331 { FR_CONF_POINTER("tcp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_tcp_sub_config },
332
334};
335
338
339 { FR_CONF_OFFSET("permissions", fr_bio_fd_config_t, perm), .dflt = "0600", .func = cf_parse_permissions },
340
341 { FR_CONF_OFFSET("mkdir", fr_bio_fd_config_t, mkdir) },
342
344};
345
347 { FR_CONF_POINTER("file", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_file_sub_config },
348
350};
351
358
361
362 { FR_CONF_OFFSET("permissions", fr_bio_fd_config_t, perm), .dflt = "0600", .func = cf_parse_permissions },
363
364 { FR_CONF_OFFSET("mode", fr_bio_fd_config_t, flags), .dflt = "read-only", .func = mode_parse },
365
366 { FR_CONF_OFFSET("mkdir", fr_bio_fd_config_t, mkdir) },
367
368 { FR_CONF_POINTER("peercred", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_peercred_config },
369
371};
372
374 { FR_CONF_POINTER("unix", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_unix_sub_config },
375
377};
378
379/*
380 * @todo - move this to client/server config in the same struct?
381 */
383 { L("file"), server_file_config },
384 { L("tcp"), server_tcp_config },
385 { L("udp"), server_udp_config },
386 { L("unix"), server_unix_config },
387};
389
390/** Parse "transport" and then set the subconfig
391 *
392 */
393static int server_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
394{
395 int rcode;
397
398 fd_config->server = true;
399
400 rcode = common_transport_parse(ctx, out, parent, ci, rule,
402 if (rcode < 0) return rcode;
403
404 /*
405 * Automatically set the BIO type, too.
406 */
407 if (fd_config->socket_type == SOCK_DGRAM) {
409 } else {
411 }
412
413 return 0;
414}
415
416/*
417 * Server uses ipaddr for our address, and doesn't use src_ipaddr.
418 */
420 { FR_CONF_OFFSET("transport", fr_bio_fd_config_t, transport), .func = server_transport_parse },
421
422 { FR_CONF_OFFSET("async", fr_bio_fd_config_t, async), .dflt = "true" },
423
425};
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define UNUSED
Definition build.h:317
#define NUM_ELEMENTS(_t)
Definition build.h:339
int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving GID strings to uid_t values.
Definition cf_parse.c:1659
int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving permissions to a mode-t.
Definition cf_parse.c:1674
int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving UID strings to uid_t values.
Definition cf_parse.c:1644
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:658
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:612
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:284
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:690
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition cf_parse.h:339
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
Definition cf_parse.h:298
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:272
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:434
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:428
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:241
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:595
Common header for all CONF_* types.
Definition cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1593
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_parent(_cf)
Definition cf_util.h:101
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:296
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
Definition fd.h:68
@ FR_BIO_FD_INVALID
not set
Definition fd.h:64
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition fd.h:65
@ FR_BIO_FD_LISTEN
returns new fd in buffer on fr_bio_read() or fr_bio_fd_accept()
Definition fd.h:69
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
Definition fd.h:82
bool server
is this a client or a server?
Definition fd.h:86
int socket_type
SOCK_STREAM or SOCK_DGRAM.
Definition fd.h:84
Configuration for sockets.
Definition fd.h:81
const conf_parser_t fr_bio_fd_server_config[]
Definition fd_config.c:419
static conf_parser_t const client_udp_unconnected_config[]
Definition fd_config.c:158
static conf_parser_t const client_file_config[]
Definition fd_config.c:206
static const conf_parser_t server_unix_sub_config[]
Definition fd_config.c:359
static size_t server_transport_names_len
Definition fd_config.c:388
static conf_parser_t const server_unix_config[]
Definition fd_config.c:373
static const conf_parser_t server_udp_sub_config[]
Definition fd_config.c:288
static int mode_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Definition fd_config.c:39
static const conf_parser_t client_udp_sub_config[]
Definition fd_config.c:104
static const conf_parser_t server_file_sub_config[]
Definition fd_config.c:336
static const conf_parser_t client_unix_sub_config[]
Definition fd_config.c:212
static int common_transport_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule, fr_table_ptr_sorted_t const *transport_table, size_t transport_table_len)
Parse "transport" and then set the subconfig.
Definition fd_config.c:58
static const conf_parser_t client_udp_unconnected_sub_config[]
Definition fd_config.c:138
const conf_parser_t fr_bio_fd_client_config[]
Definition fd_config.c:271
static conf_parser_t const client_udp_config[]
Definition fd_config.c:131
static int server_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Parse "transport" and then set the subconfig.
Definition fd_config.c:393
static fr_table_ptr_sorted_t client_transport_names[]
Definition fd_config.c:224
static size_t client_transport_names_len
Definition fd_config.c:230
static const conf_parser_t client_file_sub_config[]
Definition fd_config.c:196
static int client_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Parse "transport" and then set the subconfig.
Definition fd_config.c:235
static conf_parser_t const client_unix_config[]
Definition fd_config.c:218
static const conf_parser_t client_tcp_sub_config[]
Definition fd_config.c:165
static conf_parser_t const server_file_config[]
Definition fd_config.c:346
static conf_parser_t const server_udp_config[]
Definition fd_config.c:307
static const conf_parser_t server_peercred_config[]
Definition fd_config.c:352
static const conf_parser_t server_tcp_sub_config[]
Definition fd_config.c:313
static size_t mode_names_len
Definition fd_config.c:37
static fr_table_num_sorted_t mode_names[]
Definition fd_config.c:31
static conf_parser_t const server_tcp_config[]
Definition fd_config.c:330
static fr_table_ptr_sorted_t server_transport_names[]
Definition fd_config.c:382
static conf_parser_t const client_tcp_config[]
Definition fd_config.c:190
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
static fr_bio_fd_config_t fd_config
static char const * name
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
An element in a lexicographically sorted array of name to ptr mappings.
Definition table.h:65
static fr_slen_t parent
Definition pair.h:845
static size_t char ** out
Definition value.h:1012