diff --git a/scapy/layers/radius.py b/scapy/layers/radius.py
index 4d93bcff41d40ef76088b8a41e9c6dad5f8e1d3d..1038974efd779212aa1b93ed16fea3920c836589 100644
--- a/scapy/layers/radius.py
+++ b/scapy/layers/radius.py
@@ -9,139 +9,1199 @@ RADIUS (Remote Authentication Dial In User Service)
 """
 
 import struct
-from scapy.packet import *
-from scapy.fields import *
-from scapy.layers.inet import *
+import logging
+from scapy.packet import Packet, bind_layers
+from scapy.fields import ByteField, ByteEnumField, IntField, StrLenField,\
+    XStrLenField, XStrFixedLenField, FieldLenField, PacketField,\
+    PacketListField, IPField, MultiEnumField
+from scapy.layers.inet import UDP
+from scapy.layers.l2 import EAP
+from scapy.config import conf
+from scapy.error import Scapy_Exception
+
+
+g_log_loading = logging.getLogger("scapy.logging")
+
+_crypto_loading_failure_message = \
+    "Could not import python-cryptography."\
+    "Computations for the \"authenticator\" field (RADIUS packets) and"\
+    "\"Message-Authenticator\" attribute value field are disabled."
+
+if conf.crypto_valid:
+    from cryptography.hazmat.backends import default_backend
+    from cryptography.hazmat.primitives import hashes, hmac
+else:
+    g_log_loading.info(_crypto_loading_failure_message)
+
+
+# https://www.iana.org/assignments/radius-types/radius-types.xhtml
+_radius_attribute_types = {
+    1: "User-Name",
+    2: "User-Password",
+    3: "CHAP-Password",
+    4: "NAS-IP-Address",
+    5: "NAS-Port",
+    6: "Service-Type",
+    7: "Framed-Protocol",
+    8: "Framed-IP-Address",
+    9: "Framed-IP-Netmask",
+    10: "Framed-Routing",
+    11: "Filter-Id",
+    12: "Framed-MTU",
+    13: "Framed-Compression",
+    14: "Login-IP-Host",
+    15: "Login-Service",
+    16: "Login-TCP-Port",
+    17: "Unassigned",
+    18: "Reply-Message",
+    19: "Callback-Number",
+    20: "Callback-Id",
+    21: "Unassigned",
+    22: "Framed-Route",
+    23: "Framed-IPX-Network",
+    24: "State",
+    25: "Class",
+    26: "Vendor-Specific",
+    27: "Session-Timeout",
+    28: "Idle-Timeout",
+    29: "Termination-Action",
+    30: "Called-Station-Id",
+    31: "Calling-Station-Id",
+    32: "NAS-Identifier",
+    33: "Proxy-State",
+    34: "Login-LAT-Service",
+    35: "Login-LAT-Node",
+    36: "Login-LAT-Group",
+    37: "Framed-AppleTalk-Link",
+    38: "Framed-AppleTalk-Network",
+    39: "Framed-AppleTalk-Zone",
+    40: "Acct-Status-Type",
+    41: "Acct-Delay-Time",
+    42: "Acct-Input-Octets",
+    43: "Acct-Output-Octets",
+    44: "Acct-Session-Id",
+    45: "Acct-Authentic",
+    46: "Acct-Session-Time",
+    47: "Acct-Input-Packets",
+    48: "Acct-Output-Packets",
+    49: "Acct-Terminate-Cause",
+    50: "Acct-Multi-Session-Id",
+    51: "Acct-Link-Count",
+    52: "Acct-Input-Gigawords",
+    53: "Acct-Output-Gigawords",
+    54: "Unassigned",
+    55: "Event-Timestamp",
+    56: "Egress-VLANID",
+    57: "Ingress-Filters",
+    58: "Egress-VLAN-Name",
+    59: "User-Priority-Table",
+    60: "CHAP-Challenge",
+    61: "NAS-Port-Type",
+    62: "Port-Limit",
+    63: "Login-LAT-Port",
+    64: "Tunnel-Type",
+    65: "Tunnel-Medium-Type",
+    66: "Tunnel-Client-Endpoint",
+    67: "Tunnel-Server-Endpoint",
+    68: "Acct-Tunnel-Connection",
+    69: "Tunnel-Password",
+    70: "ARAP-Password",
+    71: "ARAP-Features",
+    72: "ARAP-Zone-Access",
+    73: "ARAP-Security",
+    74: "ARAP-Security-Data",
+    75: "Password-Retry",
+    76: "Prompt",
+    77: "Connect-Info",
+    78: "Configuration-Token",
+    79: "EAP-Message",
+    80: "Message-Authenticator",
+    81: "Tunnel-Private-Group-ID",
+    82: "Tunnel-Assignment-ID",
+    83: "Tunnel-Preference",
+    84: "ARAP-Challenge-Response",
+    85: "Acct-Interim-Interval",
+    86: "Acct-Tunnel-Packets-Lost",
+    87: "NAS-Port-Id",
+    88: "Framed-Pool",
+    89: "CUI",
+    90: "Tunnel-Client-Auth-ID",
+    91: "Tunnel-Server-Auth-ID",
+    92: "NAS-Filter-Rule",
+    93: "Unassigned",
+    94: "Originating-Line-Info",
+    95: "NAS-IPv6-Address",
+    96: "Framed-Interface-Id",
+    97: "Framed-IPv6-Prefix",
+    98: "Login-IPv6-Host",
+    99: "Framed-IPv6-Route",
+    100: "Framed-IPv6-Pool",
+    101: "Error-Cause",
+    102: "EAP-Key-Name",
+    103: "Digest-Response",
+    104: "Digest-Realm",
+    105: "Digest-Nonce",
+    106: "Digest-Response-Auth",
+    107: "Digest-Nextnonce",
+    108: "Digest-Method",
+    109: "Digest-URI",
+    110: "Digest-Qop",
+    111: "Digest-Algorithm",
+    112: "Digest-Entity-Body-Hash",
+    113: "Digest-CNonce",
+    114: "Digest-Nonce-Count",
+    115: "Digest-Username",
+    116: "Digest-Opaque",
+    117: "Digest-Auth-Param",
+    118: "Digest-AKA-Auts",
+    119: "Digest-Domain",
+    120: "Digest-Stale",
+    121: "Digest-HA1",
+    122: "SIP-AOR",
+    123: "Delegated-IPv6-Prefix",
+    124: "MIP6-Feature-Vector",
+    125: "MIP6-Home-Link-Prefix",
+    126: "Operator-Name",
+    127: "Location-Information",
+    128: "Location-Data",
+    129: "Basic-Location-Policy-Rules",
+    130: "Extended-Location-Policy-Rules",
+    131: "Location-Capable",
+    132: "Requested-Location-Info",
+    133: "Framed-Management-Protocol",
+    134: "Management-Transport-Protection",
+    135: "Management-Policy-Id",
+    136: "Management-Privilege-Level",
+    137: "PKM-SS-Cert",
+    138: "PKM-CA-Cert",
+    139: "PKM-Config-Settings",
+    140: "PKM-Cryptosuite-List",
+    141: "PKM-SAID",
+    142: "PKM-SA-Descriptor",
+    143: "PKM-Auth-Key",
+    144: "DS-Lite-Tunnel-Name",
+    145: "Mobile-Node-Identifier",
+    146: "Service-Selection",
+    147: "PMIP6-Home-LMA-IPv6-Address",
+    148: "PMIP6-Visited-LMA-IPv6-Address",
+    149: "PMIP6-Home-LMA-IPv4-Address",
+    150: "PMIP6-Visited-LMA-IPv4-Address",
+    151: "PMIP6-Home-HN-Prefix",
+    152: "PMIP6-Visited-HN-Prefix",
+    153: "PMIP6-Home-Interface-ID",
+    154: "PMIP6-Visited-Interface-ID",
+    155: "PMIP6-Home-IPv4-HoA",
+    156: "PMIP6-Visited-IPv4-HoA",
+    157: "PMIP6-Home-DHCP4-Server-Address",
+    158: "PMIP6-Visited-DHCP4-Server-Address",
+    159: "PMIP6-Home-DHCP6-Server-Address",
+    160: "PMIP6-Visited-DHCP6-Server-Address",
+    161: "PMIP6-Home-IPv4-Gateway",
+    162: "PMIP6-Visited-IPv4-Gateway",
+    163: "EAP-Lower-Layer",
+    164: "GSS-Acceptor-Service-Name",
+    165: "GSS-Acceptor-Host-Name",
+    166: "GSS-Acceptor-Service-Specifics",
+    167: "GSS-Acceptor-Realm-Name",
+    168: "Framed-IPv6-Address",
+    169: "DNS-Server-IPv6-Address",
+    170: "Route-IPv6-Information",
+    171: "Delegated-IPv6-Prefix-Pool",
+    172: "Stateful-IPv6-Address-Pool",
+    173: "IPv6-6rd-Configuration",
+    174: "Allowed-Called-Station-Id",
+    175: "EAP-Peer-Id",
+    176: "EAP-Server-Id",
+    177: "Mobility-Domain-Id",
+    178: "Preauth-Timeout",
+    179: "Network-Id-Name",
+    180: "EAPoL-Announcement",
+    181: "WLAN-HESSID",
+    182: "WLAN-Venue-Info",
+    183: "WLAN-Venue-Language",
+    184: "WLAN-Venue-Name",
+    185: "WLAN-Reason-Code",
+    186: "WLAN-Pairwise-Cipher",
+    187: "WLAN-Group-Cipher",
+    188: "WLAN-AKM-Suite",
+    189: "WLAN-Group-Mgmt-Cipher",
+    190: "WLAN-RF-Band",
+    191: "Unassigned",
+}
+
+
+class RadiusAttribute(Packet):
+    """
+    Implements a RADIUS attribute (RFC 2865). Every specific RADIUS attribute
+    class should inherit from this one.
+    """
 
-class RadiusAttribute(Packet): 
     name = "Radius Attribute"
     fields_desc = [
-        ByteEnumField("type",1,{ 1:"User-Name",
-                                 2:"User-Password",
-                                 3:"CHAP-Password",
-                                 4:"NAS-IP-Address",
-                                 5:"NAS-Port",
-                                 6:"Service-Type",
-                                 7:"Framed-Protocol",
-                                 8:"Framed-IP-Address",
-                                 9:"Framed-IP-Netmask",
-                                 10:"Framed-Routing",
-                                 11:"Filter-Id",
-                                 12:"Framed-MTU",
-                                 13:"Framed-Compression",
-                                 14:"Login-IP-Host",
-                                 15:"Login-Service",
-                                 16:"Login-TCP-Port",
-                                 17:"(unassigned)",
-                                 18:"Reply-Message",
-                                 19:"Callback-Number",
-                                 20:"Callback-Id",
-                                 21:"(unassigned)",
-                                 22:"Framed-Route",
-                                 23:"Framed-IPX-Network",
-                                 24:"State",
-                                 25:"Class",
-                                 26:"Vendor-Specific",
-                                 27:"Session-Timeout",
-                                 28:"Idle-Timeout",
-                                 29:"Termination-Action",
-                                 30:"Called-Station-Id",
-                                 31:"Calling-Station-Id",
-                                 32:"NAS-Identifier",
-                                 33:"Proxy-State",
-                                 34:"Login-LAT-Service",
-                                 35:"Login-LAT-Node",
-                                 36:"Login-LAT-Group",
-                                 37:"Framed-AppleTalk-Link",
-                                 38:"Framed-AppleTalk-Network",
-                                 39:"Framed-AppleTalk-Zone",
-                                 40:"Acct-Status-Type",
-                                 41:"Acct-Delay-Time",
-                                 42:"Acct-Input-Octets",
-                                 43:"Acct-Output-Octets",
-                                 44:"Acct-Session-Id",
-                                 45:"Acct-Authentic",
-                                 46:"Acct-Session-Time",
-                                 47:"Acct-Input-Packets",
-                                 48:"Acct-Output-Packets",
-                                 49:"Acct-Terminate-Cause",
-                                 50:"Acct-Multi-Session-Id",
-                                 51:"Acct-Link-Count",
-                                 60:"CHAP-Challenge",
-                                 61:"NAS-Port-Type",
-                                 62:"Port-Limit",
-                                 63:"Login-LAT-Port",
-                                 70:"ARAP-Password",
-                                 75:"Password-Retry",
-                                 79:"EAP-Message",
-                                 80:"Message-Authenticator",
-                                 94:"Originating-Line-Info",
-                                 101:"Error-Cause"
-                                 }),
-        FieldLenField("len", None, "value", "B", adjust=lambda pkt,x:len(pkt.value)+2),
-        StrLenField("value", "" , length_from=lambda pkt:pkt.len-2),]
+        ByteEnumField("type", 1, _radius_attribute_types),
+        FieldLenField("len", None, "value", "B",
+                      adjust=lambda pkt, x: len(pkt.value) + 2),
+        StrLenField("value", "", length_from=lambda pkt: pkt.len - 2)
+    ]
+
+    registered_attributes = {}
+
+    @classmethod
+    def register_variant(cls):
+        """
+        Registers the RADIUS attributes defined in this module.
+        """
+
+        if hasattr(cls, "val"):
+            cls.registered_attributes[cls.val] = cls
+        else:
+            cls.registered_attributes[cls.type.default] = cls
+
+    @classmethod
+    def dispatch_hook(cls, _pkt=None, *args, **kargs):
+        """
+        Returns the right RadiusAttribute class for the given data.
+        """
+
+        if _pkt:
+            attr_type = ord(_pkt[0])
+            return cls.registered_attributes.get(attr_type, cls)
+        return cls
+
+    def haslayer(self, cls):
+        if cls == RadiusAttribute:
+            for attr_class in RadiusAttribute.registered_attributes.values():
+                if isinstance(self, attr_class):
+                    return True
+        elif cls in RadiusAttribute.registered_attributes.values() and isinstance(self, cls):
+            return True
+        return False
+
+    def getlayer(self, cls, nb=1, _track=None):
+        layer = None
+        if cls == RadiusAttribute:
+            for attr_class in RadiusAttribute.registered_attributes.values():
+                if isinstance(self, attr_class):
+                    layer = self
+                    break
+        else:
+            layer = Packet.getlayer(self, cls, nb, _track)
+        return layer
+
 
     def post_build(self, p, pay):
-        l = self.len
-        if l is None:
-            l = len(p)
-            p = p[:1]+struct.pack("!B", l)+p[2:]
+        length = self.len
+        if length is None:
+            length = len(p)
+            p = p[:1] + struct.pack("!B", length) + p[2:]
         return p
-        
-    def extract_padding(self, pay):
-        return "",pay
+
+
+class _SpecificRadiusAttr(RadiusAttribute):
+    """
+    Class from which every "specific" RADIUS attribute defined in this module
+    inherits.
+    """
+
+    __slots__ = ["val"]
+
+    def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields):
+        super(_SpecificRadiusAttr, self).__init__(
+            _pkt,
+            post_transform,
+            _internal,
+            _underlayer
+        )
+        self.fields["type"] = self.val
+        name_parts = self.__class__.__name__.split('RadiusAttr_')
+        if len(name_parts) < 2:
+            raise Scapy_Exception(
+                "Invalid class name: {}".format(self.__class__.__name__)
+            )
+        self.name = name_parts[1].replace('_', '-')
+
+
+#
+# RADIUS attributes which values are 4 bytes integers
+#
+
+class _RadiusAttrIntValue(_SpecificRadiusAttr):
+    """
+    Implements a RADIUS attribute which value field is 4 bytes long integer.
+    """
+
+    fields_desc = [
+        ByteEnumField("type", 5, _radius_attribute_types),
+        ByteField("len", 6),
+        IntField("value", 0)
+    ]
+
+
+class RadiusAttr_NAS_Port(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 5
+
+
+class RadiusAttr_Framed_MTU(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 12
+
+
+class RadiusAttr_Login_TCP_Port(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 16
+
+
+class RadiusAttr_Session_Timeout(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 27
+
+
+class RadiusAttr_Idle_Timeout(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 28
+
+
+class RadiusAttr_Framed_AppleTalk_Link(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 37
+
+
+class RadiusAttr_Framed_AppleTalk_Network(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 38
+
+
+class RadiusAttr_Acct_Delay_Time(_RadiusAttrIntValue):
+    """RFC 2866"""
+    val = 41
+
+
+class RadiusAttr_Acct_Input_Octets(_RadiusAttrIntValue):
+    """RFC 2866"""
+    val = 42
+
+
+class RadiusAttr_Acct_Output_Octets(_RadiusAttrIntValue):
+    """RFC 2866"""
+    val = 43
+
+
+class RadiusAttr_Acct_Session_Time(_RadiusAttrIntValue):
+    """RFC 2866"""
+    val = 46
+
+
+class RadiusAttr_Acct_Input_Packets(_RadiusAttrIntValue):
+    """RFC 2866"""
+    val = 47
+
+
+class RadiusAttr_Acct_Output_Packets(_RadiusAttrIntValue):
+    """RFC 2866"""
+    val = 48
+
+
+class RadiusAttr_Acct_Link_Count(_RadiusAttrIntValue):
+    """RFC 2866"""
+    val = 51
+
+
+class RadiusAttr_Acct_Input_Gigawords(_RadiusAttrIntValue):
+    """RFC 2869"""
+    val = 52
+
+
+class RadiusAttr_Acct_Output_Gigawords(_RadiusAttrIntValue):
+    """RFC 2869"""
+    val = 53
+
+
+class RadiusAttr_Egress_VLANID(_RadiusAttrIntValue):
+    """RFC 4675"""
+    val = 56
+
+
+class RadiusAttr_Port_Limit(_RadiusAttrIntValue):
+    """RFC 2865"""
+    val = 62
+
+
+class RadiusAttr_ARAP_Security(_RadiusAttrIntValue):
+    """RFC 2869"""
+    val = 73
+
+
+class RadiusAttr_Password_Retry(_RadiusAttrIntValue):
+    """RFC 2869"""
+    val = 75
+
+
+class RadiusAttr_Tunnel_Preference(_RadiusAttrIntValue):
+    """RFC 2868"""
+    val = 83
+
+
+class RadiusAttr_Acct_Interim_Interval(_RadiusAttrIntValue):
+    """RFC 2869"""
+    val = 85
+
+
+class RadiusAttr_Acct_Tunnel_Packets_Lost(_RadiusAttrIntValue):
+    """RFC 2867"""
+    val = 86
+
+
+class RadiusAttr_Management_Privilege_Level(_RadiusAttrIntValue):
+    """RFC 5607"""
+    val = 136
+
+
+class RadiusAttr_Mobility_Domain_Id(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 177
+
+
+class RadiusAttr_Preauth_Timeout(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 178
+
+
+class RadiusAttr_WLAN_Venue_Info(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 182
+
+
+class RadiusAttr_WLAN_Reason_Code(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 185
+
+
+class RadiusAttr_WLAN_Pairwise_Cipher(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 186
+
+
+class RadiusAttr_WLAN_Group_Cipher(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 187
+
+
+class RadiusAttr_WLAN_AKM_Suite(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 188
+
+
+class RadiusAttr_WLAN_Group_Mgmt_Cipher(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 189
+
+
+class RadiusAttr_WLAN_RF_Band(_RadiusAttrIntValue):
+    """RFC 7268"""
+    val = 190
+
+
+#
+# RADIUS attributes which values are string (displayed as hex)
+#
+
+class _RadiusAttrHexStringVal(_SpecificRadiusAttr):
+    """
+    Implements a RADIUS attribute which value field is a string that will be
+    as a hex string.
+    """
+
+    __slots__ = ["val"]
+
+    def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields):
+        super(_RadiusAttrHexStringVal, self).__init__(
+            _pkt,
+            post_transform,
+            _internal,
+            _underlayer
+        )
+        self.fields["type"] = self.val
+        name_parts = self.__class__.__name__.split('RadiusAttr_')
+        if len(name_parts) < 2:
+            raise Scapy_Exception(
+                "Invalid class name: {}".format(self.__class__.__name__)
+            )
+        self.name = name_parts[1].replace('_', '-')
+
+    fields_desc = [
+        ByteEnumField("type", 24, _radius_attribute_types),
+        FieldLenField(
+            "len",
+            None,
+            "value",
+            "B",
+            adjust=lambda p, x: len(p.value) + 2
+        ),
+        XStrLenField("value", "", length_from=lambda p: p.len - 2 if p.len else 0)
+    ]
+
+
+class RadiusAttr_State(_RadiusAttrHexStringVal):
+    """RFC 2865"""
+    val = 24
+
+
+class RadiusAttr_Message_Authenticator(_RadiusAttrHexStringVal):
+    """RFC 2869"""
+    val = 80
+
+    fields_desc = [
+        ByteEnumField("type", 24, _radius_attribute_types),
+        FieldLenField(
+            "len",
+            18,
+            "value",
+            "B",
+        ),
+        XStrFixedLenField("value", "\x00" * 16, length=16)
+    ]
+
+    @staticmethod
+    def compute_message_authenticator(
+            radius_packet,
+            packed_req_authenticator,
+            shared_secret
+    ):
+        """
+        Computes the "Message-Authenticator" of a given RADIUS packet.
+        """
+
+        if not conf.crypto_valid:
+            g_log_loading.info(_crypto_loading_failure_message)
+            return None
+
+        packed_hdr = struct.pack("!B", radius_packet.code)
+        packed_hdr += struct.pack("!B", radius_packet.id)
+        packed_hdr += struct.pack("!H", radius_packet.len)
+        packed_attrs = ''
+        for index in range(0, len(radius_packet.attributes)):
+            packed_attrs = packed_attrs + str(radius_packet.attributes[index])
+
+        hmac_ = hmac.HMAC(
+            shared_secret,
+            hashes.MD5(),
+            backend=default_backend()
+        )
+        packed_data = packed_hdr + packed_req_authenticator + packed_attrs
+        hmac_.update(packed_data)
+        return hmac_.finalize()
+
+
+#
+# RADIUS attributes which values are IPv4 prefixes
+#
+
+class _RadiusAttrIPv4AddrVal(RadiusAttribute):
+    """
+    Implements a RADIUS attribute which value field is an IPv4 address.
+    """
+
+    __slots__ = ["val"]
+
+    fields_desc = [
+        ByteEnumField("type", 4, _radius_attribute_types),
+        ByteField("len", 6),
+        IPField("value", "0.0.0.0")
+    ]
+
+
+class RadiusAttr_NAS_IP_Address(_RadiusAttrIPv4AddrVal):
+    """RFC 2865"""
+    val = 4
+
+
+class RadiusAttr_Framed_IP_Address(_RadiusAttrIPv4AddrVal):
+    """RFC 2865"""
+    val = 8
+
+
+class RadiusAttr_Framed_IP_Netmask(_RadiusAttrIPv4AddrVal):
+    """RFC 2865"""
+    val = 9
+
+
+class RadiusAttr_Login_IP_Host(_RadiusAttrIPv4AddrVal):
+    """RFC 2865"""
+    val = 14
+
+
+class RadiusAttr_Framed_IPX_Network(_RadiusAttrIPv4AddrVal):
+    """RFC 2865"""
+    val = 23
+
+
+class RadiusAttr_PMIP6_Home_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal):
+    """RFC 6572"""
+    val = 149
+
+
+class RadiusAttr_PMIP6_Visited_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal):
+    """RFC 6572"""
+    val = 150
+
+
+class RadiusAttr_PMIP6_Home_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal):
+    """RFC 6572"""
+    val = 157
+
+
+class RadiusAttr_PMIP6_Visited_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal):
+    """RFC 6572"""
+    val = 158
+
+
+class RadiusAttr_PMIP6_Home_IPv4_Gateway(_RadiusAttrIPv4AddrVal):
+    """RFC 6572"""
+    val = 161
+
+
+class RadiusAttr_PMIP6_Visited_IPv4_Gateway(_RadiusAttrIPv4AddrVal):
+    """RFC 6572"""
+    val = 162
+
+
+# See IANA registry "RADIUS Types"
+_radius_attrs_values = {
+    # Service-Type
+    6:
+    {
+        1: "Login",
+        2: "Framed",
+        3: "Callback Login",
+        4: "Callback Framed",
+        5: "Outbound",
+        6: "Administrative",
+        7: "NAS Prompt",
+        8: "Authenticate Only",
+        9: "Callback NAS Prompt",
+        10: "Call Check",
+        11: "Callback Administrative",
+        12: "Voice",
+        13: "Fax",
+        14: "Modem Relay",
+        15: "IAPP-Register",
+        16: "IAPP-AP-Check",
+        17: "Authorize Only",
+        18: "Framed-Management",
+        19: "Additional-Authorization"
+    },
+
+    # Framed-Protocol
+    7:
+    {
+        1: "PPP",
+        2: "SLIP",
+        3: "AppleTalk Remote Access Protocol (ARAP)",
+        4: "Gandalf proprietary SingleLink/MultiLink protocol",
+        5: "Xylogics proprietary IPX/SLIP",
+        6: "X.75 Synchronous",
+        7: "GPRS PDP Context"
+    },
+
+    # Framed-Routing
+    10:
+    {
+        0: "None",
+        1: "Send routing packets",
+        2: "Listen for routing packets",
+        3: "Send and Listen"
+    },
+
+    # Framed-Compression
+    13:
+    {
+        0: "None",
+        1: "VJ TCP/IP header compression",
+        2: "IPX header compression",
+        3: "Stac-LZS compression"
+    },
+
+    # Login-Service
+    15:
+    {
+        0: "Telnet",
+        1: "Rlogin",
+        2: "TCP Clear",
+        3: "PortMaster (proprietary)",
+        4: "LAT",
+        5: "X25-PAD",
+        6: "X25-T3POS",
+        7: "Unassigned",
+        8: "TCP Clear Quiet (suppresses any NAS-generated connect string)"
+    },
+
+    # Termination-Action
+    29:
+    {
+        0: "Default",
+        1: "RADIUS-Request"
+    },
+
+    # Acct-Status-Type
+    40:
+    {
+        1: "Start",
+        2: "Stop",
+        3: "Interim-Update",
+        4: "Unassigned",
+        5: "Unassigned",
+        6: "Unassigned",
+        7: "Accounting-On",
+        8: "Accounting-Off",
+        9: "Tunnel-Start",
+        10: "Tunnel-Stop",
+        11: "Tunnel-Reject",
+        12: "Tunnel-Link-Start",
+        13: "Tunnel-Link-Stop",
+        14: "Tunnel-Link-Reject",
+        15: "Failed"
+    },
+
+    # Acct-Authentic
+    45:
+    {
+        1: "RADIUS",
+        2: "Local",
+        3: "Remote",
+        4: "Diameter"
+    },
+
+    # Acct-Terminate-Cause
+    49:
+    {
+        1: "User Request",
+        2: "Lost Carrier",
+        3: "Lost Service",
+        4: "Idle Timeout",
+        5: "Session Timeout",
+        6: "Admin Reset",
+        7: "Admin Reboot",
+        8: "Port Error",
+        9: "NAS Error",
+        10: "NAS Request",
+        11: "NAS Reboot",
+        12: "Port Unneeded",
+        13: "Port Preempted",
+        14: "Port Suspended",
+        15: "Service Unavailable",
+        16: "Callback",
+        17: "User Error",
+        18: "Host Request",
+        19: "Supplicant Restart",
+        20: "Reauthentication Failure",
+        21: "Port Reinitialized",
+        22: "Port Administratively Disabled",
+        23: "Lost Power",
+    },
+
+    # NAS-Port-Type
+    61:
+    {
+        0: "Async",
+        1: "Sync",
+        2: "ISDN Sync",
+        3: "ISDN Async V.120",
+        4: "ISDN Async V.110",
+        5: "Virtual",
+        6: "PIAFS",
+        7: "HDLC Clear Channel",
+        8: "X.25",
+        9: "X.75",
+        10: "G.3 Fax",
+        11: "SDSL - Symmetric DSL",
+        12: "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation",
+        13: "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone",
+        14: "IDSL - ISDN Digital Subscriber Line",
+        15: "Ethernet",
+        16: "xDSL - Digital Subscriber Line of unknown type",
+        17: "Cable",
+        18: "Wireles - Other",
+        19: "Wireless - IEEE 802.11",
+        20: "Token-Ring",
+        21: "FDDI",
+        22: "Wireless - CDMA2000",
+        23: "Wireless - UMTS",
+        24: "Wireless - 1X-EV",
+        25: "IAPP",
+        26: "FTTP - Fiber to the Premises",
+        27: "Wireless - IEEE 802.16",
+        28: "Wireless - IEEE 802.20",
+        29: "Wireless - IEEE 802.22",
+        30: "PPPoA - PPP over ATM",
+        31: "PPPoEoA - PPP over Ethernet over ATM",
+        32: "PPPoEoE - PPP over Ethernet over Ethernet",
+        33: "PPPoEoVLAN - PPP over Ethernet over VLAN",
+        34: "PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ",
+        35: "xPON - Passive Optical Network",
+        36: "Wireless - XGP",
+        37: "WiMAX Pre-Release 8 IWK Function",
+        38: "WIMAX-WIFI-IWK: WiMAX WIFI Interworking",
+        39: "WIMAX-SFF: Signaling Forwarding Function for LTE/3GPP2",
+        40: "WIMAX-HA-LMA: WiMAX HA and or LMA function",
+        41: "WIMAX-DHCP: WIMAX DCHP service",
+        42: "WIMAX-LBS: WiMAX location based service",
+        43: "WIMAX-WVS: WiMAX voice service"
+    },
+
+    # Tunnel-Type
+    64:
+    {
+        1: "Point-to-Point Tunneling Protocol (PPTP)",
+        2: "Layer Two Forwarding (L2F)",
+        3: "Layer Two Tunneling Protocol (L2TP)",
+        4: "Ascend Tunnel Management Protocol (ATMP)",
+        5: "Virtual Tunneling Protocol (VTP)",
+        6: "IP Authentication Header in the Tunnel-mode (AH)",
+        7: "IP-in-IP Encapsulation (IP-IP)",
+        8: "Minimal IP-in-IP Encapsulation (MIN-IP-IP)",
+        9: "IP Encapsulating Security Payload in the Tunnel-mode (ESP)",
+        10: "Generic Route Encapsulation (GRE)",
+        11: "Bay Dial Virtual Services (DVS)",
+        12: "IP-in-IP Tunneling",
+        13: "Virtual LANs (VLAN)"
+    },
+
+    # Tunnel-Medium-Type
+    65:
+    {
+        1: "IPv4 (IP version 4)",
+        2: "IPv6 (IP version 6)",
+        3: "NSAP",
+        4: "HDLC (8-bit multidrop)",
+        5: "BBN 1822",
+        6: "802",
+        7: "E.163 (POTS)",
+        8: "E.164 (SMDS, Frame Relay, ATM)",
+        9: "F.69 (Telex)",
+        10: "X.121 (X.25, Frame Relay)",
+        11: "IPX",
+        12: "Appletalk",
+        13: "Decnet IV",
+        14: "Banyan Vine",
+        15: "E.164 with NSAP format subaddress"
+    },
+
+    # ARAP-Zone-Access
+    72:
+    {
+        1: "Only allow access to default zone",
+        2: "Use zone filter inclusively",
+        3: "Not used",
+        4: "Use zone filter exclusively"
+    },
+
+    # Prompt
+    76:
+    {
+        0: "No Echo",
+        1: "Echo"
+    },
+
+    # Error-Cause Attribute
+    101:
+    {
+        201: "Residual Session Context Removed",
+        202: "Invalid EAP Packet (Ignored)",
+        401: "Unsupported Attribute",
+        402: "Missing Attribute",
+        403: "NAS Identification Mismatch",
+        404: "Invalid Request",
+        405: "Unsupported Service",
+        406: "Unsupported Extension",
+        407: "Invalid Attribute Value",
+        501: "Administratively Prohibited",
+        502: "Request Not Routable (Proxy)",
+        503: "Session Context Not Found",
+        504: "Session Context Not Removable",
+        505: "Other Proxy Processing Error",
+        506: "Resources Unavailable",
+        507: "Request Initiated",
+        508: "Multiple Session Selection Unsupported",
+        509: "Location-Info-Required",
+        601: "Response Too Big"
+    },
+
+    # Operator Namespace Identifier - Attribute 126
+    126:
+    {
+        0x30: "TADIG",
+        0x31: "REALM",
+        0x32: "E212",
+        0x33: "ICC",
+        0xFF: "Reserved"
+    },
+
+    # Basic-Location-Policy-Rules
+    129:
+    {
+        0: "Retransmission allowed",
+    },
+
+    # Location-Capable
+    131:
+    {
+        1: "CIVIC_LOCATION",
+        2: "GEO_LOCATION",
+        4: "USERS_LOCATION",
+        8: "NAS_LOCATION"
+    },
+
+    # Framed-Management-Protocol
+    133:
+    {
+        1: "SNMP",
+        2: "Web-based",
+        3: "NETCONF",
+        4: "FTP",
+        5: "TFTP",
+        6: "SFTP",
+        7: "RCP",
+        8: "SCP"
+    },
+
+    # Management-Transport-Protection
+    134:
+    {
+        1: "No-Protection",
+        2: "Integrity-Protection",
+        3: "Integrity-Confidentiality-Protection",
+    },
+}
+
+
+class _RadiusAttrIntEnumVal(_SpecificRadiusAttr):
+    """
+    Implements a RADIUS attribute which value field is 4 bytes long integer.
+    """
+
+    __slots__ = ["val"]
+
+    fields_desc = [
+        ByteEnumField("type", 6, _radius_attribute_types),
+        ByteField("len", 6),
+        MultiEnumField(
+            "value",
+            0,
+            _radius_attrs_values,
+            depends_on=lambda p: p.type,
+            fmt="I"
+        )
+    ]
+
+
+class RadiusAttr_Service_Type(_RadiusAttrIntEnumVal):
+    """RFC 2865"""
+    val = 6
+
+
+class RadiusAttr_Framed_Protocol(_RadiusAttrIntEnumVal):
+    """RFC 2865"""
+    val = 7
+
+
+class RadiusAttr_NAS_Port_Type(_RadiusAttrIntEnumVal):
+    """RFC 2865"""
+    val = 61
+
+
+class _EAPPacketField(PacketField):
+
+    """
+    Handles EAP-Message attribute value (the actual EAP packet).
+    """
+
+    def m2i(self, pkt, m):
+        ret = None
+        eap_packet_len = struct.unpack("!H", m[2:4])[0]
+        if eap_packet_len < 254:
+            # If the EAP packet has not been fragmented, build a Scapy EAP
+            # packet from the data.
+            ret = EAP(m)
+        else:
+            ret = conf.raw_layer(m)
+        return ret
+
+
+class RadiusAttr_EAP_Message(RadiusAttribute):
+    """
+    Implements the "EAP-Message" attribute (RFC 3579).
+    """
+
+    name = "EAP-Message"
+    fields_desc = [
+        ByteEnumField("type", 79, _radius_attribute_types),
+        FieldLenField(
+            "len",
+            None,
+            "value",
+            "B",
+            adjust=lambda pkt, x: len(pkt.value) + 2
+        ),
+        _EAPPacketField("value", "", EAP)
+    ]
+
+
+class RadiusAttr_Vendor_Specific(RadiusAttribute):
+    """
+    Implements the "Vendor-Specific" attribute, as described in RFC 2865.
+    """
+
+    name = "Vendor-Specific"
+    fields_desc = [
+        ByteEnumField("type", 26, _radius_attribute_types),
+        FieldLenField(
+            "len",
+            None,
+            "value",
+            "B",
+            adjust=lambda pkt, x: len(pkt.value) + 8
+        ),
+        IntField("vendor_id", 0),
+        ByteField("vendor_type", 0),
+        FieldLenField(
+            "vendor_len",
+            None,
+            "value",
+            "B",
+            adjust=lambda p, x: len(p.value) + 2
+        ),
+        StrLenField("value", "", length_from=lambda p: p.vendor_len - 2)
+    ]
+
+
+class _RADIUSAttrPacketListField(PacketListField):
+    """
+    PacketListField handling a list of RADIUS attributes.
+    """
+
+    def getfield(self, pkt, s):
+        lst = []
+        length = None
+        ret = ""
+
+        if self.length_from is not None:
+            length = self.length_from(pkt)
+
+        if length is not None:
+            remain, ret = s[:length], s[length:]
+
+        while remain:
+            attr_len = struct.unpack("!B", remain[1])[0]
+            current = remain[:attr_len]
+            remain = remain[attr_len:]
+            packet = self.m2i(pkt, current)
+            lst.append(packet)
+
+        return remain + ret, lst
+
+
+# See IANA RADIUS Packet Type Codes registry
+_packet_codes = {
+    1: "Access-Request",
+    2: "Access-Accept",
+    3: "Access-Reject",
+    4: "Accounting-Request",
+    5: "Accounting-Response",
+    6: "Accounting-Status (now Interim Accounting)",
+    7: "Password-Request",
+    8: "Password-Ack",
+    9: "Password-Reject",
+    10: "Accounting-Message",
+    11: "Access-Challenge",
+    12: "Status-Server (experimental)",
+    13: "Status-Client (experimental)",
+    21: "Resource-Free-Request",
+    22: "Resource-Free-Response",
+    23: "Resource-Query-Request",
+    24: "Resource-Query-Response",
+    25: "Alternate-Resource-Reclaim-Request",
+    26: "NAS-Reboot-Request",
+    27: "NAS-Reboot-Response",
+    28: "Reserved",
+    29: "Next-Passcode",
+    30: "New-Pin",
+    31: "Terminate-Session",
+    32: "Password-Expired",
+    33: "Event-Request",
+    34: "Event-Response",
+    40: "Disconnect-Request",
+    41: "Disconnect-ACK",
+    42: "Disconnect-NAK",
+    43: "CoA-Request",
+    44: "CoA-ACK",
+    45: "CoA-NAK",
+    50: "IP-Address-Allocate",
+    51: "IP-Address-Release",
+    52: "Protocol-Error",
+    250: "Experimental Use",
+    251: "Experimental Use",
+    252: "Experimental Use",
+    253: "Experimental Use",
+    254: "Reserved",
+    255: "Reserved"
+}
 
 
 class Radius(Packet):
-    name = "Radius"
-    fields_desc = [ ByteEnumField("code", 1, {1: "Access-Request",
-                                              2: "Access-Accept",
-                                              3: "Access-Reject",
-                                              4: "Accounting-Request",
-                                              5: "Accounting-Accept",
-                                              6: "Accounting-Status",
-                                              7: "Password-Request",
-                                              8: "Password-Ack",
-                                              9: "Password-Reject",
-                                              10: "Accounting-Message",
-                                              11: "Access-Challenge",
-                                              12: "Status-Server",
-                                              13: "Status-Client",
-                                              21: "Resource-Free-Request",
-                                              22: "Resource-Free-Response",
-                                              23: "Resource-Query-Request",
-                                              24: "Resource-Query-Response",
-                                              25: "Alternate-Resource-Reclaim-Request",
-                                              26: "NAS-Reboot-Request",
-                                              27: "NAS-Reboot-Response",
-                                              29: "Next-Passcode",
-                                              30: "New-Pin",
-                                              31: "Terminate-Session",
-                                              32: "Password-Expired",
-                                              33: "Event-Request",
-                                              34: "Event-Response",
-                                              40: "Disconnect-Request",
-                                              41: "Disconnect-ACK",
-                                              42: "Disconnect-NAK",
-                                              43: "CoA-Request",
-                                              44: "CoA-ACK",
-                                              45: "CoA-NAK",
-                                              50: "IP-Address-Allocate",
-                                              51: "IP-Address-Release",
-                                              253: "Experimental-use",
-                                              254: "Reserved",
-                                              255: "Reserved"} ),
-                    ByteField("id", 0),
-                    FieldLenField("len", None, "attributes", "H" , adjust=lambda pkt,x:len(pkt.attributes)+20),
-                    StrFixedLenField("authenticator","",16),
-                    PacketListField("attributes", [], RadiusAttribute, length_from=lambda pkt:pkt.len-20) ]
+    """
+    Implements a RADIUS packet (RFC 2865).
+    """
+
+    name = "RADIUS"
+    fields_desc = [
+        ByteEnumField("code", 1, _packet_codes),
+        ByteField("id", 0),
+        FieldLenField(
+            "len",
+            None,
+            "attributes",
+            "H",
+            adjust=lambda pkt, x: len(pkt.attributes) + 20
+        ),
+        XStrFixedLenField("authenticator", "", 16),
+        _RADIUSAttrPacketListField(
+            "attributes",
+            [],
+            RadiusAttribute,
+            length_from=lambda pkt: pkt.len - 20
+        )
+    ]
+
+    def compute_authenticator(self, packed_request_auth, shared_secret):
+        """
+        Computes the authenticator field (RFC 2865 - Section 3)
+        """
+
+        if not conf.crypto_valid:
+            g_log_loading.info(_crypto_loading_failure_message)
+            return None
+
+        packed_hdr = struct.pack("!B", self.code)
+        packed_hdr += struct.pack("!B", self.id)
+        packed_hdr += struct.pack("!H", self.len)
+        packed_attrs = ''
+        for index in range(0, len(self.attributes)):
+            packed_attrs = packed_attrs + str(self.attributes[index])
+        packed_data = packed_hdr + packed_request_auth + packed_attrs +\
+            shared_secret
+
+        digest = hashes.Hash(hashes.MD5(), backend=default_backend())
+        digest.update(packed_data)
+        return digest.finalize()
+
 
     def post_build(self, p, pay):
         p += pay
-        l = self.len
-        if l is None:
-            l = len(p)
-            p = p[:2]+struct.pack("!H",l)+p[4:]
+        length = self.len
+        if length is None:
+            length = len(p)
+            p = p[:2] + struct.pack("!H", length) + p[4:]
         return p
 
 
diff --git a/test/regression.uts b/test/regression.uts
index 02e741310fdf48b8f92765cd0bc9ee7bdee101fe..843088abaefa4f6ac4d768e35482ab4691ef1b82 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -7547,16 +7547,177 @@ RIPEntry in p and RIPAuth in p and p[RIPAuth].password.startswith("scapy")
 
 ############
 ############
-+ Radius tests
++ RADIUS tests
 
-= Radius - build
+= IP/UDP/RADIUS - Build
 s = str(IP()/UDP(sport=1812)/Radius(authenticator="scapy")/RadiusAttribute(value="scapy"))
 s == b'E\x00\x007\x00\x01\x00\x00@\x11|\xb3\x7f\x00\x00\x01\x7f\x00\x00\x01\x07\x14\x07\x15\x00#U\xb2\x01\x00\x00\x1bscapy\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x07scapy'
 
-= Radius - dissection
+= IP/UDP/RADIUS - Dissection
 p = IP(s)
 Radius in p and len(p[Radius].attributes) == 1 and p[Radius].attributes[0].value == "scapy"
 
+= RADIUS - Access-Request - Dissection (1)
+s = b'\x01\xae\x01\x17>k\xd4\xc4\x19V\x0b*1\x99\xc8D\xea\xc2\x94Z\x01\x06leap\x06\x06\x00\x00\x00\x02\x1a\x1b\x00\x00\x00\t\x01\x15service-type=Framed\x0c\x06\x00\x00#\xee\x1e\x13AC-7E-8A-4E-E2-92\x1f\x1300-26-73-9E-0F-D3O\x0b\x02\x01\x00\t\x01leapP\x12U\xbc\x12\xcdM\x00\xf8\xdb4\xf1\x18r\xca_\x8c\xf6f\x02\x1a1\x00\x00\x00\t\x01+audit-session-id=0AC8090E0000001A0354CA00\x1a\x14\x00\x00\x00\t\x01\x0emethod=dot1x\x08\x06\xc0\xa8\n\xb9\x04\x06\xc0\xa8\n\x80\x1a\x1d\x00\x00\x00\t\x02\x17GigabitEthernet1/0/18W\x17GigabitEthernet1/0/18=\x06\x00\x00\x00\x0f\x05\x06\x00\x00\xc3\xc6'
+radius_packet = Radius(s)
+assert(radius_packet.id == 174)
+assert(radius_packet.len == 279)
+assert(radius_packet.authenticator == b'>k\xd4\xc4\x19V\x0b*1\x99\xc8D\xea\xc2\x94Z')
+assert(len(radius_packet.attributes) == 17)
+assert(radius_packet.attributes[0].type == 1)
+assert(type(radius_packet.attributes[0]) == RadiusAttribute)
+assert(radius_packet.attributes[0].len == 6)
+assert(radius_packet.attributes[0].value == "leap")
+assert(radius_packet.attributes[1].type == 6)
+assert(type(radius_packet.attributes[1]) == RadiusAttr_Service_Type)
+assert(radius_packet.attributes[1].len == 6)
+assert(radius_packet.attributes[1].value == 2)
+assert(radius_packet.attributes[2].type == 26)
+assert(type(radius_packet.attributes[2]) == RadiusAttr_Vendor_Specific)
+assert(radius_packet.attributes[2].len == 27)
+assert(radius_packet.attributes[2].vendor_id == 9)
+assert(radius_packet.attributes[2].vendor_type == 1)
+assert(radius_packet.attributes[2].vendor_len == 21)
+assert(radius_packet.attributes[2].value == "service-type=Framed")
+assert(radius_packet.attributes[6].type == 79)
+assert(type(radius_packet.attributes[6]) == RadiusAttr_EAP_Message)
+assert(radius_packet.attributes[6].len == 11)
+assert(radius_packet.attributes[6].value.haslayer(EAP))
+assert(radius_packet.attributes[6].value[EAP].code == 2)
+assert(radius_packet.attributes[6].value[EAP].id == 1)
+assert(radius_packet.attributes[6].value[EAP].len == 9)
+assert(radius_packet.attributes[6].value[EAP].type == 1)
+assert(hasattr(radius_packet.attributes[6].value[EAP], "identity"))
+assert(radius_packet.attributes[6].value[EAP].identity == "leap")
+assert(radius_packet.attributes[7].type == 80)
+assert(type(radius_packet.attributes[7]) == RadiusAttr_Message_Authenticator)
+assert(radius_packet.attributes[7].len == 18)
+assert(radius_packet.attributes[7].value == b'U\xbc\x12\xcdM\x00\xf8\xdb4\xf1\x18r\xca_\x8c\xf6')
+assert(radius_packet.attributes[11].type == 8)
+assert(type(radius_packet.attributes[11]) == RadiusAttr_Framed_IP_Address)
+assert(radius_packet.attributes[11].len == 6)
+assert(radius_packet.attributes[11].value == '192.168.10.185')
+assert(radius_packet.attributes[16].type == 5)
+assert(type(radius_packet.attributes[16]) == RadiusAttr_NAS_Port)
+assert(radius_packet.attributes[16].len == 6)
+assert(radius_packet.attributes[16].value == 50118)
+
+= RADIUS - Access-Challenge - Dissection (2)
+s = b'\x0b\xae\x00[\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8\x12\rHello, leapO\x16\x01\x02\x00\x14\x11\x01\x00\x08\xb8\xc4\x1a4\x97x\xd3\x82leapP\x12\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO'
+radius_packet = Radius(s)
+assert(radius_packet.id == 174)
+assert(radius_packet.len == 91)
+assert(radius_packet.authenticator == b'\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8')
+assert(len(radius_packet.attributes) == 4)
+assert(radius_packet.attributes[0].type == 18)
+assert(type(radius_packet.attributes[0]) == RadiusAttribute)
+assert(radius_packet.attributes[0].len == 13)
+assert(radius_packet.attributes[0].value == "Hello, leap")
+assert(radius_packet.attributes[1].type == 79)
+assert(type(radius_packet.attributes[1]) == RadiusAttr_EAP_Message)
+assert(radius_packet.attributes[1].len == 22)
+assert(radius_packet.attributes[1][EAP].code == 1)
+assert(radius_packet.attributes[1][EAP].id == 2)
+assert(radius_packet.attributes[1][EAP].len == 20)
+assert(radius_packet.attributes[1][EAP].type == 17)
+assert(radius_packet.attributes[2].type == 80)
+assert(type(radius_packet.attributes[2]) == RadiusAttr_Message_Authenticator)
+assert(radius_packet.attributes[2].len == 18)
+assert(radius_packet.attributes[2].value == b'\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c')
+assert(radius_packet.attributes[3].type == 24)
+assert(type(radius_packet.attributes[3]) == RadiusAttr_State)
+assert(radius_packet.attributes[3].len == 18)
+assert(radius_packet.attributes[3].value == b'iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO')
+
+= RADIUS - Access-Request - Dissection (3)
+s = b'\x01\xaf\x01DC\xbe!J\x08\xdf\xcf\x9f\x00v~,\xfb\x8e`\xc8\x01\x06leap\x06\x06\x00\x00\x00\x02\x1a\x1b\x00\x00\x00\t\x01\x15service-type=Framed\x0c\x06\x00\x00#\xee\x1e\x13AC-7E-8A-4E-E2-92\x1f\x1300-26-73-9E-0F-D3O&\x02\x02\x00$\x11\x01\x00\x18\rE\xc9\x92\xf6\x9ae\x04\xa2\x06\x13\x8f\x0b#\xf1\xc56\x8eU\xd9\x89\xe5\xa1)leapP\x12|\x1c\x9d[dv\x9c\x19\x96\xc6\xec\xb82\x8f\n f\x02\x1a1\x00\x00\x00\t\x01+audit-session-id=0AC8090E0000001A0354CA00\x1a\x14\x00\x00\x00\t\x01\x0emethod=dot1x\x08\x06\xc0\xa8\n\xb9\x04\x06\xc0\xa8\n\x80\x1a\x1d\x00\x00\x00\t\x02\x17GigabitEthernet1/0/18W\x17GigabitEthernet1/0/18=\x06\x00\x00\x00\x0f\x05\x06\x00\x00\xc3\xc6\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO'
+radius_packet = Radius(s)
+assert(radius_packet.id == 175)
+assert(radius_packet.len == 324)
+assert(radius_packet.authenticator == 'C\xbe!J\x08\xdf\xcf\x9f\x00v~,\xfb\x8e`\xc8')
+assert(len(radius_packet.attributes) == 18)
+assert(radius_packet.attributes[0].type == 1)
+assert(type(radius_packet.attributes[0]) == RadiusAttribute)
+assert(radius_packet.attributes[0].len == 6)
+assert(radius_packet.attributes[0].value == "leap")
+assert(radius_packet.attributes[1].type == 6)
+assert(type(radius_packet.attributes[1]) == RadiusAttr_Service_Type)
+assert(radius_packet.attributes[1].len == 6)
+assert(radius_packet.attributes[1].value == 2)
+assert(radius_packet.attributes[2].type == 26)
+assert(type(radius_packet.attributes[2]) == RadiusAttr_Vendor_Specific)
+assert(radius_packet.attributes[2].len == 27)
+assert(radius_packet.attributes[2].vendor_id == 9)
+assert(radius_packet.attributes[2].vendor_type == 1)
+assert(radius_packet.attributes[2].vendor_len == 21)
+assert(radius_packet.attributes[2].value == "service-type=Framed")
+assert(radius_packet.attributes[6].type == 79)
+assert(type(radius_packet.attributes[6]) == RadiusAttr_EAP_Message)
+assert(radius_packet.attributes[6].len == 38)
+assert(radius_packet.attributes[6].value.haslayer(EAP))
+assert(radius_packet.attributes[6].value[EAP].code == 2)
+assert(radius_packet.attributes[6].value[EAP].id == 2)
+assert(radius_packet.attributes[6].value[EAP].len == 36)
+assert(radius_packet.attributes[6].value[EAP].type == 17)
+assert(radius_packet.attributes[7].type == 80)
+assert(type(radius_packet.attributes[7]) == RadiusAttr_Message_Authenticator)
+assert(radius_packet.attributes[7].len == 18)
+assert(radius_packet.attributes[7].value == b'|\x1c\x9d[dv\x9c\x19\x96\xc6\xec\xb82\x8f\n ')
+assert(radius_packet.attributes[11].type == 8)
+assert(type(radius_packet.attributes[11]) == RadiusAttr_Framed_IP_Address)
+assert(radius_packet.attributes[11].len == 6)
+assert(radius_packet.attributes[11].value == '192.168.10.185')
+assert(radius_packet.attributes[16].type == 5)
+assert(type(radius_packet.attributes[16]) == RadiusAttr_NAS_Port)
+assert(radius_packet.attributes[16].len == 6)
+assert(radius_packet.attributes[16].value == 50118)
+assert(radius_packet.attributes[17].type == 24)
+assert(type(radius_packet.attributes[17]) == RadiusAttr_State)
+assert(radius_packet.attributes[17].len == 18)
+assert(radius_packet.attributes[17].value == b'iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO')
+
+= RADIUS - Access-Challenge - Dissection (4)
+s = b'\x0b\xaf\x00K\x82 \x95=\xfd\x80\x05 -l}\xab)\xa5kU\x12\rHello, leapO\x06\x03\x03\x00\x04P\x12l0\xb9\x8d\xca\xfc!\xf3\xa7\x08\x80\xe1\xf6}\x84\xff\x18\x12iQs\xf7hRb@k\x9d,\xa0\x99\x8ehO'
+radius_packet = Radius(s)
+assert(radius_packet.id == 175)
+assert(radius_packet.len == 75)
+assert(radius_packet.authenticator == b'\x82 \x95=\xfd\x80\x05 -l}\xab)\xa5kU')
+assert(len(radius_packet.attributes) == 4)
+assert(radius_packet.attributes[0].type == 18)
+assert(type(radius_packet.attributes[0]) == RadiusAttribute)
+assert(radius_packet.attributes[0].len == 13)
+assert(radius_packet.attributes[0].value == "Hello, leap")
+assert(radius_packet.attributes[1].type == 79)
+assert(type(radius_packet.attributes[1]) == RadiusAttr_EAP_Message)
+assert(radius_packet.attributes[1].len == 6)
+assert(radius_packet.attributes[1][EAP].code == 3)
+assert(radius_packet.attributes[1][EAP].id == 3)
+assert(radius_packet.attributes[1][EAP].len == 4)
+assert(radius_packet.attributes[2].type == 80)
+assert(type(radius_packet.attributes[2]) == RadiusAttr_Message_Authenticator)
+assert(radius_packet.attributes[2].len == 18)
+assert(radius_packet.attributes[2].value == b'l0\xb9\x8d\xca\xfc!\xf3\xa7\x08\x80\xe1\xf6}\x84\xff')
+assert(radius_packet.attributes[3].type == 24)
+assert(type(radius_packet.attributes[3]) == RadiusAttr_State)
+assert(radius_packet.attributes[3].len == 18)
+assert(radius_packet.attributes[3].value == b'iQs\xf7hRb@k\x9d,\xa0\x99\x8ehO')
+
+= RADIUS - Response Authenticator computation
+~ crypto
+s = b'\x01\xae\x01\x17>k\xd4\xc4\x19V\x0b*1\x99\xc8D\xea\xc2\x94Z\x01\x06leap\x06\x06\x00\x00\x00\x02\x1a\x1b\x00\x00\x00\t\x01\x15service-type=Framed\x0c\x06\x00\x00#\xee\x1e\x13AC-7E-8A-4E-E2-92\x1f\x1300-26-73-9E-0F-D3O\x0b\x02\x01\x00\t\x01leapP\x12U\xbc\x12\xcdM\x00\xf8\xdb4\xf1\x18r\xca_\x8c\xf6f\x02\x1a1\x00\x00\x00\t\x01+audit-session-id=0AC8090E0000001A0354CA00\x1a\x14\x00\x00\x00\t\x01\x0emethod=dot1x\x08\x06\xc0\xa8\n\xb9\x04\x06\xc0\xa8\n\x80\x1a\x1d\x00\x00\x00\t\x02\x17GigabitEthernet1/0/18W\x17GigabitEthernet1/0/18=\x06\x00\x00\x00\x0f\x05\x06\x00\x00\xc3\xc6'
+access_request = Radius(s)
+s = b'\x0b\xae\x00[\xc7\xae\xfc6\xa1=\xb5\x99&^\xdf=\xe9\x00\xa6\xe8\x12\rHello, leapO\x16\x01\x02\x00\x14\x11\x01\x00\x08\xb8\xc4\x1a4\x97x\xd3\x82leapP\x12\xd3\x12\x17\xa6\x0c.\x94\x85\x03]t\xd1\xdb\xd0\x13\x8c\x18\x12iQs\xf7iSb@k\x9d,\xa0\x99\x8ehO'
+access_challenge = Radius(s)
+access_challenge.compute_authenticator(access_request.authenticator, "radiuskey") == access_challenge.authenticator
+
+= RADIUS - Layers (1)
+radius_attr = RadiusAttr_EAP_Message(value = EAP())
+assert(RadiusAttr_EAP_Message in radius_attr)
+assert(RadiusAttribute in radius_attr)
+type(radius_attr[RadiusAttribute])
+assert(type(radius_attr[RadiusAttribute]) == RadiusAttr_EAP_Message)
+assert(EAP in radius_attr.value)
+
 
 ############
 ############