diff --git a/README.md b/README.md
index 6f8835bba4fdec5992f8a7a36e306bc89379c2dc..e5f9ebc4f9e281f9de67327a48fa1983c95a839e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[PACKAGE]: ../../raw/master/mkp/check_radius-0.0.1-20240421.mkp "check_radius-0.0.1-20240421.mkp"
+[PACKAGE]: ../../raw/master/mkp/check_radius-0.1.0-20240428.mkp "check_radius-0.1.0-20240428.mkp"
 # Check RADIUS
 
 This is a (very) basic active RADIUS check. Tests if a RADIUS server is responsive (accept/reject/timeout). There is (limited) support to add AV-pairs to the RADIUS request.
diff --git a/mkp/check_radius-0.1.0-20240428.mkp b/mkp/check_radius-0.1.0-20240428.mkp
new file mode 100644
index 0000000000000000000000000000000000000000..c895811b07fc9b346597ffd6feffbc1f8170408e
Binary files /dev/null and b/mkp/check_radius-0.1.0-20240428.mkp differ
diff --git a/source/checks/check_radius b/source/checks/check_radius
index eaa316ccf62ee5d8b362af8f23c6e1108a317835..352190350c977cc390bdc4c6f3459ba87b02d9f6 100644
--- a/source/checks/check_radius
+++ b/source/checks/check_radius
@@ -14,32 +14,53 @@
 def check_radius_arguments(params):
     args = []
 
-    if server := params.get('server'):
+    if (server := params.get('server')) is not None:
         args.extend(['-H', server])
     else:
         args.append('-H $HOSTADDRESS$')
 
-    if auth_port := params.get("auth_port"):
-        args.extend(['--authport', auth_port])
+    if (auth_port := params.get("auth_port")) is not None:
+        args.extend(['--auth-port', auth_port])
 
-    if secret := params.get("secret"):
+    if (secret := params.get("secret")) is not None:
         args.extend(["--secret", passwordstore_get_cmdline("%s", secret)])
 
-    if user_name := params.get("user_name"):
+    if (user_name := params.get("user_name")) is not None:
         args.extend([f'--username', user_name])
 
-    if user_password := params.get("user_password"):
+    if (user_password := params.get("user_password")) is not None:
         args.extend(["--password", passwordstore_get_cmdline("%s", user_password)])
 
-    if timeout := params.get('timeout'):
-        args.extend(['-timeout', timeout])
+    if (timeout := params.get('timeout')) is not None:
+        args.extend(['--timeout', timeout])
+
+    if (request_attributes := params.get('request_params').get('request_attributes')) is not None:
+        for av_name, av_value in request_attributes:
+            args.extend(['--request-attribute', f'{av_name}:{av_value}'])
+
+    if (expected_response := params.get('response_params').get('expected_response')) is not None:
+        args.extend(['--expected-response', expected_response])
+
+    if (state_not_expected_response := params.get('response_params').get('state_not_expected_response')) is not None:
+        args.extend(['--state-not-expected-response', state_not_expected_response])
+
+    if (num_resp_attributes := params.get('response_params').get('num_resp_attributes')) is not None:
+        args.extend(['--num-resp-attributes', num_resp_attributes])
+
+    if (state_wrong_number_of_response_attributes := params.get('response_params').get(
+            'state_wrong_number_of_response_attributes')) is not None:
+        args.extend(['--state-wrong-num-resp-attributes', state_wrong_number_of_response_attributes])
+
+    if (level_upper_response_time := params.get('response_params').get('level_upper_response_time')) is not None:
+        warn, crit = level_upper_response_time
+        args.extend(['--max-response-time', f'{warn}, {crit}'])
 
     return args
 
 
 def _check_description(params):
     if 'description' in params:
-        return f'RADIUS server {params["description"]}'
+        return f'RADIUS {params["description"]}'
 
     return 'RADIUS server'
 
diff --git a/source/gui/metrics/check_radius.py b/source/gui/metrics/check_radius.py
index 5c8cff2d37eb286eab8a4daaa3e67c47783a8052..67790d936ba06f7cb8f4428512b353c4ffd0da2b 100644
--- a/source/gui/metrics/check_radius.py
+++ b/source/gui/metrics/check_radius.py
@@ -18,8 +18,8 @@ from cmk.gui.plugins.metrics.utils import (
     perfometer_info
 )
 
-metric_info['radius_request_time'] = {
-    'title': _('Request time'),
+metric_info['radius_response_time'] = {
+    'title': _('Response time'),
     'unit': 's',
     'color': '#9a52bf',
 }
@@ -27,17 +27,17 @@ metric_info['radius_request_time'] = {
 graph_info['check_radius_time'] = {
     'title': _('RADIUS request time'),
     'metrics': [
-        ('radius_request_time', 'area'),
+        ('radius_response_time', 'area'),
     ],
     'scalars': [
-        ('radius_request_time:crit', _('Crit')),
-        ('radius_request_time:warn', _('Warn')),
+        ('radius_response_time:crit', _('Crit')),
+        ('radius_response_time:warn', _('Warn')),
     ],
 }
 
 perfometer_info.append({
     'type': 'logarithmic',
-    'metric': 'radius_request_time',
+    'metric': 'radius_response_time',
     'half_value': 1.0,
     'exponent': 10.0,
 })
diff --git a/source/gui/wato/check_parameters/check_radius.py b/source/gui/wato/check_parameters/check_radius.py
index d38398d35ae7d0a57649ebea1663a574716f9ca7..71dd1d8c8eb0d373222188b480412f94e70da35e 100644
--- a/source/gui/wato/check_parameters/check_radius.py
+++ b/source/gui/wato/check_parameters/check_radius.py
@@ -12,15 +12,153 @@
 # 2024-01-01: modified for cmk 2.2.x
 
 from cmk.gui.i18n import _
+from cmk.gui.plugins.wato.active_checks.common import RulespecGroupActiveChecks
+from cmk.gui.plugins.wato.utils import HostRulespec, IndividualOrStoredPassword, rulespec_registry
 from cmk.gui.valuespec import (
+    Alternative,
     Dictionary,
+    DropdownChoice,
+    FixedValue,
+    Foldable,
+    IPv4Address,
     Integer,
-    TextAscii,
+    ListOf,
+    MonitoringState,
+    TextInput,
     Transform,
+    Tuple,
 )
 
-from cmk.gui.plugins.wato.active_checks.common import RulespecGroupActiveChecks
-from cmk.gui.plugins.wato.utils import HostRulespec, rulespec_registry, IndividualOrStoredPassword
+_called_station_id = Tuple(
+    title='Called-Station-Id',
+    orientation='horizontal',
+    elements=[
+        FixedValue('Called-Station-Id'),  # , totext='' # add empty totext to remove "duplicate" attribute name
+        TextInput(
+            size=20,
+            placeholder='AA-BB-CC-DD-EE-FF',
+            allow_empty=False,
+        ),
+    ],
+)
+_calling_station_id = Tuple(
+    title='Calling-Station-Id',
+    orientation='horizontal',
+    elements=[
+        FixedValue('Calling-Station-Id'),
+        TextInput(
+            size=20,
+            placeholder='AA-BB-CC-DD-EE-FF',
+            allow_empty=False,
+        ),
+    ],
+)
+_framed_mtu = Tuple(
+    title='Framed-MTU',
+    orientation='horizontal',
+    elements=[
+        FixedValue('Framed-MTU'),
+        Integer(
+            size=5,
+            default_value=1500
+        ),
+    ],
+)
+_nas_identifier = Tuple(
+    title='NAS-Identifier',
+    orientation='horizontal',
+    elements=[
+        FixedValue('NAS-Identifier'),
+        TextInput(
+            size=20,
+            placeholder='NAS001',
+            allow_empty=False,
+        ),
+    ],
+)
+_nas_ip_address = Tuple(
+    title='NAS-IP-Address',
+    orientation='horizontal',
+    elements=[
+        FixedValue('NAS-IP-Address'),
+        IPv4Address(),
+    ],
+)
+_nas_port_id = Tuple(
+    title='NAS-Port-Id',
+    orientation='horizontal',
+    elements=[
+        FixedValue('NAS-Port-Id'),
+        TextInput(
+            size=20,
+            placeholder='GigabitEthernet0/8',
+            allow_empty=False,
+        ),
+    ],
+)
+_nas_port_type = Tuple(
+    title='NAS-Port-Type',
+    orientation='horizontal',
+    elements=[
+        FixedValue('NAS-Port-Type'),
+        DropdownChoice(
+            choices=[
+                ('0', 'Async'),
+                ('1', 'Sync'),
+                ('2', 'ISDN'),
+                ('3', 'ISDN-V120'),
+                ('4', 'ISDN-V110'),
+                ('5', 'Virtual'),
+                ('6', 'PIAFS'),
+                ('7', 'HDLC-Clear-Channel'),
+                ('8', 'X.25'),
+                ('9', 'X.75'),
+                ('10', 'G.3-Fax'),
+                ('11', 'SDSL'),
+                ('12', 'ADSL-CAP'),
+                ('13', 'ADSL-DMT'),
+                ('14', 'IDSL'),
+                ('15', 'Ethernet'),
+                ('16', 'xDSL'),
+                ('17', 'Cable'),
+                ('18', 'Wireless-Other'),
+                ('19', 'Wireless-802.11'),
+            ]
+        ),
+    ],
+)
+_nas_port = Tuple(
+    title='NAS-Port',
+    orientation='horizontal',
+    elements=[
+        FixedValue('NAS-Port'),
+        Integer(
+            size=7,
+        ),
+    ],
+)
+_service_type = Tuple(
+    title='Service-Type',
+    orientation='horizontal',
+    elements=[
+        FixedValue('Service-Type'),
+        DropdownChoice(
+            choices=[
+                ('1', 'Login-User'),
+                ('2', 'Framed-User'),
+                ('3', 'Callback-Login-User'),
+                ('4', 'Callback-Framed-User'),
+                ('5', 'Outbound-User'),
+                ('6', 'Administrative-User'),
+                ('7', 'NAS-Prompt-User'),
+                ('8', 'Authenticate-Only'),
+                ('9', 'Callback-NAS-Prompt'),
+                ('10', 'Call-Check'),
+                ('11', 'Callback-Administrative'),
+            ]
+        ),
+    ],
+)
 
 
 def _valuespec_active_checks_radius():
@@ -30,49 +168,51 @@ def _valuespec_active_checks_radius():
             help=_(''),
             elements=[
                 ('description',
-                 TextAscii(
+                 TextInput(
                      title=_('Service description'),
                      help=_(
-                         'Must be unique for every host. The service description starts always with \"RADIUS server\".'),
+                         'Must be unique for every host. The service description starts always with \"RADIUS server\".'
+                     ),
                      size=50,
                      placeholder='Item name for the service',
                      allow_empty=False,
                  )),
                 ('server',
-                 TextAscii(
+                 TextInput(
                      title=_('Server IP-address or name'),
                      help=_(
                          'Hostname or IP-address to monitor. Default is the host name/IP-Address of the monitored host.'
                      ),
                      size=50,
                      allow_empty=False,
+                     placeholder='i.e 192.168.10.10 or srvrad01.company.intern'
                  )),
                 ('auth_port',
                  Integer(
-                     title=_('RADIUS authentication port'),
+                     title=_('Authentication port'),
                      help=_('The RADIUS port to use for authentication. Default is 1812.'),
-                     # size=5,
+                     size=5,
                      default_value=1812,
                      minvalue=1,
                      maxvalue=65535,
                  )),
                 ('secret',
                  IndividualOrStoredPassword(
-                     title=_('Server secret'),
-                     help=_('The RADIUS secret.'),
-                     # size=50,
+                     title=_('Shared secret'),
+                     help=_('The shared secret.'),
                      allow_empty=False,
                  )),
                 ('timeout',
                  Integer(
-                     title=_('Server timeout'),
-                     help=_('The user password.'),
+                     title=_('Request timeout'),
+                     help=_('The timeout for the RADIUS request.'),
                      default_value=2,
                      minvalue=1,
                      maxvalue=30,
+                     unit='s',
                  )),
                 ('user_name',
-                 TextAscii(
+                 TextInput(
                      title=_('User name'),
                      help=_('The user name to use in the request.'),
                      size=50,
@@ -83,11 +223,85 @@ def _valuespec_active_checks_radius():
                  IndividualOrStoredPassword(
                      title=_('User password'),
                      help=_('The user password.'),
-                     # size=50,
                      allow_empty=False
                  )),
+                ('request_params',
+                 Foldable(
+                     Dictionary(
+                         title="Hide/Show Request Parameters",
+                         elements=[
+                             ('request_attributes',
+                              ListOf(
+                                  Alternative(
+                                      orientation='horizontal',
+                                      elements=[
+                                          _called_station_id,
+                                          _calling_station_id,
+                                          _framed_mtu,
+                                          _nas_identifier,
+                                          _nas_ip_address,
+                                          _nas_port,
+                                          _nas_port_id,
+                                          _nas_port_type,
+                                          _service_type,
+                                      ],
+                                  ),
+                                  title=_('Request Attributes'),
+                                  add_label=_('add attribute'),
+                              )),
+                         ],
+                     ),
+                     title='Request paranmeters',
+                 )),
+                ('response_params',
+                 Foldable(
+                     Dictionary(
+                         title="Hide/Show Response Parameters",
+                         elements=[
+                             ('expected_response',
+                              DropdownChoice(
+                                  choices=(
+                                      (2, 'Accepted'),
+                                      (3, 'Rejected'),
+                                  ),
+                                  title=_('Expected response'),
+                                  help=_('Expected response from the RADIUS server.'),
+                              )),
+                             ('state_not_expected_response',
+                              MonitoringState(
+                                  title=_('Monitoring state not expected response'),
+                                  default_value=2,
+                              )),
+                             ('level_upper_response_time',
+                              Tuple(
+                                  elements=[
+                                      Integer(title=_('Warning at'), unit='ms', minvalue=0, maxvalue=10000),
+                                      Integer(title=_('Critical at'), unit='ms', minvalue=0, maxvalue=10000),
+                                  ],
+                                  title=_('Max. response time'),
+                              )),
+                             ('num_resp_attributes',
+                              Integer(
+                                  title=_('# of expected attribues in response'),
+                                  help=_('The expected number of RADIUS attibutes in the response.'),
+                                  minvalue=0,
+                                  maxvalue=65535,
+                              )),
+                             ('state_wrong_number_of_response_attributes',
+                              MonitoringState(
+                                  title=_('Monitoring state on wrong # of response attributes'),
+                                  default_value=1,
+                              )),
+                         ],
+                     ),
+                     title='Response paranmeters',
+                 ))
             ],
-            required_keys=['secret']
+            required_keys=[
+                'secret',
+                'request_params',
+                'response_params',
+            ]
         ),
     )
 
diff --git a/source/lib/nagios/plugins/check_radius b/source/lib/nagios/plugins/check_radius
index 4680980d163fb9c979abae40296bfc20a073f5d7..2147c1fb272c5e898485f36d218cd8947869ed58 100755
--- a/source/lib/nagios/plugins/check_radius
+++ b/source/lib/nagios/plugins/check_radius
@@ -13,48 +13,146 @@
 #
 # https://github.com/pyradius/pyrad
 #
-import socket
 
-from typing import Sequence
-import sys
-from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, Namespace, ArgumentTypeError
-from time import time_ns
+from argparse import (
+    ArgumentDefaultsHelpFormatter,
+    ArgumentParser,
+    ArgumentTypeError,
+    Namespace,
+)
 from os import environ
+from socket import error as socket_error
+from sys import (
+    argv as sys_argv,
+    exit as sys_exit,
+    stdout as sys_stdout,
+)
+from time import time_ns
+from typing import Sequence, Tuple
 
 import cmk.utils.password_store
 
 no_radiuslib = False
 try:
-    from pyrad.client import Client as rad_client
-    from pyrad.dictionary import Dictionary as rad_dictionary
-    import pyrad.packet
+    from pyrad.client import Client as radClient
+    from pyrad.dictionary import Dictionary as radDictionary
+    from pyrad.packet import AccessAccept, AccessReject, AccessRequest
+    from pyrad.client import Timeout as pyTimeout
 except ModuleNotFoundError:
     no_radiuslib = True
 
 
-def parse_arguments(argv: Sequence[str]) -> Namespace:
+class Args(Namespace):
+    host: str
+    auth_port: int
+    secret: str
+    timeout: int
+    username: str
+    password: str
+    num_resp_attributes: int
+    state_wrong_num_resp_attributes: int
+    request_attribute: Tuple[str, str]
+    max_response_time: Tuple[int, int]
+    expected_response: int
+    state_not_expected_response: int
+
+
+VERSION = '0.1.0-20240428'
+
+cmk_state = {
+    0: '',
+    1: '(!)',
+    2: '(!!)',
+    3: '(?)',
+}
+response_str = {
+    2: 'accept',
+    3: 'reject',
+}
+
+
+def parse_arguments(argv: Sequence[str]) -> Args:
+    def _av_pair(s):
+        try:
+            name, value = s.split(':')
+            return name, value
+        except ValueError:
+            raise ArgumentTypeError("AV-Pairs must be in the form of name:vale")
+
+    def _levels(s) -> Tuple[int, int]:
+        try:
+            warn, crit = s.split(',')
+            warn = int(warn)
+            crit = int(crit)
+            return warn, crit
+        except ValueError:
+            raise ArgumentTypeError("Levels must be in the form 'warn,crit' value")
+
     parser = ArgumentParser(
+        description='This is a (very) basic active RADIUS check for Check_mk. Tests if a RADIUS server is responsive '
+                    '(accept/reject/timeout). There is (limited) support to add AV-pairs to the RADIUS request.',
         formatter_class=ArgumentDefaultsHelpFormatter,
-        epilog=''
+        epilog=f'(c) thl-cmk[at]outlook[dot], Version: {VERSION}, For more information see: https://thl-cmk.hopto.org'
     )
+    #
+    # required request parameters
+    #
     parser.add_argument(
         '-H', '--host', required=True,
-        help='Host/IP-Address of RADIUS server to query (required)')
+        help='Host/IP-Address of RADIUS server to query (required)',
+    )
     parser.add_argument(
         '--secret', required=True,
-        help='secret RADIUS key')
+        help='secret RADIUS key',
+    )
     parser.add_argument(
-        '--username', default='dummyuser',
-        help='user name to test with')
+        '--username', default='dummyuser', required=True,
+        help='user name to test with',
+    )
     parser.add_argument(
-        '--password', default='dummyuser',
-        help='user password to test with')
+        '--password', default='dummypassword', required=True,
+        help='user password to test with',
+    )
+    #
+    # optional request parameters
+    #
     parser.add_argument(
-        '--authport', type=int, default=1812,
-        help='RADIUS authentication port to use.')
+        '--auth_port', type=int, default=1812,
+        help='RADIUS authentication port to use.',
+    )
     parser.add_argument(
         '--timeout', type=int, default=1,
-        help='RADIUS server timeout.')
+        help='RADIUS server timeout',
+    )
+    parser.add_argument(
+        '--request-attribute', nargs='*', type=_av_pair, action='append', default=[],
+        help='add request attribute in the form of "attribute-name:attribute-value" '
+             'ie: "Called-Station-Id:AA-BB-CC-DD-EE-FF". Repeat to add more attributes. '
+             'For valid attributes the dictionary file.',
+    )
+    #
+    # response parameters
+    #
+    parser.add_argument(
+        '--expected-response', type=int, choices=[2, 3],
+        help=' 2 -> Accepted, 3 -> Rejected',
+    )
+    parser.add_argument(
+        '--state-not-expected-response', type=int, choices=[0, 1, 2, 3], default=1,
+        help='Monitoring state: 0 -> OK, 1 -> WARN, 2 -> CRIT, 3 -> UNKNOWN',
+    )
+    parser.add_argument(
+        '--num-resp-attributes', type=int,
+        help='Expected number of response attributes',
+    )
+    parser.add_argument(
+        '--state-wrong-num-resp-attributes', type=int, choices=[0, 1, 2, 3], default=1,
+        help='Monitoring state: 0 -> OK, 1 -> WARN, 2 -> CRIT, 3 -> UNKNOWN',
+    )
+    parser.add_argument(
+        '--max-response-time', type=_levels,
+        help='Upper levels for response time in ms in the format WARN,CRIT time. ie: 10,50'
+    )
 
     args = parser.parse_args(argv)
     args.host = args.host.strip(' ')
@@ -63,80 +161,130 @@ def parse_arguments(argv: Sequence[str]) -> Namespace:
 
 def main(args=None):
     if args is None:
-        args = sys.argv[1:]  # without the path/plugin itself
+        args = sys_argv[1:]  # without the path/plugin itself
 
     args = parse_arguments(args)
 
     if no_radiuslib:
-        sys.stdout.write(
-            'To use this check plugin you need to install the python pyrad lib in your CMK python environment.\n'
+        sys_stdout.write(
+            'To use this check plugin you need to install the python pyrad lib in your CMK python environment.(!!!)\n'
         )
-        sys.exit(3)
+        sys_exit(3)
 
     omd_root = environ["OMD_ROOT"]
-    info_text = ''
-    long_output = ''
-    perf_data = ''
+    info_text = []
+    long_output = []
+    perf_data = []
     status = 0
 
-    rad_server = rad_client(
+    rad_server = radClient(
         server=args.host,
-        authport=args.authport,
+        authport=args.auth_port,
         secret=args.secret.encode('utf-8'),
-        dict=rad_dictionary(f'{omd_root}/local/lib/nagios/plugins/dictionary'),
+        # freeradius dictionaries are under /usr/share/freeradius/
+        dict=radDictionary(f'{omd_root}/local/lib/nagios/plugins/dictionary'),
         timeout=args.timeout,
     )
 
     rad_req = rad_server.CreateAuthPacket(
-        code=pyrad.packet.AccessRequest,
+        code=AccessRequest,
         User_Name=args.username,
         NAS_Identifier=args.host,
     )
     rad_req["User-Password"] = rad_req.PwCrypt(args.password)
+
+    # add optional request attributes
+    for av_pair in args.request_attribute:
+        name, value = av_pair[0]
+        try:
+            rad_req[name] = value
+        except TypeError:
+            sys_stdout.write(
+                f'WARNING: attribute value must be the real value not the name of the '
+                f'value: {value}{cmk_state[1]}{cmk_state[1]}'
+            )
+            status = max(status, 1)
+            continue
+
     before_request_time = time_ns()
     try:
         response = rad_server.SendPacket(rad_req)
-    except pyrad.client.Timeout as e:
-        status = 2
-        info_text = 'Radius request timeout'
-        long_output += f'\nRadius request timeout.\n{e}'
-    except socket.error as e:
-        status = 2
-        info_text = 'Network error'
-        long_output += f'\nNetwork error\n{e}'
+    except pyTimeout as e:
+        status = max(status, 2)
+        message = f'Radius request timeout{cmk_state[2]}'
+        info_text.append(message)
+        long_output.append(f'{message}\n{e}')
+    except socket_error as e:
+        status = max(status, 2)
+        message = f'Network error{cmk_state[2]}'
+        info_text.append(message)
+        long_output.append(f'{message}\n{e}')
     else:
-        request_time = (time_ns() - before_request_time) / 1000 / 1000 / 1000  # -> ns to seconds
-        match response.code:
-            case pyrad.packet.AccessAccept:
-                info_text += 'Response: access accept'
-                long_output += '\nResponse: access accept'
-                long_output += f'\nResponse code: {response.code}'
-                if response.has_key:
-                    long_output += f'\nNumber of attributes in response: {len(response.keys())}'
-                    long_output += f'\n\nResponse attributes:'
-                    for key in response.keys():
-                        long_output += f'\n{key}: {response.get(key)}'
+        # first: calculate response time
+        response_time = (time_ns() - before_request_time) / 1000 / 1000 / 1000  # -> ns to seconds
+
+        #
+        # second: check response code
+        message = f'Response: access {response_str.get(response.code, f"unknown ({response.code})")}'
+        if args.expected_response and response.code != args.expected_response:
+            message += f' (expected: {response_str[args.expected_response]}{cmk_state[args.state_not_expected_response]})'
+            status = max(status, args.state_not_expected_response)
+        info_text.append(message)
+        long_output.append(message)
+
+        # third: check response time
+        message = f'Response time {response_time * 1000:.0f}ms'
+        if args.max_response_time:
+            warn, crit = args.max_response_time
+            warn = warn
+            crit = crit
+            if response_time >= warn / 1000:
+                message += f' (WARN/CRIT at {warn}/{crit}'
+                if response_time >= crit / 1000:
+                    message += cmk_state[2]
+                    status = max(status, 2)
                 else:
-                    long_output += f'\nNo attributes in response: {len(response.keys())}'
-            case pyrad.packet.AccessReject:
-                info_text += 'Response: access reject'
-                long_output += '\nResponse: access reject'
-                long_output += f'\nResponse code: {response.code}'
-            case _:
-                info_text += f'Response: code unknown'
-                long_output += f'\nResponse: code unknown'
-                long_output += f'\nResponse code: {response.code}'
-                status = 3
-
-        perf_data += f'radius_request_time={request_time}'
-
-    info_text = info_text.strip(',').strip(' ')
-    sys.stdout.write(f'{info_text}\n{long_output} | {perf_data}\n')
+                    message += cmk_state[1]
+                    status = max(status, 1)
+            perf_data.append(f'radius_response_time={response_time};{warn};{crit};;')
+        else:
+            perf_data.append(f'radius_response_time={response_time}')
+        info_text.append(message)
+        long_output.append(message)
+
+        if response.code == AccessAccept:
+            #
+            # forth: check return attributes
+            if response.has_key:
+                message = f'Number of attributes in response: {len(response.keys())}'
+            else:
+                message = long_output.append('No return attributes in response')
 
+            if args.num_resp_attributes and len(response.keys()) != args.num_resp_attributes:
+                message += f' (expected {args.num_resp_attributes}{cmk_state[args.state_wrong_num_resp_attributes]})'
+                status = max(status, args.state_wrong_num_resp_attributes)
+                info_text.append(message)
+
+            long_output.append(message)
+
+            if response.has_key:
+                long_output.append('\nResponse attributes:')
+                for key in response.keys():
+                    long_output.append(f'{key}: {response.get(key)}')
+
+    #
+    # format output data
+    info_text = ', '.join(info_text)
+    long_output = '\n'.join(long_output)
+    perf_data = '|'.join(perf_data)
+    if perf_data:
+        sys_stdout.write(f'{info_text}\n{long_output}|{perf_data}\n')
+    else:
+        sys_stdout.write(f'{info_text}\n{long_output}')
     return status
 
 
 if __name__ == '__main__':
     cmk.utils.password_store.replace_passwords()
     exitcode = main()
-    sys.exit(exitcode)
+    sys_exit(exitcode)
diff --git a/source/lib/nagios/plugins/dictionary b/source/lib/nagios/plugins/dictionary
old mode 100644
new mode 100755
index 30fb5281c4db8ff587c5f44350b61b171baae5c7..125de2fc6581f18a66137b2e1ebddc3d3a05c292
--- a/source/lib/nagios/plugins/dictionary
+++ b/source/lib/nagios/plugins/dictionary
@@ -230,7 +230,7 @@ ATTRIBUTE	Autz-Type		1011	integer
 #	User Types
 
 VALUE		Service-Type		Login-User		1
-VALUE		Service-Type		Framed-User		2
+VALUE		Service-Type		pdate		2
 VALUE		Service-Type		Callback-Login-User	3
 VALUE		Service-Type		Callback-Framed-User	4
 VALUE		Service-Type		Outbound-User		5
diff --git a/source/lib/nagios/plugins/dictionary.freeradius b/source/lib/nagios/plugins/dictionary.freeradius
old mode 100644
new mode 100755
diff --git a/source/packages/check_radius b/source/packages/check_radius
index b14b394a21c71e70af36010c262794dcad5dbe2c..bff1f3c988c75b7826db24dbb66a2de962974128 100644
--- a/source/packages/check_radius
+++ b/source/packages/check_radius
@@ -1,5 +1,12 @@
 {'author': 'Th.L. (thl-cmk[at]outlook[dot]com)',
- 'description': 'active RADIUS check\n',
+ 'description': 'This is a (very) basic active RADIUS check:\n'
+                '\n'
+                ' - tests if a RADIUS server is responsive '
+                '(accept/reject/timeout).\n'
+                ' - (limited) support to add AV-pairs to the RADIUS request\n'
+                ' - checks response code, response time and number of response '
+                'attributes\n'
+                '\n',
  'download_url': 'https://thl-cmk.hopto.org',
  'files': {'checks': ['check_radius'],
            'gui': ['metrics/check_radius.py',
@@ -9,7 +16,7 @@
                    'nagios/plugins/dictionary.freeradius']},
  'name': 'check_radius',
  'title': 'Check RADIUS',
- 'version': '0.0.1-20240421',
+ 'version': '0.1.0-20240428',
  'version.min_required': '2.2.0b1',
  'version.packaged': '2.2.0p24',
  'version.usable_until': None}