[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2 Rewrite

Rewrite is the GNU Radius extension language. Its name reflects the fact that it was originally designed to rewrite the broken request packets so they could be processed as usual (see section Rewriting Incoming Requests). Beside this basic use, however, Rewrite functions are used to control various aspects of GNU Radius functionality, such as verifying the activity of user sessions, controlling the amount of information displayed in log messages, etc (see section Interaction with Radius).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.1 Syntax Overview

The syntax of Rewrite resembles that of C. Rewrite has two basic data types: integer and string. It does not have global variables; all variables are automatic. The only exceptions are the A/V pairs from the incoming request, which are accessible to Rewrite functions via the special notation %[attr].


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.2 Quick Start

As an example, let's consider the following Rewrite function:

 
string
foo(integer i)
{
    string rc;
    if (i % 2)
        rc = "odd";
    else
        rc = "even";
    return "the number is " + rc;
}

The function takes an integer argument and returns the string ‘the number is odd’ or ‘the number is even’, depending on the value of i. This illustrates the fact that in Rewrite the addition operator is defined on the string type. The result of such operation is the concatenation of operands.

Another example is a function that adds a prefix to the User-Name attribute:

 
integer
px_add()
{
        %[User-Name] = "pfx-" + %[User-Name];
        return 0;
}

This function manipulates the contents of the incoming request; its return value has no special meaning.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.3 Interaction with Radius

A Rewrite function can be invoked in several ways, depending on its purpose. There are three major kinds of Rewrite functions:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.4 Rewriting Incoming Requests

The need for rewriting the incoming requests arises from the fact that some NASes are very particular about the information they send with the requests. There are cases when the information they send is hardly usable or even completely unusable. For example, a Cisco AS5300 terminal server used as a voice-over IP router packs a lot of information into its Acct-Session-Id attribute. Though the information stored there is otherwise relevant, it makes proper accounting impossible, since the Acct-Session-Id attributes in the start and stop packets of the same session become different, and thus Radius cannot determine the session start to which the given session stop request corresponds (see section Acct-Session-Id).

In order to cope with such NASes, GNU Radius is able to invoke a Rewrite function upon arrival of the packet and before processing it further. This function can transform the packet so that it obtains the form prescribed by RFCs and its further processing becomes possible.

For example, in the case of the AS5300 router, a corresponding Rewrite function parses the Acct-Session-Id attribute; breaks it down into fields; stores them into proper attributes, creating them if necessary; and finally replaces Acct-Session-Id with its real value, which is the same for the start and stop records corresponding to a single session. Thus all the information that came with the packet is preserved, but the packet itself is made usable for proper accounting.

A special attribute, Rewrite-Function, is used to trigger invocation of a Rewrite function. Its value is a name of the function to be invoked.

When used in a ‘naslist’ profile, the attribute causes the function to be invoked when the incoming request matches the huntgroup (see section Huntgroups). For example, to have a function fixup invoked for each packet from the NAS 10.10.10.11, the following huntgroup rule may be used:

 
DEFAULT  NAS-IP-Address = 11.10.10.11
         Rewrite-Function = "fixup"

The Rewrite-Function attribute may also be used in a ‘hints’ rule. In this case, it will invoke the function if the request matches the rule (see section Hints). For example, this ‘hints’ rule will cause the function to be invoked for each request containing the user name starting with ‘P’:

 
DEFAULT  Prefix = "P"
         Rewrite-Function = "fixup"

Note that in both cases the attribute can be used either in LHS or in RHS pairs of a rule.

The packet rewrite function must be declared as having no arguments and returning an integer value:

 
integer fixup()
{
}

The actual return value from such a function is ignored, the integer return type is just a matter of convention.

The following subsection present some examples of packet rewrite functions.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.4.1 Examples of Various Rewrite Functions

The examples found in this chapter are working functions that can be used with various existing NAS types. They are taken from the ‘rewrite’ file contained in distribution of GNU Radius.

1. Port rewriting for MAX Ascend terminal servers

Some MAX Ascend terminal servers pack additional information into the NAS-Port-Id attribute. The port number is constructed as XYYZZ, where X = 1 for digital, X = 2 for analog, YY is the line number (1 for first PRI/T1/E1, 2 for second, and so on), and ZZ is the channel number (on the PRI or channelized T1/E1).

The following rewrite functions are intended to compute the integer port number in the range (1 .. portcnt), where portcnt represents the real number of physical ports available on the NAS. Such a port number can be used, for example, to create a dynamic pool of IP addresses (see section Framed-IP-Address).

 
/*
 * decode MAX port number
 * input: P        --  The value of NAS-Port-Id attribute
 *        portcnt  --  number of physical ports on the NAS
 */
integer
max_decode_port(integer P, integer portcnt)
{
    if (P > 9999) {
        integer s, l, c;

        s = P / 10000;
        l = (P - (10000 * s))/100; 
        c = P - ((10000 * s) + (100 * l)); 
        return (c-1) + (l-1) * portcnt;
    }
    return P;
}

/*
 * Interface function for MAX terminal server with 23 ports.
 * Note that it saves the received NAS-Port-Id attribute in
 * the Orig-NAS-Port-Id attribute. The latter must be
 * defined somewhere in the dictionary
 */
integer
max_fixup()
{
    %[Orig-NAS-Port-Id] = %[NAS-Port-Id];
                                  # Preserve original data
    %[NAS-Port-Id] = max_decode_port(%[NAS-Port-Id], 23);
    return 0;
}

2. Session ID parsing for Cisco AS 5300 series

Cisco VOIP IOS encodes a lot of other information into its Acct-Session-Id. The pieces of information are separated by ‘/’ characters. The part of Acct-Session-Id up to the first ‘/’ character is the actual session ID.

On the other hand, its accounting packets lack NAS-Port-Id, though they may contain the vendor-specific pair with code 2 (vendor PEC 9), which is a string in the form ‘ISDN 9:D:999’ (‘9’ represents any decimal digit). The number after the last ‘:’ character can be used as a port number.

The following code parses Acct-Session-Id attribute and stores the information it contains in various other attributes, generates a normal Acct-Session-Id, and attempts to generate a NAS-Port-Id attribute.

 
/* 
 * The port rewriting function for Cisco AS5300 used for
 * VoIP. This function is used to generate NAS-Port-Id pair
 * on the basis of vendor-specific pair 2. If the latter is
 * in the form "ISDN 9:D:999" (where each 9 represents a
 * decimal digit), then the function returns the number
 * after the last colon. This is used as a port number.
 */
integer
cisco_pid(string A)
{
    if (A =~ 
        ".*\([0-9][0-9]*\):
         [A-Z0-9][A-Z0-9]*:\([0-9][0-9]*\)") {
        return (integer)\2;
    }
    return -1;
}

/*
 * This function parses the packed session id.
 * The actual sid is the number before the first slash
 * character.  Other possibly relevant fields are also
 * parsed out and saved in the Voip-* A/V pairs. The latter
 * should be defined somewhere in the dictionary.
 * Note that the regular expression in this example
 * spans several lines for readability. It should be on one 
 * line in real file.
 */
string
cisco_sid(string S)
{
   if (S =~ "\(.[^/]*\)/[^/]*/[^/]*/\([^/]*\)/\([^/]*\)/
             \([^/]*\)/\([^/]*\)/\([^/]*\)/\([^/]*\)
             /\([^/]*\).*") {
        %[Voip-Connection-ID] = \2;
        %[Voip-Call-Leg-Type] = \3;
        %[Voip-Connection-Type] = \4;
        %[Voip-Connect-Time] = \5;
        %[Voip-Disconnect-Time] = \6;
        %[Voip-Disconnect-Cause] = \7;
        %[Voip-Remote-IP] = \8;
        return \1;
   } 
   return S;
}

/*
 * Normalize cisco AS5300 packets
 */
integer
cisco_fixup()
{
    integer pid;

    if ((pid = cisco_pid(%[Cisco-PRI-Circuit])) != -1) {
        if (*%[NAS-Port-Id])
            %[Orig-NAS-Port-Id] = %[NAS-Port-Id];
        %[NAS-Port-Id] = pid;
    }
    if (*%[Acct-Session-Id]) {
        %[Orig-Acct-Session-Id] = %[Acct-Session-Id];
        %[Acct-Session-Id] = cisco_sid(%[Acct-Session-Id]);
    }
    return 0;
}

3. User-name rewriting for NT machines

Users coming from Windows NT machines often authenticate themselves as ‘NT_DOMAIN\username’. The following function selects the user-name part and stores it in the User-Name attribute:

 
integer
login_nt(string uname)
{
    integer i;
        
    if ((i = index(uname, '\\')) != -1)
        return substr(uname, i+1, -1);
    return uname;
}

integer
nt_rewrite()
{
    %[Orig-User-Name] = %[User-Name];
    %[User-Name] = login_nt(%[User-Name]);
    return 0;
}

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.5 Login Verification Functions

A login verification function is invoked to process the output from the NAS. This process is described in Multiple Login Checking. The function to be invoked for given NAS is defined by a function flag in the ‘raddb/nastypes’ or ‘raddb/naslist’ file (see section NAS Types — ‘raddb/nastypes). It must be defined as follows:

Function Template: integer check (string str, string name, integer pid, string sid)

Its arguments are:

str

Input string. If the query method is finger, this is the string of output received from the NAS with trailing newline stripped off. If the query method is snmp, it is the received variable value converted to its string representation.

name

User name.

pid

Port ID of the session.

sid

Session ID.

The function should return non-0 if its arguments match the user's session, and 0 otherwise.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.5.1 Examples of Login Verification Functions

As an example, let's consider the function for analyzing a line of output from a standard UNIX finger service. In each line of finger output the first field contains the user name; the third field, the The function must return 1 if the three fields match the input user name and port and session IDs:

 
integer
check_unix(string str, string name, integer pid, string sid)
{
    return field(str, 1) == name
           && field(str, 3) == pid
           && field(str, 7) == sid;
}

The next example is a function to analyze a line of output from an SNMP query returning a user name. This function must return 1 if the entire input line matches the user name:

 
integer
check_username(string str, string name, integer pid, string sid)
{
    return str == name;
}

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.6 Attribute Creation Functions

These are the functions used to create Radius reply attributes. An attribute creation function can take any number of arguments. The type of its return is determined by the type of Radius attribute the value will be assigned to. To invoke the function, write its name in the A/V pair of the RHS in the ‘raddb/users’ file, e.g.:

 
DEFAULT Auth-Type = SQL
        Service-Type = Framed-User,
            Framed-IP-Address = "=get_ip_addr(10.10.10.1)"

The function get_ip_addr will be invoked after successful authentication and it will be passed the IP 10.10.10.1 as its argument. An example of a useful function that can be invoked this way is

 
integer
get_ip_address(integer base)
{
    return base + %[NAS-Port-Id] - %[NAS-Port-Id]/16;
}

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.7 Logging Hook Functions

A logging hook functions should be declared as follows:

Function Template: string hook (integer reqtype, string nasid, integer reqid)
reqtype

Type of the request. It can be converted to string using request_code_string function (see section Rewrite Built-in Functions).

nasid

NAS identifier from ‘raddb/naslist’, or its host name if not declared there

reqid

Request identifier.

Notice that the hook function shall not produce any side effects, in particular it shall not modify the incoming request in any way.

Following is an example prefix hook function that formats the incoming request data:

 
string
compat_log_prefix(integer reqtype, string nas, integer id)
{
        string result;

        return "(" + request_code_string(reqtype) + " "
                   + nas + " " + (string)id + " " + %[User-Name] + ")";
}

Here is a sample log produced by radiusd before and after enabling this function:

 
Auth.notice: Login OK [jsmith]
…
Auth.notice: (AUTHREQ nas-2 251 jsmith): Login OK [jsmith]

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8 Full Syntax Description


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8.1 Rewrite Data Types

There are only two data types: integer and string, the two being coercible to each other in the sense that a string can be coerced to an integer if it contains a valid ASCII representation of a decimal, octal, or hex number, and an integer can always be coerced to a string, the result of such coercion being the ASCII string that is the decimal representation of the number.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8.2 Rewrite Symbols

A symbol is a lexical token. The following symbols are recognized:

Arithmetical operators

These are ‘+’, ‘-’, ‘*’, ‘/’ representing the basic arithmetical operations, and ‘%’ meaning remainder.

Comparison operators

These are: ‘==’, ‘!=’, ‘<’, ‘<=’, ‘>’, ‘>=’ with the same meaning they have in C. Special operators are provided for regular-expression matching. The binary operator ‘=~’ returns true if its left-hand-side operand matches the regular expression on its right-hand side (see section Regular Expressions). ‘!~’ returns true if its left-hand-side operand does not match the regexp on its right-hand side. The right-hand-side operand of ‘!~’ or ‘=~’ must be a literal string, i.e., the regular expression must be known at compile time.

Unary operators

The unary operators are ‘-’ and ‘+’ for unary plus and minus, ‘!’ for boolean negation, and ‘*’ for testing for the existence of an attribute.

Boolean operators

These are ‘&&’ and ‘||’.

Parentheses ‘(’ and ‘)

These are used to change the precedence of operators, to introduce type casts (type coercions), to declare functions, and to pass actual arguments to functions.

Curly braces (‘{’ and ‘}’)

These are used to delimit blocks of code.

Numbers

Numbers follow the usual C convention for integers. A number consisting of a sequence of digits is taken to be octal if it begins with ‘0’ (digit zero), and decimal otherwise. If the sequence of digits is preceded by ‘0x’ or ‘0X’, it is taken to be a hexadecimal integer.

IP Numbers

IP numbers are represented by a standard numbers-and-dots notation. IP numbers do not constitute a separate data type, rather they are in all respects similar to initeger numbers.

Characters

These follow the usual C convention for characters, i.e., they consist either of an ASCII character itself or of its value, enclosed in a pair of singlequotes. The character value begins with ‘\’ (backslash) and consists either of three octal or of two hexadecimal digits. A character does not form a special data type; it is represented internally by an integer.

Quoted strings

These follow slightly modified C conventions for strings. A string is a sequence of characters surrounded by double quotes, as in ‘"..."’. In a string, the double quote character ‘"’ must be preceeded by a backslash ‘\’. A ‘\’ and an immediately following newline are ignored. Following escape sequences have special meaning:

\a

Audible bell character (ASCII 7)

\b

Backspace (ASCII 8)

\e

Escape character (ASCII 27)

\f

Form feed (ASCII 12)

\n

Newline (ASCII 10)

\r

Carriage return (ASCII 13)

\t

Horizontal tab (ASCII 9)

\\

Backslash

\ooo

(‘o’ represents an octal digit) A character whose ASCII value is represented by the octal number ‘ooo’.

\xHH
\XHH

(‘H’ represents a hex digit) A character whose ASCII value is represented by the hex number ‘HH’.

\(

Two characters ‘\(’.

\)

Two characters ‘\)’.

If the character following the backslash is not one of those specified, the backslash is ignored.

Attribute values

The incoming request is passed implicitly to functions invoked via the Rewrite-Function attribute. It is kept as an associative array, whose entries can be accessed using the following syntax:

 
%[attribute-name]’
‘%[attribute-name]’ ‘(n)

The first form returns the value of the attribute attribute-name. Here attribute-name should be a valid Radius dictionary name (see section Dictionary of Attributes — ‘raddb/dictionary).

The second form returns the value of the nth attribute of type attribute-name. The index n is counted from zero, so

 
        %[attribute-name](0)

is equivalent to

 
        %[attribute-name]
Identifiers

Identifiers represent functions and variables. These are described in the next sub-subsection.

Regexp group references

A sequence of characters in the form

 
\number

refers to the contents of parenthesized group number number obtained as a result of the last executed ‘=~’ command. The regexp group reference has always string data type. For example:

 
string
basename(string arg)
{
    if (arg =~ ".*/\(.*\)\..*")
        return \1;
    else
        return arg;
}

This function strips from arg all leading components up to the last slash character, and all trailing components after the last dot character. It returns arg unaltered if it does not contain slashes and dots. It is roughly analogous to the system basename utility.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8.3 Rewrite Identifiers

A valid identifier is a string of characters meeting the following requirements:

  1. It starts with either a lower- or an uppercase letter of the Latin alphabet or either of the following symbols: ‘_’, ‘$’.
  2. It consists of alphanumeric characters, underscores(‘_’), and dollar signs (‘$’).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8.4 Rewrite Declarations

Function declarations

A Rewrite function is declared as follows:

 
type function-name (parameter-list)

where type specifies the return type of the function, function-name declares the symbolic name of the function, and parameter-list declares the formal parameters to the function. It is a comma-separated list of declarations in the form

 
type parm-name

type being the parameter type, and parm-name being its symbolic name. Both function-name and parm-name should be valid identifiers.

Variable declarations

There are no global variables in Rewrite. All variables are local. The local variables are declared right after the opening curly brace (‘{’) and before any executable statements. The declaration syntax is

 
type ident_list ;

Here ident_list is either a valid Rewrite identifier or a comma-separated list of such identifiers.

Note that, unlike in C, no assignments are allowed in variable declarations.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8.5 Rewrite Statements

The Rewrite statements are: expressions, assignments, conditional statements, and return statements. A statement is terminated by a semicolon.

Expressions

An expression is one of the following:

Type coercion

The type coercion is like a type cast in C. Its syntax is

 
(type)ident

The result of type coercion is as follows:

type

Variable type

Resulting conversion

integer

integer

No conversion. This results in the same integer value.

integer

string

If the string value of the variable is a valid ASCII representation of the integer number (either decimal, octal, or hex), it is converted to the integer; otherwise the result of the conversion is undefined.

string

integer

The ASCII representation (in decimal) of the integer number.

string

string

No conversion. This results in the same string value.

Assignment

An assignment is

 
ident = expression ;

The variable ident is assigned the value of expression.

Function calls

These take the form

 
ident ( arg-list )

where ident is the identifier representing the function, and arg-list is a comma-separated list of expressions supplying actual arguments to the function. The number of the expressions must correspond exactly to the number of formal parameters in the function definition. The function that ident references can be either a compiled function or a built-in function.

delete’ statement

The ‘delete’ statement is used to delete an attribute or attributes from the incoming request. Its syntax is:

 
delete attribute-name;
delete attribute-name(n);

The first variant deletes all the attributes of the given type. The second variant deletes only the nth occurrence of the matching attribute.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8.6 Regular Expressions

Rewrite uses POSIX regular expressions (See (regex)Top section `Regular Expression Library' in Regular Expression Library, for the detailed description of these).

You control the exact type of regular expressions by the use of the pragmatic comment regex. Its syntax is as follows:

 
#pragma regex option-list

Option-list is a whitespace-separated list of options. Each option is one of the following words prefixed with ‘+’ or ‘-’:

extended

Use POSIX extended regular expression syntax when interpreting regular expressions.

icase

Do not differentiate case. Subsequent regular expression comparisons will be case insensitive.

newline

Match-any-character operators don't match a newline.

A non-matching list (‘[^...]’) not containing a newline does not match a newline.

Match-beginning-of-line operator (‘^’) matches the empty string immediately after a newline.

Match-end-of-line operator (‘$’) matches the empty string immediately before a newline.

Prefixing an option with ‘+’ means to enable the corresponding behavior. Prefixing it with ‘-’ means to disable it. Thus, the following statement:

 
#pragma regex +extended +icase

will enable extended POSIX regular expressions using case-insensitive comparison.

Using the following comment:

 
#pragma regex -extended 

will switch to the basic POSIX regular expressions.

The settings of a regex pragmatic comment remain in force up to the end of current source file, or to the next regex comment, whichever occurs first.

For compatibility with previous versions, GNU Radius uses the following defaults:

 
#pragma regex -extended -icase -newline

i.e. all regular expressions are treated as basic POSIX, comparison is case-sensitive.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2.8.7 Rewrite Built-in Functions

The following built-in functions are provided:

Function: integer length (string s)

Returns the length of the string s.

 
length("string") ⇒ 6
Function: integer index (string s, integer c)

Returns the index of the first occurrence of the character c in the string s. Returns -1 if no such occurrence is found.

 
index("/raddb/users", 47) ⇒ 0

index("/raddb/users", 45) ⇒ -1
Function: integer rindex (string s, integer i)

Returns the index of the last occurrence of the character c in the string s. Returns -1 if no such occurrence is found.

 
rindex("/raddb/users", 47) ⇒ 6
Function: string substr (string s, integer start, integer length)

Returns the substring of s of length at most length starting at position start.

 
substr("foo-bar-baz", 3, 5) ⇒ "-bar-"

All character positions in strings are counted from 0.

Function: string field (string buffer, integer n)

This function regards the buffer argument as consisting of fields separated with any amount of whitespace. It extracts and returns the nth field. n is counted from 1.

 
field("GNU's not UNIX", 1) ⇒ "GNU's"
field("GNU's not UNIX", 2) ⇒ "not"
field("GNU's not UNIX", 3) ⇒ "UNIX"
field("GNU's not UNIX", 4) ⇒ ""
Function: integer logit (string msg)

Outputs its argument to the Radius log channel info. Returns 0. For debugging purposes.

Function: integer inet_aton (string str)

Converts the Internet host address str from the standard numbers-and-dots notation into the equivalent integer in host byte order.

 
inet_aton("127.0.0.1") ⇒ 2130706433
Function: string inet_ntoa (integer ip)

Converts the Internet host address ip given in host byte order to a string in standard numbers-and-dots notation.

 
inet_ntoa(2130706433) ⇒ "127.0.0.1"
Function: integer htonl (integer n)

Converts the integer n, regarded as long, from host to network byte order.

Function: integer ntohl (integer n)

Converts the integer n, regarded as long, from network to host byte order.

Function: integer htons (integer n)

Converts the integer n, regarded as short, from host to network byte order.

Function: integer ntohs (integer n)

Converts the integer n, regarded as short, from network to host byte order.

Function: string gsub (string regex, string repl, string str)

For each substring matching the regular expression regex in the string str, substitute the string repl, and return the resulting string.

 
gsub("s","S","strings")
    ⇒ "StringS"
gsub("[0-9][0-9]*","N","28 or 29 days")
    ⇒ "N or N days"
gsub("[()'\"]","/","\"a\" (quoted) 'string'")
    ⇒ "/a/ /quoted/ /string/"
Function: string qprn (string str)

Replace all non-printable characters in string S by their corresponding hex value preceeded by a percent sign. Return the resulting string. Printable are alphabetical characters, decimal digits and dash (‘-’). Other characters are considered non-printable. For example:

 
qprn("a string/value") ⇒ "a%20string%2Fvalue"
Function: string quote_string (string str)

Replace all non-printable characters in string str by their three-digit octal code prefixed with a backslash, or by their C escape notation, as appropriate. Non-printable characters depend on the locale settings. For example, suppose that the current locale is set to ISO-8859-1 (a so called “Latin-1” character set) and ∗ represents a tab character. Then:

 
quote_string("François contains non∗printable chars")
  ⇒ "Fran\347ois contains non\tprintable chars"
Function: string unquote_string (string str)

Replace C escape notations in string str with corresponding characters using current locale. For example, for ISO-8859-1 locale:

 
unquote_string("Fran\347ois") ⇒ "François"
Function: string toupper (string str)

Returns the copy of the string str with all alphabetical characters converted to upper case. For example:

 
toupper("a-string") ⇒ "A-STRING"
Function: string tolower (string str)

Returns the copy of the string str with all alphabetical characters converted to lower case. For example:

 
tolower("A-STRING") ⇒ "a-string"
Function: string request_code_string (integer code)

Converts integer RADIUS request code to its textual representation as per RFC 3575. This function is useful in logging hooks (see section Logging hooks).

 
request_code_string(4) ⇒ "Accounting-Request"

Native Language Support

The native language support is provided via the functions described below. These functions are interfaces to GNU gettext library. For the information about general concepts and principles of Native Language Support, please refer to GNU gettext utilities: (gettext)Top section `gettext' in GNU gettext utilities.

The default current textual domain is ‘radius’.

Function: string textdomain (string domain)

Sets the new value for the current textual domain. This domain is used by the functions gettext and ngettext. Returns the name of the previously used domain.

Function: string gettext (string msgid)
Function: string _ (string msgid)

The function returns the translation of the string msgid if it is available in the current domain. If it is not available, the argument itself is returned.

The second form of this function provides a traditional shortcut notation.

For a detailed description of the GNU gettext interface, refer to (gettext)Interface to gettext section `Interface to gettext' in GNU gettext utilities.

Function: string dgettext (string domain, string msgid)

Returns the translation of the string msgid if it is available in the domain domain. If it is not available, the argument itself is returned.

Function: string ngettext (string msgid_singular, string msgid_plural, integer number)

The ngettext function is used to translate the messages that have singular and plural forms. The msgid_singular parameter must contain the singular form of the string to be converted. It is also used as the key for the search in the catalog. The msgid_plural parameter is the plural form. The parameter number is used to determine the plural form. If no message catalog is found msgid_singular is returned if number == 1, otherwise msgid_plural.

For a detailed description of the GNU gettext interface for the plural translation, refer to (gettext)Plural forms section `Additional functions for plural forms' in GNU gettext utilities.

Function: string dngettext (string domain, string msg_sing, string msg_plur, integer number)

Similar to ngettext, but searches translation in the given domain.

Request Accessors

The following functions are used to read some internal fields of a RADIUS request.

Function: Integer request_source_ip ()

Returns source IP address of the currently processed request. This function can be used to add NAS-IP-Address attribute to the requests lacking one, e.g.:

 
integer
restore_nas_ip()
{
        if (!*%[NAS-IP-Address])
                %[NAS-IP-Address] = request_source_ip();
        return 0;
}
Function: Integer request_source_port ()

Returns the source UDP port.

Function: Integer request_id ()

Returns the request identifier.

Function: Integer request_code ()

Returns the request code.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Sergey Poznyakoff on December, 6 2008 using texi2html 1.78.