28 RCSID(
"$Id: f3758b4968e0cde22c54acff241974e6ef04c7f0 $")
30 #include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
31 #include <freeradius-devel/server/base.h>
32 #include <freeradius-devel/server/command.h>
33 #include <freeradius-devel/server/dl_module.h>
34 #include <freeradius-devel/server/global_lib.h>
35 #include <freeradius-devel/server/modpriv.h>
36 #include <freeradius-devel/server/process.h>
37 #include <freeradius-devel/server/protocol.h>
38 #include <freeradius-devel/server/virtual_servers.h>
40 #include <freeradius-devel/io/application.h>
41 #include <freeradius-devel/io/master.h>
42 #include <freeradius-devel/io/listen.h>
188 char const *
namespace;
189 char *module_name, *p, *end;
193 "virtual_servers_init MUST be called before reading virtual server config");
195 namespace = cf_pair_value(cp);
196 module_name = talloc_strdup(ctx,
namespace);
201 for (p = module_name, end = module_name + talloc_array_length(module_name) - 1;
203 p++)
if (*p ==
'-') *p =
'_';
221 cf_log_err(ci,
"Process module is invalid - missing namespace dictionary");
225 cf_data_add(server_cs, mi,
"process_module",
false);
254 static inline CC_HINT(always_inline)
262 for (i = 0; list[i].
name != NULL; i++) {
266 cf_log_err(cs,
"Failed registering processing section name %s for %s",
292 char const *
namespace = cf_pair_value(cp);
315 cf_log_perr(ci,
"Failed bootstrapping process module");
351 char const *inst_name;
352 char *qual_inst_name;
357 "virtual_servers_init MUST be called before reading virtual server config");
360 cf_log_err(server_cs,
"No 'namespace' set for virtual server");
361 cf_log_err(server_cs,
"Please add 'namespace = <protocol>' inside of the 'server %s { ... }' section",
428 if (!inst_name) inst_name =
mod_name;
430 qual_inst_name = talloc_asprintf(NULL,
"%s.%s",
cf_section_name2(server_cs), inst_name);
434 cf_log_err(listener_cs,
"Failed loading listener");
441 cf_log_perr(ci,
"Failed parsing config for listener");
448 cf_data_add(listener_cs, mi,
"proto_module",
false);
473 cf_log_err(server_cs,
"virtual server %s MUST contain a 'namespace' option",
505 if (!server_cs)
return NULL;
523 if (!cd)
return NULL;
544 if (!cd)
return NULL;
576 if (ci)
cf_log_err(ci,
"Can't find virtual server \"%s\"", virtual_server);
584 if (ci)
cf_log_err(ci,
"No namespace found in virtual server \"%s\"", virtual_server);
588 if (
dict !=
namespace) {
591 "Expected virtual server \"%s\" to be of namespace \"%s\", got namespace \"%s\"",
597 if (
out) *
out = server_cs;
612 REDEBUG(
"server_cs does not contain virtual server data");
629 if (!server_cnt)
return 0;
631 for (i = 0; i < server_cnt; i++) {
643 .help =
"Show virtual server settings.",
648 .parent =
"show server",
651 .help =
"Show the list of virtual servers loaded in the server.",
703 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.af);
710 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.scope_id);
724 }
else if (ret > 0) {
831 for (i = 0; list[i].
name != NULL; i++) {
841 void *instruction = NULL;
845 DEBUG3(
"Warning: Skipping %s %s { ... } as it was not found.",
846 list[i].
name, list[i].name2);
850 if ((instance) && !list[i].dont_cache) {
862 cf_log_err(bad,
"Duplicate sections are forbidden.");
863 cf_log_err(subcs,
"Previous definition occurs here.");
867 rcode =
unlang_compile(subcs, list[i].component, rules, &instruction);
868 if (rcode < 0)
return -1;
874 if (!list[i].dont_cache) {
877 if (list[i].instruction > 0) {
878 *(
void **) (((
uint8_t *) instance) + list[i].instruction) = instruction;
902 cf_log_err(subcs,
"Invalid '%s { ... }' section, it must have a name", list[i].
name);
910 if (bad)
goto forbidden;
913 if (rcode < 0)
return -1;
937 if (ret != 0)
return ret;
975 ERROR(
"Processing sections cannot allow \"*\"");
980 ERROR(
"Processing sections cannot allow \"%s *\"",
1015 if (entry)
return entry->
methods;
1026 if (!entry)
return NULL;
1055 cf_log_err(subcs,
"Invalid '%s { ... }' section, it must have a name", subcs_name);
1066 cf_log_debug(subcs,
"Creating %s = %s", da->name, name2);
1075 PERROR(
"Failed adding section value");
1093 cf_log_err(cs,
"Expected 'values <name> { ... }'");
1099 cf_log_err(cs,
"No such attribute \"%s\"", ref);
1104 cf_log_err(cs,
"Cannot define value for structural attribute \"%s\"", ref);
1113 cf_log_err(cs,
"Cannot define value for 'string' attribute \"%s\"", ref);
1119 char const *attr, *
value;
1139 cf_log_err(ci,
"Definition is not in 'name = value' format");
1154 len = talloc_array_length(
value) - 1;
1166 cf_log_err(cp,
"Unexpected text after value");
1195 char const *attr, *
value;
1205 if (strcmp(attr,
"values") == 0) {
1214 cf_log_err(ci,
"Definition is not in 'tlv name { ... }' format");
1233 cf_log_err(ci,
"Definition is not in 'type name' format");
1243 cf_log_err(ci,
"Invalid data type '%s'", attr);
1257 cf_log_err(ci,
"Local variable '%s' duplicates a dictionary attribute.",
value);
1262 cf_log_err(ci,
"Local variable '%s' duplicates a previous local attribute.",
value);
1274 if (!subcs)
return -1;
1292 if (!cs)
return dict_def;
1296 cf_log_err(cs,
"Failed allocating local dictionary");
1325 DEBUG2(
"#### Opening listener interfaces ####");
1328 for (i = 0; i < server_cnt; i++) {
1330 size_t j, listener_cnt;
1333 listener_cnt = talloc_array_length(listeners);
1335 for (j = 0; j < listener_cnt; j++) {
1357 "Opening %s I/O interface failed",
1403 size_t i, server_cnt;
1409 ERROR(
"No virtual servers configured");
1415 DEBUG2(
"#### Instantiating listeners ####");
1418 PERROR(
"Failed registering radmin commands for virtual servers");
1422 for (i = 0; i < server_cnt; i++) {
1424 size_t j, listener_cnt;
1432 listener_cnt = talloc_array_length(listeners);
1435 if (!
dict)
return -1;
1439 for (j = 0; j < listener_cnt; j++) {
1448 "Failed instantiating listener");
1460 "Failed instantiating process module");
1503 if ((strcmp(
name,
"listen") == 0) || (strcmp(
name,
"client") == 0))
continue;
1513 if (!name2) name2 =
"";
1576 PERROR(
"%s", __FUNCTION__);
1580 PERROR(
"%s", __FUNCTION__);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
module_t common
Common fields provided by all modules.
fr_app_open_t open
Callback to allow the fr_app_t to build an fr_listen_t and register it with the scheduler so we can r...
Describes a new application (protocol)
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
static int invalid_type(fr_type_t type)
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
#define CONF_PARSER_TERMINATOR
char const * name2
Second identifier for CONF_SECTION.
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
@ CONF_FLAG_OK_MISSING
OK if it's missing.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
#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
Defines a CONF_PAIR to C data type mapping.
Internal data that is associated with a configuration section.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_section_find_in_parent(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a section in the lineage of a CONF_SECTION which matches a specific name1 and optionally name2.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
#define cf_log_err(_cf, _fmt,...)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_data_find(_cf, _type, _name)
#define cf_data_remove(_cf, _type, _name)
Remove an item from a parent by type and name.
#define cf_item_next(_ci, _prev)
#define cf_log_perr(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define cf_data_find_in_parent(_cf, _type, _name)
#define cf_log_warn(_cf, _fmt,...)
#define cf_log_debug(_cf, _fmt,...)
fr_command_register_hook_t fr_command_register_hook
char const * parent
e.g. "show module"
int unlang_compile(CONF_SECTION *cs, rlm_components_t component, tmpl_rules_t const *rules, void **instruction)
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
int fr_dict_enum_add_name(fr_dict_attr_t *da, char const *name, fr_value_box_t const *value, bool coerce, bool replace)
Add a value name.
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
#define fr_dict_autofree(_to_free)
fr_dict_t * fr_dict_protocol_alloc(fr_dict_t const *parent)
Allocate a new local dictionary.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
int fr_dict_enum_add_name_next(fr_dict_attr_t *da, char const *name)
Add an name to an integer attribute hashing the name for the integer value.
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
#define fr_dict_autoload(_to_load)
int fr_dict_attr_add(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, int attr, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
Specifies an attribute which must be present for the module to function.
Values of the encryption flags.
Specifies a dictionary which must be loaded/loadable for the module to function.
Value of an enumerated attribute.
char const * dl_module_inst_name_from_conf(CONF_SECTION *conf)
Avoid boilerplate when setting the module instance name.
@ DL_MODULE_TYPE_PROTO
Protocol module.
@ DL_MODULE_TYPE_PROCESS
protocol processor.
dl_module_t const *_CONST module
Module.
void *_CONST data
Module instance's parsed configuration.
CONF_SECTION *_CONST conf
Module's instance configuration.
dl_module_common_t const *_CONST common
Symbol exported by the module, containing its public functions, name and behaviour control flags.
int global_lib_instantiate(void)
Walk the tree of libraries and instantiate any which are pending.
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
fr_socket_t * app_io_addr
for tracking duplicate sockets
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
Stores all information relating to an event list.
static char const * mod_name(fr_listen_t *li)
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_GROUP
A grouping of other attributes.
static const virtual_server_compile_t compile_list[]
static const conf_parser_t config[]
fr_dict_t const ** dict
pointer to local fr_dict_t *
module_method_t process
Process packets.
virtual_server_compile_t const * compile_list
list of processing sections
module_t common
Common fields for all loadable modules.
Common public symbol definition for all process modules.
static char const * proto(int id, int porttype)
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
#define fr_rb_alloc(_ctx, _data_cmp, _data_free)
Allocs a red black tree.
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
The main red black tree structure.
fr_dict_attr_t const * request_attr_request
dl_module_inst_t * dl_inst
Structure containing the module's instance data, configuration, and dl handle.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Optional arguments passed to vp_tmpl functions.
static const uchar sc[16]
int modules_thread_instantiate(TALLOC_CTX *ctx, module_list_t const *ml, fr_event_list_t *el)
Creates per-thread instance data for modules which need it.
module_instance_t * module_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name)
Allocate a new module and add it to a module list for later bootstrap/instantiation.
int module_conf_parse(module_instance_t *mi, CONF_SECTION *mod_conf)
Parse the configuration associated with a module.
void modules_thread_detach(module_list_t const *ml)
Remove thread-specific data for a given module list.
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
module_list_t * module_list_alloc(TALLOC_CTX *ctx, char const *name)
Allocate a new module list.
int unlang_module_push(rlm_rcode_t *p_result, request_t *request, module_instance_t *module_instance, module_method_t method, bool top_frame)
Push a module or submodule onto the stack for evaluation.
if(!subtype_vp) goto fail
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
static fr_event_list_t * el
Generic representation of a grouping.
int af
AF_INET, AF_INET6, or AF_UNIX.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_const(_msg)
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
#define fr_type_is_structural(_x)
#define fr_type_is_leaf(_x)
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
static size_t char ** out
static int server_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
fr_dict_autoload_t virtual_server_dict_autoload[]
fr_process_module_t const * process_module
Public interface to the process_mi.
static const conf_parser_t server_on_read_config[]
bool listen_record(fr_listen_t *li)
Record that we're listening on a particular IP / port.
fr_dict_t const * virtual_server_dict_by_child_ci(CONF_ITEM const *ci)
Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server.
int virtual_servers_bootstrap(CONF_SECTION *config)
Load protocol modules and call their bootstrap methods.
const conf_parser_t virtual_servers_on_read_config[]
static int server_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
CONF_SECTION * virtual_server_find(char const *name)
Return virtual server matching the specified name.
static int namespace_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
int virtual_server_compile_sections(CONF_SECTION *server, virtual_server_compile_t const *list, tmpl_rules_t const *rules, void *instance)
Compile sections for a virtual server.
fr_dict_attr_autoload_t virtual_server_dict_attr_autoload[]
CONF_SECTION * virtual_server_by_child(CONF_SECTION *section)
Find a virtual server using one of its sections.
int virtual_servers_open(fr_schedule_t *sc)
Open all the listen sockets.
int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Wrapper for the config parser to allow pass1 resolution of virtual servers.
static module_list_t * process_modules
List of process modules we've loaded.
int virtual_server_has_namespace(CONF_SECTION **out, char const *virtual_server, fr_dict_t const *namespace, CONF_ITEM *ci)
Verify that a given virtual_server exists and is of a particular namespace.
static fr_dict_t const * dict_freeradius
const conf_parser_t virtual_servers_config[]
static CONF_SECTION * virtual_server_root
CONF_SECTION holding all the virtual servers.
static const conf_parser_t server_config[]
CONF_SECTION * server_cs
The server section.
fr_virtual_listen_t ** listeners
Listeners in this virtual server.
static fr_virtual_server_t ** virtual_servers
Top level structure holding all virtual servers.
static fr_dict_t const * virtual_server_local_dict(CONF_SECTION *server_cs, fr_dict_t const *dict_def)
static int add_compile_list(CONF_SECTION *cs, virtual_server_compile_t const *compile_list, char const *name)
virtual_server_method_t const * virtual_server_section_methods(char const *name1, char const *name2)
Find the component for a section.
static fr_dict_attr_t const * attr_auth_type
int virtual_server_section_attribute_define(CONF_SECTION *server_cs, char const *subcs_name, fr_dict_attr_t const *da)
Define a values for Auth-Type attributes by the sections present in a virtual-server.
unlang_action_t virtual_server_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Set the request processing function.
void virtual_servers_thread_detach(void)
Free thread-specific data for all process modules and listeners.
static fr_cmd_table_t cmd_table[]
fr_dict_t const * virtual_server_dict_by_cs(CONF_SECTION const *server_cs)
Return the namespace for the virtual server specified by a config section.
int virtual_servers_init(void)
Performs global initialisation for the virtual server code.
static fr_rb_tree_t * listen_addr_root
module_instance_t * process_mi
The process_* module for a virtual server.
static int define_server_attrs(CONF_SECTION *cs, fr_dict_t *dict, fr_dict_attr_t *parent, fr_dict_attr_t const *root)
int virtual_server_section_register(virtual_server_compile_t const *entry)
Register name1 / name2 as allowed processing sections.
static int8_t listen_addr_cmp(void const *one, void const *two)
Compare listeners by app_io_addr.
static module_list_t * proto_modules
List of proto modules we've loaded.
static fr_rb_tree_t * server_section_name_tree
Lookup allowed section names for modules.
fr_listen_t * listen_find_any(fr_listen_t *li)
See if another global listener is using a particular IP / port.
static int _virtual_servers_atexit(UNUSED void *uctx)
static int listen_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
fr_dict_t const * virtual_server_dict_by_name(char const *virtual_server)
Return the namespace for the named virtual server.
int virtual_servers_instantiate(void)
Instantiate all the virtual servers.
static int8_t server_section_name_cmp(void const *one, void const *two)
int virtual_servers_free(void)
static int namespace_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
module_instance_t * proto_mi
The proto_* module for a listen section.
int virtual_servers_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Perform thread instantiation for all process modules and listeners.
static int cmd_show_server_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
static int define_server_values(CONF_SECTION *cs, fr_dict_attr_t *parent)
fr_app_t const * proto_module
Public interface to the proto_mi.
char const * name
module method name1 which is allowed in this section
virtual_server_method_t const * methods
list of module methods which are allowed in this section
char const * name
Name of the processing section, such as "recv" or "send".
char const * name2
Second name, such as "Access-Request".
size_t offset
where the CONF_SECTION pointer is written
char const * name2
module method name2 which is allowed in this section
Processing sections which are allowed in this virtual server.
Module methods which are allowed in virtual servers.