RADIUS::avp

Description

This command returns or adds/changes/removes RADIUS attribute-value pairs. Radius profile must be applied for access to this command.

Syntax

RADIUS::avp <attr> [attr_type]
RADIUS::avp <attr> [attr_type] [index x] [vendor-id y] [vendor-type z]
RADIUS::avp delete <attr>
RADIUS::avp delete <attr> [index x] [vendor-id y] [vendor-type z]
RADIUS::avp insert <attr> <value> [attr_type]
RADIUS::avp replace <attr> <value> [attr_type]
RADIUS::avp replace <attr> <value> [attr_type] [index x] [vendor-id y] [vendor-type z]

RADIUS::avp [attr_type]

  • Returns the value of the specified RADIUS attribute. optional attr_type = ( octet | ip4 | ip6 | integer | string | integer64 | ip4prefix | ip6prefix )

RADIUS::avp [attr_type] [index x] [vendor-id y] [vendor-type z]

  • RADIUS Vendor-Specific attribute
  • Optional attr_type = ( octet | ip4 | ip6 | integer | integer64 | ip4prefix | ip6prefix )
  • See example below
  • Introduced in Version 11.4.0

RADIUS::avp delete

  • Deletes the specified RADIUS attribute.

RADIUS::avp delete [index x] [vendor-id y] [vendor-type z]

  • Returns the value of the specified RADIUS Vendor-Specific attribute
  • Optional attr_type = ( octet | ip4 | ip6 | integer | integer64 | ip4prefix | ip6prefix )
  • See example below
  • Introduced in Version 11.4.0

RADIUS::avp insert [attr_type]

  • Inserts the specified RADIUS attribute and value. optional attr_type = ( octet | ip4 | ip6 | integer | string | integer64 | ip4prefix | ip6prefix )

RADIUS::avp replace [attr_type]

  • Rewrites the specified RADIUS attribute with new value. optional attr_type = ( octet | ip4 | ip6 | integer | string | integer64 | ip4prefix | ip6prefix )

Note

The attr should be supplied as the decimal value 1 to 255 or as the UPPERCASE strings specified in RFC 2865 and RFC 2866 . The optional attr_type indicates how a value should be interpreted. Valid types are octet, string, ip4, ip6, integer, integer64, ip4prefix, and ip6prefix ). An unknown type is treated as octet.

Examples

when CLIENT_DATA {
  persist uie [RADIUS::avp 1]
  RADIUS::avp replace  USER-NAME "foo"
}

This example sends only START and STOP messages to a AAA complex that can’t handle the full load of accounting updates
when CLIENT_DATA {
    set type [RADIUS::avp 40 integer]
        switch $type {
            1 -
            2 {
                if { [active_members radius_test_pool] > 0 } {
                    pool radius_test_pool
                }
            }
            default {
                drop
            }
    }
}

In Version 11.4.0 vendor specific attribute parsing was introduced, here as an example how to add custom attributes to PEM Session
when RULE_INIT {
    set static::DBG_X 1

    #http://tools.ietf.org/html/rfc2865
    #http://tools.ietf.org/html/rfc2866
    array set static::R_AVP {
        User_Name   1
        User_Password   2
        Framed_IP_Address   8
        Called_Station_Id   30
        Calling_Station_Id  31
    }

    array set static::ACCOUNTINGT_STATUS_T {
        1   START
        2   STOP
        3   INTERIM_UPDATE
    }

    array set static::RADIUS_CODE {
        4   ACCOUNTING_REQUEST
        5   ACCOUNTING_RESPONSE
    }

    # http://www.3gpp.org/ftp/Specs/archive/29_series/29.061/29061_9b0.zip
    array set static::3GGP {
        VENDOR_ID   10415
        3GPP_IMSI        1
        3GPP_IMEISV      20
        3GPP_RAT_Type    21
        3GPP_User_Location_Info 22
    }
}

when CLIENT_DATA {
    set radius_code $static::RADIUS_CODE([RADIUS::code])

    if {$static::DBG_X}{
        log local0. "$radius_code from [IP::client_addr]:[UDP::client_port]"
    }

    switch $radius_code {
    ACCOUNTING_REQUEST {
        set user_name  [RADIUS::avp  $static::R_AVP(User_Name) "string"]
        set framed_ip_address [RADIUS::avp  $static::R_AVP(Framed_IP_Address) ip4 ]
        set accounting_status_t $static::ACCOUNTINGT_STATUS_T([RADIUS::avp 40 "integer"])

        switch $accounting_status_t {
        START {
            set msisdn  [RADIUS::avp $static::R_AVP(Calling_Station_Id) "string"]

            set imsi [RADIUS::avp 26 "string" \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_IMSI)]

            set imeisv [RADIUS::avp 26 "string" \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_IMEISV)]

            set rat_type [scan [RADIUS::avp 26 "octet" \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_RAT_Type)] "%c"]

            binary scan [RADIUS::avp 26 \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_User_Location_Info) \
                        ] H* 3gpp_user_location_info

            PEM::session create $framed_ip_address \
                                subscriber-id $msisdn \
                                subscriber-type e164 \
                                user-name $user_name \
                                imsi $imsi \
                                imeisv $imeisv \
                                tower-id $3gpp_user_location_info \
                                rat_type $rat_type

            if {$static::DBG_X}{
                set msg "Accounting-Status-Type: $accounting_status_t"
                append msg " PEM::Session create $framed_ip_address subscriber_id $msisdn"
                append msg " subscriber_type e164 user_name $user_name"
                append msg " imsi $imsi tower_id $3gpp_user_location_info"
                append msg " imeisv $imeisv rat_type $rat_type "
                log local0. $msg
            }
        }

        STOP {
            PEM::session delete $framed_ip_address

            if {$static::DBG_X}{
                set msg "Accounting-Status-Type: $accounting_status_t"
                append msg " PEM::session delete $framed_ip_address"
                log local0. $msg
            }
        }

        INTERIM_UPDATE {
            set rat_type [scan [RADIUS::avp 26 "octet" \
                        index 0 \
                        vendor_id $static::3GGP(VENDOR_ID) \
                        vendor_type $static::3GGP(3GPP_RAT_Type)] "%c"]

            PEM::session info attr $framed_ip_address rat_type $rat_type

            if {$static::DBG_X}{
                set msg "Accounting-Status-Type: $accounting_status_t"
                append msg " PEM::session info attr $framed_ip_address RAT_TYPE $rat_type"
                log local0. $msg
            }
        }
        }
    }
    }
}

See this code when you want to sent a RADIUS Accounting Accept
when RULE_INIT {
    set static::secret "linus"
}
when CLIENT_DATA {
    # getting base information, see also RFC 2865
    #0                   1                   2                   3
    #0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    #|     Code      |  Identifier   |            Length             |
    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    #|                         Authenticator                         |
    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    #|  Attributes ...
    #+-+-+-+-+-+-+-+-+-+-+-+-+-

    binary scan [UDP::payload] caSa16 code id len req_auth
        # Checking if Radius Code is 4 Accounting-Request
    if { $code == 4 } {

    # Accounting-Response will be 5, hardcode it
    # Accounting Response will be 20 bytes long, hardcode it
    # creating  ResponseAuth =
    #  MD5(Code+ID+Length+RequestAuth+Attributes+Secret)

    set res_auth [md5 "\x05${id}\x00\x14${req_auth}${static::secret}"]
    set reply [binary format caSa16 5 $id 20 $res_auth]
    clientside { UDP::respond ${reply}}

    # Drop the packet since we are not going to send it anywhere
    # If we would, we would not need to sent a reply, right ?
    UDP::drop
    }
}

Use iRule for PEM:Session and reply

when RULE_INIT {
    set static::DBG_X 1
    set static::secret "linus"

    #http://tools.ietf.org/html/rfc2865
    #http://tools.ietf.org/html/rfc2866
    array set static::R_AVP {
        User_Name   1
        User_Password   2
        Framed_IP_Address   8
        Called_Station_Id   30
        Calling_Station_Id  31
    }

    array set static::ACCOUNTINGT_STATUS_T {
        1   START
        2   STOP
        3   INTERIM_UPDATE
    }

    array set static::RADIUS_CODE {
        4   ACCOUNTING_REQUEST
        5   ACCOUNTING_RESPONSE
    }

    # http://www.3gpp.org/ftp/Specs/archive/29_series/29.061/29061_9b0.zip
    array set static::3GGP {
        VENDOR_ID   10415
        3GPP_IMSI        1
        3GPP_IMEISV      20
        3GPP_RAT_Type    21
        3GPP_User_Location_Info 22
    }
}

when CLIENT_DATA {
    set radius_code $static::RADIUS_CODE([RADIUS::code])
    # getting base information, see also RFC 2865
    #0                   1                   2                   3
    #0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    #|     Code      |  Identifier   |            Length             |
    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    #|                         Authenticator                         |
    #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    #|  Attributes ...
    #+-+-+-+-+-+-+-+-+-+-+-+-+-

    binary scan [UDP::payload] caSa16 code id len req_auth

    if {$static::DBG_X}{
        log local0. "$radius_code from [IP::client_addr]:[UDP::client_port]"
    }

    switch $radius_code {
    ACCOUNTING_REQUEST {
        set user_name  [RADIUS::avp  $static::R_AVP(User_Name) "string"]
        set framed_ip_address [RADIUS::avp  $static::R_AVP(Framed_IP_Address) ip4 ]
        set accounting_status_t $static::ACCOUNTINGT_STATUS_T([RADIUS::avp 40 "integer"])

        switch $accounting_status_t {
        START {
            set msisdn  [RADIUS::avp $static::R_AVP(Calling_Station_Id) "string"]

            set imsi [RADIUS::avp 26 "string" \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_IMSI)]

            set imeisv [RADIUS::avp 26 "string" \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_IMEISV)]

            set rat_type [scan [RADIUS::avp 26 "octet" \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_RAT_Type)] "%c"]

            binary scan [RADIUS::avp 26 \
                        index 0 \
                        vendor-id $static::3GGP(VENDOR_ID) \
                        vendor-type $static::3GGP(3GPP_User_Location_Info) \
                        ] H* 3gpp_user_location_info

            PEM::session create $framed_ip_address \
                                subscriber-id $msisdn \
                                subscriber-type e164 \
                                user-name $user_name \
                                imsi $imsi \
                                imeisv $imeisv \
                                tower-id $3gpp_user_location_info \
                                rat_type $rat_type

            if {$static::DBG_X}{
                set msg "Accounting-Status-Type: $accounting_status_t"
                append msg " PEM::Session create $framed_ip_address subscriber_id $msisdn"
                append msg " subscriber_type e164 user_name $user_name"
                append msg " imsi $imsi tower_id $3gpp_user_location_info"
                append msg " imeisv $imeisv rat_type $rat_type "
                log local0. $msg
            }
        }

        STOP {
            PEM::session delete $framed_ip_address

            if {$static::DBG_X}{
                set msg "Accounting-Status-Type: $accounting_status_t"
                append msg " PEM::session delete $framed_ip_address"
                log local0. $msg
            }
        }

        INTERIM_UPDATE {
            set rat_type [scan [RADIUS::avp 26 "octet" \
                        index 0 \
                        vendor_id $static::3GGP(VENDOR_ID) \
                        vendor_type $static::3GGP(3GPP_RAT_Type)] "%c"]

            PEM::session info attr $framed_ip_address rat_type $rat_type

            if {$static::DBG_X}{
                set msg "Accounting-Status-Type: $accounting_status_t"
                append msg " PEM::session info attr $framed_ip_address RAT_TYPE $rat_type"
                log local0. $msg
            }
        }
        }
        # Accounting-Response will be 5, hardcode it
        # Accounting Response will be 20 bytes long, hardcode it
        # creating  ResponseAuth =
        #  MD5(Code+ID+Length+RequestAuth+Attributes+Secret)

        set res_auth [md5 "\x05${id}\x00\x14${req_auth}${static::secret}"]
        set reply [binary format caSa16 5 $id 20 $res_auth]
        clientside { UDP::respond ${reply}}

        # Drop the packet since we are not going to send it anywhere
        # If we would, we would not need to sent a reply, right ?
        UDP::drop
    }
    }
}

This example shows how to parse multiple nested AVPs

when CLIENT_ACCEPTED {
# this example shows how to parse multiple nested AVPs
for {set i 0; set res ""} {$i < 10} {incr i} {
    set avp  [ RADIUS::avp 26 "string" index $i vendor-id 10415 vendor-type 13]
    if { $avp eq "" }{
        break
    }
    lappend res $avp
}
log local0. "result $res "
}