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

12.2.12 Sample Radtest Program

As an example, let's consider radauth program (see section radauth). Its main purpose is to send authentication request to the remote server, analyze its reply and if it is positive, send an appropriate accounting record, thereby initiating user's session. Optionally, the script should also be able to send a lone accounting record.

In the discussion below, we will show and explain subsequent parts of the script text. For the ease of explanation, each line of program text will be prepended by its ordinal line number.

Parsing command line options

The script begins as follows:

  1 #! /usr/bin/radtest -f
  3 while getopt "n:s:P:hv"
  4 begin
  5   case $OPTVAR in
  6   "-n") NASIP = $OPTARG 
  7   "-s") SID = $OPTARG 
  8   "-P") PID = $OPTARG 
  9   "-v") set -v

It is a pragmatic comment informing shell that it should run radtest in order to interpret the program.


This line starts option processing loop. Getopt (see section getopt) in line 3 analyzes each subsequent command line argument and if it is an option checks whether it matches one of the option letters defined in its first argument. The option letter will be returned in OPTVAR variable, its argument (if any) – in OPTARG variable.

4 – 8

OPTARG value is analyzed using case statement. Lines 6 – 8 preserve OPTARG values in appropriate variables for later use. NASIP will be used as the value of NAS-IP-Address attribute, SID is the session id (Acct-Session-Id attribute), and PID is the port number (for NAS-Port-Id attribute.


This line sets ‘-v’ option to the radtest interpreter (see section Invoking radtest).

The next piece of code handles ‘-h’ and erroneous options:

 10   "-h") begin
 11           print <<-EOT
 12            usage: radauth [OPTIONS] [COMMAND] login [password]
 13            Options are:
 14            -v         Print verbose descriptions of what is being done
 15            -n IP      Set NAS IP address
 16            -s SID     Set session ID
 17            -P PORT    Set NAS port number
 18            COMMAND is one of:
 19            auth       Send only Access-Request (default)
 20            acct       Send Access-Request. If successfull, send
 21                       accounting start request
 22            start      Send accounting start request
 23            stop       Send accounting stop request
 24            EOT
 25           exit 0
 26         end
 27   ".*") begin
 28           print "Unknown option: " $OPTVAR "\n"
 29           exit 1
 30         end
 31   end
 32 end
10 – 26

Print short description and exit, if the program is given ‘-h’. Notice that ‘here document’ syntax is used to print the text (See section Character Strings, for its description). The leading whitespace in lines 12 to 24 is composed of tabulation characters (ASCII 9), not usual space characters (ASCII 32), as required by ‘<<-’ construct.

27 – 30

These lines handle unrecognized options.


Closes case statement started on line 5


Closes compound statement started on line 4

Checking Command Line Consistency

 34 shift ${OPTIND}-1
 36 if $# > 3
 37 begin
 38         print "Wrong number of arguments."
 39         print "Try radauth -h for more info"
 40         exit 1
 41 end

OPTIND keeps the ordinal number of the first non-optional argument. This line shifts off all the options processed by getopt, so that the first non-optional argument may be addressed by $1 notation. Notice use of curly braces to solve minus ambiguity (see minus-ambiguity).

36 – 41

At this point we may have at most three arguments: command, user name, and password. If there are more, display the diagnostic message and exit the program.

Next piece of code:

 43 case $1 in
 44 "auth|acct|start|stop") begin
 45                           COMMAND=$1
 46                           shift 1
 47                         end
 48 ".*")   COMMAND="auth"
 49 end
 51 LOGIN=${1:?User name is not specified. Try radauth -h for more info.}
 53 if ${NASIP:-} = ""
 54         NASIP=$SOURCEIP
 56 LIST = ( User-Name = $LOGIN NAS-IP-Address = $NASIP )
43 – 48

Check if a command is given. If so, store command name in the variable COMMAND and shift arguments by one, so login becomes argument $1. Otherwise, assume ‘auth’ command.


If the user login name is supplied, store it into LOGIN variable. Otherwise, print diagnostic message and exit.

53 – 54

Provide a default value for NASIP variable from the built-in variable SOURCEIP (see section Built-in Variables)


The variable LIST will hold the list of A/V pairs to be sent to the server. This line initializes it with a list of two A/V pairs: User-Name and NAS-IP-Address.

Defining Accounting Function

Accounting function will be used to send accounting requests to the server. It is supposed to take a single argument: an avlist of A/V pairs to be sent to the server.

 58 'acct'
 59 begin
 60   if ${SID:-} = ""
 61     input "Enter session ID: " SID
 62   if ${PID:-} = ""
 63     input "Enter NAS port ID: " PID
 64   send acct Accounting-Request $1 + \
            (Acct-Session-Id = $SID NAS-Port-Id = $PID)
58 – 59

These lines start the function definition. Notice quoting of the function name (‘acct’): it is necessary because it coincides with a reserved keyword (see section Reserved Keywords).

60 – 61

If the value of SID (session ID) is not supplied, prompt the user to input it.

62 – 63

If the value of PID (port ID) is not supplied, prompt the user to input it.


Send accounting request. The list of A/V pairs to send is formed by concatenating Acct-Session-Id and NAS-Port-Id attributes to the function's first argument.

The final part of acct function analyzes the reply from the server:

 65   if $REPLY_CODE != Accounting-Response
 66   begin
 67     print "Accounting failed.\n"
 68     exit 1  
 69   end
 70   print "Accounting OK.\n"
 71   exit 0
 72 end

Notice, that acct never returns. Instead it exits with an error code indicating success or failure.

Defining Authentication Function

The purpose of the authentication function auth is to send an Access-Request to the server and perform some actions based on its reply.

The function will take three arguments:


The list of A/V pairs to include in the request.


User password.


This argument indicates whether accounting request must be sent after successful authentication. String ‘yes’ means to send the accounting request, ‘no’ means not to send it.

The function is not expected to return. Instead it should exit to the shell with an appropriate error code.

 74 'auth'
 75 begin
 76   send auth Access-Request $1 + (User-Password = $2)
74 – 75

Begin the function definition. Notice quoting of the function name (‘auth’): it is necessary because it coincides with a reserved keyword (see section Reserved Keywords).


Send the initial authentication request. The list of A/V pairs is formed by appending User-Password pair to the list given by the first argument to the function.

The rest of the function analyzes the reply from the server and takes appropriate actions. Notice that if the server replies with an Access-Challenge packet, we will have to send subsequent authentication requests, so this piece of code is enclosed within a while loop.

First, the function handles Access-Accept and Access-Reject replies:

 77   while 1
 78   begin
 79     if $REPLY_CODE = Access-Accept
 80     begin
 81       print "Authentication passed. " + $REPLY[Reply-Message*] + "\n"
 82       if ${3:-no} = no
 83         exit 0
 84       'acct'($1 + ( Acct-Status-Type = Start ))
 85     end else if $REPLY_CODE = Access-Reject
 86     begin
 87       print "Authentication failed. " + $REPLY[Reply-Message*] + "\n"
 88       break

Begin an “endless” while loop. It will eventually be exited either using break, or using exit (see below).

79 – 84

Hanlde Access-Accept replies:


Print the reply message. Notice the use of ‘*’ to print all the instances of Reply-Message attribute from the reply packet (see section Accessing Elements of A/V Pair Lists).

82 – 83

If the third argument is missing or is a string ‘no’, exit indicating success (see section Dereferencing Variables).


Otherwise, call acct function to perform accounting. The A/V pairs included in the accounting request are formed by adding Acct-Status-Type attribute to the list given by the first argument to the function.

85 – 88

Handle Access-Reject replies. Print the reply message and break from the loop.

Next piece of code deals with Access-Challenge replies. For simplicity we assume that such replies always carry user menus (See section Login Menus — ‘raddb/menus, for the description of these). So, upon receiving an Access-Challenge we should print out the menu, read the users selection and send back an Access-Request to the server. This part is the only one that actually continues the loop at line 77.

 89     end else if $REPLY_CODE = Access-Challenge
 90     begin
 91       print $REPLY[Reply-Message*]
 92       input 
 93       send auth Access-Request \
 94         (User-Name = $LOGIN User-Password = $INPUT \
             State = $REPLY[State])

Print the menu contents carrieb by Reply-Message attributes. There may be several instances of the attribute, hence the use of ‘*’ to concatenate their values together.


Read the input from the user. The input will be stored in INPUT variable. See section Built-in Primitives, for the description of input statement.

93 – 94

Send an Access-Request packet with three attributes. User-Password contains the user reply, State contains the menu state from the server reply packet.

Final part of the function:

 95     end else begin
 96       print "Authentication failed. Reply code " + $REPLY_CODE + "\n"
 97       break
 98     end
 99   end
100   exit 1
101 end
95 – 98

Handle unknown reply codes.


Closes the while loop started on line 77.


Exit to the shell indicating failure. This statement will be reached only if a break is executed either on line 88 or on line 97.


Closes function definition started on lines 74 – 75

Final Part of Radauth Program

The final part selects an action based on the user command and executes it. It is equivalent to the main function in a C program:

103 case ${COMMAND} in
104 "auth")   'auth'($LIST, ${2:&Password: }, no)
105 "acct")   'auth'($LIST, ${2:&Password: }, yes)
106 "start")  'acct'($LIST+(Acct-Status-Type = Start))
107 "stop")   'acct'($LIST+(Acct-Status-Type = Stop))
108 ".*")       begin
109               print "Unknown command. Try radauth -h for more info"
110               exit 1
111             end
112 end
114 # End of radauth

Select an action based on the value of COMMAND variable.

104 – 105

Call auth function. If the second argument is given in the command line, its value is taken as user's password. Otherwise, the user is prompted for the password with the string ‘Password: ’. The input is read with echo turned off to prevent the password from being compromised (the ‘:&’ construct, see section Dereferencing Variables).

106 – 107

Call acct function for ‘start’ and stop commands.

108 – 111

Handle an unknown command verb.


Closes case statement from line 103.

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

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