Go to the first, previous, next, last section, table of contents.


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 NAS-Port-Id attribute. The port number is constructed as XYYZZ, where X = 1 for digital, X = 2 for analog, YY is line number (1 for first PRI/T1/E1, 2 for second, so on), and ZZ = 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 port number can be used, for example, with Add-Port-To-IP-Address attribute (see section Add-Port-To-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 `/' character. The part of Acct-Session-Id up to 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 the string in the form `ISDN 9:D:999' (`9' represents a 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 normal Acct-Session-Id and attempts to generate 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.
     * Please 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. Username rewriting for NT machines.

Users coming from Windows NT machines often authenticate themselves as `NT_DOMAIN\username'. The following function selects the username 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;
    }


Go to the first, previous, next, last section, table of contents.