Forum Discussion

John_Allen's avatar
John_Allen
Icon for Altostratus rankAltostratus
Dec 08, 2011

How to decode the five different data types in a RADIUS packet

How to decode the five different data types in a RADIUS packet

 

 

When a handset device on a cellular carrier turns on, usually a RADIUS packet is generated and sent out to a number of different network nodes to let them know that the handset device is on and about to access services of the wireless network. In some of those networks, F5 BIGIP devices also receive this RADIUS packet so that they too can get ready to handle network traffic from the handset device. Some times the BIGIP will query some sort of AAA or Policy servers to see if the handset device is allowed to connect to nodes beyond the BIGIP, and needs some of the information contained in the RADIUS packet in order to do the query. Here’s how to pull that information out within iRules.

 

 

RADIUS packets have five official data types: Integer, Text, String, IPAddress, and Time. These are defined in the RADIUS standards (RFC-2865, RFC-2866, among others). “String” can be something of a misnomer, as it can contain binary data. “Text” is used for textual, printable, strings (I.E. UTF-8 encoded characters). Of these five types, only Text can be used without modification or checks. Here’s how to decode the other four:

 

 

Integer -- One would think that you could use Integer types without modification, but there is one subtle gotcha. RADIUS integers are “unsigned”, meaning they are always positive. iRules integers are signed – the left-most bit is used as a flag to denote positive and negative numbers. If the left-most bit is set, then the number is negative. So in some cases, the numbers coming from RADIUS may show up as negative, rather than positive, numbers. You just need to make sure this left-most bit is unset:

 

 

set acctAuthen [RADIUS::avp 45 "integer"]

 

set acctAuthen [expr { $acctAuthen && 0xff }]

 

if { $static::DEBUG eq 1 && $acctAuthen != "" } { puts "Acct-Authentic: $acctAuthen" }

 

 

String -- Since iRules can handle non-UTF-8 bytes in its string type, there is no issue using what you get from the RADIUS packet without modification. The problem comes if you want to print out or otherwise log the contents of the String when its holding binary data. This can be done using a simple binary scan command:

 

 

 

set acctSessId [RADIUS::avp 44 "string"]

 

binary scan $acctSessId H* acctSessId

 

if { $static::DEBUG eq 1 && $acctSessId != "" } { puts "Acct-Session-Id: $acctSessId" }

 

 

In /var/log/tmm:

 

… local/bigipfw notice Acct-Session-Id: ff082000

 

 

IPAddress -- Or “address” as its referenced in the spec. This is almost always an IPv4 address. When you retrieve this avp, you get a four-byte string, with the four octets of an IPv4 address. It’s pretty simple to decode:

 

 

set a1 [RADIUS::avp 8 "ipaddr"] ; network byte order

 

binary scan $a1 cccc a b c d

 

set a [expr { $a & 0xff }] ; make unsigned values

 

set b [expr { $b & 0xff }]

 

set c [expr { $c & 0xff }]

 

set d [expr { $c & 0xff }]

 

set frmdIPAddr "$a.$b.$c.$d"

 

if { $static::DEBUG eq 1 & $frmdIPAddr != "" } { puts "Framed-IP-Address: $frmdIPAddr" }

 

 

Time -- These values are stored as a four-byte “epoch” value (this is, the number of seconds since July 1, 1970… which I believe was the next closest start of the month at the time the programmer who wrote the procedure, wrote it). Give that iRules is derived from the TCL programming language, we are lucky in that TCL has built in functions to manipulate this value and print out a date/time format that we can use:

 

 

set eventTimestamp [RADIUS::avp 55 "integer"]

 

set timest [clock format $eventTimestamp -format {%a %b %d %Y %H:%M:%S}]

 

if { $static::DEBUG eq 1 && $timest != "" } { puts "Event-Timestamp: $timest" }

 

 

More information about the RADIUS:: iRules commands can be found .