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: 2786f0f76ea3fe506835d49f19d26fc0ba380221 $
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
117 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
118
119 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
120 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
121
123};
124
126 { FR_CONF_POINTER("udp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_udp_sub_config },
127
129};
130
131
133 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipaddr", FR_TYPE_COMBO_IP_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
134 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
135 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
136
137 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
138
139 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
140 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
141
143};
144
150
151
154 { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, dst_ipaddr) },
155 { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, dst_ipaddr) },
156
157 { FR_CONF_OFFSET("port", fr_bio_fd_config_t, dst_port) },
158
159 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipaddr", FR_TYPE_COMBO_IP_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
160 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
161 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
162
163 { FR_CONF_OFFSET("src_port", fr_bio_fd_config_t, src_port) },
164
165 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
166
167 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
168 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
169
170 { FR_CONF_OFFSET("delay_tcp_writes", fr_bio_fd_config_t, tcp_delay) },
171
173};
174
176 { FR_CONF_POINTER("tcp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_tcp_sub_config },
177
179};
180
183
184 { FR_CONF_OFFSET("permissions", fr_bio_fd_config_t, perm), .dflt = "0600", .func = cf_parse_permissions },
185
186 { FR_CONF_OFFSET("mode", fr_bio_fd_config_t, flags), .dflt = "read-write", .func = mode_parse },
187
189};
190
192 { FR_CONF_POINTER("file", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_file_sub_config },
193
195};
196
202
204 { FR_CONF_POINTER("unix", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_unix_sub_config },
205
207};
208
210 { L("file"), client_file_config },
211 { L("tcp"), client_tcp_config },
212 { L("udp"), client_udp_config },
213 { L("unix"), client_unix_config },
214};
216
217/** Parse "transport" and then set the subconfig
218 *
219 */
220static int client_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
221{
223
224 /*
225 * Unconnected UDP sockets can only take src_ipaddr, but not port, and not dst_ipaddr.
226 */
228 char const *name = cf_pair_value(cf_item_to_pair(ci));
230
231 if (strcmp(name, "udp") != 0) {
232 cf_log_err(ci, "Invalid transport for unconnected UDP socket");
233 return -1;
234 }
235
237 cf_log_perr(ci, "Failed updating parse rules");
238 return -1;
239 }
240
241 fd_config->socket_type = SOCK_DGRAM;
242 *(char const **) out = name;
243
244 return 0;
245 }
246
248
249 return common_transport_parse(ctx, out, parent, ci, rule,
251}
252
253/*
254 * Client uses src_ipaddr for our address, and ipaddr for their address.
255 */
257 { FR_CONF_OFFSET("transport", fr_bio_fd_config_t, transport), .func = client_transport_parse },
258
259 { FR_CONF_OFFSET("async", fr_bio_fd_config_t, async), .dflt = "true" },
260
262};
263
264/*
265 * Server configuration
266 *
267 * "ipaddr" is src_ipaddr
268 * There's no "dst_ipaddr" or "src_ipaddr" in the config.
269 *
270 * Files have permissions which can be set.
271 */
272
275 { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
276 { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
277
278 { FR_CONF_OFFSET("port", fr_bio_fd_config_t, src_port) },
279
280 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
281
282 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
283 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
284
286};
287
289 { FR_CONF_POINTER("udp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_udp_sub_config },
290
292};
293
296 { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
297 { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, fr_bio_fd_config_t, src_ipaddr) },
298
299 { FR_CONF_OFFSET("port", fr_bio_fd_config_t, src_port) },
300
301 { FR_CONF_OFFSET("interface", fr_bio_fd_config_t, interface) },
302
303 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, recv_buff) },
304 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, fr_bio_fd_config_t, send_buff) },
305
306 { FR_CONF_OFFSET("delay_tcp_writes", fr_bio_fd_config_t, tcp_delay) },
307
309};
310
312 { FR_CONF_POINTER("tcp", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_tcp_sub_config },
313
315};
316
319
320 { FR_CONF_OFFSET("permissions", fr_bio_fd_config_t, perm), .dflt = "0600", .func = cf_parse_permissions },
321
322 { FR_CONF_OFFSET("mkdir", fr_bio_fd_config_t, mkdir) },
323
325};
326
328 { FR_CONF_POINTER("file", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_file_sub_config },
329
331};
332
339
342
343 { FR_CONF_OFFSET("permissions", fr_bio_fd_config_t, perm), .dflt = "0600", .func = cf_parse_permissions },
344
345 { FR_CONF_OFFSET("mode", fr_bio_fd_config_t, flags), .dflt = "read-only", .func = mode_parse },
346
347 { FR_CONF_OFFSET("mkdir", fr_bio_fd_config_t, mkdir) },
348
349 { FR_CONF_POINTER("peercred", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_peercred_config },
350
352};
353
355 { FR_CONF_POINTER("unix", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) server_unix_sub_config },
356
358};
359
360/*
361 * @todo - move this to client/server config in the same struct?
362 */
364 { L("file"), server_file_config },
365 { L("tcp"), server_tcp_config },
366 { L("udp"), server_udp_config },
367 { L("unix"), server_unix_config },
368};
370
371/** Parse "transport" and then set the subconfig
372 *
373 */
374static int server_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
375{
376 int rcode;
378
379 fd_config->server = true;
380
381 rcode = common_transport_parse(ctx, out, parent, ci, rule,
383 if (rcode < 0) return rcode;
384
385 /*
386 * Automatically set the BIO type, too.
387 */
388 if (fd_config->socket_type == SOCK_DGRAM) {
390 } else {
392 }
393
394 return 0;
395}
396
397/*
398 * Server uses ipaddr for our address, and doesn't use src_ipaddr.
399 */
401 { FR_CONF_OFFSET("transport", fr_bio_fd_config_t, transport), .func = server_transport_parse },
402
403 { FR_CONF_OFFSET("async", fr_bio_fd_config_t, async), .dflt = "true" },
404
406};
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define UNUSED
Definition build.h:315
#define NUM_ELEMENTS(_t)
Definition build.h:337
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:1617
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:1632
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:1602
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:596
#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:268
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:674
#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:323
#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:282
#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:256
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:418
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
#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:579
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:1028
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:684
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:664
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
#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:400
static conf_parser_t const client_udp_unconnected_config[]
Definition fd_config.c:145
static conf_parser_t const client_file_config[]
Definition fd_config.c:191
static const conf_parser_t server_unix_sub_config[]
Definition fd_config.c:340
static size_t server_transport_names_len
Definition fd_config.c:369
static conf_parser_t const server_unix_config[]
Definition fd_config.c:354
static const conf_parser_t server_udp_sub_config[]
Definition fd_config.c:273
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:317
static const conf_parser_t client_unix_sub_config[]
Definition fd_config.c:197
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:132
const conf_parser_t fr_bio_fd_client_config[]
Definition fd_config.c:256
static conf_parser_t const client_udp_config[]
Definition fd_config.c:125
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:374
static fr_table_ptr_sorted_t client_transport_names[]
Definition fd_config.c:209
static size_t client_transport_names_len
Definition fd_config.c:215
static const conf_parser_t client_file_sub_config[]
Definition fd_config.c:181
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:220
static conf_parser_t const client_unix_config[]
Definition fd_config.c:203
static const conf_parser_t client_tcp_sub_config[]
Definition fd_config.c:152
static conf_parser_t const server_file_config[]
Definition fd_config.c:327
static conf_parser_t const server_udp_config[]
Definition fd_config.c:288
static const conf_parser_t server_peercred_config[]
Definition fd_config.c:333
static const conf_parser_t server_tcp_sub_config[]
Definition fd_config.c:294
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:311
static fr_table_ptr_sorted_t server_transport_names[]
Definition fd_config.c:363
static conf_parser_t const client_tcp_config[]
Definition fd_config.c:175
@ 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:851
static size_t char ** out
Definition value.h:997