From 14911b39574d1ca442a8ffd55e9ba5a5708fab46 Mon Sep 17 00:00:00 2001 From: jcarneal Date: Sat, 14 Oct 2000 16:00:16 +0000 Subject: [PATCH] Committing file for Alan Curry documenting the RLM code interface. --- doc/module_interface | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 doc/module_interface diff --git a/doc/module_interface b/doc/module_interface new file mode 100644 index 0000000..4087eb4 --- /dev/null +++ b/doc/module_interface @@ -0,0 +1,137 @@ + +RLM Module Interface (for developers) +------------------------------------- + +Section 1 - overview + +The fundamental concepts of the rlm interface are module, instance, and +component. + +A module is a chunk of code that knows how to deal with a particular kind of +database, or perhaps a collection of similar databases. Examples: + + - rlm_sql contains code for talking to MySQL or Postgres, and for mapping + RADIUS records onto SQL tables. + - rlm_unix contains code for making radiusd fit in well on unix-like + systems, including getpw* authentication and utmp/wtmp-style logging. + +An instance specifies the actual location of a collection data that can be +used by a module. Examples: + + - /var/log/radutmp + - "the MySQL database on bigserver.theisp.com.example" + +A module can have up to 4 (soon to be 5? 6?) components which act on RADIUS +requests at different stages. The components are: + + - authorization: check that a user exists, decide on an authentication + method or proxy realm, and possibly apply some attributes to be returned + in the reply packet. + - authentication: verify that the password is correct. + - preaccounting: decide whether to proxy the request, and possibly add + attributes that should be included in any logs + - accounting: record the request in the log + - checksimul (AVAILABLE AS EXTERNAL PATCH): count the number of active + sessions for the user + - postproxyauth (DOES NOT EXIST YET): filter attributes from a reply to a + proxied request + +A module declares which components it supports by putting function pointers +in its "module_t rlm_*" structure. + +Section 2 - Module configuration: + +The administrator requests the creation of a module instance by adding it +inside the modules{} block in radiusd.conf. The instance definition looks +like this: + + module_name [instance_name] { + param1 = value1 + param2 = value2 + param3 = value3 + ... + } + +The module_name is used to load the module. To see the names of the available +modules, look for the rlm_*.so files in $installprefix/lib. The module_name +is that, minus the rlm_ and the .so. + +instance_name is an identifier for distinguishing multiple instances of the +same module. If you are only loading a module once, you can leave out the +instance_name and it will be assumed to be the same as the module_name. + +The parameters inside the module block are passed without interpretation to +the module and generally point to the exact location of a database or enable +optional features of the module. Each module should document what parameters +it accepts and what they do. + +For each Access-Request that comes to the server, the authorize{} block is +called. Then one of the authtype{} blocks from authenticate{} is called, +depending on the Auth-Type attribute that was chosen by authorize{}. If +authorize{} set the Proxy-To-Realm attribute, then proxying takes over and +the local authenticate{} phase is skipped. + +For each Accounting-Request that comes to the server, the preacct{} block is +called, followed by the accounting{} block. accounting{} is skipped if +preacct{} sets Proxy-To-Realm. + +For an explanation of what "calling" a config block means, see +README.failover. + +Section 3 - The lifetime of a module + +When the server is starting up, or reinitializing itself as a result of a +SIGHUP, it reads the modules{} section. Each configured module will be loaded +and its init() method will be called. + + int init(void) + +The init() method should take care of +any setup that is not tied to a specific instance. It will only be called +once, even if there are multiple instances configured. + +For each configured instance, after the init() method, the instantiate() +method is called. It is given a handle to the configuration block holding its +parameters, which it can access with cf_section_parse(). + + int instantiate(CONF_SECTION *cs, void **instance) + +The instantiate() function should look up options in the config section, and +open whatever files or network connections are necessary for the module to do +its job. It also should create a structure holding all of the persistent +variables that are particular to this instance (open file descriptors, +configured pathnames, etc.) and store a pointer to it in *instance. That +void * becomes a handle (some would call it a "cookie") representing this +instance. The instance handle is passed as a parameter in all subsequent +calls to the module's methods, so they can determine which database they are +supposed to act on. + +The authorize(), authenticate(), preaccounting(), and accounting() functions +are all called the same way: + + int authorize(void *instance, REQUEST *request) + int authenticate(void *instance, REQUEST *request) + int preaccounting(void *instance, REQUEST *request) + int accounting(void *instance, REQUEST *request) + +they each receive the instance handle and the request, and are expected to +act on the request using the database pointed to by the instance handle +(which was set by the instantiate() function). + +When the server is being shut down (as the first part of SIGHUP for example) +detach() is called for each module instance. + + int detach(void *instance) + +The detach() method should release whatever resources were allocated by the +instantiate() method. + +After all instances are detached, the destroy() method is called. + + int destroy(void) + +It should release resources that were acquired by the init() method. + +See also src/modules/README for more information. + +--Alan Curry -- 2.1.4