Navigation


Changeset 271:411314907b43 in freeDiameter


Ignore:
Timestamp:
Apr 20, 2010, 7:34:59 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Added translation of Accounting messages

Files:
8 edited

Legend:

Unmodified
Added
Removed
  • doc/app_radgw.conf.sample

    r254 r271  
    4040# an error is logged if some RADIUS attributes of the message have not been handled.
    4141
     42RGWX = "extensions/echodrop.rgwx" : "echodrop.rgwx.conf"; # See echodrop.rgwx.conf.sample file
     43RGWX = "extensions/auth.rgwx" : auth;
     44RGWX = "extensions/acct.rgwx" : acct;
     45# RGWX = "extensions/debug.rgwx"; # Uncomment to see the result of the translation plugins.
    4246
    4347##################
  • extensions/app_radgw/rgw.h

    r258 r271  
    103103int rgw_clients_check_origin(struct rgw_radius_msg_meta *msg, struct rgw_client *cli);
    104104int rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm);
     105char * rgw_clients_id(struct rgw_client *cli);
    105106int rgw_client_finish_send(struct radius_msg ** msg, struct rgw_radius_msg_meta * req, struct rgw_client * cli);
    106107void rgw_clients_dispose(struct rgw_client ** ref);
  • extensions/app_radgw/rgw_clients.c

    r261 r271  
    444444}
    445445
     446char * rgw_clients_id(struct rgw_client *cli)
     447{
     448        return cli->fqdn;
     449}
     450
    446451
    447452void rgw_clients_dispose(struct rgw_client ** ref)
  • extensions/app_radgw/rgw_common.h

    r258 r271  
    130130       RADIUS_ATTR_PROMPT = 76,
    131131       RADIUS_ATTR_CONFIGURATION_TOKEN = 78,
    132        RADIUS_ATTR_TUNNEL_ASSIGNEMENT_ID = 82,
     132       RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID = 82,
    133133       RADIUS_ATTR_TUNNEL_PREFERENCE = 83,
    134134       RADIUS_ATTR_ARAP_CHALLENGE_RESPONSE = 84,
     
    149149enum {  DIAM_ATTR_USER_NAME = 1,
    150150        DIAM_ATTR_USER_PASSWORD = 2,
     151        DIAM_ATTR_NAS_IP_ADDRESS = 4,
     152        DIAM_ATTR_NAS_PORT = 5,
    151153        DIAM_ATTR_SERVICE_TYPE = 6,
    152154        DIAM_ATTR_FRAMED_PROTOCOL = 7,
     
    168170        DIAM_ATTR_CLASS = 25,
    169171        DIAM_ATTR_IDLE_TIMEOUT = 28,
     172        DIAM_ATTR_NAS_IDENTIFIER = 32,
    170173        DIAM_ATTR_LOGIN_LAT_SERVICE = 34,
    171174        DIAM_ATTR_LOGIN_LAT_NODE = 35,
     
    174177        DIAM_ATTR_FRAMED_APPLETALK_NETWORK = 38,
    175178        DIAM_ATTR_FRAMED_APPLETALK_ZONE = 39,
     179        DIAM_ATTR_ACCT_SESSION_ID = 44,
     180        DIAM_ATTR_ACCT_MULTI_SESSION_ID = 50,
     181        DIAM_ATTR_EVENT_TIMESTAMP = 55,
     182        DIAM_ATTR_NAS_PORT_TYPE = 61,
    176183        DIAM_ATTR_PORT_LIMIT = 62,
    177184        DIAM_ATTR_LOGIN_LAT_PORT = 63,
     
    189196        DIAM_ATTR_CONFIGURATION_TOKEN = 78,
    190197        DIAM_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81,
    191         DIAM_ATTR_TUNNEL_ASSIGNEMENT_ID = 82,
     198        DIAM_ATTR_TUNNEL_ASSIGNMENT_ID = 82,
    192199        DIAM_ATTR_TUNNEL_PREFERENCE = 83,
    193200        DIAM_ATTR_ARAP_CHALLENGE_RESPONSE = 84,
    194201        DIAM_ATTR_ACCT_INTERIM_INTERVAL = 85,
     202        DIAM_ATTR_NAS_PORT_ID = 87,
    195203        DIAM_ATTR_FRAMED_POOL = 88,
    196204        DIAM_ATTR_TUNNEL_CLIENT_AUTH_ID = 90,
    197205        DIAM_ATTR_TUNNEL_SERVER_AUTH_ID = 91,
     206        DIAM_ATTR_NAS_IPV6_ADDRESS = 95,
    198207        DIAM_ATTR_FRAMED_INTERFACE_ID = 96,
    199208        DIAM_ATTR_FRAMED_IPV6_PREFIX = 97,
     
    203212        DIAM_ATTR_EAP_KEY_NAME = 102,
    204213        DIAM_ATTR_AUTH_APPLICATION_ID = 258,
     214        DIAM_ATTR_ACCT_APPLICATION_ID = 259,
     215        DIAM_ATTR_VENDOR_SPECIFIC_APPLICATION_ID = 260,
     216        DIAM_ATTR_SESSION_ID = 263,
     217        DIAM_ATTR_ORIGIN_HOST = 264,
    205218        DIAM_ATTR_MULTI_ROUND_TIMEOUT = 272,
    206219        DIAM_ATTR_AUTH_REQUEST_TYPE = 274,
     
    212225        DIAM_ATTR_ROUTE_RECORD = 282,
    213226        DIAM_ATTR_PROXY_INFO = 284,
     227        DIAM_ATTR_ACCOUNTING_SUB_SESSION_ID = 287,
    214228        DIAM_ATTR_ERROR_REPORTING_HOST = 294,
     229        DIAM_ATTR_TERMINATION_CAUSE = 295,
     230        DIAM_ATTR_ORIGIN_REALM = 296,
    215231        DIAM_ATTR_NAS_FILTER_RULE = 400,
    216232        DIAM_ATTR_TUNNELING = 401,
     
    220236        DIAM_ATTR_EAP_REISSUED_PAYLOAD = 463,
    221237        DIAM_ATTR_EAP_MASTER_SESSION_KEY = 464,
    222         DIAM_ATTR_ACCOUNTING_EAP_AUTH_METHOD = 465
     238        DIAM_ATTR_ACCOUNTING_EAP_AUTH_METHOD = 465,
     239        DIAM_ATTR_ACCOUNTING_RECORD_TYPE = 480,
     240        DIAM_ATTR_ACCOUNTING_REALTIME_REQUIRED = 483,
     241        DIAM_ATTR_ACCOUNTING_RECORD_NUMBER = 485
    223242};
    224243
  • extensions/app_radgw/rgw_plugins.c

    r258 r271  
    381381        if (ret > 0) {
    382382                /* Critical error, log and exit */
    383                 fd_log_debug("An error occurred while handling a RADIUS message, turn on DEBUG for details: %s\n", strerror(ret));
     383                TRACE_DEBUG(NONE, "An error occurred while handling a RADIUS message from '%s': %s\n", rgw_clients_id(cli), strerror(ret));
    384384                return ret;
    385385        }
     
    438438       
    439439        /* We might define other return values with special meaning here (ret == -1, ...) for example create a new Diameter request */
     440       
     441        /* -1: just abord the translation with no more processing. */
    440442       
    441443        return 0;
  • extensions/app_radgw/rgw_worker.c

    r258 r271  
    248248        /* Pass the Diameter answer to the same extensions as the request */
    249249        CHECK_FCT_DO( rgw_plg_loop_ans(pa->rad, pa->sess, ans, &rad_ans, pa->cli), goto out );
    250        
    251         /* Now check what AVPs remain in the diameter answer. If AVPs with the 'M' flag are here, we have a problem... */
    252         CHECK_FCT_DO( fd_msg_browse(*ans, MSG_BRW_FIRST_CHILD, &avp, NULL), { avp = NULL; pb++; } );
    253         while (avp) {
    254                 CHECK_FCT_DO( fd_msg_avp_hdr ( avp, &ahdr ), { pb++; continue; } );
    255                 if (ahdr->avp_flags & AVP_FLAG_MANDATORY) {
    256                         if (ahdr->avp_flags & AVP_FLAG_VENDOR) {
    257                                 TRACE_DEBUG(FULL, "Remaining Mandatory Vendor AVP, code %d", ahdr->avp_code);
    258                                 pb++;
    259                         } else {
    260                                 switch (ahdr->avp_code) {
    261                                         /* A few AVPs can be safely ignored here: */
    262                                         case DIAM_ATTR_ROUTE_RECORD:
    263                                         case DIAM_ATTR_PROXY_INFO:
    264                                                
    265                                                
    266                                                 /* just ignore */
    267                                                 break;
    268                                        
    269                                         default:
    270                                                 TRACE_DEBUG(FULL, "Remaining Mandatory AVP, code %d", ahdr->avp_code);
    271                                                 pb++;
     250
     251        if (*ans != NULL) {
     252
     253                /* Now check what AVPs remain in the diameter answer. If AVPs with the 'M' flag are here, we have a problem... */
     254                CHECK_FCT_DO( fd_msg_browse(*ans, MSG_BRW_FIRST_CHILD, &avp, NULL), { avp = NULL; pb++; } );
     255                while (avp) {
     256                        CHECK_FCT_DO( fd_msg_avp_hdr ( avp, &ahdr ), { pb++; continue; } );
     257                        if (ahdr->avp_flags & AVP_FLAG_MANDATORY) {
     258                                if (ahdr->avp_flags & AVP_FLAG_VENDOR) {
     259                                        TRACE_DEBUG(FULL, "Remaining Mandatory Vendor AVP, code %d", ahdr->avp_code);
     260                                        pb++;
     261                                } else {
     262                                        switch (ahdr->avp_code) {
     263                                                /* A few AVPs can be safely ignored here: */
     264                                                case DIAM_ATTR_ROUTE_RECORD:
     265                                                case DIAM_ATTR_PROXY_INFO:
     266
     267
     268                                                        /* just ignore */
     269                                                        break;
     270
     271                                                default:
     272                                                        TRACE_DEBUG(FULL, "Remaining Mandatory AVP, code %d", ahdr->avp_code);
     273                                                        pb++;
     274                                        }
    272275                                }
    273276                        }
    274                 }
    275                 CHECK_FCT_DO( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), { pb++; break; } );
    276         }
    277        
    278         if (pb) {
    279                 TRACE_DEBUG(INFO, "[radgw] WARNING: %d mandatory AVP in the Diameter answer have not been translated to RADIUS!\n Please use plg_debug.rgwx for more information.", pb);
     277                        CHECK_FCT_DO( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), { pb++; break; } );
     278                }
     279
     280                if (pb) {
     281                        TRACE_DEBUG(INFO, "[radgw] WARNING: %d mandatory AVP in the Diameter answer have not been translated to RADIUS!\n Please use plg_debug.rgwx for more information.", pb);
     282                }
    280283        }
    281284       
  • extensions/app_radgw/rgwx_acct.c

    r268 r271  
    3838#include "rgw_common.h"
    3939
     40
     41/* Other constants we use */
     42#define AI_ACCT                 3       /* Diameter Base Accounting application */
     43#define CC_AC                   271     /* ACR/ACA */
     44#define ACV_ART_START_RECORD            2       /* START_RECORD */
     45#define ACV_ART_INTERIM_RECORD          3       /* INTERIM_RECORD */
     46#define ACV_ART_STOP_RECORD             4       /* STOP_RECORD */
     47#define ACV_ART_AUTHORIZE_AUTHENTICATE  3       /* AUTHORIZE_AUTHENTICATE */
     48#define ER_DIAMETER_LIMITED_SUCCESS     2002
     49
     50
    4051/* The state we keep for this plugin */
    4152struct rgwp_config {
    4253        struct {
     54                struct dict_object * Accounting_Record_Type;    /* Accounting-Record-Type */
     55                struct dict_object * Acct_Application_Id;       /* Acct-Application-Id */
     56                struct dict_object * Acct_Delay_Time;           /* Acct-Delay-Time */
     57                struct dict_object * Accounting_Input_Octets;   /* Accounting-Input-Octets */
     58                struct dict_object * Accounting_Output_Octets;  /* Accounting-Output-Octets */
     59                struct dict_object * Accounting_Input_Packets;  /* Accounting-Input-Packets */
     60                struct dict_object * Accounting_Output_Packets; /* Accounting-Output-Packets */
     61                struct dict_object * Acct_Link_Count;           /* Acct-Link-Count */
     62                struct dict_object * Acct_Authentic;            /* Acct-Authentic */
     63                struct dict_object * Acct_Multi_Session_Id;     /* Acct-Multi-Session-Id */
     64                struct dict_object * Acct_Session_Id;           /* Acct-Session-Id */
     65                struct dict_object * Acct_Session_Time;         /* Acct-Session-Time */
     66               
     67                struct dict_object * ARAP_Password;             /* ARAP-Password */
     68                struct dict_object * ARAP_Security;             /* ARAP-Security */
     69                struct dict_object * ARAP_Security_Data;        /* ARAP-Security-Data */
     70                struct dict_object * Auth_Application_Id;       /* Auth-Application-Id */
     71                struct dict_object * Auth_Request_Type;         /* Auth-Request-Type */
     72                struct dict_object * Authorization_Lifetime;    /* Authorization-Lifetime */
     73                struct dict_object * Callback_Number;           /* Callback-Number */
     74                struct dict_object * Callback_Id;               /* Callback-Id */
     75                struct dict_object * Called_Station_Id;         /* Called-Station-Id */
     76                struct dict_object * Calling_Station_Id;        /* Calling-Station-Id */
     77                struct dict_object * Class;                     /* Class */
     78                struct dict_object * CHAP_Algorithm;            /* CHAP-Algorithm */
     79                struct dict_object * CHAP_Auth;                 /* CHAP-Auth */
     80                struct dict_object * CHAP_Challenge;            /* CHAP-Challenge */
     81                struct dict_object * CHAP_Ident;                /* CHAP-Ident */
     82                struct dict_object * CHAP_Response;             /* CHAP-Response */
     83                struct dict_object * Connect_Info;              /* Connect-Info */
     84                struct dict_object * EAP_Payload;               /* EAP-Payload */
    4385                struct dict_object * Error_Message;             /* Error-Message */
    4486                struct dict_object * Error_Reporting_Host;      /* Error-Reporting-Host */
     87                struct dict_object * Event_Timestamp;           /* Event-Timestamp */
    4588                struct dict_object * Failed_AVP;                /* Failed-AVP */
     89                struct dict_object * Framed_AppleTalk_Link;     /* Framed-AppleTalk-Link */
     90                struct dict_object * Framed_AppleTalk_Network;  /* Framed-AppleTalk-Network */
     91                struct dict_object * Framed_AppleTalk_Zone;     /* Framed-AppleTalk-Zone */
     92                struct dict_object * Framed_Compression;        /* Framed-Compression */
     93                struct dict_object * Framed_IP_Address;         /* Framed-IP-Address */
     94                struct dict_object * Framed_IP_Netmask;         /* Framed-IP-Netmask */
     95                struct dict_object * Framed_Interface_Id;       /* Framed-Interface-Id */
     96                struct dict_object * Framed_IPv6_Prefix;        /* Framed-IPv6-Prefix */
     97                struct dict_object * Framed_IPX_Network;        /* Framed-IPX-Network */
     98                struct dict_object * Framed_MTU;                /* Framed-MTU */
     99                struct dict_object * Framed_Protocol;           /* Framed-Protocol */
     100                struct dict_object * Framed_Pool;               /* Framed-Pool */
     101                struct dict_object * Framed_IPv6_Route;         /* Framed-IPv6-Route */
     102                struct dict_object * Framed_IPv6_Pool;          /* Framed-IPv6-Pool */
     103                struct dict_object * Framed_Route;              /* Framed-Route */
     104                struct dict_object * Framed_Routing;            /* Framed-Routing */
     105                struct dict_object * Filter_Id;                 /* Filter-Id */
     106                struct dict_object * Idle_Timeout;              /* Idle-Timeout */
     107                struct dict_object * Login_IP_Host;             /* Login-IP-Host */
     108                struct dict_object * Login_IPv6_Host;           /* Login-IPv6-Host */
     109                struct dict_object * Login_LAT_Group;           /* Login-LAT-Group */
     110                struct dict_object * Login_LAT_Node;            /* Login-LAT-Node */
     111                struct dict_object * Login_LAT_Port;            /* Login-LAT-Port */
     112                struct dict_object * Login_LAT_Service;         /* Login-LAT-Service */
     113                struct dict_object * Login_Service;             /* Login-Service */
     114                struct dict_object * Login_TCP_Port;            /* Login-TCP-Port */
     115                struct dict_object * NAS_Identifier;            /* NAS-Identifier */
     116                struct dict_object * NAS_IP_Address;            /* NAS-IP-Address */
     117                struct dict_object * NAS_IPv6_Address;          /* NAS-IPv6-Address */
     118                struct dict_object * NAS_Port;                  /* NAS-Port */
     119                struct dict_object * NAS_Port_Id;               /* NAS-Port-Id */
     120                struct dict_object * NAS_Port_Type;             /* NAS-Port-Type */
     121                struct dict_object * Origin_AAA_Protocol;       /* Origin-AAA-Protocol */
    46122                struct dict_object * Origin_Host;               /* Origin-Host */
    47123                struct dict_object * Origin_Realm;              /* Origin-Realm */
     124                struct dict_object * Originating_Line_Info;     /* Originating-Line-Info */
     125                struct dict_object * Port_Limit;                /* Port-Limit */
     126                struct dict_object * Re_Auth_Request_Type;      /* Re-Auth-Request-Type */
    48127                struct dict_object * Result_Code;               /* Result-Code */
     128                struct dict_object * Service_Type;              /* Service-Type */
    49129                struct dict_object * Session_Id;                /* Session-Id */
     130                struct dict_object * Session_Timeout;           /* Session-Timeout */
    50131                struct dict_object * State;                     /* State */
     132                struct dict_object * Tunneling;                 /* Tunneling */
     133                struct dict_object * Tunnel_Type;               /* Tunnel-Type */
     134                struct dict_object * Tunnel_Assignment_Id;      /* Tunnel-Assignment-Id */
     135                struct dict_object * Tunnel_Medium_Type;        /* Tunnel-Medium-Type */
     136                struct dict_object * Tunnel_Client_Endpoint;    /* Tunnel-Client-Endpoint */
     137                struct dict_object * Tunnel_Server_Endpoint;    /* Tunnel-Server-Endpoint */
     138                struct dict_object * Tunnel_Private_Group_Id;   /* Tunnel-Private-Group-Id */
     139                struct dict_object * Tunnel_Preference;         /* Tunnel-Preference */
     140                struct dict_object * Tunnel_Client_Auth_Id;     /* Tunnel-Client-Auth-Id */
     141                struct dict_object * Tunnel_Server_Auth_Id;     /* Tunnel-Server-Auth-Id */
    51142                struct dict_object * User_Name;                 /* User-Name */
    52143        } dict; /* cache of the dictionary objects we use */
     144        struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */
    53145        char * confstr;
     146};
     147
     148/* The state we store in the session */
     149struct sess_state {
     150        uint8_t  req_auth[16];  /* The request authenticator */
     151        int      send_str;      /* If not 0, we must send a STR when the ACA is received. */
     152        uint32_t term_cause;    /* If not 0, the Termination-Cause to put in the STR. */
    54153};
    55154
     
    58157{
    59158        struct rgwp_config * new;
     159        struct dict_object * app;
    60160       
    61161        TRACE_ENTRY("%p %p", conffile, state);
     
    68168       
    69169        /* Resolve all dictionary objects we use */
     170        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &new->dict.Accounting_Record_Type, ENOENT) );
     171        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Application-Id", &new->dict.Acct_Application_Id, ENOENT) );
     172        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Delay-Time", &new->dict.Acct_Delay_Time, ENOENT) );
     173        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Input-Octets", &new->dict.Accounting_Input_Octets, ENOENT) );
     174        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Output-Octets", &new->dict.Accounting_Output_Octets, ENOENT) );
     175        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Input-Packets", &new->dict.Accounting_Input_Packets, ENOENT) );
     176        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Output-Packets", &new->dict.Accounting_Output_Packets, ENOENT) );
     177        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Authentic", &new->dict.Acct_Authentic, ENOENT) );
     178        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Link-Count", &new->dict.Acct_Link_Count, ENOENT) );
     179        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Multi-Session-Id", &new->dict.Acct_Multi_Session_Id, ENOENT) );
     180        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Session-Id", &new->dict.Acct_Session_Id, ENOENT) );
     181        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Session-Time", &new->dict.Acct_Session_Time, ENOENT) );
     182       
     183        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Password", &new->dict.ARAP_Password, ENOENT) );
     184        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security", &new->dict.ARAP_Security, ENOENT) );
     185        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security-Data", &new->dict.ARAP_Security_Data, ENOENT) );
     186        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &new->dict.Auth_Application_Id, ENOENT) );
     187        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Request-Type", &new->dict.Auth_Request_Type, ENOENT) );
     188        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Authorization-Lifetime", &new->dict.Authorization_Lifetime, ENOENT) );
     189        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Callback-Number", &new->dict.Callback_Number, ENOENT) );
     190        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Callback-Id", &new->dict.Callback_Id, ENOENT) );
     191        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Called-Station-Id", &new->dict.Called_Station_Id, ENOENT) );
     192        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Calling-Station-Id", &new->dict.Calling_Station_Id, ENOENT) );
     193        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Class", &new->dict.Class, ENOENT) );
     194        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Connect-Info", &new->dict.Connect_Info, ENOENT) );
     195        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "EAP-Payload", &new->dict.EAP_Payload, ENOENT) );
    70196        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message", &new->dict.Error_Message, ENOENT) );
    71197        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &new->dict.Error_Reporting_Host, ENOENT) );
     198        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Event-Timestamp", &new->dict.Event_Timestamp, ENOENT) );
    72199        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP", &new->dict.Failed_AVP, ENOENT) );
     200        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Link", &new->dict.Framed_AppleTalk_Link, ENOENT) );
     201        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Network", &new->dict.Framed_AppleTalk_Network, ENOENT) );
     202        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Zone", &new->dict.Framed_AppleTalk_Zone, ENOENT) );
     203        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Compression", &new->dict.Framed_Compression, ENOENT) );
     204        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Address", &new->dict.Framed_IP_Address, ENOENT) );
     205        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Netmask", &new->dict.Framed_IP_Netmask, ENOENT) );
     206        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Interface-Id", &new->dict.Framed_Interface_Id, ENOENT) );
     207        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Prefix", &new->dict.Framed_IPv6_Prefix, ENOENT) );
     208        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPX-Network", &new->dict.Framed_IPX_Network, ENOENT) );
     209        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-MTU", &new->dict.Framed_MTU, ENOENT) );
     210        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Protocol", &new->dict.Framed_Protocol, ENOENT) );
     211        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Pool", &new->dict.Framed_Pool, ENOENT) );
     212        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Route", &new->dict.Framed_Route, ENOENT) );
     213        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Route", &new->dict.Framed_IPv6_Route, ENOENT) );
     214        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Pool", &new->dict.Framed_IPv6_Pool, ENOENT) );
     215        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Routing", &new->dict.Framed_Routing, ENOENT) );
     216        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Filter-Id", &new->dict.Filter_Id, ENOENT) );
     217        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Idle-Timeout", &new->dict.Idle_Timeout, ENOENT) );
     218        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IP-Host", &new->dict.Login_IP_Host, ENOENT) );
     219        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IPv6-Host", &new->dict.Login_IPv6_Host, ENOENT) );
     220        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Group", &new->dict.Login_LAT_Group, ENOENT) );
     221        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Node", &new->dict.Login_LAT_Node, ENOENT) );
     222        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Port", &new->dict.Login_LAT_Port, ENOENT) );
     223        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Service", &new->dict.Login_LAT_Service, ENOENT) );
     224        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-Service", &new->dict.Login_Service, ENOENT) );
     225        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-TCP-Port", &new->dict.Login_TCP_Port, ENOENT) );
     226        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Identifier", &new->dict.NAS_Identifier, ENOENT) );
     227        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IP-Address", &new->dict.NAS_IP_Address, ENOENT) );
     228        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IPv6-Address", &new->dict.NAS_IPv6_Address, ENOENT) );
     229        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port", &new->dict.NAS_Port, ENOENT) );
     230        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Id", &new->dict.NAS_Port_Id, ENOENT) );
     231        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Type", &new->dict.NAS_Port_Type, ENOENT) );
     232        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-AAA-Protocol", &new->dict.Origin_AAA_Protocol, ENOENT) );
    73233        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &new->dict.Origin_Host, ENOENT) );
    74234        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &new->dict.Origin_Realm, ENOENT) );
     235        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Originating-Line-Info", &new->dict.Originating_Line_Info, ENOENT) );
     236        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Port-Limit", &new->dict.Port_Limit, ENOENT) );
     237        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Re-Auth-Request-Type", &new->dict.Re_Auth_Request_Type, ENOENT) );
    75238        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code", &new->dict.Result_Code, ENOENT) );
     239        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Service-Type", &new->dict.Service_Type, ENOENT) );
    76240        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &new->dict.Session_Id, ENOENT) );
     241        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Timeout", &new->dict.Session_Timeout, ENOENT) );
    77242        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "State", &new->dict.State, ENOENT) );
     243        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunneling", &new->dict.Tunneling, ENOENT) );
     244        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Assignment-Id", &new->dict.Tunnel_Assignment_Id, ENOENT) );
     245        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Type", &new->dict.Tunnel_Type, ENOENT) );
     246        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Medium-Type", &new->dict.Tunnel_Medium_Type, ENOENT) );
     247        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Endpoint", &new->dict.Tunnel_Client_Endpoint, ENOENT) );
     248        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Endpoint", &new->dict.Tunnel_Server_Endpoint, ENOENT) );
     249        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Private-Group-Id", &new->dict.Tunnel_Private_Group_Id, ENOENT) );
     250        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Preference", &new->dict.Tunnel_Preference, ENOENT) );
     251        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Auth-Id", &new->dict.Tunnel_Client_Auth_Id, ENOENT) );
     252        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Auth-Id", &new->dict.Tunnel_Server_Auth_Id, ENOENT) );
    78253        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &new->dict.User_Name, ENOENT) );
    79254       
    80         TODO("Advertize application support...");
     255        /* This plugin provides the following Diameter authentication applications support: */
     256        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &app, ENOENT) );
     257        CHECK_FCT( fd_disp_app_support ( app, NULL, 0, 1 ) );
    81258       
    82259        *state = new;
     
    97274{
    98275        int idx;
     276        int send_str=0;
     277        uint32_t str_cause=0;
    99278        int got_id = 0;
    100279        uint32_t status_type;
     280        uint32_t termination_action = 0;
     281        uint32_t gigawords_in=0, gigawords_out=0;
     282        size_t nattr_used = 0;
     283        union avp_value value;
     284        struct avp ** avp_tun = NULL, *avp = NULL;
    101285       
    102286        TRACE_ENTRY("%p %p %p %p %p %p", cs, session, rad_req, rad_ans, diam_fw, cli);
    103287        CHECK_PARAMS(rad_req && (rad_req->hdr->code == RADIUS_CODE_ACCOUNTING_REQUEST) && rad_ans && diam_fw && *diam_fw);
    104288       
    105         /* Check the message contains the NAS identification */
     289        /*
     290              Either NAS-IP-Address or NAS-Identifier MUST be present in a
     291              RADIUS Accounting-Request.  It SHOULD contain a NAS-Port or NAS-
     292              Port-Type attribute or both unless the service does not involve a
     293              port or the NAS does not distinguish among its ports.
     294        */
    106295        for (idx = 0; idx < rad_req->attr_used; idx++) {
    107296                struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
     297                uint8_t * v = (uint8_t *)(attr + 1);
    108298                switch (attr->type) {
    109299                        case RADIUS_ATTR_NAS_IP_ADDRESS:
     
    112302                                got_id = 1;
    113303                                break;
     304                               
     305                        case RADIUS_ATTR_TERMINATION_ACTION:
     306                                CHECK_PARAMS( attr->length == 6 );
     307                                termination_action  = (v[0] << 24)
     308                                                   | (v[1] << 16)
     309                                                   | (v[2] <<  8)
     310                                                   |  v[3] ;
     311                                break;
     312                               
     313                        case RADIUS_ATTR_ACCT_INPUT_GIGAWORDS:
     314                                CHECK_PARAMS( attr->length == 6 );
     315                                gigawords_in  = (v[0] << 24)
     316                                                   | (v[1] << 16)
     317                                                   | (v[2] <<  8)
     318                                                   |  v[3] ;
     319                                break;
     320                               
     321                        case RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS:
     322                                CHECK_PARAMS( attr->length == 6 );
     323                                gigawords_out  = (v[0] << 24)
     324                                                   | (v[1] << 16)
     325                                                   | (v[2] <<  8)
     326                                                   |  v[3] ;
     327                                break;
    114328                }
    115329        }
     
    117331        /* Check basic information is there */
    118332        if (!got_id || radius_msg_get_attr_int32(rad_req, RADIUS_ATTR_ACCT_STATUS_TYPE, &status_type)) {
    119                 TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request did not contain a NAS ip/identifier or Acct-Status-Type attribute, reject.");
     333                TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request from %s did not contain a NAS ip/identifier or Acct-Status-Type attribute, reject.", rgw_clients_id(cli));
    120334                return EINVAL;
    121335        }
    122336       
    123         /* Handle the Accounting-On/Off case: nothing to do, just reply OK, since Diameter does not support this */
    124         if ((status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON) || (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF)) {
     337        /*
     338              -- RFC2866:
     339              In Accounting-Request Packets, the Authenticator value is a 16
     340              octet MD5 [5] checksum, called the Request Authenticator.
     341
     342              The NAS and RADIUS accounting server share a secret.  The Request
     343              Authenticator field in Accounting-Request packets contains a one-
     344              way MD5 hash calculated over a stream of octets consisting of the
     345              Code + Identifier + Length + 16 zero octets + request attributes +
     346              shared secret (where + indicates concatenation).  The 16 octet MD5
     347              hash value is stored in the Authenticator field of the
     348              Accounting-Request packet.
     349
     350              Note that the Request Authenticator of an Accounting-Request can
     351              not be done the same way as the Request Authenticator of a RADIUS
     352              Access-Request, because there is no User-Password attribute in an
     353              Accounting-Request.
     354             
     355             
     356              -- RFC5080:
     357              The Request Authenticator field MUST contain the correct data, as
     358              given by the above calculation.  Invalid packets are silently
     359              discarded.  Note that some early implementations always set the
     360              Request Authenticator to all zeros.  New implementations of RADIUS
     361              clients MUST use the above algorithm to calculate the Request
     362              Authenticator field.  New RADIUS server implementations MUST
     363              silently discard invalid packets.
     364             
     365        */     
     366        {
     367                uint8_t save[MD5_MAC_LEN];
     368                uint8_t * secret;
     369                size_t secret_len;
     370               
     371                /* Get the shared secret */
     372                CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len));
     373               
     374                /* Copy the received Request Authenticator */
     375                memcpy(&save[0], &rad_req->hdr->authenticator[0], MD5_MAC_LEN);
     376               
     377                /* Compute the same authenticator */
     378                radius_msg_finish_acct(rad_req, secret, secret_len);
     379               
     380                /* And now compare with the received value */
     381                if (memcmp(&save[0], &rad_req->hdr->authenticator[0], MD5_MAC_LEN)) {
     382                        /* Invalid authenticator */
     383                        TRACE_DEBUG_BUFFER(FULL+1, "Received ReqAuth: ", &save[0], MD5_MAC_LEN, "" );
     384                        TRACE_DEBUG_BUFFER(FULL+1, "Expected ReqAuth: ", &rad_req->hdr->authenticator[0], MD5_MAC_LEN, "" );
     385                        TRACE_DEBUG(INFO, "[acct.rgwx] Invalid Request Authenticator in Account-Request from %s, discarding the message.", rgw_clients_id(cli));
     386                        return EINVAL;
     387                }
     388        }
     389       
     390       
     391        /* Handle the Accounting-On case: nothing to do, just reply OK */
     392        if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON) {
    125393                TRACE_DEBUG(FULL, "[acct.rgwx] Received Accounting-On Acct-Status-Type attribute, replying without translation to Diameter.");
    126394                CHECK_MALLOC( *rad_ans = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, rad_req->hdr->identifier) );
     
    128396        }
    129397       
    130         /* Other cases */
    131         return ENOTSUP;
    132                         /*
    133                               -  If the RADIUS message received is an Accounting-Request, the
    134                                  Acct-Status-Type attribute value must be converted to a
    135                                  Accounting-Record-Type AVP value.  If the Acct-Status-Type
    136                                  attribute value is STOP, the local server MUST issue a
    137                                  Session-Termination-Request message once the Diameter
    138                                  Accounting-Answer message has been received.
     398        if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF) {
     399                TRACE_DEBUG(FULL, "[acct.rgwx] Received Accounting-Off Acct-Status-Type attribute, we must terminate all active sessions.");
     400                TODO("RADIUS side is rebooting, send STR on all sessions?");
     401                return ENOTSUP;
     402        }
     403       
     404        /* Add the command code */
     405        {
     406                struct msg_hdr * header = NULL;
     407                CHECK_FCT( fd_msg_hdr ( *diam_fw, &header ) );
     408                header->msg_flags = CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE;
     409                header->msg_code = CC_AC;
     410                header->msg_appl = AI_ACCT;
     411               
     412                /* Add the Acct-Application-Id */
     413                CHECK_FCT( fd_msg_avp_new ( cs->dict.Acct_Application_Id, 0, &avp ) );
     414                value.i32 = header->msg_appl;
     415                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     416                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     417        }
     418       
     419        /* Convert the RADIUS attributes, as they appear in the message */
     420        for (idx = 0; idx < rad_req->attr_used; idx++) {
     421                struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
     422
     423                switch (attr->type) {
     424                        /*     
     425                              Any attribute valid in a RADIUS Access-Request or Access-Accept
     426                              packet is valid in a RADIUS Accounting-Request packet, except that
     427                              the following attributes MUST NOT be present in an Accounting-
     428                              Request:  User-Password, CHAP-Password, Reply-Message, State.
    139429                        */
    140 
    141                         /*
    142                               -  If the Accounting message contains an Acct-Termination-Cause
    143                                  attribute, it should be translated to the equivalent
    144                                  Termination-Cause AVP value.  (see below)
    145                         */
    146 
     430                        case RADIUS_ATTR_USER_PASSWORD:
     431                        case RADIUS_ATTR_CHAP_PASSWORD:
     432                        case RADIUS_ATTR_REPLY_MESSAGE:
     433                        case RADIUS_ATTR_STATE:
     434                        case RADIUS_ATTR_MESSAGE_AUTHENTICATOR:
     435                        case RADIUS_ATTR_EAP_MESSAGE:
     436                                TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request contains a forbidden attribute (%hhd), reject.", attr->type);
     437                                return EINVAL;
     438                               
     439                       
     440                        /* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */
     441                        #define CONV2DIAM_STR( _dictobj_ )      \
     442                                CHECK_PARAMS( attr->length >= 2 );                                              \
     443                                /* Create the AVP with the specified dictionary model */                        \
     444                                CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \
     445                                value.os.len = attr->length - 2;                                                \
     446                                value.os.data = (unsigned char *)(attr + 1);                                    \
     447                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \
     448                                /* Add the AVP in the Diameter message. */                                      \
     449                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );               \
     450                               
     451                        /* Same thing, for scalar AVPs of 32 bits */
     452                        #define CONV2DIAM_32B( _dictobj_ )      \
     453                                CHECK_PARAMS( attr->length == 6 );                                              \
     454                                CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \
     455                                {                                                                               \
     456                                        uint8_t * v = (uint8_t *)(attr + 1);                                    \
     457                                        value.u32  = (v[0] << 24)                                               \
     458                                                   | (v[1] << 16)                                               \
     459                                                   | (v[2] <<  8)                                               \
     460                                                   |  v[3] ;                                                    \
     461                                }                                                                               \
     462                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \
     463                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );               \
     464                               
     465                        /* And the 64b version */
     466                        #define CONV2DIAM_64B( _dictobj_ )      \
     467                                CHECK_PARAMS( attr->length == 10);                                              \
     468                                CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \
     469                                {                                                                               \
     470                                        uint8_t * v = (uint8_t *)(attr + 1);                                    \
     471                                        value.u64  = ((uint64_t)(v[0]) << 56)                                   \
     472                                                   | ((uint64_t)(v[1]) << 48)                                   \
     473                                                   | ((uint64_t)(v[2]) << 40)                                   \
     474                                                   | ((uint64_t)(v[3]) << 32)                                   \
     475                                                   | ((uint64_t)(v[4]) << 24)                                   \
     476                                                   | ((uint64_t)(v[5]) << 16)                                   \
     477                                                   | ((uint64_t)(v[6]) <<  8)                                   \
     478                                                   |  (uint64_t)(v[7]) ;                                        \
     479                                }                                                                               \
     480                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \
     481                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );               \
     482                               
     483                       
     484                        /* Attributes as listed in RFC2866, section 5.13  and RFC4005, section 10.2.1 */
     485                        case RADIUS_ATTR_USER_NAME:
     486                                CONV2DIAM_STR( User_Name );
     487                                break;
     488                               
     489                        case RADIUS_ATTR_NAS_IP_ADDRESS:
     490                                CONV2DIAM_STR( NAS_IP_Address );
     491                                break;
     492                               
     493                        case RADIUS_ATTR_NAS_PORT:
     494                                CONV2DIAM_32B( NAS_Port );
     495                                break;
     496                               
     497                        case RADIUS_ATTR_SERVICE_TYPE:
     498                                CONV2DIAM_32B( Service_Type );
     499                                break;
     500                               
     501                        case RADIUS_ATTR_FRAMED_PROTOCOL:
     502                                CONV2DIAM_32B( Framed_Protocol );
     503                                break;
     504                               
     505                        case RADIUS_ATTR_FRAMED_IP_ADDRESS:
     506                                CONV2DIAM_STR( Framed_IP_Address );
     507                                break;
     508                               
     509                        case RADIUS_ATTR_FRAMED_IP_NETMASK:
     510                                CONV2DIAM_STR( Framed_IP_Netmask );
     511                                break;
     512                               
     513                        case RADIUS_ATTR_FRAMED_ROUTING:
     514                                CONV2DIAM_32B( Framed_Routing );
     515                                break;
     516                               
     517                        case RADIUS_ATTR_FILTER_ID:
     518                                CONV2DIAM_STR( Filter_Id );
     519                                break;
     520                               
     521                        case RADIUS_ATTR_FRAMED_MTU:
     522                                CONV2DIAM_32B( Framed_MTU );
     523                                break;
     524                       
     525                        case RADIUS_ATTR_FRAMED_COMPRESSION:
     526                                CONV2DIAM_32B( Framed_Compression );
     527                                break;
     528                       
     529                        case RADIUS_ATTR_LOGIN_IP_HOST:
     530                                CONV2DIAM_STR( Login_IP_Host );
     531                                break;
     532                               
     533                        case RADIUS_ATTR_LOGIN_SERVICE:
     534                                CONV2DIAM_32B( Login_Service );
     535                                break;
     536                               
     537                        case RADIUS_ATTR_LOGIN_TCP_PORT:
     538                                CONV2DIAM_32B( Login_TCP_Port );
     539                                break;
     540                               
     541                        case RADIUS_ATTR_CALLBACK_NUMBER:
     542                                CONV2DIAM_STR( Callback_Number );
     543                                break;
     544                               
     545                        case RADIUS_ATTR_CALLBACK_ID:
     546                                CONV2DIAM_STR( Callback_Id );
     547                                break;
     548                               
     549                        case RADIUS_ATTR_FRAMED_ROUTE:
     550                                CONV2DIAM_STR( Framed_Route );
     551                                break;
     552                               
     553                        case RADIUS_ATTR_FRAMED_IPX_NETWORK:
     554                                CONV2DIAM_32B( Framed_IPX_Network );
     555                                break;
     556                               
     557                        case RADIUS_ATTR_CLASS:
     558                                CONV2DIAM_STR( Class );
     559                                break;
     560                       
     561                        case RADIUS_ATTR_VENDOR_SPECIFIC:
     562                                if (attr->length >= 6) {
     563                                        uint32_t vendor_id;
     564                                        uint8_t * c = (uint8_t *)(attr + 1);
     565                                       
     566                                        vendor_id = c[0] << 24 | c[1] << 16 | c[2] << 8 | c[3];
     567                                        c += 4;
     568                                       
     569                                        switch (vendor_id) {
     570                                               
     571                                                /* For the vendors we KNOW they follow the VSA recommended format, we convert following the rules of RFC4005 (9.6.2) */
     572                                                case RADIUS_VENDOR_ID_MICROSOFT : /* RFC 2548 */
     573                                                /* other vendors ? */
     574                                                {
     575                                                        size_t left;
     576                                                        struct radius_attr_vendor *vtlv;
     577                                                       
     578                                                        left = attr->length - 6;
     579                                                        vtlv = (struct radius_attr_vendor *)c;
     580                                               
     581                                                        while ((left >= 2) && (vtlv->vendor_length <= left)) {
     582                                                                /* Search our dictionary for corresponding Vendor's AVP */
     583                                                                struct dict_avp_request req;
     584                                                                struct dict_object * avp_model = NULL;
     585                                                                memset(&req, 0, sizeof(struct dict_avp_request));
     586                                                                req.avp_vendor = vendor_id;
     587                                                                req.avp_code = vtlv->vendor_type;
     588                                                               
     589                                                                CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE_AND_VENDOR, &req, &avp_model, 0) );
     590                                                                if (!avp_model) {
     591                                                                        TRACE_DEBUG(FULL, "Unknown attribute (vendor 0x%x, code 0x%x) ignored.", req.avp_vendor, req.avp_code);
     592                                                                } else {
     593                                                                        CHECK_FCT( fd_msg_avp_new ( avp_model, 0, &avp ) );
     594                                                                        value.os.len = vtlv->vendor_length - 2;
     595                                                                        value.os.data = (unsigned char *)(vtlv + 1);
     596                                                                        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     597                                                                        CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     598                                                                }
     599                                                                c += vtlv->vendor_length;
     600                                                                left -= vtlv->vendor_length;
     601                                                                vtlv = (struct radius_attr_vendor *)c;
     602                                                        }
     603                                                }
     604                                                break;
     605                                               
     606                                                /* Other vendors we KNOw how to convert the attributes would be added here... */
     607                                                /* case RADIUS_VENDOR_ID_CISCO :
     608                                                        break; */
     609                                                /* case RADIUS_VENDOR_ID_IETF : (extended RADIUS attributes)
     610                                                        break; */
     611                                               
     612                                                /* When we don't know, just discard the attribute... VSA are optional with regards to RADIUS anyway */
     613                                                default:
     614                                                        /* do nothing */
     615                                                        TRACE_DEBUG(FULL, "VSA attribute from vendor %d discarded", vendor_id);
     616                                                       
     617                                        }
     618                                }
     619                                break;
     620                               
     621                        case RADIUS_ATTR_SESSION_TIMEOUT:
     622                                /* Translation depends on Termination-Action : rfc4005#section-9.2.1 */
     623                                if (termination_action != RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) {
     624                                        CONV2DIAM_32B( Session_Timeout );
     625                                } else {
     626                                        CONV2DIAM_32B( Authorization_Lifetime );
     627                                        /* And add this additional AVP */
     628                                        CHECK_FCT( fd_msg_avp_new ( cs->dict.Re_Auth_Request_Type, 0, &avp ) );
     629                                        value.u32 = ACV_ART_AUTHORIZE_AUTHENTICATE;
     630                                        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     631                                        CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     632                                }
     633                                break;
     634                               
     635                        case RADIUS_ATTR_IDLE_TIMEOUT:
     636                                CONV2DIAM_32B( Idle_Timeout );
     637                                break;
     638                       
     639                        case RADIUS_ATTR_TERMINATION_ACTION:
     640                                /* Just remove */
     641                                break;
     642                       
     643                        case RADIUS_ATTR_CALLED_STATION_ID:
     644                                CONV2DIAM_STR( Called_Station_Id );
     645                                break;
     646                       
     647                        case RADIUS_ATTR_CALLING_STATION_ID:
     648                                CONV2DIAM_STR( Calling_Station_Id );
     649                                break;
     650                       
     651                        case RADIUS_ATTR_NAS_IDENTIFIER:
     652                                CONV2DIAM_STR( NAS_Identifier );
     653                                break;
     654                       
     655                        /* Proxy-State is handled by echo_drop.rgwx plugin, we ignore it here */
     656                       
     657                        case RADIUS_ATTR_LOGIN_LAT_SERVICE:
     658                                CONV2DIAM_STR( Login_LAT_Service );
     659                                break;
     660                       
     661                        case RADIUS_ATTR_LOGIN_LAT_NODE:
     662                                CONV2DIAM_STR( Login_LAT_Node );
     663                                break;
     664                       
     665                        case RADIUS_ATTR_LOGIN_LAT_GROUP:
     666                                CONV2DIAM_STR( Login_LAT_Group );
     667                                break;
     668                       
     669                        case RADIUS_ATTR_FRAMED_APPLETALK_LINK:
     670                                CONV2DIAM_32B( Framed_AppleTalk_Link );
     671                                break;
     672                               
     673                        case RADIUS_ATTR_FRAMED_APPLETALK_NETWORK:
     674                                CONV2DIAM_32B( Framed_AppleTalk_Network );
     675                                break;
     676                               
     677                        case RADIUS_ATTR_FRAMED_APPLETALK_ZONE:
     678                                CONV2DIAM_STR( Framed_AppleTalk_Zone );
     679                                break;
     680                       
     681                        case RADIUS_ATTR_ACCT_STATUS_TYPE:
     682                                /*
     683                                      -  If the RADIUS message received is an Accounting-Request, the
     684                                         Acct-Status-Type attribute value must be converted to a
     685                                         Accounting-Record-Type AVP value.  If the Acct-Status-Type
     686                                         attribute value is STOP, the local server MUST issue a
     687                                         Session-Termination-Request message once the Diameter
     688                                         Accounting-Answer message has been received.
     689                                */
     690                                switch (status_type) {
     691                                        case RADIUS_ACCT_STATUS_TYPE_START:
     692                                                value.u32 = ACV_ART_START_RECORD;
     693                                                break;
     694                                        case RADIUS_ACCT_STATUS_TYPE_STOP:
     695                                                value.u32 = ACV_ART_STOP_RECORD;
     696                                                send_str = 1; /* Register this info in the session */
     697                                                break;
     698                                        case RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE:
     699                                                value.u32 = ACV_ART_INTERIM_RECORD;
     700                                                break;
     701                                        default:
     702                                                TRACE_DEBUG(INFO, "Unknown RADIUS_ATTR_ACCT_STATUS_TYPE value %d, abording...", status_type);
     703                                                return ENOTSUP;
     704                                }
     705                                CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Record_Type, 0, &avp ) );
     706                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     707                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     708                                break;
     709                       
     710                        case RADIUS_ATTR_ACCT_DELAY_TIME:
     711                                CONV2DIAM_32B( Acct_Delay_Time );
     712                                break;
     713                               
    147714                        /*
    148715                              -  If the RADIUS message contains the Accounting-Input-Octets,
     
    154721                                 AVPs.
    155722                        */
     723                        case RADIUS_ATTR_ACCT_INPUT_OCTETS:
     724                                memset(&value, 0, sizeof(value));
     725                                {
     726                                        uint8_t * v = (uint8_t *)(attr + 1);
     727                                        value.u64  = (v[0] << 24)
     728                                                   | (v[1] << 16)
     729                                                   | (v[2] <<  8)
     730                                                   |  v[3] ;
     731                                }
     732                                value.u64 += ((uint64_t)gigawords_in << 32);
     733                                CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Input_Octets, 0, &avp ) );
     734                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     735                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     736                                break;
     737                               
     738                        case RADIUS_ATTR_ACCT_OUTPUT_OCTETS:
     739                                memset(&value, 0, sizeof(value));
     740                                {
     741                                        uint8_t * v = (uint8_t *)(attr + 1);
     742                                        value.u64  = (v[0] << 24)
     743                                                   | (v[1] << 16)
     744                                                   | (v[2] <<  8)
     745                                                   |  v[3] ;
     746                                }
     747                                value.u64 += ((uint64_t)gigawords_out << 32);
     748                                CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Output_Octets, 0, &avp ) );
     749                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     750                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     751                                break;
     752                               
     753                        case RADIUS_ATTR_ACCT_SESSION_ID:
     754                                CONV2DIAM_STR( Acct_Session_Id );
     755                                break;
     756                               
     757                        case RADIUS_ATTR_ACCT_AUTHENTIC:
     758                                CONV2DIAM_32B( Acct_Authentic );
     759                                break;
     760                               
     761                        case RADIUS_ATTR_ACCT_SESSION_TIME:
     762                                CONV2DIAM_32B( Acct_Session_Time );
     763                                break;
     764                               
     765                        case RADIUS_ATTR_ACCT_INPUT_PACKETS:
     766                                memset(&value, 0, sizeof(value));
     767                                {
     768                                        uint8_t * v = (uint8_t *)(attr + 1);
     769                                        value.u64  = (v[0] << 24)
     770                                                   | (v[1] << 16)
     771                                                   | (v[2] <<  8)
     772                                                   |  v[3] ;
     773                                }
     774                                /* value.u64 += (gigawords_in << 32); */
     775                                CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Input_Packets, 0, &avp ) );
     776                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     777                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     778                                break;
     779                               
     780                        case RADIUS_ATTR_ACCT_OUTPUT_PACKETS:
     781                                memset(&value, 0, sizeof(value));
     782                                {
     783                                        uint8_t * v = (uint8_t *)(attr + 1);
     784                                        value.u64  = (v[0] << 24)
     785                                                   | (v[1] << 16)
     786                                                   | (v[2] <<  8)
     787                                                   |  v[3] ;
     788                                }
     789                                /* value.u64 += (gigawords_out << 32); */
     790                                CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Output_Packets, 0, &avp ) );
     791                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     792                                CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     793                                break;
     794                               
     795                        /*
     796                              -  If the Accounting message contains an Acct-Termination-Cause
     797                                 attribute, it should be translated to the equivalent
     798                                 Termination-Cause AVP value.
     799                        */
     800                        case RADIUS_ATTR_ACCT_TERMINATE_CAUSE:
     801                                /* rfc4005#section-9.3.5 */
     802                                {
     803                                        uint8_t * v = (uint8_t *)(attr + 1);
     804                                        str_cause  = (v[0] << 24)
     805                                                   | (v[1] << 16)
     806                                                   | (v[2] <<  8)
     807                                                   |  v[3] ;
     808                                }
     809                                str_cause += 10; /* This seems to be the rule, we can modify later if needed */
     810                                break;
     811
     812                        case RADIUS_ATTR_ACCT_MULTI_SESSION_ID:
     813                                CONV2DIAM_STR( Acct_Multi_Session_Id );
     814                                break;
     815                               
     816                        case RADIUS_ATTR_ACCT_LINK_COUNT:
     817                                CONV2DIAM_32B( Acct_Link_Count );
     818                                break;
     819                               
     820                        /* CHAP-Challenge is not present in Accounting-Request */
     821                       
     822                        case RADIUS_ATTR_NAS_PORT_TYPE:
     823                                CONV2DIAM_32B( NAS_Port_Type );
     824                                break;
     825                       
     826                        case RADIUS_ATTR_PORT_LIMIT:
     827                                CONV2DIAM_32B( Port_Limit );
     828                                break;
     829                       
     830                        case RADIUS_ATTR_LOGIN_LAT_PORT:
     831                                CONV2DIAM_STR( Login_LAT_Port );
     832                                break;
     833                       
     834                        /* RFC 3162 */ 
     835                        case RADIUS_ATTR_NAS_IPV6_ADDRESS:
     836                                CONV2DIAM_STR( NAS_IPv6_Address );
     837                                break;
     838                               
     839                        case RADIUS_ATTR_FRAMED_INTERFACE_ID:
     840                                CONV2DIAM_64B( Framed_Interface_Id );
     841                                break;
     842                               
     843                        case RADIUS_ATTR_FRAMED_IPV6_PREFIX:
     844                                CONV2DIAM_STR( Framed_IPv6_Prefix );
     845                                break;
     846                               
     847                        case RADIUS_ATTR_LOGIN_IPV6_HOST:
     848                                CONV2DIAM_STR( Login_IPv6_Host );
     849                                break;
     850                               
     851                        case RADIUS_ATTR_FRAMED_IPV6_ROUTE:
     852                                CONV2DIAM_STR( Framed_IPv6_Route );
     853                                break;
     854                               
     855                        case RADIUS_ATTR_FRAMED_IPV6_POOL:
     856                                CONV2DIAM_STR( Framed_IPv6_Pool );
     857                                break;
     858                               
     859                        /* RFC 2868 */
     860                        /* Prepare the top-level Tunneling AVP for each tag values, as needed, and add to the Diameter message.
     861                                This macro is called when an AVP is added inside the group, so we will not have empty grouped AVPs */
     862                        #define AVP_TUN_PREPARE() {                                                                             \
     863                                                if (avp_tun == NULL) {                                                          \
     864                                                        CHECK_MALLOC( avp_tun = calloc(sizeof(struct avp *), 32 ) );            \
     865                                                }                                                                               \
     866                                                tag = *(uint8_t *)(attr + 1);                                                   \
     867                                                if (tag > 0x1F) tag = 0;                                                        \
     868                                                if (avp_tun[tag] == NULL) {                                                     \
     869                                                        CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) );   \
     870                                                        CHECK_FCT( fd_msg_avp_add (*diam_fw, MSG_BRW_LAST_CHILD, avp_tun[tag]));\
     871                                                }                                                                               \
     872                                        }
     873                       
     874                        /* Convert an attribute to an OctetString AVP and add inside the Tunneling AVP corresponding to the tag */
     875                        #define CONV2DIAM_TUN_STR( _dictobj_ ) {                                                \
     876                                uint8_t tag;                                                                    \
     877                                CHECK_PARAMS( attr->length >= 3);                                               \
     878                                AVP_TUN_PREPARE();                                                              \
     879                                CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \
     880                                value.os.len = attr->length - (tag ? 3 : 2);                                    \
     881                                value.os.data = ((unsigned char *)(attr + 1)) + (tag ? 1 : 0);                  \
     882                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \
     883                                CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) );           \
     884                                }
     885                               
     886                        /* Convert an attribute to a scalar AVP and add inside the Tunneling AVP corresponding to the tag */
     887                        #define CONV2DIAM_TUN_24B( _dictobj_ ) {                                                \
     888                                uint8_t tag;                                                                    \
     889                                CHECK_PARAMS( attr->length == 6);                                               \
     890                                AVP_TUN_PREPARE();                                                              \
     891                                CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \
     892                                {                                                                               \
     893                                        uint8_t * v = (uint8_t *)(attr + 1);                                    \
     894                                        value.u32 = (v[1] << 16) | (v[2] <<8) | v[3] ;                          \
     895                                }                                                                               \
     896                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \
     897                                CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) );           \
     898                                }
     899
     900                        /*
     901                              -  If the RADIUS message contains Tunnel information [RADTunnels],
     902                                 the attributes or tagged groups should each be converted to a
     903                                 Diameter Tunneling Grouped AVP set.  If the tunnel information
     904                                 contains a Tunnel-Password attribute, the RADIUS encryption
     905                                 must be resolved, and the password forwarded, by using Diameter
     906                                 security methods.
     907                                    -> If the RADIUS message does not use properly the Tag info, result is unpredictable here..
     908                        */
     909                        case RADIUS_ATTR_TUNNEL_TYPE:
     910                                CONV2DIAM_TUN_24B( Tunnel_Type );
     911                                break;
     912                       
     913                        case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE:
     914                                CONV2DIAM_TUN_24B( Tunnel_Medium_Type );
     915                                break;
     916                       
     917                        case RADIUS_ATTR_TUNNEL_CLIENT_ENDPOINT:
     918                                CONV2DIAM_TUN_STR( Tunnel_Client_Endpoint );
     919                                break;
     920                       
     921                        case RADIUS_ATTR_TUNNEL_SERVER_ENDPOINT:
     922                                CONV2DIAM_TUN_STR( Tunnel_Server_Endpoint );
     923                                break;
     924                       
     925                        /* Tunnel-Password never present in an Accounting-Request */
     926
     927                        case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID:
     928                                CONV2DIAM_TUN_STR( Tunnel_Private_Group_Id );
     929                                break;
     930                       
     931                        case RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID:
     932                                CONV2DIAM_TUN_STR( Tunnel_Assignment_Id );
     933                                break;
     934                       
     935                        /* Tunnel-Reference never present in an Accounting-Request */
     936                       
     937                        case RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID:
     938                                CONV2DIAM_TUN_STR( Tunnel_Client_Auth_Id );
     939                                break;
     940                       
     941                        case RADIUS_ATTR_TUNNEL_SERVER_AUTH_ID:
     942                                CONV2DIAM_TUN_STR( Tunnel_Server_Auth_Id );
     943                                break;
     944                       
     945                /* RFC 2869 */
     946                        /*
     947                                                              Acct-Input-Gigawords, Acct-Output-
     948                           Gigawords, Event-Timestamp, and NAS-Port-Id may have 0-1 instances in
     949                           an Accounting-Request packet.  Connect-Info may have 0+ instances in
     950                           an Accounting-Request packet.  The other attributes added in this
     951                           document must not be present in an Accounting-Request.
     952                        */
     953                        case RADIUS_ATTR_ACCT_INPUT_GIGAWORDS:
     954                                break; /* we already saved the value in gigawords_in */
     955                               
     956                        case RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS:
     957                                break; /* we already saved the value in gigawords_out */
     958                               
     959                        case RADIUS_ATTR_EVENT_TIMESTAMP:
     960                                /* RADIUS:
     961                                      The Value field is four octets encoding an unsigned integer with
     962                                      the number of seconds since January 1, 1970 00:00 UTC.
     963                                   Diameter:
     964                                      The Time format is derived from the OctetString AVP Base Format.
     965                                      The string MUST contain four octets, in the same format as the
     966                                      first four bytes are in the NTP timestamp format.  The NTP
     967                                      Timestamp format is defined in Chapter 3 of [RFC4330].
     968
     969                                      This represents the number of seconds since 0h on 1 January 1900
     970                                      with respect to the Coordinated Universal Time (UTC).
     971                                     
     972                                      -- RFC4330:
     973                                         NTP timestamps are represented as a 64-bit unsigned
     974                                           fixed-point number, in seconds relative to 0h on 1 January 1900.  The
     975                                           integer part is in the first 32 bits, and the fraction part in the
     976                                           last 32 bits.  In the fraction part, the non-significant low-order
     977                                           bits are not specified and are ordinarily set to 0.
     978                                */
     979                                {
     980                                        uint32_t ts;
     981                                       
     982                                        uint8_t * v = (uint8_t *)(attr + 1);
     983                                        /* Read the RADIUS attribute value */
     984                                        ts  = (v[0] << 24)
     985                                                   | (v[1] << 16)
     986                                                   | (v[2] <<  8)
     987                                                   |  v[3] ;
     988                                       
     989                                        /* Add the 70 missing years */
     990                                        ts += 2208988800U; /* 60 * 60 * 24 * ( 365 * 70 + 17 ) */
     991                                       
     992                                        /* Convert to network byte order */
     993                                        ts = htonl(ts);
     994                                       
     995                                         /* Diameter Time datatype is derived from OctetString */
     996                                        value.os.data = (void *) &ts;
     997                                        value.os.len = sizeof(uint32_t);
     998                                       
     999                                        CHECK_FCT( fd_msg_avp_new ( cs->dict.Event_Timestamp, 0, &avp ) );
     1000                                        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
     1001                                        CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
     1002                                }
     1003                                break;
     1004                       
     1005                        case RADIUS_ATTR_NAS_PORT_ID:
     1006                                CONV2DIAM_STR( NAS_Port_Id );
     1007                                break;
     1008                                               
     1009                        case RADIUS_ATTR_CONNECT_INFO:
     1010                                CONV2DIAM_STR( Connect_Info );
     1011                                break;
     1012                       
     1013                        case RADIUS_ATTR_FRAMED_POOL: /* To follow the IPv6 version */
     1014                                CONV2DIAM_STR( Framed_Pool );
     1015                                break;
     1016                               
     1017                       
     1018                /* RFC 3579 */
     1019                        /*
     1020                         The EAP-Message and Message-Authenticator attributes specified in
     1021                           this document MUST NOT be present in an Accounting-Request.
     1022                        */                             
     1023                        case RADIUS_ATTR_ORIGINATING_LINE_INFO:
     1024                                CONV2DIAM_STR( Originating_Line_Info );
     1025                                break;
     1026                               
     1027                /* Default */           
     1028                        default: /* unknown attribute */
     1029                                /* We just keep the attribute in the RADIUS message */
     1030                                rad_req->attr_pos[nattr_used++] = rad_req->attr_pos[idx];
     1031                }
     1032        }
     1033       
     1034        /* Update the radius message to remove all handled attributes */
     1035        rad_req->attr_used = nattr_used;
     1036       
     1037        /* Store useful information in the session */
     1038        {
     1039                struct sess_state * st;
     1040                CHECK_PARAMS(session);
     1041               
     1042                CHECK_MALLOC( st = malloc(sizeof(struct sess_state)) );
     1043                memset(st, 0, sizeof(struct sess_state));
     1044                memcpy(&st->req_auth, &rad_req->hdr->authenticator[0], 16);
     1045                st->send_str = send_str;
     1046                st->term_cause = str_cause;
     1047                CHECK_FCT( fd_sess_state_store( cs->sess_hdl, session, &st ) );
     1048        }
     1049       
     1050        return 0;
    1561051}
    1571052
    1581053static int acct_diam_ans( struct rgwp_config * cs, struct session * session, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
    1591054{
     1055        struct sess_state * st = NULL;
     1056        struct avp *avp, *next;
     1057        struct avp_hdr *ahdr, *sid, *oh, *or;
     1058       
    1601059        TRACE_ENTRY("%p %p %p %p %p", cs, session, diam_ans, rad_fw, cli);
    1611060        CHECK_PARAMS(cs);
    162 
    163         return ENOTSUP;
     1061       
     1062        if (session) {
     1063                CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, session, &st ) );
     1064        }
     1065       
     1066        if (!st) {
     1067                TRACE_DEBUG(INFO, "Received an ACA without corresponding session information, cannot translate to RADIUS");
     1068                return EINVAL;
     1069        }
     1070       
     1071        /* Search these AVPs first */
     1072        CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Session_Id, &avp) );
     1073        CHECK_FCT( fd_msg_avp_hdr ( avp, &sid ) );
     1074       
     1075        CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Host, &avp) );
     1076        CHECK_FCT( fd_msg_avp_hdr ( avp, &oh ) );
     1077
     1078        CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Realm, &avp) );
     1079        CHECK_FCT( fd_msg_avp_hdr ( avp, &or ) );
     1080
     1081        /* Check the Diameter error code */
     1082        CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Result_Code, &avp) );
     1083        ASSERT( avp ); /* otherwise the message should have been discarded a lot earlier because of ABNF */
     1084        CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
     1085        switch (ahdr->avp_value->u32) {
     1086                case ER_DIAMETER_SUCCESS:
     1087                case ER_DIAMETER_LIMITED_SUCCESS:
     1088                        (*rad_fw)->hdr->code = RADIUS_CODE_ACCOUNTING_RESPONSE;
     1089                        break;
     1090               
     1091                default:
     1092                        fd_log_debug("[auth.rgwx] Received Diameter answer with error code '%d' from server '%.*s', session %.*s, not translating into Accounting-Response\n",
     1093                                        ahdr->avp_value->u32,
     1094                                        oh->avp_value->os.len, oh->avp_value->os.data,
     1095                                        sid->avp_value->os.len, sid->avp_value->os.data);
     1096                        CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Message, &avp) );
     1097                        if (avp) {
     1098                                CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
     1099                                fd_log_debug("[auth.rgwx]   Error-Message content: '%.*s'\n",
     1100                                                ahdr->avp_value->os.len, ahdr->avp_value->os.data);
     1101                        }
     1102                        CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Reporting_Host, &avp) );
     1103                        if (avp) {
     1104                                CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
     1105                                fd_log_debug("[auth.rgwx]   Error-Reporting-Host: '%.*s'\n",
     1106                                                ahdr->avp_value->os.len, ahdr->avp_value->os.data);
     1107                        }
     1108                        CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Failed_AVP, &avp) );
     1109                        if (avp) {
     1110                                fd_log_debug("[auth.rgwx]   Failed-AVP was included in the message.\n");
     1111                                /* Dump its content ? */
     1112                        }
     1113                        return -1;
     1114        }
     1115        /* Remove this Result-Code avp */
     1116        CHECK_FCT( fd_msg_free( avp ) );
     1117       
     1118        /* If it was a response to a STOP record, we must send an STR for this session */
     1119        if (st->send_str) {
     1120                TODO("Send STR, including sid, [Dest-Host=oh,] Dest-Realm=or, Term-Cause=st->term_cause... Register to receive the answer.");
     1121        }
     1122       
     1123       
     1124        /*
     1125                No attributes should be found in
     1126                   Accounting-Response packets except Proxy-State and possibly Vendor-
     1127                   Specific.
     1128        */
     1129
     1130        /* Now loop in the list of AVPs and convert those that we know how */
     1131        CHECK_FCT( fd_msg_browse(*diam_ans, MSG_BRW_FIRST_CHILD, &next, NULL) );
     1132       
     1133        while (next) {
     1134                int handled = 1;
     1135                avp = next;
     1136                CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &next, NULL) );
     1137               
     1138                CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
     1139               
     1140                if (!(ahdr->avp_flags & AVP_FLAG_VENDOR)) {
     1141                        switch (ahdr->avp_code) {
     1142                                /* Based on RFC4005, sec 3.10 */
     1143                                case DIAM_ATTR_SESSION_ID:
     1144                                case DIAM_ATTR_ORIGIN_HOST:
     1145                                case DIAM_ATTR_ORIGIN_REALM:
     1146                                case DIAM_ATTR_ACCOUNTING_RECORD_TYPE:
     1147                                case DIAM_ATTR_ACCOUNTING_RECORD_NUMBER:
     1148                                case DIAM_ATTR_ACCT_APPLICATION_ID:
     1149                                case DIAM_ATTR_VENDOR_SPECIFIC_APPLICATION_ID:
     1150                                case DIAM_ATTR_USER_NAME:
     1151                                case DIAM_ATTR_ACCOUNTING_SUB_SESSION_ID:
     1152                                case DIAM_ATTR_ACCT_SESSION_ID:
     1153                                case DIAM_ATTR_ACCT_MULTI_SESSION_ID:
     1154                                case DIAM_ATTR_EVENT_TIMESTAMP:
     1155                                case DIAM_ATTR_ORIGIN_AAA_PROTOCOL:
     1156                                case DIAM_ATTR_ORIGIN_STATE_ID:
     1157                                case DIAM_ATTR_NAS_IDENTIFIER:
     1158                                case DIAM_ATTR_NAS_IP_ADDRESS:
     1159                                case DIAM_ATTR_NAS_IPV6_ADDRESS:
     1160                                case DIAM_ATTR_NAS_PORT:
     1161                                case DIAM_ATTR_NAS_PORT_ID:
     1162                                case DIAM_ATTR_NAS_PORT_TYPE:
     1163                                case DIAM_ATTR_SERVICE_TYPE:
     1164                                case DIAM_ATTR_TERMINATION_CAUSE:
     1165                                case DIAM_ATTR_ACCOUNTING_REALTIME_REQUIRED:
     1166                                case DIAM_ATTR_ACCT_INTERIM_INTERVAL:
     1167                                case DIAM_ATTR_CLASS:
     1168                                        /* We just remove these AVP, they are not expected in RADIUS client */
     1169                                        break;
     1170                                       
     1171                                default:
     1172                                        /* Leave the AVP in the message for further treatment */
     1173                                        handled = 0;
     1174                        }
     1175                } else {
     1176                        /* Vendor-specific AVPs */
     1177                        switch (ahdr->avp_vendor) {
     1178                               
     1179                                default: /* unknown vendor */
     1180                                        handled = 0;
     1181                        }
     1182                }
     1183               
     1184                if (handled) {
     1185                        CHECK_FCT( fd_msg_free( avp ) );
     1186                }
     1187        }
     1188       
     1189        /*
     1190              The Authenticator field in an Accounting-Response packet is called
     1191              the Response Authenticator, and contains a one-way MD5 hash
     1192              calculated over a stream of octets consisting of the Accounting-
     1193              Response Code, Identifier, Length, the Request Authenticator field
     1194              from the Accounting-Request packet being replied to, and the
     1195              response attributes if any, followed by the shared secret.  The
     1196              resulting 16 octet MD5 hash value is stored in the Authenticator
     1197              field of the Accounting-Response packet.
     1198             
     1199              -- done in radius_msg_finish_srv
     1200        */
     1201
     1202        return 0;
    1641203}
    1651204
  • extensions/app_radgw/rgwx_auth.c

    r264 r271  
    4747#define CC_AA                   265     /* AAR */
    4848#define CC_DIAMETER_EAP         268     /* DER */
    49 #define CC_DIAMETER_EAP         268     /* DER */
    5049#define ACV_ART_AUTHORIZE_AUTHENTICATE  3       /* AUTHORIZE_AUTHENTICATE */
    5150#define ACV_OAP_RADIUS                  1       /* RADIUS */
     
    5655/* The state we keep for this plugin */
    5756struct rgwp_config {
    58         struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */
    5957        struct {
    6058                struct dict_object * ARAP_Password;             /* ARAP-Password */
     
    120118               
    121119        } dict; /* cache of the dictionary objects we use */
     120        struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */
    122121        char * confstr;
    123122};
     
    768767                                                if (tag > 0x1F) tag = 0;                                                        \
    769768                                                if (avp_tun[tag] == NULL) {                                                     \
    770                                                         CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) );           \
     769                                                        CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) );   \
    771770                                                        CHECK_FCT( fd_msg_avp_add (*diam_fw, MSG_BRW_LAST_CHILD, avp_tun[tag]));\
    772771                                                }                                                                               \
     
    774773                       
    775774                        /* Convert an attribute to an OctetString AVP and add inside the Tunneling AVP corresponding to the tag */
    776                         #define CONV2DIAM_TUN_STR( _dictobj_ ) {                                                        \
     775                        #define CONV2DIAM_TUN_STR( _dictobj_ ) {                                                \
    777776                                uint8_t tag;                                                                    \
    778777                                CHECK_PARAMS( attr->length >= 3);                                               \
     
    786785                               
    787786                        /* Convert an attribute to a scalar AVP and add inside the Tunneling AVP corresponding to the tag */
    788                         #define CONV2DIAM_TUN_24B( _dictobj_ ) {                                                        \
     787                        #define CONV2DIAM_TUN_24B( _dictobj_ ) {                                                \
    789788                                uint8_t tag;                                                                    \
    790789                                CHECK_PARAMS( attr->length == 6);                                               \
     
    916915static int auth_diam_ans( struct rgwp_config * cs, struct session * session, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
    917916{
    918         struct msg_hdr *mhdr;
    919917        struct avp *avp, *next, *avp_x, *avp_y, *asid, *aoh;
    920918        struct avp_hdr *ahdr, *sid, *oh;
     
    931929                CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, session, &req_auth ) );
    932930        }
    933        
    934         CHECK_FCT( fd_msg_hdr( *diam_ans, &mhdr ) );
    935931       
    936932        /*     
     
    14661462                                                                                break;
    14671463                                                                               
    1468                                                                         case DIAM_ATTR_TUNNEL_ASSIGNEMENT_ID:
    1469                                                                                 CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_ASSIGNEMENT_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
     1464                                                                        case DIAM_ATTR_TUNNEL_ASSIGNMENT_ID:
     1465                                                                                CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
    14701466                                                                                break;
    14711467                                                                               
Note: See TracChangeset for help on using the changeset viewer.